From 719cebdd87d0904dd57cbf6297ce8789324cb974 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Tue, 31 May 2022 21:03:47 +0800 Subject: [PATCH 1/2] stmt new api --- include/client/taos.h | 10 +++ include/libs/parser/parser.h | 4 +- source/client/inc/clientStmt.h | 3 + source/client/src/clientMain.c | 41 ++++++++++ source/client/src/clientStmt.c | 121 +++++++++++++++++++++++++++-- source/libs/parser/src/parInsert.c | 23 +++--- 6 files changed, 184 insertions(+), 18 deletions(-) diff --git a/include/client/taos.h b/include/client/taos.h index 0b8c67aa79..94e6221b31 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -85,6 +85,14 @@ typedef struct taosField { int32_t bytes; } TAOS_FIELD; +typedef struct TAOS_FIELD_E { + char name[65]; + int8_t type; + uint8_t precision; + uint8_t scale; + int32_t bytes; +} TAOS_FIELD_E; + #ifdef WINDOWS #define DLL_EXPORT __declspec(dllexport) #else @@ -135,6 +143,8 @@ DLL_EXPORT int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsign 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); DLL_EXPORT int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name); +DLL_EXPORT int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields); +DLL_EXPORT int taos_stmt_get_col_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields); DLL_EXPORT int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert); DLL_EXPORT int taos_stmt_num_params(TAOS_STMT *stmt, int *nums); diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 06272b8151..ca825b9e2f 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -77,8 +77,8 @@ int32_t qStmtParseQuerySql(SParseContext* pCxt, SQuery* pQuery); int32_t qBindStmtColsValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen); int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen, int32_t colIdx, int32_t rowNum); -int32_t qBuildStmtColFields(void* pDataBlock, int32_t* fieldNum, TAOS_FIELD** fields); -int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TAOS_FIELD** fields); +int32_t qBuildStmtColFields(void* pDataBlock, int32_t* fieldNum, TAOS_FIELD_E** fields); +int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TAOS_FIELD_E** fields); int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tName, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen); void destroyBoundColumnInfo(void* pBoundInfo); diff --git a/source/client/inc/clientStmt.h b/source/client/inc/clientStmt.h index f0c9dcd67d..936fb92fc4 100644 --- a/source/client/inc/clientStmt.h +++ b/source/client/inc/clientStmt.h @@ -116,8 +116,11 @@ int stmtAffectedRowsOnce(TAOS_STMT *stmt); int stmtPrepare(TAOS_STMT *stmt, const char *sql, unsigned long length); int stmtSetTbName(TAOS_STMT *stmt, const char *tbName); int stmtSetTbTags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags); +int stmtGetTagFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields); +int stmtGetColFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields); int stmtIsInsert(TAOS_STMT *stmt, int *insert); int stmtGetParamNum(TAOS_STMT *stmt, int *nums); +int stmtGetParam(TAOS_STMT *stmt, int idx, int *type, int *bytes); int stmtAddBatch(TAOS_STMT *stmt); TAOS_RES *stmtUseResult(TAOS_STMT *stmt); int stmtBindBatch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int32_t colIdx); diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 53eb443b36..e144885e9e 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -666,8 +666,39 @@ int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) { return stmtSetTbName(stmt, name); } +int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) { + if (stmt == NULL || tags == NULL) { + tscError("NULL parameter for %s", __FUNCTION__); + terrno = TSDB_CODE_INVALID_PARA; + return terrno; + } + + return stmtSetTbTags(stmt, tags); +} + + int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); } +int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields) { + if (stmt == NULL || NULL == fieldNum) { + tscError("NULL parameter for %s", __FUNCTION__); + terrno = TSDB_CODE_INVALID_PARA; + return terrno; + } + + return stmtGetTagFields(stmt, fieldNum, fields); +} + +int taos_stmt_get_col_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields) { + if (stmt == NULL || NULL == fieldNum) { + tscError("NULL parameter for %s", __FUNCTION__); + terrno = TSDB_CODE_INVALID_PARA; + return terrno; + } + + return stmtGetColFields(stmt, fieldNum, fields); +} + int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) { if (stmt == NULL || bind == NULL) { tscError("NULL parameter for %s", __FUNCTION__); @@ -772,6 +803,16 @@ int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) { return stmtGetParamNum(stmt, nums); } +int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) { + if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) { + tscError("invalid parameter for %s", __FUNCTION__); + terrno = TSDB_CODE_INVALID_PARA; + return terrno; + } + + return stmtGetParam(stmt, idx, type, bytes); +} + TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) { if (stmt == NULL) { tscError("NULL parameter for %s", __FUNCTION__); diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c index 01d785ef73..3adb3684da 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -17,7 +17,7 @@ int32_t stmtSwitchStatus(STscStmt* pStmt, STMT_STATUS newStatus) { } break; case STMT_SETTAGS: - if (STMT_STATUS_NE(SETTBNAME)) { + if (STMT_STATUS_NE(SETTBNAME) && STMT_STATUS_NE(FETCH_FIELDS)) { code = TSDB_CODE_TSC_STMT_API_ERROR; } break; @@ -540,6 +540,8 @@ int stmtSetTbName(TAOS_STMT* stmt, const char* tbName) { if (pStmt->bInfo.needParse) { strncpy(pStmt->bInfo.tbName, tbName, sizeof(pStmt->bInfo.tbName) - 1); pStmt->bInfo.tbName[sizeof(pStmt->bInfo.tbName) - 1] = 0; + + STMT_ERR_RET(stmtParseSql(pStmt)); } return TSDB_CODE_SUCCESS; @@ -550,10 +552,6 @@ int stmtSetTbTags(TAOS_STMT* stmt, TAOS_MULTI_BIND* tags) { STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTAGS)); - if (pStmt->bInfo.needParse) { - STMT_ERR_RET(stmtParseSql(pStmt)); - } - if (pStmt->bInfo.inExecCache) { return TSDB_CODE_SUCCESS; } @@ -571,7 +569,7 @@ int stmtSetTbTags(TAOS_STMT* stmt, TAOS_MULTI_BIND* tags) { return TSDB_CODE_SUCCESS; } -int32_t stmtFetchTagFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD** fields) { +int stmtFetchTagFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields) { if (STMT_TYPE_QUERY == pStmt->sql.type) { tscError("invalid operation to get query tag fileds"); STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR); @@ -589,7 +587,7 @@ int32_t stmtFetchTagFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD** fiel return TSDB_CODE_SUCCESS; } -int32_t stmtFetchColFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD** fields) { +int stmtFetchColFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields) { if (STMT_TYPE_QUERY == pStmt->sql.type) { tscError("invalid operation to get query column fileds"); STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR); @@ -852,6 +850,71 @@ int stmtIsInsert(TAOS_STMT* stmt, int* insert) { return TSDB_CODE_SUCCESS; } +int stmtGetTagFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) { + STscStmt* pStmt = (STscStmt*)stmt; + + if (STMT_TYPE_QUERY == pStmt->sql.type) { + STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR); + } + + STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS)); + + if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 && + STMT_TYPE_MULTI_INSERT != pStmt->sql.type) { + pStmt->bInfo.needParse = false; + } + + if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) { + taos_free_result(pStmt->exec.pRequest); + pStmt->exec.pRequest = NULL; + } + + if (NULL == pStmt->exec.pRequest) { + STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest)); + } + + if (pStmt->bInfo.needParse) { + STMT_ERR_RET(stmtParseSql(pStmt)); + } + + STMT_ERR_RET(stmtFetchTagFields(stmt, nums, fields)); + + return TSDB_CODE_SUCCESS; +} + +int stmtGetColFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) { + STscStmt* pStmt = (STscStmt*)stmt; + + if (STMT_TYPE_QUERY == pStmt->sql.type) { + STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR); + } + + STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS)); + + if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 && + STMT_TYPE_MULTI_INSERT != pStmt->sql.type) { + pStmt->bInfo.needParse = false; + } + + if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) { + taos_free_result(pStmt->exec.pRequest); + pStmt->exec.pRequest = NULL; + } + + if (NULL == pStmt->exec.pRequest) { + STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest)); + } + + if (pStmt->bInfo.needParse) { + STMT_ERR_RET(stmtParseSql(pStmt)); + } + + STMT_ERR_RET(stmtFetchColFields(stmt, nums, fields)); + + return TSDB_CODE_SUCCESS; +} + + int stmtGetParamNum(TAOS_STMT* stmt, int* nums) { STscStmt* pStmt = (STscStmt*)stmt; @@ -884,6 +947,50 @@ int stmtGetParamNum(TAOS_STMT* stmt, int* nums) { return TSDB_CODE_SUCCESS; } +int stmtGetParam(TAOS_STMT *stmt, int idx, int *type, int *bytes) { + STscStmt* pStmt = (STscStmt*)stmt; + + if (STMT_TYPE_QUERY == pStmt->sql.type) { + STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR); + } + + STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS)); + + if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 && + STMT_TYPE_MULTI_INSERT != pStmt->sql.type) { + pStmt->bInfo.needParse = false; + } + + if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) { + taos_free_result(pStmt->exec.pRequest); + pStmt->exec.pRequest = NULL; + } + + if (NULL == pStmt->exec.pRequest) { + STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest)); + } + + if (pStmt->bInfo.needParse) { + STMT_ERR_RET(stmtParseSql(pStmt)); + } + + int32_t nums = 0; + TAOS_FIELD_E *pField = NULL; + STMT_ERR_RET(stmtFetchColFields(stmt, &nums, &pField)); + if (idx >= nums) { + tscError("idx %d is too big", idx); + taosMemoryFree(pField); + STMT_ERR_RET(TSDB_CODE_INVALID_PARA); + } + + *type = pField[idx].type; + *bytes = pField[idx].bytes; + + taosMemoryFree(pField); + + return TSDB_CODE_SUCCESS; +} + TAOS_RES* stmtUseResult(TAOS_STMT* stmt) { STscStmt* pStmt = (STscStmt*)stmt; diff --git a/source/libs/parser/src/parInsert.c b/source/libs/parser/src/parInsert.c index 047c2d1504..a6e2473c4f 100644 --- a/source/libs/parser/src/parInsert.c +++ b/source/libs/parser/src/parInsert.c @@ -1724,18 +1724,23 @@ int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBu return TSDB_CODE_SUCCESS; } -int32_t buildBoundFields(SParsedDataColInfo* boundInfo, SSchema* pSchema, int32_t* fieldNum, TAOS_FIELD** fields) { +int32_t buildBoundFields(SParsedDataColInfo* boundInfo, SSchema* pSchema, int32_t* fieldNum, TAOS_FIELD_E** fields, uint8_t timePrec) { if (fields) { *fields = taosMemoryCalloc(boundInfo->numOfBound, sizeof(TAOS_FIELD)); if (NULL == *fields) { return TSDB_CODE_OUT_OF_MEMORY; } + SSchema* pSchema = &pSchema[boundInfo->boundColumns[0]]; + if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type) { + (*fields)[0].precision = timePrec; + } + for (int32_t i = 0; i < boundInfo->numOfBound; ++i) { - SSchema* pTagSchema = &pSchema[boundInfo->boundColumns[i]]; - strcpy((*fields)[i].name, pTagSchema->name); - (*fields)[i].type = pTagSchema->type; - (*fields)[i].bytes = pTagSchema->bytes; + SSchema* pSchema = &pSchema[boundInfo->boundColumns[i]]; + strcpy((*fields)[i].name, pSchema->name); + (*fields)[i].type = pSchema->type; + (*fields)[i].bytes = pSchema->bytes; } } @@ -1744,7 +1749,7 @@ int32_t buildBoundFields(SParsedDataColInfo* boundInfo, SSchema* pSchema, int32_ return TSDB_CODE_SUCCESS; } -int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TAOS_FIELD** fields) { +int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TAOS_FIELD_E** fields) { STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; SParsedDataColInfo* tags = (SParsedDataColInfo*)boundTags; if (NULL == tags) { @@ -1759,12 +1764,12 @@ int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TA return TSDB_CODE_SUCCESS; } - CHECK_CODE(buildBoundFields(tags, pSchema, fieldNum, fields)); + CHECK_CODE(buildBoundFields(tags, pSchema, fieldNum, fields, 0)); return TSDB_CODE_SUCCESS; } -int32_t qBuildStmtColFields(void* pBlock, int32_t* fieldNum, TAOS_FIELD** fields) { +int32_t qBuildStmtColFields(void* pBlock, int32_t* fieldNum, TAOS_FIELD_E** fields) { STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; SSchema* pSchema = getTableColumnSchema(pDataBlock->pTableMeta); if (pDataBlock->boundColumnInfo.numOfBound <= 0) { @@ -1776,7 +1781,7 @@ int32_t qBuildStmtColFields(void* pBlock, int32_t* fieldNum, TAOS_FIELD** fields return TSDB_CODE_SUCCESS; } - CHECK_CODE(buildBoundFields(&pDataBlock->boundColumnInfo, pSchema, fieldNum, fields)); + CHECK_CODE(buildBoundFields(&pDataBlock->boundColumnInfo, pSchema, fieldNum, fields, pDataBlock->pTableMeta->tableInfo.precision)); return TSDB_CODE_SUCCESS; } From d86d8803be02a081a9a0b0b1b0bfd0afb61232e9 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 1 Jun 2022 13:14:28 +0800 Subject: [PATCH 2/2] stmt new api --- include/client/taos.h | 1 + source/libs/parser/src/parInsert.c | 18 +- source/libs/parser/src/parTranslater.c | 3 +- tests/script/api/batchprepare.c | 318 +++++++++++++++++++------ 4 files changed, 263 insertions(+), 77 deletions(-) diff --git a/include/client/taos.h b/include/client/taos.h index 94e6221b31..97b94e0a53 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -142,6 +142,7 @@ DLL_EXPORT TAOS_STMT *taos_stmt_init(TAOS *taos); 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); +DLL_EXPORT int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags); DLL_EXPORT int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name); DLL_EXPORT int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields); DLL_EXPORT int taos_stmt_get_col_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields); diff --git a/source/libs/parser/src/parInsert.c b/source/libs/parser/src/parInsert.c index a6e2473c4f..8a843c2c1a 100644 --- a/source/libs/parser/src/parInsert.c +++ b/source/libs/parser/src/parInsert.c @@ -1525,14 +1525,14 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tN SKvParam param = {.builder = &tagBuilder}; for (int c = 0; c < tags->numOfBound; ++c) { + SSchema* pTagSchema = &pSchema[tags->boundColumns[c]]; + param.schema = pTagSchema; + if (bind[c].is_null && bind[c].is_null[0]) { KvRowAppend(&pBuf, NULL, 0, ¶m); continue; } - SSchema* pTagSchema = &pSchema[tags->boundColumns[c]]; - param.schema = pTagSchema; - int32_t colLen = pTagSchema->bytes; if (IS_VAR_DATA_TYPE(pTagSchema->type)) { colLen = bind[c].length[0]; @@ -1731,16 +1731,16 @@ int32_t buildBoundFields(SParsedDataColInfo* boundInfo, SSchema* pSchema, int32_ return TSDB_CODE_OUT_OF_MEMORY; } - SSchema* pSchema = &pSchema[boundInfo->boundColumns[0]]; - if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type) { + SSchema* schema = &pSchema[boundInfo->boundColumns[0]]; + if (TSDB_DATA_TYPE_TIMESTAMP == schema->type) { (*fields)[0].precision = timePrec; } for (int32_t i = 0; i < boundInfo->numOfBound; ++i) { - SSchema* pSchema = &pSchema[boundInfo->boundColumns[i]]; - strcpy((*fields)[i].name, pSchema->name); - (*fields)[i].type = pSchema->type; - (*fields)[i].bytes = pSchema->bytes; + schema = &pSchema[boundInfo->boundColumns[i]]; + strcpy((*fields)[i].name, schema->name); + (*fields)[i].type = schema->type; + (*fields)[i].bytes = schema->bytes; } } diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 0dda71023f..a64d6de71f 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -830,7 +830,8 @@ static EDealRes translateComparisonOperator(STranslateContext* pCxt, SOperatorNo if (!IS_VAR_DATA_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) { return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName); } - if (QUERY_NODE_VALUE != nodeType(pOp->pRight) || !IS_STR_DATA_TYPE(((SExprNode*)(pOp->pRight))->resType.type)) { + if (QUERY_NODE_VALUE != nodeType(pOp->pRight) || + ((!IS_STR_DATA_TYPE(((SExprNode*)(pOp->pRight))->resType.type)) && (((SExprNode*)(pOp->pRight))->resType.type != TSDB_DATA_TYPE_NULL))) { return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); } } diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 2ded58a979..7dd7621d0b 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -10,6 +10,9 @@ #include "../../../include/client/taos.h" #define FUNCTION_TEST_IDX 1 +#define TIME_PRECISION_MILLI 0 +#define TIME_PRECISION_MICRO 1 +#define TIME_PRECISION_NANO 2 int32_t shortColList[] = {TSDB_DATA_TYPE_TIMESTAMP, TSDB_DATA_TYPE_INT}; int32_t fullColList[] = {TSDB_DATA_TYPE_TIMESTAMP, TSDB_DATA_TYPE_BOOL, TSDB_DATA_TYPE_TINYINT, TSDB_DATA_TYPE_UTINYINT, TSDB_DATA_TYPE_SMALLINT, TSDB_DATA_TYPE_USMALLINT, TSDB_DATA_TYPE_INT, TSDB_DATA_TYPE_UINT, TSDB_DATA_TYPE_BIGINT, TSDB_DATA_TYPE_UBIGINT, TSDB_DATA_TYPE_FLOAT, TSDB_DATA_TYPE_DOUBLE, TSDB_DATA_TYPE_BINARY, TSDB_DATA_TYPE_NCHAR}; @@ -32,6 +35,8 @@ typedef enum { BP_BIND_COL, } BP_BIND_TYPE; +#define BP_BIND_TYPE_STR(t) (((t) == BP_BIND_COL) ? "column" : "tag") + OperInfo operInfo[] = { {">", 2, false}, {">=", 2, false}, @@ -57,11 +62,12 @@ FuncInfo funcInfo[] = { {"min", 1}, }; +#define BP_STARTUP_TS 1591060628000 + char *bpStbPrefix = "st"; char *bpTbPrefix = "t"; int32_t bpDefaultStbId = 1; - - +int64_t bpTs; //char *operatorList[] = {">", ">=", "<", "<=", "=", "<>", "in", "not in"}; //char *varoperatorList[] = {">", ">=", "<", "<=", "=", "<>", "in", "not in", "like", "not like", "match", "nmatch"}; @@ -188,8 +194,10 @@ typedef struct { bool printCreateTblSql; bool printQuerySql; bool printStmtSql; + bool printVerbose; bool autoCreateTbl; bool numericParam; + uint8_t precision; int32_t rowNum; //row num for one table int32_t bindColNum; int32_t bindTagNum; @@ -209,12 +217,15 @@ typedef struct { int32_t caseRunNum; // total run case num } CaseCtrl; -#if 1 +#if 0 CaseCtrl gCaseCtrl = { // default + .precision = TIME_PRECISION_MICRO, .bindNullNum = 0, .printCreateTblSql = false, .printQuerySql = true, .printStmtSql = true, + .printVerbose = false, + .printRes = false, .autoCreateTbl = false, .numericParam = false, .rowNum = 0, @@ -230,7 +241,6 @@ CaseCtrl gCaseCtrl = { // default .funcIdxListNum = 0, .funcIdxList = NULL, .checkParamNum = false, - .printRes = false, .runTimes = 0, .caseIdx = -1, .caseNum = -1, @@ -240,26 +250,35 @@ CaseCtrl gCaseCtrl = { // default #endif -#if 0 +#if 1 CaseCtrl gCaseCtrl = { + .precision = TIME_PRECISION_MILLI, .bindNullNum = 0, - .printCreateTblSql = true, + .printCreateTblSql = false, .printQuerySql = true, .printStmtSql = true, + .printVerbose = false, + .printRes = true, .autoCreateTbl = false, + .numericParam = false, .rowNum = 0, .bindColNum = 0, .bindTagNum = 0, .bindRowNum = 0, + .bindColTypeNum = 0, + .bindColTypeList = NULL, .bindTagTypeNum = 0, .bindTagTypeList = NULL, + .optrIdxListNum = 0, + .optrIdxList = NULL, + .funcIdxListNum = 0, + .funcIdxList = NULL, .checkParamNum = false, - .printRes = false, .runTimes = 0, - .caseIdx = 1, - .caseNum = 1, + .caseIdx = -1, + .caseNum = -1, .caseRunIdx = -1, - .caseRunNum = 1, + .caseRunNum = -1, }; #endif @@ -891,7 +910,6 @@ int32_t prepareColData(BP_BIND_TYPE bType, BindData *data, int32_t bindIdx, int3 int32_t prepareInsertData(BindData *data) { - static int64_t tsData = 1591060628000; uint64_t allRowNum = gCurCase->rowNum * gCurCase->tblNum; data->colNum = 0; @@ -918,7 +936,7 @@ int32_t prepareInsertData(BindData *data) { } for (int32_t i = 0; i < allRowNum; ++i) { - data->tsData[i] = tsData++; + data->tsData[i] = bpTs++; data->boolData[i] = (bool)(i % 2); data->tinyData[i] = (int8_t)i; data->utinyData[i] = (uint8_t)(i+1); @@ -956,7 +974,6 @@ int32_t prepareInsertData(BindData *data) { } int32_t prepareQueryCondData(BindData *data, int32_t tblIdx) { - static int64_t tsData = 1591060628000; uint64_t bindNum = gCurCase->rowNum / gCurCase->bindRowNum; data->colNum = 0; @@ -982,7 +999,7 @@ int32_t prepareQueryCondData(BindData *data, int32_t tblIdx) { } for (int32_t i = 0; i < bindNum; ++i) { - data->tsData[i] = tsData + tblIdx*gCurCase->rowNum + rand()%gCurCase->rowNum; + data->tsData[i] = bpTs + tblIdx*gCurCase->rowNum + rand()%gCurCase->rowNum; data->boolData[i] = (bool)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); data->tinyData[i] = (int8_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); data->utinyData[i] = (uint8_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); @@ -1014,7 +1031,6 @@ int32_t prepareQueryCondData(BindData *data, int32_t tblIdx) { int32_t prepareQueryMiscData(BindData *data, int32_t tblIdx) { - static int64_t tsData = 1591060628000; uint64_t bindNum = gCurCase->rowNum / gCurCase->bindRowNum; data->colNum = 0; @@ -1040,7 +1056,7 @@ int32_t prepareQueryMiscData(BindData *data, int32_t tblIdx) { } for (int32_t i = 0; i < bindNum; ++i) { - data->tsData[i] = tsData + tblIdx*gCurCase->rowNum + rand()%gCurCase->rowNum; + data->tsData[i] = bpTs + tblIdx*gCurCase->rowNum + rand()%gCurCase->rowNum; data->boolData[i] = (bool)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); data->tinyData[i] = (int8_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); data->utinyData[i] = (uint8_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); @@ -1202,39 +1218,7 @@ int32_t bpAppendValueString(char *buf, int type, void *value, int32_t valueLen, } -int32_t bpBindParam(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) { - static int32_t n = 0; - - if (gCurCase->bindRowNum > 1) { - if (0 == (n++%2)) { - if (taos_stmt_bind_param_batch(stmt, bind)) { - printf("!!!taos_stmt_bind_param_batch error:%s\n", taos_stmt_errstr(stmt)); - exit(1); - } - } else { - for (int32_t i = 0; i < gCurCase->bindColNum; ++i) { - if (taos_stmt_bind_single_param_batch(stmt, bind++, i)) { - printf("!!!taos_stmt_bind_single_param_batch error:%s\n", taos_stmt_errstr(stmt)); - exit(1); - } - } - } - } else { - if (0 == (n++%2)) { - if (taos_stmt_bind_param_batch(stmt, bind)) { - printf("!!!taos_stmt_bind_param_batch error:%s\n", taos_stmt_errstr(stmt)); - exit(1); - } - } else { - if (taos_stmt_bind_param(stmt, bind)) { - printf("!!!taos_stmt_bind_param error:%s\n", taos_stmt_errstr(stmt)); - exit(1); - } - } - } - return 0; -} void bpCheckIsInsert(TAOS_STMT *stmt, int32_t insert) { int32_t isInsert = 0; @@ -1280,15 +1264,12 @@ void bpCheckAffectedRowsOnce(TAOS_STMT *stmt, int32_t expectedNum) { } void bpCheckQueryResult(TAOS_STMT *stmt, TAOS *taos, char *stmtSql, TAOS_MULTI_BIND* bind) { - TAOS_RES* res = taos_stmt_use_result(stmt); - int32_t sqlResNum = 0; - int32_t stmtResNum = 0; - bpFetchRows(res, gCaseCtrl.printRes, &stmtResNum); - + // query using sql char sql[1024]; int32_t len = 0; char* p = stmtSql; char* s = NULL; + int32_t sqlResNum = 0; for (int32_t i = 0; true; ++i, p=s+1) { s = strchr(p, '?'); @@ -1313,6 +1294,12 @@ void bpCheckQueryResult(TAOS_STMT *stmt, TAOS *taos, char *stmtSql, TAOS_MULTI_B } bpExecQuery(taos, sql, gCaseCtrl.printRes, &sqlResNum); + + // query using stmt + TAOS_RES* res = taos_stmt_use_result(stmt); + int32_t stmtResNum = 0; + bpFetchRows(res, gCaseCtrl.printRes, &stmtResNum); + if (sqlResNum != stmtResNum) { printf("!!!sql res num %d mis-match stmt res num %d\n", sqlResNum, stmtResNum); exit(1); @@ -1321,9 +1308,165 @@ void bpCheckQueryResult(TAOS_STMT *stmt, TAOS *taos, char *stmtSql, TAOS_MULTI_B printf("***sql res num match stmt res num %d\n", stmtResNum); } +void bpCheckColTagFields(TAOS_STMT *stmt, int32_t fieldNum, TAOS_FIELD_E* pFields, int32_t expecteNum, TAOS_MULTI_BIND* pBind, BP_BIND_TYPE type) { + int32_t code = 0; + + if (fieldNum != expecteNum) { + printf("!!!%s field num %d mis-match expect num %d\n", BP_BIND_TYPE_STR(type), fieldNum, expecteNum); + exit(1); + } + + if (type == BP_BIND_COL) { + if (pFields[0].precision != gCaseCtrl.precision) { + printf("!!!db precision %d mis-match expect %d\n", pFields[0].precision, gCaseCtrl.precision); + exit(1); + } + } + + for (int32_t i = 0; i < fieldNum; ++i) { + if (pFields[i].type != pBind[i].buffer_type) { + printf("!!!%s %dth field type %d mis-match expect type %d\n", BP_BIND_TYPE_STR(type), i, pFields[i].type, pBind[i].buffer_type); + exit(1); + } + + if (pFields[i].type == TSDB_DATA_TYPE_BINARY) { + if (pFields[i].bytes != (pBind[i].buffer_length + 2)) { + printf("!!!%s %dth field len %d mis-match expect len %d\n", BP_BIND_TYPE_STR(type), i, pFields[i].bytes, (pBind[i].buffer_length + 2)); + exit(1); + } + } else if (pFields[i].type == TSDB_DATA_TYPE_NCHAR) { + if (pFields[i].bytes != (pBind[i].buffer_length * 4 + 2)) { + printf("!!!%s %dth field len %d mis-match expect len %d\n", BP_BIND_TYPE_STR(type), i, pFields[i].bytes, (pBind[i].buffer_length + 2)); + exit(1); + } + } else if (pFields[i].bytes != pBind[i].buffer_length) { + printf("!!!%s %dth field len %d mis-match expect len %d\n", BP_BIND_TYPE_STR(type), i, pFields[i].bytes, pBind[i].buffer_length); + exit(1); + } + } + + if (type == BP_BIND_COL) { + int fieldType = 0; + int fieldBytes = 0; + for (int32_t i = 0; i < fieldNum; ++i) { + code = taos_stmt_get_param(stmt, i, &fieldType, &fieldBytes); + if (code) { + printf("!!!taos_stmt_get_param error:%s\n", taos_stmt_errstr(stmt)); + exit(1); + } + + if (pFields[i].type != fieldType) { + printf("!!!%s %dth field type %d mis-match expect type %d\n", BP_BIND_TYPE_STR(type), i, fieldType, pFields[i].type); + exit(1); + } + + if (pFields[i].bytes != fieldBytes) { + printf("!!!%s %dth field len %d mis-match expect len %d\n", BP_BIND_TYPE_STR(type), i, fieldBytes, pFields[i].bytes); + exit(1); + } + } + } + + if (gCaseCtrl.printVerbose) { + printf("%s fields check passed\n", BP_BIND_TYPE_STR(type)); + } +} + + +void bpCheckTagFields(TAOS_STMT *stmt, TAOS_MULTI_BIND* pBind) { + int32_t code = 0; + int fieldNum = 0; + TAOS_FIELD_E* pFields = NULL; + code = taos_stmt_get_tag_fields(stmt, &fieldNum, &pFields); + if (code != 0){ + printf("!!!taos_stmt_get_tag_fields error:%s\n", taos_stmt_errstr(stmt)); + exit(1); + } + + bpCheckColTagFields(stmt, fieldNum, pFields, gCurCase->bindTagNum, pBind, BP_BIND_TAG); +} + +void bpCheckColFields(TAOS_STMT *stmt, TAOS_MULTI_BIND* pBind) { + if (gCurCase->testType == TTYPE_QUERY) { + return; + } + + int32_t code = 0; + int fieldNum = 0; + TAOS_FIELD_E* pFields = NULL; + code = taos_stmt_get_col_fields(stmt, &fieldNum, &pFields); + if (code != 0){ + printf("!!!taos_stmt_get_col_fields error:%s\n", taos_stmt_errstr(stmt)); + exit(1); + } + + bpCheckColTagFields(stmt, fieldNum, pFields, gCurCase->bindColNum, pBind, BP_BIND_COL); +} + +void bpShowBindParam(TAOS_MULTI_BIND *bind, int32_t num) { + for (int32_t i = 0; i < num; ++i) { + TAOS_MULTI_BIND* b = &bind[i]; + printf("Bind %d: type[%d],buf[%p],buflen[%d],len[%],null[%d],num[%d]\n", + i, b->buffer_type, b->buffer, b->buffer_length, b->length ? *b->length : 0, b->is_null ? *b->is_null : 0, b->num); + } +} + +int32_t bpBindParam(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) { + static int32_t n = 0; + + bpCheckColFields(stmt, bind); + + if (gCurCase->bindRowNum > 1) { + if (0 == (n++%2)) { + if (taos_stmt_bind_param_batch(stmt, bind)) { + printf("!!!taos_stmt_bind_param_batch error:%s\n", taos_stmt_errstr(stmt)); + bpShowBindParam(bind, gCurCase->bindColNum); + exit(1); + } + } else { + for (int32_t i = 0; i < gCurCase->bindColNum; ++i) { + if (taos_stmt_bind_single_param_batch(stmt, bind+i, i)) { + printf("!!!taos_stmt_bind_single_param_batch %d error:%s\n", taos_stmt_errstr(stmt), i); + bpShowBindParam(bind, gCurCase->bindColNum); + exit(1); + } + } + } + } else { + if (0 == (n++%2)) { + if (taos_stmt_bind_param_batch(stmt, bind)) { + printf("!!!taos_stmt_bind_param_batch error:%s\n", taos_stmt_errstr(stmt)); + bpShowBindParam(bind, gCurCase->bindColNum); + exit(1); + } + } else { + if (taos_stmt_bind_param(stmt, bind)) { + printf("!!!taos_stmt_bind_param error:%s\n", taos_stmt_errstr(stmt)); + bpShowBindParam(bind, gCurCase->bindColNum); + exit(1); + } + } + } + + return 0; +} + int32_t bpSetTableNameTags(BindData *data, int32_t tblIdx, char *tblName, TAOS_STMT *stmt) { + int32_t code = 0; if (gCurCase->bindTagNum > 0) { - return taos_stmt_set_tbname_tags(stmt, tblName, data->pTags + tblIdx * gCurCase->bindTagNum); + if ((rand() % 2) == 0) { + code = taos_stmt_set_tbname(stmt, tblName); + if (code != 0){ + printf("!!!taos_stmt_set_tbname error:%s\n", taos_stmt_errstr(stmt)); + exit(1); + } + + bpCheckTagFields(stmt, data->pTags + tblIdx * gCurCase->bindTagNum); + + return taos_stmt_set_tags(stmt, data->pTags + tblIdx * gCurCase->bindTagNum); + } else { + return taos_stmt_set_tbname_tags(stmt, tblName, data->pTags + tblIdx * gCurCase->bindTagNum); + } } else { return taos_stmt_set_tbname(stmt, tblName); } @@ -1755,7 +1898,7 @@ int insertAUTOTest1(TAOS_STMT *stmt, TAOS *taos) { if (gCurCase->tblNum > 1) { char buf[32]; sprintf(buf, "t%d", t); - code = taos_stmt_set_tbname_tags(stmt, buf, data.pTags + t * gCurCase->bindTagNum); + code = bpSetTableNameTags(&data, t, buf, stmt); if (code != 0){ printf("!!!taos_stmt_set_tbname_tags error:%s\n", taos_stmt_errstr(stmt)); exit(1); @@ -2223,14 +2366,48 @@ void generateCreateTableSQL(char *buf, int32_t tblIdx, int32_t colNum, int32_t * } } +char *bpPrecisionStr(uint8_t precision) { + switch (precision) { + case TIME_PRECISION_MILLI: + return "ms"; + case TIME_PRECISION_MICRO: + return "us"; + case TIME_PRECISION_NANO: + return "ns"; + default: + return "unknwon"; + } +} + +void bpSetStartupTs() { + switch (gCaseCtrl.precision) { + case TIME_PRECISION_MILLI: + bpTs = BP_STARTUP_TS; + break; + case TIME_PRECISION_MICRO: + bpTs = BP_STARTUP_TS * 1000; + break; + case TIME_PRECISION_NANO: + bpTs = BP_STARTUP_TS * 1000000; + break; + default: + bpTs = BP_STARTUP_TS; + break; + } +} + void prepare(TAOS *taos, int32_t colNum, int32_t *colList, int prepareStb) { TAOS_RES *result; int code; + char createDbSql[128] = {0}; result = taos_query(taos, "drop database demo"); taos_free_result(result); - result = taos_query(taos, "create database demo keep 36500"); + sprintf(createDbSql, "create database demo keep 36500 precision \"%s\"", bpPrecisionStr(gCaseCtrl.precision)); + printf("\tCreate Database SQL:%s\n", createDbSql); + + result = taos_query(taos, createDbSql); code = taos_errno(result); if (code != 0) { printf("!!!failed to create database, reason:%s\n", taos_errstr(result)); @@ -2278,6 +2455,8 @@ int32_t runCase(TAOS *taos, int32_t caseIdx, int32_t caseRunIdx, bool silent) { CaseCfg cfg = gCase[caseIdx]; CaseCfg cfgBk; gCurCase = &cfg; + + bpSetStartupTs(); if ((gCaseCtrl.bindColTypeNum || gCaseCtrl.bindColNum) && (gCurCase->colNum != gFullColNum)) { return 1; @@ -2413,22 +2592,28 @@ void* runCaseList(TAOS *taos) { } void runAll(TAOS *taos) { -#if 1 - - strcpy(gCaseCtrl.caseCatalog, "Normal Test"); + strcpy(gCaseCtrl.caseCatalog, "Default Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); runCaseList(taos); + strcpy(gCaseCtrl.caseCatalog, "Micro DB precision Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); + gCaseCtrl.precision = TIME_PRECISION_MICRO; + runCaseList(taos); + gCaseCtrl.precision = TIME_PRECISION_MILLI; + strcpy(gCaseCtrl.caseCatalog, "Nano DB precision Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); + gCaseCtrl.precision = TIME_PRECISION_NANO; + runCaseList(taos); + gCaseCtrl.precision = TIME_PRECISION_MILLI; + strcpy(gCaseCtrl.caseCatalog, "Auto Create Table Test"); gCaseCtrl.autoCreateTbl = true; printf("%s Begin\n", gCaseCtrl.caseCatalog); runCaseList(taos); gCaseCtrl.autoCreateTbl = false; - -#endif -/* strcpy(gCaseCtrl.caseCatalog, "Null Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindNullNum = 1; @@ -2441,6 +2626,7 @@ void runAll(TAOS *taos) { runCaseList(taos); gCaseCtrl.bindRowNum = 0; +#if 0 strcpy(gCaseCtrl.caseCatalog, "Row Num Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.rowNum = 1000; @@ -2448,23 +2634,21 @@ void runAll(TAOS *taos) { runCaseList(taos); gCaseCtrl.rowNum = 0; gCaseCtrl.printRes = true; -*/ strcpy(gCaseCtrl.caseCatalog, "Runtimes Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.runTimes = 2; runCaseList(taos); gCaseCtrl.runTimes = 0; +#endif -#if 1 strcpy(gCaseCtrl.caseCatalog, "Check Param Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.checkParamNum = true; runCaseList(taos); gCaseCtrl.checkParamNum = false; -#endif -/* +#if 0 strcpy(gCaseCtrl.caseCatalog, "Bind Col Num Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindColNum = 6; @@ -2476,7 +2660,7 @@ void runAll(TAOS *taos) { gCaseCtrl.bindColTypeNum = tListLen(bindColTypeList); gCaseCtrl.bindColTypeList = bindColTypeList; runCaseList(taos); -*/ +#endif printf("All Test End\n"); }