From 15d7abf46f204018bafb3d8254f6efa9bfaf4cbf Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Mon, 25 Apr 2022 20:03:28 +0800 Subject: [PATCH 1/3] stmt query --- include/client/taos.h | 14 +- include/libs/parser/parser.h | 6 +- include/libs/planner/planner.h | 2 +- source/client/inc/clientInt.h | 3 + source/client/inc/clientStmt.h | 12 +- source/client/src/clientImpl.c | 5 + source/client/src/clientMain.c | 34 ++++- source/client/src/clientStmt.c | 160 ++++++++++++++++------ source/libs/parser/src/parInsert.c | 6 +- source/libs/planner/src/planner.c | 20 ++- source/libs/planner/test/planStmtTest.cpp | 4 +- source/libs/scalar/src/filter.c | 3 +- tests/script/api/batchprepare.c | 41 +++--- 13 files changed, 215 insertions(+), 95 deletions(-) diff --git a/include/client/taos.h b/include/client/taos.h index 6afbcee6f1..b784136d3f 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -92,14 +92,14 @@ typedef struct taosField { typedef void (*__taos_async_fn_t)(void *param, TAOS_RES *, int code); -typedef struct TAOS_BIND_v2 { +typedef struct TAOS_MULTI_BIND { int buffer_type; void *buffer; - int32_t buffer_length; + uintptr_t buffer_length; int32_t *length; char *is_null; int num; -} TAOS_BIND_v2; +} TAOS_MULTI_BIND; typedef enum { SET_CONF_RET_SUCC = 0, @@ -130,16 +130,16 @@ const char *taos_data_type(int type); 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_BIND_v2 *tags); +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_is_insert(TAOS_STMT *stmt, int *insert); DLL_EXPORT int taos_stmt_num_params(TAOS_STMT *stmt, int *nums); DLL_EXPORT int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes); -DLL_EXPORT int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_BIND_v2 *bind); -DLL_EXPORT int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind); -DLL_EXPORT int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind, int colIdx); +DLL_EXPORT int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind); +DLL_EXPORT int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind); +DLL_EXPORT int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx); DLL_EXPORT int taos_stmt_add_batch(TAOS_STMT *stmt); DLL_EXPORT int taos_stmt_execute(TAOS_STMT *stmt); DLL_EXPORT TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt); diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 58482735ba..875cdc2755 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -88,11 +88,11 @@ int32_t qCloneStmtDataBlock(void** pDst, void* pSrc); void qFreeStmtDataBlock(void* pDataBlock); int32_t qRebuildStmtDataBlock(void** pDst, void* pSrc); void qDestroyStmtDataBlock(void* pBlock); -int32_t qBindStmtColsValue(void *pBlock, TAOS_BIND_v2 *bind, char *msgBuf, int32_t msgBufLen); -int32_t qBindStmtSingleColValue(void *pBlock, TAOS_BIND_v2 *bind, char *msgBuf, int32_t msgBufLen, int32_t colIdx, int32_t rowNum); +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 qBindStmtTagsValue(void *pBlock, void *boundTags, int64_t suid, SName *pName, TAOS_BIND_v2 *bind, char *msgBuf, int32_t msgBufLen); +int32_t qBindStmtTagsValue(void *pBlock, void *boundTags, int64_t suid, SName *pName, TAOS_MULTI_BIND *bind, char *msgBuf, int32_t msgBufLen); void destroyBoundColumnInfo(void* pBoundInfo); int32_t qCreateSName(SName* pName, const char* pTableName, int32_t acctId, char* dbName, char *msgBuf, int32_t msgBufLen); diff --git a/include/libs/planner/planner.h b/include/libs/planner/planner.h index 78d0911502..b78cbb639c 100644 --- a/include/libs/planner/planner.h +++ b/include/libs/planner/planner.h @@ -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_BIND_v2* pParams); +int32_t qStmtBindParam(SQueryPlan* pPlan, TAOS_MULTI_BIND* pParams, int32_t colIdx); // 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/clientInt.h b/source/client/inc/clientInt.h index 814caf330a..c431f40c68 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -306,6 +306,9 @@ int hbAddConnInfo(SAppHbMgr* pAppHbMgr, SClientHbKey connKey, void* key, void* v void hbMgrInitMqHbRspHandle(); SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, int32_t code, bool keepQuery); +int32_t getQueryPlan(SRequestObj* pRequest, SQuery* pQuery, SArray** pNodeList); +int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList); + #ifdef __cplusplus } diff --git a/source/client/inc/clientStmt.h b/source/client/inc/clientStmt.h index 04e9c3be9a..061d757551 100644 --- a/source/client/inc/clientStmt.h +++ b/source/client/inc/clientStmt.h @@ -34,8 +34,7 @@ typedef enum { STMT_PREPARE, STMT_SETTBNAME, STMT_SETTAGS, - STMT_FETCH_TAG_FIELDS, - STMT_FETCH_COL_FIELDS, + STMT_FETCH_FIELDS, STMT_BIND, STMT_BIND_COL, STMT_ADD_BATCH, @@ -75,6 +74,8 @@ typedef struct SStmtSQLInfo { SQuery* pQuery; char* sqlStr; int32_t sqlLen; + SArray* nodeList; + SQueryPlan* pQueryPlan; } SStmtSQLInfo; typedef struct STscStmt { @@ -87,6 +88,8 @@ typedef struct STscStmt { SStmtBindInfo bInfo; } STscStmt; +#define STMT_STATUS_NE(S) (pStmt->sql.status != STMT_##S) +#define STMT_STATUS_EQ(S) (pStmt->sql.status == STMT_##S) #define STMT_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; return _code; } } while (0) #define STMT_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0) @@ -97,14 +100,15 @@ int stmtClose(TAOS_STMT *stmt); int stmtExec(TAOS_STMT *stmt); const char *stmtErrstr(TAOS_STMT *stmt); int stmtAffectedRows(TAOS_STMT *stmt); +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_BIND_v2 *tags); +int stmtSetTbTags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags); int stmtIsInsert(TAOS_STMT *stmt, int *insert); int stmtGetParamNum(TAOS_STMT *stmt, int *nums); int stmtAddBatch(TAOS_STMT *stmt); TAOS_RES *stmtUseResult(TAOS_STMT *stmt); -int stmtBindBatch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind, int32_t colIdx); +int stmtBindBatch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int32_t colIdx); #ifdef __cplusplus diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 367baef53f..f161f6827c 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -306,6 +306,11 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList return pRequest->code; } +int32_t getQueryPlan(SRequestObj* pRequest, SQuery* pQuery, SArray** pNodeList) { + *pNodeList = taosArrayInit(4, sizeof(struct SQueryNodeAddr)); + return getPlan(pRequest, pQuery, &pRequest->body.pDag, *pNodeList); +} + SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, int32_t code, bool keepQuery) { if (TSDB_CODE_SUCCESS == code) { switch (pQuery->execMode) { diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 27efcee76e..954f36a16d 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -603,7 +603,7 @@ int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) { return stmtPrepare(stmt, sql, length); } -int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_BIND_v2 *tags) { +int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) { if (stmt == NULL || name == NULL) { tscError("NULL parameter for %s", __FUNCTION__); terrno = TSDB_CODE_INVALID_PARA; @@ -636,7 +636,7 @@ int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); } -int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_BIND_v2 *bind) { +int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) { if (stmt == NULL || bind == NULL) { tscError("NULL parameter for %s", __FUNCTION__); terrno = TSDB_CODE_INVALID_PARA; @@ -652,7 +652,7 @@ int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_BIND_v2 *bind) { return stmtBindBatch(stmt, bind, -1); } -int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind) { +int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) { if (stmt == NULL || bind == NULL) { tscError("NULL parameter for %s", __FUNCTION__); terrno = TSDB_CODE_INVALID_PARA; @@ -665,10 +665,18 @@ int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind) { return terrno; } + int32_t insert = 0; + stmtIsInsert(stmt, &insert); + if (0 == insert && bind->num > 1) { + tscError("only one row data allowed for query"); + terrno = TSDB_CODE_INVALID_PARA; + return terrno; + } + return stmtBindBatch(stmt, bind, -1); } -int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind, int colIdx) { +int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) { if (stmt == NULL || bind == NULL) { tscError("NULL parameter for %s", __FUNCTION__); terrno = TSDB_CODE_INVALID_PARA; @@ -680,6 +688,14 @@ int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind, int c terrno = TSDB_CODE_INVALID_PARA; return terrno; } + + int32_t insert = 0; + stmtIsInsert(stmt, &insert); + if (0 == insert && bind->num > 1) { + tscError("only one row data allowed for query"); + terrno = TSDB_CODE_INVALID_PARA; + return terrno; + } return stmtBindBatch(stmt, bind, colIdx); } @@ -748,6 +764,16 @@ int taos_stmt_affected_rows(TAOS_STMT *stmt) { return stmtAffectedRows(stmt); } +int taos_stmt_affected_rows_once(TAOS_STMT *stmt) { + if (stmt == NULL) { + tscError("NULL parameter for %s", __FUNCTION__); + terrno = TSDB_CODE_INVALID_PARA; + return 0; + } + + return stmtAffectedRowsOnce(stmt); +} + int taos_stmt_close(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 0972ff3477..5bda8f52ce 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -5,14 +5,51 @@ #include "tdef.h" int32_t stmtSwitchStatus(STscStmt* pStmt, STMT_STATUS newStatus) { + int32_t code = 0; + switch (newStatus) { - case STMT_SETTBNAME: + case STMT_PREPARE: break; + case STMT_SETTBNAME: + if (STMT_STATUS_NE(PREPARE) && STMT_STATUS_NE(ADD_BATCH) && STMT_STATUS_NE(EXECUTE)) { + code = TSDB_CODE_TSC_STMT_API_ERROR; + } + break; + case STMT_SETTAGS: + if (STMT_STATUS_NE(SETTBNAME)) { + code = TSDB_CODE_TSC_STMT_API_ERROR; + } + break; + case STMT_FETCH_FIELDS: + if (STMT_STATUS_EQ(INIT)) { + code = TSDB_CODE_TSC_STMT_API_ERROR; + } + break; + case STMT_BIND: + if (STMT_STATUS_EQ(INIT) || STMT_STATUS_EQ(BIND_COL)) { + code = TSDB_CODE_TSC_STMT_API_ERROR; + } + break; + case STMT_BIND_COL: + if (STMT_STATUS_EQ(INIT) || STMT_STATUS_EQ(BIND)) { + code = TSDB_CODE_TSC_STMT_API_ERROR; + } + break; + case STMT_ADD_BATCH: + if (STMT_STATUS_NE(BIND) && STMT_STATUS_NE(BIND_COL) && STMT_STATUS_NE(FETCH_FIELDS)) { + code = TSDB_CODE_TSC_STMT_API_ERROR; + } + break; + case STMT_EXECUTE: + if (STMT_STATUS_NE(ADD_BATCH) && STMT_STATUS_NE(FETCH_FIELDS)) { + code = TSDB_CODE_TSC_STMT_API_ERROR; + } default: + code = TSDB_CODE_TSC_APP_ERROR; break; } - //STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR); + STMT_ERR_RET(code); pStmt->sql.status = newStatus; @@ -69,15 +106,10 @@ int32_t stmtCacheBlock(STscStmt *pStmt) { return TSDB_CODE_SUCCESS; } - uint64_t uid; - if (TSDB_CHILD_TABLE == pStmt->bInfo.tbType) { - uid = pStmt->bInfo.tbSuid; - } else { - ASSERT(TSDB_NORMAL_TABLE == pStmt->bInfo.tbType); - uid = pStmt->bInfo.tbUid; - } + uint64_t uid = pStmt->bInfo.tbUid; + uint64_t tuid = (TSDB_CHILD_TABLE == pStmt->bInfo.tbType) ? pStmt->bInfo.tbSuid : uid; - if (taosHashGet(pStmt->sql.pTableCache, &uid, sizeof(uid))) { + if (taosHashGet(pStmt->sql.pTableCache, &tuid, sizeof(tuid))) { return TSDB_CODE_SUCCESS; } @@ -91,7 +123,7 @@ int32_t stmtCacheBlock(STscStmt *pStmt) { .boundTags = pStmt->bInfo.boundTags, }; - if (taosHashPut(pStmt->sql.pTableCache, &uid, sizeof(uid), &cache, sizeof(cache))) { + if (taosHashPut(pStmt->sql.pTableCache, &tuid, sizeof(tuid), &cache, sizeof(cache))) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -149,9 +181,11 @@ int32_t stmtCleanBindInfo(STscStmt* pStmt) { return TSDB_CODE_SUCCESS; } -int32_t stmtCleanExecInfo(STscStmt* pStmt, bool keepTable) { - taos_free_result(pStmt->exec.pRequest); - pStmt->exec.pRequest = NULL; +int32_t stmtCleanExecInfo(STscStmt* pStmt, bool keepTable, bool freeRequest) { + if (STMT_TYPE_QUERY != pStmt->sql.type || freeRequest) { + taos_free_result(pStmt->exec.pRequest); + pStmt->exec.pRequest = NULL; + } void *pIter = taosHashIterate(pStmt->exec.pBlockHash, NULL); while (pIter) { @@ -186,7 +220,9 @@ int32_t stmtCleanExecInfo(STscStmt* pStmt, bool keepTable) { int32_t stmtCleanSQLInfo(STscStmt* pStmt) { taosMemoryFree(pStmt->sql.sqlStr); qDestroyQuery(pStmt->sql.pQuery); - + qDestroyQueryPlan(pStmt->sql.pQueryPlan); + taosArrayDestroy(pStmt->sql.nodeList); + void *pIter = taosHashIterate(pStmt->sql.pTableCache, NULL); while (pIter) { SStmtTableCache* pCache = (SStmtTableCache*)pIter; @@ -201,7 +237,7 @@ int32_t stmtCleanSQLInfo(STscStmt* pStmt) { memset(&pStmt->sql, 0, sizeof(pStmt->sql)); - STMT_ERR_RET(stmtCleanExecInfo(pStmt, false)); + STMT_ERR_RET(stmtCleanExecInfo(pStmt, false, true)); STMT_ERR_RET(stmtCleanBindInfo(pStmt)); return TSDB_CODE_SUCCESS; @@ -333,6 +369,13 @@ int stmtSetTbName(TAOS_STMT *stmt, const char *tbName) { STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTBNAME)); + int32_t insert = 0; + stmtIsInsert(stmt, &insert); + if (0 == insert) { + tscError("set tb name not available for none insert statement"); + STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR); + } + if (NULL == pStmt->exec.pRequest) { STMT_ERR_RET(buildRequest(pStmt->taos, pStmt->sql.sqlStr, pStmt->sql.sqlLen, &pStmt->exec.pRequest)); } @@ -349,7 +392,7 @@ int stmtSetTbName(TAOS_STMT *stmt, const char *tbName) { return TSDB_CODE_SUCCESS; } -int stmtSetTbTags(TAOS_STMT *stmt, TAOS_BIND_v2 *tags) { +int stmtSetTbTags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) { STscStmt* pStmt = (STscStmt*)stmt; STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTAGS)); @@ -370,15 +413,7 @@ int stmtSetTbTags(TAOS_STMT *stmt, TAOS_BIND_v2 *tags) { } -int32_t stmtFetchTagFields(TAOS_STMT *stmt, int32_t *fieldNum, TAOS_FIELD** fields) { - STscStmt* pStmt = (STscStmt*)stmt; - - STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_TAG_FIELDS)); - - if (pStmt->bInfo.needParse) { - STMT_ERR_RET(stmtParseSql(pStmt)); - } - +int32_t stmtFetchTagFields(STscStmt* pStmt, int32_t *fieldNum, TAOS_FIELD** 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); @@ -395,15 +430,7 @@ int32_t stmtFetchTagFields(TAOS_STMT *stmt, int32_t *fieldNum, TAOS_FIELD** fiel return TSDB_CODE_SUCCESS; } -int32_t stmtFetchColFields(TAOS_STMT *stmt, int32_t *fieldNum, TAOS_FIELD** fields) { - STscStmt* pStmt = (STscStmt*)stmt; - - STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_COL_FIELDS)); - - if (pStmt->bInfo.needParse) { - STMT_ERR_RET(stmtParseSql(pStmt)); - } - +int32_t stmtFetchColFields(STscStmt* pStmt, int32_t *fieldNum, TAOS_FIELD** 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); @@ -420,7 +447,7 @@ int32_t stmtFetchColFields(TAOS_STMT *stmt, int32_t *fieldNum, TAOS_FIELD** fiel return TSDB_CODE_SUCCESS; } -int stmtBindBatch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind, int32_t colIdx) { +int stmtBindBatch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int32_t colIdx) { STscStmt* pStmt = (STscStmt*)stmt; STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_BIND)); @@ -429,6 +456,11 @@ int stmtBindBatch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind, int32_t colIdx) { 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)); } @@ -437,6 +469,16 @@ int stmtBindBatch(TAOS_STMT *stmt, TAOS_BIND_v2 *bind, int32_t colIdx) { STMT_ERR_RET(stmtParseSql(pStmt)); } + if (STMT_TYPE_QUERY == pStmt->sql.type) { + if (NULL == pStmt->sql.pQueryPlan) { + 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_RET(qStmtBindParam(pStmt->sql.pQueryPlan, bind, colIdx)); + } + STableDataBlocks **pDataBlock = (STableDataBlocks**)taosHashGet(pStmt->exec.pBlockHash, (const char*)&pStmt->bInfo.tbUid, sizeof(pStmt->bInfo.tbUid)); if (NULL == pDataBlock) { tscError("table uid %" PRIx64 "not found in exec blockHash", pStmt->bInfo.tbUid); @@ -480,10 +522,13 @@ int stmtExec(TAOS_STMT *stmt) { STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_EXECUTE)); - STMT_ERR_RET(qBuildStmtOutput(pStmt->sql.pQuery, pStmt->exec.pVgHash, pStmt->exec.pBlockHash)); - - launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, TSDB_CODE_SUCCESS, true); - + if (STMT_TYPE_QUERY == pStmt->sql.type) { + scheduleQuery(pStmt->exec.pRequest, pStmt->sql.pQueryPlan, pStmt->sql.nodeList); + } else { + STMT_ERR_RET(qBuildStmtOutput(pStmt->sql.pQuery, pStmt->exec.pVgHash, pStmt->exec.pBlockHash)); + launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, TSDB_CODE_SUCCESS, true); + } + STMT_ERR_JRET(pStmt->exec.pRequest->code); pStmt->exec.affectedRows = taos_affected_rows(pStmt->exec.pRequest); @@ -491,7 +536,7 @@ int stmtExec(TAOS_STMT *stmt) { _return: - stmtCleanExecInfo(pStmt, (code ? false : true)); + stmtCleanExecInfo(pStmt, (code ? false : true), false); ++pStmt->sql.runTimes; @@ -523,6 +568,10 @@ int stmtAffectedRows(TAOS_STMT *stmt) { return ((STscStmt*)stmt)->affectedRows; } +int stmtAffectedRowsOnce(TAOS_STMT *stmt) { + return ((STscStmt*)stmt)->exec.affectedRows; +} + int stmtIsInsert(TAOS_STMT *stmt, int *insert) { STscStmt* pStmt = (STscStmt*)stmt; @@ -536,13 +585,38 @@ int stmtIsInsert(TAOS_STMT *stmt, int *insert) { } int stmtGetParamNum(TAOS_STMT *stmt, int *nums) { - STMT_ERR_RET(stmtFetchColFields(stmt, nums, NULL)); + STscStmt* pStmt = (STscStmt*)stmt; + + STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS)); + + if (pStmt->bInfo.needParse) { + STMT_ERR_RET(stmtParseSql(pStmt)); + } + + if (STMT_TYPE_QUERY == pStmt->sql.type) { + if (NULL == pStmt->sql.pQueryPlan) { + 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; + } + + *nums = (pStmt->sql.pQueryPlan->pPlaceholderValues) ? pStmt->sql.pQueryPlan->pPlaceholderValues->length : 0; + } else { + STMT_ERR_RET(stmtFetchColFields(stmt, nums, NULL)); + } return TSDB_CODE_SUCCESS; } TAOS_RES *stmtUseResult(TAOS_STMT *stmt) { - return NULL; + STscStmt* pStmt = (STscStmt*)stmt; + + if (STMT_TYPE_QUERY != pStmt->sql.type) { + tscError("useResult only for query statement"); + return NULL; + } + + return pStmt->exec.pRequest; } diff --git a/source/libs/parser/src/parInsert.c b/source/libs/parser/src/parInsert.c index f69a383005..fb14d897b1 100644 --- a/source/libs/parser/src/parInsert.c +++ b/source/libs/parser/src/parInsert.c @@ -1257,7 +1257,7 @@ int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash return TSDB_CODE_SUCCESS; } -int32_t qBindStmtTagsValue(void *pBlock, void *boundTags, int64_t suid, SName *pName, TAOS_BIND_v2 *bind, char *msgBuf, int32_t msgBufLen){ +int32_t qBindStmtTagsValue(void *pBlock, void *boundTags, int64_t suid, SName *pName, TAOS_MULTI_BIND *bind, char *msgBuf, int32_t msgBufLen){ STableDataBlocks *pDataBlock = (STableDataBlocks *)pBlock; SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; SParsedDataColInfo* tags = (SParsedDataColInfo*)boundTags; @@ -1308,7 +1308,7 @@ int32_t qBindStmtTagsValue(void *pBlock, void *boundTags, int64_t suid, SName *p } -int32_t qBindStmtColsValue(void *pBlock, TAOS_BIND_v2 *bind, char *msgBuf, int32_t msgBufLen) { +int32_t qBindStmtColsValue(void *pBlock, TAOS_MULTI_BIND *bind, char *msgBuf, int32_t msgBufLen) { STableDataBlocks *pDataBlock = (STableDataBlocks *)pBlock; SSchema* pSchema = getTableColumnSchema(pDataBlock->pTableMeta); int32_t extendedRowSize = getExtendedRowSize(pDataBlock); @@ -1382,7 +1382,7 @@ int32_t qBindStmtColsValue(void *pBlock, TAOS_BIND_v2 *bind, char *msgBuf, int32 return TSDB_CODE_SUCCESS; } -int32_t qBindStmtSingleColValue(void *pBlock, TAOS_BIND_v2 *bind, char *msgBuf, int32_t msgBufLen, int32_t colIdx, int32_t rowNum) { +int32_t qBindStmtSingleColValue(void *pBlock, TAOS_MULTI_BIND *bind, char *msgBuf, int32_t msgBufLen, int32_t colIdx, int32_t rowNum) { STableDataBlocks *pDataBlock = (STableDataBlocks *)pBlock; SSchema* pSchema = getTableColumnSchema(pDataBlock->pTableMeta); int32_t extendedRowSize = getExtendedRowSize(pDataBlock); diff --git a/source/libs/planner/src/planner.c b/source/libs/planner/src/planner.c index 004f0b18fd..828b108283 100644 --- a/source/libs/planner/src/planner.c +++ b/source/libs/planner/src/planner.c @@ -101,8 +101,8 @@ int32_t qSetSubplanExecutionNode(SSubplan* subplan, int32_t groupId, SDownstream return setSubplanExecutionNode(subplan->pNode, groupId, pSource); } -static int32_t setValueByBindParam(SValueNode* pVal, TAOS_BIND_v2* pParam) { - if (1 == *(pParam->is_null)) { +static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam) { + if (pParam->is_null && 1 == *(pParam->is_null)) { pVal->node.resType.type = TSDB_DATA_TYPE_NULL; pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes; return TSDB_CODE_SUCCESS; @@ -168,11 +168,17 @@ static int32_t setValueByBindParam(SValueNode* pVal, TAOS_BIND_v2* pParam) { return TSDB_CODE_SUCCESS; } -int32_t qStmtBindParam(SQueryPlan* pPlan, TAOS_BIND_v2* pParams) { - int32_t index = 0; - SNode* pNode = NULL; - FOREACH(pNode, pPlan->pPlaceholderValues) { - setValueByBindParam((SValueNode*)pNode, pParams + index); +int32_t qStmtBindParam(SQueryPlan* pPlan, TAOS_MULTI_BIND* pParams, int32_t colIdx) { + if (colIdx < 0) { + int32_t index = 0; + SNode* pNode = NULL; + + FOREACH(pNode, pPlan->pPlaceholderValues) { + setValueByBindParam((SValueNode*)pNode, pParams + index); + ++index; + } + } else { + setValueByBindParam((SValueNode*)nodesListGetNode(pPlan->pPlaceholderValues, colIdx), pParams); } return TSDB_CODE_SUCCESS; } diff --git a/source/libs/planner/test/planStmtTest.cpp b/source/libs/planner/test/planStmtTest.cpp index ca206c7843..3642e24b32 100644 --- a/source/libs/planner/test/planStmtTest.cpp +++ b/source/libs/planner/test/planStmtTest.cpp @@ -26,7 +26,7 @@ public: } void bindParam(int32_t val) { - TAOS_BIND_v2* pBind = pBindParams_ + paramNo_++; + TAOS_MULTI_BIND* pBind = pBindParams_ + paramNo_++; pBind->buffer_type = TSDB_DATA_TYPE_INT; pBind->num = 1; pBind->buffer_length = sizeof(int32_t); @@ -43,7 +43,7 @@ public: } private: - TAOS_BIND_v2* pBindParams_; + TAOS_MULTI_BIND* pBindParams_; int32_t paramNo_; }; diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index c17e854aa9..1fb6781d5d 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -3774,11 +3774,12 @@ bool filterExecute(SFilterInfo *info, SSDataBlock *pSrc, int8_t** p, SColumnData SDataType type = {.type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)}; output.columnData = createColumnInfoData(&type, pSrc->info.rows); - *p = (int8_t *)output.columnData->pData; SArray *pList = taosArrayInit(1, POINTER_BYTES); taosArrayPush(pList, &pSrc); FLT_ERR_RET(scalarCalculate(info->sclCtx.node, pList, &output)); + *p = (int8_t *)output.columnData->pData; + taosArrayDestroy(pList); return false; } diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 2e046bd3ff..06c832497c 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -31,7 +31,7 @@ typedef struct { char* binaryData; char* isNull; int32_t* binaryLen; - TAOS_BIND_v2* pBind; + TAOS_MULTI_BIND* pBind; char* sql; int32_t* colTypes; int32_t colNum; @@ -163,7 +163,7 @@ static int64_t taosGetTimestampUs() { return (int64_t)systemTime.tv_sec * 1000000L + (int64_t)systemTime.tv_usec; } -bool colExists(TAOS_BIND_v2* pBind, int32_t dataType) { +bool colExists(TAOS_MULTI_BIND* pBind, int32_t dataType) { int32_t i = 0; while (true) { if (0 == pBind[i].buffer_type) { @@ -393,7 +393,7 @@ int32_t prepareData(BindData *data) { data->colNum = 0; data->colTypes = taosMemoryCalloc(30, sizeof(int32_t)); data->sql = taosMemoryCalloc(1, 1024); - data->pBind = taosMemoryCalloc((allRowNum/gCurCase->bindRowNum)*gCurCase->bindColNum, sizeof(TAOS_BIND_v2)); + data->pBind = taosMemoryCalloc((allRowNum/gCurCase->bindRowNum)*gCurCase->bindColNum, sizeof(TAOS_MULTI_BIND)); data->tsData = taosMemoryMalloc(allRowNum * sizeof(int64_t)); data->boolData = taosMemoryMalloc(allRowNum * sizeof(bool)); data->tinyData = taosMemoryMalloc(allRowNum * sizeof(int8_t)); @@ -463,7 +463,7 @@ void destroyData(BindData *data) { taosMemoryFree(data->colTypes); } -int32_t bpBindParam(TAOS_STMT *stmt, TAOS_BIND_v2 *bind) { +int32_t bpBindParam(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) { static int32_t n = 0; if (gCurCase->bindRowNum > 1) { @@ -951,7 +951,7 @@ int stmt_funcb_autoctb1(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); // int one_null = 1; int one_not_null = 0; @@ -1164,7 +1164,7 @@ int stmt_funcb_autoctb2(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); // int one_null = 1; int one_not_null = 0; @@ -1378,7 +1378,7 @@ int stmt_funcb_autoctb3(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); // int one_null = 1; int one_not_null = 0; @@ -1569,7 +1569,7 @@ int stmt_funcb_autoctb4(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*5); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*5); // int one_null = 1; int one_not_null = 0; @@ -1722,7 +1722,7 @@ int stmt_funcb_autoctb_e1(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); // int one_null = 1; int one_not_null = 0; @@ -1911,7 +1911,7 @@ int stmt_funcb_autoctb_e2(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); // int one_null = 1; int one_not_null = 0; @@ -2128,7 +2128,7 @@ int stmt_funcb_autoctb_e3(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); // int one_null = 1; int one_not_null = 0; @@ -2343,7 +2343,7 @@ int stmt_funcb_autoctb_e4(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); // int one_null = 1; int one_not_null = 0; @@ -2570,7 +2570,7 @@ int stmt_funcb_autoctb_e5(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(10 * sizeof(int)); TAOS_BIND *tags = taosMemoryCalloc(1, sizeof(TAOS_BIND) * 9 * 1); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 1*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); // int one_null = 1; int one_not_null = 0; @@ -2791,7 +2791,7 @@ int stmt_funcb4(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(60 * sizeof(int)); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 900000*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 900000*10); char* is_null = taosMemoryMalloc(sizeof(char) * 60); char* no_null = taosMemoryMalloc(sizeof(char) * 60); @@ -2950,7 +2950,7 @@ int stmt_funcb5(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(18000 * sizeof(int)); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 3000*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 3000*10); char* is_null = taosMemoryMalloc(sizeof(char) * 18000); char* no_null = taosMemoryMalloc(sizeof(char) * 18000); @@ -3094,7 +3094,7 @@ int stmt_funcb_ssz1(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(30000 * sizeof(int)); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 3000*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 3000*10); char* no_null = taosMemoryMalloc(sizeof(int) * 200000); for (int i = 0; i < 30000; ++i) { @@ -3185,7 +3185,7 @@ int stmt_funcb_s1(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(60 * sizeof(int)); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 900000*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 900000*10); char* is_null = taosMemoryMalloc(sizeof(char) * 60); char* no_null = taosMemoryMalloc(sizeof(char) * 60); @@ -3347,7 +3347,7 @@ int stmt_funcb_sc1(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(60 * sizeof(int)); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 900000*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 900000*10); char* is_null = taosMemoryMalloc(sizeof(char) * 60); char* no_null = taosMemoryMalloc(sizeof(char) * 60); @@ -3505,7 +3505,7 @@ int stmt_funcb_sc2(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(60 * sizeof(int)); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 900000*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 900000*10); char* is_null = taosMemoryMalloc(sizeof(char) * 60); char* no_null = taosMemoryMalloc(sizeof(char) * 60); @@ -3665,7 +3665,7 @@ int stmt_funcb_sc3(TAOS_STMT *stmt) { int *lb = taosMemoryMalloc(60 * sizeof(int)); - TAOS_BIND_v2 *params = taosMemoryCalloc(1, sizeof(TAOS_BIND_v2) * 60*10); + TAOS_MULTI_BIND *params = taosMemoryCalloc(1, sizeof(TAOS_MULTI_BIND) * 60*10); char* is_null = taosMemoryMalloc(sizeof(char) * 60); char* no_null = taosMemoryMalloc(sizeof(char) * 60); @@ -4147,6 +4147,7 @@ void prepare(TAOS *taos, int32_t colNum, int32_t *colList, int autoCreate) { exit(1); } taos_free_result(result); + sleep(2); //TODO REMOVE IT result = taos_query(taos, "use demo"); taos_free_result(result); From 65a7d0f1c2be5d820f0545edfb6d02c8483a0814 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Tue, 26 Apr 2022 15:51:46 +0800 Subject: [PATCH 2/3] scalar constant --- include/util/tdef.h | 2 + source/client/src/clientStmt.c | 3 +- source/libs/executor/src/scanoperator.c | 5 +- source/libs/scalar/inc/sclInt.h | 1 + source/libs/scalar/src/filter.c | 29 ++++--- source/libs/scalar/src/scalar.c | 85 ++++++++++++++++++-- source/libs/scalar/src/sclvector.c | 16 ++-- tests/script/api/batchprepare.c | 69 +++++++++++----- tests/script/tsim/query/scalarNull.sim | 102 ++++++++++++++++++++++++ 9 files changed, 265 insertions(+), 47 deletions(-) create mode 100644 tests/script/tsim/query/scalarNull.sim diff --git a/include/util/tdef.h b/include/util/tdef.h index aa0d0bd8ff..bc6915766e 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -195,6 +195,8 @@ typedef enum EOperatorType { OP_TYPE_JSON_CONTAINS } EOperatorType; +#define OP_TYPE_CALC_MAX OP_TYPE_BIT_OR + typedef enum ELogicConditionType { LOGIC_COND_TYPE_AND = 1, LOGIC_COND_TYPE_OR, diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c index 5bda8f52ce..20c318e212 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -11,7 +11,7 @@ int32_t stmtSwitchStatus(STscStmt* pStmt, STMT_STATUS newStatus) { case STMT_PREPARE: break; case STMT_SETTBNAME: - if (STMT_STATUS_NE(PREPARE) && STMT_STATUS_NE(ADD_BATCH) && STMT_STATUS_NE(EXECUTE)) { + if (STMT_STATUS_EQ(INIT) || STMT_STATUS_EQ(BIND) || STMT_STATUS_EQ(BIND_COL)) { code = TSDB_CODE_TSC_STMT_API_ERROR; } break; @@ -44,6 +44,7 @@ int32_t stmtSwitchStatus(STscStmt* pStmt, STMT_STATUS newStatus) { if (STMT_STATUS_NE(ADD_BATCH) && STMT_STATUS_NE(FETCH_FIELDS)) { code = TSDB_CODE_TSC_STMT_API_ERROR; } + break; default: code = TSDB_CODE_TSC_APP_ERROR; break; diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index a70e402871..f59c04b840 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -245,6 +245,9 @@ int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanInfo* pTableScanInfo, relocateColumnData(pBlock, pTableScanInfo->pColMatchInfo, pCols); + // reset the block to be 0 by default, this blockId is assigned by physical plan and is used by direct upstream operator. + pBlock->info.blockId = 0; + doFilter(pTableScanInfo->pFilterNode, pBlock); if (pBlock->info.rows == 0) { pCost->filterOutBlocks += 1; @@ -294,8 +297,6 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator, bool* newgroup) { continue; } - // reset the block to be 0 by default, this blockId is assigned by physical plan and is used by direct upstream operator. - pBlock->info.blockId = 0; return pBlock; } diff --git a/source/libs/scalar/inc/sclInt.h b/source/libs/scalar/inc/sclInt.h index 9142cc41c4..021e0e0f96 100644 --- a/source/libs/scalar/inc/sclInt.h +++ b/source/libs/scalar/inc/sclInt.h @@ -34,6 +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 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 1fb6781d5d..ef35d19544 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -1031,18 +1031,29 @@ int32_t fltAddGroupUnitFromNode(SFilterInfo *info, SNode* tree, SArray *group) { SScalarParam out = {.columnData = taosMemoryCalloc(1, sizeof(SColumnInfoData))}; out.columnData->info.type = type; + out.columnData->info.bytes = tDataTypes[type].bytes; for (int32_t i = 0; i < listNode->pNodeList->length; ++i) { SValueNode *valueNode = (SValueNode *)cell->pNode; - code = doConvertDataType(valueNode, &out); - if (code) { -// fltError("convert from %d to %d failed", in.type, out.type); - FLT_ERR_RET(code); - } - - len = tDataTypes[type].bytes; + if (valueNode->node.resType.type != type) { + code = doConvertDataType(valueNode, &out); + if (code) { + // fltError("convert from %d to %d failed", in.type, out.type); + FLT_ERR_RET(code); + } + + len = tDataTypes[type].bytes; - filterAddField(info, NULL, (void**) &out.columnData->pData, FLD_TYPE_VALUE, &right, len, true); + filterAddField(info, NULL, (void**) &out.columnData->pData, FLD_TYPE_VALUE, &right, len, true); + out.columnData->pData = NULL; + } else { + void *data = taosMemoryCalloc(1, tDataTypes[type].bytes); + if (NULL == data) { + FLT_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + memcpy(data, nodesGetValueFromNode(valueNode), tDataTypes[type].bytes); + filterAddField(info, NULL, (void**) &data, FLD_TYPE_VALUE, &right, len, true); + } filterAddUnit(info, OP_TYPE_EQUAL, &left, &right, &uidx); SFilterGroup fgroup = {0}; @@ -3599,7 +3610,7 @@ EDealRes fltReviseRewriter(SNode** pNode, void* pContext) { return DEAL_RES_CONTINUE; } - if ((QUERY_NODE_COLUMN != nodeType(node->pRight)) && (QUERY_NODE_VALUE != nodeType(node->pRight))) { + if ((QUERY_NODE_COLUMN != nodeType(node->pRight)) && (QUERY_NODE_VALUE != nodeType(node->pRight)) && (QUERY_NODE_NODE_LIST != nodeType(node->pRight))) { stat->scalarMode = true; return DEAL_RES_CONTINUE; } diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index 6773f8192b..befc0be08e 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -71,7 +71,7 @@ int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type) { for (int32_t i = 0; i < nodeList->pNodeList->length; ++i) { SValueNode *valueNode = (SValueNode *)cell->pNode; - + if (valueNode->node.resType.type != type) { out.columnData->info.type = type; out.columnData->info.bytes = tDataTypes[type].bytes; @@ -176,7 +176,7 @@ int32_t sclInitParam(SNode* node, SScalarParam *param, SScalarCtx *ctx, int32_t SCL_RET(TSDB_CODE_QRY_INVALID_INPUT); } - SCL_ERR_RET(scalarGenerateSetFromList((void**) ¶m->pHashFilter, node, nodeList->dataType.type)); + SCL_ERR_RET(scalarGenerateSetFromList((void **)¶m->pHashFilter, node, nodeList->dataType.type)); if (taosHashPut(ctx->pRes, &node, POINTER_BYTES, param, sizeof(*param))) { taosHashCleanup(param->pHashFilter); sclError("taosHashPut nodeList failed, size:%d", (int32_t)sizeof(*param)); @@ -483,6 +483,79 @@ _return: SCL_RET(code); } +EDealRes sclRewriteBasedOnOptr(SNode** pNode, SScalarCtx *ctx, EOperatorType opType) { + if (opType <= OP_TYPE_CALC_MAX) { + SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE); + if (NULL == res) { + sclError("make value node failed"); + ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY; + return DEAL_RES_ERROR; + } + + res->node.resType.type = TSDB_DATA_TYPE_NULL; + + nodesDestroyNode(*pNode); + *pNode = (SNode*)res; + } else { + SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE); + if (NULL == res) { + sclError("make value node failed"); + ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY; + return DEAL_RES_ERROR; + } + + res->node.resType.type = TSDB_DATA_TYPE_BOOL; + res->datum.b = false; + + nodesDestroyNode(*pNode); + *pNode = (SNode*)res; + } + + return DEAL_RES_CONTINUE; +} + + +EDealRes sclRewriteOperatorForNullValue(SNode** pNode, SScalarCtx *ctx) { + SOperatorNode *node = (SOperatorNode *)*pNode; + + 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)) { + 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)) { + return sclRewriteBasedOnOptr(pNode, ctx, node->opType); + } + } + + if (node->pRight && (QUERY_NODE_NODE_LIST == nodeType(node->pRight))) { + SNodeListNode *listNode = (SNodeListNode *)node->pRight; + SNode* tnode = NULL; + WHERE_EACH(tnode, listNode->pNodeList) { + if (SCL_IS_NULL_VALUE_NODE(tnode)) { + if (node->opType == OP_TYPE_IN) { + ERASE_NODE(listNode->pNodeList); + continue; + } else { //OP_TYPE_NOT_IN + return sclRewriteBasedOnOptr(pNode, ctx, node->opType); + } + } + + WHERE_NEXT; + } + + if (listNode->pNodeList->length <= 0) { + return sclRewriteBasedOnOptr(pNode, ctx, node->opType); + } + } + + return DEAL_RES_CONTINUE; +} + EDealRes sclRewriteFunction(SNode** pNode, SScalarCtx *ctx) { SFunctionNode *node = (SFunctionNode *)*pNode; SNode* tnode = NULL; @@ -572,12 +645,8 @@ EDealRes sclRewriteLogic(SNode** pNode, SScalarCtx *ctx) { EDealRes sclRewriteOperator(SNode** pNode, SScalarCtx *ctx) { SOperatorNode *node = (SOperatorNode *)*pNode; - if (!SCL_IS_CONST_NODE(node->pLeft)) { - return DEAL_RES_CONTINUE; - } - - if (!SCL_IS_CONST_NODE(node->pRight)) { - return DEAL_RES_CONTINUE; + if ((!SCL_IS_CONST_NODE(node->pLeft)) || (!SCL_IS_CONST_NODE(node->pRight))) { + return sclRewriteOperatorForNullValue(pNode, ctx); } SScalarParam output = {.columnData = taosMemoryCalloc(1, sizeof(SColumnInfoData))}; diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c index f63e539a96..bb7364aea6 100644 --- a/source/libs/scalar/src/sclvector.c +++ b/source/libs/scalar/src/sclvector.c @@ -1367,7 +1367,8 @@ void vectorCompareImpl(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam * if (pRight->pHashFilter != NULL) { for (; i >= 0 && i < pLeft->numOfRows; i += step) { if (colDataIsNull_s(pLeft->columnData, i)) { - colDataAppendNULL(pOut->columnData, i); + bool res = false; + colDataAppendInt8(pOut->columnData, i, (int8_t*)&res); continue; } @@ -1381,7 +1382,8 @@ void vectorCompareImpl(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam * if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step) { if (colDataIsNull_s(pLeft->columnData, i) || colDataIsNull_s(pRight->columnData, i)) { - colDataAppendNULL(pOut->columnData, i); + bool res = false; + colDataAppendInt8(pOut->columnData, i, (int8_t*)&res); continue; // TODO set null or ignore } @@ -1402,8 +1404,9 @@ void vectorCompareImpl(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam * } else if (pRight->numOfRows == 1) { ASSERT(pLeft->pHashFilter == NULL); for (; i >= 0 && i < pLeft->numOfRows; i += step) { - if (colDataIsNull_s(pLeft->columnData, i)) { - colDataAppendNULL(pOut->columnData, i); + if (colDataIsNull_s(pLeft->columnData, i) || colDataIsNull_s(pRight->columnData, 0)) { + bool res = false; + colDataAppendInt8(pOut->columnData, i, (int8_t*)&res); continue; } @@ -1422,8 +1425,9 @@ void vectorCompareImpl(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam * } } else if (pLeft->numOfRows == 1) { for (; i >= 0 && i < pRight->numOfRows; i += step) { - if (colDataIsNull_s(pRight->columnData, i)) { - colDataAppendNULL(pOut->columnData, i); + if (colDataIsNull_s(pRight->columnData, i) || colDataIsNull_s(pLeft->columnData, 0)) { + bool res = false; + colDataAppendInt8(pOut->columnData, i, (int8_t*)&res); continue; } diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 06c832497c..8fd3272055 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -97,15 +97,14 @@ CaseCfg gCase[] = { {"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}, - {"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; typedef struct { + char caseCatalog[255]; int32_t bindNullNum; bool autoCreate; bool checkParamNum; @@ -118,6 +117,8 @@ typedef struct { int32_t bindColTypeNum; int32_t* bindColTypeList; int32_t runTimes; + int32_t caseIdx; + int32_t caseRunNum; } CaseCtrl; CaseCtrl gCaseCtrl = { @@ -133,6 +134,8 @@ CaseCtrl gCaseCtrl = { .checkParamNum = false, .printRes = true, .runTimes = 0, + .caseIdx = -1, + .caseRunNum = -1, }; int32_t taosGetTimeOfDay(struct timeval *tv) { @@ -4147,7 +4150,6 @@ void prepare(TAOS *taos, int32_t colNum, int32_t *colList, int autoCreate) { exit(1); } taos_free_result(result); - sleep(2); //TODO REMOVE IT result = taos_query(taos, "use demo"); taos_free_result(result); @@ -4184,9 +4186,15 @@ void prepare(TAOS *taos, int32_t colNum, int32_t *colList, int autoCreate) { void* runcase(TAOS *taos) { TAOS_STMT *stmt = NULL; - int32_t caseIdx = 0; + 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; + } + CaseCfg cfg = gCase[i]; gCurCase = &cfg; @@ -4194,7 +4202,10 @@ void* runcase(TAOS *taos) { continue; } - printf("* Case %d - %s Begin *\n", caseIdx, gCurCase->caseDesc); + if (gCaseCtrl.caseIdx >= 0 && caseIdx < gCaseCtrl.caseIdx) { + caseIdx++; + continue; + } if (gCaseCtrl.runTimes) { gCurCase->runTimes = gCaseCtrl.runTimes; @@ -4221,10 +4232,15 @@ void* runcase(TAOS *taos) { gCurCase->bindColNum = gCaseCtrl.bindColTypeNum; gCurCase->fullCol = false; } - + + printf("* Case %d - [%s]%s Begin *\n", caseIdx, gCaseCtrl.caseCatalog, gCurCase->caseDesc); + + totalUs = 0; for (int32_t n = 0; n < gCurCase->runTimes; ++n) { prepare(taos, gCurCase->colNum, gCurCase->colList, gCurCase->autoCreate); - + + beginUs = taosGetTimestampUs(); + stmt = taos_stmt_init(taos); if (NULL == stmt) { printf("taos_stmt_init failed, error:%s\n", taos_stmt_errstr(stmt)); @@ -4233,62 +4249,73 @@ void* runcase(TAOS *taos) { (*gCurCase->runFn)(stmt); - prepareCheckResult(taos); - taos_stmt_close(stmt); + + endUs = taosGetTimestampUs(); + totalUs += (endUs - beginUs); + + prepareCheckResult(taos); } - printf("* Case %d - %s End *\n", caseIdx, gCurCase->caseDesc); + printf("* Case %d - [%s]%s [AvgTime:%.3fms] End *\n", caseIdx, gCaseCtrl.caseCatalog, gCurCase->caseDesc, ((double)totalUs)/1000/gCurCase->runTimes); caseIdx++; + caseRunNum++; } - printf("test end\n"); - return NULL; - } void runAll(TAOS *taos) { - printf("Normal Test\n"); + strcpy(gCaseCtrl.caseCatalog, "Normal Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); runcase(taos); - printf("Null Test\n"); + strcpy(gCaseCtrl.caseCatalog, "Null Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindNullNum = 1; runcase(taos); gCaseCtrl.bindNullNum = 0; - printf("Bind Row Test\n"); + strcpy(gCaseCtrl.caseCatalog, "Bind Row Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindRowNum = 1; runcase(taos); gCaseCtrl.bindRowNum = 0; - printf("Row Num Test\n"); + strcpy(gCaseCtrl.caseCatalog, "Row Num Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.rowNum = 1000; gCaseCtrl.printRes = false; runcase(taos); gCaseCtrl.rowNum = 0; gCaseCtrl.printRes = true; - printf("Runtimes Test\n"); + strcpy(gCaseCtrl.caseCatalog, "Runtimes Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.runTimes = 2; runcase(taos); gCaseCtrl.runTimes = 0; - printf("Check Param Test\n"); + strcpy(gCaseCtrl.caseCatalog, "Check Param Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.checkParamNum = true; runcase(taos); gCaseCtrl.checkParamNum = false; - printf("Bind Col Num Test\n"); + strcpy(gCaseCtrl.caseCatalog, "Bind Col Num Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindColNum = 6; runcase(taos); gCaseCtrl.bindColNum = 0; - printf("Bind Col Type Test\n"); + strcpy(gCaseCtrl.caseCatalog, "Bind Col Type Test"); + printf("%s Begin\n", gCaseCtrl.caseCatalog); gCaseCtrl.bindColTypeNum = tListLen(bindColTypeList); gCaseCtrl.bindColTypeList = bindColTypeList; runcase(taos); + + printf("All Test End\n"); } int main(int argc, char *argv[]) diff --git a/tests/script/tsim/query/scalarNull.sim b/tests/script/tsim/query/scalarNull.sim new file mode 100644 index 0000000000..66d3c48f5d --- /dev/null +++ b/tests/script/tsim/query/scalarNull.sim @@ -0,0 +1,102 @@ +system sh/stop_dnodes.sh + +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c wallevel -v 2 +system sh/cfg.sh -n dnode1 -c numOfMnodes -v 1 + +print ========= start dnode1 as LEADER +system sh/exec.sh -n dnode1 -s start +sleep 2000 +sql connect + +print ======== step1 +sql create database db1 vgroups 3; +sql use db1; +sql show databases; +sql create stable st1 (ts timestamp, f1 int, f2 binary(200)) tags(t1 int); +sql create stable st2 (ts timestamp, f1 int, f2 binary(200)) tags(t1 int); +sql create table tb1 using st1 tags(1); +sql insert into tb1 values (now, 1, "Hash Join (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)"); + +sql create table tb2 using st1 tags(2); +sql insert into tb2 values (now, 2, "Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)"); +sql create table tb3 using st1 tags(3); +sql insert into tb3 values (now, 3, "Hash (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)"); +sql create table tb4 using st1 tags(4); +sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)"); + +sql create table tb1 using st2 tags(1); +sql insert into tb1 values (now, 1, "Hash Join (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)"); + +sql create table tb2 using st2 tags(2); +sql insert into tb2 values (now, 2, "Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)"); +sql create table tb3 using st2 tags(3); +sql insert into tb3 values (now, 3, "Hash (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)"); +sql create table tb4 using st2 tags(4); +sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)"); + + +print ======== step2 +sql explain select * from st1 where -2; +sql explain select ts from tb1; +sql explain select * from st1; +sql explain select * from st1 order by ts; +sql explain select * from information_schema.user_stables; +sql explain select count(*),sum(f1) from tb1; +sql explain select count(*),sum(f1) from st1; +sql explain select count(*),sum(f1) from st1 group by f1; +#sql explain select count(f1) from tb1 interval(10s, 2s) sliding(3s) fill(prev); +sql explain select min(f1) from st1 interval(1m, 2a) sliding(30s); + +print ======== step3 +sql explain verbose true select * from st1 where -2; +sql explain verbose true select ts from tb1 where f1 > 0; +sql explain verbose true select * from st1 where f1 > 0 and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00'; +sql explain verbose true select * from information_schema.user_stables where db_name='db2'; +sql explain verbose true select count(*),sum(f1) from st1 where f1 > 0 and ts > '2021-10-31 00:00:00' group by f1 having sum(f1) > 0; + +print ======== step4 +sql explain analyze select ts from st1 where -2; +sql explain analyze select ts from tb1; +sql explain analyze select ts from st1; +sql explain analyze select ts from st1; +sql explain analyze select ts from st1 order by ts; +sql explain analyze select * from information_schema.user_stables; +sql explain analyze select count(*),sum(f1) from tb1; +sql explain analyze select count(*),sum(f1) from st1; +sql explain analyze select count(*),sum(f1) from st1 group by f1; +#sql explain analyze select count(f1) from tb1 interval(10s, 2s) sliding(3s) fill(prev); +sql explain analyze select min(f1) from st1 interval(3m, 2a) sliding(1m); + +print ======== step5 +sql explain analyze verbose true select ts from st1 where -2; +sql explain analyze verbose true select ts from tb1; +sql explain analyze verbose true select ts from st1; +sql explain analyze verbose true select ts from st1; +sql explain analyze verbose true select ts from st1 order by ts; +sql explain analyze verbose true select * from information_schema.user_stables; +sql explain analyze verbose true select count(*),sum(f1) from tb1; +sql explain analyze verbose true select count(*),sum(f1) from st1; +sql explain analyze verbose true select count(*),sum(f1) from st1 group by f1; +#sql explain analyze verbose true select count(f1) from tb1 interval(10s, 2s) sliding(3s) fill(prev); +sql explain analyze verbose true select ts from tb1 where f1 > 0; +sql explain analyze verbose true select f1 from st1 where f1 > 0 and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00'; +sql explain analyze verbose true select * from information_schema.user_stables where db_name='db2'; +sql explain analyze verbose true select count(*),sum(f1) from st1 where f1 > 0 and ts > '2021-10-31 00:00:00' group by f1 having sum(f1) > 0; +sql explain analyze verbose true select min(f1) from st1 interval(3m, 2a) sliding(1m); +sql explain analyze verbose true select * from (select min(f1),count(*) a from st1 where f1 > 0) where a < 0; + +#not pass case +#sql explain verbose true select count(*),sum(f1) as aa from tb1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' order by aa; +#sql explain verbose true select * from st1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' order by ts; +#sql explain verbose true select count(*),sum(f1) from st1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' order by ts; +#sql explain verbose true select count(f1) from tb1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' interval(10s, 2s) sliding(3s) order by ts; +#sql explain verbose true select min(f1) from st1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' interval(1m, 2a) sliding(30s) fill(linear) order by ts; +#sql explain select max(f1) from tb1 SESSION(ts, 1s); +#sql explain select max(f1) from st1 SESSION(ts, 1s); +#sql explain select * from tb1, tb2 where tb1.ts=tb2.ts; +#sql explain select * from st1, st2 where tb1.ts=tb2.ts; +#sql explain analyze verbose true select sum(a+b) from (select _rowts, min(f1) b,count(*) a from st1 where f1 > 0 interval(1a)) where a < 0 interval(1s); + + +system sh/exec.sh -n dnode1 -s stop -x SIGINT From 4d595938df61b031ab7b61f9a012149212e9a24f Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Tue, 26 Apr 2022 16:40:30 +0800 Subject: [PATCH 3/3] handle null value --- source/libs/scalar/src/filter.c | 5 + tests/script/jenkins/basic.txt | 1 + tests/script/tsim/query/scalarNull.sim | 146 ++++++++++++------------- 3 files changed, 74 insertions(+), 78 deletions(-) diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index ef35d19544..5522bfc6a3 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -3587,6 +3587,11 @@ 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) { + stat->scalarMode = true; + return DEAL_RES_CONTINUE; + } + if (NULL == node->pRight) { if (scalarGetOperatorParamNum(node->opType) > 1) { fltError("invalid operator, pRight:%p, nodeType:%d, opType:%d", node->pRight, nodeType(node), node->opType); diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index 83bd016d2f..0256905a6e 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -34,6 +34,7 @@ ./test.sh -f tsim/query/charScalarFunction.sim ./test.sh -f tsim/query/explain.sim ./test.sh -f tsim/query/session.sim +./test.sh -f tsim/query/scalarNull.sim # ---- qnode ./test.sh -f tsim/qnode/basic1.sim diff --git a/tests/script/tsim/query/scalarNull.sim b/tests/script/tsim/query/scalarNull.sim index 66d3c48f5d..c7e7aa9a34 100644 --- a/tests/script/tsim/query/scalarNull.sim +++ b/tests/script/tsim/query/scalarNull.sim @@ -14,89 +14,79 @@ sql create database db1 vgroups 3; sql use db1; sql show databases; sql create stable st1 (ts timestamp, f1 int, f2 binary(200)) tags(t1 int); -sql create stable st2 (ts timestamp, f1 int, f2 binary(200)) tags(t1 int); sql create table tb1 using st1 tags(1); -sql insert into tb1 values (now, 1, "Hash Join (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)"); +sql insert into tb1 values ('2022-04-26 15:15:00', 1, "a"); +sql insert into tb1 values ('2022-04-26 15:15:01', 2, "b"); +sql insert into tb1 values ('2022-04-26 15:15:02', 3, "c"); +sql insert into tb1 values ('2022-04-26 15:15:03', 4, "d"); +sql insert into tb1 values ('2022-04-26 15:15:04', 5, "e"); +sql insert into tb1 values ('2022-04-26 15:15:05', 6, "f"); +sql insert into tb1 values ('2022-04-26 15:15:06', null, null); +sql insert into tb1 values ('2022-04-26 15:15:07', null, "g"); +sql insert into tb1 values ('2022-04-26 15:15:08', 7, null); -sql create table tb2 using st1 tags(2); -sql insert into tb2 values (now, 2, "Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)"); -sql create table tb3 using st1 tags(3); -sql insert into tb3 values (now, 3, "Hash (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)"); -sql create table tb4 using st1 tags(4); -sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)"); +sql select * from tb1 where f1 in (1,2,3); +if $rows != 3 then + return -1 +endi +sql select * from tb1 where f1 <>3; +if $rows != 6 then + return -1 +endi +sql select * from tb1 where f1 in (1,2,3,null); +if $rows != 3 then + return -1 +endi +sql select * from tb1 where f1 not in (1,2,3,null); +if $rows != 0 then + return -1 +endi +sql select * from tb1 where f1 in (null); +if $rows != 0 then + return -1 +endi +sql select * from tb1 where f1 = null; +if $rows != 0 then + return -1 +endi +sql select * from tb1 where f1 <> null; +if $rows != 0 then + return -1 +endi +sql select * from tb1 where f1 + 3 <> null; +if $rows != 0 then + return -1 +endi +sql select * from tb1 where f1+1 <>3+null; +if $rows != 0 then + return -1 +endi +sql select * from tb1 where f1+1*null <>3+null; +if $rows != 0 then + return -1 +endi +sql select * from tb1 where null; +if $rows != 0 then + return -1 +endi +sql select * from tb1 where null = null; +if $rows != 0 then + return -1 +endi +sql select * from tb1 where null <> null; +if $rows != 0 then + return -1 +endi -sql create table tb1 using st2 tags(1); -sql insert into tb1 values (now, 1, "Hash Join (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)"); - -sql create table tb2 using st2 tags(2); -sql insert into tb2 values (now, 2, "Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)"); -sql create table tb3 using st2 tags(3); -sql insert into tb3 values (now, 3, "Hash (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)"); -sql create table tb4 using st2 tags(4); -sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)"); +#TODO: ENABLE IT +#sql select * from tb1 where not (null <> null); +#if $rows != 9 then +# return -1 +#endi -print ======== step2 -sql explain select * from st1 where -2; -sql explain select ts from tb1; -sql explain select * from st1; -sql explain select * from st1 order by ts; -sql explain select * from information_schema.user_stables; -sql explain select count(*),sum(f1) from tb1; -sql explain select count(*),sum(f1) from st1; -sql explain select count(*),sum(f1) from st1 group by f1; -#sql explain select count(f1) from tb1 interval(10s, 2s) sliding(3s) fill(prev); -sql explain select min(f1) from st1 interval(1m, 2a) sliding(30s); - -print ======== step3 -sql explain verbose true select * from st1 where -2; -sql explain verbose true select ts from tb1 where f1 > 0; -sql explain verbose true select * from st1 where f1 > 0 and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00'; -sql explain verbose true select * from information_schema.user_stables where db_name='db2'; -sql explain verbose true select count(*),sum(f1) from st1 where f1 > 0 and ts > '2021-10-31 00:00:00' group by f1 having sum(f1) > 0; - -print ======== step4 -sql explain analyze select ts from st1 where -2; -sql explain analyze select ts from tb1; -sql explain analyze select ts from st1; -sql explain analyze select ts from st1; -sql explain analyze select ts from st1 order by ts; -sql explain analyze select * from information_schema.user_stables; -sql explain analyze select count(*),sum(f1) from tb1; -sql explain analyze select count(*),sum(f1) from st1; -sql explain analyze select count(*),sum(f1) from st1 group by f1; -#sql explain analyze select count(f1) from tb1 interval(10s, 2s) sliding(3s) fill(prev); -sql explain analyze select min(f1) from st1 interval(3m, 2a) sliding(1m); - -print ======== step5 -sql explain analyze verbose true select ts from st1 where -2; -sql explain analyze verbose true select ts from tb1; -sql explain analyze verbose true select ts from st1; -sql explain analyze verbose true select ts from st1; -sql explain analyze verbose true select ts from st1 order by ts; -sql explain analyze verbose true select * from information_schema.user_stables; -sql explain analyze verbose true select count(*),sum(f1) from tb1; -sql explain analyze verbose true select count(*),sum(f1) from st1; -sql explain analyze verbose true select count(*),sum(f1) from st1 group by f1; -#sql explain analyze verbose true select count(f1) from tb1 interval(10s, 2s) sliding(3s) fill(prev); -sql explain analyze verbose true select ts from tb1 where f1 > 0; -sql explain analyze verbose true select f1 from st1 where f1 > 0 and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00'; -sql explain analyze verbose true select * from information_schema.user_stables where db_name='db2'; -sql explain analyze verbose true select count(*),sum(f1) from st1 where f1 > 0 and ts > '2021-10-31 00:00:00' group by f1 having sum(f1) > 0; -sql explain analyze verbose true select min(f1) from st1 interval(3m, 2a) sliding(1m); -sql explain analyze verbose true select * from (select min(f1),count(*) a from st1 where f1 > 0) where a < 0; - -#not pass case -#sql explain verbose true select count(*),sum(f1) as aa from tb1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' order by aa; -#sql explain verbose true select * from st1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' order by ts; -#sql explain verbose true select count(*),sum(f1) from st1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' order by ts; -#sql explain verbose true select count(f1) from tb1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' interval(10s, 2s) sliding(3s) order by ts; -#sql explain verbose true select min(f1) from st1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' interval(1m, 2a) sliding(30s) fill(linear) order by ts; -#sql explain select max(f1) from tb1 SESSION(ts, 1s); -#sql explain select max(f1) from st1 SESSION(ts, 1s); -#sql explain select * from tb1, tb2 where tb1.ts=tb2.ts; -#sql explain select * from st1, st2 where tb1.ts=tb2.ts; -#sql explain analyze verbose true select sum(a+b) from (select _rowts, min(f1) b,count(*) a from st1 where f1 > 0 interval(1a)) where a < 0 interval(1s); +#TODO: MOVE IT TO NORMAL CASE +sql_error select * from tb1 where not (null); system sh/exec.sh -n dnode1 -s stop -x SIGINT