From 1a32f1bb58cce60ab0ded2f885deab8f25229ea3 Mon Sep 17 00:00:00 2001 From: freemine Date: Tue, 20 Oct 2020 19:30:56 +0800 Subject: [PATCH 01/85] temporary commit --- src/connector/odbc/src/todbc.c | 666 ++++++++-------------------- src/connector/odbc/src/todbc_conv.c | 363 +++++++++++++++ src/connector/odbc/src/todbc_conv.h | 69 +++ src/connector/odbc/src/todbc_util.c | 16 + src/connector/odbc/src/todbc_util.h | 4 + src/connector/odbc/tests/odbc.py | 10 + src/inc/taoserror.h | 29 +- 7 files changed, 662 insertions(+), 495 deletions(-) create mode 100644 src/connector/odbc/src/todbc_conv.c create mode 100644 src/connector/odbc/src/todbc_conv.h diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 953999c434..594d53d132 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -22,6 +22,7 @@ #include "os.h" #include "taoserror.h" #include "todbc_util.h" +#include "todbc_conv.h" #include #include @@ -143,17 +144,36 @@ do { \ D("%s: elapsed: [%.6f]s", #statement, delta); \ } while (0) - -#define CHK_CONV(statement) \ -do { \ - const char *sqlstate = statement; \ - if (sqlstate) { \ - SET_ERROR(sql, sqlstate, TSDB_CODE_ODBC_OUT_OF_RANGE, \ - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", \ - sql_c_type(valueType), valueType, valueType, \ - taos_data_type(type), type, type, idx+1); \ - return SQL_ERROR; \ - } \ +#define CHK_CONV(statement) \ +do { \ + TSDB_CONV_CODE code = (statement); \ + switch (code) { \ + case TSDB_CONV_OK: return SQL_SUCCESS; \ + case TSDB_CONV_OOM: { \ + SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_OOR: { \ + SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_OOR, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_CHAR_NOT_NUM: { \ + SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_TRUNC_FRACTION: { \ + SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC_FRAC, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_TRUNC: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ + return SQL_ERROR; \ + } break; \ + default: { \ + DASSERTX(0, "internal logic error"); \ + return SQL_ERROR; /* never reached here */ \ + } break; \ + } \ } while (0) typedef struct env_s env_t; @@ -229,39 +249,6 @@ struct c_target_s { static pthread_once_t init_once = PTHREAD_ONCE_INIT; static void init_routine(void); -// conversions - -const char* tsdb_int64_to_bit(int64_t src, int8_t *dst); -const char* tsdb_int64_to_tinyint(int64_t src, int8_t *dst); -const char* tsdb_int64_to_smallint(int64_t src, int16_t *dst); -const char* tsdb_int64_to_int(int64_t src, int32_t *dst); -const char* tsdb_int64_to_bigint(int64_t src, int64_t *dst); -const char* tsdb_int64_to_ts(int64_t src, int64_t *dst); -const char* tsdb_int64_to_float(int64_t src, float *dst); -const char* tsdb_int64_to_double(int64_t src, double *dst); -const char* tsdb_int64_to_char(int64_t src, char *dst, size_t dlen); - -const char* tsdb_double_to_bit(double src, int precision, int8_t *dst); -const char* tsdb_double_to_tinyint(double src, int precision, int8_t *dst); -const char* tsdb_double_to_smallint(double src, int precision, int16_t *dst); -const char* tsdb_double_to_int(double src, int precision, int32_t *dst); -const char* tsdb_double_to_bigint(double src, int precision, int64_t *dst); -const char* tsdb_double_to_ts(double src, int precision, int64_t *dst); -const char* tsdb_double_to_float(double src, int precision, float *dst); -const char* tsdb_double_to_double(double src, int precision, double *dst); -const char* tsdb_double_to_char(double src, int precision, char *dst, size_t dlen); - -const char* tsdb_chars_to_bit(const char *src, int8_t *dst); -const char* tsdb_chars_to_tinyint(const char *src, int8_t *dst); -const char* tsdb_chars_to_smallint(const char *src, int16_t *dst); -const char* tsdb_chars_to_int(const char *src, int32_t *dst); -const char* tsdb_chars_to_bigint(const char *src, int64_t *dst); -const char* tsdb_chars_to_ts(const char *src, int64_t *dst); -const char* tsdb_chars_to_float(const char *src, float *dst); -const char* tsdb_chars_to_double(const char *src, double *dst); -const char* tsdb_chars_to_char(const char *src, char *dst, size_t dlen); - - static int do_field_display_size(TAOS_FIELD *field); static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) @@ -1280,25 +1267,35 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = &bind->u.b; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_bit(*(int32_t*)paramValue, &bind->u.b)); - } break; case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_bit(*(int8_t*)paramValue, &bind->u.b)); + CHK_CONV(tsdb_int64_to_bit(1, *(int8_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_TINYINT: + case SQL_C_STINYINT: { + CHK_CONV(tsdb_int64_to_bit(1, *(int8_t*)paramValue, &bind->u.b)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: case SQL_C_SHORT: - case SQL_C_SSHORT: + case SQL_C_SSHORT: { + CHK_CONV(tsdb_int64_to_bit(1, *(int16_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_LONG: + case SQL_C_SLONG: { + CHK_CONV(tsdb_int64_to_bit(1, *(int32_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(tsdb_int64_to_bit(1, *(int64_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_CHAR: { + CHK_CONV(tsdb_chars_to_bit(1, (const char *)paramValue, &bind->u.b)); + } break; + case SQL_C_WCHAR: { + CHK_CONV(tsdb_wchars_to_bit(1, (const unsigned char*)paramValue, *soi, &bind->u.b)); + } break; case SQL_C_USHORT: - case SQL_C_SLONG: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1324,28 +1321,34 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = &bind->u.v1; bind->length = &bind->buffer_length; switch (valueType) { + case SQL_C_BIT: { + CHK_CONV(tsdb_int64_to_tinyint(1, *(int8_t*)paramValue, &bind->u.v1)); + } break; + case SQL_C_STINYINT: case SQL_C_TINYINT: { - CHK_CONV(tsdb_int64_to_tinyint(*(int8_t*)paramValue, &bind->u.v1)); + CHK_CONV(tsdb_int64_to_tinyint(1, *(int8_t*)paramValue, &bind->u.v1)); } break; + case SQL_C_SSHORT: case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_tinyint(*(int16_t*)paramValue, &bind->u.v1)); + CHK_CONV(tsdb_int64_to_tinyint(1, *(int16_t*)paramValue, &bind->u.v1)); } break; + case SQL_C_SLONG: case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_tinyint(*(int32_t*)paramValue, &bind->u.v1)); + CHK_CONV(tsdb_int64_to_tinyint(1, *(int32_t*)paramValue, &bind->u.v1)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_tinyint(*(int64_t*)paramValue, &bind->u.v1)); + CHK_CONV(tsdb_int64_to_tinyint(1, *(int64_t*)paramValue, &bind->u.v1)); + } break; + case SQL_C_CHAR: { + CHK_CONV(tsdb_chars_to_tinyint(1, (const char*)paramValue, &bind->u.v1)); + } break; + case SQL_C_WCHAR: { + CHK_CONV(tsdb_wchars_to_tinyint(1, (const unsigned char*)paramValue, *soi, &bind->u.v1)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SSHORT: case SQL_C_USHORT: - case SQL_C_SLONG: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: case SQL_C_UBIGINT: case SQL_C_BINARY: @@ -1372,25 +1375,35 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = &bind->u.v2; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_smallint(*(int32_t*)paramValue, &bind->u.v2)); + case SQL_C_BIT: { + CHK_CONV(tsdb_int64_to_smallint(1, *(int8_t*)paramValue, &bind->u.v2)); } break; - case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_smallint(*(int16_t*)paramValue, &bind->u.v2)); + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(tsdb_int64_to_smallint(1, *(int8_t*)paramValue, &bind->u.v2)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: case SQL_C_SSHORT: - case SQL_C_USHORT: + case SQL_C_SHORT: { + CHK_CONV(tsdb_int64_to_smallint(1, *(int16_t*)paramValue, &bind->u.v2)); + } break; case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(tsdb_int64_to_smallint(1, *(int32_t*)paramValue, &bind->u.v2)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(tsdb_int64_to_smallint(1, *(int64_t*)paramValue, &bind->u.v2)); + } break; + case SQL_C_CHAR: { + CHK_CONV(tsdb_chars_to_smallint(1, (const char*)paramValue, &bind->u.v2)); + } break; + case SQL_C_WCHAR: { + CHK_CONV(tsdb_wchars_to_smallint(1, (const unsigned char*)paramValue, *soi, &bind->u.v2)); + } break; + case SQL_C_USHORT: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1416,23 +1429,35 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = &bind->u.v4; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_int(*(int32_t*)paramValue, &bind->u.v4)); + case SQL_C_BIT: { + CHK_CONV(tsdb_int64_to_int(1, *(int8_t*)paramValue, &bind->u.v4)); + } break; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(tsdb_int64_to_int(1, *(int8_t*)paramValue, &bind->u.v4)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: case SQL_C_SSHORT: - case SQL_C_USHORT: + case SQL_C_SHORT: { + CHK_CONV(tsdb_int64_to_int(1, *(int16_t*)paramValue, &bind->u.v4)); + } break; case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(tsdb_int64_to_int(1, *(int32_t*)paramValue, &bind->u.v4)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(tsdb_int64_to_int(1, *(int64_t*)paramValue, &bind->u.v4)); + } break; + case SQL_C_CHAR: { + CHK_CONV(tsdb_chars_to_int(1, (const char*)paramValue, &bind->u.v4)); + } break; + case SQL_C_WCHAR: { + CHK_CONV(tsdb_wchars_to_int(1, (const unsigned char*)paramValue, *soi, &bind->u.v4)); + } break; + case SQL_C_USHORT: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1458,24 +1483,34 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = &bind->u.v8; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_SBIGINT: { - bind->u.v8 = *(int64_t*)paramValue; + case SQL_C_BIT: { + CHK_CONV(tsdb_int64_to_bigint(1, *(int8_t*)paramValue, &bind->u.v8)); } break; - case SQL_C_LONG: { - bind->u.v8 = *(int32_t*)paramValue; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(tsdb_int64_to_bigint(1, *(int8_t*)paramValue, &bind->u.v8)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: case SQL_C_SSHORT: - case SQL_C_USHORT: + case SQL_C_SHORT: { + CHK_CONV(tsdb_int64_to_bigint(1, *(int16_t*)paramValue, &bind->u.v8)); + } break; case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(tsdb_int64_to_bigint(1, *(int32_t*)paramValue, &bind->u.v8)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(tsdb_int64_to_bigint(1, *(int64_t*)paramValue, &bind->u.v8)); + } break; + case SQL_C_CHAR: { + CHK_CONV(tsdb_chars_to_bigint(1, (const char*)paramValue, &bind->u.v8)); + } break; + case SQL_C_WCHAR: { + CHK_CONV(tsdb_wchars_to_bigint(1, (const unsigned char*)paramValue, *soi, &bind->u.v8)); + } break; + case SQL_C_USHORT: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: case SQL_C_UBIGINT: case SQL_C_BINARY: @@ -1502,26 +1537,38 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = &bind->u.f4; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_DOUBLE: { - bind->u.f4 = *(double*)paramValue; + case SQL_C_BIT: { + CHK_CONV(tsdb_int64_to_float(1, *(int8_t*)paramValue, &bind->u.f4)); + } break; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(tsdb_int64_to_float(1, *(int8_t*)paramValue, &bind->u.f4)); + } break; + case SQL_C_SSHORT: + case SQL_C_SHORT: { + CHK_CONV(tsdb_int64_to_float(1, *(int16_t*)paramValue, &bind->u.f4)); + } break; + case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(tsdb_int64_to_float(1, *(int32_t*)paramValue, &bind->u.f4)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(tsdb_int64_to_float(1, *(int64_t*)paramValue, &bind->u.f4)); } break; case SQL_C_FLOAT: { bind->u.f4 = *(float*)paramValue; } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: + case SQL_C_CHAR: { + CHK_CONV(tsdb_chars_to_float(1, (const char*)paramValue, &bind->u.f4)); + } break; + case SQL_C_WCHAR: { + CHK_CONV(tsdb_wchars_to_float(1, (const unsigned char*)paramValue, *soi, &bind->u.f4)); + } break; case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: case SQL_C_ULONG: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: + case SQL_C_DOUBLE: case SQL_C_BINARY: case SQL_C_DATE: case SQL_C_TIME: @@ -1546,23 +1593,39 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = &bind->u.f8; bind->length = &bind->buffer_length; switch (valueType) { + case SQL_C_BIT: { + CHK_CONV(tsdb_int64_to_double(1, *(int8_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(tsdb_int64_to_double(1, *(int8_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_SSHORT: + case SQL_C_SHORT: { + CHK_CONV(tsdb_int64_to_double(1, *(int16_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(tsdb_int64_to_double(1, *(int32_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(tsdb_int64_to_double(1, *(int64_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_FLOAT: { + bind->u.f8 = *(float*)paramValue; + } break; case SQL_C_DOUBLE: { bind->u.f8 = *(double*)paramValue; } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: + case SQL_C_CHAR: { + CHK_CONV(tsdb_chars_to_double(1, (const char*)paramValue, &bind->u.f8)); + } break; + case SQL_C_WCHAR: { + CHK_CONV(tsdb_wchars_to_double(1, (const unsigned char*)paramValue, *soi, &bind->u.f8)); + } break; case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1614,12 +1677,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: case SQL_C_TINYINT: case SQL_C_STINYINT: case SQL_C_UTINYINT: case SQL_C_SBIGINT: case SQL_C_UBIGINT: + case SQL_C_BIT: case SQL_C_DATE: case SQL_C_TIME: case SQL_C_TIMESTAMP: @@ -3117,364 +3180,3 @@ static SQLRETURN conv_tsdb_str_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIE -const char* tsdb_int64_to_bit(int64_t src, int8_t *dst) -{ - *dst = src; - if (src==0 || src==1) return NULL; - return "22003"; -} - -const char* tsdb_int64_to_tinyint(int64_t src, int8_t *dst) -{ - *dst = src; - if (src>=SCHAR_MIN && src<=SCHAR_MAX) return NULL; - return "22003"; -} - -const char* tsdb_int64_to_smallint(int64_t src, int16_t *dst) -{ - *dst = src; - if (src>=SHRT_MIN && src<=SHRT_MAX) return NULL; - return "22003"; -} - -const char* tsdb_int64_to_int(int64_t src, int32_t *dst) -{ - *dst = src; - if (src>=LONG_MIN && src<=LONG_MAX) return NULL; - return "22003"; -} - -const char* tsdb_int64_to_bigint(int64_t src, int64_t *dst) -{ - *dst = src; - return NULL; -} - -const char* tsdb_int64_to_ts(int64_t src, int64_t *dst) -{ - *dst = src; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%" PRId64 "", src); - DASSERT(n>=0); - DASSERT(n=2) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(nSCHAR_MAX) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(nSHRT_MAX) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(nLONG_MAX) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(nLLONG_MAX) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(n=0); - DASSERT(n=0); - DASSERT(n2>=0); - DASSERT(n1=0); - if (n>=dlen) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_bit(const char *src, int8_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (v==0 || v==1) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (v==0 || v==1) return NULL; - - return "22003"; -} - -const char* tsdb_chars_to_tinyint(const char *src, int8_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vSCHAR_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vSCHAR_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_smallint(const char *src, int16_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vSHRT_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vSHRT_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_int(const char *src, int32_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vLONG_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vLONG_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_bigint(const char *src, int64_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vLLONG_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vLLONG_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_ts(const char *src, int64_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vLLONG_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vLLONG_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_float(const char *src, float *dst) -{ - int bytes = 0; - int n = sscanf(src, "%f%n", dst, &bytes); - if (n!=1) return "22018"; - - if (bytes!=strlen(src)) return "22018"; - - return NULL; -} - -const char* tsdb_chars_to_double(const char *src, double *dst) -{ - int bytes = 0; - int n = sscanf(src, "%lf%n", dst, &bytes); - if (n!=1) return "22018"; - - if (bytes!=strlen(src)) return "22018"; - - return NULL; -} - -const char* tsdb_chars_to_char(const char *src, char *dst, size_t dlen) -{ - int n = snprintf(dst, dlen, "%s", src); - if (n>=dlen) return "22001"; - - return NULL; -} - diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c new file mode 100644 index 0000000000..ccfead3eb3 --- /dev/null +++ b/src/connector/odbc/src/todbc_conv.c @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "todbc_conv.h" + +#include "todbc_util.h" + +#include +#include +#include +#include + + +// src: int +TSDB_CONV_CODE tsdb_int64_to_bit(int todb, int64_t src, int8_t *dst) { + *dst = (int8_t)src; + if (src==0 || src==1) return TSDB_CONV_OK; + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_tinyint(int todb, int64_t src, int8_t *dst) { + *dst = (int8_t)src; + if (src == *dst) return TSDB_CONV_OK; + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_smallint(int todb, int64_t src, int16_t *dst) { + *dst = (int16_t)src; + if (src == *dst) return TSDB_CONV_OK; + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_int(int todb, int64_t src, int32_t *dst) { + *dst = (int32_t)src; + if (src == *dst) return TSDB_CONV_OK; + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_bigint(int todb, int64_t src, int64_t *dst) { + *dst = src; + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_int64_to_ts(int todb, int64_t src, int64_t *dst) { + *dst = src; + + time_t t = (time_t)(src / 1000); + struct tm tm = {0}; + if (localtime_r(&t, &tm)) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_float(int todb, int64_t src, float *dst) { + *dst = (float)src; + + int64_t v = (int64_t)*dst; + if (v==src) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_double(int todb, int64_t src, double *dst) { + *dst = (double)src; + + int64_t v = (int64_t)*dst; + if (v==src) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_char(int todb, int64_t src, char *dst, size_t dlen) { + int n = snprintf(dst, dlen, "%" PRId64 "", src); + + if (n=2) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_tinyint(int todb, double src, int8_t *dst) { + *dst = (int8_t)src; + + if (srcSCHAR_MAX) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_smallint(int todb, double src, int16_t *dst) { + *dst = (int16_t)src; + + if (srcSHRT_MAX) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_int(int todb, double src, int32_t *dst) { + *dst = (int32_t)src; + + if (srcLONG_MAX) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_bigint(int todb, double src, int64_t *dst) { + *dst = (int64_t)src; + + if (srcLLONG_MAX) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_ts(int todb, double src, int64_t *dst) { + TSDB_CONV_CODE code = tsdb_double_to_bigint(todb, src, dst); + + if (code==TSDB_CONV_OK || code==TSDB_CONV_TRUNC_FRACTION) { + int64_t v = (int64_t)src; + time_t t = (time_t)(v / 1000); + struct tm tm = {0}; + if (localtime_r(&t, &tm)) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; + } + + return code; +} + +// src: chars +TSDB_CONV_CODE tsdb_chars_to_bit(int todb, const char *src, int8_t *dst) { + if (strcmp(src, "0")==0) { + *dst = 0; + return TSDB_CONV_OK; + } + + if (strcmp(src, "1")==0) { + *dst = 1; + return TSDB_CONV_OK; + } + + double v; + int bytes; + int n = sscanf(src, "%lg%n", &v, &bytes); + + if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; + if (bytes!=strlen(src)) return TSDB_CONV_CHAR_NOT_NUM; + + if (v<0 || v>=2) return TSDB_CONV_OOR; + + return TSDB_CONV_TRUNC_FRACTION; +} + +TSDB_CONV_CODE tsdb_chars_to_tinyint(int todb, const char *src, int8_t *dst) { + int64_t v; + TSDB_CONV_CODE code = tsdb_chars_to_bigint(todb, src, &v); + if (code!=TSDB_CONV_OK) return code; + + *dst = (int8_t)v; + + if (v==*dst) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_chars_to_smallint(int todb, const char *src, int16_t *dst) { + int64_t v; + TSDB_CONV_CODE code = tsdb_chars_to_bigint(todb, src, &v); + if (code!=TSDB_CONV_OK) return code; + + *dst = (int16_t)v; + + if (v==*dst) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_chars_to_int(int todb, const char *src, int32_t *dst) { + int64_t v; + TSDB_CONV_CODE code = tsdb_chars_to_bigint(todb, src, &v); + if (code!=TSDB_CONV_OK) return code; + + *dst = (int32_t)v; + + if (v==*dst) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_chars_to_bigint(int todb, const char *src, int64_t *dst) { + int bytes; + int n = sscanf(src, "%" PRId64 "%n", dst, &bytes); + + if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; + if (bytes==strlen(src)) { + return TSDB_CONV_OK; + } + + double v; + n = sscanf(src, "%lg%n", &v, &bytes); + if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; + if (bytes==strlen(src)) { + return TSDB_CONV_TRUNC_FRACTION; + } + + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_chars_to_ts(int todb, const char *src, int64_t *dst) { + int64_t v; + TSDB_CONV_CODE code = tsdb_chars_to_bigint(todb, src, &v); + if (code!=TSDB_CONV_OK) return code; + + *dst = v; + + if (v==*dst) { + time_t t = (time_t)(v / 1000); + struct tm tm = {0}; + if (localtime_r(&t, &tm)) return TSDB_CONV_OK; + } + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_chars_to_float(int todb, const char *src, float *dst) { + int bytes; + int n = sscanf(src, "%g%n", dst, &bytes); + + if (n==1 && bytes==strlen(src)) { + return TSDB_CONV_OK; + } + + return TSDB_CONV_CHAR_NOT_NUM; +} + +TSDB_CONV_CODE tsdb_chars_to_double(int todb, const char *src, double *dst) { + int bytes; + int n = sscanf(src, "%lg%n", dst, &bytes); + + if (n==1 && bytes==strlen(src)) { + return TSDB_CONV_OK; + } + + return TSDB_CONV_CHAR_NOT_NUM; +} + +TSDB_CONV_CODE tsdb_chars_to_char(int todb, const char *src, char *dst, size_t dlen) { + int n = snprintf(dst, dlen, "%s", src); + if (n= sizeof(buf)) { + plen = slen * 2 + 1; + p = (char*)malloc(plen); + if (!p) return TSDB_CONV_OOM; + } + + size_t n = wchars_to_chars2((const SQLWCHAR*)src, slen, (SQLCHAR*)p, plen); + + TSDB_CONV_CODE code = TSDB_CONV_OK; + do { + if (n<0) { + code = TSDB_CONV_CHAR_NOT_NUM; + break; + } + if (n>=plen) { + code = TSDB_CONV_CHAR_NOT_NUM; + break; + } + + p[n] = '\0'; + code = tsdb_chars_to_bit(todb, p, dst); + } while (0); + + if (p!=buf) { + free(p); + } + + return code; +} + +TSDB_CONV_CODE tsdb_wchars_to_tinyint(int todb, const unsigned char *src, size_t slen, int8_t *dst) { + char buf[4096]; + char *p = buf; + size_t plen = sizeof(buf); + if (slen * 2 + 1 >= sizeof(buf)) { + plen = slen * 2 + 1; + p = (char*)malloc(plen); + if (!p) return TSDB_CONV_OOM; + } + + size_t n = wchars_to_chars2((const SQLWCHAR*)src, slen, (SQLCHAR*)p, plen); + TSDB_CONV_CODE code = TSDB_CONV_OK; + do { + if (n<0) { + code = TSDB_CONV_CHAR_NOT_NUM; + break; + } + if (n>=sizeof(buf)) { + code = TSDB_CONV_CHAR_NOT_NUM; + break; + } + + buf[n] = '\0'; + code = tsdb_chars_to_tinyint(todb, buf, dst); + } while (0); + + if (p!=buf) { + free(p); + } + + return code; +} + + + + diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h new file mode 100644 index 0000000000..3ff7e24de2 --- /dev/null +++ b/src/connector/odbc/src/todbc_conv.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _todbc_conv_h_ +#define _todbc_conv_h_ + +#include +#include + +typedef enum { + TSDB_CONV_OK = 0, + TSDB_CONV_OOM, + TSDB_CONV_OOR, + TSDB_CONV_TRUNC_FRACTION, + TSDB_CONV_TRUNC, + TSDB_CONV_CHAR_NOT_NUM, +} TSDB_CONV_CODE; + +TSDB_CONV_CODE tsdb_int64_to_bit(int todb, int64_t src, int8_t *dst); +TSDB_CONV_CODE tsdb_int64_to_tinyint(int todb, int64_t src, int8_t *dst); +TSDB_CONV_CODE tsdb_int64_to_smallint(int todb, int64_t src, int16_t *dst); +TSDB_CONV_CODE tsdb_int64_to_int(int todb, int64_t src, int32_t *dst); +TSDB_CONV_CODE tsdb_int64_to_bigint(int todb, int64_t src, int64_t *dst); +TSDB_CONV_CODE tsdb_int64_to_ts(int todb, int64_t src, int64_t *dst); +TSDB_CONV_CODE tsdb_int64_to_float(int todb, int64_t src, float *dst); +TSDB_CONV_CODE tsdb_int64_to_double(int todb, int64_t src, double *dst); +TSDB_CONV_CODE tsdb_int64_to_char(int todb, int64_t src, char *dst, size_t dlen); + +TSDB_CONV_CODE tsdb_double_to_bit(int todb, double src, int8_t *dst); +TSDB_CONV_CODE tsdb_double_to_tinyint(int todb, double src, int8_t *dst); +TSDB_CONV_CODE tsdb_double_to_smallint(int todb, double src, int16_t *dst); +TSDB_CONV_CODE tsdb_double_to_int(int todb, double src, int32_t *dst); +TSDB_CONV_CODE tsdb_double_to_bigint(int todb, double src, int64_t *dst); +TSDB_CONV_CODE tsdb_double_to_ts(int todb, double src, int64_t *dst); + +TSDB_CONV_CODE tsdb_chars_to_bit(int todb, const char *src, int8_t *dst); +TSDB_CONV_CODE tsdb_chars_to_tinyint(int todb, const char *src, int8_t *dst); +TSDB_CONV_CODE tsdb_chars_to_smallint(int todb, const char *src, int16_t *dst); +TSDB_CONV_CODE tsdb_chars_to_int(int todb, const char *src, int32_t *dst); +TSDB_CONV_CODE tsdb_chars_to_bigint(int todb, const char *src, int64_t *dst); +TSDB_CONV_CODE tsdb_chars_to_ts(int todb, const char *src, int64_t *dst); +TSDB_CONV_CODE tsdb_chars_to_float(int todb, const char *src, float *dst); +TSDB_CONV_CODE tsdb_chars_to_double(int todb, const char *src, double *dst); +TSDB_CONV_CODE tsdb_chars_to_char(int todb, const char *src, char *dst, size_t dlen); + +TSDB_CONV_CODE tsdb_wchars_to_bit(int todb, const unsigned char *src, size_t slen, int8_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_tinyint(int todb, const unsigned char *src, size_t slen, int8_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_smallint(int todb, const unsigned char *src, size_t slen, int16_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_int(int todb, const unsigned char *src, size_t slen, int32_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_bigint(int todb, const unsigned char *src, size_t slen, int64_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_ts(int todb, const unsigned char *src, size_t slen, int64_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_float(int todb, const unsigned char *src, size_t slen, float *dst); +TSDB_CONV_CODE tsdb_wchars_to_double(int todb, const unsigned char *src, size_t slen, double *dst); +TSDB_CONV_CODE tsdb_wchars_to_char(int todb, const unsigned char *src, size_t slen, char *dst, size_t dlen); + +#endif // _todbc_conv_h_ + diff --git a/src/connector/odbc/src/todbc_util.c b/src/connector/odbc/src/todbc_util.c index b6b45d8120..378a2e1b75 100644 --- a/src/connector/odbc/src/todbc_util.c +++ b/src/connector/odbc/src/todbc_util.c @@ -236,3 +236,19 @@ SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes) return dst; } +size_t wchars_to_chars2(const SQLWCHAR *src, size_t slen, SQLCHAR *dst, size_t dlen) +{ + size_t consumed=0, generated=0; + int n = string_conv("UCS-2LE", "UTF-8", (const unsigned char*)src, slen, dst, dlen, &consumed, &generated); + if (n) return -1; + return generated; +} + +size_t chars_to_wchars2(const SQLCHAR *src, size_t slen, SQLWCHAR *dst, size_t dlen) +{ + size_t consumed=0, generated=0; + int n = string_conv("UTF-8", "UCS-2LE", (const unsigned char*)src, slen, (unsigned char*)dst, dlen, &consumed, &generated); + if (n) return -1; + return generated; +} + diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index 43264975b4..b3c307b85f 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -60,4 +60,8 @@ unsigned char* utf8_to_ucs4le(const char *utf8, size_t *chars); char* ucs4le_to_utf8(const unsigned char *ucs4le, size_t slen, size_t *chars); SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes); +size_t wchars_to_chars2(const SQLWCHAR *src, size_t slen, SQLCHAR *dst, size_t dlen); +size_t chars_to_wchars2(const SQLCHAR *src, size_t slen, SQLWCHAR *dst, size_t dlen); + #endif // _TODBC_UTIL_H_ + diff --git a/src/connector/odbc/tests/odbc.py b/src/connector/odbc/tests/odbc.py index d2de8f39c6..5218957fb9 100644 --- a/src/connector/odbc/tests/odbc.py +++ b/src/connector/odbc/tests/odbc.py @@ -118,3 +118,13 @@ while row: row = cursor.fetchone() cursor.close() +cursor = cnxn.cursor() +cursor.execute("create table db.f (ts timestamp, v1 bool)") +cursor.close() + +params = [ ('2020-10-20 00:00:00', 'acb') ] +cursor = cnxn.cursor() +cursor.fast_executemany = True +cursor.executemany("insert into db.f values (?, ?)", params) +cursor.close() + diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index bb111d2da0..ad8bce7ca7 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -355,20 +355,23 @@ TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_NULL, 0, 0x11A5, "value not TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_TYPE, 0, 0x11A6, "value type should be boolean, number or string") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, 0, 0x2101, "out of memory") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, 0, 0x2100, "out of memory") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, 0, 0x2101, "convertion not a valid literal input") TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_UNDEF, 0, 0x2102, "convertion undefined") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC, 0, 0x2103, "convertion truncated") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_SUPPORT, 0, 0x2104, "convertion not supported") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OUT_OF_RANGE, 0, 0x2105, "out of range") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NOT_SUPPORT, 0, 0x2106, "not supported yet") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_HANDLE, 0, 0x2107, "invalid handle") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_RESULT, 0, 0x2108, "no result set") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_FIELDS, 0, 0x2109, "no fields returned") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_CURSOR, 0, 0x2110, "invalid cursor") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_STATEMENT_NOT_READY, 0, 0x2111, "statement not ready") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONNECTION_BUSY, 0, 0x2112, "connection still busy") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_CONNSTR, 0, 0x2113, "bad connection string") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_ARG, 0, 0x2114, "bad argument") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC_FRAC, 0, 0x2103, "convertion fractional truncated") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC, 0, 0x2104, "convertion truncated") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_SUPPORT, 0, 0x2105, "convertion not supported") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_OOR, 0, 0x2106, "convertion numeric value out of range") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OUT_OF_RANGE, 0, 0x2107, "out of range") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NOT_SUPPORT, 0, 0x2108, "not supported yet") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_HANDLE, 0, 0x2109, "invalid handle") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_RESULT, 0, 0x210a, "no result set") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_FIELDS, 0, 0x210b, "no fields returned") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_CURSOR, 0, 0x210c, "invalid cursor") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_STATEMENT_NOT_READY, 0, 0x210d, "statement not ready") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONNECTION_BUSY, 0, 0x210e, "connection still busy") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_CONNSTR, 0, 0x210f, "bad connection string") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_ARG, 0, 0x2110, "bad argument") #ifdef TAOS_ERROR_C From 15364b8e78b97c1621056f620939b9a600013233 Mon Sep 17 00:00:00 2001 From: freemine Date: Thu, 22 Oct 2020 20:19:18 +0800 Subject: [PATCH 02/85] refactor --- src/client/src/tscPrepare.c | 3 +- src/connector/odbc/src/todbc.c | 1104 +++++---------------------- src/connector/odbc/src/todbc_conv.c | 333 +++++--- src/connector/odbc/src/todbc_conv.h | 79 +- src/connector/odbc/src/todbc_util.h | 2 - src/connector/odbc/tests/odbc.py | 4 +- 6 files changed, 474 insertions(+), 1051 deletions(-) diff --git a/src/client/src/tscPrepare.c b/src/client/src/tscPrepare.c index 1739e4348c..68f2ecbf0e 100644 --- a/src/client/src/tscPrepare.c +++ b/src/client/src/tscPrepare.c @@ -268,7 +268,6 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) { if (1) { // allow user bind param data with different type - short size = 0; union { int8_t v1; int16_t v2; @@ -600,7 +599,7 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) { if ((*bind->length) > (uintptr_t)param->bytes) { return TSDB_CODE_TSC_INVALID_VALUE; } - size = (short)*bind->length; + short size = (short)*bind->length; STR_WITH_SIZE_TO_VARSTR(data + param->offset, bind->buffer, size); return TSDB_CODE_SUCCESS; } break; diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 594d53d132..5ec8846128 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -144,7 +144,7 @@ do { \ D("%s: elapsed: [%.6f]s", #statement, delta); \ } while (0) -#define CHK_CONV(statement) \ +#define CHK_CONV(todb, statement) \ do { \ TSDB_CONV_CODE code = (statement); \ switch (code) { \ @@ -163,7 +163,7 @@ do { \ } break; \ case TSDB_CONV_TRUNC_FRACTION: { \ SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC_FRAC, ""); \ - return SQL_ERROR; \ + return todb ? SQL_ERROR : SQL_SUCCESS_WITH_INFO; \ } break; \ case TSDB_CONV_TRUNC: { \ SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ @@ -221,6 +221,10 @@ struct sql_s { uint64_t refcount; conn_t *conn; + iconv_t w2c; // wchar* -> char* + iconv_t u2c; // unicode -> char* + iconv_t u2w; // unicode -> wchar* + TAOS_STMT *stmt; param_bind_t *params; int n_params; @@ -250,6 +254,29 @@ static pthread_once_t init_once = PTHREAD_ONCE_INIT; static void init_routine(void); static int do_field_display_size(TAOS_FIELD *field); +static iconv_t sql_get_w2c(sql_t *sql) { + if (sql->w2c == (iconv_t)-1) { + sql->w2c = iconv_open("UTF-8", "UCS-2LE"); + } + + return sql->w2c; +} + +// static iconv_t sql_get_u2c(sql_t *sql) { +// if (sql->u2c == (iconv_t)-1) { +// sql->u2c = iconv_open("UTF-8", "UCS-4LE"); +// } +// +// return sql->u2c; +// } +// +// static iconv_t sql_get_u2w(sql_t *sql) { +// if (sql->u2w == (iconv_t)-1) { +// sql->u2w = iconv_open("UCS-2LE", "UCS-4LE"); +// } +// +// return sql->u2w; +// } static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) { @@ -456,6 +483,10 @@ static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle, break; } + sql->w2c = (iconv_t)-1; + sql->u2c = (iconv_t)-1; + sql->u2w = (iconv_t)-1; + sql->conn = conn; DASSERT(INC_REF(sql)>0); @@ -547,6 +578,20 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle, sql->conn = NULL; FREE_ERROR(sql); + + if (sql->w2c!=(iconv_t)-1) { + iconv_close(sql->w2c); + sql->w2c = (iconv_t)-1; + } + if (sql->u2c!=(iconv_t)-1) { + iconv_close(sql->u2c); + sql->u2c = (iconv_t)-1; + } + if (sql->u2w!=(iconv_t)-1) { + iconv_close(sql->u2w); + sql->u2w = (iconv_t)-1; + } + free(sql); return SQL_SUCCESS; @@ -753,64 +798,6 @@ SQLRETURN SQL_API SQLColAttribute(SQLHSTMT StatementHandle, return r; } -static SQLRETURN conv_tsdb_bool_to_c_bit(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_tinyint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_v1_to_c_tinyint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v2_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v4_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v8_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_v8_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_v8_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_v8_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_v8_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_f4_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4); -static SQLRETURN conv_tsdb_f4_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4); -static SQLRETURN conv_tsdb_f4_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4); -static SQLRETURN conv_tsdb_f4_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4); -static SQLRETURN conv_tsdb_f8_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8); -static SQLRETURN conv_tsdb_f8_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8); -static SQLRETURN conv_tsdb_f8_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8); -static SQLRETURN conv_tsdb_ts_to_c_v8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts); -static SQLRETURN conv_tsdb_ts_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts); -static SQLRETURN conv_tsdb_ts_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts); -static SQLRETURN conv_tsdb_ts_to_c_ts(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts); -static SQLRETURN conv_tsdb_bin_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const unsigned char *bin); -static SQLRETURN conv_tsdb_bin_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const unsigned char *bin); -static SQLRETURN conv_tsdb_str_to_c_bit(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_v1(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_v2(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_v4(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_v8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_f4(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_f8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); - static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValue, SQLLEN BufferLength, @@ -865,89 +852,45 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, target.soi = StrLen_or_Ind; switch (field->type) { - case TSDB_DATA_TYPE_BOOL: { - int8_t v = *(int8_t*)row; - if (v) v = 1; - switch (target.ct) { - case SQL_C_BIT: return conv_tsdb_bool_to_c_bit(sql, &target, field, v); - case SQL_C_TINYINT: return conv_tsdb_bool_to_c_tinyint(sql, &target, field, v); - case SQL_C_SHORT: return conv_tsdb_bool_to_c_short(sql, &target, field, v); - case SQL_C_LONG: return conv_tsdb_bool_to_c_long(sql, &target, field, v); - case SQL_C_SBIGINT: return conv_tsdb_bool_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_bool_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_bool_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_bool_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_bool_to_c_binary(sql, &target, field, v); - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_TINYINT: { - int8_t v = *(int8_t*)row; - switch (target.ct) { - case SQL_C_TINYINT: return conv_tsdb_v1_to_c_tinyint(sql, &target, field, v); - case SQL_C_SHORT: return conv_tsdb_v1_to_c_short(sql, &target, field, v); - case SQL_C_LONG: return conv_tsdb_v1_to_c_long(sql, &target, field, v); - case SQL_C_SBIGINT: return conv_tsdb_v1_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_v1_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_v1_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_v1_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_v1_to_c_binary(sql, &target, field, v); - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_SMALLINT: { - int16_t v = *(int16_t*)row; - switch (target.ct) { - case SQL_C_SHORT: return conv_tsdb_v2_to_c_short(sql, &target, field, v); - case SQL_C_LONG: return conv_tsdb_v2_to_c_long(sql, &target, field, v); - case SQL_C_SBIGINT: return conv_tsdb_v2_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_v2_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_v2_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_v2_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_v2_to_c_binary(sql, &target, field, v); - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_INT: { - int32_t v = *(int32_t*)row; - switch (target.ct) { - case SQL_C_LONG: return conv_tsdb_v4_to_c_long(sql, &target, field, v); - case SQL_C_SBIGINT: return conv_tsdb_v4_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_v4_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_v4_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_v4_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_v4_to_c_binary(sql, &target, field, v); - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_INT: case TSDB_DATA_TYPE_BIGINT: { - int64_t v = *(int64_t*)row; + int64_t v; + switch (field->type) { + case TSDB_DATA_TYPE_BOOL: v = *(int8_t*)row; if (v) v = 1; break; + case TSDB_DATA_TYPE_TINYINT: v = *(int8_t*)row; break; + case TSDB_DATA_TYPE_SMALLINT: v = *(int16_t*)row; break; + case TSDB_DATA_TYPE_INT: v = *(int32_t*)row; break; + case TSDB_DATA_TYPE_BIGINT: // fall through + default: v = *(int64_t*)row; break; + } switch (target.ct) { - case SQL_C_SBIGINT: return conv_tsdb_v8_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_v8_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_v8_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_v8_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_v8_to_c_binary(sql, &target, field, v); + case SQL_C_BIT: { + CHK_CONV(0, tsdb_int64_to_bit(v, TargetValue)); + } break; + case SQL_C_TINYINT: { + CHK_CONV(0, tsdb_int64_to_tinyint(v, TargetValue)); + } break; + case SQL_C_SHORT: { + CHK_CONV(0, tsdb_int64_to_smallint(v, TargetValue)); + } break; + case SQL_C_LONG: { + CHK_CONV(0, tsdb_int64_to_int(v, TargetValue)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(0, tsdb_int64_to_bigint(v, TargetValue)); + } break; + case SQL_C_FLOAT: { + CHK_CONV(0, tsdb_int64_to_float(v, TargetValue)); + } break; + case SQL_C_DOUBLE: { + CHK_CONV(0, tsdb_int64_to_double(v, TargetValue)); + } break; + case SQL_C_CHAR: { + CHK_CONV(0, tsdb_int64_to_char(v, TargetValue, BufferLength)); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -959,10 +902,17 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, case TSDB_DATA_TYPE_FLOAT: { float v = *(float*)row; switch (target.ct) { - case SQL_C_FLOAT: return conv_tsdb_f4_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_f4_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_f4_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_f4_to_c_binary(sql, &target, field, v); + case SQL_C_FLOAT: { + *(float*)TargetValue = v; + return SQL_SUCCESS; + } break; + case SQL_C_DOUBLE: { + *(double*)TargetValue = v; + return SQL_SUCCESS; + } break; + case SQL_C_CHAR: { + CHK_CONV(0, tsdb_double_to_char(v, TargetValue, BufferLength)); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -974,9 +924,13 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, case TSDB_DATA_TYPE_DOUBLE: { double v = *(double*)row; switch (target.ct) { - case SQL_C_DOUBLE: return conv_tsdb_f8_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_f8_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_f8_to_c_binary(sql, &target, field, v); + case SQL_C_DOUBLE: { + *(double*)TargetValue = v; + return SQL_SUCCESS; + } break; + case SQL_C_CHAR: { + CHK_CONV(0, tsdb_double_to_char(v, TargetValue, BufferLength)); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -999,11 +953,18 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, ts.second = tm.tm_sec; ts.fraction = v%1000 * 1000000; switch (target.ct) { - case SQL_C_SBIGINT: return conv_tsdb_ts_to_c_v8(sql, &target, field, &ts); - case SQL_C_CHAR: return conv_tsdb_ts_to_c_str(sql, &target, field, &ts); - case SQL_C_BINARY: return conv_tsdb_ts_to_c_bin(sql, &target, field, &ts); + case SQL_C_SBIGINT: { + *(int64_t*)TargetValue = v; + return SQL_SUCCESS; + } break; + case SQL_C_CHAR: { + CHK_CONV(0, tsdb_timestamp_to_char(ts, TargetValue, BufferLength)); + } break; case SQL_C_TYPE_TIMESTAMP: - case SQL_C_TIMESTAMP: return conv_tsdb_ts_to_c_ts(sql, &target, field, &ts); + case SQL_C_TIMESTAMP: { + *(SQL_TIMESTAMP_STRUCT*)TargetValue = ts; + return SQL_SUCCESS; + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -1013,10 +974,12 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, } } break; case TSDB_DATA_TYPE_BINARY: { - const unsigned char *bin = (const unsigned char *)row; + size_t field_bytes = field->bytes; + field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { - case SQL_C_CHAR: return conv_tsdb_bin_to_c_str(sql, &target, field, bin); - case SQL_C_BINARY: return conv_tsdb_bin_to_c_bin(sql, &target, field, bin); + case SQL_C_CHAR: { + CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, BufferLength)); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -1026,17 +989,12 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, } } break; case TSDB_DATA_TYPE_NCHAR: { - const char *str = (const char *)row; + size_t field_bytes = field->bytes; + field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { - case SQL_C_BIT: return conv_tsdb_str_to_c_bit(sql, &target, field, str); - case SQL_C_TINYINT: return conv_tsdb_str_to_c_v1(sql, &target, field, str); - case SQL_C_SHORT: return conv_tsdb_str_to_c_v2(sql, &target, field, str); - case SQL_C_LONG: return conv_tsdb_str_to_c_v4(sql, &target, field, str); - case SQL_C_SBIGINT: return conv_tsdb_str_to_c_v8(sql, &target, field, str); - case SQL_C_FLOAT: return conv_tsdb_str_to_c_f4(sql, &target, field, str); - case SQL_C_DOUBLE: return conv_tsdb_str_to_c_f8(sql, &target, field, str); - case SQL_C_CHAR: return conv_tsdb_str_to_c_str(sql, &target, field, str); - case SQL_C_BINARY: return conv_tsdb_str_to_c_bin(sql, &target, field, str); + case SQL_C_CHAR: { + CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, BufferLength)); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -1268,33 +1226,37 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_bit(1, *(int8_t*)paramValue, &bind->u.b)); + CHK_CONV(1, tsdb_int64_to_bit(*(int8_t*)paramValue, &bind->u.b)); } break; case SQL_C_TINYINT: case SQL_C_STINYINT: { - CHK_CONV(tsdb_int64_to_bit(1, *(int8_t*)paramValue, &bind->u.b)); + CHK_CONV(1, tsdb_int64_to_bit(*(int8_t*)paramValue, &bind->u.b)); } break; case SQL_C_SHORT: case SQL_C_SSHORT: { - CHK_CONV(tsdb_int64_to_bit(1, *(int16_t*)paramValue, &bind->u.b)); + CHK_CONV(1, tsdb_int64_to_bit(*(int16_t*)paramValue, &bind->u.b)); } break; case SQL_C_LONG: case SQL_C_SLONG: { - CHK_CONV(tsdb_int64_to_bit(1, *(int32_t*)paramValue, &bind->u.b)); + CHK_CONV(1, tsdb_int64_to_bit(*(int32_t*)paramValue, &bind->u.b)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_bit(1, *(int64_t*)paramValue, &bind->u.b)); + CHK_CONV(1, tsdb_int64_to_bit(*(int64_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_FLOAT: { + CHK_CONV(1, tsdb_double_to_bit(*(float*)paramValue, &bind->u.b)); + } break; + case SQL_C_DOUBLE: { + CHK_CONV(1, tsdb_double_to_bit(*(double*)paramValue, &bind->u.b)); } break; case SQL_C_CHAR: { - CHK_CONV(tsdb_chars_to_bit(1, (const char *)paramValue, &bind->u.b)); + CHK_CONV(1, tsdb_chars_to_bit((const char *)paramValue, *soi, &bind->u.b)); } break; case SQL_C_WCHAR: { - CHK_CONV(tsdb_wchars_to_bit(1, (const unsigned char*)paramValue, *soi, &bind->u.b)); + CHK_CONV(1, tsdb_wchars_to_bit(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.b)); } break; case SQL_C_USHORT: case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: case SQL_C_UTINYINT: case SQL_C_UBIGINT: case SQL_C_BINARY: @@ -1322,28 +1284,28 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_tinyint(1, *(int8_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int8_t*)paramValue, &bind->u.v1)); } break; case SQL_C_STINYINT: case SQL_C_TINYINT: { - CHK_CONV(tsdb_int64_to_tinyint(1, *(int8_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int8_t*)paramValue, &bind->u.v1)); } break; case SQL_C_SSHORT: case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_tinyint(1, *(int16_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int16_t*)paramValue, &bind->u.v1)); } break; case SQL_C_SLONG: case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_tinyint(1, *(int32_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int32_t*)paramValue, &bind->u.v1)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_tinyint(1, *(int64_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int64_t*)paramValue, &bind->u.v1)); } break; case SQL_C_CHAR: { - CHK_CONV(tsdb_chars_to_tinyint(1, (const char*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_chars_to_tinyint((const char*)paramValue, *soi, &bind->u.v1)); } break; case SQL_C_WCHAR: { - CHK_CONV(tsdb_wchars_to_tinyint(1, (const unsigned char*)paramValue, *soi, &bind->u.v1)); + CHK_CONV(1, tsdb_wchars_to_tinyint(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.v1)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1376,28 +1338,28 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_smallint(1, *(int8_t*)paramValue, &bind->u.v2)); + CHK_CONV(1, tsdb_int64_to_smallint(*(int8_t*)paramValue, &bind->u.v2)); } break; case SQL_C_STINYINT: case SQL_C_TINYINT: { - CHK_CONV(tsdb_int64_to_smallint(1, *(int8_t*)paramValue, &bind->u.v2)); + CHK_CONV(1, tsdb_int64_to_smallint(*(int8_t*)paramValue, &bind->u.v2)); } break; case SQL_C_SSHORT: case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_smallint(1, *(int16_t*)paramValue, &bind->u.v2)); + CHK_CONV(1, tsdb_int64_to_smallint(*(int16_t*)paramValue, &bind->u.v2)); } break; case SQL_C_SLONG: case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_smallint(1, *(int32_t*)paramValue, &bind->u.v2)); + CHK_CONV(1, tsdb_int64_to_smallint(*(int32_t*)paramValue, &bind->u.v2)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_smallint(1, *(int64_t*)paramValue, &bind->u.v2)); + CHK_CONV(1, tsdb_int64_to_smallint(*(int64_t*)paramValue, &bind->u.v2)); } break; case SQL_C_CHAR: { - CHK_CONV(tsdb_chars_to_smallint(1, (const char*)paramValue, &bind->u.v2)); + CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, *soi, &bind->u.v2)); } break; case SQL_C_WCHAR: { - CHK_CONV(tsdb_wchars_to_smallint(1, (const unsigned char*)paramValue, *soi, &bind->u.v2)); + CHK_CONV(1, tsdb_wchars_to_smallint(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.v2)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1430,28 +1392,28 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_int(1, *(int8_t*)paramValue, &bind->u.v4)); + CHK_CONV(1, tsdb_int64_to_int(*(int8_t*)paramValue, &bind->u.v4)); } break; case SQL_C_STINYINT: case SQL_C_TINYINT: { - CHK_CONV(tsdb_int64_to_int(1, *(int8_t*)paramValue, &bind->u.v4)); + CHK_CONV(1, tsdb_int64_to_int(*(int8_t*)paramValue, &bind->u.v4)); } break; case SQL_C_SSHORT: case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_int(1, *(int16_t*)paramValue, &bind->u.v4)); + CHK_CONV(1, tsdb_int64_to_int(*(int16_t*)paramValue, &bind->u.v4)); } break; case SQL_C_SLONG: case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_int(1, *(int32_t*)paramValue, &bind->u.v4)); + CHK_CONV(1, tsdb_int64_to_int(*(int32_t*)paramValue, &bind->u.v4)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_int(1, *(int64_t*)paramValue, &bind->u.v4)); + CHK_CONV(1, tsdb_int64_to_int(*(int64_t*)paramValue, &bind->u.v4)); } break; case SQL_C_CHAR: { - CHK_CONV(tsdb_chars_to_int(1, (const char*)paramValue, &bind->u.v4)); + CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, *soi, &bind->u.v4)); } break; case SQL_C_WCHAR: { - CHK_CONV(tsdb_wchars_to_int(1, (const unsigned char*)paramValue, *soi, &bind->u.v4)); + CHK_CONV(1, tsdb_wchars_to_int(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.v4)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1484,28 +1446,28 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_bigint(1, *(int8_t*)paramValue, &bind->u.v8)); + CHK_CONV(1, tsdb_int64_to_bigint(*(int8_t*)paramValue, &bind->u.v8)); } break; case SQL_C_STINYINT: case SQL_C_TINYINT: { - CHK_CONV(tsdb_int64_to_bigint(1, *(int8_t*)paramValue, &bind->u.v8)); + CHK_CONV(1, tsdb_int64_to_bigint(*(int8_t*)paramValue, &bind->u.v8)); } break; case SQL_C_SSHORT: case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_bigint(1, *(int16_t*)paramValue, &bind->u.v8)); + CHK_CONV(1, tsdb_int64_to_bigint(*(int16_t*)paramValue, &bind->u.v8)); } break; case SQL_C_SLONG: case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_bigint(1, *(int32_t*)paramValue, &bind->u.v8)); + CHK_CONV(1, tsdb_int64_to_bigint(*(int32_t*)paramValue, &bind->u.v8)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_bigint(1, *(int64_t*)paramValue, &bind->u.v8)); + CHK_CONV(1, tsdb_int64_to_bigint(*(int64_t*)paramValue, &bind->u.v8)); } break; case SQL_C_CHAR: { - CHK_CONV(tsdb_chars_to_bigint(1, (const char*)paramValue, &bind->u.v8)); + CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, *soi, &bind->u.v8)); } break; case SQL_C_WCHAR: { - CHK_CONV(tsdb_wchars_to_bigint(1, (const unsigned char*)paramValue, *soi, &bind->u.v8)); + CHK_CONV(1, tsdb_wchars_to_bigint(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.v8)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1538,37 +1500,39 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_float(1, *(int8_t*)paramValue, &bind->u.f4)); + CHK_CONV(1, tsdb_int64_to_float(*(int8_t*)paramValue, &bind->u.f4)); } break; case SQL_C_STINYINT: case SQL_C_TINYINT: { - CHK_CONV(tsdb_int64_to_float(1, *(int8_t*)paramValue, &bind->u.f4)); + CHK_CONV(1, tsdb_int64_to_float(*(int8_t*)paramValue, &bind->u.f4)); } break; case SQL_C_SSHORT: case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_float(1, *(int16_t*)paramValue, &bind->u.f4)); + CHK_CONV(1, tsdb_int64_to_float(*(int16_t*)paramValue, &bind->u.f4)); } break; case SQL_C_SLONG: case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_float(1, *(int32_t*)paramValue, &bind->u.f4)); + CHK_CONV(1, tsdb_int64_to_float(*(int32_t*)paramValue, &bind->u.f4)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_float(1, *(int64_t*)paramValue, &bind->u.f4)); + CHK_CONV(1, tsdb_int64_to_float(*(int64_t*)paramValue, &bind->u.f4)); } break; case SQL_C_FLOAT: { bind->u.f4 = *(float*)paramValue; } break; + case SQL_C_DOUBLE: { + bind->u.f4 = (float)*(double*)paramValue; + } break; case SQL_C_CHAR: { - CHK_CONV(tsdb_chars_to_float(1, (const char*)paramValue, &bind->u.f4)); + CHK_CONV(1, tsdb_chars_to_float((const char*)paramValue, *soi, &bind->u.f4)); } break; case SQL_C_WCHAR: { - CHK_CONV(tsdb_wchars_to_float(1, (const unsigned char*)paramValue, *soi, &bind->u.f4)); + CHK_CONV(1, tsdb_wchars_to_float(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.f4)); } break; case SQL_C_USHORT: case SQL_C_ULONG: case SQL_C_UTINYINT: case SQL_C_UBIGINT: - case SQL_C_DOUBLE: case SQL_C_BINARY: case SQL_C_DATE: case SQL_C_TIME: @@ -1594,22 +1558,22 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_double(1, *(int8_t*)paramValue, &bind->u.f8)); + CHK_CONV(1, tsdb_int64_to_double(*(int8_t*)paramValue, &bind->u.f8)); } break; case SQL_C_STINYINT: case SQL_C_TINYINT: { - CHK_CONV(tsdb_int64_to_double(1, *(int8_t*)paramValue, &bind->u.f8)); + CHK_CONV(1, tsdb_int64_to_double(*(int8_t*)paramValue, &bind->u.f8)); } break; case SQL_C_SSHORT: case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_double(1, *(int16_t*)paramValue, &bind->u.f8)); + CHK_CONV(1, tsdb_int64_to_double(*(int16_t*)paramValue, &bind->u.f8)); } break; case SQL_C_SLONG: case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_double(1, *(int32_t*)paramValue, &bind->u.f8)); + CHK_CONV(1, tsdb_int64_to_double(*(int32_t*)paramValue, &bind->u.f8)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_double(1, *(int64_t*)paramValue, &bind->u.f8)); + CHK_CONV(1, tsdb_int64_to_double(*(int64_t*)paramValue, &bind->u.f8)); } break; case SQL_C_FLOAT: { bind->u.f8 = *(float*)paramValue; @@ -1618,10 +1582,10 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->u.f8 = *(double*)paramValue; } break; case SQL_C_CHAR: { - CHK_CONV(tsdb_chars_to_double(1, (const char*)paramValue, &bind->u.f8)); + CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, *soi, &bind->u.f8)); } break; case SQL_C_WCHAR: { - CHK_CONV(tsdb_wchars_to_double(1, (const unsigned char*)paramValue, *soi, &bind->u.f8)); + CHK_CONV(1, tsdb_wchars_to_double(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.f8)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -2281,7 +2245,7 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, } break; case TSDB_DATA_TYPE_BINARY: { - *DataType = SQL_BINARY; + *DataType = SQL_CHAR; if (ColumnSize) *ColumnSize -= VARSTR_HEADER_SIZE; } break; @@ -2474,709 +2438,5 @@ static int do_field_display_size(TAOS_FIELD *field) { return 10; } -// convertion from TSDB_DATA_TYPE_XXX to SQL_C_XXX -static SQLRETURN conv_tsdb_bool_to_c_bit(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int8_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_tinyint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int8_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int16_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int32_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int64_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - float v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - double v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - DASSERT(target->len>0); - *target->soi = 1; - target->ptr[0] = '0' + b; - if (target->len>1) { - target->ptr[1] = '\0'; - } - - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - DASSERT(target->len>0); - *target->soi = 1; - target->ptr[0] = '0' + b; - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_tinyint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - int8_t v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - int16_t v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - int32_t v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - int64_t v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - float v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - double v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v1); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_TINYINT -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v1_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v1); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_TINYINT -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v2_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - int16_t v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - int32_t v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - int64_t v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - float v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - double v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v2); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_SMALLINT -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v2_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v2); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_SMALLINT -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_v4_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - int32_t v = v4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v4_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - int64_t v = v4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v4_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - float v = v4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v4_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - double v = v4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v4_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v4); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_INTEGER -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v4_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v4); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_INTEGER -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_v8_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - int64_t v = v8; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v8_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - float v = v8; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v8_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - double v = v8; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v8_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%" PRId64 "", v8); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_BIGINT -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v8_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%" PRId64 "", v8); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_BIGINT -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_f4_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4) -{ - float v = f4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_f4_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4) -{ - double v = f4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_f4_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%g", f4); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_FLOAT -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_f4_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%g", f4); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_FLOAT -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_f8_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8) -{ - double v = f8; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_f8_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%.6f", f8); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_DOUBLE -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_f8_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%g", f8); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_DOUBLE -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_ts_to_c_v8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts) -{ - struct tm tm = {0}; - tm.tm_sec = ts->second; - tm.tm_min = ts->minute; - tm.tm_hour = ts->hour; - tm.tm_mday = ts->day; - tm.tm_mon = ts->month - 1; - tm.tm_year = ts->year - 1900; - time_t t = mktime(&tm); - DASSERT(sizeof(t) == sizeof(int64_t)); - int64_t v = (int64_t)t; - v *= 1000; - v += ts->fraction / 1000000; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_ts_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts) -{ - struct tm tm = {0}; - tm.tm_sec = ts->second; - tm.tm_min = ts->minute; - tm.tm_hour = ts->hour; - tm.tm_mday = ts->day; - tm.tm_mon = ts->month - 1; - tm.tm_year = ts->year - 1900; - - char buf[64]; - int n = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); - DASSERT(n < sizeof(buf)); - - *target->soi = n; - - unsigned int fraction = ts->fraction; - fraction /= 1000000; - snprintf(target->ptr, target->len, "%s.%03d", buf, fraction); - if (target->soi) *target->soi = strlen((const char*)target->ptr); - - if (n <= target->len) { - return SQL_SUCCESS; - } - - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_TIMESTAMP -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_ts_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts) -{ - struct tm tm = {0}; - tm.tm_sec = ts->second; - tm.tm_min = ts->minute; - tm.tm_hour = ts->hour; - tm.tm_mday = ts->day; - tm.tm_mon = ts->month - 1; - tm.tm_year = ts->year - 1900; - - char buf[64]; - int n = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); - DASSERT(n < sizeof(buf)); - - unsigned int fraction = ts->fraction; - fraction /= 1000000; - snprintf(target->ptr, target->len, "%s.%03d", buf, fraction); - if (target->soi) *target->soi = strlen((const char*)target->ptr); - - if (n <= target->len) { - return SQL_SUCCESS; - } - - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_TIMESTAMP -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_ts_to_c_ts(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts) -{ - DASSERT(target->len == sizeof(*ts)); - memcpy(target->ptr, ts, sizeof(*ts)); - *target->soi = target->len; - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bin_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const unsigned char *bin) -{ - if (target->len<1) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - size_t field_bytes = field->bytes - VARSTR_HEADER_SIZE; - size_t n = strnlen((const char*)bin, field_bytes); - - if (n < target->len) { - memcpy(target->ptr, bin, n); - target->ptr[n] = '\0'; - *target->soi = n; - return SQL_SUCCESS; - } - n = target->len - 1; - *target->soi = n; - if (n > 0) { - memcpy(target->ptr, bin, n-1); - target->ptr[n-1] = '\0'; - } - SET_ERROR(sql, "01004", TSDB_CODE_ODBC_CONV_TRUNC, ""); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_bin_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const unsigned char *bin) -{ - if (target->len<1) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - size_t field_bytes = field->bytes - VARSTR_HEADER_SIZE; - size_t n = strnlen((const char*)bin, field_bytes); - - if (n <= target->len) { - memcpy(target->ptr, bin, n); - if (nlen) target->ptr[n] = '\0'; - *target->soi = n; - return SQL_SUCCESS; - } - - n = target->len; - memcpy(target->ptr, bin, n); - *target->soi = n; - SET_ERROR(sql, "01004", TSDB_CODE_ODBC_CONV_TRUNC, ""); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_bit(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int8_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 1; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - - if (strcmp(buf, str)==0) { - if (v==0 || v==1) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; - } - - if (f8>0 || f8<2) { - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; - } - - if (f8<0 || f8>2) { - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_v1(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int8_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 1; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_TINYINT"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - - if (strcmp(buf, str)==0) return SQL_SUCCESS; - - if (f8>INT8_MAX || f8 SQL_C_TINYINT"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_TINYINT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_v2(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int16_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 2; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_SHORT"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - - if (strcmp(buf, str)==0) return SQL_SUCCESS; - - if (f8>INT16_MAX || f8 SQL_C_SHORT"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_SHORT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_v4(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int32_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 4; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_LONG"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - - if (strcmp(buf, str)==0) return SQL_SUCCESS; - - if (f8>INT32_MAX || f8 SQL_C_LONG"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_LONG"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_v8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int64_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 8; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_SBIGINT"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%" PRId64 "", v); - - if (strcmp(buf, str)==0) return SQL_SUCCESS; - - if (f8>INT64_MAX || f8 SQL_C_SBIGINT"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_SBIGINT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_f4(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - float v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 4; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_FLOAT"); - return SQL_SUCCESS_WITH_INFO; - } - - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_str_to_c_f8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - float v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 8; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_DOUBLE"); - return SQL_SUCCESS_WITH_INFO; - } - - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_str_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - return conv_tsdb_bin_to_c_str(sql, target, field, (const unsigned char*)str); -} - -static SQLRETURN conv_tsdb_str_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - return conv_tsdb_bin_to_c_bin(sql, target, field, (const unsigned char*)str); -} - - diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index ccfead3eb3..c4e0ff653f 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -17,43 +17,102 @@ #include "todbc_util.h" +#include #include #include #include #include +typedef struct buf_s buf_t; + +struct buf_s { + char buf[1024*16+1]; + + char *ptr; +}; + +static char* buf_init(buf_t *buf, size_t len); +static void buf_clean(buf_t *buf); + +static char* buf_init(buf_t *buf, size_t len) { + if (len>sizeof(buf->buf)) { + buf->ptr = (char*)malloc(len); + } else if (len>0) { + buf->ptr = &buf->buf[0]; + } else { + buf->ptr = NULL; + } + return buf->ptr; +} + +static void buf_clean(buf_t *buf) { + if (buf->ptr && buf->ptr != buf->buf) { + free(buf->ptr); + buf->ptr = NULL; + } +} + +TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen) { + if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; + + char *s = (char*)src; + char *d = (char*)dst; + size_t sl = *slen; + size_t dl = *dlen; + + int n = iconv(cnv, &s, &sl, &d, &dl); + int e = errno; + if (dl) *d = '\0'; // what if all consumed? + + *slen = sl; + *dlen = dl; + + if (e==0) { + if (n) return TSDB_CONV_BAD_CHAR; + return TSDB_CONV_OK; + } + + iconv(cnv, NULL, NULL, NULL, NULL); + + switch (e) { + case E2BIG: return TSDB_CONV_TRUNC; + case EILSEQ: return TSDB_CONV_BAD_CHAR; + case EINVAL: return TSDB_CONV_BAD_CHAR; + default: return TSDB_CONV_GENERAL; + } +} // src: int -TSDB_CONV_CODE tsdb_int64_to_bit(int todb, int64_t src, int8_t *dst) { +TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst) { *dst = (int8_t)src; if (src==0 || src==1) return TSDB_CONV_OK; return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_int64_to_tinyint(int todb, int64_t src, int8_t *dst) { +TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst) { *dst = (int8_t)src; if (src == *dst) return TSDB_CONV_OK; return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_int64_to_smallint(int todb, int64_t src, int16_t *dst) { +TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst) { *dst = (int16_t)src; if (src == *dst) return TSDB_CONV_OK; return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_int64_to_int(int todb, int64_t src, int32_t *dst) { +TSDB_CONV_CODE tsdb_int64_to_int(int64_t src, int32_t *dst) { *dst = (int32_t)src; if (src == *dst) return TSDB_CONV_OK; return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_int64_to_bigint(int todb, int64_t src, int64_t *dst) { +TSDB_CONV_CODE tsdb_int64_to_bigint(int64_t src, int64_t *dst) { *dst = src; return TSDB_CONV_OK; } -TSDB_CONV_CODE tsdb_int64_to_ts(int todb, int64_t src, int64_t *dst) { +TSDB_CONV_CODE tsdb_int64_to_ts(int64_t src, int64_t *dst) { *dst = src; time_t t = (time_t)(src / 1000); @@ -63,7 +122,7 @@ TSDB_CONV_CODE tsdb_int64_to_ts(int todb, int64_t src, int64_t *dst) { return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_int64_to_float(int todb, int64_t src, float *dst) { +TSDB_CONV_CODE tsdb_int64_to_float(int64_t src, float *dst) { *dst = (float)src; int64_t v = (int64_t)*dst; @@ -72,7 +131,7 @@ TSDB_CONV_CODE tsdb_int64_to_float(int todb, int64_t src, float *dst) { return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_int64_to_double(int todb, int64_t src, double *dst) { +TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst) { *dst = (double)src; int64_t v = (int64_t)*dst; @@ -81,7 +140,7 @@ TSDB_CONV_CODE tsdb_int64_to_double(int todb, int64_t src, double *dst) { return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_int64_to_char(int todb, int64_t src, char *dst, size_t dlen) { +TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen) { int n = snprintf(dst, dlen, "%" PRId64 "", src); if (n=2) return TSDB_CONV_OOR; @@ -102,7 +161,7 @@ TSDB_CONV_CODE tsdb_double_to_bit(int todb, double src, int8_t *dst) { return TSDB_CONV_TRUNC; } -TSDB_CONV_CODE tsdb_double_to_tinyint(int todb, double src, int8_t *dst) { +TSDB_CONV_CODE tsdb_double_to_tinyint(double src, int8_t *dst) { *dst = (int8_t)src; if (srcSCHAR_MAX) return TSDB_CONV_OOR; @@ -114,7 +173,7 @@ TSDB_CONV_CODE tsdb_double_to_tinyint(int todb, double src, int8_t *dst) { return TSDB_CONV_TRUNC; } -TSDB_CONV_CODE tsdb_double_to_smallint(int todb, double src, int16_t *dst) { +TSDB_CONV_CODE tsdb_double_to_smallint(double src, int16_t *dst) { *dst = (int16_t)src; if (srcSHRT_MAX) return TSDB_CONV_OOR; @@ -126,7 +185,7 @@ TSDB_CONV_CODE tsdb_double_to_smallint(int todb, double src, int16_t *dst) { return TSDB_CONV_TRUNC; } -TSDB_CONV_CODE tsdb_double_to_int(int todb, double src, int32_t *dst) { +TSDB_CONV_CODE tsdb_double_to_int(double src, int32_t *dst) { *dst = (int32_t)src; if (srcLONG_MAX) return TSDB_CONV_OOR; @@ -138,7 +197,7 @@ TSDB_CONV_CODE tsdb_double_to_int(int todb, double src, int32_t *dst) { return TSDB_CONV_TRUNC; } -TSDB_CONV_CODE tsdb_double_to_bigint(int todb, double src, int64_t *dst) { +TSDB_CONV_CODE tsdb_double_to_bigint(double src, int64_t *dst) { *dst = (int64_t)src; if (srcLLONG_MAX) return TSDB_CONV_OOR; @@ -150,8 +209,8 @@ TSDB_CONV_CODE tsdb_double_to_bigint(int todb, double src, int64_t *dst) { return TSDB_CONV_TRUNC; } -TSDB_CONV_CODE tsdb_double_to_ts(int todb, double src, int64_t *dst) { - TSDB_CONV_CODE code = tsdb_double_to_bigint(todb, src, dst); +TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst) { + TSDB_CONV_CODE code = tsdb_double_to_bigint(src, dst); if (code==TSDB_CONV_OK || code==TSDB_CONV_TRUNC_FRACTION) { int64_t v = (int64_t)src; @@ -165,8 +224,29 @@ TSDB_CONV_CODE tsdb_double_to_ts(int todb, double src, int64_t *dst) { return code; } +TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen) { + int n = snprintf(dst, dlen, "%lg", src); + + if (n=19) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + // src: chars -TSDB_CONV_CODE tsdb_chars_to_bit(int todb, const char *src, int8_t *dst) { +TSDB_CONV_CODE tsdb_chars_to_bit(const char *src, size_t smax, int8_t *dst) { if (strcmp(src, "0")==0) { *dst = 0; return TSDB_CONV_OK; @@ -189,11 +269,11 @@ TSDB_CONV_CODE tsdb_chars_to_bit(int todb, const char *src, int8_t *dst) { return TSDB_CONV_TRUNC_FRACTION; } -TSDB_CONV_CODE tsdb_chars_to_tinyint(int todb, const char *src, int8_t *dst) { +TSDB_CONV_CODE tsdb_chars_to_tinyint(const char *src, size_t smax, int8_t *dst) { int64_t v; - TSDB_CONV_CODE code = tsdb_chars_to_bigint(todb, src, &v); + TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); if (code!=TSDB_CONV_OK) return code; - + *dst = (int8_t)v; if (v==*dst) return TSDB_CONV_OK; @@ -201,11 +281,11 @@ TSDB_CONV_CODE tsdb_chars_to_tinyint(int todb, const char *src, int8_t *dst) { return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_chars_to_smallint(int todb, const char *src, int16_t *dst) { +TSDB_CONV_CODE tsdb_chars_to_smallint(const char *src, size_t smax, int16_t *dst) { int64_t v; - TSDB_CONV_CODE code = tsdb_chars_to_bigint(todb, src, &v); + TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); if (code!=TSDB_CONV_OK) return code; - + *dst = (int16_t)v; if (v==*dst) return TSDB_CONV_OK; @@ -213,11 +293,11 @@ TSDB_CONV_CODE tsdb_chars_to_smallint(int todb, const char *src, int16_t *dst) { return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_chars_to_int(int todb, const char *src, int32_t *dst) { +TSDB_CONV_CODE tsdb_chars_to_int(const char *src, size_t smax, int32_t *dst) { int64_t v; - TSDB_CONV_CODE code = tsdb_chars_to_bigint(todb, src, &v); + TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); if (code!=TSDB_CONV_OK) return code; - + *dst = (int32_t)v; if (v==*dst) return TSDB_CONV_OK; @@ -225,7 +305,7 @@ TSDB_CONV_CODE tsdb_chars_to_int(int todb, const char *src, int32_t *dst) { return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_chars_to_bigint(int todb, const char *src, int64_t *dst) { +TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst) { int bytes; int n = sscanf(src, "%" PRId64 "%n", dst, &bytes); @@ -244,11 +324,11 @@ TSDB_CONV_CODE tsdb_chars_to_bigint(int todb, const char *src, int64_t *dst) { return TSDB_CONV_OK; } -TSDB_CONV_CODE tsdb_chars_to_ts(int todb, const char *src, int64_t *dst) { +TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst) { int64_t v; - TSDB_CONV_CODE code = tsdb_chars_to_bigint(todb, src, &v); + TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); if (code!=TSDB_CONV_OK) return code; - + *dst = v; if (v==*dst) { @@ -260,7 +340,7 @@ TSDB_CONV_CODE tsdb_chars_to_ts(int todb, const char *src, int64_t *dst) { return TSDB_CONV_OOR; } -TSDB_CONV_CODE tsdb_chars_to_float(int todb, const char *src, float *dst) { +TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst) { int bytes; int n = sscanf(src, "%g%n", dst, &bytes); @@ -271,7 +351,7 @@ TSDB_CONV_CODE tsdb_chars_to_float(int todb, const char *src, float *dst) { return TSDB_CONV_CHAR_NOT_NUM; } -TSDB_CONV_CODE tsdb_chars_to_double(int todb, const char *src, double *dst) { +TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst) { int bytes; int n = sscanf(src, "%lg%n", dst, &bytes); @@ -282,82 +362,155 @@ TSDB_CONV_CODE tsdb_chars_to_double(int todb, const char *src, double *dst) { return TSDB_CONV_CHAR_NOT_NUM; } -TSDB_CONV_CODE tsdb_chars_to_char(int todb, const char *src, char *dst, size_t dlen) { - int n = snprintf(dst, dlen, "%s", src); - if (n= sizeof(buf)) { - plen = slen * 2 + 1; - p = (char*)malloc(plen); - if (!p) return TSDB_CONV_OOM; +TSDB_CONV_CODE tsdb_wchars_to_bit(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst) { + if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; + + size_t len = smax * 2; + buf_t buf; + buf_init(&buf, len+1); + if (!buf.ptr) return TSDB_CONV_OOM; + + size_t dmax = len + 1; + TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); + if (code==TSDB_CONV_OK) { + code = tsdb_chars_to_bit(buf.ptr, len+1-dmax, dst); } - size_t n = wchars_to_chars2((const SQLWCHAR*)src, slen, (SQLCHAR*)p, plen); - - TSDB_CONV_CODE code = TSDB_CONV_OK; - do { - if (n<0) { - code = TSDB_CONV_CHAR_NOT_NUM; - break; - } - if (n>=plen) { - code = TSDB_CONV_CHAR_NOT_NUM; - break; - } - - p[n] = '\0'; - code = tsdb_chars_to_bit(todb, p, dst); - } while (0); - - if (p!=buf) { - free(p); - } + buf_clean(&buf); return code; } -TSDB_CONV_CODE tsdb_wchars_to_tinyint(int todb, const unsigned char *src, size_t slen, int8_t *dst) { - char buf[4096]; - char *p = buf; - size_t plen = sizeof(buf); - if (slen * 2 + 1 >= sizeof(buf)) { - plen = slen * 2 + 1; - p = (char*)malloc(plen); - if (!p) return TSDB_CONV_OOM; +TSDB_CONV_CODE tsdb_wchars_to_tinyint(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst) { + if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; + + size_t len = smax * 2; + buf_t buf; + buf_init(&buf, len+1); + if (!buf.ptr) return TSDB_CONV_OOM; + + size_t dmax = len + 1; + TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); + if (code==TSDB_CONV_OK) { + code = tsdb_chars_to_tinyint(buf.ptr, len+1-dmax, dst); } - size_t n = wchars_to_chars2((const SQLWCHAR*)src, slen, (SQLCHAR*)p, plen); - TSDB_CONV_CODE code = TSDB_CONV_OK; - do { - if (n<0) { - code = TSDB_CONV_CHAR_NOT_NUM; - break; - } - if (n>=sizeof(buf)) { - code = TSDB_CONV_CHAR_NOT_NUM; - break; - } - - buf[n] = '\0'; - code = tsdb_chars_to_tinyint(todb, buf, dst); - } while (0); - - if (p!=buf) { - free(p); - } + buf_clean(&buf); return code; } +TSDB_CONV_CODE tsdb_wchars_to_smallint(iconv_t cnv, const unsigned char *src, size_t smax, int16_t *dst) { + if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; + + size_t len = smax * 2; + buf_t buf; + buf_init(&buf, len+1); + if (!buf.ptr) return TSDB_CONV_OOM; + + size_t dmax = len + 1; + TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); + if (code==TSDB_CONV_OK) { + code = tsdb_chars_to_smallint(buf.ptr, len+1-dmax, dst); + } + + buf_clean(&buf); + + return code; +} + +TSDB_CONV_CODE tsdb_wchars_to_int(iconv_t cnv, const unsigned char *src, size_t smax, int32_t *dst) { + if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; + + size_t len = smax * 2; + buf_t buf; + buf_init(&buf, len+1); + if (!buf.ptr) return TSDB_CONV_OOM; + + size_t dmax = len + 1; + TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); + if (code==TSDB_CONV_OK) { + code = tsdb_chars_to_int(buf.ptr, len+1-dmax, dst); + } + + buf_clean(&buf); + + return code; +} + +TSDB_CONV_CODE tsdb_wchars_to_bigint(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst) { + if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; + + size_t len = smax * 2; + buf_t buf; + buf_init(&buf, len+1); + if (!buf.ptr) return TSDB_CONV_OOM; + + size_t dmax = len + 1; + TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); + if (code==TSDB_CONV_OK) { + code = tsdb_chars_to_bigint(buf.ptr, len+1-dmax, dst); + } + + buf_clean(&buf); + + return code; +} + +TSDB_CONV_CODE tsdb_wchars_to_ts(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst) { + return tsdb_wchars_to_bigint(cnv, src, smax, dst); +} + +TSDB_CONV_CODE tsdb_wchars_to_float(iconv_t cnv, const unsigned char *src, size_t smax, float *dst) { + if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; + + size_t len = smax * 2; + buf_t buf; + buf_init(&buf, len+1); + if (!buf.ptr) return TSDB_CONV_OOM; + + size_t dmax = len + 1; + TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); + if (code==TSDB_CONV_OK) { + code = tsdb_chars_to_float(buf.ptr, len+1-dmax, dst); + } + + buf_clean(&buf); + + return code; +} + +TSDB_CONV_CODE tsdb_wchars_to_double(iconv_t cnv, const unsigned char *src, size_t smax, double *dst) { + if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; + + size_t len = smax * 2; + buf_t buf; + buf_init(&buf, len+1); + if (!buf.ptr) return TSDB_CONV_OOM; + + size_t dmax = len + 1; + TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); + if (code==TSDB_CONV_OK) { + code = tsdb_chars_to_double(buf.ptr, len+1-dmax, dst); + } + + buf_clean(&buf); + + return code; +} + +TSDB_CONV_CODE tsdb_wchars_to_char(iconv_t cnv, const unsigned char *src, size_t smax, char *dst, size_t dmax) { + return tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)dst, &dmax); +} diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h index 3ff7e24de2..8a247818f1 100644 --- a/src/connector/odbc/src/todbc_conv.h +++ b/src/connector/odbc/src/todbc_conv.h @@ -17,8 +17,12 @@ #define _todbc_conv_h_ #include +#include #include +#include "iconv.h" + + typedef enum { TSDB_CONV_OK = 0, TSDB_CONV_OOM, @@ -26,44 +30,53 @@ typedef enum { TSDB_CONV_TRUNC_FRACTION, TSDB_CONV_TRUNC, TSDB_CONV_CHAR_NOT_NUM, + TSDB_CONV_GENERAL, + TSDB_CONV_BAD_CHAR, } TSDB_CONV_CODE; -TSDB_CONV_CODE tsdb_int64_to_bit(int todb, int64_t src, int8_t *dst); -TSDB_CONV_CODE tsdb_int64_to_tinyint(int todb, int64_t src, int8_t *dst); -TSDB_CONV_CODE tsdb_int64_to_smallint(int todb, int64_t src, int16_t *dst); -TSDB_CONV_CODE tsdb_int64_to_int(int todb, int64_t src, int32_t *dst); -TSDB_CONV_CODE tsdb_int64_to_bigint(int todb, int64_t src, int64_t *dst); -TSDB_CONV_CODE tsdb_int64_to_ts(int todb, int64_t src, int64_t *dst); -TSDB_CONV_CODE tsdb_int64_to_float(int todb, int64_t src, float *dst); -TSDB_CONV_CODE tsdb_int64_to_double(int todb, int64_t src, double *dst); -TSDB_CONV_CODE tsdb_int64_to_char(int todb, int64_t src, char *dst, size_t dlen); +TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen); -TSDB_CONV_CODE tsdb_double_to_bit(int todb, double src, int8_t *dst); -TSDB_CONV_CODE tsdb_double_to_tinyint(int todb, double src, int8_t *dst); -TSDB_CONV_CODE tsdb_double_to_smallint(int todb, double src, int16_t *dst); -TSDB_CONV_CODE tsdb_double_to_int(int todb, double src, int32_t *dst); -TSDB_CONV_CODE tsdb_double_to_bigint(int todb, double src, int64_t *dst); -TSDB_CONV_CODE tsdb_double_to_ts(int todb, double src, int64_t *dst); -TSDB_CONV_CODE tsdb_chars_to_bit(int todb, const char *src, int8_t *dst); -TSDB_CONV_CODE tsdb_chars_to_tinyint(int todb, const char *src, int8_t *dst); -TSDB_CONV_CODE tsdb_chars_to_smallint(int todb, const char *src, int16_t *dst); -TSDB_CONV_CODE tsdb_chars_to_int(int todb, const char *src, int32_t *dst); -TSDB_CONV_CODE tsdb_chars_to_bigint(int todb, const char *src, int64_t *dst); -TSDB_CONV_CODE tsdb_chars_to_ts(int todb, const char *src, int64_t *dst); -TSDB_CONV_CODE tsdb_chars_to_float(int todb, const char *src, float *dst); -TSDB_CONV_CODE tsdb_chars_to_double(int todb, const char *src, double *dst); -TSDB_CONV_CODE tsdb_chars_to_char(int todb, const char *src, char *dst, size_t dlen); -TSDB_CONV_CODE tsdb_wchars_to_bit(int todb, const unsigned char *src, size_t slen, int8_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_tinyint(int todb, const unsigned char *src, size_t slen, int8_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_smallint(int todb, const unsigned char *src, size_t slen, int16_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_int(int todb, const unsigned char *src, size_t slen, int32_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_bigint(int todb, const unsigned char *src, size_t slen, int64_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_ts(int todb, const unsigned char *src, size_t slen, int64_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_float(int todb, const unsigned char *src, size_t slen, float *dst); -TSDB_CONV_CODE tsdb_wchars_to_double(int todb, const unsigned char *src, size_t slen, double *dst); -TSDB_CONV_CODE tsdb_wchars_to_char(int todb, const unsigned char *src, size_t slen, char *dst, size_t dlen); +TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst); +TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst); +TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst); +TSDB_CONV_CODE tsdb_int64_to_int(int64_t src, int32_t *dst); +TSDB_CONV_CODE tsdb_int64_to_bigint(int64_t src, int64_t *dst); +TSDB_CONV_CODE tsdb_int64_to_ts(int64_t src, int64_t *dst); +TSDB_CONV_CODE tsdb_int64_to_float(int64_t src, float *dst); +TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst); +TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen); + +TSDB_CONV_CODE tsdb_double_to_bit(double src, int8_t *dst); +TSDB_CONV_CODE tsdb_double_to_tinyint(double src, int8_t *dst); +TSDB_CONV_CODE tsdb_double_to_smallint(double src, int16_t *dst); +TSDB_CONV_CODE tsdb_double_to_int(double src, int32_t *dst); +TSDB_CONV_CODE tsdb_double_to_bigint(double src, int64_t *dst); +TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst); +TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen); + +TSDB_CONV_CODE tsdb_timestamp_to_char(SQL_TIMESTAMP_STRUCT src, char *dst, size_t dlen); + +TSDB_CONV_CODE tsdb_chars_to_bit(const char *src, size_t smax, int8_t *dst); +TSDB_CONV_CODE tsdb_chars_to_tinyint(const char *src, size_t smax, int8_t *dst); +TSDB_CONV_CODE tsdb_chars_to_smallint(const char *src, size_t smax, int16_t *dst); +TSDB_CONV_CODE tsdb_chars_to_int(const char *src, size_t smax, int32_t *dst); +TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst); +TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst); +TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst); +TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst); +TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax); + +TSDB_CONV_CODE tsdb_wchars_to_bit(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_tinyint(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_smallint(iconv_t cnv, const unsigned char *src, size_t smax, int16_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_int(iconv_t cnv, const unsigned char *src, size_t smax, int32_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_bigint(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_ts(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst); +TSDB_CONV_CODE tsdb_wchars_to_float(iconv_t cnv, const unsigned char *src, size_t smax, float *dst); +TSDB_CONV_CODE tsdb_wchars_to_double(iconv_t cnv, const unsigned char *src, size_t smax, double *dst); +TSDB_CONV_CODE tsdb_wchars_to_char(iconv_t cnv, const unsigned char *src, size_t smax, char *dst, size_t dmax); #endif // _todbc_conv_h_ diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index b3c307b85f..53a1300f86 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -42,8 +42,6 @@ do { \ abort(); \ } while (0) - - const char* sql_sql_type(int type); const char* sql_c_type(int type); diff --git a/src/connector/odbc/tests/odbc.py b/src/connector/odbc/tests/odbc.py index 5218957fb9..207523e521 100644 --- a/src/connector/odbc/tests/odbc.py +++ b/src/connector/odbc/tests/odbc.py @@ -119,10 +119,10 @@ while row: cursor.close() cursor = cnxn.cursor() -cursor.execute("create table db.f (ts timestamp, v1 bool)") +cursor.execute("create table db.f (ts timestamp, v1 float)") cursor.close() -params = [ ('2020-10-20 00:00:00', 'acb') ] +params = [ ('2020-10-20 00:00:10', '123.3') ] cursor = cnxn.cursor() cursor.fast_executemany = True cursor.executemany("insert into db.f values (?, ?)", params) From aadbd94fb11d33f645c759e3cda28ba5c79e86cb Mon Sep 17 00:00:00 2001 From: freemine Date: Thu, 22 Oct 2020 20:29:55 +0800 Subject: [PATCH 03/85] bugFix: fraction calc --- src/connector/odbc/src/todbc_conv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index c4e0ff653f..0b8b35bfd5 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -237,7 +237,7 @@ TSDB_CONV_CODE tsdb_timestamp_to_char(SQL_TIMESTAMP_STRUCT src, char *dst, size_ int n = snprintf(dst, dlen, "%04d-%02d-%02d %02d:%02d:%02d.%03d", src.year, src.month, src.day, src.hour, src.minute, src.second, - src.fraction % 1000000); + src.fraction / 1000000); if (n=19) return TSDB_CONV_TRUNC_FRACTION; From e6fba2647203a98674b2e395487e542ca37f96eb Mon Sep 17 00:00:00 2001 From: freemine Date: Thu, 22 Oct 2020 23:05:40 +0800 Subject: [PATCH 04/85] add flex-scanner to parse driver connection string --- src/connector/odbc/CMakeLists.txt | 19 ++-- src/connector/odbc/src/CMakeLists.txt | 24 +++++ src/connector/odbc/src/todbc.c | 18 +++- src/connector/odbc/src/todbc_scanner.l | 127 +++++++++++++++++++++++++ src/connector/odbc/src/todbc_util.h | 2 + src/connector/odbc/tests/odbc.py | 2 +- 6 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 src/connector/odbc/src/CMakeLists.txt create mode 100644 src/connector/odbc/src/todbc_scanner.l diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index 58e7b6acf1..3a179fc175 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -3,7 +3,6 @@ PROJECT(TDengine) IF (TD_LINUX_64) find_program(HAVE_ODBCINST NAMES odbcinst) - IF (HAVE_ODBCINST) include(CheckSymbolExists) # shall we revert CMAKE_REQUIRED_LIBRARIES and how? @@ -14,17 +13,13 @@ IF (TD_LINUX_64) message(WARNING "unixodbc-dev is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc-dev") else () message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built") - AUX_SOURCE_DIRECTORY(src SRC) - - # generate dynamic library (*.so) - ADD_LIBRARY(todbc SHARED ${SRC}) - SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) - SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) - TARGET_LINK_LIBRARIES(todbc taos) - - install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/install.sh ${CMAKE_BINARY_DIR})") - - ADD_SUBDIRECTORY(tests) + find_package(FLEX) + if(NOT FLEX_FOUND) + message(FATAL_ERROR "you need to install flex first") + else () + ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tests) + endif() endif() ELSE () message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc") diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt new file mode 100644 index 0000000000..d8438e9817 --- /dev/null +++ b/src/connector/odbc/src/CMakeLists.txt @@ -0,0 +1,24 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF (TD_LINUX_64) + FLEX_TARGET(todbcFlexScanner + todbc_scanner.l + ${CMAKE_CURRENT_BINARY_DIR}/todbc_scanner.c + ) + set(todbc_flex_scanner_src + ${FLEX_todbcFlexScanner_OUTPUTS} + ) + AUX_SOURCE_DIRECTORY(. SRC) + + # generate dynamic library (*.so) + ADD_LIBRARY(todbc SHARED ${SRC} ${todbc_flex_scanner_src}) + SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) + TARGET_LINK_LIBRARIES(todbc taos) + target_include_directories(todbc PUBLIC + .) + + install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") +ENDIF () + diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 5ec8846128..7812a991ef 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -2078,7 +2078,9 @@ static SQLRETURN doSQLDriverConnect( char *serverName = NULL; char *userName = NULL; char *auth = NULL; - int bytes = 0; + char *host = NULL; + char *ip = NULL; + int port = 0; do { if (szConnStrIn && !connStr) { @@ -2086,15 +2088,23 @@ static SQLRETURN doSQLDriverConnect( break; } - int n = sscanf((const char*)connStr, "DSN=%m[^;]; UID=%m[^;]; PWD=%m[^;] %n", &serverName, &userName, &auth, &bytes); - if (n<1) { + int n = todbc_parse_conn_string((const char *)connStr, &serverName, &userName, &auth, &host); + if (n) { SET_ERROR(conn, "HY000", TSDB_CODE_ODBC_BAD_CONNSTR, "unrecognized connection string: [%s]", (const char*)szConnStrIn); break; } + if (host) { + char *p = strchr(host, ':'); + if (p) { + ip = strndup(host, p-host); + port = atoi(p+1); + } + } // TODO: data-race // TODO: shall receive ip/port from odbc.ini - conn->taos = taos_connect("localhost", userName, auth, NULL, 0); + conn->taos = taos_connect(ip ? ip : "localhost", userName, auth, NULL, port); + free(ip); ip = NULL; if (!conn->taos) { SET_ERROR(conn, "HY000", terrno, "failed to connect to data source"); break; diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l new file mode 100644 index 0000000000..e232d4ab2e --- /dev/null +++ b/src/connector/odbc/src/todbc_scanner.l @@ -0,0 +1,127 @@ +%{ +#include "todbc_util.h" + +#include + +typedef struct params_s params_t; +struct params_s { + char *key; + char *dsn; + char *uid; + char *pwd; + char *host; +}; + +#define PUSH_STATE(state) yy_push_state(state, yyscanner) +#define POP_STATE() yy_pop_state(yyscanner) + +#define CHG_STATE(state) \ +do { \ + yy_pop_state(yyscanner); \ + yy_push_state(state, yyscanner); \ +} while (0) + +#define TOP_STATE(top) \ +do { \ + yy_push_state(INITIAL, yyscanner); \ + top = yy_top_state(yyscanner); \ + yy_pop_state(yyscanner); \ +} while (0) + +#define UNPUT() \ +do { \ + while (yyleng) unput(yytext[yyleng-1]); \ +} while (0) + +#define set_key() \ +do { \ + free(yyextra->key); \ + yyextra->key = strdup(yytext); \ +} while (0) + +#define set_val() \ +do { \ + if (!yyextra->key) break; \ + if (strcasecmp(yyextra->key, "DSN")==0) { \ + free(yyextra->dsn); \ + yyextra->dsn = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "UID")==0) { \ + free(yyextra->uid); \ + yyextra->uid = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "PWD")==0) { \ + free(yyextra->pwd); \ + yyextra->pwd = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "HOST")==0) { \ + free(yyextra->host); \ + yyextra->host = strdup(yytext); \ + break; \ + } \ +} while (0) + +%} + +%option prefix="todbc_yy" +%option extra-type="struct params_s *" +%option reentrant +%option noyywrap +%option noinput nounput +%option debug verbose +%option stack +%option nodefault +%option warn +%option perf-report +%option 8bit + +%x KEY EQ BRACE1 BRACE2 VAL + +%% +<> { int state; TOP_STATE(state); + if (state == INITIAL) yyterminate(); + if (state == VAL) yyterminate(); + return -1; } +[[:space:]]+ { } +[[:alnum:]]+ { set_key(); PUSH_STATE(KEY); } +.|\n { return -1; } + +[[:space:]]+ { } +[=] { CHG_STATE(EQ); } +.|\n { return -1; } + +[[:space:]]+ { } +[^][{}(),;?*=!@/\\\n]+ { set_val(); CHG_STATE(VAL); } +[{] { CHG_STATE(BRACE1); } +.|\n { return -1; } + +[^{}\n]+ { set_val(); CHG_STATE(BRACE2); } +.|\n { return -1; } + +[}] { CHG_STATE(VAL); } +.|\n { return -1; } + +[;] { POP_STATE(); } +.|\n { return -1; } +%% + +int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host) { + yyscan_t arg = {0}; + params_t params = {0}; + yylex_init(&arg); + yyset_debug(1, arg); + yyset_extra(¶ms, arg); + yy_scan_string(conn, arg); + int ret =yylex(arg); + yylex_destroy(arg); + *dsn = params.dsn; + *uid = params.uid; + *pwd = params.pwd; + *host = params.host; + return ret ? -1 : 0; +} + + diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index 53a1300f86..a1c32768ef 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -48,6 +48,8 @@ const char* sql_c_type(int type); int is_valid_sql_c_type(int type); int is_valid_sql_sql_type(int type); +int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host); + int string_conv(const char *fromcode, const char *tocode, const unsigned char *src, size_t sbytes, unsigned char *dst, size_t dbytes, diff --git a/src/connector/odbc/tests/odbc.py b/src/connector/odbc/tests/odbc.py index 207523e521..2d736ca032 100644 --- a/src/connector/odbc/tests/odbc.py +++ b/src/connector/odbc/tests/odbc.py @@ -1,5 +1,5 @@ import pyodbc -cnxn = pyodbc.connect('DSN=TAOS_DSN;UID=root;PWD=taosdata', autocommit=True) +cnxn = pyodbc.connect('DSN=TAOS_DSN;UID=root;PWD=taosdata;HOST=localhost:6030', autocommit=True) cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8') #cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8') #cnxn.setencoding(encoding='utf-8') From f8c905211a9f0572d11ab1b8fe68753be81ace65 Mon Sep 17 00:00:00 2001 From: freemine Date: Thu, 22 Oct 2020 23:22:46 +0800 Subject: [PATCH 05/85] scanner pattern --- src/connector/odbc/src/todbc_scanner.l | 8 +++++--- src/connector/odbc/tests/odbc.py | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l index e232d4ab2e..8e178aa366 100644 --- a/src/connector/odbc/src/todbc_scanner.l +++ b/src/connector/odbc/src/todbc_scanner.l @@ -94,13 +94,15 @@ do { \ .|\n { return -1; } [[:space:]]+ { } -[^][{}(),;?*=!@/\\\n]+ { set_val(); CHG_STATE(VAL); } +[^][{}(),;?*=!@/\\\n[:space:]]+ { set_val(); CHG_STATE(VAL); } [{] { CHG_STATE(BRACE1); } .|\n { return -1; } -[^{}\n]+ { set_val(); CHG_STATE(BRACE2); } +[[:space:]]+ { } +[^{}\n[:space:]]+ { set_val(); CHG_STATE(BRACE2); } .|\n { return -1; } +[[:space:]]+ { } [}] { CHG_STATE(VAL); } .|\n { return -1; } @@ -112,7 +114,7 @@ int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd yyscan_t arg = {0}; params_t params = {0}; yylex_init(&arg); - yyset_debug(1, arg); + yyset_debug(0, arg); yyset_extra(¶ms, arg); yy_scan_string(conn, arg); int ret =yylex(arg); diff --git a/src/connector/odbc/tests/odbc.py b/src/connector/odbc/tests/odbc.py index 2d736ca032..e98110a0d5 100644 --- a/src/connector/odbc/tests/odbc.py +++ b/src/connector/odbc/tests/odbc.py @@ -1,5 +1,6 @@ import pyodbc -cnxn = pyodbc.connect('DSN=TAOS_DSN;UID=root;PWD=taosdata;HOST=localhost:6030', autocommit=True) +# cnxn = pyodbc.connect('DSN={TAOS_DSN};UID={ root };PWD={ taosdata };HOST={ localhost:6030 }', autocommit=True) +cnxn = pyodbc.connect('DSN={TAOS_DSN}; UID=root;PWD=taosdata; HOST=localhost:6030', autocommit=True) cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8') #cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8') #cnxn.setencoding(encoding='utf-8') From 5c81c1980837ec98e119ab770574cde3685bca8a Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 23 Oct 2020 19:58:10 +0800 Subject: [PATCH 06/85] refactor and c test case --- src/connector/odbc/src/todbc.c | 23 +- src/connector/odbc/src/todbc_conv.c | 14 + src/connector/odbc/src/todbc_conv.h | 2 + src/connector/odbc/src/todbc_log.h | 44 +++ src/connector/odbc/src/todbc_util.h | 25 +- src/connector/odbc/tests/main.c | 492 ++++++++++++++++++++++------ 6 files changed, 479 insertions(+), 121 deletions(-) create mode 100644 src/connector/odbc/src/todbc_log.h diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 7812a991ef..1ba5f1ac16 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -42,12 +42,18 @@ do { obj->err.err_no = eno; \ const char* estr = tstrerror(eno); \ if (!estr) estr = "Unknown error"; \ - int n = snprintf(NULL, 0, "%s: @[%d][TSDB:%x]" err_fmt "", estr, __LINE__, eno, ##__VA_ARGS__); \ + int n = snprintf(NULL, 0, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \ + eno, estr, \ + basename((char*)__FILE__), __LINE__, \ + ##__VA_ARGS__); \ if (n<0) break; \ char *err_str = (char*)realloc(obj->err.err_str, n+1); \ if (!err_str) break; \ obj->err.err_str = err_str; \ - snprintf(obj->err.err_str, n+1, "%s: @[%d][TSDB:%x]" err_fmt "", estr, __LINE__, eno, ##__VA_ARGS__); \ + snprintf(obj->err.err_str, n+1, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \ + eno, estr, \ + basename((char*)__FILE__), __LINE__, \ + ##__VA_ARGS__); \ snprintf((char*)obj->err.sql_state, sizeof(obj->err.sql_state), "%s", sqlstate); \ } while (0) @@ -410,6 +416,19 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, return SQL_ERROR; } + NameLength1 = (NameLength1==SQL_NTS) ? strlen((const char*)ServerName) : NameLength1; + NameLength2 = (NameLength2==SQL_NTS) ? strlen((const char*)UserName) : NameLength2; + NameLength3 = (NameLength3==SQL_NTS) ? strlen((const char*)Authentication) : NameLength3; + + if (NameLength1 < 0 || NameLength2 < 0 || NameLength3 < 0) { + SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + if (NameLength1>SQL_MAX_DSN_LENGTH) { + SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + const char *serverName = SDUP(ServerName, NameLength1); const char *userName = SDUP(UserName, NameLength2); const char *auth = SDUP(Authentication, NameLength3); diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index 0b8b35bfd5..bbb59c53ad 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -52,6 +52,20 @@ static void buf_clean(buf_t *buf) { } } +const char* tsdb_conv_code_str(TSDB_CONV_CODE code) { + switch (code) { + case TSDB_CONV_OK: return "TSDB_CONV_OK"; + case TSDB_CONV_OOM: return "TSDB_CONV_OOM"; + case TSDB_CONV_OOR: return "TSDB_CONV_OOR"; + case TSDB_CONV_TRUNC_FRACTION: return "TSDB_CONV_TRUNC_FRACTION"; + case TSDB_CONV_TRUNC: return "TSDB_CONV_TRUNC"; + case TSDB_CONV_CHAR_NOT_NUM: return "TSDB_CONV_CHAR_NOT_NUM"; + case TSDB_CONV_GENERAL: return "TSDB_CONV_GENERAL"; + case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR"; + default: return "UNKNOWN"; + }; +} + TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen) { if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h index 8a247818f1..4b326230f0 100644 --- a/src/connector/odbc/src/todbc_conv.h +++ b/src/connector/odbc/src/todbc_conv.h @@ -34,6 +34,8 @@ typedef enum { TSDB_CONV_BAD_CHAR, } TSDB_CONV_CODE; +const char* tsdb_conv_code_str(TSDB_CONV_CODE code); + TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen); diff --git a/src/connector/odbc/src/todbc_log.h b/src/connector/odbc/src/todbc_log.h new file mode 100644 index 0000000000..ff0409fef6 --- /dev/null +++ b/src/connector/odbc/src/todbc_log.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _todbc_log_h_ +#define _todbc_log_h_ + +#include +#include +#include + +#define D(fmt, ...) \ + fprintf(stderr, \ + "%s[%d]:%s() " fmt "\n", \ + basename((char*)__FILE__), __LINE__, __func__, \ + ##__VA_ARGS__) + +#define DASSERT(statement) \ +do { \ + if (statement) break; \ + D("Assertion failure: %s", #statement); \ + abort(); \ +} while (0) + +#define DASSERTX(statement, fmt, ...) \ +do { \ + if (statement) break; \ + D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \ + abort(); \ +} while (0) + +#endif // _todbc_log_h_ + diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index a1c32768ef..5f58ff13ce 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -16,32 +16,11 @@ #ifndef _TODBC_UTIL_H_ #define _TODBC_UTIL_H_ -#include +#include "todbc_log.h" + #include -#include -#include #include -#define D(fmt, ...) \ - fprintf(stderr, \ - "%s[%d]:%s() " fmt "\n", \ - basename((char*)__FILE__), __LINE__, __func__, \ - ##__VA_ARGS__) - -#define DASSERT(statement) \ -do { \ - if (statement) break; \ - D("Assertion failure: %s", #statement); \ - abort(); \ -} while (0) - -#define DASSERTX(statement, fmt, ...) \ -do { \ - if (statement) break; \ - D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \ - abort(); \ -} while (0) - const char* sql_sql_type(int type); const char* sql_c_type(int type); diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index 1ac9b71369..0d42da985d 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -1,3 +1,4 @@ +#include #include #include @@ -5,11 +6,20 @@ #include #include "os.h" +#include "../src/todbc_log.h" // static const char *dsn = "TAOS_DSN"; // static const char *uid = "root"; // static const char *pwd = "taosdata"; +#define CHK_TEST(statement) \ +do { \ + D("testing: %s", #statement); \ + int r = (statement); \ + if (r) return 1; \ +} while (0); + + typedef struct data_s data_t; struct data_s { int64_t ts; @@ -37,7 +47,7 @@ static const char *pro_stmts[] = { // "drop database db" }; -#define CHK_RESULT(r, ht, h) \ +#define CHK_RESULT(r, ht, h, fmt, ...) \ do { \ if (r==0) break; \ SQLCHAR ss[10]; \ @@ -48,23 +58,124 @@ do { es[0] = '\0'; \ SQLRETURN ret = SQLGetDiagRec(ht, h, 1, ss, &ne, es, sizeof(es), &n); \ if (ret) break; \ - fprintf(stderr, "%s%s\n", ss, es); \ + D("[%s]%s: " fmt "", ss, es, ##__VA_ARGS__); \ } while (0) +static int open_connect(const char *dsn, const char *uid, const char *pwd, SQLHENV *pEnv, SQLHDBC *pConn) { + SQLRETURN r; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + r = SQLAllocEnv(&env); + if (r!=SQL_SUCCESS) return 1; + do { + r = SQLAllocConnect(env, &conn); + CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); + if (r!=SQL_SUCCESS) break; + do { + r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn), + (SQLCHAR*)uid, strlen(uid), + (SQLCHAR*)pwd, strlen(pwd)); + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r==SQL_SUCCESS) { + *pEnv = env; + *pConn = conn; + return 0; + } + } while (0); + SQLFreeConnect(conn); + } while (0); + SQLFreeEnv(env); + + return 1; +} + +static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pConn) { + SQLRETURN r; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + r = SQLAllocEnv(&env); + if (r!=SQL_SUCCESS) return 1; + do { + r = SQLAllocConnect(env, &conn); + CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); + if (r!=SQL_SUCCESS) break; + do { + SQLCHAR buf[4096]; + SQLSMALLINT blen = 0; + SQLHDBC ConnectionHandle = conn; + SQLHWND WindowHandle = NULL; + SQLCHAR * InConnectionString = (SQLCHAR*)connstr; + SQLSMALLINT StringLength1 = strlen(connstr); + SQLCHAR * OutConnectionString = buf; + SQLSMALLINT BufferLength = sizeof(buf); + SQLSMALLINT * StringLength2Ptr = &blen; + SQLUSMALLINT DriverCompletion = SQL_DRIVER_NOPROMPT; + r = SQLDriverConnect(ConnectionHandle, WindowHandle, InConnectionString, + StringLength1, OutConnectionString, BufferLength, + StringLength2Ptr, DriverCompletion); + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r==SQL_SUCCESS) { + *pEnv = env; + *pConn = conn; + return 0; + } + } while (0); + SQLFreeConnect(conn); + } while (0); + SQLFreeEnv(env); + + return 1; +} static int do_statement(SQLHSTMT stmt, const char *statement) { SQLRETURN r = 0; do { - fprintf(stderr, "prepare [%s]\n", statement); - r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement)); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + r = SQLExecDirect(stmt, (SQLCHAR*)statement, SQL_NTS); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: [%s]", statement); if (r) break; - fprintf(stderr, "execute [%s]\n", statement); - r = SQLExecute(stmt); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + SQLSMALLINT cols = 0; + r = SQLNumResultCols(stmt, &cols); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); if (r) break; - fprintf(stderr, "done\n"); + if (cols <= 0) break; + char buf[4096]; + while (1) { + SQLRETURN r = SQLFetch(stmt); + if (r==SQL_NO_DATA) break; + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + for (size_t i=0; i0) fprintf(stdout, "\n"); + return r; + } + } + if (soi==SQL_NULL_DATA) { + fprintf(stdout, "%snull", i==0?"":","); + } else { + fprintf(stdout, "%s\"%s\"", i==0?"":",", buf); + } + } + fprintf(stdout, "\n"); + } + + // r = SQLFetch(stmt); + // if (r==SQL_NO_DATA) { + // D(".........."); + // r = SQL_SUCCESS; + // break; + // } + // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + // if (r) break; + // r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement)); + // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + // if (r) break; + // r = SQLExecute(stmt); + // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); + // if (r) break; } while (0); - fprintf(stderr, "r: [%x][%d]\n", r, r); return r; } @@ -77,155 +188,344 @@ static int do_insert(SQLHSTMT stmt, data_t data) { int ignored = 0; do { - fprintf(stderr, "prepare [%s]\n", statement); r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement)); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 1 [%s]\n", statement); r = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_TIMESTAMP, ignored, ignored, &data.ts, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 2 [%s]\n", statement); r = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, ignored, ignored, &data.b, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 3 [%s]\n", statement); r = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_TINYINT, ignored, ignored, &data.v1, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 4 [%s]\n", statement); r = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, ignored, ignored, &data.v2, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 5 [%s]\n", statement); r = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, ignored, ignored, &data.v4, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 6 [%s]\n", statement); r = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, ignored, ignored, &data.v8, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 7 [%s]\n", statement); r = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, ignored, ignored, &data.f4, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 8 [%s]\n", statement); r = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, ignored, ignored, &data.f8, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 9 [%s]\n", statement); lbin = SQL_NTS; r = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sizeof(data.bin)-1, ignored, &data.bin, ignored, &lbin); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 10 [%s]\n", statement); lblob = SQL_NTS; r = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(data.blob)-1, ignored, &data.blob, ignored, &lblob); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "execute [%s]\n", statement); r = SQLExecute(stmt); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; // ts += 1; // v = 2; - // fprintf(stderr, "execute [%s]\n", statement); // r = SQLExecute(stmt); // if (r) break; - - fprintf(stderr, "done\n"); } while (0); - fprintf(stderr, "r: [%x][%d]\n", r, r); return r; } -int main(int argc, char *argv[]) { - if (argc < 4) return 1; - const char *dsn = argv[1]; - const char *uid = argv[2]; - const char *pwd = argv[3]; - SQLRETURN r; +static int test1(const char *dsn, const char *uid, const char *pwd) { + SQLRETURN r = SQL_SUCCESS; SQLHENV env = {0}; SQLHDBC conn = {0}; - r = SQLAllocEnv(&env); - if (r!=SQL_SUCCESS) return 1; + int n = open_connect(dsn, uid, pwd, &env, &conn); + if (n) return 1; + do { - r = SQLAllocConnect(env, &conn); - CHK_RESULT(r, SQL_HANDLE_ENV, env); + SQLHSTMT stmt = {0}; + r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt); if (r!=SQL_SUCCESS) break; do { - r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn), - (SQLCHAR*)uid, strlen(uid), - (SQLCHAR*)pwd, strlen(pwd)); - CHK_RESULT(r, SQL_HANDLE_DBC, conn); - if (r!=SQL_SUCCESS) break; + if (do_statement(stmt, "drop database if exists db")) { + r = SQL_ERROR; + break; + } + for (size_t i=0; i1) ? argv[1] : NULL; + const char *uid = (argc>2) ? argv[2] : NULL; + const char *pwd = (argc>3) ? argv[3] : NULL; + const char *connstr = (argc>4) ? argv[4] : NULL; + const char *sqls = (argc>5) ? argv[5] : NULL; + + if (0) { + CHK_TEST(test_env()); + + CHK_TEST(test1(dsn, uid, pwd)); + + const char *statements[] = { + "drop database if exists m", + "create database m", + "use m", + "drop database m", + NULL + }; + CHK_TEST(test_statements(dsn, uid, pwd, statements)); + + if (connstr) + CHK_TEST(test_driver_connect(connstr)); + + if (connstr) { + SQLHENV env = {0}; + SQLHDBC conn = {0}; + CHK_TEST(open_driver_connect(connstr, &env, &conn)); + int r = tests(env, conn); + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + if (r) return 1; + } + } + + if ((dsn || connstr) && 1) { + CHK_TEST(test_sqls(dsn, uid, pwd, connstr, sqls)); + } + + return 0; +} + From 7137bf89953962720a173d1799f438653fa84772 Mon Sep 17 00:00:00 2001 From: freemine Date: Sun, 25 Oct 2020 22:34:20 +0800 Subject: [PATCH 07/85] disable C4091 --- src/os/src/windows/wSysinfo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/os/src/windows/wSysinfo.c b/src/os/src/windows/wSysinfo.c index 61adc3ee14..1bfee25c4a 100644 --- a/src/os/src/windows/wSysinfo.c +++ b/src/os/src/windows/wSysinfo.c @@ -31,7 +31,10 @@ #pragma comment(lib, "Mswsock.lib ") #endif +#pragma warning(push) +#pragma warning(disable:4091) #include +#pragma warning(pop) static void taosGetSystemTimezone() { // get and set default timezone From 54ed76ec2d47596f5a8eb672bf6708d0cc9b1de7 Mon Sep 17 00:00:00 2001 From: freemine Date: Mon, 26 Oct 2020 08:22:48 +0800 Subject: [PATCH 08/85] start to enable build in windows --- src/connector/odbc/CMakeLists.txt | 9 +++++++++ src/connector/odbc/src/CMakeLists.txt | 18 ++++++++++++++++++ src/connector/odbc/src/todbc_log.h | 4 ++++ src/connector/odbc/tests/CMakeLists.txt | 6 ++++++ 4 files changed, 37 insertions(+) diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index 3a179fc175..1480a0af73 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -26,3 +26,12 @@ IF (TD_LINUX_64) ENDIF () ENDIF () +IF (TD_WINDOWS_64) + find_package(FLEX) + if(NOT FLEX_FOUND) + message(FATAL_ERROR "you need to install flex first") + else () + ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tests) + endif() +ENDIF () diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt index d8438e9817..19ee23b19f 100644 --- a/src/connector/odbc/src/CMakeLists.txt +++ b/src/connector/odbc/src/CMakeLists.txt @@ -22,3 +22,21 @@ IF (TD_LINUX_64) install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") ENDIF () +IF (TD_WINDOWS_64) + FLEX_TARGET(todbcFlexScanner + todbc_scanner.l + ${CMAKE_CURRENT_BINARY_DIR}/todbc_scanner.c + ) + set(todbc_flex_scanner_src + ${FLEX_todbcFlexScanner_OUTPUTS} + ) + AUX_SOURCE_DIRECTORY(. SRC) + + # generate dynamic library (*.so) + ADD_LIBRARY(todbc SHARED ${SRC} ${todbc_flex_scanner_src}) + SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) + TARGET_LINK_LIBRARIES(todbc taos_static) + target_include_directories(todbc PUBLIC + .) +ENDIF () diff --git a/src/connector/odbc/src/todbc_log.h b/src/connector/odbc/src/todbc_log.h index ff0409fef6..4f5b008d05 100644 --- a/src/connector/odbc/src/todbc_log.h +++ b/src/connector/odbc/src/todbc_log.h @@ -16,7 +16,11 @@ #ifndef _todbc_log_h_ #define _todbc_log_h_ +#ifdef _MSC_VER +#include "msvcLibgen.h" +#else #include +#endif #include #include diff --git a/src/connector/odbc/tests/CMakeLists.txt b/src/connector/odbc/tests/CMakeLists.txt index ac57a5647f..1649b45e02 100644 --- a/src/connector/odbc/tests/CMakeLists.txt +++ b/src/connector/odbc/tests/CMakeLists.txt @@ -5,3 +5,9 @@ IF (TD_LINUX) ADD_EXECUTABLE(tcodbc main.c) TARGET_LINK_LIBRARIES(tcodbc odbc) ENDIF () + +IF (TD_WINDOWS_64) + AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(tcodbc main.c) + TARGET_LINK_LIBRARIES(tcodbc odbc) +ENDIF () From 776e0a39c85fd34733fa572293d1f357fbce9a77 Mon Sep 17 00:00:00 2001 From: freemine Date: Mon, 26 Oct 2020 11:08:33 +0800 Subject: [PATCH 09/85] add -Wconversion and refactor accordingly --- src/connector/odbc/CMakeLists.txt | 2 + src/connector/odbc/src/todbc.c | 142 ++++++++++++++-------------- src/connector/odbc/src/todbc_conv.c | 2 +- src/connector/odbc/src/todbc_util.c | 10 +- src/connector/odbc/tests/main.c | 43 +++++---- src/inc/taoserror.h | 4 +- src/os/inc/osTime.h | 4 +- 7 files changed, 107 insertions(+), 100 deletions(-) diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index 1480a0af73..322f9c12cc 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -17,6 +17,8 @@ IF (TD_LINUX_64) if(NOT FLEX_FOUND) message(FATAL_ERROR "you need to install flex first") else () + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wconversion") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(tests) endif() diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 1ba5f1ac16..6b6998854e 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -47,10 +47,10 @@ do { basename((char*)__FILE__), __LINE__, \ ##__VA_ARGS__); \ if (n<0) break; \ - char *err_str = (char*)realloc(obj->err.err_str, n+1); \ + char *err_str = (char*)realloc(obj->err.err_str, (size_t)n+1); \ if (!err_str) break; \ obj->err.err_str = err_str; \ - snprintf(obj->err.err_str, n+1, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \ + snprintf(obj->err.err_str, (size_t)n+1, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \ eno, estr, \ basename((char*)__FILE__), __LINE__, \ ##__VA_ARGS__); \ @@ -64,14 +64,14 @@ do { obj->err.sql_state[0] = '\0'; \ } while (0) -#define FILL_ERROR(obj) \ -do { \ - size_t n = sizeof(obj->err.sql_state); \ - if (Sqlstate) strncpy((char*)Sqlstate, (char*)obj->err.sql_state, n); \ - if (NativeError) *NativeError = obj->err.err_no; \ - snprintf((char*)MessageText, BufferLength, "%s", obj->err.err_str); \ - if (TextLength && obj->err.err_str) *TextLength = strlen(obj->err.err_str); \ - if (TextLength && obj->err.err_str) *TextLength = utf8_chars(obj->err.err_str); \ +#define FILL_ERROR(obj) \ +do { \ + size_t n = sizeof(obj->err.sql_state); \ + if (Sqlstate) strncpy((char*)Sqlstate, (char*)obj->err.sql_state, n); \ + if (NativeError) *NativeError = obj->err.err_no; \ + snprintf((char*)MessageText, (size_t)BufferLength, "%s", obj->err.err_str); \ + if (TextLength && obj->err.err_str) *TextLength = (SQLSMALLINT)strlen(obj->err.err_str); \ + if (TextLength && obj->err.err_str) *TextLength = (SQLSMALLINT)utf8_chars(obj->err.err_str); \ } while (0) #define FREE_ERROR(obj) \ @@ -94,7 +94,7 @@ do { SET_ERROR(obj, sqlstate, TSDB_CODE_QRY_INVALID_QHANDLE, err_fmt, ##__VA_ARGS__); \ } while (0); -#define SDUP(s,n) (s ? (s[n] ? (const char*)strndup((const char*)s,n) : (const char*)s) : strdup("")) +#define SDUP(s,n) (s ? (s[(size_t)n] ? (const char*)strndup((const char*)s,(size_t)n) : (const char*)s) : strdup("")) #define SFRE(x,s,n) \ do { \ if (x==(const char*)s) break; \ @@ -145,7 +145,7 @@ do { \ gettimeofday(&tv1, NULL); \ double delta = difftime(tv1.tv_sec, tv0.tv_sec); \ delta *= 1000000; \ - delta += (tv1.tv_usec-tv0.tv_usec); \ + delta += (double)(tv1.tv_usec-tv0.tv_usec); \ delta /= 1000000; \ D("%s: elapsed: [%.6f]s", #statement, delta); \ } while (0) @@ -259,7 +259,7 @@ struct c_target_s { static pthread_once_t init_once = PTHREAD_ONCE_INIT; static void init_routine(void); -static int do_field_display_size(TAOS_FIELD *field); +static size_t do_field_display_size(TAOS_FIELD *field); static iconv_t sql_get_w2c(sql_t *sql) { if (sql->w2c == (iconv_t)-1) { sql->w2c = iconv_open("UTF-8", "UCS-2LE"); @@ -416,9 +416,9 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, return SQL_ERROR; } - NameLength1 = (NameLength1==SQL_NTS) ? strlen((const char*)ServerName) : NameLength1; - NameLength2 = (NameLength2==SQL_NTS) ? strlen((const char*)UserName) : NameLength2; - NameLength3 = (NameLength3==SQL_NTS) ? strlen((const char*)Authentication) : NameLength3; + NameLength1 = (NameLength1==SQL_NTS) ? (SQLSMALLINT)strlen((const char*)ServerName) : NameLength1; + NameLength2 = (NameLength2==SQL_NTS) ? (SQLSMALLINT)strlen((const char*)UserName) : NameLength2; + NameLength3 = (NameLength3==SQL_NTS) ? (SQLSMALLINT)strlen((const char*)Authentication) : NameLength3; if (NameLength1 < 0 || NameLength2 < 0 || NameLength3 < 0) { SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); @@ -678,8 +678,8 @@ SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle, SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER cbSqlStr) { size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(szSqlStr, cbSqlStr, &bytes); - return SQLExecDirect(hstmt, utf8, bytes); + SQLCHAR *utf8 = wchars_to_chars(szSqlStr, (size_t)cbSqlStr, &bytes); + return SQLExecDirect(hstmt, utf8, (SQLINTEGER)bytes); } static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, @@ -705,7 +705,7 @@ static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, int fields = taos_field_count(sql->rs); if (ColumnCount) { - *ColumnCount = fields; + *ColumnCount = (SQLSMALLINT)fields; } return SQL_SUCCESS; @@ -786,11 +786,11 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle, switch (FieldIdentifier) { case SQL_COLUMN_DISPLAY_SIZE: { - *NumericAttribute = do_field_display_size(field); + *NumericAttribute = (SQLLEN)do_field_display_size(field); } break; case SQL_COLUMN_LABEL: { size_t n = sizeof(field->name); - strncpy(CharacterAttribute, field->name, (n>BufferLength ? BufferLength : n)); + strncpy(CharacterAttribute, field->name, (n>BufferLength ? (size_t)BufferLength : n)); } break; case SQL_COLUMN_UNSIGNED: { *NumericAttribute = SQL_FALSE; @@ -908,7 +908,7 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, CHK_CONV(0, tsdb_int64_to_double(v, TargetValue)); } break; case SQL_C_CHAR: { - CHK_CONV(0, tsdb_int64_to_char(v, TargetValue, BufferLength)); + CHK_CONV(0, tsdb_int64_to_char(v, TargetValue, (size_t)BufferLength)); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -930,7 +930,7 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, return SQL_SUCCESS; } break; case SQL_C_CHAR: { - CHK_CONV(0, tsdb_double_to_char(v, TargetValue, BufferLength)); + CHK_CONV(0, tsdb_double_to_char(v, TargetValue, (size_t)BufferLength)); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -948,7 +948,7 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, return SQL_SUCCESS; } break; case SQL_C_CHAR: { - CHK_CONV(0, tsdb_double_to_char(v, TargetValue, BufferLength)); + CHK_CONV(0, tsdb_double_to_char(v, TargetValue, (size_t)BufferLength)); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -962,22 +962,22 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, SQL_TIMESTAMP_STRUCT ts = {0}; int64_t v = *(int64_t*)row; time_t t = v/1000; - struct tm tm = {0}; - localtime_r(&t, &tm); - ts.year = tm.tm_year + 1900; - ts.month = tm.tm_mon + 1; - ts.day = tm.tm_mday; - ts.hour = tm.tm_hour; - ts.minute = tm.tm_min; - ts.second = tm.tm_sec; - ts.fraction = v%1000 * 1000000; + struct tm vtm = {0}; + localtime_r(&t, &vtm); + ts.year = (SQLSMALLINT)(vtm.tm_year + 1900); + ts.month = (SQLUSMALLINT)(vtm.tm_mon + 1); + ts.day = (SQLUSMALLINT)(vtm.tm_mday); + ts.hour = (SQLUSMALLINT)(vtm.tm_hour); + ts.minute = (SQLUSMALLINT)(vtm.tm_min); + ts.second = (SQLUSMALLINT)(vtm.tm_sec); + ts.fraction = (SQLUINTEGER)(v%1000 * 1000000); switch (target.ct) { case SQL_C_SBIGINT: { *(int64_t*)TargetValue = v; return SQL_SUCCESS; } break; case SQL_C_CHAR: { - CHK_CONV(0, tsdb_timestamp_to_char(ts, TargetValue, BufferLength)); + CHK_CONV(0, tsdb_timestamp_to_char(ts, TargetValue, (size_t)BufferLength)); } break; case SQL_C_TYPE_TIMESTAMP: case SQL_C_TIMESTAMP: { @@ -993,11 +993,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, } } break; case TSDB_DATA_TYPE_BINARY: { - size_t field_bytes = field->bytes; + size_t field_bytes = (size_t)field->bytes; field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { case SQL_C_CHAR: { - CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, BufferLength)); + CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, (size_t)BufferLength)); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -1008,11 +1008,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, } } break; case TSDB_DATA_TYPE_NCHAR: { - size_t field_bytes = field->bytes; + size_t field_bytes = (size_t)field->bytes; field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { case SQL_C_CHAR: { - CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, BufferLength)); + CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, (size_t)BufferLength)); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -1104,7 +1104,7 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, int ok = 0; do { - int r = taos_stmt_prepare(sql->stmt, (const char *)StatementText, TextLength); + int r = taos_stmt_prepare(sql->stmt, (const char *)StatementText, (unsigned long)TextLength); if (r) { SET_ERROR(sql, "HY000", r, "failed to prepare a TAOS statement"); break; @@ -1128,7 +1128,7 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, DASSERT(params>=0); if (params>0) { - param_bind_t *ar = (param_bind_t*)calloc(1, params * sizeof(*ar)); + param_bind_t *ar = (param_bind_t*)calloc(1, ((size_t)params) * sizeof(*ar)); if (!ar) { SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); break; @@ -1175,7 +1175,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SQLSMALLINT valueType = param->ValueType; SQLLEN *soi = param->StrLen_or_Ind; - size_t offset = idx_row * sql->rowlen + sql->ptr_offset; + size_t offset = ((size_t)idx_row) * sql->rowlen + sql->ptr_offset; if (paramValue) paramValue += offset; if (soi) soi = (SQLLEN*)((char*)soi + offset); @@ -1269,10 +1269,10 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_double_to_bit(*(double*)paramValue, &bind->u.b)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_bit((const char *)paramValue, *soi, &bind->u.b)); + CHK_CONV(1, tsdb_chars_to_bit((const char *)paramValue, (size_t)*soi, &bind->u.b)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_bit(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.b)); + CHK_CONV(1, tsdb_wchars_to_bit(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.b)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1321,10 +1321,10 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_int64_to_tinyint(*(int64_t*)paramValue, &bind->u.v1)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_tinyint((const char*)paramValue, *soi, &bind->u.v1)); + CHK_CONV(1, tsdb_chars_to_tinyint((const char*)paramValue, (size_t)*soi, &bind->u.v1)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_tinyint(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.v1)); + CHK_CONV(1, tsdb_wchars_to_tinyint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v1)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1375,10 +1375,10 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_int64_to_smallint(*(int64_t*)paramValue, &bind->u.v2)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, *soi, &bind->u.v2)); + CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, (size_t)*soi, &bind->u.v2)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_smallint(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.v2)); + CHK_CONV(1, tsdb_wchars_to_smallint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v2)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1429,10 +1429,10 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_int64_to_int(*(int64_t*)paramValue, &bind->u.v4)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, *soi, &bind->u.v4)); + CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, (size_t)*soi, &bind->u.v4)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_int(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.v4)); + CHK_CONV(1, tsdb_wchars_to_int(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v4)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1483,10 +1483,10 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_int64_to_bigint(*(int64_t*)paramValue, &bind->u.v8)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, *soi, &bind->u.v8)); + CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, (size_t)*soi, &bind->u.v8)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_bigint(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.v8)); + CHK_CONV(1, tsdb_wchars_to_bigint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v8)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1543,10 +1543,10 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->u.f4 = (float)*(double*)paramValue; } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_float((const char*)paramValue, *soi, &bind->u.f4)); + CHK_CONV(1, tsdb_chars_to_float((const char*)paramValue, (size_t)*soi, &bind->u.f4)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_float(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.f4)); + CHK_CONV(1, tsdb_wchars_to_float(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f4)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1601,10 +1601,10 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->u.f8 = *(double*)paramValue; } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, *soi, &bind->u.f8)); + CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, (size_t)*soi, &bind->u.f8)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_double(sql_get_w2c(sql), (const unsigned char*)paramValue, *soi, &bind->u.f8)); + CHK_CONV(1, tsdb_wchars_to_double(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f8)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1636,7 +1636,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin DASSERT(soi); DASSERT(*soi != SQL_NTS); size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, *soi/2, &bytes); + SQLCHAR *utf8 = wchars_to_chars(paramValue, (size_t)*soi/2, &bytes); bind->allocated = 1; bind->u.bin = utf8; bind->buffer_length = bytes; @@ -1647,7 +1647,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin if (*soi == SQL_NTS) { bind->buffer_length = strlen((const char*)paramValue); } else { - bind->buffer_length = *soi; + bind->buffer_length = (uintptr_t)*soi; } bind->buffer = bind->u.bin; } break; @@ -1695,9 +1695,9 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin size_t bytes = 0; int r = 0; int64_t t = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, *soi/2, &bytes); + SQLCHAR *utf8 = wchars_to_chars(paramValue, (size_t)*soi/2, &bytes); // why cast utf8 to 'char*' ? - r = taosParseTime((char*)utf8, &t, strlen((const char*)utf8), TSDB_TIME_PRECISION_MILLI, 0); + r = taosParseTime((char*)utf8, &t, (int)strlen((const char*)utf8), TSDB_TIME_PRECISION_MILLI, 0); bind->u.v8 = t; free(utf8); if (r) { @@ -1751,7 +1751,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin DASSERT(soi); DASSERT(*soi != SQL_NTS); size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, *soi/2, &bytes); + SQLCHAR *utf8 = wchars_to_chars(paramValue, (size_t)(*soi/2), &bytes); bind->allocated = 1; bind->u.nchar = (char*)utf8; bind->buffer_length = bytes; @@ -1762,7 +1762,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin if (*soi == SQL_NTS) { bind->buffer_length = strlen((const char*)paramValue); } else { - bind->buffer_length = *soi; + bind->buffer_length = (uintptr_t)*soi; } bind->buffer = bind->u.nchar; } break; @@ -1843,7 +1843,7 @@ static SQLRETURN do_execute(sql_t *sql) for (int i=0; in_rows; ++i) { TAOS_BIND *binds = NULL; if (sql->n_params>0) { - binds = (TAOS_BIND*)calloc(sql->n_params, sizeof(*binds)); + binds = (TAOS_BIND*)calloc((size_t)sql->n_params, sizeof(*binds)); if (!binds) { SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); return SQL_ERROR; @@ -2115,14 +2115,14 @@ static SQLRETURN doSQLDriverConnect( if (host) { char *p = strchr(host, ':'); if (p) { - ip = strndup(host, p-host); + ip = strndup(host, (size_t)(p-host)); port = atoi(p+1); } } // TODO: data-race // TODO: shall receive ip/port from odbc.ini - conn->taos = taos_connect(ip ? ip : "localhost", userName, auth, NULL, port); + conn->taos = taos_connect(ip ? ip : "localhost", userName, auth, NULL, (uint16_t)port); free(ip); ip = NULL; if (!conn->taos) { SET_ERROR(conn, "HY000", terrno, "failed to connect to data source"); @@ -2130,7 +2130,7 @@ static SQLRETURN doSQLDriverConnect( } if (szConnStrOut) { - snprintf((char*)szConnStrOut, cbConnStrOutMax, "%s", connStr); + snprintf((char*)szConnStrOut, (size_t)cbConnStrOutMax, "%s", connStr); } if (pcbConnStrOut) { *pcbConnStrOut = cbConnStrIn; @@ -2218,14 +2218,14 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, TAOS_FIELD *field = fields + ColumnNumber - 1; if (ColumnName) { size_t n = sizeof(field->name); - if (n>BufferLength) n = BufferLength; + if (n>BufferLength) n = (size_t)BufferLength; strncpy((char*)ColumnName, field->name, n); } if (NameLength) { - *NameLength = strnlen(field->name, sizeof(field->name)); + *NameLength = (SQLSMALLINT)strnlen(field->name, sizeof(field->name)); } if (ColumnSize) { - *ColumnSize = field->bytes; + *ColumnSize = (SQLULEN)field->bytes; } if (DecimalDigits) *DecimalDigits = 0; @@ -2337,7 +2337,7 @@ static SQLRETURN doSQLNumParams(SQLHSTMT hstmt, SQLSMALLINT *pcpar) return SQL_ERROR; } - if (pcpar) *pcpar = params; + if (pcpar) *pcpar = (SQLSMALLINT)params; return SQL_SUCCESS; } @@ -2423,7 +2423,7 @@ static void init_routine(void) { taos_init(); } -static int do_field_display_size(TAOS_FIELD *field) { +static size_t do_field_display_size(TAOS_FIELD *field) { switch (field->type) { case TSDB_DATA_TYPE_TINYINT: return 5; @@ -2451,7 +2451,7 @@ static int do_field_display_size(TAOS_FIELD *field) { case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: { - return 3*(field->bytes - VARSTR_HEADER_SIZE) + 2; + return 3*((size_t)field->bytes - VARSTR_HEADER_SIZE) + 2; } break; case TSDB_DATA_TYPE_TIMESTAMP: diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index bbb59c53ad..695201af53 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -74,7 +74,7 @@ TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *sl size_t sl = *slen; size_t dl = *dlen; - int n = iconv(cnv, &s, &sl, &d, &dl); + size_t n = iconv(cnv, &s, &sl, &d, &dl); int e = errno; if (dl) *d = '\0'; // what if all consumed? diff --git a/src/connector/odbc/src/todbc_util.c b/src/connector/odbc/src/todbc_util.c index 378a2e1b75..d462b37c1e 100644 --- a/src/connector/odbc/src/todbc_util.c +++ b/src/connector/odbc/src/todbc_util.c @@ -125,7 +125,7 @@ int string_conv(const char *fromcode, const char *tocode, iconv_t conv = iconv_open(tocode, fromcode); if (!conv) return -1; - int r = 0; + size_t r = 0; do { char *s = (char*)src; char *d = (char*)dst; @@ -141,7 +141,7 @@ int string_conv(const char *fromcode, const char *tocode, } while (0); iconv_close(conv); - return r; + return (int)r; } int utf8_chars(const char *src) @@ -161,7 +161,7 @@ int utf8_chars(const char *src) size_t chars = (sizeof(buf) - dlen) / 2; iconv_close(conv); - return chars; + return (int)chars; } unsigned char* utf8_to_ucs4le(const char *utf8, size_t *chars) @@ -240,7 +240,7 @@ size_t wchars_to_chars2(const SQLWCHAR *src, size_t slen, SQLCHAR *dst, size_t d { size_t consumed=0, generated=0; int n = string_conv("UCS-2LE", "UTF-8", (const unsigned char*)src, slen, dst, dlen, &consumed, &generated); - if (n) return -1; + if (n) return (size_t)-1; return generated; } @@ -248,7 +248,7 @@ size_t chars_to_wchars2(const SQLCHAR *src, size_t slen, SQLWCHAR *dst, size_t d { size_t consumed=0, generated=0; int n = string_conv("UTF-8", "UCS-2LE", (const unsigned char*)src, slen, (unsigned char*)dst, dlen, &consumed, &generated); - if (n) return -1; + if (n) return (size_t)-1; return generated; } diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index 0d42da985d..1321ade328 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -72,9 +72,9 @@ static int open_connect(const char *dsn, const char *uid, const char *pwd, SQLHE CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); if (r!=SQL_SUCCESS) break; do { - r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn), - (SQLCHAR*)uid, strlen(uid), - (SQLCHAR*)pwd, strlen(pwd)); + r = SQLConnect(conn, (SQLCHAR*)dsn, (SQLSMALLINT)strlen(dsn), + (SQLCHAR*)uid, (SQLSMALLINT)strlen(uid), + (SQLCHAR*)pwd, (SQLSMALLINT)strlen(pwd)); CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); if (r==SQL_SUCCESS) { *pEnv = env; @@ -105,7 +105,7 @@ static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pCon SQLHDBC ConnectionHandle = conn; SQLHWND WindowHandle = NULL; SQLCHAR * InConnectionString = (SQLCHAR*)connstr; - SQLSMALLINT StringLength1 = strlen(connstr); + SQLSMALLINT StringLength1 = (SQLSMALLINT)strlen(connstr); SQLCHAR * OutConnectionString = buf; SQLSMALLINT BufferLength = sizeof(buf); SQLSMALLINT * StringLength2Ptr = &blen; @@ -144,7 +144,7 @@ static int do_statement(SQLHSTMT stmt, const char *statement) { CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); for (size_t i=0; i4) ? argv[4] : NULL; const char *sqls = (argc>5) ? argv[5] : NULL; - if (0) { + if (1) { CHK_TEST(test_env()); CHK_TEST(test1(dsn, uid, pwd)); diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index ad8bce7ca7..0e1ca01dd4 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -24,9 +24,9 @@ extern "C" { #include #ifdef TAOS_ERROR_C -#define TAOS_DEFINE_ERROR(name, mod, code, msg) {.val = (0x80000000 | ((mod)<<16) | (code)), .str=(msg)}, +#define TAOS_DEFINE_ERROR(name, mod, code, msg) {.val = (int32_t)((0x80000000 | ((mod)<<16) | (code))), .str=(msg)}, #else -#define TAOS_DEFINE_ERROR(name, mod, code, msg) static const int32_t name = (0x80000000 | ((mod)<<16) | (code)); +#define TAOS_DEFINE_ERROR(name, mod, code, msg) static const int32_t name = (int32_t)((0x80000000 | ((mod)<<16) | (code))); #endif #define TAOS_SYSTEM_ERROR(code) (0x80ff0000 | (code)) diff --git a/src/os/inc/osTime.h b/src/os/inc/osTime.h index 6b209219c6..b20ccadadb 100644 --- a/src/os/inc/osTime.h +++ b/src/os/inc/osTime.h @@ -38,14 +38,14 @@ int32_t taosGetTimestampSec(); static FORCE_INLINE int64_t taosGetTimestampMs() { struct timeval systemTime; gettimeofday(&systemTime, NULL); - return (int64_t)systemTime.tv_sec * 1000L + (uint64_t)systemTime.tv_usec / 1000; + return (int64_t)systemTime.tv_sec * 1000L + (int64_t)systemTime.tv_usec / 1000; } //@return timestamp in microsecond static FORCE_INLINE int64_t taosGetTimestampUs() { struct timeval systemTime; gettimeofday(&systemTime, NULL); - return (int64_t)systemTime.tv_sec * 1000000L + (uint64_t)systemTime.tv_usec; + return (int64_t)systemTime.tv_sec * 1000000L + (int64_t)systemTime.tv_usec; } /* From 1a5ec2e2bab45606e03ea79850f4d9f5697ef3a1 Mon Sep 17 00:00:00 2001 From: freemine Date: Mon, 26 Oct 2020 11:31:27 +0800 Subject: [PATCH 10/85] prefer unsigned char * than void *, because we will add offset to the pointer --- src/connector/odbc/src/todbc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 6b6998854e..9bde4fd2ec 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -1171,9 +1171,9 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin return SQL_ERROR; } - SQLPOINTER paramValue = param->ParameterValue; - SQLSMALLINT valueType = param->ValueType; - SQLLEN *soi = param->StrLen_or_Ind; + unsigned char *paramValue = param->ParameterValue; + SQLSMALLINT valueType = param->ValueType; + SQLLEN *soi = param->StrLen_or_Ind; size_t offset = ((size_t)idx_row) * sql->rowlen + sql->ptr_offset; @@ -1636,7 +1636,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin DASSERT(soi); DASSERT(*soi != SQL_NTS); size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, (size_t)*soi/2, &bytes); + SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)*soi/2, &bytes); bind->allocated = 1; bind->u.bin = utf8; bind->buffer_length = bytes; @@ -1695,7 +1695,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin size_t bytes = 0; int r = 0; int64_t t = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, (size_t)*soi/2, &bytes); + SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)*soi/2, &bytes); // why cast utf8 to 'char*' ? r = taosParseTime((char*)utf8, &t, (int)strlen((const char*)utf8), TSDB_TIME_PRECISION_MILLI, 0); bind->u.v8 = t; @@ -1751,7 +1751,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin DASSERT(soi); DASSERT(*soi != SQL_NTS); size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, (size_t)(*soi/2), &bytes); + SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)(*soi/2), &bytes); bind->allocated = 1; bind->u.nchar = (char*)utf8; bind->buffer_length = bytes; From 48b1fd65f19574b4f9fce6e1c95d20e1bee1e86b Mon Sep 17 00:00:00 2001 From: freemine Date: Mon, 26 Oct 2020 19:53:15 +0800 Subject: [PATCH 11/85] header file workaround for win_flex --- src/connector/odbc/src/todbc_conv.c | 3 +- src/connector/odbc/src/todbc_conv.h | 3 +- .../odbc/src/todbc_flex_workaround.h | 30 +++++++++++++++++++ src/connector/odbc/src/todbc_scanner.l | 12 ++++++++ src/connector/odbc/src/todbc_util.c | 3 -- src/connector/odbc/src/todbc_util.h | 3 +- src/connector/odbc/tests/CMakeLists.txt | 2 +- src/connector/odbc/tests/main.c | 9 ++++-- 8 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 src/connector/odbc/src/todbc_flex_workaround.h diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index 695201af53..c6ce6a29f6 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -14,9 +14,10 @@ */ #include "todbc_conv.h" - #include "todbc_util.h" +#include "os.h" + #include #include #include diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h index 4b326230f0..9753620ee2 100644 --- a/src/connector/odbc/src/todbc_conv.h +++ b/src/connector/odbc/src/todbc_conv.h @@ -16,8 +16,7 @@ #ifndef _todbc_conv_h_ #define _todbc_conv_h_ -#include -#include +#include "todbc_flex_workaround.h" #include #include "iconv.h" diff --git a/src/connector/odbc/src/todbc_flex_workaround.h b/src/connector/odbc/src/todbc_flex_workaround.h new file mode 100644 index 0000000000..d6c79cf19a --- /dev/null +++ b/src/connector/odbc/src/todbc_flex_workaround.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _todbc_flex_workaround_h_ +#define _todbc_flex_workaround_h_ + +#ifdef _MSC_VER +#include +#include +#endif +#ifndef INT8_MIN +#include +#endif +#include +#include + +#endif // _todbc_flex_workaround_h_ + diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l index 8e178aa366..4c7aa74f2c 100644 --- a/src/connector/odbc/src/todbc_scanner.l +++ b/src/connector/odbc/src/todbc_scanner.l @@ -1,8 +1,18 @@ %{ +#include +#include +#include + #include "todbc_util.h" #include +#ifdef _MSC_VER +#include "msvcLibgen.h" +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + typedef struct params_s params_t; struct params_s { char *key; @@ -68,6 +78,8 @@ do { \ %option prefix="todbc_yy" %option extra-type="struct params_s *" +%option nounistd +%option never-interactive %option reentrant %option noyywrap %option noinput nounput diff --git a/src/connector/odbc/src/todbc_util.c b/src/connector/odbc/src/todbc_util.c index d462b37c1e..35f02bedd5 100644 --- a/src/connector/odbc/src/todbc_util.c +++ b/src/connector/odbc/src/todbc_util.c @@ -17,9 +17,6 @@ #include "iconv.h" -#include -#include -#include #include #include diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index 5f58ff13ce..b987c633a2 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -16,10 +16,9 @@ #ifndef _TODBC_UTIL_H_ #define _TODBC_UTIL_H_ +#include "todbc_flex_workaround.h" #include "todbc_log.h" -#include -#include const char* sql_sql_type(int type); const char* sql_c_type(int type); diff --git a/src/connector/odbc/tests/CMakeLists.txt b/src/connector/odbc/tests/CMakeLists.txt index 1649b45e02..d998527dc8 100644 --- a/src/connector/odbc/tests/CMakeLists.txt +++ b/src/connector/odbc/tests/CMakeLists.txt @@ -9,5 +9,5 @@ ENDIF () IF (TD_WINDOWS_64) AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(tcodbc main.c) - TARGET_LINK_LIBRARIES(tcodbc odbc) + # TARGET_LINK_LIBRARIES(tcodbc odbc) ENDIF () diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index 1321ade328..2a0dca7a4d 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -1,4 +1,4 @@ -#include +#include "os.h" #include #include @@ -423,7 +423,12 @@ int test_sqls_in_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, const char *sqls char *line = NULL; size_t len = 0; - ssize_t n = getline(&line, &len, f); + ssize_t n = 0; +#ifdef _MSC_VER + n = taosGetlineImp(&line, &len, f); +#else + n = getline(&line, &len, f); +#endif if (n==-1) break; const char *p = NULL; From 9be73e7b6caf7d4149505acf9b8efdd3dc0e3221 Mon Sep 17 00:00:00 2001 From: freemine Date: Mon, 26 Oct 2020 19:58:50 +0800 Subject: [PATCH 12/85] remove obsoletes --- src/connector/odbc/src/todbc_scanner.l | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l index 4c7aa74f2c..2f8fd42950 100644 --- a/src/connector/odbc/src/todbc_scanner.l +++ b/src/connector/odbc/src/todbc_scanner.l @@ -1,14 +1,9 @@ %{ -#include -#include -#include - #include "todbc_util.h" #include #ifdef _MSC_VER -#include "msvcLibgen.h" #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif From 4e402502a2ee5e3bbe81da51c53106988ecf8c58 Mon Sep 17 00:00:00 2001 From: freemine Date: Tue, 27 Oct 2020 13:33:59 +0800 Subject: [PATCH 13/85] 1. bugFix: memory leakage 2. satisfy CI --- src/connector/odbc/src/todbc.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 1ba5f1ac16..0a2a552fa3 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -679,7 +679,9 @@ SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER { size_t bytes = 0; SQLCHAR *utf8 = wchars_to_chars(szSqlStr, cbSqlStr, &bytes); - return SQLExecDirect(hstmt, utf8, bytes); + SQLRETURN r = SQLExecDirect(hstmt, utf8, bytes); + if (utf8) free(utf8); + return r; } static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, @@ -2224,9 +2226,7 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, if (NameLength) { *NameLength = strnlen(field->name, sizeof(field->name)); } - if (ColumnSize) { - *ColumnSize = field->bytes; - } + if (ColumnSize) *ColumnSize = field->bytes; if (DecimalDigits) *DecimalDigits = 0; if (DataType) { @@ -2260,12 +2260,9 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, } break; case TSDB_DATA_TYPE_TIMESTAMP: { - // *DataType = SQL_TIMESTAMP; - // *ColumnSize = 30; - // *DecimalDigits = 3; *DataType = SQL_TIMESTAMP; - *ColumnSize = sizeof(SQL_TIMESTAMP_STRUCT); - *DecimalDigits = 0; + if (ColumnSize) *ColumnSize = sizeof(SQL_TIMESTAMP_STRUCT); + if (DecimalDigits) *DecimalDigits = 0; } break; case TSDB_DATA_TYPE_NCHAR: { From 1eec11e9872afdbf1a12bcc33e395d7e454de341 Mon Sep 17 00:00:00 2001 From: freemine Date: Tue, 27 Oct 2020 21:41:16 +0800 Subject: [PATCH 14/85] first version of runnable win odbc driver --- src/connector/odbc/CMakeLists.txt | 8 +++++ src/connector/odbc/src/CMakeLists.txt | 24 +++++++++----- src/connector/odbc/src/todbc.c | 10 +++--- src/connector/odbc/src/todbc.def | 28 +++++++++++++++++ src/connector/odbc/src/todbc.rc.in | 31 +++++++++++++++++++ src/connector/odbc/src/todbc.rsp | 5 +++ src/connector/odbc/src/todbc_conv.c | 3 -- src/connector/odbc/src/todbc_conv.h | 7 ++--- .../{todbc_flex_workaround.h => todbc_flex.h} | 16 +++------- src/connector/odbc/src/todbc_log.h | 8 +---- src/connector/odbc/src/todbc_scanner.l | 6 ++-- src/connector/odbc/src/todbc_util.c | 7 ++--- src/connector/odbc/src/todbc_util.h | 7 ++--- src/connector/odbc/tests/CMakeLists.txt | 2 +- src/connector/odbc/tests/main.c | 22 +++++++------ src/os/inc/osWindows.h | 1 + 16 files changed, 123 insertions(+), 62 deletions(-) create mode 100644 src/connector/odbc/src/todbc.def create mode 100644 src/connector/odbc/src/todbc.rc.in create mode 100644 src/connector/odbc/src/todbc.rsp rename src/connector/odbc/src/{todbc_flex_workaround.h => todbc_flex.h} (71%) diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index 322f9c12cc..3d6564c230 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -29,6 +29,14 @@ IF (TD_LINUX_64) ENDIF () IF (TD_WINDOWS_64) + find_package(ODBC) + if (NOT ODBC_FOUND) + message(FATAL_ERROR "you need to install ODBC first") + else () + message(STATUS "ODBC_INCLUDE_DIRS: ${ODBC_INCLUDE_DIRS}") + message(STATUS "ODBC_LIBRARIES: ${ODBC_LIBRARIES}") + message(STATUS "ODBC_CONFIG: ${ODBC_CONFIG}") + endif () find_package(FLEX) if(NOT FLEX_FOUND) message(FATAL_ERROR "you need to install flex first") diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt index 19ee23b19f..7249e2d1de 100644 --- a/src/connector/odbc/src/CMakeLists.txt +++ b/src/connector/odbc/src/CMakeLists.txt @@ -16,8 +16,7 @@ IF (TD_LINUX_64) SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) TARGET_LINK_LIBRARIES(todbc taos) - target_include_directories(todbc PUBLIC - .) + target_include_directories(todbc PUBLIC .) install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") ENDIF () @@ -32,11 +31,20 @@ IF (TD_WINDOWS_64) ) AUX_SOURCE_DIRECTORY(. SRC) - # generate dynamic library (*.so) - ADD_LIBRARY(todbc SHARED ${SRC} ${todbc_flex_scanner_src}) - SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) - SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) + # generate dynamic library (*.dll) + ADD_LIBRARY(todbc SHARED + ${SRC} + ${todbc_flex_scanner_src} + ${CMAKE_CURRENT_BINARY_DIR}/todbc.rc + todbc.def) TARGET_LINK_LIBRARIES(todbc taos_static) - target_include_directories(todbc PUBLIC - .) + target_include_directories(todbc PUBLIC .) + target_compile_definitions(todbc PRIVATE "todbc_EXPORT") + + CONFIGURE_FILE("todbc.rc.in" + "${CMAKE_CURRENT_BINARY_DIR}/todbc.rc") + SET_TARGET_PROPERTIES(todbc PROPERTIES LINK_FLAGS + /DEF:todbc.def) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /GL") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") ENDIF () diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 9bde4fd2ec..2805a75ff0 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -17,19 +17,17 @@ #define _XOPEN_SOURCE #define _DEFAULT_SOURCE +#include "todbc_log.h" +#include "todbc_flex.h" + #include "taos.h" -#include "os.h" #include "taoserror.h" #include "todbc_util.h" #include "todbc_conv.h" -#include #include -#include - - #define GET_REF(obj) atomic_load_64(&obj->refcount) #define INC_REF(obj) atomic_add_fetch_64(&obj->refcount, 1) #define DEC_REF(obj) atomic_sub_fetch_64(&obj->refcount, 1) @@ -1919,7 +1917,7 @@ static SQLRETURN doSQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT *StringLength) { // if this function is not exported, isql will never call SQLGetDiagRec - return SQL_ERROR; + return SQL_SUCCESS; } SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, diff --git a/src/connector/odbc/src/todbc.def b/src/connector/odbc/src/todbc.def new file mode 100644 index 0000000000..3d34eef86b --- /dev/null +++ b/src/connector/odbc/src/todbc.def @@ -0,0 +1,28 @@ +EXPORTS +SQLAllocEnv +SQLFreeEnv +SQLAllocConnect +SQLFreeConnect +SQLConnect +SQLDisconnect +SQLAllocStmt +SQLAllocHandle +SQLFreeStmt +SQLExecDirect +SQLExecDirectW +SQLNumResultCols +SQLRowCount +SQLColAttribute +SQLGetData +SQLFetch +SQLPrepare +SQLExecute +SQLGetDiagField +SQLGetDiagRec +SQLBindParameter +SQLDriverConnect +SQLSetConnectAttr +SQLDescribeCol +SQLNumParams +SQLSetStmtAttr + diff --git a/src/connector/odbc/src/todbc.rc.in b/src/connector/odbc/src/todbc.rc.in new file mode 100644 index 0000000000..cf0b211454 --- /dev/null +++ b/src/connector/odbc/src/todbc.rc.in @@ -0,0 +1,31 @@ +1 VERSIONINFO + FILEVERSION ${TD_VER_NUMBER} + PRODUCTVERSION ${TD_VER_NUMBER} + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "ODBC Driver for TDengine" + VALUE "FileVersion", "${TD_VER_NUMBER}" + VALUE "InternalName", "todbc.dll(${TD_VER_CPUTYPE})" + VALUE "LegalCopyright", "Copyright (C) 2020 TAOS Data" + VALUE "OriginalFilename", "" + VALUE "ProductName", "todbc.dll(${TD_VER_CPUTYPE})" + VALUE "ProductVersion", "${TD_VER_NUMBER}" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file diff --git a/src/connector/odbc/src/todbc.rsp b/src/connector/odbc/src/todbc.rsp new file mode 100644 index 0000000000..f5e5115658 --- /dev/null +++ b/src/connector/odbc/src/todbc.rsp @@ -0,0 +1,5 @@ +INSTALLDRIVER "TAOS ODBC|Driver=todbc.dll|FileUsage=0|ConnectFunctions=YYN" + + + + diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index c6ce6a29f6..d9ed708a5d 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -14,9 +14,6 @@ */ #include "todbc_conv.h" -#include "todbc_util.h" - -#include "os.h" #include #include diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h index 9753620ee2..21c74b5474 100644 --- a/src/connector/odbc/src/todbc_conv.h +++ b/src/connector/odbc/src/todbc_conv.h @@ -16,10 +16,9 @@ #ifndef _todbc_conv_h_ #define _todbc_conv_h_ -#include "todbc_flex_workaround.h" -#include - -#include "iconv.h" +#include "os.h" +#include +#include typedef enum { diff --git a/src/connector/odbc/src/todbc_flex_workaround.h b/src/connector/odbc/src/todbc_flex.h similarity index 71% rename from src/connector/odbc/src/todbc_flex_workaround.h rename to src/connector/odbc/src/todbc_flex.h index d6c79cf19a..5ee5b53676 100644 --- a/src/connector/odbc/src/todbc_flex_workaround.h +++ b/src/connector/odbc/src/todbc_flex.h @@ -13,18 +13,10 @@ * along with this program. If not, see . */ -#ifndef _todbc_flex_workaround_h_ -#define _todbc_flex_workaround_h_ +#ifndef _TODBC_FLEX_H_ +#define _TODBC_FLEX_H_ -#ifdef _MSC_VER -#include -#include -#endif -#ifndef INT8_MIN -#include -#endif -#include -#include +int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host); -#endif // _todbc_flex_workaround_h_ +#endif // _TODBC_FLEX_H_ diff --git a/src/connector/odbc/src/todbc_log.h b/src/connector/odbc/src/todbc_log.h index 4f5b008d05..391a690ccc 100644 --- a/src/connector/odbc/src/todbc_log.h +++ b/src/connector/odbc/src/todbc_log.h @@ -16,13 +16,7 @@ #ifndef _todbc_log_h_ #define _todbc_log_h_ -#ifdef _MSC_VER -#include "msvcLibgen.h" -#else -#include -#endif -#include -#include +#include "os.h" #define D(fmt, ...) \ fprintf(stderr, \ diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l index 2f8fd42950..25a46e03cf 100644 --- a/src/connector/odbc/src/todbc_scanner.l +++ b/src/connector/odbc/src/todbc_scanner.l @@ -1,6 +1,5 @@ %{ -#include "todbc_util.h" - +#include "todbc_flex.h" #include #ifdef _MSC_VER @@ -105,8 +104,7 @@ do { \ [{] { CHG_STATE(BRACE1); } .|\n { return -1; } -[[:space:]]+ { } -[^{}\n[:space:]]+ { set_val(); CHG_STATE(BRACE2); } +[^{}\n]+ { set_val(); CHG_STATE(BRACE2); } .|\n { return -1; } [[:space:]]+ { } diff --git a/src/connector/odbc/src/todbc_util.c b/src/connector/odbc/src/todbc_util.c index 35f02bedd5..34008a8355 100644 --- a/src/connector/odbc/src/todbc_util.c +++ b/src/connector/odbc/src/todbc_util.c @@ -14,11 +14,10 @@ */ #include "todbc_util.h" +#include "todbc_log.h" +#include +#include -#include "iconv.h" - -#include -#include const char* sql_sql_type(int type) { switch (type) { diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index b987c633a2..f9339f9396 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -16,9 +16,10 @@ #ifndef _TODBC_UTIL_H_ #define _TODBC_UTIL_H_ -#include "todbc_flex_workaround.h" -#include "todbc_log.h" +#include "os.h" +#include +#include const char* sql_sql_type(int type); const char* sql_c_type(int type); @@ -26,8 +27,6 @@ const char* sql_c_type(int type); int is_valid_sql_c_type(int type); int is_valid_sql_sql_type(int type); -int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host); - int string_conv(const char *fromcode, const char *tocode, const unsigned char *src, size_t sbytes, unsigned char *dst, size_t dbytes, diff --git a/src/connector/odbc/tests/CMakeLists.txt b/src/connector/odbc/tests/CMakeLists.txt index d998527dc8..2edf45a852 100644 --- a/src/connector/odbc/tests/CMakeLists.txt +++ b/src/connector/odbc/tests/CMakeLists.txt @@ -9,5 +9,5 @@ ENDIF () IF (TD_WINDOWS_64) AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(tcodbc main.c) - # TARGET_LINK_LIBRARIES(tcodbc odbc) + TARGET_LINK_LIBRARIES(tcodbc odbc32 os) ENDIF () diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index 2a0dca7a4d..c2d0869e02 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -1,17 +1,16 @@ +#include "../src/todbc_log.h" + +#ifdef _MSC_VER +#include +#include #include "os.h" +#endif #include #include #include #include -#include "os.h" -#include "../src/todbc_log.h" - -// static const char *dsn = "TAOS_DSN"; -// static const char *uid = "root"; -// static const char *pwd = "taosdata"; - #define CHK_TEST(statement) \ do { \ D("testing: %s", #statement); \ @@ -425,7 +424,7 @@ int test_sqls_in_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, const char *sqls ssize_t n = 0; #ifdef _MSC_VER - n = taosGetlineImp(&line, &len, f); + n = taosGetline(&line, &len, f); #else n = getline(&line, &len, f); #endif @@ -503,7 +502,12 @@ int main(int argc, char *argv[]) { const char *connstr = (argc>4) ? argv[4] : NULL; const char *sqls = (argc>5) ? argv[5] : NULL; - if (1) { + dsn = NULL; + uid = NULL; + pwd = NULL; + connstr = argv[1]; + sqls = argv[2]; + if (0) { CHK_TEST(test_env()); CHK_TEST(test1(dsn, uid, pwd)); diff --git a/src/os/inc/osWindows.h b/src/os/inc/osWindows.h index dc1da35037..518719c3f0 100644 --- a/src/os/inc/osWindows.h +++ b/src/os/inc/osWindows.h @@ -43,6 +43,7 @@ #include "msvcProcess.h" #include "msvcDirect.h" #include "msvcFcntl.h" +#include "msvcLibgen.h" #include "msvcStdio.h" #include "sys/msvcStat.h" #include "sys/msvcTypes.h" From 5cadfd3037f1501b98a1be749e9e4718ed6a0225 Mon Sep 17 00:00:00 2001 From: freemine Date: Tue, 27 Oct 2020 21:52:03 +0800 Subject: [PATCH 15/85] .sql -> .stmts, because of .gitignore --- src/connector/odbc/tests/simples.stmts | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/connector/odbc/tests/simples.stmts diff --git a/src/connector/odbc/tests/simples.stmts b/src/connector/odbc/tests/simples.stmts new file mode 100644 index 0000000000..0db58a8807 --- /dev/null +++ b/src/connector/odbc/tests/simples.stmts @@ -0,0 +1,44 @@ +P:drop database if exists m; +P:create database m; +P:use m; + +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1)); +P:insert into t (ts, b) values('2020-10-10 00:00:00', 0); +P:insert into t (ts, b) values('2020-10-10 00:00:00.001', 1); +P:insert into t (ts, b) values('2020-10-10 00:00:00.002', 10); +P:select * from t; + +P:drop table t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1)); +P:insert into t (ts, v1) values('2020-10-10 00:00:00', 0); +P:insert into t (ts, v1) values('2020-10-10 00:00:00.001', 1); +P:insert into t (ts, v1) values('2020-10-10 00:00:00.002', 10); +P:select * from t; + +P:drop table t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1)); +P:insert into t (ts, name) values('2020-10-10 00:00:00', 0); +P:insert into t (ts, name) values('2020-10-10 00:00:00.001', 1); +P:insert into t (ts, name) values('2020-10-10 00:00:00.002', '人'); +P:insert into t (ts, name) values('2020-10-10 00:00:00.003', 'a'); +P:select * from t; + +P:drop table t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1)); +P:insert into t (ts, blob) values('2020-10-10 00:00:00', 0); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.001', 1); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.002', 'a'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.003', 'b'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.004', '人'); +P:select * from t; + +P:drop table t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1)); +N:insert into t (ts, blob) values('2020-10-10 00:00:00', '1234'); +N:insert into t (ts, blob) values('2020-10-10 00:00:00.001', '0000'); +N:insert into t (ts, blob) values('2020-10-10 00:00:00.002', '人a'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.003', 'a'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.004', 'b'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.005', '人'); +P:select * from t; + From cc496e12bb6c8828ab84b1e6767cdc52e0f46442 Mon Sep 17 00:00:00 2001 From: freemine Date: Wed, 28 Oct 2020 13:47:32 +0800 Subject: [PATCH 16/85] add todbcinst to help user install/uninstall taos odbc driver --- cmake/install.inc | 14 ++- src/connector/odbc/CMakeLists.txt | 2 + src/connector/odbc/tests/CMakeLists.txt | 2 +- src/connector/odbc/tests/main.c | 8 ++ src/connector/odbc/tools/CMakeLists.txt | 11 ++ src/connector/odbc/tools/main.c | 149 ++++++++++++++++++++++++ 6 files changed, 180 insertions(+), 6 deletions(-) create mode 100644 src/connector/odbc/tools/CMakeLists.txt create mode 100644 src/connector/odbc/tools/main.c diff --git a/cmake/install.inc b/cmake/install.inc index dfca758b93..2ea2201837 100755 --- a/cmake/install.inc +++ b/cmake/install.inc @@ -9,7 +9,7 @@ ELSEIF (TD_WINDOWS) ELSE () SET(CMAKE_INSTALL_PREFIX C:/TDengine) ENDIF () - + INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/go DESTINATION connector) INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/nodejs DESTINATION connector) INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/python DESTINATION connector) @@ -19,13 +19,17 @@ ELSEIF (TD_WINDOWS) INSTALL(FILES ${TD_COMMUNITY_DIR}/src/inc/taoserror.h DESTINATION include) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.lib DESTINATION driver) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.exp DESTINATION driver) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver) - + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.lib DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.exp DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.dll DESTINATION driver) + IF (TD_POWER) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/power.exe DESTINATION .) - ELSE () - INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .) + ELSE () + INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taosdemo.exe DESTINATION .) + INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/todbcinst.exe DESTINATION .) ENDIF () #INSTALL(TARGETS taos RUNTIME DESTINATION driver) diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index 3d6564c230..ea68ddd128 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -20,6 +20,7 @@ IF (TD_LINUX_64) SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wconversion") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tools) ADD_SUBDIRECTORY(tests) endif() endif() @@ -42,6 +43,7 @@ IF (TD_WINDOWS_64) message(FATAL_ERROR "you need to install flex first") else () ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tools) ADD_SUBDIRECTORY(tests) endif() ENDIF () diff --git a/src/connector/odbc/tests/CMakeLists.txt b/src/connector/odbc/tests/CMakeLists.txt index 2edf45a852..d777bf72ee 100644 --- a/src/connector/odbc/tests/CMakeLists.txt +++ b/src/connector/odbc/tests/CMakeLists.txt @@ -9,5 +9,5 @@ ENDIF () IF (TD_WINDOWS_64) AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(tcodbc main.c) - TARGET_LINK_LIBRARIES(tcodbc odbc32 os) + TARGET_LINK_LIBRARIES(tcodbc odbc32 odbccp32 user32 legacy_stdio_definitions os) ENDIF () diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index c2d0869e02..c61969ef65 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -7,6 +7,7 @@ #endif #include #include +#include #include #include @@ -496,6 +497,13 @@ int main(int argc, char *argv[]) { return 0; } + if (argc==2 && strcmp(argv[1], "uninstall")==0) { + DWORD usage = 0; + BOOL ok = SQLRemoveDriver("TAOS ODBC", TRUE, &usage); + D("ok/usage: %d/%d", ok, usage); + return ok ? 0 : 1; + } + const char *dsn = (argc>1) ? argv[1] : NULL; const char *uid = (argc>2) ? argv[2] : NULL; const char *pwd = (argc>3) ? argv[3] : NULL; diff --git a/src/connector/odbc/tools/CMakeLists.txt b/src/connector/odbc/tools/CMakeLists.txt new file mode 100644 index 0000000000..9d7025928f --- /dev/null +++ b/src/connector/odbc/tools/CMakeLists.txt @@ -0,0 +1,11 @@ +PROJECT(TDengine) + +IF (TD_LINUX) + ADD_EXECUTABLE(todbcinst main.c) + TARGET_LINK_LIBRARIES(todbcinst odbc) +ENDIF () + +IF (TD_WINDOWS_64) + ADD_EXECUTABLE(todbcinst main.c) + TARGET_LINK_LIBRARIES(todbcinst odbc32 odbccp32 user32 legacy_stdio_definitions os) +ENDIF () diff --git a/src/connector/odbc/tools/main.c b/src/connector/odbc/tools/main.c new file mode 100644 index 0000000000..d613ce151b --- /dev/null +++ b/src/connector/odbc/tools/main.c @@ -0,0 +1,149 @@ +#include "../src/todbc_log.h" + +#ifdef _MSC_VER +#include +#include +#include "os.h" +#endif +#include + +#include +#include + +static void usage(const char *arg0); +static int do_install(int i, int argc, char *argv[]); +static int do_uninstall(int i, int argc, char *argv[]); + +int main(int argc, char *argv[]) { + for (int i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (strcmp(arg, "-h") == 0) { + usage(argv[0]); + return 0; + } else if (strcmp(arg, "-i") == 0 ) { + i = do_install(i + 1, argc, argv); + if (i > 0) continue; + return i == 0 ? 0 : 1; + } else if (strcmp(arg, "-u") == 0 ) { + i = do_uninstall(i + 1, argc, argv); + if (i > 0) continue; + return i == 0 ? 0 : 1; + } else { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return 1; + } + } +} + +static void usage(const char *arg0) { + fprintf(stderr, "%s -h | -i -n [TaosDriverName] -p [TaosDriverPath] | -u [-f] [TaosDriverName]\n", arg0); + return; +} + +static int do_install(int i, int argc, char *argv[]) { + int forceful = 0; + const char* driverName = NULL; + const char* driverFile = "todbc.dll"; + const char* driverPath = NULL; + for (; i < argc; ++i) { + const char *arg = argv[i]; + if (strcmp(arg, "-n") == 0) { + i += 1; + if (i >= argc) { + fprintf(stderr, "expecting TaosDriverName, but got nothing\n"); + return -1; + } + arg = argv[i]; + if (strstr(arg, "TAOS") != arg) { + fprintf(stderr, "TaosDriverName shall begin with 'TAOS': [%s]\n", arg); + return -1; + } + driverName = arg; + } else if (strcmp(arg, "-p") == 0) { + i += 1; + if (i >= argc) { + fprintf(stderr, "expecting TaosDriverPath, but got nothing\n"); + return -1; + } + driverPath = argv[i]; + } else { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return -1; + } + } + if (!driverName) { + fprintf(stderr, "TaosDriverName not specified\n"); + return -1; + } + if (!driverPath) { + fprintf(stderr, "TaosDriverPath not specified\n"); + return -1; + } + char buf[8192]; + snprintf(buf, sizeof(buf), "%s%cDriver=%s%cFileUage=0%cConnectFunctions=YYN%c", + driverName, 0, driverFile, 0, 0, 0); + BOOL ok = TRUE; + DWORD usageCount = 1; + char installed[PATH_MAX + 1]; + WORD len = 0; + ok = SQLInstallDriverEx(buf, driverPath, installed, sizeof(installed), &len, ODBC_INSTALL_INQUIRY, &usageCount); + if (!ok) { + fprintf(stderr, "failed to query TaosDriverName: [%s]\n", driverName); + return -1; + } + if (stricmp(driverPath, installed)) { + fprintf(stderr, "previously installed TaosDriver [%s] has different target path [%s]\n" + "it shall be uninstalled before you can install it to different path [%s]\n", + driverName, installed, driverPath); + return -1; + } + ok = SQLInstallDriverEx(buf, driverPath, installed, sizeof(installed), &len, ODBC_INSTALL_COMPLETE, &usageCount); + if (!ok) { + fprintf(stderr, "failed to install TaosDriverName: [%s][%s]\n", driverName, driverPath); + return -1; + } + + return argc; +} + +static int do_uninstall(int i, int argc, char *argv[]) { + int forceful = 0; + const char* driverName = NULL; + for (; i < argc; ++i) { + const char *arg = argv[i]; + if (strcmp(arg, "-f") == 0) { + forceful = 1; + } else if (strcmp(arg, "-n") == 0) { + i += 1; + if (i >= argc) { + fprintf(stderr, "expecting TaosDriverName, but got nothing\n"); + return -1; + } + arg = argv[i]; + if (strstr(arg, "TAOS") != arg) { + fprintf(stderr, "TaosDriverName shall begin with 'TAOS': [%s]\n", arg); + return -1; + } + driverName = arg; + } else { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return -1; + } + } + if (!driverName) { + fprintf(stderr, "TaosDriverName not specified\n"); + return -1; + } + BOOL ok = TRUE; + DWORD usageCount = 1; + do { + ok = SQLRemoveDriver(driverName, FALSE, &usageCount); + if (!ok) { + fprintf(stderr, "failed to remove driver [%s]\n", driverName); + return -1; + } + if (!forceful) return argc; + } while (usageCount > 0); + return argc; +} + From f6eefa999420ae948afdf5e69c1f1e22a1d97d00 Mon Sep 17 00:00:00 2001 From: freemine Date: Wed, 28 Oct 2020 15:03:50 +0800 Subject: [PATCH 17/85] 1. remove obsolete codes in tests/main.c 2. linux port of todbcinst --- src/connector/odbc/tests/main.c | 7 ------- src/connector/odbc/tools/CMakeLists.txt | 2 +- src/connector/odbc/tools/main.c | 22 ++++++++++++++++------ 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index c61969ef65..1bb174e7b9 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -497,13 +497,6 @@ int main(int argc, char *argv[]) { return 0; } - if (argc==2 && strcmp(argv[1], "uninstall")==0) { - DWORD usage = 0; - BOOL ok = SQLRemoveDriver("TAOS ODBC", TRUE, &usage); - D("ok/usage: %d/%d", ok, usage); - return ok ? 0 : 1; - } - const char *dsn = (argc>1) ? argv[1] : NULL; const char *uid = (argc>2) ? argv[2] : NULL; const char *pwd = (argc>3) ? argv[3] : NULL; diff --git a/src/connector/odbc/tools/CMakeLists.txt b/src/connector/odbc/tools/CMakeLists.txt index 9d7025928f..5d8afb092d 100644 --- a/src/connector/odbc/tools/CMakeLists.txt +++ b/src/connector/odbc/tools/CMakeLists.txt @@ -2,7 +2,7 @@ PROJECT(TDengine) IF (TD_LINUX) ADD_EXECUTABLE(todbcinst main.c) - TARGET_LINK_LIBRARIES(todbcinst odbc) + TARGET_LINK_LIBRARIES(todbcinst odbc odbcinst) ENDIF () IF (TD_WINDOWS_64) diff --git a/src/connector/odbc/tools/main.c b/src/connector/odbc/tools/main.c index d613ce151b..b9422830c0 100644 --- a/src/connector/odbc/tools/main.c +++ b/src/connector/odbc/tools/main.c @@ -7,6 +7,7 @@ #endif #include +#include #include #include @@ -36,14 +37,17 @@ int main(int argc, char *argv[]) { } static void usage(const char *arg0) { - fprintf(stderr, "%s -h | -i -n [TaosDriverName] -p [TaosDriverPath] | -u [-f] [TaosDriverName]\n", arg0); + fprintf(stderr, "%s -h | -i -n [TaosDriverName] -p [TaosDriverPath] | -u [-f] -n [TaosDriverName]\n", arg0); return; } static int do_install(int i, int argc, char *argv[]) { - int forceful = 0; const char* driverName = NULL; +#ifdef _MSC_VER const char* driverFile = "todbc.dll"; +#else + const char* driverFile = "libtodbc.so"; +#endif const char* driverPath = NULL; for (; i < argc; ++i) { const char *arg = argv[i]; @@ -82,7 +86,7 @@ static int do_install(int i, int argc, char *argv[]) { char buf[8192]; snprintf(buf, sizeof(buf), "%s%cDriver=%s%cFileUage=0%cConnectFunctions=YYN%c", driverName, 0, driverFile, 0, 0, 0); - BOOL ok = TRUE; + BOOL ok = 1; DWORD usageCount = 1; char installed[PATH_MAX + 1]; WORD len = 0; @@ -91,7 +95,13 @@ static int do_install(int i, int argc, char *argv[]) { fprintf(stderr, "failed to query TaosDriverName: [%s]\n", driverName); return -1; } - if (stricmp(driverPath, installed)) { + int r = 0; +#ifdef _MSC_VER + r = stricmp(driverPath, installed); +#else + r = strcasecmp(driverPath, installed); +#endif + if (r) { fprintf(stderr, "previously installed TaosDriver [%s] has different target path [%s]\n" "it shall be uninstalled before you can install it to different path [%s]\n", driverName, installed, driverPath); @@ -134,10 +144,10 @@ static int do_uninstall(int i, int argc, char *argv[]) { fprintf(stderr, "TaosDriverName not specified\n"); return -1; } - BOOL ok = TRUE; + BOOL ok = 1; DWORD usageCount = 1; do { - ok = SQLRemoveDriver(driverName, FALSE, &usageCount); + ok = SQLRemoveDriver(driverName, 0, &usageCount); if (!ok) { fprintf(stderr, "failed to remove driver [%s]\n", driverName); return -1; From 11f24b7c21c5ebd1494fa346a897f150cbe7974e Mon Sep 17 00:00:00 2001 From: freemine Date: Thu, 29 Oct 2020 15:05:49 +0800 Subject: [PATCH 18/85] parameters check in depth --- src/connector/odbc/src/todbc.c | 186 ++++++++++++++++++++++++++------- 1 file changed, 146 insertions(+), 40 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 618681aa51..93f1d832fe 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -266,6 +266,18 @@ static iconv_t sql_get_w2c(sql_t *sql) { return sql->w2c; } +// typedef struct stack_buffer_s stack_buffer_t; +// struct stack_buffer_s { +// char buf[1024*16]; +// size_t next; +// }; +// +// static char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes); +// static int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr); +// +// static const char* tsdb_conn_conv_client_to_server(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); +// static const char* tsdb_conn_conv_server_to_client(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); + // static iconv_t sql_get_u2c(sql_t *sql) { // if (sql->u2c == (iconv_t)-1) { // sql->u2c = iconv_open("UTF-8", "UCS-4LE"); @@ -287,7 +299,7 @@ static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) pthread_once(&init_once, init_routine); env_t *env = (env_t*)calloc(1, sizeof(*env)); - if (!env) return SQL_ERROR; + if (!env) return SQL_INVALID_HANDLE; DASSERT(INC_REF(env)>0); @@ -307,7 +319,7 @@ SQLRETURN SQL_API SQLAllocEnv(SQLHENV *EnvironmentHandle) static SQLRETURN doSQLFreeEnv(SQLHENV EnvironmentHandle) { env_t *env = (env_t*)EnvironmentHandle; - if (!env) return SQL_ERROR; + if (!env) return SQL_INVALID_HANDLE; DASSERT(GET_REF(env)==1); @@ -335,7 +347,12 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, SQLHDBC *ConnectionHandle) { env_t *env = (env_t*)EnvironmentHandle; - if (!env) return SQL_ERROR; + if (!env) return SQL_INVALID_HANDLE; + + if (!ConnectionHandle) { + SET_ERROR(env, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ConnectionHandle [%p] not valid", ConnectionHandle); + return SQL_ERROR; + } DASSERT(INC_REF(env)>1); @@ -371,7 +388,7 @@ SQLRETURN SQL_API SQLAllocConnect(SQLHENV EnvironmentHandle, static SQLRETURN doSQLFreeConnect(SQLHDBC ConnectionHandle) { conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; DASSERT(GET_REF(conn)==1); @@ -414,14 +431,22 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, return SQL_ERROR; } - NameLength1 = (NameLength1==SQL_NTS) ? (SQLSMALLINT)strlen((const char*)ServerName) : NameLength1; - NameLength2 = (NameLength2==SQL_NTS) ? (SQLSMALLINT)strlen((const char*)UserName) : NameLength2; - NameLength3 = (NameLength3==SQL_NTS) ? (SQLSMALLINT)strlen((const char*)Authentication) : NameLength3; - - if (NameLength1 < 0 || NameLength2 < 0 || NameLength3 < 0) { + if (NameLength1 < 0 && NameLength1!=SQL_NTS) { SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); return SQL_ERROR; } + if (NameLength2 < 0 && NameLength2!=SQL_NTS) { + SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + if (NameLength3 < 0 && NameLength3!=SQL_NTS) { + SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + if (NameLength1==SQL_NTS) NameLength1 = ServerName ? (SQLSMALLINT)strlen((const char*)ServerName) : 0; + if (NameLength2==SQL_NTS) NameLength2 = UserName ? (SQLSMALLINT)strlen((const char*)UserName) : 0; + if (NameLength3==SQL_NTS) NameLength3 = Authentication ? (SQLSMALLINT)strlen((const char*)Authentication) : 0; + if (NameLength1>SQL_MAX_DSN_LENGTH) { SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); return SQL_ERROR; @@ -468,7 +493,7 @@ SQLRETURN SQL_API SQLConnect(SQLHDBC ConnectionHandle, static SQLRETURN doSQLDisconnect(SQLHDBC ConnectionHandle) { conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; if (conn->taos) { taos_close(conn->taos); @@ -486,10 +511,15 @@ SQLRETURN SQL_API SQLDisconnect(SQLHDBC ConnectionHandle) } static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle, - SQLHSTMT *StatementHandle) + SQLHSTMT *StatementHandle) { conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; + + if (!StatementHandle) { + SET_ERROR(conn, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StatementHandle [%p] not valid", StatementHandle); + return SQL_ERROR; + } DASSERT(INC_REF(conn)>1); @@ -530,20 +560,17 @@ static SQLRETURN doSQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, switch (HandleType) { case SQL_HANDLE_ENV: { SQLHENV env = {0}; + if (!OutputHandle) return SQL_ERROR; SQLRETURN r = doSQLAllocEnv(&env); - if (r==SQL_SUCCESS && OutputHandle) *OutputHandle = env; + if (r==SQL_SUCCESS) *OutputHandle = env; return r; } break; case SQL_HANDLE_DBC: { - SQLHDBC dbc = {0}; - SQLRETURN r = doSQLAllocConnect(InputHandle, &dbc); - if (r==SQL_SUCCESS && OutputHandle) *OutputHandle = dbc; + SQLRETURN r = doSQLAllocConnect(InputHandle, OutputHandle); return r; } break; case SQL_HANDLE_STMT: { - SQLHSTMT stmt = {0}; - SQLRETURN r = doSQLAllocStmt(InputHandle, &stmt); - if (r==SQL_SUCCESS && OutputHandle) *OutputHandle = stmt; + SQLRETURN r = doSQLAllocStmt(InputHandle, OutputHandle); return r; } break; default: { @@ -563,12 +590,20 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; - if (Option == SQL_CLOSE) return SQL_SUCCESS; - if (Option != SQL_DROP) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "free statement with Option[%x] not supported yet", Option); - return SQL_ERROR; + switch (Option) { + case SQL_CLOSE: return SQL_SUCCESS; + case SQL_DROP: break; + case SQL_UNBIND: + case SQL_RESET_PARAMS: { + SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "free statement with Option[%x] not supported yet", Option); + return SQL_ERROR; + } break; + default: { + SET_ERROR(sql, "HY092", TSDB_CODE_ODBC_OUT_OF_RANGE, "free statement with Option[%x] not supported yet", Option); + return SQL_ERROR; + } break; } DASSERT(GET_REF(sql)==1); @@ -626,11 +661,21 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); + if (!StatementText) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StatementText [%p] not allowed", StatementText); + return SQL_ERROR; + } + if (TextLength < 0 && TextLength!=SQL_NTS) { + SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + if (TextLength==SQL_NTS) TextLength = StatementText ? (SQLSMALLINT)strlen((const char*)StatementText) : 0; + if (sql->rs) { taos_free_result(sql->rs); sql->rs = NULL; @@ -673,8 +718,23 @@ SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle, return r; } -SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER cbSqlStr) +static SQLRETURN doSQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER cbSqlStr) { + sql_t *sql = (sql_t*)hstmt; + if (!sql) return SQL_INVALID_HANDLE; + + CHK_CONN(sql); + CHK_CONN_TAOS(sql); + + if (!szSqlStr) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "szSqlStr [%p] not allowed", szSqlStr); + return SQL_ERROR; + } + if (cbSqlStr < 0) { + SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + size_t bytes = 0; SQLCHAR *utf8 = wchars_to_chars(szSqlStr, (size_t)cbSqlStr, &bytes); SQLRETURN r = SQLExecDirect(hstmt, utf8, (SQLINTEGER)bytes); @@ -682,11 +742,17 @@ SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER return r; } +SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER cbSqlStr) +{ + SQLRETURN r = doSQLExecDirectW(hstmt, szSqlStr, cbSqlStr); + return r; +} + static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCount) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -728,7 +794,22 @@ static SQLRETURN doSQLRowCount(SQLHSTMT StatementHandle, CHK_CONN(sql); CHK_CONN_TAOS(sql); - if (sql->is_insert) { + // ref: https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlrowcount-function?view=sql-server-ver15 + // Summary + // SQLRowCount returns the number of rows affected by an UPDATE, INSERT, or DELETE statement; + // an SQL_ADD, SQL_UPDATE_BY_BOOKMARK, or SQL_DELETE_BY_BOOKMARK operation in SQLBulkOperations; + // or an SQL_UPDATE or SQL_DELETE operation in SQLSetPos. + + // how to fetch affected rows from taos? + // taos_affected_rows? + + if (1) { + SET_ERROR(sql, "IM001", TSDB_CODE_ODBC_NOT_SUPPORT, ""); + // if (RowCount) *RowCount = 0; + return SQL_SUCCESS_WITH_INFO; + } + + if (!sql->is_insert) { if (RowCount) *RowCount = 0; return SQL_SUCCESS; } @@ -789,6 +870,7 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle, *NumericAttribute = (SQLLEN)do_field_display_size(field); } break; case SQL_COLUMN_LABEL: { + // todo: check BufferLength size_t n = sizeof(field->name); strncpy(CharacterAttribute, field->name, (n>BufferLength ? (size_t)BufferLength : n)); } break; @@ -823,7 +905,7 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, SQLLEN *StrLen_or_Ind) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -1047,7 +1129,7 @@ SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle, static SQLRETURN doSQLFetch(SQLHSTMT StatementHandle) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -1072,11 +1154,21 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); + if (!StatementText) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StatementText [%p] not allowed", StatementText); + return SQL_ERROR; + } + if (TextLength < 0 && TextLength!=SQL_NTS) { + SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + if (TextLength==SQL_NTS) TextLength = StatementText ? (SQLSMALLINT)strlen((const char*)StatementText) : 0; + if (sql->rs) { taos_free_result(sql->rs); sql->rs = NULL; @@ -1873,7 +1965,7 @@ static SQLRETURN do_execute(sql_t *sql) } sql->is_executed = 1; - if (sql->is_insert) return SQL_SUCCESS; + // if (sql->is_insert) return SQL_SUCCESS; SQLRETURN r = SQL_SUCCESS; PROFILE(sql->rs = taos_stmt_use_result(sql->stmt)); @@ -1995,7 +2087,7 @@ static SQLRETURN doSQLBindParameter( SQLLEN *StrLen_or_Ind) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -2078,17 +2170,27 @@ static SQLRETURN doSQLDriverConnect( SQLUSMALLINT fDriverCompletion) { conn_t *conn = (conn_t*)hdbc; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; + + if (conn->taos) { + SET_ERROR(conn, "08002", TSDB_CODE_ODBC_CONNECTION_BUSY, "connection still in use"); + return SQL_ERROR; + } if (fDriverCompletion!=SQL_DRIVER_NOPROMPT) { SET_ERROR(conn, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "option[%d] other than SQL_DRIVER_NOPROMPT not supported yet", fDriverCompletion); return SQL_ERROR; } - if (conn->taos) { - SET_ERROR(conn, "08002", TSDB_CODE_ODBC_CONNECTION_BUSY, "connection still in use"); + if (!szConnStrIn) { + SET_ERROR(conn, "HY009", TSDB_CODE_ODBC_BAD_ARG, "szConnStrIn [%p] not allowed", szConnStrIn); return SQL_ERROR; } + if (cbConnStrIn < 0 && cbConnStrIn!=SQL_NTS) { + SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + if (cbConnStrIn==SQL_NTS) cbConnStrIn = szConnStrIn ? (SQLSMALLINT)strlen((const char*)szConnStrIn) : 0; // DSN=; UID=; PWD= @@ -2167,7 +2269,7 @@ static SQLRETURN doSQLSetConnectAttr(SQLHDBC ConnectionHandle, SQLINTEGER StringLength) { conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; if (Attribute != SQL_ATTR_AUTOCOMMIT) { SET_ERROR(conn, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "Attribute other than SQL_ATTR_AUTOCOMMIT not supported yet"); @@ -2197,7 +2299,7 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -2214,6 +2316,10 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, SET_ERROR(sql, "07009", TSDB_CODE_ODBC_OUT_OF_RANGE, "invalid column number [%d]", ColumnNumber); return SQL_ERROR; } + if (BufferLength<0) { + SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } TAOS_FIELD *field = fields + ColumnNumber - 1; if (ColumnName) { @@ -2304,7 +2410,7 @@ SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle, static SQLRETURN doSQLNumParams(SQLHSTMT hstmt, SQLSMALLINT *pcpar) { sql_t *sql = (sql_t*)hstmt; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -2349,7 +2455,7 @@ static SQLRETURN doSQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER StringLength) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); From bf927e7375355b5ffc2baf7db53053430f1adb47 Mon Sep 17 00:00:00 2001 From: freemine Date: Thu, 29 Oct 2020 15:23:04 +0800 Subject: [PATCH 19/85] macro to normalize str/len --- src/connector/odbc/src/todbc.c | 89 ++++++++++++---------------------- 1 file changed, 32 insertions(+), 57 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 93f1d832fe..d85f7903d6 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -129,6 +129,15 @@ do { \ r_091c = SQL_SUCCESS; \ } while (0) +#define NORM_STR_LENGTH(obj, ptr, len) \ +do { \ + if ((len) < 0 && (len)!=SQL_NTS) { \ + SET_ERROR((obj), "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); \ + return SQL_ERROR; \ + } \ + if (len==SQL_NTS) len = (ptr) ? (SQLSMALLINT)strlen((const char*)(ptr)) : 0; \ +} while (0) + #define PROFILING 0 #define PROFILE(statement) \ @@ -277,22 +286,24 @@ static iconv_t sql_get_w2c(sql_t *sql) { // // static const char* tsdb_conn_conv_client_to_server(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); // static const char* tsdb_conn_conv_server_to_client(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); - +// static const char* tsdb_conn_conv_wchars_to_server(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); +// static const char* tsdb_conn_conv_server_to_wchars(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); +// // static iconv_t sql_get_u2c(sql_t *sql) { -// if (sql->u2c == (iconv_t)-1) { -// sql->u2c = iconv_open("UTF-8", "UCS-4LE"); -// } -// -// return sql->u2c; -// } -// -// static iconv_t sql_get_u2w(sql_t *sql) { -// if (sql->u2w == (iconv_t)-1) { -// sql->u2w = iconv_open("UCS-2LE", "UCS-4LE"); -// } -// -// return sql->u2w; -// } + if (sql->u2c == (iconv_t)-1) { + sql->u2c = iconv_open("UTF-8", "UCS-4LE"); + } + + return sql->u2c; +} + +static iconv_t sql_get_u2w(sql_t *sql) { + if (sql->u2w == (iconv_t)-1) { + sql->u2w = iconv_open("UCS-2LE", "UCS-4LE"); + } + + return sql->u2w; +} static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) { @@ -431,21 +442,9 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, return SQL_ERROR; } - if (NameLength1 < 0 && NameLength1!=SQL_NTS) { - SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - if (NameLength2 < 0 && NameLength2!=SQL_NTS) { - SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - if (NameLength3 < 0 && NameLength3!=SQL_NTS) { - SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - if (NameLength1==SQL_NTS) NameLength1 = ServerName ? (SQLSMALLINT)strlen((const char*)ServerName) : 0; - if (NameLength2==SQL_NTS) NameLength2 = UserName ? (SQLSMALLINT)strlen((const char*)UserName) : 0; - if (NameLength3==SQL_NTS) NameLength3 = Authentication ? (SQLSMALLINT)strlen((const char*)Authentication) : 0; + NORM_STR_LENGTH(conn, ServerName, NameLength1); + NORM_STR_LENGTH(conn, UserName, NameLength2); + NORM_STR_LENGTH(conn, Authentication, NameLength3); if (NameLength1>SQL_MAX_DSN_LENGTH) { SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); @@ -666,15 +665,7 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, CHK_CONN(sql); CHK_CONN_TAOS(sql); - if (!StatementText) { - SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StatementText [%p] not allowed", StatementText); - return SQL_ERROR; - } - if (TextLength < 0 && TextLength!=SQL_NTS) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - if (TextLength==SQL_NTS) TextLength = StatementText ? (SQLSMALLINT)strlen((const char*)StatementText) : 0; + NORM_STR_LENGTH(sql, StatementText, TextLength); if (sql->rs) { taos_free_result(sql->rs); @@ -1159,15 +1150,7 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, CHK_CONN(sql); CHK_CONN_TAOS(sql); - if (!StatementText) { - SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StatementText [%p] not allowed", StatementText); - return SQL_ERROR; - } - if (TextLength < 0 && TextLength!=SQL_NTS) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - if (TextLength==SQL_NTS) TextLength = StatementText ? (SQLSMALLINT)strlen((const char*)StatementText) : 0; + NORM_STR_LENGTH(sql, StatementText, TextLength); if (sql->rs) { taos_free_result(sql->rs); @@ -2182,15 +2165,7 @@ static SQLRETURN doSQLDriverConnect( return SQL_ERROR; } - if (!szConnStrIn) { - SET_ERROR(conn, "HY009", TSDB_CODE_ODBC_BAD_ARG, "szConnStrIn [%p] not allowed", szConnStrIn); - return SQL_ERROR; - } - if (cbConnStrIn < 0 && cbConnStrIn!=SQL_NTS) { - SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - if (cbConnStrIn==SQL_NTS) cbConnStrIn = szConnStrIn ? (SQLSMALLINT)strlen((const char*)szConnStrIn) : 0; + NORM_STR_LENGTH(conn, szConnStrIn, cbConnStrIn) // DSN=; UID=; PWD= From 7d332df5cd2595487e57cd4c579595ee4ed2d785 Mon Sep 17 00:00:00 2001 From: freemine Date: Thu, 29 Oct 2020 15:25:40 +0800 Subject: [PATCH 20/85] typo correction --- src/connector/odbc/src/todbc.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index d85f7903d6..f57fdfb067 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -288,22 +288,22 @@ static iconv_t sql_get_w2c(sql_t *sql) { // static const char* tsdb_conn_conv_server_to_client(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); // static const char* tsdb_conn_conv_wchars_to_server(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); // static const char* tsdb_conn_conv_server_to_wchars(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); -// +// // static iconv_t sql_get_u2c(sql_t *sql) { - if (sql->u2c == (iconv_t)-1) { - sql->u2c = iconv_open("UTF-8", "UCS-4LE"); - } - - return sql->u2c; -} - -static iconv_t sql_get_u2w(sql_t *sql) { - if (sql->u2w == (iconv_t)-1) { - sql->u2w = iconv_open("UCS-2LE", "UCS-4LE"); - } - - return sql->u2w; -} +// if (sql->u2c == (iconv_t)-1) { +// sql->u2c = iconv_open("UTF-8", "UCS-4LE"); +// } +// +// return sql->u2c; +// } +// +// static iconv_t sql_get_u2w(sql_t *sql) { +// if (sql->u2w == (iconv_t)-1) { +// sql->u2w = iconv_open("UCS-2LE", "UCS-4LE"); +// } +// +// return sql->u2w; +// } static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) { @@ -2165,7 +2165,7 @@ static SQLRETURN doSQLDriverConnect( return SQL_ERROR; } - NORM_STR_LENGTH(conn, szConnStrIn, cbConnStrIn) + NORM_STR_LENGTH(conn, szConnStrIn, cbConnStrIn); // DSN=; UID=; PWD= From f43bbfea2246a1ff214fa9276018401e20ba0df8 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 12:38:31 +0800 Subject: [PATCH 21/85] adding charset-endec support --- src/connector/odbc/src/todbc.c | 560 ++++++++++++++++++------- src/connector/odbc/src/todbc_conv.c | 301 +++++++++++++ src/connector/odbc/src/todbc_conv.h | 34 ++ src/connector/odbc/src/todbc_flex.h | 16 +- src/connector/odbc/src/todbc_scanner.l | 65 ++- 5 files changed, 808 insertions(+), 168 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index f57fdfb067..c39c57cd94 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -28,6 +28,11 @@ #include +#define UTF8_ENC "UTF-8" +#define UTF16_ENC "UCS-2LE" +#define UNICODE_ENC "UCS-4LE" +#define GB18030_ENC "GB18030" + #define GET_REF(obj) atomic_load_64(&obj->refcount) #define INC_REF(obj) atomic_add_fetch_64(&obj->refcount, 1) #define DEC_REF(obj) atomic_sub_fetch_64(&obj->refcount, 1) @@ -159,8 +164,8 @@ do { \ #define CHK_CONV(todb, statement) \ do { \ - TSDB_CONV_CODE code = (statement); \ - switch (code) { \ + TSDB_CONV_CODE code_0c80 = (statement); \ + switch (code_0c80) { \ case TSDB_CONV_OK: return SQL_SUCCESS; \ case TSDB_CONV_OOM: { \ SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); \ @@ -225,6 +230,16 @@ struct conn_s { uint64_t refcount; env_t *env; + char client_enc[64]; + char server_enc[64]; + + tsdb_conv_t *client_to_server; + tsdb_conv_t *server_to_client; + tsdb_conv_t *utf8_to_client; + tsdb_conv_t *utf16_to_utf8; + tsdb_conv_t *utf16_to_server; + tsdb_conv_t *client_to_utf8; + TAOS *taos; taos_error_t err; @@ -275,20 +290,88 @@ static iconv_t sql_get_w2c(sql_t *sql) { return sql->w2c; } -// typedef struct stack_buffer_s stack_buffer_t; -// struct stack_buffer_s { -// char buf[1024*16]; -// size_t next; -// }; -// -// static char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes); -// static int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr); -// -// static const char* tsdb_conn_conv_client_to_server(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); -// static const char* tsdb_conn_conv_server_to_client(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); -// static const char* tsdb_conn_conv_wchars_to_server(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); -// static const char* tsdb_conn_conv_server_to_wchars(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len); -// + +static tsdb_conv_t* tsdb_conn_client_to_server(conn_t *conn) { + if (!conn->client_to_server) { + conn->client_to_server = tsdb_conv_open(conn->client_enc, conn->server_enc); + } + return conn->client_to_server; +} + +static tsdb_conv_t* tsdb_conn_server_to_client(conn_t *conn) { + if (!conn->server_to_client) { + conn->server_to_client = tsdb_conv_open(conn->server_enc, conn->client_enc); + } + return conn->server_to_client; +} + +static tsdb_conv_t* tsdb_conn_utf8_to_client(conn_t *conn) { + if (!conn->utf8_to_client) { + conn->utf8_to_client = tsdb_conv_open(UTF8_ENC, conn->client_enc); + } + return conn->utf8_to_client; +} + +tsdb_conv_t* tsdb_conn_utf16_to_utf8(conn_t *conn) { + if (!conn->utf16_to_utf8) { + conn->utf16_to_utf8 = tsdb_conv_open(UTF16_ENC, UTF8_ENC); + } + return conn->utf16_to_utf8; +} + +tsdb_conv_t* tsdb_conn_utf16_to_server(conn_t *conn) { + if (!conn->utf16_to_server) { + conn->utf16_to_server = tsdb_conv_open(UTF16_ENC, conn->server_enc); + } + return conn->utf16_to_server; +} + +static tsdb_conv_t* tsdb_conn_client_to_utf8(conn_t *conn) { + if (!conn->client_to_utf8) { + conn->client_to_utf8 = tsdb_conv_open(conn->client_enc, UTF8_ENC); + } + return conn->client_to_utf8; +} + +static void tsdb_conn_close_convs(conn_t *conn) { + if (0) { + tsdb_conn_server_to_client(NULL); + } + if (conn->client_to_server) { + tsdb_conv_close(conn->client_to_server); + conn->client_to_server = NULL; + } + if (conn->server_to_client) { + tsdb_conv_close(conn->server_to_client); + conn->server_to_client = NULL; + } + if (conn->utf8_to_client) { + tsdb_conv_close(conn->utf8_to_client); + conn->utf8_to_client = NULL; + } + if (conn->utf16_to_utf8) { + tsdb_conv_close(conn->utf16_to_utf8); + conn->utf16_to_utf8 = NULL; + } + if (conn->utf16_to_server) { + tsdb_conv_close(conn->utf16_to_server); + conn->utf16_to_server = NULL; + } + if (conn->client_to_utf8) { + tsdb_conv_close(conn->client_to_utf8); + conn->client_to_utf8 = NULL; + } +} + +#define SFREE(buffer, v, src) \ +do { \ + const char *v_096a = (const char*)(v); \ + const char *src_6a = (const char*)(src); \ + if (v_096a && v_096a!=src_6a && !is_owned_by_stack_buffer((buffer), v_096a)) { \ + free((char*)v_096a); \ + } \ +} while (0) + // static iconv_t sql_get_u2c(sql_t *sql) { // if (sql->u2c == (iconv_t)-1) { // sql->u2c = iconv_open("UTF-8", "UCS-4LE"); @@ -375,6 +458,9 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, break; } + snprintf(conn->client_enc, sizeof(conn->client_enc), UTF8_ENC); + snprintf(conn->server_enc, sizeof(conn->server_enc), UTF8_ENC); + conn->env = env; *ConnectionHandle = conn; @@ -416,6 +502,7 @@ static SQLRETURN doSQLFreeConnect(SQLHDBC ConnectionHandle) conn->env = NULL; FREE_ERROR(conn); + tsdb_conn_close_convs(conn); free(conn); } while (0); @@ -434,6 +521,8 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, SQLCHAR *UserName, SQLSMALLINT NameLength2, SQLCHAR *Authentication, SQLSMALLINT NameLength3) { + stack_buffer_t buffer; buffer.next = 0; + conn_t *conn = (conn_t*)ConnectionHandle; if (!conn) return SQL_ERROR; @@ -451,12 +540,16 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, return SQL_ERROR; } - const char *serverName = SDUP(ServerName, NameLength1); - const char *userName = SDUP(UserName, NameLength2); - const char *auth = SDUP(Authentication, NameLength3); + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + const char *serverName = NULL; + const char *userName = NULL; + const char *auth = NULL; do { - if ((ServerName && !serverName) || (UserName && !userName) || (Authentication && !auth)) { + tsdb_conv(client_to_server, &buffer, (const char*)ServerName, (size_t)NameLength1, &serverName, NULL); + tsdb_conv(client_to_server, &buffer, (const char*)UserName, (size_t)NameLength2, &userName, NULL); + tsdb_conv(client_to_server, &buffer, (const char*)Authentication, (size_t)NameLength3, &auth, NULL); + if ((!serverName) || (!userName) || (!auth)) { SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, ""); break; } @@ -470,9 +563,9 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, } } while (0); - SFRE(serverName, ServerName, NameLength1); - SFRE(userName, UserName, NameLength2); - SFRE(auth, Authentication, NameLength3); + tsdb_conv_free(client_to_server, serverName, &buffer, (const char*)ServerName); + tsdb_conv_free(client_to_server, userName, &buffer, (const char*)UserName); + tsdb_conv_free(client_to_server, auth, &buffer, (const char*)Authentication); return conn->taos ? SQL_SUCCESS : SQL_ERROR; } @@ -659,12 +752,16 @@ SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle, static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength) { + stack_buffer_t buffer; buffer.next = 0; + sql_t *sql = (sql_t*)StatementHandle; if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); + conn_t *conn = sql->conn; + NORM_STR_LENGTH(sql, StatementText, TextLength); if (sql->rs) { @@ -684,10 +781,12 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, } sql->n_params = 0; - const char *stxt = SDUP(StatementText, TextLength); + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + const char *stxt = NULL; SQLRETURN r = SQL_ERROR; do { + tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); if (!stxt) { SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); break; @@ -696,7 +795,7 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, CHK_RS(r, sql, "failed to execute"); } while (0); - SFRE(stxt, StatementText, TextLength); + tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); return r; } @@ -901,6 +1000,8 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, CHK_CONN(sql); CHK_CONN_TAOS(sql); + conn_t *conn = sql->conn; + if (!sql->rs) { SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, ""); return SQL_ERROR; @@ -911,8 +1012,6 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, return SQL_ERROR; } - DASSERT(TargetValue); - int nfields = taos_field_count(sql->rs); TAOS_FIELD *fields = taos_fetch_fields(sql->rs); @@ -925,14 +1024,20 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "NULL TargetValue not allowed for col [%d]", ColumnNumber); return SQL_ERROR; } + if (BufferLength<0) { + SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } TAOS_FIELD *field = fields + ColumnNumber-1; void *row = sql->row[ColumnNumber-1]; if (!row) { - if (StrLen_or_Ind) { - *StrLen_or_Ind = SQL_NULL_DATA; + if (!StrLen_or_Ind) { + SET_ERROR(sql, "22002", TSDB_CODE_ODBC_BAD_ARG, "NULL StrLen_or_Ind not allowed for col [%d]", ColumnNumber); + return SQL_ERROR; } + *StrLen_or_Ind = SQL_NULL_DATA; return SQL_SUCCESS; } @@ -981,7 +1086,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, CHK_CONV(0, tsdb_int64_to_double(v, TargetValue)); } break; case SQL_C_CHAR: { - CHK_CONV(0, tsdb_int64_to_char(v, TargetValue, (size_t)BufferLength)); + tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write_int64(utf8_to_client, v, (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; + CHK_CONV(0, code); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -1003,7 +1112,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, return SQL_SUCCESS; } break; case SQL_C_CHAR: { - CHK_CONV(0, tsdb_double_to_char(v, TargetValue, (size_t)BufferLength)); + tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write_double(utf8_to_client, v, (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; + CHK_CONV(0, code); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -1021,7 +1134,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, return SQL_SUCCESS; } break; case SQL_C_CHAR: { - CHK_CONV(0, tsdb_double_to_char(v, TargetValue, (size_t)BufferLength)); + tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write_double(utf8_to_client, v, (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; + CHK_CONV(0, code); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -1050,7 +1167,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, return SQL_SUCCESS; } break; case SQL_C_CHAR: { - CHK_CONV(0, tsdb_timestamp_to_char(ts, TargetValue, (size_t)BufferLength)); + tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write_timestamp(utf8_to_client, ts, (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; + CHK_CONV(0, code); } break; case SQL_C_TYPE_TIMESTAMP: case SQL_C_TIMESTAMP: { @@ -1070,7 +1191,14 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { case SQL_C_CHAR: { - CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, (size_t)BufferLength)); + tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); + size_t slen = strnlen((const char*)row, field_bytes); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, + (const char*)row, &slen, + (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); + CHK_CONV(0, code); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -1085,7 +1213,14 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { case SQL_C_CHAR: { - CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, (size_t)BufferLength)); + tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); + size_t slen = strnlen((const char*)row, field_bytes); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, + (const char*)row, &slen, + (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); + CHK_CONV(0, code); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -1144,12 +1279,16 @@ SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle) static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength) { + stack_buffer_t buffer; buffer.next = 0; + sql_t *sql = (sql_t*)StatementHandle; if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); + conn_t *conn = sql->conn; + NORM_STR_LENGTH(sql, StatementText, TextLength); if (sql->rs) { @@ -1177,9 +1316,17 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, break; } + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + const char *stxt = NULL; int ok = 0; do { - int r = taos_stmt_prepare(sql->stmt, (const char *)StatementText, (unsigned long)TextLength); + tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); + if ((!stxt)) { + SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); + break; + } + + int r = taos_stmt_prepare(sql->stmt, stxt, (unsigned long)strlen(stxt)); if (r) { SET_ERROR(sql, "HY000", r, "failed to prepare a TAOS statement"); break; @@ -1216,6 +1363,8 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, ok = 1; } while (0); + tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); + if (!ok) { taos_stmt_close(sql->stmt); sql->stmt = NULL; @@ -1245,6 +1394,16 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "parameter [@%d] not bound yet", idx+1); return SQL_ERROR; } + if (param->ParameterValue==NULL) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ParameterValue [@%p] not allowed", param->ParameterValue); + return SQL_ERROR; + } + if (param->StrLen_or_Ind==NULL) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StrLen_or_Ind [@%p] not allowed", param->StrLen_or_Ind); + return SQL_ERROR; + } + + conn_t *conn = sql->conn; unsigned char *paramValue = param->ParameterValue; SQLSMALLINT valueType = param->ValueType; @@ -1252,11 +1411,11 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin size_t offset = ((size_t)idx_row) * sql->rowlen + sql->ptr_offset; - if (paramValue) paramValue += offset; - if (soi) soi = (SQLLEN*)((char*)soi + offset); + paramValue += offset; + soi = (SQLLEN*)((char*)soi + offset); - if (soi && *soi == SQL_NULL_DATA) { + if (*soi == SQL_NULL_DATA) { bind->is_null = (int*)&yes; return SQL_SUCCESS; } @@ -1271,6 +1430,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin } } else { switch (valueType) { + case SQL_C_SLONG: case SQL_C_LONG: { type = TSDB_DATA_TYPE_INT; } break; @@ -1282,7 +1442,6 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin case SQL_C_SHORT: case SQL_C_SSHORT: case SQL_C_USHORT: - case SQL_C_SLONG: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: @@ -1344,7 +1503,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_double_to_bit(*(double*)paramValue, &bind->u.b)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_bit((const char *)paramValue, (size_t)*soi, &bind->u.b)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_bit(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b)); + // CHK_CONV(1, tsdb_chars_to_bit((const char *)paramValue, (size_t)*soi, &bind->u.b)); } break; case SQL_C_WCHAR: { CHK_CONV(1, tsdb_wchars_to_bit(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.b)); @@ -1396,7 +1560,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_int64_to_tinyint(*(int64_t*)paramValue, &bind->u.v1)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_tinyint((const char*)paramValue, (size_t)*soi, &bind->u.v1)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_tinyint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v1)); + // CHK_CONV(1, tsdb_chars_to_tinyint((const char *)paramValue, (size_t)*soi, &bind->u.v1)); } break; case SQL_C_WCHAR: { CHK_CONV(1, tsdb_wchars_to_tinyint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v1)); @@ -1450,7 +1619,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_int64_to_smallint(*(int64_t*)paramValue, &bind->u.v2)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, (size_t)*soi, &bind->u.v2)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_smallint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v2)); + // CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, (size_t)*soi, &bind->u.v2)); } break; case SQL_C_WCHAR: { CHK_CONV(1, tsdb_wchars_to_smallint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v2)); @@ -1504,7 +1678,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_int64_to_int(*(int64_t*)paramValue, &bind->u.v4)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, (size_t)*soi, &bind->u.v4)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_int(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v4)); + // CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, (size_t)*soi, &bind->u.v4)); } break; case SQL_C_WCHAR: { CHK_CONV(1, tsdb_wchars_to_int(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v4)); @@ -1558,7 +1737,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_int64_to_bigint(*(int64_t*)paramValue, &bind->u.v8)); } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, (size_t)*soi, &bind->u.v8)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_bigint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); + // CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, (size_t)*soi, &bind->u.v8)); } break; case SQL_C_WCHAR: { CHK_CONV(1, tsdb_wchars_to_bigint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v8)); @@ -1618,10 +1802,20 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->u.f4 = (float)*(double*)paramValue; } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_float((const char*)paramValue, (size_t)*soi, &bind->u.f4)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_float(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4)); + // CHK_CONV(1, tsdb_chars_to_float((const char*)paramValue, (size_t)*soi, &bind->u.f4)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_float(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f4)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_float(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4)); + // CHK_CONV(1, tsdb_wchars_to_float(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f4)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1676,10 +1870,20 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->u.f8 = *(double*)paramValue; } break; case SQL_C_CHAR: { - CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, (size_t)*soi, &bind->u.f8)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_double(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8)); + // CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, (size_t)*soi, &bind->u.f8)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_double(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f8)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_double(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8)); + // CHK_CONV(1, tsdb_wchars_to_double(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f8)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1703,85 +1907,25 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin } break; } } break; - case TSDB_DATA_TYPE_BINARY: { - bind->buffer_type = type; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_WCHAR: { - DASSERT(soi); - DASSERT(*soi != SQL_NTS); - size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)*soi/2, &bytes); - bind->allocated = 1; - bind->u.bin = utf8; - bind->buffer_length = bytes; - bind->buffer = bind->u.bin; - } break; - case SQL_C_BINARY: { - bind->u.bin = (unsigned char*)paramValue; - if (*soi == SQL_NTS) { - bind->buffer_length = strlen((const char*)paramValue); - } else { - bind->buffer_length = (uintptr_t)*soi; - } - bind->buffer = bind->u.bin; - } break; - case SQL_C_CHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: - case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_TINYINT: - case SQL_C_STINYINT: - case SQL_C_UTINYINT: - case SQL_C_SBIGINT: - case SQL_C_UBIGINT: - case SQL_C_BIT: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); - return SQL_ERROR; - } break; - } - } break; case TSDB_DATA_TYPE_TIMESTAMP: { bind->buffer_type = type; bind->buffer_length = sizeof(bind->u.v8); bind->buffer = &bind->u.v8; bind->length = &bind->buffer_length; switch (valueType) { + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_timestamp_ts(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); + } break; case SQL_C_WCHAR: { - DASSERT(soi); - DASSERT(*soi != SQL_NTS); - size_t bytes = 0; - int r = 0; - int64_t t = 0; - SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)*soi/2, &bytes); - // why cast utf8 to 'char*' ? - r = taosParseTime((char*)utf8, &t, (int)strlen((const char*)utf8), TSDB_TIME_PRECISION_MILLI, 0); - bind->u.v8 = t; - free(utf8); - if (r) { - SET_ERROR(sql, "22007", TSDB_CODE_ODBC_OUT_OF_RANGE, - "convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d] failed", - sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); - return SQL_ERROR; - } + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_timestamp_ts(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); } break; case SQL_C_SBIGINT: { int64_t t = *(int64_t*)paramValue; @@ -1818,28 +1962,127 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin } break; } } break; + case TSDB_DATA_TYPE_BINARY: { + bind->buffer_type = type; + bind->length = &bind->buffer_length; + switch (valueType) { + case SQL_C_WCHAR: { + tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + const char *buf = NULL; + size_t blen = 0; + TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + if (code==TSDB_CONV_OK) { + if (buf!=(const char*)paramValue) { + bind->allocated = 1; + } + bind->u.bin = (unsigned char*)buf; + bind->buffer_length = blen; + bind->buffer = bind->u.bin; + } + CHK_CONV(1, code); + } break; + case SQL_C_CHAR: { + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + const char *buf = NULL; + size_t blen = 0; + TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + if (code==TSDB_CONV_OK) { + if (buf!=(const char*)paramValue) { + bind->allocated = 1; + } + bind->u.bin = (unsigned char*)buf; + bind->buffer_length = blen; + bind->buffer = bind->u.bin; + } + CHK_CONV(1, code); + // bind->u.bin = (unsigned char*)paramValue; + // if (*soi == SQL_NTS) { + // bind->buffer_length = strlen((const char*)paramValue); + // } else { + // bind->buffer_length = (uintptr_t)*soi; + // } + // bind->buffer = bind->u.bin; + } break; + case SQL_C_SHORT: + case SQL_C_SSHORT: + case SQL_C_USHORT: + case SQL_C_LONG: + case SQL_C_SLONG: + case SQL_C_ULONG: + case SQL_C_FLOAT: + case SQL_C_DOUBLE: + case SQL_C_TINYINT: + case SQL_C_STINYINT: + case SQL_C_UTINYINT: + case SQL_C_SBIGINT: + case SQL_C_UBIGINT: + case SQL_C_BIT: + case SQL_C_BINARY: + case SQL_C_DATE: + case SQL_C_TIME: + case SQL_C_TIMESTAMP: + case SQL_C_TYPE_DATE: + case SQL_C_TYPE_TIME: + case SQL_C_TYPE_TIMESTAMP: + case SQL_C_NUMERIC: + case SQL_C_GUID: + default: { + SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, + "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", + sql_c_type(valueType), valueType, valueType, + taos_data_type(type), type, type, idx+1); + return SQL_ERROR; + } break; + } + } break; case TSDB_DATA_TYPE_NCHAR: { bind->buffer_type = type; bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_WCHAR: { - DASSERT(soi); - DASSERT(*soi != SQL_NTS); - size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)(*soi/2), &bytes); - bind->allocated = 1; - bind->u.nchar = (char*)utf8; - bind->buffer_length = bytes; - bind->buffer = bind->u.nchar; + tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + const char *buf = NULL; + size_t blen = 0; + TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + if (code==TSDB_CONV_OK) { + if (buf!=(const char*)paramValue) { + bind->allocated = 1; + } + bind->u.nchar = (char*)buf; + bind->buffer_length = blen; + bind->buffer = bind->u.nchar; + } + CHK_CONV(1, code); } break; case SQL_C_CHAR: { - bind->u.nchar = (char*)paramValue; - if (*soi == SQL_NTS) { - bind->buffer_length = strlen((const char*)paramValue); - } else { - bind->buffer_length = (uintptr_t)*soi; + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + const char *buf = NULL; + size_t blen = 0; + TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + if (code==TSDB_CONV_OK) { + if (buf!=(const char*)paramValue) { + bind->allocated = 1; + } + bind->u.bin = (unsigned char*)buf; + bind->buffer_length = blen; + bind->buffer = bind->u.bin; } - bind->buffer = bind->u.nchar; + CHK_CONV(1, code); + // bind->u.nchar = (char*)paramValue; + // if (*soi == SQL_NTS) { + // bind->buffer_length = strlen((const char*)paramValue); + // } else { + // bind->buffer_length = (uintptr_t)*soi; + // } + // bind->buffer = bind->u.nchar; } break; case SQL_C_SHORT: case SQL_C_SSHORT: @@ -2110,6 +2353,16 @@ static SQLRETURN doSQLBindParameter( return SQL_ERROR; } + if (ParameterValue==NULL) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ParameterValue [@%p] not allowed", ParameterValue); + return SQL_ERROR; + } + + if (StrLen_or_Ind==NULL) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StrLen_or_Ind [@%p] not allowed", StrLen_or_Ind); + return SQL_ERROR; + } + param_bind_t *pb = sql->params + ParameterNumber - 1; pb->ParameterNumber = ParameterNumber; @@ -2171,12 +2424,7 @@ static SQLRETURN doSQLDriverConnect( const char *connStr = SDUP(szConnStrIn, cbConnStrIn); - char *serverName = NULL; - char *userName = NULL; - char *auth = NULL; - char *host = NULL; - char *ip = NULL; - int port = 0; + conn_val_t val = {0}; do { if (szConnStrIn && !connStr) { @@ -2184,22 +2432,37 @@ static SQLRETURN doSQLDriverConnect( break; } - int n = todbc_parse_conn_string((const char *)connStr, &serverName, &userName, &auth, &host); + int n = todbc_parse_conn_string((const char *)connStr, &val); if (n) { SET_ERROR(conn, "HY000", TSDB_CODE_ODBC_BAD_CONNSTR, "unrecognized connection string: [%s]", (const char*)szConnStrIn); break; } - if (host) { - char *p = strchr(host, ':'); + char *ip = NULL; + int port = 0; + if (val.host) { + char *p = strchr(val.host, ':'); if (p) { - ip = strndup(host, (size_t)(p-host)); + ip = strndup(val.host, (size_t)(p-val.host)); port = atoi(p+1); } } + if ((val.cli_enc && strcmp(val.cli_enc, conn->client_enc)) || + (val.svr_enc && strcmp(val.svr_enc, conn->server_enc)) ) + { + tsdb_conn_close_convs(conn); + if (val.cli_enc) { + snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", val.cli_enc); + } + if (val.svr_enc) { + snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", val.svr_enc); + } + } + // TODO: data-race // TODO: shall receive ip/port from odbc.ini - conn->taos = taos_connect(ip ? ip : "localhost", userName, auth, NULL, (uint16_t)port); + // shall we support non-ansi uid/pwd/db etc? + conn->taos = taos_connect(ip ? ip : "localhost", val.uid, val.pwd, val.db, (uint16_t)port); free(ip); ip = NULL; if (!conn->taos) { SET_ERROR(conn, "HY000", terrno, "failed to connect to data source"); @@ -2212,12 +2475,9 @@ static SQLRETURN doSQLDriverConnect( if (pcbConnStrOut) { *pcbConnStrOut = cbConnStrIn; } - } while (0); - if (serverName) free(serverName); - if (userName) free(userName); - if (auth) free(auth); + conn_val_reset(&val); SFRE(connStr, szConnStrIn, cbConnStrIn); diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index d9ed708a5d..aaca1f75f7 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -15,6 +15,8 @@ #include "todbc_conv.h" +#include "todbc_log.h" + #include #include #include @@ -53,11 +55,13 @@ static void buf_clean(buf_t *buf) { const char* tsdb_conv_code_str(TSDB_CONV_CODE code) { switch (code) { case TSDB_CONV_OK: return "TSDB_CONV_OK"; + case TSDB_CONV_NOT_AVAIL: return "TSDB_CONV_NOT_AVAIL"; case TSDB_CONV_OOM: return "TSDB_CONV_OOM"; case TSDB_CONV_OOR: return "TSDB_CONV_OOR"; case TSDB_CONV_TRUNC_FRACTION: return "TSDB_CONV_TRUNC_FRACTION"; case TSDB_CONV_TRUNC: return "TSDB_CONV_TRUNC"; case TSDB_CONV_CHAR_NOT_NUM: return "TSDB_CONV_CHAR_NOT_NUM"; + case TSDB_CONV_CHAR_NOT_TS: return "TSDB_CONV_CHAR_NOT_TS"; case TSDB_CONV_GENERAL: return "TSDB_CONV_GENERAL"; case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR"; default: return "UNKNOWN"; @@ -154,6 +158,7 @@ TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst) { TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen) { int n = snprintf(dst, dlen, "%" PRId64 "", src); + DASSERT(n>=0); if (n=0); if (n=0); if (n=19) return TSDB_CONV_TRUNC_FRACTION; @@ -374,8 +381,43 @@ TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst) { return TSDB_CONV_CHAR_NOT_NUM; } +TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst) { + int64_t v = 0; + // why cast to 'char*' ? + int r = taosParseTime((char*)src, &v, (int32_t)smax, TSDB_TIME_PRECISION_MILLI, 0); + + if (r) { + return TSDB_CONV_CHAR_NOT_TS; + } + + time_t t = v/1000; + struct tm vtm = {0}; + localtime_r(&t, &vtm); + dst->year = (SQLSMALLINT)(vtm.tm_year + 1900); + dst->month = (SQLUSMALLINT)(vtm.tm_mon + 1); + dst->day = (SQLUSMALLINT)(vtm.tm_mday); + dst->hour = (SQLUSMALLINT)(vtm.tm_hour); + dst->minute = (SQLUSMALLINT)(vtm.tm_min); + dst->second = (SQLUSMALLINT)(vtm.tm_sec); + dst->fraction = (SQLUINTEGER)(v%1000 * 1000000); + + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_chars_to_timestamp_ts(const char *src, size_t smax, int64_t *dst) { + // why cast to 'char*' ? + int r = taosParseTime((char*)src, dst, (int32_t)smax, TSDB_TIME_PRECISION_MILLI, 0); + + if (r) { + return TSDB_CONV_CHAR_NOT_TS; + } + + return TSDB_CONV_OK; +} + TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax) { int n = snprintf(dst, dmax, "%s", src); + DASSERT(n>=0); if (nnext + bytes; + if (next>sizeof(buffer->buf)) return NULL; + + char *p = buffer->buf + buffer->next; + buffer->next = next; + return p; +} + +int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr) { + if (!buffer) return 0; + if (ptr>=buffer->buf && ptrbuf+buffer->next) return 1; + return 0; +} +struct tsdb_conv_s { + iconv_t cnv; + unsigned int direct:1; +}; + +tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc) { + tsdb_conv_t *cnv = (tsdb_conv_t*)calloc(1, sizeof(*cnv)); + if (!cnv) return NULL; + if (strcmp(from_enc, to_enc)==0) { + cnv->cnv = (iconv_t)-1; + cnv->direct = 1; + return cnv; + } + cnv->cnv = iconv_open(to_enc, from_enc); + if (cnv->cnv == (iconv_t)-1) { + free(cnv); + return NULL; + } + cnv->direct = 0; + return cnv; +} + +void tsdb_conv_close(tsdb_conv_t *cnv) { + if (!cnv) return; + if (!cnv->direct) { + if (cnv->cnv != (iconv_t)-1) { + iconv_close(cnv->cnv); + } + } + cnv->cnv = (iconv_t)-1; + cnv->direct = 0; + free(cnv); +} + +TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen) { + if (!cnv) return TSDB_CONV_NOT_AVAIL; + if (cnv->direct) { + size_t n = (*slen > *dlen) ? *dlen : *slen; + memcpy(dst, src, n); + *slen -= n; + *dlen -= n; + if (*dlen) dst[n] = '\0'; + return TSDB_CONV_OK; + } + if (!cnv->cnv) return TSDB_CONV_NOT_AVAIL; + size_t r = iconv(cnv->cnv, (char**)&src, slen, &dst, dlen); + if (r==(size_t)-1) return TSDB_CONV_BAD_CHAR; + if (*slen) return TSDB_CONV_TRUNC; + if (*dlen) *dst = '\0'; + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen) { + char utf8[64]; + int n = snprintf(utf8, sizeof(utf8), "%" PRId64 "", val); + DASSERT(n>=0); + DASSERT(n=0); + DASSERT(n=0); + DASSERT(ndirect) { + if (src[slen]=='\0') { // access violation? + *dst = src; + if (dlen) *dlen = slen; + return TSDB_CONV_OK; + } + blen = slen + 1; + } else { + blen = (slen + 1) * 4; + } + + buf = stack_buffer_alloc(buffer, blen); + if (!buf) { + buf = (char*)malloc(blen); + if (!buf) return TSDB_CONV_OOM; + } + + if (cnv->direct) { + size_t n = slen; + DASSERT(blen > n); + memcpy(buf, src, n); + buf[n] = '\0'; + *dst = buf; + if (dlen) *dlen = n; + return TSDB_CONV_OK; + } + + const char *orig_s = src; + char *orig_d = buf; + size_t orig_blen = blen; + + TSDB_CONV_CODE code; + size_t r = iconv(cnv->cnv, (char**)&src, &slen, &buf, &blen); + do { + if (r==(size_t)-1) { + code = TSDB_CONV_BAD_CHAR; + break; + } + if (slen) { + code = TSDB_CONV_TRUNC; + break; + } + DASSERT(blen); + *buf = '\0'; + *dst = orig_d; + if (dlen) *dlen = orig_blen - blen; + return TSDB_CONV_OK; + } while (0); + + if (orig_d!=(char*)orig_s && !is_owned_by_stack_buffer(buffer, orig_d)) free(orig_d); + return code; +} + +void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src) { + if (ptr!=src && !is_owned_by_stack_buffer(buffer, ptr)) free((char*)ptr); +} + diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h index 21c74b5474..529cc10e93 100644 --- a/src/connector/odbc/src/todbc_conv.h +++ b/src/connector/odbc/src/todbc_conv.h @@ -23,17 +23,50 @@ typedef enum { TSDB_CONV_OK = 0, + TSDB_CONV_NOT_AVAIL, TSDB_CONV_OOM, TSDB_CONV_OOR, TSDB_CONV_TRUNC_FRACTION, TSDB_CONV_TRUNC, TSDB_CONV_CHAR_NOT_NUM, + TSDB_CONV_CHAR_NOT_TS, TSDB_CONV_GENERAL, TSDB_CONV_BAD_CHAR, } TSDB_CONV_CODE; const char* tsdb_conv_code_str(TSDB_CONV_CODE code); +typedef struct stack_buffer_s stack_buffer_t; +struct stack_buffer_s { + char buf[1024*16]; + size_t next; +}; + +char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes); +int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr); + +typedef struct tsdb_conv_s tsdb_conv_t; +tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc); +void tsdb_conv_close(tsdb_conv_t *cnv); +TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen); +TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen); +TSDB_CONV_CODE tsdb_conv_write_double(tsdb_conv_t *cnv, double val, char *dst, size_t *dlen); +TSDB_CONV_CODE tsdb_conv_write_timestamp(tsdb_conv_t *cnv, SQL_TIMESTAMP_STRUCT val, char *dst, size_t *dlen); + +TSDB_CONV_CODE tsdb_conv_chars_to_bit(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_tinyint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_smallint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int16_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_int(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int32_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_bigint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_float(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, float *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_double(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, double *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_timestamp(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, SQL_TIMESTAMP_STRUCT *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_timestamp_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); +TSDB_CONV_CODE tsdb_conv(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, const char **dst, size_t *dlen); +void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src); + + TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen); @@ -66,6 +99,7 @@ TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst); TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst); TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst); TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst); +TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst); TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax); TSDB_CONV_CODE tsdb_wchars_to_bit(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst); diff --git a/src/connector/odbc/src/todbc_flex.h b/src/connector/odbc/src/todbc_flex.h index 5ee5b53676..1356efd174 100644 --- a/src/connector/odbc/src/todbc_flex.h +++ b/src/connector/odbc/src/todbc_flex.h @@ -16,7 +16,21 @@ #ifndef _TODBC_FLEX_H_ #define _TODBC_FLEX_H_ -int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host); +typedef struct conn_val_s conn_val_t; +struct conn_val_s { + char *key; + char *dsn; + char *uid; + char *pwd; + char *db; + char *host; + char *svr_enc; + char *cli_enc; +}; + + +void conn_val_reset(conn_val_t *val); +int todbc_parse_conn_string(const char *conn, conn_val_t *val); #endif // _TODBC_FLEX_H_ diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l index 25a46e03cf..988a34d47c 100644 --- a/src/connector/odbc/src/todbc_scanner.l +++ b/src/connector/odbc/src/todbc_scanner.l @@ -7,15 +7,6 @@ #define strcasecmp _stricmp #endif -typedef struct params_s params_t; -struct params_s { - char *key; - char *dsn; - char *uid; - char *pwd; - char *host; -}; - #define PUSH_STATE(state) yy_push_state(state, yyscanner) #define POP_STATE() yy_pop_state(yyscanner) @@ -61,17 +52,32 @@ do { \ yyextra->pwd = strdup(yytext); \ break; \ } \ + if (strcasecmp(yyextra->key, "DB")==0) { \ + free(yyextra->db); \ + yyextra->pwd = strdup(yytext); \ + break; \ + } \ if (strcasecmp(yyextra->key, "HOST")==0) { \ free(yyextra->host); \ yyextra->host = strdup(yytext); \ break; \ } \ + if (strcasecmp(yyextra->key, "SERVER_ENC")==0) { \ + free(yyextra->svr_enc); \ + yyextra->host = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "CLIENT_ENC")==0) { \ + free(yyextra->cli_enc); \ + yyextra->host = strdup(yytext); \ + break; \ + } \ } while (0) %} %option prefix="todbc_yy" -%option extra-type="struct params_s *" +%option extra-type="conn_val_t *" %option nounistd %option never-interactive %option reentrant @@ -115,20 +121,45 @@ do { \ .|\n { return -1; } %% -int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host) { +int todbc_parse_conn_string(const char *conn, conn_val_t *val) { yyscan_t arg = {0}; - params_t params = {0}; yylex_init(&arg); yyset_debug(0, arg); - yyset_extra(¶ms, arg); + yyset_extra(val, arg); yy_scan_string(conn, arg); int ret =yylex(arg); yylex_destroy(arg); - *dsn = params.dsn; - *uid = params.uid; - *pwd = params.pwd; - *host = params.host; + if (val->key) free(val->key); val->key = NULL; + if (ret) { + conn_val_reset(val); + } return ret ? -1 : 0; } +void conn_val_reset(conn_val_t *val) { + if (val->key) { + free(val->key); val->key = NULL; + } + if (val->dsn) { + free(val->dsn); val->dsn = NULL; + } + if (val->uid) { + free(val->uid); val->uid = NULL; + } + if (val->pwd) { + free(val->pwd); val->pwd = NULL; + } + if (val->db) { + free(val->db); val->db = NULL; + } + if (val->host) { + free(val->host); val->host = NULL; + } + if (val->svr_enc) { + free(val->svr_enc); val->svr_enc = NULL; + } + if (val->cli_enc) { + free(val->cli_enc); val->cli_enc = NULL; + } +} From 810291575fcfcdf35b22ca3cc43eec9b52d9a7e4 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 14:08:00 +0800 Subject: [PATCH 22/85] typo correction,and bugfix --- src/connector/odbc/src/todbc.c | 12 +++++++++--- src/connector/odbc/src/todbc_scanner.l | 6 +++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index c39c57cd94..ac6169c6f8 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -167,7 +167,8 @@ do { \ TSDB_CONV_CODE code_0c80 = (statement); \ switch (code_0c80) { \ case TSDB_CONV_OK: return SQL_SUCCESS; \ - case TSDB_CONV_OOM: { \ + case TSDB_CONV_OOM: \ + case TSDB_CONV_NOT_AVAIL: { \ SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); \ return SQL_ERROR; \ } break; \ @@ -175,7 +176,8 @@ do { \ SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_OOR, ""); \ return SQL_ERROR; \ } break; \ - case TSDB_CONV_CHAR_NOT_NUM: { \ + case TSDB_CONV_CHAR_NOT_NUM: \ + case TSDB_CONV_CHAR_NOT_TS: { \ SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, ""); \ return SQL_ERROR; \ } break; \ @@ -187,8 +189,12 @@ do { \ SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ return SQL_ERROR; \ } break; \ + case TSDB_CONV_BAD_CHAR: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ + return SQL_ERROR; \ + } break; \ default: { \ - DASSERTX(0, "internal logic error"); \ + DASSERTX(0, "internal logic error: %d", code_0c80); \ return SQL_ERROR; /* never reached here */ \ } break; \ } \ diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l index 988a34d47c..ce7d8c421d 100644 --- a/src/connector/odbc/src/todbc_scanner.l +++ b/src/connector/odbc/src/todbc_scanner.l @@ -64,12 +64,12 @@ do { \ } \ if (strcasecmp(yyextra->key, "SERVER_ENC")==0) { \ free(yyextra->svr_enc); \ - yyextra->host = strdup(yytext); \ + yyextra->svr_enc = strdup(yytext); \ break; \ } \ if (strcasecmp(yyextra->key, "CLIENT_ENC")==0) { \ free(yyextra->cli_enc); \ - yyextra->host = strdup(yytext); \ + yyextra->cli_enc = strdup(yytext); \ break; \ } \ } while (0) @@ -98,7 +98,7 @@ do { \ if (state == VAL) yyterminate(); return -1; } [[:space:]]+ { } -[[:alnum:]]+ { set_key(); PUSH_STATE(KEY); } +[[:alnum:]_]+ { set_key(); PUSH_STATE(KEY); } .|\n { return -1; } [[:space:]]+ { } From d8cb54ffd33d6de2d16462197300492a8f44e6c9 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 15:55:04 +0800 Subject: [PATCH 23/85] add predefined environment locale support --- src/connector/odbc/src/todbc.c | 47 +++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index ac6169c6f8..8c5edf19e2 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -229,6 +229,8 @@ struct env_s { uint64_t refcount; unsigned int destroying:1; + char env_locale[64]; + taos_error_t err; }; @@ -245,6 +247,8 @@ struct conn_s { tsdb_conv_t *utf16_to_utf8; tsdb_conv_t *utf16_to_server; tsdb_conv_t *client_to_utf8; + tsdb_conv_t *env_to_client; + tsdb_conv_t *client_to_env; TAOS *taos; @@ -339,6 +343,20 @@ static tsdb_conv_t* tsdb_conn_client_to_utf8(conn_t *conn) { return conn->client_to_utf8; } +static tsdb_conv_t* tsdb_conn_env_to_client(conn_t *conn) { + if (!conn->env_to_client) { + conn->env_to_client = tsdb_conv_open(conn->env->env_locale, conn->client_enc); + } + return conn->env_to_client; +} + +static tsdb_conv_t* tsdb_conn_client_to_env(conn_t *conn) { + if (!conn->client_to_env) { + conn->client_to_env = tsdb_conv_open(conn->client_enc, conn->env->env_locale); + } + return conn->client_to_env; +} + static void tsdb_conn_close_convs(conn_t *conn) { if (0) { tsdb_conn_server_to_client(NULL); @@ -367,6 +385,14 @@ static void tsdb_conn_close_convs(conn_t *conn) { tsdb_conv_close(conn->client_to_utf8); conn->client_to_utf8 = NULL; } + if (conn->env_to_client) { + tsdb_conv_close(conn->env_to_client); + conn->env_to_client = NULL; + } + if (conn->client_to_env) { + tsdb_conv_close(conn->client_to_env); + conn->client_to_env = NULL; + } } #define SFREE(buffer, v, src) \ @@ -403,6 +429,12 @@ static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) DASSERT(INC_REF(env)>0); +#ifdef _MSC_VER + snprintf(env->env_locale, sizeof(env->env_locale), GB18030_ENC); +#else + snprintf(env->env_locale, sizeof(env->env_locale), UTF8_ENC); +#endif + *EnvironmentHandle = env; CLR_ERROR(env); @@ -464,10 +496,11 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, break; } - snprintf(conn->client_enc, sizeof(conn->client_enc), UTF8_ENC); - snprintf(conn->server_enc, sizeof(conn->server_enc), UTF8_ENC); - conn->env = env; + + snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", conn->env->env_locale); + snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", conn->env->env_locale); + *ConnectionHandle = conn; DASSERT(INC_REF(conn)>0); @@ -1219,10 +1252,10 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { case SQL_C_CHAR: { - tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); + tsdb_conv_t *env_to_client = tsdb_conn_env_to_client(conn); size_t slen = strnlen((const char*)row, field_bytes); size_t len = (size_t)BufferLength; - TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, + TSDB_CONV_CODE code = tsdb_conv_write(env_to_client, (const char*)row, &slen, (char*)TargetValue, &len); if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); @@ -2067,12 +2100,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, code); } break; case SQL_C_CHAR: { - tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + tsdb_conv_t *client_to_env = tsdb_conn_client_to_env(conn); size_t slen = (size_t)*soi; if (slen==SQL_NTS) slen = strlen((const char*)paramValue); const char *buf = NULL; size_t blen = 0; - TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + TSDB_CONV_CODE code = tsdb_conv(client_to_env, NULL, (const char *)paramValue, slen, &buf, &blen); if (code==TSDB_CONV_OK) { if (buf!=(const char*)paramValue) { bind->allocated = 1; From 309b795676add834eb683756fcf0d93e8d9d0c4b Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 16:41:06 +0800 Subject: [PATCH 24/85] bugFix: sql error windows port --- src/connector/odbc/src/todbc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 8c5edf19e2..5180247bd2 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -60,6 +60,7 @@ do { snprintf((char*)obj->err.sql_state, sizeof(obj->err.sql_state), "%s", sqlstate); \ } while (0) + #define CLR_ERROR(obj) \ do { \ obj->err.err_no = TSDB_CODE_SUCCESS; \ @@ -2275,7 +2276,11 @@ static SQLRETURN doSQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLPOINTER DiagInfo, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) { - // if this function is not exported, isql will never call SQLGetDiagRec + switch (DiagIdentifier) { + case SQL_DIAG_CLASS_ORIGIN: { + *StringLength = 0; + } break; + } return SQL_SUCCESS; } From b6fe6ab90e12696f505ca6c7b6f1475dc36b540d Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 16:49:53 +0800 Subject: [PATCH 25/85] python test case --- src/CMakeLists.txt | 2 +- src/connector/odbc/tests/odbc.py | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f619edd221..b2c6e70f68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,5 +21,5 @@ ADD_SUBDIRECTORY(wal) ADD_SUBDIRECTORY(cq) ADD_SUBDIRECTORY(dnode) ADD_SUBDIRECTORY(connector/odbc) -ADD_SUBDIRECTORY(connector/jdbc) +#ADD_SUBDIRECTORY(connector/jdbc) diff --git a/src/connector/odbc/tests/odbc.py b/src/connector/odbc/tests/odbc.py index e98110a0d5..01dd52852b 100644 --- a/src/connector/odbc/tests/odbc.py +++ b/src/connector/odbc/tests/odbc.py @@ -37,32 +37,32 @@ cursor.execute("create database db"); cursor.close() cursor = cnxn.cursor() -cursor.execute("create table db.t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))"); +cursor.execute("create table db.mt (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))"); cursor.close() cursor = cnxn.cursor() -cursor.execute("insert into db.t values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hello', 'world')") +cursor.execute("insert into db.mt values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hello', 'world')") cursor.close() cursor = cnxn.cursor() -cursor.execute("insert into db.t values(?,?,?,?,?,?,?,?,?,?)", "2020-10-13 07:06:00", 0, 127, 32767, 32768, 32769, 123.456, 789.987, "hel后lo", "wo哈rld"); +cursor.execute("insert into db.mt values(?,?,?,?,?,?,?,?,?,?)", "2020-10-13 07:06:00", 0, 127, 32767, 32768, 32769, 123.456, 789.987, "hel后lo", "wo哈rld"); cursor.close() cursor = cnxn.cursor() -cursor.execute("SELECT * from db.t") +cursor.execute("SELECT * from db.mt") row = cursor.fetchone() while row: print(row) row = cursor.fetchone() cursor.close() -cursor = cnxn.cursor() -cursor.execute("drop database if exists db"); -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("create database db"); -cursor.close() +#cursor = cnxn.cursor() +#cursor.execute("drop database if exists db"); +#cursor.close() +# +#cursor = cnxn.cursor() +#cursor.execute("create database db"); +#cursor.close() cursor = cnxn.cursor() cursor.execute("create table db.t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(4), blob nchar(4))"); From 357ce3b87daaec617b3c7676096e9fe02e675006 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 16:50:29 +0800 Subject: [PATCH 26/85] reenable jdbc --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2c6e70f68..f619edd221 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,5 +21,5 @@ ADD_SUBDIRECTORY(wal) ADD_SUBDIRECTORY(cq) ADD_SUBDIRECTORY(dnode) ADD_SUBDIRECTORY(connector/odbc) -#ADD_SUBDIRECTORY(connector/jdbc) +ADD_SUBDIRECTORY(connector/jdbc) From faec0c3ad72822a1d9a6344ef35e4f260c7a45e0 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 16:59:45 +0800 Subject: [PATCH 27/85] add select statements test file --- src/connector/odbc/tests/main.c | 4 +++- src/connector/odbc/tests/select.stmts | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 src/connector/odbc/tests/select.stmts diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index 1bb174e7b9..2c817f1385 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -434,7 +434,9 @@ int test_sqls_in_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, const char *sqls const char *p = NULL; do { if (line[0] == '#') break; - if (line[n-1] == '\n') line[n-1]='\0'; + if (n>0 && line[n-1] == '\n') line[n-1]='\0'; + if (n>0 && line[n-1] == '\r') line[n-1]='\0'; + if (n>1 && line[n-2] == '\r') line[n-2]='\0'; p = line; while (isspace(*p)) ++p; diff --git a/src/connector/odbc/tests/select.stmts b/src/connector/odbc/tests/select.stmts new file mode 100644 index 0000000000..f7152ba6cf --- /dev/null +++ b/src/connector/odbc/tests/select.stmts @@ -0,0 +1,4 @@ +P: select * from db.t; +P: select * from db.f; +P: select * from db.v; +P: select * from db.mt; \ No newline at end of file From f670e1820e0cb573df3687a9119c44e6900b7d03 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 21:43:07 +0800 Subject: [PATCH 28/85] just warn user if flex is not installed under windows platform --- src/connector/odbc/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index ea68ddd128..b1e2b63d69 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -40,7 +40,9 @@ IF (TD_WINDOWS_64) endif () find_package(FLEX) if(NOT FLEX_FOUND) - message(FATAL_ERROR "you need to install flex first") + message(WARNING "you need to install flex first\n" + "you may go to: https://github.com/lexxmark/winflexbison\n" + "or download from: https://github.com/lexxmark/winflexbison/releases") else () ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(tools) From f5219bb2977dc6e9a30970069bf6e71e153c26f6 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 22:24:04 +0800 Subject: [PATCH 29/85] add test cases --- src/connector/odbc/src/install.sh | 1 + src/connector/odbc/tests/create_data.stmts | 12 ++++++++++++ src/connector/odbc/tests/query_data.stmts | 1 + 3 files changed, 14 insertions(+) create mode 100644 src/connector/odbc/tests/create_data.stmts create mode 100644 src/connector/odbc/tests/query_data.stmts diff --git a/src/connector/odbc/src/install.sh b/src/connector/odbc/src/install.sh index b8c04677c7..6f45ce4357 100755 --- a/src/connector/odbc/src/install.sh +++ b/src/connector/odbc/src/install.sh @@ -19,6 +19,7 @@ Description=Connection to TAOS Driver=TAOS EOF +# better remove first ? sudo odbcinst -i -d -f "${BLD_DIR}/template.ini" && odbcinst -i -s -f "${BLD_DIR}/template.dsn" && echo "odbc install done" diff --git a/src/connector/odbc/tests/create_data.stmts b/src/connector/odbc/tests/create_data.stmts new file mode 100644 index 0000000000..549cb583d8 --- /dev/null +++ b/src/connector/odbc/tests/create_data.stmts @@ -0,0 +1,12 @@ +P:drop database if exists m; +P:create database m; +P:use m; + +P:drop table if exists t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1)); +P:insert into t (ts, blob, name) values('2020-10-10 00:00:00', 0, 1); +P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.001', 1, 2); +P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.002', '你', '好'); +P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.003', 'abc', 'd'); +P:select * from t; + diff --git a/src/connector/odbc/tests/query_data.stmts b/src/connector/odbc/tests/query_data.stmts new file mode 100644 index 0000000000..b0e9ea27ea --- /dev/null +++ b/src/connector/odbc/tests/query_data.stmts @@ -0,0 +1 @@ +P:select * from m.t; From a79f0de942d250b19bd8ae1b4a11c4469b67e91c Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 22:53:09 +0800 Subject: [PATCH 30/85] add README.md --- src/connector/odbc/README.md | 82 +++++++++++++++++++++++++++++++++ src/connector/odbc/tests/main.c | 6 ++- src/connector/odbc/tools/main.c | 8 +++- 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/connector/odbc/README.md diff --git a/src/connector/odbc/README.md b/src/connector/odbc/README.md new file mode 100644 index 0000000000..be3812e1e9 --- /dev/null +++ b/src/connector/odbc/README.md @@ -0,0 +1,82 @@ + +# ODBC Driver # + +- **very initial implementation of ODBC driver for TAOS + +- **currently partially supported ODBC functions are: ` +SQLAllocEnv +SQLFreeEnv +SQLAllocConnect +SQLFreeConnect +SQLConnect +SQLDisconnect +SQLAllocStmt +SQLAllocHandle +SQLFreeStmt +SQLExecDirect +SQLExecDirectW +SQLNumResultCols +SQLRowCount +SQLColAttribute +SQLGetData +SQLFetch +SQLPrepare +SQLExecute +SQLGetDiagField +SQLGetDiagRec +SQLBindParameter +SQLDriverConnect +SQLSetConnectAttr +SQLDescribeCol +SQLNumParams +SQLSetStmtAttr +` + +- **internationalized, you can specify different charset/code page for easy going. eg.: insert `utf-8.zh_cn` characters into database located in linux machine, while query them out in `gb2312/gb18030/...` code page in your chinese windows machine, or vice-versa. and much fun, insert `gb2312/gb18030/...` characters into database located in linux box from +your japanese windows box, and query them out in your local chinese windows machine. + +- **enable ODBC-aware software to communicate with TAOS. + +- **enable any language with ODBC-bindings/ODBC-plugings to communicate with TAOS + +- **still going on... + +# Building and Testing +**Note**: all `work` is done in TDengine's project directory + + +# Building under Linux, use Ubuntu as example +``` +sudo apt install unixodbc unixodbc-dev flex +rm -rf debug && cmake -B debug && cmake --build debug && cmake --install debug && echo yes +``` +# Building under Windows, use Windows 10 as example +- install windows `flex` port. We use [https://github.com/lexxmark/winflexbison](url) at the moment. Please be noted to append `` to your `PATH`. +- install Microsoft Visual Studio, take VS2015 as example here +- `"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64` +- `rmdir /s /q debug` +- `cmake -G "NMake Makefiles" -B debug` +- `cmake --build debug` +- `cmake --install debug` +- open your `Command Prompt` with Administrator's privilidge +- remove previously installed TAOS ODBC driver: run `C:\TDengine\todbcinst -u -f -n TAOS` +- install TAOS ODBC driver that was just built: run `C:\TDengine\todbcinst -i -n TAOS -p C:\TDengine\driver` + +# Test +we highly suggest that you build both in linux(ubuntu) and windows(windows 10) platform, because currently TAOS only has it's server-side port on linux platform. +**Note1**: content within <> shall be modified to match your environment +**Note2**: `.stmts` source files are all encoded in `UTF-8` +## start taosd in linux, suppose charset is `UTF-8` as default +``` +taosd -c ./debug/test/cfg +``` +## create data in linux +``` +./debug/build/bin/tcodbc 'Driver=TAOS;UID=;PWD=;Host=:6030;server_enc=UTF-8' ./src/connector/odbc/tests/create_data.stmts +``` +## query data in windows +``` +.\debug\build\bin\tcodbc "Driver=TAOS;UID=;PWD=;Host=:6030;server_enc=UTF-8" .\src\connector\odbc\tests\query_data.stmts +``` + + diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index 2c817f1385..74bceaaf31 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -16,7 +16,10 @@ do { \ D("testing: %s", #statement); \ int r = (statement); \ - if (r) return 1; \ + if (r) { \ + D("testing failed: %s", #statement); \ + return 1; \ + } \ } while (0); @@ -543,6 +546,7 @@ int main(int argc, char *argv[]) { CHK_TEST(test_sqls(dsn, uid, pwd, connstr, sqls)); } + D("Done!"); return 0; } diff --git a/src/connector/odbc/tools/main.c b/src/connector/odbc/tools/main.c index b9422830c0..7b8421c4e1 100644 --- a/src/connector/odbc/tools/main.c +++ b/src/connector/odbc/tools/main.c @@ -113,6 +113,8 @@ static int do_install(int i, int argc, char *argv[]) { return -1; } + fprintf(stderr, "ODBC driver [%s] has been installed in [%s], and UsageCount is now [%d]\n", + driverName, driverPath, usageCount); return argc; } @@ -152,8 +154,12 @@ static int do_uninstall(int i, int argc, char *argv[]) { fprintf(stderr, "failed to remove driver [%s]\n", driverName); return -1; } - if (!forceful) return argc; + if (!forceful) { + fprintf(stderr, "UsageCount for ODBC driver [%s] is now: [%d]\n", driverName, usageCount); + return argc; + } } while (usageCount > 0); + fprintf(stderr, "ODBC driver [%s] is now fully uninstalled\n", driverName); return argc; } From 0f7dd66cedc2b7aadfc7277aedaf1e5450d2555e Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 30 Oct 2020 23:15:53 +0800 Subject: [PATCH 31/85] typo correction --- src/connector/odbc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connector/odbc/README.md b/src/connector/odbc/README.md index be3812e1e9..5a9706fd1f 100644 --- a/src/connector/odbc/README.md +++ b/src/connector/odbc/README.md @@ -58,7 +58,7 @@ rm -rf debug && cmake -B debug && cmake --build debug && cmake --install debug & - `cmake -G "NMake Makefiles" -B debug` - `cmake --build debug` - `cmake --install debug` -- open your `Command Prompt` with Administrator's privilidge +- open your `Command Prompt` with Administrator's priviledge - remove previously installed TAOS ODBC driver: run `C:\TDengine\todbcinst -u -f -n TAOS` - install TAOS ODBC driver that was just built: run `C:\TDengine\todbcinst -i -n TAOS -p C:\TDengine\driver` From 32b3c2e65e01ba8feee81b2b42d9ff3f1d1f8f77 Mon Sep 17 00:00:00 2001 From: freemine Date: Sat, 31 Oct 2020 00:43:07 +0800 Subject: [PATCH 32/85] install ODBC driver components if only flex was found --- cmake/install.inc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cmake/install.inc b/cmake/install.inc index 2ea2201837..049a8a1bde 100755 --- a/cmake/install.inc +++ b/cmake/install.inc @@ -20,16 +20,20 @@ ELSEIF (TD_WINDOWS) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.lib DESTINATION driver) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.exp DESTINATION driver) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.lib DESTINATION driver) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.exp DESTINATION driver) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.dll DESTINATION driver) + if(FLEX_FOUND) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.lib DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.exp DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.dll DESTINATION driver) + endif () IF (TD_POWER) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/power.exe DESTINATION .) ELSE () INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taosdemo.exe DESTINATION .) - INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/todbcinst.exe DESTINATION .) + if(FLEX_FOUND) + INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/todbcinst.exe DESTINATION .) + endif () ENDIF () #INSTALL(TARGETS taos RUNTIME DESTINATION driver) From ac8c04bc63e424f5b5767f4c7f70f3680a40a24f Mon Sep 17 00:00:00 2001 From: freemine Date: Sat, 31 Oct 2020 01:06:30 +0800 Subject: [PATCH 33/85] stop building ODBC driver under linux if gcc 4.8.0 is chosen as the compiler --- src/connector/odbc/CMakeLists.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index b1e2b63d69..0d8c07041a 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -17,11 +17,15 @@ IF (TD_LINUX_64) if(NOT FLEX_FOUND) message(FATAL_ERROR "you need to install flex first") else () - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wconversion") - SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") - ADD_SUBDIRECTORY(src) - ADD_SUBDIRECTORY(tools) - ADD_SUBDIRECTORY(tests) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0.0) + message(WARNING "gcc 4.8.0 will complain too much about flex-generated code, we just bypass building ODBC driver in such case") + else () + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wconversion") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") + ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tools) + ADD_SUBDIRECTORY(tests) + endif () endif() endif() ELSE () From 23f49cca86c91de5b004a93a714b5daa3d9513ef Mon Sep 17 00:00:00 2001 From: freemine Date: Sat, 31 Oct 2020 13:39:39 +0800 Subject: [PATCH 34/85] add more data-type-conversions --- src/connector/odbc/src/todbc.c | 140 ++++++++++++++++------------ src/connector/odbc/src/todbc_conv.c | 15 +++ src/connector/odbc/src/todbc_conv.h | 3 + src/connector/odbc/tests/odbc.py | 14 +-- src/inc/taoserror.h | 1 + 5 files changed, 107 insertions(+), 66 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 5180247bd2..03d47dad4d 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -182,6 +182,10 @@ do { \ SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, ""); \ return SQL_ERROR; \ } break; \ + case TSDB_CONV_NOT_VALID_TS: { \ + SET_ERROR(sql, "22007", TSDB_CODE_ODBC_CONV_NOT_VALID_TS, ""); \ + return SQL_ERROR; \ + } break; \ case TSDB_CONV_TRUNC_FRACTION: { \ SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC_FRAC, ""); \ return todb ? SQL_ERROR : SQL_SUCCESS_WITH_INFO; \ @@ -1213,8 +1217,7 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; CHK_CONV(0, code); } break; - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_TIMESTAMP: { + case SQL_C_TYPE_TIMESTAMP: { *(SQL_TIMESTAMP_STRUCT*)TargetValue = ts; return SQL_SUCCESS; } break; @@ -1460,41 +1463,60 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin return SQL_SUCCESS; } bind->is_null = (int*)&no; - int type = 0; - int bytes = 0; + int tsdb_type = 0; // taos internal data tsdb_type to be bound to + int tsdb_bytes = 0; // we don't rely much on 'tsdb_bytes' here, we delay until taos to check it internally if (sql->is_insert) { - int r = taos_stmt_get_param(sql->stmt, idx, &type, &bytes); + int r = taos_stmt_get_param(sql->stmt, idx, &tsdb_type, &tsdb_bytes); if (r) { SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_OUT_OF_RANGE, "parameter [@%d] not valid", idx+1); return SQL_ERROR; } } else { + // we don't have correspondent data type from taos api + // we have to give a good guess here switch (valueType) { + case SQL_C_BIT: { + tsdb_type = TSDB_DATA_TYPE_BOOL; + } break; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + tsdb_type = TSDB_DATA_TYPE_TINYINT; + } break; + case SQL_C_SSHORT: + case SQL_C_SHORT: { + tsdb_type = TSDB_DATA_TYPE_SMALLINT; + } break; case SQL_C_SLONG: case SQL_C_LONG: { - type = TSDB_DATA_TYPE_INT; + tsdb_type = TSDB_DATA_TYPE_INT; + } break; + case SQL_C_SBIGINT: { + tsdb_type = TSDB_DATA_TYPE_BIGINT; + } break; + case SQL_C_FLOAT: { + tsdb_type = TSDB_DATA_TYPE_FLOAT; + } break; + case SQL_C_DOUBLE: { + tsdb_type = TSDB_DATA_TYPE_DOUBLE; + } break; + case SQL_C_TIMESTAMP: { + tsdb_type = TSDB_DATA_TYPE_TIMESTAMP; + } break; + case SQL_C_CHAR: { + tsdb_type = TSDB_DATA_TYPE_BINARY; + tsdb_bytes = SQL_NTS; } break; case SQL_C_WCHAR: { - type = TSDB_DATA_TYPE_NCHAR; - bytes = SQL_NTS; + tsdb_type = TSDB_DATA_TYPE_NCHAR; + tsdb_bytes = SQL_NTS; } break; - case SQL_C_CHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: case SQL_C_USHORT: case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: case SQL_C_TIME: - case SQL_C_TIMESTAMP: case SQL_C_TYPE_DATE: case SQL_C_TYPE_TIME: case SQL_C_TYPE_TIMESTAMP: @@ -1511,9 +1533,9 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin } // ref: https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/converting-data-from-c-to-sql-data-types?view=sql-server-ver15 - switch (type) { + switch (tsdb_type) { case TSDB_DATA_TYPE_BOOL: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.b); bind->buffer = &bind->u.b; bind->length = &bind->buffer_length; @@ -1548,7 +1570,6 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin size_t slen = (size_t)*soi; if (slen==SQL_NTS) slen = strlen((const char*)paramValue); CHK_CONV(1, tsdb_conv_chars_to_bit(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b)); - // CHK_CONV(1, tsdb_chars_to_bit((const char *)paramValue, (size_t)*soi, &bind->u.b)); } break; case SQL_C_WCHAR: { CHK_CONV(1, tsdb_wchars_to_bit(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.b)); @@ -1570,13 +1591,13 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_TINYINT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v1); bind->buffer = &bind->u.v1; bind->length = &bind->buffer_length; @@ -1629,13 +1650,13 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_SMALLINT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v2); bind->buffer = &bind->u.v2; bind->length = &bind->buffer_length; @@ -1688,13 +1709,13 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_INT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v4); bind->buffer = &bind->u.v4; bind->length = &bind->buffer_length; @@ -1747,13 +1768,13 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_BIGINT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v8); bind->buffer = &bind->u.v8; bind->length = &bind->buffer_length; @@ -1806,13 +1827,13 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_FLOAT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.f4); bind->buffer = &bind->u.f4; bind->length = &bind->buffer_length; @@ -1874,13 +1895,13 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_DOUBLE: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.f8); bind->buffer = &bind->u.f8; bind->length = &bind->buffer_length; @@ -1942,13 +1963,13 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_TIMESTAMP: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v8); bind->buffer = &bind->u.v8; bind->length = &bind->buffer_length; @@ -1971,6 +1992,22 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin int64_t t = *(int64_t*)paramValue; bind->u.v8 = t; } break; + case SQL_C_TYPE_TIMESTAMP: { + SQL_TIMESTAMP_STRUCT ts = *(SQL_TIMESTAMP_STRUCT*)paramValue; + struct tm vtm = {0}; + vtm.tm_year = ts.year - 1900; + vtm.tm_mon = ts.month - 1; + vtm.tm_mday = ts.day; + vtm.tm_hour = ts.hour; + vtm.tm_min = ts.minute; + vtm.tm_sec = ts.second; + int64_t t = (int64_t) mktime(&vtm); + if (t==-1) { + CHK_CONV(1, TSDB_CONV_NOT_VALID_TS); + // code never reached here + } + bind->u.ts = t * 1000 + ts.fraction / 1000000; + } break; case SQL_C_SHORT: case SQL_C_SSHORT: case SQL_C_USHORT: @@ -1990,20 +2027,19 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin case SQL_C_TIMESTAMP: case SQL_C_TYPE_DATE: case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: case SQL_C_NUMERIC: case SQL_C_GUID: default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_BINARY: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_WCHAR: { @@ -2039,13 +2075,6 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = bind->u.bin; } CHK_CONV(1, code); - // bind->u.bin = (unsigned char*)paramValue; - // if (*soi == SQL_NTS) { - // bind->buffer_length = strlen((const char*)paramValue); - // } else { - // bind->buffer_length = (uintptr_t)*soi; - // } - // bind->buffer = bind->u.bin; } break; case SQL_C_SHORT: case SQL_C_SSHORT: @@ -2055,32 +2084,32 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: + case SQL_C_BIT: case SQL_C_TINYINT: case SQL_C_STINYINT: case SQL_C_UTINYINT: case SQL_C_SBIGINT: case SQL_C_UBIGINT: - case SQL_C_BIT: case SQL_C_BINARY: case SQL_C_DATE: case SQL_C_TIME: case SQL_C_TIMESTAMP: case SQL_C_TYPE_DATE: case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: + case SQL_C_TYPE_TIMESTAMP: // we don't provide auto-converstion case SQL_C_NUMERIC: case SQL_C_GUID: default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_NCHAR: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_WCHAR: { @@ -2116,13 +2145,6 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->buffer = bind->u.bin; } CHK_CONV(1, code); - // bind->u.nchar = (char*)paramValue; - // if (*soi == SQL_NTS) { - // bind->buffer_length = strlen((const char*)paramValue); - // } else { - // bind->buffer_length = (uintptr_t)*soi; - // } - // bind->buffer = bind->u.nchar; } break; case SQL_C_SHORT: case SQL_C_SSHORT: @@ -2144,14 +2166,14 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin case SQL_C_TIMESTAMP: case SQL_C_TYPE_DATE: case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: + case SQL_C_TYPE_TIMESTAMP: // we don't provide auto-converstion case SQL_C_NUMERIC: case SQL_C_GUID: default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } @@ -2160,7 +2182,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index aaca1f75f7..4f7171d149 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -62,6 +62,7 @@ const char* tsdb_conv_code_str(TSDB_CONV_CODE code) { case TSDB_CONV_TRUNC: return "TSDB_CONV_TRUNC"; case TSDB_CONV_CHAR_NOT_NUM: return "TSDB_CONV_CHAR_NOT_NUM"; case TSDB_CONV_CHAR_NOT_TS: return "TSDB_CONV_CHAR_NOT_TS"; + case TSDB_CONV_NOT_VALID_TS: return "TSDB_CONV_NOT_VALID_TS"; case TSDB_CONV_GENERAL: return "TSDB_CONV_GENERAL"; case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR"; default: return "UNKNOWN"; @@ -592,7 +593,20 @@ struct tsdb_conv_s { unsigned int direct:1; }; +static tsdb_conv_t no_conversion = {0}; +static pthread_once_t once = PTHREAD_ONCE_INIT; +static void once_init(void) { + no_conversion.cnv = (iconv_t)-1; + no_conversion.direct = 1; +} + +tsdb_conv_t* tsdb_conv_direct() { // get a non-conversion-converter + pthread_once(&once, once_init); + return &no_conversion; +} + tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc) { + pthread_once(&once, once_init); tsdb_conv_t *cnv = (tsdb_conv_t*)calloc(1, sizeof(*cnv)); if (!cnv) return NULL; if (strcmp(from_enc, to_enc)==0) { @@ -611,6 +625,7 @@ tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc) { void tsdb_conv_close(tsdb_conv_t *cnv) { if (!cnv) return; + if (cnv == &no_conversion) return; if (!cnv->direct) { if (cnv->cnv != (iconv_t)-1) { iconv_close(cnv->cnv); diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h index 529cc10e93..2075d22870 100644 --- a/src/connector/odbc/src/todbc_conv.h +++ b/src/connector/odbc/src/todbc_conv.h @@ -30,6 +30,7 @@ typedef enum { TSDB_CONV_TRUNC, TSDB_CONV_CHAR_NOT_NUM, TSDB_CONV_CHAR_NOT_TS, + TSDB_CONV_NOT_VALID_TS, TSDB_CONV_GENERAL, TSDB_CONV_BAD_CHAR, } TSDB_CONV_CODE; @@ -46,8 +47,10 @@ char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes); int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr); typedef struct tsdb_conv_s tsdb_conv_t; +tsdb_conv_t* tsdb_conv_direct(); // get a non-conversion-converter tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc); void tsdb_conv_close(tsdb_conv_t *cnv); + TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen); TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen); TSDB_CONV_CODE tsdb_conv_write_double(tsdb_conv_t *cnv, double val, char *dst, size_t *dlen); diff --git a/src/connector/odbc/tests/odbc.py b/src/connector/odbc/tests/odbc.py index 01dd52852b..c137905775 100644 --- a/src/connector/odbc/tests/odbc.py +++ b/src/connector/odbc/tests/odbc.py @@ -5,13 +5,13 @@ cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8') #cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8') #cnxn.setencoding(encoding='utf-8') -cursor = cnxn.cursor() -cursor.execute("SELECT * from db.t") -row = cursor.fetchone() -while row: - print(row) - row = cursor.fetchone() -cursor.close() +#cursor = cnxn.cursor() +#cursor.execute("SELECT * from db.t") +#row = cursor.fetchone() +#while row: +# print(row) +# row = cursor.fetchone() +#cursor.close() #cursor = cnxn.cursor() #cursor.execute(""" diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 5330ca0bad..d15d162d6c 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -379,6 +379,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_STATEMENT_NOT_READY, 0, 0x210d, "statement TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONNECTION_BUSY, 0, 0x210e, "connection still busy") TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_CONNSTR, 0, 0x210f, "bad connection string") TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_ARG, 0, 0x2110, "bad argument") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_VALID_TS, 0, 0x2111, "not a valid timestamp") #ifdef TAOS_ERROR_C From b1792612ccc8563a7c0abad0a50f2112d91bf247 Mon Sep 17 00:00:00 2001 From: freemine Date: Sat, 31 Oct 2020 15:06:08 +0800 Subject: [PATCH 35/85] unify calls and remove obsoletes --- src/connector/odbc/src/todbc.c | 130 ++++++++---------- src/connector/odbc/src/todbc_conv.c | 201 ---------------------------- src/connector/odbc/src/todbc_conv.h | 14 -- src/connector/odbc/src/todbc_util.c | 121 ----------------- src/connector/odbc/src/todbc_util.h | 11 -- 5 files changed, 55 insertions(+), 422 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 03d47dad4d..62868163a3 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -74,7 +74,6 @@ do { if (Sqlstate) strncpy((char*)Sqlstate, (char*)obj->err.sql_state, n); \ if (NativeError) *NativeError = obj->err.err_no; \ snprintf((char*)MessageText, (size_t)BufferLength, "%s", obj->err.err_str); \ - if (TextLength && obj->err.err_str) *TextLength = (SQLSMALLINT)strlen(obj->err.err_str); \ if (TextLength && obj->err.err_str) *TextLength = (SQLSMALLINT)utf8_chars(obj->err.err_str); \ } while (0) @@ -264,10 +263,6 @@ struct sql_s { uint64_t refcount; conn_t *conn; - iconv_t w2c; // wchar* -> char* - iconv_t u2c; // unicode -> char* - iconv_t u2w; // unicode -> wchar* - TAOS_STMT *stmt; param_bind_t *params; int n_params; @@ -297,14 +292,6 @@ static pthread_once_t init_once = PTHREAD_ONCE_INIT; static void init_routine(void); static size_t do_field_display_size(TAOS_FIELD *field); -static iconv_t sql_get_w2c(sql_t *sql) { - if (sql->w2c == (iconv_t)-1) { - sql->w2c = iconv_open("UTF-8", "UCS-2LE"); - } - - return sql->w2c; -} - static tsdb_conv_t* tsdb_conn_client_to_server(conn_t *conn) { if (!conn->client_to_server) { @@ -409,22 +396,6 @@ do { } \ } while (0) -// static iconv_t sql_get_u2c(sql_t *sql) { -// if (sql->u2c == (iconv_t)-1) { -// sql->u2c = iconv_open("UTF-8", "UCS-4LE"); -// } -// -// return sql->u2c; -// } -// -// static iconv_t sql_get_u2w(sql_t *sql) { -// if (sql->u2w == (iconv_t)-1) { -// sql->u2w = iconv_open("UCS-2LE", "UCS-4LE"); -// } -// -// return sql->u2w; -// } - static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) { pthread_once(&init_once, init_routine); @@ -666,10 +637,6 @@ static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle, break; } - sql->w2c = (iconv_t)-1; - sql->u2c = (iconv_t)-1; - sql->u2w = (iconv_t)-1; - sql->conn = conn; DASSERT(INC_REF(sql)>0); @@ -767,19 +734,6 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle, FREE_ERROR(sql); - if (sql->w2c!=(iconv_t)-1) { - iconv_close(sql->w2c); - sql->w2c = (iconv_t)-1; - } - if (sql->u2c!=(iconv_t)-1) { - iconv_close(sql->u2c); - sql->u2c = (iconv_t)-1; - } - if (sql->u2w!=(iconv_t)-1) { - iconv_close(sql->u2w); - sql->u2w = (iconv_t)-1; - } - free(sql); return SQL_SUCCESS; @@ -793,11 +747,22 @@ SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle, return r; } +static SQLRETURN do_exec_direct(sql_t *sql, TSDB_CONV_CODE code, const char *statement) { + if (code) CHK_CONV(1, code); + DASSERT(code==TSDB_CONV_OK); + + SQLRETURN r = SQL_ERROR; + do { + sql->rs = taos_query(sql->conn->taos, statement); + CHK_RS(r, sql, "failed to execute"); + } while (0); + + return r; +} + static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength) { - stack_buffer_t buffer; buffer.next = 0; - sql_t *sql = (sql_t*)StatementHandle; if (!sql) return SQL_INVALID_HANDLE; @@ -825,20 +790,14 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, } sql->n_params = 0; + SQLRETURN r = SQL_SUCCESS; + stack_buffer_t buffer; buffer.next = 0; tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); const char *stxt = NULL; - - SQLRETURN r = SQL_ERROR; do { - tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); - if (!stxt) { - SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); - break; - } - sql->rs = taos_query(sql->conn->taos, stxt); - CHK_RS(r, sql, "failed to execute"); + TSDB_CONV_CODE code = tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); + r = do_exec_direct(sql, code, stxt); } while (0); - tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); return r; @@ -860,6 +819,8 @@ static SQLRETURN doSQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER CHK_CONN(sql); CHK_CONN_TAOS(sql); + conn_t *conn = sql->conn; + if (!szSqlStr) { SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "szSqlStr [%p] not allowed", szSqlStr); return SQL_ERROR; @@ -869,10 +830,17 @@ static SQLRETURN doSQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER return SQL_ERROR; } - size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(szSqlStr, (size_t)cbSqlStr, &bytes); - SQLRETURN r = SQLExecDirect(hstmt, utf8, (SQLINTEGER)bytes); - if (utf8) free(utf8); + SQLRETURN r = SQL_SUCCESS; + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); + const char *stxt = NULL; + do { + size_t slen = (size_t)cbSqlStr * sizeof(*szSqlStr); + TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, &buffer, (const char*)szSqlStr, slen, &stxt, NULL); + r = do_exec_direct(sql, code, stxt); + } while (0); + tsdb_conv_free(utf16_to_server, stxt, &buffer, (const char*)szSqlStr); + return r; } @@ -1572,7 +1540,11 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, tsdb_conv_chars_to_bit(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_bit(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.b)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_bit(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1629,7 +1601,11 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin // CHK_CONV(1, tsdb_chars_to_tinyint((const char *)paramValue, (size_t)*soi, &bind->u.v1)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_tinyint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v1)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_tinyint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v1)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1688,7 +1664,11 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin // CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, (size_t)*soi, &bind->u.v2)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_smallint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v2)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_smallint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v2)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1747,7 +1727,11 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin // CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, (size_t)*soi, &bind->u.v4)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_int(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v4)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_int(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v4)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1806,7 +1790,11 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin // CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, (size_t)*soi, &bind->u.v8)); } break; case SQL_C_WCHAR: { - CHK_CONV(1, tsdb_wchars_to_bigint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v8)); + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_bigint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1868,7 +1856,6 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin size_t slen = (size_t)*soi; if (slen==SQL_NTS) slen = strlen((const char*)paramValue); CHK_CONV(1, tsdb_conv_chars_to_float(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4)); - // CHK_CONV(1, tsdb_chars_to_float((const char*)paramValue, (size_t)*soi, &bind->u.f4)); } break; case SQL_C_WCHAR: { stack_buffer_t buffer; buffer.next = 0; @@ -1876,7 +1863,6 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin size_t slen = (size_t)*soi; DASSERT(slen != SQL_NTS); CHK_CONV(1, tsdb_conv_chars_to_float(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4)); - // CHK_CONV(1, tsdb_wchars_to_float(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f4)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -1944,7 +1930,6 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin size_t slen = (size_t)*soi; DASSERT(slen != SQL_NTS); CHK_CONV(1, tsdb_conv_chars_to_double(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8)); - // CHK_CONV(1, tsdb_wchars_to_double(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f8)); } break; case SQL_C_USHORT: case SQL_C_ULONG: @@ -2817,11 +2802,6 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, static void init_routine(void) { - if (0) { - string_conv(NULL, NULL, NULL, 0, NULL, 0, NULL, NULL); - utf8_to_ucs4le(NULL, NULL); - ucs4le_to_utf8(NULL, 0, NULL); - } taos_init(); } diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index 4f7171d149..978c6c2d84 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -23,35 +23,6 @@ #include #include -typedef struct buf_s buf_t; - -struct buf_s { - char buf[1024*16+1]; - - char *ptr; -}; - -static char* buf_init(buf_t *buf, size_t len); -static void buf_clean(buf_t *buf); - -static char* buf_init(buf_t *buf, size_t len) { - if (len>sizeof(buf->buf)) { - buf->ptr = (char*)malloc(len); - } else if (len>0) { - buf->ptr = &buf->buf[0]; - } else { - buf->ptr = NULL; - } - return buf->ptr; -} - -static void buf_clean(buf_t *buf) { - if (buf->ptr && buf->ptr != buf->buf) { - free(buf->ptr); - buf->ptr = NULL; - } -} - const char* tsdb_conv_code_str(TSDB_CONV_CODE code) { switch (code) { case TSDB_CONV_OK: return "TSDB_CONV_OK"; @@ -69,36 +40,6 @@ const char* tsdb_conv_code_str(TSDB_CONV_CODE code) { }; } -TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen) { - if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; - - char *s = (char*)src; - char *d = (char*)dst; - size_t sl = *slen; - size_t dl = *dlen; - - size_t n = iconv(cnv, &s, &sl, &d, &dl); - int e = errno; - if (dl) *d = '\0'; // what if all consumed? - - *slen = sl; - *dlen = dl; - - if (e==0) { - if (n) return TSDB_CONV_BAD_CHAR; - return TSDB_CONV_OK; - } - - iconv(cnv, NULL, NULL, NULL, NULL); - - switch (e) { - case E2BIG: return TSDB_CONV_TRUNC; - case EILSEQ: return TSDB_CONV_BAD_CHAR; - case EINVAL: return TSDB_CONV_BAD_CHAR; - default: return TSDB_CONV_GENERAL; - } -} - // src: int TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst) { *dst = (int8_t)src; @@ -425,148 +366,6 @@ TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_ } -// src: wchars -TSDB_CONV_CODE tsdb_wchars_to_bit(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst) { - if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; - - size_t len = smax * 2; - buf_t buf; - buf_init(&buf, len+1); - if (!buf.ptr) return TSDB_CONV_OOM; - - size_t dmax = len + 1; - TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); - if (code==TSDB_CONV_OK) { - code = tsdb_chars_to_bit(buf.ptr, len+1-dmax, dst); - } - - buf_clean(&buf); - - return code; -} - -TSDB_CONV_CODE tsdb_wchars_to_tinyint(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst) { - if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; - - size_t len = smax * 2; - buf_t buf; - buf_init(&buf, len+1); - if (!buf.ptr) return TSDB_CONV_OOM; - - size_t dmax = len + 1; - TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); - if (code==TSDB_CONV_OK) { - code = tsdb_chars_to_tinyint(buf.ptr, len+1-dmax, dst); - } - - buf_clean(&buf); - - return code; -} - -TSDB_CONV_CODE tsdb_wchars_to_smallint(iconv_t cnv, const unsigned char *src, size_t smax, int16_t *dst) { - if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; - - size_t len = smax * 2; - buf_t buf; - buf_init(&buf, len+1); - if (!buf.ptr) return TSDB_CONV_OOM; - - size_t dmax = len + 1; - TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); - if (code==TSDB_CONV_OK) { - code = tsdb_chars_to_smallint(buf.ptr, len+1-dmax, dst); - } - - buf_clean(&buf); - - return code; -} - -TSDB_CONV_CODE tsdb_wchars_to_int(iconv_t cnv, const unsigned char *src, size_t smax, int32_t *dst) { - if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; - - size_t len = smax * 2; - buf_t buf; - buf_init(&buf, len+1); - if (!buf.ptr) return TSDB_CONV_OOM; - - size_t dmax = len + 1; - TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); - if (code==TSDB_CONV_OK) { - code = tsdb_chars_to_int(buf.ptr, len+1-dmax, dst); - } - - buf_clean(&buf); - - return code; -} - -TSDB_CONV_CODE tsdb_wchars_to_bigint(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst) { - if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; - - size_t len = smax * 2; - buf_t buf; - buf_init(&buf, len+1); - if (!buf.ptr) return TSDB_CONV_OOM; - - size_t dmax = len + 1; - TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); - if (code==TSDB_CONV_OK) { - code = tsdb_chars_to_bigint(buf.ptr, len+1-dmax, dst); - } - - buf_clean(&buf); - - return code; -} - -TSDB_CONV_CODE tsdb_wchars_to_ts(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst) { - return tsdb_wchars_to_bigint(cnv, src, smax, dst); -} - -TSDB_CONV_CODE tsdb_wchars_to_float(iconv_t cnv, const unsigned char *src, size_t smax, float *dst) { - if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; - - size_t len = smax * 2; - buf_t buf; - buf_init(&buf, len+1); - if (!buf.ptr) return TSDB_CONV_OOM; - - size_t dmax = len + 1; - TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); - if (code==TSDB_CONV_OK) { - code = tsdb_chars_to_float(buf.ptr, len+1-dmax, dst); - } - - buf_clean(&buf); - - return code; -} - -TSDB_CONV_CODE tsdb_wchars_to_double(iconv_t cnv, const unsigned char *src, size_t smax, double *dst) { - if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL; - - size_t len = smax * 2; - buf_t buf; - buf_init(&buf, len+1); - if (!buf.ptr) return TSDB_CONV_OOM; - - size_t dmax = len + 1; - TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax); - if (code==TSDB_CONV_OK) { - code = tsdb_chars_to_double(buf.ptr, len+1-dmax, dst); - } - - buf_clean(&buf); - - return code; -} - -TSDB_CONV_CODE tsdb_wchars_to_char(iconv_t cnv, const unsigned char *src, size_t smax, char *dst, size_t dmax) { - return tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)dst, &dmax); -} - char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes) { if (!buffer) return NULL; // align-by-size_of-size_t-bytes diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h index 2075d22870..8dcaca0d02 100644 --- a/src/connector/odbc/src/todbc_conv.h +++ b/src/connector/odbc/src/todbc_conv.h @@ -70,10 +70,6 @@ TSDB_CONV_CODE tsdb_conv(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *s void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src); -TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen); - - - TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst); TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst); TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst); @@ -105,15 +101,5 @@ TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst); TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst); TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax); -TSDB_CONV_CODE tsdb_wchars_to_bit(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_tinyint(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_smallint(iconv_t cnv, const unsigned char *src, size_t smax, int16_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_int(iconv_t cnv, const unsigned char *src, size_t smax, int32_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_bigint(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_ts(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst); -TSDB_CONV_CODE tsdb_wchars_to_float(iconv_t cnv, const unsigned char *src, size_t smax, float *dst); -TSDB_CONV_CODE tsdb_wchars_to_double(iconv_t cnv, const unsigned char *src, size_t smax, double *dst); -TSDB_CONV_CODE tsdb_wchars_to_char(iconv_t cnv, const unsigned char *src, size_t smax, char *dst, size_t dmax); - #endif // _todbc_conv_h_ diff --git a/src/connector/odbc/src/todbc_util.c b/src/connector/odbc/src/todbc_util.c index 34008a8355..9c130b4f2f 100644 --- a/src/connector/odbc/src/todbc_util.c +++ b/src/connector/odbc/src/todbc_util.c @@ -107,39 +107,6 @@ int is_valid_sql_sql_type(int type) { return 1; } -int string_conv(const char *fromcode, const char *tocode, - const unsigned char *src, size_t sbytes, - unsigned char *dst, size_t dbytes, - size_t *consumed, size_t *generated) -{ - if (consumed) *consumed = 0; - if (generated) *generated = 0; - - if (dbytes <= 0) return -1; - dst[0] = '\0'; - - iconv_t conv = iconv_open(tocode, fromcode); - if (!conv) return -1; - - size_t r = 0; - do { - char *s = (char*)src; - char *d = (char*)dst; - size_t sl = sbytes; - size_t dl = dbytes; - - r = iconv(conv, &s, &sl, &d, &dl); - *d = '\0'; - - if (consumed) *consumed = sbytes - sl; - if (generated) *generated = dbytes - dl; - - } while (0); - - iconv_close(conv); - return (int)r; -} - int utf8_chars(const char *src) { const char *fromcode = "UTF-8"; @@ -160,91 +127,3 @@ int utf8_chars(const char *src) return (int)chars; } -unsigned char* utf8_to_ucs4le(const char *utf8, size_t *chars) -{ - const char *tocode = "UCS-4LE"; - const char *fromcode = "UTF-8"; - - iconv_t conv = iconv_open(tocode, fromcode); - if (!conv) return NULL; - - unsigned char *ucs4le = NULL; - - do { - size_t slen = strlen(utf8); - size_t dlen = slen * 4; - - ucs4le = (unsigned char*)malloc(dlen+1); - if (!ucs4le) break; - - char *src = (char*)utf8; - char *dst = (char*)ucs4le; - size_t s = slen; - size_t d = dlen; - iconv(conv, &src, &s, &dst, &d); - dst[0] = '\0'; - - if (chars) *chars = (dlen - d) / 4; - } while (0); - - iconv_close(conv); - return ucs4le; -} - -char* ucs4le_to_utf8(const unsigned char *ucs4le, size_t slen, size_t *chars) -{ - const char *fromcode = "UCS-4LE"; - const char *tocode = "UTF-8"; - - iconv_t conv = iconv_open(tocode, fromcode); - if (!conv) return NULL; - - char *utf8 = NULL; - - do { - size_t dlen = slen; - - utf8 = (char*)malloc(dlen+1); - if (!utf8) break; - - char *dst = utf8; - char *src = (char*)ucs4le; - size_t s = slen; - size_t d = dlen; - iconv(conv, &src, &s, &dst, &d); - dst[0] = '\0'; - - if (chars) *chars = (slen - s) / 4; - } while (0); - - iconv_close(conv); - return utf8; -} - -SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes) -{ - size_t dlen = chs * 4; - SQLCHAR *dst = (SQLCHAR*)malloc(dlen + 1); - if (!dst) return NULL; - - string_conv("UCS-2LE", "UTF-8", (const unsigned char*)wchars, chs * sizeof(*wchars), dst, dlen + 1, NULL, bytes); - - return dst; -} - -size_t wchars_to_chars2(const SQLWCHAR *src, size_t slen, SQLCHAR *dst, size_t dlen) -{ - size_t consumed=0, generated=0; - int n = string_conv("UCS-2LE", "UTF-8", (const unsigned char*)src, slen, dst, dlen, &consumed, &generated); - if (n) return (size_t)-1; - return generated; -} - -size_t chars_to_wchars2(const SQLCHAR *src, size_t slen, SQLWCHAR *dst, size_t dlen) -{ - size_t consumed=0, generated=0; - int n = string_conv("UTF-8", "UCS-2LE", (const unsigned char*)src, slen, (unsigned char*)dst, dlen, &consumed, &generated); - if (n) return (size_t)-1; - return generated; -} - diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index f9339f9396..ead0d73489 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -27,18 +27,7 @@ const char* sql_c_type(int type); int is_valid_sql_c_type(int type); int is_valid_sql_sql_type(int type); -int string_conv(const char *fromcode, const char *tocode, - const unsigned char *src, size_t sbytes, - unsigned char *dst, size_t dbytes, - size_t *consumed, size_t *generated); int utf8_chars(const char *src); -unsigned char* utf8_to_ucs4le(const char *utf8, size_t *chars); -char* ucs4le_to_utf8(const unsigned char *ucs4le, size_t slen, size_t *chars); -SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes); - -size_t wchars_to_chars2(const SQLWCHAR *src, size_t slen, SQLCHAR *dst, size_t dlen); -size_t chars_to_wchars2(const SQLCHAR *src, size_t slen, SQLWCHAR *dst, size_t dlen); - #endif // _TODBC_UTIL_H_ From 546e7d85849d819d3978c8c8fb871b753099914a Mon Sep 17 00:00:00 2001 From: freemine Date: Sat, 31 Oct 2020 16:24:59 +0800 Subject: [PATCH 36/85] odbc install directive moves into odbc-sub-module; client_to_env when SQL_CHAR in SQLExecDirect --- cmake/install.inc | 8 -------- src/connector/odbc/src/CMakeLists.txt | 4 ++++ src/connector/odbc/src/todbc.c | 6 +++--- src/connector/odbc/tools/CMakeLists.txt | 1 + 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/cmake/install.inc b/cmake/install.inc index 049a8a1bde..1a151be888 100755 --- a/cmake/install.inc +++ b/cmake/install.inc @@ -20,20 +20,12 @@ ELSEIF (TD_WINDOWS) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.lib DESTINATION driver) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.exp DESTINATION driver) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver) - if(FLEX_FOUND) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.lib DESTINATION driver) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.exp DESTINATION driver) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.dll DESTINATION driver) - endif () IF (TD_POWER) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/power.exe DESTINATION .) ELSE () INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taosdemo.exe DESTINATION .) - if(FLEX_FOUND) - INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/todbcinst.exe DESTINATION .) - endif () ENDIF () #INSTALL(TARGETS taos RUNTIME DESTINATION driver) diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt index 7249e2d1de..664ae36436 100644 --- a/src/connector/odbc/src/CMakeLists.txt +++ b/src/connector/odbc/src/CMakeLists.txt @@ -47,4 +47,8 @@ IF (TD_WINDOWS_64) /DEF:todbc.def) SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /GL") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") + + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.lib DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.exp DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.dll DESTINATION driver) ENDIF () diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 62868163a3..af8d3e99c2 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -792,13 +792,13 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, SQLRETURN r = SQL_SUCCESS; stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + tsdb_conv_t *client_to_env = tsdb_conn_client_to_env(conn); const char *stxt = NULL; do { - TSDB_CONV_CODE code = tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); + TSDB_CONV_CODE code = tsdb_conv(client_to_env, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); r = do_exec_direct(sql, code, stxt); } while (0); - tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); + tsdb_conv_free(client_to_env, stxt, &buffer, (const char*)StatementText); return r; } diff --git a/src/connector/odbc/tools/CMakeLists.txt b/src/connector/odbc/tools/CMakeLists.txt index 5d8afb092d..a0aafb1f3c 100644 --- a/src/connector/odbc/tools/CMakeLists.txt +++ b/src/connector/odbc/tools/CMakeLists.txt @@ -8,4 +8,5 @@ ENDIF () IF (TD_WINDOWS_64) ADD_EXECUTABLE(todbcinst main.c) TARGET_LINK_LIBRARIES(todbcinst odbc32 odbccp32 user32 legacy_stdio_definitions os) + INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/todbcinst.exe DESTINATION .) ENDIF () From ca120cfb096358d38d6429cfd36822f8df9bdead Mon Sep 17 00:00:00 2001 From: freemine Date: Sat, 31 Oct 2020 19:47:56 +0800 Subject: [PATCH 37/85] add TSDB CONV CODE --- src/connector/odbc/src/todbc.c | 16 ++++++++++++++++ src/connector/odbc/src/todbc_conv.c | 21 +++++++++++++++++++-- src/connector/odbc/src/todbc_conv.h | 4 ++++ src/inc/taoserror.h | 4 ++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index af8d3e99c2..e1af13f6d4 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -193,6 +193,22 @@ do { \ SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ return SQL_ERROR; \ } break; \ + case TSDB_CONV_SRC_TOO_LARGE: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_TOO_LARGE, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_SRC_BAD_SEQ: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_BAD_SEQ, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_SRC_INCOMPLETE: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_INCOMPLETE, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_SRC_GENERAL: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_GENERAL, ""); \ + return SQL_ERROR; \ + } break; \ case TSDB_CONV_BAD_CHAR: { \ SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ return SQL_ERROR; \ diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c index 978c6c2d84..9c0f19764c 100644 --- a/src/connector/odbc/src/todbc_conv.c +++ b/src/connector/odbc/src/todbc_conv.c @@ -35,6 +35,10 @@ const char* tsdb_conv_code_str(TSDB_CONV_CODE code) { case TSDB_CONV_CHAR_NOT_TS: return "TSDB_CONV_CHAR_NOT_TS"; case TSDB_CONV_NOT_VALID_TS: return "TSDB_CONV_NOT_VALID_TS"; case TSDB_CONV_GENERAL: return "TSDB_CONV_GENERAL"; + case TSDB_CONV_SRC_TOO_LARGE: return "TSDB_CONV_SRC_TOO_LARGE"; + case TSDB_CONV_SRC_BAD_SEQ: return "TSDB_CONV_SRC_BAD_SEQ"; + case TSDB_CONV_SRC_INCOMPLETE: return "TSDB_CONV_SRC_INCOMPLETE"; + case TSDB_CONV_SRC_GENERAL: return "TSDB_CONV_SRC_GENERAL"; case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR"; default: return "UNKNOWN"; }; @@ -408,7 +412,7 @@ tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc) { pthread_once(&once, once_init); tsdb_conv_t *cnv = (tsdb_conv_t*)calloc(1, sizeof(*cnv)); if (!cnv) return NULL; - if (strcmp(from_enc, to_enc)==0) { + if (strcmp(from_enc, to_enc)==0 && 0) { cnv->cnv = (iconv_t)-1; cnv->direct = 1; return cnv; @@ -619,7 +623,20 @@ TSDB_CONV_CODE tsdb_conv(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *s size_t r = iconv(cnv->cnv, (char**)&src, &slen, &buf, &blen); do { if (r==(size_t)-1) { - code = TSDB_CONV_BAD_CHAR; + switch(errno) { + case E2BIG: { + code = TSDB_CONV_SRC_TOO_LARGE; + } break; + case EILSEQ: { + code = TSDB_CONV_SRC_BAD_SEQ; + } break; + case EINVAL: { + code = TSDB_CONV_SRC_INCOMPLETE; + } break; + default: { + code = TSDB_CONV_SRC_GENERAL; + } break; + } break; } if (slen) { diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h index 8dcaca0d02..2941f3e496 100644 --- a/src/connector/odbc/src/todbc_conv.h +++ b/src/connector/odbc/src/todbc_conv.h @@ -33,6 +33,10 @@ typedef enum { TSDB_CONV_NOT_VALID_TS, TSDB_CONV_GENERAL, TSDB_CONV_BAD_CHAR, + TSDB_CONV_SRC_TOO_LARGE, + TSDB_CONV_SRC_BAD_SEQ, + TSDB_CONV_SRC_INCOMPLETE, + TSDB_CONV_SRC_GENERAL, } TSDB_CONV_CODE; const char* tsdb_conv_code_str(TSDB_CONV_CODE code); diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index d15d162d6c..50b3fb3bfc 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -380,6 +380,10 @@ TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONNECTION_BUSY, 0, 0x210e, "connection TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_CONNSTR, 0, 0x210f, "bad connection string") TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_ARG, 0, 0x2110, "bad argument") TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_VALID_TS, 0, 0x2111, "not a valid timestamp") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_SRC_TOO_LARGE, 0, 0x2112, "src too large") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_SRC_BAD_SEQ, 0, 0x2113, "src bad sequence") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_SRC_INCOMPLETE, 0, 0x2114, "src incomplete") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_SRC_GENERAL, 0, 0x2115, "src general") #ifdef TAOS_ERROR_C From 9648ae631dc9e965862a431f5c45727f68746070 Mon Sep 17 00:00:00 2001 From: freemine Date: Sun, 1 Nov 2020 07:11:46 +0800 Subject: [PATCH 38/85] add tconv --- src/connector/odbc/tests/CMakeLists.txt | 7 +++-- src/connector/odbc/tests/main.c | 36 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/connector/odbc/tests/CMakeLists.txt b/src/connector/odbc/tests/CMakeLists.txt index d777bf72ee..cb159a79ab 100644 --- a/src/connector/odbc/tests/CMakeLists.txt +++ b/src/connector/odbc/tests/CMakeLists.txt @@ -1,13 +1,16 @@ PROJECT(TDengine) IF (TD_LINUX) - AUX_SOURCE_DIRECTORY(. SRC) + # AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(tcodbc main.c) TARGET_LINK_LIBRARIES(tcodbc odbc) + ADD_EXECUTABLE(tconv tconv.c) ENDIF () IF (TD_WINDOWS_64) - AUX_SOURCE_DIRECTORY(. SRC) + # AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(tcodbc main.c) TARGET_LINK_LIBRARIES(tcodbc odbc32 odbccp32 user32 legacy_stdio_definitions os) + ADD_EXECUTABLE(tconv tconv.c) + TARGET_LINK_LIBRARIES(tconv os) ENDIF () diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index 74bceaaf31..c938bc9993 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -22,6 +22,17 @@ do { \ } \ } while (0); +typedef struct db_column_s db_column_t; +struct db_column_s { + char name[4096]; // seems enough + SQLSMALLINT nameLength; + SQLSMALLINT dataType; + SQLULEN columnSize; + SQLSMALLINT decimalDigits; + SQLSMALLINT nullable; +}; + +static db_column_t *columns = NULL; typedef struct data_s data_t; struct data_s { @@ -129,6 +140,30 @@ static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pCon return 1; } + +static SQLRETURN traverse_cols(SQLHSTMT stmt, SQLSMALLINT cols) { + SQLRETURN r = SQL_ERROR; + for (SQLSMALLINT i=0; i Date: Sun, 1 Nov 2020 07:12:38 +0800 Subject: [PATCH 39/85] add tconv.c --- src/connector/odbc/tests/tconv.c | 132 +++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/connector/odbc/tests/tconv.c diff --git a/src/connector/odbc/tests/tconv.c b/src/connector/odbc/tests/tconv.c new file mode 100644 index 0000000000..f0a528cf9a --- /dev/null +++ b/src/connector/odbc/tests/tconv.c @@ -0,0 +1,132 @@ +#include "../src/todbc_log.h" + +#ifdef _MSC_VER +#include +#include +#include "msvcIconv.h" +#else +#include +#endif + + +#include +#include + +static void usage(const char *arg0); +static int do_conv(iconv_t cnv, FILE *fin); + +int main(int argc, char *argv[]) { + const char *from_enc = "UTF-8"; + const char *to_enc = "UTF-8"; + const char *src = NULL; +#ifdef _MSC_VER + from_enc = "CP936"; + to_enc = "CP936"; +#endif + for (int i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (strcmp(arg, "-h") == 0) { + usage(argv[0]); + return 0; + } else if (strcmp(arg, "-f") == 0 ) { + i += 1; + if (i>=argc) { + fprintf(stderr, "expecing , but got nothing\n"); + return 1; + } + from_enc = argv[i]; + continue; + } else if (strcmp(arg, "-t") == 0 ) { + i += 1; + if (i>=argc) { + fprintf(stderr, "expecing , but got nothing\n"); + return 1; + } + to_enc = argv[i]; + continue; + } else if (arg[0]=='-') { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return 1; + } else { + if (src) { + fprintf(stderr, "does not allow multiple files\n"); + return 1; + } + src = arg; + continue; + } + } + FILE *fin = src ? fopen(src, "rb") : stdin; + if (!fin) { + fprintf(stderr, "failed to open file [%s]\n", src); + return 1; + } + int r = 0; + do { + iconv_t cnv = iconv_open(to_enc, from_enc); + if (cnv == (iconv_t)-1) { + fprintf(stderr, "failed to open conv from [%s] to [%s]: [%s]\n", from_enc, to_enc, strerror(errno)); + return -1; + } + r = do_conv(cnv, fin); + iconv_close(cnv); + } while (0); + fclose(fin); + return r ? 1 : 0; +} + +static void usage(const char *arg0) { + fprintf(stderr, "%s -h | [-f ] [-t ] [file]\n", arg0); + return; +} + +#define IN_SIZE (256*1024) +#define OUT_SIZE (8*IN_SIZE) +static int do_conv(iconv_t cnv, FILE *fin) { + int r = 0; + char src[IN_SIZE]; + size_t slen = sizeof(src); + char dst[OUT_SIZE]; + size_t dlen = sizeof(dst); + char *start = src; + while (!feof(fin)) { + slen = (size_t)(src + sizeof(src) - start); + size_t n = fread(start, 1, slen, fin); + if (n>0) { + char *ss = src; + size_t sl = n; + while (sl) { + char *dd = dst; + size_t dn = dlen; + size_t v = iconv(cnv, &ss, &sl, &dd, &dn); + if (v==(size_t)-1) { + int err = errno; + if (err == EILSEQ) { + fprintf(stderr, "failed to convert: [%s]\n", strerror(err)); + r = -1; + break; + } + if (err == EINVAL) { + fprintf(stderr, "[%s]\n", strerror(errno)); + size_t ava = (size_t)(src + sizeof(src) - ss); + memcpy(src, ss, ava); + start = ss; + } else { + fprintf(stderr, "internal logic error: [%s]\n", strerror(errno)); + r = -1; + break; + } + } + n = fwrite(dst, 1, (size_t)(dd-dst), stdout); + if (n Date: Sun, 1 Nov 2020 08:19:09 +0800 Subject: [PATCH 40/85] port tconv to windows --- src/connector/odbc/tests/CMakeLists.txt | 4 +- src/connector/odbc/tests/tconv.c | 58 +++++++++++++++++-------- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/connector/odbc/tests/CMakeLists.txt b/src/connector/odbc/tests/CMakeLists.txt index cb159a79ab..1cc6acaf4b 100644 --- a/src/connector/odbc/tests/CMakeLists.txt +++ b/src/connector/odbc/tests/CMakeLists.txt @@ -8,9 +8,11 @@ IF (TD_LINUX) ENDIF () IF (TD_WINDOWS_64) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /GL") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") # AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(tcodbc main.c) TARGET_LINK_LIBRARIES(tcodbc odbc32 odbccp32 user32 legacy_stdio_definitions os) ADD_EXECUTABLE(tconv tconv.c) - TARGET_LINK_LIBRARIES(tconv os) + TARGET_LINK_LIBRARIES(tconv tutil) ENDIF () diff --git a/src/connector/odbc/tests/tconv.c b/src/connector/odbc/tests/tconv.c index f0a528cf9a..acae6421bb 100644 --- a/src/connector/odbc/tests/tconv.c +++ b/src/connector/odbc/tests/tconv.c @@ -3,21 +3,21 @@ #ifdef _MSC_VER #include #include -#include "msvcIconv.h" -#else -#include #endif +#include + #include #include static void usage(const char *arg0); -static int do_conv(iconv_t cnv, FILE *fin); +static int do_conv(iconv_t cnv, FILE *fin, FILE *fout); int main(int argc, char *argv[]) { const char *from_enc = "UTF-8"; const char *to_enc = "UTF-8"; + const char *dst_file = NULL; const char *src = NULL; #ifdef _MSC_VER from_enc = "CP936"; @@ -44,6 +44,14 @@ int main(int argc, char *argv[]) { } to_enc = argv[i]; continue; + } else if (strcmp(arg, "-o") == 0 ) { + i += 1; + if (i>=argc) { + fprintf(stderr, "expecing , but got nothing\n"); + return 1; + } + dst_file = argv[i]; + continue; } else if (arg[0]=='-') { fprintf(stderr, "unknown argument: [%s]\n", arg); return 1; @@ -56,33 +64,49 @@ int main(int argc, char *argv[]) { continue; } } + int r = -1; FILE *fin = src ? fopen(src, "rb") : stdin; - if (!fin) { - fprintf(stderr, "failed to open file [%s]\n", src); - return 1; - } - int r = 0; + FILE *fout = dst_file ? fopen(dst_file, "wb") : stdout; + iconv_t cnv = iconv_open(to_enc, from_enc); do { - iconv_t cnv = iconv_open(to_enc, from_enc); + if (!fin) { + fprintf(stderr, "failed to open file [%s]\n", src); + break; + } + if (!fout) { + fprintf(stderr, "failed to open file [%s]\n", dst_file); + break; + } +#ifdef _MSC_VER + if (fout == stdout) { + r = _setmode(_fileno(fout), _O_BINARY); + if (r == -1) { + fprintf(stderr, "Cannot set binary mode for output stream: %d[%s]\n", errno, strerror(errno)); + } + } +#endif + if (cnv == (iconv_t)-1) { fprintf(stderr, "failed to open conv from [%s] to [%s]: [%s]\n", from_enc, to_enc, strerror(errno)); - return -1; + break; } - r = do_conv(cnv, fin); + r = do_conv(cnv, fin, fout); iconv_close(cnv); + cnv = (iconv_t)-1; } while (0); - fclose(fin); + if (fin && fin != stdin) fclose(fin); + if (fout && fout != stdout) fclose(fout); return r ? 1 : 0; } static void usage(const char *arg0) { - fprintf(stderr, "%s -h | [-f ] [-t ] [file]\n", arg0); + fprintf(stderr, "%s -h | [-f ] [-t ] [-o ] [file]\n", arg0); return; } -#define IN_SIZE (256*1024) +#define IN_SIZE (64*1024) #define OUT_SIZE (8*IN_SIZE) -static int do_conv(iconv_t cnv, FILE *fin) { +static int do_conv(iconv_t cnv, FILE *fin, FILE *fout) { int r = 0; char src[IN_SIZE]; size_t slen = sizeof(src); @@ -117,7 +141,7 @@ static int do_conv(iconv_t cnv, FILE *fin) { break; } } - n = fwrite(dst, 1, (size_t)(dd-dst), stdout); + n = fwrite(dst, 1, (size_t)(dd-dst), fout); if (n Date: Mon, 2 Nov 2020 14:45:15 +0800 Subject: [PATCH 41/85] special concern about `binary` field --- src/CMakeLists.txt | 2 +- src/connector/odbc/src/todbc.c | 181 ++++++++++++++++++++------------- 2 files changed, 109 insertions(+), 74 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f619edd221..2ed56d4f81 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,5 +21,5 @@ ADD_SUBDIRECTORY(wal) ADD_SUBDIRECTORY(cq) ADD_SUBDIRECTORY(dnode) ADD_SUBDIRECTORY(connector/odbc) -ADD_SUBDIRECTORY(connector/jdbc) +# ADD_SUBDIRECTORY(connector/jdbc) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index e1af13f6d4..17b243f87f 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -22,6 +22,7 @@ #include "taos.h" +#include "tglobal.h" #include "taoserror.h" #include "todbc_util.h" #include "todbc_conv.h" @@ -250,6 +251,7 @@ struct env_s { unsigned int destroying:1; char env_locale[64]; + char env_charset[64]; taos_error_t err; }; @@ -258,8 +260,8 @@ struct conn_s { uint64_t refcount; env_t *env; - char client_enc[64]; - char server_enc[64]; + char client_enc[64]; // ODBC client that communicates with this driver + char server_enc[64]; // taos dynamic library that's loaded by this driver tsdb_conv_t *client_to_server; tsdb_conv_t *server_to_client; @@ -267,8 +269,6 @@ struct conn_s { tsdb_conv_t *utf16_to_utf8; tsdb_conv_t *utf16_to_server; tsdb_conv_t *client_to_utf8; - tsdb_conv_t *env_to_client; - tsdb_conv_t *client_to_env; TAOS *taos; @@ -330,14 +330,14 @@ static tsdb_conv_t* tsdb_conn_utf8_to_client(conn_t *conn) { return conn->utf8_to_client; } -tsdb_conv_t* tsdb_conn_utf16_to_utf8(conn_t *conn) { +static tsdb_conv_t* tsdb_conn_utf16_to_utf8(conn_t *conn) { if (!conn->utf16_to_utf8) { conn->utf16_to_utf8 = tsdb_conv_open(UTF16_ENC, UTF8_ENC); } return conn->utf16_to_utf8; } -tsdb_conv_t* tsdb_conn_utf16_to_server(conn_t *conn) { +static tsdb_conv_t* tsdb_conn_utf16_to_server(conn_t *conn) { if (!conn->utf16_to_server) { conn->utf16_to_server = tsdb_conv_open(UTF16_ENC, conn->server_enc); } @@ -351,24 +351,7 @@ static tsdb_conv_t* tsdb_conn_client_to_utf8(conn_t *conn) { return conn->client_to_utf8; } -static tsdb_conv_t* tsdb_conn_env_to_client(conn_t *conn) { - if (!conn->env_to_client) { - conn->env_to_client = tsdb_conv_open(conn->env->env_locale, conn->client_enc); - } - return conn->env_to_client; -} - -static tsdb_conv_t* tsdb_conn_client_to_env(conn_t *conn) { - if (!conn->client_to_env) { - conn->client_to_env = tsdb_conv_open(conn->client_enc, conn->env->env_locale); - } - return conn->client_to_env; -} - static void tsdb_conn_close_convs(conn_t *conn) { - if (0) { - tsdb_conn_server_to_client(NULL); - } if (conn->client_to_server) { tsdb_conv_close(conn->client_to_server); conn->client_to_server = NULL; @@ -393,14 +376,6 @@ static void tsdb_conn_close_convs(conn_t *conn) { tsdb_conv_close(conn->client_to_utf8); conn->client_to_utf8 = NULL; } - if (conn->env_to_client) { - tsdb_conv_close(conn->env_to_client); - conn->env_to_client = NULL; - } - if (conn->client_to_env) { - tsdb_conv_close(conn->client_to_env); - conn->client_to_env = NULL; - } } #define SFREE(buffer, v, src) \ @@ -421,11 +396,8 @@ static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) DASSERT(INC_REF(env)>0); -#ifdef _MSC_VER - snprintf(env->env_locale, sizeof(env->env_locale), GB18030_ENC); -#else - snprintf(env->env_locale, sizeof(env->env_locale), UTF8_ENC); -#endif + snprintf(env->env_locale, sizeof(env->env_locale), "%s", tsLocale); + snprintf(env->env_charset, sizeof(env->env_charset), "%s", tsCharset); *EnvironmentHandle = env; @@ -490,8 +462,8 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, conn->env = env; - snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", conn->env->env_locale); - snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", conn->env->env_locale); + snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", conn->env->env_charset); + snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", conn->env->env_charset); *ConnectionHandle = conn; @@ -808,13 +780,13 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, SQLRETURN r = SQL_SUCCESS; stack_buffer_t buffer; buffer.next = 0; - tsdb_conv_t *client_to_env = tsdb_conn_client_to_env(conn); + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); const char *stxt = NULL; do { - TSDB_CONV_CODE code = tsdb_conv(client_to_env, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); + TSDB_CONV_CODE code = tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); r = do_exec_direct(sql, code, stxt); } while (0); - tsdb_conv_free(client_to_env, stxt, &buffer, (const char*)StatementText); + tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); return r; } @@ -1218,14 +1190,29 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { case SQL_C_CHAR: { + // taos cares nothing about what would be stored in 'binary' as most sql implementations do + // but the client requires to fetch it as a SQL_C_CHAR + // thus, we first try to decode binary to client charset + // if failed, we then do hex-serialization + tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); size_t slen = strnlen((const char*)row, field_bytes); size_t len = (size_t)BufferLength; TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, - (const char*)row, &slen, - (char*)TargetValue, &len); - if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); - CHK_CONV(0, code); + (const char*)row, &slen, + (char*)TargetValue, &len); + if (code==TSDB_CONV_OK) { + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); + CHK_CONV(0, code); + // code never reached here + } + + // todo: hex-serialization + const char *bad = ""; + int n = snprintf((char*)TargetValue, (size_t)BufferLength, "%s", bad); + // what if n < 0 ? + if (StrLen_or_Ind) *StrLen_or_Ind = n; + CHK_CONV(0, n>=BufferLength ? TSDB_CONV_TRUNC : TSDB_CONV_OK); } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, @@ -1240,10 +1227,10 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { case SQL_C_CHAR: { - tsdb_conv_t *env_to_client = tsdb_conn_env_to_client(conn); + tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); size_t slen = strnlen((const char*)row, field_bytes); size_t len = (size_t)BufferLength; - TSDB_CONV_CODE code = tsdb_conv_write(env_to_client, + TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, (const char*)row, &slen, (char*)TargetValue, &len); if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); @@ -2044,38 +2031,84 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_WCHAR: { - tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); + // taos cares nothing about what would be stored in 'binary' as most sql implementations do + // thus, we just copy it as is + // it's caller's responsibility to maintain data-consistency + // if he/she is going to use 'binary' to store characters + // taos might extend it's sql syntax to let user specify + // what charset is to be used for specific 'binary' field when + // table is to be created + // in such way, 'binary' would be 'internationalized' + // but actually speaking, normally, 'char' field is a better + // one for this purpose size_t slen = (size_t)*soi; DASSERT(slen != SQL_NTS); - const char *buf = NULL; - size_t blen = 0; - TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); - if (code==TSDB_CONV_OK) { - if (buf!=(const char*)paramValue) { - bind->allocated = 1; - } - bind->u.bin = (unsigned char*)buf; - bind->buffer_length = blen; - bind->buffer = bind->u.bin; + bind->u.bin = (unsigned char*)malloc(slen + 1); // add null-terminator, just for case of use + if (!bind->u.bin) { + CHK_CONV(1, TSDB_CONV_OOM); + // code never reached here } - CHK_CONV(1, code); + memcpy(bind->u.bin, paramValue, slen); + bind->buffer_length = slen; + bind->buffer = bind->u.bin; + CHK_CONV(1, TSDB_CONV_OK); + + // tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); + // size_t slen = (size_t)*soi; + // DASSERT(slen != SQL_NTS); + // const char *buf = NULL; + // size_t blen = 0; + // TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + // if (code==TSDB_CONV_OK) { + // if (buf!=(const char*)paramValue) { + // bind->allocated = 1; + // } + // bind->u.bin = (unsigned char*)buf; + // bind->buffer_length = blen; + // bind->buffer = bind->u.bin; + // } + // CHK_CONV(1, code); } break; case SQL_C_CHAR: { - tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + // taos cares nothing about what would be stored in 'binary' as most sql implementations do + // thus, we just copy it as is + // it's caller's responsibility to maintain data-consistency + // if he/she is going to use 'binary' to store characters + // taos might extend it's sql syntax to let user specify + // what charset is to be used for specific 'binary' field when + // table is to be created + // in such way, 'binary' would be 'internationalized' + // but actually speaking, normally, 'char' field is a better + // one for this purpose size_t slen = (size_t)*soi; if (slen==SQL_NTS) slen = strlen((const char*)paramValue); - const char *buf = NULL; - size_t blen = 0; - TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); - if (code==TSDB_CONV_OK) { - if (buf!=(const char*)paramValue) { - bind->allocated = 1; - } - bind->u.bin = (unsigned char*)buf; - bind->buffer_length = blen; - bind->buffer = bind->u.bin; + // we can not use strndup, because ODBC client might pass in a buffer without null-terminated + bind->u.bin = (unsigned char*)malloc(slen + 1); // add null-terminator, just for case of use + if (!bind->u.bin) { + CHK_CONV(1, TSDB_CONV_OOM); + // code never reached here } - CHK_CONV(1, code); + memcpy(bind->u.bin, paramValue, slen); + bind->buffer_length = slen; + bind->buffer = bind->u.bin; + CHK_CONV(1, TSDB_CONV_OK); + // code never reached here + + // tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + // size_t slen = (size_t)*soi; + // if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + // const char *buf = NULL; + // size_t blen = 0; + // TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + // if (code==TSDB_CONV_OK) { + // if (buf!=(const char*)paramValue) { + // bind->allocated = 1; + // } + // bind->u.bin = (unsigned char*)buf; + // bind->buffer_length = blen; + // bind->buffer = bind->u.bin; + // } + // CHK_CONV(1, code); } break; case SQL_C_SHORT: case SQL_C_SSHORT: @@ -2131,12 +2164,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin CHK_CONV(1, code); } break; case SQL_C_CHAR: { - tsdb_conv_t *client_to_env = tsdb_conn_client_to_env(conn); + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); size_t slen = (size_t)*soi; if (slen==SQL_NTS) slen = strlen((const char*)paramValue); const char *buf = NULL; size_t blen = 0; - TSDB_CONV_CODE code = tsdb_conv(client_to_env, NULL, (const char *)paramValue, slen, &buf, &blen); + TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); if (code==TSDB_CONV_OK) { if (buf!=(const char*)paramValue) { bind->allocated = 1; @@ -2819,6 +2852,8 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, static void init_routine(void) { taos_init(); + D("tsLocale: [%s]", tsLocale); + D("tsCharset: [%s]", tsCharset); } static size_t do_field_display_size(TAOS_FIELD *field) { From 85595c9149601d00eb0eb0f96535543de470fa37 Mon Sep 17 00:00:00 2001 From: freemine Date: Wed, 4 Nov 2020 22:52:36 +0800 Subject: [PATCH 42/85] reenable jdbc --- src/CMakeLists.txt | 2 +- src/connector/odbc/src/todbc.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2ed56d4f81..f619edd221 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,5 +21,5 @@ ADD_SUBDIRECTORY(wal) ADD_SUBDIRECTORY(cq) ADD_SUBDIRECTORY(dnode) ADD_SUBDIRECTORY(connector/odbc) -# ADD_SUBDIRECTORY(connector/jdbc) +ADD_SUBDIRECTORY(connector/jdbc) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 17b243f87f..1eb670dabf 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -2852,8 +2852,6 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, static void init_routine(void) { taos_init(); - D("tsLocale: [%s]", tsLocale); - D("tsCharset: [%s]", tsCharset); } static size_t do_field_display_size(TAOS_FIELD *field) { From 77ea55f05eb6cd6ea8c4f7b2e3d47e1a8e1b3ba7 Mon Sep 17 00:00:00 2001 From: freemine Date: Thu, 5 Nov 2020 08:22:45 +0800 Subject: [PATCH 43/85] clang complains about {0} initialization --- src/connector/odbc/tests/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index c938bc9993..bdf1bd34f1 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -24,8 +24,8 @@ do { \ typedef struct db_column_s db_column_t; struct db_column_s { - char name[4096]; // seems enough SQLSMALLINT nameLength; + char name[4096]; // seems enough SQLSMALLINT dataType; SQLULEN columnSize; SQLSMALLINT decimalDigits; From 51c4b89aac5c1c1dea7182410b70e1c7b5be1c98 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 6 Nov 2020 12:42:51 +0800 Subject: [PATCH 44/85] before windows port --- src/connector/odbc/src/CMakeLists.txt | 2 +- src/connector/odbc/src/todbc.c | 37 +++++ src/connector/odbc/src/todbc.def | 3 + src/connector/odbc/tests/main.c | 199 ++++++++++++++++++-------- 4 files changed, 183 insertions(+), 58 deletions(-) diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt index 664ae36436..c5ed1a4bd7 100644 --- a/src/connector/odbc/src/CMakeLists.txt +++ b/src/connector/odbc/src/CMakeLists.txt @@ -15,7 +15,7 @@ IF (TD_LINUX_64) ADD_LIBRARY(todbc SHARED ${SRC} ${todbc_flex_scanner_src}) SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) - TARGET_LINK_LIBRARIES(todbc taos) + TARGET_LINK_LIBRARIES(todbc taos odbcinst) target_include_directories(todbc PUBLIC .) install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 1eb670dabf..cd3e0b290e 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -27,8 +27,19 @@ #include "todbc_util.h" #include "todbc_conv.h" +#include "os.h" + +#include #include +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + #define UTF8_ENC "UTF-8" #define UTF16_ENC "UCS-2LE" #define UNICODE_ENC "UCS-4LE" @@ -549,9 +560,20 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, const char *auth = NULL; do { + D("server: %s", serverName); + D("user: %s", userName); + D("auth: %s", auth); tsdb_conv(client_to_server, &buffer, (const char*)ServerName, (size_t)NameLength1, &serverName, NULL); tsdb_conv(client_to_server, &buffer, (const char*)UserName, (size_t)NameLength2, &userName, NULL); tsdb_conv(client_to_server, &buffer, (const char*)Authentication, (size_t)NameLength3, &auth, NULL); + D("server: %s", serverName); + D("user: %s", userName); + D("auth: %s", auth); + char haha[4096]; haha[0] = '\0'; + int n = SQLGetPrivateProfileString(serverName, "Server", "null", haha, sizeof(haha)-1, NULL); + D("n: %d", n); + D("haha: [%s]", haha); + if ((!serverName) || (!userName) || (!auth)) { SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, ""); break; @@ -2847,6 +2869,21 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, return r; } +BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes) +{ + return FALSE; +} + +BOOL INSTAPI ConfigTranslator(HWND hwndParent, DWORD *pvOption) +{ + return FALSE; +} + +BOOL INSTAPI ConfigDriver(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszArgs, + LPSTR lpszMsg, WORD cbMsgMax, WORD *pcbMsgOut) +{ + return FALSE; +} diff --git a/src/connector/odbc/src/todbc.def b/src/connector/odbc/src/todbc.def index 3d34eef86b..1e080f0198 100644 --- a/src/connector/odbc/src/todbc.def +++ b/src/connector/odbc/src/todbc.def @@ -25,4 +25,7 @@ SQLSetConnectAttr SQLDescribeCol SQLNumParams SQLSetStmtAttr +ConfigDSN +ConfigTranslator +ConfigDriver diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index bdf1bd34f1..417de00d55 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -86,9 +86,9 @@ static int open_connect(const char *dsn, const char *uid, const char *pwd, SQLHE CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); if (r!=SQL_SUCCESS) break; do { - r = SQLConnect(conn, (SQLCHAR*)dsn, (SQLSMALLINT)strlen(dsn), - (SQLCHAR*)uid, (SQLSMALLINT)strlen(uid), - (SQLCHAR*)pwd, (SQLSMALLINT)strlen(pwd)); + r = SQLConnect(conn, (SQLCHAR*)dsn, (SQLSMALLINT)(dsn ? strlen(dsn) : 0), + (SQLCHAR*)uid, (SQLSMALLINT)(uid ? strlen(uid) : 0), + (SQLCHAR*)pwd, (SQLSMALLINT)(pwd ? strlen(pwd) : 0)); CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); if (r==SQL_SUCCESS) { *pEnv = env; @@ -119,7 +119,7 @@ static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pCon SQLHDBC ConnectionHandle = conn; SQLHWND WindowHandle = NULL; SQLCHAR * InConnectionString = (SQLCHAR*)connstr; - SQLSMALLINT StringLength1 = (SQLSMALLINT)strlen(connstr); + SQLSMALLINT StringLength1 = (SQLSMALLINT)(connstr ? strlen(connstr) : 0); SQLCHAR * OutConnectionString = buf; SQLSMALLINT BufferLength = sizeof(buf); SQLSMALLINT * StringLength2Ptr = &blen; @@ -525,64 +525,149 @@ int test_sqls(const char *dsn, const char *uid, const char *pwd, const char *con } else { CHK_TEST(open_driver_connect(connstr, &env, &conn)); } - r = test_sqls_in_conn(env, conn, sqls); + if (sqls) { + r = test_sqls_in_conn(env, conn, sqls); + } SQLDisconnect(conn); SQLFreeConnect(conn); SQLFreeEnv(env); return r ? 1 : 0; } -int main(int argc, char *argv[]) { - if (argc==1) { - CHK_TEST(test_env()); - return 0; - } - - const char *dsn = (argc>1) ? argv[1] : NULL; - const char *uid = (argc>2) ? argv[2] : NULL; - const char *pwd = (argc>3) ? argv[3] : NULL; - const char *connstr = (argc>4) ? argv[4] : NULL; - const char *sqls = (argc>5) ? argv[5] : NULL; - - dsn = NULL; - uid = NULL; - pwd = NULL; - connstr = argv[1]; - sqls = argv[2]; - if (0) { - CHK_TEST(test_env()); - - CHK_TEST(test1(dsn, uid, pwd)); - - const char *statements[] = { - "drop database if exists m", - "create database m", - "use m", - "drop database m", - NULL - }; - CHK_TEST(test_statements(dsn, uid, pwd, statements)); - - if (connstr) - CHK_TEST(test_driver_connect(connstr)); - - if (connstr) { - SQLHENV env = {0}; - SQLHDBC conn = {0}; - CHK_TEST(open_driver_connect(connstr, &env, &conn)); - int r = tests(env, conn); - SQLDisconnect(conn); - SQLFreeConnect(conn); - SQLFreeEnv(env); - if (r) return 1; - } - } - - if ((dsn || connstr) && 1) { - CHK_TEST(test_sqls(dsn, uid, pwd, connstr, sqls)); - } - - D("Done!"); - return 0; +void usage(const char *arg0) { + fprintf(stdout, "%s usage:\n", arg0); + fprintf(stdout, "%s [--dsn ] [--uid ] [--pwd ] [--dcs ] [--sts ]\n", arg0); + fprintf(stdout, " --dsn : DSN\n"); + fprintf(stdout, " --uid : UID\n"); + fprintf(stdout, " --pwd : PWD\n"); + fprintf(stdout, " --dcs : driver connection string\n"); + fprintf(stdout, " --sts : file where statements store\n"); +} + +int main(int argc, char *argv[]) { + // if (argc==1) { + // CHK_TEST(test_env()); + // CHK_TEST(test1("TAOS_DSN", "root", "taoxsdata")); + // D("Done!"); + // return 0; + // } + + const char *dsn = NULL; + const char *uid = NULL; + const char *pwd = NULL; + const char *dcs = NULL; // driver connection string + const char *sts = NULL; // statements file + for (size_t i=1; i=argc) { + D(" expected but got nothing"); + return 1; + } + if (dcs) { + D("--dcs has already been specified"); + return 1; + } + dsn = argv[i]; + continue; + } + if (strcmp(arg, "--uid")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + uid = argv[i]; + continue; + } + if (strcmp(arg, "--pwd")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + pwd = argv[i]; + continue; + } + if (strcmp(arg, "--dcs")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + if (dsn || uid || pwd) { + D("either of --dsn/--uid/--pwd has already been specified"); + return 1; + } + dcs = argv[i]; + continue; + } + if (strcmp(arg, "--sts")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + sts = argv[i]; + continue; + } + } + CHK_TEST(test_sqls(dsn, uid, pwd, dcs, sts)); + D("Done!"); + return 0; + + if (0) { + const char *dsn = (argc>1) ? argv[1] : NULL; + const char *uid = (argc>2) ? argv[2] : NULL; + const char *pwd = (argc>3) ? argv[3] : NULL; + const char *connstr = (argc>4) ? argv[4] : NULL; + const char *sqls = (argc>5) ? argv[5] : NULL; + + dsn = NULL; + uid = NULL; + pwd = NULL; + connstr = argv[1]; + sqls = argv[2]; + if (0) { + CHK_TEST(test_env()); + + CHK_TEST(test1(dsn, uid, pwd)); + + const char *statements[] = { + "drop database if exists m", + "create database m", + "use m", + "drop database m", + NULL + }; + CHK_TEST(test_statements(dsn, uid, pwd, statements)); + + if (connstr) + CHK_TEST(test_driver_connect(connstr)); + + if (connstr) { + SQLHENV env = {0}; + SQLHDBC conn = {0}; + CHK_TEST(open_driver_connect(connstr, &env, &conn)); + int r = tests(env, conn); + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + if (r) return 1; + } + } + + if ((dsn || connstr) && 1) { + CHK_TEST(test_sqls(dsn, uid, pwd, connstr, sqls)); + } + + D("Done!"); + return 0; + } } From 12d629024a5bf5ee6e887d8acf739c28da99b6fd Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 6 Nov 2020 20:13:50 +0800 Subject: [PATCH 45/85] implement windows odbc setup api --- src/connector/odbc/src/CMakeLists.txt | 2 +- src/connector/odbc/src/todbc.c | 218 ++++++++++++++++++++++++- src/connector/odbc/src/todbc_flex.h | 2 +- src/connector/odbc/src/todbc_scanner.l | 12 +- 4 files changed, 218 insertions(+), 16 deletions(-) diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt index c5ed1a4bd7..2699e1bc90 100644 --- a/src/connector/odbc/src/CMakeLists.txt +++ b/src/connector/odbc/src/CMakeLists.txt @@ -37,7 +37,7 @@ IF (TD_WINDOWS_64) ${todbc_flex_scanner_src} ${CMAKE_CURRENT_BINARY_DIR}/todbc.rc todbc.def) - TARGET_LINK_LIBRARIES(todbc taos_static) + TARGET_LINK_LIBRARIES(todbc taos_static odbccp32 legacy_stdio_definitions) target_include_directories(todbc PUBLIC .) target_compile_definitions(todbc PRIVATE "todbc_EXPORT") diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index cd3e0b290e..e6579d6dab 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -569,10 +569,18 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, D("server: %s", serverName); D("user: %s", userName); D("auth: %s", auth); - char haha[4096]; haha[0] = '\0'; - int n = SQLGetPrivateProfileString(serverName, "Server", "null", haha, sizeof(haha)-1, NULL); + char sbuf[4096]; sbuf[0] = '\0'; + int n = SQLGetPrivateProfileString(serverName, "Server", "null", sbuf, sizeof(sbuf)-1, "Odbc.ini"); D("n: %d", n); - D("haha: [%s]", haha); + D("sbuf: [%s]", sbuf); + if (n==0) snprintf(sbuf, sizeof(sbuf), "localhost:6030"); + char *ip = NULL; + int port = 0; + char *p = strchr(sbuf, ':'); + if (p) { + ip = strndup(sbuf, (size_t)(p-sbuf)); + port = atoi(p+1); + } if ((!serverName) || (!userName) || (!auth)) { SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, ""); @@ -581,7 +589,7 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, // TODO: data-race // TODO: shall receive ip/port from odbc.ini - conn->taos = taos_connect("localhost", userName, auth, NULL, 0); + conn->taos = taos_connect(ip, userName, auth, NULL, port); if (!conn->taos) { SET_ERROR(conn, "08001", terrno, "failed to connect to data source"); break; @@ -2561,10 +2569,10 @@ static SQLRETURN doSQLDriverConnect( } char *ip = NULL; int port = 0; - if (val.host) { - char *p = strchr(val.host, ':'); + if (val.server) { + char *p = strchr(val.server, ':'); if (p) { - ip = strndup(val.host, (size_t)(p-val.host)); + ip = strndup(val.server, (size_t)(p-val.server)); port = atoi(p+1); } } @@ -2869,19 +2877,213 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, return r; } +#define LOG(fmt, ...) \ +do { \ + FILE *fout = fopen("C:\\test\\test.log", "ab+"); \ + if (!fout) break; \ + fprintf(fout, "%s" fmt "\n", "", ##__VA_ARGS__); \ + fprintf(stderr, "%s" fmt "\n", "", ##__VA_ARGS__); \ + fclose(fout); \ +} while (0) + +typedef struct kv_s kv_t; +struct kv_s { + char *line; + int val; +}; + +static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) +{ + BOOL r = TRUE; + + kv_t *kvs = NULL; + + kv_t dsn = {0}; + kv_t driver = {0}; + + char driver_dll[MAX_PATH + 1]; + HMODULE hm = NULL; + + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCSTR) &ConfigDSN, &hm) == 0) + { + int ret = GetLastError(); + LOG("GetModuleHandle failed, error = %d\n", ret); + return FALSE; + } + if (GetModuleFileName(hm, driver_dll, sizeof(driver_dll)) == 0) + { + int ret = GetLastError(); + LOG("GetModuleFileName failed, error = %d\n", ret); + return FALSE; + } + LOG("path: [%s]", driver_dll); + + const char *p = lpszAttributes; + int ikvs = 0; + while (p && *p) { + LOG("attr: [%s]", p); + char *line = strdup(p); + if (!line) { r = FALSE; break; } + char *v = strchr(line, '='); + if (v) *v = '\0'; + + if (stricmp(line, "DSN")==0) { + if (!v) { r = FALSE; break; } + if (dsn.line) { + free(dsn.line); + dsn.line = NULL; + dsn.val = 0; + } + dsn.line = line; + if (v) dsn.val = v - line + 1; + } else if (stricmp(line, "Driver")==0) { + if (!v) { r = FALSE; break; } + if (driver.line) { + free(driver.line); + driver.line = NULL; + driver.val = 0; + } + driver.line = line; + if (v) driver.val = v - line + 1; + } else { + kv_t *t = (kv_t*)realloc(kvs, (ikvs+1)*sizeof(*t)); + if (!t) { r = FALSE; free(line); break; } + t[ikvs].line = line; + if (v) t[ikvs].val = v - line + 1; + + kvs = t; + ++ikvs; + } + + p += strlen(p) + 1; + } + + if (!dsn.line || !driver.line) { + LOG("lack of either DSN or Driver"); + } else { + LOG("Driver[%s]", driver.line+driver.val); + if (r) r = SQLWritePrivateProfileString("ODBC Data Sources", dsn.line+dsn.val, driver.line+driver.val, "Odbc.ini"); + LOG("r:%d", r); + if (r) r = SQLWritePrivateProfileString(dsn.line+dsn.val, "Driver", driver_dll, "Odbc.ini"); + LOG("r:%d", r); + } + + for (int i=0; r && ikey, "HOST")==0) { \ - free(yyextra->host); \ - yyextra->host = strdup(yytext); \ + free(yyextra->server); \ + yyextra->server = strdup(yytext); \ break; \ } \ if (strcasecmp(yyextra->key, "SERVER_ENC")==0) { \ free(yyextra->svr_enc); \ - yyextra->svr_enc = strdup(yytext); \ + yyextra->svr_enc = strdup(yytext); \ break; \ } \ if (strcasecmp(yyextra->key, "CLIENT_ENC")==0) { \ free(yyextra->cli_enc); \ - yyextra->cli_enc = strdup(yytext); \ + yyextra->cli_enc = strdup(yytext); \ break; \ } \ } while (0) @@ -152,8 +152,8 @@ void conn_val_reset(conn_val_t *val) { if (val->db) { free(val->db); val->db = NULL; } - if (val->host) { - free(val->host); val->host = NULL; + if (val->server) { + free(val->server); val->server = NULL; } if (val->svr_enc) { free(val->svr_enc); val->svr_enc = NULL; From 6c0c319baf3b0bd5f956b21c1ecf4f29fbe41f58 Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 6 Nov 2020 23:14:18 +0800 Subject: [PATCH 46/85] implement ConfigDSN for windows' --- src/connector/odbc/src/todbc.c | 230 +++++++++++++++++++-------------- 1 file changed, 134 insertions(+), 96 deletions(-) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index e6579d6dab..6a52146239 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -2892,16 +2892,8 @@ struct kv_s { int val; }; -static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) +static BOOL get_driver_dll_path(char *buf, size_t len) { - BOOL r = TRUE; - - kv_t *kvs = NULL; - - kv_t dsn = {0}; - kv_t driver = {0}; - - char driver_dll[MAX_PATH + 1]; HMODULE hm = NULL; if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, @@ -2911,72 +2903,99 @@ static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) LOG("GetModuleHandle failed, error = %d\n", ret); return FALSE; } - if (GetModuleFileName(hm, driver_dll, sizeof(driver_dll)) == 0) + if (GetModuleFileName(hm, buf, len) == 0) { int ret = GetLastError(); LOG("GetModuleFileName failed, error = %d\n", ret); return FALSE; } - LOG("path: [%s]", driver_dll); + return TRUE; +} - const char *p = lpszAttributes; - int ikvs = 0; - while (p && *p) { - LOG("attr: [%s]", p); - char *line = strdup(p); - if (!line) { r = FALSE; break; } - char *v = strchr(line, '='); - if (v) *v = '\0'; +static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) +{ + BOOL r = TRUE; - if (stricmp(line, "DSN")==0) { + kv_t *kvs = NULL; + + kv_t dsn = {0}; + char *line = NULL; + + do { + char driver_dll[MAX_PATH + 1]; + r = get_driver_dll_path(driver_dll, sizeof(driver_dll)); + LOG("path: [%s]", driver_dll); + if (!r) break; + + dsn.line = strdup("DSN=TAOS_DEMO"); + if (!dsn.line) { r = FALSE; break; } + + const char *p = lpszAttributes; + int ikvs = 0; + while (p && *p) { + LOG("attr: [%s]", p); + line = strdup(p); + if (!line) { r = FALSE; break; } + char *v = strchr(line, '='); if (!v) { r = FALSE; break; } - if (dsn.line) { - free(dsn.line); - dsn.line = NULL; - dsn.val = 0; - } - dsn.line = line; - if (v) dsn.val = v - line + 1; - } else if (stricmp(line, "Driver")==0) { - if (!v) { r = FALSE; break; } - if (driver.line) { - free(driver.line); - driver.line = NULL; - driver.val = 0; - } - driver.line = line; - if (v) driver.val = v - line + 1; - } else { - kv_t *t = (kv_t*)realloc(kvs, (ikvs+1)*sizeof(*t)); - if (!t) { r = FALSE; free(line); break; } - t[ikvs].line = line; - if (v) t[ikvs].val = v - line + 1; - kvs = t; - ++ikvs; + if (strstr(line, "DSN")==line) { + if (dsn.line) { + free(dsn.line); + dsn.line = NULL; + dsn.val = 0; + } + dsn.line = line; + line = NULL; + } else { + kv_t *t = (kv_t*)realloc(kvs, (ikvs+1)*sizeof(*t)); + if (!t) { r = FALSE; free(line); break; } + t[ikvs].line = line; + *v = '\0'; + if (v) t[ikvs].val = v - line + 1; + line = NULL; + + kvs = t; + ++ikvs; + } + + p += strlen(p) + 1; } - p += strlen(p) + 1; - } + if (hwndParent) { + MessageBox(hwndParent, "Please use odbcconf to add DSN for TAOS ODBC Driver", "Warning!", MB_OK|MB_ICONEXCLAMATION); + } + if (!r) break; - if (!dsn.line || !driver.line) { - LOG("lack of either DSN or Driver"); - } else { - LOG("Driver[%s]", driver.line+driver.val); - if (r) r = SQLWritePrivateProfileString("ODBC Data Sources", dsn.line+dsn.val, driver.line+driver.val, "Odbc.ini"); - LOG("r:%d", r); - if (r) r = SQLWritePrivateProfileString(dsn.line+dsn.val, "Driver", driver_dll, "Odbc.ini"); - LOG("r:%d", r); - } + char *v = NULL; + v = strchr(dsn.line, '='); + if (!v) { r = FALSE; break; } + *v = '\0'; + dsn.val = v - dsn.line + 1; - for (int i=0; r && i Date: Sat, 7 Nov 2020 10:41:30 +0800 Subject: [PATCH 47/85] 1. setup dll functions (ConfigDSN ...) compiled and exported only on windows 2. add 'Server' key in Odbc.ini to allow connecting server other than localhost via DSN --- src/connector/odbc/src/install.sh | 5 +-- src/connector/odbc/src/todbc.c | 59 ++++++++++++++++--------------- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/connector/odbc/src/install.sh b/src/connector/odbc/src/install.sh index 6f45ce4357..02f31de70e 100755 --- a/src/connector/odbc/src/install.sh +++ b/src/connector/odbc/src/install.sh @@ -9,14 +9,15 @@ rm -f "${BLD_DIR}/template.dsn" cat > "${BLD_DIR}/template.ini" < "${BLD_DIR}/template.dsn" <taos = taos_connect(ip, userName, auth, NULL, port); + conn->taos = taos_connect(ip, uid, pwd, NULL, (uint16_t)port); if (!conn->taos) { - SET_ERROR(conn, "08001", terrno, "failed to connect to data source"); + SET_ERROR(conn, "08001", terrno, "failed to connect to data source for DSN[%s] @[%s:%d]", dsn, ip, port); break; } } while (0); - tsdb_conv_free(client_to_server, serverName, &buffer, (const char*)ServerName); - tsdb_conv_free(client_to_server, userName, &buffer, (const char*)UserName); - tsdb_conv_free(client_to_server, auth, &buffer, (const char*)Authentication); + tsdb_conv_free(client_to_server, dsn, &buffer, (const char*)ServerName); + tsdb_conv_free(client_to_server, uid, &buffer, (const char*)UserName); + tsdb_conv_free(client_to_server, pwd, &buffer, (const char*)Authentication); + tsdb_conv_free(client_to_server, svr, &buffer, (const char*)server); return conn->taos ? SQL_SUCCESS : SQL_ERROR; } @@ -2877,6 +2875,8 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, return r; } +#ifdef _MSC_VER + #define LOG(fmt, ...) \ do { \ FILE *fout = fopen("C:\\test\\test.log", "ab+"); \ @@ -3125,6 +3125,7 @@ BOOL INSTAPI ConfigDriver(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver, LPC return FALSE; } +#endif // _MSC_VER static void init_routine(void) { From 61e2195b55ec818d97ed69c241557b849baffe2a Mon Sep 17 00:00:00 2001 From: freemine Date: Sun, 8 Nov 2020 08:00:29 +0800 Subject: [PATCH 48/85] ConfigDSN windows port' --- src/connector/odbc/README.md | 10 ++++- src/connector/odbc/src/todbc.c | 54 +++++++++++--------------- src/connector/odbc/src/todbc_scanner.l | 2 +- 3 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/connector/odbc/README.md b/src/connector/odbc/README.md index 5a9706fd1f..e026884a07 100644 --- a/src/connector/odbc/README.md +++ b/src/connector/odbc/README.md @@ -30,6 +30,7 @@ SQLSetConnectAttr SQLDescribeCol SQLNumParams SQLSetStmtAttr +ConfigDSN ` - **internationalized, you can specify different charset/code page for easy going. eg.: insert `utf-8.zh_cn` characters into database located in linux machine, while query them out in `gb2312/gb18030/...` code page in your chinese windows machine, or vice-versa. and much fun, insert `gb2312/gb18030/...` characters into database located in linux box from @@ -61,6 +62,7 @@ rm -rf debug && cmake -B debug && cmake --build debug && cmake --install debug & - open your `Command Prompt` with Administrator's priviledge - remove previously installed TAOS ODBC driver: run `C:\TDengine\todbcinst -u -f -n TAOS` - install TAOS ODBC driver that was just built: run `C:\TDengine\todbcinst -i -n TAOS -p C:\TDengine\driver` +- add a new user dsn: run `odbcconf CONFIGDSN TAOS "DSN=TAOS_DSN|Server=:` # Test we highly suggest that you build both in linux(ubuntu) and windows(windows 10) platform, because currently TAOS only has it's server-side port on linux platform. @@ -72,11 +74,15 @@ taosd -c ./debug/test/cfg ``` ## create data in linux ``` -./debug/build/bin/tcodbc 'Driver=TAOS;UID=;PWD=;Host=:6030;server_enc=UTF-8' ./src/connector/odbc/tests/create_data.stmts +./debug/build/bin/tcodbc --dsn TAOS_DSN --uid --pwd --sts ./src/connector/odbc/tests/create_data.stmts +-- +./debug/build/bin/tcodbc --dcs 'Driver=TAOS;UID=;PWD=;Server=:;client_enc=UTF-8' ./src/connector/odbc/tests/create_data.stmts ``` ## query data in windows ``` -.\debug\build\bin\tcodbc "Driver=TAOS;UID=;PWD=;Host=:6030;server_enc=UTF-8" .\src\connector\odbc\tests\query_data.stmts +.\debug\build\bin\tcodbc --dsn TAOS_DSN --uid --pwd --sts .\src\connector\odbc\tests\query_data.stmts +-- +.\debug\build\bin\tcodbc --dcs "Driver=TAOS;UID=;PWD=;Server=:;client_enc=UTF-8" .\src\connector\odbc\tests\query_data.stmts ``` diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index efd4570d77..30c0de70f0 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -2877,22 +2877,25 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, #ifdef _MSC_VER -#define LOG(fmt, ...) \ -do { \ - FILE *fout = fopen("C:\\test\\test.log", "ab+"); \ - if (!fout) break; \ - fprintf(fout, "%s" fmt "\n", "", ##__VA_ARGS__); \ - fprintf(stderr, "%s" fmt "\n", "", ##__VA_ARGS__); \ - fclose(fout); \ +#define POST_INSTALLER_ERROR(hwndParent, code, fmt, ...) \ +do { \ + char buf[4096]; \ + snprintf(buf, sizeof(buf), "%s[%d]%s():" fmt "", \ + basename((char*)__FILE__), __LINE__, __func__, \ + ##__VA_ARGS__); \ + SQLPostInstallerError(code, buf); \ + if (hwndParent) { \ + MessageBox(hwndParent, buf, "Error", MB_OK|MB_ICONEXCLAMATION); \ + } \ } while (0) typedef struct kv_s kv_t; struct kv_s { - char *line; - int val; + char *line; + size_t val; }; -static BOOL get_driver_dll_path(char *buf, size_t len) +static BOOL get_driver_dll_path(HWND hwndParent, char *buf, size_t len) { HMODULE hm = NULL; @@ -2900,13 +2903,13 @@ static BOOL get_driver_dll_path(char *buf, size_t len) (LPCSTR) &ConfigDSN, &hm) == 0) { int ret = GetLastError(); - LOG("GetModuleHandle failed, error = %d\n", ret); + POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "GetModuleHandle failed, error = %d\n", ret); return FALSE; } - if (GetModuleFileName(hm, buf, len) == 0) + if (GetModuleFileName(hm, buf, (DWORD)len) == 0) { int ret = GetLastError(); - LOG("GetModuleFileName failed, error = %d\n", ret); + POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "GetModuleFileName failed, error = %d\n", ret); return FALSE; } return TRUE; @@ -2923,8 +2926,7 @@ static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) do { char driver_dll[MAX_PATH + 1]; - r = get_driver_dll_path(driver_dll, sizeof(driver_dll)); - LOG("path: [%s]", driver_dll); + r = get_driver_dll_path(hwndParent, driver_dll, sizeof(driver_dll)); if (!r) break; dsn.line = strdup("DSN=TAOS_DEMO"); @@ -2933,7 +2935,6 @@ static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) const char *p = lpszAttributes; int ikvs = 0; while (p && *p) { - LOG("attr: [%s]", p); line = strdup(p); if (!line) { r = FALSE; break; } char *v = strchr(line, '='); @@ -2974,23 +2975,17 @@ static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) dsn.val = v - dsn.line + 1; if ((!dsn.line)) { - if (!r) LOG("lack of either DSN or Driver"); + if (!r) POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "lack of either DSN or Driver"); } else { - LOG("DSN/Driver[%s/%s]", dsn.line+dsn.val, lpszDriver); if (r) r = SQLWritePrivateProfileString("ODBC Data Sources", dsn.line+dsn.val, lpszDriver, "Odbc.ini"); - LOG("r:%d", r); - LOG("DSN/Driver_dll[%s/%s]", dsn.line+dsn.val, driver_dll); if (r) r = SQLWritePrivateProfileString(dsn.line+dsn.val, "Driver", driver_dll, "Odbc.ini"); - LOG("r:%d", r); } for (int i=0; r && i Date: Tue, 17 Nov 2020 16:06:15 +0800 Subject: [PATCH 51/85] [TD-225] fix memory leaks. --- src/query/src/qFill.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/src/qFill.c b/src/query/src/qFill.c index 1764289219..ca1203cb17 100644 --- a/src/query/src/qFill.c +++ b/src/query/src/qFill.c @@ -332,7 +332,7 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, tFilePage** data, char** sr point1 = (SPoint){.key = *(TSKEY*)(prev), .val = prev + pCol->col.offset}; point2 = (SPoint){.key = ts, .val = srcData[i] + pFillInfo->index * bytes}; - point = (SPoint){.key = pFillInfo->start, .val = val1}; + point = (SPoint){.key = pFillInfo->currentKey, .val = val1}; taosGetLinearInterpolationVal(type, &point1, &point2, &point); } } else { From 80323814b7f959b9cf7d4a0b2f15f0fef9920527 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 17 Nov 2020 17:39:10 +0800 Subject: [PATCH 52/85] [TD-225] fix bugs. --- src/client/inc/tscSubquery.h | 3 +- src/client/src/tscLocalMerge.c | 4 +- src/client/src/tscServer.c | 18 ++- src/client/src/tscSql.c | 19 +++ src/client/src/tscSubquery.c | 35 ++++-- src/inc/taos.h | 3 +- tests/script/general/parser/join.sim | 4 +- .../script/general/parser/join_multivnode.sim | 11 +- tests/script/general/parser/testSuite.sim | 112 +++++++++--------- 9 files changed, 126 insertions(+), 83 deletions(-) diff --git a/src/client/inc/tscSubquery.h b/src/client/inc/tscSubquery.h index aa9bda23de..598ff94835 100644 --- a/src/client/inc/tscSubquery.h +++ b/src/client/inc/tscSubquery.h @@ -41,7 +41,8 @@ int32_t tscHandleInsertRetry(SSqlObj* pSql); void tscBuildResFromSubqueries(SSqlObj *pSql); TAOS_ROW doSetResultRowData(SSqlObj *pSql); -char *getArithemicInputSrc(void *param, const char *name, int32_t colId); +char *getArithmeticInputSrc(void *param, const char *name, int32_t colId); +void doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize); #ifdef __cplusplus } diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index b07c7ca66d..5cdcd6d8c1 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -30,8 +30,6 @@ typedef struct SCompareParam { int32_t groupOrderType; } SCompareParam; -static void doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize); - int32_t treeComparator(const void *pLeft, const void *pRight, void *param) { int32_t pLeftIdx = *(int32_t *)pLeft; int32_t pRightIdx = *(int32_t *)pRight; @@ -1637,7 +1635,7 @@ void doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t r // calculate the result from several other columns if (pSup->pArithExprInfo != NULL) { arithSup.pArithExpr = pSup->pArithExprInfo; - tExprTreeCalcTraverse(arithSup.pArithExpr->pExpr, (int32_t) pOutput->num, pbuf + pOutput->num*offset, &arithSup, TSDB_ORDER_ASC, getArithemicInputSrc); + tExprTreeCalcTraverse(arithSup.pArithExpr->pExpr, (int32_t) pOutput->num, pbuf + pOutput->num*offset, &arithSup, TSDB_ORDER_ASC, getArithmeticInputSrc); } else { SSqlExpr* pExpr = pSup->pSqlExpr; memcpy(pbuf + pOutput->num * offset, pExpr->offset * pOutput->num + pOutput->data, pExpr->resBytes * pOutput->num); diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index a367d14604..63c68e1209 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -2187,11 +2187,25 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) { return pRes->code; } - STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); - if (!UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo) || tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) || pCmd->command == TSDB_SQL_RETRIEVE) { + STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); + if (pCmd->command == TSDB_SQL_RETRIEVE) { + tscSetResRawPtr(pRes, pQueryInfo); + } else if ((UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_SUBQUERY)) { + tscSetResRawPtr(pRes, pQueryInfo); + } else if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_QUERY) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) { tscSetResRawPtr(pRes, pQueryInfo); } +// if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) { +// +// } +// +// if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY) || +// ((!UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo) || pCmd->command == TSDB_SQL_RETRIEVE) && +// !(TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_SUBQUERY)))) { +// tscSetResRawPtr(pRes, pQueryInfo); +// } + if (pSql->pSubscription != NULL) { int32_t numOfCols = pQueryInfo->fieldsInfo.numOfOutput; diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index bb02472e58..9e32892814 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -787,6 +787,25 @@ void taos_stop_query(TAOS_RES *res) { tscDebug("%p query is cancelled", res); } +bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) { + SSqlObj *pSql = (SSqlObj *)res; + if (pSql == NULL || pSql->signature != pSql) { + return true; + } + + SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0); + if (pQueryInfo == NULL) { + return true; + } + + SInternalField* pInfo = (SInternalField*)TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, col); + if (col < 0 || col >= tscNumOfFields(pQueryInfo) || row < 0 || row > pSql->res.numOfRows) { + return true; + } + + return isNull(pSql->res.urow[col] + row * pInfo->field.bytes, pInfo->field.type); +} + int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) { int len = 0; for (int i = 0; i < num_fields; ++i) { diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index a532a5ead7..52db86f0ad 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -2312,10 +2312,10 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) { return; } - int32_t totalSize = tscGetResRowLength(pQueryInfo->exprList); + int32_t rowSize = tscGetResRowLength(pQueryInfo->exprList); - assert(numOfRes * totalSize > 0); - char* tmp = realloc(pRes->pRsp, numOfRes * totalSize); + assert(numOfRes * rowSize > 0); + char* tmp = realloc(pRes->pRsp, numOfRes * rowSize + sizeof(tFilePage)); if (tmp == NULL) { pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; return; @@ -2323,9 +2323,12 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) { pRes->pRsp = tmp; } - pRes->data = pRes->pRsp; + tFilePage* pFilePage = (tFilePage*) pRes->pRsp; + pFilePage->num = numOfRes; + pRes->data = pFilePage->data; char* data = pRes->data; + int16_t bytes = 0; size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); @@ -2352,6 +2355,17 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) { pRes->numOfRows = numOfRes; pRes->numOfClauseTotal += numOfRes; + + int32_t finalRowSize = 0; + for(int32_t i = 0; i < tscNumOfFields(pQueryInfo); ++i) { + TAOS_FIELD* pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i); + finalRowSize += pField->bytes; + } + + doArithmeticCalculate(pQueryInfo, pFilePage, rowSize, finalRowSize); + + pRes->data = pFilePage->data; + tscSetResRawPtr(pRes, pQueryInfo); } void tscBuildResFromSubqueries(SSqlObj *pSql) { @@ -2364,13 +2378,12 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) { if (pRes->tsrow == NULL) { SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex); + pRes->numOfCols = (int16_t) tscSqlExprNumOfExprs(pQueryInfo); - size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); - pRes->numOfCols = (int16_t)numOfExprs; - - pRes->tsrow = calloc(numOfExprs, POINTER_BYTES); - pRes->buffer = calloc(numOfExprs, POINTER_BYTES); - pRes->length = calloc(numOfExprs, sizeof(int32_t)); + pRes->tsrow = calloc(pRes->numOfCols, POINTER_BYTES); + pRes->urow = calloc(pRes->numOfCols, POINTER_BYTES); + pRes->buffer = calloc(pRes->numOfCols, POINTER_BYTES); + pRes->length = calloc(pRes->numOfCols, sizeof(int32_t)); if (pRes->tsrow == NULL || pRes->buffer == NULL || pRes->length == NULL) { pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; @@ -2414,7 +2427,7 @@ static UNUSED_FUNC void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TA } } -char *getArithemicInputSrc(void *param, const char *name, int32_t colId) { +char *getArithmeticInputSrc(void *param, const char *name, int32_t colId) { SArithmeticSupport *pSupport = (SArithmeticSupport *) param; int32_t index = -1; diff --git a/src/inc/taos.h b/src/inc/taos.h index 2c6454ced1..e517d22b2b 100644 --- a/src/inc/taos.h +++ b/src/inc/taos.h @@ -109,13 +109,14 @@ DLL_EXPORT TAOS_RES *taos_query(TAOS *taos, const char *sql); DLL_EXPORT TAOS_ROW taos_fetch_row(TAOS_RES *res); DLL_EXPORT int taos_result_precision(TAOS_RES *res); // get the time precision of result DLL_EXPORT void taos_free_result(TAOS_RES *res); -DLL_EXPORT int taos_field_count(TAOS_RES *tres); +DLL_EXPORT int taos_field_count(TAOS_RES *res); DLL_EXPORT int taos_num_fields(TAOS_RES *res); DLL_EXPORT int taos_affected_rows(TAOS_RES *res); DLL_EXPORT TAOS_FIELD *taos_fetch_fields(TAOS_RES *res); DLL_EXPORT int taos_select_db(TAOS *taos, const char *db); DLL_EXPORT int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields); DLL_EXPORT void taos_stop_query(TAOS_RES *res); +DLL_EXPORT bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col); int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows); int taos_validate_sql(TAOS *taos, const char *sql); diff --git a/tests/script/general/parser/join.sim b/tests/script/general/parser/join.sim index 624c2e72c4..d6e4a6a5a7 100644 --- a/tests/script/general/parser/join.sim +++ b/tests/script/general/parser/join.sim @@ -360,9 +360,7 @@ endi sql select join_mt1.* from join_mt1 print $rows - -$val = 2000 -if $rows != $val then +if $rows != 2000 then return -1 endi diff --git a/tests/script/general/parser/join_multivnode.sim b/tests/script/general/parser/join_multivnode.sim index a5e71260b4..6bca0e75c4 100644 --- a/tests/script/general/parser/join_multivnode.sim +++ b/tests/script/general/parser/join_multivnode.sim @@ -136,9 +136,8 @@ sql select join_mt0.ts, join_mt1.t1, join_mt0.t1, join_mt1.tbname, join_mt0.tbna #1970-01-01 08:01:40.790 | 10 | 945.000000000 | 90 | true | true | 0 | sql_error select count(join_mt0.c1), sum(join_mt1.c2), first(join_mt0.c5), last(join_mt1.c7), first(join_mt1.c7) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts interval(10a) group by join_mt0.t1 order by join_mt0.ts desc limit 20 offset 19; - sql select count(join_mt0.c1), sum(join_mt0.c2)/count(*), avg(c2), first(join_mt0.c5), last(c7) from join_mt0 interval(10a) group by join_mt0.t1 order by join_mt0.ts desc; -if $rows != 100 then +if $rows != 300 then return -1 endi @@ -147,7 +146,7 @@ if $data00 != @70-01-01 08:01:40.990@ then return -1 endi -if $data01 != 30 then +if $data01 != 10 then return -1 endi @@ -168,7 +167,7 @@ if $data05 != 1 then return -1 endi -if $data06 != 2 then +if $data06 != 0 then return -1 endi @@ -177,7 +176,7 @@ if $data10 != @70-01-01 08:01:40.980@ then return -1 endi -if $data11 != 30 then +if $data11 != 10 then return -1 endi @@ -198,7 +197,7 @@ if $data15 != 1 then return -1 endi -if $data16 != 2 then +if $data16 != 0 then return -1 endi diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index d16cec9619..1374199548 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -1,59 +1,59 @@ -#sleep 1000 -#run general/parser/alter.sim -#sleep 1000 -#run general/parser/alter1.sim -#sleep 1000 -#run general/parser/alter_stable.sim -#sleep 1000 -#run general/parser/auto_create_tb.sim -#sleep 1000 -#run general/parser/auto_create_tb_drop_tb.sim -#sleep 1000 -#run general/parser/col_arithmetic_operation.sim -#sleep 1000 -#run general/parser/columnValue.sim -#sleep 1000 -#run general/parser/commit.sim -#sleep 1000 -#run general/parser/create_db.sim -#sleep 1000 -#run general/parser/create_mt.sim -#sleep 1000 -#run general/parser/create_tb.sim -#sleep 1000 -#run general/parser/dbtbnameValidate.sim -#sleep 1000 -#run general/parser/fill.sim -#sleep 1000 -#run general/parser/fill_stb.sim -#sleep 1000 -##run general/parser/fill_us.sim # -#sleep 1000 -#run general/parser/first_last.sim -#sleep 1000 -#run general/parser/import_commit1.sim -#sleep 1000 -#run general/parser/import_commit2.sim -#sleep 1000 -#run general/parser/import_commit3.sim -#sleep 1000 -##run general/parser/import_file.sim -#sleep 1000 -#run general/parser/insert_tb.sim -#sleep 1000 -#run general/parser/tags_dynamically_specifiy.sim -#sleep 1000 -#run general/parser/interp.sim -#sleep 1000 -#run general/parser/lastrow.sim -#sleep 1000 -#run general/parser/limit.sim -#sleep 1000 -#run general/parser/limit1.sim -#sleep 1000 -#run general/parser/limit1_tblocks100.sim -#sleep 1000 -#run general/parser/limit2.sim +sleep 1000 +run general/parser/alter.sim +sleep 1000 +run general/parser/alter1.sim +sleep 1000 +run general/parser/alter_stable.sim +sleep 1000 +run general/parser/auto_create_tb.sim +sleep 1000 +run general/parser/auto_create_tb_drop_tb.sim +sleep 1000 +run general/parser/col_arithmetic_operation.sim +sleep 1000 +run general/parser/columnValue.sim +sleep 1000 +run general/parser/commit.sim +sleep 1000 +run general/parser/create_db.sim +sleep 1000 +run general/parser/create_mt.sim +sleep 1000 +run general/parser/create_tb.sim +sleep 1000 +run general/parser/dbtbnameValidate.sim +sleep 1000 +run general/parser/fill.sim +sleep 1000 +run general/parser/fill_stb.sim +sleep 1000 +#run general/parser/fill_us.sim # +sleep 1000 +run general/parser/first_last.sim +sleep 1000 +run general/parser/import_commit1.sim +sleep 1000 +run general/parser/import_commit2.sim +sleep 1000 +run general/parser/import_commit3.sim +sleep 1000 +#run general/parser/import_file.sim +sleep 1000 +run general/parser/insert_tb.sim +sleep 1000 +run general/parser/tags_dynamically_specifiy.sim +sleep 1000 +run general/parser/interp.sim +sleep 1000 +run general/parser/lastrow.sim +sleep 1000 +run general/parser/limit.sim +sleep 1000 +run general/parser/limit1.sim +sleep 1000 +run general/parser/limit1_tblocks100.sim +sleep 1000 +run general/parser/limit2.sim sleep 1000 run general/parser/mixed_blocks.sim sleep 1000 From 6852339a0da74bee2037f959865fb8fde81dba07 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 17 Nov 2020 17:41:09 +0800 Subject: [PATCH 53/85] [TD-225] --- src/client/src/tscSql.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 9e32892814..261467ad29 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -559,6 +559,8 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) { return 0; } + tscResetForNextRetrieve(pRes); + // set the sql object owner tscSetSqlOwner(pSql); From 91dcb46d73b46970216d9d75a762654fb0171bd2 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 17 Nov 2020 17:45:11 +0800 Subject: [PATCH 54/85] [TD-225] fix memory leaks. --- src/inc/taos.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/inc/taos.h b/src/inc/taos.h index e517d22b2b..cd863587a6 100644 --- a/src/inc/taos.h +++ b/src/inc/taos.h @@ -17,6 +17,7 @@ #define TDENGINE_TAOS_H #include +#include #ifdef __cplusplus extern "C" { From 87ab74823dcf53532d1496a5041ab85df11dcf5e Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 18 Nov 2020 16:37:04 +0800 Subject: [PATCH 55/85] [TD-2070]: optimize the load data performance. --- .../jni/com_taosdata_jdbc_TSDBJNIConnector.h | 8 + src/client/src/TSDBJNIConnector.c | 250 ++++++++++-------- src/client/src/tscServer.c | 10 - .../com/taosdata/jdbc/TSDBJNIConnector.java | 5 + .../java/com/taosdata/jdbc/TSDBResultSet.java | 198 +++++++++----- .../taosdata/jdbc/TSDBResultSetRowData.java | 1 - .../java/com/taosdata/jdbc/TSDBStatement.java | 6 +- 7 files changed, 287 insertions(+), 191 deletions(-) diff --git a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h index eaea91d1bf..582bd6bac0 100644 --- a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h +++ b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h @@ -129,6 +129,14 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp (JNIEnv *, jobject, jlong, jlong, jobject); +/* + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: fetchBlockImp + * Signature: (JJLcom/taosdata/jdbc/TSDBResultSetBlockData;)I + */ +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp + (JNIEnv *, jobject, jlong, jlong, jobject); + /* * Class: com_taosdata_jdbc_TSDBJNIConnector * Method: closeConnectionImp diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index 4e2272eb05..a8829499a3 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -17,7 +17,6 @@ #include "taos.h" #include "tlog.h" #include "tscUtil.h" -#include "tsclient.h" #include "com_taosdata_jdbc_TSDBJNIConnector.h" @@ -57,6 +56,10 @@ jmethodID g_rowdataSetStringFp; jmethodID g_rowdataSetTimestampFp; jmethodID g_rowdataSetByteArrayFp; +jmethodID g_blockdataSetByteArrayFp; +jmethodID g_blockdataSetNumOfRowsFp; +jmethodID g_blockdataSetNumOfColsFp; + #define JNI_SUCCESS 0 #define JNI_TDENGINE_ERROR -1 #define JNI_CONNECTION_NULL -2 @@ -66,7 +69,7 @@ jmethodID g_rowdataSetByteArrayFp; #define JNI_FETCH_END -6 #define JNI_OUT_OF_MEMORY -7 -void jniGetGlobalMethod(JNIEnv *env) { +static void jniGetGlobalMethod(JNIEnv *env) { // make sure init function executed once switch (atomic_val_compare_exchange_32(&__init, 0, 1)) { case 0: @@ -114,10 +117,31 @@ void jniGetGlobalMethod(JNIEnv *env) { g_rowdataSetByteArrayFp = (*env)->GetMethodID(env, g_rowdataClass, "setByteArray", "(I[B)V"); (*env)->DeleteLocalRef(env, rowdataClass); + jclass blockdataClass = (*env)->FindClass(env, "com/taosdata/jdbc/TSDBResultSetBlockData"); + jclass g_blockdataClass = (*env)->NewGlobalRef(env, blockdataClass); + g_blockdataSetByteArrayFp = (*env)->GetMethodID(env, g_blockdataClass, "setByteArray", "(II[B)V"); + g_blockdataSetNumOfRowsFp = (*env)->GetMethodID(env, g_blockdataClass, "setNumOfRows", "(I)V"); + g_blockdataSetNumOfColsFp = (*env)->GetMethodID(env, g_blockdataClass, "setNumOfCols", "(I)V"); + (*env)->DeleteLocalRef(env, blockdataClass); + atomic_store_32(&__init, 2); jniDebug("native method register finished"); } +static int32_t check_for_params(jobject jobj, jlong conn, jlong res) { + if ((TAOS*) conn == NULL) { + jniError("jobj:%p, connection is closed", jobj); + return JNI_CONNECTION_NULL; + } + + if ((TAOS_RES *) res == NULL) { + jniError("jobj:%p, conn:%p, res is null", jobj, (TAOS*) conn); + return JNI_RESULT_SET_NULL; + } + + return JNI_SUCCESS; +} + JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp(JNIEnv *env, jobject jobj, jint jMode, jstring jPath, jboolean jAutoDump) { if (jPath != NULL) { @@ -192,39 +216,37 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEnv *env, jobject jobj, jstring jhost, jint jport, jstring jdbName, jstring juser, jstring jpass) { - jlong ret = 0; + jlong ret = 0; const char *host = NULL; - const char *dbname = NULL; const char *user = NULL; const char *pass = NULL; + const char *dbname = NULL; if (jhost != NULL) { host = (*env)->GetStringUTFChars(env, jhost, NULL); } + if (jdbName != NULL) { dbname = (*env)->GetStringUTFChars(env, jdbName, NULL); } + if (juser != NULL) { user = (*env)->GetStringUTFChars(env, juser, NULL); } + if (jpass != NULL) { pass = (*env)->GetStringUTFChars(env, jpass, NULL); } if (user == NULL) { - jniDebug("jobj:%p, user is null, use default user %s", jobj, TSDB_DEFAULT_USER); + jniDebug("jobj:%p, user not specified, use default user %s", jobj, TSDB_DEFAULT_USER); } + if (pass == NULL) { - jniDebug("jobj:%p, pass is null, use default password", jobj); + jniDebug("jobj:%p, pass not specified, use default password", jobj); } - /* - * set numOfThreadsPerCore = 0 - * means only one thread for client side scheduler - */ - tsNumOfThreadsPerCore = 0.0; - - ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport); + ret = (jlong) taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport); if (ret == 0) { jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret, (char *)host, (char *)user, (char *)dbname, (int32_t)jport); @@ -233,10 +255,21 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn (char *)host, (char *)user, (char *)dbname, (int32_t)jport); } - if (host != NULL) (*env)->ReleaseStringUTFChars(env, jhost, host); - if (dbname != NULL) (*env)->ReleaseStringUTFChars(env, jdbName, dbname); - if (user != NULL) (*env)->ReleaseStringUTFChars(env, juser, user); - if (pass != NULL) (*env)->ReleaseStringUTFChars(env, jpass, pass); + if (host != NULL) { + (*env)->ReleaseStringUTFChars(env, jhost, host); + } + + if (dbname != NULL) { + (*env)->ReleaseStringUTFChars(env, jdbName, dbname); + } + + if (user != NULL) { + (*env)->ReleaseStringUTFChars(env, juser, user); + } + + if (pass != NULL) { + (*env)->ReleaseStringUTFChars(env, jpass, pass); + } return ret; } @@ -245,64 +278,53 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp( jbyteArray jsql, jlong con) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { - jniError("jobj:%p, connection is already closed", jobj); + jniError("jobj:%p, connection already closed", jobj); return JNI_CONNECTION_NULL; } if (jsql == NULL) { - jniError("jobj:%p, conn:%p, sql is null", jobj, tscon); + jniError("jobj:%p, conn:%p, empty sql string", jobj, tscon); return JNI_SQL_NULL; } jsize len = (*env)->GetArrayLength(env, jsql); - char *dst = (char *)calloc(1, sizeof(char) * (len + 1)); - if (dst == NULL) { - jniError("jobj:%p, conn:%p, can not alloc memory", jobj, tscon); + char *str = (char *) calloc(1, sizeof(char) * (len + 1)); + if (str == NULL) { + jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon); return JNI_OUT_OF_MEMORY; } - (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)dst); + (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str); if ((*env)->ExceptionCheck(env)) { // todo handle error } - jniDebug("jobj:%p, conn:%p, sql:%s", jobj, tscon, dst); - - SSqlObj *pSql = taos_query(tscon, dst); + SSqlObj *pSql = taos_query(tscon, str); int32_t code = taos_errno(pSql); if (code != TSDB_CODE_SUCCESS) { jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, tscon, tstrerror(code), taos_errstr(pSql)); } else { - int32_t affectRows = 0; if (pSql->cmd.command == TSDB_SQL_INSERT) { - affectRows = taos_affected_rows(pSql); + int32_t affectRows = taos_affected_rows(pSql); jniDebug("jobj:%p, conn:%p, code:%s, affect rows:%d", jobj, tscon, tstrerror(code), affectRows); } else { jniDebug("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); } } - free(dst); - return (jlong)pSql; + free(str); + return (jlong) pSql; } JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) { - TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return (jint)TSDB_CODE_TSC_INVALID_CONNECTION; + int32_t code = check_for_params(jobj, con, tres); + if (code != JNI_SUCCESS) { + return code; } - if ((void *)tres == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; - } - - TAOS_RES *pSql = (TAOS_RES *)tres; - - return (jint)taos_errno(pSql); + return (jint)taos_errno((TAOS_RES*) tres); } JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(JNIEnv *env, jobject jobj, jlong tres) { @@ -313,23 +335,16 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(J JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) { TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; - } - - if ((void *)tres == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; + int32_t code = check_for_params(jobj, con, tres); + if (code != JNI_SUCCESS) { + return code; } SSqlObj *pSql = (TAOS_RES *)tres; - STscObj *pObj = pSql->pTscObj; - if (tscIsUpdateQuery(pSql)) { - jniDebug("jobj:%p, conn:%p, update query, no resultset, %p", jobj, pObj, (void *)tres); + jniDebug("jobj:%p, conn:%p, update query, no resultset, %p", jobj, tscon, (void *)tres); } else { - jniDebug("jobj:%p, conn:%p, get resultset, %p", jobj, pObj, (void *)tres); + jniDebug("jobj:%p, conn:%p, get resultset, %p", jobj, tscon, (void *)tres); } return tres; @@ -337,15 +352,9 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp( JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) { - TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; - } - - if ((void *)tres == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; + int32_t code = check_for_params(jobj, con, tres); + if (code != JNI_SUCCESS) { + return code; } SSqlObj *pSql = (TAOS_RES *)tres; @@ -355,37 +364,27 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp( JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *env, jobject jobj, jlong con, jlong res) { - TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; - } - - if ((void *)res == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; + int32_t code = check_for_params(jobj, con, res); + if (code != JNI_SUCCESS) { + return code; } taos_free_result((void *)res); - jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, tscon, (void *)res); + jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, (TAOS*) con, (void *)res); + return JNI_SUCCESS; } JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp(JNIEnv *env, jobject jobj, jlong con, jlong res) { TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; - } - - if ((void *)res == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; + int32_t code = check_for_params(jobj, con, res); + if (code != JNI_SUCCESS) { + return code; } jint ret = taos_affected_rows((SSqlObj *)res); - jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (void *)con, (void *)res, (int32_t)ret); + jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (TAOS *)con, (TAOS_RES *)res, (int32_t)ret); return ret; } @@ -394,27 +393,20 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData jlong con, jlong res, jobject arrayListObj) { TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; + int32_t code = check_for_params(jobj, con, res); + if (code != JNI_SUCCESS) { + return code; } - TAOS_RES *result = (TAOS_RES *)res; - if (result == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; - } - - TAOS_FIELD *fields = taos_fetch_fields(result); - int num_fields = taos_num_fields(result); - - // jobject arrayListObj = (*env)->NewObject(env, g_arrayListClass, g_arrayListConstructFp, ""); + TAOS_RES* tres = (TAOS_RES*) res; + TAOS_FIELD *fields = taos_fetch_fields(tres); + int32_t num_fields = taos_num_fields(tres); if (num_fields == 0) { - jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void *)res, num_fields); + jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, num_fields); return JNI_NUM_OF_FIELDS_0; } else { - jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void *)res, num_fields); + jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, num_fields); for (int i = 0; i < num_fields; ++i) { jobject metadataObj = (*env)->NewObject(env, g_metadataClass, g_metadataConstructFp); (*env)->SetIntField(env, metadataObj, g_metadataColtypeField, fields[i].type); @@ -457,21 +449,21 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn } TAOS_FIELD *fields = taos_fetch_fields(result); - int num_fields = taos_num_fields(result); - if (num_fields == 0) { - jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void*)res, num_fields); + int32_t numOfFields = taos_num_fields(result); + if (numOfFields == 0) { + jniError("jobj:%p, conn:%p, resultset:%p, fields size %d", jobj, tscon, (void*)res, numOfFields); return JNI_NUM_OF_FIELDS_0; } TAOS_ROW row = taos_fetch_row(result); if (row == NULL) { - int tserrno = taos_errno(result); - if (tserrno == 0) { - jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void*)res, num_fields); + int code = taos_errno(result); + if (code == TSDB_CODE_SUCCESS) { + jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void*)res, numOfFields); return JNI_FETCH_END; } else { - jniDebug("jobj:%p, conn:%p, interruptted query", jobj, tscon); + jniDebug("jobj:%p, conn:%p, interrupted query", jobj, tscon); return JNI_RESULT_SET_NULL; } } @@ -480,7 +472,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn char tmp[TSDB_MAX_BYTES_PER_ROW] = {0}; - for (int i = 0; i < num_fields; i++) { + for (int i = 0; i < numOfFields; i++) { if (row[i] == NULL) { continue; } @@ -534,6 +526,45 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn return JNI_SUCCESS; } +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNIEnv *env, jobject jobj, jlong con, + jlong res, jobject rowobj) { + TAOS * tscon = (TAOS *)con; + int32_t code = check_for_params(jobj, con, res); + if (code != JNI_SUCCESS) { + return code; + } + + TAOS_RES * tres = (TAOS_RES *)res; + TAOS_FIELD *fields = taos_fetch_fields(tres); + + int32_t numOfFields = taos_num_fields(tres); + assert(numOfFields > 0); + + TAOS_ROW row = NULL; + int32_t numOfRows = taos_fetch_block(tres, &row); + if (numOfRows == 0) { + code = taos_errno(tres); + if (code == JNI_SUCCESS) { + jniDebug("jobj:%p, conn:%p, resultset:%p, numOfFields:%d, no data to retrieve", jobj, tscon, (void *)res, + numOfFields); + return JNI_FETCH_END; + } else { + jniDebug("jobj:%p, conn:%p, query interrupted", jobj, tscon); + return JNI_RESULT_SET_NULL; + } + } + + (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfRowsFp, (jint)numOfRows); + (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfColsFp, (jint)numOfFields); + + for (int i = 0; i < numOfFields; i++) { + (*env)->CallVoidMethod(env, rowobj, g_blockdataSetByteArrayFp, i, fields[i].bytes * numOfRows, + jniFromNCharToByteArray(env, (char *)row[i], fields[i].bytes * numOfRows)); + } + + return JNI_SUCCESS; +} + JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionImp(JNIEnv *env, jobject jobj, jlong con) { TAOS *tscon = (TAOS *)con; @@ -589,7 +620,6 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_consumeImp(JNIEn jniGetGlobalMethod(env); TAOS_SUB *tsub = (TAOS_SUB *)sub; - TAOS_RES *res = taos_consume(tsub); if (res == NULL) { @@ -621,16 +651,16 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTab jsize len = (*env)->GetArrayLength(env, jsql); - char *dst = (char *)calloc(1, sizeof(char) * (len + 1)); - (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)dst); + char *str = (char *)calloc(1, sizeof(char) * (len + 1)); + (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str); if ((*env)->ExceptionCheck(env)) { // todo handle error } - int code = taos_validate_sql(tscon, dst); + int code = taos_validate_sql(tscon, str); jniDebug("jobj:%p, conn:%p, code is %d", jobj, tscon, code); - free(dst); + free(str); return code; } diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 63c68e1209..7465e25895 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -2196,16 +2196,6 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) { tscSetResRawPtr(pRes, pQueryInfo); } -// if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) { -// -// } -// -// if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY) || -// ((!UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo) || pCmd->command == TSDB_SQL_RETRIEVE) && -// !(TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_SUBQUERY)))) { -// tscSetResRawPtr(pRes, pQueryInfo); -// } - if (pSql->pSubscription != NULL) { int32_t numOfCols = pQueryInfo->fieldsInfo.numOfOutput; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java index edc160e323..f918463439 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java @@ -243,6 +243,11 @@ public class TSDBJNIConnector { private native int fetchRowImp(long connection, long resultSet, TSDBResultSetRowData rowData); + public int fetchBlock(long resultSet, TSDBResultSetBlockData blockData) { + return this.fetchBlockImp(this.taos, resultSet, blockData); + } + + private native int fetchBlockImp(long connection, long resultSet, TSDBResultSetBlockData blockData); /** * Execute close operation from C to release connection pointer by JNI * diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java index 961633b8ae..56c1719ddb 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java @@ -47,10 +47,14 @@ public class TSDBResultSet implements ResultSet { private List columnMetaDataList = new ArrayList(); private TSDBResultSetRowData rowData; + private TSDBResultSetBlockData blockData; + private boolean blockwiseFetch = false; private boolean lastWasNull = false; private final int COLUMN_INDEX_START_VALUE = 1; + private int rowIndex = 0; + public TSDBJNIConnector getJniConnector() { return jniConnector; } @@ -67,6 +71,10 @@ public class TSDBResultSet implements ResultSet { this.resultSetPointer = resultSetPointer; } + public void setBlockWiseFetch(boolean fetchBlock) { + this.blockwiseFetch = fetchBlock; + } + public List getColumnMetaDataList() { return columnMetaDataList; } @@ -107,6 +115,7 @@ public class TSDBResultSet implements ResultSet { } this.rowData = new TSDBResultSetRowData(this.columnMetaDataList.size()); + this.blockData = new TSDBResultSetBlockData(this.columnMetaDataList, this.columnMetaDataList.size()); } public T unwrap(Class iface) throws SQLException { @@ -118,21 +127,42 @@ public class TSDBResultSet implements ResultSet { } public boolean next() throws SQLException { - if (rowData != null) { - this.rowData.clear(); - } + if (this.blockwiseFetch) { + if (this.blockData.forward()) { + return true; + } + + int code = this.jniConnector.fetchBlock(this.resultSetPointer, this.blockData); + this.blockData.resetCursor(); + + if (code == TSDBConstants.JNI_CONNECTION_NULL) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); + } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL)); + } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0)); + } else if (code == TSDBConstants.JNI_FETCH_END) { + return false; + } - int code = this.jniConnector.fetchRow(this.resultSetPointer, this.rowData); - if (code == TSDBConstants.JNI_CONNECTION_NULL) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); - } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL)); - } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0)); - } else if (code == TSDBConstants.JNI_FETCH_END) { - return false; - } else { return true; + } else { + if (rowData != null) { + this.rowData.clear(); + } + + int code = this.jniConnector.fetchRow(this.resultSetPointer, this.rowData); + if (code == TSDBConstants.JNI_CONNECTION_NULL) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); + } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL)); + } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0)); + } else if (code == TSDBConstants.JNI_FETCH_END) { + return false; + } else { + return true; + } } } @@ -155,21 +185,30 @@ public class TSDBResultSet implements ResultSet { String res = null; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return this.blockData.getString(colIndex); } - return res; } public boolean getBoolean(int columnIndex) throws SQLException { boolean res = false; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + } else { + return this.blockData.getBoolean(colIndex); } + return res; } @@ -177,66 +216,91 @@ public class TSDBResultSet implements ResultSet { byte res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return (byte) this.blockData.getInt(colIndex); } - return res; } public short getShort(int columnIndex) throws SQLException { short res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return (short) this.blockData.getInt(colIndex); } - return res; } public int getInt(int columnIndex) throws SQLException { int res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return this.blockData.getInt(colIndex); } - return res; + } public long getLong(int columnIndex) throws SQLException { long res = 0l; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return this.blockData.getLong(colIndex); } - return res; } public float getFloat(int columnIndex) throws SQLException { float res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return (float) this.blockData.getDouble(colIndex); } - return res; } public double getDouble(int columnIndex) throws SQLException { double res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return this.blockData.getDouble(colIndex); } - return res; } /* @@ -249,25 +313,11 @@ public class TSDBResultSet implements ResultSet { */ @Deprecated public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - BigDecimal res = null; - int colIndex = getTrueColumnIndex(columnIndex); - - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); - } - return res; + return new BigDecimal(getLong(columnIndex)); } public byte[] getBytes(int columnIndex) throws SQLException { - byte[] res = null; - int colIndex = getTrueColumnIndex(columnIndex); - - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()).getBytes(); - } - return res; + return getString(columnIndex).getBytes(); } public Date getDate(int columnIndex) throws SQLException { @@ -284,11 +334,15 @@ public class TSDBResultSet implements ResultSet { Timestamp res = null; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getTimestamp(colIndex); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getTimestamp(colIndex); + } + return res; + } else { + return this.blockData.getTimestamp(columnIndex); } - return res; } public InputStream getAsciiStream(int columnIndex) throws SQLException { @@ -400,8 +454,12 @@ public class TSDBResultSet implements ResultSet { public Object getObject(int columnIndex) throws SQLException { int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - return this.rowData.get(colIndex); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + return this.rowData.get(colIndex); + } else { + return this.blockData.get(colIndex); + } } public Object getObject(String columnLabel) throws SQLException { @@ -433,8 +491,12 @@ public class TSDBResultSet implements ResultSet { public BigDecimal getBigDecimal(int columnIndex) throws SQLException { int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); + if (!this.blockwiseFetch) { + this.lastWasNull = this.rowData.wasNull(colIndex); + return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); + } else { + return new BigDecimal(this.blockData.getLong(colIndex)); + } } public BigDecimal getBigDecimal(String columnLabel) throws SQLException { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java index 8efcac9000..c57f19550d 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java @@ -218,5 +218,4 @@ public class TSDBResultSetRowData { public void setData(ArrayList data) { this.data = (ArrayList) data.clone(); } - } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java index 5c6b0545e9..15a978a2fd 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java @@ -81,7 +81,9 @@ public class TSDBStatement implements Statement { } if (!this.connecter.isUpdateQuery(pSql)) { - return new TSDBResultSet(this.connecter, resultSetPointer); + TSDBResultSet res = new TSDBResultSet(this.connecter, resultSetPointer); + res.setBlockWiseFetch(true); + return res; } else { this.connecter.freeResultSet(pSql); return null; @@ -136,7 +138,7 @@ public class TSDBStatement implements Statement { } public void setMaxRows(int max) throws SQLException { - // always set maxRows to zero, meaning unlimitted rows in a resultSet + // always set maxRows to zero, meaning unlimited rows in a resultSet } public void setEscapeProcessing(boolean enable) throws SQLException { From 75d4d18c74f549bd869ffe0d11c88a8606e42b16 Mon Sep 17 00:00:00 2001 From: zyyang Date: Wed, 18 Nov 2020 18:04:26 +0800 Subject: [PATCH 56/85] [TD-1590]: a test case for JDBC failover --- .../com/taosdata/jdbc/cases/FailOverTest.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java new file mode 100644 index 0000000000..aa0f3946fd --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java @@ -0,0 +1,53 @@ +package com.taosdata.jdbc.cases; + +import com.taosdata.jdbc.lib.TSDBCommon; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +public class FailOverTest { + + private Connection conn; + private static final String host = "localhost"; + + @Before + public void before() { + try { + Class.forName("com.taosdata.jdbc.TSDBDriver"); + conn = TSDBCommon.getConn(host); + TSDBCommon.createDatabase(conn, "failover_test"); + } catch (ClassNotFoundException | SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void testFailOver() { + try (Statement stmt = conn.createStatement()) { + ResultSet resultSet = stmt.executeQuery("select server_status()"); + while (true) { + resultSet.next(); + int status = resultSet.getInt("server_status()"); + System.out.println(">>>>>>>>> status : " + status); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + } + + @After + public void after() { + try { + if (conn != null) + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} From 88232e2e35a25ee9d9a61d71cbeb9294ae2c4d0b Mon Sep 17 00:00:00 2001 From: zyyang Date: Wed, 18 Nov 2020 18:05:50 +0800 Subject: [PATCH 57/85] change --- .../test/java/com/taosdata/jdbc/cases/FailOverTest.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java index aa0f3946fd..eab7ba3ea7 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java @@ -5,21 +5,18 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.sql.*; public class FailOverTest { private Connection conn; - private static final String host = "localhost"; @Before public void before() { try { Class.forName("com.taosdata.jdbc.TSDBDriver"); - conn = TSDBCommon.getConn(host); + final String url = "jdbc:TAOS://:/?user=root&password=taosdata"; + conn = DriverManager.getConnection(url); TSDBCommon.createDatabase(conn, "failover_test"); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); From 7be93e19085a0c42376d59ad86d2961d8741e15a Mon Sep 17 00:00:00 2001 From: zyyang Date: Wed, 18 Nov 2020 18:16:48 +0800 Subject: [PATCH 58/85] change --- .../com/taosdata/jdbc/cases/FailOverTest.java | 47 +++++++------------ 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java index eab7ba3ea7..dd223777d9 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java @@ -1,50 +1,37 @@ package com.taosdata.jdbc.cases; -import com.taosdata.jdbc.lib.TSDBCommon; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.sql.*; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.concurrent.TimeUnit; public class FailOverTest { - private Connection conn; - - @Before - public void before() { - try { - Class.forName("com.taosdata.jdbc.TSDBDriver"); - final String url = "jdbc:TAOS://:/?user=root&password=taosdata"; - conn = DriverManager.getConnection(url); - TSDBCommon.createDatabase(conn, "failover_test"); - } catch (ClassNotFoundException | SQLException e) { - e.printStackTrace(); - } - } + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); @Test - public void testFailOver() { - try (Statement stmt = conn.createStatement()) { - ResultSet resultSet = stmt.executeQuery("select server_status()"); - while (true) { + public void testFailOver() throws ClassNotFoundException { + Class.forName("com.taosdata.jdbc.TSDBDriver"); + final String url = "jdbc:TAOS://:/?user=root&password=taosdata"; + + while (true) { + try (Connection conn = DriverManager.getConnection(url)) { + Statement stmt = conn.createStatement(); + ResultSet resultSet = stmt.executeQuery("select server_status()"); resultSet.next(); int status = resultSet.getInt("server_status()"); - System.out.println(">>>>>>>>> status : " + status); + System.out.println(">>>>>>>>>" + sdf.format(new Date()) + " status : " + status); + stmt.close(); + TimeUnit.SECONDS.sleep(5); + } catch (SQLException | InterruptedException e) { + e.printStackTrace(); } - } catch (SQLException e) { - e.printStackTrace(); } } - @After - public void after() { - try { - if (conn != null) - conn.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } } From 07bd21e6c6f099729ac8dc39de832600a2f1e532 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 18 Nov 2020 18:33:22 +0800 Subject: [PATCH 59/85] [TD-2070] --- .../taosdata/jdbc/TSDBResultSetBlockData.java | 650 ++++++++++++++++++ 1 file changed, 650 insertions(+) create mode 100644 src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java new file mode 100644 index 0000000000..77e53f5731 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java @@ -0,0 +1,650 @@ +/*************************************************************************** + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + *****************************************************************************/ +package com.taosdata.jdbc; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.nio.ShortBuffer; +import java.sql.SQLDataException; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class TSDBResultSetBlockData { + private int numOfRows = 0; + private int numOfCols = 0; + + private int rowIndex = 0; + + private List columnMetaDataList; + private ArrayList colData = null; + + public TSDBResultSetBlockData(List colMeta, int numOfCols) { + this.columnMetaDataList = colMeta; + this.setNumOfCols(numOfCols); + } + + public TSDBResultSetBlockData() { + this.colData = new ArrayList(); + this.setNumOfCols(0); + } + + public void clear() { + if (this.colData != null) { + this.colData.clear(); + } + + if (this.numOfCols == 0) { + return; + } + + this.colData = new ArrayList(numOfCols); + this.colData.addAll(Collections.nCopies(this.numOfCols, null)); + } + + public boolean wasNull(int col) { + return colData.get(col) == null; + } + + public int getNumOfRows() { + return this.numOfRows; + } + + public void setNumOfRows(int numOfRows) { + this.numOfRows = numOfRows; + } + + public int getNumOfCols() { + return numOfCols; + } + + public void setNumOfCols(int numOfCols) { + this.numOfCols = numOfCols; + this.clear(); + } + + public void setColumnData(int col, byte val) { + this.colData.set(col, val); + } + + public boolean hasMore() { + return this.rowIndex < this.numOfRows; + } + + public boolean forward() { + this.rowIndex++; + return (this.rowIndex < this.numOfRows); + } + + public void resetCursor() { + this.rowIndex = 0; + } + + public void setBoolean(int col, boolean value) { + colData.set(col, value); + } + + public void setByteArray(int col, int length, byte[] value) { + try { + switch (this.columnMetaDataList.get(col).getColType()) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + ShortBuffer sb = buf.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); + this.colData.set(col, sb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_INT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + IntBuffer ib = buf.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); + this.colData.set(col, ib); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); + this.colData.set(col, lb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + FloatBuffer fb = buf.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer(); + this.colData.set(col, fb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + DoubleBuffer db = buf.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer(); + this.colData.set(col, db); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); + this.colData.set(col, lb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + class NullType { + public String toString() { + return new String("null"); + } + } + + /** + * The original type may not be a string type, but will be converted to by + * calling this method + * + * @param col column index + * @return + * @throws SQLException + */ + public String getString(int col) throws SQLException { + Object obj = get(col); + if (obj == null) { + return new NullType().toString(); + } + + return obj.toString(); + } + + private boolean isBooleanNull(byte val) { + return val == 0x2; + } + + private boolean isTinyIntNull(byte val) { + return val == 0x80; + } + + private boolean isSmallIntNull(short val) { + return val == 0x8000; + } + + private boolean isIntNull(int val) { + return val == 0x80000000L; + } + + private boolean isBigIntNull(long val) { + return val == 0x8000000000000000L; + } + + private boolean isFloatNull(float val) { + return Float.isNaN(val); + } + + private boolean isDoubleNull(double val) { + return Double.isNaN(val); + } + + private boolean isBinaryNull(byte[] val, int length) { + return val[0] == 0xFF && length == 1; + } + + private boolean isNcharNull(byte[] val, int length) { + return (val[0] & val[1] & val[2] & val[3]) == 0xFF && length == 4; + } + + public int getInt(int col) { + Object obj = get(col); + if (obj == null) { + return 0; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return ((Long) obj).intValue(); + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return ((Double) obj).intValue(); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + return Integer.parseInt((String) obj); + } + } + + return 0; + } + + public boolean getBoolean(int col) throws SQLException { + Object obj = get(col); + if (obj == null) { + return Boolean.FALSE; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return ((int) obj == 0L)? Boolean.FALSE:Boolean.TRUE; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (((Long) obj) == 0L)? Boolean.FALSE:Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return (((Double) obj) == 0)? Boolean.FALSE:Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + if ("TRUE".compareToIgnoreCase((String) obj) == 0) { + return Boolean.TRUE; + } else if ("FALSE".compareToIgnoreCase((String) obj) == 0) { + return Boolean.TRUE; + } else { + throw new SQLDataException(); + } + } + } + + return Boolean.FALSE; + } + + public long getLong(int col) throws SQLException { + int fieldSize = this.columnMetaDataList.get(col).getColSize(); + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + + switch (this.columnMetaDataList.get(col).getColType()) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + byte val = bb.get(this.rowIndex); + if (isBooleanNull(val)) { + return 0; + } + + return (val == 0x0) ? 0 : 1; + } + + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + byte val = bb.get(this.rowIndex); + if (isTinyIntNull(val)) { + return 0; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + ShortBuffer sb = (ShortBuffer) this.colData.get(col); + short val = sb.get(this.rowIndex); + if (isSmallIntNull(val)) { + return 0; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_INT: { + IntBuffer ib = (IntBuffer) this.colData.get(col); + int val = ib.get(this.rowIndex); + if (isIntNull(val)) { + return 0; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + LongBuffer lb = (LongBuffer) this.colData.get(col); + long val = lb.get(this.rowIndex); + if (isBigIntNull(val)) { + return 0; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + FloatBuffer fb = (FloatBuffer) this.colData.get(col); + float val = fb.get(this.rowIndex); + if (isFloatNull(val)) { + return 0; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); + double val = lb.get(this.rowIndex); + if (isDoubleNull(val)) { + return 0; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (isBinaryNull(dest, length)) { + return 0; + } + + return Long.parseLong(new String(dest)); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (isNcharNull(dest, length)) { + return 0; + } + + try { + return Long.parseLong(new String(dest, TaosGlobalConfig.getCharset())); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + + return 0; + } + + public Timestamp getTimestamp(int col) { + try { + return new Timestamp(getLong(col)); + } catch (SQLException e) { + e.printStackTrace(); + } + + return null; + } + + public double getDouble(int col) { + int fieldSize = this.columnMetaDataList.get(col).getColSize(); + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + + switch (this.columnMetaDataList.get(col).getColType()) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + byte val = bb.get(this.rowIndex); + if (isBooleanNull(val)) { + return 0; + } + + return (val == 0x0) ? 0 : 1; + } + + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + byte val = bb.get(this.rowIndex); + if (isTinyIntNull(val)) { + return 0; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + ShortBuffer sb = (ShortBuffer) this.colData.get(col); + short val = sb.get(this.rowIndex); + if (isSmallIntNull(val)) { + return 0; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_INT: { + IntBuffer ib = (IntBuffer) this.colData.get(col); + int val = ib.get(this.rowIndex); + if (isIntNull(val)) { + return 0; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + LongBuffer lb = (LongBuffer) this.colData.get(col); + long val = lb.get(this.rowIndex); + if (isBigIntNull(val)) { + return 0; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + FloatBuffer fb = (FloatBuffer) this.colData.get(col); + float val = fb.get(this.rowIndex); + if (isFloatNull(val)) { + return 0; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); + double val = lb.get(this.rowIndex); + if (isDoubleNull(val)) { + return 0; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (isBinaryNull(dest, length)) { + return 0; + } + + return Double.parseDouble(new String(dest)); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (isNcharNull(dest, length)) { + return 0; + } + + try { + return Double.parseDouble(new String(dest, TaosGlobalConfig.getCharset())); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + + return 0; + } + + public Object get(int col) { + int fieldSize = this.columnMetaDataList.get(col).getColSize(); + + switch (this.columnMetaDataList.get(col).getColType()) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + + byte val = bb.get(this.rowIndex); + if (isBooleanNull(val)) { + return null; + } + + return (val == 0x0) ? Boolean.FALSE : Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + + byte val = bb.get(this.rowIndex); + if (isTinyIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + ShortBuffer sb = (ShortBuffer) this.colData.get(col); + short val = sb.get(this.rowIndex); + if (isSmallIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_INT: { + IntBuffer ib = (IntBuffer) this.colData.get(col); + int val = ib.get(this.rowIndex); + if (isIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + LongBuffer lb = (LongBuffer) this.colData.get(col); + long val = lb.get(this.rowIndex); + if (isBigIntNull(val)) { + return null; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + FloatBuffer fb = (FloatBuffer) this.colData.get(col); + float val = fb.get(this.rowIndex); + if (isFloatNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); + double val = lb.get(this.rowIndex); + if (isDoubleNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (isBinaryNull(dest, length)) { + return null; + } + + return new String(dest); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (isNcharNull(dest, length)) { + return null; + } + + try { + return new String(dest, TaosGlobalConfig.getCharset()); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + + return 0; + } +} From 65e904b7a760ecb370a9db7cc03c3fc7c2e40cd4 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 18 Nov 2020 18:58:50 +0800 Subject: [PATCH 60/85] [TD-225] fix memory leaks. --- .../taosdata/jdbc/TSDBResultSetBlockData.java | 237 ++++-------------- 1 file changed, 46 insertions(+), 191 deletions(-) diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java index 77e53f5731..50ebe283e2 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java @@ -224,11 +224,19 @@ public class TSDBResultSetBlockData { } private boolean isBinaryNull(byte[] val, int length) { - return val[0] == 0xFF && length == 1; + if (length != 1) { + return false; + } + + return val[0] == 0xFF; } private boolean isNcharNull(byte[] val, int length) { - return (val[0] & val[1] & val[2] & val[3]) == 0xFF && length == 4; + if (length != 4) { + return false; + } + + return (val[0] & val[1] & val[2] & val[3]) == 0xFF ; } public int getInt(int col) { @@ -304,109 +312,32 @@ public class TSDBResultSetBlockData { } public long getLong(int col) throws SQLException { - int fieldSize = this.columnMetaDataList.get(col).getColSize(); - ByteBuffer bb = (ByteBuffer) this.colData.get(col); - - switch (this.columnMetaDataList.get(col).getColType()) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: { - byte val = bb.get(this.rowIndex); - if (isBooleanNull(val)) { - return 0; - } - - return (val == 0x0) ? 0 : 1; - } - - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { - byte val = bb.get(this.rowIndex); - if (isTinyIntNull(val)) { - return 0; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { - ShortBuffer sb = (ShortBuffer) this.colData.get(col); - short val = sb.get(this.rowIndex); - if (isSmallIntNull(val)) { - return 0; - } - - return val; + Object obj = get(col); + if (obj == null) { + return 0; } + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: case TSDBConstants.TSDB_DATA_TYPE_INT: { - IntBuffer ib = (IntBuffer) this.colData.get(col); - int val = ib.get(this.rowIndex); - if (isIntNull(val)) { - return 0; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { - LongBuffer lb = (LongBuffer) this.colData.get(col); - long val = lb.get(this.rowIndex); - if (isBigIntNull(val)) { - return 0; - } - - return (long) val; - } - - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { - FloatBuffer fb = (FloatBuffer) this.colData.get(col); - float val = fb.get(this.rowIndex); - if (isFloatNull(val)) { - return 0; - } - - return (long) val; + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (long) obj; } + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); - double val = lb.get(this.rowIndex); - if (isDoubleNull(val)) { - return 0; - } - - return (long) val; + return ((Double) obj).longValue(); } + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: case TSDBConstants.TSDB_DATA_TYPE_BINARY: { - bb.position(fieldSize * this.rowIndex); - - int length = bb.getShort(); - - byte[] dest = new byte[length]; - bb.get(dest, 0, length); - if (isBinaryNull(dest, length)) { - return 0; - } - - return Long.parseLong(new String(dest)); - } - - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { - bb.position(fieldSize * this.rowIndex); - - int length = bb.getShort(); - - byte[] dest = new byte[length]; - bb.get(dest, 0, length); - if (isNcharNull(dest, length)) { - return 0; - } - - try { - return Long.parseLong(new String(dest, TaosGlobalConfig.getCharset())); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + return Long.parseLong((String) obj); } } @@ -424,109 +355,32 @@ public class TSDBResultSetBlockData { } public double getDouble(int col) { - int fieldSize = this.columnMetaDataList.get(col).getColSize(); - ByteBuffer bb = (ByteBuffer) this.colData.get(col); - - switch (this.columnMetaDataList.get(col).getColType()) { - case TSDBConstants.TSDB_DATA_TYPE_BOOL: { - byte val = bb.get(this.rowIndex); - if (isBooleanNull(val)) { - return 0; - } - - return (val == 0x0) ? 0 : 1; - } - - case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { - byte val = bb.get(this.rowIndex); - if (isTinyIntNull(val)) { - return 0; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { - ShortBuffer sb = (ShortBuffer) this.colData.get(col); - short val = sb.get(this.rowIndex); - if (isSmallIntNull(val)) { - return 0; - } - - return val; + Object obj = get(col); + if (obj == null) { + return 0; } + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: case TSDBConstants.TSDB_DATA_TYPE_INT: { - IntBuffer ib = (IntBuffer) this.colData.get(col); - int val = ib.get(this.rowIndex); - if (isIntNull(val)) { - return 0; - } - - return val; - } - - case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: - case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { - LongBuffer lb = (LongBuffer) this.colData.get(col); - long val = lb.get(this.rowIndex); - if (isBigIntNull(val)) { - return 0; - } - - return (long) val; - } - - case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { - FloatBuffer fb = (FloatBuffer) this.colData.get(col); - float val = fb.get(this.rowIndex); - if (isFloatNull(val)) { - return 0; - } - - return (long) val; + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (long) obj; } + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); - double val = lb.get(this.rowIndex); - if (isDoubleNull(val)) { - return 0; - } - - return (long) val; + return (double) obj; } + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: case TSDBConstants.TSDB_DATA_TYPE_BINARY: { - bb.position(fieldSize * this.rowIndex); - - int length = bb.getShort(); - - byte[] dest = new byte[length]; - bb.get(dest, 0, length); - if (isBinaryNull(dest, length)) { - return 0; - } - - return Double.parseDouble(new String(dest)); - } - - case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { - bb.position(fieldSize * this.rowIndex); - - int length = bb.getShort(); - - byte[] dest = new byte[length]; - bb.get(dest, 0, length); - if (isNcharNull(dest, length)) { - return 0; - } - - try { - return Double.parseDouble(new String(dest, TaosGlobalConfig.getCharset())); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + return Double.parseDouble((String) obj); } } @@ -638,7 +492,8 @@ public class TSDBResultSetBlockData { } try { - return new String(dest, TaosGlobalConfig.getCharset()); + String ss = TaosGlobalConfig.getCharset(); + return new String(dest, ss); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } From fec8a784e9f939ec017a1a45a93da8aea84721e6 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Wed, 18 Nov 2020 11:20:02 +0000 Subject: [PATCH 61/85] [TD-2148]: SQL exceeding limits return unclear msg --- src/client/src/tscAsync.c | 4 ++-- src/client/src/tscSql.c | 8 +++----- src/inc/taoserror.h | 1 + src/query/src/qResultbuf.c | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c index e9e8214c4c..3ff8a68d8f 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -91,8 +91,8 @@ void taos_query_a(TAOS *taos, const char *sqlstr, __async_cb_func_t fp, void *pa int32_t sqlLen = (int32_t)strlen(sqlstr); if (sqlLen > tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); - terrno = TSDB_CODE_TSC_INVALID_SQL; - tscQueueAsyncError(fp, param, TSDB_CODE_TSC_INVALID_SQL); + terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT; + tscQueueAsyncError(fp, param, terrno); return; } diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index a7b859b294..8339b480da 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -321,7 +321,7 @@ TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen, TAOS_RES if (sqlLen > (uint32_t)tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); - terrno = TSDB_CODE_TSC_INVALID_SQL; + terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT; return NULL; } @@ -892,18 +892,16 @@ int taos_validate_sql(TAOS *taos, const char *sql) { int32_t sqlLen = (int32_t)strlen(sql); if (sqlLen > tsMaxSQLStringLen) { tscError("%p sql too long", pSql); - pRes->code = TSDB_CODE_TSC_INVALID_SQL; tfree(pSql); - return pRes->code; + return TSDB_CODE_TSC_EXCEED_SQL_LIMIT; } pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1); if (pSql->sqlstr == NULL) { - pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; tscError("%p failed to malloc sql string buffer", pSql); tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(pSql), pObj); tfree(pSql); - return pRes->code; + return TSDB_CODE_TSC_OUT_OF_MEMORY; } strtolower(pSql->sqlstr, sql); diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 1aa9095b30..117b9c4ad0 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -107,6 +107,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_CONN_KILLED, 0, 0x0215, "Connection TAOS_DEFINE_ERROR(TSDB_CODE_TSC_SQL_SYNTAX_ERROR, 0, 0x0216, "Syntax error in SQL") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DB_NOT_SELECTED, 0, 0x0217, "Database not specified or available") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TABLE_NAME, 0, 0x0218, "Table does not exist") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_EXCEED_SQL_LIMIT, 0, 0x0219, "SQL statement too long, check maxSQLLength config") // mnode TAOS_DEFINE_ERROR(TSDB_CODE_MND_MSG_NOT_PROCESSED, 0, 0x0300, "Message not processed") diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index 2645cff678..ec7be3b204 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -165,7 +165,7 @@ static char* doFlushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { static char* flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { int32_t ret = TSDB_CODE_SUCCESS; - assert(pResultBuf->numOfPages * pResultBuf->pageSize == pResultBuf->totalBufSize && pResultBuf->numOfPages >= pResultBuf->inMemPages); + assert((int64_t)pResultBuf->numOfPages * pResultBuf->pageSize == pResultBuf->totalBufSize && pResultBuf->numOfPages >= pResultBuf->inMemPages); if (pResultBuf->file == NULL) { if ((ret = createDiskFile(pResultBuf)) != TSDB_CODE_SUCCESS) { From 7b7fc4df86e736068a37f89bcb6ff539cb032fbc Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 18 Nov 2020 21:41:15 +0800 Subject: [PATCH 62/85] [TD-225] --- src/query/src/qExecutor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 869f57f117..984061e70f 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -5336,8 +5336,11 @@ static char *getArithemicInputSrc(void *param, const char *name, int32_t colId) } static void doSecondaryArithmeticProcess(SQuery* pQuery) { - SArithmeticSupport arithSup = {0}; + if (pQuery->numOfExpr2 == 0) { + return; + } + SArithmeticSupport arithSup = {0}; tFilePage **data = calloc(pQuery->numOfExpr2, POINTER_BYTES); for (int32_t i = 0; i < pQuery->numOfExpr2; ++i) { int32_t bytes = pQuery->pExpr2[i].bytes; From 4dff524a5bd9a68f66827f41dbb5ac70cee9c974 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 18 Nov 2020 23:49:44 +0800 Subject: [PATCH 63/85] [TD-225] refactor jdbc driver --- .../com/taosdata/jdbc/ColumnMetaData.java | 8 +- .../java/com/taosdata/jdbc/TSDBDriver.java | 29 ++-- .../java/com/taosdata/jdbc/TSDBResultSet.java | 40 ++--- .../taosdata/jdbc/TSDBResultSetBlockData.java | 140 +++++++++--------- .../java/com/taosdata/jdbc/TSDBStatement.java | 52 +++---- 5 files changed, 136 insertions(+), 133 deletions(-) diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java index 5c7f80c715..633fdcd5ab 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java @@ -16,10 +16,10 @@ package com.taosdata.jdbc; public class ColumnMetaData { - int colType = 0; - String colName = null; - int colSize = -1; - int colIndex = 0; + private int colType = 0; + private String colName = null; + private int colSize = -1; + private int colIndex = 0; public int getColSize() { return colSize; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java index 8fb607483b..4dc48c84b3 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java @@ -86,6 +86,11 @@ public class TSDBDriver extends AbstractTaosDriver { */ public static final String PROPERTY_KEY_CHARSET = "charset"; + /** + * fetch data from native function in a batch model + */ + public static final String PROPERTY_KEY_BATCH_LOAD = "batch"; + private TSDBDatabaseMetaData dbMetaData = null; static { @@ -172,26 +177,21 @@ public class TSDBDriver extends AbstractTaosDriver { url = url.substring(0, index); StringTokenizer queryParams = new StringTokenizer(paramString, "&"); while (queryParams.hasMoreElements()) { - String parameterValuePair = queryParams.nextToken(); - int indexOfEqual = parameterValuePair.indexOf("="); - String parameter = null; - String value = null; - if (indexOfEqual != -1) { - parameter = parameterValuePair.substring(0, indexOfEqual); - if (indexOfEqual + 1 < parameterValuePair.length()) { - value = parameterValuePair.substring(indexOfEqual + 1); - } - } - if ((value != null && value.length() > 0) && (parameter != null && parameter.length() > 0)) { - urlProps.setProperty(parameter, value); + String oneToken = queryParams.nextToken(); + String[] pair = oneToken.split("="); + + if ((pair[0] != null && pair[0].trim().length() > 0) && (pair[1] != null && pair[1].trim().length() > 0)) { + urlProps.setProperty(pair[0].trim(), pair[1].trim()); } } } + // parse Product Name String dbProductName = url.substring(0, beginningOfSlashes); dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1); dbProductName = dbProductName.substring(0, dbProductName.indexOf(":")); - // parse dbname + + // parse database name url = url.substring(beginningOfSlashes + 2); int indexOfSlash = url.indexOf("/"); if (indexOfSlash != -1) { @@ -200,6 +200,7 @@ public class TSDBDriver extends AbstractTaosDriver { } url = url.substring(0, indexOfSlash); } + // parse port int indexOfColon = url.indexOf(":"); if (indexOfColon != -1) { @@ -208,9 +209,11 @@ public class TSDBDriver extends AbstractTaosDriver { } url = url.substring(0, indexOfColon); } + if (url != null && url.length() > 0 && url.trim().length() > 0) { urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url); } + this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, urlProps.getProperty(TSDBDriver.PROPERTY_KEY_USER)); return urlProps; } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java index 56c1719ddb..84a3f58f46 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java @@ -49,7 +49,7 @@ public class TSDBResultSet implements ResultSet { private TSDBResultSetRowData rowData; private TSDBResultSetBlockData blockData; - private boolean blockwiseFetch = false; + private boolean batchFetch = false; private boolean lastWasNull = false; private final int COLUMN_INDEX_START_VALUE = 1; @@ -71,8 +71,12 @@ public class TSDBResultSet implements ResultSet { this.resultSetPointer = resultSetPointer; } - public void setBlockWiseFetch(boolean fetchBlock) { - this.blockwiseFetch = fetchBlock; + public void setBatchFetch(boolean batchFetch) { + this.batchFetch = batchFetch; + } + + public Boolean getBatchFetch() { + return this.batchFetch; } public List getColumnMetaDataList() { @@ -102,8 +106,8 @@ public class TSDBResultSet implements ResultSet { public TSDBResultSet() { } - public TSDBResultSet(TSDBJNIConnector connecter, long resultSetPointer) throws SQLException { - this.jniConnector = connecter; + public TSDBResultSet(TSDBJNIConnector connector, long resultSetPointer) throws SQLException { + this.jniConnector = connector; this.resultSetPointer = resultSetPointer; int code = this.jniConnector.getSchemaMetaData(this.resultSetPointer, this.columnMetaDataList); if (code == TSDBConstants.JNI_CONNECTION_NULL) { @@ -127,13 +131,13 @@ public class TSDBResultSet implements ResultSet { } public boolean next() throws SQLException { - if (this.blockwiseFetch) { + if (this.getBatchFetch()) { if (this.blockData.forward()) { return true; } int code = this.jniConnector.fetchBlock(this.resultSetPointer, this.blockData); - this.blockData.resetCursor(); + this.blockData.reset(); if (code == TSDBConstants.JNI_CONNECTION_NULL) { throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); @@ -185,7 +189,7 @@ public class TSDBResultSet implements ResultSet { String res = null; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()); @@ -200,7 +204,7 @@ public class TSDBResultSet implements ResultSet { boolean res = false; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType()); @@ -216,7 +220,7 @@ public class TSDBResultSet implements ResultSet { byte res = 0; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); @@ -231,7 +235,7 @@ public class TSDBResultSet implements ResultSet { short res = 0; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); @@ -246,7 +250,7 @@ public class TSDBResultSet implements ResultSet { int res = 0; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); @@ -262,7 +266,7 @@ public class TSDBResultSet implements ResultSet { long res = 0l; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()); @@ -277,7 +281,7 @@ public class TSDBResultSet implements ResultSet { float res = 0; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType()); @@ -292,7 +296,7 @@ public class TSDBResultSet implements ResultSet { double res = 0; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType()); @@ -334,7 +338,7 @@ public class TSDBResultSet implements ResultSet { Timestamp res = null; int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); if (!lastWasNull) { res = this.rowData.getTimestamp(colIndex); @@ -454,7 +458,7 @@ public class TSDBResultSet implements ResultSet { public Object getObject(int columnIndex) throws SQLException { int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); return this.rowData.get(colIndex); } else { @@ -491,7 +495,7 @@ public class TSDBResultSet implements ResultSet { public BigDecimal getBigDecimal(int columnIndex) throws SQLException { int colIndex = getTrueColumnIndex(columnIndex); - if (!this.blockwiseFetch) { + if (!this.getBatchFetch()) { this.lastWasNull = this.rowData.wasNull(colIndex); return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); } else { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java index 50ebe283e2..7373890428 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java @@ -56,13 +56,6 @@ public class TSDBResultSetBlockData { if (this.numOfCols == 0) { return; } - - this.colData = new ArrayList(numOfCols); - this.colData.addAll(Collections.nCopies(this.numOfCols, null)); - } - - public boolean wasNull(int col) { - return colData.get(col) == null; } public int getNumOfRows() { @@ -82,20 +75,19 @@ public class TSDBResultSetBlockData { this.clear(); } - public void setColumnData(int col, byte val) { - this.colData.set(col, val); - } - public boolean hasMore() { return this.rowIndex < this.numOfRows; } public boolean forward() { - this.rowIndex++; - return (this.rowIndex < this.numOfRows); + if (this.rowIndex > this.numOfRows) { + return false; + } + + return ((++this.rowIndex) < this.numOfRows); } - public void resetCursor() { + public void reset() { this.rowIndex = 0; } @@ -172,10 +164,58 @@ public class TSDBResultSetBlockData { } } - class NullType { + private static class NullType { + private static final byte NULL_BOOL_VAL = 0x2; + private static final String NULL_STR = "null"; + public String toString() { - return new String("null"); + return NullType.NULL_STR; } + + public static boolean isBooleanNull(byte val) { + return val == NullType.NULL_BOOL_VAL; + } + + private static boolean isTinyIntNull(byte val) { + return val == Byte.MIN_VALUE; + } + + private static boolean isSmallIntNull(short val) { + return val == Short.MIN_VALUE; + } + + private static boolean isIntNull(int val) { + return val == Integer.MIN_VALUE; + } + + private static boolean isBigIntNull(long val) { + return val == Long.MIN_VALUE; + } + + private static boolean isFloatNull(float val) { + return Float.isNaN(val); + } + + private static boolean isDoubleNull(double val) { + return Double.isNaN(val); + } + + private static boolean isBinaryNull(byte[] val, int length) { + if (length != Byte.BYTES) { + return false; + } + + return val[0] == 0xFF; + } + + private static boolean isNcharNull(byte[] val, int length) { + if (length != Integer.BYTES) { + return false; + } + + return (val[0] & val[1] & val[2] & val[3]) == 0xFF; + } + } /** @@ -195,50 +235,6 @@ public class TSDBResultSetBlockData { return obj.toString(); } - private boolean isBooleanNull(byte val) { - return val == 0x2; - } - - private boolean isTinyIntNull(byte val) { - return val == 0x80; - } - - private boolean isSmallIntNull(short val) { - return val == 0x8000; - } - - private boolean isIntNull(int val) { - return val == 0x80000000L; - } - - private boolean isBigIntNull(long val) { - return val == 0x8000000000000000L; - } - - private boolean isFloatNull(float val) { - return Float.isNaN(val); - } - - private boolean isDoubleNull(double val) { - return Double.isNaN(val); - } - - private boolean isBinaryNull(byte[] val, int length) { - if (length != 1) { - return false; - } - - return val[0] == 0xFF; - } - - private boolean isNcharNull(byte[] val, int length) { - if (length != 4) { - return false; - } - - return (val[0] & val[1] & val[2] & val[3]) == 0xFF ; - } - public int getInt(int col) { Object obj = get(col); if (obj == null) { @@ -284,16 +280,16 @@ public class TSDBResultSetBlockData { case TSDBConstants.TSDB_DATA_TYPE_TINYINT: case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: case TSDBConstants.TSDB_DATA_TYPE_INT: { - return ((int) obj == 0L)? Boolean.FALSE:Boolean.TRUE; + return ((int) obj == 0L) ? Boolean.FALSE : Boolean.TRUE; } case TSDBConstants.TSDB_DATA_TYPE_BIGINT: case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { - return (((Long) obj) == 0L)? Boolean.FALSE:Boolean.TRUE; + return (((Long) obj) == 0L) ? Boolean.FALSE : Boolean.TRUE; } case TSDBConstants.TSDB_DATA_TYPE_FLOAT: case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { - return (((Double) obj) == 0)? Boolean.FALSE:Boolean.TRUE; + return (((Double) obj) == 0) ? Boolean.FALSE : Boolean.TRUE; } case TSDBConstants.TSDB_DATA_TYPE_NCHAR: @@ -395,7 +391,7 @@ public class TSDBResultSetBlockData { ByteBuffer bb = (ByteBuffer) this.colData.get(col); byte val = bb.get(this.rowIndex); - if (isBooleanNull(val)) { + if (NullType.isBooleanNull(val)) { return null; } @@ -406,7 +402,7 @@ public class TSDBResultSetBlockData { ByteBuffer bb = (ByteBuffer) this.colData.get(col); byte val = bb.get(this.rowIndex); - if (isTinyIntNull(val)) { + if (NullType.isTinyIntNull(val)) { return null; } @@ -416,7 +412,7 @@ public class TSDBResultSetBlockData { case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { ShortBuffer sb = (ShortBuffer) this.colData.get(col); short val = sb.get(this.rowIndex); - if (isSmallIntNull(val)) { + if (NullType.isSmallIntNull(val)) { return null; } @@ -426,7 +422,7 @@ public class TSDBResultSetBlockData { case TSDBConstants.TSDB_DATA_TYPE_INT: { IntBuffer ib = (IntBuffer) this.colData.get(col); int val = ib.get(this.rowIndex); - if (isIntNull(val)) { + if (NullType.isIntNull(val)) { return null; } @@ -437,7 +433,7 @@ public class TSDBResultSetBlockData { case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { LongBuffer lb = (LongBuffer) this.colData.get(col); long val = lb.get(this.rowIndex); - if (isBigIntNull(val)) { + if (NullType.isBigIntNull(val)) { return null; } @@ -447,7 +443,7 @@ public class TSDBResultSetBlockData { case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { FloatBuffer fb = (FloatBuffer) this.colData.get(col); float val = fb.get(this.rowIndex); - if (isFloatNull(val)) { + if (NullType.isFloatNull(val)) { return null; } @@ -457,7 +453,7 @@ public class TSDBResultSetBlockData { case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); double val = lb.get(this.rowIndex); - if (isDoubleNull(val)) { + if (NullType.isDoubleNull(val)) { return null; } @@ -472,7 +468,7 @@ public class TSDBResultSetBlockData { byte[] dest = new byte[length]; bb.get(dest, 0, length); - if (isBinaryNull(dest, length)) { + if (NullType.isBinaryNull(dest, length)) { return null; } @@ -487,7 +483,7 @@ public class TSDBResultSetBlockData { byte[] dest = new byte[length]; bb.get(dest, 0, length); - if (isNcharNull(dest, length)) { + if (NullType.isNcharNull(dest, length)) { return null; } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java index 15a978a2fd..cdd88b825e 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java @@ -19,7 +19,7 @@ import java.util.ArrayList; import java.util.List; public class TSDBStatement implements Statement { - private TSDBJNIConnector connecter = null; + private TSDBJNIConnector connector = null; /** * To store batched commands @@ -45,9 +45,9 @@ public class TSDBStatement implements Statement { this.connection = connection; } - TSDBStatement(TSDBConnection connection, TSDBJNIConnector connecter) { + TSDBStatement(TSDBConnection connection, TSDBJNIConnector connector) { this.connection = connection; - this.connecter = connecter; + this.connector = connector; this.isClosed = false; } @@ -65,27 +65,27 @@ public class TSDBStatement implements Statement { } // TODO make sure it is not a update query - pSql = this.connecter.executeQuery(sql); + pSql = this.connector.executeQuery(sql); - long resultSetPointer = this.connecter.getResultSet(); + long resultSetPointer = this.connector.getResultSet(); if (resultSetPointer == TSDBConstants.JNI_CONNECTION_NULL) { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); } // create/insert/update/delete/alter if (resultSetPointer == TSDBConstants.JNI_NULL_POINTER) { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); return null; } - if (!this.connecter.isUpdateQuery(pSql)) { - TSDBResultSet res = new TSDBResultSet(this.connecter, resultSetPointer); - res.setBlockWiseFetch(true); + if (!this.connector.isUpdateQuery(pSql)) { + TSDBResultSet res = new TSDBResultSet(this.connector, resultSetPointer); + res.setBatchFetch(this.connection.getBatchFetch()); return res; } else { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); return null; } @@ -97,28 +97,28 @@ public class TSDBStatement implements Statement { } // TODO check if current query is update query - pSql = this.connecter.executeQuery(sql); - long resultSetPointer = this.connecter.getResultSet(); + pSql = this.connector.executeQuery(sql); + long resultSetPointer = this.connector.getResultSet(); if (resultSetPointer == TSDBConstants.JNI_CONNECTION_NULL) { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); } - this.affectedRows = this.connecter.getAffectedRows(pSql); - this.connecter.freeResultSet(pSql); + this.affectedRows = this.connector.getAffectedRows(pSql); + this.connector.freeResultSet(pSql); return this.affectedRows; } public String getErrorMsg(long pSql) { - return this.connecter.getErrMsg(pSql); + return this.connector.getErrMsg(pSql); } public void close() throws SQLException { if (!isClosed) { - if (!this.connecter.isResultsetClosed()) { - this.connecter.freeResultSet(); + if (!this.connector.isResultsetClosed()) { + this.connector.freeResultSet(); } isClosed = true; } @@ -174,15 +174,15 @@ public class TSDBStatement implements Statement { throw new SQLException("Invalid method call on a closed statement."); } boolean res = true; - pSql = this.connecter.executeQuery(sql); - long resultSetPointer = this.connecter.getResultSet(); + pSql = this.connector.executeQuery(sql); + long resultSetPointer = this.connector.getResultSet(); if (resultSetPointer == TSDBConstants.JNI_CONNECTION_NULL) { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); } else if (resultSetPointer == TSDBConstants.JNI_NULL_POINTER) { // no result set is retrieved - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); res = false; } @@ -193,10 +193,10 @@ public class TSDBStatement implements Statement { if (isClosed) { throw new SQLException("Invalid method call on a closed statement."); } - long resultSetPointer = connecter.getResultSet(); + long resultSetPointer = connector.getResultSet(); TSDBResultSet resSet = null; if (resultSetPointer != TSDBConstants.JNI_NULL_POINTER) { - resSet = new TSDBResultSet(connecter, resultSetPointer); + resSet = new TSDBResultSet(connector, resultSetPointer); } return resSet; } @@ -269,7 +269,7 @@ public class TSDBStatement implements Statement { } public Connection getConnection() throws SQLException { - if (this.connecter != null) + if (this.connector != null) return this.connection; throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG); } From 835e9da1f86b076c7e01ecf304dedd459dcf848a Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 18 Nov 2020 23:58:12 +0800 Subject: [PATCH 64/85] [TD-225] refactor jdbc driver --- .../com/taosdata/jdbc/TSDBConnection.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java index f93412ffec..94abe39655 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java @@ -14,7 +14,6 @@ *****************************************************************************/ package com.taosdata.jdbc; -import java.io.*; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; @@ -35,11 +34,10 @@ import java.util.*; import java.util.concurrent.Executor; public class TSDBConnection implements Connection { + protected Properties props = null; private TSDBJNIConnector connector = null; - protected Properties props = null; - private String catalog = null; private TSDBDatabaseMetaData dbMetaData = null; @@ -47,15 +45,21 @@ public class TSDBConnection implements Connection { private Properties clientInfoProps = new Properties(); private int timeoutMilliseconds = 0; - - private String tsCharSet = ""; + + private boolean batchFetch = false; public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException { this.dbMetaData = meta; connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST), Integer.parseInt(info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "0")), - info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME), info.getProperty(TSDBDriver.PROPERTY_KEY_USER), + info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME), + info.getProperty(TSDBDriver.PROPERTY_KEY_USER), info.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD)); + + String batchLoad = info.getProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD); + if (batchLoad != null) { + this.batchFetch = Boolean.parseBoolean(batchLoad); + } } private void connect(String host, int port, String dbName, String user, String password) throws SQLException { @@ -223,6 +227,14 @@ public class TSDBConnection implements Connection { return this.prepareStatement(sql); } + + public Boolean getBatchFetch() { + return this.batchFetch; + } + + public void setBatchFetch(Boolean batchFetch) { + this.batchFetch = batchFetch; + } public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG); From 15d1a1ba9a7e451a69862747c59d53b59670d4d8 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 00:00:56 +0800 Subject: [PATCH 65/85] [TD-225] refactor --- src/client/inc/tscSubquery.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/inc/tscSubquery.h b/src/client/inc/tscSubquery.h index 598ff94835..f7832c9818 100644 --- a/src/client/inc/tscSubquery.h +++ b/src/client/inc/tscSubquery.h @@ -42,7 +42,6 @@ void tscBuildResFromSubqueries(SSqlObj *pSql); TAOS_ROW doSetResultRowData(SSqlObj *pSql); char *getArithmeticInputSrc(void *param, const char *name, int32_t colId); -void doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize); #ifdef __cplusplus } From 38459ed3546624bfcce7ca010da558bd48089b6a Mon Sep 17 00:00:00 2001 From: zyyang Date: Thu, 19 Nov 2020 09:46:30 +0800 Subject: [PATCH 66/85] change --- .../src/test/java/com/taosdata/jdbc/BaseTest.java | 12 ++++++------ .../java/com/taosdata/jdbc/cases/FailOverTest.java | 2 -- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/BaseTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/BaseTest.java index b793a47c99..ce3735c128 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/BaseTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/BaseTest.java @@ -5,24 +5,24 @@ import com.taosdata.jdbc.utils.TDNodes; import org.junit.AfterClass; import org.junit.BeforeClass; -public class BaseTest { +public abstract class BaseTest { - private static boolean testCluster = false; + private static boolean testCluster = false; private static TDNodes nodes = new TDNodes(); - + @BeforeClass public static void setupEnv() { - try{ + try { if (nodes.getTDNode(1).getTaosdPid() != null) { System.out.println("Kill taosd before running JDBC test"); nodes.getTDNode(1).setRunning(1); nodes.stop(1); } - nodes.setTestCluster(testCluster); + nodes.setTestCluster(testCluster); nodes.deploy(1); nodes.start(1); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(); } } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java index dd223777d9..2a803e0f19 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java @@ -1,7 +1,5 @@ package com.taosdata.jdbc.cases; -import org.junit.After; -import org.junit.Before; import org.junit.Test; import java.sql.*; From 521bda2f55796b3438d594121940b64a76230c7e Mon Sep 17 00:00:00 2001 From: liuyq-617 Date: Thu, 19 Nov 2020 09:52:09 +0800 Subject: [PATCH 67/85] fix python connector err --- .../python/linux/python3/taos/cinterface.py | 78 +++++++++++-------- .../python/linux/python3/taos/cursor.py | 1 - 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/connector/python/linux/python3/taos/cinterface.py b/src/connector/python/linux/python3/taos/cinterface.py index 609154a3a4..be5b99d8c1 100644 --- a/src/connector/python/linux/python3/taos/cinterface.py +++ b/src/connector/python/linux/python3/taos/cinterface.py @@ -18,7 +18,7 @@ def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): _timestamp_converter = _convert_microsecond_to_datetime if num_of_rows > 0: - return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::-1])) + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::1])) else: return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)])) @@ -26,7 +26,7 @@ def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bool row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] @@ -34,7 +34,7 @@ def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C tinyint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] @@ -42,7 +42,7 @@ def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C smallint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::1]] else: return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] @@ -50,7 +50,7 @@ def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C int row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] @@ -58,7 +58,7 @@ def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bigint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)] ] @@ -66,7 +66,7 @@ def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C float row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] @@ -74,7 +74,7 @@ def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C double row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] @@ -82,7 +82,7 @@ def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C binary row to python row """ if num_of_rows > 0: - return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::1]] else: return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] @@ -111,7 +111,7 @@ def _crow_nchar_to_python(data, num_of_rows, nbytes=None, micro=False): # except ValueError: # res.append(None) # return res - # # return [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[:abs(num_of_rows)][::-1]] + # # return [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[:abs(num_of_rows)][::1]] # else: # return [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[:abs(num_of_rows)]] @@ -308,32 +308,48 @@ class CTaosInterface(object): return fields + # @staticmethod + # def fetchBlock(result, fields): + # pblock = ctypes.c_void_p(0) + # num_of_rows = CTaosInterface.libtaos.taos_fetch_block( + # result, ctypes.byref(pblock)) + # if num_of_rows == 0: + # return None, 0 + + # isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + # blocks = [None] * len(fields) + # fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + # fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + # for i in range(len(fields)): + # data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + + # if fields[i]['type'] not in _CONVERT_FUNC: + # raise DatabaseError("Invalid data type returned from database") + # print('====================',fieldLen[i]) + # blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + + # return blocks, abs(num_of_rows) @staticmethod def fetchBlock(result, fields): pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - - if num_of_rows == 0: + pblock = CTaosInterface.libtaos.taos_fetch_row(result) + if pblock : + num_of_rows = 1 + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + else: return None, 0 - - isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if data == None: - blocks[i] = [None] * num_of_rows - continue - - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError("Invalid data type returned from database") - - blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) - return blocks, abs(num_of_rows) - @staticmethod def freeResult(result): CTaosInterface.libtaos.taos_free_result(result) diff --git a/src/connector/python/linux/python3/taos/cursor.py b/src/connector/python/linux/python3/taos/cursor.py index ec7a85ee1a..eb10bed485 100644 --- a/src/connector/python/linux/python3/taos/cursor.py +++ b/src/connector/python/linux/python3/taos/cursor.py @@ -216,7 +216,6 @@ class TDengineCursor(object): self._rowcount += num_of_fields for i in range(len(self._fields)): buffer[i].extend(block[i]) - return list(map(tuple, zip(*buffer))) def nextset(self): From 312f26fda6a1c96a6eee2a81e051ca725aab6aca Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 10:01:58 +0800 Subject: [PATCH 68/85] [TD-1355] --- src/query/src/qExecutor.c | 47 ++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 869f57f117..87ec62c021 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -847,35 +847,50 @@ static int32_t getNextQualifiedWindow(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow } int32_t startPos = 0; + // tumbling time window query, a special case of sliding time window query if (pQuery->interval.sliding == pQuery->interval.interval && prevPosition != -1) { int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); startPos = prevPosition + factor; } else { - startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order); + if (startKey < pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) { + startPos = 0; + } else if (startKey > pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) { + startPos = pDataBlockInfo->rows - 1; + } else { + startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order); + } } /* * This time window does not cover any data, try next time window, * this case may happen when the time window is too small */ - if (QUERY_IS_ASC_QUERY(pQuery) && primaryKeys[startPos] > pNext->ekey) { - TSKEY next = primaryKeys[startPos]; - if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { - pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision); - pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; + if (primaryKeys == NULL) { + if (QUERY_IS_ASC_QUERY(pQuery)) { + assert(pDataBlockInfo->window.skey <= pNext->ekey); } else { - pNext->ekey += ((next - pNext->ekey + pQuery->interval.sliding - 1)/pQuery->interval.sliding) * pQuery->interval.sliding; - pNext->skey = pNext->ekey - pQuery->interval.interval + 1; + assert(pDataBlockInfo->window.ekey >= pNext->skey); } - } else if ((!QUERY_IS_ASC_QUERY(pQuery)) && primaryKeys[startPos] < pNext->skey) { - TSKEY next = primaryKeys[startPos]; - if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { - pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision); - pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; - } else { - pNext->skey -= ((pNext->skey - next + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding; - pNext->ekey = pNext->skey + pQuery->interval.interval - 1; + } else { + if (QUERY_IS_ASC_QUERY(pQuery) && primaryKeys[startPos] > pNext->ekey) { + TSKEY next = primaryKeys[startPos]; + if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { + pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision); + pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; + } else { + pNext->ekey += ((next - pNext->ekey + pQuery->interval.sliding - 1)/pQuery->interval.sliding) * pQuery->interval.sliding; + pNext->skey = pNext->ekey - pQuery->interval.interval + 1; + } + } else if ((!QUERY_IS_ASC_QUERY(pQuery)) && primaryKeys[startPos] < pNext->skey) { + TSKEY next = primaryKeys[startPos]; + if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { + pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision); + pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; + } else { + pNext->skey -= ((pNext->skey - next + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding; + pNext->ekey = pNext->skey + pQuery->interval.interval - 1; + } } } From 99c985983b00fad54acd63384e8067e051951bd3 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 10:13:54 +0800 Subject: [PATCH 69/85] [TD-225] fix regression test bugs. --- src/client/src/tscServer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 1b1388238c..7dcb554494 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -790,7 +790,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { size_t output = tscNumOfFields(pQueryInfo); if ((tscIsSecondStageQuery(pQueryInfo) || UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || - UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo)) && (output != tscSqlExprNumOfExprs(pQueryInfo))) { + UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo))) { pQueryMsg->secondStageOutput = htonl((int32_t) output); SSqlFuncMsg *pSqlFuncExpr1 = (SSqlFuncMsg *)pMsg; From 4c8a92c9ef5a64396a5a8ac34bac1aaf77f61438 Mon Sep 17 00:00:00 2001 From: liuyq-617 Date: Thu, 19 Nov 2020 10:20:34 +0800 Subject: [PATCH 70/85] fix python connector err --- .../python/linux/python2/taos/cinterface.py | 55 +++++++++---------- .../python/linux/python2/taos/cursor.py | 13 ++--- .../python/windows/python2/taos/cinterface.py | 54 +++++++++--------- .../python/windows/python2/taos/cursor.py | 8 ++- .../python/windows/python3/taos/cinterface.py | 55 +++++++++---------- .../python/windows/python3/taos/cursor.py | 7 +++ 6 files changed, 96 insertions(+), 96 deletions(-) diff --git a/src/connector/python/linux/python2/taos/cinterface.py b/src/connector/python/linux/python2/taos/cinterface.py index 32859f6b34..269326535c 100644 --- a/src/connector/python/linux/python2/taos/cinterface.py +++ b/src/connector/python/linux/python2/taos/cinterface.py @@ -18,7 +18,7 @@ def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): _timestamp_converter = _convert_microsecond_to_datetime if num_of_rows > 0: - return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::-1])) + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::1])) else: return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)])) @@ -26,7 +26,7 @@ def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bool row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] @@ -34,7 +34,7 @@ def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C tinyint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] @@ -42,7 +42,7 @@ def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C smallint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::1]] else: return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] @@ -50,7 +50,7 @@ def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C int row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] @@ -58,7 +58,7 @@ def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bigint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)] ] @@ -66,7 +66,7 @@ def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C float row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] @@ -74,7 +74,7 @@ def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C double row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] @@ -82,7 +82,7 @@ def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C binary row to python row """ if num_of_rows > 0: - return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::1]] else: return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] @@ -311,29 +311,24 @@ class CTaosInterface(object): @staticmethod def fetchBlock(result, fields): pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - - if num_of_rows == 0: + pblock = CTaosInterface.libtaos.taos_fetch_row(result) + if pblock : + num_of_rows = 1 + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + else: return None, 0 - - isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if data == None: - blocks[i] = [None] * num_of_rows - continue - - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError("Invalid data type returned from database") - - blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) - return blocks, abs(num_of_rows) - @staticmethod def freeResult(result): CTaosInterface.libtaos.taos_free_result(result) diff --git a/src/connector/python/linux/python2/taos/cursor.py b/src/connector/python/linux/python2/taos/cursor.py index 37c02d330e..bc6670ca77 100644 --- a/src/connector/python/linux/python2/taos/cursor.py +++ b/src/connector/python/linux/python2/taos/cursor.py @@ -1,6 +1,7 @@ from .cinterface import CTaosInterface from .error import * from .constants import FieldType +import threading class TDengineCursor(object): @@ -35,6 +36,7 @@ class TDengineCursor(object): self._block_iter = 0 self._affected_rows = 0 self._logfile = "" + self._threadId = threading.get_ident() if connection is not None: self._connection = connection @@ -42,7 +44,7 @@ class TDengineCursor(object): def __iter__(self): return self - def next(self): + def __next__(self): if self._result is None or self._fields is None: raise OperationalError("Invalid use of fetch iterator") @@ -137,7 +139,7 @@ class TDengineCursor(object): else: raise ProgrammingError( CTaosInterface.errStr( - self._result ), errno) + self._result), errno) def executemany(self, operation, seq_of_parameters): """Prepare a database operation (query or command) and then execute it against all parameter sequences or mappings found in the sequence seq_of_parameters. @@ -148,6 +150,8 @@ class TDengineCursor(object): """Fetch the next row of a query result set, returning a single sequence, or None when no more data is available. """ pass + def fetchmany(self): + pass def istype(self, col, dataType): if (dataType.upper() == "BOOL"): @@ -180,9 +184,6 @@ class TDengineCursor(object): return False - def fetchmany(self): - pass - def fetchall(self): """Fetch all (remaining) rows of a query result, returning them as a sequence of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute can affect the performance of this operation. """ @@ -201,8 +202,6 @@ class TDengineCursor(object): self._rowcount += num_of_fields for i in range(len(self._fields)): buffer[i].extend(block[i]) - - return list(map(tuple, zip(*buffer))) def nextset(self): diff --git a/src/connector/python/windows/python2/taos/cinterface.py b/src/connector/python/windows/python2/taos/cinterface.py index 6a9c5bfcef..084d38e41c 100644 --- a/src/connector/python/windows/python2/taos/cinterface.py +++ b/src/connector/python/windows/python2/taos/cinterface.py @@ -18,7 +18,7 @@ def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): _timestamp_converter = _convert_microsecond_to_datetime if num_of_rows > 0: - return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1])) + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::1])) else: return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)])) @@ -26,7 +26,7 @@ def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bool row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] @@ -34,7 +34,7 @@ def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C tinyint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] @@ -42,7 +42,7 @@ def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C smallint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::1]] else: return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] @@ -50,7 +50,7 @@ def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C int row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] @@ -58,7 +58,7 @@ def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bigint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)] ] @@ -66,7 +66,7 @@ def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C float row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] @@ -74,7 +74,7 @@ def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C double row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] @@ -82,7 +82,7 @@ def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C binary row to python row """ if num_of_rows > 0: - return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::1]] else: return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] @@ -310,27 +310,23 @@ class CTaosInterface(object): @staticmethod def fetchBlock(result, fields): pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - - if num_of_rows == 0: + pblock = CTaosInterface.libtaos.taos_fetch_row(result) + if pblock : + num_of_rows = 1 + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + else: return None, 0 - - isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if data == None: - blocks[i] = [None] * num_of_rows - continue - - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError("Invalid data type returned from database") - - blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) - return blocks, abs(num_of_rows) @staticmethod diff --git a/src/connector/python/windows/python2/taos/cursor.py b/src/connector/python/windows/python2/taos/cursor.py index 8714fe77cb..35846cbe11 100644 --- a/src/connector/python/windows/python2/taos/cursor.py +++ b/src/connector/python/windows/python2/taos/cursor.py @@ -1,5 +1,9 @@ from .cinterface import CTaosInterface from .error import * +from .constants import FieldType +import threading + +# querySeqNum = 0 class TDengineCursor(object): """Database cursor which is used to manage the context of a fetch operation. @@ -32,6 +36,8 @@ class TDengineCursor(object): self._block_rows = -1 self._block_iter = 0 self._affected_rows = 0 + self._logfile = "" + self._threadId = threading.get_ident() if connection is not None: self._connection = connection @@ -39,7 +45,7 @@ class TDengineCursor(object): def __iter__(self): return self - def next(self): + def __next__(self): if self._result is None or self._fields is None: raise OperationalError("Invalid use of fetch iterator") diff --git a/src/connector/python/windows/python3/taos/cinterface.py b/src/connector/python/windows/python3/taos/cinterface.py index fa7124431c..68adf191c9 100644 --- a/src/connector/python/windows/python3/taos/cinterface.py +++ b/src/connector/python/windows/python3/taos/cinterface.py @@ -18,7 +18,7 @@ def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): _timestamp_converter = _convert_microsecond_to_datetime if num_of_rows > 0: - return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1])) + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::1])) else: return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)])) @@ -26,7 +26,7 @@ def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bool row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] @@ -34,7 +34,7 @@ def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C tinyint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] @@ -42,7 +42,7 @@ def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C smallint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::1]] else: return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] @@ -50,7 +50,7 @@ def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C int row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] @@ -58,7 +58,7 @@ def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bigint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)] ] @@ -66,7 +66,7 @@ def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C float row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] @@ -74,7 +74,7 @@ def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C double row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] @@ -82,7 +82,7 @@ def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C binary row to python row """ if num_of_rows > 0: - return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::1]] else: return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] @@ -225,6 +225,7 @@ class CTaosInterface(object): if connection.value == None: print('connect to TDengine failed') + raise ConnectionError("connect to TDengine failed") # sys.exit(1) else: print('connect to TDengine success') @@ -310,27 +311,23 @@ class CTaosInterface(object): @staticmethod def fetchBlock(result, fields): pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - - if num_of_rows == 0: + pblock = CTaosInterface.libtaos.taos_fetch_row(result) + if pblock : + num_of_rows = 1 + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + else: return None, 0 - - isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if data == None: - blocks[i] = [None] * num_of_rows - continue - - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError("Invalid data type returned from database") - - blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) - return blocks, abs(num_of_rows) @staticmethod diff --git a/src/connector/python/windows/python3/taos/cursor.py b/src/connector/python/windows/python3/taos/cursor.py index c2c442b06e..b58b494cad 100644 --- a/src/connector/python/windows/python3/taos/cursor.py +++ b/src/connector/python/windows/python3/taos/cursor.py @@ -1,5 +1,10 @@ from .cinterface import CTaosInterface from .error import * +from .constants import FieldType +import threading + +# querySeqNum = 0 + class TDengineCursor(object): """Database cursor which is used to manage the context of a fetch operation. @@ -32,6 +37,8 @@ class TDengineCursor(object): self._block_rows = -1 self._block_iter = 0 self._affected_rows = 0 + self._logfile = "" + self._threadId = threading.get_ident() if connection is not None: self._connection = connection From 4410234af264dc6e8fccb1c67c89c3cb945e6ce5 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 10:44:03 +0800 Subject: [PATCH 71/85] [TD-225] --- src/client/src/tscSql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 261467ad29..ddff004f82 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -573,7 +573,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) { *rows = pRes->urow; tscClearSqlOwner(pSql); - return pRes->numOfRows; + return (int32_t) pRes->numOfRows; } int taos_select_db(TAOS *taos, const char *db) { From ad5474d8aaf84ded6a6d5b23a8a205e1ad2a84bd Mon Sep 17 00:00:00 2001 From: zyyang Date: Thu, 19 Nov 2020 10:49:01 +0800 Subject: [PATCH 72/85] change --- .../src/test/java/com/taosdata/jdbc/cases/FailOverTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java index 2a803e0f19..83295df527 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java @@ -16,7 +16,8 @@ public class FailOverTest { Class.forName("com.taosdata.jdbc.TSDBDriver"); final String url = "jdbc:TAOS://:/?user=root&password=taosdata"; - while (true) { + long end = System.currentTimeMillis() + 1000 * 60 * 5; + while (System.currentTimeMillis() < end) { try (Connection conn = DriverManager.getConnection(url)) { Statement stmt = conn.createStatement(); ResultSet resultSet = stmt.executeQuery("select server_status()"); From a41312d5242f91f1ba80629ff3a317839080df33 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 10:51:39 +0800 Subject: [PATCH 73/85] [TD-225] --- src/client/src/tscSql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index ddff004f82..fa4dcd1a76 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -805,7 +805,7 @@ bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) { return true; } - return isNull(pSql->res.urow[col] + row * pInfo->field.bytes, pInfo->field.type); + return isNull(((char*) pSql->res.urow[col]) + row * pInfo->field.bytes, pInfo->field.type); } int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) { From 1faef8863d954bde6ca8c4bda71627b390c97912 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 10:56:15 +0800 Subject: [PATCH 74/85] [TD-225] --- src/client/src/tscSubquery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index d5f69fd45a..c2594ddbd8 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -2463,7 +2463,7 @@ TAOS_ROW doSetResultRowData(SSqlObj *pSql) { for (int i = 0; i < size; ++i) { SInternalField* pInfo = (SInternalField*)TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i); - int32_t type = pInfo->field.type; + int32_t type = pInfo->field.type; int32_t bytes = pInfo->field.bytes; if (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR) { @@ -2473,7 +2473,7 @@ TAOS_ROW doSetResultRowData(SSqlObj *pSql) { pRes->length[i] = varDataLen(pRes->urow[i]); } - pRes->urow[i] += bytes; + ((char**) pRes->urow)[i] += bytes; } pRes->row++; // index increase one-step From 0b1abeb5d654cabc79a803fa1d98edb0a36b9c47 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 11:00:48 +0800 Subject: [PATCH 75/85] [TD-225] --- src/client/src/tscUtil.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index d4bdcd6ed9..4c2d25601f 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -220,13 +220,16 @@ bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo) { } bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo) { - size_t numOfOutput = tscNumOfFields(pQueryInfo); - size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); - - if (numOfOutput == numOfExprs) { + STableMetaInfo* pTableMetaInfo = pQueryInfo->pTableMetaInfo[0]; + if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { return false; } + if (tscIsProjectionQuery(pQueryInfo)) { + return false; + } + + size_t numOfOutput = tscNumOfFields(pQueryInfo); for(int32_t i = 0; i < numOfOutput; ++i) { SExprInfo* pExprInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i)->pArithExprInfo; if (pExprInfo != NULL) { @@ -309,14 +312,14 @@ void tscSetResRawPtr(SSqlRes* pRes, SQueryInfo* pQueryInfo) { assert(pInfo->pSqlExpr->param[1].nLen <= pInfo->field.bytes); for (int32_t k = 0; k < pRes->numOfRows; ++k) { - char* p = pRes->urow[i] + k * pInfo->field.bytes; + char* p = ((char**)pRes->urow)[i] + k * pInfo->field.bytes; memcpy(varDataVal(p), pInfo->pSqlExpr->param[1].pz, pInfo->pSqlExpr->param[1].nLen); varDataSetLen(p, pInfo->pSqlExpr->param[1].nLen); } } else { for (int32_t k = 0; k < pRes->numOfRows; ++k) { - char* p = pRes->urow[i] + k * pInfo->field.bytes; + char* p = ((char**)pRes->urow)[i] + k * pInfo->field.bytes; memcpy(p, &pInfo->pSqlExpr->param[1].i64Key, pInfo->field.bytes); } } From d0afbae3ccf1dd94241f06aa5996da5ce771c46f Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 11:03:37 +0800 Subject: [PATCH 76/85] [TD-225] --- src/client/src/tscUtil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 4c2d25601f..7a58e8b372 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -306,7 +306,7 @@ void tscSetResRawPtr(SSqlRes* pRes, SQueryInfo* pQueryInfo) { // generated the user-defined column result if (pInfo->pSqlExpr != NULL && TSDB_COL_IS_UD_COL(pInfo->pSqlExpr->colInfo.flag)) { if (pInfo->pSqlExpr->param[1].nType == TSDB_DATA_TYPE_NULL) { - setNullN(pRes->urow[i], pInfo->field.type, pInfo->field.bytes, pRes->numOfRows); + setNullN(pRes->urow[i], pInfo->field.type, pInfo->field.bytes, (int32_t) pRes->numOfRows); } else { if (pInfo->field.type == TSDB_DATA_TYPE_NCHAR || pInfo->field.type == TSDB_DATA_TYPE_BINARY) { assert(pInfo->pSqlExpr->param[1].nLen <= pInfo->field.bytes); From 39406da3bcd70a746b7bb7d9b297052018d92ce9 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Thu, 19 Nov 2020 11:05:23 +0800 Subject: [PATCH 77/85] [TD-2155] : fix compile error for centos 7. --- src/connector/odbc/src/todbc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index 953999c434..7de46a444e 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -16,6 +16,7 @@ // #define _BSD_SOURCE #define _XOPEN_SOURCE #define _DEFAULT_SOURCE +#define _GNU_SOURCE #include "taos.h" From 3cbbc55e464ff0220ee5f51e9a6eb474eb53f70c Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 13:26:37 +0800 Subject: [PATCH 78/85] [TD-225] --- src/client/inc/tsclient.h | 51 ++++++++++++++++++------------------ src/client/src/tscServer.c | 5 ++-- src/client/src/tscSubquery.c | 8 +++--- src/client/src/tscUtil.c | 5 ---- src/query/src/qExecutor.c | 4 +-- 5 files changed, 33 insertions(+), 40 deletions(-) diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index 6c6ceb92bb..ff36cf0f5a 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -293,33 +293,32 @@ typedef struct SResRec { } SResRec; typedef struct { - int64_t numOfRows; // num of results in current retrieved - int64_t numOfRowsGroup; // num of results of current group - int64_t numOfTotal; // num of total results - int64_t numOfClauseTotal; // num of total result in current subclause - char * pRsp; - int32_t rspType; - int32_t rspLen; - uint64_t qhandle; - int64_t uid; - int64_t useconds; - int64_t offset; // offset value from vnode during projection query of stable - int32_t row; - int16_t numOfCols; - int16_t precision; - bool completed; - int32_t code; - int32_t numOfGroups; - SResRec * pGroupRec; - char * data; - TAOS_ROW tsrow; - TAOS_ROW urow; - int32_t* length; // length for each field for current row - char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t) - SColumnIndex * pColumnIndex; + int32_t numOfRows; // num of results in current retrieval + int64_t numOfRowsGroup; // num of results of current group + int64_t numOfTotal; // num of total results + int64_t numOfClauseTotal; // num of total result in current subclause + char * pRsp; + int32_t rspType; + int32_t rspLen; + uint64_t qhandle; + int64_t useconds; + int64_t offset; // offset value from vnode during projection query of stable + int32_t row; + int16_t numOfCols; + int16_t precision; + bool completed; + int32_t code; + int32_t numOfGroups; + SResRec * pGroupRec; + char * data; + TAOS_ROW tsrow; + TAOS_ROW urow; + int32_t* length; // length for each field for current row + char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t) + SColumnIndex* pColumnIndex; + SArithmeticSupport* pArithSup; // support the arithmetic expression calculation on agg functions - - struct SLocalReducer *pLocalReducer; + struct SLocalReducer* pLocalReducer; } SSqlRes; typedef struct STscObj { diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 78c56ac8cc..cbc5604a27 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -789,8 +789,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { size_t output = tscNumOfFields(pQueryInfo); - if ((tscIsSecondStageQuery(pQueryInfo) || UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || - UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo))) { + if (tscIsSecondStageQuery(pQueryInfo)) { pQueryMsg->secondStageOutput = htonl((int32_t) output); SSqlFuncMsg *pSqlFuncExpr1 = (SSqlFuncMsg *)pMsg; @@ -2219,7 +2218,7 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) { } pRes->row = 0; - tscDebug("%p numOfRows:%" PRId64 ", offset:%" PRId64 ", complete:%d", pSql, pRes->numOfRows, pRes->offset, pRes->completed); + tscDebug("%p numOfRows:%d, offset:%" PRId64 ", complete:%d", pSql, pRes->numOfRows, pRes->offset, pRes->completed); return 0; } diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index c2594ddbd8..4f2d98433b 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -1085,7 +1085,7 @@ static void joinRetrieveFinalResCallback(void* param, TAOS_RES* tres, int numOfR SSqlRes* pRes1 = &pParentSql->pSubs[i]->res; if (pRes1->row > 0 && pRes1->numOfRows > 0) { - tscDebug("%p sub:%p index:%d numOfRows:%"PRId64" total:%"PRId64 " (not retrieve)", pParentSql, pParentSql->pSubs[i], i, + tscDebug("%p sub:%p index:%d numOfRows:%d total:%"PRId64 " (not retrieve)", pParentSql, pParentSql->pSubs[i], i, pRes1->numOfRows, pRes1->numOfTotal); assert(pRes1->row < pRes1->numOfRows); } else { @@ -1093,7 +1093,7 @@ static void joinRetrieveFinalResCallback(void* param, TAOS_RES* tres, int numOfR pRes1->numOfClauseTotal += pRes1->numOfRows; } - tscDebug("%p sub:%p index:%d numOfRows:%"PRId64" total:%"PRId64, pParentSql, pParentSql->pSubs[i], i, + tscDebug("%p sub:%p index:%d numOfRows:%d total:%"PRId64, pParentSql, pParentSql->pSubs[i], i, pRes1->numOfRows, pRes1->numOfTotal); } } @@ -2032,7 +2032,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR assert(pRes->numOfRows == numOfRows); int64_t num = atomic_add_fetch_64(&pState->numOfRetrievedRows, numOfRows); - tscDebug("%p sub:%p retrieve numOfRows:%" PRId64 " totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d", pParentSql, pSql, + tscDebug("%p sub:%p retrieve numOfRows:%d totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d", pParentSql, pSql, pRes->numOfRows, pState->numOfRetrievedRows, pSql->epSet.fqdn[pSql->epSet.inUse], idx); if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0)) { @@ -2171,7 +2171,7 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows) return; } - tscDebug("%p Async insertion completed, total inserted:%" PRId64, pParentObj, pParentObj->res.numOfRows); + tscDebug("%p Async insertion completed, total inserted:%d", pParentObj, pParentObj->res.numOfRows); // restore user defined fp pParentObj->fp = pParentObj->fetchFp; diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 7a58e8b372..7a82bcaaab 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -220,11 +220,6 @@ bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo) { } bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo) { - STableMetaInfo* pTableMetaInfo = pQueryInfo->pTableMetaInfo[0]; - if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { - return false; - } - if (tscIsProjectionQuery(pQueryInfo)) { return false; } diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index f4ffb0aa85..2096cf4766 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -853,9 +853,9 @@ static int32_t getNextQualifiedWindow(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); startPos = prevPosition + factor; } else { - if (startKey < pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) { + if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) { startPos = 0; - } else if (startKey > pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) { + } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) { startPos = pDataBlockInfo->rows - 1; } else { startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order); From fa3205dceebe208ea63be3b3ad3316ab68cafdba Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 13:32:08 +0800 Subject: [PATCH 79/85] [TD-225] --- src/query/src/qParserImpl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index 4481ff5e8f..0853565fc6 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -225,7 +225,8 @@ tSQLExpr *tSQLExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { tSQLExprDestroy(pLeft); tSQLExprDestroy(pRight); - } else if ((pLeft->nSQLOptr == TK_FLOAT && pRight->nSQLOptr == TK_INTEGER) || (pLeft->nSQLOptr == TK_INTEGER && pRight->nSQLOptr == TK_FLOAT)) { + } else if ((pLeft->nSQLOptr == TK_FLOAT && pRight->nSQLOptr == TK_INTEGER) || (pLeft->nSQLOptr == TK_INTEGER && pRight->nSQLOptr == TK_FLOAT) || + (pLeft->nSQLOptr == TK_FLOAT && pRight->nSQLOptr == TK_FLOAT)) { pExpr->val.nType = TSDB_DATA_TYPE_DOUBLE; pExpr->nSQLOptr = TK_FLOAT; From bc8fb310b44e2308267d8273ef3167efe30b62a9 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 13:34:07 +0800 Subject: [PATCH 80/85] [TD-225] update sim. --- tests/script/general/parser/alter.sim | 12 +- tests/script/general/parser/alter1.sim | 4 +- tests/script/general/parser/alter_stable.sim | 2 +- .../script/general/parser/auto_create_tb.sim | 8 +- .../general/parser/auto_create_tb_drop_tb.sim | 8 +- .../general/parser/binary_escapeCharacter.sim | 2 +- .../parser/col_arithmetic_operation.sim | 7 +- tests/script/general/parser/columnValue.sim | 2 +- .../general/parser/columnValue_bigint.sim | 2 +- .../general/parser/columnValue_bool.sim | 2 +- .../general/parser/columnValue_double.sim | 2 +- .../general/parser/columnValue_float.sim | 2 +- .../script/general/parser/columnValue_int.sim | 2 +- .../general/parser/columnValue_smallint.sim | 2 +- .../general/parser/columnValue_tinyint.sim | 2 +- tests/script/general/parser/commit.sim | 11 +- tests/script/general/parser/constCol.sim | 4 +- tests/script/general/parser/create_db.sim | 2 +- tests/script/general/parser/create_mt.sim | 2 +- tests/script/general/parser/create_tb.sim | 2 +- .../general/parser/dbtbnameValidate.sim | 2 +- tests/script/general/parser/fill.sim | 2 +- tests/script/general/parser/fill_stb.sim | 2 +- tests/script/general/parser/fill_us.sim | 2 +- tests/script/general/parser/first_last.sim | 6 +- .../general/parser/first_last_query.sim | 2 +- tests/script/general/parser/groupby.sim | 2 +- tests/script/general/parser/import.sim | 4 +- .../script/general/parser/import_commit1.sim | 4 +- .../script/general/parser/import_commit2.sim | 4 +- .../script/general/parser/import_commit3.sim | 6 +- .../script/general/parser/insert_multiTbl.sim | 2 +- tests/script/general/parser/insert_tb.sim | 6 +- tests/script/general/parser/interp.sim | 4 +- tests/script/general/parser/interp_test.sim | 2 +- tests/script/general/parser/join.sim | 2 +- .../script/general/parser/join_multivnode.sim | 2 +- tests/script/general/parser/lastrow.sim | 6 +- tests/script/general/parser/lastrow_query.sim | 2 +- tests/script/general/parser/limit.sim | 6 +- tests/script/general/parser/limit1.sim | 7 +- tests/script/general/parser/limit1_stb.sim | 2 +- tests/script/general/parser/limit1_tb.sim | 2 +- .../general/parser/limit1_tblocks100.sim | 7 +- tests/script/general/parser/limit2.sim | 4 +- tests/script/general/parser/limit2_query.sim | 2 +- .../general/parser/limit2_tblocks100.sim | 4 +- tests/script/general/parser/limit_stb.sim | 2 +- tests/script/general/parser/limit_tb.sim | 2 +- tests/script/general/parser/mixed_blocks.sim | 2 +- tests/script/general/parser/nchar.sim | 2 +- tests/script/general/parser/null_char.sim | 4 +- .../parser/projection_limit_offset.sim | 4 +- tests/script/general/parser/selectResNum.sim | 11 +- .../general/parser/select_across_vnodes.sim | 2 +- .../general/parser/select_from_cache_disk.sim | 6 +- .../general/parser/select_with_tags.sim | 2 +- tests/script/general/parser/set_tag_vals.sim | 2 +- .../general/parser/single_row_in_tb.sim | 4 +- .../general/parser/single_row_in_tb_query.sim | 2 +- tests/script/general/parser/sliding.sim | 2 +- tests/script/general/parser/slimit.sim | 6 +- tests/script/general/parser/slimit1.sim | 6 +- tests/script/general/parser/slimit1_query.sim | 2 +- .../general/parser/slimit_alter_tags.sim | 6 +- tests/script/general/parser/slimit_query.sim | 2 +- tests/script/general/parser/stream_on_sys.sim | 2 +- .../parser/tags_dynamically_specifiy.sim | 4 +- tests/script/general/parser/tags_filter.sim | 2 +- tests/script/general/parser/tbnameIn.sim | 4 +- .../script/general/parser/tbnameIn_query.sim | 2 +- tests/script/general/parser/testSuite.sim | 176 +++++++++--------- tests/script/general/parser/timestamp.sim | 6 +- .../script/general/parser/timestamp_query.sim | 2 +- tests/script/general/parser/topbot.sim | 10 +- tests/script/general/parser/union.sim | 4 +- tests/script/general/parser/where.sim | 2 +- 77 files changed, 226 insertions(+), 233 deletions(-) diff --git a/tests/script/general/parser/alter.sim b/tests/script/general/parser/alter.sim index 2a9e3a8873..5c15656f24 100644 --- a/tests/script/general/parser/alter.sim +++ b/tests/script/general/parser/alter.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = m_alt_db @@ -114,7 +114,7 @@ endi sql drop table tb sql drop table mt -sleep 1000 +sleep 500 ### ALTER TABLE WHILE STREAMING [TBASE271] #sql create table tb1 (ts timestamp, c1 int, c2 nchar(5), c3 int) #sql create table strm as select count(*), avg(c1), first(c2), sum(c3) from tb1 interval(2s) @@ -134,7 +134,7 @@ sleep 1000 # return -1 #endi #sql alter table tb1 drop column c3 -#sleep 6000 +#sleep 3000 #sql insert into tb1 values (now, 2, 'taos') #sleep 30000 #sql select * from strm @@ -145,9 +145,9 @@ sleep 1000 # return -1 #endi #sql alter table tb1 add column c3 int -#sleep 6000 +#sleep 3000 #sql insert into tb1 values (now, 3, 'taos', 3); -#sleep 1000 +#sleep 500 #sql select * from strm #if $rows != 3 then # return -1 @@ -186,7 +186,7 @@ sql create database $db sql use $db sql create table mt (ts timestamp, c1 int, c2 nchar(7), c3 int) tags (t1 int) sql create table tb using mt tags(1) -sleep 1000 +sleep 500 sql insert into tb values ('2018-11-01 16:30:00.000', 1, 'insert', 1) sql alter table mt drop column c3 diff --git a/tests/script/general/parser/alter1.sim b/tests/script/general/parser/alter1.sim index 0326f9b23f..e013242b82 100644 --- a/tests/script/general/parser/alter1.sim +++ b/tests/script/general/parser/alter1.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect sql reset query cache @@ -87,7 +87,7 @@ if $data13 != NULL then return -1 endi -sleep 1000 +sleep 500 print ================== insert values into table sql insert into car1 values (now, 1, 1,1 ) (now +1s, 2,2,2,) car2 values (now, 1,3,3) diff --git a/tests/script/general/parser/alter_stable.sim b/tests/script/general/parser/alter_stable.sim index b0d94ef68c..6b3f3a8f53 100644 --- a/tests/script/general/parser/alter_stable.sim +++ b/tests/script/general/parser/alter_stable.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ========== alter_stable.sim diff --git a/tests/script/general/parser/auto_create_tb.sim b/tests/script/general/parser/auto_create_tb.sim index c72147be95..6deaf92a6c 100644 --- a/tests/script/general/parser/auto_create_tb.sim +++ b/tests/script/general/parser/auto_create_tb.sim @@ -4,7 +4,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ======================== dnode1 start @@ -208,11 +208,11 @@ endi print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 sql use $db #### auto create multiple tables @@ -298,7 +298,7 @@ endi sql create table tu(ts timestamp, k int); sql_error create table txu using tu tags(0) values(now, 1); -#[TBASE-675] +print =================> [TBASE-675] sql insert into tu values(1565971200000, 1) (1565971200000,2) (1565971200001, 3)(1565971200001, 4) sql select * from tu if $rows != 2 then diff --git a/tests/script/general/parser/auto_create_tb_drop_tb.sim b/tests/script/general/parser/auto_create_tb_drop_tb.sim index 2a809fa9db..8a429cf91a 100644 --- a/tests/script/general/parser/auto_create_tb_drop_tb.sim +++ b/tests/script/general/parser/auto_create_tb_drop_tb.sim @@ -4,7 +4,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c maxTablesPerVnode -v 4 system sh/cfg.sh -n dnode1 -c ctime -v 30 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = db @@ -49,7 +49,7 @@ while $t < $tbNum endw print ====== tables created -sleep 60000 +sleep 500 sql drop table tb2 $x = 0 @@ -59,9 +59,7 @@ while $x < $rowNum $t1 = $t1 . ' sql insert into tb1 using $stb tags( $t1 ) values ( $ts , $x ) $x = $x + 1 -endw - -sleep 6000 +endw $ts = $ts0 + $delta $ts = $ts + 1 diff --git a/tests/script/general/parser/binary_escapeCharacter.sim b/tests/script/general/parser/binary_escapeCharacter.sim index 780916258b..e9e61f35bf 100644 --- a/tests/script/general/parser/binary_escapeCharacter.sim +++ b/tests/script/general/parser/binary_escapeCharacter.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect sql drop database if exists ecdb diff --git a/tests/script/general/parser/col_arithmetic_operation.sim b/tests/script/general/parser/col_arithmetic_operation.sim index f5e91b933a..d5ba57e6c7 100644 --- a/tests/script/general/parser/col_arithmetic_operation.sim +++ b/tests/script/general/parser/col_arithmetic_operation.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = ca_db @@ -34,7 +34,7 @@ while $i < $halfTbNum $tb1 = $tbPrefix . $tbId sql create table $tb using $stb tags( $i ) sql create table $tb1 using $stb tags( $tbId ) - + $x = 0 while $x < $rowNum $xs = $x * $delta @@ -46,8 +46,7 @@ while $i < $halfTbNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) $x = $x + 1 endw $i = $i + 1 diff --git a/tests/script/general/parser/columnValue.sim b/tests/script/general/parser/columnValue.sim index c7aac1a8fa..2c03a3552a 100644 --- a/tests/script/general/parser/columnValue.sim +++ b/tests/script/general/parser/columnValue.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ========== columnValues.sim diff --git a/tests/script/general/parser/columnValue_bigint.sim b/tests/script/general/parser/columnValue_bigint.sim index 002240fa25..3546ca15ee 100644 --- a/tests/script/general/parser/columnValue_bigint.sim +++ b/tests/script/general/parser/columnValue_bigint.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_bool.sim b/tests/script/general/parser/columnValue_bool.sim index e43f2289e7..d68f375900 100644 --- a/tests/script/general/parser/columnValue_bool.sim +++ b/tests/script/general/parser/columnValue_bool.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_double.sim b/tests/script/general/parser/columnValue_double.sim index 009ef971c9..fd2da37838 100644 --- a/tests/script/general/parser/columnValue_double.sim +++ b/tests/script/general/parser/columnValue_double.sim @@ -1,5 +1,5 @@ #### -sleep 1000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_float.sim b/tests/script/general/parser/columnValue_float.sim index f7b77cdc0a..019cf176d0 100644 --- a/tests/script/general/parser/columnValue_float.sim +++ b/tests/script/general/parser/columnValue_float.sim @@ -1,5 +1,5 @@ #### -sleep 1000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_int.sim b/tests/script/general/parser/columnValue_int.sim index 46e466c417..1f84df5ca0 100644 --- a/tests/script/general/parser/columnValue_int.sim +++ b/tests/script/general/parser/columnValue_int.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_smallint.sim b/tests/script/general/parser/columnValue_smallint.sim index cdaceaa05f..af5c581871 100644 --- a/tests/script/general/parser/columnValue_smallint.sim +++ b/tests/script/general/parser/columnValue_smallint.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_tinyint.sim b/tests/script/general/parser/columnValue_tinyint.sim index 31eff422d4..3efe52cc91 100644 --- a/tests/script/general/parser/columnValue_tinyint.sim +++ b/tests/script/general/parser/columnValue_tinyint.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/commit.sim b/tests/script/general/parser/commit.sim index 5aa5b8f40c..c798bf9d7c 100644 --- a/tests/script/general/parser/commit.sim +++ b/tests/script/general/parser/commit.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxTablesperVnode -v 100 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = sc_db @@ -50,8 +50,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -83,12 +82,12 @@ endw print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 print ================== server restart completed sql connect -sleep 1000 +sleep 500 print ====== select from table and check num of rows returned sql use $db diff --git a/tests/script/general/parser/constCol.sim b/tests/script/general/parser/constCol.sim index b5a4d4abea..4a8e443281 100644 --- a/tests/script/general/parser/constCol.sim +++ b/tests/script/general/parser/constCol.sim @@ -353,8 +353,8 @@ if $rows != 3 then endi print =============================> td-2036 -if $data00 != 0.3000000 then - print expect: 0.3000000, actual:$data00 +if $data00 != 0.300000000 then + print expect: 0.300000000, actual:$data00 return -1 endi diff --git a/tests/script/general/parser/create_db.sim b/tests/script/general/parser/create_db.sim index c8337ea81d..3b7f24b6d9 100644 --- a/tests/script/general/parser/create_db.sim +++ b/tests/script/general/parser/create_db.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ======================== dnode1 start diff --git a/tests/script/general/parser/create_mt.sim b/tests/script/general/parser/create_mt.sim index d940853984..e11f322761 100644 --- a/tests/script/general/parser/create_mt.sim +++ b/tests/script/general/parser/create_mt.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ======================== dnode1 start diff --git a/tests/script/general/parser/create_tb.sim b/tests/script/general/parser/create_tb.sim index 1027e2b25f..609aad2adb 100644 --- a/tests/script/general/parser/create_tb.sim +++ b/tests/script/general/parser/create_tb.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ======================== dnode1 start diff --git a/tests/script/general/parser/dbtbnameValidate.sim b/tests/script/general/parser/dbtbnameValidate.sim index b46a222282..fd40ecc3f7 100644 --- a/tests/script/general/parser/dbtbnameValidate.sim +++ b/tests/script/general/parser/dbtbnameValidate.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ========== db name and table name check in create and drop, describe diff --git a/tests/script/general/parser/fill.sim b/tests/script/general/parser/fill.sim index 0b535272bd..9851a4e7fc 100644 --- a/tests/script/general/parser/fill.sim +++ b/tests/script/general/parser/fill.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = m_fl_db diff --git a/tests/script/general/parser/fill_stb.sim b/tests/script/general/parser/fill_stb.sim index a84aa0c557..83eb98c465 100644 --- a/tests/script/general/parser/fill_stb.sim +++ b/tests/script/general/parser/fill_stb.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = fl1_db diff --git a/tests/script/general/parser/fill_us.sim b/tests/script/general/parser/fill_us.sim index b6de72464f..dc8ee8659d 100644 --- a/tests/script/general/parser/fill_us.sim +++ b/tests/script/general/parser/fill_us.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = m_fl_db diff --git a/tests/script/general/parser/first_last.sim b/tests/script/general/parser/first_last.sim index e4f50ea365..a934d3bcab 100644 --- a/tests/script/general/parser/first_last.sim +++ b/tests/script/general/parser/first_last.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxTablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = first_db @@ -76,11 +76,11 @@ run general/parser/first_last_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 run general/parser/first_last_query.sim diff --git a/tests/script/general/parser/first_last_query.sim b/tests/script/general/parser/first_last_query.sim index 512fc70245..a982f10362 100644 --- a/tests/script/general/parser/first_last_query.sim +++ b/tests/script/general/parser/first_last_query.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = first_db diff --git a/tests/script/general/parser/groupby.sim b/tests/script/general/parser/groupby.sim index 145c4a008f..c0a6709fe4 100644 --- a/tests/script/general/parser/groupby.sim +++ b/tests/script/general/parser/groupby.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = group_db diff --git a/tests/script/general/parser/import.sim b/tests/script/general/parser/import.sim index 9ef83fa35b..6da2483738 100644 --- a/tests/script/general/parser/import.sim +++ b/tests/script/general/parser/import.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = impt_db @@ -64,7 +64,7 @@ sleep 2000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 sql use $db sql select * from tb diff --git a/tests/script/general/parser/import_commit1.sim b/tests/script/general/parser/import_commit1.sim index 9af1acfe77..9c5144a630 100644 --- a/tests/script/general/parser/import_commit1.sim +++ b/tests/script/general/parser/import_commit1.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c ctime -v 30 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = ic_db @@ -40,7 +40,7 @@ while $x < $rowNum endw print ====== tables created -sleep 6000 +sleep 3000 $ts = $ts0 + $delta $ts = $ts + 1 diff --git a/tests/script/general/parser/import_commit2.sim b/tests/script/general/parser/import_commit2.sim index 3c8635f3fd..000394386e 100644 --- a/tests/script/general/parser/import_commit2.sim +++ b/tests/script/general/parser/import_commit2.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c ctime -v 30 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = ic_db @@ -39,7 +39,7 @@ while $x < $rowNum endw print ====== tables created -sleep 6000 +sleep 3000 $ts = $ts0 + $delta $ts = $ts + 1 diff --git a/tests/script/general/parser/import_commit3.sim b/tests/script/general/parser/import_commit3.sim index 3ceb025f32..997a4a22aa 100644 --- a/tests/script/general/parser/import_commit3.sim +++ b/tests/script/general/parser/import_commit3.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c ctime -v 30 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = ic_db @@ -39,7 +39,7 @@ while $x < $rowNum endw print ====== tables created -sleep 6000 +sleep 3000 $ts = $ts + 1 sql insert into $tb values ( $ts , -1, -1, -1, -1, -1) @@ -47,7 +47,7 @@ $ts = $ts0 + $delta $ts = $ts + 1 sql import into $tb values ( $ts , -2, -2, -2, -2, -2) -sleep 6000 +sleep 3000 sql show databases diff --git a/tests/script/general/parser/insert_multiTbl.sim b/tests/script/general/parser/insert_multiTbl.sim index f3b9c4a390..887f97a198 100644 --- a/tests/script/general/parser/insert_multiTbl.sim +++ b/tests/script/general/parser/insert_multiTbl.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start sleep 2000 sql connect -sleep 1000 +sleep 500 print ======================== dnode1 start sql create database mul_db diff --git a/tests/script/general/parser/insert_tb.sim b/tests/script/general/parser/insert_tb.sim index 5eb973520a..0a9eb9f678 100644 --- a/tests/script/general/parser/insert_tb.sim +++ b/tests/script/general/parser/insert_tb.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ======================== dnode1 start @@ -103,7 +103,7 @@ if $rows != 1 then endi sql drop database $db -sleep 1000 +sleep 500 sql create database $db sql use $db sql create table stb1 (ts timestamp, c1 int) tags(t1 int) @@ -136,7 +136,7 @@ if $data21 != 1.000000000 then endi sql drop database $db -sleep 1000 +sleep 500 sql create database $db sql use $db sql create table stb (ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 nchar(10), c6 binary(20)) tags(t1 int, t2 bigint, t3 double, t4 float, t5 nchar(10)) diff --git a/tests/script/general/parser/interp.sim b/tests/script/general/parser/interp.sim index c83d3ab5c4..8777c3ed9b 100644 --- a/tests/script/general/parser/interp.sim +++ b/tests/script/general/parser/interp.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = intp_db @@ -60,7 +60,7 @@ run general/parser/interp_test.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/interp_test.sim b/tests/script/general/parser/interp_test.sim index 6de8de0b7a..42738a8bd1 100644 --- a/tests/script/general/parser/interp_test.sim +++ b/tests/script/general/parser/interp_test.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = intp_db diff --git a/tests/script/general/parser/join.sim b/tests/script/general/parser/join.sim index d6e4a6a5a7..3ee90cda35 100644 --- a/tests/script/general/parser/join.sim +++ b/tests/script/general/parser/join.sim @@ -7,7 +7,7 @@ system sh/cfg.sh -n dnode1 -c rpcDebugFlag -v 135 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = join_db diff --git a/tests/script/general/parser/join_multivnode.sim b/tests/script/general/parser/join_multivnode.sim index 6bca0e75c4..52489bba01 100644 --- a/tests/script/general/parser/join_multivnode.sim +++ b/tests/script/general/parser/join_multivnode.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start sql connect -sleep 1000 +sleep 500 $dbPrefix = join_m_db $tbPrefix = join_tb diff --git a/tests/script/general/parser/lastrow.sim b/tests/script/general/parser/lastrow.sim index 7db233ee9d..cc71123a77 100644 --- a/tests/script/general/parser/lastrow.sim +++ b/tests/script/general/parser/lastrow.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = lr_db @@ -62,11 +62,11 @@ run general/parser/lastrow_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 run general/parser/lastrow_query.sim diff --git a/tests/script/general/parser/lastrow_query.sim b/tests/script/general/parser/lastrow_query.sim index 1a9b1a74a9..5b9c8b60c3 100644 --- a/tests/script/general/parser/lastrow_query.sim +++ b/tests/script/general/parser/lastrow_query.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = lr_db diff --git a/tests/script/general/parser/limit.sim b/tests/script/general/parser/limit.sim index 909ac71cbf..fb5e704bf1 100644 --- a/tests/script/general/parser/limit.sim +++ b/tests/script/general/parser/limit.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxVgroupsPerDb -v 1 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = lm_db @@ -62,11 +62,11 @@ run general/parser/limit_stb.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 run general/parser/limit_tb.sim run general/parser/limit_stb.sim diff --git a/tests/script/general/parser/limit1.sim b/tests/script/general/parser/limit1.sim index 59ecdb92b0..7236421ec2 100644 --- a/tests/script/general/parser/limit1.sim +++ b/tests/script/general/parser/limit1.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxVgroupsPerDb -v 1 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = lm1_db @@ -48,8 +48,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -62,7 +61,7 @@ run general/parser/limit1_stb.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/limit1_stb.sim b/tests/script/general/parser/limit1_stb.sim index 3eee6132a4..d5846adc45 100644 --- a/tests/script/general/parser/limit1_stb.sim +++ b/tests/script/general/parser/limit1_stb.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = lm1_db diff --git a/tests/script/general/parser/limit1_tb.sim b/tests/script/general/parser/limit1_tb.sim index 52c4615c9f..1e473eb858 100644 --- a/tests/script/general/parser/limit1_tb.sim +++ b/tests/script/general/parser/limit1_tb.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = lm1_db diff --git a/tests/script/general/parser/limit1_tblocks100.sim b/tests/script/general/parser/limit1_tblocks100.sim index 2860305b3d..9a123e645c 100644 --- a/tests/script/general/parser/limit1_tblocks100.sim +++ b/tests/script/general/parser/limit1_tblocks100.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxVgroupsPerDb -v 1 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = lm1_db @@ -48,8 +48,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -62,7 +61,7 @@ run general/parser/limit1_stb.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/limit2.sim b/tests/script/general/parser/limit2.sim index 8ffa157945..47c3eb6d08 100644 --- a/tests/script/general/parser/limit2.sim +++ b/tests/script/general/parser/limit2.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c rowsInFileBlock -v 255 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = lm2_db @@ -69,7 +69,7 @@ print ====== tables created print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/limit2_query.sim b/tests/script/general/parser/limit2_query.sim index 327c867be4..f9a1dd8e4b 100644 --- a/tests/script/general/parser/limit2_query.sim +++ b/tests/script/general/parser/limit2_query.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = lm2_db diff --git a/tests/script/general/parser/limit2_tblocks100.sim b/tests/script/general/parser/limit2_tblocks100.sim index 2f3e30de60..1aaa8e885a 100644 --- a/tests/script/general/parser/limit2_tblocks100.sim +++ b/tests/script/general/parser/limit2_tblocks100.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c rowsInFileBlock -v 255 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = lm2_db @@ -69,7 +69,7 @@ print ====== tables created print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 1000 +sleep 500 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/limit_stb.sim b/tests/script/general/parser/limit_stb.sim index e43a78bc31..b41b7b726b 100644 --- a/tests/script/general/parser/limit_stb.sim +++ b/tests/script/general/parser/limit_stb.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = lm_db diff --git a/tests/script/general/parser/limit_tb.sim b/tests/script/general/parser/limit_tb.sim index eed78a37ec..b917627fdf 100644 --- a/tests/script/general/parser/limit_tb.sim +++ b/tests/script/general/parser/limit_tb.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = lm_db diff --git a/tests/script/general/parser/mixed_blocks.sim b/tests/script/general/parser/mixed_blocks.sim index f6744f22ab..d3558560df 100644 --- a/tests/script/general/parser/mixed_blocks.sim +++ b/tests/script/general/parser/mixed_blocks.sim @@ -5,7 +5,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = mb_db diff --git a/tests/script/general/parser/nchar.sim b/tests/script/general/parser/nchar.sim index 082a6331a6..ab4ed2607a 100644 --- a/tests/script/general/parser/nchar.sim +++ b/tests/script/general/parser/nchar.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ======================== dnode1 start diff --git a/tests/script/general/parser/null_char.sim b/tests/script/general/parser/null_char.sim index 9ac83eb779..7b1c81a295 100644 --- a/tests/script/general/parser/null_char.sim +++ b/tests/script/general/parser/null_char.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ========== NULL_char.sim @@ -251,7 +251,7 @@ endi ################### nchar sql alter table st41 set tag tag_nchar = "��˼����" sql select tag_binary, tag_nchar, tag_int, tag_bool, tag_float, tag_double from st41 -#sleep 1000 +#sleep 500 #if $data01 != ��˼���� then # print ==== expect ��˼����, actually $data01 # return -1 diff --git a/tests/script/general/parser/projection_limit_offset.sim b/tests/script/general/parser/projection_limit_offset.sim index 4cadc706d9..92ebb6fd79 100644 --- a/tests/script/general/parser/projection_limit_offset.sim +++ b/tests/script/general/parser/projection_limit_offset.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = group_db @@ -402,7 +402,7 @@ sql_error select k, sum(k)+1 from tm0; print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/selectResNum.sim b/tests/script/general/parser/selectResNum.sim index b80cfa9ce4..464f363222 100644 --- a/tests/script/general/parser/selectResNum.sim +++ b/tests/script/general/parser/selectResNum.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 200 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = sc_db @@ -50,8 +50,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -119,12 +118,12 @@ endw print ====== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 6000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ====== server restart completed -sleep 1000 +sleep 500 sql connect -sleep 1000 +sleep 500 sql use $db ##### repeat test after server restart diff --git a/tests/script/general/parser/select_across_vnodes.sim b/tests/script/general/parser/select_across_vnodes.sim index ed8c3a51eb..44e5576dac 100644 --- a/tests/script/general/parser/select_across_vnodes.sim +++ b/tests/script/general/parser/select_across_vnodes.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 5 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = sav_db diff --git a/tests/script/general/parser/select_from_cache_disk.sim b/tests/script/general/parser/select_from_cache_disk.sim index d778f20de0..0fa0848144 100644 --- a/tests/script/general/parser/select_from_cache_disk.sim +++ b/tests/script/general/parser/select_from_cache_disk.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = scd_db @@ -35,11 +35,11 @@ sql insert into $tb values ('2018-09-17 09:00:00.030', 3) print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 sql use $db # generate some data in cache diff --git a/tests/script/general/parser/select_with_tags.sim b/tests/script/general/parser/select_with_tags.sim index 68d145a5f2..dab76f6004 100644 --- a/tests/script/general/parser/select_with_tags.sim +++ b/tests/script/general/parser/select_with_tags.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = select_tags_db diff --git a/tests/script/general/parser/set_tag_vals.sim b/tests/script/general/parser/set_tag_vals.sim index 95ec4a77ec..bf29fe3902 100644 --- a/tests/script/general/parser/set_tag_vals.sim +++ b/tests/script/general/parser/set_tag_vals.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxVgroupsPerDb -v 1 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = db diff --git a/tests/script/general/parser/single_row_in_tb.sim b/tests/script/general/parser/single_row_in_tb.sim index d5b61944ef..fe1edb1f73 100644 --- a/tests/script/general/parser/single_row_in_tb.sim +++ b/tests/script/general/parser/single_row_in_tb.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = sr_db @@ -32,7 +32,7 @@ run general/parser/single_row_in_tb_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/single_row_in_tb_query.sim b/tests/script/general/parser/single_row_in_tb_query.sim index 2292e6d0a1..9e90b91220 100644 --- a/tests/script/general/parser/single_row_in_tb_query.sim +++ b/tests/script/general/parser/single_row_in_tb_query.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = sr_db diff --git a/tests/script/general/parser/sliding.sim b/tests/script/general/parser/sliding.sim index b9fd66334d..4283421169 100644 --- a/tests/script/general/parser/sliding.sim +++ b/tests/script/general/parser/sliding.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c debugFlag -v 135 system sh/cfg.sh -n dnode1 -c rpcDebugFlag -v 135 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = sliding_db diff --git a/tests/script/general/parser/slimit.sim b/tests/script/general/parser/slimit.sim index 4b5f013d31..f7a23019cf 100644 --- a/tests/script/general/parser/slimit.sim +++ b/tests/script/general/parser/slimit.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = slm_db @@ -97,11 +97,11 @@ run general/parser/slimit_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 run general/parser/slimit_query.sim diff --git a/tests/script/general/parser/slimit1.sim b/tests/script/general/parser/slimit1.sim index 9c69dd6c8b..7a2511eb76 100644 --- a/tests/script/general/parser/slimit1.sim +++ b/tests/script/general/parser/slimit1.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = slm_alt_tg_db @@ -56,11 +56,11 @@ run general/parser/slimit1_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 run general/parser/slimit1_query.sim diff --git a/tests/script/general/parser/slimit1_query.sim b/tests/script/general/parser/slimit1_query.sim index ad892fbf86..c205d45689 100644 --- a/tests/script/general/parser/slimit1_query.sim +++ b/tests/script/general/parser/slimit1_query.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = slm_alt_tg_db diff --git a/tests/script/general/parser/slimit_alter_tags.sim b/tests/script/general/parser/slimit_alter_tags.sim index 178f151475..1072f9ccb4 100644 --- a/tests/script/general/parser/slimit_alter_tags.sim +++ b/tests/script/general/parser/slimit_alter_tags.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = slm_alt_tg_db @@ -171,11 +171,11 @@ endi print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 sql use $db ### repeat above queries diff --git a/tests/script/general/parser/slimit_query.sim b/tests/script/general/parser/slimit_query.sim index dc1116405f..3020f80472 100644 --- a/tests/script/general/parser/slimit_query.sim +++ b/tests/script/general/parser/slimit_query.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = slm_db diff --git a/tests/script/general/parser/stream_on_sys.sim b/tests/script/general/parser/stream_on_sys.sim index 4032871591..1c8eb82c79 100644 --- a/tests/script/general/parser/stream_on_sys.sim +++ b/tests/script/general/parser/stream_on_sys.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c monitor -v 1 system sh/cfg.sh -n dnode1 -c monitorInterval -v 1 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ======================== stream_on_sys.sim diff --git a/tests/script/general/parser/tags_dynamically_specifiy.sim b/tests/script/general/parser/tags_dynamically_specifiy.sim index 6c79f30bd2..8303a9c86d 100644 --- a/tests/script/general/parser/tags_dynamically_specifiy.sim +++ b/tests/script/general/parser/tags_dynamically_specifiy.sim @@ -3,9 +3,9 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect -sleep 1000 +sleep 500 $db = dytag_db $tbNum = 10 diff --git a/tests/script/general/parser/tags_filter.sim b/tests/script/general/parser/tags_filter.sim index 1ba7b60cfe..c3d0fdfc61 100644 --- a/tests/script/general/parser/tags_filter.sim +++ b/tests/script/general/parser/tags_filter.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $db = tf_db diff --git a/tests/script/general/parser/tbnameIn.sim b/tests/script/general/parser/tbnameIn.sim index f1962d968f..87c4871792 100644 --- a/tests/script/general/parser/tbnameIn.sim +++ b/tests/script/general/parser/tbnameIn.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = ti_db @@ -68,7 +68,7 @@ run general/parser/tbnameIn_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/tbnameIn_query.sim b/tests/script/general/parser/tbnameIn_query.sim index 3f87d20327..ad7456f557 100644 --- a/tests/script/general/parser/tbnameIn_query.sim +++ b/tests/script/general/parser/tbnameIn_query.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = ti_db diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index 1374199548..0e12379659 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -1,113 +1,113 @@ -sleep 1000 -run general/parser/alter.sim -sleep 1000 -run general/parser/alter1.sim -sleep 1000 -run general/parser/alter_stable.sim -sleep 1000 -run general/parser/auto_create_tb.sim -sleep 1000 -run general/parser/auto_create_tb_drop_tb.sim -sleep 1000 -run general/parser/col_arithmetic_operation.sim -sleep 1000 -run general/parser/columnValue.sim -sleep 1000 -run general/parser/commit.sim -sleep 1000 -run general/parser/create_db.sim -sleep 1000 -run general/parser/create_mt.sim -sleep 1000 -run general/parser/create_tb.sim -sleep 1000 -run general/parser/dbtbnameValidate.sim -sleep 1000 -run general/parser/fill.sim -sleep 1000 -run general/parser/fill_stb.sim -sleep 1000 -#run general/parser/fill_us.sim # -sleep 1000 -run general/parser/first_last.sim -sleep 1000 -run general/parser/import_commit1.sim -sleep 1000 -run general/parser/import_commit2.sim -sleep 1000 -run general/parser/import_commit3.sim -sleep 1000 -#run general/parser/import_file.sim -sleep 1000 -run general/parser/insert_tb.sim -sleep 1000 -run general/parser/tags_dynamically_specifiy.sim -sleep 1000 -run general/parser/interp.sim -sleep 1000 -run general/parser/lastrow.sim -sleep 1000 -run general/parser/limit.sim -sleep 1000 -run general/parser/limit1.sim -sleep 1000 -run general/parser/limit1_tblocks100.sim -sleep 1000 -run general/parser/limit2.sim -sleep 1000 -run general/parser/mixed_blocks.sim -sleep 1000 -run general/parser/nchar.sim -sleep 1000 -run general/parser/null_char.sim -sleep 1000 -run general/parser/selectResNum.sim -sleep 1000 +#sleep 500 +#run general/parser/alter.sim +#sleep 500 +#run general/parser/alter1.sim +#sleep 500 +#run general/parser/alter_stable.sim +#sleep 500 +#run general/parser/auto_create_tb.sim +#sleep 500 +#run general/parser/auto_create_tb_drop_tb.sim +#sleep 500 +#run general/parser/col_arithmetic_operation.sim +#sleep 500 +#run general/parser/columnValue.sim +#sleep 500 +#run general/parser/commit.sim +#sleep 500 +#run general/parser/create_db.sim +#sleep 500 +#run general/parser/create_mt.sim +#sleep 500 +#run general/parser/create_tb.sim +#sleep 500 +#run general/parser/dbtbnameValidate.sim +#sleep 500 +#run general/parser/fill.sim +#sleep 500 +#run general/parser/fill_stb.sim +#sleep 500 +##run general/parser/fill_us.sim # +#sleep 500 +#run general/parser/first_last.sim +#sleep 500 +#run general/parser/import_commit1.sim +#sleep 500 +#run general/parser/import_commit2.sim +#sleep 500 +#run general/parser/import_commit3.sim +#sleep 500 +##run general/parser/import_file.sim +#sleep 500 +#run general/parser/insert_tb.sim +#sleep 500 +#run general/parser/tags_dynamically_specifiy.sim +#sleep 500 +#run general/parser/interp.sim +#sleep 500 +#run general/parser/lastrow.sim +#sleep 500 +#run general/parser/limit.sim +#sleep 500 +#run general/parser/limit1.sim +#sleep 500 +#run general/parser/limit1_tblocks100.sim +#sleep 500 +#run general/parser/limit2.sim +#sleep 500 +#run general/parser/mixed_blocks.sim +#sleep 500 +#run general/parser/nchar.sim +#sleep 500 +#run general/parser/null_char.sim +#sleep 500 +#run general/parser/selectResNum.sim +sleep 500 run general/parser/select_across_vnodes.sim -sleep 1000 +sleep 500 run general/parser/select_from_cache_disk.sim -sleep 1000 +sleep 500 run general/parser/set_tag_vals.sim -sleep 1000 +sleep 500 run general/parser/single_row_in_tb.sim -sleep 1000 +sleep 500 run general/parser/slimit.sim -sleep 1000 +sleep 500 run general/parser/slimit1.sim -sleep 1000 +sleep 500 run general/parser/slimit_alter_tags.sim -sleep 1000 +sleep 500 run general/parser/tbnameIn.sim -sleep 1000 +sleep 500 run general/parser/slimit_alter_tags.sim # persistent failed -sleep 1000 +sleep 500 run general/parser/join.sim -sleep 1000 +sleep 500 run general/parser/join_multivnode.sim -sleep 1000 +sleep 500 run general/parser/projection_limit_offset.sim -sleep 1000 +sleep 500 run general/parser/select_with_tags.sim -sleep 1000 +sleep 500 run general/parser/groupby.sim -sleep 1000 +sleep 500 run general/parser/tags_filter.sim -sleep 1000 +sleep 500 run general/parser/topbot.sim -sleep 1000 +sleep 500 run general/parser/union.sim -sleep 1000 +sleep 500 run general/parser/constCol.sim -sleep 1000 +sleep 500 run general/parser/where.sim -sleep 1000 +sleep 500 run general/parser/timestamp.sim -sleep 1000 +sleep 500 run general/parser/sliding.sim -#sleep 1000 +#sleep 500 #run general/parser/repeatStream.sim -#sleep 1000 +#sleep 500 #run general/parser/stream_on_sys.sim -#sleep 1000 +#sleep 500 #run general/parser/stream.sim \ No newline at end of file diff --git a/tests/script/general/parser/timestamp.sim b/tests/script/general/parser/timestamp.sim index 4603e23813..72966459d0 100644 --- a/tests/script/general/parser/timestamp.sim +++ b/tests/script/general/parser/timestamp.sim @@ -5,7 +5,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = ts_db @@ -59,10 +59,10 @@ run general/parser/timestamp_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 1000 +sleep 500 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 run general/parser/timestamp_query.sim diff --git a/tests/script/general/parser/timestamp_query.sim b/tests/script/general/parser/timestamp_query.sim index ab892c0287..056e8bba6b 100644 --- a/tests/script/general/parser/timestamp_query.sim +++ b/tests/script/general/parser/timestamp_query.sim @@ -1,4 +1,4 @@ -sleep 1000 +sleep 500 sql connect $dbPrefix = ts_db diff --git a/tests/script/general/parser/topbot.sim b/tests/script/general/parser/topbot.sim index c2b41888d7..08e2f6ab00 100644 --- a/tests/script/general/parser/topbot.sim +++ b/tests/script/general/parser/topbot.sim @@ -5,7 +5,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 200 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = tb_db @@ -128,11 +128,11 @@ sql insert into test values(29999, 1)(70000, 2)(80000, 3) print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 sql select count(*) from t1.test where ts>10000 and ts<90000 interval(5000a) if $rows != 3 then @@ -169,7 +169,7 @@ endw system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start sql connect -sleep 1000 +sleep 500 sql use db; $ts = 1000 @@ -221,7 +221,7 @@ sql insert into t2 values('2020-2-2 1:1:1', 1); system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start sql connect -sleep 1000 +sleep 500 sql use db sql select count(*), first(ts), last(ts) from t2 interval(1d); diff --git a/tests/script/general/parser/union.sim b/tests/script/general/parser/union.sim index 024b9c76ef..d779d75731 100644 --- a/tests/script/general/parser/union.sim +++ b/tests/script/general/parser/union.sim @@ -7,7 +7,7 @@ system sh/cfg.sh -n dnode1 -c rpcDebugFlag -v 135 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = union_db @@ -96,7 +96,7 @@ while $i < $tbNum endw print sleep 1sec. -sleep 1000 +sleep 500 $i = 1 $tb = $tbPrefix . $i diff --git a/tests/script/general/parser/where.sim b/tests/script/general/parser/where.sim index 3ea354f4da..4a38e3c68c 100644 --- a/tests/script/general/parser/where.sim +++ b/tests/script/general/parser/where.sim @@ -5,7 +5,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = wh_db From a29327ef42e3290909c77421b9fe66ab099ef540 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 13:44:47 +0800 Subject: [PATCH 81/85] [TD-225] --- src/client/src/tscLocalMerge.c | 4 +-- src/client/src/tscSql.c | 47 +++------------------------------- src/client/src/tscSubquery.c | 6 ++--- 3 files changed, 8 insertions(+), 49 deletions(-) diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index 5133309e8c..839f6474b3 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -884,11 +884,11 @@ static void genFinalResWithoutFill(SSqlRes* pRes, SLocalReducer *pLocalReducer, tFilePage * pBeforeFillData = pLocalReducer->pResultBuf; pRes->data = pLocalReducer->pFinalRes; - pRes->numOfRows = pBeforeFillData->num; + pRes->numOfRows = (int32_t) pBeforeFillData->num; if (pQueryInfo->limit.offset > 0) { if (pQueryInfo->limit.offset < pRes->numOfRows) { - int32_t prevSize = (int32_t)pBeforeFillData->num; + int32_t prevSize = (int32_t) pBeforeFillData->num; tColModelErase(pLocalReducer->finalModel, pBeforeFillData, prevSize, 0, (int32_t)pQueryInfo->limit.offset - 1); /* remove the hole in column model */ diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index fa4dcd1a76..a4ac9b9d92 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -394,7 +394,7 @@ int taos_affected_rows(TAOS_RES *tres) { SSqlObj* pSql = (SSqlObj*) tres; if (pSql == NULL || pSql->signature != pSql) return 0; - return (int)(pSql->res.numOfRows); + return pSql->res.numOfRows; } TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) { @@ -440,53 +440,12 @@ int taos_retrieve(TAOS_RES *res) { tscResetForNextRetrieve(pRes); - if (pCmd->command < TSDB_SQL_LOCAL) { - pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH; - } - tscProcessSql(pSql); - - return (int)pRes->numOfRows; -} - -int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) { - SSqlObj *pSql = (SSqlObj *)res; - SSqlCmd *pCmd = &pSql->cmd; - SSqlRes *pRes = &pSql->res; - - if (pRes->qhandle == 0 || pSql->signature != pSql) { - *rows = NULL; - return 0; - } - - // Retrieve new block - tscResetForNextRetrieve(pRes); if (pCmd->command < TSDB_SQL_LOCAL) { pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH; } tscProcessSql(pSql); - if (pRes->numOfRows == 0) { - *rows = NULL; - return 0; - } - - // secondary merge has handle this situation - if (pCmd->command != TSDB_SQL_RETRIEVE_LOCALMERGE) { - pRes->numOfClauseTotal += pRes->numOfRows; - } - - SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0); - if (pQueryInfo == NULL) - return 0; - - assert(0); - for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { - tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i, 0); - } - - *rows = pRes->tsrow; - - return (int)((pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows); + return pRes->numOfRows; } static bool needToFetchNewBlock(SSqlObj* pSql) { @@ -573,7 +532,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) { *rows = pRes->urow; tscClearSqlOwner(pSql); - return (int32_t) pRes->numOfRows; + return pRes->numOfRows; } int taos_select_db(TAOS *taos, const char *db) { diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index 4f2d98433b..7066477aed 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -948,7 +948,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow if (!pRes->completed) { taosGetTmpfilePath("ts-join", pSupporter->path); pSupporter->f = fopen(pSupporter->path, "w"); - pRes->row = (int32_t)pRes->numOfRows; + pRes->row = pRes->numOfRows; taos_fetch_rows_a(tres, tsCompRetrieveCallback, param); return; @@ -974,7 +974,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow // TODO check for failure pSupporter->f = fopen(pSupporter->path, "w"); - pRes->row = (int32_t)pRes->numOfRows; + pRes->row = pRes->numOfRows; // set the callback function pSql->fp = tscJoinQueryCallback; @@ -2059,7 +2059,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR } int32_t ret = saveToBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pRes->data, - (int32_t)pRes->numOfRows, pQueryInfo->groupbyExpr.orderType); + pRes->numOfRows, pQueryInfo->groupbyExpr.orderType); if (ret != 0) { // set no disk space error info, and abort retry tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE); } else if (pRes->completed) { From af8f4bb2362d566c6bf9294367803acec9699c1e Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 19 Nov 2020 13:53:56 +0800 Subject: [PATCH 82/85] [TD-225] --- src/client/src/tscLocalMerge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index 839f6474b3..3c7d46f914 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -894,7 +894,7 @@ static void genFinalResWithoutFill(SSqlRes* pRes, SLocalReducer *pLocalReducer, /* remove the hole in column model */ tColModelCompact(pLocalReducer->finalModel, pBeforeFillData, prevSize); - pRes->numOfRows -= pQueryInfo->limit.offset; + pRes->numOfRows -= (int32_t) pQueryInfo->limit.offset; pQueryInfo->limit.offset = 0; } else { pQueryInfo->limit.offset -= pRes->numOfRows; @@ -962,7 +962,7 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO } pRes->data = pLocalReducer->pFinalRes; - pRes->numOfRows = newRows; + pRes->numOfRows = (int32_t) newRows; pQueryInfo->limit.offset = 0; break; From 182328eba981ddea7051537505047c7dec520968 Mon Sep 17 00:00:00 2001 From: zyyang-taosdata Date: Thu, 19 Nov 2020 06:43:56 +0000 Subject: [PATCH 83/85] [TD-2156]: change packaging scripts for aarch32 --- packaging/tools/install.sh | 2 +- packaging/tools/install_client.sh | 2 +- src/client/src/tscSubquery.c | 6 +++--- src/connector/grafanaplugin | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packaging/tools/install.sh b/packaging/tools/install.sh index aedfb0a683..ddf7114f08 100755 --- a/packaging/tools/install.sh +++ b/packaging/tools/install.sh @@ -312,7 +312,7 @@ function install_data() { } function install_connector() { - ${csudo} cp -rf ${script_dir}/connector/* ${install_main_dir}/connector + ${csudo} cp -rf ${script_dir}/connector/ ${install_main_dir}/ } function install_examples() { diff --git a/packaging/tools/install_client.sh b/packaging/tools/install_client.sh index 24586d3390..34a9bfaecb 100755 --- a/packaging/tools/install_client.sh +++ b/packaging/tools/install_client.sh @@ -163,7 +163,7 @@ function install_log() { } function install_connector() { - ${csudo} cp -rf ${script_dir}/connector/* ${install_main_dir}/connector + ${csudo} cp -rf ${script_dir}/connector/ ${install_main_dir}/ } function install_examples() { diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index 7066477aed..3f475f648d 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -594,7 +594,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr if (taosArrayGetSize(result) > 0) { SVgroupTableInfo* prevGroup = taosArrayGet(result, taosArrayGetSize(result) - 1); - tscDebug("%p vgId:%d, tables:%"PRId64, pSql, prevGroup->vgInfo.vgId, taosArrayGetSize(prevGroup->itemList)); + tscDebug("%p vgId:%d, tables:%u", pSql, prevGroup->vgInfo.vgId, taosArrayGetSize(prevGroup->itemList)); } taosArrayPush(result, &info); @@ -612,7 +612,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr if (taosArrayGetSize(result) > 0) { SVgroupTableInfo* g = taosArrayGet(result, taosArrayGetSize(result) - 1); - tscDebug("%p vgId:%d, tables:%"PRId64, pSql, g->vgInfo.vgId, taosArrayGetSize(g->itemList)); + tscDebug("%p vgId:%d, tables:%u", pSql, g->vgInfo.vgId, taosArrayGetSize(g->itemList)); } } @@ -753,7 +753,7 @@ static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pPar } #endif - tscDebug("%p tags match complete, result: %"PRId64", %"PRId64, pParentSql, t1, t2); + tscDebug("%p tags match complete, result: %u, %u", pParentSql, t1, t2); return TSDB_CODE_SUCCESS; } diff --git a/src/connector/grafanaplugin b/src/connector/grafanaplugin index d598db167e..ec77d9049a 160000 --- a/src/connector/grafanaplugin +++ b/src/connector/grafanaplugin @@ -1 +1 @@ -Subproject commit d598db167eb256fe67409b7bb3d0eb7fffc3ff8c +Subproject commit ec77d9049a719dabfd1a7c1122a209e201861944 From cd6bb16a0bf9d99fb544aa268cd4fd3f55b9dae7 Mon Sep 17 00:00:00 2001 From: plum-lihui Date: Thu, 19 Nov 2020 15:44:29 +0800 Subject: [PATCH 84/85] change packaging scripts --- src/client/src/tscSubquery.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index 3f475f648d..6ebbeeef41 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -594,7 +594,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr if (taosArrayGetSize(result) > 0) { SVgroupTableInfo* prevGroup = taosArrayGet(result, taosArrayGetSize(result) - 1); - tscDebug("%p vgId:%d, tables:%u", pSql, prevGroup->vgInfo.vgId, taosArrayGetSize(prevGroup->itemList)); + tscDebug("%p vgId:%d, tables:%"PRIzu, pSql, prevGroup->vgInfo.vgId, taosArrayGetSize(prevGroup->itemList)); } taosArrayPush(result, &info); @@ -612,7 +612,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr if (taosArrayGetSize(result) > 0) { SVgroupTableInfo* g = taosArrayGet(result, taosArrayGetSize(result) - 1); - tscDebug("%p vgId:%d, tables:%u", pSql, g->vgInfo.vgId, taosArrayGetSize(g->itemList)); + tscDebug("%p vgId:%d, tables:%"PRIzu, pSql, g->vgInfo.vgId, taosArrayGetSize(g->itemList)); } } @@ -753,7 +753,7 @@ static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pPar } #endif - tscDebug("%p tags match complete, result: %u, %u", pParentSql, t1, t2); + tscDebug("%p tags match complete, result: %"PRIzu", %"PRIzu, pParentSql, t1, t2); return TSDB_CODE_SUCCESS; } From 727ed76d0059a285ff8ea11e6bfc83355abadc08 Mon Sep 17 00:00:00 2001 From: Hui Li Date: Thu, 19 Nov 2020 15:49:39 +0800 Subject: [PATCH 85/85] [temp not compile odbc] --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f619edd221..a2600785c3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,6 @@ ADD_SUBDIRECTORY(tsdb) ADD_SUBDIRECTORY(wal) ADD_SUBDIRECTORY(cq) ADD_SUBDIRECTORY(dnode) -ADD_SUBDIRECTORY(connector/odbc) +#ADD_SUBDIRECTORY(connector/odbc) ADD_SUBDIRECTORY(connector/jdbc)