diff --git a/include/common/taosdef.h b/include/common/taosdef.h index af8bda2593fdcd84533414176ee7084343f982aa..1fbbb3f1599afdf77957869ff6d3399a318fda2f 100644 --- a/include/common/taosdef.h +++ b/include/common/taosdef.h @@ -82,6 +82,8 @@ extern char *qtypeStr[]; #define TSDB_PORT_HTTP 11 +#undef TD_DEBUG_PRINT_ROW + #ifdef __cplusplus } #endif diff --git a/include/common/trow.h b/include/common/trow.h index 464e0dd69f131bd27c063982c5716b1b30c0a9a7..24baf25e1f2cdb8af5189fabfd2594d918ec0760 100644 --- a/include/common/trow.h +++ b/include/common/trow.h @@ -214,6 +214,7 @@ STSRow *tdRowDup(STSRow *row); static FORCE_INLINE SKvRowIdx *tdKvRowColIdxAt(STSRow *pRow, col_id_t idx) { return (SKvRowIdx *)TD_ROW_COL_IDX(pRow) + idx; } + static FORCE_INLINE int16_t tdKvRowColIdAt(STSRow *pRow, col_id_t idx) { ASSERT(idx >= 0); if (idx == 0) { @@ -222,6 +223,7 @@ static FORCE_INLINE int16_t tdKvRowColIdAt(STSRow *pRow, col_id_t idx) { return ((SKvRowIdx *)TD_ROW_COL_IDX(pRow) + idx - 1)->colId; } + static FORCE_INLINE void *tdKVRowColVal(STSRow *pRow, SKvRowIdx *pIdx) { return POINTER_SHIFT(pRow, pIdx->offset); } #define TD_ROW_OFFSET(p) ((p)->toffset); // During ParseInsert when without STSchema, how to get the offset for STpRow? @@ -1117,7 +1119,7 @@ static FORCE_INLINE bool tdGetKvRowValOfColEx(STSRowIter *pIter, col_id_t colId, } if (!colFound) { - if(colId <= pIter->maxColId) { + if (colId <= pIter->maxColId) { pVal->valType = TD_VTYPE_NONE; return true; } else { @@ -1367,14 +1369,14 @@ static void tdSCellValPrint(SCellVal *pVal, int8_t colType) { } } -static void tdSRowPrint(STSRow *row, STSchema *pSchema) { +static void tdSRowPrint(STSRow *row, STSchema *pSchema, const char* tag) { STSRowIter iter = {0}; tdSTSRowIterInit(&iter, pSchema); tdSTSRowIterReset(&iter, row); - printf(">>>"); + printf("%s >>>", tag); for (int i = 0; i < pSchema->numOfCols; ++i) { STColumn *stCol = pSchema->columns + i; - SCellVal sVal = { 255, NULL}; + SCellVal sVal = {.valType = 255, .val = NULL}; if (!tdSTSRowIterNext(&iter, stCol->colId, stCol->type, &sVal)) { break; } diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index d4197cd399391448e2795337f35fe9428b1b2e19..a34d4e3c80a75e29c5fb6e81125c98bcd5fec56f 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -340,7 +340,7 @@ typedef struct SQueryPlan { int32_t numOfSubplans; SNodeList* pSubplans; // Element is SNodeListNode. The execution level of subplan, starting from 0. SExplainInfo explainInfo; - SNodeList* pPlaceholderValues; + SArray* pPlaceholderValues; } SQueryPlan; void nodesWalkPhysiPlan(SNode* pNode, FNodeWalker walker, void* pContext); diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 875cdc275530c4957318d9a43ccbd8579f0732c3..de71192a9bdb928c3c9dfed061d8fca972518731 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -73,6 +73,7 @@ typedef struct SQuery { SArray* pDbList; SArray* pTableList; bool showRewrite; + int32_t placeholderNum; } SQuery; int32_t qParseQuerySql(SParseContext* pCxt, SQuery** pQuery); diff --git a/include/libs/planner/planner.h b/include/libs/planner/planner.h index b78cbb639c8942e313fd8bfb300e4f6f9be3b3e9..adbd84b04477049647d87ec6bbf4a09fadbfdf75 100644 --- a/include/libs/planner/planner.h +++ b/include/libs/planner/planner.h @@ -34,7 +34,7 @@ typedef struct SPlanContext { bool showRewrite; int8_t triggerType; int64_t watermark; - bool isStmtQuery; + int32_t placeholderNum; void* pTransporter; struct SCatalog* pCatalog; char* pMsg; @@ -50,7 +50,7 @@ int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan, SArray* pExecNo // @pSource one execution location of this group of datasource subplans int32_t qSetSubplanExecutionNode(SSubplan* pSubplan, int32_t groupId, SDownstreamSourceNode* pSource); -int32_t qStmtBindParam(SQueryPlan* pPlan, TAOS_MULTI_BIND* pParams, int32_t colIdx); +int32_t qStmtBindParam(SQueryPlan* pPlan, TAOS_MULTI_BIND* pParams, int32_t colIdx, uint64_t queryId); // Convert to subplan to string for the scheduler to send to the executor int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen); diff --git a/source/client/inc/clientStmt.h b/source/client/inc/clientStmt.h index 061d757551589e2e64210db20df7e2b0e6845b2d..ab27d7f00c4a1c1d55b67240d7d7e641f69e3e6e 100644 --- a/source/client/inc/clientStmt.h +++ b/source/client/inc/clientStmt.h @@ -46,6 +46,12 @@ typedef struct SStmtTableCache { void* boundTags; } SStmtTableCache; +typedef struct SQueryFields { + TAOS_FIELD* fields; + TAOS_FIELD* userFields; + uint32_t numOfCols; +} SQueryFields; + typedef struct SStmtBindInfo { bool needParse; uint64_t tbUid; @@ -66,16 +72,17 @@ typedef struct SStmtExecInfo { } SStmtExecInfo; typedef struct SStmtSQLInfo { - STMT_TYPE type; - STMT_STATUS status; - bool autoCreate; - uint64_t runTimes; - SHashObj* pTableCache; //SHash - SQuery* pQuery; - char* sqlStr; - int32_t sqlLen; - SArray* nodeList; - SQueryPlan* pQueryPlan; + STMT_TYPE type; + STMT_STATUS status; + bool autoCreate; + uint64_t runTimes; + SHashObj* pTableCache; //SHash + SQuery* pQuery; + char* sqlStr; + int32_t sqlLen; + SArray* nodeList; + SQueryPlan* pQueryPlan; + SQueryFields fields; } SStmtSQLInfo; typedef struct STscStmt { diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index b876f9b65cc42f6c833ea85ca97622ed1c6fd6f9..427cd72c0f290e13584af1d0ad94ab6f14d78ec1 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -234,7 +234,8 @@ int32_t getPlan(SRequestObj* pRequest, SQuery* pQuery, SQueryPlan** pPlan, SArra .showRewrite = pQuery->showRewrite, .pTransporter = pRequest->pTscObj->pAppInfo->pTransporter, .pMsg = pRequest->msgBuf, - .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE}; + .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE, + .placeholderNum = pQuery->placeholderNum}; int32_t code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &cxt.pCatalog); if (TSDB_CODE_SUCCESS == code) { code = qCreateQueryPlan(&cxt, pPlan, pNodeList); diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c index 20c318e21215a488858b442de4c69f0ed96d9e26..ca6a11a668aedcf797b31fe6d0f1d615ba2290f9 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -73,6 +73,22 @@ int32_t stmtGetTbName(TAOS_STMT *stmt, char **tbName) { return TSDB_CODE_SUCCESS; } +int32_t stmtBackupQueryFields(STscStmt* pStmt) { + SQueryFields *pFields = &pStmt->sql.fields; + int32_t size = pFields->numOfCols * sizeof(TAOS_FIELD); + + pFields->numOfCols = pStmt->exec.pRequest->body.resInfo.numOfCols; + pFields->fields = taosMemoryMalloc(size); + pFields->userFields = taosMemoryMalloc(size); + if (NULL == pFields->fields || NULL == pFields->userFields) { + STMT_ERR_RET(TSDB_CODE_TSC_OUT_OF_MEMORY); + } + memcpy(pFields->fields, pStmt->exec.pRequest->body.resInfo.fields, size); + memcpy(pFields->userFields, pStmt->exec.pRequest->body.resInfo.userFields, size); + + return TSDB_CODE_SUCCESS; +} + int32_t stmtSetBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags) { STscStmt* pStmt = (STscStmt*)stmt; @@ -258,37 +274,42 @@ int32_t stmtGetFromCache(STscStmt* pStmt) { STableMeta *pTableMeta = NULL; SEpSet ep = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp); STMT_ERR_RET(catalogGetTableMeta(pStmt->pCatalog, pStmt->taos->pAppInfo->pTransporter, &ep, &pStmt->bInfo.sname, &pTableMeta)); - - if (pTableMeta->uid == pStmt->bInfo.tbUid) { + uint64_t uid = pTableMeta->uid; + uint64_t suid = pTableMeta->suid; + int8_t tableType = pTableMeta->tableType; + taosMemoryFree(pTableMeta); + + if (uid == pStmt->bInfo.tbUid) { pStmt->bInfo.needParse = false; - + return TSDB_CODE_SUCCESS; } - if (taosHashGet(pStmt->exec.pBlockHash, &pTableMeta->uid, sizeof(pTableMeta->uid))) { - SStmtTableCache* pCache = taosHashGet(pStmt->sql.pTableCache, &pTableMeta->uid, sizeof(pTableMeta->uid)); + if (taosHashGet(pStmt->exec.pBlockHash, &uid, sizeof(uid))) { + SStmtTableCache* pCache = taosHashGet(pStmt->sql.pTableCache, &uid, sizeof(uid)); if (NULL == pCache) { - tscError("table uid %" PRIx64 "found in exec blockHash, but not in sql blockHash", pTableMeta->uid); + tscError("table uid %" PRIx64 "found in exec blockHash, but not in sql blockHash", uid); + STMT_ERR_RET(TSDB_CODE_TSC_APP_ERROR); } pStmt->bInfo.needParse = false; - pStmt->bInfo.tbUid = pTableMeta->uid; - pStmt->bInfo.tbSuid = pTableMeta->suid; - pStmt->bInfo.tbType = pTableMeta->tableType; + pStmt->bInfo.tbUid = uid; + pStmt->bInfo.tbSuid = suid; + pStmt->bInfo.tbType = tableType; pStmt->bInfo.boundTags = pCache->boundTags; - + return TSDB_CODE_SUCCESS; } - SStmtTableCache* pCache = taosHashGet(pStmt->sql.pTableCache, &pTableMeta->uid, sizeof(pTableMeta->uid)); + SStmtTableCache* pCache = taosHashGet(pStmt->sql.pTableCache, &uid, sizeof(uid)); if (pCache) { pStmt->bInfo.needParse = false; - pStmt->bInfo.tbUid = pTableMeta->uid; - pStmt->bInfo.tbSuid = pTableMeta->suid; - pStmt->bInfo.tbType = pTableMeta->tableType; + pStmt->bInfo.tbUid = uid; + pStmt->bInfo.tbSuid = suid; + pStmt->bInfo.tbType = tableType; pStmt->bInfo.boundTags = pCache->boundTags; STableDataBlocks* pNewBlock = NULL; @@ -475,9 +496,10 @@ int stmtBindBatch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int32_t colIdx) { STMT_ERR_RET(getQueryPlan(pStmt->exec.pRequest, pStmt->sql.pQuery, &pStmt->sql.nodeList)); pStmt->sql.pQueryPlan = pStmt->exec.pRequest->body.pDag; pStmt->exec.pRequest->body.pDag = NULL; + STMT_ERR_RET(stmtBackupQueryFields(pStmt)); } - STMT_RET(qStmtBindParam(pStmt->sql.pQueryPlan, bind, colIdx)); + STMT_RET(qStmtBindParam(pStmt->sql.pQueryPlan, bind, colIdx, pStmt->exec.pRequest->requestId)); } STableDataBlocks **pDataBlock = (STableDataBlocks**)taosHashGet(pStmt->exec.pBlockHash, (const char*)&pStmt->bInfo.tbUid, sizeof(pStmt->bInfo.tbUid)); @@ -549,6 +571,8 @@ int stmtClose(TAOS_STMT *stmt) { STscStmt* pStmt = (STscStmt*)stmt; STMT_RET(stmtCleanSQLInfo(pStmt)); + + taosMemoryFree(stmt); } const char *stmtErrstr(TAOS_STMT *stmt) { @@ -601,7 +625,7 @@ int stmtGetParamNum(TAOS_STMT *stmt, int *nums) { pStmt->exec.pRequest->body.pDag = NULL; } - *nums = (pStmt->sql.pQueryPlan->pPlaceholderValues) ? pStmt->sql.pQueryPlan->pPlaceholderValues->length : 0; + *nums = taosArrayGetSize(pStmt->sql.pQueryPlan->pPlaceholderValues); } else { STMT_ERR_RET(stmtFetchColFields(stmt, nums, NULL)); } diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c index 638e1e3a1c40aa9088ebbcb0ecc3539bb8bd9708..148f2630ca157866d128186c75d7062823b4fa5d 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead.c @@ -1490,6 +1490,10 @@ static void mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capacit pSchema1 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row1)); } +#ifdef TD_DEBUG_PRINT_ROW + tdSRowPrint(row1, pSchema1, __func__); +#endif + if (isRow1DataRow) { numOfColsOfRow1 = schemaNCols(pSchema1); } else { diff --git a/source/libs/nodes/src/nodesTraverseFuncs.c b/source/libs/nodes/src/nodesTraverseFuncs.c index 84eccf85325083265025efaa156276f68fece4ff..88f5d914e4998234367ebd03803aa5b75bf47850 100644 --- a/source/libs/nodes/src/nodesTraverseFuncs.c +++ b/source/libs/nodes/src/nodesTraverseFuncs.c @@ -423,6 +423,9 @@ static EDealRes dispatchPhysiPlan(SNode* pNode, ETraversalOrder order, FNodeWalk EDealRes res = DEAL_RES_CONTINUE; switch (nodeType(pNode)) { + case QUERY_NODE_NODE_LIST: + res = walkPhysiPlans(((SNodeListNode*)pNode)->pNodeList, order, walker, pContext); + break; case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: res = walkScanPhysi((SScanPhysiNode*)pNode, order, walker, pContext); break; @@ -534,10 +537,7 @@ static EDealRes dispatchPhysiPlan(SNode* pNode, ETraversalOrder order, FNodeWalk break; case QUERY_NODE_PHYSICAL_SUBPLAN: { SSubplan* pSubplan = (SSubplan*)pNode; - res = walkPhysiNode((SPhysiNode*)pNode, order, walker, pContext); - if (DEAL_RES_ERROR != res && DEAL_RES_END != res) { - res = walkPhysiPlans(pSubplan->pChildren, order, walker, pContext); - } + res = walkPhysiPlans(pSubplan->pChildren, order, walker, pContext); if (DEAL_RES_ERROR != res && DEAL_RES_END != res) { res = walkPhysiPlan((SNode*)pSubplan->pNode, order, walker, pContext); } diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index ff77fcf31ec2f1df2b821ba5d629435584812094..c7438b0c3dd0f2bbfa6765dbd1227e9da1ccd710 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -44,7 +44,7 @@ void initAstCreateContext(SParseContext* pParseCxt, SAstCreateContext* pCxt) { pCxt->notSupport = false; pCxt->valid = true; pCxt->pRootNode = NULL; - pCxt->placeholderNo = 1; + pCxt->placeholderNo = 0; } static void copyStringFormStringToken(SToken* pToken, char* pBuf, int32_t len) { @@ -315,7 +315,7 @@ SNode* createPlaceholderValueNode(SAstCreateContext* pCxt, const SToken* pLitera CHECK_OUT_OF_MEM(val); val->literal = strndup(pLiteral->z, pLiteral->n); CHECK_OUT_OF_MEM(val->literal); - val->placeholderNo = pCxt->placeholderNo++; + val->placeholderNo = ++pCxt->placeholderNo; return (SNode*)val; } @@ -380,6 +380,11 @@ SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataType d CHECK_OUT_OF_MEM(func); strcpy(func->functionName, "cast"); func->node.resType = dt; + if (TSDB_DATA_TYPE_BINARY == dt.type) { + func->node.resType.bytes += 2; + } else if (TSDB_DATA_TYPE_NCHAR == dt.type) { + func->node.resType.bytes = func->node.resType.bytes * TSDB_NCHAR_SIZE + 2; + } nodesListMakeAppend(&func->pParameterList, pExpr); return (SNode*)func; } diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c index 723ad577f4e7b439e21a7506ed6e9c74b5fa64a9..270cd30231e6a83cc4424157c0a03be8dbd55fb7 100644 --- a/source/libs/parser/src/parAstParser.c +++ b/source/libs/parser/src/parAstParser.c @@ -80,6 +80,7 @@ abort_parse: return TSDB_CODE_OUT_OF_MEMORY; } (*pQuery)->pRoot = cxt.pRootNode; + (*pQuery)->placeholderNum = cxt.placeholderNo; } return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED; } diff --git a/source/libs/parser/src/parInsert.c b/source/libs/parser/src/parInsert.c index 62bb96f1cb0a80961849a464c60a9b819d2f2688..f452838921d629bdbb86dd600adbf52c3ae7d0a6 100644 --- a/source/libs/parser/src/parInsert.c +++ b/source/libs/parser/src/parInsert.c @@ -937,6 +937,11 @@ static int parseOneRow(SInsertParseContext* pCxt, STableDataBlocks* pDataBlocks, } *gotRow = true; +#ifdef TD_DEBUG_PRINT_ROW + STSchema* pSTSchema = tdGetSTSChemaFromSSChema(&schema, spd->numOfCols); + tdSRowPrint(row, pSTSchema, __func__); + taosMemoryFree(pSTSchema); +#endif } // *len = pBuilder->extendedRowSize; @@ -1328,10 +1333,6 @@ int32_t qBindStmtColsValue(void *pBlock, TAOS_MULTI_BIND *bind, char *msgBuf, in for (int c = 0; c < spd->numOfBound; ++c) { SSchema* pColSchema = &pSchema[spd->boundColumns[c] - 1]; - if (bind[c].buffer_type != pColSchema->type) { - return buildInvalidOperationMsg(&pBuf, "column type mis-match with buffer type"); - } - if (bind[c].num != rowNum) { return buildInvalidOperationMsg(&pBuf, "row number in each bind param should be the same"); } @@ -1346,6 +1347,10 @@ int32_t qBindStmtColsValue(void *pBlock, TAOS_MULTI_BIND *bind, char *msgBuf, in CHECK_CODE(MemRowAppend(&pBuf, NULL, 0, ¶m)); } else { + if (bind[c].buffer_type != pColSchema->type) { + return buildInvalidOperationMsg(&pBuf, "column type mis-match with buffer type"); + } + int32_t colLen = pColSchema->bytes; if (IS_VAR_DATA_TYPE(pColSchema->type)) { colLen = bind[c].length[r]; @@ -1359,7 +1364,6 @@ int32_t qBindStmtColsValue(void *pBlock, TAOS_MULTI_BIND *bind, char *msgBuf, in checkTimestamp(pDataBlock, (const char*)&tsKey); } } - // set the null value for the columns that do not assign values if ((spd->numOfBound < spd->numOfCols) && TD_IS_TP_ROW(row)) { for (int32_t i = 0; i < spd->numOfCols; ++i) { @@ -1369,6 +1373,11 @@ int32_t qBindStmtColsValue(void *pBlock, TAOS_MULTI_BIND *bind, char *msgBuf, in } } } +#ifdef TD_DEBUG_PRINT_ROW + STSchema* pSTSchema = tdGetSTSChemaFromSSChema(&pSchema, spd->numOfCols); + tdSRowPrint(row, pSTSchema, __func__); + taosMemoryFree(pSTSchema); +#endif pDataBlock->size += extendedRowSize; } @@ -1447,6 +1456,14 @@ int32_t qBindStmtSingleColValue(void *pBlock, TAOS_MULTI_BIND *bind, char *msgBu } } } + +#ifdef TD_DEBUG_PRINT_ROW + if(rowEnd) { + STSchema* pSTSchema = tdGetSTSChemaFromSSChema(&pSchema, spd->numOfCols); + tdSRowPrint(row, pSTSchema, __func__); + taosMemoryFree(pSTSchema); + } +#endif } if (rowEnd) { diff --git a/source/libs/planner/src/planner.c b/source/libs/planner/src/planner.c index 4d4670379e6460ebe5df840e2e52ef71366571a4..70a969584a0042b02d00c410232b686ef1d73ac4 100644 --- a/source/libs/planner/src/planner.c +++ b/source/libs/planner/src/planner.c @@ -19,26 +19,23 @@ typedef struct SCollectPlaceholderValuesCxt { int32_t errCode; - SNodeList* pValues; + SArray* pValues; } SCollectPlaceholderValuesCxt; static EDealRes collectPlaceholderValuesImpl(SNode* pNode, void* pContext) { if (QUERY_NODE_VALUE == nodeType(pNode) && ((SValueNode*)pNode)->placeholderNo > 0) { SCollectPlaceholderValuesCxt* pCxt = pContext; - pCxt->errCode = nodesListMakeAppend(&pCxt->pValues, pNode); + taosArrayInsert(pCxt->pValues, ((SValueNode*)pNode)->placeholderNo - 1, &pNode); return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR; } return DEAL_RES_CONTINUE; } static int32_t collectPlaceholderValues(SPlanContext* pCxt, SQueryPlan* pPlan) { - SCollectPlaceholderValuesCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pValues = NULL}; + pPlan->pPlaceholderValues = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); + + SCollectPlaceholderValuesCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pValues = pPlan->pPlaceholderValues}; nodesWalkPhysiPlan((SNode*)pPlan, collectPlaceholderValuesImpl, &cxt); - if (TSDB_CODE_SUCCESS == cxt.errCode) { - pPlan->pPlaceholderValues = cxt.pValues; - } else { - nodesDestroyList(cxt.pValues); - } return cxt.errCode; } @@ -60,7 +57,7 @@ int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan, SArray* pExecNo if (TSDB_CODE_SUCCESS == code) { code = createPhysiPlan(pCxt, pLogicPlan, pPlan, pExecNodeList); } - if (TSDB_CODE_SUCCESS == code && pCxt->isStmtQuery) { + if (TSDB_CODE_SUCCESS == code && pCxt->placeholderNum > 0) { code = collectPlaceholderValues(pCxt, *pPlan); } @@ -108,7 +105,7 @@ static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam) { return TSDB_CODE_SUCCESS; } pVal->node.resType.type = pParam->buffer_type; - pVal->node.resType.bytes = *(pParam->length); + pVal->node.resType.bytes = NULL != pParam->length ? *(pParam->length) : tDataTypes[pParam->buffer_type].bytes; switch (pParam->buffer_type) { case TSDB_DATA_TYPE_BOOL: pVal->datum.b = *((bool*)pParam->buffer); @@ -133,6 +130,7 @@ static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam) { break; case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_NCHAR: pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1); if (NULL == pVal->datum.p) { return TSDB_CODE_OUT_OF_MEMORY; @@ -155,7 +153,6 @@ static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam) { case TSDB_DATA_TYPE_UBIGINT: pVal->datum.u = *((uint64_t*)pParam->buffer); break; - case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_JSON: case TSDB_DATA_TYPE_DECIMAL: case TSDB_DATA_TYPE_BLOB: @@ -168,18 +165,35 @@ static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam) { return TSDB_CODE_SUCCESS; } -int32_t qStmtBindParam(SQueryPlan* pPlan, TAOS_MULTI_BIND* pParams, int32_t colIdx) { - if (colIdx < 0) { - int32_t index = 0; - SNode* pNode = NULL; +static EDealRes updatePlanQueryId(SNode* pNode, void* pContext) { + int64_t queryId = *(uint64_t *)pContext; + + if (QUERY_NODE_PHYSICAL_PLAN == nodeType(pNode)) { + SQueryPlan* planNode = (SQueryPlan*)pNode; + planNode->queryId = queryId; + } else if (QUERY_NODE_PHYSICAL_SUBPLAN == nodeType(pNode)) { + SSubplan* subplanNode = (SSubplan*)pNode; + subplanNode->id.queryId = queryId; + } - FOREACH(pNode, pPlan->pPlaceholderValues) { - setValueByBindParam((SValueNode*)pNode, pParams + index); - ++index; + return DEAL_RES_CONTINUE; +} + +int32_t qStmtBindParam(SQueryPlan* pPlan, TAOS_MULTI_BIND* pParams, int32_t colIdx, uint64_t queryId) { + int32_t size = taosArrayGetSize(pPlan->pPlaceholderValues); + + if (colIdx < 0) { + for (int32_t i = 0; i < size; ++i) { + setValueByBindParam((SValueNode*)taosArrayGetP(pPlan->pPlaceholderValues, i), pParams + i); } } else { - setValueByBindParam((SValueNode*)nodesListGetNode(pPlan->pPlaceholderValues, colIdx), pParams); + setValueByBindParam((SValueNode*)taosArrayGetP(pPlan->pPlaceholderValues, colIdx), pParams); + } + + if (colIdx < 0 || ((colIdx + 1) == size)) { + nodesWalkPhysiPlan((SNode*)pPlan, updatePlanQueryId, &queryId); } + return TSDB_CODE_SUCCESS; } diff --git a/source/libs/scalar/inc/sclInt.h b/source/libs/scalar/inc/sclInt.h index 021e0e0f96545085973d49853006bcbe1e362f8d..659d7dcf7e3b3a33d5b741e184da80f7c953c5ec 100644 --- a/source/libs/scalar/inc/sclInt.h +++ b/source/libs/scalar/inc/sclInt.h @@ -34,7 +34,7 @@ typedef struct SScalarCtx { #define SCL_IS_CONST_NODE(_node) ((NULL == (_node)) || (QUERY_NODE_VALUE == (_node)->type) || (QUERY_NODE_NODE_LIST == (_node)->type)) #define SCL_IS_CONST_CALC(_ctx) (NULL == (_ctx)->pBlockList) -#define SCL_IS_NULL_VALUE_NODE(_node) ((QUERY_NODE_VALUE == nodeType(_node)) && (TSDB_DATA_TYPE_NULL == ((SValueNode *)_node)->node.resType.type)) +#define SCL_IS_NULL_VALUE_NODE(_node) ((QUERY_NODE_VALUE == nodeType(_node)) && (TSDB_DATA_TYPE_NULL == ((SValueNode *)_node)->node.resType.type) && (((SValueNode *)_node)->placeholderNo <= 0)) #define sclFatal(...) qFatal(__VA_ARGS__) #define sclError(...) qError(__VA_ARGS__) diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index 5522bfc6a3d0c133e0a17c3ca1d5507fced5548e..864894fa42d09816750a9468bb2f9a54f8700835 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -3541,11 +3541,16 @@ EDealRes fltReviseRewriter(SNode** pNode, void* pContext) { } if (QUERY_NODE_VALUE == nodeType(*pNode)) { + SValueNode *valueNode = (SValueNode *)*pNode; + if (valueNode->placeholderNo >= 1) { + stat->scalarMode = true; + return DEAL_RES_CONTINUE; + } + if (!FILTER_GET_FLAG(stat->info->options, FLT_OPTION_TIMESTAMP)) { return DEAL_RES_CONTINUE; } - SValueNode *valueNode = (SValueNode *)*pNode; if (TSDB_DATA_TYPE_BINARY != valueNode->node.resType.type && TSDB_DATA_TYPE_NCHAR != valueNode->node.resType.type) { return DEAL_RES_CONTINUE; } @@ -3587,7 +3592,7 @@ EDealRes fltReviseRewriter(SNode** pNode, void* pContext) { return DEAL_RES_CONTINUE; } - if (node->opType == OP_TYPE_NOT_IN || node->opType == OP_TYPE_NOT_LIKE || node->opType > OP_TYPE_IS_NOT_NULL) { + if (node->opType == OP_TYPE_NOT_IN || node->opType == OP_TYPE_NOT_LIKE || node->opType > OP_TYPE_IS_NOT_NULL || node->opType == OP_TYPE_NOT_EQUAL) { stat->scalarMode = true; return DEAL_RES_CONTINUE; } diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index 34b0cf730dd5d80d2a74f97d96710833e00770ec..a6656dc87d3f805d0798392a5943281a1aee3e09 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -505,6 +505,7 @@ EDealRes sclRewriteBasedOnOptr(SNode** pNode, SScalarCtx *ctx, EOperatorType opT } res->node.resType.type = TSDB_DATA_TYPE_BOOL; + res->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; res->datum.b = false; nodesDestroyNode(*pNode); @@ -520,14 +521,14 @@ EDealRes sclRewriteOperatorForNullValue(SNode** pNode, SScalarCtx *ctx) { if (node->pLeft && (QUERY_NODE_VALUE == nodeType(node->pLeft))) { SValueNode *valueNode = (SValueNode *)node->pLeft; - if (TSDB_DATA_TYPE_NULL == valueNode->node.resType.type && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)) { + if (SCL_IS_NULL_VALUE_NODE(valueNode) && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)) { return sclRewriteBasedOnOptr(pNode, ctx, node->opType); } } if (node->pRight && (QUERY_NODE_VALUE == nodeType(node->pRight))) { SValueNode *valueNode = (SValueNode *)node->pRight; - if (TSDB_DATA_TYPE_NULL == valueNode->node.resType.type && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)) { + if (SCL_IS_NULL_VALUE_NODE(valueNode) && (node->opType != OP_TYPE_IS_NULL && node->opType != OP_TYPE_IS_NOT_NULL)) { return sclRewriteBasedOnOptr(pNode, ctx, node->opType); } } @@ -589,7 +590,10 @@ EDealRes sclRewriteFunction(SNode** pNode, SScalarCtx *ctx) { if (colDataIsNull_s(output.columnData, 0)) { res->node.resType.type = TSDB_DATA_TYPE_NULL; } else { - res->node.resType = node->node.resType; + res->node.resType.type = output.columnData->info.type; + res->node.resType.bytes = output.columnData->info.bytes; + res->node.resType.scale = output.columnData->info.scale; + res->node.resType.precision = output.columnData->info.precision; int32_t type = output.columnData->info.type; if (IS_VAR_DATA_TYPE(type)) { res->datum.p = taosMemoryCalloc(res->node.resType.bytes + VARSTR_HEADER_SIZE + 1, 1); diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 94b84c5861be9bcef28b254e37b11e4526d235f9..5c1b95e2147eb5bed3da7f0008011d85d12eff1f 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -658,11 +658,6 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp int16_t outputType = GET_PARAM_TYPE(&pOutput[0]); int64_t outputLen = GET_PARAM_BYTES(&pOutput[0]); - if (IS_VAR_DATA_TYPE(outputType)) { - int32_t factor = (TSDB_DATA_TYPE_NCHAR == outputType) ? TSDB_NCHAR_SIZE : 1; - outputLen = outputLen * factor + VARSTR_HEADER_SIZE; - } - char *outputBuf = taosMemoryCalloc(outputLen * pInput[0].numOfRows, 1); char *output = outputBuf; diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 8fd3272055f08a8316123abd07da7656c213a5ee..b1ab5253addda28221b88929e45677438d29f790 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -11,7 +11,39 @@ 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}; -int32_t bindColTypeList[] = {TSDB_DATA_TYPE_TIMESTAMP, TSDB_DATA_TYPE_NCHAR}; +int32_t bindColTypeList[] = {TSDB_DATA_TYPE_TIMESTAMP}; + +typedef struct { + char* oper; + int32_t paramNum; + bool enclose; +} OperInfo; + +OperInfo operInfo[] = { + {">", 2, false}, + {">=", 2, false}, + {"<", 2, false}, + {"<=", 2, false}, + {"=", 2, false}, + {"<>", 2, false}, + {"in", 2, true}, + {"not in", 2, true}, + + {"like", 2, false}, + {"not like", 2, false}, + {"match", 2, false}, + {"nmake", 2, false}, +}; + +int32_t operatorList[] = {0, 1, 2, 3, 4, 5, 6, 7}; +int32_t varoperatorList[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + +char *bpStbPrefix = "st"; +char *bpTbPrefix = "t"; + + +//char *operatorList[] = {">", ">=", "<", "<=", "=", "<>", "in", "not in"}; +//char *varoperatorList[] = {">", ">=", "<", "<=", "=", "<>", "in", "not in", "like", "not like", "match", "nmatch"}; #define tListLen(x) (sizeof(x) / sizeof((x)[0])) @@ -43,62 +75,74 @@ int32_t gVarCharLen = 5; int32_t gExecLoopTimes = 1; // no change int32_t gFullColNum = tListLen(fullColList); -int insertMBSETest1(TAOS_STMT *stmt); -int insertMBSETest2(TAOS_STMT *stmt); -int insertMBMETest1(TAOS_STMT *stmt); -int insertMBMETest2(TAOS_STMT *stmt); -int insertMBMETest3(TAOS_STMT *stmt); -int insertMBMETest4(TAOS_STMT *stmt); -int insertMPMETest1(TAOS_STMT *stmt); - - - +int insertMBSETest1(TAOS_STMT *stmt, TAOS *taos); +int insertMBSETest2(TAOS_STMT *stmt, TAOS *taos); +int insertMBMETest1(TAOS_STMT *stmt, TAOS *taos); +int insertMBMETest2(TAOS_STMT *stmt, TAOS *taos); +int insertMBMETest3(TAOS_STMT *stmt, TAOS *taos); +int insertMBMETest4(TAOS_STMT *stmt, TAOS *taos); +int insertMPMETest1(TAOS_STMT *stmt, TAOS *taos); +int querySUBTTest1(TAOS_STMT *stmt, TAOS *taos); + +enum { + TTYPE_INSERT = 1, + TTYPE_QUERY, +}; typedef struct { char caseDesc[128]; int32_t colNum; int32_t *colList; // full table column list - bool autoCreate; + int32_t testType; + bool prepareStb; bool fullCol; - int32_t (*runFn)(TAOS_STMT*); + int32_t (*runFn)(TAOS_STMT*, TAOS*); int32_t tblNum; int32_t rowNum; int32_t bindRowNum; int32_t bindColNum; // equal colNum in full column case int32_t bindNullNum; int32_t runTimes; + int32_t preCaseIdx; } CaseCfg; CaseCfg gCase[] = { - {"insert:MBSE1-FULL", tListLen(shortColList), shortColList, false, true, insertMBSETest1, 1, 10, 10, 0, 0, 1}, - {"insert:MBSE1-FULL", tListLen(shortColList), shortColList, false, true, insertMBSETest1, 10, 100, 10, 0, 0, 1}, + {"insert:MBSE1-FULL", tListLen(shortColList), shortColList, TTYPE_INSERT, false, true, insertMBSETest1, 1, 10, 10, 0, 0, 1, -1}, + {"insert:MBSE1-FULL", tListLen(shortColList), shortColList, TTYPE_INSERT, false, true, insertMBSETest1, 10, 100, 10, 0, 0, 1, -1}, + + {"insert:MBSE1-FULL", tListLen(fullColList), fullColList, TTYPE_INSERT, false, true, insertMBSETest1, 10, 10, 2, 0, 0, 1, -1}, + {"insert:MBSE1-C012", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBSETest1, 10, 10, 2, 12, 0, 1, -1}, + {"insert:MBSE1-C002", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBSETest1, 10, 10, 2, 2, 0, 1, -1}, + + {"insert:MBSE2-FULL", tListLen(fullColList), fullColList, TTYPE_INSERT, false, true, insertMBSETest2, 10, 10, 2, 0, 0, 1, -1}, + {"insert:MBSE2-C012", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBSETest2, 10, 10, 2, 12, 0, 1, -1}, + {"insert:MBSE2-C002", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBSETest2, 10, 10, 2, 2, 0, 1, -1}, - {"insert:MBSE1-FULL", tListLen(fullColList), fullColList, false, true, insertMBSETest1, 10, 10, 2, 0, 0, 1}, - {"insert:MBSE1-C012", tListLen(fullColList), fullColList, false, false, insertMBSETest1, 10, 10, 2, 12, 0, 1}, - {"insert:MBSE1-C002", tListLen(fullColList), fullColList, false, false, insertMBSETest1, 10, 10, 2, 2, 0, 1}, + {"insert:MBME1-FULL", tListLen(fullColList), fullColList, TTYPE_INSERT, false, true, insertMBMETest1, 10, 10, 2, 0, 0, 1, -1}, + {"insert:MBME1-C012", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBMETest1, 10, 10, 2, 12, 0, 1, -1}, + {"insert:MBME1-C002", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBMETest1, 10, 10, 2, 2, 0, 1, -1}, - {"insert:MBSE2-FULL", tListLen(fullColList), fullColList, false, true, insertMBSETest2, 10, 10, 2, 0, 0, 1}, - {"insert:MBSE2-C012", tListLen(fullColList), fullColList, false, false, insertMBSETest2, 10, 10, 2, 12, 0, 1}, - {"insert:MBSE2-C002", tListLen(fullColList), fullColList, false, false, insertMBSETest2, 10, 10, 2, 2, 0, 1}, + // 11 + {"insert:MBME2-FULL", tListLen(fullColList), fullColList, TTYPE_INSERT, false, true, insertMBMETest2, 10, 10, 2, 0, 0, 1, -1}, + {"insert:MBME2-C012", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBMETest2, 10, 10, 2, 12, 0, 1, -1}, + {"insert:MBME2-C002", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBMETest2, 10, 10, 2, 2, 0, 1, -1}, - {"insert:MBME1-FULL", tListLen(fullColList), fullColList, false, true, insertMBMETest1, 10, 10, 2, 0, 0, 1}, - {"insert:MBME1-C012", tListLen(fullColList), fullColList, false, false, insertMBMETest1, 10, 10, 2, 12, 0, 1}, - {"insert:MBME1-C002", tListLen(fullColList), fullColList, false, false, insertMBMETest1, 10, 10, 2, 2, 0, 1}, + {"insert:MBME3-FULL", tListLen(fullColList), fullColList, TTYPE_INSERT, false, true, insertMBMETest3, 10, 10, 2, 0, 0, 1, -1}, + {"insert:MBME3-C012", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBMETest3, 10, 10, 2, 12, 0, 1, -1}, + {"insert:MBME3-C002", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBMETest3, 10, 10, 2, 2, 0, 1, -1}, - {"insert:MBME2-FULL", tListLen(fullColList), fullColList, false, true, insertMBMETest2, 10, 10, 2, 0, 0, 1}, - {"insert:MBME2-C012", tListLen(fullColList), fullColList, false, false, insertMBMETest2, 10, 10, 2, 12, 0, 1}, - {"insert:MBME2-C002", tListLen(fullColList), fullColList, false, false, insertMBMETest2, 10, 10, 2, 2, 0, 1}, + {"insert:MBME4-FULL", tListLen(fullColList), fullColList, TTYPE_INSERT, false, true, insertMBMETest4, 10, 10, 2, 0, 0, 1, -1}, + {"insert:MBME4-C012", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBMETest4, 10, 10, 2, 12, 0, 1, -1}, + {"insert:MBME4-C002", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMBMETest4, 10, 10, 2, 2, 0, 1, -1}, - {"insert:MBME3-FULL", tListLen(fullColList), fullColList, false, true, insertMBMETest3, 10, 10, 2, 0, 0, 1}, - {"insert:MBME3-C012", tListLen(fullColList), fullColList, false, false, insertMBMETest3, 10, 10, 2, 12, 0, 1}, - {"insert:MBME3-C002", tListLen(fullColList), fullColList, false, false, insertMBMETest3, 10, 10, 2, 2, 0, 1}, + {"insert:MPME1-FULL", tListLen(fullColList), fullColList, TTYPE_INSERT, false, true, insertMPMETest1, 10, 10, 2, 0, 0, 1, -1}, + {"insert:MPME1-C012", tListLen(fullColList), fullColList, TTYPE_INSERT, false, false, insertMPMETest1, 10, 10, 2, 12, 0, 1, -1}, - {"insert:MBME4-FULL", tListLen(fullColList), fullColList, false, true, insertMBMETest4, 10, 10, 2, 0, 0, 1}, - {"insert:MBME4-C012", tListLen(fullColList), fullColList, false, false, insertMBMETest4, 10, 10, 2, 12, 0, 1}, - {"insert:MBME4-C002", tListLen(fullColList), fullColList, false, false, insertMBMETest4, 10, 10, 2, 2, 0, 1}, + // 22 + //{"query:SUBT-FULL", tListLen(fullColList), fullColList, TTYPE_QUERY, false, false, querySUBTTest1, 10, 10, 1, 3, 0, 1, 2}, + + {"query:SUBT-FULL", tListLen(fullColList), fullColList, TTYPE_QUERY, false, false, querySUBTTest1, 1, 10, 1, 3, 0, 1, 2}, - {"insert:MPME1-FULL", tListLen(fullColList), fullColList, false, true, insertMPMETest1, 10, 10, 2, 0, 0, 1}, - {"insert:MPME1-C012", tListLen(fullColList), fullColList, false, false, insertMPMETest1, 10, 10, 2, 12, 0, 1}, }; CaseCfg *gCurCase = NULL; @@ -106,38 +150,74 @@ CaseCfg *gCurCase = NULL; typedef struct { char caseCatalog[255]; int32_t bindNullNum; - bool autoCreate; + bool prepareStb; bool checkParamNum; bool printRes; bool printCreateTblSql; - bool printInsertSql; + bool printQuerySql; + bool printStmtSql; int32_t rowNum; //row num for one table int32_t bindColNum; int32_t bindRowNum; //row num for once bind int32_t bindColTypeNum; int32_t* bindColTypeList; int32_t runTimes; - int32_t caseIdx; - int32_t caseRunNum; + int32_t caseIdx; // static case idx + int32_t caseNum; // num in static case list + int32_t caseRunIdx; // runtime case idx + int32_t caseRunNum; // total run case num } CaseCtrl; +#if 1 +CaseCtrl gCaseCtrl = { + .bindNullNum = 0, + .prepareStb = false, + .printCreateTblSql = false, + .printQuerySql = true, + .printStmtSql = true, + .rowNum = 0, + .bindColNum = 0, + .bindRowNum = 0, +// .bindColTypeNum = 0, +// .bindColTypeList = NULL, + .checkParamNum = false, + .printRes = true, + .runTimes = 0, +// .caseIdx = -1, +// .caseNum = -1, + .caseRunIdx = -1, +// .caseRunNum = -1, + + .bindColTypeNum = tListLen(bindColTypeList), + .bindColTypeList = bindColTypeList, + .caseIdx = 22, + .caseNum = 1, + .caseRunNum = 1, + +}; +#else CaseCtrl gCaseCtrl = { .bindNullNum = 0, - .autoCreate = false, + .prepareStb = false, .printCreateTblSql = false, - .printInsertSql = true, + .printQuerySql = true, + .printStmtSql = true, .rowNum = 0, .bindColNum = 0, .bindRowNum = 0, - .bindColTypeNum = 0, - .bindColTypeList = NULL, + .bindColTypeNum = tListLen(bindColTypeList), + .bindColTypeList = bindColTypeList, .checkParamNum = false, .printRes = true, .runTimes = 0, .caseIdx = -1, + .caseNum = -1, + .caseRunIdx = -1, .caseRunNum = -1, }; +#endif + int32_t taosGetTimeOfDay(struct timeval *tv) { return gettimeofday(tv, NULL); } @@ -182,7 +262,12 @@ bool colExists(TAOS_MULTI_BIND* pBind, int32_t dataType) { } void generateInsertSQL(BindData *data) { - int32_t len = sprintf(data->sql, "insert into %s ", (gCurCase->tblNum > 1 ? "? " : "t0 ")); + int32_t len = 0; + if (gCurCase->tblNum > 1) { + len = sprintf(data->sql, "insert into ? "); + } else { + len = sprintf(data->sql, "insert into %s0 ", bpTbPrefix); + } if (!gCurCase->fullCol) { len += sprintf(data->sql + len, "("); for (int c = 0; c < gCurCase->bindColNum; ++c) { @@ -250,11 +335,99 @@ void generateInsertSQL(BindData *data) { } len += sprintf(data->sql + len, ")"); - if (gCaseCtrl.printInsertSql) { + if (gCaseCtrl.printStmtSql) { printf("SQL: %s\n", data->sql); } } +void bpAppendOperatorParam(BindData *data, int32_t *len, int32_t dataType) { + OperInfo *pInfo = NULL; + + if (TSDB_DATA_TYPE_VARCHAR == dataType || TSDB_DATA_TYPE_NCHAR == dataType) { + pInfo = &operInfo[varoperatorList[rand() % tListLen(varoperatorList)]]; + } else { + pInfo = &operInfo[operatorList[rand() % tListLen(operatorList)]]; + } + + switch (pInfo->paramNum) { + case 2: + if (pInfo->enclose) { + *len += sprintf(data->sql + *len, " %s (?)", pInfo->oper); + } else { + *len += sprintf(data->sql + *len, " %s ?", pInfo->oper); + } + break; + default: + printf("invalid paramNum:%d\n", pInfo->paramNum); + exit(1); + } +} + +void generateQuerySQL(BindData *data, int32_t tblIdx) { + int32_t len = sprintf(data->sql, "select * from %s%d where ", bpTbPrefix, tblIdx); + if (!gCurCase->fullCol) { + for (int c = 0; c < gCurCase->bindColNum; ++c) { + if (c) { + len += sprintf(data->sql + len, " and "); + } + switch (data->pBind[c].buffer_type) { + case TSDB_DATA_TYPE_BOOL: + len += sprintf(data->sql + len, "booldata"); + break; + case TSDB_DATA_TYPE_TINYINT: + len += sprintf(data->sql + len, "tinydata"); + break; + case TSDB_DATA_TYPE_SMALLINT: + len += sprintf(data->sql + len, "smalldata"); + break; + case TSDB_DATA_TYPE_INT: + len += sprintf(data->sql + len, "intdata"); + break; + case TSDB_DATA_TYPE_BIGINT: + len += sprintf(data->sql + len, "bigdata"); + break; + case TSDB_DATA_TYPE_FLOAT: + len += sprintf(data->sql + len, "floatdata"); + break; + case TSDB_DATA_TYPE_DOUBLE: + len += sprintf(data->sql + len, "doubledata"); + break; + case TSDB_DATA_TYPE_VARCHAR: + len += sprintf(data->sql + len, "binarydata"); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + len += sprintf(data->sql + len, "ts"); + break; + case TSDB_DATA_TYPE_NCHAR: + len += sprintf(data->sql + len, "nchardata"); + break; + case TSDB_DATA_TYPE_UTINYINT: + len += sprintf(data->sql + len, "utinydata"); + break; + case TSDB_DATA_TYPE_USMALLINT: + len += sprintf(data->sql + len, "usmalldata"); + break; + case TSDB_DATA_TYPE_UINT: + len += sprintf(data->sql + len, "uintdata"); + break; + case TSDB_DATA_TYPE_UBIGINT: + len += sprintf(data->sql + len, "ubigdata"); + break; + default: + printf("invalid col type:%d", data->pBind[c].buffer_type); + exit(1); + } + + bpAppendOperatorParam(data, &len, data->pBind[c].buffer_type); + } + } + + if (gCaseCtrl.printStmtSql) { + printf("SQL: %s\n", data->sql); + } +} + + void generateDataType(BindData *data, int32_t bindIdx, int32_t colIdx, int32_t *dataType) { if (bindIdx < gCurCase->bindColNum) { if (gCaseCtrl.bindColTypeNum) { @@ -389,7 +562,7 @@ int32_t prepareColData(BindData *data, int32_t bindIdx, int32_t rowIdx, int32_t } -int32_t prepareData(BindData *data) { +int32_t prepareInsertData(BindData *data) { static int64_t tsData = 1591060628000; uint64_t allRowNum = gCurCase->rowNum * gCurCase->tblNum; @@ -417,17 +590,17 @@ int32_t prepareData(BindData *data) { for (int32_t i = 0; i < allRowNum; ++i) { data->tsData[i] = tsData++; - data->boolData[i] = i % 2; - data->tinyData[i] = i; - data->utinyData[i] = i+1; - data->smallData[i] = i; - data->usmallData[i] = i+1; - data->intData[i] = i; - data->uintData[i] = i+1; - data->bigData[i] = i; - data->ubigData[i] = i+1; - data->floatData[i] = i; - data->doubleData[i] = i+1; + data->boolData[i] = (bool)(i % 2); + data->tinyData[i] = (int8_t)i; + data->utinyData[i] = (uint8_t)(i+1); + data->smallData[i] = (int16_t)i; + data->usmallData[i] = (uint16_t)(i+1); + data->intData[i] = (int32_t)i; + data->uintData[i] = (uint32_t)(i+1); + data->bigData[i] = (int64_t)i; + data->ubigData[i] = (uint64_t)(i+1); + data->floatData[i] = (float)i; + data->doubleData[i] = (double)(i+1); memset(data->binaryData + gVarCharSize * i, 'a'+i%26, gVarCharLen); if (gCurCase->bindNullNum) { data->isNull[i] = i % 2; @@ -446,6 +619,64 @@ int32_t prepareData(BindData *data) { return 0; } +int32_t prepareQueryData(BindData *data, int32_t tblIdx) { + static int64_t tsData = 1591060628000; + uint64_t bindNum = gCurCase->rowNum / gCurCase->bindRowNum; + + data->colNum = 0; + data->colTypes = taosMemoryCalloc(30, sizeof(int32_t)); + data->sql = taosMemoryCalloc(1, 1024); + data->pBind = taosMemoryCalloc(bindNum*gCurCase->bindColNum, sizeof(TAOS_MULTI_BIND)); + data->tsData = taosMemoryMalloc(bindNum * sizeof(int64_t)); + data->boolData = taosMemoryMalloc(bindNum * sizeof(bool)); + data->tinyData = taosMemoryMalloc(bindNum * sizeof(int8_t)); + data->utinyData = taosMemoryMalloc(bindNum * sizeof(uint8_t)); + data->smallData = taosMemoryMalloc(bindNum * sizeof(int16_t)); + data->usmallData = taosMemoryMalloc(bindNum * sizeof(uint16_t)); + data->intData = taosMemoryMalloc(bindNum * sizeof(int32_t)); + data->uintData = taosMemoryMalloc(bindNum * sizeof(uint32_t)); + data->bigData = taosMemoryMalloc(bindNum * sizeof(int64_t)); + data->ubigData = taosMemoryMalloc(bindNum * sizeof(uint64_t)); + data->floatData = taosMemoryMalloc(bindNum * sizeof(float)); + data->doubleData = taosMemoryMalloc(bindNum * sizeof(double)); + data->binaryData = taosMemoryMalloc(bindNum * gVarCharSize); + data->binaryLen = taosMemoryMalloc(bindNum * sizeof(int32_t)); + if (gCurCase->bindNullNum) { + data->isNull = taosMemoryCalloc(bindNum, sizeof(char)); + } + + for (int32_t i = 0; i < bindNum; ++i) { + data->tsData[i] = tsData + 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); + data->smallData[i] = (int16_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->usmallData[i] = (uint16_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->intData[i] = (int32_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->uintData[i] = (uint32_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->bigData[i] = (int64_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->ubigData[i] = (uint64_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->floatData[i] = (float)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->doubleData[i] = (double)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + memset(data->binaryData + gVarCharSize * i, 'a'+i%26, gVarCharLen); + if (gCurCase->bindNullNum) { + data->isNull[i] = i % 2; + } + data->binaryLen[i] = gVarCharLen; + } + + for (int b = 0; b < bindNum; b++) { + for (int c = 0; c < gCurCase->bindColNum; ++c) { + prepareColData(data, b*gCurCase->bindColNum+c, b*gCurCase->bindRowNum, c); + } + } + + generateQuerySQL(data, tblIdx); + + return 0; +} + + void destroyData(BindData *data) { taosMemoryFree(data->tsData); taosMemoryFree(data->boolData); @@ -466,6 +697,106 @@ void destroyData(BindData *data) { taosMemoryFree(data->colTypes); } +void bpFetchRows(TAOS_RES *result, bool printr, int32_t *rows) { + TAOS_ROW row; + int num_fields = taos_num_fields(result); + TAOS_FIELD *fields = taos_fetch_fields(result); + char temp[256]; + + // fetch the records row by row + while ((row = taos_fetch_row(result))) { + (*rows)++; + if (printr) { + memset(temp, 0, sizeof(temp)); + taos_print_row(temp, row, fields, num_fields); + printf("[%s]\n", temp); + } + } +} + +void bpExecQuery(TAOS * taos, char* sql, bool printr, int32_t *rows) { + TAOS_RES *result = taos_query(taos, sql); + int code = taos_errno(result); + if (code != 0) { + printf("failed to query table, reason:%s\n", taos_errstr(result)); + taos_free_result(result); + exit(1); + } + + bpFetchRows(result, printr, rows); + + taos_free_result(result); +} + + +int32_t bpAppendValueString(char *buf, int type, void *value, int32_t valueLen, int32_t *len) { + switch (type) { + case TSDB_DATA_TYPE_NULL: + *len += sprintf(buf + *len, "null"); + break; + + case TSDB_DATA_TYPE_BOOL: + *len += sprintf(buf + *len, (*(bool*)value) ? "true" : "false"); + break; + + case TSDB_DATA_TYPE_TINYINT: + *len += sprintf(buf + *len, "%d", *(int8_t*)value); + break; + + case TSDB_DATA_TYPE_SMALLINT: + *len += sprintf(buf + *len, "%d", *(int16_t*)value); + break; + + case TSDB_DATA_TYPE_INT: + *len += sprintf(buf + *len, "%d", *(int32_t*)value); + break; + + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: + *len += sprintf(buf + *len, "%ld", *(int64_t*)value); + break; + + case TSDB_DATA_TYPE_FLOAT: + *len += sprintf(buf + *len, "%e", *(float*)value); + break; + + case TSDB_DATA_TYPE_DOUBLE: + *len += sprintf(buf + *len, "%e", *(double*)value); + break; + + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + buf[*len] = '\''; + ++(*len); + memcpy(buf + *len, value, valueLen); + *len += valueLen; + buf[*len] = '\''; + ++(*len); + break; + + case TSDB_DATA_TYPE_UTINYINT: + *len += sprintf(buf + *len, "%d", *(uint8_t*)value); + break; + + case TSDB_DATA_TYPE_USMALLINT: + *len += sprintf(buf + *len, "%d", *(uint16_t*)value); + break; + + case TSDB_DATA_TYPE_UINT: + *len += sprintf(buf + *len, "%u", *(uint32_t*)value); + break; + + case TSDB_DATA_TYPE_UBIGINT: + *len += sprintf(buf + *len, "%lu", *(uint64_t*)value); + break; + + default: + printf("invalid data type:%d\n", type); + exit(1); + } +} + + int32_t bpBindParam(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) { static int32_t n = 0; @@ -484,23 +815,30 @@ int32_t bpBindParam(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) { } } } else { - if (taos_stmt_bind_param(stmt, bind)) { - printf("taos_stmt_bind_param error:%s\n", taos_stmt_errstr(stmt)); - exit(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 { + 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) { +void bpCheckIsInsert(TAOS_STMT *stmt, int32_t insert) { int32_t isInsert = 0; if (taos_stmt_is_insert(stmt, &isInsert)) { printf("taos_stmt_is_insert error:%s\n", taos_stmt_errstr(stmt)); exit(1); } - if (0 == isInsert) { + if (insert != isInsert) { printf("is insert failed\n"); exit(1); } @@ -528,11 +866,60 @@ void bpCheckAffectedRows(TAOS_STMT *stmt, int32_t times) { } } +void bpCheckAffectedRowsOnce(TAOS_STMT *stmt, int32_t expectedNum) { + int32_t rows = taos_stmt_affected_rows_once(stmt); + if (expectedNum != rows) { + printf("affected rows %d mis-match with expected num %d\n", rows, expectedNum); + exit(1); + } +} + +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); + + char sql[1024]; + int32_t len = 0; + char* p = stmtSql; + char* s = NULL; + + for (int32_t i = 0; true; ++i, p=s+1) { + s = strchr(p, '?'); + if (NULL == s) { + strcpy(&sql[len], p); + break; + } + + memcpy(&sql[len], p, (int64_t)s - (int64_t)p); + len += (int64_t)s - (int64_t)p; + + if (bind[i].is_null && bind[i].is_null[0]) { + bpAppendValueString(sql, TSDB_DATA_TYPE_NULL, NULL, 0, &len); + continue; + } + + bpAppendValueString(sql, bind[i].buffer_type, bind[i].buffer, (bind[i].length ? bind[i].length[0] : 0), &len); + } + + if (gCaseCtrl.printQuerySql) { + printf("Query SQL: %s\n", sql); + } + + bpExecQuery(taos, sql, gCaseCtrl.printRes, &sqlResNum); + if (sqlResNum != stmtResNum) { + printf("sql res num %d mis-match stmt res num %d\n", sqlResNum, stmtResNum); + exit(1); + } + + printf("sql res num match stmt res num %d\n", stmtResNum); +} /* prepare [settbname [bind add]] exec */ -int insertMBSETest1(TAOS_STMT *stmt) { +int insertMBSETest1(TAOS_STMT *stmt, TAOS *taos) { BindData data = {0}; - prepareData(&data); + prepareInsertData(&data); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ @@ -540,7 +927,7 @@ int insertMBSETest1(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); int32_t bindTimes = gCurCase->rowNum/gCurCase->bindRowNum; for (int32_t t = 0; t< gCurCase->tblNum; ++t) { @@ -575,7 +962,7 @@ int insertMBSETest1(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); bpCheckAffectedRows(stmt, 1); destroyData(&data); @@ -585,9 +972,9 @@ int insertMBSETest1(TAOS_STMT *stmt) { /* prepare [settbname bind add] exec */ -int insertMBSETest2(TAOS_STMT *stmt) { +int insertMBSETest2(TAOS_STMT *stmt, TAOS *taos) { BindData data = {0}; - prepareData(&data); + prepareInsertData(&data); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ @@ -595,7 +982,7 @@ int insertMBSETest2(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); int32_t bindTimes = gCurCase->rowNum/gCurCase->bindRowNum; @@ -631,7 +1018,7 @@ int insertMBSETest2(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); bpCheckAffectedRows(stmt, 1); destroyData(&data); @@ -640,9 +1027,9 @@ int insertMBSETest2(TAOS_STMT *stmt) { } /* prepare [settbname [bind add] exec] */ -int insertMBMETest1(TAOS_STMT *stmt) { +int insertMBMETest1(TAOS_STMT *stmt, TAOS *taos) { BindData data = {0}; - prepareData(&data); + prepareInsertData(&data); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ @@ -650,7 +1037,7 @@ int insertMBMETest1(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); int32_t bindTimes = gCurCase->rowNum/gCurCase->bindRowNum; for (int32_t t = 0; t< gCurCase->tblNum; ++t) { @@ -685,7 +1072,7 @@ int insertMBMETest1(TAOS_STMT *stmt) { } } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); bpCheckAffectedRows(stmt, 1); destroyData(&data); @@ -694,9 +1081,9 @@ int insertMBMETest1(TAOS_STMT *stmt) { } /* prepare [settbname [bind add exec]] */ -int insertMBMETest2(TAOS_STMT *stmt) { +int insertMBMETest2(TAOS_STMT *stmt, TAOS *taos) { BindData data = {0}; - prepareData(&data); + prepareInsertData(&data); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ @@ -704,7 +1091,7 @@ int insertMBMETest2(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); int32_t bindTimes = gCurCase->rowNum/gCurCase->bindRowNum; for (int32_t t = 0; t< gCurCase->tblNum; ++t) { @@ -739,7 +1126,7 @@ int insertMBMETest2(TAOS_STMT *stmt) { } } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); bpCheckAffectedRows(stmt, 1); destroyData(&data); @@ -748,9 +1135,9 @@ int insertMBMETest2(TAOS_STMT *stmt) { } /* prepare [settbname [settbname bind add exec]] */ -int insertMBMETest3(TAOS_STMT *stmt) { +int insertMBMETest3(TAOS_STMT *stmt, TAOS *taos) { BindData data = {0}; - prepareData(&data); + prepareInsertData(&data); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ @@ -758,7 +1145,7 @@ int insertMBMETest3(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); int32_t bindTimes = gCurCase->rowNum/gCurCase->bindRowNum; for (int32_t t = 0; t< gCurCase->tblNum; ++t) { @@ -803,7 +1190,7 @@ int insertMBMETest3(TAOS_STMT *stmt) { } } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); bpCheckAffectedRows(stmt, 1); destroyData(&data); @@ -813,9 +1200,9 @@ int insertMBMETest3(TAOS_STMT *stmt) { /* prepare [settbname bind add exec] */ -int insertMBMETest4(TAOS_STMT *stmt) { +int insertMBMETest4(TAOS_STMT *stmt, TAOS *taos) { BindData data = {0}; - prepareData(&data); + prepareInsertData(&data); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ @@ -823,7 +1210,7 @@ int insertMBMETest4(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); int32_t bindTimes = gCurCase->rowNum/gCurCase->bindRowNum; @@ -859,7 +1246,7 @@ int insertMBMETest4(TAOS_STMT *stmt) { } } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); bpCheckAffectedRows(stmt, 1); destroyData(&data); @@ -868,12 +1255,12 @@ int insertMBMETest4(TAOS_STMT *stmt) { } /* [prepare [settbname [bind add] exec]] */ -int insertMPMETest1(TAOS_STMT *stmt) { +int insertMPMETest1(TAOS_STMT *stmt, TAOS *taos) { int32_t loop = 0; while (gCurCase->bindColNum >= 2) { BindData data = {0}; - prepareData(&data); + prepareInsertData(&data); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ @@ -881,7 +1268,7 @@ int insertMPMETest1(TAOS_STMT *stmt) { exit(1); } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); int32_t bindTimes = gCurCase->rowNum/gCurCase->bindRowNum; for (int32_t t = 0; t< gCurCase->tblNum; ++t) { @@ -916,7 +1303,7 @@ int insertMPMETest1(TAOS_STMT *stmt) { } } - bpCheckIsInsert(stmt); + bpCheckIsInsert(stmt, 1); destroyData(&data); @@ -932,6 +1319,51 @@ int insertMPMETest1(TAOS_STMT *stmt) { return 0; } +int querySUBTTest1(TAOS_STMT *stmt, TAOS *taos) { + BindData data = {0}; + + for (int32_t t = 0; t< gCurCase->tblNum; ++t) { + memset(&data, 0, sizeof(data)); + prepareQueryData(&data, t); + + int code = taos_stmt_prepare(stmt, data.sql, 0); + if (code != 0){ + printf("failed to execute taos_stmt_prepare. error:%s\n", taos_stmt_errstr(stmt)); + exit(1); + } + + for (int32_t n = 0; n< (gCurCase->rowNum/gCurCase->bindRowNum); ++n) { + bpCheckIsInsert(stmt, 0); + + if (gCaseCtrl.checkParamNum) { + bpCheckParamNum(stmt); + } + + if (bpBindParam(stmt, data.pBind + n * gCurCase->bindColNum)) { + exit(1); + } + + if (taos_stmt_add_batch(stmt)) { + printf("taos_stmt_add_batch error:%s\n", taos_stmt_errstr(stmt)); + exit(1); + } + + if (taos_stmt_execute(stmt) != 0) { + printf("taos_stmt_execute error:%s\n", taos_stmt_errstr(stmt)); + exit(1); + } + + bpCheckQueryResult(stmt, taos, data.sql, data.pBind + n * gCurCase->bindColNum); + } + + bpCheckIsInsert(stmt, 0); + + destroyData(&data); + } + + return 0; +} + #if 0 @@ -3807,59 +4239,35 @@ int stmt_funcb_sc3(TAOS_STMT *stmt) { } #endif -void prepareCheckResultImpl(TAOS *taos, char *tname, bool printr, int expected) { - char sql[255] = "SELECT * FROM "; - TAOS_RES *result; +void prepareCheckResultImpl(TAOS * taos, char *tname, bool printr, int expected, bool silent) { + char sql[255] = "SELECT * FROM "; + int32_t rows = 0; + strcat(sql, tname); - - result = taos_query(taos, sql); - int code = taos_errno(result); - if (code != 0) { - printf("failed to query table, reason:%s\n", taos_errstr(result)); - taos_free_result(result); - exit(1); - } - - - TAOS_ROW row; - int rows = 0; - int num_fields = taos_num_fields(result); - TAOS_FIELD *fields = taos_fetch_fields(result); - char temp[256]; - - // fetch the records row by row - while ((row = taos_fetch_row(result))) { - rows++; - if (printr) { - memset(temp, 0, sizeof(temp)); - taos_print_row(temp, row, fields, num_fields); - printf("[%s]\n", temp); - } - } + bpExecQuery(taos, sql, printr, &rows); if (rows == expected) { - printf("%d rows are fetched as expected from %s\n", rows, tname); + if (!silent) { + printf("%d rows are fetched as expected from %s\n", rows, tname); + } } else { printf("!!!expect %d rows, but %d rows are fetched from %s\n", expected, rows, tname); exit(1); } - - taos_free_result(result); - } -void prepareCheckResult(TAOS *taos) { +void prepareCheckResult(TAOS *taos, bool silent) { char buf[32]; for (int32_t t = 0; t< gCurCase->tblNum; ++t) { if (gCurCase->tblNum > 1) { - sprintf(buf, "t%d", t); + sprintf(buf, "%s%d", bpTbPrefix, t); } else { - sprintf(buf, "t%d", 0); + sprintf(buf, "%s%d", bpTbPrefix, 0); } - prepareCheckResultImpl(taos, buf, gCaseCtrl.printRes, gCurCase->rowNum * gExecLoopTimes); + prepareCheckResultImpl(taos, buf, gCaseCtrl.printRes, gCurCase->rowNum * gExecLoopTimes, silent); } gExecLoopTimes = 1; @@ -4013,7 +4421,7 @@ int sql_s_perf1(TAOS *taos) { void generateCreateTableSQL(char *buf, int32_t tblIdx, int32_t colNum, int32_t *colList, bool stable) { int32_t blen = 0; - blen = sprintf(buf, "create table %s%d ", (stable ? "st" : "t"), tblIdx); + blen = sprintf(buf, "create table %s%d ", (stable ? bpStbPrefix : bpTbPrefix), tblIdx); if (stable) { blen += sprintf(buf + blen, "tags ("); for (int c = 0; c < colNum; ++c) { @@ -4135,7 +4543,7 @@ void generateCreateTableSQL(char *buf, int32_t tblIdx, int32_t colNum, int32_t * } } -void prepare(TAOS *taos, int32_t colNum, int32_t *colList, int autoCreate) { +void prepare(TAOS *taos, int32_t colNum, int32_t *colList, int prepareStb) { TAOS_RES *result; int code; @@ -4154,7 +4562,7 @@ void prepare(TAOS *taos, int32_t colNum, int32_t *colList, int autoCreate) { result = taos_query(taos, "use demo"); taos_free_result(result); - if (!autoCreate) { + if (!prepareStb) { // create table for (int i = 0 ; i < 10; i++) { char buf[1024]; @@ -4184,82 +4592,115 @@ void prepare(TAOS *taos, int32_t colNum, int32_t *colList, int autoCreate) { } -void* runcase(TAOS *taos) { +int32_t runCase(TAOS *taos, int32_t caseIdx, int32_t caseRunIdx, bool silent) { TAOS_STMT *stmt = NULL; - static int32_t caseIdx = 0; - static int32_t caseRunNum = 0; - int64_t beginUs, endUs, totalUs; - - for (int32_t i = 0; i < sizeof(gCase)/sizeof(gCase[0]); ++i) { - if (gCaseCtrl.caseRunNum > 0 && caseRunNum >= gCaseCtrl.caseRunNum) { - break; - } + int64_t beginUs, endUs, totalUs; + CaseCfg cfg = gCase[caseIdx]; + gCurCase = &cfg; + + if ((gCaseCtrl.bindColTypeNum || gCaseCtrl.bindColNum) && (gCurCase->colNum != gFullColNum)) { + return 1; + } + + if (gCurCase->preCaseIdx >= 0) { + bool printRes = gCaseCtrl.printRes; + bool printStmtSql = gCaseCtrl.printStmtSql; + gCaseCtrl.printRes = false; + gCaseCtrl.printStmtSql = false; + runCase(taos, gCurCase->preCaseIdx, caseRunIdx, true); + gCaseCtrl.printRes = printRes; + gCaseCtrl.printStmtSql = printStmtSql; - CaseCfg cfg = gCase[i]; gCurCase = &cfg; + } + + if (gCaseCtrl.runTimes) { + gCurCase->runTimes = gCaseCtrl.runTimes; + } + + if (gCaseCtrl.rowNum) { + gCurCase->rowNum = gCaseCtrl.rowNum; + } + + if (gCurCase->fullCol) { + gCurCase->bindColNum = gCurCase->colNum; + } + + gCurCase->bindNullNum = gCaseCtrl.bindNullNum; + gCurCase->prepareStb = gCaseCtrl.prepareStb; + if (gCaseCtrl.bindColNum) { + gCurCase->bindColNum = gCaseCtrl.bindColNum; + gCurCase->fullCol = false; + } + if (gCaseCtrl.bindRowNum) { + gCurCase->bindRowNum = gCaseCtrl.bindRowNum; + } + if (gCaseCtrl.bindColTypeNum) { + gCurCase->bindColNum = gCaseCtrl.bindColTypeNum; + gCurCase->fullCol = false; + } - if ((gCaseCtrl.bindColTypeNum || gCaseCtrl.bindColNum) && (gCurCase->colNum != gFullColNum)) { - continue; - } - - if (gCaseCtrl.caseIdx >= 0 && caseIdx < gCaseCtrl.caseIdx) { - caseIdx++; - continue; - } - - if (gCaseCtrl.runTimes) { - gCurCase->runTimes = gCaseCtrl.runTimes; - } - - if (gCaseCtrl.rowNum) { - gCurCase->rowNum = gCaseCtrl.rowNum; + if (!silent) { + printf("* Case %d - [%s]%s Begin *\n", caseRunIdx, gCaseCtrl.caseCatalog, gCurCase->caseDesc); + } + + totalUs = 0; + for (int32_t n = 0; n < gCurCase->runTimes; ++n) { + if (gCurCase->preCaseIdx < 0) { + prepare(taos, gCurCase->colNum, gCurCase->colList, gCurCase->prepareStb); } - if (gCurCase->fullCol) { - gCurCase->bindColNum = gCurCase->colNum; - } - - gCurCase->bindNullNum = gCaseCtrl.bindNullNum; - gCurCase->autoCreate = gCaseCtrl.autoCreate; - if (gCaseCtrl.bindColNum) { - gCurCase->bindColNum = gCaseCtrl.bindColNum; - gCurCase->fullCol = false; - } - if (gCaseCtrl.bindRowNum) { - gCurCase->bindRowNum = gCaseCtrl.bindRowNum; - } - if (gCaseCtrl.bindColTypeNum) { - gCurCase->bindColNum = gCaseCtrl.bindColTypeNum; - gCurCase->fullCol = false; + beginUs = taosGetTimestampUs(); + + stmt = taos_stmt_init(taos); + if (NULL == stmt) { + printf("taos_stmt_init failed, error:%s\n", taos_stmt_errstr(stmt)); + exit(1); } + + (*gCurCase->runFn)(stmt, taos); + + taos_stmt_close(stmt); + + endUs = taosGetTimestampUs(); + totalUs += (endUs - beginUs); - printf("* Case %d - [%s]%s Begin *\n", caseIdx, gCaseCtrl.caseCatalog, gCurCase->caseDesc); + prepareCheckResult(taos, silent); + } - totalUs = 0; - for (int32_t n = 0; n < gCurCase->runTimes; ++n) { - prepare(taos, gCurCase->colNum, gCurCase->colList, gCurCase->autoCreate); + if (!silent) { + printf("* Case %d - [%s]%s [AvgTime:%.3fms] End *\n", caseRunIdx, gCaseCtrl.caseCatalog, gCurCase->caseDesc, ((double)totalUs)/1000/gCurCase->runTimes); + } + + return 0; +} - beginUs = taosGetTimestampUs(); - - stmt = taos_stmt_init(taos); - if (NULL == stmt) { - printf("taos_stmt_init failed, error:%s\n", taos_stmt_errstr(stmt)); - exit(1); - } +void* runCaseList(TAOS *taos) { + static int32_t caseRunIdx = 0; + static int32_t caseRunNum = 0; + int32_t caseNum = 0; + int32_t caseIdx = (gCaseCtrl.caseIdx >= 0) ? gCaseCtrl.caseIdx : 0; - (*gCurCase->runFn)(stmt); + for (int32_t i = caseIdx; i < sizeof(gCase)/sizeof(gCase[0]); ++i) { + if (gCaseCtrl.caseNum > 0 && caseNum >= gCaseCtrl.caseNum) { + break; + } - taos_stmt_close(stmt); + if (gCaseCtrl.caseRunNum > 0 && caseRunNum >= gCaseCtrl.caseRunNum) { + break; + } - endUs = taosGetTimestampUs(); - totalUs += (endUs - beginUs); + if (gCaseCtrl.caseRunIdx >= 0 && caseRunIdx < gCaseCtrl.caseRunIdx) { + caseRunIdx++; + continue; + } - prepareCheckResult(taos); + if (runCase(taos, i, caseRunIdx, false)) { + continue; } - - printf("* Case %d - [%s]%s [AvgTime:%.3fms] End *\n", caseIdx, gCaseCtrl.caseCatalog, gCurCase->caseDesc, ((double)totalUs)/1000/gCurCase->runTimes); - caseIdx++; + caseRunIdx++; + caseNum++; caseRunNum++; } @@ -4269,51 +4710,51 @@ void* runcase(TAOS *taos) { void runAll(TAOS *taos) { strcpy(gCaseCtrl.caseCatalog, "Normal Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); - runcase(taos); + runCaseList(taos); strcpy(gCaseCtrl.caseCatalog, "Null Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindNullNum = 1; - runcase(taos); + runCaseList(taos); gCaseCtrl.bindNullNum = 0; strcpy(gCaseCtrl.caseCatalog, "Bind Row Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindRowNum = 1; - runcase(taos); + runCaseList(taos); gCaseCtrl.bindRowNum = 0; strcpy(gCaseCtrl.caseCatalog, "Row Num Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.rowNum = 1000; gCaseCtrl.printRes = false; - runcase(taos); + runCaseList(taos); gCaseCtrl.rowNum = 0; gCaseCtrl.printRes = true; strcpy(gCaseCtrl.caseCatalog, "Runtimes Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.runTimes = 2; - runcase(taos); + runCaseList(taos); gCaseCtrl.runTimes = 0; strcpy(gCaseCtrl.caseCatalog, "Check Param Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.checkParamNum = true; - runcase(taos); + runCaseList(taos); gCaseCtrl.checkParamNum = false; strcpy(gCaseCtrl.caseCatalog, "Bind Col Num Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindColNum = 6; - runcase(taos); + runCaseList(taos); gCaseCtrl.bindColNum = 0; strcpy(gCaseCtrl.caseCatalog, "Bind Col Type Test"); printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindColTypeNum = tListLen(bindColTypeList); gCaseCtrl.bindColTypeList = bindColTypeList; - runcase(taos); + runCaseList(taos); printf("All Test End\n"); }