diff --git a/include/libs/function/function.h b/include/libs/function/function.h index 1bc0128dbe..a8872ad323 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -221,7 +221,7 @@ typedef struct SScalarFunctionInfo { char name[FUNCTIONS_NAME_MAX_LENGTH]; int8_t type; // scalar function or aggregation function uint32_t functionId; // index of scalar function - void (*process)(const struct SScalarFuncParam *pInput, struct SScalarFuncParam* pOutput); + void (*process)(struct SScalarFuncParam* pOutput, size_t numOfInput, const struct SScalarFuncParam *pInput); } SScalarFunctionInfo; typedef struct SMultiFunctionsDesc { diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index f79ad35862..7b8d50bf16 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -80,8 +80,7 @@ typedef struct SQueryStmtInfo { SGroupbyExpr groupbyExpr; // groupby tags info SArray * colList; // SArray SFieldInfo fieldsInfo; - SArray * exprList; // SArray - SArray * exprList1; // final exprlist in case of arithmetic expression exists + SArray** exprList; // SArray SLimit limit; SLimit slimit; STagCond tagCond; @@ -112,6 +111,7 @@ typedef struct SQueryStmtInfo { struct SQueryStmtInfo *pDownstream; int32_t havingFieldNum; SMultiFunctionsDesc info; + int32_t exprListLevelIndex; } SQueryStmtInfo; typedef struct SColumnIndex { @@ -165,7 +165,7 @@ void assignExprInfo(SExprInfo* dst, const SExprInfo* src); void columnListCopy(SArray* dst, const SArray* src, uint64_t uid); void columnListDestroy(SArray* pColumnList); -void dropAllExprInfo(SArray* pExprInfo); +void dropAllExprInfo(SArray** pExprInfo, int32_t numOfLevel); SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SColumnIndex* pColIndex, struct tExprNode* pParamExpr, SSchema* pResSchema, int16_t interSize); int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy); diff --git a/include/util/tdef.h b/include/util/tdef.h index 652d329cd3..65230e2a7e 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -140,8 +140,9 @@ do { \ #define FUNCTION_ROUND 4503 #define FUNCTION_LENGTH 4800 -#define FUNCTION_LTRIM 4801 -#define FUNCTION_RTRIM 4802 +#define FUNCTION_CONCAT 4801 +#define FUNCTION_LTRIM 4802 +#define FUNCTION_RTRIM 4803 #define IS_RELATION_OPTR(op) (((op) >= TSDB_RELATION_LESS) && ((op) < TSDB_RELATION_IN)) #define IS_ARITHMETIC_OPTR(op) (((op) >= TSDB_BINARY_OP_ADD) && ((op) <= TSDB_BINARY_OP_REMAINDER)) diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index aa7ea48432..7e19093b10 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -12,10 +12,11 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#include #include "os.h" -#include "ttime.h" #include "taosmsg.h" #include "tglobal.h" +#include "ttime.h" #include "exception.h" #include "executorimpl.h" @@ -161,7 +162,7 @@ int64_t genQueryId(void) { static int32_t getExprFunctionId(SExprInfo *pExprInfo) { assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_UNARYEXPR_NODE); - return pExprInfo->pExpr->_node.functionId; + return pExprInfo->pExpr->_function.functionId; } static void getNextTimeWindow(SQueryAttr* pQueryAttr, STimeWindow* tw) { @@ -1069,6 +1070,7 @@ void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlo } static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { +#if 0 for (int32_t i = 0; i < pOperator->numOfOutput; ++i) { pCtx[i].order = order; pCtx[i].size = pBlock->info.rows; @@ -1079,7 +1081,7 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, if (pCtx[i].functionId == FUNCTION_ARITHM) { // setArithParams((SScalarFunctionSupport*)pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock); } else { - SColIndex* pCol = &pOperator->pExpr[i].base.colInfo; + SColIndex* pCol = &pOperator->pExpr[i].base.pColumns->info.; if (TSDB_COL_IS_NORMAL_COL(pCol->flag) || (pCtx[i].functionId == FUNCTION_BLKINFO) || (TSDB_COL_IS_TAG(pCol->flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) { SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo; @@ -1087,7 +1089,7 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, // in case of the block distribution query, the inputBytes is not a constant value. pCtx[i].pInput = p->pData; - assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type); + assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type); if (pCtx[i].functionId < 0) { SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0); @@ -1112,7 +1114,7 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex); pCtx[i].pInput = p->pData; - assert(p->info.colId == pColIndex->colId && pCtx[i].inputType == p->info.type); + assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type); for(int32_t j = 0; j < pBlock->info.rows; ++j) { char* dst = p->pData + j * p->info.bytes; taosVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true); @@ -1120,6 +1122,8 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, } } } +#endif + } static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock) { @@ -1170,11 +1174,11 @@ void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo, continue; } - SColIndex * pColIndex = &pExpr[k].base.colInfo; + SColIndex * pColIndex = NULL/*&pExpr[k].base.colInfo*/; int16_t index = pColIndex->colIndex; SColumnInfoData *pColInfo = taosArrayGet(pDataBlock, index); - assert(pColInfo->info.colId == pColIndex->colId && curTs != windowKey); +// assert(pColInfo->info.colId == pColIndex->info.colId && curTs != windowKey); double v1 = 0, v2 = 0, v = 0; if (prevRowIndex == -1) { @@ -1858,7 +1862,7 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr for (int32_t i = 0; i < numOfOutput; ++i) { SSqlExpr *pSqlExpr = &pExpr[i].base; SQLFunctionCtx* pCtx = &pFuncCtx[i]; - +#if 0 SColIndex *pIndex = &pSqlExpr->colInfo; if (TSDB_COL_REQ_NULL(pIndex->flag)) { @@ -1867,7 +1871,7 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr } else { pCtx->requireNull = false; } - +#endif // pCtx->inputBytes = pSqlExpr->colBytes; // pCtx->inputType = pSqlExpr->colType; @@ -2359,7 +2363,7 @@ bool onlyQueryTags(SQueryAttr* pQueryAttr) { if (functionId != FUNCTION_TAGPRJ && functionId != FUNCTION_TID_TAG && - (!(functionId == FUNCTION_COUNT && pExprInfo->base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX)) && + (!(functionId == FUNCTION_COUNT && pExprInfo->base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX)) && (!(functionId == FUNCTION_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.pColumns->flag)))) { return false; } @@ -2879,7 +2883,7 @@ static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSData int32_t numOfOutput = pTableScanInfo->numOfOutput; for (int32_t i = 0; i < numOfOutput; ++i) { int32_t functionId = pCtx[i].functionId; - int32_t colId = pTableScanInfo->pExpr[i].base.pColumns->colId; + int32_t colId = pTableScanInfo->pExpr[i].base.pColumns->info.colId; // group by + first/last should not apply the first/last block filter if (functionId < 0) { @@ -3211,7 +3215,7 @@ void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCt } // todo use tag column index to optimize performance - doSetTagValueInParam(pTable, pLocalExprInfo->base.pColumns->colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type, + doSetTagValueInParam(pTable, pLocalExprInfo->base.pColumns->info.colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type, pLocalExprInfo->base.resSchema.bytes); if (IS_NUMERIC_TYPE(pLocalExprInfo->base.resSchema.type) @@ -3787,7 +3791,7 @@ void setParamForStableStddev(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx* pCtx int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult); for (int32_t k = 0; k < numOfCols; ++k) { SStddevInterResult* pres = taosArrayGet(p->pResult, k); - if (pres->colId == pExpr->colInfo.colId) { + if (pres->info.colId == pExpr->colInfo.colId) { pCtx[i].param[0].arr = pres->pResult; break; } @@ -3819,7 +3823,7 @@ void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunction int32_t numOfCols = (int32_t)taosArrayGetSize(p->pResult); for (int32_t k = 0; k < numOfCols; ++k) { SStddevInterResult* pres = taosArrayGet(p->pResult, k); - if (pres->colId == pExpr1->colInfo.colId) { + if (pres->info.colId == pExpr1->colInfo.colId) { pCtx[i].param[0].arr = pres->pResult; break; } @@ -5041,7 +5045,7 @@ SArray* getOrderCheckColumns(SQueryAttr* pQuery) { SSqlExpr* pExpr = &pQuery->pExpr1[j].base; int32_t functionId = getExprFunctionId(&pQuery->pExpr1[j]); - if (index->colId == pExpr->colInfo.colId && + if (index->colId == pExpr->pColumns->info.colId && (functionId == FUNCTION_PRJ || functionId == FUNCTION_TAG || functionId == FUNCTION_TS)) { index->colIndex = j; index->colId = pExpr->resSchema.colId; @@ -5073,8 +5077,8 @@ SArray* getResultGroupCheckColumns(SQueryAttr* pQuery) { // FUNCTION_TAG_DUMMY function needs to be ignored if (index->colId == pExpr->pColumns->info.colId && - ((TSDB_COL_IS_TAG(pExpr->colInfo.flag) && functionId == FUNCTION_TAG) || - (TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag) && functionId == FUNCTION_PRJ))) { + ((TSDB_COL_IS_TAG(pExpr->pColumns->flag) && functionId == FUNCTION_TAG) || + (TSDB_COL_IS_NORMAL_COL(pExpr->pColumns->flag) && functionId == FUNCTION_PRJ))) { index->colIndex = j; index->colId = pExpr->resSchema.colId; found = true; @@ -5291,7 +5295,7 @@ SOperatorInfo *createOrderOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI pDataBlock->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData)); for(int32_t i = 0; i < numOfOutput; ++i) { SColumnInfoData col = {{0}}; - col.info.colId = pExpr[i].base.pColumns->colId; + col.info.colId = pExpr[i].base.pColumns->info.colId; // col.info.bytes = pExpr[i].base.colBytes; // col.info.type = pExpr[i].base.colType; taosArrayPush(pDataBlock->pDataBlock, &col); @@ -6777,7 +6781,7 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { int16_t type = pExprInfo->base.resSchema.type; for(int32_t i = 0; i < pQueryAttr->numOfTags; ++i) { - if (pQueryAttr->tagColList[i].colId == pExprInfo->base.pColumns->colId) { + if (pQueryAttr->tagColList[i].colId == pExprInfo->base.pColumns->info.colId) { bytes = pQueryAttr->tagColList[i].bytes; type = pQueryAttr->tagColList[i].type; break; @@ -6809,10 +6813,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { output += sizeof(pQueryAttr->vgId); char* data = NULL; - if (pExprInfo->base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX) { + if (pExprInfo->base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX) { data = tsdbGetTableName(item->pTable); } else { - data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.pColumns->colId, type, bytes); + data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.pColumns->info.colId, type, bytes); } doSetTagValueToResultBuf(output, data, type, bytes); @@ -6848,10 +6852,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { type = pExprInfo[j].base.resSchema.type; bytes = pExprInfo[j].base.resSchema.bytes; - if (pExprInfo[j].base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX) { + if (pExprInfo[j].base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX) { data = tsdbGetTableName(item->pTable); } else { - data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.pColumns->colId, type, bytes); + data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.pColumns->info.colId, type, bytes); } dst = pColInfo->pData + count * pExprInfo[j].base.resSchema.bytes; @@ -7047,20 +7051,20 @@ SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperat static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *pExpr, SColumnInfo* pTagCols) { int32_t j = 0; - if (TSDB_COL_IS_TAG(pExpr->colInfo.flag)) { - if (pExpr->colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { + if (TSDB_COL_IS_TAG(pExpr->pColumns->flag)) { + if (pExpr->pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX) { return TSDB_TBNAME_COLUMN_INDEX; } while(j < pTableInfo->numOfTags) { - if (pExpr->colInfo.colId == pTagCols[j].colId) { + if (pExpr->pColumns->info.colId == pTagCols[j].colId) { return j; } j += 1; } - } else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) { // user specified column data + } /*else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) { // user specified column data return TSDB_UD_COLUMN_INDEX; } else { while (j < pTableInfo->numOfCols) { @@ -7070,7 +7074,7 @@ static int32_t getColumnIndexInSource(SQueriedTableInfo *pTableInfo, SSqlExpr *p j += 1; } - } + }*/ return INT32_MIN; // return a less than TSDB_TBNAME_COLUMN_INDEX value } @@ -7815,7 +7819,7 @@ int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t nu // bytes = tDataTypes[type].bytes; // } else { // int32_t index = pExprs[i].base.colInfo.colIndex; -// assert(prevExpr[index].base.resSchema.colId == pExprs[i].base.pColumns->colId); +// assert(prevExpr[index].base.resSchema.colId == pExprs[i].base.pColumns->info.colId); // // type = prevExpr[index].base.resSchema.type; // bytes = prevExpr[index].base.resSchema.bytes; @@ -7951,7 +7955,7 @@ static void doUpdateExprColumnIndex(SQueryAttr *pQueryAttr) { // } // todo opt performance - SColIndex *pColIndex = &pSqlExprMsg->colInfo; + SColIndex *pColIndex = NULL;/*&pSqlExprMsg->colInfo;*/ if (TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) { int32_t f = 0; for (f = 0; f < pQueryAttr->numOfCols; ++f) { diff --git a/source/libs/function/inc/tscalarfunction.h b/source/libs/function/inc/tscalarfunction.h index ddb56518e0..6d23775610 100644 --- a/source/libs/function/inc/tscalarfunction.h +++ b/source/libs/function/inc/tscalarfunction.h @@ -37,7 +37,7 @@ typedef struct SScalarFunctionSupport { char** data; } SScalarFunctionSupport; -extern struct SScalarFunctionInfo scalarFunc[5]; +extern struct SScalarFunctionInfo scalarFunc[8]; int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncParam* pOutput, void* param, char* (*getSourceDataBlock)(void*, const char*, int32_t)); diff --git a/source/libs/function/src/tscalarfunction.c b/source/libs/function/src/tscalarfunction.c index 80d426f101..1e7e3ef155 100644 --- a/source/libs/function/src/tscalarfunction.c +++ b/source/libs/function/src/tscalarfunction.c @@ -9,8 +9,9 @@ static void assignBasicParaInfo(struct SScalarFuncParam* dst, const struct SScal dst->num = src->num; } -static void tceil(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { +static void tceil(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) { assignBasicParaInfo(pOutput, pLeft); + assert(numOfInput == 1); switch (pLeft->bytes) { case TSDB_DATA_TYPE_FLOAT: { @@ -34,8 +35,9 @@ static void tceil(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { } } -static void tfloor(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { +static void tfloor(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) { assignBasicParaInfo(pOutput, pLeft); + assert(numOfInput == 1); switch (pLeft->bytes) { case TSDB_DATA_TYPE_FLOAT: { @@ -61,8 +63,9 @@ static void tfloor(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { } } -static void _tabs(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { +static void _tabs(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) { assignBasicParaInfo(pOutput, pLeft); + assert(numOfInput == 1); switch (pLeft->bytes) { case TSDB_DATA_TYPE_FLOAT: { @@ -118,8 +121,9 @@ static void _tabs(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { } } -static void tround(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { +static void tround(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) { assignBasicParaInfo(pOutput, pLeft); + assert(numOfInput == 1); switch (pLeft->bytes) { case TSDB_DATA_TYPE_FLOAT: { @@ -143,7 +147,9 @@ static void tround(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { } } -static void tlength(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { +static void tlength(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) { + assert(numOfInput == 1); + int64_t* out = (int64_t*) pOutput->data; char* s = pLeft->data; @@ -152,6 +158,46 @@ static void tlength(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { } } +static void tconcat(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) { + assert(numOfInput > 0); + + int32_t rowLen = 0; + int32_t num = 1; + for(int32_t i = 0; i < numOfInput; ++i) { + rowLen += pLeft[i].bytes; + + if (pLeft[i].num > 1) { + num = pLeft[i].num; + } + } + + pOutput->data = realloc(pOutput->data, rowLen * num); + assert(pOutput->data); + + char* rstart = pOutput->data; + for(int32_t i = 0; i < num; ++i) { + + char* s = rstart; + varDataSetLen(s, 0); + for (int32_t j = 0; j < numOfInput; ++j) { + char* p1 = POINTER_SHIFT(pLeft[j].data, i * pLeft[j].bytes); + + memcpy(varDataVal(s) + varDataLen(s), varDataVal(p1), varDataLen(p1)); + varDataLen(s) += varDataLen(p1); + } + + rstart += rowLen; + } +} + +static void tltrim(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) { + +} + +static void trtrim(SScalarFuncParam* pOutput, size_t numOfInput, const SScalarFuncParam *pLeft) { + +} + static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOfRows) { switch(type) { case TSDB_DATA_TYPE_TINYINT: @@ -256,7 +302,6 @@ int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncPa _bin_scalar_fn_t OperatorFn = getBinScalarOperatorFn(pExprs->_node.optr); SScalarFuncParam left = {0}, right = {0}; - if (pLeft->nodeType == TEXPR_BINARYEXPR_NODE || pLeft->nodeType == TEXPR_UNARYEXPR_NODE) { setScalarFuncParam(&left, leftOutput.type, leftOutput.bytes, leftOutput.data, leftOutput.num); } else if (pLeft->nodeType == TEXPR_COL_NODE) { @@ -318,12 +363,15 @@ int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncPa return 0; } -SScalarFunctionInfo scalarFunc[5] = { +SScalarFunctionInfo scalarFunc[8] = { {"ceil", FUNCTION_TYPE_SCALAR, FUNCTION_CEIL, tceil}, {"floor", FUNCTION_TYPE_SCALAR, FUNCTION_FLOOR, tfloor}, {"abs", FUNCTION_TYPE_SCALAR, FUNCTION_ABS, _tabs}, {"round", FUNCTION_TYPE_SCALAR, FUNCTION_ROUND, tround}, {"length", FUNCTION_TYPE_SCALAR, FUNCTION_LENGTH, tlength}, + {"concat", FUNCTION_TYPE_SCALAR, FUNCTION_CONCAT, tconcat}, + {"ltrim", FUNCTION_TYPE_SCALAR, FUNCTION_LTRIM, tltrim}, + {"rtrim", FUNCTION_TYPE_SCALAR, FUNCTION_RTRIM, trtrim}, }; void setScalarFunctionSupp(struct SScalarFunctionSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) { diff --git a/source/libs/parser/inc/queryInfoUtil.h b/source/libs/parser/inc/queryInfoUtil.h index 68fe08db47..6edcc4b225 100644 --- a/source/libs/parser/inc/queryInfoUtil.h +++ b/source/libs/parser/inc/queryInfoUtil.h @@ -31,7 +31,7 @@ SSchema *getTableTagSchema(const STableMeta* pTableMeta); size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo); SExprInfo* createBinaryExprInfo(struct tExprNode* pNode, SSchema* pResSchema); -void addExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index, SExprInfo* pExprInfo); +void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level); void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize); SExprInfo* getExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index); diff --git a/source/libs/parser/src/astValidate.c b/source/libs/parser/src/astValidate.c index c25e647b48..d7e367cd0f 100644 --- a/source/libs/parser/src/astValidate.c +++ b/source/libs/parser/src/astValidate.c @@ -202,7 +202,6 @@ SQueryStmtInfo *createQueryInfo() { SQueryStmtInfo* pQueryInfo = calloc(1, sizeof(SQueryStmtInfo)); pQueryInfo->fieldsInfo.internalField = taosArrayInit(4, sizeof(SInternalField)); - pQueryInfo->exprList = taosArrayInit(4, POINTER_BYTES); pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); pQueryInfo->udColumnId = TSDB_UD_COLUMN_INDEX; pQueryInfo->limit.limit = -1; @@ -213,6 +212,13 @@ SQueryStmtInfo *createQueryInfo() { pQueryInfo->pUpstream = taosArrayInit(4, POINTER_BYTES); pQueryInfo->window = TSWINDOW_INITIALIZER; + pQueryInfo->exprList = calloc(10, POINTER_BYTES); + for(int32_t i = 0; i < 10; ++i) { + pQueryInfo->exprList[i] = taosArrayInit(4, POINTER_BYTES); + } + + pQueryInfo->exprListLevelIndex = 0; + return pQueryInfo; } @@ -221,14 +227,9 @@ static void destroyQueryInfoImpl(SQueryStmtInfo* pQueryInfo) { cleanupColumnCond(&pQueryInfo->colCond); cleanupFieldInfo(&pQueryInfo->fieldsInfo); - dropAllExprInfo(pQueryInfo->exprList); + dropAllExprInfo(pQueryInfo->exprList, 10); pQueryInfo->exprList = NULL; - if (pQueryInfo->exprList1 != NULL) { - dropAllExprInfo(pQueryInfo->exprList1); - pQueryInfo->exprList1 = NULL; - } - columnListDestroy(pQueryInfo->colList); pQueryInfo->colList = NULL; @@ -1707,18 +1708,27 @@ void setResultColName(char* name, tSqlExprItem* pItem, SToken* pToken, SToken* f } } +SArray* getCurrentExprList(SQueryStmtInfo* pQueryInfo) { + assert(pQueryInfo != NULL && pQueryInfo->exprListLevelIndex >= 0 && pQueryInfo->exprListLevelIndex < 10); + return pQueryInfo->exprList[pQueryInfo->exprListLevelIndex]; +} + SExprInfo* doAddOneExprInfo(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId, SColumnIndex* pIndex, SSchema* pColSchema, SSchema* pResultSchema, tExprNode* pExprNode, int32_t interSize, const char* token, bool finalResult) { STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); SExprInfo* pExpr = createExprInfo(pTableMetaInfo, functionId, pIndex, pExprNode, pResultSchema, interSize); - addExprInfo(pQueryInfo, outputColIndex, pExpr); + + SArray* pExprList = getCurrentExprList(pQueryInfo); + addExprInfo(pExprList, outputColIndex, pExpr, pQueryInfo->exprListLevelIndex); tstrncpy(pExpr->base.token, token, sizeof(pExpr->base.token)); uint64_t uid = pTableMetaInfo->pTableMeta->uid; - SArray* p = TSDB_COL_IS_TAG(pIndex->type)?pTableMetaInfo->tagColList:pQueryInfo->colList; - columnListInsert(p, uid, pColSchema, pIndex->type); + if (pIndex->columnIndex != COLUMN_INDEX_INITIAL_VAL) { + SArray* p = TSDB_COL_IS_TAG(pIndex->type) ? pTableMetaInfo->tagColList : pQueryInfo->colList; + columnListInsert(p, uid, pColSchema, pIndex->type); + } pExpr->base.pColumns->flag = pIndex->type; if (TSDB_COL_IS_NORMAL_COL(pIndex->type)) { @@ -1792,7 +1802,8 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab SExprInfo* pExpr = createExprInfo(pTableMetaInfo, FUNCTION_TS_DUMMY, &indexTS, NULL, &s, TSDB_KEYSIZE); strncpy(pExpr->base.token, "ts", tListLen(pExpr->base.token)); - addExprInfo(pQueryInfo, outputIndex, pExpr); + SArray* pExprList = getCurrentExprList(pQueryInfo); + addExprInfo(pExprList, outputIndex, pExpr, pQueryInfo->exprListLevelIndex); SSchema* pSourceSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, indexTS.columnIndex); columnListInsert(pQueryInfo->colList, pTableMetaInfo->pTableMeta->uid, pSourceSchema, TSDB_COL_NORMAL); @@ -1900,8 +1911,9 @@ static int32_t doHandleOneParam(SQueryStmtInfo *pQueryInfo, tSqlExprItem* pItem, static int32_t multiColumnListInsert(SQueryStmtInfo* pQueryInfo, SArray* pColumnList, SMsgBuf* pMsgBuf); static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf); -int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo, SSchema* columnSchema, - tExprNode** pNode, SColumnIndex* pIndex, tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf) { +int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo, + SSchema* columnSchema, tExprNode** pNode, SColumnIndex* pIndex, + tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf) { const char* msg1 = "not support column types"; const char* msg2 = "invalid parameters"; const char* msg3 = "illegal column name"; @@ -1926,11 +1938,20 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId return buildInvalidOperationMsg(pMsgBuf, msg6); } - int32_t code = createComplexExpr(pQueryInfo, i, pParamElem, pMsgBuf); + SArray* pExprList = getCurrentExprList(pQueryInfo); + size_t n = taosArrayGetSize(pExprList); + + // todo extract the table uid + pIndex->tableIndex = 0; + int32_t code = createComplexExpr(pQueryInfo, n, pParamElem, pMsgBuf); if (code != TSDB_CODE_SUCCESS) { return code; } + SExprInfo** pLastExpr = taosArrayGetLast(pExprList); + *pNode = (*pLastExpr)->pExpr; + *(SSchema*) columnSchema = (*pLastExpr)->base.resSchema; + *pTableMetaInfo = getMetaInfo(pQueryInfo, 0); } else { if ((getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, pIndex, pMsgBuf) != TSDB_CODE_SUCCESS)) { return buildInvalidOperationMsg(pMsgBuf, msg3); @@ -1945,36 +1966,20 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId *pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); *columnSchema = *(SSchema*)getOneColumnSchema((*pTableMetaInfo)->pTableMeta, pIndex->columnIndex); } - }else if (tokenId == TK_PLUS || tokenId == TK_MINUS || tokenId == TK_STAR || tokenId == TK_REM || tokenId == TK_DIVIDE || tokenId == TK_CONCAT) { - int32_t arithmeticType = NON_ARITHMEIC_EXPR; - SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); - if (validateComplexExpr(pParamElem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); + } else if (tokenId == TK_PLUS || tokenId == TK_MINUS || tokenId == TK_STAR || tokenId == TK_REM || tokenId == TK_DIVIDE || tokenId == TK_CONCAT) { + pIndex->tableIndex = 0; // todo set the correct table index + + SArray* pExprList = getCurrentExprList(pQueryInfo); + size_t n = taosArrayGetSize(pExprList); + int32_t code = createComplexExpr(pQueryInfo, n, pParamElem, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; } - if (arithmeticType != NORMAL_ARITHMETIC) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - *pTableMetaInfo = getMetaInfo(pQueryInfo, 0); // todo get the first table meta. - *columnSchema = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), ""); - - SToken* pExprToken = &pParamElem->pNode->exprToken; - int32_t len = MIN(TSDB_COL_NAME_LEN, pExprToken->n + 1); - tstrncpy(columnSchema->name, pExprToken->z, len); - - SArray* colList = taosArrayInit(10, sizeof(SColIndex)); - int32_t ret = sqlExprToExprNode(pNode, pParamElem->pNode, pQueryInfo, colList, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - taosArrayDestroy(colList); - tExprTreeDestroy(*pNode, NULL); - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - - pIndex->tableIndex = 0; - multiColumnListInsert(pQueryInfo, pColumnList, pMsgBuf); - taosArrayDestroy(colList); - taosArrayDestroy(pColumnList); + SExprInfo** pLastExpr = taosArrayGetLast(getCurrentExprList(pQueryInfo)); + *pNode = (*pLastExpr)->pExpr; + *(SSchema*) columnSchema = (*pLastExpr)->base.resSchema; + *pTableMetaInfo = getMetaInfo(pQueryInfo, 0); } else { assert(0); } @@ -1997,7 +2002,7 @@ static int32_t checkForkParam(tSqlExpr* pSqlExpr, size_t k, SMsgBuf* pMsgBuf) { return TSDB_CODE_SUCCESS; } -int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult, SMsgBuf* pMsgBuf) { +int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem, bool finalResult, SMsgBuf* pMsgBuf) { STableMetaInfo* pTableMetaInfo = NULL; int32_t functionId = pItem->functionId; int32_t code = TSDB_CODE_SUCCESS; @@ -2071,12 +2076,15 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx tSqlExprItem* pParamElem = taosArrayGet(pItem->pNode->Expr.paramList, 0); - tExprNode* pNode = NULL; - int32_t tokenId = pParamElem->pNode->tokenId; - SColumnIndex index = COLUMN_INDEX_INITIALIZER; + tExprNode* pNode = NULL; + int32_t tokenId = pParamElem->pNode->tokenId; + SColumnIndex index = COLUMN_INDEX_INITIALIZER; SSchema columnSchema = {0}; - code = extractFunctionParameterInfo(pQueryInfo, tokenId, &pTableMetaInfo, &columnSchema, &pNode, &index, pParamElem,pMsgBuf); + pQueryInfo->exprListLevelIndex += 1; + code = extractFunctionParameterInfo(pQueryInfo, tokenId, &pTableMetaInfo, &columnSchema, &pNode, &index, pParamElem, pMsgBuf); + pQueryInfo->exprListLevelIndex -= 1; + if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2440,23 +2448,31 @@ static int32_t validateExprLeafFunctionNode(SQueryStmtInfo* pQueryInfo, tSqlExpr } int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo); - if (addExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - // It is invalid in case of more than one sqlExpr, such as first(ts, k) - last(ts, k) - int32_t inc = (int32_t) getNumOfExprs(pQueryInfo) - outputIndex; - if (inc > 1) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // Not supported data type in expression - for(int32_t i = 0; i < inc; ++i) { - SExprInfo* p1 = getExprInfo(pQueryInfo, i + outputIndex); - int16_t t = p1->base.resSchema.type; - if (t == TSDB_DATA_TYPE_TIMESTAMP) { + if (scalar) { + printf("scalar function found!\n"); +// if (createComplexExpr(pQueryInfo, outputIndex, &item, pMsgBuf) != TSDB_CODE_SUCCESS) { +// return TSDB_CODE_TSC_INVALID_OPERATION; +// } + } else { + if (addAggExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; } + + // It is invalid in case of more than one sqlExpr, such as first(ts, k) - last(ts, k) + int32_t inc = (int32_t)getNumOfExprs(pQueryInfo) - outputIndex; + if (inc > 1) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + // Not supported data type in expression + for (int32_t i = 0; i < inc; ++i) { + SExprInfo* p1 = getExprInfo(pQueryInfo, i + outputIndex); + int16_t t = p1->base.resSchema.type; + if (t == TSDB_DATA_TYPE_TIMESTAMP) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + } } return TSDB_CODE_SUCCESS; @@ -2480,7 +2496,6 @@ int32_t validateScalarFunctionParamNum(tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { int32_t validateScalarFunctionParam(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr, SArray* pList, int32_t* exprType, SMsgBuf* pMsgBuf) { int32_t code = TSDB_CODE_SUCCESS; - // more than one parameter for count() function SArray* pParamList = pExpr->Expr.paramList; *exprType = NORMAL_ARITHMETIC; @@ -2491,6 +2506,7 @@ int32_t validateScalarFunctionParam(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr, int32_t type = pSqlExpr->type; if (type == SQL_NODE_VALUE) { + // do nothing for scalar function, or maybe the evaluation can be done here } else if (type == SQL_NODE_SQLFUNCTION) { code = validateExprLeafFunctionNode(pQueryInfo, pSqlExpr, pMsgBuf); if (code != TSDB_CODE_SUCCESS) { @@ -2785,45 +2801,95 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt tExprNode* pLeft = NULL; tExprNode* pRight= NULL; - if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { - // assert it is a scalar function - *pExpr = calloc(1, sizeof(tExprNode)); - (*pExpr)->nodeType = TEXPR_FUNCTION_NODE; - (*pExpr)->_function.num = 1; - (*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n); - - SArray* pParamList = pSqlExpr->Expr.paramList; - size_t num = taosArrayGetSize(pParamList); - (*pExpr)->_function.pChild = calloc(num, POINTER_BYTES); - - for(int32_t i = 0; i < num; ++i) { - tSqlExprItem* pItem = taosArrayGet(pParamList, i); - sqlExprToExprNode(&(((*pExpr)->_function.pChild)[0]), pItem->pNode, pQueryInfo, pCols, pMsgBuf); - } - - return TSDB_CODE_SUCCESS; - } +// if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { +// // assert it is a scalar function +// *pExpr = calloc(1, sizeof(tExprNode)); +// (*pExpr)->nodeType = TEXPR_FUNCTION_NODE; +// (*pExpr)->_function.num = 1; +// (*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n); +// +// SArray* pParamList = pSqlExpr->Expr.paramList; +// size_t num = taosArrayGetSize(pParamList); +// (*pExpr)->_function.pChild = calloc(num, POINTER_BYTES); +// +// for(int32_t i = 0; i < num; ++i) { +// tSqlExprItem* pItem = taosArrayGet(pParamList, i); +// sqlExprToExprNode(&(((*pExpr)->_function.pChild)[0]), pItem->pNode, pQueryInfo, pCols, pMsgBuf); +// } +// +// return TSDB_CODE_SUCCESS; +// } SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (pSqlExpr->pLeft != NULL) { - int32_t ret = sqlExprToExprNode(&pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + if (pSqlExpr->type == SQL_NODE_EXPR) { + if (pSqlExpr->pLeft != NULL) { + int32_t ret = sqlExprToExprNode(&pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, pMsgBuf); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } } - } - if (pSqlExpr->pRight != NULL) { - int32_t ret = sqlExprToExprNode(&pRight, pSqlExpr->pRight, pQueryInfo, pCols, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - tExprTreeDestroy(pLeft, NULL); - return ret; + if (pSqlExpr->pRight != NULL) { + int32_t ret = sqlExprToExprNode(&pRight, pSqlExpr->pRight, pQueryInfo, pCols, pMsgBuf); + if (ret != TSDB_CODE_SUCCESS) { + tExprTreeDestroy(pLeft, NULL); + return ret; + } } - } - if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->tokenId == 0) { - *pExpr = calloc(1, sizeof(tExprNode)); - return TSDB_CODE_SUCCESS; - } + if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->tokenId == 0) { + *pExpr = calloc(1, sizeof(tExprNode)); + return TSDB_CODE_SUCCESS; + } + } else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { + SArray* pParamList = pSqlExpr->Expr.paramList; + + if (pParamList != NULL && taosArrayGetSize(pParamList) > 0) { + size_t num = taosArrayGetSize(pParamList); + + tExprNode** p = calloc(num, POINTER_BYTES); + pQueryInfo->exprListLevelIndex += 1; + + for(int32_t i = 0; i < num; ++i) { + tSqlExprItem* pItem = taosArrayGet(pParamList, i); + int32_t code = sqlExprToExprNode(&p[i], pItem->pNode, pQueryInfo, pCols, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + + pQueryInfo->exprListLevelIndex -= 1; + + bool scalar = false; + int32_t functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalar); + if (functionId < 0) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo); + + if (scalar) { + printf("scalar function found! %s\n", pSqlExpr->exprToken.z); + + // Expression on the results of aggregation functions + *pExpr = calloc(1, sizeof(tExprNode)); + (*pExpr)->nodeType = TEXPR_FUNCTION_NODE; + + (*pExpr)->_function.pChild = p; + (*pExpr)->_function.functionId = functionId; + (*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n + 1); + return TSDB_CODE_SUCCESS; + } else { + printf("agg function found, %s\n", pSqlExpr->exprToken.z); + tSqlExprItem item = {.pNode = (tSqlExpr*)pSqlExpr, .aliasName = NULL, .functionId = functionId}; + if (addAggExprAndResColumn(pQueryInfo, outputIndex, &item, false, pMsgBuf) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + // convert the aggregate function to be the input data columns for the outer function. + } + } + } if (pSqlExpr->pLeft == NULL) { // it is the leaf node assert(pSqlExpr->pRight == NULL); @@ -2856,12 +2922,13 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt strncpy((*pExpr)->pSchema->name, pSqlExpr->exprToken.z, pSqlExpr->exprToken.n); // set the input column data byte and type. - size_t size = taosArrayGetSize(pQueryInfo->exprList); + SArray* pExprList = getCurrentExprList(pQueryInfo); + size_t size = taosArrayGetSize(pExprList); bool found = false; uint64_t uid = 0; for (int32_t i = 0; i < size; ++i) { - SExprInfo* p1 = taosArrayGetP(pQueryInfo->exprList, i); + SExprInfo* p1 = taosArrayGetP(pExprList, i); if (strcmp((*pExpr)->pSchema->name, p1->base.resSchema.name) == 0) { memcpy((*pExpr)->pSchema, &p1->base.resSchema, sizeof(SSchema)); @@ -2982,9 +3049,9 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, int32_t arithmeticType = NON_ARITHMEIC_EXPR; SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); - if (validateComplexExpr(pItem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } +// if (validateComplexExpr(pItem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) { +// return buildInvalidOperationMsg(pMsgBuf, msg1); +// } if (arithmeticType == NORMAL_ARITHMETIC) { // expr string is set as the parameter of function @@ -2999,8 +3066,9 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, return buildInvalidOperationMsg(pMsgBuf, msg2); } - SExprInfo* pExpr = createBinaryExprInfo(pNode, &s); - addExprInfo(pQueryInfo, exprIndex, pExpr); + SExprInfo* pExpr = createBinaryExprInfo(pNode, &s); + SArray* pExprList = getCurrentExprList(pQueryInfo); + addExprInfo(pExprList, exprIndex, pExpr, pQueryInfo->exprListLevelIndex); setTokenAndResColumnName(pItem, pExpr->base.resSchema.name, pExpr->base.token, TSDB_COL_NAME_LEN); // check for if there is a tag in the arithmetic express @@ -3026,7 +3094,11 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, // set the serialized binary string as the parameter of arithmetic expression addExprInfoParam(&pExpr->base, c, TSDB_DATA_TYPE_BINARY, (int32_t)len); - addResColumnInfo(pQueryInfo, exprIndex, &pExpr->base.resSchema, pExpr); + + // Need to be added to the final result list. + if (pQueryInfo->exprListLevelIndex == 0) { + addResColumnInfo(pQueryInfo, exprIndex, &pExpr->base.resSchema, pExpr); + } tbufCloseWriter(&bw); taosArrayDestroy(colList); @@ -3043,8 +3115,9 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); } - SExprInfo* pExpr = createBinaryExprInfo(pNode, &s); - addExprInfo(pQueryInfo, exprIndex, pExpr); + SExprInfo* pExpr = createBinaryExprInfo(pNode, &s); + SArray* pExprList = getCurrentExprList(pQueryInfo); + addExprInfo(pExprList, exprIndex, pExpr, pQueryInfo->exprListLevelIndex); setTokenAndResColumnName(pItem, pExpr->base.resSchema.name, pExpr->base.token, TSDB_COL_NAME_LEN); @@ -3099,7 +3172,7 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, size_t numOfExpr = taosArrayGetSize(pSelNodeList); for (int32_t i = 0; i < numOfExpr; ++i) { - int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo); + int32_t outputIndex = (int32_t) getNumOfExprs(pQueryInfo); tSqlExprItem* pItem = taosArrayGet(pSelNodeList, i); int32_t type = pItem->pNode->type; @@ -3111,9 +3184,8 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, pQueryInfo->info.distinct = true; } - bool scalarFunc = false; - if (type == SQL_NODE_SQLFUNCTION) { + bool scalarFunc = false; pItem->functionId = qIsBuiltinFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &scalarFunc); if (pItem->functionId == FUNCTION_INVALID_ID) { int32_t functionId = FUNCTION_INVALID_ID; @@ -3123,15 +3195,17 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, } pItem->functionId = functionId; - } else if (scalarFunc) { - if ((code = createComplexExpr(pQueryInfo, i, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; - } } - // sql function in selection clause, append sql function info in pSqlCmd structure sequentially - if ((code = addExprAndResColumn(pQueryInfo, outputIndex, pItem, true, pMsgBuf)) != TSDB_CODE_SUCCESS) { - return code; + if (scalarFunc) { // scalar function + if ((code = createComplexExpr(pQueryInfo, outputIndex, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { + return code; + } + } else { // aggregate function + // sql function in selection clause, append sql function info in pSqlCmd structure sequentially + if ((code = addAggExprAndResColumn(pQueryInfo, outputIndex, pItem, true, pMsgBuf)) != TSDB_CODE_SUCCESS) { + return code; + } } } else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) { // use the dynamic array list to decide if the function is valid or not @@ -3654,7 +3728,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer validateSqlNode(p, pQueryInfo, &buf); } - SArray* functionList = extractFunctionIdList(pQueryInfo->exprList); + SArray* functionList = extractFunctionIdList(pQueryInfo->exprList[0]); extractFunctionDesc(functionList, &pQueryInfo->info); if ((code = checkForInvalidExpr(pQueryInfo, &buf)) != TSDB_CODE_SUCCESS) { diff --git a/source/libs/parser/src/queryInfoUtil.c b/source/libs/parser/src/queryInfoUtil.c index 98a800c3c6..df58651179 100644 --- a/source/libs/parser/src/queryInfoUtil.c +++ b/source/libs/parser/src/queryInfoUtil.c @@ -19,7 +19,7 @@ SSchema* getTbnameColumnSchema() { } size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo) { - return taosArrayGetSize(pQueryInfo->exprList); + return taosArrayGetSize(pQueryInfo->exprList[0]); } SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) { @@ -104,7 +104,6 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC if (pParamExpr != NULL) { pExpr->pExpr = createFunctionExprNode(functionId, NULL, pParamExpr, 1); -// pExpr->base.pColumns // todo set the correct number of columns } else if (pColIndex->columnIndex == TSDB_TBNAME_COLUMN_INDEX) { assert(pParamExpr == NULL); @@ -140,15 +139,17 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC return pExpr; } -void addExprInfo(SQueryStmtInfo* pQueryInfo, int32_t index, SExprInfo* pExprInfo) { - assert(pQueryInfo != NULL && pQueryInfo->exprList != NULL); +void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level) { + assert(pExprList != NULL ); - int32_t num = (int32_t) taosArrayGetSize(pQueryInfo->exprList); + int32_t num = (int32_t) taosArrayGetSize(pExprList); if (index == num) { - taosArrayPush(pQueryInfo->exprList, &pExprInfo); + taosArrayPush(pExprList, &pExprInfo); } else { - taosArrayInsert(pQueryInfo->exprList, index, &pExprInfo); + taosArrayInsert(pExprList, index, &pExprInfo); } + + printf("add function, id:%d, level:%d\n", pExprInfo->pExpr->_function.functionId, level); } void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize) { @@ -176,10 +177,10 @@ void destroyExprInfo(SExprInfo* pExprInfo) { tfree(pExprInfo); } -void dropAllExprInfo(SArray* pExprInfo) { +static void dropOneLevelExprInfo(SArray* pExprInfo) { size_t size = taosArrayGetSize(pExprInfo); - for(int32_t i = 0; i < size; ++i) { + for (int32_t i = 0; i < size; ++i) { SExprInfo* pExpr = taosArrayGetP(pExprInfo, i); destroyExprInfo(pExpr); } @@ -187,6 +188,12 @@ void dropAllExprInfo(SArray* pExprInfo) { taosArrayDestroy(pExprInfo); } +void dropAllExprInfo(SArray** pExprInfo, int32_t numOfLevel) { + for(int32_t i = 0; i < numOfLevel; ++i) { + dropOneLevelExprInfo(pExprInfo[i]); + } +} + void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes) { assert (pExpr != NULL || argument != NULL || bytes != 0); diff --git a/source/libs/parser/src/ttokenizer.c b/source/libs/parser/src/ttokenizer.c index b71fb4538e..683fe142ef 100644 --- a/source/libs/parser/src/ttokenizer.c +++ b/source/libs/parser/src/ttokenizer.c @@ -70,7 +70,7 @@ static SKeyword keywordTable[] = { {"STAR", TK_STAR}, {"SLASH", TK_SLASH}, {"REM ", TK_REM}, - {"CONCAT", TK_CONCAT}, + {"||", TK_CONCAT}, {"UMINUS", TK_UMINUS}, {"UPLUS", TK_UPLUS}, {"BITNOT", TK_BITNOT}, diff --git a/source/libs/parser/test/parserTests.cpp b/source/libs/parser/test/parserTests.cpp index 73c6b900f0..24b62d1313 100644 --- a/source/libs/parser/test/parserTests.cpp +++ b/source/libs/parser/test/parserTests.cpp @@ -46,7 +46,7 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) { SName* name = (SName*)taosArrayGet(req->pTableName, 0); memcpy(&pTableMetaInfo->name, taosArrayGet(req->pTableName, 0), sizeof(SName)); - pTableMetaInfo->pTableMeta = (STableMeta*)calloc(1, sizeof(STableMeta) + 4 * sizeof(SSchema)); + pTableMetaInfo->pTableMeta = (STableMeta*)calloc(1, sizeof(STableMeta) + 6 * sizeof(SSchema)); strcpy(pTableMetaInfo->aliasName, name->tname); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; pTableMeta->tableType = TSDB_NORMAL_TABLE; @@ -99,6 +99,7 @@ void sqlCheck(const char* sql, bool valid) { qParserClearupMetaRequestInfo(&req); destroySqlInfo(&info1); } + } //TEST(testCase, validateAST_test) { @@ -125,7 +126,7 @@ void sqlCheck(const char* sql, bool valid) { // SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); // ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); // -// SArray* pExprList = pQueryInfo->exprList; +// SArray* pExprList = pQueryInfo->exprList[0]; // ASSERT_EQ(taosArrayGetSize(pExprList), 3); // // SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); @@ -183,7 +184,7 @@ void sqlCheck(const char* sql, bool valid) { // SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); // ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); // -// SArray* pExprList = pQueryInfo->exprList; +// SArray* pExprList = pQueryInfo->exprList[0]; // ASSERT_EQ(taosArrayGetSize(pExprList), 1); // // SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); @@ -229,7 +230,7 @@ void sqlCheck(const char* sql, bool valid) { // SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); // ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); // -// SArray* pExprList = pQueryInfo->exprList; +// SArray* pExprList = pQueryInfo->exprList[0]; // ASSERT_EQ(taosArrayGetSize(pExprList), 1); // // SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); @@ -275,7 +276,7 @@ void sqlCheck(const char* sql, bool valid) { // SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); // ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); // -// SArray* pExprList = pQueryInfo->exprList; +// SArray* pExprList = pQueryInfo->exprList[0]; // ASSERT_EQ(taosArrayGetSize(pExprList), 4); // // SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); @@ -320,7 +321,7 @@ void sqlCheck(const char* sql, bool valid) { // SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); // ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); // -// SArray* pExprList = pQueryInfo->exprList; +// SArray* pExprList = pQueryInfo->exprList[0]; // ASSERT_EQ(taosArrayGetSize(pExprList), 1); // // SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); @@ -369,7 +370,7 @@ void sqlCheck(const char* sql, bool valid) { // ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); // ASSERT_EQ(ret, 0); // -// SArray* pExprList = pQueryInfo->exprList; +// SArray* pExprList = pQueryInfo->exprList[0]; // ASSERT_EQ(taosArrayGetSize(pExprList), 3); // // SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); @@ -395,236 +396,242 @@ void sqlCheck(const char* sql, bool valid) { TEST(testCase, function_Test10) { // sqlCheck("select c from `t.1abc`", true); // sqlCheck("select length(c) from `t.1abc`", true); - sqlCheck("select sum(length(a+b)) from `t.1abc`", false); +// sqlCheck("select sum(length(a+b)) from `t.1abc`", true); // sqlCheck("select sum(sum(a+b)) from `t.1abc`", false); +// sqlCheck("select sum(length(a) + length(b)) from `t.1abc`", true); +// sqlCheck("select length(sum(a) + sum(b)) + length(sum(a) + sum(b)) from `t.1abc`", true); +// sqlCheck("select sum(length(sum(a))) from `t.1abc`", true); + sqlCheck("select concat(a,b) from `t.1abc`", true); +// sqlCheck("select concat(concat(a,b), concat(a,b)) from `t.1abc`", true); +// sqlCheck("select length(length(length(a))) from `t.1abc`", true); } -TEST(testCase, function_Test6) { - SSqlInfo info1 = doGenerateAST("select sum(a+b) as a1, first(b*a), count(b+b), count(1), count(42.1) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SMetaReq req = {0}; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 5); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1"); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "sum(a+b)"); - ASSERT_EQ(p1->base.interBytes, 16); - ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); - ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_SUM); - ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); - - tExprNode* pParam = p1->pExpr->_node.pLeft; - - ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); - ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD); - ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE); - ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 5); - - SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p2->base.pColumns->uid, 110); - ASSERT_EQ(p2->base.numOfParams, 0); - ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p2->base.resSchema.name, "first(b*a)"); - ASSERT_EQ(p2->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p2->base.token, "first(b*a)"); - ASSERT_EQ(p2->base.interBytes, 24); - ASSERT_EQ(p2->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); - ASSERT_EQ(p2->pExpr->_function.functionId, FUNCTION_FIRST); - ASSERT_TRUE(p2->pExpr->_node.pRight == NULL); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test7) { - SSqlInfo info1 = doGenerateAST("select count(a+b),count(1) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SMetaReq req = {0}; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 2); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a+b)"); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "count(a+b)"); - ASSERT_EQ(p1->base.interBytes, 8); - ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); - ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_COUNT); - ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); - - tExprNode* pParam = p1->pExpr->_node.pLeft; - - ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); - ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD); - ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE); - ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test8) { - SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SMetaReq req = {0}; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 2); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 1); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)"); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)"); - ASSERT_EQ(p1->base.interBytes, 16); - - ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); - ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP); - ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); - - tExprNode* pParam = p1->pExpr->_node.pLeft; - - ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); - ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE); - ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE); - ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, invalid_sql_Test) { - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlInfo info1 = doGenerateAST("select count(k) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SMetaReq req = {0}; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_NE(ret, 0); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); -//=============================================================================================================== - info1 = doGenerateAST("select top(a*b, ABC) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); - code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_NE(ret, 0); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} \ No newline at end of file +//TEST(testCase, function_Test6) { +// SSqlInfo info1 = doGenerateAST("select sum(a+b) as a1, first(b*a), count(b+b), count(1), count(42.1) from `t.1abc` interval(10s, 1s)"); +// ASSERT_EQ(info1.valid, true); +// +// char msg[128] = {0}; +// SMsgBuf buf; +// buf.len = 128; +// buf.buf = msg; +// +// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); +// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); +// ASSERT_EQ(code, 0); +// +// SMetaReq req = {0}; +// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); +// ASSERT_EQ(ret, 0); +// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); +// +// SQueryStmtInfo* pQueryInfo = createQueryInfo(); +// setTableMetaInfo(pQueryInfo, &req); +// +// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); +// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); +// ASSERT_EQ(ret, 0); +// +// SArray* pExprList = pQueryInfo->exprList[0]; +// ASSERT_EQ(taosArrayGetSize(pExprList), 5); +// +// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); +// ASSERT_EQ(p1->base.pColumns->uid, 110); +// ASSERT_EQ(p1->base.numOfParams, 0); +// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); +// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1"); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "sum(a+b)"); +// ASSERT_EQ(p1->base.interBytes, 16); +// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); +// ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_SUM); +// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); +// +// tExprNode* pParam = p1->pExpr->_node.pLeft; +// +// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); +// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD); +// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE); +// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 5); +// +// SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1); +// ASSERT_EQ(p2->base.pColumns->uid, 110); +// ASSERT_EQ(p2->base.numOfParams, 0); +// ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); +// ASSERT_STRCASEEQ(p2->base.resSchema.name, "first(b*a)"); +// ASSERT_EQ(p2->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p2->base.token, "first(b*a)"); +// ASSERT_EQ(p2->base.interBytes, 24); +// ASSERT_EQ(p2->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); +// ASSERT_EQ(p2->pExpr->_function.functionId, FUNCTION_FIRST); +// ASSERT_TRUE(p2->pExpr->_node.pRight == NULL); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} +// +//TEST(testCase, function_Test7) { +// SSqlInfo info1 = doGenerateAST("select count(a+b),count(1) from `t.1abc` interval(10s, 1s)"); +// ASSERT_EQ(info1.valid, true); +// +// char msg[128] = {0}; +// SMsgBuf buf; +// buf.len = 128; +// buf.buf = msg; +// +// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); +// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); +// ASSERT_EQ(code, 0); +// +// SMetaReq req = {0}; +// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); +// ASSERT_EQ(ret, 0); +// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); +// +// SQueryStmtInfo* pQueryInfo = createQueryInfo(); +// setTableMetaInfo(pQueryInfo, &req); +// +// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); +// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); +// ASSERT_EQ(ret, 0); +// +// SArray* pExprList = pQueryInfo->exprList[0]; +// ASSERT_EQ(taosArrayGetSize(pExprList), 2); +// +// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); +// ASSERT_EQ(p1->base.pColumns->uid, 110); +// ASSERT_EQ(p1->base.numOfParams, 0); +// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT); +// ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a+b)"); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "count(a+b)"); +// ASSERT_EQ(p1->base.interBytes, 8); +// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); +// ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_COUNT); +// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); +// +// tExprNode* pParam = p1->pExpr->_node.pLeft; +// +// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); +// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD); +// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE); +// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} +// +//TEST(testCase, function_Test8) { +// SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"); +// ASSERT_EQ(info1.valid, true); +// +// char msg[128] = {0}; +// SMsgBuf buf; +// buf.len = 128; +// buf.buf = msg; +// +// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); +// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); +// ASSERT_EQ(code, 0); +// +// SMetaReq req = {0}; +// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); +// ASSERT_EQ(ret, 0); +// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); +// +// SQueryStmtInfo* pQueryInfo = createQueryInfo(); +// setTableMetaInfo(pQueryInfo, &req); +// +// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); +// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); +// ASSERT_EQ(ret, 0); +// +// SArray* pExprList = pQueryInfo->exprList[0]; +// ASSERT_EQ(taosArrayGetSize(pExprList), 2); +// +// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); +// ASSERT_EQ(p1->base.pColumns->uid, 110); +// ASSERT_EQ(p1->base.numOfParams, 1); +// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); +// ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)"); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)"); +// ASSERT_EQ(p1->base.interBytes, 16); +// +// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE); +// ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP); +// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); +// +// tExprNode* pParam = p1->pExpr->_node.pLeft; +// +// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); +// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE); +// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE); +// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} +// +//TEST(testCase, invalid_sql_Test) { +// char msg[128] = {0}; +// SMsgBuf buf; +// buf.len = 128; +// buf.buf = msg; +// +// SSqlInfo info1 = doGenerateAST("select count(k) from `t.1abc` interval(10s, 1s)"); +// ASSERT_EQ(info1.valid, true); +// +// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); +// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); +// ASSERT_EQ(code, 0); +// +// SMetaReq req = {0}; +// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); +// ASSERT_EQ(ret, 0); +// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); +// +// SQueryStmtInfo* pQueryInfo = createQueryInfo(); +// setTableMetaInfo(pQueryInfo, &req); +// +// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); +// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); +// ASSERT_NE(ret, 0); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +////=============================================================================================================== +// info1 = doGenerateAST("select top(a*b, ABC) from `t.1abc` interval(10s, 1s)"); +// ASSERT_EQ(info1.valid, true); +// +// pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); +// code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); +// ASSERT_EQ(code, 0); +// +// ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); +// ASSERT_EQ(ret, 0); +// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); +// +// pQueryInfo = createQueryInfo(); +// setTableMetaInfo(pQueryInfo, &req); +// +// pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); +// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); +// ASSERT_NE(ret, 0); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} \ No newline at end of file diff --git a/source/libs/parser/test/plannerTest.cpp b/source/libs/parser/test/plannerTest.cpp index c357d92b11..6e091bf8f4 100644 --- a/source/libs/parser/test/plannerTest.cpp +++ b/source/libs/parser/test/plannerTest.cpp @@ -66,65 +66,65 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) { } } -TEST(testCase, planner_test) { - SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"); - ASSERT_EQ(info1.valid, true); - - char msg[128] = {0}; - SMsgBuf buf; - buf.len = 128; - buf.buf = msg; - - SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); - int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); - ASSERT_EQ(code, 0); - - SMetaReq req = {0}; - int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); - ASSERT_EQ(ret, 0); - ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); - - SQueryStmtInfo* pQueryInfo = createQueryInfo(); - setTableMetaInfo(pQueryInfo, &req); - - SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); - ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - ASSERT_EQ(ret, 0); - - SArray* pExprList = pQueryInfo->exprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 2); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p1->base.pColumns->uid, 110); - ASSERT_EQ(p1->base.numOfParams, 1); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)"); - ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)"); - ASSERT_EQ(p1->base.interBytes, 16); - - ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE); - ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP); - ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); - - tExprNode* pParam = p1->pExpr->_node.pLeft; - - ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); - ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE); - ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE); - ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); - - struct SQueryPlanNode* n = nullptr; - code = qCreateQueryPlan(pQueryInfo, &n); - - char* str = NULL; - qQueryPlanToString(n, &str); - printf("%s\n", str); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} \ No newline at end of file +//TEST(testCase, planner_test) { +// SSqlInfo info1 = doGenerateAST("select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"); +// ASSERT_EQ(info1.valid, true); +// +// char msg[128] = {0}; +// SMsgBuf buf; +// buf.len = 128; +// buf.buf = msg; +// +// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0); +// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf); +// ASSERT_EQ(code, 0); +// +// SMetaReq req = {0}; +// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128); +// ASSERT_EQ(ret, 0); +// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1); +// +// SQueryStmtInfo* pQueryInfo = createQueryInfo(); +// setTableMetaInfo(pQueryInfo, &req); +// +// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); +// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); +// ASSERT_EQ(ret, 0); +// +// SArray* pExprList = pQueryInfo->exprList[0]; +// ASSERT_EQ(taosArrayGetSize(pExprList), 2); +// +// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); +// ASSERT_EQ(p1->base.pColumns->uid, 110); +// ASSERT_EQ(p1->base.numOfParams, 1); +// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); +// ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)"); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)"); +// ASSERT_EQ(p1->base.interBytes, 16); +// +// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_FUNCTION_NODE); +// ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP); +// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); +// +// tExprNode* pParam = p1->pExpr->_node.pLeft; +// +// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE); +// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE); +// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE); +// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); +// +// struct SQueryPlanNode* n = nullptr; +// code = qCreateQueryPlan(pQueryInfo, &n); +// +// char* str = NULL; +// qQueryPlanToString(n, &str); +// printf("%s\n", str); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} \ No newline at end of file diff --git a/source/libs/planner/src/planner.c b/source/libs/planner/src/planner.c index 25e63507c2..53631fc9f1 100644 --- a/source/libs/planner/src/planner.c +++ b/source/libs/planner/src/planner.c @@ -226,9 +226,9 @@ static SQueryPlanNode* doCreateQueryPlanForOneTableImpl(SQueryStmtInfo* pQueryIn } if (pQueryInfo->havingFieldNum > 0 || pQueryInfo->info.arithmeticOnAgg) { - int32_t numOfExpr = (int32_t)taosArrayGetSize(pQueryInfo->exprList1); - pNode = - createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pQueryInfo->exprList1->pData, numOfExpr, info, NULL); +// int32_t numOfExpr = (int32_t)taosArrayGetSize(pQueryInfo->exprList1); +// pNode = +// createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pQueryInfo->exprList1->pData, numOfExpr, info, NULL); } if (pQueryInfo->fillType != TSDB_FILL_NONE) { @@ -292,7 +292,7 @@ SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) { SArray* exprList = taosArrayInit(4, POINTER_BYTES); if (copyExprInfoList(exprList, pQueryInfo->exprList, uid, true) != 0) { terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; - dropAllExprInfo(exprList); +// dropAllExprInfo(exprList); exit(-1); } @@ -308,7 +308,7 @@ SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) { // 4. add the projection query node SQueryPlanNode* pNode = doAddTableColumnNode(pQueryInfo, pTableMetaInfo, &info, exprList, tableColumnList); columnListDestroy(tableColumnList); - dropAllExprInfo(exprList); +// dropAllExprInfo(exprList); taosArrayPush(upstream, &pNode); } @@ -316,7 +316,7 @@ SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) { SQueryTableInfo info = {0}; int32_t num = (int32_t) taosArrayGetSize(pQueryInfo->exprList); SQueryPlanNode* pNode = createQueryNode(QNODE_JOIN, "Join", upstream->pData, pQueryInfo->numOfTables, - pQueryInfo->exprList->pData, num, &info, NULL); + pQueryInfo->exprList[0]->pData, num, &info, NULL); // 4. add the aggregation or projection execution node pNode = doCreateQueryPlanForOneTableImpl(pQueryInfo, pNode, &info, pQueryInfo->exprList); @@ -338,7 +338,7 @@ static void doDestroyQueryNode(SQueryPlanNode* pQueryNode) { tfree(pQueryNode->info.name); tfree(pQueryNode->tableInfo.tableName); - dropAllExprInfo(pQueryNode->pExpr); +// dropAllExprInfo(pQueryNode->pExpr); if (pQueryNode->pPrevNodes != NULL) { int32_t size = (int32_t) taosArrayGetSize(pQueryNode->pPrevNodes);