From c336f2db2aee77b191f09f392fd6e88be3bf9a4f Mon Sep 17 00:00:00 2001 From: 54liuyao <54liuyao@163.com> Date: Sat, 2 Apr 2022 16:04:49 +0800 Subject: [PATCH] feat(query):added where expression [TS-1210] --- src/client/src/tscSQLParser.c | 218 +++++++++++++++------ src/client/src/tscUtil.c | 2 +- src/common/src/tarithoperator.c | 323 ++++++++------------------------ src/common/src/texpr.c | 167 +---------------- src/inc/ttype.h | 1 + src/query/inc/qFilter.h | 17 +- src/query/src/qExecutor.c | 4 + src/query/src/qFilter.c | 183 +++++++++++++++--- src/tsdb/src/tsdbRead.c | 72 ++++++- 9 files changed, 488 insertions(+), 499 deletions(-) diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 7d54ae514d..e66e89df47 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -145,6 +145,8 @@ static int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo); static tSqlExpr* extractExprForSTable(SSqlCmd* pCmd, tSqlExpr** pExpr, SQueryInfo* pQueryInfo, int32_t tableIndex); static void convertWhereStringCharset(tSqlExpr* pRight); +static bool isLogicalOperator(tSqlExpr* pExpr); +static bool isComparisonOperator(tSqlExpr* pExpr); int validateTableName(char *tblName, int len, SStrToken* psTblToken, bool *dbIncluded); static bool isTimeWindowQuery(SQueryInfo* pQueryInfo) { @@ -4274,15 +4276,10 @@ static int32_t checkColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCol STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex); - int32_t ret = 0; + int32_t ret = TSDB_CODE_SUCCESS; const char* msg1 = "non binary column not support like/match operator"; const char* msg3 = "bool column not support this operator"; const char* msg4 = "primary key not support this operator"; - - SColumn* pColumn = tscColumnListInsert(pQueryInfo->colList, pIndex->columnIndex, pTableMeta->id.uid, pSchema); - - pColumn->info.flist.numOfFilters++; - /* * in case of TK_AND filter condition, we first find the corresponding column and build the query condition together * the already existed condition. @@ -4296,8 +4293,8 @@ static int32_t checkColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCol pColFilter->filterstr = ((pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0); - if (!pColFilter->filterstr) { - if (pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_MATCH || pExpr->tokenId == TK_NMATCH) { + if (!pColFilter->filterstr && tSqlExprIsParentOfLeaf(pExpr)) { + if (pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_MATCH || pExpr->tokenId == TK_NMATCH) { ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); goto _err_ret; } @@ -4310,11 +4307,10 @@ static int32_t checkColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCol } } } - - pColumn->columnIndex = pIndex->columnIndex; - pColumn->tableUid = pTableMeta->id.uid; - if (pColumn->columnIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX && pExpr->tokenId == TK_IN) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); + if (pIndex->columnIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX && pTableMeta->id.uid == TK_IN + && tSqlExprIsParentOfLeaf(pExpr)) { + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); + goto _err_ret; } STableComInfo tinfo = tscGetTableInfo(pTableMeta); @@ -4326,8 +4322,32 @@ _err_ret: return ret; } +static int32_t addAllColumn(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, uint32_t conTokenId, + SColumnIndex* pIndex) { + int32_t ret = TSDB_CODE_SUCCESS; + + if(!tSqlExprIsLeaf(pExpr) || pExpr->tokenId == TK_ARROW) { + ret = addAllColumn(pCmd, pQueryInfo, pExpr->pLeft, conTokenId, pIndex); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + return addAllColumn(pCmd, pQueryInfo, pExpr->pRight, conTokenId, pIndex); + } else if (pExpr->tokenId == TK_ID) { + if (getColumnIndexByName(&pExpr->columnName, pQueryInfo, pIndex, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex); + STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; + SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex); + SColumn* pColumn = tscColumnListInsert(pQueryInfo->colList, pIndex->columnIndex, pTableMeta->id.uid, pSchema); + pColumn->info.flist.numOfFilters++; + } + return ret; +} + static int32_t getColQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr) { int32_t ret = TSDB_CODE_SUCCESS; + const char* msg6 = "illegal condition expression"; for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { tSqlExpr* p1 = extractExprForSTable(pCmd, pExpr, pQueryInfo, i); @@ -4339,7 +4359,18 @@ static int32_t getColQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlEx SArray* colList = taosArrayInit(10, sizeof(SColIndex)); ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL); + size_t colNum = taosArrayGetSize(colList); + for (int32_t k = 0; k < colNum; k++) { + SColIndex* pColIndex = taosArrayGet(colList, k); + if (TSDB_COL_IS_TAG(pColIndex->flag)) { + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); + break; + } + } taosArrayDestroy(&colList); + if (ret == TSDB_CODE_SUCCESS) { + ret = exprTreeValidateTree(tscGetErrorMsgPayload(pCmd), p); + } SBufferWriter bw = tbufInitWriter(NULL, false); @@ -4387,7 +4418,7 @@ static int32_t checkColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t } pQueryInfo->onlyHasTagCond &= false; - if (!tSqlExprIsParentOfLeaf(pExpr)) { // internal node + if (isLogicalOperator(pExpr)) { // internal node int32_t ret = checkColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId); if (ret != TSDB_CODE_SUCCESS) { return ret; @@ -4396,12 +4427,10 @@ static int32_t checkColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t return checkColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->tokenId); } else { // handle leaf node SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getColumnIndexByName(&pExpr->pLeft->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - + addAllColumn(pCmd, pQueryInfo, pExpr, pExpr->tokenId, &index); return checkColumnFilterInfo(pCmd, pQueryInfo, &index, pExpr, relOptr); } + return TSDB_CODE_SUCCESS; } static int32_t checkAndSetJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) { @@ -5137,6 +5166,38 @@ void convertWhereStringCharset(tSqlExpr* pRight){ free(newData); } +static int32_t handleColumnInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, SColumnIndex* index) { + const char* msg2 = "illegal column name"; + int32_t ret = TSDB_CODE_SUCCESS; + if (pExpr == NULL) { + return ret; + } else if (!tSqlExprIsLeaf(pExpr)) { + if (isComparisonOperator(pExpr)) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + ret = handleColumnInQueryCond(pCmd, pQueryInfo, pExpr->pLeft, index); + if( ret != TSDB_CODE_SUCCESS) { + return ret; + } + ret = handleColumnInQueryCond(pCmd, pQueryInfo, pExpr->pRight, index); + return ret; + } + + SStrToken* colName = NULL; + if (pExpr->tokenId == TK_ARROW) { + colName = &(pExpr->pLeft->columnName); + } else if (pExpr->tokenId == TK_ID) { + colName = &(pExpr->columnName); + } + + if (colName) { + if (getColumnIndexByName(colName, pQueryInfo, index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + } + } + return ret; +} + static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr, int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr, bool joinQuery) { @@ -5144,7 +5205,6 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql const char* msg2 = "illegal column name"; const char* msg4 = "too many join tables"; const char* msg5 = "not support ordinary column join"; - const char* msg6 = "illegal condition expression"; tSqlExpr* pLeft = (*pExpr)->pLeft; tSqlExpr* pRight = (*pExpr)->pRight; @@ -5158,14 +5218,23 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql int32_t ret = TSDB_CODE_SUCCESS; SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getColumnIndexByName(colName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + if (!tSqlExprIsParentOfLeaf(*pExpr)) { + ret = handleColumnInQueryCond(pCmd, pQueryInfo, pLeft, &index); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + ret = handleColumnInQueryCond(pCmd, pQueryInfo, pRight, &index); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + } else { + if (getColumnIndexByName(colName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + } } *tbIdx = index.tableIndex; - assert(tSqlExprIsParentOfLeaf(*pExpr)); - STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; @@ -5194,7 +5263,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql } if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP && index.columnIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) { // query on time range - if (!validateJoinExprNode(pCmd, pQueryInfo, *pExpr, &index)) { + if (!tSqlExprIsParentOfLeaf(*pExpr) || !validateJoinExprNode(pCmd, pQueryInfo, *pExpr, &index)) { return TSDB_CODE_TSC_INVALID_OPERATION; } @@ -5316,8 +5385,6 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql if (pRight->tokenId == TK_ID) { if (joinQuery) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); // other column cannot be served as the join column - } else { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); } } @@ -5368,7 +5435,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr int32_t leftTbIdx = 0; int32_t rightTbIdx = 0; - if (!tSqlExprIsParentOfLeaf(*pExpr)) { + if (isLogicalOperator(*pExpr)) { ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, type ? &leftType : NULL, &leftTbIdx, (*pExpr)->tokenId, &columnLeft, &tsLeft, joinQuery); if (ret != TSDB_CODE_SUCCESS) { goto err_ret; @@ -5429,6 +5496,11 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr goto err_ret; } + if (!tSqlExprIsLeaf((*pExpr)->pRight) ) { + ret = TSDB_CODE_TSC_INVALID_OPERATION; + goto err_ret; + } + ret = handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, tbIdx, parentOptr, columnExpr, tsExpr, joinQuery); if (ret) { goto err_ret; @@ -5451,19 +5523,21 @@ static void doExtractExprForSTable(SSqlCmd* pCmd, tSqlExpr** pExpr, SQueryInfo* return; } - if (tSqlExprIsParentOfLeaf(*pExpr)) { + if (!isLogicalOperator(*pExpr)) { tSqlExpr* pLeft = (*pExpr)->pLeft; - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if(pLeft->tokenId == TK_ARROW) { - pLeft = pLeft->pLeft; - } - if (getColumnIndexByName(&pLeft->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { - return; - } + if (pLeft->tokenId == TK_ARROW || pLeft->tokenId == TK_ID) { + SColumnIndex index = COLUMN_INDEX_INITIALIZER; + if(pLeft->tokenId == TK_ARROW) { + pLeft = pLeft->pLeft; + } + if (getColumnIndexByName(&pLeft->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { + return; + } - if (index.tableIndex != tableIndex) { - return; + if (index.tableIndex != tableIndex) { + return; + } } *pOut = *pExpr; @@ -5686,7 +5760,6 @@ static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInf */ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) { - const char *msg1 = "invalid tag operator"; const char* msg2 = "not supported filter condition"; do { @@ -5706,10 +5779,6 @@ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) { if (p->_node.pRight && (retVal = validateTagCondExpr(pCmd, p->_node.pRight)) != TSDB_CODE_SUCCESS) { return retVal; } - - if (IS_ARITHMETIC_OPTR(p->_node.optr)) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); - } if (!IS_RELATION_OPTR(p->_node.optr)) { break; @@ -5771,8 +5840,13 @@ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) { return TSDB_CODE_SUCCESS; } +bool isTablename(char* colName) { + return (strlen(colName) == strlen(TSQL_TBNAME_L) && strncasecmp(TSQL_TBNAME_L, colName, strlen(TSQL_TBNAME_L)) == 0); +} + static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr) { int32_t ret = TSDB_CODE_SUCCESS; + const char* msg6 = "illegal condition expression"; if (pCondExpr->pTagCond == NULL) { return ret; @@ -5788,6 +5862,17 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE SArray* colList = taosArrayInit(10, sizeof(SColIndex)); ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL); + size_t colNum = taosArrayGetSize(colList); + for (int32_t k = 0; k < colNum; k++) { + SColIndex* pColIndex = taosArrayGet(colList, k); + if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag) && !isTablename(pColIndex->name)) { + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); + break; + } + } + if (ret == TSDB_CODE_SUCCESS) { + ret = exprTreeValidateTree(tscGetErrorMsgPayload(pCmd), p); + } //if (ret == TSDB_CODE_SUCCESS) { // ret = filterInitFromTree(p, &pQueryInfo->tagFilter, (int32_t)taosArrayGetSize(colList), NULL); //} @@ -10253,23 +10338,6 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS } } - if (pSqlExpr->tokenId == TK_BITAND && pSqlExpr->pLeft != NULL && pSqlExpr->pRight != NULL) { - // for example: col type is "bool" but expr "col & 1" received - uint8_t colType = pLeft->pSchema->type; - SStrToken *exprToken = &pSqlExpr->pRight->exprToken; - if (pSqlExpr->pLeft->type == SQL_NODE_TABLE_COLUMN && pSqlExpr->pRight->type == SQL_NODE_VALUE) { - if (colType == TSDB_DATA_TYPE_BOOL) { - if ((exprToken->n != 4 || strncasecmp(exprToken->z, "true", 4)) && (exprToken->n != 5 || strncasecmp(exprToken->z, "false", 5))) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } else if (IS_SIGNED_NUMERIC_TYPE(colType) || IS_UNSIGNED_NUMERIC_TYPE(colType)) { - if ((exprToken->n == 4 && strncasecmp(exprToken->z, "true", 4) == 0) || (exprToken->n == 5 || strncasecmp(exprToken->z, "false", 5) == 0)) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } - } - } - if (pSqlExpr->pRight != NULL) { int32_t ret = exprTreeFromSqlExpr(pCmd, &pRight, pSqlExpr->pRight, pQueryInfo, pCols, uid); if (ret != TSDB_CODE_SUCCESS) { @@ -10408,3 +10476,35 @@ void normalizeSqlNode(SSqlNode* pSqlNode, const char* dbName) { } #endif + +bool isLogicalOperator(tSqlExpr* pExpr) { + if (pExpr->tokenId == TK_AND || pExpr->tokenId == TK_OR) { + return true; + } + return false; +} + +bool isComparisonOperator(tSqlExpr* pExpr) { + switch (pExpr->tokenId) { + case TK_EQ: + case TK_NE: + case TK_ISNULL: + case TK_NOTNULL: + case TK_IS: + case TK_LIKE: + case TK_MATCH: + case TK_NMATCH: + case TK_CONTAINS: + case TK_GLOB: + case TK_BETWEEN: + case TK_IN: + case TK_GT: + case TK_GE: + case TK_LT: + case TK_LE: + return true; + default: + return false; + } + return false; +} diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index ec4f2c1daf..bfb9c5d3d2 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -1004,7 +1004,7 @@ static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, void* pFilterI filterConverNcharColumns(pFilterInfo, pBlock->info.rows, &gotNchar); int8_t* p = NULL; //bool all = doFilterDataBlock(pFilterInfo, numOfFilterCols, pBlock->info.rows, p); - bool all = filterExecute(pFilterInfo, pBlock->info.rows, &p, NULL, 0); + bool all = filterExecute(pFilterInfo, pBlock->info.rows, &p, NULL, (int16_t)taosArrayGetSize(pBlock->pDataBlock)); if (gotNchar) { filterFreeNcharColumns(pFilterInfo); } diff --git a/src/common/src/tarithoperator.c b/src/common/src/tarithoperator.c index 6144105378..0e31e6a70b 100644 --- a/src/common/src/tarithoperator.c +++ b/src/common/src/tarithoperator.c @@ -403,267 +403,94 @@ void vectorRemainder(void *left, int32_t len1, int32_t _left_type, void *right, } } +typedef int64_t (*_arithmetic_getVectorBigintValue_fn_t)(void *src, int32_t index); + +int64_t getVectorBigintValue_BOOL(void *src, int32_t index) { + return (int64_t)*((bool *)src + index); +} +int64_t getVectorBigintValue_TINYINT(void *src, int32_t index) { + return (int64_t)*((int8_t *)src + index); +} +int64_t getVectorBigintValue_UTINYINT(void *src, int32_t index) { + return (int64_t)*((uint8_t *)src + index); +} +int64_t getVectorBigintValue_SMALLINT(void *src, int32_t index) { + return (int64_t)*((int16_t *)src + index); +} +int64_t getVectorBigintValue_USMALLINT(void *src, int32_t index) { + return (int64_t)*((uint16_t *)src + index); +} +int64_t getVectorBigintValue_INT(void *src, int32_t index) { + return (int64_t)*((int32_t *)src + index); +} +int64_t getVectorBigintValue_UINT(void *src, int32_t index) { + return (int64_t)*((uint32_t *)src + index); +} +int64_t getVectorBigintValue_BIGINT(void *src, int32_t index) { + return (int64_t)*((int64_t *)src + index); +} +int64_t getVectorBigintValue_UBIGINT(void *src, int32_t index) { + return (int64_t)*((uint64_t *)src + index); +} + +_arithmetic_getVectorBigintValue_fn_t getVectorBigintValueFn(int32_t srcType) { + _arithmetic_getVectorBigintValue_fn_t p = NULL; + if (srcType==TSDB_DATA_TYPE_BOOL) { + p = getVectorBigintValue_BOOL; + } else if (srcType==TSDB_DATA_TYPE_TINYINT) { + p = getVectorBigintValue_TINYINT; + } else if (srcType==TSDB_DATA_TYPE_UTINYINT) { + p = getVectorBigintValue_UTINYINT; + } else if (srcType==TSDB_DATA_TYPE_SMALLINT) { + p = getVectorBigintValue_SMALLINT; + } else if (srcType==TSDB_DATA_TYPE_USMALLINT) { + p = getVectorBigintValue_USMALLINT; + }else if (srcType==TSDB_DATA_TYPE_INT) { + p = getVectorBigintValue_INT; + } else if (srcType==TSDB_DATA_TYPE_UINT) { + p = getVectorBigintValue_UINT; + } else if (srcType==TSDB_DATA_TYPE_BIGINT) { + p = getVectorBigintValue_BIGINT; + } else if (srcType==TSDB_DATA_TYPE_UBIGINT) { + p = getVectorBigintValue_UBIGINT; + } else { + assert(0); + } + return p; +} + void vectorBitand(void *left, int32_t len1, int32_t _left_type, void *right, int32_t len2, int32_t _right_type, void *out, int32_t _ord) { - int32_t i = (_ord == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; - int32_t step = (_ord == TSDB_ORDER_ASC) ? 1 : -1; - char *output = out; + int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; + int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; + double *output=(double*)out; _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(_left_type); _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(_right_type); + _arithmetic_getVectorBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(_left_type); + _arithmetic_getVectorBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(_right_type); - if (len1 == (len2)) { - for (; i >= 0 && i < (len2); i += step) { - if (isNull(getVectorValueAddrFnLeft(left, i), _left_type) || isNull(getVectorValueAddrFnRight(right, i), _right_type)) { - switch (_left_type) { - case TSDB_DATA_TYPE_BOOL: - *(bool *) output = TSDB_DATA_BOOL_NULL; - output += sizeof(bool); - break; - case TSDB_DATA_TYPE_TINYINT: - *(int8_t *) output = TSDB_DATA_TINYINT_NULL; - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_SMALLINT: - *(int16_t *) output = TSDB_DATA_SMALLINT_NULL; - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_INT: - *(int32_t *) output = TSDB_DATA_INT_NULL; - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_BIGINT: - *(int64_t *) output = TSDB_DATA_BIGINT_NULL; - output += sizeof(int64_t); - break; - - case TSDB_DATA_TYPE_UTINYINT: - *(uint8_t *) output = TSDB_DATA_UTINYINT_NULL; - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_USMALLINT: - *(uint16_t *) output = TSDB_DATA_USMALLINT_NULL; - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_UINT: - *(uint32_t *) output = TSDB_DATA_UINT_NULL; - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_UBIGINT: - *(uint64_t *) output = TSDB_DATA_UBIGINT_NULL; - output += sizeof(int64_t); - break; - } + if ((len1) == (len2)) { + for (; i < (len2) && i >= 0; i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_BIGINT_NULL(output); continue; } - - switch (_left_type) { - case TSDB_DATA_TYPE_BOOL: - *(bool *) output = (*((bool *) left + i)) & (*((bool *) right + i)); - output += sizeof(bool); - break; - case TSDB_DATA_TYPE_TINYINT: - *(int8_t *) output = (*((int8_t *) left + i)) & (*((int8_t *) right + i)); - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_SMALLINT: - *(int16_t *) output = (*((int16_t *) left + i)) & (*((int16_t *) right + i)); - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_INT: - *(int32_t *) output = (*((int32_t *) left + i)) & (*((int32_t *) right + i)); - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_BIGINT: - *(int64_t *) output = (*((int64_t *) left + i)) & (*((int64_t *) right + i)); - output += sizeof(int64_t); - break; - - case TSDB_DATA_TYPE_UTINYINT: - *(uint8_t *) output = (*((uint8_t *) left + i)) & (*((uint8_t *) right + i)); - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_USMALLINT: - *(uint16_t *) output = (*((uint16_t *) left + i)) & (*((uint16_t *) right + i)); - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_UINT: - *(uint32_t *) output = (*((uint32_t *) left + i)) & (*((uint32_t *) right + i)); - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_UBIGINT: - *(uint64_t *) output = (*((uint64_t *) left + i)) & (*((uint64_t *) right + i)); - output += sizeof(int64_t); - break; - } + *(int64_t *) output = getVectorBigintValueFnLeft(left,i) & getVectorBigintValueFnRight(right,i); } - } else if (len1 == 1) { - for (; i >= 0 && i < (len2); i += step) { - if (isNull(getVectorValueAddrFnLeft(left, 0), _left_type) || isNull(getVectorValueAddrFnRight(right, i), _right_type)) { - switch (_left_type) { - case TSDB_DATA_TYPE_BOOL: - *(bool *) output = TSDB_DATA_BOOL_NULL; - output += sizeof(bool); - break; - case TSDB_DATA_TYPE_TINYINT: - *(int8_t *) output = TSDB_DATA_TINYINT_NULL; - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_SMALLINT: - *(int16_t *) output = TSDB_DATA_SMALLINT_NULL; - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_INT: - *(int32_t *) output = TSDB_DATA_INT_NULL; - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_BIGINT: - *(int64_t *) output = TSDB_DATA_BIGINT_NULL; - output += sizeof(int64_t); - break; - - case TSDB_DATA_TYPE_UTINYINT: - *(uint8_t *) output = TSDB_DATA_UTINYINT_NULL; - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_USMALLINT: - *(uint16_t *) output = TSDB_DATA_USMALLINT_NULL; - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_UINT: - *(uint32_t *) output = TSDB_DATA_UINT_NULL; - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_UBIGINT: - *(uint64_t *) output = TSDB_DATA_UBIGINT_NULL; - output += sizeof(int64_t); - break; - } + } else if ((len1) == 1) { + for (; i >= 0 && i < (len2); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,0), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_BIGINT_NULL(output); continue; } - - switch (_left_type) { - case TSDB_DATA_TYPE_BOOL: - *(bool *) output = (*(bool *) left) & (*((bool *) right + i)); - output += sizeof(bool); - break; - case TSDB_DATA_TYPE_TINYINT: - *(int8_t *) output = (*(int8_t *) left) & (*((int8_t *) right + i)); - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_SMALLINT: - *(int16_t *) output = (*(int16_t *) left) & (*((int16_t *) right + i)); - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_INT: - *(int32_t *) output = (*(int32_t *) left) & (*((int32_t *) right + i)); - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_BIGINT: - *(int64_t *) output = (*(int64_t *) left) & (*((int64_t *) right + i)); - output += sizeof(int64_t); - break; - - case TSDB_DATA_TYPE_UTINYINT: - *(uint8_t *) output = (*(uint8_t *) left) & (*((uint8_t *) right + i)); - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_USMALLINT: - *(uint16_t *) output = (*(uint16_t *) left) & (*((uint16_t *) right + i)); - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_UINT: - *(uint32_t *) output = (*(uint32_t *) left) & (*((uint32_t *) right + i)); - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_UBIGINT: - *(uint64_t *) output = (*(uint64_t *) left) & (*((uint64_t *) right + i)); - output += sizeof(int64_t); - break; - } + *(int64_t *) output = getVectorBigintValueFnLeft(left,0) & getVectorBigintValueFnRight(right,i); } } else if ((len2) == 1) { - for (; i >= 0 && i < len1; i += step) { - if (isNull(getVectorValueAddrFnLeft(left, i), _left_type) || isNull(getVectorValueAddrFnRight(right, 0), _right_type)) { - switch (_left_type) { - case TSDB_DATA_TYPE_BOOL: - *(bool *) output = TSDB_DATA_BOOL_NULL; - output += sizeof(bool); - break; - case TSDB_DATA_TYPE_TINYINT: - *(int8_t *) output = TSDB_DATA_TINYINT_NULL; - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_SMALLINT: - *(int16_t *) output = TSDB_DATA_SMALLINT_NULL; - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_INT: - *(int32_t *) output = TSDB_DATA_INT_NULL; - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_BIGINT: - *(int64_t *) output = TSDB_DATA_BIGINT_NULL; - output += sizeof(int64_t); - break; - - case TSDB_DATA_TYPE_UTINYINT: - *(uint8_t *) output = TSDB_DATA_UTINYINT_NULL; - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_USMALLINT: - *(uint16_t *) output = TSDB_DATA_USMALLINT_NULL; - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_UINT: - *(uint32_t *) output = TSDB_DATA_UINT_NULL; - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_UBIGINT: - *(uint64_t *) output = TSDB_DATA_UBIGINT_NULL; - output += sizeof(int64_t); - break; - } + for (; i >= 0 && i < (len1); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,0), _right_type)) { + SET_BIGINT_NULL(output); continue; } - - switch (_left_type) { - case TSDB_DATA_TYPE_BOOL: - *(bool *) output = (*((bool *) left + i)) & (*(bool *) right); - output += sizeof(bool); - break; - case TSDB_DATA_TYPE_TINYINT: - *(int8_t *) output = (*((int8_t *) left + i)) & (*(int8_t *) right); - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_SMALLINT: - *(int16_t *) output = (*((int16_t *) left + i)) & (*(int16_t *) right); - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_INT: - *(int32_t *) output = (*((int32_t *) left + i)) & (*(int32_t *) right); - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_BIGINT: - *(int64_t *) output = (*((int64_t *) left + i)) & (*(int64_t *) right); - output += sizeof(int64_t); - break; - - case TSDB_DATA_TYPE_UTINYINT: - *(uint8_t *) output = (*((uint8_t *) left + i)) & (*(uint8_t *) right); - output += sizeof(int8_t); - break; - case TSDB_DATA_TYPE_USMALLINT: - *(uint16_t *) output = (*((uint16_t *) left + i)) & (*(uint16_t *) right); - output += sizeof(int16_t); - break; - case TSDB_DATA_TYPE_UINT: - *(uint32_t *) output = (*((uint32_t *) left + i)) & (*(uint32_t *) right); - output += sizeof(int32_t); - break; - case TSDB_DATA_TYPE_UBIGINT: - *(uint64_t *) output = (*((uint64_t *) left + i)) & (*(uint64_t *) right); - output += sizeof(int64_t); - break; - } + *(int64_t *) output = getVectorBigintValueFnLeft(left,i) & getVectorBigintValueFnRight(right,0); } } } diff --git a/src/common/src/texpr.c b/src/common/src/texpr.c index b764ffbb01..12206e1a3c 100644 --- a/src/common/src/texpr.c +++ b/src/common/src/texpr.c @@ -88,7 +88,6 @@ int32_t exprTreeValidateFunctionNode(char* msgbuf, tExprNode *pExpr) { int32_t exprTreeValidateExprNode(tExprNode *pExpr) { int16_t leftType = pExpr->_node.pLeft->resultType; int16_t rightType = pExpr->_node.pRight->resultType; - int16_t resultType = leftType; if (pExpr->_node.optr == TSDB_BINARY_OP_ADD || pExpr->_node.optr == TSDB_BINARY_OP_SUBTRACT || pExpr->_node.optr == TSDB_BINARY_OP_MULTIPLY || pExpr->_node.optr == TSDB_BINARY_OP_DIVIDE || @@ -100,169 +99,15 @@ int32_t exprTreeValidateExprNode(tExprNode *pExpr) { pExpr->resultBytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes; return TSDB_CODE_SUCCESS; } else if (pExpr->_node.optr == TSDB_BINARY_OP_BITAND) { - if ((leftType != TSDB_DATA_TYPE_BOOL && !IS_SIGNED_NUMERIC_TYPE(leftType) && !IS_UNSIGNED_NUMERIC_TYPE(leftType)) || - (rightType != TSDB_DATA_TYPE_BOOL && !IS_SIGNED_NUMERIC_TYPE(rightType) && !IS_UNSIGNED_NUMERIC_TYPE(rightType))) - { + if (! (IS_NUMERIC_TYPE(leftType)|| leftType == TSDB_DATA_TYPE_BOOL) + || ! (IS_NUMERIC_TYPE(rightType) || rightType == TSDB_DATA_TYPE_BOOL)) { return TSDB_CODE_TSC_INVALID_OPERATION; } - - uint8_t schemaType; - // now leftType and rightType are both numeric - if (pExpr->_node.pLeft->nodeType == TSQL_NODE_COL && pExpr->_node.pRight->nodeType == TSQL_NODE_COL) { - if (leftType != rightType) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - } else if (pExpr->_node.pLeft->nodeType == TSQL_NODE_COL) { - if (pExpr->_node.pRight->nodeType != TSQL_NODE_VALUE) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } else { - schemaType = pExpr->_node.pLeft->pSchema->type; - int64_t sVal = pExpr->_node.pRight->pVal->i64; - uint64_t uVal = pExpr->_node.pRight->pVal->u64; - - switch (schemaType) { - case TSDB_DATA_TYPE_BOOL: - if ((pExpr->_node.pRight->pVal->nType != TSDB_DATA_TYPE_BOOL) || - (pExpr->_node.pRight->pVal->i64 != 0 && - pExpr->_node.pRight->pVal->i64 != 1 && - pExpr->_node.pRight->pVal->i64 != TSDB_DATA_BOOL_NULL)) - { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - case TSDB_DATA_TYPE_TINYINT: - if (sVal < -128 || sVal > 127) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - case TSDB_DATA_TYPE_SMALLINT: - if (sVal < -32768 || sVal > 32767) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - case TSDB_DATA_TYPE_INT: - if (sVal < INT32_MIN || sVal > INT32_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - case TSDB_DATA_TYPE_BIGINT: - if (sVal < INT64_MIN || sVal > INT64_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - case TSDB_DATA_TYPE_UTINYINT: - if (uVal > 255) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - case TSDB_DATA_TYPE_USMALLINT: - if (uVal > 65535) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - case TSDB_DATA_TYPE_UINT: - if (uVal > UINT32_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - case TSDB_DATA_TYPE_UBIGINT: - if (uVal > UINT64_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - break; - } - - pExpr->_node.pRight->pSchema->type = schemaType; - pExpr->_node.pRight->pVal->nType = schemaType; - - pExpr->_node.pRight->resultType = schemaType; - pExpr->_node.pRight->resultBytes = tDataTypes[schemaType].bytes; - } - } else { - if (pExpr->_node.pLeft->nodeType != TSQL_NODE_VALUE) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } else { - schemaType = pExpr->_node.pRight->pSchema->type; - int64_t sVal = pExpr->_node.pLeft->pVal->i64; - uint64_t uVal = pExpr->_node.pLeft->pVal->u64; - switch (schemaType) { - case TSDB_DATA_TYPE_BOOL: - if ((pExpr->_node.pLeft->pVal->nType != TSDB_DATA_TYPE_BOOL) || - (pExpr->_node.pLeft->pVal->i64 != 0 && - pExpr->_node.pLeft->pVal->i64 != 1 && - pExpr->_node.pLeft->pVal->i64 != TSDB_DATA_BOOL_NULL)) - { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 1; - break; - case TSDB_DATA_TYPE_TINYINT: - if (sVal < -128 || sVal > 127) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 1; - break; - case TSDB_DATA_TYPE_SMALLINT: - if (sVal < -32768 || sVal > 32767) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 2; - break; - case TSDB_DATA_TYPE_INT: - if (sVal < INT32_MIN || sVal > INT32_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 4; - break; - case TSDB_DATA_TYPE_BIGINT: - if (sVal < INT64_MIN || sVal > INT64_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 8; - break; - case TSDB_DATA_TYPE_UTINYINT: - if (uVal > 255) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 1; - break; - case TSDB_DATA_TYPE_USMALLINT: - if (uVal > 65535) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 2; - break; - case TSDB_DATA_TYPE_UINT: - if (uVal > UINT32_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 4; - break; - case TSDB_DATA_TYPE_UBIGINT: - if (uVal > UINT64_MAX) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - pExpr->_node.pLeft->pVal->nLen = 8; - break; - } - - pExpr->_node.pLeft->pSchema->type = schemaType; - pExpr->_node.pLeft->pVal->nType = schemaType; - - pExpr->_node.pLeft->resultType = schemaType; - pExpr->_node.pLeft->resultBytes = tDataTypes[schemaType].bytes; - } - - resultType = schemaType; - } - - if (resultType == TSDB_DATA_TYPE_BOOL) { - pExpr->resultType = TSDB_DATA_TYPE_BOOL; - pExpr->resultBytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; - } else { - pExpr->resultType = resultType; - pExpr->resultBytes = tDataTypes[resultType].bytes; + if (IS_FLOAT_TYPE(leftType) || IS_FLOAT_TYPE(rightType)) { + return TSDB_CODE_TSC_INVALID_OPERATION; } + pExpr->resultType = TSDB_DATA_TYPE_BIGINT; + pExpr->resultBytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; return TSDB_CODE_SUCCESS; } else { return TSDB_CODE_SUCCESS; diff --git a/src/inc/ttype.h b/src/inc/ttype.h index 1b7d07262e..ff7d6e5835 100644 --- a/src/inc/ttype.h +++ b/src/inc/ttype.h @@ -289,6 +289,7 @@ void* getDataMax(int32_t type); int32_t tStrToInteger(const char* z, int16_t type, int32_t n, int64_t* value, bool issigned); #define SET_DOUBLE_NULL(v) (*(uint64_t *)(v) = TSDB_DATA_DOUBLE_NULL) +#define SET_BIGINT_NULL(v) (*(int64_t *)(v) = TSDB_DATA_BIGINT_NULL) #ifdef __cplusplus } diff --git a/src/query/inc/qFilter.h b/src/query/inc/qFilter.h index fe9ef0f47f..c1e2a745f9 100644 --- a/src/query/inc/qFilter.h +++ b/src/query/inc/qFilter.h @@ -39,10 +39,11 @@ extern "C" { enum { FLD_TYPE_COLUMN = 1, FLD_TYPE_VALUE = 2, - FLD_TYPE_MAX = 3, - FLD_DESC_NO_FREE = 4, - FLD_DATA_NO_FREE = 8, - FLD_DATA_IS_HASH = 16, + FLD_TYPE_EXPR = 3, + FLD_TYPE_MAX = 4, + FLD_DESC_NO_FREE = 16, + FLD_DATA_NO_FREE = 32, + FLD_DATA_IS_HASH = 64, }; enum { @@ -182,6 +183,7 @@ typedef struct SFilterGroupCtx { uint32_t colNum; uint32_t *colIdx; SFilterColInfo *colInfo; + bool hasExpr; } SFilterGroupCtx; typedef struct SFilterColCtx { @@ -206,6 +208,8 @@ typedef struct SFilterComUnit { void *colData; void *valData; void *valData2; + void *expr; + void *exprData; uint16_t colId; uint16_t dataSize; uint8_t dataType; @@ -289,7 +293,10 @@ typedef struct SFilterInfo { #define FILTER_GET_VAL_FIELD_TYPE(fi) (((tVariant *)((fi)->desc))->nType) #define FILTER_GET_VAL_FIELD_DATA(fi) ((char *)(fi)->data) #define FILTER_GET_JSON_VAL_FIELD_DATA(fi) ((char *)(fi)->desc) -#define FILTER_GET_TYPE(fl) ((fl) & FLD_TYPE_MAX) +#define FILTER_GET_TYPE(fl) ((fl) & 0xF) +#define FILTER_GET_FIELD_DESC(fi) ((fi)->desc) +#define FILTER_GET_EXPR_TYPE(i, id) (((tExprNode*)(FILTER_GET_FIELD_DESC(FILTER_GET_FIELD(i, id))))->resultType) +#define FILTER_GET_EXPR_SIZE(i, id) (((tExprNode*)(FILTER_GET_FIELD_DESC(FILTER_GET_FIELD(i, id))))->resultBytes) #define FILTER_GROUP_UNIT(i, g, uid) ((i)->units + (g)->unitIdxs[uid]) #define FILTER_UNIT_LEFT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->left) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index c9b0e7f7ae..554de3e33a 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -3155,6 +3155,10 @@ void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFi FORCE_INLINE int32_t getColumnDataFromId(void *param, int32_t id, void **data) { int32_t numOfCols = ((SColumnDataParam *)param)->numOfCols; SArray* pDataBlock = ((SColumnDataParam *)param)->pDataBlock; + if (id == INT32_MAX) { + *data = pDataBlock; + return TSDB_CODE_SUCCESS; + } for (int32_t j = 0; j < numOfCols; ++j) { SColumnInfoData* pColInfo = taosArrayGet(pDataBlock, j); diff --git a/src/query/src/qFilter.c b/src/query/src/qFilter.c index 6b0720a8db..ac33df4700 100644 --- a/src/query/src/qFilter.c +++ b/src/query/src/qFilter.c @@ -54,11 +54,16 @@ static FORCE_INLINE int32_t filterFieldValDescCompare(const void *desc1, const v return tVariantCompare(val1, val2); } +static FORCE_INLINE int32_t filterExprCompare(const void *desc1, const void *desc2) { + return -1; +} + filter_desc_compare_func gDescCompare [FLD_TYPE_MAX] = { NULL, filterFieldColDescCompare, - filterFieldValDescCompare + filterFieldValDescCompare, + filterExprCompare }; bool filterRangeCompGi (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { @@ -833,7 +838,7 @@ int32_t filterAddField(SFilterInfo *info, void *desc, void **data, int32_t type, info->fields[type].fields[idx].desc = desc; info->fields[type].fields[idx].data = data ? *data : NULL; - if (type == FLD_TYPE_COLUMN) { + if (type == FLD_TYPE_COLUMN || type == FLD_TYPE_EXPR) { FILTER_SET_FLAG(info->fields[type].fields[idx].flag, FLD_DATA_NO_FREE); } @@ -873,7 +878,8 @@ static FORCE_INLINE int32_t filterAddColFieldFromField(SFilterInfo *info, SFilte int32_t filterAddFieldFromNode(SFilterInfo *info, tExprNode *node, SFilterFieldId *fid) { CHK_LRET(node == NULL, TSDB_CODE_QRY_APP_ERROR, "empty node"); - CHK_RET(node->nodeType != TSQL_NODE_COL && node->nodeType != TSQL_NODE_VALUE, TSDB_CODE_QRY_APP_ERROR); + CHK_RET(node->nodeType != TSQL_NODE_COL && node->nodeType != TSQL_NODE_VALUE + &&node->nodeType != TSQL_NODE_EXPR, TSDB_CODE_QRY_APP_ERROR); int32_t type; void *v; @@ -882,6 +888,9 @@ int32_t filterAddFieldFromNode(SFilterInfo *info, tExprNode *node, SFilterFieldI type = FLD_TYPE_COLUMN; v = node->pSchema; node->pSchema = NULL; + } else if (node->nodeType == TSQL_NODE_EXPR) { + type = FLD_TYPE_EXPR; + v = node; } else { type = FLD_TYPE_VALUE; v = node->pVal; @@ -933,9 +942,11 @@ int32_t filterAddUnit(SFilterInfo *info, uint8_t optr, SFilterFieldId *left, SFi } SFilterField *col = FILTER_UNIT_LEFT_FIELD(info, u); - assert(FILTER_GET_FLAG(col->flag, FLD_TYPE_COLUMN)); - - info->units[info->unitNum].compare.type = FILTER_GET_COL_FIELD_TYPE(col); + if (FILTER_GET_TYPE(col->flag) == FLD_TYPE_COLUMN) { + info->units[info->unitNum].compare.type = FILTER_GET_COL_FIELD_TYPE(col); + } else { + info->units[info->unitNum].compare.type = (uint8_t)FILTER_GET_EXPR_TYPE(info, u->left); + } *uidx = info->unitNum; @@ -1188,7 +1199,7 @@ static int32_t filterDealJson(SFilterInfo *info, tExprNode* tree, tExprNode** pL jsonKeyMd5((*pLeft)->_node.pRight->pVal->pz, (*pLeft)->_node.pRight->pVal->nLen, keyMd5); memcpy(schema->name, keyMd5, TSDB_MAX_JSON_KEY_MD5_LEN); (*pLeft) = (*pLeft)->_node.pLeft; // -> operation use left as input - }else if(((*pLeft)->pSchema->type == TSDB_DATA_TYPE_JSON) && + }else if((*pLeft)->nodeType == TSQL_NODE_COL && ((*pLeft)->pSchema->type == TSDB_DATA_TYPE_JSON) && (tree->_node.optr == TSDB_RELATION_ISNULL || tree->_node.optr == TSDB_RELATION_NOTNULL)){ SSchema* schema = (*pLeft)->pSchema; char keyMd5[TSDB_MAX_JSON_KEY_MD5_LEN] = {0}; @@ -1212,7 +1223,16 @@ int32_t filterAddGroupUnitFromNode(SFilterInfo *info, tExprNode* tree, SArray *g if((ret = filterDealJson(info, tree, &pLeft)) != TSDB_CODE_SUCCESS) return ret; SFilterFieldId left = {0}, right = {0}; filterAddFieldFromNode(info, pLeft, &left); - uint8_t type = FILTER_GET_COL_FIELD_TYPE(FILTER_GET_FIELD(info, left)); + if (pLeft->nodeType != TSQL_NODE_VALUE && pLeft->nodeType != TSQL_NODE_COL) { + tree->_node.pLeft = NULL; + } + + uint8_t type; + if (left.type == FLD_TYPE_EXPR) { + type = (uint8_t)FILTER_GET_EXPR_TYPE(info, left); + } else { + type = FILTER_GET_COL_FIELD_TYPE(FILTER_GET_FIELD(info, left)); + } int32_t len = 0; uint32_t uidx = 0; @@ -1576,6 +1596,9 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options) char str[512] = {0}; SFilterField *left = FILTER_UNIT_LEFT_FIELD(info, unit); + if (FILTER_GET_TYPE(left->flag) == FLD_TYPE_EXPR) { + continue; + } SSchema *sch = left->desc; if (unit->compare.optr >= TSDB_RELATION_INVALID && unit->compare.optr <= TSDB_RELATION_CONTAINS){ len = sprintf(str, "UNIT[%d] => [%d][%s] %s [", i, sch->colId, sch->name, gOptrStr[unit->compare.optr].str); @@ -1751,6 +1774,9 @@ void filterFreeField(SFilterField* field, int32_t type) { if (!FILTER_GET_FLAG(field->flag, FLD_DESC_NO_FREE)) { if (type == FLD_TYPE_VALUE) { tVariantDestroy(field->desc); + } else if (type == FLD_TYPE_EXPR) { + tExprTreeDestroy(field->desc, NULL); + field->desc = NULL; } tfree(field->desc); @@ -2100,6 +2126,9 @@ _return: int32_t filterMergeGroupUnits(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t* gResNum) { bool empty = false; + if (info->fields[FLD_TYPE_COLUMN].num == 0) { + return TSDB_CODE_SUCCESS; + } uint32_t *colIdx = malloc(info->fields[FLD_TYPE_COLUMN].num * sizeof(uint32_t)); uint32_t colIdxi = 0; uint32_t gResIdx = 0; @@ -2109,11 +2138,16 @@ int32_t filterMergeGroupUnits(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t gRes[gResIdx] = calloc(1, sizeof(SFilterGroupCtx)); gRes[gResIdx]->colInfo = calloc(info->fields[FLD_TYPE_COLUMN].num, sizeof(SFilterColInfo)); + gRes[gResIdx]->hasExpr = false; colIdxi = 0; empty = false; for (uint32_t j = 0; j < g->unitNum; ++j) { SFilterUnit* u = FILTER_GROUP_UNIT(info, g, j); + if(u->left.type == FLD_TYPE_EXPR) { + gRes[gResIdx]->hasExpr = true; + continue; + } uint32_t cidx = FILTER_UNIT_COL_IDX(u); if (gRes[gResIdx]->colInfo[cidx].info == NULL) { @@ -2174,6 +2208,10 @@ int32_t filterMergeGroupUnits(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t void filterCheckColConflict(SFilterGroupCtx* gRes1, SFilterGroupCtx* gRes2, bool *conflict) { uint32_t idx1 = 0, idx2 = 0, m = 0, n = 0; bool equal = false; + if (gRes1->hasExpr || gRes2->hasExpr) { + *conflict = true; + return; + } for (; m < gRes1->colNum; ++m) { idx1 = gRes1->colIdx[m]; @@ -2646,7 +2684,12 @@ int32_t filterGenerateComInfo(SFilterInfo *info) { info->cunits[i].rfunc = filterGetRangeCompFuncFromOptrs(unit->compare.optr, unit->compare.optr2); info->cunits[i].optr = FILTER_UNIT_OPTR(unit); info->cunits[i].colData = NULL; - info->cunits[i].colId = FILTER_UNIT_COL_ID(info, unit); + info->cunits[i].expr = NULL; + if (unit->left.type == FLD_TYPE_COLUMN) { + info->cunits[i].colId = FILTER_UNIT_COL_ID(info, unit); + } else if (unit->left.type == FLD_TYPE_EXPR) { + info->cunits[i].expr = FILTER_GET_FIELD_DESC(FILTER_GET_FIELD(info, unit->left)); + } if (unit->right.type == FLD_TYPE_VALUE) { if(FILTER_UNIT_DATA_TYPE(unit) == TSDB_DATA_TYPE_JSON){ // json value is tVariant @@ -2662,8 +2705,12 @@ int32_t filterGenerateComInfo(SFilterInfo *info) { } else { info->cunits[i].valData2 = info->cunits[i].valData; } - - info->cunits[i].dataSize = FILTER_UNIT_COL_SIZE(info, unit); + + if (unit->left.type == FLD_TYPE_COLUMN) { + info->cunits[i].dataSize = FILTER_UNIT_COL_SIZE(info, unit); + } else { + info->cunits[i].dataSize = FILTER_GET_EXPR_SIZE(info, unit->left); + } info->cunits[i].dataType = FILTER_UNIT_DATA_TYPE(unit); } @@ -2673,8 +2720,14 @@ int32_t filterGenerateComInfo(SFilterInfo *info) { int32_t filterUpdateComUnits(SFilterInfo *info) { for (uint32_t i = 0; i < info->unitNum; ++i) { SFilterUnit *unit = &info->units[i]; - - info->cunits[i].colData = FILTER_UNIT_COL_DATA(info, unit, 0); + if (unit->left.type == FLD_TYPE_EXPR) { + SFilterField *t = FILTER_UNIT_LEFT_FIELD(info, unit); + info->cunits[i].colData = NULL; + info->cunits[i].exprData = t->data; + } else { + info->cunits[i].colData = FILTER_UNIT_COL_DATA(info, unit, 0); + info->cunits[i].exprData = NULL; + } } return TSDB_CODE_SUCCESS; @@ -2953,6 +3006,20 @@ _return: return TSDB_CODE_SUCCESS; } +char *getExprColumnData(void *param, const char* name, int32_t colId) { + void *data = NULL; + getColumnDataFromId(param, colId, &data); + return (char *) data; +} + +void* filterExprTraverse (SFilterInfo *info, int32_t numOfRows, int16_t numOfCols) { + tExprOperandInfo output; + output.data = malloc(sizeof(int64_t) * numOfRows); + SSDataBlock* pBlock = (SSDataBlock*) info->cunits[0].exprData; + SColumnDataParam param = {.numOfCols = numOfCols, .pDataBlock = (SArray*)pBlock}; + exprTreeNodeTraverse(info->cunits[0].expr, numOfRows, &output, ¶m, TSDB_ORDER_ASC, getExprColumnData); + return output.data; +} static FORCE_INLINE bool filterExecuteImplAll(void *info, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) { return true; @@ -2963,18 +3030,26 @@ static FORCE_INLINE bool filterExecuteImplEmpty(void *info, int32_t numOfRows, i static FORCE_INLINE bool filterExecuteImplIsNull(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) { SFilterInfo *info = (SFilterInfo *)pinfo; bool all = true; + char *exprData = NULL; + uint32_t uidx = info->groups[0].unitIdxs[0]; + void *colData = NULL; if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) { return all; } + if (info->cunits[0].expr) { + exprData = filterExprTraverse(info, numOfRows, numOfCols); + } else { + exprData = info->cunits[uidx].colData; + } + if (*p == NULL) { *p = calloc(numOfRows, sizeof(int8_t)); } for (int32_t i = 0; i < numOfRows; ++i) { - uint32_t uidx = info->groups[0].unitIdxs[0]; - void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + colData = (char *)exprData + info->cunits[uidx].dataSize * i; if(info->cunits[uidx].dataType == TSDB_DATA_TYPE_JSON){ if (!colData){ // for json->'key' is null (*p)[i] = 1; @@ -2992,23 +3067,35 @@ static FORCE_INLINE bool filterExecuteImplIsNull(void *pinfo, int32_t numOfRows, } } + if (info->cunits[0].expr) { + tfree(exprData); + } + return all; } static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) { SFilterInfo *info = (SFilterInfo *)pinfo; bool all = true; + char *exprData = NULL; + uint32_t uidx = info->groups[0].unitIdxs[0]; + void *colData = NULL; if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) { return all; } + if (info->cunits[0].expr) { + exprData = filterExprTraverse(info, numOfRows, numOfCols); + } else { + exprData = info->cunits[uidx].colData; + } + if (*p == NULL) { *p = calloc(numOfRows, sizeof(int8_t)); } for (int32_t i = 0; i < numOfRows; ++i) { - uint32_t uidx = info->groups[0].unitIdxs[0]; - void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + colData = (char *)exprData + info->cunits[uidx].dataSize * i; if(info->cunits[uidx].dataType == TSDB_DATA_TYPE_JSON){ if (!colData) { // for json->'key' is not null @@ -3028,6 +3115,10 @@ static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows } } + if (info->cunits[0].expr) { + tfree(exprData); + } + return all; } @@ -3081,11 +3172,16 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t** p, SDataSta void *valData = info->cunits[0].valData; void *valData2 = info->cunits[0].valData2; __compar_fn_t func = gDataCompare[info->cunits[0].func]; + char *exprData = NULL; if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) { return all; } + if (info->cunits[0].expr) { + exprData = colData = filterExprTraverse(info, numOfRows, numOfCols); + } + if (*p == NULL) { *p = calloc(numOfRows, sizeof(int8_t)); } @@ -3105,6 +3201,9 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t** p, SDataSta colData += dataSize; } + if (info->cunits[0].expr) { + tfree(exprData); + } return all; } @@ -3112,18 +3211,26 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t** p, SDataSta bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis *statis, int16_t numOfCols) { SFilterInfo *info = (SFilterInfo *)pinfo; bool all = true; + char *exprData = NULL; + uint32_t uidx = info->groups[0].unitIdxs[0]; + void *colData = NULL; if (filterExecuteBasedOnStatis(info, numOfRows, p, statis, numOfCols, &all) == 0) { return all; } + if (info->cunits[0].expr) { + exprData = filterExprTraverse(info, numOfRows, numOfCols); + } else { + exprData = info->cunits[uidx].colData; + } + if (*p == NULL) { *p = calloc(numOfRows, sizeof(int8_t)); } - + for (int32_t i = 0; i < numOfRows; ++i) { - uint32_t uidx = info->groups[0].unitIdxs[0]; - void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + colData = (char *)exprData + info->cunits[uidx].dataSize * i; if (colData == NULL || isNull(colData, info->cunits[uidx].dataType)) { (*p)[i] = 0; all = false; @@ -3152,6 +3259,10 @@ bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t** p, SDataStat } } + if (info->cunits[0].expr) { + tfree(exprData); + } + return all; } @@ -3167,6 +3278,27 @@ bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis * *p = calloc(numOfRows, sizeof(int8_t)); } + SArray* tmpData = NULL; + for (uint32_t g = 0; g < info->groupNum; ++g) { + SFilterGroup *group = &info->groups[g]; + for (uint32_t u = 0; u < group->unitNum; ++u) { + uint32_t uidx = group->unitIdxs[u]; + SFilterComUnit *cunit = &info->cunits[uidx]; + if (cunit->expr) { + if (!tmpData) { + tmpData = taosArrayInit(10, POINTER_BYTES); + } + tExprOperandInfo output; + output.data = malloc(sizeof(int64_t) * numOfRows); + taosArrayPush(tmpData, output.data); + SSDataBlock* pBlock = (SSDataBlock*) cunit->exprData; + SColumnDataParam param = {.numOfCols = numOfCols, .pDataBlock = (SArray*)pBlock}; + exprTreeNodeTraverse(cunit->expr, numOfRows, &output, ¶m, TSDB_ORDER_ASC, getExprColumnData); + cunit->colData = (char *) output.data; + } + } + } + for (int32_t i = 0; i < numOfRows; ++i) { //FILTER_UNIT_CLR_F(info); @@ -3228,6 +3360,9 @@ bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis * } } + if (tmpData) { + taosArrayDestroy(&tmpData); + } return all; } @@ -3317,7 +3452,8 @@ _return: int32_t filterSetColFieldData(SFilterInfo *info, void *param, filer_get_col_from_id fp) { CHK_LRET(info == NULL, TSDB_CODE_QRY_APP_ERROR, "info NULL"); - CHK_LRET(info->fields[FLD_TYPE_COLUMN].num <= 0, TSDB_CODE_QRY_APP_ERROR, "no column fileds"); + CHK_LRET(info->fields[FLD_TYPE_COLUMN].num <= 0 && info->fields[FLD_TYPE_EXPR].num <= 0, + TSDB_CODE_QRY_APP_ERROR, "no column fileds"); if (FILTER_ALL_RES(info) || FILTER_EMPTY_RES(info)) { return TSDB_CODE_SUCCESS; @@ -3330,6 +3466,11 @@ int32_t filterSetColFieldData(SFilterInfo *info, void *param, filer_get_col_from (*fp)(param, sch->colId, &fi->data); } + for (uint32_t i = 0; i < info->fields[FLD_TYPE_EXPR].num; ++i) { + SFilterField* fi = &info->fields[FLD_TYPE_EXPR].fields[i]; + (*fp)(param, INT32_MAX, &fi->data); + } + filterUpdateComUnits(info); return TSDB_CODE_SUCCESS; diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index e559839e3e..2abeed87a6 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -173,6 +173,11 @@ typedef struct SRange { int32_t to; } SRange; +typedef struct STagBlockInfo { + SSkipListNode *pSkipListNode; + SArray *pBlock; +} STagBlockInfo; + static STimeWindow updateLastrowForEachGroup(STableGroupInfo *groupList); static int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList); static int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle); @@ -4334,7 +4339,15 @@ static FORCE_INLINE int32_t tsdbGetTagDataFromId(void *param, int32_t id, void * return TSDB_CODE_SUCCESS; } - +static FORCE_INLINE int32_t tsdbGetTagData(void *param, int32_t id, void **data) { + STagBlockInfo* pInfo = (STagBlockInfo*) param; + if (id == INT32_MAX) { + *data = pInfo->pBlock; + } else { + return tsdbGetTagDataFromId(pInfo->pSkipListNode, id, data); + } + return TSDB_CODE_SUCCESS; +} static void queryIndexedColumn(SSkipList* pSkipList, void* filterInfo, SArray* res) { SSkipListIterator* iter = NULL; @@ -4389,26 +4402,77 @@ static void queryIndexedColumn(SSkipList* pSkipList, void* filterInfo, SArray* r tsdbDebug("filter index column end"); } +static void getAllExprColId(tExprNode* pExpr, SArray* array) { + if (!pExpr) { + return; + } + if (pExpr->nodeType == TSQL_NODE_FUNC) { + for (int32_t i = 0; i < pExpr->_func.numChildren; ++i) { + getAllExprColId(pExpr->_func.pChildren[i], array); + } + } else if (pExpr->nodeType == TSQL_NODE_EXPR) { + getAllExprColId(pExpr->_node.pLeft, array); + getAllExprColId(pExpr->_node.pRight, array); + } else if (pExpr->nodeType == TSQL_NODE_COL) { + taosArrayPush(array, &pExpr->pSchema->colId); + } +} + +static void getAllFilterExprColId(SFilterFields* pSf, SArray* array) { + for (uint32_t i = 0; i < pSf->num; ++i) { + SFilterField* fi = &(pSf->fields[i]); + if (FILTER_GET_TYPE(fi->flag) == FLD_TYPE_EXPR) { + getAllExprColId(fi->desc, array); + } + } + taosArraySort(array, getComparFunc(TSDB_DATA_TYPE_SMALLINT, 0)); + taosArrayRemoveDuplicate(array, getComparFunc(TSDB_DATA_TYPE_SMALLINT, 0), NULL); +} + static void queryIndexlessColumn(SSkipList* pSkipList, void* filterInfo, SArray* res) { SSkipListIterator* iter = tSkipListCreateIter(pSkipList); int8_t *addToResult = NULL; + SFilterInfo *sfInfo = (SFilterInfo *)filterInfo; + SArray *array = NULL; + SArray *pDataBlock = NULL; + if (sfInfo->fields[FLD_TYPE_EXPR].num > 0) { + array = taosArrayInit(10, sizeof(int16_t)); + getAllFilterExprColId(&(sfInfo->fields[FLD_TYPE_EXPR]), array); + } while (tSkipListIterNext(iter)) { SSkipListNode *pNode = tSkipListIterGet(iter); - filterSetColFieldData(filterInfo, pNode, tsdbGetTagDataFromId); - char *pData = SL_GET_NODE_DATA(pNode); + if (sfInfo->fields[FLD_TYPE_EXPR].num > 0) { + pDataBlock = taosArrayInit(10, sizeof(SColumnInfoData)); + size_t num = taosArrayGetSize(array); + for(int32_t i = 0; i < num; ++i) { + int16_t *pColId = taosArrayGet(array, i); + void *data = NULL; + tsdbGetTagDataFromId(pNode, *pColId, &data); + SColumnInfoData colData = {{0}}; + colData.pData = data; + colData.info.colId = *pColId; + taosArrayPush(pDataBlock, &colData); + } + } + STagBlockInfo stInfo = {.pSkipListNode = pNode, .pBlock = pDataBlock}; + filterSetColFieldData(filterInfo, &stInfo, tsdbGetTagData); - bool all = filterExecute(filterInfo, 1, &addToResult, NULL, 0); + char *pData = SL_GET_NODE_DATA(pNode); + int16_t numOfCols = array ? (int16_t)taosArrayGetSize(array) : 0; + bool all = filterExecute(filterInfo, 1, &addToResult, NULL, numOfCols); if (all || (addToResult && *addToResult)) { STableKeyInfo info = {.pTable = (void*)pData, .lastKey = TSKEY_INITIAL_VAL}; taosArrayPush(res, &info); } + taosArrayDestroy(&pDataBlock); } + taosArrayDestroy(&array); tfree(addToResult); tSkipListDestroyIter(iter); -- GitLab