diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index 4a9007acec..37edc739e4 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -15,6 +15,7 @@ IF (TD_LINUX) add_executable(tmq "") add_executable(stream_demo "") add_executable(demoapi "") + add_executable(api_reqid "") target_sources(tmq PRIVATE @@ -31,6 +32,12 @@ IF (TD_LINUX) "demoapi.c" ) + target_sources(api_reqid + PRIVATE + "api_with_reqid_test.c" + ) + + target_link_libraries(tmq taos_static ) @@ -43,6 +50,11 @@ IF (TD_LINUX) taos_static ) + target_link_libraries(api_reqid + taos_static + ) + + target_include_directories(tmq PUBLIC "${TD_SOURCE_DIR}/include/os" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" @@ -58,9 +70,16 @@ IF (TD_LINUX) PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" ) + target_include_directories(api_reqid + PUBLIC "${TD_SOURCE_DIR}/include/client" + PUBLIC "${TD_SOURCE_DIR}/include/os" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" + ) + SET_TARGET_PROPERTIES(tmq PROPERTIES OUTPUT_NAME tmq) SET_TARGET_PROPERTIES(stream_demo PROPERTIES OUTPUT_NAME stream_demo) SET_TARGET_PROPERTIES(demoapi PROPERTIES OUTPUT_NAME demoapi) + SET_TARGET_PROPERTIES(api_reqid PROPERTIES OUTPUT_NAME api_reqid) ENDIF () IF (TD_DARWIN) INCLUDE_DIRECTORIES(. ${TD_SOURCE_DIR}/src/inc ${TD_SOURCE_DIR}/src/client/inc ${TD_SOURCE_DIR}/inc) diff --git a/examples/c/api_with_reqid_test.c b/examples/c/api_with_reqid_test.c new file mode 100644 index 0000000000..003639ba00 --- /dev/null +++ b/examples/c/api_with_reqid_test.c @@ -0,0 +1,449 @@ +// sample code to verify all TDengine API +// to compile: gcc -o apitest apitest.c -ltaos + +#include +#include +#include +#include +#include "taos.h" +static int64_t count = 10000; + +int64_t genReqid() { + count += 100; + return count; +} +static void prepare_data(TAOS* taos) { + TAOS_RES* result; + result = taos_query_with_reqid(taos, "drop database if exists test;", genReqid()); + taos_free_result(result); + usleep(100000); + result = taos_query_with_reqid(taos, "create database test precision 'us';", genReqid()); + taos_free_result(result); + usleep(100000); + taos_select_db(taos, "test"); + + result = taos_query_with_reqid(taos, "create table meters(ts timestamp, a int) tags(area int);", genReqid()); + taos_free_result(result); + + result = taos_query_with_reqid(taos, "create table t0 using meters tags(0);", genReqid()); + taos_free_result(result); + result = taos_query_with_reqid(taos, "create table t1 using meters tags(1);", genReqid()); + taos_free_result(result); + result = taos_query_with_reqid(taos, "create table t2 using meters tags(2);", genReqid()); + taos_free_result(result); + result = taos_query_with_reqid(taos, "create table t3 using meters tags(3);", genReqid()); + taos_free_result(result); + result = taos_query_with_reqid(taos, "create table t4 using meters tags(4);", genReqid()); + taos_free_result(result); + result = taos_query_with_reqid(taos, "create table t5 using meters tags(5);", genReqid()); + taos_free_result(result); + result = taos_query_with_reqid(taos, "create table t6 using meters tags(6);", genReqid()); + taos_free_result(result); + result = taos_query_with_reqid(taos, "create table t7 using meters tags(7);", genReqid()); + taos_free_result(result); + result = taos_query_with_reqid(taos, "create table t8 using meters tags(8);", genReqid()); + taos_free_result(result); + result = taos_query(taos, "create table t9 using meters tags(9);"); + taos_free_result(result); + + result = taos_query_with_reqid(taos, + "insert into t0 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:02:00.000', 0)" + " t1 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:02:00.000', 0)" + " ('2020-01-01 00:03:00.000', 0)" + " t2 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:01:01.000', 0)" + " ('2020-01-01 00:01:02.000', 0)" + " t3 values('2020-01-01 00:01:02.000', 0)" + " t4 values('2020-01-01 00:01:02.000', 0)" + " t5 values('2020-01-01 00:01:02.000', 0)" + " t6 values('2020-01-01 00:01:02.000', 0)" + " t7 values('2020-01-01 00:01:02.000', 0)" + " t8 values('2020-01-01 00:01:02.000', 0)" + " t9 values('2020-01-01 00:01:02.000', 0)", + genReqid()); + int affected = taos_affected_rows(result); + if (affected != 18) { + printf("\033[31m%d rows affected by last insert statement, but it should be 18\033[0m\n", affected); + } + taos_free_result(result); + // super tables subscription + usleep(1000000); +} + +static int print_result(TAOS_RES* res, int blockFetch) { + TAOS_ROW row = NULL; + int num_fields = taos_num_fields(res); + TAOS_FIELD* fields = taos_fetch_fields(res); + int nRows = 0; + + if (blockFetch) { + int rows = 0; + while ((rows = taos_fetch_block(res, &row))) { + // for (int i = 0; i < rows; i++) { + // char temp[256]; + // taos_print_row(temp, row + i, fields, num_fields); + // puts(temp); + // } + nRows += rows; + } + } else { + while ((row = taos_fetch_row(res))) { + char temp[256] = {0}; + taos_print_row(temp, row, fields, num_fields); + puts(temp); + nRows++; + } + } + + printf("%d rows consumed.\n", nRows); + return nRows; +} + +static void check_row_count(int line, TAOS_RES* res, int expected) { + int actual = print_result(res, expected % 2); + if (actual != expected) { + printf("\033[31mline %d: row count mismatch, expected: %d, actual: %d\033[0m\n", line, expected, actual); + } else { + printf("line %d: %d rows consumed as expected\n", line, actual); + } +} + +static void verify_query(TAOS* taos) { + prepare_data(taos); + + int code = taos_load_table_info(taos, "t0,t1,t2,t3,t4,t5,t6,t7,t8,t9"); + if (code != 0) { + printf("\033[31mfailed to load table info: 0x%08x\033[0m\n", code); + } + + code = taos_validate_sql(taos, "select * from nonexisttable"); + if (code == 0) { + printf("\033[31mimpossible, the table does not exists\033[0m\n"); + } + + code = taos_validate_sql(taos, "select * from meters"); + if (code != 0) { + printf("\033[31mimpossible, the table does exists: 0x%08x\033[0m\n", code); + } + + TAOS_RES* res = taos_query_with_reqid(taos, "select * from meters", genReqid()); + check_row_count(__LINE__, res, 18); + printf("result precision is: %d\n", taos_result_precision(res)); + int c = taos_field_count(res); + printf("field count is: %d\n", c); + int* lengths = taos_fetch_lengths(res); + for (int i = 0; i < c; i++) { + printf("length of column %d is %d\n", i, lengths[i]); + } + taos_free_result(res); + + res = taos_query_with_reqid(taos, "select * from t0", genReqid()); + check_row_count(__LINE__, res, 3); + taos_free_result(res); + + res = taos_query_with_reqid(taos, "select * from nonexisttable", genReqid()); + code = taos_errno(res); + printf("code=%d, error msg=%s\n", code, taos_errstr(res)); + taos_free_result(res); + + res = taos_query_with_reqid(taos, "select * from meters", genReqid()); + taos_stop_query(res); + taos_free_result(res); +} + +void retrieve_callback(void* param, TAOS_RES* tres, int numOfRows) { + if (numOfRows > 0) { + printf("%d rows async retrieved\n", numOfRows); + taos_fetch_rows_a(tres, retrieve_callback, param); + } else { + if (numOfRows < 0) { + printf("\033[31masync retrieve failed, code: %d\033[0m\n", numOfRows); + } else { + printf("async retrieve completed\n"); + } + taos_free_result(tres); + } +} + +void select_callback(void* param, TAOS_RES* tres, int code) { + if (code == 0 && tres) { + taos_fetch_rows_a(tres, retrieve_callback, param); + } else { + printf("\033[31masync select failed, code: %d\033[0m\n", code); + } +} + +void verify_async(TAOS* taos) { + prepare_data(taos); + taos_query_a_with_reqid(taos, "select * from meters", select_callback, NULL, genReqid()); + usleep(1000000); +} + +int32_t verify_schema_less(TAOS* taos) { + TAOS_RES* result; + result = taos_query_with_reqid(taos, "drop database if exists test;", genReqid()); + taos_free_result(result); + usleep(100000); + result = taos_query_with_reqid(taos, "create database test precision 'us' update 1;", genReqid()); + taos_free_result(result); + usleep(100000); + + taos_select_db(taos, "test"); + result = taos_query_with_reqid(taos, "create stable ste(ts timestamp, f int) tags(t1 bigint)", genReqid()); + taos_free_result(result); + usleep(100000); + + int code = 0; + + char* lines[] = { + "st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", + "st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000ns", + "ste,t2=5f64,t3=L\"ste\" c1=true,c2=4i64,c3=\"iam\" 1626056811823316532ns", + "st,t1=4i64,t2=5f64,t3=\"t4\" c1=3i64,c3=L\"passitagain\",c2=true,c4=5f64 1626006833642000000ns", + "ste,t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false 1626056811843316532ns", + "ste,t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false,c5=32i8,c6=64i16,c7=32i32,c8=88.88f32 1626056812843316532ns", + "st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 " + "1626006933640000000ns", + "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 " + "1626006933640000000ns", + "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 " + "1626006933641000000ns"}; + + taos_select_db(taos, "test"); + + TAOS_RES* res = taos_schemaless_insert_with_reqid(taos, lines, sizeof(lines) / sizeof(char*), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_NOT_CONFIGURED, genReqid()); + if (taos_errno(res) != 0) { + printf("failed to insert schema-less data, reason: %s\n", taos_errstr(res)); + } else { + int affectedRow = taos_affected_rows(res); + printf("successfully inserted %d rows\n", affectedRow); + } + taos_free_result(res); + + return (code); +} + +void veriry_stmt(TAOS* taos) { + TAOS_RES* result = taos_query(taos, "drop database if exists test;"); + taos_free_result(result); + usleep(100000); + result = taos_query(taos, "create database test;"); + + int code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + return; + } + taos_free_result(result); + + usleep(100000); + taos_select_db(taos, "test"); + + // create table + const char* sql = + "create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin " + "binary(40), blob nchar(10))"; + result = taos_query(taos, sql); + code = taos_errno(result); + if (code != 0) { + printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result)); + taos_free_result(result); + return; + } + taos_free_result(result); + + // insert 10 records + struct { + int64_t ts[10]; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + char blob[10][80]; + } v; + + int32_t* t8_len = malloc(sizeof(int32_t) * 10); + int32_t* t16_len = malloc(sizeof(int32_t) * 10); + int32_t* t32_len = malloc(sizeof(int32_t) * 10); + int32_t* t64_len = malloc(sizeof(int32_t) * 10); + int32_t* float_len = malloc(sizeof(int32_t) * 10); + int32_t* double_len = malloc(sizeof(int32_t) * 10); + int32_t* bin_len = malloc(sizeof(int32_t) * 10); + int32_t* blob_len = malloc(sizeof(int32_t) * 10); + + TAOS_STMT* stmt = taos_stmt_init_with_reqid(taos, genReqid()); + TAOS_MULTI_BIND params[10]; + char is_null[10] = {0}; + + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[0].buffer_length = sizeof(v.ts[0]); + params[0].buffer = v.ts; + params[0].length = t64_len; + params[0].is_null = is_null; + params[0].num = 10; + + params[1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[1].buffer_length = sizeof(v.b[0]); + params[1].buffer = v.b; + params[1].length = t8_len; + params[1].is_null = is_null; + params[1].num = 10; + + params[2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[2].buffer_length = sizeof(v.v1[0]); + params[2].buffer = v.v1; + params[2].length = t8_len; + params[2].is_null = is_null; + params[2].num = 10; + + params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[3].buffer_length = sizeof(v.v2[0]); + params[3].buffer = v.v2; + params[3].length = t16_len; + params[3].is_null = is_null; + params[3].num = 10; + + params[4].buffer_type = TSDB_DATA_TYPE_INT; + params[4].buffer_length = sizeof(v.v4[0]); + params[4].buffer = v.v4; + params[4].length = t32_len; + params[4].is_null = is_null; + params[4].num = 10; + + params[5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[5].buffer_length = sizeof(v.v8[0]); + params[5].buffer = v.v8; + params[5].length = t64_len; + params[5].is_null = is_null; + params[5].num = 10; + + params[6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[6].buffer_length = sizeof(v.f4[0]); + params[6].buffer = v.f4; + params[6].length = float_len; + params[6].is_null = is_null; + params[6].num = 10; + + params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[7].buffer_length = sizeof(v.f8[0]); + params[7].buffer = v.f8; + params[7].length = double_len; + params[7].is_null = is_null; + params[7].num = 10; + + params[8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[8].buffer_length = sizeof(v.bin[0]); + params[8].buffer = v.bin; + params[8].length = bin_len; + params[8].is_null = is_null; + params[8].num = 10; + + params[9].buffer_type = TSDB_DATA_TYPE_NCHAR; + params[9].buffer_length = sizeof(v.blob[0]); + params[9].buffer = v.blob; + params[9].length = blob_len; + params[9].is_null = is_null; + params[9].num = 10; + + sql = "insert into ? (ts, b, v1, v2, v4, v8, f4, f8, bin, blob) values(?,?,?,?,?,?,?,?,?,?)"; + code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0) { + printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + return; + } + + code = taos_stmt_set_tbname(stmt, "m1"); + if (code != 0) { + printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + return; + } + + int64_t ts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts[i] = ts++; + is_null[i] = 0; + + v.b[i] = (int8_t)i % 2; + v.v1[i] = (int8_t)i; + v.v2[i] = (int16_t)(i * 2); + v.v4[i] = (int32_t)(i * 4); + v.v8[i] = (int64_t)(i * 8); + v.f4[i] = (float)(i * 40); + v.f8[i] = (double)(i * 80); + for (int j = 0; j < sizeof(v.bin[0]); ++j) { + v.bin[i][j] = (char)(i + '0'); + } + strcpy(v.blob[i], "一二三四五六七八九十"); + + t8_len[i] = sizeof(int8_t); + t16_len[i] = sizeof(int16_t); + t32_len[i] = sizeof(int32_t); + t64_len[i] = sizeof(int64_t); + float_len[i] = sizeof(float); + double_len[i] = sizeof(double); + bin_len[i] = sizeof(v.bin[0]); + blob_len[i] = (int32_t)strlen(v.blob[i]); + } + + taos_stmt_bind_param_batch(stmt, params); + taos_stmt_add_batch(stmt); + + if (taos_stmt_execute(stmt) != 0) { + printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); + taos_stmt_close(stmt); + return; + } + + taos_stmt_close(stmt); + + free(t8_len); + free(t16_len); + free(t32_len); + free(t64_len); + free(float_len); + free(double_len); + free(bin_len); + free(blob_len); +} + +int main(int argc, char* argv[]) { + const char* host = "127.0.0.1"; + const char* user = "root"; + const char* passwd = "taosdata"; + + taos_options(TSDB_OPTION_TIMEZONE, "GMT-8"); + TAOS* taos = taos_connect(host, user, passwd, "", 0); + if (taos == NULL) { + printf("\033[31mfailed to connect to db, reason:%s\033[0m\n", taos_errstr(taos)); + exit(1); + } + + printf("************ verify schema-less *************\n"); + verify_schema_less(taos); + + printf("************ verify query *************\n"); + verify_query(taos); + + printf("********* verify async query **********\n"); + verify_async(taos); + + printf("********* verify stmt query **********\n"); + veriry_stmt(taos); + + printf("done\n"); + taos_close(taos); + taos_cleanup(); +} diff --git a/examples/c/apitest.c b/examples/c/apitest.c index 9f4c7678ec..c179acaf4e 100644 --- a/examples/c/apitest.c +++ b/examples/c/apitest.c @@ -1,8 +1,8 @@ // sample code to verify all TDengine API // to compile: gcc -o apitest apitest.c -ltaos -#include "taoserror.h" #include "cJSON.h" +#include "taoserror.h" #include #include @@ -11,7 +11,7 @@ #include "../../../include/client/taos.h" static void prepare_data(TAOS* taos) { - TAOS_RES *result; + TAOS_RES* result; result = taos_query(taos, "drop database if exists test;"); taos_free_result(result); usleep(100000); @@ -44,24 +44,25 @@ static void prepare_data(TAOS* taos) { result = taos_query(taos, "create table t9 using meters tags(9);"); taos_free_result(result); - result = taos_query(taos, "insert into t0 values('2020-01-01 00:00:00.000', 0)" - " ('2020-01-01 00:01:00.000', 0)" - " ('2020-01-01 00:02:00.000', 0)" - " t1 values('2020-01-01 00:00:00.000', 0)" - " ('2020-01-01 00:01:00.000', 0)" - " ('2020-01-01 00:02:00.000', 0)" - " ('2020-01-01 00:03:00.000', 0)" - " t2 values('2020-01-01 00:00:00.000', 0)" - " ('2020-01-01 00:01:00.000', 0)" - " ('2020-01-01 00:01:01.000', 0)" - " ('2020-01-01 00:01:02.000', 0)" - " t3 values('2020-01-01 00:01:02.000', 0)" - " t4 values('2020-01-01 00:01:02.000', 0)" - " t5 values('2020-01-01 00:01:02.000', 0)" - " t6 values('2020-01-01 00:01:02.000', 0)" - " t7 values('2020-01-01 00:01:02.000', 0)" - " t8 values('2020-01-01 00:01:02.000', 0)" - " t9 values('2020-01-01 00:01:02.000', 0)"); + result = taos_query(taos, + "insert into t0 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:02:00.000', 0)" + " t1 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:02:00.000', 0)" + " ('2020-01-01 00:03:00.000', 0)" + " t2 values('2020-01-01 00:00:00.000', 0)" + " ('2020-01-01 00:01:00.000', 0)" + " ('2020-01-01 00:01:01.000', 0)" + " ('2020-01-01 00:01:02.000', 0)" + " t3 values('2020-01-01 00:01:02.000', 0)" + " t4 values('2020-01-01 00:01:02.000', 0)" + " t5 values('2020-01-01 00:01:02.000', 0)" + " t6 values('2020-01-01 00:01:02.000', 0)" + " t7 values('2020-01-01 00:01:02.000', 0)" + " t8 values('2020-01-01 00:01:02.000', 0)" + " t9 values('2020-01-01 00:01:02.000', 0)"); int affected = taos_affected_rows(result); if (affected != 18) { printf("\033[31m%d rows affected by last insert statement, but it should be 18\033[0m\n", affected); @@ -80,11 +81,11 @@ static int print_result(TAOS_RES* res, int blockFetch) { if (blockFetch) { int rows = 0; while ((rows = taos_fetch_block(res, &row))) { - //for (int i = 0; i < rows; i++) { - // char temp[256]; - // taos_print_row(temp, row + i, fields, num_fields); - // puts(temp); - //} + // for (int i = 0; i < rows; i++) { + // char temp[256]; + // taos_print_row(temp, row + i, fields, num_fields); + // puts(temp); + // } nRows += rows; } } else { @@ -127,32 +128,32 @@ static void verify_query(TAOS* taos) { printf("\033[31mimpossible, the table does exists: 0x%08x\033[0m\n", code); } - TAOS_RES* res = taos_query(taos, "select * from meters"); + TAOS_RES* res = taos_query_with_reqid(taos, "select * from meters", genReqid()); check_row_count(__LINE__, res, 18); - printf("result precision is: %d\n", taos_result_precision(res)); + printf("result precision is: %d\n", taos_result_precision(res)); int c = taos_field_count(res); - printf("field count is: %d\n", c); + printf("field count is: %d\n", c); int* lengths = taos_fetch_lengths(res); for (int i = 0; i < c; i++) { printf("length of column %d is %d\n", i, lengths[i]); } taos_free_result(res); - res = taos_query(taos, "select * from t0"); + res = taos_query_with_reqid(taos, "select * from t0", genReqid()); check_row_count(__LINE__, res, 3); taos_free_result(res); - res = taos_query(taos, "select * from nonexisttable"); + res = taos_query_with_reqid(taos, "select * from nonexisttable", genReqid()); code = taos_errno(res); printf("code=%d, error msg=%s\n", code, taos_errstr(res)); taos_free_result(res); - res = taos_query(taos, "select * from meters"); + res = taos_query_with_reqid(taos, "select * from meters", genReqid()); taos_stop_query(res); taos_free_result(res); } -void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) { +void subscribe_callback(TAOS_SUB* tsub, TAOS_RES* res, void* param, int code) { int rows = print_result(res, *(int*)param); printf("%d rows consumed in subscribe_callback\n", rows); } @@ -167,7 +168,7 @@ static void verify_subscribe(TAOS* taos) { res = taos_consume(tsub); check_row_count(__LINE__, res, 0); - TAOS_RES *result; + TAOS_RES* result; result = taos_query(taos, "insert into t0 values('2020-01-01 00:02:00.001', 0);"); taos_free_result(result); result = taos_query(taos, "insert into t8 values('2020-01-01 00:01:03.000', 0);"); @@ -253,8 +254,10 @@ void verify_prepare(TAOS* taos) { taos_select_db(taos, "test"); // create table - const char* sql = "create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))"; - result = taos_query(taos, sql); + const char* sql = + "create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin " + "binary(40), blob nchar(10))"; + result = taos_query_with_reqid(taos, sql, genReqid()); code = taos_errno(result); if (code != 0) { printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result)); @@ -265,20 +268,20 @@ void verify_prepare(TAOS* taos) { // insert 10 records struct { - int64_t ts; - int8_t b; - int8_t v1; - int16_t v2; - int32_t v4; - int64_t v8; - float f4; - double f8; - char bin[40]; - char blob[80]; + int64_t ts; + int8_t b; + int8_t v1; + int16_t v2; + int32_t v4; + int64_t v8; + float f4; + double f8; + char bin[40]; + char blob[80]; } v = {0}; TAOS_STMT* stmt = taos_stmt_init(taos); - TAOS_BIND params[10]; + TAOS_BIND params[10]; params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; params[0].buffer_length = sizeof(v.ts); params[0].buffer = &v.ts; @@ -344,7 +347,7 @@ void verify_prepare(TAOS* taos) { sql = "insert into m1 values(?,?,?,?,?,?,?,?,?,?)"; code = taos_stmt_prepare(stmt, sql, 0); - if (code != 0){ + if (code != 0) { printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); taos_stmt_close(stmt); return; @@ -393,7 +396,7 @@ void verify_prepare(TAOS* taos) { TAOS_ROW row; int rows = 0; int num_fields = taos_num_fields(result); - TAOS_FIELD *fields = taos_fetch_fields(result); + TAOS_FIELD* fields = taos_fetch_fields(result); // fetch the records row by row while ((row = taos_fetch_row(result))) { @@ -425,7 +428,9 @@ void verify_prepare2(TAOS* taos) { taos_select_db(taos, "test"); // create table - const char* sql = "create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))"; + const char* sql = + "create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin " + "binary(40), blob nchar(10))"; result = taos_query(taos, sql); code = taos_errno(result); if (code != 0) { @@ -437,31 +442,31 @@ void verify_prepare2(TAOS* taos) { // insert 10 records struct { - int64_t ts[10]; - int8_t b[10]; - int8_t v1[10]; - int16_t v2[10]; - int32_t v4[10]; - int64_t v8[10]; - float f4[10]; - double f8[10]; - char bin[10][40]; - char blob[10][80]; + int64_t ts[10]; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + char blob[10][80]; } v; - int32_t *t8_len = malloc(sizeof(int32_t) * 10); - int32_t *t16_len = malloc(sizeof(int32_t) * 10); - int32_t *t32_len = malloc(sizeof(int32_t) * 10); - int32_t *t64_len = malloc(sizeof(int32_t) * 10); - int32_t *float_len = malloc(sizeof(int32_t) * 10); - int32_t *double_len = malloc(sizeof(int32_t) * 10); - int32_t *bin_len = malloc(sizeof(int32_t) * 10); - int32_t *blob_len = malloc(sizeof(int32_t) * 10); + int32_t* t8_len = malloc(sizeof(int32_t) * 10); + int32_t* t16_len = malloc(sizeof(int32_t) * 10); + int32_t* t32_len = malloc(sizeof(int32_t) * 10); + int32_t* t64_len = malloc(sizeof(int32_t) * 10); + int32_t* float_len = malloc(sizeof(int32_t) * 10); + int32_t* double_len = malloc(sizeof(int32_t) * 10); + int32_t* bin_len = malloc(sizeof(int32_t) * 10); + int32_t* blob_len = malloc(sizeof(int32_t) * 10); - TAOS_STMT* stmt = taos_stmt_init(taos); + TAOS_STMT* stmt = taos_stmt_init(taos); TAOS_MULTI_BIND params[10]; - char is_null[10] = {0}; - + char is_null[10] = {0}; + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; params[0].buffer_length = sizeof(v.ts[0]); params[0].buffer = v.ts; @@ -541,12 +546,12 @@ void verify_prepare2(TAOS* taos) { } code = taos_stmt_set_tbname(stmt, "m1"); - if (code != 0){ + if (code != 0) { printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); taos_stmt_close(stmt); return; } - + int64_t ts = 1591060628000; for (int i = 0; i < 10; ++i) { v.ts[i] = ts++; @@ -561,7 +566,7 @@ void verify_prepare2(TAOS* taos) { v.f8[i] = (double)(i * 80); for (int j = 0; j < sizeof(v.bin[0]); ++j) { v.bin[i][j] = (char)(i + '0'); - } + } strcpy(v.blob[i], "一二三四五六七八九十"); t8_len[i] = sizeof(int8_t); @@ -576,7 +581,7 @@ void verify_prepare2(TAOS* taos) { taos_stmt_bind_param_batch(stmt, params); taos_stmt_add_batch(stmt); - + if (taos_stmt_execute(stmt) != 0) { printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); taos_stmt_close(stmt); @@ -590,7 +595,7 @@ void verify_prepare2(TAOS* taos) { taos_stmt_prepare(stmt, "SELECT * FROM m1 WHERE v1 > ? AND v2 < ?", 0); TAOS_BIND qparams[2]; - int8_t v1 = 5; + int8_t v1 = 5; int16_t v2 = 15; qparams[0].buffer_type = TSDB_DATA_TYPE_TINYINT; qparams[0].buffer_length = sizeof(v1); @@ -607,7 +612,7 @@ void verify_prepare2(TAOS* taos) { taos_stmt_bind_param(stmt, qparams); if (taos_stmt_execute(stmt) != 0) { printf("\033[31mfailed to execute select statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); - taos_stmt_close(stmt); + taos_stmt_close(stmt); return; } @@ -616,7 +621,7 @@ void verify_prepare2(TAOS* taos) { TAOS_ROW row; int rows = 0; int num_fields = taos_num_fields(result); - TAOS_FIELD *fields = taos_fetch_fields(result); + TAOS_FIELD* fields = taos_fetch_fields(result); // fetch the records row by row while ((row = taos_fetch_row(result))) { @@ -657,7 +662,9 @@ void verify_prepare3(TAOS* taos) { taos_select_db(taos, "test"); // create table - const char* sql = "create stable st1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10)) tags (id1 int, id2 binary(40))"; + const char* sql = + "create stable st1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin " + "binary(40), blob nchar(10)) tags (id1 int, id2 binary(40))"; result = taos_query(taos, sql); code = taos_errno(result); if (code != 0) { @@ -669,10 +676,10 @@ void verify_prepare3(TAOS* taos) { TAOS_BIND tags[2]; - int32_t id1 = 1; - char id2[40] = "abcdefghijklmnopqrstuvwxyz0123456789"; + int32_t id1 = 1; + char id2[40] = "abcdefghijklmnopqrstuvwxyz0123456789"; uintptr_t id2_len = strlen(id2); - + tags[0].buffer_type = TSDB_DATA_TYPE_INT; tags[0].buffer_length = sizeof(int); tags[0].buffer = &id1; @@ -685,34 +692,33 @@ void verify_prepare3(TAOS* taos) { tags[1].length = &id2_len; tags[1].is_null = NULL; - // insert 10 records struct { - int64_t ts[10]; - int8_t b[10]; - int8_t v1[10]; - int16_t v2[10]; - int32_t v4[10]; - int64_t v8[10]; - float f4[10]; - double f8[10]; - char bin[10][40]; - char blob[10][80]; + int64_t ts[10]; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + char blob[10][80]; } v; - int32_t *t8_len = malloc(sizeof(int32_t) * 10); - int32_t *t16_len = malloc(sizeof(int32_t) * 10); - int32_t *t32_len = malloc(sizeof(int32_t) * 10); - int32_t *t64_len = malloc(sizeof(int32_t) * 10); - int32_t *float_len = malloc(sizeof(int32_t) * 10); - int32_t *double_len = malloc(sizeof(int32_t) * 10); - int32_t *bin_len = malloc(sizeof(int32_t) * 10); - int32_t *blob_len = malloc(sizeof(int32_t) * 10); + int32_t* t8_len = malloc(sizeof(int32_t) * 10); + int32_t* t16_len = malloc(sizeof(int32_t) * 10); + int32_t* t32_len = malloc(sizeof(int32_t) * 10); + int32_t* t64_len = malloc(sizeof(int32_t) * 10); + int32_t* float_len = malloc(sizeof(int32_t) * 10); + int32_t* double_len = malloc(sizeof(int32_t) * 10); + int32_t* bin_len = malloc(sizeof(int32_t) * 10); + int32_t* blob_len = malloc(sizeof(int32_t) * 10); - TAOS_STMT* stmt = taos_stmt_init(taos); + TAOS_STMT* stmt = taos_stmt_init(taos); TAOS_MULTI_BIND params[10]; - char is_null[10] = {0}; - + char is_null[10] = {0}; + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; params[0].buffer_length = sizeof(v.ts[0]); params[0].buffer = v.ts; @@ -783,27 +789,26 @@ void verify_prepare3(TAOS* taos) { params[9].is_null = is_null; params[9].num = 10; - sql = "insert into ? using st1 tags(?,?) values(?,?,?,?,?,?,?,?,?,?)"; code = taos_stmt_prepare(stmt, sql, 0); - if (code != 0){ + if (code != 0) { printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); taos_stmt_close(stmt); - return; + return; } code = taos_stmt_set_tbname_tags(stmt, "m1", tags); - if (code != 0){ + if (code != 0) { printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt)); - taos_stmt_close(stmt); + taos_stmt_close(stmt); return; } - + int64_t ts = 1591060628000; for (int i = 0; i < 10; ++i) { v.ts[i] = ts++; is_null[i] = 0; - + v.b[i] = (int8_t)i % 2; v.v1[i] = (int8_t)i; v.v2[i] = (int16_t)(i * 2); @@ -813,7 +818,7 @@ void verify_prepare3(TAOS* taos) { v.f8[i] = (double)(i * 80); for (int j = 0; j < sizeof(v.bin[0]); ++j) { v.bin[i][j] = (char)(i + '0'); - } + } strcpy(v.blob[i], "一二三四五六七八九十"); t8_len[i] = sizeof(int8_t); @@ -828,10 +833,10 @@ void verify_prepare3(TAOS* taos) { taos_stmt_bind_param_batch(stmt, params); taos_stmt_add_batch(stmt); - + if (taos_stmt_execute(stmt) != 0) { printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); - taos_stmt_close(stmt); + taos_stmt_close(stmt); return; } taos_stmt_close(stmt); @@ -842,7 +847,7 @@ void verify_prepare3(TAOS* taos) { TAOS_BIND qparams[2]; - int8_t v1 = 5; + int8_t v1 = 5; int16_t v2 = 15; qparams[0].buffer_type = TSDB_DATA_TYPE_TINYINT; qparams[0].buffer_length = sizeof(v1); @@ -859,7 +864,7 @@ void verify_prepare3(TAOS* taos) { taos_stmt_bind_param(stmt, qparams); if (taos_stmt_execute(stmt) != 0) { printf("\033[31mfailed to execute select statement.error:%s\033[0m\n", taos_stmt_errstr(stmt)); - taos_stmt_close(stmt); + taos_stmt_close(stmt); return; } @@ -868,7 +873,7 @@ void verify_prepare3(TAOS* taos) { TAOS_ROW row; int rows = 0; int num_fields = taos_num_fields(result); - TAOS_FIELD *fields = taos_fetch_fields(result); + TAOS_FIELD* fields = taos_fetch_fields(result); // fetch the records row by row while ((row = taos_fetch_row(result))) { @@ -891,8 +896,7 @@ void verify_prepare3(TAOS* taos) { free(blob_len); } -void retrieve_callback(void *param, TAOS_RES *tres, int numOfRows) -{ +void retrieve_callback(void* param, TAOS_RES* tres, int numOfRows) { if (numOfRows > 0) { printf("%d rows async retrieved\n", numOfRows); taos_fetch_rows_a(tres, retrieve_callback, param); @@ -906,8 +910,7 @@ void retrieve_callback(void *param, TAOS_RES *tres, int numOfRows) } } -void select_callback(void *param, TAOS_RES *tres, int code) -{ +void select_callback(void* param, TAOS_RES* tres, int code) { if (code == 0 && tres) { taos_fetch_rows_a(tres, retrieve_callback, param); } else { @@ -921,11 +924,11 @@ void verify_async(TAOS* taos) { usleep(1000000); } -void stream_callback(void *param, TAOS_RES *res, TAOS_ROW row) { +void stream_callback(void* param, TAOS_RES* res, TAOS_ROW row) { if (res == NULL || row == NULL) { return; } - + int num_fields = taos_num_fields(res); TAOS_FIELD* fields = taos_fetch_fields(res); @@ -937,14 +940,9 @@ void stream_callback(void *param, TAOS_RES *res, TAOS_ROW row) { void verify_stream(TAOS* taos) { prepare_data(taos); - TAOS_STREAM* strm = taos_open_stream( - taos, - "select count(*) from meters interval(1m)", - stream_callback, - 0, - NULL, - NULL); - printf("waiting for stream data\n"); + TAOS_STREAM* strm = + taos_open_stream(taos, "select count(*) from meters interval(1m)", stream_callback, 0, NULL, NULL); + printf("waiting for stream data\n"); usleep(100000); TAOS_RES* result = taos_query(taos, "insert into t0 values(now, 0)(now+5s,1)(now+10s, 2);"); taos_free_result(result); @@ -953,7 +951,7 @@ void verify_stream(TAOS* taos) { } int32_t verify_schema_less(TAOS* taos) { - TAOS_RES *result; + TAOS_RES* result; result = taos_query(taos, "drop database if exists test;"); taos_free_result(result); usleep(100000); @@ -975,50 +973,52 @@ int32_t verify_schema_less(TAOS* taos) { "st,t1=4i64,t2=5f64,t3=\"t4\" c1=3i64,c3=L\"passitagain\",c2=true,c4=5f64 1626006833642000000ns", "ste,t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false 1626056811843316532ns", "ste,t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false,c5=32i8,c6=64i16,c7=32i32,c8=88.88f32 1626056812843316532ns", - "st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000ns", - "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000ns", - "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641000000ns" - }; + "st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 " + "1626006933640000000ns", + "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 " + "1626006933640000000ns", + "stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 " + "1626006933641000000ns"}; - code = taos_insert_lines(taos, lines , sizeof(lines)/sizeof(char*)); + code = taos_insert_lines(taos, lines, sizeof(lines) / sizeof(char*)); char* lines2[] = { "stg,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", - "stg,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000ns" - }; + "stg,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000ns"}; code = taos_insert_lines(taos, &lines2[0], 1); code = taos_insert_lines(taos, &lines2[1], 1); char* lines3[] = { - "sth,t1=4i64,t2=5f64,t4=5f64,ID=\"childtable\" c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641ms", - "sth,t1=4i64,t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933654ms" - }; + "sth,t1=4i64,t2=5f64,t4=5f64,ID=\"childtable\" c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 " + "1626006933641ms", + "sth,t1=4i64,t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933654ms"}; code = taos_insert_lines(taos, lines3, 2); - char* lines4[] = { - "st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", - "dgtyqodr,t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532ns" - }; + char* lines4[] = {"st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", + "dgtyqodr,t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532ns"}; code = taos_insert_lines(taos, lines4, 2); char* lines5[] = { - "zqlbgs,id=\"zqlbgs_39302_21680\",t0=f,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000ns", - "zqlbgs,t9=f,id=\"zqlbgs_39302_21680\",t0=f,t1=127i8,t11=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\",t10=L\"ncharTagValue\" c10=f,c0=f,c1=127i8,c12=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64,c11=L\"ncharColValue\" 1626006833639000000ns" - }; + "zqlbgs,id=\"zqlbgs_39302_21680\",t0=f,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." + "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " + "c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=" + "\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000ns", + "zqlbgs,t9=f,id=\"zqlbgs_39302_21680\",t0=f,t1=127i8,t11=127i8,t2=32767i16,t3=2147483647i32,t4=" + "9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\",t10=" + "L\"ncharTagValue\" " + "c10=f,c0=f,c1=127i8,c12=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." + "123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64,c11=L\"ncharColValue\" 1626006833639000000ns"}; code = taos_insert_lines(taos, &lines5[0], 1); code = taos_insert_lines(taos, &lines5[1], 1); - - char* lines6[] = { - "st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", - "dgtyqodr,t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532ns" - }; + char* lines6[] = {"st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", + "dgtyqodr,t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532ns"}; code = taos_insert_lines(taos, lines6, 2); return (code); } void verify_telnet_insert(TAOS* taos) { - TAOS_RES *result; + TAOS_RES* result; result = taos_query(taos, "drop database if exists db;"); taos_free_result(result); @@ -1043,12 +1043,9 @@ void verify_telnet_insert(TAOS* taos) { /* timestamp */ char* lines1[] = { - "stb1 1626006833s 1i8 host=\"host0\"", - "stb1 1626006833639000000ns 2i8 host=\"host0\"", - "stb1 1626006833640000us 3i8 host=\"host0\"", - "stb1 1626006833641123 4i8 host=\"host0\"", - "stb1 1626006833651ms 5i8 host=\"host0\"", - "stb1 0 6i8 host=\"host0\"", + "stb1 1626006833s 1i8 host=\"host0\"", "stb1 1626006833639000000ns 2i8 host=\"host0\"", + "stb1 1626006833640000us 3i8 host=\"host0\"", "stb1 1626006833641123 4i8 host=\"host0\"", + "stb1 1626006833651ms 5i8 host=\"host0\"", "stb1 0 6i8 host=\"host0\"", }; code = taos_insert_telnet_lines(taos, lines1, 6); if (code) { @@ -1056,113 +1053,83 @@ void verify_telnet_insert(TAOS* taos) { } /* metric value */ - //tinyin - char* lines2_0[] = { - "stb2_0 1626006833651ms -127i8 host=\"host0\"", - "stb2_0 1626006833652ms 127i8 host=\"host0\"" - }; + // tinyin + char* lines2_0[] = {"stb2_0 1626006833651ms -127i8 host=\"host0\"", "stb2_0 1626006833652ms 127i8 host=\"host0\""}; code = taos_insert_telnet_lines(taos, lines2_0, 2); if (code) { printf("lines2_0 code: %d, %s.\n", code, tstrerror(code)); } - //smallint - char* lines2_1[] = { - "stb2_1 1626006833651ms -32767i16 host=\"host0\"", - "stb2_1 1626006833652ms 32767i16 host=\"host0\"" - }; + // smallint + char* lines2_1[] = {"stb2_1 1626006833651ms -32767i16 host=\"host0\"", + "stb2_1 1626006833652ms 32767i16 host=\"host0\""}; code = taos_insert_telnet_lines(taos, lines2_1, 2); if (code) { printf("lines2_1 code: %d, %s.\n", code, tstrerror(code)); } - //int - char* lines2_2[] = { - "stb2_2 1626006833651ms -2147483647i32 host=\"host0\"", - "stb2_2 1626006833652ms 2147483647i32 host=\"host0\"" - }; + // int + char* lines2_2[] = {"stb2_2 1626006833651ms -2147483647i32 host=\"host0\"", + "stb2_2 1626006833652ms 2147483647i32 host=\"host0\""}; code = taos_insert_telnet_lines(taos, lines2_2, 2); if (code) { printf("lines2_2 code: %d, %s.\n", code, tstrerror(code)); } - //bigint - char* lines2_3[] = { - "stb2_3 1626006833651ms -9223372036854775807i64 host=\"host0\"", - "stb2_3 1626006833652ms 9223372036854775807i64 host=\"host0\"" - }; + // bigint + char* lines2_3[] = {"stb2_3 1626006833651ms -9223372036854775807i64 host=\"host0\"", + "stb2_3 1626006833652ms 9223372036854775807i64 host=\"host0\""}; code = taos_insert_telnet_lines(taos, lines2_3, 2); if (code) { printf("lines2_3 code: %d, %s.\n", code, tstrerror(code)); } - //float + // float char* lines2_4[] = { - "stb2_4 1626006833610ms 3f32 host=\"host0\"", - "stb2_4 1626006833620ms -3f32 host=\"host0\"", - "stb2_4 1626006833630ms 3.4f32 host=\"host0\"", - "stb2_4 1626006833640ms -3.4f32 host=\"host0\"", - "stb2_4 1626006833650ms 3.4E10f32 host=\"host0\"", - "stb2_4 1626006833660ms -3.4e10f32 host=\"host0\"", - "stb2_4 1626006833670ms 3.4E+2f32 host=\"host0\"", - "stb2_4 1626006833680ms -3.4e-2f32 host=\"host0\"", - "stb2_4 1626006833690ms 3.15 host=\"host0\"", - "stb2_4 1626006833700ms 3.4E38f32 host=\"host0\"", - "stb2_4 1626006833710ms -3.4E38f32 host=\"host0\"" - }; + "stb2_4 1626006833610ms 3f32 host=\"host0\"", "stb2_4 1626006833620ms -3f32 host=\"host0\"", + "stb2_4 1626006833630ms 3.4f32 host=\"host0\"", "stb2_4 1626006833640ms -3.4f32 host=\"host0\"", + "stb2_4 1626006833650ms 3.4E10f32 host=\"host0\"", "stb2_4 1626006833660ms -3.4e10f32 host=\"host0\"", + "stb2_4 1626006833670ms 3.4E+2f32 host=\"host0\"", "stb2_4 1626006833680ms -3.4e-2f32 host=\"host0\"", + "stb2_4 1626006833690ms 3.15 host=\"host0\"", "stb2_4 1626006833700ms 3.4E38f32 host=\"host0\"", + "stb2_4 1626006833710ms -3.4E38f32 host=\"host0\""}; code = taos_insert_telnet_lines(taos, lines2_4, 11); if (code) { printf("lines2_4 code: %d, %s.\n", code, tstrerror(code)); } - //double + // double char* lines2_5[] = { - "stb2_5 1626006833610ms 3f64 host=\"host0\"", - "stb2_5 1626006833620ms -3f64 host=\"host0\"", - "stb2_5 1626006833630ms 3.4f64 host=\"host0\"", - "stb2_5 1626006833640ms -3.4f64 host=\"host0\"", - "stb2_5 1626006833650ms 3.4E10f64 host=\"host0\"", - "stb2_5 1626006833660ms -3.4e10f64 host=\"host0\"", - "stb2_5 1626006833670ms 3.4E+2f64 host=\"host0\"", - "stb2_5 1626006833680ms -3.4e-2f64 host=\"host0\"", - "stb2_5 1626006833690ms 1.7E308f64 host=\"host0\"", - "stb2_5 1626006833700ms -1.7E308f64 host=\"host0\"" - }; + "stb2_5 1626006833610ms 3f64 host=\"host0\"", "stb2_5 1626006833620ms -3f64 host=\"host0\"", + "stb2_5 1626006833630ms 3.4f64 host=\"host0\"", "stb2_5 1626006833640ms -3.4f64 host=\"host0\"", + "stb2_5 1626006833650ms 3.4E10f64 host=\"host0\"", "stb2_5 1626006833660ms -3.4e10f64 host=\"host0\"", + "stb2_5 1626006833670ms 3.4E+2f64 host=\"host0\"", "stb2_5 1626006833680ms -3.4e-2f64 host=\"host0\"", + "stb2_5 1626006833690ms 1.7E308f64 host=\"host0\"", "stb2_5 1626006833700ms -1.7E308f64 host=\"host0\""}; code = taos_insert_telnet_lines(taos, lines2_5, 10); if (code) { printf("lines2_5 code: %d, %s.\n", code, tstrerror(code)); } - //bool - char* lines2_6[] = { - "stb2_6 1626006833610ms t host=\"host0\"", - "stb2_6 1626006833620ms T host=\"host0\"", - "stb2_6 1626006833630ms true host=\"host0\"", - "stb2_6 1626006833640ms True host=\"host0\"", - "stb2_6 1626006833650ms TRUE host=\"host0\"", - "stb2_6 1626006833660ms f host=\"host0\"", - "stb2_6 1626006833670ms F host=\"host0\"", - "stb2_6 1626006833680ms false host=\"host0\"", - "stb2_6 1626006833690ms False host=\"host0\"", - "stb2_6 1626006833700ms FALSE host=\"host0\"" - }; + // bool + char* lines2_6[] = {"stb2_6 1626006833610ms t host=\"host0\"", "stb2_6 1626006833620ms T host=\"host0\"", + "stb2_6 1626006833630ms true host=\"host0\"", "stb2_6 1626006833640ms True host=\"host0\"", + "stb2_6 1626006833650ms TRUE host=\"host0\"", "stb2_6 1626006833660ms f host=\"host0\"", + "stb2_6 1626006833670ms F host=\"host0\"", "stb2_6 1626006833680ms false host=\"host0\"", + "stb2_6 1626006833690ms False host=\"host0\"", "stb2_6 1626006833700ms FALSE host=\"host0\""}; code = taos_insert_telnet_lines(taos, lines2_6, 10); if (code) { printf("lines2_6 code: %d, %s.\n", code, tstrerror(code)); } - //binary - char* lines2_7[] = { - "stb2_7 1626006833610ms \"binary_val.!@#$%^&*\" host=\"host0\"", - "stb2_7 1626006833620ms \"binary_val.:;,./?|+-=\" host=\"host0\"", - "stb2_7 1626006833630ms \"binary_val.()[]{}<>\" host=\"host0\"" - }; + // binary + char* lines2_7[] = {"stb2_7 1626006833610ms \"binary_val.!@#$%^&*\" host=\"host0\"", + "stb2_7 1626006833620ms \"binary_val.:;,./?|+-=\" host=\"host0\"", + "stb2_7 1626006833630ms \"binary_val.()[]{}<>\" host=\"host0\""}; code = taos_insert_telnet_lines(taos, lines2_7, 3); if (code) { printf("lines2_7 code: %d, %s.\n", code, tstrerror(code)); } - //nchar + // nchar char* lines2_8[] = { "stb2_8 1626006833610ms L\"nchar_val数值一\" host=\"host0\"", "stb2_8 1626006833620ms L\"nchar_val数值二\" host=\"host0\"", @@ -1173,22 +1140,23 @@ void verify_telnet_insert(TAOS* taos) { } /* tags */ - //tag value types + // tag value types char* lines3_0[] = { - "stb3_0 1626006833610ms 1 t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=3.4E38f32,t6=1.7E308f64,t7=true,t8=\"binary_val_1\",t9=L\"标签值1\"", - "stb3_0 1626006833610ms 2 t1=-127i8,t2=-32767i16,t3=-2147483647i32,t4=-9223372036854775807i64,t5=-3.4E38f32,t6=-1.7E308f64,t7=false,t8=\"binary_val_2\",t9=L\"标签值2\"" - }; + "stb3_0 1626006833610ms 1 " + "t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=3.4E38f32,t6=1.7E308f64,t7=true,t8=\"binary_" + "val_1\",t9=L\"标签值1\"", + "stb3_0 1626006833610ms 2 " + "t1=-127i8,t2=-32767i16,t3=-2147483647i32,t4=-9223372036854775807i64,t5=-3.4E38f32,t6=-1.7E308f64,t7=false,t8=" + "\"binary_val_2\",t9=L\"标签值2\""}; code = taos_insert_telnet_lines(taos, lines3_0, 2); if (code) { printf("lines3_0 code: %d, %s.\n", code, tstrerror(code)); } - //tag ID as child table name - char* lines3_1[] = { - "stb3_1 1626006833610ms 1 id=\"child_table1\",host=\"host1\"", - "stb3_1 1626006833610ms 2 host=\"host2\",iD=\"child_table2\"", - "stb3_1 1626006833610ms 3 ID=\"child_table3\",host=\"host3\"" - }; + // tag ID as child table name + char* lines3_1[] = {"stb3_1 1626006833610ms 1 id=\"child_table1\",host=\"host1\"", + "stb3_1 1626006833610ms 2 host=\"host2\",iD=\"child_table2\"", + "stb3_1 1626006833610ms 3 ID=\"child_table3\",host=\"host3\""}; code = taos_insert_telnet_lines(taos, lines3_1, 3); if (code) { printf("lines3_1 code: %d, %s.\n", code, tstrerror(code)); @@ -1198,7 +1166,7 @@ void verify_telnet_insert(TAOS* taos) { } void verify_json_insert(TAOS* taos) { - TAOS_RES *result; + TAOS_RES* result; result = taos_query(taos, "drop database if exists db;"); taos_free_result(result); @@ -1210,8 +1178,8 @@ void verify_json_insert(TAOS* taos) { (void)taos_select_db(taos, "db"); int32_t code = 0; - char *message = - "{ \ + char* message = + "{ \ \"metric\":\"cpu_load_0\", \ \"timestamp\": 1626006833610123, \ \"value\": 55.5, \ @@ -1228,8 +1196,8 @@ void verify_json_insert(TAOS* taos) { printf("payload_0 code: %d, %s.\n", code, tstrerror(code)); } - char *message1 = - "[ \ + char* message1 = + "[ \ { \ \"metric\":\"cpu_load_1\", \ \"timestamp\": 1626006833610123, \ @@ -1259,8 +1227,8 @@ void verify_json_insert(TAOS* taos) { printf("payload_1 code: %d, %s.\n", code, tstrerror(code)); } - char *message2 = - "[ \ + char* message2 = + "[ \ { \ \"metric\":\"cpu_load_3\", \ \"timestamp\": \ @@ -1310,12 +1278,11 @@ void verify_json_insert(TAOS* taos) { printf("payload_2 code: %d, %s.\n", code, tstrerror(code)); } - cJSON *payload, *tags; - char *payload_str; + char* payload_str; /* Default format */ - //number + // number payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb0_0"); cJSON_AddNumberToObject(payload, "timestamp", 1626006833610123); @@ -1327,7 +1294,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1336,7 +1303,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //true + // true payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb0_1"); cJSON_AddNumberToObject(payload, "timestamp", 1626006833610123); @@ -1348,7 +1315,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1357,7 +1324,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //false + // false payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb0_2"); cJSON_AddNumberToObject(payload, "timestamp", 1626006833610123); @@ -1369,7 +1336,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1378,7 +1345,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //string + // string payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb0_3"); cJSON_AddNumberToObject(payload, "timestamp", 1626006833610123); @@ -1390,7 +1357,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1399,7 +1366,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //timestamp 0 -> current time + // timestamp 0 -> current time payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb0_4"); cJSON_AddNumberToObject(payload, "timestamp", 0); @@ -1411,7 +1378,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1420,7 +1387,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //ID + // ID payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb0_5"); cJSON_AddNumberToObject(payload, "timestamp", 0); @@ -1435,7 +1402,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "id", "tb555"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1445,9 +1412,9 @@ void verify_json_insert(TAOS* taos) { cJSON_Delete(payload); /* Nested format */ - //timestamp - cJSON *timestamp; - //seconds + // timestamp + cJSON* timestamp; + // seconds payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb1_0"); @@ -1464,7 +1431,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1473,7 +1440,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //milleseconds + // milleseconds payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb1_1"); @@ -1490,7 +1457,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1499,7 +1466,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //microseconds + // microseconds payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb1_2"); @@ -1516,7 +1483,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1525,7 +1492,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //nanoseconds + // nanoseconds payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb1_3"); @@ -1542,7 +1509,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1551,7 +1518,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //now + // now payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb1_4"); @@ -1568,7 +1535,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1577,9 +1544,9 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //metric value - cJSON *metric_val; - //bool + // metric value + cJSON* metric_val; + // bool payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_0"); @@ -1600,7 +1567,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1609,7 +1576,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //tinyint + // tinyint payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_1"); @@ -1630,7 +1597,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1639,7 +1606,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //smallint + // smallint payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_2"); @@ -1660,7 +1627,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1669,7 +1636,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //int + // int payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_3"); @@ -1690,7 +1657,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1699,7 +1666,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //bigint + // bigint payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_4"); @@ -1720,7 +1687,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1729,7 +1696,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //float + // float payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_5"); @@ -1750,7 +1717,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1759,7 +1726,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //double + // double payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_6"); @@ -1780,7 +1747,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1789,7 +1756,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //binary + // binary payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_7"); @@ -1810,7 +1777,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1819,7 +1786,7 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //nchar + // nchar payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb2_8"); @@ -1840,7 +1807,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddStringToObject(tags, "t4", "123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>"); cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1849,8 +1816,8 @@ void verify_json_insert(TAOS* taos) { free(payload_str); cJSON_Delete(payload); - //tag value - cJSON *tag; + // tag value + cJSON* tag; payload = cJSON_CreateObject(); cJSON_AddStringToObject(payload, "metric", "stb3_0"); @@ -1920,7 +1887,7 @@ void verify_json_insert(TAOS* taos) { cJSON_AddItemToObject(payload, "tags", tags); payload_str = cJSON_Print(payload); - //printf("%s\n", payload_str); + // printf("%s\n", payload_str); code = taos_insert_json_payload(taos, payload_str); if (code) { @@ -1930,7 +1897,7 @@ void verify_json_insert(TAOS* taos) { cJSON_Delete(payload); } -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { const char* host = "127.0.0.1"; const char* user = "root"; const char* passwd = "taosdata"; diff --git a/include/client/taos.h b/include/client/taos.h index 44443752c5..25887b2879 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -130,17 +130,16 @@ typedef struct TAOS_VGROUP_HASH_INFO { int32_t vgId; uint32_t hashBegin; uint32_t hashEnd; -} TAOS_VGROUP_HASH_INFO ; +} TAOS_VGROUP_HASH_INFO; typedef struct TAOS_DB_ROUTE_INFO { - int32_t routeVersion; - int16_t hashPrefix; - int16_t hashSuffix; - int8_t hashMethod; - int32_t vgNum; + int32_t routeVersion; + int16_t hashPrefix; + int16_t hashSuffix; + int8_t hashMethod; + int32_t vgNum; TAOS_VGROUP_HASH_INFO *vgHash; -} TAOS_DB_ROUTE_INFO ; - +} TAOS_DB_ROUTE_INFO; DLL_EXPORT void taos_cleanup(void); DLL_EXPORT int taos_options(TSDB_OPTION option, const void *arg, ...); @@ -153,6 +152,7 @@ DLL_EXPORT void taos_close(TAOS *taos); const char *taos_data_type(int type); DLL_EXPORT TAOS_STMT *taos_stmt_init(TAOS *taos); +DLL_EXPORT TAOS_STMT *taos_stmt_init_with_reqid(TAOS *taos, int64_t reqid); DLL_EXPORT int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length); DLL_EXPORT int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags); DLL_EXPORT int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name); @@ -176,6 +176,7 @@ DLL_EXPORT int taos_stmt_affected_rows(TAOS_STMT *stmt); DLL_EXPORT int taos_stmt_affected_rows_once(TAOS_STMT *stmt); DLL_EXPORT TAOS_RES *taos_query(TAOS *taos, const char *sql); +DLL_EXPORT TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqId); 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 @@ -207,17 +208,23 @@ DLL_EXPORT const char *taos_get_client_info(); DLL_EXPORT const char *taos_errstr(TAOS_RES *res); DLL_EXPORT int taos_errno(TAOS_RES *res); -DLL_EXPORT void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param); -DLL_EXPORT void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param); -DLL_EXPORT void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param); +DLL_EXPORT void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param); +DLL_EXPORT void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid); +DLL_EXPORT void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param); +DLL_EXPORT void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param); DLL_EXPORT const void *taos_get_raw_block(TAOS_RES *res); -DLL_EXPORT int taos_get_db_route_info(TAOS* taos, const char* db, TAOS_DB_ROUTE_INFO* dbInfo); -DLL_EXPORT int taos_get_table_vgId(TAOS* taos, const char* db, const char* table, int* vgId); +DLL_EXPORT int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInfo); +DLL_EXPORT int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId); DLL_EXPORT int taos_load_table_info(TAOS *taos, const char *tableNameList); DLL_EXPORT TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int protocol, int precision); -DLL_EXPORT TAOS_RES *taos_schemaless_insert_raw(TAOS* taos, char* lines, int len, int32_t *totalRows, int protocol, int precision); +DLL_EXPORT TAOS_RES *taos_schemaless_insert_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, + int precision, int64_t reqid); +DLL_EXPORT TAOS_RES *taos_schemaless_insert_raw(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, + int precision); +DLL_EXPORT TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, + int protocol, int precision, int64_t reqid); /* --------------------------TMQ INTERFACE------------------------------- */ diff --git a/include/common/tmsg.h b/include/common/tmsg.h index c0ac7da5bf..8aa85fa6b4 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -216,14 +216,9 @@ typedef struct SEp { uint16_t port; } SEp; -#define SHOW_REWRITE_MASK() (1 << 0) - -#define TEST_SHOW_REWRITE_MASK(m) (((m) & SHOW_REWRITE_MASK()) != 0) - typedef struct { int32_t contLen; int32_t vgId; - int32_t msgMask; } SMsgHead; // Submit message for one table @@ -1616,6 +1611,7 @@ typedef struct SSubQueryMsg { int8_t needFetch; uint32_t sqlLen; // the query sql, uint32_t phyLen; + int32_t msgMask; char msg[]; } SSubQueryMsg; diff --git a/include/libs/catalog/catalog.h b/include/libs/catalog/catalog.h index b310ec8080..3902224f0b 100644 --- a/include/libs/catalog/catalog.h +++ b/include/libs/catalog/catalog.h @@ -207,7 +207,7 @@ int32_t catalogGetCachedTableMeta(SCatalog* pCtg, const SName* pTableName, STabl int32_t catalogGetCachedSTableMeta(SCatalog* pCtg, const SName* pTableName, STableMeta** pTableMeta); -int32_t catalogGetCachedTableHashVgroup(SCatalog* pCtg, const SName* pTableName, SVgroupInfo* pVgroup, bool* exists); +int32_t catalogGetCachedTableHashVgroup(SCatalog* pCtg, const SName* pTableName, SVgroupInfo* pVgroup, bool* exists); /** * Force refresh DB's local cached vgroup info. @@ -307,8 +307,8 @@ int32_t catalogGetUdfInfo(SCatalog* pCtg, SRequestConnInfo* pConn, const char* f int32_t catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, const char* user, const char* dbFName, AUTH_TYPE type, bool* pass); -int32_t catalogChkAuthFromCache(SCatalog* pCtg, const char* user, const char* dbFName, AUTH_TYPE type, - bool* pass, bool* exists); +int32_t catalogChkAuthFromCache(SCatalog* pCtg, const char* user, const char* dbFName, AUTH_TYPE type, bool* pass, + bool* exists); int32_t catalogUpdateUserAuthInfo(SCatalog* pCtg, SGetUserAuthRsp* pAuth); @@ -324,9 +324,9 @@ SMetaData* catalogCloneMetaData(SMetaData* pData); void catalogFreeMetaData(SMetaData* pData); -int32_t ctgdEnableDebug(char *option, bool enable); +int32_t ctgdEnableDebug(char* option, bool enable); -int32_t ctgdHandleDbgCommand(char *command); +int32_t ctgdHandleDbgCommand(char* command); /** * Destroy catalog and relase all resources diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 837834f795..a85f8bf63d 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -354,12 +354,33 @@ typedef struct SVgDataBlocks { void* pData; // SMsgDesc + SSubmitReq + SSubmitBlk + ... } SVgDataBlocks; +typedef void (*FFreeDataBlockHash)(SHashObj*); +typedef void (*FFreeDataBlockArray)(SArray*); + typedef struct SVnodeModifOpStmt { - ENodeType nodeType; - ENodeType sqlNodeType; - SArray* pDataBlocks; // data block for each vgroup, SArray. - uint32_t insertType; // insert data from [file|sql statement| bound statement] - const char* sql; // current sql statement position + ENodeType nodeType; + ENodeType sqlNodeType; + SArray* pDataBlocks; // data block for each vgroup, SArray. + uint32_t insertType; // insert data from [file|sql statement| bound statement] + const char* pSql; // current sql statement position + int32_t totalRowsNum; + int32_t totalTbNum; + SName targetTableName; + SName usingTableName; + const char* pBoundCols; + struct STableMeta* pTableMeta; + SHashObj* pVgroupsHashObj; + SHashObj* pTableBlockHashObj; + SHashObj* pSubTableHashObj; + SHashObj* pTableNameHashObj; + SHashObj* pDbFNameHashObj; + SArray* pVgDataBlocks; + SVCreateTbReq createTblReq; + TdFilePtr fp; + FFreeDataBlockHash freeHashFunc; + FFreeDataBlockArray freeArrayFunc; + bool usingTableProcessing; + bool fileProcessing; } SVnodeModifOpStmt; typedef struct SExplainOptions { @@ -389,24 +410,32 @@ typedef enum EQueryExecMode { QUERY_EXEC_MODE_EMPTY_RESULT } EQueryExecMode; +typedef enum EQueryExecStage { + QUERY_EXEC_STAGE_PARSE = 1, + QUERY_EXEC_STAGE_ANALYSE, + QUERY_EXEC_STAGE_SCHEDULE, + QUERY_EXEC_STAGE_END +} EQueryExecStage; + typedef struct SQuery { - ENodeType type; - EQueryExecMode execMode; - bool haveResultSet; - SNode* pRoot; - int32_t numOfResCols; - SSchema* pResSchema; - int8_t precision; - SCmdMsgInfo* pCmdMsg; - int32_t msgType; - SArray* pTargetTableList; - SArray* pTableList; - SArray* pDbList; - bool showRewrite; - int32_t placeholderNum; - SArray* pPlaceholderValues; - SNode* pPrepareRoot; - bool stableQuery; + ENodeType type; + EQueryExecStage execStage; + EQueryExecMode execMode; + bool haveResultSet; + SNode* pRoot; + int32_t numOfResCols; + SSchema* pResSchema; + int8_t precision; + SCmdMsgInfo* pCmdMsg; + int32_t msgType; + SArray* pTargetTableList; + SArray* pTableList; + SArray* pDbList; + bool showRewrite; + int32_t placeholderNum; + SArray* pPlaceholderValues; + SNode* pPrepareRoot; + bool stableQuery; } SQuery; void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext); diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index bcd2316baf..1a7e6dc748 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -64,8 +64,6 @@ typedef struct SParseContext { SArray* pTableMetaPos; // sql table pos => catalog data pos SArray* pTableVgroupPos; // sql table pos => catalog data pos int64_t allocatorId; - bool needMultiParse; - SParseCsvCxt csvCxt; } SParseContext; int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery); @@ -75,6 +73,8 @@ bool qIsInsertValuesSql(const char* pStr, size_t length); int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq); int32_t qAnalyseSqlSemantic(SParseContext* pCxt, const struct SCatalogReq* pCatalogReq, const struct SMetaData* pMetaData, SQuery* pQuery); +int32_t qContinueParseSql(SParseContext* pCxt, struct SCatalogReq* pCatalogReq, const struct SMetaData* pMetaData, + SQuery* pQuery); void qDestroyParseContext(SParseContext* pCxt); diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h index 651b379851..74c1a8c07c 100644 --- a/include/libs/qcom/query.h +++ b/include/libs/qcom/query.h @@ -57,6 +57,10 @@ typedef enum { #define QUERY_RSP_POLICY_DELAY 0 #define QUERY_RSP_POLICY_QUICK 1 +#define QUERY_MSG_MASK_SHOW_REWRITE() (1 << 0) +#define TEST_SHOW_REWRITE_MASK(m) (((m) & QUERY_MSG_MASK_SHOW_REWRITE()) != 0) + + typedef struct STableComInfo { uint8_t numOfTags; // the number of tags in schema uint8_t precision; // the number of precision diff --git a/include/libs/qworker/qworker.h b/include/libs/qworker/qworker.h index 7a1e9bb272..6ddd906700 100644 --- a/include/libs/qworker/qworker.h +++ b/include/libs/qworker/qworker.h @@ -76,7 +76,7 @@ int32_t qWorkerInit(int8_t nodeType, int32_t nodeId, void **qWorkerMgmt, const S int32_t qWorkerAbortPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg); -int32_t qWorkerPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg); +int32_t qWorkerPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg, bool chkGrant); int32_t qWorkerProcessQueryMsg(void *node, void *qWorkerMgmt, SRpcMsg *pMsg, int64_t ts); diff --git a/include/libs/sync/sync.h b/include/libs/sync/sync.h index 8db3d89e39..74a73f6b10 100644 --- a/include/libs/sync/sync.h +++ b/include/libs/sync/sync.h @@ -138,6 +138,7 @@ typedef struct SSyncFSM { void (*FpRestoreFinishCb)(const struct SSyncFSM* pFsm); void (*FpReConfigCb)(const struct SSyncFSM* pFsm, const SRpcMsg* pMsg, const SReConfigCbMeta* pMeta); void (*FpLeaderTransferCb)(const struct SSyncFSM* pFsm, const SRpcMsg* pMsg, const SFsmCbMeta* pMeta); + bool (*FpApplyQueueEmptyCb)(const struct SSyncFSM* pFsm); void (*FpBecomeLeaderCb)(const struct SSyncFSM* pFsm); void (*FpBecomeFollowerCb)(const struct SSyncFSM* pFsm); diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index 33af862528..e569a97723 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -271,7 +271,11 @@ int32_t transferTableNameList(const char* tbList, int32_t acctId, char* dbName, void syncCatalogFn(SMetaData* pResult, void* param, int32_t code); TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly); -void taosAsyncQueryImpl(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly); +TAOS_RES* taosQueryImplWithReqid(TAOS* taos, const char* sql, bool validateOnly, int64_t reqid); + +void taosAsyncQueryImpl(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly); +void taosAsyncQueryImplWithReqid(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly, + int64_t reqid); int32_t getVersion1BlockMetaSize(const char* p, int32_t numOfCols); @@ -318,11 +322,11 @@ void* createTscObj(const char* user, const char* auth, const char* db, int32_ void destroyTscObj(void* pObj); STscObj* acquireTscObj(int64_t rid); int32_t releaseTscObj(int64_t rid); -void destroyAppInst(SAppInstInfo *pAppInfo); +void destroyAppInst(SAppInstInfo* pAppInfo); uint64_t generateRequestId(); -void* createRequest(uint64_t connId, int32_t type); +void* createRequest(uint64_t connId, int32_t type, int64_t reqid); void destroyRequest(SRequestObj* pRequest); SRequestObj* acquireRequest(int64_t rid); int32_t releaseRequest(int64_t rid); @@ -353,7 +357,7 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC int32_t getPlan(SRequestObj* pRequest, SQuery* pQuery, SQueryPlan** pPlan, SArray* pNodeList); int32_t buildRequest(uint64_t connId, const char* sql, int sqlLen, void* param, bool validateSql, - SRequestObj** pRequest); + SRequestObj** pRequest, int64_t reqid); void taos_close_internal(void* taos); @@ -380,7 +384,6 @@ void hbMgrInitMqHbRspHandle(); typedef struct SSqlCallbackWrapper { SParseContext* pParseCtx; SCatalogReq* pCatalogReq; - SMetaData* pResultMeta; SRequestObj* pRequest; } SSqlCallbackWrapper; @@ -394,7 +397,7 @@ int32_t removeMeta(STscObj* pTscObj, SArray* tbList); int32_t handleAlterTbExecRes(void* res, struct SCatalog* pCatalog); int32_t handleCreateTbExecRes(void* res, SCatalog* pCatalog); bool qnodeRequired(SRequestObj* pRequest); -int32_t continueInsertFromCsv(SSqlCallbackWrapper* pWrapper, SRequestObj* pRequest); +void continueInsertFromCsv(SSqlCallbackWrapper* pWrapper, SRequestObj* pRequest); void destorySqlCallbackWrapper(SSqlCallbackWrapper* pWrapper); #ifdef __cplusplus diff --git a/source/client/inc/clientStmt.h b/source/client/inc/clientStmt.h index ef4c05afae..e5507ccf81 100644 --- a/source/client/inc/clientStmt.h +++ b/source/client/inc/clientStmt.h @@ -101,11 +101,18 @@ typedef struct STscStmt { SStmtSQLInfo sql; SStmtExecInfo exec; SStmtBindInfo bInfo; + + int64_t reqid; } STscStmt; extern char *gStmtStatusStr[]; -#define STMT_LOG_SEQ(n) do { (pStmt)->seqId++; (pStmt)->seqIds[n]++; STMT_DLOG("the %dth:%d %s", (pStmt)->seqIds[n], (pStmt)->seqId, gStmtStatusStr[n]); } while (0) +#define STMT_LOG_SEQ(n) \ + do { \ + (pStmt)->seqId++; \ + (pStmt)->seqIds[n]++; \ + STMT_DLOG("the %dth:%d %s", (pStmt)->seqIds[n], (pStmt)->seqId, gStmtStatusStr[n]); \ + } while (0) #define STMT_STATUS_NE(S) (pStmt->sql.status != STMT_##S) #define STMT_STATUS_EQ(S) (pStmt->sql.status == STMT_##S) @@ -141,7 +148,7 @@ extern char *gStmtStatusStr[]; #define STMT_ELOG_E(param) qError("stmt:%p " param, pStmt) #define STMT_DLOG_E(param) qDebug("stmt:%p " param, pStmt) -TAOS_STMT *stmtInit(STscObj *taos); +TAOS_STMT *stmtInit(STscObj *taos, int64_t reqid); int stmtClose(TAOS_STMT *stmt); int stmtExec(TAOS_STMT *stmt); const char *stmtErrstr(TAOS_STMT *stmt); diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c index 0f6d394611..bb25a595af 100644 --- a/source/client/src/clientEnv.c +++ b/source/client/src/clientEnv.c @@ -77,19 +77,19 @@ static void deregisterRequest(SRequestObj *pRequest) { pRequest->self, pTscObj->id, pRequest->requestId, duration / 1000.0, num, currentInst); if (QUERY_NODE_VNODE_MODIF_STMT == pRequest->stmtType) { -// tscPerf("insert duration %" PRId64 "us: syntax:%" PRId64 "us, ctg:%" PRId64 "us, semantic:%" PRId64 -// "us, exec:%" PRId64 "us", -// duration, pRequest->metric.syntaxEnd - pRequest->metric.syntaxStart, -// pRequest->metric.ctgEnd - pRequest->metric.ctgStart, pRequest->metric.semanticEnd - pRequest->metric.ctgEnd, -// pRequest->metric.execEnd - pRequest->metric.semanticEnd); + // tscPerf("insert duration %" PRId64 "us: syntax:%" PRId64 "us, ctg:%" PRId64 "us, semantic:%" PRId64 + // "us, exec:%" PRId64 "us", + // duration, pRequest->metric.syntaxEnd - pRequest->metric.syntaxStart, + // pRequest->metric.ctgEnd - pRequest->metric.ctgStart, pRequest->metric.semanticEnd - + // pRequest->metric.ctgEnd, pRequest->metric.execEnd - pRequest->metric.semanticEnd); atomic_add_fetch_64((int64_t *)&pActivity->insertElapsedTime, duration); } else if (QUERY_NODE_SELECT_STMT == pRequest->stmtType) { -// tscPerf("select duration %" PRId64 "us: syntax:%" PRId64 "us, ctg:%" PRId64 "us, semantic:%" PRId64 -// "us, planner:%" PRId64 "us, exec:%" PRId64 "us, reqId:0x%" PRIx64, -// duration, pRequest->metric.syntaxEnd - pRequest->metric.syntaxStart, -// pRequest->metric.ctgEnd - pRequest->metric.ctgStart, pRequest->metric.semanticEnd - pRequest->metric.ctgEnd, -// pRequest->metric.planEnd - pRequest->metric.semanticEnd, -// pRequest->metric.resultReady - pRequest->metric.planEnd, pRequest->requestId); + // tscPerf("select duration %" PRId64 "us: syntax:%" PRId64 "us, ctg:%" PRId64 "us, semantic:%" PRId64 + // "us, planner:%" PRId64 "us, exec:%" PRId64 "us, reqId:0x%" PRIx64, + // duration, pRequest->metric.syntaxEnd - pRequest->metric.syntaxStart, + // pRequest->metric.ctgEnd - pRequest->metric.ctgStart, pRequest->metric.semanticEnd - + // pRequest->metric.ctgEnd, pRequest->metric.planEnd - pRequest->metric.semanticEnd, + // pRequest->metric.resultReady - pRequest->metric.planEnd, pRequest->requestId); atomic_add_fetch_64((int64_t *)&pActivity->queryElapsedTime, duration); } @@ -271,7 +271,7 @@ STscObj *acquireTscObj(int64_t rid) { return (STscObj *)taosAcquireRef(clientCon int32_t releaseTscObj(int64_t rid) { return taosReleaseRef(clientConnRefPool, rid); } -void *createRequest(uint64_t connId, int32_t type) { +void *createRequest(uint64_t connId, int32_t type, int64_t reqid) { SRequestObj *pRequest = (SRequestObj *)taosMemoryCalloc(1, sizeof(SRequestObj)); if (NULL == pRequest) { terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; @@ -286,7 +286,7 @@ void *createRequest(uint64_t connId, int32_t type) { } pRequest->resType = RES_TYPE__QUERY; - pRequest->requestId = generateRequestId(); + pRequest->requestId = reqid == 0 ? generateRequestId() : reqid; pRequest->metric.start = taosGetTimestampUs(); pRequest->body.resInfo.convertUcs4 = true; // convert ucs4 by default diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index e9e30a0be2..88d7823593 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -154,8 +154,8 @@ STscObj* taos_connect_internal(const char* ip, const char* user, const char* pas } int32_t buildRequest(uint64_t connId, const char* sql, int sqlLen, void* param, bool validateSql, - SRequestObj** pRequest) { - *pRequest = createRequest(connId, TSDB_SQL_SELECT); + SRequestObj** pRequest, int64_t reqid) { + *pRequest = createRequest(connId, TSDB_SQL_SELECT, reqid); if (*pRequest == NULL) { tscError("failed to malloc sqlObj, %s", sql); return terrno; @@ -873,6 +873,10 @@ int32_t handleQueryExecRsp(SRequestObj* pRequest) { return code; } +static bool incompletaFileParsing(SNode* pStmt) { + return QUERY_NODE_VNODE_MODIF_STMT != nodeType(pStmt) ? false : ((SVnodeModifOpStmt*)pStmt)->fileProcessing; +} + // todo refacto the error code mgmt void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) { SSqlCallbackWrapper* pWrapper = param; @@ -927,11 +931,10 @@ void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) { pRequest->code = code1; } - if (pRequest->code == TSDB_CODE_SUCCESS && NULL != pWrapper->pParseCtx && pWrapper->pParseCtx->needMultiParse) { - code = continueInsertFromCsv(pWrapper, pRequest); - if (TSDB_CODE_SUCCESS == code) { - return; - } + if (pRequest->code == TSDB_CODE_SUCCESS && NULL != pRequest->pQuery && + incompletaFileParsing(pRequest->pQuery->pRoot)) { + continueInsertFromCsv(pWrapper, pRequest); + return; } destorySqlCallbackWrapper(pWrapper); @@ -1055,7 +1058,9 @@ static int32_t asyncExecSchQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaDat } if (TSDB_CODE_SUCCESS == code && !pRequest->validateOnly) { SArray* pNodeList = NULL; - buildAsyncExecNodeList(pRequest, &pNodeList, pMnodeList, pResultMeta); + if (QUERY_NODE_VNODE_MODIF_STMT != nodeType(pQuery->pRoot)) { + buildAsyncExecNodeList(pRequest, &pNodeList, pMnodeList, pResultMeta); + } SRequestConnInfo conn = {.pTrans = getAppInfo(pRequest)->pTransporter, .requestId = pRequest->requestId, @@ -1230,7 +1235,7 @@ STscObj* taosConnectImpl(const char* user, const char* auth, const char* db, __t return pTscObj; } - SRequestObj* pRequest = createRequest(pTscObj->id, TDMT_MND_CONNECT); + SRequestObj* pRequest = createRequest(pTscObj->id, TDMT_MND_CONNECT, 0); if (pRequest == NULL) { destroyTscObj(pTscObj); return NULL; @@ -2234,7 +2239,37 @@ void taosAsyncQueryImpl(uint64_t connId, const char* sql, __taos_async_fn_t fp, } SRequestObj* pRequest = NULL; - int32_t code = buildRequest(connId, sql, sqlLen, param, validateOnly, &pRequest); + int32_t code = buildRequest(connId, sql, sqlLen, param, validateOnly, &pRequest, 0); + if (code != TSDB_CODE_SUCCESS) { + terrno = code; + fp(param, NULL, terrno); + return; + } + + pRequest->body.queryFp = fp; + doAsyncQuery(pRequest, false); +} +void taosAsyncQueryImplWithReqid(uint64_t connId, const char* sql, __taos_async_fn_t fp, void* param, bool validateOnly, + int64_t reqid) { + if (sql == NULL || NULL == fp) { + terrno = TSDB_CODE_INVALID_PARA; + if (fp) { + fp(param, NULL, terrno); + } + + return; + } + + size_t sqlLen = strlen(sql); + if (sqlLen > (size_t)TSDB_MAX_ALLOWED_SQL_LEN) { + tscError("sql string exceeds max length:%d", TSDB_MAX_ALLOWED_SQL_LEN); + terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT; + fp(param, NULL, terrno); + return; + } + + SRequestObj* pRequest = NULL; + int32_t code = buildRequest(connId, sql, sqlLen, param, validateOnly, &pRequest, reqid); if (code != TSDB_CODE_SUCCESS) { terrno = code; fp(param, NULL, terrno); @@ -2261,3 +2296,20 @@ TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly) { } return param->pRequest; } + +TAOS_RES* taosQueryImplWithReqid(TAOS* taos, const char* sql, bool validateOnly, int64_t reqid) { + if (NULL == taos) { + terrno = TSDB_CODE_TSC_DISCONNECTED; + return NULL; + } + + SSyncQueryParam* param = taosMemoryCalloc(1, sizeof(SSyncQueryParam)); + tsem_init(¶m->sem, 0, 0); + + taosAsyncQueryImplWithReqid(*(int64_t*)taos, sql, syncQueryFn, param, validateOnly, reqid); + tsem_wait(¶m->sem); + if (param->pRequest != NULL) { + param->pRequest->syncQuery = true; + } + return param->pRequest; +} diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index a08eab3a29..71a87a4b54 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -248,6 +248,9 @@ TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) { } TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false); } +TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) { + return taosQueryImplWithReqid(taos, sql, false, reqid); +} TAOS_ROW taos_fetch_row(TAOS_RES *res) { if (res == NULL) { @@ -683,11 +686,10 @@ void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) { } destoryCatalogReq(pWrapper->pCatalogReq); qDestroyParseContext(pWrapper->pParseCtx); - catalogFreeMetaData(pWrapper->pResultMeta); taosMemoryFree(pWrapper); } -void retrieveMetaCallback(SMetaData *pResultMeta, void *param, int32_t code) { +static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) { SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param; SRequestObj *pRequest = pWrapper->pRequest; SQuery *pQuery = pRequest->pQuery; @@ -705,13 +707,6 @@ void retrieveMetaCallback(SMetaData *pResultMeta, void *param, int32_t code) { pRequest->metric.semanticEnd = taosGetTimestampUs(); - if (code == TSDB_CODE_SUCCESS && pWrapper->pParseCtx->needMultiParse) { - pWrapper->pResultMeta = catalogCloneMetaData(pResultMeta); - if (NULL == pWrapper->pResultMeta) { - code = TSDB_CODE_OUT_OF_MEMORY; - } - } - if (code == TSDB_CODE_SUCCESS) { if (pQuery->haveResultSet) { setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols); @@ -748,14 +743,83 @@ void retrieveMetaCallback(SMetaData *pResultMeta, void *param, int32_t code) { } } -int32_t continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) { - qDestroyQuery(pRequest->pQuery); - pRequest->pQuery = (SQuery *)nodesMakeNode(QUERY_NODE_QUERY); - if (NULL == pRequest->pQuery) { - return TSDB_CODE_OUT_OF_MEMORY; +static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) { + SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter, + .requestId = pWrapper->pParseCtx->requestId, + .requestObjRefId = pWrapper->pParseCtx->requestRid, + .mgmtEps = pWrapper->pParseCtx->mgmtEpSet}; + + pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs(); + + return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper, + &pWrapper->pRequest->body.queryJob); +} + +static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code); + +static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) { + int32_t code = TSDB_CODE_SUCCESS; + switch (pWrapper->pRequest->pQuery->execStage) { + case QUERY_EXEC_STAGE_PARSE: { + // continue parse after get metadata + code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse); + break; + } + case QUERY_EXEC_STAGE_ANALYSE: { + // analysis after get metadata + code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse); + break; + } + case QUERY_EXEC_STAGE_SCHEDULE: { + launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper); + break; + } + default: + break; + } + return code; +} + +static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) { + SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param; + SRequestObj *pRequest = pWrapper->pRequest; + SQuery *pQuery = pRequest->pQuery; + + pRequest->metric.ctgEnd = taosGetTimestampUs(); + qDebug("0x%" PRIx64 " start to continue parse, reqId:0x%" PRIx64, pRequest->self, pRequest->requestId); + + if (code == TSDB_CODE_SUCCESS) { + code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery); + } + + if (TSDB_CODE_SUCCESS == code) { + code = phaseAsyncQuery(pWrapper); + } + + if (TSDB_CODE_SUCCESS != code) { + tscError("0x%" PRIx64 " error happens, code:%d - %s, reqId:0x%" PRIx64, pWrapper->pRequest->self, code, + tstrerror(code), pWrapper->pRequest->requestId); + destorySqlCallbackWrapper(pWrapper); + terrno = code; + pRequest->code = code; + pRequest->body.queryFp(pRequest->body.param, pRequest, code); + } +} + +void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) { + int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq); + if (TSDB_CODE_SUCCESS == code) { + code = phaseAsyncQuery(pWrapper); + } + + if (TSDB_CODE_SUCCESS != code) { + tscError("0x%" PRIx64 " error happens, code:%d - %s, reqId:0x%" PRIx64, pWrapper->pRequest->self, code, + tstrerror(code), pWrapper->pRequest->requestId); + destorySqlCallbackWrapper(pWrapper); + terrno = code; + pWrapper->pRequest->code = code; + pWrapper->pRequest->body.queryFp(pWrapper->pRequest->body.param, pWrapper->pRequest, code); } - retrieveMetaCallback(pWrapper->pResultMeta, pWrapper, TSDB_CODE_SUCCESS); - return TSDB_CODE_SUCCESS; } void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) { @@ -763,6 +827,11 @@ void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param taosAsyncQueryImpl(connId, sql, fp, param, false); } +void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) { + int64_t connId = *(int64_t *)taos; + taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid); +} + int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt) { const STscObj *pTscObj = pRequest->pTscObj; @@ -837,26 +906,16 @@ void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) { if (TSDB_CODE_SUCCESS == code && !updateMetaForce) { SAppClusterSummary *pActivity = &pTscObj->pAppInfo->summary; - if (NULL == pRequest->pQuery->pRoot) { + if (QUERY_NODE_INSERT_STMT == nodeType(pRequest->pQuery->pRoot)) { atomic_add_fetch_64((int64_t *)&pActivity->numOfInsertsReq, 1); - } else if (QUERY_NODE_SELECT_STMT == pRequest->pQuery->pRoot->type) { + } else if (QUERY_NODE_SELECT_STMT == nodeType(pRequest->pQuery->pRoot)) { atomic_add_fetch_64((int64_t *)&pActivity->numOfQueryReq, 1); } } if (TSDB_CODE_SUCCESS == code) { - SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter, - .requestId = pWrapper->pParseCtx->requestId, - .requestObjRefId = pWrapper->pParseCtx->requestRid, - .mgmtEps = pWrapper->pParseCtx->mgmtEpSet}; - - pRequest->metric.ctgStart = taosGetTimestampUs(); - - code = catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, retrieveMetaCallback, - pWrapper, &pRequest->body.queryJob); - } - - if (TSDB_CODE_SUCCESS != code) { + phaseAsyncQuery(pWrapper); + } else { tscError("0x%" PRIx64 " error happens, code:%d - %s, reqId:0x%" PRIx64, pRequest->self, code, tstrerror(code), pRequest->requestId); destorySqlCallbackWrapper(pWrapper); @@ -992,7 +1051,7 @@ int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInf int64_t connId = *(int64_t *)taos; SRequestObj *pRequest = NULL; char *sql = "taos_get_db_route_info"; - int32_t code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest); + int32_t code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { terrno = code; return terrno; @@ -1041,7 +1100,7 @@ int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId int64_t connId = *(int64_t *)taos; SRequestObj *pRequest = NULL; char *sql = "taos_get_table_vgId"; - int32_t code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest); + int32_t code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { return terrno; } @@ -1102,7 +1161,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { } char *sql = "taos_load_table_info"; - code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest); + code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { terrno = code; goto _return; @@ -1147,7 +1206,22 @@ TAOS_STMT *taos_stmt_init(TAOS *taos) { return NULL; } - TAOS_STMT *pStmt = stmtInit(pObj); + TAOS_STMT *pStmt = stmtInit(pObj, 0); + + releaseTscObj(*(int64_t *)taos); + + return pStmt; +} + +TAOS_STMT *taos_stmt_init_with_reqid(TAOS *taos, int64_t reqid) { + STscObj *pObj = acquireTscObj(*(int64_t *)taos); + if (NULL == pObj) { + tscError("invalid parameter for %s", __FUNCTION__); + terrno = TSDB_CODE_TSC_DISCONNECTED; + return NULL; + } + + TAOS_STMT *pStmt = stmtInit(pObj, reqid); releaseTscObj(*(int64_t *)taos); diff --git a/source/client/src/clientRawBlockWrite.c b/source/client/src/clientRawBlockWrite.c index 4326ab3519..90a2adb647 100644 --- a/source/client/src/clientRawBlockWrite.c +++ b/source/client/src/clientRawBlockWrite.c @@ -410,7 +410,7 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) { SDecoder decoder = {0}; SVAlterTbReq vAlterTbReq = {0}; char* string = NULL; - cJSON* json = NULL; + cJSON* json = NULL; // decode void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); @@ -525,7 +525,7 @@ static char* processDropSTable(SMqMetaRsp* metaRsp) { SDecoder decoder = {0}; SVDropStbReq req = {0}; char* string = NULL; - cJSON* json = NULL; + cJSON* json = NULL; // decode void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); @@ -558,7 +558,7 @@ static char* processDropTable(SMqMetaRsp* metaRsp) { SDecoder decoder = {0}; SVDropTbBatchReq req = {0}; char* string = NULL; - cJSON* json = NULL; + cJSON* json = NULL; // decode void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); @@ -603,7 +603,7 @@ static int32_t taosCreateStb(TAOS* taos, void* meta, int32_t metaLen) { int32_t code = TSDB_CODE_SUCCESS; SRequestObj* pRequest = NULL; - code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest); + code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; } @@ -692,7 +692,7 @@ static int32_t taosDropStb(TAOS* taos, void* meta, int32_t metaLen) { int32_t code = TSDB_CODE_SUCCESS; SRequestObj* pRequest = NULL; - code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest); + code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; } @@ -773,7 +773,7 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) { SQuery* pQuery = NULL; SHashObj* pVgroupHashmap = NULL; - code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest); + code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; } @@ -926,7 +926,7 @@ static int32_t taosDropTable(TAOS* taos, void* meta, int32_t metaLen) { SQuery* pQuery = NULL; SHashObj* pVgroupHashmap = NULL; - code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest); + code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; } @@ -1097,7 +1097,7 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) { SArray* pArray = NULL; SVgDataBlocks* pVgData = NULL; - code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest); + code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; @@ -1217,7 +1217,7 @@ int taos_write_raw_block(TAOS* taos, int rows, char* pData, const char* tbname) SQuery* pQuery = NULL; SSubmitReq* subReq = NULL; - SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT); + SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0); if (!pRequest) { uError("WriteRaw:createRequest error request is null"); code = terrno; @@ -1281,7 +1281,7 @@ int taos_write_raw_block(TAOS* taos, int rows, char* pData, const char* tbname) int32_t schemaLen = 0; int32_t submitLen = sizeof(SSubmitBlk) + schemaLen + rows * extendedRowSize; - int32_t totalLen = sizeof(SSubmitReq) + submitLen; + int32_t totalLen = sizeof(SSubmitReq) + submitLen; subReq = taosMemoryCalloc(1, totalLen); SSubmitBlk* blk = POINTER_SHIFT(subReq, sizeof(SSubmitReq)); void* blkSchema = POINTER_SHIFT(blk, sizeof(SSubmitBlk)); @@ -1407,7 +1407,7 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) { STableMeta* pTableMeta = NULL; terrno = TSDB_CODE_SUCCESS; - SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT); + SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0); if (!pRequest) { uError("WriteRaw:createRequest error request is null"); return terrno; @@ -1674,7 +1674,7 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) STableMeta* pTableMeta = NULL; terrno = TSDB_CODE_SUCCESS; - SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT); + SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0); if (!pRequest) { uError("WriteRaw:createRequest error request is null"); return terrno; diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c index 5da7bebf2a..d1aeaac587 100644 --- a/source/client/src/clientSml.c +++ b/source/client/src/clientSml.c @@ -28,12 +28,12 @@ #define QUOTE '"' #define SLASH '\\' -#define JUMP_SPACE(sql, sqlEnd) \ - while (sql < sqlEnd) { \ - if (*sql == SPACE) \ - sql++; \ - else \ - break; \ +#define JUMP_SPACE(sql, sqlEnd) \ + while (sql < sqlEnd) { \ + if (*sql == SPACE) \ + sql++; \ + else \ + break; \ } // comma , #define IS_SLASH_COMMA(sql) (*(sql) == COMMA && *((sql)-1) == SLASH) @@ -353,7 +353,7 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns, pReq.numOfTags = taosArrayGetSize(pTags); pReq.pTags = pTags; - code = buildRequest(info->taos->id, "", 0, NULL, false, &pRequest); + code = buildRequest(info->taos->id, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; } @@ -1010,9 +1010,9 @@ static void smlParseTelnetElement(const char **sql, const char *sqlEnd, const ch } } -static int32_t smlParseTelnetTags(const char *data, const char *sqlEnd, SArray *cols, char *childTableName, SHashObj *dumplicateKey, - SSmlMsgBuf *msg) { - if(!cols) return TSDB_CODE_OUT_OF_MEMORY; +static int32_t smlParseTelnetTags(const char *data, const char *sqlEnd, SArray *cols, char *childTableName, + SHashObj *dumplicateKey, SSmlMsgBuf *msg) { + if (!cols) return TSDB_CODE_OUT_OF_MEMORY; const char *sql = data; size_t childTableNameLen = strlen(tsSmlChildTableName); while (sql < sqlEnd) { @@ -1093,7 +1093,8 @@ static int32_t smlParseTelnetTags(const char *data, const char *sqlEnd, SArray * } // format: =[ =] -static int32_t smlParseTelnetString(SSmlHandle *info, const char *sql, const char *sqlEnd, SSmlTableInfo *tinfo, SArray *cols) { +static int32_t smlParseTelnetString(SSmlHandle *info, const char *sql, const char *sqlEnd, SSmlTableInfo *tinfo, + SArray *cols) { if (!sql) return TSDB_CODE_SML_INVALID_DATA; // parse metric @@ -1372,19 +1373,19 @@ static int32_t smlKvTimeArrayCompare(const void *key1, const void *key2) { static int32_t smlKvTimeHashCompare(const void *key1, const void *key2) { SHashObj *s1 = *(SHashObj **)key1; SHashObj *s2 = *(SHashObj **)key2; - SSmlKv **kv1pp = (SSmlKv **)taosHashGet(s1, TS, TS_LEN); - SSmlKv **kv2pp = (SSmlKv **)taosHashGet(s2, TS, TS_LEN); - if(!kv1pp || !kv2pp){ + SSmlKv **kv1pp = (SSmlKv **)taosHashGet(s1, TS, TS_LEN); + SSmlKv **kv2pp = (SSmlKv **)taosHashGet(s2, TS, TS_LEN); + if (!kv1pp || !kv2pp) { uError("smlKvTimeHashCompare kv is null"); return -1; } - SSmlKv *kv1 = *kv1pp; - SSmlKv *kv2 = *kv2pp; - if(!kv1 || kv1->type != TSDB_DATA_TYPE_TIMESTAMP){ + SSmlKv *kv1 = *kv1pp; + SSmlKv *kv2 = *kv2pp; + if (!kv1 || kv1->type != TSDB_DATA_TYPE_TIMESTAMP) { uError("smlKvTimeHashCompare kv1"); return -1; } - if(!kv2 || kv2->type != TSDB_DATA_TYPE_TIMESTAMP){ + if (!kv2 || kv2->type != TSDB_DATA_TYPE_TIMESTAMP) { uError("smlKvTimeHashCompare kv2"); return -1; } @@ -1947,7 +1948,7 @@ static int32_t smlParseValueFromJSON(cJSON *root, SSmlKv *kv) { } static int32_t smlParseColsFromJSON(cJSON *root, SArray *cols) { - if(!cols) return TSDB_CODE_OUT_OF_MEMORY; + if (!cols) return TSDB_CODE_OUT_OF_MEMORY; cJSON *metricVal = cJSON_GetObjectItem(root, "value"); if (metricVal == NULL) { return TSDB_CODE_TSC_INVALID_JSON; @@ -1971,7 +1972,7 @@ static int32_t smlParseColsFromJSON(cJSON *root, SArray *cols) { static int32_t smlParseTagsFromJSON(cJSON *root, SArray *pKVs, char *childTableName, SHashObj *dumplicateKey, SSmlMsgBuf *msg) { int32_t ret = TSDB_CODE_SUCCESS; - if (!pKVs){ + if (!pKVs) { return TSDB_CODE_OUT_OF_MEMORY; } cJSON *tags = cJSON_GetObjectItem(root, "tags"); @@ -2204,7 +2205,7 @@ static int32_t smlParseTelnetLine(SSmlHandle *info, void *data, const int len) { } if (info->protocol == TSDB_SML_TELNET_PROTOCOL) { - ret = smlParseTelnetString(info, (const char *)data, (char*)data + len, tinfo, cols); + ret = smlParseTelnetString(info, (const char *)data, (char *)data + len, tinfo, cols); } else if (info->protocol == TSDB_SML_JSON_PROTOCOL) { ret = smlParseJSONString(info, (cJSON *)data, tinfo, cols); } else { @@ -2384,16 +2385,16 @@ static void smlPrintStatisticInfo(SSmlHandle *info) { info->cost.endTime - info->cost.insertRpcTime, info->cost.endTime - info->cost.parseTime); } -static int32_t smlParseLine(SSmlHandle *info, char *lines[], char* rawLine, char* rawLineEnd, int numLines) { +static int32_t smlParseLine(SSmlHandle *info, char *lines[], char *rawLine, char *rawLineEnd, int numLines) { int32_t code = TSDB_CODE_SUCCESS; if (info->protocol == TSDB_SML_JSON_PROTOCOL) { - if(lines){ + if (lines) { code = smlParseJSON(info, *lines); - }else if(rawLine){ + } else if (rawLine) { code = smlParseJSON(info, rawLine); } if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlParseJSON failed:%s", info->id, lines?*lines:rawLine); + uError("SML:0x%" PRIx64 " smlParseJSON failed:%s", info->id, lines ? *lines : rawLine); return code; } return code; @@ -2401,19 +2402,19 @@ static int32_t smlParseLine(SSmlHandle *info, char *lines[], char* rawLine, char for (int32_t i = 0; i < numLines; ++i) { char *tmp = NULL; - int len = 0; - if(lines){ + int len = 0; + if (lines) { tmp = lines[i]; len = strlen(tmp); - }else if(rawLine){ + } else if (rawLine) { tmp = rawLine; - while(rawLine < rawLineEnd){ - if(*(rawLine++) == '\n'){ + while (rawLine < rawLineEnd) { + if (*(rawLine++) == '\n') { break; } len++; } - if(info->protocol == TSDB_SML_LINE_PROTOCOL && tmp[0] == '#'){ // this line is comment + if (info->protocol == TSDB_SML_LINE_PROTOCOL && tmp[0] == '#') { // this line is comment continue; } } @@ -2433,7 +2434,7 @@ static int32_t smlParseLine(SSmlHandle *info, char *lines[], char* rawLine, char return code; } -static int smlProcess(SSmlHandle *info, char *lines[], char* rawLine, char* rawLineEnd, int numLines) { +static int smlProcess(SSmlHandle *info, char *lines[], char *rawLine, char *rawLineEnd, int numLines) { int32_t code = TSDB_CODE_SUCCESS; int32_t retryNum = 0; @@ -2532,8 +2533,8 @@ static void smlInsertCallback(void *param, void *res, int32_t code) { smlDestroyInfo(info); } - -TAOS_RES *taos_schemaless_insert_inner(SRequestObj *request, char *lines[], char *rawLine, char *rawLineEnd, int numLines, int protocol, int precision) { +TAOS_RES *taos_schemaless_insert_inner(SRequestObj *request, char *lines[], char *rawLine, char *rawLineEnd, + int numLines, int protocol, int precision) { int batchs = 0; STscObj *pTscObj = request->pTscObj; @@ -2581,7 +2582,7 @@ TAOS_RES *taos_schemaless_insert_inner(SRequestObj *request, char *lines[], char batchs = ceil(((double)numLines) / LINE_BATCH); params.total = batchs; for (int i = 0; i < batchs; ++i) { - SRequestObj *req = (SRequestObj *)createRequest(pTscObj->id, TSDB_SQL_INSERT); + SRequestObj *req = (SRequestObj *)createRequest(pTscObj->id, TSDB_SQL_INSERT, 0); if (!req) { request->code = TSDB_CODE_OUT_OF_MEMORY; uError("SML:taos_schemaless_insert error request is null"); @@ -2608,16 +2609,16 @@ TAOS_RES *taos_schemaless_insert_inner(SRequestObj *request, char *lines[], char info->pRequest->body.queryFp = smlInsertCallback; info->pRequest->body.param = info; int32_t code = smlProcess(info, lines, rawLine, rawLineEnd, perBatch); - if(lines){ + if (lines) { lines += perBatch; } - if(rawLine){ + if (rawLine) { int num = 0; - while(rawLine < rawLineEnd){ - if(*(rawLine++) == '\n'){ + while (rawLine < rawLineEnd) { + if (*(rawLine++) == '\n') { num++; } - if(num == perBatch){ + if (num == perBatch) { break; } } @@ -2628,7 +2629,7 @@ TAOS_RES *taos_schemaless_insert_inner(SRequestObj *request, char *lines[], char } tsem_wait(¶ms.sem); - end: +end: taosThreadSpinDestroy(¶ms.lock); tsem_destroy(¶ms.sem); // ((STscObj *)taos)->schemalessType = 0; @@ -2653,9 +2654,7 @@ TAOS_RES *taos_schemaless_insert_inner(SRequestObj *request, char *lines[], char * 0 - influxDB line protocol * 1 - OpenTSDB telnet line protocol * 2 - OpenTSDB JSON format protocol - * @return return zero for successful insertion. Otherwise return none-zero error code of - * failure reason. - * + * @return TAOS_RES */ TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int protocol, int precision) { @@ -2664,7 +2663,7 @@ TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int pr return NULL; } - SRequestObj *request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT); + SRequestObj *request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT, 0); if (!request) { uError("SML:taos_schemaless_insert error request is null"); return NULL; @@ -2680,13 +2679,37 @@ TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int pr return taos_schemaless_insert_inner(request, lines, NULL, NULL, numLines, protocol, precision); } -TAOS_RES *taos_schemaless_insert_raw(TAOS* taos, char* lines, int len, int32_t *totalRows, int protocol, int precision){ +TAOS_RES *taos_schemaless_insert_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision, + int64_t reqid) { if (NULL == taos) { terrno = TSDB_CODE_TSC_DISCONNECTED; return NULL; } - SRequestObj *request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT); + SRequestObj *request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT, reqid); + if (!request) { + uError("SML:taos_schemaless_insert error request is null"); + return NULL; + } + + if (!lines) { + SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf}; + request->code = TSDB_CODE_SML_INVALID_DATA; + smlBuildInvalidDataMsg(&msg, "lines is null", NULL); + return (TAOS_RES *)request; + } + + return taos_schemaless_insert_inner(request, lines, NULL, NULL, numLines, protocol, precision); +} + +TAOS_RES *taos_schemaless_insert_raw(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, + int precision) { + if (NULL == taos) { + terrno = TSDB_CODE_TSC_DISCONNECTED; + return NULL; + } + + SRequestObj *request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT, 0); if (!request) { uError("SML:taos_schemaless_insert error request is null"); return NULL; @@ -2702,10 +2725,45 @@ TAOS_RES *taos_schemaless_insert_raw(TAOS* taos, char* lines, int len, int32_t * int numLines = 0; *totalRows = 0; char *tmp = lines; - for(int i = 0; i < len; i++){ - if(lines[i] == '\n' || i == len - 1){ + for (int i = 0; i < len; i++) { + if (lines[i] == '\n' || i == len - 1) { numLines++; - if(tmp[0] != '#' || protocol != TSDB_SML_LINE_PROTOCOL){ //ignore comment + if (tmp[0] != '#' || protocol != TSDB_SML_LINE_PROTOCOL) { // ignore comment + (*totalRows)++; + } + tmp = lines + i + 1; + } + } + return taos_schemaless_insert_inner(request, NULL, lines, lines + len, numLines, protocol, precision); +} + +TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, + int precision, int64_t reqid) { + if (NULL == taos) { + terrno = TSDB_CODE_TSC_DISCONNECTED; + return NULL; + } + + SRequestObj *request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT, reqid); + if (!request) { + uError("SML:taos_schemaless_insert error request is null"); + return NULL; + } + + if (!lines || len <= 0) { + SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf}; + request->code = TSDB_CODE_SML_INVALID_DATA; + smlBuildInvalidDataMsg(&msg, "lines is null", NULL); + return (TAOS_RES *)request; + } + + int numLines = 0; + *totalRows = 0; + char *tmp = lines; + for (int i = 0; i < len; i++) { + if (lines[i] == '\n' || i == len - 1) { + numLines++; + if (tmp[0] != '#' || protocol != TSDB_SML_LINE_PROTOCOL) { // ignore comment (*totalRows)++; } tmp = lines + i + 1; diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c index 7f8d857a0f..c5f49bce89 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -5,13 +5,18 @@ #include "clientStmt.h" -char *gStmtStatusStr[] = {"unknown", "init", "prepare", "settbname", "settags", "fetchFields", "bind", "bindCol", "addBatch", "exec"}; +char* gStmtStatusStr[] = {"unknown", "init", "prepare", "settbname", "settags", + "fetchFields", "bind", "bindCol", "addBatch", "exec"}; static int32_t stmtCreateRequest(STscStmt* pStmt) { int32_t code = 0; if (pStmt->exec.pRequest == NULL) { - code = buildRequest(pStmt->taos->id, pStmt->sql.sqlStr, pStmt->sql.sqlLen, NULL, false, &pStmt->exec.pRequest); + code = buildRequest(pStmt->taos->id, pStmt->sql.sqlStr, pStmt->sql.sqlLen, NULL, false, &pStmt->exec.pRequest, + pStmt->reqid); + if (pStmt->reqid != 0) { + pStmt->reqid++; + } if (TSDB_CODE_SUCCESS == code) { pStmt->exec.pRequest->syncQuery = true; } @@ -207,10 +212,10 @@ int32_t stmtCacheBlock(STscStmt* pStmt) { } STableDataBlocks** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); - if(!pSrc){ + if (!pSrc) { return TSDB_CODE_OUT_OF_MEMORY; } - STableDataBlocks* pDst = NULL; + STableDataBlocks* pDst = NULL; STMT_ERR_RET(qCloneStmtDataBlock(&pDst, *pSrc)); @@ -513,7 +518,7 @@ int32_t stmtResetStmt(STscStmt* pStmt) { return TSDB_CODE_SUCCESS; } -TAOS_STMT* stmtInit(STscObj* taos) { +TAOS_STMT* stmtInit(STscObj* taos, int64_t reqid) { STscObj* pObj = (STscObj*)taos; STscStmt* pStmt = NULL; @@ -533,9 +538,10 @@ TAOS_STMT* stmtInit(STscObj* taos) { pStmt->taos = pObj; pStmt->bInfo.needParse = true; pStmt->sql.status = STMT_INIT; + pStmt->reqid = reqid; STMT_LOG_SEQ(STMT_INIT); - + tscDebug("stmt:%p initialized", pStmt); return pStmt; diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index ebb7b50692..5d0121aa15 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -1172,11 +1172,7 @@ static int32_t doEnsureCapacity(SColumnInfoData* pColumn, const SDataBlockInfo* pColumn->nullbitmap = tmp; memset(&pColumn->nullbitmap[oldLen], 0, BitmapLen(numOfRows) - oldLen); - if (pColumn->info.type == TSDB_DATA_TYPE_NULL) { - return TSDB_CODE_SUCCESS; - } - - assert(pColumn->info.bytes); + ASSERT(pColumn->info.bytes); tmp = taosMemoryRealloc(pColumn->pData, numOfRows * pColumn->info.bytes); if (tmp == NULL) { return TSDB_CODE_OUT_OF_MEMORY; diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c index ccd781d138..d401f9c17b 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c @@ -145,7 +145,6 @@ static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtyp pHead->contLen = ntohl(pHead->contLen); pHead->vgId = ntohl(pHead->vgId); - pHead->msgMask = ntohl(pHead->msgMask); SVnodeObj *pVnode = vmAcquireVnode(pMgmt, pHead->vgId); if (pVnode == NULL) { @@ -156,15 +155,9 @@ static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtyp switch (qtype) { case QUERY_QUEUE: - if ((pMsg->msgType == TDMT_SCH_QUERY) && (grantCheck(TSDB_GRANT_TIME) != TSDB_CODE_SUCCESS) && !TEST_SHOW_REWRITE_MASK(pHead->msgMask)) { - terrno = TSDB_CODE_GRANT_EXPIRED; - code = terrno; - dDebug("vgId:%d, msg:%p put into vnode-query queue failed since %s", pVnode->vgId, pMsg, terrstr(code)); - } else { - vnodePreprocessQueryMsg(pVnode->pImpl, pMsg); - dGTrace("vgId:%d, msg:%p put into vnode-query queue", pVnode->vgId, pMsg); - taosWriteQitem(pVnode->pQueryQ, pMsg); - } + vnodePreprocessQueryMsg(pVnode->pImpl, pMsg); + dGTrace("vgId:%d, msg:%p put into vnode-query queue", pVnode->vgId, pMsg); + taosWriteQitem(pVnode->pQueryQ, pMsg); break; case STREAM_QUEUE: dGTrace("vgId:%d, msg:%p put into vnode-stream queue", pVnode->vgId, pMsg); diff --git a/source/dnode/mnode/impl/src/mndQuery.c b/source/dnode/mnode/impl/src/mndQuery.c index ca69d0c71c..2b0edfebc2 100644 --- a/source/dnode/mnode/impl/src/mndQuery.c +++ b/source/dnode/mnode/impl/src/mndQuery.c @@ -21,7 +21,7 @@ int32_t mndPreProcessQueryMsg(SRpcMsg *pMsg) { if (TDMT_SCH_QUERY != pMsg->msgType && TDMT_SCH_MERGE_QUERY != pMsg->msgType) return 0; SMnode *pMnode = pMsg->info.node; - return qWorkerPreprocessQueryMsg(pMnode->pQuery, pMsg); + return qWorkerPreprocessQueryMsg(pMnode->pQuery, pMsg, false); } void mndPostProcessQueryMsg(SRpcMsg *pMsg) { diff --git a/source/dnode/mnode/impl/src/mndStb.c b/source/dnode/mnode/impl/src/mndStb.c index b6f7e31638..cee0b84672 100644 --- a/source/dnode/mnode/impl/src/mndStb.c +++ b/source/dnode/mnode/impl/src/mndStb.c @@ -519,7 +519,6 @@ static void *mndBuildVDropStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStb, pHead->contLen = htonl(contLen); pHead->vgId = htonl(pVgroup->vgId); - pHead->msgMask = htonl(0); void *pBuf = POINTER_SHIFT(pHead, sizeof(SMsgHead)); diff --git a/source/dnode/mnode/impl/src/mndSync.c b/source/dnode/mnode/impl/src/mndSync.c index abb23bfb89..ebab83cf6d 100644 --- a/source/dnode/mnode/impl/src/mndSync.c +++ b/source/dnode/mnode/impl/src/mndSync.c @@ -202,6 +202,13 @@ static void mndBecomeLeader(const SSyncFSM *pFsm) { SMnode *pMnode = pFsm->data; } +static bool mndApplyQueueEmpty(const SSyncFSM *pFsm) { + SMnode *pMnode = pFsm->data; + + int32_t itemSize = tmsgGetQueueSize(&pMnode->msgCb, 1, APPLY_QUEUE); + return (itemSize == 0); +} + SSyncFSM *mndSyncMakeFsm(SMnode *pMnode) { SSyncFSM *pFsm = taosMemoryCalloc(1, sizeof(SSyncFSM)); pFsm->data = pMnode; @@ -210,6 +217,7 @@ SSyncFSM *mndSyncMakeFsm(SMnode *pMnode) { pFsm->FpRollBackCb = NULL; pFsm->FpRestoreFinishCb = mndRestoreFinish; pFsm->FpLeaderTransferCb = NULL; + pFsm->FpApplyQueueEmptyCb = mndApplyQueueEmpty; pFsm->FpReConfigCb = NULL; pFsm->FpBecomeLeaderCb = mndBecomeLeader; pFsm->FpBecomeFollowerCb = mndBecomeFollower; diff --git a/source/dnode/qnode/src/qnode.c b/source/dnode/qnode/src/qnode.c index 289251f560..5efc714e95 100644 --- a/source/dnode/qnode/src/qnode.c +++ b/source/dnode/qnode/src/qnode.c @@ -69,7 +69,7 @@ int32_t qndPreprocessQueryMsg(SQnode *pQnode, SRpcMsg *pMsg) { return 0; } - return qWorkerPreprocessQueryMsg(pQnode->pQuery, pMsg); + return qWorkerPreprocessQueryMsg(pQnode->pQuery, pMsg, false); } int32_t qndProcessQueryMsg(SQnode *pQnode, int64_t ts, SRpcMsg *pMsg) { diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c index 43e80b99d4..4aabd39800 100644 --- a/source/dnode/vnode/src/meta/metaQuery.c +++ b/source/dnode/vnode/src/meta/metaQuery.c @@ -153,7 +153,7 @@ bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid) { int metaGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid) { SMeta *pMeta = pReader->pMeta; - int64_t version; + int64_t version1; // query uid.idx if (tdbTbGet(pMeta->pUidIdx, &uid, sizeof(uid), &pReader->pBuf, &pReader->szBuf) < 0) { @@ -161,8 +161,8 @@ int metaGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid) { return -1; } - version = ((SUidIdxVal *)pReader->pBuf)[0].version; - return metaGetTableEntryByVersion(pReader, version, uid); + version1 = ((SUidIdxVal *)pReader->pBuf)[0].version; + return metaGetTableEntryByVersion(pReader, version1, uid); } int metaGetTableEntryByName(SMetaReader *pReader, const char *name) { diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c index 78d95cf0d7..089905ee20 100644 --- a/source/dnode/vnode/src/vnd/vnodeSvr.c +++ b/source/dnode/vnode/src/vnd/vnodeSvr.c @@ -329,7 +329,7 @@ int32_t vnodePreprocessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) { return 0; } - return qWorkerPreprocessQueryMsg(pVnode->pQuery, pMsg); + return qWorkerPreprocessQueryMsg(pVnode->pQuery, pMsg, TDMT_SCH_QUERY == pMsg->msgType); } int32_t vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) { diff --git a/source/dnode/vnode/src/vnd/vnodeSync.c b/source/dnode/vnode/src/vnd/vnodeSync.c index 3913561ae7..e7f8c9f562 100644 --- a/source/dnode/vnode/src/vnd/vnodeSync.c +++ b/source/dnode/vnode/src/vnd/vnodeSync.c @@ -436,6 +436,12 @@ static void vnodeBecomeLeader(const SSyncFSM *pFsm) { vDebug("vgId:%d, become leader", pVnode->config.vgId); } +static bool vnodeApplyQueueEmpty(const SSyncFSM *pFsm) { + SVnode *pVnode = pFsm->data; + int32_t itemSize = tmsgGetQueueSize(&pVnode->msgCb, pVnode->config.vgId, APPLY_QUEUE); + return (itemSize == 0); +} + static SSyncFSM *vnodeSyncMakeFsm(SVnode *pVnode) { SSyncFSM *pFsm = taosMemoryCalloc(1, sizeof(SSyncFSM)); pFsm->data = pVnode; @@ -445,6 +451,7 @@ static SSyncFSM *vnodeSyncMakeFsm(SVnode *pVnode) { pFsm->FpGetSnapshotInfo = vnodeSyncGetSnapshot; pFsm->FpRestoreFinishCb = vnodeRestoreFinish; pFsm->FpLeaderTransferCb = NULL; + pFsm->FpApplyQueueEmptyCb = vnodeApplyQueueEmpty; pFsm->FpBecomeLeaderCb = vnodeBecomeLeader; pFsm->FpBecomeFollowerCb = vnodeBecomeFollower; pFsm->FpReConfigCb = NULL; diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index e20c8ee955..5051bedf8d 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -298,6 +298,12 @@ typedef struct { SExprSupp* pExprSup; // expr supporter of aggregate operator } SAggOptrPushDownInfo; +typedef struct STableMetaCacheInfo { + SLRUCache* pTableMetaEntryCache; // 100 by default + uint64_t metaFetch; + uint64_t cacheHit; +} STableMetaCacheInfo; + typedef struct STableScanInfo { STsdbReader* dataReader; SReadHandle readHandle; @@ -305,7 +311,6 @@ typedef struct STableScanInfo { SFileBlockLoadRecorder readRecorder; SScanInfo scanInfo; int32_t scanTimes; - SNode* pFilterNode; // filter info, which is push down by optimizer SSDataBlock* pResBlock; SColMatchInfo matchInfo; SExprSupp pseudoSup; @@ -318,6 +323,7 @@ typedef struct STableScanInfo { int8_t scanMode; SAggOptrPushDownInfo pdInfo; int8_t assignBlockUid; + STableMetaCacheInfo metaCache; } STableScanInfo; typedef struct STableMergeScanInfo { @@ -326,7 +332,6 @@ typedef struct STableMergeScanInfo { int32_t tableEndIndex; bool hasGroupId; uint64_t groupId; - SArray* dataReaders; // array of tsdbReaderT* SArray* queryConds; // array of queryTableDataCond STsdbReader* pReader; SReadHandle readHandle; @@ -342,7 +347,6 @@ typedef struct STableMergeScanInfo { int64_t numOfRows; SScanInfo scanInfo; int32_t scanTimes; - SNode* pFilterNode; // filter info, which is push down by optimizer SqlFunctionCtx* pCtx; // which belongs to the direct upstream operator operator query context SResultRowInfo* pResultRowInfo; int32_t* rowEntryInfoOffset; @@ -460,7 +464,6 @@ typedef struct SStreamScanInfo { SReadHandle readHandle; SInterval interval; // if the upstream is an interval operator, the interval info is also kept here. SColMatchInfo matchInfo; - SNode* pCondition; SArray* pBlockLists; // multiple SSDatablock. SSDataBlock* pRes; // result SSDataBlock @@ -564,7 +567,6 @@ typedef struct SIntervalAggOperatorInfo { EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model] STimeWindowAggSupp twAggSup; SArray* pPrevValues; // SArray used to keep the previous not null value for interpolation. - SNode* pCondition; } SIntervalAggOperatorInfo; typedef struct SMergeAlignedIntervalAggOperatorInfo { @@ -573,12 +575,10 @@ typedef struct SMergeAlignedIntervalAggOperatorInfo { uint64_t groupId; // current groupId int64_t curTs; // current ts SSDataBlock* prefetchedBlock; - SNode* pCondition; SResultRow* pResultRow; } SMergeAlignedIntervalAggOperatorInfo; typedef struct SStreamIntervalOperatorInfo { - // SOptrBasicInfo should be first, SAggSupporter should be second for stream encode SOptrBasicInfo binfo; // basic info SAggSupporter aggSup; // aggregate supporter SExprSupp scalarSupp; // supporter for perform scalar function @@ -604,26 +604,21 @@ typedef struct SStreamIntervalOperatorInfo { } SStreamIntervalOperatorInfo; typedef struct SAggOperatorInfo { - // SOptrBasicInfo should be first, SAggSupporter should be second for stream encode - SOptrBasicInfo binfo; - SAggSupporter aggSup; - + SOptrBasicInfo binfo; + SAggSupporter aggSup; STableQueryInfo* current; uint64_t groupId; SGroupResInfo groupResInfo; SExprSupp scalarExprSup; - SNode* pCondition; } SAggOperatorInfo; typedef struct SProjectOperatorInfo { SOptrBasicInfo binfo; SAggSupporter aggSup; - SNode* pFilterNode; // filter info, which is push down by optimizer SArray* pPseudoColInfo; SLimitInfo limitInfo; bool mergeDataBlocks; SSDataBlock* pFinalRes; - SNode* pCondition; } SProjectOperatorInfo; typedef struct SIndefOperatorInfo { @@ -631,10 +626,8 @@ typedef struct SIndefOperatorInfo { SAggSupporter aggSup; SArray* pPseudoColInfo; SExprSupp scalarSup; - SNode* pCondition; uint64_t groupId; - - SSDataBlock* pNextGroupRes; + SSDataBlock* pNextGroupRes; } SIndefOperatorInfo; typedef struct SFillOperatorInfo { @@ -645,7 +638,6 @@ typedef struct SFillOperatorInfo { void** p; SSDataBlock* existNewGroupBlock; STimeWindow win; - SNode* pCondition; SColMatchInfo matchInfo; int32_t primaryTsCol; int32_t primarySrcSlotId; @@ -660,7 +652,6 @@ typedef struct SGroupbyOperatorInfo { SAggSupporter aggSup; SArray* pGroupCols; // group by columns, SArray SArray* pGroupColVals; // current group column values, SArray - SNode* pCondition; bool isInit; // denote if current val is initialized or not char* keyBuf; // group by keys for hash int32_t groupKeyLen; // total group by column width @@ -710,7 +701,6 @@ typedef struct SSessionAggOperatorInfo { int64_t gap; // session window gap int32_t tsSlotId; // primary timestamp slot id STimeWindowAggSupp twAggSup; - const SNode* pCondition; } SSessionAggOperatorInfo; typedef struct SResultWindowInfo { @@ -784,7 +774,6 @@ typedef struct SStreamFillOperatorInfo { SSDataBlock* pSrcDelBlock; int32_t srcDelRowIndex; SSDataBlock* pDelRes; - SNode* pCondition; SColMatchInfo matchInfo; int32_t primaryTsCol; int32_t primarySrcSlotId; @@ -821,7 +810,6 @@ typedef struct SStateWindowOperatorInfo { SStateKeys stateKey; int32_t tsSlotId; // primary timestamp column slot id STimeWindowAggSupp twAggSup; - const SNode* pCondition; } SStateWindowOperatorInfo; typedef struct SSortOperatorInfo { @@ -834,7 +822,6 @@ typedef struct SSortOperatorInfo { int64_t startTs; // sort start time uint64_t sortElapsed; // sort elapsed time, time to flush to disk not included. SLimitInfo limitInfo; - SNode* pCondition; } SSortOperatorInfo; typedef struct SJoinOperatorInfo { @@ -895,9 +882,9 @@ int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scan int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, uint32_t* defaultBufsz); void doSetOperatorCompleted(SOperatorInfo* pOperator); -void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock, SColMatchInfo* pColMatchInfo, SFilterInfo* pFilterInfo); -int32_t addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_t numOfPseudoExpr, - SSDataBlock* pBlock, int32_t rows, const char* idStr); +void doFilter(SSDataBlock* pBlock, SFilterInfo* pFilterInfo, SColMatchInfo* pColMatchInfo); +int32_t addTagPseudoColumnData(SReadHandle* pHandle, const SExprInfo* pExpr, int32_t numOfExpr, + SSDataBlock* pBlock, int32_t rows, const char* idStr, STableMetaCacheInfo * pCache); void cleanupAggSup(SAggSupporter* pAggSup); void appendOneRowToDataBlock(SSDataBlock* pBlock, STupleHandle* pTupleHandle); diff --git a/source/libs/executor/src/cachescanoperator.c b/source/libs/executor/src/cachescanoperator.c index 95d3c5cf23..76866eedb7 100644 --- a/source/libs/executor/src/cachescanoperator.c +++ b/source/libs/executor/src/cachescanoperator.c @@ -172,7 +172,7 @@ SSDataBlock* doScanCache(SOperatorInfo* pOperator) { SExprSupp* pSup = &pInfo->pseudoExprSup; int32_t code = addTagPseudoColumnData(&pInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pRes, - pRes->info.rows, GET_TASKID(pTaskInfo)); + pRes->info.rows, GET_TASKID(pTaskInfo), NULL); if (code != TSDB_CODE_SUCCESS) { pTaskInfo->code = code; return NULL; @@ -221,7 +221,7 @@ SSDataBlock* doScanCache(SOperatorInfo* pOperator) { pInfo->pRes->info.uid = *(tb_uid_t*)taosArrayGet(pInfo->pUidList, 0); code = addTagPseudoColumnData(&pInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pInfo->pRes, pInfo->pRes->info.rows, - GET_TASKID(pTaskInfo)); + GET_TASKID(pTaskInfo), NULL); if (code != TSDB_CODE_SUCCESS) { pTaskInfo->code = code; return NULL; diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index deb628f30e..7e93232e0c 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -1039,39 +1039,24 @@ void setResultRowInitCtx(SResultRow* pResult, SqlFunctionCtx* pCtx, int32_t numO static void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const SColumnInfoData* p, bool keep, int32_t status); -void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock, SColMatchInfo* pColMatchInfo, SFilterInfo* pFilterInfo) { - if (pFilterNode == NULL || pBlock->info.rows == 0) { +void doFilter(SSDataBlock* pBlock, SFilterInfo* pFilterInfo, SColMatchInfo* pColMatchInfo) { + if (pFilterInfo == NULL || pBlock->info.rows == 0) { return; } - SFilterInfo* filter = pFilterInfo; - int64_t st = taosGetTimestampUs(); - - // todo move to the initialization function - int32_t code = 0; - bool needFree = false; - if (filter == NULL) { - needFree = true; - code = filterInitFromNode((SNode*)pFilterNode, &filter, 0); - } - SFilterColumnParam param1 = {.numOfCols = taosArrayGetSize(pBlock->pDataBlock), .pDataBlock = pBlock->pDataBlock}; - code = filterSetDataFromSlotId(filter, ¶m1); + int32_t code = filterSetDataFromSlotId(pFilterInfo, ¶m1); SColumnInfoData* p = NULL; int32_t status = 0; // todo the keep seems never to be True?? - bool keep = filterExecute(filter, pBlock, &p, NULL, param1.numOfCols, &status); - - if (needFree) { - filterFreeInfo(filter); - } - + bool keep = filterExecute(pFilterInfo, pBlock, &p, NULL, param1.numOfCols, &status); extractQualifiedTupleByFilterResult(pBlock, p, keep, status); if (pColMatchInfo != NULL) { - for (int32_t i = 0; i < taosArrayGetSize(pColMatchInfo->pList); ++i) { + size_t size = taosArrayGetSize(pColMatchInfo->pList); + for (int32_t i = 0; i < size; ++i) { SColMatchItem* pInfo = taosArrayGet(pColMatchInfo->pList, i); if (pInfo->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, pInfo->dstSlotId); @@ -2393,7 +2378,7 @@ static SSDataBlock* getAggregateResult(SOperatorInfo* pOperator) { blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity); while (1) { doBuildResultDatablock(pOperator, pInfo, &pAggInfo->groupResInfo, pAggInfo->aggSup.pResultBuf); - doFilter(pAggInfo->pCondition, pInfo->pRes, NULL, NULL); + doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); if (!hasRemainResults(&pAggInfo->groupResInfo)) { doSetOperatorCompleted(pOperator); @@ -2726,7 +2711,7 @@ static SSDataBlock* doFill(SOperatorInfo* pOperator) { break; } - doFilter(pInfo->pCondition, fillResult, &pInfo->matchInfo, NULL); + doFilter(fillResult, pOperator->exprSupp.pFilterInfo, &pInfo->matchInfo ); if (fillResult->info.rows > 0) { break; } @@ -2945,9 +2930,13 @@ SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SAggPhysiN goto _error; } + code = filterInitFromNode((SNode*)pAggNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + pInfo->binfo.mergeResultBlock = pAggNode->mergeDataBlock; pInfo->groupId = UINT64_MAX; - pInfo->pCondition = pAggNode->node.pConditions; pOperator->name = "TableAggregate"; pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_HASH_AGG; pOperator->blocking = true; @@ -3173,7 +3162,11 @@ SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SFillPhysiNode* pInfo->pFinalRes = createOneDataBlock(pInfo->pRes, false); blockDataEnsureCapacity(pInfo->pFinalRes, pOperator->resultInfo.capacity); - pInfo->pCondition = pPhyFillNode->node.pConditions; + code = filterInitFromNode((SNode*)pPhyFillNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + pOperator->name = "FillOperator"; pOperator->blocking = false; pOperator->status = OP_NOT_OPENED; diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c index ecc9c7e7dd..891eb6e7a4 100644 --- a/source/libs/executor/src/groupoperator.c +++ b/source/libs/executor/src/groupoperator.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "filter.h" #include "function.h" #include "os.h" #include "tname.h" @@ -312,7 +313,7 @@ static SSDataBlock* buildGroupResultDataBlock(SOperatorInfo* pOperator) { SSDataBlock* pRes = pInfo->binfo.pRes; while (1) { doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf); - doFilter(pInfo->pCondition, pRes, NULL, NULL); + doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL); if (!hasRemainResults(&pInfo->groupResInfo)) { doSetOperatorCompleted(pOperator); @@ -411,8 +412,6 @@ SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* } pInfo->pGroupCols = extractColumnInfo(pAggNode->pGroupKeys); - pInfo->pCondition = pAggNode->node.pConditions; - int32_t code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, numOfScalarExpr); if (code != TSDB_CODE_SUCCESS) { goto _error; @@ -433,6 +432,11 @@ SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* goto _error; } + code = filterInitFromNode((SNode*)pAggNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + initResultRowInfo(&pInfo->binfo.resultRowInfo); pOperator->name = "GroupbyAggOperator"; diff --git a/source/libs/executor/src/joinoperator.c b/source/libs/executor/src/joinoperator.c index 8dac44684f..45d76dce74 100644 --- a/source/libs/executor/src/joinoperator.c +++ b/source/libs/executor/src/joinoperator.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "filter.h" #include "executorimpl.h" #include "function.h" #include "os.h" @@ -108,6 +109,11 @@ SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t pInfo->pCondAfterMerge = NULL; } + code = filterInitFromNode(pInfo->pCondAfterMerge, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + pInfo->inputOrder = TSDB_ORDER_ASC; if (pJoinNode->inputTsOrder == ORDER_ASC) { pInfo->inputOrder = TSDB_ORDER_ASC; @@ -400,8 +406,8 @@ SSDataBlock* doMergeJoin(struct SOperatorInfo* pOperator) { if (numOfNewRows == 0) { break; } - if (pJoinInfo->pCondAfterMerge != NULL) { - doFilter(pJoinInfo->pCondAfterMerge, pRes, NULL, NULL); + if (pOperator->exprSupp.pFilterInfo != NULL) { + doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL); } if (pRes->info.rows >= pOperator->resultInfo.threshold) { break; diff --git a/source/libs/executor/src/projectoperator.c b/source/libs/executor/src/projectoperator.c index ba076233aa..b2865d15f0 100644 --- a/source/libs/executor/src/projectoperator.c +++ b/source/libs/executor/src/projectoperator.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "filter.h" #include "executorimpl.h" #include "functionMgt.h" @@ -71,13 +72,7 @@ SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhys pInfo->binfo.pRes = pResBlock; pInfo->pFinalRes = createOneDataBlock(pResBlock, false); - pInfo->pFilterNode = pProjPhyNode->node.pConditions; - - if (pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM) { - pInfo->mergeDataBlocks = false; - } else { - pInfo->mergeDataBlocks = pProjPhyNode->mergeDataBlock; - } + pInfo->mergeDataBlocks = (pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM)? false:pProjPhyNode->mergeDataBlock; int32_t numOfRows = 4096; size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES; @@ -97,6 +92,11 @@ SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhys initBasicInfo(&pInfo->binfo, pResBlock); setFunctionResultOutput(pOperator, &pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, numOfCols); + code = filterInitFromNode((SNode*)pProjPhyNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pOperator->exprSupp.pCtx, numOfCols); pOperator->name = "ProjectOperator"; pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_PROJECT; @@ -313,7 +313,7 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) { } // do apply filter - doFilter(pProjectInfo->pFilterNode, pFinalRes, NULL, NULL); + doFilter(pFinalRes, pOperator->exprSupp.pFilterInfo, NULL); // when apply the limit/offset for each group, pRes->info.rows may be 0, due to limit constraint. if (pFinalRes->info.rows > 0 || (pOperator->status == OP_EXEC_DONE)) { @@ -323,7 +323,7 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) { } else { // do apply filter if (pRes->info.rows > 0) { - doFilter(pProjectInfo->pFilterNode, pRes, NULL, NULL); + doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL); if (pRes->info.rows == 0) { continue; } @@ -392,7 +392,12 @@ SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhy } setFunctionResultOutput(pOperator, &pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, numOfExpr); - pInfo->pCondition = pPhyNode->node.pConditions; + code = filterInitFromNode((SNode*)pPhyNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + pInfo->binfo.pRes = pResBlock; pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pSup->pCtx, numOfExpr); pOperator->name = "IndefinitOperator"; @@ -515,7 +520,7 @@ SSDataBlock* doApplyIndefinitFunction(SOperatorInfo* pOperator) { } } - doFilter(pIndefInfo->pCondition, pInfo->pRes, NULL, NULL); + doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); size_t rows = pInfo->pRes->info.rows; if (rows > 0 || pOperator->status == OP_EXEC_DONE) { break; @@ -617,7 +622,7 @@ SSDataBlock* doGenerateSourceData(SOperatorInfo* pOperator) { } pRes->info.rows = 1; - doFilter(pProjectInfo->pFilterNode, pRes, NULL, NULL); + doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL); /*int32_t status = */ doIngroupLimitOffset(&pProjectInfo->limitInfo, 0, pRes, pOperator); diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index 937069b5cc..ee935837d0 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include #include "executorimpl.h" #include "filter.h" #include "function.h" @@ -115,8 +116,10 @@ static int32_t sysTableUserTagsFillOneTableTags(const SSysTableScanInfo* pInfo, SMetaReader* smrChildTable, const char* dbname, const char* tableName, int32_t* pNumOfRows, const SSDataBlock* dataBlock); -static void relocateAndFilterSysTagsScanResult(SSysTableScanInfo* pInfo, int32_t numOfRows, SSDataBlock* dataBlock); -bool processBlockWithProbability(const SSampleExecInfo* pInfo) { +static void relocateAndFilterSysTagsScanResult(SSysTableScanInfo* pInfo, int32_t numOfRows, SSDataBlock* dataBlock, + SFilterInfo* pFilterInfo); + +bool processBlockWithProbability(const SSampleExecInfo* pInfo) { #if 0 if (pInfo->sampleRatio == 1) { return true; @@ -280,19 +283,13 @@ static int32_t doDynamicPruneDataBlock(SOperatorInfo* pOperator, SDataBlockInfo* return TSDB_CODE_SUCCESS; } -static bool doFilterByBlockSMA(const SNode* pFilterNode, SColumnDataAgg** pColsAgg, int32_t numOfCols, +static bool doFilterByBlockSMA(SFilterInfo* pFilterInfo, SColumnDataAgg** pColsAgg, int32_t numOfCols, int32_t numOfRows) { - if (pColsAgg == NULL || pFilterNode == NULL) { + if (pColsAgg == NULL || pFilterInfo == NULL) { return true; } - SFilterInfo* filter = NULL; - - // todo move to the initialization function - int32_t code = filterInitFromNode((SNode*)pFilterNode, &filter, 0); - bool keep = filterRangeExecute(filter, pColsAgg, numOfCols, numOfRows); - - filterFreeInfo(filter); + bool keep = filterRangeExecute(pFilterInfo, pColsAgg, numOfCols, numOfRows); return keep; } @@ -339,7 +336,7 @@ static void doSetTagColumnData(STableScanInfo* pTableScanInfo, SSDataBlock* pBlo SExprSupp* pSup = &pTableScanInfo->pseudoSup; int32_t code = addTagPseudoColumnData(&pTableScanInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pBlock, rows, - GET_TASKID(pTaskInfo)); + GET_TASKID(pTaskInfo), &pTableScanInfo->metaCache); if (code != TSDB_CODE_SUCCESS) { T_LONG_JMP(pTaskInfo->env, code); } @@ -386,7 +383,7 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanInfo* pTableSca bool loadSMA = false; *status = pInfo->dataBlockLoadFlag; - if (pTableScanInfo->pFilterNode != NULL || + if (pOperator->exprSupp.pFilterInfo != NULL || overlapWithTimeWindow(&pTableScanInfo->pdInfo.interval, &pBlock->info, pTableScanInfo->cond.order)) { (*status) = FUNC_DATA_REQUIRED_DATA_LOAD; } @@ -424,11 +421,11 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanInfo* pTableSca ASSERT(*status == FUNC_DATA_REQUIRED_DATA_LOAD); // try to filter data block according to sma info - if (pTableScanInfo->pFilterNode != NULL && (!loadSMA)) { + if (pOperator->exprSupp.pFilterInfo != NULL && (!loadSMA)) { bool success = doLoadBlockSMA(pTableScanInfo, pBlock, pTaskInfo); if (success) { size_t size = taosArrayGetSize(pBlock->pDataBlock); - bool keep = doFilterByBlockSMA(pTableScanInfo->pFilterNode, pBlock->pBlockAgg, size, pBlockInfo->rows); + bool keep = doFilterByBlockSMA(pOperator->exprSupp.pFilterInfo, pBlock->pBlockAgg, size, pBlockInfo->rows); if (!keep) { qDebug("%s data block filter out by block SMA, brange:%" PRId64 "-%" PRId64 ", rows:%d", GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); @@ -468,9 +465,9 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanInfo* pTableSca // restore the previous value pCost->totalRows -= pBlock->info.rows; - if (pTableScanInfo->pFilterNode != NULL) { + if (pOperator->exprSupp.pFilterInfo != NULL) { int64_t st = taosGetTimestampUs(); - doFilter(pTableScanInfo->pFilterNode, pBlock, &pTableScanInfo->matchInfo, pOperator->exprSupp.pFilterInfo); + doFilter(pBlock, pOperator->exprSupp.pFilterInfo, &pTableScanInfo->matchInfo); double el = (taosGetTimestampUs() - st) / 1000.0; pTableScanInfo->readRecorder.filterTime += el; @@ -495,51 +492,128 @@ static void prepareForDescendingScan(STableScanInfo* pTableScanInfo, SqlFunction SET_REVERSE_SCAN_FLAG(pTableScanInfo); switchCtxOrder(pCtx, numOfOutput); - // setupQueryRangeForReverseScan(pTableScanInfo); - pTableScanInfo->cond.order = TSDB_ORDER_DESC; STimeWindow* pTWindow = &pTableScanInfo->cond.twindows; TSWAP(pTWindow->skey, pTWindow->ekey); } -int32_t addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int32_t numOfPseudoExpr, - SSDataBlock* pBlock, int32_t rows, const char* idStr) { +typedef struct STableCachedVal { + const char* pName; + STag* pTags; +} STableCachedVal; + +static void freeTableCachedVal(void* param) { + if (param == NULL) { + return; + } + + STableCachedVal* pVal = param; + taosMemoryFree((void*)pVal->pName); + taosMemoryFree(pVal->pTags); + taosMemoryFree(pVal); +} + +//const void *key, size_t keyLen, void *value +static void freeCachedMetaItem(const void *key, size_t keyLen, void *value) { + freeTableCachedVal(value); +} + +int32_t addTagPseudoColumnData(SReadHandle* pHandle, const SExprInfo* pExpr, int32_t numOfExpr, + SSDataBlock* pBlock, int32_t rows, const char* idStr, STableMetaCacheInfo* pCache) { // currently only the tbname pseudo column - if (numOfPseudoExpr <= 0) { + if (numOfExpr <= 0) { return TSDB_CODE_SUCCESS; } + int32_t code = 0; + // backup the rows int32_t backupRows = pBlock->info.rows; pBlock->info.rows = rows; - SMetaReader mr = {0}; - metaReaderInit(&mr, pHandle->meta, 0); - int32_t code = metaGetTableEntryByUid(&mr, pBlock->info.uid); - metaReaderReleaseLock(&mr); + bool freeReader = false; + STableCachedVal val = {0}; - if (code != TSDB_CODE_SUCCESS) { - qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", pBlock->info.uid, tstrerror(terrno), idStr); - metaReaderClear(&mr); - return terrno; + SMetaReader mr = {0}; + LRUHandle* h = NULL; + + // 1. check if it is existed in meta cache + if (pCache == NULL) { + metaReaderInit(&mr, pHandle->meta, 0); + code = metaGetTableEntryByUid(&mr, pBlock->info.uid); + if (code != TSDB_CODE_SUCCESS) { + qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", pBlock->info.uid, tstrerror(terrno), idStr); + metaReaderClear(&mr); + return terrno; + } + + metaReaderReleaseLock(&mr); + + val.pName = mr.me.name; + val.pTags = (STag*)mr.me.ctbEntry.pTags; + + freeReader = true; + } else { + pCache->metaFetch += 1; + + h = taosLRUCacheLookup(pCache->pTableMetaEntryCache, &pBlock->info.uid, sizeof(pBlock->info.uid)); + if (h == NULL) { + metaReaderInit(&mr, pHandle->meta, 0); + code = metaGetTableEntryByUid(&mr, pBlock->info.uid); + if (code != TSDB_CODE_SUCCESS) { + qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", pBlock->info.uid, tstrerror(terrno), idStr); + metaReaderClear(&mr); + return terrno; + } + + metaReaderReleaseLock(&mr); + + STableCachedVal* pVal = taosMemoryMalloc(sizeof(STableCachedVal)); + pVal->pName = strdup(mr.me.name); + pVal->pTags = NULL; + + // only child table has tag value + if (mr.me.type == TSDB_CHILD_TABLE) { + STag* pTag = (STag*)mr.me.ctbEntry.pTags; + pVal->pTags = taosMemoryMalloc(pTag->len); + memcpy(pVal->pTags, mr.me.ctbEntry.pTags, pTag->len); + } + + val = *pVal; + freeReader = true; + + int32_t ret = taosLRUCacheInsert(pCache->pTableMetaEntryCache, &pBlock->info.uid, sizeof(uint64_t), pVal, sizeof(STableCachedVal), freeCachedMetaItem, NULL, TAOS_LRU_PRIORITY_LOW); + if (ret != TAOS_LRU_STATUS_OK) { + qError("failed to put meta into lru cache, code:%d, %s", ret, idStr); + freeTableCachedVal(pVal); + } + } else { + pCache->cacheHit += 1; + STableCachedVal* pVal = taosLRUCacheValue(pCache->pTableMetaEntryCache, h); + val = *pVal; + taosLRUCacheRelease(pCache->pTableMetaEntryCache, h, false); + } + + qDebug("retrieve table meta from cache:%"PRIu64", hit:%"PRIu64 " miss:%"PRIu64", %s", pCache->metaFetch, pCache->cacheHit, + (pCache->metaFetch - pCache->cacheHit), idStr); } - for (int32_t j = 0; j < numOfPseudoExpr; ++j) { - SExprInfo* pExpr = &pPseudoExpr[j]; - int32_t dstSlotId = pExpr->base.resSchema.slotId; + for (int32_t j = 0; j < numOfExpr; ++j) { + const SExprInfo* pExpr1 = &pExpr[j]; + int32_t dstSlotId = pExpr1->base.resSchema.slotId; SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, dstSlotId); colInfoDataCleanup(pColInfoData, pBlock->info.rows); - int32_t functionId = pExpr->pExpr->_function.functionId; + int32_t functionId = pExpr1->pExpr->_function.functionId; // this is to handle the tbname if (fmIsScanPseudoColumnFunc(functionId)) { - setTbNameColData(pBlock, pColInfoData, functionId, mr.me.name); + setTbNameColData(pBlock, pColInfoData, functionId, val.pName); } else { // these are tags STagVal tagVal = {0}; - tagVal.cid = pExpr->base.pParam[0].pCol->colId; - const char* p = metaGetTableTagVal(mr.me.ctbEntry.pTags, pColInfoData->info.type, &tagVal); + tagVal.cid = pExpr1->base.pParam[0].pCol->colId; + const char* p = metaGetTableTagVal(val.pTags, pColInfoData->info.type, &tagVal); char* data = NULL; if (pColInfoData->info.type != TSDB_DATA_TYPE_JSON && p != NULL) { @@ -564,10 +638,12 @@ int32_t addTagPseudoColumnData(SReadHandle* pHandle, SExprInfo* pPseudoExpr, int } } - metaReaderClear(&mr); - // restore the rows pBlock->info.rows = backupRows; + if (freeReader) { + metaReaderClear(&mr); + } + return TSDB_CODE_SUCCESS; } @@ -815,6 +891,7 @@ static void destroyTableScanOperatorInfo(void* param) { taosArrayDestroy(pTableScanInfo->matchInfo.pList); } + taosLRUCacheCleanup(pTableScanInfo->metaCache.pTableMetaEntryCache); cleanupExprSupp(&pTableScanInfo->pseudoSup); taosMemoryFreeClear(param); } @@ -861,12 +938,9 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, pInfo->pResBlock = createResDataBlock(pDescNode); blockDataEnsureCapacity(pInfo->pResBlock, pOperator->resultInfo.capacity); - pInfo->pFilterNode = pScanNode->node.pConditions; - if (pInfo->pFilterNode != NULL) { - code = filterInitFromNode((SNode*)pInfo->pFilterNode, &pOperator->exprSupp.pFilterInfo, 0); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } + code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; } pInfo->scanFlag = MAIN_SCAN; @@ -881,6 +955,9 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, pOperator->exprSupp.numOfExprs = numOfCols; pOperator->pTaskInfo = pTaskInfo; + pInfo->metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024*128, -1, .5); + taosLRUCacheSetStrictCapacity(pInfo->metaCache.pTableMetaEntryCache, false); + pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doTableScan, NULL, NULL, destroyTableScanOperatorInfo, getTableScannerExecInfo); @@ -1295,7 +1372,7 @@ static SSDataBlock* doRangeScan(SStreamScanInfo* pInfo, SSDataBlock* pSDB, int32 return NULL; } - doFilter(pInfo->pCondition, pResult, NULL, NULL); + doFilter(pResult, pInfo->pTableScanOp->exprSupp.pFilterInfo, NULL); if (pResult->info.rows == 0) { continue; } @@ -1631,7 +1708,7 @@ static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock // currently only the tbname pseudo column if (pInfo->numOfPseudoExpr > 0) { int32_t code = addTagPseudoColumnData(&pInfo->readHandle, pInfo->pPseudoExpr, pInfo->numOfPseudoExpr, pInfo->pRes, - pInfo->pRes->info.rows, GET_TASKID(pTaskInfo)); + pInfo->pRes->info.rows, GET_TASKID(pTaskInfo), NULL); if (code != TSDB_CODE_SUCCESS) { blockDataFreeRes((SSDataBlock*)pBlock); T_LONG_JMP(pTaskInfo->env, code); @@ -1639,7 +1716,7 @@ static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock } if (filter) { - doFilter(pInfo->pCondition, pInfo->pRes, NULL, NULL); + doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); } blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex); @@ -2091,7 +2168,7 @@ FETCH_NEXT_BLOCK: } } - doFilter(pInfo->pCondition, pInfo->pRes, NULL, NULL); + doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex); if (pBlockInfo->rows > 0 || pInfo->pUpdateDataRes->info.rows > 0) { @@ -2456,9 +2533,13 @@ SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhys pInfo->pPseudoExpr = createExprInfo(pTableScanNode->scan.pScanPseudoCols, NULL, &pInfo->numOfPseudoExpr); } + code = filterInitFromNode((SNode*)pScanPhyNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + pInfo->pRes = createResDataBlock(pDescNode); pInfo->pUpdateRes = createSpecialDataBlock(STREAM_CLEAR); - pInfo->pCondition = pScanPhyNode->node.pConditions; pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE; pInfo->windowSup = (SWindowSupporter){.pStreamAggSup = NULL, .gap = -1, .parentType = QUERY_NODE_PHYSICAL_PLAN}; pInfo->groupId = 0; @@ -2599,13 +2680,13 @@ static int32_t loadSysTableCallback(void* param, SDataBuf* pMsg, int32_t code) { return TSDB_CODE_SUCCESS; } -static SSDataBlock* doFilterResult(SSysTableScanInfo* pInfo) { - if (pInfo->pCondition == NULL) { - return pInfo->pRes->info.rows == 0 ? NULL : pInfo->pRes; +static SSDataBlock* doFilterResult(SSDataBlock* pDataBlock, SFilterInfo* pFilterInfo) { + if (pFilterInfo == NULL) { + return pDataBlock->info.rows == 0 ? NULL : pDataBlock; } - doFilter(pInfo->pCondition, pInfo->pRes, NULL, NULL); - return pInfo->pRes->info.rows == 0 ? NULL : pInfo->pRes; + doFilter(pDataBlock, pFilterInfo, NULL); + return pDataBlock->info.rows == 0 ? NULL : pDataBlock; } static SSDataBlock* buildInfoSchemaTableMetaBlock(char* tableName) { @@ -2810,7 +2891,7 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) { metaReaderClear(&smrSuperTable); metaReaderClear(&smrChildTable); if (numOfRows > 0) { - relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock); + relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock, pOperator->exprSupp.pFilterInfo); numOfRows = 0; } blockDataDestroy(dataBlock); @@ -2850,7 +2931,7 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) { metaReaderClear(&smrSuperTable); if (numOfRows >= pOperator->resultInfo.capacity) { - relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock); + relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock, pOperator->exprSupp.pFilterInfo); numOfRows = 0; if (pInfo->pRes->info.rows > 0) { @@ -2860,7 +2941,7 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) { } if (numOfRows > 0) { - relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock); + relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock, pOperator->exprSupp.pFilterInfo); numOfRows = 0; } @@ -2875,13 +2956,13 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) { return (pInfo->pRes->info.rows == 0) ? NULL : pInfo->pRes; } -static void relocateAndFilterSysTagsScanResult(SSysTableScanInfo* pInfo, int32_t numOfRows, SSDataBlock* dataBlock) { +void relocateAndFilterSysTagsScanResult(SSysTableScanInfo* pInfo, int32_t numOfRows, SSDataBlock* dataBlock, + SFilterInfo* pFilterInfo) { dataBlock->info.rows = numOfRows; pInfo->pRes->info.rows = numOfRows; relocateColumnData(pInfo->pRes, pInfo->matchInfo.pList, dataBlock->pDataBlock, false); - doFilterResult(pInfo); - + doFilterResult(pInfo->pRes, pFilterInfo); blockDataCleanup(dataBlock); } @@ -3635,7 +3716,7 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) { pInfo->pRes->info.rows = numOfRows; relocateColumnData(pInfo->pRes, pInfo->matchInfo.pList, p->pDataBlock, false); - doFilterResult(pInfo); + doFilterResult(pInfo->pRes, pOperator->exprSupp.pFilterInfo); blockDataCleanup(p); numOfRows = 0; @@ -3651,7 +3732,7 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) { pInfo->pRes->info.rows = numOfRows; relocateColumnData(pInfo->pRes, pInfo->matchInfo.pList, p->pDataBlock, false); - doFilterResult(pInfo); + doFilterResult(pInfo->pRes, pOperator->exprSupp.pFilterInfo); blockDataCleanup(p); numOfRows = 0; @@ -3668,6 +3749,7 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) { pInfo->loadInfo.totalRows += pInfo->pRes->info.rows; return (pInfo->pRes->info.rows == 0) ? NULL : pInfo->pRes; } + static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; @@ -3811,7 +3893,7 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) { pInfo->pRes->info.rows = numOfRows; relocateColumnData(pInfo->pRes, pInfo->matchInfo.pList, p->pDataBlock, false); - doFilterResult(pInfo); + doFilterResult(pInfo->pRes, pOperator->exprSupp.pFilterInfo); blockDataCleanup(p); numOfRows = 0; @@ -3827,7 +3909,7 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) { pInfo->pRes->info.rows = numOfRows; relocateColumnData(pInfo->pRes, pInfo->matchInfo.pList, p->pDataBlock, false); - doFilterResult(pInfo); + doFilterResult(pInfo->pRes, pOperator->exprSupp.pFilterInfo); blockDataCleanup(p); numOfRows = 0; @@ -3858,8 +3940,7 @@ static SSDataBlock* sysTableScanUserTables(SOperatorInfo* pOperator) { // the retrieve is executed on the mnode, so return tables that belongs to the information schema database. if (pInfo->readHandle.mnd != NULL) { buildSysDbTableInfo(pInfo, pOperator->resultInfo.capacity); - - doFilterResult(pInfo); + doFilterResult(pInfo->pRes, pOperator->exprSupp.pFilterInfo); pInfo->loadInfo.totalRows += pInfo->pRes->info.rows; doSetOperatorCompleted(pOperator); @@ -3994,7 +4075,7 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) { updateLoadRemoteInfo(&pInfo->loadInfo, pRsp->numOfRows, pRsp->compLen, startTs, pOperator); // todo log the filter info - doFilterResult(pInfo); + doFilterResult(pInfo->pRes, pOperator->exprSupp.pFilterInfo); taosMemoryFree(pRsp); if (pInfo->pRes->info.rows > 0) { return pInfo->pRes; @@ -4092,9 +4173,15 @@ SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScan pInfo->sysInfo = pScanPhyNode->sysInfo; pInfo->showRewrite = pScanPhyNode->showRewrite; pInfo->pRes = createResDataBlock(pDescNode); + pInfo->pCondition = pScanNode->node.pConditions; + code = filterInitFromNode(pScanNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } initResultSizeInfo(&pOperator->resultInfo, 4096); + blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity); tNameAssign(&pInfo->name, &pScanNode->tableName); const char* name = tNameGetTableName(&pInfo->name); @@ -4102,7 +4189,6 @@ SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScan if (strncasecmp(name, TSDB_INS_TABLE_TABLES, TSDB_TABLE_FNAME_LEN) == 0 || strncasecmp(name, TSDB_INS_TABLE_TAGS, TSDB_TABLE_FNAME_LEN) == 0) { pInfo->readHandle = *(SReadHandle*)readHandle; - blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity); } else { tsem_init(&pInfo->ready, 0, 0); pInfo->epSet = pScanPhyNode->mgmtEpSet; @@ -4118,7 +4204,6 @@ SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScan pOperator->pTaskInfo = pTaskInfo; pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doSysTableScan, NULL, NULL, destroySysScanOperator, NULL); - return pOperator; _error: @@ -4126,7 +4211,7 @@ _error: destroySysScanOperator(pInfo); } taosMemoryFreeClear(pOperator); - terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; + pTaskInfo->code = code; return NULL; } @@ -4280,7 +4365,7 @@ static int32_t loadDataBlockFromOneTable(SOperatorInfo* pOperator, STableMergeSc pCost->totalRows += pBlock->info.rows; *status = pInfo->dataBlockLoadFlag; - if (pTableScanInfo->pFilterNode != NULL || + if (pOperator->exprSupp.pFilterInfo != NULL || overlapWithTimeWindow(&pTableScanInfo->interval, &pBlock->info, pTableScanInfo->cond.order)) { (*status) = FUNC_DATA_REQUIRED_DATA_LOAD; } @@ -4361,14 +4446,14 @@ static int32_t loadDataBlockFromOneTable(SOperatorInfo* pOperator, STableMergeSc SExprSupp* pSup = &pTableScanInfo->pseudoSup; int32_t code = addTagPseudoColumnData(&pTableScanInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pBlock, - pBlock->info.rows, GET_TASKID(pTaskInfo)); + pBlock->info.rows, GET_TASKID(pTaskInfo), NULL); if (code != TSDB_CODE_SUCCESS) { T_LONG_JMP(pTaskInfo->env, code); } - if (pTableScanInfo->pFilterNode != NULL) { + if (pOperator->exprSupp.pFilterInfo!= NULL) { int64_t st = taosGetTimestampMs(); - doFilter(pTableScanInfo->pFilterNode, pBlock, &pTableScanInfo->matchInfo, NULL); + doFilter(pBlock, pOperator->exprSupp.pFilterInfo, &pTableScanInfo->matchInfo); double el = (taosGetTimestampUs() - st) / 1000.0; pTableScanInfo->readRecorder.filterTime += el; @@ -4741,7 +4826,13 @@ SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanN pInfo->sample.sampleRatio = pTableScanNode->ratio; pInfo->sample.seed = taosGetTimestampSec(); pInfo->dataBlockLoadFlag = pTableScanNode->dataRequired; - pInfo->pFilterNode = pTableScanNode->scan.node.pConditions; + + + code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + pInfo->tableListInfo = pTableListInfo; pInfo->scanFlag = MAIN_SCAN; diff --git a/source/libs/executor/src/sortoperator.c b/source/libs/executor/src/sortoperator.c index 7abf05e7d6..af87c4b2eb 100644 --- a/source/libs/executor/src/sortoperator.c +++ b/source/libs/executor/src/sortoperator.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "filter.h" #include "executorimpl.h" #include "tdatablock.h" @@ -42,12 +43,14 @@ SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* extractColMatchInfo(pSortNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID, &pInfo->matchInfo); pOperator->exprSupp.pCtx = createSqlFunctionCtx(pExprInfo, numOfCols, &pOperator->exprSupp.rowEntryInfoOffset); - initResultSizeInfo(&pOperator->resultInfo, 1024); + code = filterInitFromNode((SNode*)pSortNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } pInfo->binfo.pRes = pResBlock; pInfo->pSortInfo = createSortInfo(pSortNode->pSortKeys); - pInfo->pCondition = pSortNode->node.pConditions; initLimitInfo(pSortNode->node.pLimit, pSortNode->node.pSlimit, &pInfo->limitInfo); pOperator->name = "SortOperator"; @@ -215,7 +218,7 @@ SSDataBlock* doSort(SOperatorInfo* pOperator) { return NULL; } - doFilter(pInfo->pCondition, pBlock, &pInfo->matchInfo, NULL); + doFilter(pBlock, pOperator->exprSupp.pFilterInfo, &pInfo->matchInfo); if (blockDataGetNumOfRows(pBlock) == 0) { continue; } @@ -479,24 +482,31 @@ SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SGroupSort SExecTaskInfo* pTaskInfo) { SGroupSortOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SGroupSortOperatorInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); - if (pInfo == NULL || pOperator == NULL /* || rowSize > 100 * 1024 * 1024*/) { + if (pInfo == NULL || pOperator == NULL) { goto _error; } + SExprSupp* pSup = &pOperator->exprSupp; SDataBlockDescNode* pDescNode = pSortPhyNode->node.pOutputDataBlockDesc; int32_t numOfCols = 0; - SSDataBlock* pResBlock = createResDataBlock(pDescNode); SExprInfo* pExprInfo = createExprInfo(pSortPhyNode->pExprs, NULL, &numOfCols); + pSup->pExprInfo = pExprInfo; + pSup->numOfExprs = numOfCols; + + initResultSizeInfo(&pOperator->resultInfo, 1024); + pOperator->exprSupp.pCtx = createSqlFunctionCtx(pExprInfo, numOfCols, &pOperator->exprSupp.rowEntryInfoOffset); + + pInfo->binfo.pRes = createResDataBlock(pDescNode); + blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity); + int32_t numOfOutputCols = 0; int32_t code = extractColMatchInfo(pSortPhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID, &pInfo->matchInfo); - - pOperator->exprSupp.pCtx = createSqlFunctionCtx(pExprInfo, numOfCols, &pOperator->exprSupp.rowEntryInfoOffset); - pInfo->binfo.pRes = pResBlock; - - initResultSizeInfo(&pOperator->resultInfo, 1024); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } pInfo->pSortInfo = createSortInfo(pSortPhyNode->pSortKeys); @@ -505,8 +515,6 @@ SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SGroupSort pOperator->blocking = false; pOperator->status = OP_NOT_OPENED; pOperator->info = pInfo; - pOperator->exprSupp.pExprInfo = pExprInfo; - pOperator->exprSupp.numOfExprs = numOfCols; pOperator->pTaskInfo = pTaskInfo; pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doGroupSort, NULL, NULL, destroyGroupSortOperatorInfo, @@ -520,8 +528,10 @@ SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SGroupSort return pOperator; _error: - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; - taosMemoryFree(pInfo); + pTaskInfo->code = code; + if (pInfo != NULL) { + destroyGroupSortOperatorInfo(pInfo); + } taosMemoryFree(pOperator); return NULL; } diff --git a/source/libs/executor/src/tfill.c b/source/libs/executor/src/tfill.c index 23847928da..ebc3a962d3 100644 --- a/source/libs/executor/src/tfill.c +++ b/source/libs/executor/src/tfill.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "filter.h" #include "os.h" #include "query.h" #include "taosdef.h" @@ -1499,7 +1500,7 @@ static SSDataBlock* doStreamFill(SOperatorInfo* pOperator) { } doStreamFillImpl(pOperator); - doFilter(pInfo->pCondition, pInfo->pRes, &pInfo->matchInfo, NULL); + doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, &pInfo->matchInfo); memcpy(pInfo->pRes->info.parTbName, pInfo->pSrcBlock->info.parTbName, TSDB_TABLE_NAME_LEN); pOperator->resultInfo.totalRows += pInfo->pRes->info.rows; if (pInfo->pRes->info.rows > 0) { @@ -1677,7 +1678,12 @@ SOperatorInfo* createStreamFillOperatorInfo(SOperatorInfo* downstream, SStreamFi int32_t numOfOutputCols = 0; int32_t code = extractColMatchInfo(pPhyFillNode->pFillExprs, pPhyFillNode->node.pOutputDataBlockDesc, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID, &pInfo->matchInfo); - pInfo->pCondition = pPhyFillNode->node.pConditions; + + code = filterInitFromNode((SNode*)pPhyFillNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + code = initExprSupp(&pOperator->exprSupp, pFillExprInfo, numOfFillCols); if (code != TSDB_CODE_SUCCESS) { goto _error; diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c index a0d3de5676..88f3e4cff9 100644 --- a/source/libs/executor/src/timewindowoperator.c +++ b/source/libs/executor/src/timewindowoperator.c @@ -12,6 +12,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#include "filter.h" #include "executorimpl.h" #include "function.h" #include "functionMgt.h" @@ -1227,7 +1228,7 @@ static SSDataBlock* doStateWindowAgg(SOperatorInfo* pOperator) { blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity); while (1) { doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf); - doFilter(pInfo->pCondition, pBInfo->pRes, NULL, NULL); + doFilter(pBInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); bool hasRemain = hasRemainResults(&pInfo->groupResInfo); if (!hasRemain) { @@ -1265,7 +1266,7 @@ static SSDataBlock* doBuildIntervalResult(SOperatorInfo* pOperator) { blockDataEnsureCapacity(pBlock, pOperator->resultInfo.capacity); while (1) { doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf); - doFilter(pInfo->pCondition, pBlock, NULL, NULL); + doFilter(pBlock, pOperator->exprSupp.pFilterInfo, NULL); bool hasRemain = hasRemainResults(&pInfo->groupResInfo); if (!hasRemain) { @@ -1747,7 +1748,6 @@ SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPh pInfo->interval = interval; pInfo->execModel = pTaskInfo->execModel; pInfo->twAggSup = as; - pInfo->pCondition = pPhyNode->window.node.pConditions; pInfo->binfo.mergeResultBlock = pPhyNode->window.mergeDataBlock; if (pPhyNode->window.pExprs != NULL) { @@ -1759,6 +1759,11 @@ SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPh } } + code = filterInitFromNode((SNode*)pPhyNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + if (isStream) { ASSERT(num > 0); initStreamFunciton(pSup->pCtx, pSup->numOfExprs); @@ -1883,7 +1888,7 @@ static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) { if (pOperator->status == OP_RES_TO_RETURN) { while (1) { doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf); - doFilter(pInfo->pCondition, pBInfo->pRes, NULL, NULL); + doFilter(pBInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); bool hasRemain = hasRemainResults(&pInfo->groupResInfo); if (!hasRemain) { @@ -1926,7 +1931,7 @@ static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) { blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity); while (1) { doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf); - doFilter(pInfo->pCondition, pBInfo->pRes, NULL, NULL); + doFilter(pBInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); bool hasRemain = hasRemainResults(&pInfo->groupResInfo); if (!hasRemain) { @@ -2600,17 +2605,22 @@ SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SStateWi pInfo->stateKey.type = pInfo->stateCol.type; pInfo->stateKey.bytes = pInfo->stateCol.bytes; pInfo->stateKey.pData = taosMemoryCalloc(1, pInfo->stateCol.bytes); - pInfo->pCondition = pStateNode->window.node.pConditions; if (pInfo->stateKey.pData == NULL) { goto _error; } + int32_t code = filterInitFromNode((SNode*)pStateNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES; int32_t num = 0; SExprInfo* pExprInfo = createExprInfo(pStateNode->window.pFuncs, NULL, &num); initResultSizeInfo(&pOperator->resultInfo, 4096); - int32_t code = initAggInfo(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str); + + code = initAggInfo(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str); if (code != TSDB_CODE_SUCCESS) { goto _error; } @@ -2698,7 +2708,10 @@ SOperatorInfo* createSessionAggOperatorInfo(SOperatorInfo* downstream, SSessionW pInfo->binfo.pRes = pResBlock; pInfo->winSup.prevTs = INT64_MIN; pInfo->reptScan = false; - pInfo->pCondition = pSessionNode->window.node.pConditions; + code = filterInitFromNode((SNode*)pSessionNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } pOperator->name = "SessionWindowAggOperator"; pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION; @@ -4877,7 +4890,7 @@ static void doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) { setInputDataBlock(pSup, pBlock, pIaInfo->inputOrder, scanFlag, true); doMergeAlignedIntervalAggImpl(pOperator, &pIaInfo->binfo.resultRowInfo, pBlock, pRes); - doFilter(pMiaInfo->pCondition, pRes, NULL, NULL); + doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL); if (pRes->info.rows >= pOperator->resultInfo.capacity) { break; } @@ -4940,7 +4953,11 @@ SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo; SExprSupp* pSup = &pOperator->exprSupp; - miaInfo->pCondition = pNode->window.node.pConditions; + int32_t code = filterInitFromNode((SNode*)pNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + miaInfo->curTs = INT64_MIN; iaInfo->win = pTaskInfo->window; iaInfo->inputOrder = TSDB_ORDER_ASC; @@ -4954,7 +4971,8 @@ SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, int32_t num = 0; SExprInfo* pExprInfo = createExprInfo(pNode->window.pFuncs, NULL, &num); - int32_t code = initAggInfo(&pOperator->exprSupp, &iaInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str); + + code = initAggInfo(&pOperator->exprSupp, &iaInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str); if (code != TSDB_CODE_SUCCESS) { goto _error; } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 17d1b5bf48..c5b2dfed66 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -792,9 +792,24 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode((SNode*)pStmt->pSlimit); break; } - case QUERY_NODE_VNODE_MODIF_STMT: - destroyVgDataBlockArray(((SVnodeModifOpStmt*)pNode)->pDataBlocks); + case QUERY_NODE_VNODE_MODIF_STMT: { + SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)pNode; + destroyVgDataBlockArray(pStmt->pDataBlocks); + taosMemoryFreeClear(pStmt->pTableMeta); + taosHashCleanup(pStmt->pVgroupsHashObj); + taosHashCleanup(pStmt->pSubTableHashObj); + taosHashCleanup(pStmt->pTableNameHashObj); + taosHashCleanup(pStmt->pDbFNameHashObj); + if (pStmt->freeHashFunc) { + pStmt->freeHashFunc(pStmt->pTableBlockHashObj); + } + if (pStmt->freeArrayFunc) { + pStmt->freeArrayFunc(pStmt->pVgDataBlocks); + } + tdDestroySVCreateTbReq(&pStmt->createTblReq); + taosCloseFile(&pStmt->fp); break; + } case QUERY_NODE_CREATE_DATABASE_STMT: nodesDestroyNode((SNode*)((SCreateDatabaseStmt*)pNode)->pOptions); break; diff --git a/source/libs/parser/inc/parInsertUtil.h b/source/libs/parser/inc/parInsertUtil.h index 1e941632e7..09d55d369f 100644 --- a/source/libs/parser/inc/parInsertUtil.h +++ b/source/libs/parser/inc/parInsertUtil.h @@ -79,29 +79,6 @@ typedef struct SInsertParseBaseContext { SMsgBuf msg; } SInsertParseBaseContext; -typedef struct SInsertParseContext { - SParseContext *pComCxt; // input - char *pSql; // input - SMsgBuf msg; // input - STableMeta *pTableMeta; // each table - SParsedDataColInfo tags; // each table - SVCreateTbReq createTblReq; // each table - SHashObj *pVgroupsHashObj; // global - SHashObj *pTableBlockHashObj; // global - SHashObj *pSubTableHashObj; // global - SArray *pVgDataBlocks; // global - SHashObj *pTableNameHashObj; // global - SHashObj *pDbFNameHashObj; // global - int32_t totalNum; - SVnodeModifOpStmt *pOutput; - SStmtCallback *pStmtCb; - SParseMetaCache *pMetaCache; - char sTableName[TSDB_TABLE_NAME_LEN]; - char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW]; - int64_t memElapsed; - int64_t parRowElapsed; -} SInsertParseContext; - typedef struct SInsertParseSyntaxCxt { SParseContext *pComCxt; char *pSql; @@ -142,7 +119,7 @@ typedef struct STableDataBlocks { int32_t insGetExtendedRowSize(STableDataBlocks *pBlock); void insGetSTSRowAppendInfo(uint8_t rowType, SParsedDataColInfo *spd, col_id_t idx, int32_t *toffset, col_id_t *colIdx); -int32_t insSetBlockInfo(SSubmitBlk *pBlocks, STableDataBlocks *dataBuf, int32_t numOfRows); +int32_t insSetBlockInfo(SSubmitBlk *pBlocks, STableDataBlocks *dataBuf, int32_t numOfRows, SMsgBuf *pMsg); int32_t insSchemaIdxCompar(const void *lhs, const void *rhs); int32_t insBoundIdxCompar(const void *lhs, const void *rhs); void insSetBoundColumnInfo(SParsedDataColInfo *pColList, SSchema *pSchema, col_id_t numOfCols); @@ -161,7 +138,7 @@ void insBuildCreateTbReq(SVCreateTbReq *pTbReq, const char *tname, STag *pTag SArray *tagName, uint8_t tagNum); int32_t insMemRowAppend(SMsgBuf *pMsgBuf, const void *value, int32_t len, void *param); int32_t insCheckTimestamp(STableDataBlocks *pDataBlocks, const char *start); -int32_t insBuildOutput(SInsertParseContext *pCxt); +int32_t insBuildOutput(SHashObj *pVgroupsHashObj, SArray *pVgDataBlocks, SArray **pDataBlocks); void insDestroyDataBlock(STableDataBlocks *pDataBlock); #endif // TDENGINE_PAR_INSERT_UTIL_H diff --git a/source/libs/parser/inc/parInt.h b/source/libs/parser/inc/parInt.h index b799fa9855..66aec272d7 100644 --- a/source/libs/parser/inc/parInt.h +++ b/source/libs/parser/inc/parInt.h @@ -27,8 +27,7 @@ extern "C" { #define QUERY_SMA_OPTIMIZE_DISABLE 0 #define QUERY_SMA_OPTIMIZE_ENABLE 1 -int32_t parseInsertSyntax(SParseContext* pContext, SQuery** pQuery, SParseMetaCache* pMetaCache); -int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery, SParseMetaCache* pMetaCache); +int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData); int32_t parse(SParseContext* pParseCxt, SQuery** pQuery); int32_t collectMetaKey(SParseContext* pParseCxt, SQuery* pQuery, SParseMetaCache* pMetaCache); int32_t authenticate(SParseContext* pParseCxt, SQuery* pQuery, SParseMetaCache* pMetaCache); diff --git a/source/libs/parser/inc/parUtil.h b/source/libs/parser/inc/parUtil.h index 75b631ec9d..10a86866d5 100644 --- a/source/libs/parser/inc/parUtil.h +++ b/source/libs/parser/inc/parUtil.h @@ -60,22 +60,17 @@ typedef struct SInsertTablesMetaReq { } SInsertTablesMetaReq; typedef struct SParseMetaCache { - SHashObj* pTableMeta; // key is tbFName, element is STableMeta* - SHashObj* pDbVgroup; // key is dbFName, element is SArray* - SHashObj* pTableVgroup; // key is tbFName, element is SVgroupInfo* - SHashObj* pDbCfg; // key is tbFName, element is SDbCfgInfo* - SHashObj* pDbInfo; // key is tbFName, element is SDbInfo* - SHashObj* pUserAuth; // key is SUserAuthInfo serialized string, element is bool indicating whether or not to pass - SHashObj* pUdf; // key is funcName, element is SFuncInfo* - SHashObj* pTableIndex; // key is tbFName, element is SArray* - SHashObj* pTableCfg; // key is tbFName, element is STableCfg* - SArray* pDnodes; // element is SEpSet - bool dnodeRequired; - SHashObj* pInsertTables; // key is dbName, element is SInsertTablesMetaReq*, for insert - const char* pUser; - const SArray* pTableMetaData; // pRes = STableMeta* - const SArray* pTableVgroupData; // pRes = SVgroupInfo* - int32_t sqlTableNum; + SHashObj* pTableMeta; // key is tbFName, element is STableMeta* + SHashObj* pDbVgroup; // key is dbFName, element is SArray* + SHashObj* pTableVgroup; // key is tbFName, element is SVgroupInfo* + SHashObj* pDbCfg; // key is tbFName, element is SDbCfgInfo* + SHashObj* pDbInfo; // key is tbFName, element is SDbInfo* + SHashObj* pUserAuth; // key is SUserAuthInfo serialized string, element is bool indicating whether or not to pass + SHashObj* pUdf; // key is funcName, element is SFuncInfo* + SHashObj* pTableIndex; // key is tbFName, element is SArray* + SHashObj* pTableCfg; // key is tbFName, element is STableCfg* + SArray* pDnodes; // element is SEpSet + bool dnodeRequired; } SParseMetaCache; int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...); @@ -93,9 +88,8 @@ STableMeta* tableMetaDup(const STableMeta* pTableMeta); int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen); int32_t getInsTagsTableTargetName(int32_t acctId, SNode* pWhere, SName* pName); -int32_t buildCatalogReq(SParseContext* pCxt, const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq); -int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache, - bool insertValuesStmt); +int32_t buildCatalogReq(const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq); +int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache); int32_t reserveTableMetaInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache); int32_t reserveTableMetaInCacheExt(const SName* pName, SParseMetaCache* pMetaCache); int32_t reserveDbVgInfoInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache); @@ -122,12 +116,6 @@ int32_t getUdfInfoFromCache(SParseMetaCache* pMetaCache, const char* pFunc, SFun int32_t getTableIndexFromCache(SParseMetaCache* pMetaCache, const SName* pName, SArray** pIndexes); int32_t getTableCfgFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableCfg** pOutput); int32_t getDnodeListFromCache(SParseMetaCache* pMetaCache, SArray** pDnodes); -int32_t reserveTableMetaInCacheForInsert(const SName* pName, ECatalogReqType reqType, int32_t tableNo, - SParseMetaCache* pMetaCache); -int32_t getTableMetaFromCacheForInsert(SArray* pTableMetaPos, SParseMetaCache* pMetaCache, int32_t tableNo, - STableMeta** pMeta); -int32_t getTableVgroupFromCacheForInsert(SArray* pTableVgroupPos, SParseMetaCache* pMetaCache, int32_t tableNo, - SVgroupInfo* pVgroup); void destoryParseMetaCache(SParseMetaCache* pMetaCache, bool request); #ifdef __cplusplus diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c index 28dc6179f9..bb3d1a2cb3 100644 --- a/source/libs/parser/src/parAstParser.c +++ b/source/libs/parser/src/parAstParser.c @@ -84,6 +84,7 @@ abort_parse: (*pQuery)->pRoot = cxt.pRootNode; (*pQuery)->placeholderNum = cxt.placeholderNo; TSWAP((*pQuery)->pPlaceholderValues, cxt.pPlaceholderValues); + (*pQuery)->execStage = QUERY_EXEC_STAGE_ANALYSE; } taosArrayDestroy(cxt.pPlaceholderValues); return cxt.errCode; diff --git a/source/libs/parser/src/parInsertSml.c b/source/libs/parser/src/parInsertSml.c index 8be5b86b37..d18b11ad57 100644 --- a/source/libs/parser/src/parInsertSml.c +++ b/source/libs/parser/src/parInsertSml.c @@ -333,11 +333,7 @@ int32_t smlBindData(void* handle, SArray* tags, SArray* colsSchema, SArray* cols } SSubmitBlk* pBlocks = (SSubmitBlk*)(pDataBlock->pData); - if (TSDB_CODE_SUCCESS != insSetBlockInfo(pBlocks, pDataBlock, rowNum)) { - return buildInvalidOperationMsg(&pBuf, "too many rows in sql, total number of rows should be less than INT32_MAX"); - } - - return TSDB_CODE_SUCCESS; + return insSetBlockInfo(pBlocks, pDataBlock, rowNum, &pBuf); } void* smlInitHandle(SQuery* pQuery) { diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 1ccb34cd1f..7a38f48cb2 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -18,215 +18,39 @@ #include "tglobal.h" #include "ttime.h" -#define NEXT_TOKEN_WITH_PREV(pSql, sToken) \ - do { \ - int32_t index = 0; \ - sToken = tStrGetToken(pSql, &index, true); \ - pSql += index; \ - } while (0) - -#define NEXT_TOKEN_KEEP_SQL(pSql, sToken, index) \ - do { \ - sToken = tStrGetToken(pSql, &index, false); \ - } while (0) - -#define NEXT_VALID_TOKEN(pSql, sToken) \ +#define NEXT_TOKEN_WITH_PREV(pSql, token) \ do { \ - sToken.n = tGetToken(pSql, &sToken.type); \ - sToken.z = pSql; \ - pSql += sToken.n; \ - } while (TK_NK_SPACE == sToken.type) + int32_t index = 0; \ + token = tStrGetToken(pSql, &index, true); \ + pSql += index; \ + } while (0) + +#define NEXT_TOKEN_KEEP_SQL(pSql, token, index) \ + do { \ + token = tStrGetToken(pSql, &index, false); \ + } while (0) + +#define NEXT_VALID_TOKEN(pSql, token) \ + do { \ + (token).n = tGetToken(pSql, &(token).type); \ + (token).z = (char*)pSql; \ + pSql += (token).n; \ + } while (TK_NK_SPACE == (token).type) + +typedef struct SInsertParseContext { + SParseContext* pComCxt; + SMsgBuf msg; + char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW]; + SParsedDataColInfo tags; // for stmt + bool missCache; + bool usingDuplicateTable; +} SInsertParseContext; typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param); static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE; static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE; -static int32_t skipInsertInto(char** pSql, SMsgBuf* pMsg) { - SToken sToken; - NEXT_TOKEN(*pSql, sToken); - if (TK_INSERT != sToken.type && TK_IMPORT != sToken.type) { - return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", sToken.z); - } - NEXT_TOKEN(*pSql, sToken); - if (TK_INTO != sToken.type) { - return buildSyntaxErrMsg(pMsg, "keyword INTO is expected", sToken.z); - } - return TSDB_CODE_SUCCESS; -} - -static int32_t checkAuth(SInsertParseContext* pCxt, char* pDbFname, bool* pPass) { - SParseContext* pBasicCtx = pCxt->pComCxt; - if (pBasicCtx->async) { - return getUserAuthFromCache(pCxt->pMetaCache, pBasicCtx->pUser, pDbFname, AUTH_TYPE_WRITE, pPass); - } - SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter, - .requestId = pBasicCtx->requestId, - .requestObjRefId = pBasicCtx->requestRid, - .mgmtEps = pBasicCtx->mgmtEpSet}; - - return catalogChkAuth(pBasicCtx->pCatalog, &conn, pBasicCtx->pUser, pDbFname, AUTH_TYPE_WRITE, pPass); -} - -static int32_t getTableSchema(SInsertParseContext* pCxt, int32_t tbNo, SName* pTbName, bool isStb, - STableMeta** pTableMeta) { - SParseContext* pBasicCtx = pCxt->pComCxt; - if (pBasicCtx->async) { - return getTableMetaFromCacheForInsert(pBasicCtx->pTableMetaPos, pCxt->pMetaCache, tbNo, pTableMeta); - } - SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter, - .requestId = pBasicCtx->requestId, - .requestObjRefId = pBasicCtx->requestRid, - .mgmtEps = pBasicCtx->mgmtEpSet}; - - if (isStb) { - return catalogGetSTableMeta(pBasicCtx->pCatalog, &conn, pTbName, pTableMeta); - } - return catalogGetTableMeta(pBasicCtx->pCatalog, &conn, pTbName, pTableMeta); -} - -static int32_t getTableVgroup(SInsertParseContext* pCxt, int32_t tbNo, SName* pTbName, SVgroupInfo* pVg) { - SParseContext* pBasicCtx = pCxt->pComCxt; - if (pBasicCtx->async) { - return getTableVgroupFromCacheForInsert(pBasicCtx->pTableVgroupPos, pCxt->pMetaCache, tbNo, pVg); - } - SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter, - .requestId = pBasicCtx->requestId, - .requestObjRefId = pBasicCtx->requestRid, - .mgmtEps = pBasicCtx->mgmtEpSet}; - return catalogGetTableHashVgroup(pBasicCtx->pCatalog, &conn, pTbName, pVg); -} - -static int32_t getTableMetaImpl(SInsertParseContext* pCxt, int32_t tbNo, SName* name, bool isStb) { - CHECK_CODE(getTableSchema(pCxt, tbNo, name, isStb, &pCxt->pTableMeta)); - if (!isStb) { - SVgroupInfo vg; - CHECK_CODE(getTableVgroup(pCxt, tbNo, name, &vg)); - CHECK_CODE(taosHashPut(pCxt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg))); - } - return TSDB_CODE_SUCCESS; -} - -static int32_t getTableMeta(SInsertParseContext* pCxt, int32_t tbNo, SName* name) { - return getTableMetaImpl(pCxt, tbNo, name, false); -} - -static int32_t getSTableMeta(SInsertParseContext* pCxt, int32_t tbNo, SName* name) { - return getTableMetaImpl(pCxt, tbNo, name, true); -} - -static int32_t getDBCfg(SInsertParseContext* pCxt, const char* pDbFName, SDbCfgInfo* pInfo) { - SParseContext* pBasicCtx = pCxt->pComCxt; - if (pBasicCtx->async) { - CHECK_CODE(getDbCfgFromCache(pCxt->pMetaCache, pDbFName, pInfo)); - } else { - SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter, - .requestId = pBasicCtx->requestId, - .requestObjRefId = pBasicCtx->requestRid, - .mgmtEps = pBasicCtx->mgmtEpSet}; - CHECK_CODE(catalogGetDBCfg(pBasicCtx->pCatalog, &conn, pDbFName, pInfo)); - } - return TSDB_CODE_SUCCESS; -} - -static int parseTime(char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf) { - int32_t index = 0; - SToken sToken; - int64_t interval; - int64_t ts = 0; - char* pTokenEnd = *end; - - if (pToken->type == TK_NOW) { - ts = taosGetTimestamp(timePrec); - } else if (pToken->type == TK_TODAY) { - ts = taosGetTimestampToday(timePrec); - } else if (pToken->type == TK_NK_INTEGER) { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &ts)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); - } - } else { // parse the RFC-3339/ISO-8601 timestamp format string - if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { - return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); - } - - return TSDB_CODE_SUCCESS; - } - - for (int k = pToken->n; pToken->z[k] != '\0'; k++) { - if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue; - if (pToken->z[k] == '(' && pToken->z[k + 1] == ')') { // for insert NOW()/TODAY() - *end = pTokenEnd = &pToken->z[k + 2]; - k++; - continue; - } - if (pToken->z[k] == ',') { - *end = pTokenEnd; - *time = ts; - return 0; - } - - break; - } - - /* - * time expression: - * e.g., now+12a, now-5h - */ - SToken valueToken; - index = 0; - sToken = tStrGetToken(pTokenEnd, &index, false); - pTokenEnd += index; - - if (sToken.type == TK_NK_MINUS || sToken.type == TK_NK_PLUS) { - index = 0; - valueToken = tStrGetToken(pTokenEnd, &index, false); - pTokenEnd += index; - - if (valueToken.n < 2) { - return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", sToken.z); - } - - char unit = 0; - if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval, &unit, timePrec) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (sToken.type == TK_NK_PLUS) { - ts += interval; - } else { - ts = ts - interval; - } - - *end = pTokenEnd; - } - - *time = ts; - return TSDB_CODE_SUCCESS; -} - -static FORCE_INLINE int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf) { - if ((pToken->type != TK_NOW && pToken->type != TK_TODAY && pToken->type != TK_NK_INTEGER && - pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL && - pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && - pToken->type != TK_NK_BIN) || - (pToken->n == 0) || (pToken->type == TK_NK_RP)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z); - } - - // Remove quotation marks - if (TK_NK_STRING == pToken->type) { - if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) { - return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z); - } - - int32_t len = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW); - pToken->z = tmpTokenBuf; - pToken->n = len; - } - - return TSDB_CODE_SUCCESS; -} - static bool isNullStr(SToken* pToken) { return ((pToken->type == TK_NK_STRING) && (strlen(TSDB_DATA_NULL_STR_L) == pToken->n) && (strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0)); @@ -248,182 +72,108 @@ static FORCE_INLINE int32_t toDouble(SToken* pToken, double* value, char** endPt return pToken->type; } -static int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, - _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf) { - int64_t iv; - uint64_t uv; - char* endptr = NULL; - - int32_t code = checkAndTrimValue(pToken, tmpTokenBuf, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; +static int32_t skipInsertInto(const char** pSql, SMsgBuf* pMsg) { + SToken token; + NEXT_TOKEN(*pSql, token); + if (TK_INSERT != token.type && TK_IMPORT != token.type) { + return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", token.z); } - - if (isNullValue(pSchema->type, pToken)) { - if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { - return buildSyntaxErrMsg(pMsgBuf, "primary timestamp should not be null", pToken->z); - } - - return func(pMsgBuf, NULL, 0, param); + NEXT_TOKEN(*pSql, token); + if (TK_INTO != token.type) { + return buildSyntaxErrMsg(pMsg, "keyword INTO is expected", token.z); } - - if (IS_NUMERIC_TYPE(pSchema->type) && pToken->n == 0) { - return buildSyntaxErrMsg(pMsgBuf, "invalid numeric data", pToken->z); - } - - switch (pSchema->type) { - case TSDB_DATA_TYPE_BOOL: { - if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) { - if (strncmp(pToken->z, "true", pToken->n) == 0) { - return func(pMsgBuf, &TRUE_VALUE, pSchema->bytes, param); - } else if (strncmp(pToken->z, "false", pToken->n) == 0) { - return func(pMsgBuf, &FALSE_VALUE, pSchema->bytes, param); - } else { - return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); - } - } else if (pToken->type == TK_NK_INTEGER) { - return func(pMsgBuf, ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, - param); - } else if (pToken->type == TK_NK_FLOAT) { - return func(pMsgBuf, ((taosStr2Double(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, - param); - } else { - return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); - } - } - - case TSDB_DATA_TYPE_TINYINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z); - } else if (!IS_VALID_TINYINT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z); - } - - uint8_t tmpVal = (uint8_t)iv; - return func(pMsgBuf, &tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_UTINYINT: { - if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z); - } else if (uv > UINT8_MAX) { - return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z); - } - uint8_t tmpVal = (uint8_t)uv; - return func(pMsgBuf, &tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_SMALLINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z); - } else if (!IS_VALID_SMALLINT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z); - } - int16_t tmpVal = (int16_t)iv; - return func(pMsgBuf, &tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_USMALLINT: { - if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z); - } else if (uv > UINT16_MAX) { - return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z); - } - uint16_t tmpVal = (uint16_t)uv; - return func(pMsgBuf, &tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_INT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z); - } else if (!IS_VALID_INT(iv)) { - return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z); - } - int32_t tmpVal = (int32_t)iv; - return func(pMsgBuf, &tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_UINT: { - if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z); - } else if (uv > UINT32_MAX) { - return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z); - } - uint32_t tmpVal = (uint32_t)uv; - return func(pMsgBuf, &tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_BIGINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z); - } - return func(pMsgBuf, &iv, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_UBIGINT: { - if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { - return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z); - } - return func(pMsgBuf, &uv, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_FLOAT: { - double dv; - if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { - return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); - } - if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || - isnan(dv)) { - return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); - } - float tmpVal = (float)dv; - return func(pMsgBuf, &tmpVal, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_DOUBLE: { - double dv; - if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { - return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); - } - if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) { - return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); - } - return func(pMsgBuf, &dv, pSchema->bytes, param); - } - - case TSDB_DATA_TYPE_BINARY: { - // Too long values will raise the invalid sql error message - if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { - return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); - } - - return func(pMsgBuf, pToken->z, pToken->n, param); - } - - case TSDB_DATA_TYPE_NCHAR: { - return func(pMsgBuf, pToken->z, pToken->n, param); - } - case TSDB_DATA_TYPE_JSON: { - if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { - return buildSyntaxErrMsg(pMsgBuf, "json string too long than 4095", pToken->z); - } - return func(pMsgBuf, pToken->z, pToken->n, param); - } - case TSDB_DATA_TYPE_TIMESTAMP: { - int64_t tmpVal; - if (parseTime(end, pToken, timePrec, &tmpVal, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z); - } - - return func(pMsgBuf, &tmpVal, pSchema->bytes, param); - } - } - - return TSDB_CODE_FAILED; + return TSDB_CODE_SUCCESS; } -// pSql -> tag1_name, ...) -static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo* pColList, SSchema* pSchema) { +static int32_t skipParentheses(SInsertParseContext* pCxt, const char** pSql) { + SToken token; + int32_t expectRightParenthesis = 1; + while (1) { + NEXT_TOKEN(*pSql, token); + if (TK_NK_LP == token.type) { + ++expectRightParenthesis; + } else if (TK_NK_RP == token.type && 0 == --expectRightParenthesis) { + break; + } + if (0 == token.n) { + return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL); + } + } + return TSDB_CODE_SUCCESS; +} + +static int32_t skipTableOptions(SInsertParseContext* pCxt, const char** pSql) { + do { + int32_t index = 0; + SToken token; + NEXT_TOKEN_KEEP_SQL(*pSql, token, index); + if (TK_TTL == token.type || TK_COMMENT == token.type) { + *pSql += index; + NEXT_TOKEN_WITH_PREV(*pSql, token); + } else { + break; + } + } while (1); + return TSDB_CODE_SUCCESS; +} + +// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) +static int32_t ignoreUsingClause(SInsertParseContext* pCxt, const char** pSql) { + int32_t code = TSDB_CODE_SUCCESS; + SToken token; + NEXT_TOKEN(*pSql, token); + + NEXT_TOKEN(*pSql, token); + if (TK_NK_LP == token.type) { + code = skipParentheses(pCxt, pSql); + if (TSDB_CODE_SUCCESS == code) { + NEXT_TOKEN(*pSql, token); + } + } + + // pSql -> TAGS (tag1_value, ...) + if (TSDB_CODE_SUCCESS == code) { + if (TK_TAGS != token.type) { + code = buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z); + } else { + NEXT_TOKEN(*pSql, token); + } + } + if (TSDB_CODE_SUCCESS == code) { + if (TK_NK_LP != token.type) { + code = buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z); + } else { + code = skipParentheses(pCxt, pSql); + } + } + + if (TSDB_CODE_SUCCESS == code) { + code = skipTableOptions(pCxt, pSql); + } + + return code; +} + +static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, bool* pDuplicate) { + *pDuplicate = false; + + char tbFName[TSDB_TABLE_FNAME_LEN]; + tNameExtractFullName(&pStmt->targetTableName, tbFName); + STableMeta** pMeta = taosHashGet(pStmt->pSubTableHashObj, tbFName, strlen(tbFName)); + if (NULL != pMeta) { + *pDuplicate = true; + int32_t code = ignoreUsingClause(pCxt, &pStmt->pSql); + if (TSDB_CODE_SUCCESS == code) { + return cloneTableMeta(*pMeta, &pStmt->pTableMeta); + } + } + + return TSDB_CODE_SUCCESS; +} + +// pStmt->pSql -> field1_name, ...) +static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, SParsedDataColInfo* pColList, + SSchema* pSchema) { col_id_t nCols = pColList->numOfCols; pColList->numOfBound = 0; @@ -433,32 +183,32 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo* pColList->cols[i].valStat = VAL_STAT_NONE; } - SToken sToken; + SToken token; bool isOrdered = true; col_id_t lastColIdx = -1; // last column found while (1) { - NEXT_TOKEN(pCxt->pSql, sToken); + NEXT_TOKEN(*pSql, token); - if (TK_NK_RP == sToken.type) { + if (TK_NK_RP == token.type) { break; } char tmpTokenBuf[TSDB_COL_NAME_LEN + 2] = {0}; // used for deleting Escape character backstick(`) - strncpy(tmpTokenBuf, sToken.z, sToken.n); - sToken.z = tmpTokenBuf; - sToken.n = strdequote(sToken.z); + strncpy(tmpTokenBuf, token.z, token.n); + token.z = tmpTokenBuf; + token.n = strdequote(token.z); col_id_t t = lastColIdx + 1; - col_id_t index = insFindCol(&sToken, t, nCols, pSchema); + col_id_t index = insFindCol(&token, t, nCols, pSchema); if (index < 0 && t > 0) { - index = insFindCol(&sToken, 0, t, pSchema); + index = insFindCol(&token, 0, t, pSchema); isOrdered = false; } if (index < 0) { - return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, sToken.z); + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z); } if (pColList->cols[index].valStat == VAL_STAT_HAS) { - return buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", sToken.z); + return buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z); } lastColIdx = index; pColList->cols[index].valStat = VAL_STAT_HAS; @@ -504,7 +254,80 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo* return TSDB_CODE_SUCCESS; } -static int32_t parseTagToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val, +static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf) { + int32_t index = 0; + int64_t interval; + int64_t ts = 0; + const char* pTokenEnd = *end; + + if (pToken->type == TK_NOW) { + ts = taosGetTimestamp(timePrec); + } else if (pToken->type == TK_TODAY) { + ts = taosGetTimestampToday(timePrec); + } else if (pToken->type == TK_NK_INTEGER) { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &ts)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); + } + } else { // parse the RFC-3339/ISO-8601 timestamp format string + if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { + return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); + } + + return TSDB_CODE_SUCCESS; + } + + for (int k = pToken->n; pToken->z[k] != '\0'; k++) { + if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue; + if (pToken->z[k] == '(' && pToken->z[k + 1] == ')') { // for insert NOW()/TODAY() + *end = pTokenEnd = &pToken->z[k + 2]; + k++; + continue; + } + if (pToken->z[k] == ',') { + *end = pTokenEnd; + *time = ts; + return 0; + } + + break; + } + + /* + * time expression: + * e.g., now+12a, now-5h + */ + index = 0; + SToken token = tStrGetToken(pTokenEnd, &index, false); + pTokenEnd += index; + + if (token.type == TK_NK_MINUS || token.type == TK_NK_PLUS) { + index = 0; + SToken valueToken = tStrGetToken(pTokenEnd, &index, false); + pTokenEnd += index; + + if (valueToken.n < 2) { + return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", token.z); + } + + char unit = 0; + if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval, &unit, timePrec) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + if (token.type == TK_NK_PLUS) { + ts += interval; + } else { + ts = ts - interval; + } + + *end = pTokenEnd; + } + + *time = ts; + return TSDB_CODE_SUCCESS; +} + +static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val, SMsgBuf* pMsgBuf) { int64_t iv; uint64_t uv; @@ -688,22 +511,96 @@ static int32_t parseTagToken(char** end, SToken* pToken, SSchema* pSchema, int16 return TSDB_CODE_SUCCESS; } -// pSql -> tag1_value, ...) -static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint8_t precision, const char* tName) { - int32_t code = TSDB_CODE_SUCCESS; - SArray* pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal)); - SArray* tagName = taosArrayInit(8, TSDB_COL_NAME_LEN); - SToken sToken; - bool isParseBindParam = false; - bool isJson = false; - STag* pTag = NULL; - for (int i = 0; i < pCxt->tags.numOfBound; ++i) { - NEXT_TOKEN_WITH_PREV(pCxt->pSql, sToken); +// input pStmt->pSql: [(tag1_name, ...)] TAGS (tag1_value, ...) ... +// output pStmt->pSql: TAGS (tag1_value, ...) ... +static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + SSchema* pTagsSchema = getTableTagSchema(pStmt->pTableMeta); + insSetBoundColumnInfo(&pCxt->tags, pTagsSchema, getNumOfTags(pStmt->pTableMeta)); - if (sToken.type == TK_NK_QUESTION) { + SToken token; + int32_t index = 0; + NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index); + if (TK_NK_LP != token.type) { + return TSDB_CODE_SUCCESS; + } + + pStmt->pSql += index; + return parseBoundColumns(pCxt, &pStmt->pSql, &pCxt->tags, pTagsSchema); +} + +static int32_t parseTagValue(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SSchema* pTagSchema, SToken* pToken, + SArray* pTagName, SArray* pTagVals, STag** pTag) { + if (!isNullValue(pTagSchema->type, pToken)) { + taosArrayPush(pTagName, pTagSchema->name); + } + + if (pTagSchema->type == TSDB_DATA_TYPE_JSON) { + if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { + return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z); + } + + if (isNullValue(pTagSchema->type, pToken)) { + return tTagNew(pTagVals, 1, true, pTag); + } else { + return parseJsontoTagData(pToken->z, pTagVals, pTag, &pCxt->msg); + } + } + + STagVal val = {0}; + int32_t code = + parseTagToken(&pStmt->pSql, pToken, pTagSchema, pStmt->pTableMeta->tableInfo.precision, &val, &pCxt->msg); + if (TSDB_CODE_SUCCESS == code) { + taosArrayPush(pTagVals, &val); + } + + return code; +} + +static void buildCreateTbReq(SVnodeModifOpStmt* pStmt, STag* pTag, SArray* pTagName) { + insBuildCreateTbReq(&pStmt->createTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid, + pStmt->usingTableName.tname, pTagName, pStmt->pTableMeta->tableInfo.numOfTags); +} + +static int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf) { + if ((pToken->type != TK_NOW && pToken->type != TK_TODAY && pToken->type != TK_NK_INTEGER && + pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL && + pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && + pToken->type != TK_NK_BIN) || + (pToken->n == 0) || (pToken->type == TK_NK_RP)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z); + } + + // Remove quotation marks + if (TK_NK_STRING == pToken->type) { + if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) { + return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z); + } + + int32_t len = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW); + pToken->z = tmpTokenBuf; + pToken->n = len; + } + + return TSDB_CODE_SUCCESS; +} + +// pSql -> tag1_value, ...) +static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + int32_t code = TSDB_CODE_SUCCESS; + SSchema* pSchema = getTableTagSchema(pStmt->pTableMeta); + SArray* pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal)); + SArray* pTagName = taosArrayInit(8, TSDB_COL_NAME_LEN); + SToken token; + bool isParseBindParam = false; + bool isJson = false; + STag* pTag = NULL; + for (int i = 0; TSDB_CODE_SUCCESS == code && i < pCxt->tags.numOfBound; ++i) { + NEXT_TOKEN_WITH_PREV(pStmt->pSql, token); + + if (token.type == TK_NK_QUESTION) { isParseBindParam = true; - if (NULL == pCxt->pStmtCb) { - code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", sToken.z); + if (NULL == pCxt->pComCxt->pStmtCb) { + code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", token.z); break; } @@ -716,33 +613,10 @@ static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint } SSchema* pTagSchema = &pSchema[pCxt->tags.boundColumns[i]]; - char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW] = {0}; // todo this can be optimize with parse column - code = checkAndTrimValue(&sToken, tmpTokenBuf, &pCxt->msg); + isJson = pTagSchema->type == TSDB_DATA_TYPE_JSON; + code = checkAndTrimValue(&token, pCxt->tmpTokenBuf, &pCxt->msg); if (TSDB_CODE_SUCCESS == code) { - if (!isNullValue(pTagSchema->type, &sToken)) { - taosArrayPush(tagName, pTagSchema->name); - } - if (pTagSchema->type == TSDB_DATA_TYPE_JSON) { - isJson = true; - if (sToken.n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { - code = buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", sToken.z); - break; - } - if (isNullValue(pTagSchema->type, &sToken)) { - code = tTagNew(pTagVals, 1, true, &pTag); - } else { - code = parseJsontoTagData(sToken.z, pTagVals, &pTag, &pCxt->msg); - } - } else { - STagVal val = {0}; - code = parseTagToken(&pCxt->pSql, &sToken, pTagSchema, precision, &val, &pCxt->msg); - if (TSDB_CODE_SUCCESS == code) { - taosArrayPush(pTagVals, &val); - } - } - } - if (TSDB_CODE_SUCCESS != code) { - break; + code = parseTagValue(pCxt, pStmt, pTagSchema, &token, pTagName, pTagVals, &pTag); } } @@ -751,8 +625,7 @@ static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint } if (TSDB_CODE_SUCCESS == code && !isParseBindParam) { - insBuildCreateTbReq(&pCxt->createTblReq, tName, pTag, pCxt->pTableMeta->suid, pCxt->sTableName, tagName, - pCxt->pTableMeta->tableInfo.numOfTags); + buildCreateTbReq(pStmt, pTag, pTagName); pTag = NULL; } @@ -763,96 +636,82 @@ static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint } } taosArrayDestroy(pTagVals); - taosArrayDestroy(tagName); + taosArrayDestroy(pTagName); tTagFree(pTag); return code; } -static int32_t storeTableMeta(SInsertParseContext* pCxt, SHashObj* pHash, int32_t tbNo, SName* pTableName, - const char* pName, int32_t len, STableMeta* pMeta) { - SVgroupInfo vg; - CHECK_CODE(getTableVgroup(pCxt, tbNo, pTableName, &vg)); - CHECK_CODE(taosHashPut(pCxt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg))); +// input pStmt->pSql: TAGS (tag1_value, ...) [table_options] ... +// output pStmt->pSql: [table_options] ... +static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + SToken token; + NEXT_TOKEN(pStmt->pSql, token); + if (TK_TAGS != token.type) { + return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z); + } - pMeta->uid = tbNo; - pMeta->vgId = vg.vgId; - pMeta->tableType = TSDB_CHILD_TABLE; + NEXT_TOKEN(pStmt->pSql, token); + if (TK_NK_LP != token.type) { + return buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z); + } + + int32_t code = parseTagsClauseImpl(pCxt, pStmt); + if (TSDB_CODE_SUCCESS == code) { + NEXT_VALID_TOKEN(pStmt->pSql, token); + if (TK_NK_COMMA == token.type) { + code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_TAGS_NOT_MATCHED); + } else if (TK_NK_RP != token.type) { + code = buildSyntaxErrMsg(&pCxt->msg, ") is expected", token.z); + } + } + return code; +} + +static int32_t storeTableMeta(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + pStmt->pTableMeta->suid = pStmt->pTableMeta->uid; + pStmt->pTableMeta->uid = pStmt->totalTbNum; + pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE; STableMeta* pBackup = NULL; - if (TSDB_CODE_SUCCESS != cloneTableMeta(pMeta, &pBackup)) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; + if (TSDB_CODE_SUCCESS != cloneTableMeta(pStmt->pTableMeta, &pBackup)) { + return TSDB_CODE_OUT_OF_MEMORY; } - return taosHashPut(pHash, pName, len, &pBackup, POINTER_BYTES); + + char tbFName[TSDB_TABLE_FNAME_LEN]; + tNameExtractFullName(&pStmt->targetTableName, tbFName); + return taosHashPut(pStmt->pSubTableHashObj, tbFName, strlen(tbFName), &pBackup, POINTER_BYTES); } -static int32_t skipParentheses(SInsertParseSyntaxCxt* pCxt) { - SToken sToken; - int32_t expectRightParenthesis = 1; - while (1) { - NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_NK_LP == sToken.type) { - ++expectRightParenthesis; - } else if (TK_NK_RP == sToken.type && 0 == --expectRightParenthesis) { - break; - } - if (0 == sToken.n) { - return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL); - } - } - return TSDB_CODE_SUCCESS; -} - -static int32_t skipBoundColumns(SInsertParseSyntaxCxt* pCxt) { return skipParentheses(pCxt); } - -static int32_t ignoreBoundColumns(SInsertParseContext* pCxt) { - SInsertParseSyntaxCxt cxt = {.pComCxt = pCxt->pComCxt, .pSql = pCxt->pSql, .msg = pCxt->msg, .pMetaCache = NULL}; - int32_t code = skipBoundColumns(&cxt); - pCxt->pSql = cxt.pSql; - return code; -} - -static int32_t skipUsingClause(SInsertParseSyntaxCxt* pCxt); - -// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) -static int32_t ignoreAutoCreateTableClause(SInsertParseContext* pCxt) { - SToken sToken; - NEXT_TOKEN(pCxt->pSql, sToken); - SInsertParseSyntaxCxt cxt = {.pComCxt = pCxt->pComCxt, .pSql = pCxt->pSql, .msg = pCxt->msg, .pMetaCache = NULL}; - int32_t code = skipUsingClause(&cxt); - pCxt->pSql = cxt.pSql; - return code; -} - -static int32_t parseTableOptions(SInsertParseContext* pCxt) { +static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { do { int32_t index = 0; - SToken sToken; - NEXT_TOKEN_KEEP_SQL(pCxt->pSql, sToken, index); - if (TK_TTL == sToken.type) { - pCxt->pSql += index; - NEXT_TOKEN_WITH_PREV(pCxt->pSql, sToken); - if (TK_NK_INTEGER != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", sToken.z); + SToken token; + NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index); + if (TK_TTL == token.type) { + pStmt->pSql += index; + NEXT_TOKEN_WITH_PREV(pStmt->pSql, token); + if (TK_NK_INTEGER != token.type) { + return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z); } - pCxt->createTblReq.ttl = taosStr2Int32(sToken.z, NULL, 10); - if (pCxt->createTblReq.ttl < 0) { - return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", sToken.z); + pStmt->createTblReq.ttl = taosStr2Int32(token.z, NULL, 10); + if (pStmt->createTblReq.ttl < 0) { + return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z); } - } else if (TK_COMMENT == sToken.type) { - pCxt->pSql += index; - NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_NK_STRING != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, "Invalid option comment", sToken.z); + } else if (TK_COMMENT == token.type) { + pStmt->pSql += index; + NEXT_TOKEN(pStmt->pSql, token); + if (TK_NK_STRING != token.type) { + return buildSyntaxErrMsg(&pCxt->msg, "Invalid option comment", token.z); } - if (sToken.n >= TSDB_TB_COMMENT_LEN) { - return buildSyntaxErrMsg(&pCxt->msg, "comment too long", sToken.z); + if (token.n >= TSDB_TB_COMMENT_LEN) { + return buildSyntaxErrMsg(&pCxt->msg, "comment too long", token.z); } - int32_t len = trimString(sToken.z, sToken.n, pCxt->tmpTokenBuf, TSDB_TB_COMMENT_LEN); - pCxt->createTblReq.comment = strndup(pCxt->tmpTokenBuf, len); - if (NULL == pCxt->createTblReq.comment) { + int32_t len = trimString(token.z, token.n, pCxt->tmpTokenBuf, TSDB_TB_COMMENT_LEN); + pStmt->createTblReq.comment = strndup(pCxt->tmpTokenBuf, len); + if (NULL == pStmt->createTblReq.comment) { return TSDB_CODE_OUT_OF_MEMORY; } - pCxt->createTblReq.commentLen = len; + pStmt->createTblReq.commentLen = len; } else { break; } @@ -860,119 +719,505 @@ static int32_t parseTableOptions(SInsertParseContext* pCxt) { return TSDB_CODE_SUCCESS; } -// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) -static int32_t parseUsingClause(SInsertParseContext* pCxt, int32_t tbNo, SName* name, char* tbFName) { - int32_t len = strlen(tbFName); - STableMeta** pMeta = taosHashGet(pCxt->pSubTableHashObj, tbFName, len); - if (NULL != pMeta) { - CHECK_CODE(ignoreAutoCreateTableClause(pCxt)); - return cloneTableMeta(*pMeta, &pCxt->pTableMeta); +// input pStmt->pSql: +// 1. [(tag1_name, ...)] ... +// 2. VALUES ... | FILE ... +// output pStmt->pSql: +// 1. [(field1_name, ...)] +// 2. VALUES ... | FILE ... +static int32_t parseUsingClauseBottom(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + if (!pStmt->usingTableProcessing || pCxt->usingDuplicateTable) { + return TSDB_CODE_SUCCESS; } - SToken sToken; - // pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) - NEXT_TOKEN(pCxt->pSql, sToken); - - SName sname; - CHECK_CODE(insCreateSName(&sname, &sToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg)); - char dbFName[TSDB_DB_FNAME_LEN]; - tNameGetFullDbName(&sname, dbFName); - strcpy(pCxt->sTableName, sname.tname); - - CHECK_CODE(getSTableMeta(pCxt, tbNo, &sname)); - if (TSDB_SUPER_TABLE != pCxt->pTableMeta->tableType) { - return buildInvalidOperationMsg(&pCxt->msg, "create table only from super table is allowed"); + int32_t code = parseBoundTagsClause(pCxt, pStmt); + if (TSDB_CODE_SUCCESS == code) { + code = parseTagsClause(pCxt, pStmt); } - CHECK_CODE(storeTableMeta(pCxt, pCxt->pSubTableHashObj, tbNo, name, tbFName, len, pCxt->pTableMeta)); - - SSchema* pTagsSchema = getTableTagSchema(pCxt->pTableMeta); - insSetBoundColumnInfo(&pCxt->tags, pTagsSchema, getNumOfTags(pCxt->pTableMeta)); - - // pSql -> [(tag1_name, ...)] TAGS (tag1_value, ...) - NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_NK_LP == sToken.type) { - CHECK_CODE(parseBoundColumns(pCxt, &pCxt->tags, pTagsSchema)); - NEXT_TOKEN(pCxt->pSql, sToken); + if (TSDB_CODE_SUCCESS == code) { + code = parseTableOptions(pCxt, pStmt); } - if (TK_TAGS != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", sToken.z); - } - // pSql -> (tag1_value, ...) - NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_NK_LP != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, "( is expected", sToken.z); - } - CHECK_CODE(parseTagsClause(pCxt, pTagsSchema, getTableInfo(pCxt->pTableMeta).precision, name->tname)); - NEXT_VALID_TOKEN(pCxt->pSql, sToken); - if (TK_NK_COMMA == sToken.type) { - return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_TAGS_NOT_MATCHED); - } else if (TK_NK_RP != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, ") is expected", sToken.z); - } - - return parseTableOptions(pCxt); + return code; } -static int parseOneRow(SInsertParseContext* pCxt, STableDataBlocks* pDataBlocks, int16_t timePrec, bool* gotRow, - char* tmpTokenBuf) { - SParsedDataColInfo* spd = &pDataBlocks->boundColumnInfo; - SRowBuilder* pBuilder = &pDataBlocks->rowBuilder; - STSRow* row = (STSRow*)(pDataBlocks->pData + pDataBlocks->size); // skip the SSubmitBlk header +static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool* pMissCache) { + char dbFName[TSDB_DB_FNAME_LEN]; + tNameGetFullDbName(pTbName, dbFName); + int32_t code = TSDB_CODE_SUCCESS; + bool pass = true; + bool exists = true; + if (pCxt->async) { + code = catalogChkAuthFromCache(pCxt->pCatalog, pCxt->pUser, dbFName, AUTH_TYPE_WRITE, &pass, &exists); + } else { + SRequestConnInfo conn = {.pTrans = pCxt->pTransporter, + .requestId = pCxt->requestId, + .requestObjRefId = pCxt->requestRid, + .mgmtEps = pCxt->mgmtEpSet}; + code = catalogChkAuth(pCxt->pCatalog, &conn, pCxt->pUser, dbFName, AUTH_TYPE_WRITE, &pass); + } + if (TSDB_CODE_SUCCESS == code) { + if (!exists) { + *pMissCache = true; + } else if (!pass) { + code = TSDB_CODE_PAR_PERMISSION_DENIED; + } + } + return code; +} - tdSRowResetBuf(pBuilder, row); +static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, bool isStb, STableMeta** pTableMeta, + bool* pMissCache) { + SParseContext* pComCxt = pCxt->pComCxt; + int32_t code = TSDB_CODE_SUCCESS; + if (pComCxt->async) { + if (isStb) { + code = catalogGetCachedSTableMeta(pComCxt->pCatalog, pTbName, pTableMeta); + } else { + code = catalogGetCachedTableMeta(pComCxt->pCatalog, pTbName, pTableMeta); + } + } else { + SRequestConnInfo conn = {.pTrans = pComCxt->pTransporter, + .requestId = pComCxt->requestId, + .requestObjRefId = pComCxt->requestRid, + .mgmtEps = pComCxt->mgmtEpSet}; + if (isStb) { + code = catalogGetSTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta); + } else { + code = catalogGetTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta); + } + } + if (TSDB_CODE_SUCCESS == code) { + if (NULL == *pTableMeta) { + *pMissCache = true; + } else if (isStb && TSDB_SUPER_TABLE != (*pTableMeta)->tableType) { + code = buildInvalidOperationMsg(&pCxt->msg, "create table only from super table is allowed"); + } + } + return code; +} - bool isParseBindParam = false; - SSchema* schema = getTableColumnSchema(pDataBlocks->pTableMeta); - SMemParam param = {.rb = pBuilder}; - SToken sToken = {0}; - // 1. set the parsed value from sql string - for (int i = 0; i < spd->numOfBound; ++i) { - NEXT_TOKEN_WITH_PREV(pCxt->pSql, sToken); - SSchema* pSchema = &schema[spd->boundColumns[i]]; +static int32_t getTableVgroup(SParseContext* pCxt, SVnodeModifOpStmt* pStmt, bool isStb, bool* pMissCache) { + int32_t code = TSDB_CODE_SUCCESS; + SVgroupInfo vg; + bool exists = true; + if (pCxt->async) { + code = catalogGetCachedTableHashVgroup(pCxt->pCatalog, &pStmt->targetTableName, &vg, &exists); + } else { + SRequestConnInfo conn = {.pTrans = pCxt->pTransporter, + .requestId = pCxt->requestId, + .requestObjRefId = pCxt->requestRid, + .mgmtEps = pCxt->mgmtEpSet}; + code = catalogGetTableHashVgroup(pCxt->pCatalog, &conn, &pStmt->targetTableName, &vg); + } + if (TSDB_CODE_SUCCESS == code) { + if (exists) { + if (isStb) { + pStmt->pTableMeta->vgId = vg.vgId; + } + code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg)); + } + *pMissCache = !exists; + } + return code; +} - if (sToken.type == TK_NK_QUESTION) { - isParseBindParam = true; - if (NULL == pCxt->pStmtCb) { - return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", sToken.z); +static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache); + if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { + code = getTableMeta(pCxt, &pStmt->targetTableName, false, &pStmt->pTableMeta, &pCxt->missCache); + } + if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { + code = getTableVgroup(pCxt->pComCxt, pStmt, false, &pCxt->missCache); + } + return code; +} + +static int32_t preParseUsingTableName(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName) { + return insCreateSName(&pStmt->usingTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg); +} + +static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache); + if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { + code = getTableMeta(pCxt, &pStmt->usingTableName, true, &pStmt->pTableMeta, &pCxt->missCache); + } + if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { + code = getTableVgroup(pCxt->pComCxt, pStmt, true, &pCxt->missCache); + } + return code; +} + +static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + SToken token; + NEXT_TOKEN(pStmt->pSql, token); + int32_t code = preParseUsingTableName(pCxt, pStmt, &token); + if (TSDB_CODE_SUCCESS == code) { + code = getUsingTableSchema(pCxt, pStmt); + } + if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { + code = storeTableMeta(pCxt, pStmt); + } + return code; +} + +// input pStmt->pSql: +// 1(care). [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ... +// 2. VALUES ... | FILE ... +// output pStmt->pSql: +// 1. [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ... +// 2. VALUES ... | FILE ... +static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + SToken token; + int32_t index = 0; + NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index); + if (TK_USING != token.type) { + return getTargetTableSchema(pCxt, pStmt); + } + + pStmt->usingTableProcessing = true; + // pStmt->pSql -> stb_name [(tag1_name, ...) + pStmt->pSql += index; + int32_t code = parseDuplicateUsingClause(pCxt, pStmt, &pCxt->usingDuplicateTable); + if (TSDB_CODE_SUCCESS == code && !pCxt->usingDuplicateTable) { + return parseUsingTableNameImpl(pCxt, pStmt); + } + return code; +} + +static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName) { + return insCreateSName(&pStmt->targetTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg); +} + +// input pStmt->pSql: +// 1(care). [(field1_name, ...)] ... +// 2. [ USING ... ] ... +// 3. VALUES ... | FILE ... +// output pStmt->pSql: +// 1. [ USING ... ] ... +// 2. VALUES ... | FILE ... +static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + SToken token; + int32_t index = 0; + NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index); + if (TK_NK_LP != token.type) { + return TSDB_CODE_SUCCESS; + } + + // pStmt->pSql -> field1_name, ...) + pStmt->pSql += index; + pStmt->pBoundCols = pStmt->pSql; + return skipParentheses(pCxt, &pStmt->pSql); +} + +static int32_t getTableDataBlocks(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks** pDataBuf) { + if (pCxt->pComCxt->async) { + return insGetDataBlockFromList(pStmt->pTableBlockHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid), + TSDB_DEFAULT_PAYLOAD_SIZE, sizeof(SSubmitBlk), + getTableInfo(pStmt->pTableMeta).rowSize, pStmt->pTableMeta, pDataBuf, NULL, + &pStmt->createTblReq); + } + char tbFName[TSDB_TABLE_FNAME_LEN]; + tNameExtractFullName(&pStmt->targetTableName, tbFName); + return insGetDataBlockFromList(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), TSDB_DEFAULT_PAYLOAD_SIZE, + sizeof(SSubmitBlk), getTableInfo(pStmt->pTableMeta).rowSize, pStmt->pTableMeta, + pDataBuf, NULL, &pStmt->createTblReq); +} + +static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, + STableDataBlocks* pDataBuf) { + SToken token; + int32_t index = 0; + NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index); + if (TK_NK_LP == token.type) { + pStmt->pSql += index; + if (NULL != pStmt->pBoundCols) { + return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z); + } + // pStmt->pSql -> field1_name, ...) + return parseBoundColumns(pCxt, &pStmt->pSql, &pDataBuf->boundColumnInfo, getTableColumnSchema(pStmt->pTableMeta)); + } + + if (NULL != pStmt->pBoundCols) { + return parseBoundColumns(pCxt, &pStmt->pBoundCols, &pDataBuf->boundColumnInfo, + getTableColumnSchema(pStmt->pTableMeta)); + } + + return TSDB_CODE_SUCCESS; +} + +// input pStmt->pSql: +// 1. [(tag1_name, ...)] ... +// 2. VALUES ... | FILE ... +// output pStmt->pSql: VALUES ... | FILE ... +static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, + STableDataBlocks** pDataBuf) { + int32_t code = parseUsingClauseBottom(pCxt, pStmt); + if (TSDB_CODE_SUCCESS == code) { + code = getTableDataBlocks(pCxt, pStmt, pDataBuf); + } + if (TSDB_CODE_SUCCESS == code) { + code = parseBoundColumnsClause(pCxt, pStmt, *pDataBuf); + } + return code; +} + +// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ... +// output pStmt->pSql: +// 1. [(tag1_name, ...)] ... +// 2. VALUES ... | FILE ... +static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName) { + int32_t code = preParseTargetTableName(pCxt, pStmt, pTbName); + if (TSDB_CODE_SUCCESS == code) { + // option: [(field1_name, ...)] + code = preParseBoundColumnsClause(pCxt, pStmt); + } + if (TSDB_CODE_SUCCESS == code) { + // option: [USING stb_name] + code = parseUsingTableName(pCxt, pStmt); + } + return code; +} + +static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema, + int16_t timePrec, _row_append_fn_t func, void* param) { + int64_t iv; + uint64_t uv; + char* endptr = NULL; + + switch (pSchema->type) { + case TSDB_DATA_TYPE_BOOL: { + if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) { + if (strncmp(pToken->z, "true", pToken->n) == 0) { + return func(&pCxt->msg, &TRUE_VALUE, pSchema->bytes, param); + } else if (strncmp(pToken->z, "false", pToken->n) == 0) { + return func(&pCxt->msg, &FALSE_VALUE, pSchema->bytes, param); + } else { + return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z); + } + } else if (pToken->type == TK_NK_INTEGER) { + return func(&pCxt->msg, ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), + pSchema->bytes, param); + } else if (pToken->type == TK_NK_FLOAT) { + return func(&pCxt->msg, ((taosStr2Double(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, + param); + } else { + return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z); + } + } + + case TSDB_DATA_TYPE_TINYINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z); + } else if (!IS_VALID_TINYINT(iv)) { + return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z); } + uint8_t tmpVal = (uint8_t)iv; + return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_UTINYINT: { + if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z); + } else if (uv > UINT8_MAX) { + return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z); + } + uint8_t tmpVal = (uint8_t)uv; + return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_SMALLINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z); + } else if (!IS_VALID_SMALLINT(iv)) { + return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z); + } + int16_t tmpVal = (int16_t)iv; + return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_USMALLINT: { + if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z); + } else if (uv > UINT16_MAX) { + return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z); + } + uint16_t tmpVal = (uint16_t)uv; + return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_INT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z); + } else if (!IS_VALID_INT(iv)) { + return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z); + } + int32_t tmpVal = (int32_t)iv; + return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_UINT: { + if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z); + } else if (uv > UINT32_MAX) { + return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z); + } + uint32_t tmpVal = (uint32_t)uv; + return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_BIGINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z); + } + return func(&pCxt->msg, &iv, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_UBIGINT: { + if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z); + } + return func(&pCxt->msg, &uv, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_FLOAT: { + double dv; + if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { + return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z); + } + if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || + isnan(dv)) { + return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z); + } + float tmpVal = (float)dv; + return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_DOUBLE: { + double dv; + if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { + return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z); + } + if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) { + return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z); + } + return func(&pCxt->msg, &dv, pSchema->bytes, param); + } + + case TSDB_DATA_TYPE_BINARY: { + // Too long values will raise the invalid sql error message + if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); + } + + return func(&pCxt->msg, pToken->z, pToken->n, param); + } + + case TSDB_DATA_TYPE_NCHAR: { + return func(&pCxt->msg, pToken->z, pToken->n, param); + } + case TSDB_DATA_TYPE_JSON: { + if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { + return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z); + } + return func(&pCxt->msg, pToken->z, pToken->n, param); + } + case TSDB_DATA_TYPE_TIMESTAMP: { + int64_t tmpVal; + if (parseTime(pSql, pToken, timePrec, &tmpVal, &pCxt->msg) != TSDB_CODE_SUCCESS) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z); + } + + return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + } + } + + return TSDB_CODE_FAILED; +} + +static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema, + int16_t timePrec, _row_append_fn_t func, void* param) { + int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg); + if (TSDB_CODE_SUCCESS == code && isNullValue(pSchema->type, pToken)) { + if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { + return buildSyntaxErrMsg(&pCxt->msg, "primary timestamp should not be null", pToken->z); + } + + return func(&pCxt->msg, NULL, 0, param); + } + + if (TSDB_CODE_SUCCESS == code && IS_NUMERIC_TYPE(pSchema->type) && pToken->n == 0) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid numeric data", pToken->z); + } + + if (TSDB_CODE_SUCCESS == code) { + code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, timePrec, func, param); + } + + return code; +} + +static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataBlocks* pDataBuf, bool* pGotRow, + SToken* pToken) { + SRowBuilder* pBuilder = &pDataBuf->rowBuilder; + STSRow* row = (STSRow*)(pDataBuf->pData + pDataBuf->size); // skip the SSubmitBlk header + SParsedDataColInfo* pCols = &pDataBuf->boundColumnInfo; + bool isParseBindParam = false; + SSchema* pSchemas = getTableColumnSchema(pDataBuf->pTableMeta); + SMemParam param = {.rb = pBuilder}; + + int32_t code = tdSRowResetBuf(pBuilder, row); + // 1. set the parsed value from sql string + for (int i = 0; i < pCols->numOfBound && TSDB_CODE_SUCCESS == code; ++i) { + NEXT_TOKEN_WITH_PREV(*pSql, *pToken); + SSchema* pSchema = &pSchemas[pCols->boundColumns[i]]; + + if (pToken->type == TK_NK_QUESTION) { + isParseBindParam = true; + if (NULL == pCxt->pComCxt->pStmtCb) { + code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pToken->z); + } continue; } - if (TK_NK_RP == sToken.type) { - return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM); + if (TSDB_CODE_SUCCESS == code && TK_NK_RP == pToken->type) { + code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM); } - if (isParseBindParam) { - return buildInvalidOperationMsg(&pCxt->msg, "no mix usage for ? and values"); + if (TSDB_CODE_SUCCESS == code && isParseBindParam) { + code = buildInvalidOperationMsg(&pCxt->msg, "no mix usage for ? and values"); } - param.schema = pSchema; - insGetSTSRowAppendInfo(pBuilder->rowType, spd, i, ¶m.toffset, ¶m.colIdx); - CHECK_CODE( - parseValueToken(&pCxt->pSql, &sToken, pSchema, timePrec, tmpTokenBuf, insMemRowAppend, ¶m, &pCxt->msg)); + if (TSDB_CODE_SUCCESS == code) { + param.schema = pSchema; + insGetSTSRowAppendInfo(pBuilder->rowType, pCols, i, ¶m.toffset, ¶m.colIdx); + code = parseValueToken(pCxt, pSql, pToken, pSchema, getTableInfo(pDataBuf->pTableMeta).precision, insMemRowAppend, + ¶m); + } - if (i < spd->numOfBound - 1) { - NEXT_VALID_TOKEN(pCxt->pSql, sToken); - if (TK_NK_COMMA != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, ", expected", sToken.z); + if (TSDB_CODE_SUCCESS == code && i < pCols->numOfBound - 1) { + NEXT_VALID_TOKEN(*pSql, *pToken); + if (TK_NK_COMMA != pToken->type) { + code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z); } } } - TSKEY tsKey = TD_ROW_KEY(row); - insCheckTimestamp(pDataBlocks, (const char*)&tsKey); + if (TSDB_CODE_SUCCESS == code) { + TSKEY tsKey = TD_ROW_KEY(row); + code = insCheckTimestamp(pDataBuf, (const char*)&tsKey); + } - if (!isParseBindParam) { + if (TSDB_CODE_SUCCESS == code && !isParseBindParam) { // set the null value for the columns that do not assign values - if ((spd->numOfBound < spd->numOfCols) && TD_IS_TP_ROW(row)) { + if ((pCols->numOfBound < pCols->numOfCols) && TD_IS_TP_ROW(row)) { pBuilder->hasNone = true; } tdSRowEnd(pBuilder); - *gotRow = true; + *pGotRow = true; #ifdef TD_DEBUG_PRINT_ROW STSchema* pSTSchema = tdGetSTSChemaFromSSChema(schema, spd->numOfCols, 1); @@ -981,8 +1226,7 @@ static int parseOneRow(SInsertParseContext* pCxt, STableDataBlocks* pDataBlocks, #endif } - // *len = pBuilder->extendedRowSize; - return TSDB_CODE_SUCCESS; + return code; } static int32_t allocateMemIfNeed(STableDataBlocks* pDataBlock, int32_t rowSize, int32_t* numOfRows) { @@ -1014,84 +1258,82 @@ static int32_t allocateMemIfNeed(STableDataBlocks* pDataBlock, int32_t rowSize, } // pSql -> (field1_value, ...) [(field1_value2, ...) ...] -static int32_t parseValues(SInsertParseContext* pCxt, STableDataBlocks* pDataBlock, int maxRows, int32_t* numOfRows) { - STableComInfo tinfo = getTableInfo(pDataBlock->pTableMeta); - int32_t extendedRowSize = insGetExtendedRowSize(pDataBlock); - CHECK_CODE( - insInitRowBuilder(&pDataBlock->rowBuilder, pDataBlock->pTableMeta->sversion, &pDataBlock->boundColumnInfo)); +static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf, + int32_t maxRows, int32_t* pNumOfRows, SToken* pToken) { + int32_t code = insInitRowBuilder(&pDataBuf->rowBuilder, pDataBuf->pTableMeta->sversion, &pDataBuf->boundColumnInfo); - (*numOfRows) = 0; - // char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW] = {0}; // used for deleting Escape character: \\, \', \" - SToken sToken; - while (1) { + int32_t extendedRowSize = insGetExtendedRowSize(pDataBuf); + (*pNumOfRows) = 0; + while (TSDB_CODE_SUCCESS == code) { int32_t index = 0; - NEXT_TOKEN_KEEP_SQL(pCxt->pSql, sToken, index); - if (TK_NK_LP != sToken.type) { + NEXT_TOKEN_KEEP_SQL(pStmt->pSql, *pToken, index); + if (TK_NK_LP != pToken->type) { break; } - pCxt->pSql += index; + pStmt->pSql += index; - if ((*numOfRows) >= maxRows || pDataBlock->size + extendedRowSize >= pDataBlock->nAllocSize) { - int32_t tSize; - CHECK_CODE(allocateMemIfNeed(pDataBlock, extendedRowSize, &tSize)); - ASSERT(tSize >= maxRows); - maxRows = tSize; + if ((*pNumOfRows) >= maxRows || pDataBuf->size + extendedRowSize >= pDataBuf->nAllocSize) { + code = allocateMemIfNeed(pDataBuf, extendedRowSize, &maxRows); } bool gotRow = false; - CHECK_CODE(parseOneRow(pCxt, pDataBlock, tinfo.precision, &gotRow, pCxt->tmpTokenBuf)); - if (gotRow) { - pDataBlock->size += extendedRowSize; // len; + if (TSDB_CODE_SUCCESS == code) { + code = parseOneRow(pCxt, &pStmt->pSql, pDataBuf, &gotRow, pToken); } - NEXT_VALID_TOKEN(pCxt->pSql, sToken); - if (TK_NK_COMMA == sToken.type) { - return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM); - } else if (TK_NK_RP != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, ") expected", sToken.z); + if (TSDB_CODE_SUCCESS == code) { + NEXT_VALID_TOKEN(pStmt->pSql, *pToken); + if (TK_NK_COMMA == pToken->type) { + code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM); + } else if (TK_NK_RP != pToken->type) { + code = buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z); + } } - if (gotRow) { - (*numOfRows)++; + if (TSDB_CODE_SUCCESS == code && gotRow) { + pDataBuf->size += extendedRowSize; + (*pNumOfRows)++; } } - if (0 == (*numOfRows) && (!TSDB_QUERY_HAS_TYPE(pCxt->pOutput->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) { - return buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL); + if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) && + (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) { + code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL); } - return TSDB_CODE_SUCCESS; + return code; } -static int32_t parseValuesClause(SInsertParseContext* pCxt, STableDataBlocks* dataBuf) { - int32_t maxNumOfRows; - CHECK_CODE(allocateMemIfNeed(dataBuf, insGetExtendedRowSize(dataBuf), &maxNumOfRows)); - +// VALUES (field1_value, ...) [(field1_value2, ...) ...] +static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf, + SToken* pToken) { + int32_t maxNumOfRows = 0; int32_t numOfRows = 0; - CHECK_CODE(parseValues(pCxt, dataBuf, maxNumOfRows, &numOfRows)); - - SSubmitBlk* pBlocks = (SSubmitBlk*)(dataBuf->pData); - if (TSDB_CODE_SUCCESS != insSetBlockInfo(pBlocks, dataBuf, numOfRows)) { - return buildInvalidOperationMsg(&pCxt->msg, - "too many rows in sql, total number of rows should be less than INT32_MAX"); + int32_t code = allocateMemIfNeed(pDataBuf, insGetExtendedRowSize(pDataBuf), &maxNumOfRows); + if (TSDB_CODE_SUCCESS == code) { + code = parseValues(pCxt, pStmt, pDataBuf, maxNumOfRows, &numOfRows, pToken); } - - dataBuf->numOfTables = 1; - pCxt->totalNum += numOfRows; - return TSDB_CODE_SUCCESS; + if (TSDB_CODE_SUCCESS == code) { + code = insSetBlockInfo((SSubmitBlk*)(pDataBuf->pData), pDataBuf, numOfRows, &pCxt->msg); + } + if (TSDB_CODE_SUCCESS == code) { + pDataBuf->numOfTables = 1; + pStmt->totalRowsNum += numOfRows; + pStmt->totalTbNum += 1; + TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_INSERT); + } + return code; } -static int32_t parseCsvFile(SInsertParseContext* pCxt, TdFilePtr fp, STableDataBlocks* pDataBlock, int maxRows, - int32_t* numOfRows) { - STableComInfo tinfo = getTableInfo(pDataBlock->pTableMeta); - int32_t extendedRowSize = insGetExtendedRowSize(pDataBlock); - CHECK_CODE( - insInitRowBuilder(&pDataBlock->rowBuilder, pDataBlock->pTableMeta->sversion, &pDataBlock->boundColumnInfo)); +static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf, + int maxRows, int32_t* pNumOfRows) { + int32_t code = insInitRowBuilder(&pDataBuf->rowBuilder, pDataBuf->pTableMeta->sversion, &pDataBuf->boundColumnInfo); - (*numOfRows) = 0; - char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW] = {0}; // used for deleting Escape character: \\, \', \" + int32_t extendedRowSize = insGetExtendedRowSize(pDataBuf); + (*pNumOfRows) = 0; char* pLine = NULL; int64_t readLen = 0; - while ((readLen = taosGetLineFile(fp, &pLine)) != -1) { + pStmt->fileProcessing = false; + while (TSDB_CODE_SUCCESS == code && (readLen = taosGetLineFile(pStmt->fp, &pLine)) != -1) { if (('\r' == pLine[readLen - 1]) || ('\n' == pLine[readLen - 1])) { pLine[--readLen] = '\0'; } @@ -1100,588 +1342,570 @@ static int32_t parseCsvFile(SInsertParseContext* pCxt, TdFilePtr fp, STableDataB continue; } - if ((*numOfRows) >= maxRows || pDataBlock->size + extendedRowSize >= pDataBlock->nAllocSize) { - int32_t tSize; - CHECK_CODE(allocateMemIfNeed(pDataBlock, extendedRowSize, &tSize)); - ASSERT(tSize >= maxRows); - maxRows = tSize; + if ((*pNumOfRows) >= maxRows || pDataBuf->size + extendedRowSize >= pDataBuf->nAllocSize) { + code = allocateMemIfNeed(pDataBuf, extendedRowSize, &maxRows); } - strtolower(pLine, pLine); - char* pRawSql = pCxt->pSql; - pCxt->pSql = pLine; - bool gotRow = false; - int32_t code = parseOneRow(pCxt, pDataBlock, tinfo.precision, &gotRow, tmpTokenBuf); - if (TSDB_CODE_SUCCESS != code) { - pCxt->pSql = pRawSql; - return code; + bool gotRow = false; + if (TSDB_CODE_SUCCESS == code) { + SToken token; + strtolower(pLine, pLine); + const char* pRow = pLine; + code = parseOneRow(pCxt, (const char**)&pRow, pDataBuf, &gotRow, &token); } - if (gotRow) { - pDataBlock->size += extendedRowSize; // len; - (*numOfRows)++; - } - pCxt->pSql = pRawSql; - if (pDataBlock->nAllocSize > tsMaxMemUsedByInsert * 1024 * 1024) { + if (TSDB_CODE_SUCCESS == code && gotRow) { + pDataBuf->size += extendedRowSize; + (*pNumOfRows)++; + } + + if (TSDB_CODE_SUCCESS == code && pDataBuf->nAllocSize > tsMaxMemUsedByInsert * 1024 * 1024) { + pStmt->fileProcessing = true; break; } } - if (0 == (*numOfRows) && (!TSDB_QUERY_HAS_TYPE(pCxt->pOutput->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) { - return buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL); + if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) && + (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) && !pStmt->fileProcessing) { + code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL); } - return TSDB_CODE_SUCCESS; + return code; } -static int32_t parseDataFromFileAgain(SInsertParseContext* pCxt, int16_t tableNo, const SName* pTableName, - STableDataBlocks* dataBuf) { - int32_t maxNumOfRows; - CHECK_CODE(allocateMemIfNeed(dataBuf, insGetExtendedRowSize(dataBuf), &maxNumOfRows)); - +static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf) { + int32_t maxNumOfRows = 0; int32_t numOfRows = 0; - CHECK_CODE(parseCsvFile(pCxt, pCxt->pComCxt->csvCxt.fp, dataBuf, maxNumOfRows, &numOfRows)); - - SSubmitBlk* pBlocks = (SSubmitBlk*)(dataBuf->pData); - if (TSDB_CODE_SUCCESS != insSetBlockInfo(pBlocks, dataBuf, numOfRows)) { - return buildInvalidOperationMsg(&pCxt->msg, - "too many rows in sql, total number of rows should be less than INT32_MAX"); + int32_t code = allocateMemIfNeed(pDataBuf, insGetExtendedRowSize(pDataBuf), &maxNumOfRows); + if (TSDB_CODE_SUCCESS == code) { + code = parseCsvFile(pCxt, pStmt, pDataBuf, maxNumOfRows, &numOfRows); } - - if (!taosEOFFile(pCxt->pComCxt->csvCxt.fp)) { - pCxt->pComCxt->needMultiParse = true; - pCxt->pComCxt->csvCxt.tableNo = tableNo; - memcpy(&pCxt->pComCxt->csvCxt.tableName, pTableName, sizeof(SName)); - pCxt->pComCxt->csvCxt.pLastSqlPos = pCxt->pSql; + if (TSDB_CODE_SUCCESS == code) { + code = insSetBlockInfo((SSubmitBlk*)(pDataBuf->pData), pDataBuf, numOfRows, &pCxt->msg); } - - dataBuf->numOfTables = 1; - pCxt->totalNum += numOfRows; - return TSDB_CODE_SUCCESS; + if (TSDB_CODE_SUCCESS == code) { + pDataBuf->numOfTables = 1; + pStmt->totalRowsNum += numOfRows; + pStmt->totalTbNum += 1; + TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT); + if (!pStmt->fileProcessing) { + taosCloseFile(&pStmt->fp); + } else { + parserDebug("0x%" PRIx64 " insert from csv. File is too large, do it in batches.", pCxt->pComCxt->requestId); + } + } + return code; } -static int32_t parseDataFromFile(SInsertParseContext* pCxt, int16_t tableNo, const SName* pTableName, SToken filePath, - STableDataBlocks* dataBuf) { +static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pFilePath, + STableDataBlocks* pDataBuf) { char filePathStr[TSDB_FILENAME_LEN] = {0}; - if (TK_NK_STRING == filePath.type) { - trimString(filePath.z, filePath.n, filePathStr, sizeof(filePathStr)); + if (TK_NK_STRING == pFilePath->type) { + trimString(pFilePath->z, pFilePath->n, filePathStr, sizeof(filePathStr)); } else { - strncpy(filePathStr, filePath.z, filePath.n); + strncpy(filePathStr, pFilePath->z, pFilePath->n); } - pCxt->pComCxt->csvCxt.fp = taosOpenFile(filePathStr, TD_FILE_READ | TD_FILE_STREAM); - if (NULL == pCxt->pComCxt->csvCxt.fp) { + pStmt->fp = taosOpenFile(filePathStr, TD_FILE_READ | TD_FILE_STREAM); + if (NULL == pStmt->fp) { return TAOS_SYSTEM_ERROR(errno); } - return parseDataFromFileAgain(pCxt, tableNo, pTableName, dataBuf); + return parseDataFromFileImpl(pCxt, pStmt, pDataBuf); } -static void destroyInsertParseContextForTable(SInsertParseContext* pCxt) { - if (!pCxt->pComCxt->needMultiParse) { - taosCloseFile(&pCxt->pComCxt->csvCxt.fp); +static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf, + SToken* pToken) { + NEXT_TOKEN(pStmt->pSql, *pToken); + if (0 == pToken->n || (TK_NK_STRING != pToken->type && TK_NK_ID != pToken->type)) { + return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", pToken->z); } - taosMemoryFreeClear(pCxt->pTableMeta); + return parseDataFromFile(pCxt, pStmt, pToken, pDataBuf); +} + +// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path +static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf) { + SToken token; + NEXT_TOKEN(pStmt->pSql, token); + switch (token.type) { + case TK_VALUES: + return parseValuesClause(pCxt, pStmt, pDataBuf, &token); + case TK_FILE: + return parseFileClause(pCxt, pStmt, pDataBuf, &token); + default: + break; + } + return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z); +} + +// input pStmt->pSql: +// 1. [(tag1_name, ...)] ... +// 2. VALUES ... | FILE ... +static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + STableDataBlocks* pDataBuf = NULL; + int32_t code = parseSchemaClauseBottom(pCxt, pStmt, &pDataBuf); + if (TSDB_CODE_SUCCESS == code) { + code = parseDataClause(pCxt, pStmt, pDataBuf); + } + return code; +} + +static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { destroyBoundColumnInfo(&pCxt->tags); - tdDestroySVCreateTbReq(&pCxt->createTblReq); + taosMemoryFreeClear(pStmt->pTableMeta); + tdDestroySVCreateTbReq(&pStmt->createTblReq); + pCxt->missCache = false; + pCxt->usingDuplicateTable = false; + pStmt->pBoundCols = NULL; + pStmt->usingTableProcessing = false; + pStmt->fileProcessing = false; +} + +// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ... +static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName) { + resetEnvPreTable(pCxt, pStmt); + int32_t code = parseSchemaClauseTop(pCxt, pStmt, pTbName); + if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { + code = parseInsertTableClauseBottom(pCxt, pStmt); + } + return code; +} + +static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName, + bool* pHasData) { + // no data in the sql string anymore. + if (0 == pTbName->n) { + if (0 != pTbName->type && '\0' != pStmt->pSql[0]) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid charactor in SQL", pTbName->z); + } + + if (0 == pStmt->totalRowsNum && (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) { + return buildInvalidOperationMsg(&pCxt->msg, "no data in sql"); + } + + *pHasData = false; + return TSDB_CODE_SUCCESS; + } + + if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT) && pStmt->totalTbNum > 0) { + return buildInvalidOperationMsg(&pCxt->msg, "single table allowed in one stmt"); + } + + if (TK_NK_QUESTION == pTbName->type) { + if (NULL == pCxt->pComCxt->pStmtCb) { + return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z); + } + + char* tbName = NULL; + int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName); + if (TSDB_CODE_SUCCESS == code) { + pTbName->z = tbName; + pTbName->n = strlen(tbName); + } else { + return code; + } + } + + *pHasData = true; + return TSDB_CODE_SUCCESS; +} + +static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + SParsedDataColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags)); + if (NULL == tags) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + memcpy(tags, &pCxt->tags, sizeof(pCxt->tags)); + + SStmtCallback* pStmtCb = pCxt->pComCxt->pStmtCb; + char tbFName[TSDB_TABLE_FNAME_LEN]; + tNameExtractFullName(&pStmt->targetTableName, tbFName); + int32_t code = (*pStmtCb->setInfoFn)(pStmtCb->pStmt, pStmt->pTableMeta, tags, tbFName, pStmt->usingTableProcessing, + pStmt->pVgroupsHashObj, pStmt->pTableBlockHashObj, pStmt->usingTableName.tname); + + memset(&pCxt->tags, 0, sizeof(pCxt->tags)); + pStmt->pVgroupsHashObj = NULL; + pStmt->pTableBlockHashObj = NULL; + return code; +} + +static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) { + return setStmtInfo(pCxt, pStmt); + } + + // merge according to vgId + int32_t code = TSDB_CODE_SUCCESS; + if (taosHashGetSize(pStmt->pTableBlockHashObj) > 0) { + code = insMergeTableDataBlocks(pStmt->pTableBlockHashObj, &pStmt->pVgDataBlocks); + } + if (TSDB_CODE_SUCCESS == code) { + code = insBuildOutput(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks); + } + return code; +} + +// tb_name +// [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)] +// [(field1_name, ...)] +// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path +// [...]; +static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + SToken token; + int32_t code = TSDB_CODE_SUCCESS; + bool hasData = true; + // for each table + while (TSDB_CODE_SUCCESS == code && hasData && !pCxt->missCache && !pStmt->fileProcessing) { + // pStmt->pSql -> tb_name ... + NEXT_TOKEN(pStmt->pSql, token); + code = checkTableClauseFirstToken(pCxt, pStmt, &token, &hasData); + if (TSDB_CODE_SUCCESS == code && hasData) { + code = parseInsertTableClause(pCxt, pStmt, &token); + } + } + + if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { + code = parseInsertBodyBottom(pCxt, pStmt); + } + return code; } static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); } -static void destroyInsertParseContext(SInsertParseContext* pCxt) { - destroyInsertParseContextForTable(pCxt); - taosHashCleanup(pCxt->pVgroupsHashObj); - taosHashCleanup(pCxt->pSubTableHashObj); - taosHashCleanup(pCxt->pTableNameHashObj); - taosHashCleanup(pCxt->pDbFNameHashObj); +static int32_t createVnodeModifOpStmt(SParseContext* pCxt, bool reentry, SNode** pOutput) { + SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); + if (NULL == pStmt) { + return TSDB_CODE_OUT_OF_MEMORY; + } - insDestroyBlockHashmap(pCxt->pTableBlockHashObj); - insDestroyBlockArrayList(pCxt->pVgDataBlocks); + if (pCxt->pStmtCb) { + TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT); + } + pStmt->pSql = pCxt->pSql; + pStmt->freeHashFunc = insDestroyBlockHashmap; + pStmt->freeArrayFunc = insDestroyBlockArrayList; + + if (!reentry) { + pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + pStmt->pTableBlockHashObj = + taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); + } + pStmt->pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK); + pStmt->pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK); + pStmt->pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK); + if ((!reentry && (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj)) || + NULL == pStmt->pSubTableHashObj || NULL == pStmt->pTableNameHashObj || NULL == pStmt->pDbFNameHashObj) { + nodesDestroyNode((SNode*)pStmt); + return TSDB_CODE_OUT_OF_MEMORY; + } + + taosHashSetFreeFp(pStmt->pSubTableHashObj, destroySubTableHashElem); + + *pOutput = (SNode*)pStmt; + return TSDB_CODE_SUCCESS; } -static int32_t parseTableName(SInsertParseContext* pCxt, SToken* pTbnameToken, SName* pName, char* pDbFName, - char* pTbFName) { - int32_t code = insCreateSName(pName, pTbnameToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg); - if (TSDB_CODE_SUCCESS == code) { - tNameExtractFullName(pName, pTbFName); - code = taosHashPut(pCxt->pTableNameHashObj, pTbFName, strlen(pTbFName), pName, sizeof(SName)); +static int32_t createInsertQuery(SParseContext* pCxt, SQuery** pOutput) { + SQuery* pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY); + if (NULL == pQuery) { + return TSDB_CODE_OUT_OF_MEMORY; } + + pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; + pQuery->haveResultSet = false; + pQuery->msgType = TDMT_VND_SUBMIT; + + int32_t code = createVnodeModifOpStmt(pCxt, false, &pQuery->pRoot); if (TSDB_CODE_SUCCESS == code) { - tNameGetFullDbName(pName, pDbFName); - code = taosHashPut(pCxt->pDbFNameHashObj, pDbFName, strlen(pDbFName), pDbFName, TSDB_DB_FNAME_LEN); + *pOutput = pQuery; + } else { + nodesDestroyNode((SNode*)pQuery); } return code; } -// tb_name -// [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)] -// [(field1_name, ...)] -// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path -// [...]; -static int32_t parseInsertBody(SInsertParseContext* pCxt) { - int32_t tbNum = 0; - SName name; - char tbFName[TSDB_TABLE_FNAME_LEN]; - char dbFName[TSDB_DB_FNAME_LEN]; - bool autoCreateTbl = false; - - // for each table - while (1) { - SToken sToken; - char* tbName = NULL; - - // pSql -> tb_name ... - NEXT_TOKEN(pCxt->pSql, sToken); - - // no data in the sql string anymore. - if (sToken.n == 0) { - if (sToken.type && pCxt->pSql[0]) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid charactor in SQL", sToken.z); - } - - if (0 == pCxt->totalNum && (!TSDB_QUERY_HAS_TYPE(pCxt->pOutput->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) && - !pCxt->pComCxt->needMultiParse) { - return buildInvalidOperationMsg(&pCxt->msg, "no data in sql"); - } - break; - } - - if (TSDB_QUERY_HAS_TYPE(pCxt->pOutput->insertType, TSDB_QUERY_TYPE_STMT_INSERT) && tbNum > 0) { - return buildInvalidOperationMsg(&pCxt->msg, "single table allowed in one stmt"); - } - - destroyInsertParseContextForTable(pCxt); - - if (TK_NK_QUESTION == sToken.type) { - if (pCxt->pStmtCb) { - CHECK_CODE((*pCxt->pStmtCb->getTbNameFn)(pCxt->pStmtCb->pStmt, &tbName)); - - sToken.z = tbName; - sToken.n = strlen(tbName); - } else { - return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", sToken.z); - } - } - - SToken tbnameToken = sToken; - NEXT_TOKEN(pCxt->pSql, sToken); - - if (!pCxt->pComCxt->async || TK_USING == sToken.type) { - CHECK_CODE(parseTableName(pCxt, &tbnameToken, &name, dbFName, tbFName)); - } - - bool existedUsing = false; - // USING clause - if (TK_USING == sToken.type) { - existedUsing = true; - CHECK_CODE(parseUsingClause(pCxt, tbNum, &name, tbFName)); - NEXT_TOKEN(pCxt->pSql, sToken); - autoCreateTbl = true; - } - - char* pBoundColsStart = NULL; - if (TK_NK_LP == sToken.type) { - // pSql -> field1_name, ...) - pBoundColsStart = pCxt->pSql; - CHECK_CODE(ignoreBoundColumns(pCxt)); - NEXT_TOKEN(pCxt->pSql, sToken); - } - - if (TK_USING == sToken.type) { - if (pCxt->pComCxt->async) { - CHECK_CODE(parseTableName(pCxt, &tbnameToken, &name, dbFName, tbFName)); - } - CHECK_CODE(parseUsingClause(pCxt, tbNum, &name, tbFName)); - NEXT_TOKEN(pCxt->pSql, sToken); - autoCreateTbl = true; - } else if (!existedUsing) { - CHECK_CODE(getTableMeta(pCxt, tbNum, &name)); - if (TSDB_SUPER_TABLE == pCxt->pTableMeta->tableType) { - return buildInvalidOperationMsg(&pCxt->msg, "insert data into super table is not supported"); - } - } - - STableDataBlocks* dataBuf = NULL; - if (pCxt->pComCxt->async) { - CHECK_CODE(insGetDataBlockFromList(pCxt->pTableBlockHashObj, &pCxt->pTableMeta->uid, - sizeof(pCxt->pTableMeta->uid), TSDB_DEFAULT_PAYLOAD_SIZE, sizeof(SSubmitBlk), - getTableInfo(pCxt->pTableMeta).rowSize, pCxt->pTableMeta, &dataBuf, NULL, - &pCxt->createTblReq)); - } else { - CHECK_CODE(insGetDataBlockFromList(pCxt->pTableBlockHashObj, tbFName, strlen(tbFName), TSDB_DEFAULT_PAYLOAD_SIZE, - sizeof(SSubmitBlk), getTableInfo(pCxt->pTableMeta).rowSize, pCxt->pTableMeta, - &dataBuf, NULL, &pCxt->createTblReq)); - } - - if (NULL != pBoundColsStart) { - char* pCurrPos = pCxt->pSql; - pCxt->pSql = pBoundColsStart; - CHECK_CODE(parseBoundColumns(pCxt, &dataBuf->boundColumnInfo, getTableColumnSchema(pCxt->pTableMeta))); - pCxt->pSql = pCurrPos; - } - - if (TK_VALUES == sToken.type) { - // pSql -> (field1_value, ...) [(field1_value2, ...) ...] - CHECK_CODE(parseValuesClause(pCxt, dataBuf)); - TSDB_QUERY_SET_TYPE(pCxt->pOutput->insertType, TSDB_QUERY_TYPE_INSERT); - - tbNum++; - continue; - } - - // FILE csv_file_path - if (TK_FILE == sToken.type) { - // pSql -> csv_file_path - NEXT_TOKEN(pCxt->pSql, sToken); - if (0 == sToken.n || (TK_NK_STRING != sToken.type && TK_NK_ID != sToken.type)) { - return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", sToken.z); - } - CHECK_CODE(parseDataFromFile(pCxt, tbNum, &name, sToken, dataBuf)); - pCxt->pOutput->insertType = TSDB_QUERY_TYPE_FILE_INSERT; - - tbNum++; - if (!pCxt->pComCxt->needMultiParse) { - continue; - } else { - parserDebug("0x%" PRIx64 " insert from csv. File is too large, do it in batches.", pCxt->pComCxt->requestId); - break; - } - } - - return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", sToken.z); +static int32_t checkAuthFromMetaData(const SArray* pUsers) { + if (1 != taosArrayGetSize(pUsers)) { + return TSDB_CODE_FAILED; } - parserDebug("0x%" PRIx64 " insert input rows: %d", pCxt->pComCxt->requestId, pCxt->totalNum); - - if (TSDB_QUERY_HAS_TYPE(pCxt->pOutput->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) { - SParsedDataColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags)); - if (NULL == tags) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - memcpy(tags, &pCxt->tags, sizeof(pCxt->tags)); - (*pCxt->pStmtCb->setInfoFn)(pCxt->pStmtCb->pStmt, pCxt->pTableMeta, tags, tbFName, autoCreateTbl, - pCxt->pVgroupsHashObj, pCxt->pTableBlockHashObj, pCxt->sTableName); - - memset(&pCxt->tags, 0, sizeof(pCxt->tags)); - pCxt->pVgroupsHashObj = NULL; - pCxt->pTableBlockHashObj = NULL; - - return TSDB_CODE_SUCCESS; + SMetaRes* pRes = taosArrayGet(pUsers, 0); + if (TSDB_CODE_SUCCESS == pRes->code) { + return (*(bool*)pRes->pRes) ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED; } - - // merge according to vgId - if (taosHashGetSize(pCxt->pTableBlockHashObj) > 0) { - CHECK_CODE(insMergeTableDataBlocks(pCxt->pTableBlockHashObj, &pCxt->pVgDataBlocks)); - } - return insBuildOutput(pCxt); + return pRes->code; } -static int32_t parseInsertBodyAgain(SInsertParseContext* pCxt) { - STableDataBlocks* dataBuf = NULL; - CHECK_CODE(getTableMeta(pCxt, pCxt->pComCxt->csvCxt.tableNo, &pCxt->pComCxt->csvCxt.tableName)); - CHECK_CODE(insGetDataBlockFromList(pCxt->pTableBlockHashObj, &pCxt->pTableMeta->uid, sizeof(pCxt->pTableMeta->uid), - TSDB_DEFAULT_PAYLOAD_SIZE, sizeof(SSubmitBlk), - getTableInfo(pCxt->pTableMeta).rowSize, pCxt->pTableMeta, &dataBuf, NULL, - &pCxt->createTblReq)); - CHECK_CODE(parseDataFromFileAgain(pCxt, pCxt->pComCxt->csvCxt.tableNo, &pCxt->pComCxt->csvCxt.tableName, dataBuf)); - if (taosEOFFile(pCxt->pComCxt->csvCxt.fp)) { - CHECK_CODE(parseInsertBody(pCxt)); - pCxt->pComCxt->needMultiParse = false; - return TSDB_CODE_SUCCESS; +static int32_t getTableMetaFromMetaData(const SArray* pTables, STableMeta** pMeta) { + if (1 != taosArrayGetSize(pTables)) { + return TSDB_CODE_FAILED; } - parserDebug("0x%" PRIx64 " insert again input rows: %d", pCxt->pComCxt->requestId, pCxt->totalNum); - // merge according to vgId - if (taosHashGetSize(pCxt->pTableBlockHashObj) > 0) { - CHECK_CODE(insMergeTableDataBlocks(pCxt->pTableBlockHashObj, &pCxt->pVgDataBlocks)); + SMetaRes* pRes = taosArrayGet(pTables, 0); + if (TSDB_CODE_SUCCESS == pRes->code) { + *pMeta = tableMetaDup((const STableMeta*)pRes->pRes); + if (NULL == *pMeta) { + return TSDB_CODE_OUT_OF_MEMORY; + } } - return insBuildOutput(pCxt); + return pRes->code; +} + +static int32_t getTableVgroupFromMetaData(const SArray* pTables, SVnodeModifOpStmt* pStmt, bool isStb) { + if (1 != taosArrayGetSize(pTables)) { + return TSDB_CODE_FAILED; + } + + SMetaRes* pRes = taosArrayGet(pTables, 0); + if (TSDB_CODE_SUCCESS != pRes->code) { + return pRes->code; + } + + SVgroupInfo* pVg = pRes->pRes; + if (isStb) { + pStmt->pTableMeta->vgId = pVg->vgId; + } + return taosHashPut(pStmt->pVgroupsHashObj, (const char*)&pVg->vgId, sizeof(pVg->vgId), (char*)pVg, + sizeof(SVgroupInfo)); +} + +static int32_t getTableSchemaFromMetaData(const SMetaData* pMetaData, SVnodeModifOpStmt* pStmt, bool isStb) { + int32_t code = checkAuthFromMetaData(pMetaData->pUser); + if (TSDB_CODE_SUCCESS == code) { + code = getTableMetaFromMetaData(pMetaData->pTableMeta, &pStmt->pTableMeta); + } + if (TSDB_CODE_SUCCESS == code) { + code = getTableVgroupFromMetaData(pMetaData->pTableHash, pStmt, isStb); + } + return code; +} + +static void destoryTablesReq(void* p) { + STablesReq* pRes = (STablesReq*)p; + taosArrayDestroy(pRes->pTables); +} + +static void clearCatalogReq(SCatalogReq* pCatalogReq) { + if (NULL == pCatalogReq) { + return; + } + + taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq); + pCatalogReq->pTableMeta = NULL; + taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq); + pCatalogReq->pTableHash = NULL; + taosArrayDestroy(pCatalogReq->pUser); + pCatalogReq->pUser = NULL; +} + +static int32_t setVnodeModifOpStmt(SParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData, + SVnodeModifOpStmt* pStmt) { + clearCatalogReq(pCatalogReq); + + if (pStmt->usingTableProcessing) { + return getTableSchemaFromMetaData(pMetaData, pStmt, true); + } + return getTableSchemaFromMetaData(pMetaData, pStmt, false); +} + +static int32_t resetVnodeModifOpStmt(SParseContext* pCxt, SQuery* pQuery) { + nodesDestroyNode(pQuery->pRoot); + + int32_t code = createVnodeModifOpStmt(pCxt, true, &pQuery->pRoot); + if (TSDB_CODE_SUCCESS == code) { + SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)pQuery->pRoot; + + (*pCxt->pStmtCb->getExecInfoFn)(pCxt->pStmtCb->pStmt, &pStmt->pVgroupsHashObj, &pStmt->pTableBlockHashObj); + if (NULL == pStmt->pVgroupsHashObj) { + pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + } + if (NULL == pStmt->pTableBlockHashObj) { + pStmt->pTableBlockHashObj = + taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); + } + if (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + } + + return code; +} + +static int32_t initInsertQuery(SParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData, + SQuery** pQuery) { + if (NULL == *pQuery) { + return createInsertQuery(pCxt, pQuery); + } + + if (NULL != pCxt->pStmtCb) { + return resetVnodeModifOpStmt(pCxt, *pQuery); + } + + SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)(*pQuery)->pRoot; + + if (!pStmt->fileProcessing) { + return setVnodeModifOpStmt(pCxt, pCatalogReq, pMetaData, pStmt); + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t setRefreshMate(SQuery* pQuery) { + SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)pQuery->pRoot; + SName* pTable = taosHashIterate(pStmt->pTableNameHashObj, NULL); + while (NULL != pTable) { + taosArrayPush(pQuery->pTableList, pTable); + pTable = taosHashIterate(pStmt->pTableNameHashObj, pTable); + } + + char* pDb = taosHashIterate(pStmt->pDbFNameHashObj, NULL); + while (NULL != pDb) { + taosArrayPush(pQuery->pDbList, pDb); + pDb = taosHashIterate(pStmt->pDbFNameHashObj, pDb); + } + + return TSDB_CODE_SUCCESS; } // INSERT INTO // tb_name -// [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)] +// [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] // [(field1_name, ...)] // VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path // [...]; -int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery, SParseMetaCache* pMetaCache) { - SInsertParseContext context = { - .pComCxt = pContext, - .pSql = pContext->needMultiParse ? (char*)pContext->csvCxt.pLastSqlPos : (char*)pContext->pSql, - .msg = {.buf = pContext->pMsg, .len = pContext->msgLen}, - .pTableMeta = NULL, - .createTblReq = {0}, - .pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK), - .pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK), - .pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK), - .totalNum = 0, - .pOutput = (SVnodeModifOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT), - .pStmtCb = pContext->pStmtCb, - .pMetaCache = pMetaCache, - .memElapsed = 0, - .parRowElapsed = 0}; - - if (pContext->pStmtCb && *pQuery) { - (*pContext->pStmtCb->getExecInfoFn)(pContext->pStmtCb->pStmt, &context.pVgroupsHashObj, - &context.pTableBlockHashObj); - if (NULL == context.pVgroupsHashObj) { - context.pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); - } - if (NULL == context.pTableBlockHashObj) { - context.pTableBlockHashObj = - taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); - } - } else { - context.pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); - context.pTableBlockHashObj = - taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); +static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + int32_t code = skipInsertInto(&pStmt->pSql, &pCxt->msg); + if (TSDB_CODE_SUCCESS == code) { + code = parseInsertBody(pCxt, pStmt); } - - if (NULL == context.pVgroupsHashObj || NULL == context.pTableBlockHashObj || NULL == context.pSubTableHashObj || - NULL == context.pTableNameHashObj || NULL == context.pDbFNameHashObj || NULL == context.pOutput) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - taosHashSetFreeFp(context.pSubTableHashObj, destroySubTableHashElem); - - if (pContext->pStmtCb) { - TSDB_QUERY_SET_TYPE(context.pOutput->insertType, TSDB_QUERY_TYPE_STMT_INSERT); - } - - if (NULL == *pQuery) { - *pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY); - if (NULL == *pQuery) { - return TSDB_CODE_OUT_OF_MEMORY; - } - } else { - nodesDestroyNode((*pQuery)->pRoot); - } - - (*pQuery)->execMode = QUERY_EXEC_MODE_SCHEDULE; - (*pQuery)->haveResultSet = false; - (*pQuery)->msgType = TDMT_VND_SUBMIT; - (*pQuery)->pRoot = (SNode*)context.pOutput; - - if (NULL == (*pQuery)->pTableList) { - (*pQuery)->pTableList = taosArrayInit(taosHashGetSize(context.pTableNameHashObj), sizeof(SName)); - if (NULL == (*pQuery)->pTableList) { - return TSDB_CODE_OUT_OF_MEMORY; - } - } - - if (NULL == (*pQuery)->pDbList) { - (*pQuery)->pDbList = taosArrayInit(taosHashGetSize(context.pDbFNameHashObj), TSDB_DB_FNAME_LEN); - if (NULL == (*pQuery)->pDbList) { - return TSDB_CODE_OUT_OF_MEMORY; - } - } - - int32_t code = TSDB_CODE_SUCCESS; - if (!context.pComCxt->needMultiParse) { - code = skipInsertInto(&context.pSql, &context.msg); - if (TSDB_CODE_SUCCESS == code) { - code = parseInsertBody(&context); - } - } else { - code = parseInsertBodyAgain(&context); - } - - if (TSDB_CODE_SUCCESS == code || NEED_CLIENT_HANDLE_ERROR(code)) { - SName* pTable = taosHashIterate(context.pTableNameHashObj, NULL); - while (NULL != pTable) { - taosArrayPush((*pQuery)->pTableList, pTable); - pTable = taosHashIterate(context.pTableNameHashObj, pTable); - } - - char* pDb = taosHashIterate(context.pDbFNameHashObj, NULL); - while (NULL != pDb) { - taosArrayPush((*pQuery)->pDbList, pDb); - pDb = taosHashIterate(context.pDbFNameHashObj, pDb); - } - } - if (pContext->pStmtCb) { - context.pVgroupsHashObj = NULL; - context.pTableBlockHashObj = NULL; - } - destroyInsertParseContext(&context); return code; } -// pSql -> (field1_value, ...) [(field1_value2, ...) ...] -static int32_t skipValuesClause(SInsertParseSyntaxCxt* pCxt) { - int32_t numOfRows = 0; - SToken sToken; - while (1) { - int32_t index = 0; - NEXT_TOKEN_KEEP_SQL(pCxt->pSql, sToken, index); - if (TK_NK_LP != sToken.type) { - break; - } - pCxt->pSql += index; - - CHECK_CODE(skipParentheses(pCxt)); - ++numOfRows; +static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + STableDataBlocks* pDataBuf = NULL; + int32_t code = getTableDataBlocks(pCxt, pStmt, &pDataBuf); + if (TSDB_CODE_SUCCESS == code) { + code = parseDataFromFileImpl(pCxt, pStmt, pDataBuf); } - if (0 == numOfRows) { - return buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL); - } - return TSDB_CODE_SUCCESS; -} -static int32_t skipTagsClause(SInsertParseSyntaxCxt* pCxt) { return skipParentheses(pCxt); } - -static int32_t skipTableOptions(SInsertParseSyntaxCxt* pCxt) { - do { - int32_t index = 0; - SToken sToken; - NEXT_TOKEN_KEEP_SQL(pCxt->pSql, sToken, index); - if (TK_TTL == sToken.type || TK_COMMENT == sToken.type) { - pCxt->pSql += index; - NEXT_TOKEN_WITH_PREV(pCxt->pSql, sToken); + if (TSDB_CODE_SUCCESS == code) { + if (pStmt->fileProcessing) { + code = parseInsertBodyBottom(pCxt, pStmt); } else { - break; + code = parseInsertBody(pCxt, pStmt); } - } while (1); - return TSDB_CODE_SUCCESS; -} - -// pSql -> [(tag1_name, ...)] TAGS (tag1_value, ...) -static int32_t skipUsingClause(SInsertParseSyntaxCxt* pCxt) { - SToken sToken; - NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_NK_LP == sToken.type) { - CHECK_CODE(skipBoundColumns(pCxt)); - NEXT_TOKEN(pCxt->pSql, sToken); } - if (TK_TAGS != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", sToken.z); - } - // pSql -> (tag1_value, ...) - NEXT_TOKEN(pCxt->pSql, sToken); - if (TK_NK_LP != sToken.type) { - return buildSyntaxErrMsg(&pCxt->msg, "( is expected", sToken.z); - } - CHECK_CODE(skipTagsClause(pCxt)); - CHECK_CODE(skipTableOptions(pCxt)); - - return TSDB_CODE_SUCCESS; + return code; } -static int32_t collectTableMetaKey(SInsertParseSyntaxCxt* pCxt, bool isStable, int32_t tableNo, SToken* pTbToken) { - SName name = {0}; - CHECK_CODE(insCreateSName(&name, pTbToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg)); - CHECK_CODE(reserveTableMetaInCacheForInsert(&name, isStable ? CATALOG_REQ_TYPE_META : CATALOG_REQ_TYPE_BOTH, tableNo, - pCxt->pMetaCache)); - return TSDB_CODE_SUCCESS; -} - -static int32_t checkTableName(const char* pTableName, SMsgBuf* pMsgBuf) { - if (NULL != strchr(pTableName, '.')) { - return generateSyntaxErrMsgExt(pMsgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, "The table name cannot contain '.'"); - } - return TSDB_CODE_SUCCESS; -} - -static int32_t collectAutoCreateTableMetaKey(SInsertParseSyntaxCxt* pCxt, int32_t tableNo, SToken* pTbToken) { - SName name = {0}; - CHECK_CODE(insCreateSName(&name, pTbToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg)); - CHECK_CODE(checkTableName(name.tname, &pCxt->msg)); - CHECK_CODE(reserveTableMetaInCacheForInsert(&name, CATALOG_REQ_TYPE_VGROUP, tableNo, pCxt->pMetaCache)); - return TSDB_CODE_SUCCESS; -} - -static int32_t parseInsertBodySyntax(SInsertParseSyntaxCxt* pCxt) { - bool hasData = false; - int32_t tableNo = 0; - // for each table - while (1) { - SToken sToken; - - // pSql -> tb_name ... - NEXT_TOKEN(pCxt->pSql, sToken); - - // no data in the sql string anymore. - if (sToken.n == 0) { - if (sToken.type && pCxt->pSql[0]) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid charactor in SQL", sToken.z); - } - - if (!hasData) { - return buildInvalidOperationMsg(&pCxt->msg, "no data in sql"); - } - break; - } - - hasData = false; - - SToken tbnameToken = sToken; - NEXT_TOKEN(pCxt->pSql, sToken); - - bool existedUsing = false; - // USING clause - if (TK_USING == sToken.type) { - existedUsing = true; - CHECK_CODE(collectAutoCreateTableMetaKey(pCxt, tableNo, &tbnameToken)); - NEXT_TOKEN(pCxt->pSql, sToken); - CHECK_CODE(collectTableMetaKey(pCxt, true, tableNo, &sToken)); - CHECK_CODE(skipUsingClause(pCxt)); - NEXT_TOKEN(pCxt->pSql, sToken); - } - - if (TK_NK_LP == sToken.type) { - // pSql -> field1_name, ...) - CHECK_CODE(skipBoundColumns(pCxt)); - NEXT_TOKEN(pCxt->pSql, sToken); - } - - if (TK_USING == sToken.type && !existedUsing) { - existedUsing = true; - CHECK_CODE(collectAutoCreateTableMetaKey(pCxt, tableNo, &tbnameToken)); - NEXT_TOKEN(pCxt->pSql, sToken); - CHECK_CODE(collectTableMetaKey(pCxt, true, tableNo, &sToken)); - CHECK_CODE(skipUsingClause(pCxt)); - NEXT_TOKEN(pCxt->pSql, sToken); - } else if (!existedUsing) { - CHECK_CODE(collectTableMetaKey(pCxt, false, tableNo, &tbnameToken)); - } - - ++tableNo; - - if (TK_VALUES == sToken.type) { - // pSql -> (field1_value, ...) [(field1_value2, ...) ...] - CHECK_CODE(skipValuesClause(pCxt)); - hasData = true; - continue; - } - - // FILE csv_file_path - if (TK_FILE == sToken.type) { - // pSql -> csv_file_path - NEXT_TOKEN(pCxt->pSql, sToken); - if (0 == sToken.n || (TK_NK_STRING != sToken.type && TK_NK_ID != sToken.type)) { - return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", sToken.z); - } - hasData = true; - continue; - } - - return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", sToken.z); - } - - return TSDB_CODE_SUCCESS; -} - -int32_t parseInsertSyntax(SParseContext* pContext, SQuery** pQuery, SParseMetaCache* pMetaCache) { - SInsertParseSyntaxCxt context = {.pComCxt = pContext, - .pSql = (char*)pContext->pSql, - .msg = {.buf = pContext->pMsg, .len = pContext->msgLen}, - .pMetaCache = pMetaCache}; - int32_t code = skipInsertInto(&context.pSql, &context.msg); +static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + int32_t code = parseInsertTableClauseBottom(pCxt, pStmt); if (TSDB_CODE_SUCCESS == code) { - code = parseInsertBodySyntax(&context); - } - if (TSDB_CODE_SUCCESS == code) { - *pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY); - if (NULL == *pQuery) { - return TSDB_CODE_OUT_OF_MEMORY; - } + code = parseInsertBody(pCxt, pStmt); } return code; } + +static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { + if (pStmt->pSql == pCxt->pComCxt->pSql || NULL != pCxt->pComCxt->pStmtCb) { + return parseInsertSqlFromStart(pCxt, pStmt); + } + + if (pStmt->fileProcessing) { + return parseInsertSqlFromCsv(pCxt, pStmt); + } + + return parseInsertSqlFromTable(pCxt, pStmt); +} + +static int32_t buildInsertTableReq(SName* pName, SArray** pTables) { + *pTables = taosArrayInit(1, sizeof(SName)); + if (NULL == *pTables) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + taosArrayPush(*pTables, pName); + return TSDB_CODE_SUCCESS; +} + +static int32_t buildInsertDbReq(SName* pName, SArray** pDbs) { + if (NULL == *pDbs) { + *pDbs = taosArrayInit(1, sizeof(STablesReq)); + if (NULL == *pDbs) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } + + STablesReq req = {0}; + tNameGetFullDbName(pName, req.dbFName); + buildInsertTableReq(pName, &req.pTables); + taosArrayPush(*pDbs, &req); + + return TSDB_CODE_SUCCESS; +} + +static int32_t buildInsertUserAuthReq(const char* pUser, SName* pName, SArray** pUserAuth) { + *pUserAuth = taosArrayInit(1, sizeof(SUserAuthInfo)); + if (NULL == *pUserAuth) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SUserAuthInfo userAuth = {.type = AUTH_TYPE_WRITE}; + snprintf(userAuth.user, sizeof(userAuth.user), "%s", pUser); + tNameGetFullDbName(pName, userAuth.dbFName); + taosArrayPush(*pUserAuth, &userAuth); + + return TSDB_CODE_SUCCESS; +} + +static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SCatalogReq* pCatalogReq) { + int32_t code = buildInsertUserAuthReq(pCxt->pComCxt->pUser, &pStmt->targetTableName, &pCatalogReq->pUser); + if (TSDB_CODE_SUCCESS == code) { + if (0 == pStmt->usingTableName.type) { + code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableMeta); + } else { + code = buildInsertDbReq(&pStmt->usingTableName, &pCatalogReq->pTableMeta); + } + } + if (TSDB_CODE_SUCCESS == code) { + code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableHash); + } + return code; +} + +static int32_t setNextStageInfo(SInsertParseContext* pCxt, SQuery* pQuery, SCatalogReq* pCatalogReq) { + if (pCxt->missCache) { + parserDebug("0x%" PRIx64 " %d rows have been inserted before cache miss", pCxt->pComCxt->requestId, + ((SVnodeModifOpStmt*)pQuery->pRoot)->totalRowsNum); + + pQuery->execStage = QUERY_EXEC_STAGE_PARSE; + return buildInsertCatalogReq(pCxt, (SVnodeModifOpStmt*)pQuery->pRoot, pCatalogReq); + } + + parserDebug("0x%" PRIx64 " %d rows have been inserted", pCxt->pComCxt->requestId, + ((SVnodeModifOpStmt*)pQuery->pRoot)->totalRowsNum); + + pQuery->execStage = QUERY_EXEC_STAGE_SCHEDULE; + return TSDB_CODE_SUCCESS; +} + +int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) { + SInsertParseContext context = { + .pComCxt = pCxt, + .msg = {.buf = pCxt->pMsg, .len = pCxt->msgLen}, + .missCache = false, + .usingDuplicateTable = false, + }; + + int32_t code = initInsertQuery(pCxt, pCatalogReq, pMetaData, pQuery); + if (TSDB_CODE_SUCCESS == code) { + code = parseInsertSqlImpl(&context, (SVnodeModifOpStmt*)(*pQuery)->pRoot); + } + if (TSDB_CODE_SUCCESS == code) { + code = setNextStageInfo(&context, *pQuery, pCatalogReq); + } + if ((TSDB_CODE_SUCCESS == code || NEED_CLIENT_HANDLE_ERROR(code)) && + QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) { + code = setRefreshMate(*pQuery); + } + destroyBoundColumnInfo(&context.tags); + return code; +} diff --git a/source/libs/parser/src/parInsertStmt.c b/source/libs/parser/src/parInsertStmt.c index f85ceccf6e..9a5f349d8f 100644 --- a/source/libs/parser/src/parInsertStmt.c +++ b/source/libs/parser/src/parInsertStmt.c @@ -30,23 +30,17 @@ typedef struct SKvParam { } SKvParam; int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash) { - SVnodeModifOpStmt* modifyNode = (SVnodeModifOpStmt*)pQuery->pRoot; - int32_t code = 0; - SInsertParseContext insertCtx = { - .pVgroupsHashObj = pVgHash, - .pTableBlockHashObj = pBlockHash, - .pOutput = (SVnodeModifOpStmt*)pQuery->pRoot, - }; - + int32_t code = TSDB_CODE_SUCCESS; + SArray* pVgDataBlocks = NULL; // merge according to vgId - if (taosHashGetSize(insertCtx.pTableBlockHashObj) > 0) { - CHECK_CODE(insMergeTableDataBlocks(insertCtx.pTableBlockHashObj, &insertCtx.pVgDataBlocks)); + if (taosHashGetSize(pBlockHash) > 0) { + code = insMergeTableDataBlocks(pBlockHash, &pVgDataBlocks); } - - CHECK_CODE(insBuildOutput(&insertCtx)); - - insDestroyBlockArrayList(insertCtx.pVgDataBlocks); - return TSDB_CODE_SUCCESS; + if (TSDB_CODE_SUCCESS == code) { + code = insBuildOutput(pVgHash, pVgDataBlocks, &((SVnodeModifOpStmt*)pQuery->pRoot)->pDataBlocks); + } + insDestroyBlockArrayList(pVgDataBlocks); + return code; } int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const char* sTableName, char* tName, @@ -222,11 +216,7 @@ int32_t qBindStmtColsValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, in } SSubmitBlk* pBlocks = (SSubmitBlk*)(pDataBlock->pData); - if (TSDB_CODE_SUCCESS != insSetBlockInfo(pBlocks, pDataBlock, bind->num)) { - return buildInvalidOperationMsg(&pBuf, "too many rows in sql, total number of rows should be less than INT32_MAX"); - } - - return TSDB_CODE_SUCCESS; + return insSetBlockInfo(pBlocks, pDataBlock, bind->num, &pBuf); } int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen, int32_t colIdx, @@ -308,10 +298,7 @@ int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBu pDataBlock->size += extendedRowSize * bind->num; SSubmitBlk* pBlocks = (SSubmitBlk*)(pDataBlock->pData); - if (TSDB_CODE_SUCCESS != insSetBlockInfo(pBlocks, pDataBlock, bind->num)) { - return buildInvalidOperationMsg(&pBuf, - "too many rows in sql, total number of rows should be less than INT32_MAX"); - } + CHECK_CODE(insSetBlockInfo(pBlocks, pDataBlock, bind->num, &pBuf)); } return TSDB_CODE_SUCCESS; diff --git a/source/libs/parser/src/parInsertUtil.c b/source/libs/parser/src/parInsertUtil.c index 570a6f9859..bc09163753 100644 --- a/source/libs/parser/src/parInsertUtil.c +++ b/source/libs/parser/src/parInsertUtil.c @@ -110,18 +110,17 @@ void insGetSTSRowAppendInfo(uint8_t rowType, SParsedDataColInfo* spd, col_id_t i } } -int32_t insSetBlockInfo(SSubmitBlk* pBlocks, STableDataBlocks* dataBuf, int32_t numOfRows) { +int32_t insSetBlockInfo(SSubmitBlk* pBlocks, STableDataBlocks* dataBuf, int32_t numOfRows, SMsgBuf* pMsg) { pBlocks->suid = (TSDB_NORMAL_TABLE == dataBuf->pTableMeta->tableType ? 0 : dataBuf->pTableMeta->suid); pBlocks->uid = dataBuf->pTableMeta->uid; pBlocks->sversion = dataBuf->pTableMeta->sversion; pBlocks->schemaLen = dataBuf->createTbReqLen; if (pBlocks->numOfRows + numOfRows >= INT32_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } else { - pBlocks->numOfRows += numOfRows; - return TSDB_CODE_SUCCESS; + return buildInvalidOperationMsg(pMsg, "too many rows in sql, total number of rows should be less than INT32_MAX"); } + pBlocks->numOfRows += numOfRows; + return TSDB_CODE_SUCCESS; } void insSetBoundColumnInfo(SParsedDataColInfo* pColList, SSchema* pSchema, col_id_t numOfCols) { @@ -271,12 +270,8 @@ void insDestroyDataBlock(STableDataBlocks* pDataBlock) { } taosMemoryFreeClear(pDataBlock->pData); - // if (!pDataBlock->cloned) { - // free the refcount for metermeta taosMemoryFreeClear(pDataBlock->pTableMeta); - destroyBoundColumnInfo(&pDataBlock->boundColumnInfo); - // } taosMemoryFreeClear(pDataBlock); } @@ -312,20 +307,6 @@ int32_t insGetDataBlockFromList(SHashObj* pHashList, void* id, int32_t idLen, in return TSDB_CODE_SUCCESS; } -#if 0 -static int32_t getRowExpandSize(STableMeta* pTableMeta) { - int32_t result = TD_ROW_HEAD_LEN - sizeof(TSKEY); - int32_t columns = getNumOfColumns(pTableMeta); - SSchema* pSchema = getTableColumnSchema(pTableMeta); - for (int32_t i = 0; i < columns; ++i) { - if (IS_VAR_DATA_TYPE((pSchema + i)->type)) { - result += TYPE_BYTES[TSDB_DATA_TYPE_BINARY]; - } - } - result += (int32_t)TD_BITMAP_BYTES(columns - 1); - return result; -} -#endif void insDestroyBlockArrayList(SArray* pDataBlockList) { if (pDataBlockList == NULL) { @@ -357,51 +338,6 @@ void insDestroyBlockHashmap(SHashObj* pDataBlockHash) { taosHashCleanup(pDataBlockHash); } -#if 0 -// data block is disordered, sort it in ascending order -void sortRemoveDataBlockDupRowsRaw(STableDataBlocks* dataBuf) { - SSubmitBlk* pBlocks = (SSubmitBlk*)dataBuf->pData; - - // size is less than the total size, since duplicated rows may be removed yet. - assert(pBlocks->numOfRows * dataBuf->rowSize + sizeof(SSubmitBlk) == dataBuf->size); - - if (!dataBuf->ordered) { - char* pBlockData = pBlocks->data; - - // todo. qsort is unstable, if timestamp is same, should get the last one - taosSort(pBlockData, pBlocks->numOfRows, dataBuf->rowSize, rowDataCompar); - - int32_t i = 0; - int32_t j = 1; - - // delete rows with timestamp conflicts - while (j < pBlocks->numOfRows) { - TSKEY ti = *(TSKEY*)(pBlockData + dataBuf->rowSize * i); - TSKEY tj = *(TSKEY*)(pBlockData + dataBuf->rowSize * j); - - if (ti == tj) { - ++j; - continue; - } - - int32_t nextPos = (++i); - if (nextPos != j) { - memmove(pBlockData + dataBuf->rowSize * nextPos, pBlockData + dataBuf->rowSize * j, dataBuf->rowSize); - } - - ++j; - } - - dataBuf->ordered = true; - - pBlocks->numOfRows = i + 1; - dataBuf->size = sizeof(SSubmitBlk) + dataBuf->rowSize * pBlocks->numOfRows; - } - - dataBuf->prevTS = INT64_MIN; -} -#endif - // data block is disordered, sort it in ascending order static int sortRemoveDataBlockDupRows(STableDataBlocks* dataBuf, SBlockKeyInfo* pBlkKeyInfo) { SSubmitBlk* pBlocks = (SSubmitBlk*)dataBuf->pData; @@ -896,6 +832,10 @@ int32_t insCreateSName(SName* pName, SToken* pTableName, int32_t acctId, const c } } + if (NULL != strchr(pName->tname, '.')) { + code = generateSyntaxErrMsgExt(pMsgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, "The table name cannot contain '.'"); + } + return code; } @@ -994,24 +934,24 @@ static void buildMsgHeader(STableDataBlocks* src, SVgDataBlocks* blocks) { } } -int32_t insBuildOutput(SInsertParseContext* pCxt) { - size_t numOfVg = taosArrayGetSize(pCxt->pVgDataBlocks); - pCxt->pOutput->pDataBlocks = taosArrayInit(numOfVg, POINTER_BYTES); - if (NULL == pCxt->pOutput->pDataBlocks) { +int32_t insBuildOutput(SHashObj* pVgroupsHashObj, SArray* pVgDataBlocks, SArray** pDataBlocks) { + size_t numOfVg = taosArrayGetSize(pVgDataBlocks); + *pDataBlocks = taosArrayInit(numOfVg, POINTER_BYTES); + if (NULL == *pDataBlocks) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } for (size_t i = 0; i < numOfVg; ++i) { - STableDataBlocks* src = taosArrayGetP(pCxt->pVgDataBlocks, i); + STableDataBlocks* src = taosArrayGetP(pVgDataBlocks, i); SVgDataBlocks* dst = taosMemoryCalloc(1, sizeof(SVgDataBlocks)); if (NULL == dst) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } - taosHashGetDup(pCxt->pVgroupsHashObj, (const char*)&src->vgId, sizeof(src->vgId), &dst->vg); + taosHashGetDup(pVgroupsHashObj, (const char*)&src->vgId, sizeof(src->vgId), &dst->vg); dst->numOfTables = src->numOfTables; dst->size = src->size; TSWAP(dst->pData, src->pData); buildMsgHeader(src, dst); - taosArrayPush(pCxt->pOutput->pDataBlocks, &dst); + taosArrayPush(*pDataBlocks, &dst); } return TSDB_CODE_SUCCESS; } diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index d98d513d5d..466c6edd24 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -612,62 +612,7 @@ static int32_t buildUdfReq(SHashObj* pUdfHash, SArray** pUdf) { return TSDB_CODE_SUCCESS; } -static int32_t buildCatalogReqForInsert(SParseContext* pCxt, const SParseMetaCache* pMetaCache, - SCatalogReq* pCatalogReq) { - int32_t ndbs = taosHashGetSize(pMetaCache->pInsertTables); - pCatalogReq->pTableMeta = taosArrayInit(ndbs, sizeof(STablesReq)); - if (NULL == pCatalogReq->pTableMeta) { - return TSDB_CODE_OUT_OF_MEMORY; - } - pCatalogReq->pTableHash = taosArrayInit(ndbs, sizeof(STablesReq)); - if (NULL == pCatalogReq->pTableHash) { - return TSDB_CODE_OUT_OF_MEMORY; - } - pCatalogReq->pUser = taosArrayInit(ndbs, sizeof(SUserAuthInfo)); - if (NULL == pCatalogReq->pUser) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - pCxt->pTableMetaPos = taosArrayInit(pMetaCache->sqlTableNum, sizeof(int32_t)); - pCxt->pTableVgroupPos = taosArrayInit(pMetaCache->sqlTableNum, sizeof(int32_t)); - - int32_t metaReqNo = 0; - int32_t vgroupReqNo = 0; - SInsertTablesMetaReq* p = taosHashIterate(pMetaCache->pInsertTables, NULL); - while (NULL != p) { - STablesReq req = {0}; - strcpy(req.dbFName, p->dbFName); - TSWAP(req.pTables, p->pTableMetaReq); - taosArrayPush(pCatalogReq->pTableMeta, &req); - - req.pTables = NULL; - TSWAP(req.pTables, p->pTableVgroupReq); - taosArrayPush(pCatalogReq->pTableHash, &req); - - int32_t ntables = taosArrayGetSize(p->pTableMetaPos); - for (int32_t i = 0; i < ntables; ++i) { - taosArrayInsert(pCxt->pTableMetaPos, *(int32_t*)taosArrayGet(p->pTableMetaPos, i), &metaReqNo); - ++metaReqNo; - } - - ntables = taosArrayGetSize(p->pTableVgroupPos); - for (int32_t i = 0; i < ntables; ++i) { - taosArrayInsert(pCxt->pTableVgroupPos, *(int32_t*)taosArrayGet(p->pTableVgroupPos, i), &vgroupReqNo); - ++vgroupReqNo; - } - - SUserAuthInfo auth = {0}; - snprintf(auth.user, sizeof(auth.user), "%s", pCxt->pUser); - snprintf(auth.dbFName, sizeof(auth.dbFName), "%s", p->dbFName); - auth.type = AUTH_TYPE_WRITE; - taosArrayPush(pCatalogReq->pUser, &auth); - - p = taosHashIterate(pMetaCache->pInsertTables, p); - } - return TSDB_CODE_SUCCESS; -} - -int32_t buildCatalogReqForQuery(const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq) { +int32_t buildCatalogReq(const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq) { int32_t code = buildTableReqFromDb(pMetaCache->pTableMeta, &pCatalogReq->pTableMeta); if (TSDB_CODE_SUCCESS == code) { code = buildDbReq(pMetaCache->pDbVgroup, &pCatalogReq->pDbVgroup); @@ -697,13 +642,6 @@ int32_t buildCatalogReqForQuery(const SParseMetaCache* pMetaCache, SCatalogReq* return code; } -int32_t buildCatalogReq(SParseContext* pCxt, const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq) { - if (NULL != pMetaCache->pInsertTables) { - return buildCatalogReqForInsert(pCxt, pMetaCache, pCatalogReq); - } - return buildCatalogReqForQuery(pMetaCache, pCatalogReq); -} - static int32_t putMetaDataToHash(const char* pKey, int32_t len, const SArray* pData, int32_t index, SHashObj** pHash) { if (NULL == *pHash) { *pHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); @@ -791,8 +729,7 @@ static int32_t putUdfToCache(const SArray* pUdfReq, const SArray* pUdfData, SHas return TSDB_CODE_SUCCESS; } -int32_t putMetaDataToCacheForQuery(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, - SParseMetaCache* pMetaCache) { +int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache) { int32_t code = putDbTableDataToCache(pCatalogReq->pTableMeta, pMetaData->pTableMeta, &pMetaCache->pTableMeta); if (TSDB_CODE_SUCCESS == code) { code = putDbDataToCache(pCatalogReq->pDbVgroup, pMetaData->pDbVgroup, &pMetaCache->pDbVgroup); @@ -822,30 +759,6 @@ int32_t putMetaDataToCacheForQuery(const SCatalogReq* pCatalogReq, const SMetaDa return code; } -int32_t putMetaDataToCacheForInsert(const SMetaData* pMetaData, SParseMetaCache* pMetaCache) { - int32_t ndbs = taosArrayGetSize(pMetaData->pUser); - for (int32_t i = 0; i < ndbs; ++i) { - SMetaRes* pRes = taosArrayGet(pMetaData->pUser, i); - if (TSDB_CODE_SUCCESS != pRes->code) { - return pRes->code; - } - if (!(*(bool*)pRes->pRes)) { - return TSDB_CODE_PAR_PERMISSION_DENIED; - } - } - pMetaCache->pTableMetaData = pMetaData->pTableMeta; - pMetaCache->pTableVgroupData = pMetaData->pTableHash; - return TSDB_CODE_SUCCESS; -} - -int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache, - bool insertValuesStmt) { - if (insertValuesStmt) { - return putMetaDataToCacheForInsert(pMetaData, pMetaCache); - } - return putMetaDataToCacheForQuery(pCatalogReq, pMetaData, pMetaCache); -} - static int32_t reserveTableReqInCacheImpl(const char* pTbFName, int32_t len, SHashObj** pTables) { if (NULL == *pTables) { *pTables = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); @@ -1146,82 +1059,6 @@ int32_t getDnodeListFromCache(SParseMetaCache* pMetaCache, SArray** pDnodes) { return TSDB_CODE_SUCCESS; } -static int32_t reserveTableReqInCacheForInsert(const SName* pName, ECatalogReqType reqType, int32_t tableNo, - SInsertTablesMetaReq* pReq) { - switch (reqType) { - case CATALOG_REQ_TYPE_META: - taosArrayPush(pReq->pTableMetaReq, pName); - taosArrayPush(pReq->pTableMetaPos, &tableNo); - break; - case CATALOG_REQ_TYPE_VGROUP: - taosArrayPush(pReq->pTableVgroupReq, pName); - taosArrayPush(pReq->pTableVgroupPos, &tableNo); - break; - case CATALOG_REQ_TYPE_BOTH: - taosArrayPush(pReq->pTableMetaReq, pName); - taosArrayPush(pReq->pTableMetaPos, &tableNo); - taosArrayPush(pReq->pTableVgroupReq, pName); - taosArrayPush(pReq->pTableVgroupPos, &tableNo); - break; - default: - break; - } - return TSDB_CODE_SUCCESS; -} - -static int32_t reserveTableReqInDbCacheForInsert(const SName* pName, ECatalogReqType reqType, int32_t tableNo, - SHashObj* pDbs) { - SInsertTablesMetaReq req = {.pTableMetaReq = taosArrayInit(4, sizeof(SName)), - .pTableMetaPos = taosArrayInit(4, sizeof(int32_t)), - .pTableVgroupReq = taosArrayInit(4, sizeof(SName)), - .pTableVgroupPos = taosArrayInit(4, sizeof(int32_t))}; - tNameGetFullDbName(pName, req.dbFName); - int32_t code = reserveTableReqInCacheForInsert(pName, reqType, tableNo, &req); - if (TSDB_CODE_SUCCESS == code) { - code = taosHashPut(pDbs, pName->dbname, strlen(pName->dbname), &req, sizeof(SInsertTablesMetaReq)); - } - return code; -} - -int32_t reserveTableMetaInCacheForInsert(const SName* pName, ECatalogReqType reqType, int32_t tableNo, - SParseMetaCache* pMetaCache) { - if (NULL == pMetaCache->pInsertTables) { - pMetaCache->pInsertTables = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); - if (NULL == pMetaCache->pInsertTables) { - return TSDB_CODE_OUT_OF_MEMORY; - } - } - pMetaCache->sqlTableNum = tableNo; - SInsertTablesMetaReq* pReq = taosHashGet(pMetaCache->pInsertTables, pName->dbname, strlen(pName->dbname)); - if (NULL == pReq) { - return reserveTableReqInDbCacheForInsert(pName, reqType, tableNo, pMetaCache->pInsertTables); - } - return reserveTableReqInCacheForInsert(pName, reqType, tableNo, pReq); -} - -int32_t getTableMetaFromCacheForInsert(SArray* pTableMetaPos, SParseMetaCache* pMetaCache, int32_t tableNo, - STableMeta** pMeta) { - int32_t reqIndex = *(int32_t*)taosArrayGet(pTableMetaPos, tableNo); - SMetaRes* pRes = taosArrayGet(pMetaCache->pTableMetaData, reqIndex); - if (TSDB_CODE_SUCCESS == pRes->code) { - *pMeta = tableMetaDup((const STableMeta*)pRes->pRes); - if (NULL == *pMeta) { - return TSDB_CODE_OUT_OF_MEMORY; - } - } - return pRes->code; -} - -int32_t getTableVgroupFromCacheForInsert(SArray* pTableVgroupPos, SParseMetaCache* pMetaCache, int32_t tableNo, - SVgroupInfo* pVgroup) { - int32_t reqIndex = *(int32_t*)taosArrayGet(pTableVgroupPos, tableNo); - SMetaRes* pRes = taosArrayGet(pMetaCache->pTableVgroupData, reqIndex); - if (TSDB_CODE_SUCCESS == pRes->code) { - memcpy(pVgroup, pRes->pRes, sizeof(SVgroupInfo)); - } - return pRes->code; -} - void destoryParseTablesMetaReqHash(SHashObj* pHash) { SParseTablesMetaReq* p = taosHashIterate(pHash, NULL); while (NULL != p) { @@ -1239,16 +1076,6 @@ void destoryParseMetaCache(SParseMetaCache* pMetaCache, bool request) { taosHashCleanup(pMetaCache->pTableMeta); taosHashCleanup(pMetaCache->pTableVgroup); } - SInsertTablesMetaReq* p = taosHashIterate(pMetaCache->pInsertTables, NULL); - while (NULL != p) { - taosArrayDestroy(p->pTableMetaPos); - taosArrayDestroy(p->pTableMetaReq); - taosArrayDestroy(p->pTableVgroupPos); - taosArrayDestroy(p->pTableVgroupReq); - - p = taosHashIterate(pMetaCache->pInsertTables, p); - } - taosHashCleanup(pMetaCache->pInsertTables); taosHashCleanup(pMetaCache->pDbVgroup); taosHashCleanup(pMetaCache->pDbCfg); taosHashCleanup(pMetaCache->pDbInfo); diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index 748478778a..cf338d63ff 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -167,7 +167,7 @@ static void rewriteExprAlias(SNode* pRoot) { int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery) { int32_t code = TSDB_CODE_SUCCESS; if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) { - code = parseInsertSql(pCxt, pQuery, NULL); + code = parseInsertSql(pCxt, pQuery, NULL, NULL); } else { code = parseSqlIntoAst(pCxt, pQuery); } @@ -175,21 +175,26 @@ int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery) { return code; } -int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) { +static int32_t parseQuerySyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) { SParseMetaCache metaCache = {0}; - int32_t code = nodesAcquireAllocator(pCxt->allocatorId); + int32_t code = parseSqlSyntax(pCxt, pQuery, &metaCache); + if (TSDB_CODE_SUCCESS == code) { + code = buildCatalogReq(&metaCache, pCatalogReq); + } + destoryParseMetaCache(&metaCache, true); + return code; +} + +int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) { + int32_t code = nodesAcquireAllocator(pCxt->allocatorId); if (TSDB_CODE_SUCCESS == code) { if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) { - code = parseInsertSyntax(pCxt, pQuery, &metaCache); + code = parseInsertSql(pCxt, pQuery, pCatalogReq, NULL); } else { - code = parseSqlSyntax(pCxt, pQuery, &metaCache); + code = parseQuerySyntax(pCxt, pQuery, pCatalogReq); } } - if (TSDB_CODE_SUCCESS == code) { - code = buildCatalogReq(pCxt, &metaCache, pCatalogReq); - } nodesReleaseAllocator(pCxt->allocatorId); - destoryParseMetaCache(&metaCache, true); terrno = code; return code; } @@ -199,14 +204,10 @@ int32_t qAnalyseSqlSemantic(SParseContext* pCxt, const struct SCatalogReq* pCata SParseMetaCache metaCache = {0}; int32_t code = nodesAcquireAllocator(pCxt->allocatorId); if (TSDB_CODE_SUCCESS == code) { - code = putMetaDataToCache(pCatalogReq, pMetaData, &metaCache, NULL == pQuery->pRoot); + code = putMetaDataToCache(pCatalogReq, pMetaData, &metaCache); } if (TSDB_CODE_SUCCESS == code) { - if (NULL == pQuery->pRoot) { - code = parseInsertSql(pCxt, &pQuery, &metaCache); - } else { - code = analyseSemantic(pCxt, pQuery, &metaCache); - } + code = analyseSemantic(pCxt, pQuery, &metaCache); } nodesReleaseAllocator(pCxt->allocatorId); destoryParseMetaCache(&metaCache, false); @@ -214,6 +215,11 @@ int32_t qAnalyseSqlSemantic(SParseContext* pCxt, const struct SCatalogReq* pCata return code; } +int32_t qContinueParseSql(SParseContext* pCxt, struct SCatalogReq* pCatalogReq, const struct SMetaData* pMetaData, + SQuery* pQuery) { + return parseInsertSql(pCxt, &pQuery, pCatalogReq, pMetaData); +} + void qDestroyParseContext(SParseContext* pCxt) { if (NULL == pCxt) { return; diff --git a/source/libs/parser/test/mockCatalog.cpp b/source/libs/parser/test/mockCatalog.cpp index 7f18a7b282..4f5ddd9a51 100644 --- a/source/libs/parser/test/mockCatalog.cpp +++ b/source/libs/parser/test/mockCatalog.cpp @@ -228,11 +228,21 @@ int32_t __catalogGetTableMeta(struct SCatalog* pCatalog, SRequestConnInfo* pConn return g_mockCatalogService->catalogGetTableMeta(pTableName, pTableMeta); } +int32_t __catalogGetCachedTableMeta(SCatalog* pCtg, const SName* pTableName, STableMeta** pTableMeta) { + return g_mockCatalogService->catalogGetTableMeta(pTableName, pTableMeta, true); +} + int32_t __catalogGetTableHashVgroup(struct SCatalog* pCatalog, SRequestConnInfo* pConn, const SName* pTableName, SVgroupInfo* vgInfo) { return g_mockCatalogService->catalogGetTableHashVgroup(pTableName, vgInfo); } +int32_t __catalogGetCachedTableHashVgroup(SCatalog* pCtg, const SName* pTableName, SVgroupInfo* pVgroup, bool* exists) { + int32_t code = g_mockCatalogService->catalogGetTableHashVgroup(pTableName, pVgroup, true); + *exists = 0 != pVgroup->vgId; + return code; +} + int32_t __catalogGetTableDistVgInfo(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, SArray** pVgList) { return g_mockCatalogService->catalogGetTableDistVgInfo(pTableName, pVgList); @@ -257,6 +267,13 @@ int32_t __catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, const char* us return 0; } +int32_t __catalogChkAuthFromCache(SCatalog* pCtg, const char* user, const char* dbFName, AUTH_TYPE type, bool* pass, + bool* exists) { + *pass = true; + *exists = true; + return 0; +} + int32_t __catalogGetUdfInfo(SCatalog* pCtg, SRequestConnInfo* pConn, const char* funcName, SFuncInfo* pInfo) { return g_mockCatalogService->catalogGetUdfInfo(funcName, pInfo); } @@ -289,13 +306,17 @@ void initMetaDataEnv() { static Stub stub; stub.set(catalogGetHandle, __catalogGetHandle); stub.set(catalogGetTableMeta, __catalogGetTableMeta); + stub.set(catalogGetCachedTableMeta, __catalogGetCachedTableMeta); stub.set(catalogGetSTableMeta, __catalogGetTableMeta); + stub.set(catalogGetCachedSTableMeta, __catalogGetCachedTableMeta); stub.set(catalogGetTableHashVgroup, __catalogGetTableHashVgroup); + stub.set(catalogGetCachedTableHashVgroup, __catalogGetCachedTableHashVgroup); stub.set(catalogGetTableDistVgInfo, __catalogGetTableDistVgInfo); stub.set(catalogGetDBVgVersion, __catalogGetDBVgVersion); stub.set(catalogGetDBVgList, __catalogGetDBVgList); stub.set(catalogGetDBCfg, __catalogGetDBCfg); stub.set(catalogChkAuth, __catalogChkAuth); + stub.set(catalogChkAuthFromCache, __catalogChkAuthFromCache); stub.set(catalogGetUdfInfo, __catalogGetUdfInfo); stub.set(catalogRefreshGetTableMeta, __catalogRefreshGetTableMeta); stub.set(catalogRemoveTableMeta, __catalogRemoveTableMeta); diff --git a/source/libs/parser/test/mockCatalogService.cpp b/source/libs/parser/test/mockCatalogService.cpp index f2cebcb08d..95f7af435d 100644 --- a/source/libs/parser/test/mockCatalogService.cpp +++ b/source/libs/parser/test/mockCatalogService.cpp @@ -91,7 +91,7 @@ class MockCatalogServiceImpl { public: static const int32_t numOfDataTypes = sizeof(tDataTypes) / sizeof(tDataTypes[0]); - MockCatalogServiceImpl() : id_(1) {} + MockCatalogServiceImpl() : id_(1), havaCache_(true) {} ~MockCatalogServiceImpl() { for (auto& cfg : dbCfg_) { @@ -106,7 +106,11 @@ class MockCatalogServiceImpl { int32_t catalogGetHandle() const { return 0; } - int32_t catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta) const { + int32_t catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta, bool onlyCache = false) const { + if (onlyCache && !havaCache_) { + return TSDB_CODE_SUCCESS; + } + std::unique_ptr table; char db[TSDB_DB_NAME_LEN] = {0}; @@ -121,7 +125,12 @@ class MockCatalogServiceImpl { return TSDB_CODE_SUCCESS; } - int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo) const { + int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo, bool onlyCache = false) const { + if (onlyCache && !havaCache_) { + vgInfo->vgId = 0; + return TSDB_CODE_SUCCESS; + } + vgInfo->vgId = 1; return TSDB_CODE_SUCCESS; } @@ -618,6 +627,7 @@ class MockCatalogServiceImpl { IndexMetaCache index_; DnodeCache dnode_; DbCfgCache dbCfg_; + bool havaCache_; }; MockCatalogService::MockCatalogService() : impl_(new MockCatalogServiceImpl()) {} @@ -651,12 +661,14 @@ void MockCatalogService::createDatabase(const std::string& db, bool rollup, int8 impl_->createDatabase(db, rollup, cacheLast); } -int32_t MockCatalogService::catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta) const { - return impl_->catalogGetTableMeta(pTableName, pTableMeta); +int32_t MockCatalogService::catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta, + bool onlyCache) const { + return impl_->catalogGetTableMeta(pTableName, pTableMeta, onlyCache); } -int32_t MockCatalogService::catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo) const { - return impl_->catalogGetTableHashVgroup(pTableName, vgInfo); +int32_t MockCatalogService::catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo, + bool onlyCache) const { + return impl_->catalogGetTableHashVgroup(pTableName, vgInfo, onlyCache); } int32_t MockCatalogService::catalogGetTableDistVgInfo(const SName* pTableName, SArray** pVgList) const { diff --git a/source/libs/parser/test/mockCatalogService.h b/source/libs/parser/test/mockCatalogService.h index d9d2185728..acd7fab8e1 100644 --- a/source/libs/parser/test/mockCatalogService.h +++ b/source/libs/parser/test/mockCatalogService.h @@ -67,8 +67,8 @@ class MockCatalogService { void createDnode(int32_t dnodeId, const std::string& host, int16_t port); void createDatabase(const std::string& db, bool rollup = false, int8_t cacheLast = 0); - int32_t catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta) const; - int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo) const; + int32_t catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta, bool onlyCache = false) const; + int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo, bool onlyCache = false) const; int32_t catalogGetTableDistVgInfo(const SName* pTableName, SArray** pVgList) const; int32_t catalogGetDBVgList(const char* pDbFName, SArray** pVgList) const; int32_t catalogGetDBCfg(const char* pDbFName, SDbCfgInfo* pDbCfg) const; diff --git a/source/libs/parser/test/parTestUtil.cpp b/source/libs/parser/test/parTestUtil.cpp index c9cbf3f5f3..dbae302e42 100644 --- a/source/libs/parser/test/parTestUtil.cpp +++ b/source/libs/parser/test/parTestUtil.cpp @@ -233,16 +233,15 @@ class ParserTestBaseImpl { } void doBuildCatalogReq(SParseContext* pCxt, const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq) { - DO_WITH_THROW(buildCatalogReq, pCxt, pMetaCache, pCatalogReq); + DO_WITH_THROW(buildCatalogReq, pMetaCache, pCatalogReq); } void doGetAllMeta(const SCatalogReq* pCatalogReq, SMetaData* pMetaData) { DO_WITH_THROW(g_mockCatalogService->catalogGetAllMeta, pCatalogReq, pMetaData); } - void doPutMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache, - bool isInsertValues) { - DO_WITH_THROW(putMetaDataToCache, pCatalogReq, pMetaData, pMetaCache, isInsertValues); + void doPutMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache) { + DO_WITH_THROW(putMetaDataToCache, pCatalogReq, pMetaData, pMetaCache); } void doAuthenticate(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) { @@ -280,15 +279,14 @@ class ParserTestBaseImpl { res_.calcConstAst_ = toString(pQuery->pRoot); } - void doParseInsertSql(SParseContext* pCxt, SQuery** pQuery, SParseMetaCache* pMetaCache) { - DO_WITH_THROW(parseInsertSql, pCxt, pQuery, pMetaCache); + void doParseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) { + DO_WITH_THROW(parseInsertSql, pCxt, pQuery, pCatalogReq, pMetaData); ASSERT_NE(*pQuery, nullptr); res_.parsedAst_ = toString((*pQuery)->pRoot); } - void doParseInsertSyntax(SParseContext* pCxt, SQuery** pQuery, SParseMetaCache* pMetaCache) { - DO_WITH_THROW(parseInsertSyntax, pCxt, pQuery, pMetaCache); - ASSERT_NE(*pQuery, nullptr); + void doContinueParseSql(SParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SQuery* pQuery) { + DO_WITH_THROW(qContinueParseSql, pCxt, pCatalogReq, pMetaData, pQuery); } string toString(const SNode* pRoot) { @@ -314,7 +312,7 @@ class ParserTestBaseImpl { if (qIsInsertValuesSql(cxt.pSql, cxt.sqlLen)) { unique_ptr query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery); - doParseInsertSql(&cxt, query.get(), nullptr); + doParseInsertSql(&cxt, query.get(), nullptr, nullptr); } else { unique_ptr query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery); doParse(&cxt, query.get()); @@ -360,61 +358,102 @@ class ParserTestBaseImpl { } } + void runQueryAsyncInternalFuncs(SParseContext* pParCxt) { + unique_ptr query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery); + bool request = true; + unique_ptr > metaCache( + new SParseMetaCache(), bind(destoryParseMetaCacheWarpper, _1, cref(request))); + doParse(pParCxt, query.get()); + doCollectMetaKey(pParCxt, *(query.get()), metaCache.get()); + + SQuery* pQuery = *(query.get()); + + unique_ptr catalogReq(new SCatalogReq(), + MockCatalogService::destoryCatalogReq); + doBuildCatalogReq(pParCxt, metaCache.get(), catalogReq.get()); + + string err; + thread t1([&]() { + try { + unique_ptr metaData(new SMetaData(), MockCatalogService::destoryMetaData); + doGetAllMeta(catalogReq.get(), metaData.get()); + + metaCache.reset(new SParseMetaCache()); + request = false; + doPutMetaDataToCache(catalogReq.get(), metaData.get(), metaCache.get()); + + doAuthenticate(pParCxt, pQuery, metaCache.get()); + + doTranslate(pParCxt, pQuery, metaCache.get()); + + doCalculateConstant(pParCxt, pQuery); + } catch (const TerminateFlag& e) { + // success and terminate + } catch (const runtime_error& e) { + err = e.what(); + } catch (...) { + err = "unknown error"; + } + }); + + t1.join(); + if (!err.empty()) { + throw runtime_error(err); + } + } + + void runInsertAsyncInternalFuncsImpl(SParseContext* pParCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, + SMetaData* pMetaData) { + doParseInsertSql(pParCxt, pQuery, pCatalogReq, pMetaData); + + if (QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) { + return; + } + + string err; + thread t1([&]() { + try { + doGetAllMeta(pCatalogReq, pMetaData); + + doParseInsertSql(pParCxt, pQuery, pCatalogReq, pMetaData); + + if (QUERY_EXEC_STAGE_SCHEDULE != (*pQuery)->execStage) { + runInsertAsyncInternalFuncsImpl(pParCxt, pQuery, pCatalogReq, pMetaData); + } + } catch (const TerminateFlag& e) { + // success and terminate + } catch (const runtime_error& e) { + err = e.what(); + } catch (...) { + err = "unknown error"; + } + }); + + t1.join(); + if (!err.empty()) { + throw runtime_error(err); + } + } + + void runInsertAsyncInternalFuncs(SParseContext* pParCxt) { + unique_ptr query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery); + unique_ptr catalogReq(new SCatalogReq(), + MockCatalogService::destoryCatalogReq); + unique_ptr metaData(new SMetaData(), MockCatalogService::destoryMetaData); + runInsertAsyncInternalFuncsImpl(pParCxt, query.get(), catalogReq.get(), metaData.get()); + } + void runAsyncInternalFuncs(const string& sql, int32_t expect, ParserStage checkStage) { reset(expect, checkStage, TEST_INTERFACE_ASYNC_INTERNAL); try { unique_ptr > cxt(new SParseContext(), destoryParseContext); setParseContext(sql, cxt.get(), true); - unique_ptr query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery); - bool request = true; - unique_ptr > metaCache( - new SParseMetaCache(), bind(destoryParseMetaCacheWarpper, _1, cref(request))); bool isInsertValues = qIsInsertValuesSql(cxt->pSql, cxt->sqlLen); if (isInsertValues) { - doParseInsertSyntax(cxt.get(), query.get(), metaCache.get()); + runInsertAsyncInternalFuncs(cxt.get()); } else { - doParse(cxt.get(), query.get()); - doCollectMetaKey(cxt.get(), *(query.get()), metaCache.get()); - } - - SQuery* pQuery = *(query.get()); - - unique_ptr catalogReq(new SCatalogReq(), - MockCatalogService::destoryCatalogReq); - doBuildCatalogReq(cxt.get(), metaCache.get(), catalogReq.get()); - - string err; - thread t1([&]() { - try { - unique_ptr metaData(new SMetaData(), MockCatalogService::destoryMetaData); - doGetAllMeta(catalogReq.get(), metaData.get()); - - metaCache.reset(new SParseMetaCache()); - request = false; - doPutMetaDataToCache(catalogReq.get(), metaData.get(), metaCache.get(), isInsertValues); - - if (isInsertValues) { - doParseInsertSql(cxt.get(), query.get(), metaCache.get()); - } else { - doAuthenticate(cxt.get(), pQuery, metaCache.get()); - - doTranslate(cxt.get(), pQuery, metaCache.get()); - - doCalculateConstant(cxt.get(), pQuery); - } - } catch (const TerminateFlag& e) { - // success and terminate - } catch (const runtime_error& e) { - err = e.what(); - } catch (...) { - err = "unknown error"; - } - }); - - t1.join(); - if (!err.empty()) { - throw runtime_error(err); + runQueryAsyncInternalFuncs(cxt.get()); } if (g_dump) { @@ -441,25 +480,39 @@ class ParserTestBaseImpl { doParseSqlSyntax(cxt.get(), query.get(), catalogReq.get()); SQuery* pQuery = *(query.get()); - string err; - thread t1([&]() { - try { - unique_ptr metaData(new SMetaData(), MockCatalogService::destoryMetaData); - doGetAllMeta(catalogReq.get(), metaData.get()); + switch (pQuery->execStage) { + case QUERY_EXEC_STAGE_PARSE: + case QUERY_EXEC_STAGE_ANALYSE: { + string err; + thread t1([&]() { + try { + unique_ptr metaData(new SMetaData(), + MockCatalogService::destoryMetaData); + doGetAllMeta(catalogReq.get(), metaData.get()); + if (QUERY_EXEC_STAGE_PARSE == pQuery->execStage) { + doContinueParseSql(cxt.get(), catalogReq.get(), metaData.get(), pQuery); + } else { + doAnalyseSqlSemantic(cxt.get(), catalogReq.get(), metaData.get(), pQuery); + } + } catch (const TerminateFlag& e) { + // success and terminate + } catch (const runtime_error& e) { + err = e.what(); + } catch (...) { + err = "unknown error"; + } + }); - doAnalyseSqlSemantic(cxt.get(), catalogReq.get(), metaData.get(), pQuery); - } catch (const TerminateFlag& e) { - // success and terminate - } catch (const runtime_error& e) { - err = e.what(); - } catch (...) { - err = "unknown error"; + t1.join(); + if (!err.empty()) { + throw runtime_error(err); + } + break; } - }); - - t1.join(); - if (!err.empty()) { - throw runtime_error(err); + case QUERY_EXEC_STAGE_SCHEDULE: + break; + default: + break; } if (g_dump) { diff --git a/source/libs/qworker/src/qwMsg.c b/source/libs/qworker/src/qwMsg.c index 14ac4f5bea..7e7f71b176 100644 --- a/source/libs/qworker/src/qwMsg.c +++ b/source/libs/qworker/src/qwMsg.c @@ -8,6 +8,7 @@ #include "tcommon.h" #include "tmsg.h" #include "tname.h" +#include "tgrant.h" int32_t qwMallocFetchRsp(int8_t rpcMalloc, int32_t length, SRetrieveTableRsp **rsp) { int32_t msgSize = sizeof(SRetrieveTableRsp) + length; @@ -305,7 +306,7 @@ int32_t qwRegisterHbBrokenLinkArg(SQWorker *mgmt, uint64_t sId, SRpcHandleInfo * return TSDB_CODE_SUCCESS; } -int32_t qWorkerPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg) { +int32_t qWorkerPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg, bool chkGrant) { if (NULL == qWorkerMgmt || NULL == pMsg) { QW_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } @@ -326,6 +327,12 @@ int32_t qWorkerPreprocessQueryMsg(void *qWorkerMgmt, SRpcMsg *pMsg) { msg->execId = ntohl(msg->execId); msg->phyLen = ntohl(msg->phyLen); msg->sqlLen = ntohl(msg->sqlLen); + msg->msgMask = ntohl(msg->msgMask); + + if (chkGrant && (!TEST_SHOW_REWRITE_MASK(msg->msgMask)) && (grantCheck(TSDB_GRANT_TIME) != TSDB_CODE_SUCCESS)) { + QW_ELOG("query failed cause of grant expired, msgMask:%d", msg->msgMask); + QW_ERR_RET(TSDB_CODE_GRANT_EXPIRED); + } uint64_t sId = msg->sId; uint64_t qId = msg->queryId; diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index 4738e1bbf9..939be1809a 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -3994,9 +3994,12 @@ int32_t filterSetDataFromColId(SFilterInfo *info, void *param) { } int32_t filterInitFromNode(SNode *pNode, SFilterInfo **pInfo, uint32_t options) { - int32_t code = 0; SFilterInfo *info = NULL; + if (pNode == NULL) { + return TSDB_CODE_SUCCESS; + } + int32_t code = 0; if (pNode == NULL || pInfo == NULL) { fltError("invalid param"); FLT_ERR_RET(TSDB_CODE_QRY_APP_ERROR); @@ -4034,9 +4037,7 @@ int32_t filterInitFromNode(SNode *pNode, SFilterInfo **pInfo, uint32_t options) _return: filterFreeInfo(*pInfo); - *pInfo = NULL; - FLT_RET(code); } diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c index 17f1ea6728..801f38bd1a 100644 --- a/source/libs/scheduler/src/schRemote.c +++ b/source/libs/scheduler/src/schRemote.c @@ -1047,7 +1047,6 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, SSubQueryMsg *pMsg = msg; pMsg->header.vgId = htonl(addr->nodeId); - pMsg->header.msgMask = htonl((pTask->plan->showRewrite) ? SHOW_REWRITE_MASK() : 0); pMsg->sId = htobe64(schMgmt.sId); pMsg->queryId = htobe64(pJob->queryId); pMsg->taskId = htobe64(pTask->taskId); @@ -1058,6 +1057,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, pMsg->needFetch = SCH_TASK_NEED_FETCH(pTask); pMsg->phyLen = htonl(pTask->msgLen); pMsg->sqlLen = htonl(len); + pMsg->msgMask = htonl((pTask->plan->showRewrite) ? QUERY_MSG_MASK_SHOW_REWRITE() : 0); memcpy(pMsg->msg, pJob->sql, len); memcpy(pMsg->msg + len, pTask->msg, pTask->msgLen); @@ -1157,6 +1157,7 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, SCH_ERR_RET(schAppendTaskExecNode(pJob, pTask, addr, pTask->execId)); } } else { + taosMemoryFree(msg); SCH_ERR_RET(schProcessOnTaskSuccess(pJob, pTask)); } #endif diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index 3a17e021aa..65c6f427ab 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -420,16 +420,22 @@ bool syncIsReadyForRead(int64_t rid) { bool ready = false; if (pSyncNode->state == TAOS_SYNC_STATE_LEADER && !pSyncNode->restoreFinish) { - if (!pSyncNode->pLogStore->syncLogIsEmpty(pSyncNode->pLogStore)) { - SSyncRaftEntry* pEntry = NULL; - int32_t code = pSyncNode->pLogStore->syncLogGetEntry( - pSyncNode->pLogStore, pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore), &pEntry); - if (code == 0 && pEntry != NULL) { - if (pEntry->originalRpcType == TDMT_SYNC_NOOP && pEntry->term == pSyncNode->pRaftStore->currentTerm) { - ready = true; - } + if (!pSyncNode->pFsm->FpApplyQueueEmptyCb(pSyncNode->pFsm)) { + // apply queue not empty + ready = false; - syncEntryDestory(pEntry); + } else { + if (!pSyncNode->pLogStore->syncLogIsEmpty(pSyncNode->pLogStore)) { + SSyncRaftEntry* pEntry = NULL; + int32_t code = pSyncNode->pLogStore->syncLogGetEntry( + pSyncNode->pLogStore, pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore), &pEntry); + if (code == 0 && pEntry != NULL) { + if (pEntry->originalRpcType == TDMT_SYNC_NOOP && pEntry->term == pSyncNode->pRaftStore->currentTerm) { + ready = true; + } + + syncEntryDestory(pEntry); + } } } } diff --git a/source/libs/sync/src/syncRaftEntry.c b/source/libs/sync/src/syncRaftEntry.c index e539c70a79..82875c58b4 100644 --- a/source/libs/sync/src/syncRaftEntry.c +++ b/source/libs/sync/src/syncRaftEntry.c @@ -72,7 +72,6 @@ SSyncRaftEntry* syncEntryBuildNoop(SyncTerm term, SyncIndex index, int32_t vgId) SMsgHead head; head.vgId = vgId; head.contLen = sizeof(SMsgHead); - head.msgMask = 0; SRpcMsg rpcMsg; memset(&rpcMsg, 0, sizeof(SRpcMsg)); rpcMsg.contLen = head.contLen; diff --git a/tests/system-test/1-insert/delete_data.py b/tests/system-test/1-insert/delete_data.py index c085d2763a..718a4497dc 100644 --- a/tests/system-test/1-insert/delete_data.py +++ b/tests/system-test/1-insert/delete_data.py @@ -1,312 +1,313 @@ -################################################################### -# Copyright (c) 2016 by TAOS Technologies, Inc. -# All rights reserved. -# -# This file is proprietary and confidential to TAOS Technologies. -# No part of this file may be reproduced, stored, transmitted, -# disclosed or used in any form or by any means other than as -# expressly provided by the written permission from Jianhui Tao -# -################################################################### - -# -*- coding: utf-8 -*- - -import random -import string - -from numpy import logspace -from util import constant -from util.log import * -from util.cases import * -from util.sql import * -from util.common import * -from util.sqlset import TDSetSql - -class TDTestCase: - def init(self, conn, logSql, replicaVar=1): - self.replicaVar = int(replicaVar) - tdLog.debug("start to execute %s" % __file__) - tdSql.init(conn.cursor(), True) - self.dbname = 'db_test' - self.setsql = TDSetSql() - self.stbname = 'stb' - self.ntbname = 'ntb' - self.rowNum = 10 - self.tbnum = 3 - self.ts = 1537146000000 - self.binary_str = 'taosdata' - self.nchar_str = '涛思数据' - self.str_length = 20 - self.column_dict = { - 'col1': 'tinyint', - 'col2': 'smallint', - 'col3': 'int', - 'col4': 'bigint', - 'col5': 'tinyint unsigned', - 'col6': 'smallint unsigned', - 'col7': 'int unsigned', - 'col8': 'bigint unsigned', - 'col9': 'float', - 'col10': 'double', - 'col11': 'bool', - 'col12': f'binary({self.str_length})', - 'col13': f'nchar({self.str_length})', - - } - - self.tinyint_val = random.randint(constant.TINYINT_MIN,constant.TINYINT_MAX) - self.smallint_val = random.randint(constant.SMALLINT_MIN,constant.SMALLINT_MAX) - self.int_val = random.randint(constant.INT_MIN,constant.INT_MAX) - self.bigint_val = random.randint(constant.BIGINT_MIN,constant.BIGINT_MAX) - self.untingint_val = random.randint(constant.TINYINT_UN_MIN,constant.TINYINT_UN_MAX) - self.unsmallint_val = random.randint(constant.SMALLINT_UN_MIN,constant.SMALLINT_UN_MAX) - self.unint_val = random.randint(constant.INT_UN_MIN,constant.INT_MAX) - self.unbigint_val = random.randint(constant.BIGINT_UN_MIN,constant.BIGINT_UN_MAX) - self.float_val = random.uniform(constant.FLOAT_MIN,constant.FLOAT_MAX) - self.double_val = random.uniform(constant.DOUBLE_MIN*(1E-300),constant.DOUBLE_MAX*(1E-300)) - self.bool_val = random.randint(0,100)%2 - self.binary_val = tdCom.getLongName(random.randint(0,self.str_length)) - self.nchar_val = tdCom.getLongName(random.randint(0,self.str_length)) - self.base_data = { - 'tinyint':self.tinyint_val, - 'smallint':self.smallint_val, - 'int':self.int_val, - 'bigint':self.bigint_val, - 'tinyint unsigned':self.untingint_val, - 'smallint unsigned':self.unsmallint_val, - 'int unsigned':self.unint_val, - 'bigint unsigned':self.unbigint_val, - 'bool':self.bool_val, - 'float':self.float_val, - 'double':self.double_val, - 'binary':self.binary_val, - 'nchar':self.nchar_val - } - - def insert_base_data(self,col_type,tbname,rows,base_data): - for i in range(rows): - if col_type.lower() == 'tinyint': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["tinyint"]})') - elif col_type.lower() == 'smallint': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["smallint"]})') - elif col_type.lower() == 'int': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["int"]})') - elif col_type.lower() == 'bigint': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["bigint"]})') - elif col_type.lower() == 'tinyint unsigned': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["tinyint unsigned"]})') - elif col_type.lower() == 'smallint unsigned': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["smallint unsigned"]})') - elif col_type.lower() == 'int unsigned': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["int unsigned"]})') - elif col_type.lower() == 'bigint unsigned': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["bigint unsigned"]})') - elif col_type.lower() == 'bool': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["bool"]})') - elif col_type.lower() == 'float': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["float"]})') - elif col_type.lower() == 'double': - tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["double"]})') - elif 'binary' in col_type.lower(): - tdSql.execute(f'''insert into {tbname} values({self.ts+i},"{base_data['binary']}")''') - elif 'nchar' in col_type.lower(): - tdSql.execute(f'''insert into {tbname} values({self.ts+i},"{base_data['nchar']}")''') - def delete_all_data(self,tbname,col_type,row_num,base_data,dbname,tb_type,tb_num=1,stbname=''): - tdSql.query(f'select count(*) from {tbname}') - tdSql.execute(f'delete from {tbname}') - tdSql.execute(f'flush database {dbname}') - tdSql.execute('reset query cache') - tdSql.query(f'select * from {tbname}') - tdSql.checkRows(0) - if tb_type == 'ntb' or tb_type == 'ctb': - if tb_type == 'ctb': - tdSql.query(f'select count(*) from {stbname}') - if tb_num <= 1: - if len(tdSql.queryResult) != 0: - tdLog.exit('delete case failure!') - else: - tdSql.checkEqual(tdSql.queryResult[0][0],(tb_num-1)*row_num) - - self.insert_base_data(col_type,tbname,row_num,base_data) - elif tb_type == 'stb': - for i in range(tb_num): - self.insert_base_data(col_type,f'{tbname}_{i}',row_num,base_data) - tdSql.execute(f'flush database {dbname}') - tdSql.execute('reset query cache') - tdSql.query(f'select * from {tbname}') - if tb_type == 'ntb' or tb_type == 'ctb': - tdSql.checkRows(row_num) - elif tb_type =='stb': - tdSql.checkRows(row_num*tb_num) - def delete_one_row(self,tbname,column_type,column_name,base_data,row_num,dbname,tb_type,tb_num=1): - tdSql.execute(f'delete from {tbname} where ts={self.ts}') - tdSql.execute(f'flush database {dbname}') - tdSql.execute('reset query cache') - tdSql.query(f'select {column_name} from {tbname}') - if tb_type == 'ntb' or tb_type == 'ctb': - tdSql.checkRows(row_num-1) - elif tb_type == 'stb': - tdSql.checkRows((row_num-1)*tb_num) - tdSql.query(f'select {column_name} from {tbname} where ts={self.ts}') - tdSql.checkRows(0) - if tb_type == 'ntb' or tb_type == 'ctb': - if 'binary' in column_type.lower(): - tdSql.execute(f'''insert into {tbname} values({self.ts},"{base_data['binary']}")''') - elif 'nchar' in column_type.lower(): - tdSql.execute(f'''insert into {tbname} values({self.ts},"{base_data['nchar']}")''') - else: - tdSql.execute(f'insert into {tbname} values({self.ts},{base_data[column_type]})') - elif tb_type == 'stb': - for i in range(tb_num): - if 'binary' in column_type.lower(): - tdSql.execute(f'''insert into {tbname}_{i} values({self.ts},"{base_data['binary']}")''') - elif 'nchar' in column_type.lower(): - tdSql.execute(f'''insert into {tbname}_{i} values({self.ts},"{base_data['nchar']}")''') - else: - tdSql.execute(f'insert into {tbname}_{i} values({self.ts},{base_data[column_type]})') - tdSql.query(f'select {column_name} from {tbname} where ts={self.ts}') - if column_type.lower() == 'float' or column_type.lower() == 'double': - if abs(tdSql.queryResult[0][0] - base_data[column_type]) / base_data[column_type] <= 0.0001: - tdSql.checkEqual(tdSql.queryResult[0][0],tdSql.queryResult[0][0]) - else: - tdLog.exit(f'{column_type} data check failure') - elif 'binary' in column_type.lower(): - tdSql.checkEqual(tdSql.queryResult[0][0],base_data['binary']) - elif 'nchar' in column_type.lower(): - tdSql.checkEqual(tdSql.queryResult[0][0],base_data['nchar']) - else: - tdSql.checkEqual(tdSql.queryResult[0][0],base_data[column_type]) - def delete_rows(self,dbname,tbname,col_name,col_type,base_data,row_num,tb_type,tb_num=1): - for i in range(row_num): - tdSql.execute(f'delete from {tbname} where ts>{self.ts+i}') - tdSql.execute(f'flush database {dbname}') - tdSql.execute('reset query cache') - tdSql.query(f'select {col_name} from {tbname}') - if tb_type == 'ntb' or tb_type == 'ctb': - tdSql.checkRows(i+1) - self.insert_base_data(col_type,tbname,row_num,base_data) - elif tb_type == 'stb': - tdSql.checkRows((i+1)*tb_num) - for j in range(tb_num): - self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) - for i in range(row_num): - tdSql.execute(f'delete from {tbname} where ts>={self.ts+i}') - tdSql.execute(f'flush database {dbname}') - tdSql.execute('reset query cache') - tdSql.query(f'select {col_name} from {tbname}') - if tb_type == 'ntb' or tb_type == 'ctb': - tdSql.checkRows(i) - self.insert_base_data(col_type,tbname,row_num,base_data) - elif tb_type == 'stb': - tdSql.checkRows(i*tb_num) - for j in range(tb_num): - self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) - for i in range(row_num): - tdSql.execute(f'delete from {tbname} where ts<={self.ts+i}') - tdSql.execute(f'flush database {dbname}') - tdSql.execute('reset query cache') - tdSql.query(f'select {col_name} from {tbname}') - if tb_type == 'ntb' or tb_type == 'ctb': - tdSql.checkRows(row_num-i-1) - self.insert_base_data(col_type,tbname,row_num,base_data) - elif tb_type == 'stb': - tdSql.checkRows((row_num-i-1)*tb_num) - for j in range(tb_num): - self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) - for i in range(row_num): - tdSql.execute(f'delete from {tbname} where ts<{self.ts+i}') - tdSql.execute(f'flush database {dbname}') - tdSql.execute('reset query cache') - tdSql.query(f'select {col_name} from {tbname}') - if tb_type == 'ntb' or tb_type == 'ctb': - tdSql.checkRows(row_num-i) - self.insert_base_data(col_type,tbname,row_num,base_data) - elif tb_type == 'stb': - tdSql.checkRows((row_num-i)*tb_num) - for j in range(tb_num): - self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) - for i in range(row_num): - tdSql.execute(f'delete from {tbname} where ts between {self.ts} and {self.ts+i}') - tdSql.execute(f'flush database {dbname}') - tdSql.execute('reset query cache') - tdSql.query(f'select {col_name} from {tbname}') - if tb_type == 'ntb' or tb_type == 'ctb': - tdSql.checkRows(row_num - i-1) - self.insert_base_data(col_type,tbname,row_num,base_data) - elif tb_type == 'stb': - tdSql.checkRows(tb_num*(row_num - i-1)) - for j in range(tb_num): - self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) - tdSql.execute(f'delete from {tbname} where ts between {self.ts+i+1} and {self.ts}') - tdSql.query(f'select {col_name} from {tbname}') - if tb_type == 'ntb' or tb_type == 'ctb': - tdSql.checkRows(row_num) - elif tb_type == 'stb': - tdSql.checkRows(tb_num*row_num) - def delete_error(self,tbname,column_name,column_type,base_data): - for error_list in ['',f'ts = {self.ts} and',f'ts = {self.ts} or']: - if 'binary' in column_type.lower(): - tdSql.error(f'''delete from {tbname} where {error_list} {column_name} ="{base_data['binary']}"''') - elif 'nchar' in column_type.lower(): - tdSql.error(f'''delete from {tbname} where {error_list} {column_name} ="{base_data['nchar']}"''') - else: - tdSql.error(f'delete from {tbname} where {error_list} {column_name} = {base_data[column_type]}') - - def delete_data_ntb(self): - tdSql.execute(f'create database if not exists {self.dbname}') - tdSql.execute(f'use {self.dbname}') - for col_name,col_type in self.column_dict.items(): - tdSql.execute(f'create table {self.ntbname} (ts timestamp,{col_name} {col_type})') - self.insert_base_data(col_type,self.ntbname,self.rowNum,self.base_data) - self.delete_one_row(self.ntbname,col_type,col_name,self.base_data,self.rowNum,self.dbname,'ntb') - self.delete_all_data(self.ntbname,col_type,self.rowNum,self.base_data,self.dbname,'ntb') - self.delete_error(self.ntbname,col_name,col_type,self.base_data) - self.delete_rows(self.dbname,self.ntbname,col_name,col_type,self.base_data,self.rowNum,'ntb') - for func in ['first','last']: - tdSql.query(f'select {func}(*) from {self.ntbname}') - tdSql.execute(f'drop table {self.ntbname}') - tdSql.execute(f'drop database {self.dbname}') - def delete_data_ctb(self): - tdSql.execute(f'create database if not exists {self.dbname}') - tdSql.execute(f'use {self.dbname}') - for col_name,col_type in self.column_dict.items(): - tdSql.execute(f'create table {self.stbname} (ts timestamp,{col_name} {col_type}) tags(t1 int)') - for i in range(self.tbnum): - tdSql.execute(f'create table {self.stbname}_{i} using {self.stbname} tags(1)') - self.insert_base_data(col_type,f'{self.stbname}_{i}',self.rowNum,self.base_data) - self.delete_one_row(f'{self.stbname}_{i}',col_type,col_name,self.base_data,self.rowNum,self.dbname,'ctb') - self.delete_all_data(f'{self.stbname}_{i}',col_type,self.rowNum,self.base_data,self.dbname,'ctb',i+1,self.stbname) - self.delete_error(f'{self.stbname}_{i}',col_name,col_type,self.base_data) - self.delete_rows(self.dbname,f'{self.stbname}_{i}',col_name,col_type,self.base_data,self.rowNum,'ctb') - for func in ['first','last']: - tdSql.query(f'select {func}(*) from {self.stbname}_{i}') - tdSql.execute(f'drop table {self.stbname}') - def delete_data_stb(self): - tdSql.execute(f'create database if not exists {self.dbname}') - tdSql.execute(f'use {self.dbname}') - for col_name,col_type in self.column_dict.items(): - tdSql.execute(f'create table {self.stbname} (ts timestamp,{col_name} {col_type}) tags(t1 int)') - for i in range(self.tbnum): - tdSql.execute(f'create table {self.stbname}_{i} using {self.stbname} tags(1)') - self.insert_base_data(col_type,f'{self.stbname}_{i}',self.rowNum,self.base_data) - self.delete_error(self.stbname,col_name,col_type,self.base_data) - self.delete_one_row(self.stbname,col_type,col_name,self.base_data,self.rowNum,self.dbname,'stb',self.tbnum) - self.delete_all_data(self.stbname,col_type,self.rowNum,self.base_data,self.dbname,'stb',self.tbnum) - self.delete_rows(self.dbname,self.stbname,col_name,col_type,self.base_data,self.rowNum,'stb',self.tbnum) - for func in ['first','last']: - tdSql.query(f'select {func}(*) from {self.stbname}') - tdSql.execute(f'drop table {self.stbname}') - tdSql.execute(f'drop database {self.dbname}') - def run(self): - self.delete_data_ntb() - self.delete_data_ctb() - self.delete_data_stb() - tdDnodes.stoptaosd(1) - tdDnodes.starttaosd(1) - self.delete_data_ntb() - def stop(self): - tdSql.close() - tdLog.success("%s successfully executed" % __file__) - -tdCases.addWindows(__file__, TDTestCase()) -tdCases.addLinux(__file__, TDTestCase()) + +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import random +import string + +from numpy import logspace +from util import constant +from util.log import * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import TDSetSql + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), True) + self.dbname = 'db_test' + self.setsql = TDSetSql() + self.stbname = 'stb' + self.ntbname = 'ntb' + self.rowNum = 10 + self.tbnum = 3 + self.ts = 1537146000000 + self.binary_str = 'taosdata' + self.nchar_str = '涛思数据' + self.str_length = 20 + self.column_dict = { + 'col1': 'tinyint', + 'col2': 'smallint', + 'col3': 'int', + 'col4': 'bigint', + 'col5': 'tinyint unsigned', + 'col6': 'smallint unsigned', + 'col7': 'int unsigned', + 'col8': 'bigint unsigned', + 'col9': 'float', + 'col10': 'double', + 'col11': 'bool', + 'col12': f'binary({self.str_length})', + 'col13': f'nchar({self.str_length})', + + } + + self.tinyint_val = random.randint(constant.TINYINT_MIN,constant.TINYINT_MAX) + self.smallint_val = random.randint(constant.SMALLINT_MIN,constant.SMALLINT_MAX) + self.int_val = random.randint(constant.INT_MIN,constant.INT_MAX) + self.bigint_val = random.randint(constant.BIGINT_MIN,constant.BIGINT_MAX) + self.untingint_val = random.randint(constant.TINYINT_UN_MIN,constant.TINYINT_UN_MAX) + self.unsmallint_val = random.randint(constant.SMALLINT_UN_MIN,constant.SMALLINT_UN_MAX) + self.unint_val = random.randint(constant.INT_UN_MIN,constant.INT_MAX) + self.unbigint_val = random.randint(constant.BIGINT_UN_MIN,constant.BIGINT_UN_MAX) + self.float_val = random.uniform(constant.FLOAT_MIN,constant.FLOAT_MAX) + self.double_val = random.uniform(constant.DOUBLE_MIN*(1E-300),constant.DOUBLE_MAX*(1E-300)) + self.bool_val = random.randint(0,100)%2 + self.binary_val = tdCom.getLongName(random.randint(0,self.str_length)) + self.nchar_val = tdCom.getLongName(random.randint(0,self.str_length)) + self.base_data = { + 'tinyint':self.tinyint_val, + 'smallint':self.smallint_val, + 'int':self.int_val, + 'bigint':self.bigint_val, + 'tinyint unsigned':self.untingint_val, + 'smallint unsigned':self.unsmallint_val, + 'int unsigned':self.unint_val, + 'bigint unsigned':self.unbigint_val, + 'bool':self.bool_val, + 'float':self.float_val, + 'double':self.double_val, + 'binary':self.binary_val, + 'nchar':self.nchar_val + } + + def insert_base_data(self,col_type,tbname,rows,base_data): + for i in range(rows): + if col_type.lower() == 'tinyint': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["tinyint"]})') + elif col_type.lower() == 'smallint': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["smallint"]})') + elif col_type.lower() == 'int': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["int"]})') + elif col_type.lower() == 'bigint': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["bigint"]})') + elif col_type.lower() == 'tinyint unsigned': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["tinyint unsigned"]})') + elif col_type.lower() == 'smallint unsigned': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["smallint unsigned"]})') + elif col_type.lower() == 'int unsigned': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["int unsigned"]})') + elif col_type.lower() == 'bigint unsigned': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["bigint unsigned"]})') + elif col_type.lower() == 'bool': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["bool"]})') + elif col_type.lower() == 'float': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["float"]})') + elif col_type.lower() == 'double': + tdSql.execute(f'insert into {tbname} values({self.ts+i},{base_data["double"]})') + elif 'binary' in col_type.lower(): + tdSql.execute(f'''insert into {tbname} values({self.ts+i},"{base_data['binary']}")''') + elif 'nchar' in col_type.lower(): + tdSql.execute(f'''insert into {tbname} values({self.ts+i},"{base_data['nchar']}")''') + def delete_all_data(self,tbname,col_type,row_num,base_data,dbname,tb_type,tb_num=1,stbname=''): + tdSql.query(f'select count(*) from {tbname}') + tdSql.execute(f'delete from {tbname}') + tdSql.execute(f'flush database {dbname}') + tdSql.execute('reset query cache') + tdSql.query(f'select * from {tbname}') + tdSql.checkRows(0) + if tb_type == 'ntb' or tb_type == 'ctb': + if tb_type == 'ctb': + tdSql.query(f'select count(*) from {stbname}') + if tb_num <= 1: + if len(tdSql.queryResult) != 0: + tdLog.exit('delete case failure!') + else: + tdSql.checkEqual(tdSql.queryResult[0][0],(tb_num-1)*row_num) + + self.insert_base_data(col_type,tbname,row_num,base_data) + elif tb_type == 'stb': + for i in range(tb_num): + self.insert_base_data(col_type,f'{tbname}_{i}',row_num,base_data) + tdSql.execute(f'flush database {dbname}') + tdSql.execute('reset query cache') + tdSql.query(f'select * from {tbname}') + if tb_type == 'ntb' or tb_type == 'ctb': + tdSql.checkRows(row_num) + elif tb_type =='stb': + tdSql.checkRows(row_num*tb_num) + def delete_one_row(self,tbname,column_type,column_name,base_data,row_num,dbname,tb_type,tb_num=1): + tdSql.execute(f'delete from {tbname} where ts={self.ts}') + tdSql.execute(f'flush database {dbname}') + tdSql.execute('reset query cache') + tdSql.query(f'select {column_name} from {tbname}') + if tb_type == 'ntb' or tb_type == 'ctb': + tdSql.checkRows(row_num-1) + elif tb_type == 'stb': + tdSql.checkRows((row_num-1)*tb_num) + tdSql.query(f'select {column_name} from {tbname} where ts={self.ts}') + tdSql.checkRows(0) + if tb_type == 'ntb' or tb_type == 'ctb': + if 'binary' in column_type.lower(): + tdSql.execute(f'''insert into {tbname} values({self.ts},"{base_data['binary']}")''') + elif 'nchar' in column_type.lower(): + tdSql.execute(f'''insert into {tbname} values({self.ts},"{base_data['nchar']}")''') + else: + tdSql.execute(f'insert into {tbname} values({self.ts},{base_data[column_type]})') + elif tb_type == 'stb': + for i in range(tb_num): + if 'binary' in column_type.lower(): + tdSql.execute(f'''insert into {tbname}_{i} values({self.ts},"{base_data['binary']}")''') + elif 'nchar' in column_type.lower(): + tdSql.execute(f'''insert into {tbname}_{i} values({self.ts},"{base_data['nchar']}")''') + else: + tdSql.execute(f'insert into {tbname}_{i} values({self.ts},{base_data[column_type]})') + tdSql.query(f'select {column_name} from {tbname} where ts={self.ts}') + if column_type.lower() == 'float' or column_type.lower() == 'double': + if abs(tdSql.queryResult[0][0] - base_data[column_type]) / base_data[column_type] <= 0.0001: + tdSql.checkEqual(tdSql.queryResult[0][0],tdSql.queryResult[0][0]) + else: + tdLog.exit(f'{column_type} data check failure') + elif 'binary' in column_type.lower(): + tdSql.checkEqual(tdSql.queryResult[0][0],base_data['binary']) + elif 'nchar' in column_type.lower(): + tdSql.checkEqual(tdSql.queryResult[0][0],base_data['nchar']) + else: + tdSql.checkEqual(tdSql.queryResult[0][0],base_data[column_type]) + def delete_rows(self,dbname,tbname,col_name,col_type,base_data,row_num,tb_type,tb_num=1): + for i in range(row_num): + tdSql.execute(f'delete from {tbname} where ts>{self.ts+i}') + tdSql.execute(f'flush database {dbname}') + tdSql.execute('reset query cache') + tdSql.query(f'select {col_name} from {tbname}') + if tb_type == 'ntb' or tb_type == 'ctb': + tdSql.checkRows(i+1) + self.insert_base_data(col_type,tbname,row_num,base_data) + elif tb_type == 'stb': + tdSql.checkRows((i+1)*tb_num) + for j in range(tb_num): + self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) + for i in range(row_num): + tdSql.execute(f'delete from {tbname} where ts>={self.ts+i}') + tdSql.execute(f'flush database {dbname}') + tdSql.execute('reset query cache') + tdSql.query(f'select {col_name} from {tbname}') + if tb_type == 'ntb' or tb_type == 'ctb': + tdSql.checkRows(i) + self.insert_base_data(col_type,tbname,row_num,base_data) + elif tb_type == 'stb': + tdSql.checkRows(i*tb_num) + for j in range(tb_num): + self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) + for i in range(row_num): + tdSql.execute(f'delete from {tbname} where ts<={self.ts+i}') + tdSql.execute(f'flush database {dbname}') + tdSql.execute('reset query cache') + tdSql.query(f'select {col_name} from {tbname}') + if tb_type == 'ntb' or tb_type == 'ctb': + tdSql.checkRows(row_num-i-1) + self.insert_base_data(col_type,tbname,row_num,base_data) + elif tb_type == 'stb': + tdSql.checkRows((row_num-i-1)*tb_num) + for j in range(tb_num): + self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) + for i in range(row_num): + tdSql.execute(f'delete from {tbname} where ts<{self.ts+i}') + tdSql.execute(f'flush database {dbname}') + tdSql.execute('reset query cache') + tdSql.query(f'select {col_name} from {tbname}') + if tb_type == 'ntb' or tb_type == 'ctb': + tdSql.checkRows(row_num-i) + self.insert_base_data(col_type,tbname,row_num,base_data) + elif tb_type == 'stb': + tdSql.checkRows((row_num-i)*tb_num) + for j in range(tb_num): + self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) + for i in range(row_num): + tdSql.execute(f'delete from {tbname} where ts between {self.ts} and {self.ts+i}') + tdSql.execute(f'flush database {dbname}') + tdSql.execute('reset query cache') + tdSql.query(f'select {col_name} from {tbname}') + if tb_type == 'ntb' or tb_type == 'ctb': + tdSql.checkRows(row_num - i-1) + self.insert_base_data(col_type,tbname,row_num,base_data) + elif tb_type == 'stb': + tdSql.checkRows(tb_num*(row_num - i-1)) + for j in range(tb_num): + self.insert_base_data(col_type,f'{tbname}_{j}',row_num,base_data) + tdSql.execute(f'delete from {tbname} where ts between {self.ts+i+1} and {self.ts}') + tdSql.query(f'select {col_name} from {tbname}') + if tb_type == 'ntb' or tb_type == 'ctb': + tdSql.checkRows(row_num) + elif tb_type == 'stb': + tdSql.checkRows(tb_num*row_num) + def delete_error(self,tbname,column_name,column_type,base_data): + for error_list in ['',f'ts = {self.ts} and',f'ts = {self.ts} or']: + if 'binary' in column_type.lower(): + tdSql.error(f'''delete from {tbname} where {error_list} {column_name} ="{base_data['binary']}"''') + elif 'nchar' in column_type.lower(): + tdSql.error(f'''delete from {tbname} where {error_list} {column_name} ="{base_data['nchar']}"''') + else: + tdSql.error(f'delete from {tbname} where {error_list} {column_name} = {base_data[column_type]}') + + def delete_data_ntb(self): + tdSql.execute(f'create database if not exists {self.dbname}') + tdSql.execute(f'use {self.dbname}') + for col_name,col_type in self.column_dict.items(): + tdSql.execute(f'create table {self.ntbname} (ts timestamp,{col_name} {col_type})') + self.insert_base_data(col_type,self.ntbname,self.rowNum,self.base_data) + self.delete_one_row(self.ntbname,col_type,col_name,self.base_data,self.rowNum,self.dbname,'ntb') + self.delete_all_data(self.ntbname,col_type,self.rowNum,self.base_data,self.dbname,'ntb') + self.delete_error(self.ntbname,col_name,col_type,self.base_data) + self.delete_rows(self.dbname,self.ntbname,col_name,col_type,self.base_data,self.rowNum,'ntb') + for func in ['first','last']: + tdSql.query(f'select {func}(*) from {self.ntbname}') + tdSql.execute(f'drop table {self.ntbname}') + tdSql.execute(f'drop database {self.dbname}') + def delete_data_ctb(self): + tdSql.execute(f'create database if not exists {self.dbname}') + tdSql.execute(f'use {self.dbname}') + for col_name,col_type in self.column_dict.items(): + tdSql.execute(f'create table {self.stbname} (ts timestamp,{col_name} {col_type}) tags(t1 int)') + for i in range(self.tbnum): + tdSql.execute(f'create table {self.stbname}_{i} using {self.stbname} tags(1)') + self.insert_base_data(col_type,f'{self.stbname}_{i}',self.rowNum,self.base_data) + self.delete_one_row(f'{self.stbname}_{i}',col_type,col_name,self.base_data,self.rowNum,self.dbname,'ctb') + self.delete_all_data(f'{self.stbname}_{i}',col_type,self.rowNum,self.base_data,self.dbname,'ctb',i+1,self.stbname) + self.delete_error(f'{self.stbname}_{i}',col_name,col_type,self.base_data) + self.delete_rows(self.dbname,f'{self.stbname}_{i}',col_name,col_type,self.base_data,self.rowNum,'ctb') + for func in ['first','last']: + tdSql.query(f'select {func}(*) from {self.stbname}_{i}') + tdSql.execute(f'drop table {self.stbname}') + def delete_data_stb(self): + tdSql.execute(f'create database if not exists {self.dbname}') + tdSql.execute(f'use {self.dbname}') + for col_name,col_type in self.column_dict.items(): + tdSql.execute(f'create table {self.stbname} (ts timestamp,{col_name} {col_type}) tags(t1 int)') + for i in range(self.tbnum): + tdSql.execute(f'create table {self.stbname}_{i} using {self.stbname} tags(1)') + self.insert_base_data(col_type,f'{self.stbname}_{i}',self.rowNum,self.base_data) + self.delete_error(self.stbname,col_name,col_type,self.base_data) + self.delete_one_row(self.stbname,col_type,col_name,self.base_data,self.rowNum,self.dbname,'stb',self.tbnum) + self.delete_all_data(self.stbname,col_type,self.rowNum,self.base_data,self.dbname,'stb',self.tbnum) + self.delete_rows(self.dbname,self.stbname,col_name,col_type,self.base_data,self.rowNum,'stb',self.tbnum) + for func in ['first','last']: + tdSql.query(f'select {func}(*) from {self.stbname}') + tdSql.execute(f'drop table {self.stbname}') + tdSql.execute(f'drop database {self.dbname}') + def run(self): + self.delete_data_ntb() + self.delete_data_ctb() + self.delete_data_stb() + tdDnodes.stoptaosd(1) + tdDnodes.starttaosd(1) + self.delete_data_ntb() + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) \ No newline at end of file diff --git a/tests/system-test/fulltest.sh b/tests/system-test/fulltest.sh index 622dbba223..913ce557bd 100755 --- a/tests/system-test/fulltest.sh +++ b/tests/system-test/fulltest.sh @@ -76,8 +76,8 @@ python3 ./test.py -f 2-query/count_partition.py python3 ./test.py -f 2-query/count_partition.py -R python3 ./test.py -f 2-query/count.py python3 ./test.py -f 2-query/count.py -R -python3 ./test.py -f 2-query/countAlwaysReturnValue.py -python3 ./test.py -f 2-query/countAlwaysReturnValue.py -R +# python3 ./test.py -f 2-query/countAlwaysReturnValue.py +# python3 ./test.py -f 2-query/countAlwaysReturnValue.py -R python3 ./test.py -f 2-query/db.py python3 ./test.py -f 2-query/db.py -R python3 ./test.py -f 2-query/diff.py @@ -387,7 +387,7 @@ python3 ./test.py -f 2-query/Today.py -Q 2 python3 ./test.py -f 2-query/max.py -Q 2 python3 ./test.py -f 2-query/min.py -Q 2 python3 ./test.py -f 2-query/count.py -Q 2 -python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 2 +# python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 2 python3 ./test.py -f 2-query/last.py -Q 2 python3 ./test.py -f 2-query/first.py -Q 2 python3 ./test.py -f 2-query/To_iso8601.py -Q 2 @@ -483,7 +483,7 @@ python3 ./test.py -f 2-query/Today.py -Q 3 python3 ./test.py -f 2-query/max.py -Q 3 python3 ./test.py -f 2-query/min.py -Q 3 python3 ./test.py -f 2-query/count.py -Q 3 -python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 3 +# python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 3 python3 ./test.py -f 2-query/last.py -Q 3 python3 ./test.py -f 2-query/first.py -Q 3 python3 ./test.py -f 2-query/To_iso8601.py -Q 3 @@ -581,7 +581,7 @@ python3 ./test.py -f 2-query/Today.py -Q 4 python3 ./test.py -f 2-query/max.py -Q 4 python3 ./test.py -f 2-query/min.py -Q 4 python3 ./test.py -f 2-query/count.py -Q 4 -python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 4 +# python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 4 python3 ./test.py -f 2-query/last.py -Q 4 python3 ./test.py -f 2-query/first.py -Q 4 python3 ./test.py -f 2-query/To_iso8601.py -Q 4