diff --git a/include/common/common.h b/include/common/common.h index bcb48d2ce2ee383ae71db28cc871b7306eef35a9..8f9b595d7aae9e347432b9ee20e27f4c8ca9836b 100644 --- a/include/common/common.h +++ b/include/common/common.h @@ -68,6 +68,13 @@ typedef struct SColumnInfoData { //====================================================================================================================== // the following structure shared by parser and executor +typedef struct SColumn { + uint64_t uid; + char name[TSDB_COL_NAME_LEN]; + int8_t flag; // column type: normal column, tag, or user-input column (integer/float/string) + SColumnInfo info; +} SColumn; + typedef struct SLimit { int64_t limit; int64_t offset; @@ -89,8 +96,9 @@ typedef struct SGroupbyExpr { typedef struct SSqlExpr { char token[TSDB_COL_NAME_LEN]; // original token SSchema resSchema; - SColIndex colInfo; // there may be mutiple input columns - uint64_t uid; // table uid, todo refactor use the pointer + + int32_t numOfCols; + SColumn* pColumns; // data columns that are required by query int32_t interBytes; // inter result buffer size int16_t numOfParams; // argument value of each function SVariant param[3]; // parameters are not more than 3 diff --git a/include/libs/function/function.h b/include/libs/function/function.h index 3f5422824ad47f40a2489efee03620f61c328e38..1bc0128dbed1e185d11039feee0210562c4ed224 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -161,6 +161,7 @@ enum { TEXPR_NODE_DUMMY = 0x0, TEXPR_BINARYEXPR_NODE= 0x1, TEXPR_UNARYEXPR_NODE = 0x2, + TEXPR_FUNCTION_NODE = 0x3, TEXPR_COL_NODE = 0x4, TEXPR_VALUE_NODE = 0x8, }; @@ -169,10 +170,7 @@ typedef struct tExprNode { uint8_t nodeType; union { struct { - union { - int32_t optr; // binary operator - int32_t functionId;// unary operator - }; + int32_t optr; // binary operator void *info; // support filter operation on this expression only available for leaf node struct tExprNode *pLeft; // left child pointer struct tExprNode *pRight; // right child pointer @@ -180,18 +178,32 @@ typedef struct tExprNode { SSchema *pSchema;// column node struct SVariant *pVal; // value node + + struct {// function node + char *functionName; + int32_t functionId; + int32_t num; + + // Note that the attribute of pChild is not the parameter of function, it is the columns that involved in the + // calculation instead. + // E.g., Cov(col1, col2), the column information, w.r.t. the col1 and col2, is kept in pChild nodes. + // The concat function, concat(col1, col2), is a binary scalar + // operator and is kept in the attribute of _node. + struct tExprNode **pChild; + } _function; }; } tExprNode; +//TODO create? void exprTreeToBinary(SBufferWriter* bw, tExprNode* pExprTree); void tExprTreeDestroy(tExprNode *pNode, void (*fp)(void *)); typedef struct SAggFunctionInfo { - char name[FUNCTIONS_NAME_MAX_LENGTH]; - int8_t type; // Scalar function or aggregation function - uint8_t functionId; // Function Id - int8_t sFunctionId; // Transfer function for super table query - uint16_t status; + char name[FUNCTIONS_NAME_MAX_LENGTH]; + int8_t type; // Scalar function or aggregation function + uint32_t functionId; // Function Id + int8_t sFunctionId; // Transfer function for super table query + uint16_t status; bool (*init)(SQLFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); // setup the execute environment void (*addInput)(SQLFunctionCtx *pCtx); @@ -203,13 +215,13 @@ typedef struct SAggFunctionInfo { int32_t (*dataReqFunc)(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId); } SAggFunctionInfo; -typedef struct SScalarFunctionInfo { - char name[FUNCTIONS_NAME_MAX_LENGTH]; - int8_t type; // scalar function or aggregation function - uint8_t functionId; // index of scalar function +struct SScalarFuncParam; - bool (*init)(SQLFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); // setup the execute environment - void (*addInput)(SQLFunctionCtx *pCtx); +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); } SScalarFunctionInfo; typedef struct SMultiFunctionsDesc { @@ -241,7 +253,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI * @param len * @return */ -int32_t qIsBuiltinFunction(const char* name, int32_t len); +int32_t qIsBuiltinFunction(const char* name, int32_t len, bool* scalarFunction); bool qIsValidUdf(SArray* pUdfInfo, const char* name, int32_t len, int32_t* functionId); diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index ff28a032609f37fd5accfde65753f9a47a0a7386..f79ad35862a3cd0d876554576e16eee6fe352be0 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -26,29 +26,6 @@ extern "C" { #include "tvariant.h" #include "function.h" -typedef struct SColumn { - uint64_t tableUid; - int32_t columnIndex; - SColumnInfo info; -} SColumn; - - - -//typedef struct SInterval { -// int32_t tz; // query client timezone -// char intervalUnit; -// char slidingUnit; -// char offsetUnit; -// int64_t interval; -// int64_t sliding; -// int64_t offset; -//} SInterval; -// -//typedef struct SSessionWindow { -// int64_t gap; // gap between two session window(in microseconds) -// int32_t primaryColId; // primary timestamp column -//} SSessionWindow; - typedef struct SField { char name[TSDB_COL_NAME_LEN]; uint8_t type; @@ -89,12 +66,6 @@ typedef struct STagCond { typedef struct STableMetaInfo { STableMeta *pTableMeta; // table meta, cached in client side and acquired by name SVgroupsInfo *vgroupList; - - /* - * 1. keep the vgroup index during the multi-vnode super table projection query - * 2. keep the vgroup index for multi-vnode insertion - */ - int32_t vgroupIndex; SName name; char aliasName[TSDB_TABLE_NAME_LEN]; // alias name of table specified in query sql SArray *tagColList; // SArray, involved tag columns diff --git a/include/util/tdef.h b/include/util/tdef.h index c7a421a55fae36f14fe801ea5dc17be67e4a2e36..652d329cd34cac8093fd38e2d5c003729cf90127 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -134,14 +134,14 @@ do { \ #define TSDB_BINARY_OP_REMAINDER 4004 #define TSDB_BINARY_OP_CONCAT 4005 -#define TSDB_UNARY_OP_CEIL 4500 -#define TSDB_UNARY_OP_FLOOR 4501 -#define TSDB_UNARY_OP_ABS 4502 -#define TSDB_UNARY_OP_ROUND 4503 - -#define TSDB_UNARY_OP_LEN 4600 -#define TSDB_UNARY_OP_LTRIM 4601 -#define TSDB_UNARY_OP_RTRIM 4601 +#define FUNCTION_CEIL 4500 +#define FUNCTION_FLOOR 4501 +#define FUNCTION_ABS 4502 +#define FUNCTION_ROUND 4503 + +#define FUNCTION_LENGTH 4800 +#define FUNCTION_LTRIM 4801 +#define FUNCTION_RTRIM 4802 #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 9b3cbcf9cca45c8ecc417db16626e1b169d39838..aa7ea484328546a6ae4b83aee6214d9d34f8dfbd 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -1040,13 +1040,14 @@ static TSKEY getStartTsKey(SQueryAttr* pQueryAttr, STimeWindow* win, const TSKEY } static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order); + static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { for (int32_t i = 0; i < pOperator->numOfOutput; ++i) { pCtx[i].order = order; pCtx[i].size = pBlock->info.rows; pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag; - setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo); + setBlockStatisInfo(&pCtx[i], pBlock, NULL/*&pOperator->pExpr[i].base.colInfo*/); } } @@ -2358,8 +2359,8 @@ bool onlyQueryTags(SQueryAttr* pQueryAttr) { if (functionId != FUNCTION_TAGPRJ && functionId != FUNCTION_TID_TAG && - (!(functionId == FUNCTION_COUNT && pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX)) && - (!(functionId == FUNCTION_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.colInfo.flag)))) { + (!(functionId == FUNCTION_COUNT && pExprInfo->base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX)) && + (!(functionId == FUNCTION_PRJ && TSDB_COL_IS_UD_COL(pExprInfo->base.pColumns->flag)))) { return false; } } @@ -2878,7 +2879,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.colInfo.colId; + int32_t colId = pTableScanInfo->pExpr[i].base.pColumns->colId; // group by + first/last should not apply the first/last block filter if (functionId < 0) { @@ -3205,12 +3206,12 @@ void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCt SExprInfo* pLocalExprInfo = &pExpr[idx]; // ts_comp column required the tag value for join filter - if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.colInfo.flag)) { + if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.pColumns->flag)) { continue; } // todo use tag column index to optimize performance - doSetTagValueInParam(pTable, pLocalExprInfo->base.colInfo.colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type, + doSetTagValueInParam(pTable, pLocalExprInfo->base.pColumns->colId, &pCtx[idx].tag, pLocalExprInfo->base.resSchema.type, pLocalExprInfo->base.resSchema.bytes); if (IS_NUMERIC_TYPE(pLocalExprInfo->base.resSchema.type) @@ -5071,7 +5072,7 @@ SArray* getResultGroupCheckColumns(SQueryAttr* pQuery) { int32_t functionId = getExprFunctionId(&pQuery->pExpr1[j]); // FUNCTION_TAG_DUMMY function needs to be ignored - if (index->colId == pExpr->colInfo.colId && + 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))) { index->colIndex = j; @@ -5290,7 +5291,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.colInfo.colId; + col.info.colId = pExpr[i].base.pColumns->colId; // col.info.bytes = pExpr[i].base.colBytes; // col.info.type = pExpr[i].base.colType; taosArrayPush(pDataBlock->pDataBlock, &col); @@ -6776,7 +6777,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.colInfo.colId) { + if (pQueryAttr->tagColList[i].colId == pExprInfo->base.pColumns->colId) { bytes = pQueryAttr->tagColList[i].bytes; type = pQueryAttr->tagColList[i].type; break; @@ -6808,10 +6809,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { output += sizeof(pQueryAttr->vgId); char* data = NULL; - if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { + if (pExprInfo->base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX) { data = tsdbGetTableName(item->pTable); } else { - data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.colInfo.colId, type, bytes); + data = tsdbGetTableTagVal(item->pTable, pExprInfo->base.pColumns->colId, type, bytes); } doSetTagValueToResultBuf(output, data, type, bytes); @@ -6839,7 +6840,7 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { int16_t type = 0, bytes = 0; for(int32_t j = 0; j < pOperator->numOfOutput; ++j) { // not assign value in case of user defined constant output column - if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.colInfo.flag)) { + if (TSDB_COL_IS_UD_COL(pExprInfo[j].base.pColumns->flag)) { continue; } @@ -6847,10 +6848,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { type = pExprInfo[j].base.resSchema.type; bytes = pExprInfo[j].base.resSchema.bytes; - if (pExprInfo[j].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) { + if (pExprInfo[j].base.pColumns->colId == TSDB_TBNAME_COLUMN_INDEX) { data = tsdbGetTableName(item->pTable); } else { - data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.colInfo.colId, type, bytes); + data = tsdbGetTableTagVal(item->pTable, pExprInfo[j].base.pColumns->colId, type, bytes); } dst = pColInfo->pData + count * pExprInfo[j].base.resSchema.bytes; @@ -7310,9 +7311,9 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { for (int32_t i = 0; i < pQueryMsg->numOfOutput; ++i) { param->pExpr[i] = pExprMsg; - pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex); - pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId); - pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag); +// pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex); +// pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId); +// pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag); // pExprMsg->colBytes = htons(pExprMsg->colBytes); // pExprMsg->colType = htons(pExprMsg->colType); @@ -7361,9 +7362,9 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { for (int32_t i = 0; i < pQueryMsg->secondStageOutput; ++i) { param->pSecExpr[i] = pExprMsg; - pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex); - pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId); - pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag); +// pExprMsg->colInfo.colIndex = htons(pExprMsg->colInfo.colIndex); +// pExprMsg->colInfo.colId = htons(pExprMsg->colInfo.colId); +// pExprMsg->colInfo.flag = htons(pExprMsg->colInfo.flag); // pExprMsg->resType = htons(pExprMsg->resType); // pExprMsg->resBytes = htons(pExprMsg->resBytes); // pExprMsg->colBytes = htons(pExprMsg->colBytes); @@ -7677,11 +7678,11 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp SSchema s = {.type=TSDB_DATA_TYPE_BINARY, .bytes=TSDB_MAX_BINARY_LEN}; type = s.type; bytes = s.bytes; - } else if (pExprs[i].base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX && functionId == FUNCTION_TAGPRJ) { // parse the normal column + } else if (pExprs[i].base.pColumns->info.colId == TSDB_TBNAME_COLUMN_INDEX && functionId == FUNCTION_TAGPRJ) { // parse the normal column SSchema* s = tGetTbnameColumnSchema(); type = s->type; bytes = s->bytes; - } else if (pExprs[i].base.colInfo.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.colInfo.colId > TSDB_RES_COL_ID) { + } else if (pExprs[i].base.pColumns->info.colId <= TSDB_UD_COLUMN_INDEX && pExprs[i].base.pColumns->info.colId > TSDB_RES_COL_ID) { // it is a user-defined constant value column assert(functionId == FUNCTION_PRJ); @@ -7692,7 +7693,7 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp } } else { int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols); - if (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag)) { + if (TSDB_COL_IS_TAG(pExprs[i].base.pColumns->flag)) { if (j < TSDB_TBNAME_COLUMN_INDEX || j >= pTableInfo->numOfTags) { tfree(pExprs); return TSDB_CODE_QRY_INVALID_MSG; @@ -7704,8 +7705,8 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp } } - if (pExprs[i].base.colInfo.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) { - SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.colInfo.flag))? &pTagCols[j]:&pTableInfo->colList[j]; + if (pExprs[i].base.pColumns->info.colId != TSDB_TBNAME_COLUMN_INDEX && j >= 0) { + SColumnInfo* pCol = (TSDB_COL_IS_TAG(pExprs[i].base.pColumns->flag))? &pTagCols[j]:&pTableInfo->colList[j]; type = pCol->type; bytes = pCol->bytes; } else { @@ -7814,7 +7815,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.colInfo.colId); +// assert(prevExpr[index].base.resSchema.colId == pExprs[i].base.pColumns->colId); // // type = prevExpr[index].base.resSchema.type; // bytes = prevExpr[index].base.resSchema.bytes; @@ -8083,7 +8084,7 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S pQueryAttr->resultRowSize += pExprs[col].base.resSchema.bytes; // keep the tag length - if (TSDB_COL_IS_TAG(pExprs[col].base.colInfo.flag)) { + if (TSDB_COL_IS_TAG(pExprs[col].base.pColumns->flag)) { pQueryAttr->tagLen += pExprs[col].base.resSchema.bytes; } diff --git a/source/libs/function/inc/tscalarfunction.h b/source/libs/function/inc/tscalarfunction.h index d8e4c1eeaf46986d35def147dffeb00548c9045e..ddb56518e0f635c847d1f9393f2d7e49185b4dda 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[1]; +extern struct SScalarFunctionInfo scalarFunc[5]; 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/tfill.c b/source/libs/function/src/tfill.c index aac4eb1f6d5eb97c1860908909441eac4ea6988a..aa10523dea9da145c0b0737189b276d646df0747 100644 --- a/source/libs/function/src/tfill.c +++ b/source/libs/function/src/tfill.c @@ -543,8 +543,8 @@ struct SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, co pFillCol[i].col.offset = offset; pFillCol[i].col.colId = pExprInfo->base.resSchema.colId; pFillCol[i].tagIndex = -2; - pFillCol[i].flag = pExprInfo->base.colInfo.flag; // always be the normal column for table query - pFillCol[i].functionId = pExprInfo->pExpr->_node.functionId; + pFillCol[i].flag = pExprInfo->base.pColumns->flag; // always be the normal column for table query + pFillCol[i].functionId = pExprInfo->pExpr->_function.functionId; pFillCol[i].fillVal.i = fillVal[i]; offset += pExprInfo->base.resSchema.bytes; diff --git a/source/libs/function/src/tfunction.c b/source/libs/function/src/tfunction.c index e9a59f7d690b73f86cd1fe02e2efb25669701003..c47f3a249a1e28480a301e5e5c9b120b2a0b2033 100644 --- a/source/libs/function/src/tfunction.c +++ b/source/libs/function/src/tfunction.c @@ -30,11 +30,12 @@ static void doInitFunctionHashTable() { static pthread_once_t functionHashTableInit = PTHREAD_ONCE_INIT; -int32_t qIsBuiltinFunction(const char* name, int32_t len) { +int32_t qIsBuiltinFunction(const char* name, int32_t len, bool* scalarFunction) { pthread_once(&functionHashTableInit, doInitFunctionHashTable); SAggFunctionInfo** pInfo = taosHashGet(functionHashTable, name, len); if (pInfo != NULL) { + *scalarFunction = ((*pInfo)->type == FUNCTION_TYPE_SCALAR); return (*pInfo)->functionId; } else { return -1; diff --git a/source/libs/function/src/tscalarfunction.c b/source/libs/function/src/tscalarfunction.c index 8c9d670e874445ea7b7c716be3085f093c64fd9a..80d426f101ba83d6f7d2eda7f806256b13a2ae0c 100644 --- a/source/libs/function/src/tscalarfunction.c +++ b/source/libs/function/src/tscalarfunction.c @@ -2,6 +2,156 @@ #include "tbinoperator.h" #include "tunaryoperator.h" + +static void assignBasicParaInfo(struct SScalarFuncParam* dst, const struct SScalarFuncParam* src) { + dst->type = src->type; + dst->bytes = src->bytes; + dst->num = src->num; +} + +static void tceil(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { + assignBasicParaInfo(pOutput, pLeft); + + switch (pLeft->bytes) { + case TSDB_DATA_TYPE_FLOAT: { + float* p = (float*) pLeft->data; + float* out = (float*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = ceilf(p[i]); + } + } + + case TSDB_DATA_TYPE_DOUBLE: { + double* p = (double*) pLeft->data; + double* out = (double*)pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = ceil(p[i]); + } + } + + default: + memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes); + } +} + +static void tfloor(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { + assignBasicParaInfo(pOutput, pLeft); + + switch (pLeft->bytes) { + case TSDB_DATA_TYPE_FLOAT: { + float* p = (float*) pLeft->data; + float* out = (float*) pOutput->data; + + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = floorf(p[i]); + } + } + + case TSDB_DATA_TYPE_DOUBLE: { + double* p = (double*) pLeft->data; + double* out = (double*) pOutput->data; + + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = floor(p[i]); + } + } + + default: + memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes); + } +} + +static void _tabs(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { + assignBasicParaInfo(pOutput, pLeft); + + switch (pLeft->bytes) { + case TSDB_DATA_TYPE_FLOAT: { + float* p = (float*) pLeft->data; + float* out = (float*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = (p[i] > 0)? p[i]:-p[i]; + } + } + + case TSDB_DATA_TYPE_DOUBLE: { + double* p = (double*) pLeft->data; + double* out = (double*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = (p[i] > 0)? p[i]:-p[i]; + } + } + + case TSDB_DATA_TYPE_TINYINT: { + int8_t* p = (int8_t*) pLeft->data; + int8_t* out = (int8_t*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = (p[i] > 0)? p[i]:-p[i]; + } + } + + case TSDB_DATA_TYPE_SMALLINT: { + int16_t* p = (int16_t*) pLeft->data; + int16_t* out = (int16_t*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = (p[i] > 0)? p[i]:-p[i]; + } + } + + case TSDB_DATA_TYPE_INT: { + int32_t* p = (int32_t*) pLeft->data; + int32_t* out = (int32_t*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = (p[i] > 0)? p[i]:-p[i]; + } + } + + case TSDB_DATA_TYPE_BIGINT: { + int64_t* p = (int64_t*) pLeft->data; + int64_t* out = (int64_t*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = (p[i] > 0)? p[i]:-p[i]; + } + } + + default: + memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes); + } +} + +static void tround(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { + assignBasicParaInfo(pOutput, pLeft); + + switch (pLeft->bytes) { + case TSDB_DATA_TYPE_FLOAT: { + float* p = (float*) pLeft->data; + float* out = (float*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = roundf(p[i]); + } + } + + case TSDB_DATA_TYPE_DOUBLE: { + double* p = (double*) pLeft->data; + double* out = (double*) pOutput->data; + for (int32_t i = 0; i < pLeft->num; ++i) { + out[i] = round(p[i]); + } + } + + default: + memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes); + } +} + +static void tlength(const SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { + int64_t* out = (int64_t*) pOutput->data; + char* s = pLeft->data; + + for(int32_t i = 0; i < pLeft->num; ++i) { + out[i] = varDataLen(POINTER_SHIFT(s, i * pLeft->bytes)); + } +} + static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOfRows) { switch(type) { case TSDB_DATA_TYPE_TINYINT: @@ -168,11 +318,12 @@ int32_t evaluateExprNodeTree(tExprNode* pExprs, int32_t numOfRows, SScalarFuncPa return 0; } -SScalarFunctionInfo scalarFunc[1] = { - { - - }, - +SScalarFunctionInfo scalarFunc[5] = { + {"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}, }; void setScalarFunctionSupp(struct SScalarFunctionSupport* sas, SExprInfo *pExprInfo, SSDataBlock* pSDataBlock) { diff --git a/source/libs/function/src/tunaryoperator.c b/source/libs/function/src/tunaryoperator.c index 9105942d26bd2d4a9a9e271cc175f37b8496b1e5..9651f98d087a673fe98b0dc7be53d96a581b0428 100644 --- a/source/libs/function/src/tunaryoperator.c +++ b/source/libs/function/src/tunaryoperator.c @@ -1,171 +1,13 @@ #include "tunaryoperator.h" -static void assignBasicParaInfo(struct SScalarFuncParam* dst, const struct SScalarFuncParam* src) { - dst->type = src->type; - dst->bytes = src->bytes; - dst->num = src->num; -} - -static void tceil(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { - assignBasicParaInfo(pOutput, pLeft); - - switch (pLeft->bytes) { - case TSDB_DATA_TYPE_FLOAT: { - float* p = (float*) pLeft->data; - float* out = (float*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = ceilf(p[i]); - } - } - - case TSDB_DATA_TYPE_DOUBLE: { - double* p = (double*) pLeft->data; - double* out = (double*)pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = ceil(p[i]); - } - } - - default: - memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes); - } -} - -static void tfloor(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { - assignBasicParaInfo(pOutput, pLeft); - - switch (pLeft->bytes) { - case TSDB_DATA_TYPE_FLOAT: { - float* p = (float*) pLeft->data; - float* out = (float*) pOutput->data; - - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = floorf(p[i]); - } - } - - case TSDB_DATA_TYPE_DOUBLE: { - double* p = (double*) pLeft->data; - double* out = (double*) pOutput->data; - - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = floor(p[i]); - } - } - - default: - memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes); - } -} - -static void _tabs(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { - assignBasicParaInfo(pOutput, pLeft); - switch (pLeft->bytes) { - case TSDB_DATA_TYPE_FLOAT: { - float* p = (float*) pLeft->data; - float* out = (float*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = (p[i] > 0)? p[i]:-p[i]; - } - } - case TSDB_DATA_TYPE_DOUBLE: { - double* p = (double*) pLeft->data; - double* out = (double*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = (p[i] > 0)? p[i]:-p[i]; - } - } - - case TSDB_DATA_TYPE_TINYINT: { - int8_t* p = (int8_t*) pLeft->data; - int8_t* out = (int8_t*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = (p[i] > 0)? p[i]:-p[i]; - } - } - - case TSDB_DATA_TYPE_SMALLINT: { - int16_t* p = (int16_t*) pLeft->data; - int16_t* out = (int16_t*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = (p[i] > 0)? p[i]:-p[i]; - } - } - - case TSDB_DATA_TYPE_INT: { - int32_t* p = (int32_t*) pLeft->data; - int32_t* out = (int32_t*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = (p[i] > 0)? p[i]:-p[i]; - } - } - - case TSDB_DATA_TYPE_BIGINT: { - int64_t* p = (int64_t*) pLeft->data; - int64_t* out = (int64_t*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = (p[i] > 0)? p[i]:-p[i]; - } - } - - default: - memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes); - } -} - -static void tround(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { - assignBasicParaInfo(pOutput, pLeft); - - switch (pLeft->bytes) { - case TSDB_DATA_TYPE_FLOAT: { - float* p = (float*) pLeft->data; - float* out = (float*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = roundf(p[i]); - } - } - - case TSDB_DATA_TYPE_DOUBLE: { - double* p = (double*) pLeft->data; - double* out = (double*) pOutput->data; - for (int32_t i = 0; i < pLeft->num; ++i) { - out[i] = round(p[i]); - } - } - - default: - memcpy(pOutput->data, pLeft->data, pLeft->num* pLeft->bytes); - } -} - -static void tlen(SScalarFuncParam *pLeft, SScalarFuncParam* pOutput) { - int64_t* out = (int64_t*) pOutput->data; - char* s = pLeft->data; - - for(int32_t i = 0; i < pLeft->num; ++i) { - out[i] = varDataLen(POINTER_SHIFT(s, i * pLeft->bytes)); - } -} +// TODO dynamic define these functions _unary_scalar_fn_t getUnaryScalarOperatorFn(int32_t operator) { - switch(operator) { - case TSDB_UNARY_OP_CEIL: - return tceil; - case TSDB_UNARY_OP_FLOOR: - return tfloor; - case TSDB_UNARY_OP_ROUND: - return tround; - case TSDB_UNARY_OP_ABS: - return _tabs; - case TSDB_UNARY_OP_LEN: - return tlen; - default: - assert(0); - } + assert(0); } bool isStringOperatorFn(int32_t op) { - return op == TSDB_UNARY_OP_LEN; + return op == FUNCTION_LENGTH; } diff --git a/source/libs/parser/inc/parserUtil.h b/source/libs/parser/inc/parserUtil.h index 922b9c2d4431ad751d9ebbe1b0f9cf778899e5a7..0f5acf5bccab7b4eaba99c9eb57fd8090713bae3 100644 --- a/source/libs/parser/inc/parserUtil.h +++ b/source/libs/parser/inc/parserUtil.h @@ -38,6 +38,7 @@ extern "C" { TAOS_FIELD createField(const SSchema* pSchema); SSchema createSchema(uint8_t type, int16_t bytes, int16_t colId, const char* name); +void setColumn(SColumn* pColumn, uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema); SInternalField* insertFieldInfo(SFieldInfo* pFieldInfo, int32_t index, SSchema* field); int32_t getNumOfFields(SFieldInfo* pFieldInfo); @@ -51,7 +52,7 @@ STableMetaInfo* addEmptyMetaInfo(SQueryStmtInfo* pQueryInfo); void columnListCopyAll(SArray* dst, const SArray* src); -SColumn* columnListInsert(SArray* pColumnList, int32_t columnIndex, uint64_t uid, SSchema* pSchema); +SColumn* columnListInsert(SArray* pColumnList, uint64_t uid, SSchema* pSchema, int32_t flag); SColumn* insertPrimaryTsColumn(SArray* pColumnList, uint64_t tableUid); void cleanupTagCond(STagCond* pTagCond); diff --git a/source/libs/parser/src/astValidate.c b/source/libs/parser/src/astValidate.c index 26ab04cb85469204501d741e52cc38198b423461..c25e647b48c032d0d67cc6628ac12d2482a75af8 100644 --- a/source/libs/parser/src/astValidate.c +++ b/source/libs/parser/src/astValidate.c @@ -327,7 +327,7 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SQueryStmtI int32_t startOffset = (int32_t) taosArrayGetSize(pQueryInfo->colList); for(int32_t i = 0; i < pMeta->tableInfo.numOfColumns; ++i) { - columnListInsert(pQueryInfo->colList, i + startOffset, pMeta->uid, &pMeta->schema[i]); + columnListInsert(pQueryInfo->colList, pMeta->uid, &pMeta->schema[i], TSDB_COL_NORMAL); } return TSDB_CODE_SUCCESS; @@ -556,14 +556,14 @@ int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf* taosArrayPush(pGroupExpr->columnInfo, &colIndex); index.columnIndex = relIndex; - columnListInsert(pTableMetaInfo->tagColList, index.columnIndex, pTableMeta->uid, pSchema); + columnListInsert(pTableMetaInfo->tagColList, pTableMeta->uid, pSchema, colIndex.flag); } else { // check if the column type is valid, here only support the bool/tinyint/smallint/bigint group by if (pSchema->type == TSDB_DATA_TYPE_FLOAT || pSchema->type == TSDB_DATA_TYPE_DOUBLE) { return buildInvalidOperationMsg(pMsgBuf, msg5); } - columnListInsert(pQueryInfo->colList, index.columnIndex, pTableMeta->uid, pSchema); + columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, TSDB_COL_NORMAL); SColIndex colIndex = { .colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId }; strncpy(colIndex.name, pSchema->name, tListLen(colIndex.name)); @@ -854,7 +854,7 @@ int32_t validateStateWindowNode(SQueryStmtInfo *pQueryInfo, SWindowStateVal* pWi return buildInvalidOperationMsg(pMsgBuf, msg2); } - columnListInsert(pQueryInfo->colList, index.columnIndex, pTableMeta->uid, pSchema); + columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, TSDB_COL_NORMAL); SColIndex colIndex = { .colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId }; //TODO use group by routine? state window query not support stable query. @@ -1114,7 +1114,7 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S pExpr = getExprInfo(pQueryInfo, pos); // other tag are not allowed - if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) { + if (pExpr->base.pColumns->colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) { return buildInvalidOperationMsg(pMsgBuf, msg5); } @@ -1133,7 +1133,7 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S bool found = false; for (int32_t i = 0; i < getNumOfExprs(pQueryInfo); ++i) { SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - if (getExprFunctionId(pExpr) == FUNCTION_PRJ && pExpr->base.colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_ID) { + if (getExprFunctionId(pExpr) == FUNCTION_PRJ && pExpr->base.pColumns->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { found = true; break; } @@ -1214,7 +1214,7 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S pExpr = getExprInfo(pQueryInfo, pos); - if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) { + if (pExpr->base.pColumns->colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_ID) { return buildInvalidOperationMsg(pMsgBuf, msg5); } } @@ -1614,7 +1614,7 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { for (int32_t i = 0; i < size; ++i) { SExprInfo* pExpr = getExprInfo(pQueryInfo, i); int32_t functionId = getExprFunctionId(pExpr); - if (functionId == FUNCTION_COUNT && TSDB_COL_IS_TAG(pExpr->base.colInfo.flag)) { + if (functionId == FUNCTION_COUNT && TSDB_COL_IS_TAG(pExpr->base.pColumns->flag)) { return buildInvalidOperationMsg(pMsgBuf, msg1); } } @@ -1718,15 +1718,15 @@ SExprInfo* doAddOneExprInfo(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, uint64_t uid = pTableMetaInfo->pTableMeta->uid; SArray* p = TSDB_COL_IS_TAG(pIndex->type)?pTableMetaInfo->tagColList:pQueryInfo->colList; - columnListInsert(p, pIndex->columnIndex, uid, pColSchema); + columnListInsert(p, uid, pColSchema, pIndex->type); - pExpr->base.colInfo.flag = pIndex->type; + pExpr->base.pColumns->flag = pIndex->type; if (TSDB_COL_IS_NORMAL_COL(pIndex->type)) { insertPrimaryTsColumn(pQueryInfo->colList, uid); } if (finalResult) { - addResColumnInfo(pQueryInfo, outputColIndex, pColSchema, pExpr); + addResColumnInfo(pQueryInfo, outputColIndex, pResultSchema, pExpr); } return pExpr; @@ -1762,7 +1762,7 @@ static int32_t checkForAliasName(SMsgBuf* pMsgBuf, char* aliasName) { } static int32_t validateComplexExpr(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf); -static int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, uint64_t *uid, SMsgBuf* pMsgBuf); +static int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, SMsgBuf* pMsgBuf); static int64_t getTickPerSecond(SVariant* pVariant, int32_t precision, int64_t* tickPerSec, SMsgBuf *pMsgBuf) { const char* msg10 = "derivative duration should be greater than 1 Second"; @@ -1795,7 +1795,7 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab addExprInfo(pQueryInfo, outputIndex, pExpr); SSchema* pSourceSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, indexTS.columnIndex); - columnListInsert(pQueryInfo->colList, indexTS.columnIndex, pTableMetaInfo->pTableMeta->uid, pSourceSchema); + columnListInsert(pQueryInfo->colList, pTableMetaInfo->pTableMeta->uid, pSourceSchema, TSDB_COL_NORMAL); addResColumnInfo(pQueryInfo, outputIndex, &pExpr->base.resSchema, pExpr); } @@ -1898,6 +1898,7 @@ 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) { @@ -1906,24 +1907,47 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId const char* msg3 = "illegal column name"; const char* msg4 = "nested function is not supported"; const char* msg5 = "functions applied to tags are not allowed"; + const char* msg6 = "aggregate function can not be nested in aggregate function"; + const char* msg7 = "invalid function name"; if (tokenId == TK_ALL || tokenId == TK_ID) { // simple parameter - if ((getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, pIndex, pMsgBuf) != TSDB_CODE_SUCCESS)) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } + // simple parameter or nested function + // It is a parameter of a aggregate function, so it can not be still a aggregate function. + // E.g., the sql statement of "select count(count(*)) from table_name" is invalid. + tSqlExpr* pSqlExpr = pParamElem->pNode; + if (pParamElem->pNode->type == SQL_NODE_SQLFUNCTION) { + bool scalarFunc = false; + pParamElem->functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalarFunc); + if (pParamElem->functionId == FUNCTION_INVALID_ID) { + return buildInvalidOperationMsg(pMsgBuf, msg7); + } - // functions can not be applied to tags - if (TSDB_COL_IS_TAG(pIndex->type)) { - return buildInvalidOperationMsg(pMsgBuf, msg5); - } + if (!scalarFunc) { + return buildInvalidOperationMsg(pMsgBuf, msg6); + } + + int32_t code = createComplexExpr(pQueryInfo, i, pParamElem, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + } else { + if ((getColumnIndexByName(&pParamElem->pNode->columnName, pQueryInfo, pIndex, pMsgBuf) != TSDB_CODE_SUCCESS)) { + return buildInvalidOperationMsg(pMsgBuf, msg3); + } - *pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); + // functions can not be applied to tags + if (TSDB_COL_IS_TAG(pIndex->type)) { + return buildInvalidOperationMsg(pMsgBuf, msg5); + } - // 2. check if sql function can be applied on this column data type - *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) { + // 2. check if sql function can be applied on this column data type + *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(SColumnIndex)); + SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); if (validateComplexExpr(pParamElem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) { return buildInvalidOperationMsg(pMsgBuf, msg1); } @@ -1940,7 +1964,7 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId tstrncpy(columnSchema->name, pExprToken->z, len); SArray* colList = taosArrayInit(10, sizeof(SColIndex)); - int32_t ret = sqlExprToExprNode(pNode, pParamElem->pNode, pQueryInfo, colList, NULL, pMsgBuf); + int32_t ret = sqlExprToExprNode(pNode, pParamElem->pNode, pQueryInfo, colList, pMsgBuf); if (ret != TSDB_CODE_SUCCESS) { taosArrayDestroy(colList); tExprTreeDestroy(*pNode, NULL); @@ -2290,7 +2314,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx return buildInvalidOperationMsg(pMsgBuf, msg1); } - columnListInsert(pTableMetaInfo->tagColList, index.columnIndex, pTableMetaInfo->pTableMeta->uid, &pSchema[index.columnIndex]); + columnListInsert(pTableMetaInfo->tagColList, pTableMetaInfo->pTableMeta->uid, &pSchema[index.columnIndex], TSDB_COL_TAG); SSchema* pTagSchema = getTableTagSchema(pTableMetaInfo->pTableMeta); SSchema s = {0}; @@ -2337,6 +2361,8 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx return TSDB_CODE_SUCCESS; } + + default: { // pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n); // if (pUdfInfo == NULL) { @@ -2380,6 +2406,110 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx return TSDB_CODE_TSC_INVALID_OPERATION; } +static int32_t validateExprLeafColumnNode(SQueryStmtInfo *pQueryInfo, SToken* pColumnName, SArray* pList, SMsgBuf* pMsgBuf) { + SColumnIndex index = COLUMN_INDEX_INITIALIZER; + if (getColumnIndexByName(pColumnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + // if column is timestamp not support arithmetic, so return invalid sql + STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); + STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; + + SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex); + if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + SColumn c = {0}; + setColumn(&c, pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema); + taosArrayPush(pList, &c); + + return TSDB_CODE_SUCCESS; +} + +static int32_t validateExprLeafFunctionNode(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr, SMsgBuf* pMsgBuf) { + tSqlExprItem item = {.pNode = pExpr, .aliasName = NULL}; + + // sql function list in selection clause. + // Append the sqlExpr into exprList of pQueryInfo structure sequentially + bool scalar = false; + item.functionId = qIsBuiltinFunction(pExpr->Expr.operand.z, pExpr->Expr.operand.n, &scalar); + if (item.functionId < 0) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + 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) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + } + + return TSDB_CODE_SUCCESS; +} + +int32_t validateScalarFunctionParamNum(tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { + int32_t code = TSDB_CODE_SUCCESS; + switch (pItem->functionId) { + case FUNCTION_CEIL: { + code = checkForkParam(pItem->pNode, 1, pMsgBuf); + break; + } + case FUNCTION_LENGTH: { + code = checkForkParam(pItem->pNode, 1, pMsgBuf); + break; + } + } + + return code; +} + +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; + + for (int32_t i = 0; i < 1; ++i) { + tSqlExprItem* pParamElem = taosArrayGet(pParamList, i); + tSqlExpr* pSqlExpr = pParamElem->pNode; + + int32_t type = pSqlExpr->type; + if (type == SQL_NODE_VALUE) { + } else if (type == SQL_NODE_SQLFUNCTION) { + code = validateExprLeafFunctionNode(pQueryInfo, pSqlExpr, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } else if (type == SQL_NODE_EXPR) { + code = validateComplexExpr(pSqlExpr, pQueryInfo, pList, exprType, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } else if (type == SQL_NODE_TABLE_COLUMN) { + code = validateExprLeafColumnNode(pQueryInfo, &pSqlExpr->columnName, pList, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + } +} + SExprInfo* doAddProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, SColumnIndex* pColIndex, const char* aliasName, int32_t colId) { STableMeta* pTableMeta = getMetaInfo(pQueryInfo, pColIndex->tableIndex)->pTableMeta; @@ -2452,6 +2582,48 @@ static SSchema createConstantColumnSchema(SVariant* pVal, const SToken* exprStr, return s; } +static int32_t handleTbnameProjection(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, SColumnIndex* pIndex, int32_t startPos, bool outerQuery, SMsgBuf* pMsgBuf) { + const char* msg3 = "tbname not allowed in outer query"; + + SSchema colSchema = {0}; + int32_t functionId = 0; + + if (outerQuery) { // todo?? + STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); + + bool existed = false; + SSchema* pSchema = pTableMetaInfo->pTableMeta->schema; + + int32_t numOfCols = getNumOfColumns(pTableMetaInfo->pTableMeta); + for (int32_t i = 0; i < numOfCols; ++i) { + if (strncasecmp(pSchema[i].name, TSQL_TBNAME_L, tListLen(pSchema[i].name)) == 0) { + existed = true; + pIndex->columnIndex = i; + break; + } + } + + if (!existed) { + return buildInvalidOperationMsg(pMsgBuf, msg3); + } + + colSchema = pSchema[pIndex->columnIndex]; + functionId = FUNCTION_PRJ; + } else { + colSchema = *getTbnameColumnSchema(); + functionId = FUNCTION_TAGPRJ; + } + + SSchema resultSchema = colSchema; + resultSchema.colId = getNewResColId(); + + char rawName[TSDB_COL_NAME_LEN] = {0}; + setTokenAndResColumnName(pItem, resultSchema.name, rawName, sizeof(colSchema.name) - 1); + + doAddOneExprInfo(pQueryInfo, startPos, functionId, pIndex, &colSchema, &resultSchema, NULL, 0, rawName, true); + return TSDB_CODE_SUCCESS; +} + int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, bool outerQuery, SMsgBuf* pMsgBuf) { const char* msg1 = "tag for normal table query is not allowed"; const char* msg2 = "invalid column name"; @@ -2487,7 +2659,7 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* if (pTableMeta->tableType != TSDB_TEMP_TABLE) { insertPrimaryTsColumn(pQueryInfo->colList, pTableMeta->uid); } - } else if (tokenId == TK_STRING || tokenId == TK_INTEGER || tokenId == TK_FLOAT) { // simple column projection query + } else if (tokenId == TK_STRING || tokenId == TK_INTEGER || tokenId == TK_FLOAT) { //constant value column SColumnIndex index = createConstantColumnIndex(&pQueryInfo->udColumnId); SSchema colSchema = createConstantColumnSchema(&pItem->pNode->value, &pItem->pNode->exprToken, pItem->aliasName); @@ -2498,49 +2670,14 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* // NOTE: the first parameter is reserved for the tag column id during join query process. pExpr->base.numOfParams = 2; taosVariantAssign(&pExpr->base.param[1], &pItem->pNode->value); - } else if (tokenId == TK_ID) { + } else if (tokenId == TK_ID) { // column name SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (getColumnIndexByName(&pItem->pNode->columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { return buildInvalidOperationMsg(pMsgBuf, msg2); } if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - SSchema colSchema = {0}; - int32_t functionId = 0; - - if (outerQuery) { // todo?? - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - - bool existed = false; - SSchema* pSchema = pTableMetaInfo->pTableMeta->schema; - - int32_t numOfCols = getNumOfColumns(pTableMetaInfo->pTableMeta); - for (int32_t i = 0; i < numOfCols; ++i) { - if (strncasecmp(pSchema[i].name, TSQL_TBNAME_L, tListLen(pSchema[i].name)) == 0) { - existed = true; - index.columnIndex = i; - break; - } - } - - if (!existed) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - - colSchema = pSchema[index.columnIndex]; - functionId = FUNCTION_PRJ; - } else { - colSchema = *getTbnameColumnSchema(); - functionId = FUNCTION_TAGPRJ; - } - - SSchema resultSchema = colSchema; - resultSchema.colId = getNewResColId(); - - char rawName[TSDB_COL_NAME_LEN] = {0}; - setTokenAndResColumnName(pItem, resultSchema.name, rawName, sizeof(colSchema.name) - 1); - - doAddOneExprInfo(pQueryInfo, startPos, functionId, &index, &colSchema, &resultSchema, NULL, 0, rawName, true); + handleTbnameProjection(pQueryInfo, pItem, &index, startPos, outerQuery, pMsgBuf); } else { STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); if (TSDB_COL_IS_TAG(index.type) && UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) { @@ -2562,8 +2699,7 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* return TSDB_CODE_SUCCESS; } -static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pList, int32_t* type, uint64_t* uid, - SMsgBuf* pMsgBuf) { +static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pList, int32_t* type, SMsgBuf* pMsgBuf) { if (pExpr->type == SQL_NODE_TABLE_COLUMN) { if (*type == NON_ARITHMEIC_EXPR) { *type = NORMAL_ARITHMETIC; @@ -2571,21 +2707,10 @@ static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, return TSDB_CODE_TSC_INVALID_OPERATION; } - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - if (getColumnIndexByName(&pExpr->columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - // if column is timestamp, bool, binary, nchar, not support arithmetic, so return invalid sql - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, index.tableIndex)->pTableMeta; - - SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex); - if ((pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) || (pSchema->type == TSDB_DATA_TYPE_BOOL) || - (pSchema->type == TSDB_DATA_TYPE_BINARY) || (pSchema->type == TSDB_DATA_TYPE_NCHAR)) { - return TSDB_CODE_TSC_INVALID_OPERATION; + int32_t code = validateExprLeafColumnNode(pQueryInfo, &pExpr->columnName, pList, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; } - - taosArrayPush(pList, &index); } else if ((pExpr->tokenId == TK_FLOAT && (isnan(pExpr->value.d) || isinf(pExpr->value.d))) || pExpr->tokenId == TK_NULL) { return TSDB_CODE_TSC_INVALID_OPERATION; @@ -2596,103 +2721,99 @@ static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, return TSDB_CODE_TSC_INVALID_OPERATION; } - tSqlExprItem item = {.pNode = pExpr, .aliasName = NULL}; - - // sql function list in selection clause. - // Append the sqlExpr into exprList of pQueryInfo structure sequentially - item.functionId = qIsBuiltinFunction(pExpr->Expr.operand.z, pExpr->Expr.operand.n); - if (item.functionId < 0) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - 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 arithmetic expression - uint64_t id = -1; - for(int32_t i = 0; i < inc; ++i) { - SExprInfo* p1 = getExprInfo(pQueryInfo, i + outputIndex); - - int16_t t = p1->base.resSchema.type; - if (IS_VAR_DATA_TYPE(t) || t == TSDB_DATA_TYPE_BOOL || t == TSDB_DATA_TYPE_TIMESTAMP) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - - if (i == 0) { - id = p1->base.uid; - continue; - } - - if (id != p1->base.uid) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } + int32_t code = validateExprLeafFunctionNode(pQueryInfo, pExpr, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; } - - *uid = id; } return TSDB_CODE_SUCCESS; } -int32_t validateComplexExpr(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf) { +int32_t validateComplexExpr(tSqlExpr * pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf) { if (pExpr == NULL) { return TSDB_CODE_SUCCESS; } - tSqlExpr* pLeft = pExpr->pLeft; - uint64_t uidLeft = 0; - uint64_t uidRight = 0; + int32_t code = TSDB_CODE_SUCCESS; + if (pExpr->type == SQL_NODE_SQLFUNCTION) { + return validateScalarFunctionParam(pQueryInfo, pExpr, pColList, type, pMsgBuf); + } + tSqlExpr* pLeft = pExpr->pLeft; if (pLeft->type == SQL_NODE_EXPR) { - int32_t ret = validateComplexExpr(pLeft, pQueryInfo, pColList, type, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + code = validateComplexExpr(pLeft, pQueryInfo, pColList, type, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; } } else { - int32_t ret = validateExprLeafNode(pLeft, pQueryInfo, pColList, type, &uidLeft, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + code = validateExprLeafNode(pLeft, pQueryInfo, pColList, type, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; } } tSqlExpr* pRight = pExpr->pRight; if (pRight->type == SQL_NODE_EXPR) { - int32_t ret = validateComplexExpr(pRight, pQueryInfo, pColList, type, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + code = validateComplexExpr(pRight, pQueryInfo, pColList, type, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; } } else { - int32_t ret = validateExprLeafNode(pRight, pQueryInfo, pColList, type, &uidRight, pMsgBuf); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + code = validateExprLeafNode(pRight, pQueryInfo, pColList, type, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + + // check divide by 0 + if (pExpr->tokenId == TK_DIVIDE && pRight->type == SQL_NODE_VALUE) { + int32_t type1 = pRight->value.nType; + const char* msg1 = "invalid expr (divide by 0)"; + + if (type1 == TSDB_DATA_TYPE_DOUBLE && pRight->value.d < DBL_EPSILON) { + return buildInvalidOperationMsg(pMsgBuf, msg1); + } else if (type1 == TSDB_DATA_TYPE_INT && pRight->value.i == 0) { + return buildInvalidOperationMsg(pMsgBuf, msg1); } } return TSDB_CODE_SUCCESS; } -int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, uint64_t *uid, SMsgBuf* pMsgBuf) { +int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, SMsgBuf* pMsgBuf) { 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; + } + SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (pSqlExpr->pLeft != NULL) { - int32_t ret = sqlExprToExprNode(&pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, uid, pMsgBuf); + 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, uid, pMsgBuf); + int32_t ret = sqlExprToExprNode(&pRight, pSqlExpr->pRight, pQueryInfo, pCols, pMsgBuf); if (ret != TSDB_CODE_SUCCESS) { tExprTreeDestroy(pLeft, NULL); return ret; @@ -2728,7 +2849,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt } return ret; } else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { - // arithmetic expression on the results of aggregation functions + // Expression on the results of aggregation functions *pExpr = calloc(1, sizeof(tExprNode)); (*pExpr)->nodeType = TEXPR_COL_NODE; (*pExpr)->pSchema = calloc(1, sizeof(SSchema)); @@ -2737,19 +2858,28 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt // set the input column data byte and type. size_t size = taosArrayGetSize(pQueryInfo->exprList); + bool found = false; + uint64_t uid = 0; for (int32_t i = 0; i < size; ++i) { SExprInfo* p1 = taosArrayGetP(pQueryInfo->exprList, i); if (strcmp((*pExpr)->pSchema->name, p1->base.resSchema.name) == 0) { memcpy((*pExpr)->pSchema, &p1->base.resSchema, sizeof(SSchema)); - if (uid != NULL) { - *uid = p1->base.uid; - } - + found = true; + uid = p1->base.pColumns->uid; break; } } - } else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column arithmetic expression + + assert(found); + + if (pCols != NULL) { // record the involved columns + SColumn c = {0}; + setColumn(&c, uid, NULL, TSDB_COL_NORMAL, (*pExpr)->pSchema); + taosArrayPush(pCols, &c); + } + + } else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column expression int32_t ret = getColumnIndexByName(&pSqlExpr->columnName, pQueryInfo, &index, pMsgBuf); if (ret != TSDB_CODE_SUCCESS) { return ret; @@ -2764,17 +2894,6 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt SSchema* pSchema = getOneColumnSchema(pTableMeta, index.columnIndex); *(*pExpr)->pSchema = *pSchema; - - if (pCols != NULL) { // record the involved columns - SColIndex colIndex = {0}; - tstrncpy(colIndex.name, pSchema->name, sizeof(colIndex.name)); - colIndex.colId = pSchema->colId; - colIndex.colIndex = index.columnIndex; - colIndex.flag = index.type; - - taosArrayPush(pCols, &colIndex); - } - return TSDB_CODE_SUCCESS; } else if (pSqlExpr->tokenId == TK_SET) { int32_t colType = -1; @@ -2823,17 +2942,6 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt assert((*pExpr)->_node.optr != 0); - // check for dividing by 0 - if ((*pExpr)->_node.optr == TSDB_BINARY_OP_DIVIDE) { - if (pRight->nodeType == TEXPR_VALUE_NODE) { - if (pRight->pVal->nType == TSDB_DATA_TYPE_INT && pRight->pVal->i == 0) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expr (divide by 0)"); - } else if (pRight->pVal->nType == TSDB_DATA_TYPE_FLOAT && pRight->pVal->d == 0) { - return buildInvalidOperationMsg(pMsgBuf, "invalid expr (divide by 0)"); - } - } - } - // NOTE: binary|nchar data allows the >|< type filter if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) { if (pRight != NULL && pRight->nodeType == TEXPR_VALUE_NODE) { @@ -2848,33 +2956,32 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt } static int32_t multiColumnListInsert(SQueryStmtInfo* pQueryInfo, SArray* pColumnList, SMsgBuf* pMsgBuf) { - const char* msg3 = "tag columns can not be used in arithmetic expression"; + const char* msg1 = "tag can not be used in expression"; - SColumnIndex* p1 = taosArrayGet(pColumnList, 0); - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, p1->tableIndex)->pTableMeta; + SColumn* p1 = taosArrayGet(pColumnList, 0); size_t numOfNode = taosArrayGetSize(pColumnList); for(int32_t k = 0; k < numOfNode; ++k) { - SColumnIndex* pIndex = taosArrayGet(pColumnList, k); - if (TSDB_COL_IS_TAG(pIndex->type)) { - return buildInvalidOperationMsg(pMsgBuf, msg3); + SColumn* p = taosArrayGet(pColumnList, k); + if (TSDB_COL_IS_TAG(p->flag)) { + return buildInvalidOperationMsg(pMsgBuf, msg1); } - SSchema* ps = getOneColumnSchema(pTableMeta, pIndex->columnIndex); - columnListInsert(pQueryInfo->colList, pIndex->columnIndex, pTableMeta->uid, ps); + SSchema s = createSchema(p->info.type, p->info.bytes, p->info.colId, p->name); + columnListInsert(pQueryInfo->colList, p->uid, &s, p->flag); } - insertPrimaryTsColumn(pQueryInfo->colList, pTableMeta->uid); + insertPrimaryTsColumn(pQueryInfo->colList, p1->uid); return TSDB_CODE_SUCCESS; } static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { - const char* msg1 = "invalid column name, illegal column type, or columns in arithmetic expression from two tables"; + const char* msg1 = "invalid column name, illegal column type, or columns in expression from two tables"; const char* msg2 = "invalid arithmetic expression in select clause"; - const char* msg3 = "tag columns can not be used in arithmetic expression"; int32_t arithmeticType = NON_ARITHMEIC_EXPR; - SArray* pColumnList = taosArrayInit(4, sizeof(SColumnIndex)); + + SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); if (validateComplexExpr(pItem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) { return buildInvalidOperationMsg(pMsgBuf, msg1); } @@ -2884,8 +2991,8 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, SSchema s = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), ""); tExprNode* pNode = NULL; - SArray* colList = taosArrayInit(10, sizeof(SColIndex)); - int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, colList, NULL, pMsgBuf); + SArray* colList = taosArrayInit(10, sizeof(SColumn)); + int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, colList, pMsgBuf); if (ret != TSDB_CODE_SUCCESS) { taosArrayDestroy(colList); tExprTreeDestroy(pNode, NULL); @@ -2924,13 +3031,13 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tbufCloseWriter(&bw); taosArrayDestroy(colList); } else { - SColumnIndex columnIndex = {0}; - SSchema s = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), ""); addResColumnInfo(pQueryInfo, exprIndex, &s, NULL); + assert(taosArrayGetSize(pColumnList) == 0); + tExprNode* pNode = NULL; - int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, NULL, NULL, pMsgBuf); + int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, pColumnList, pMsgBuf); if (ret != TSDB_CODE_SUCCESS) { tExprTreeDestroy(pNode, NULL); return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); @@ -2938,10 +3045,19 @@ static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, SExprInfo* pExpr = createBinaryExprInfo(pNode, &s); addExprInfo(pQueryInfo, exprIndex, pExpr); + setTokenAndResColumnName(pItem, pExpr->base.resSchema.name, pExpr->base.token, TSDB_COL_NAME_LEN); - pExpr->base.numOfParams = 1; + // extract columns according to the tExprNode tree + size_t num = taosArrayGetSize(pColumnList); + pExpr->base.pColumns = calloc(num, sizeof(SColumn)); + for(int32_t i = 0; i < num; ++i) { + pExpr->base.pColumns[i] = *(SColumn*) taosArrayGet(pColumnList, i); + } + pExpr->base.numOfCols = num; + + pExpr->base.numOfParams = 1; SBufferWriter bw = tbufInitWriter(NULL, false); // TRY(0) { exprTreeToBinary(&bw, pExpr->pExpr); @@ -2979,7 +3095,8 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, return buildInvalidOperationMsg(pMsgBuf, msg1); } - size_t numOfExpr = taosArrayGetSize(pSelNodeList); + int32_t code = TSDB_CODE_SUCCESS; + size_t numOfExpr = taosArrayGetSize(pSelNodeList); for (int32_t i = 0; i < numOfExpr; ++i) { int32_t outputIndex = (int32_t)getNumOfExprs(pQueryInfo); @@ -2987,15 +3104,17 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, int32_t type = pItem->pNode->type; if (pItem->distinct) { - if (i != 0/* || type == SQL_NODE_SQLFUNCTION || type == SQL_NODE_EXPR*/) { + if (i != 0 || type == SQL_NODE_SQLFUNCTION || type == SQL_NODE_EXPR) { return buildInvalidOperationMsg(pMsgBuf, msg4); } pQueryInfo->info.distinct = true; } + bool scalarFunc = false; + if (type == SQL_NODE_SQLFUNCTION) { - pItem->functionId = qIsBuiltinFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n); + 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; bool valid = qIsValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &functionId); @@ -3004,21 +3123,24 @@ 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 (addExprAndResColumn(pQueryInfo, outputIndex, pItem, true, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; + if ((code = addExprAndResColumn(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 // select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2 - if (addProjectionExprAndResColumn(pQueryInfo, pItem, outerQuery, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; + if ((code = addProjectionExprAndResColumn(pQueryInfo, pItem, outerQuery, pMsgBuf)) != TSDB_CODE_SUCCESS) { + return code; } } else if (type == SQL_NODE_EXPR) { - int32_t code = createComplexExpr(pQueryInfo, i, pItem, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { + if ((code = createComplexExpr(pQueryInfo, i, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { return code; } } else { diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index 504971cc103ca2e667b354ed842a004807100354..0585dc89054ec283981f3ffc5a569d4746cb03f6 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -177,7 +177,8 @@ int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SMetaReq* pMet } // Let's assume that it is an UDF/UDAF, if it is not a built-in function. - if (qIsBuiltinFunction(t->z, t->n) < 0) { + bool scalarFunc = false; + if (qIsBuiltinFunction(t->z, t->n, &scalarFunc) < 0) { char* fname = strndup(t->z, t->n); taosArrayPush(pMetaInfo->pUdf, &fname); } diff --git a/source/libs/parser/src/parserUtil.c b/source/libs/parser/src/parserUtil.c index 7dc5fd00b24f9afe714f584ec395d6edf489aad7..13148da66bdea50d53dea6e19410b73564c336b5 100644 --- a/source/libs/parser/src/parserUtil.c +++ b/source/libs/parser/src/parserUtil.c @@ -513,6 +513,20 @@ SSchema createSchema(uint8_t type, int16_t bytes, int16_t colId, const char* nam return s; } +void setColumn(SColumn* pColumn, uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema) { + pColumn->uid = uid; + pColumn->flag = flag; + pColumn->info.colId = pSchema->colId; + pColumn->info.bytes = pSchema->bytes; + pColumn->info.type = pSchema->type; + + if (tableName != NULL) { + snprintf(pColumn->name, tListLen(pColumn->name), "%s.%s", tableName, pSchema->name); + } else { + tstrncpy(pColumn->name, pSchema->name, tListLen(pColumn->name)); + } +} + int32_t getNumOfFields(SFieldInfo* pFieldInfo) { return pFieldInfo->numOfOutput; } @@ -701,7 +715,7 @@ int32_t columnExists(SArray* pColumnList, int32_t columnId, uint64_t uid) { int32_t i = 0; while (i < numOfCols) { SColumn* pCol = taosArrayGetP(pColumnList, i); - if ((pCol->info.colId != columnId) || (pCol->tableUid != uid)) { + if ((pCol->info.colId != columnId) || (pCol->uid != uid)) { ++i; continue; } else { @@ -716,64 +730,60 @@ int32_t columnExists(SArray* pColumnList, int32_t columnId, uint64_t uid) { return i; } -SColumn* columnListInsert(SArray* pColumnList, int32_t columnIndex, uint64_t uid, SSchema* pSchema) { - // ignore the tbname columnIndex to be inserted into source list - if (columnIndex < 0) { - return NULL; - } +static int32_t doFindPosition(const SArray* pColumnList, uint64_t uid, const SSchema* pSchema) { + int32_t i = 0; size_t numOfCols = taosArrayGetSize(pColumnList); - - int32_t i = 0; while (i < numOfCols) { SColumn* pCol = taosArrayGetP(pColumnList, i); - if (pCol->columnIndex < columnIndex) { + if (pCol->uid < uid) { i++; - } else if (pCol->tableUid < uid) { - i++; - } else { - break; + continue; } - } - if (i >= numOfCols || numOfCols == 0) { - SColumn* b = calloc(1, sizeof(SColumn)); - if (b == NULL) { - return NULL; + if (pCol->info.colId < pSchema->colId) { + i++; + continue; } - b->columnIndex = columnIndex; - b->tableUid = uid; - b->info.colId = pSchema->colId; - b->info.bytes = pSchema->bytes; - b->info.type = pSchema->type; - - taosArrayInsert(pColumnList, i, &b); - } else { - SColumn* pCol = taosArrayGetP(pColumnList, i); + break; + } - if (i < numOfCols && (pCol->columnIndex > columnIndex || pCol->tableUid != uid)) { - SColumn* b = calloc(1, sizeof(SColumn)); - if (b == NULL) { - return NULL; - } + return i; +} - b->columnIndex = columnIndex; - b->tableUid = uid; - b->info.colId = pSchema->colId; - b->info.bytes = pSchema->bytes; - b->info.type = pSchema->type; +SColumn* columnListInsert(SArray* pColumnList, uint64_t uid, SSchema* pSchema, int32_t flag) { + // ignore the tbname columnIndex to be inserted into source list + assert(pSchema != NULL && pColumnList != NULL); - taosArrayInsert(pColumnList, i, &b); + int32_t i = doFindPosition(pColumnList, uid, pSchema); + size_t size = taosArrayGetSize(pColumnList); + if (size > 0 && i < size) { + SColumn* pCol = taosArrayGetP(pColumnList, i); + if (pCol->uid == uid && pCol->info.colId == pSchema->colId) { + return pCol; } } - return taosArrayGetP(pColumnList, i); + SColumn* b = calloc(1, sizeof(SColumn)); + if (b == NULL) { + return NULL; + } + + b->uid = uid; + b->flag = flag; + b->info.colId = pSchema->colId; + b->info.bytes = pSchema->bytes; + b->info.type = pSchema->type; + tstrncpy(b->name, pSchema->name, tListLen(b->name)); + + taosArrayInsert(pColumnList, i, &b); + return b; } SColumn* insertPrimaryTsColumn(SArray* pColumnList, uint64_t tableUid) { SSchema s = {.type = TSDB_DATA_TYPE_TIMESTAMP, .bytes = TSDB_KEYSIZE, .colId = PRIMARYKEY_TIMESTAMP_COL_ID}; - return columnListInsert(pColumnList, PRIMARYKEY_TIMESTAMP_COL_ID, tableUid, &s); + return columnListInsert(pColumnList, tableUid, &s, TSDB_COL_NORMAL); } void columnCopy(SColumn* pDest, const SColumn* pSrc); @@ -817,8 +827,7 @@ SColumnFilterInfo* tFilterInfoDup(const SColumnFilterInfo* src, int32_t numOfFil void columnCopy(SColumn* pDest, const SColumn* pSrc) { destroyFilterInfo(&pDest->info.flist); - pDest->columnIndex = pSrc->columnIndex; - pDest->tableUid = pSrc->tableUid; + pDest->uid = pSrc->uid; pDest->info.flist.numOfFilters = pSrc->info.flist.numOfFilters; pDest->info.flist.filterInfo = tFilterInfoDup(pSrc->info.flist.filterInfo, pSrc->info.flist.numOfFilters); pDest->info.type = pSrc->info.type; @@ -844,7 +853,7 @@ void columnListCopy(SArray* dst, const SArray* src, uint64_t uid) { for (int32_t i = 0; i < num; ++i) { SColumn* pCol = taosArrayGetP(src, i); - if (pCol->tableUid == uid) { + if (pCol->uid == uid) { SColumn* p = columnClone(pCol); taosArrayPush(dst, &p); } diff --git a/source/libs/parser/src/queryInfoUtil.c b/source/libs/parser/src/queryInfoUtil.c index 21ab193157f18968d38e1d0169d44151db691dd8..98a800c3c698947bda1131519c224aa202f11398 100644 --- a/source/libs/parser/src/queryInfoUtil.c +++ b/source/libs/parser/src/queryInfoUtil.c @@ -55,7 +55,7 @@ SSchema* getTableTagSchema(const STableMeta* pTableMeta) { return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns); } -static tExprNode* createUnaryFunctionExprNode(int32_t functionId, SSchema* pSchema, tExprNode* pColumnNode) { +static tExprNode* createFunctionExprNode(int32_t functionId, SSchema* pSchema, tExprNode* pColumnNode, int32_t numOfCols) { if (pColumnNode == NULL) { pColumnNode = calloc(1, sizeof(tExprNode)); pColumnNode->nodeType = TEXPR_COL_NODE; @@ -66,9 +66,10 @@ static tExprNode* createUnaryFunctionExprNode(int32_t functionId, SSchema* pSche } tExprNode* pNode = calloc(1, sizeof(tExprNode)); - pNode->nodeType = TEXPR_UNARYEXPR_NODE; - pNode->_node.functionId = functionId; - pNode->_node.pLeft = pColumnNode; + pNode->nodeType = TEXPR_FUNCTION_NODE; + pNode->_function.functionId = functionId; + pNode->_function.pChild = pColumnNode; + pNode->_function.num = numOfCols; return pNode; } @@ -92,48 +93,50 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC return NULL; } + uint64_t uid = 0; + if (pTableMetaInfo->pTableMeta) { + uid = pTableMetaInfo->pTableMeta->uid; + } + SSqlExpr* p = &pExpr->base; + p->pColumns = calloc(1, sizeof(SColumn)); + p->numOfCols = 1; if (pParamExpr != NULL) { - pExpr->pExpr = createUnaryFunctionExprNode(functionId, NULL, pParamExpr); + 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); SSchema* s = getTbnameColumnSchema(); - p->colInfo.colId = TSDB_TBNAME_COLUMN_INDEX; - pExpr->pExpr = createUnaryFunctionExprNode(functionId, s, pParamExpr); + setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_TAG, s); + + pExpr->pExpr = createFunctionExprNode(functionId, s, pParamExpr, 1); } else if (pColIndex->columnIndex <= TSDB_UD_COLUMN_INDEX || functionId == FUNCTION_BLKINFO) { assert(pParamExpr == NULL); + setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_UDC, pResSchema); - p->colInfo.colId = pColIndex->columnIndex; SSchema s = createSchema(pResSchema->type, pResSchema->bytes, pColIndex->columnIndex, pResSchema->name); - pExpr->pExpr = createUnaryFunctionExprNode(functionId, &s, pParamExpr); + pExpr->pExpr = createFunctionExprNode(functionId, &s, pParamExpr, 1); } else { - int32_t len = tListLen(p->colInfo.name); if (TSDB_COL_IS_TAG(pColIndex->type)) { SSchema* pSchema = getTableTagSchema(pTableMetaInfo->pTableMeta); - p->colInfo.colId = pSchema[pColIndex->columnIndex].colId; - pExpr->pExpr = createUnaryFunctionExprNode(functionId, &pSchema[pColIndex->columnIndex], pParamExpr); - snprintf(p->colInfo.name, len, "%s.%s", pTableMetaInfo->aliasName, pSchema[pColIndex->columnIndex].name); + setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_TAG, &pSchema[pColIndex->columnIndex]); + pExpr->pExpr = createFunctionExprNode(functionId, &pSchema[pColIndex->columnIndex], pParamExpr, 1); } else if (pTableMetaInfo->pTableMeta != NULL) { // in handling select database/version/server_status(), the pTableMeta is NULL SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, pColIndex->columnIndex); - p->colInfo.colId = pSchema->colId; - snprintf(p->colInfo.name, len, "%s.%s", pTableMetaInfo->aliasName, pSchema->name); + setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_NORMAL, pSchema); - pExpr->pExpr = createUnaryFunctionExprNode(functionId, pSchema, pParamExpr); + pExpr->pExpr = createFunctionExprNode(functionId, pSchema, pParamExpr, 1); } } - p->colInfo.flag = pColIndex->type; - p->colInfo.colIndex = pColIndex->columnIndex; + p->pColumns->flag = pColIndex->type; p->interBytes = interSize; memcpy(&p->resSchema, pResSchema, sizeof(SSchema)); - if (pTableMetaInfo->pTableMeta) { - p->uid = pTableMetaInfo->pTableMeta->uid; - } - return pExpr; } @@ -152,10 +155,9 @@ void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int assert(pExprInfo != NULL); SSqlExpr* pse = &pExprInfo->base; - pExprInfo->pExpr->_node.functionId = functionId; + pExprInfo->pExpr->_function.functionId = functionId; + assert(0); - pse->colInfo.colIndex = srcColumnIndex; - pse->colInfo.colId = colId; pse->resSchema.type = resType; pse->resSchema.bytes = resSize; } @@ -198,7 +200,7 @@ void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t byt 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; } void assignExprInfo(SExprInfo* dst, const SExprInfo* src) { @@ -225,8 +227,9 @@ int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deep size_t size = taosArrayGetSize(src); for (int32_t i = 0; i < size; ++i) { SExprInfo* pExpr = taosArrayGetP(src, i); + uint64_t exprUid = pExpr->base.pColumns->uid; - if (pExpr->base.uid == uid) { + if (exprUid == uid) { if (deepcopy) { SExprInfo* p1 = calloc(1, sizeof(SExprInfo)); assignExprInfo(p1, pExpr); @@ -300,7 +303,7 @@ SArray* extractFunctionIdList(SArray* pExprInfoList) { SArray* p = taosArrayInit(len, sizeof(int32_t)); for(int32_t i = 0; i < len; ++i) { SExprInfo* pExprInfo = taosArrayGetP(pExprInfoList, i); - taosArrayPush(p, &pExprInfo->pExpr->_node.functionId); + taosArrayPush(p, &pExprInfo->pExpr->_function.functionId); } return p; diff --git a/source/libs/parser/test/parserTests.cpp b/source/libs/parser/test/parserTests.cpp index 9fb50e1006e950df54521cd0fe4f9d13686d87ab..73c6b900f0d91bfd169f69f3eccf0b06df65b927 100644 --- a/source/libs/parser/test/parserTests.cpp +++ b/source/libs/parser/test/parserTests.cpp @@ -50,7 +50,7 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) { strcpy(pTableMetaInfo->aliasName, name->tname); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; pTableMeta->tableType = TSDB_NORMAL_TABLE; - pTableMeta->tableInfo.numOfColumns = 4; + pTableMeta->tableInfo.numOfColumns = 6; pTableMeta->tableInfo.rowSize = 28; pTableMeta->uid = 110; @@ -61,162 +61,12 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) { setSchema(&pSchema[1], TSDB_DATA_TYPE_INT, 4, "a", 1); setSchema(&pSchema[2], TSDB_DATA_TYPE_DOUBLE, 8, "b", 2); setSchema(&pSchema[3], TSDB_DATA_TYPE_DOUBLE, 8, "col", 3); - -} -} - -TEST(testCase, validateAST_test) { - SSqlInfo info1 = doGenerateAST("select a a1111, a+b + 22, tbname from `t.1abc` where tsexprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 3); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_INT); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1111"); - ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.a"); - ASSERT_EQ(p1->base.colInfo.colId, 1); - ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "a"); - - ASSERT_EQ(taosArrayGetSize(pExprList), 3); - - SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p2->base.uid, 0); - ASSERT_EQ(p2->base.numOfParams, 1); // it is the serialized binary string of expression. - ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p2->base.resSchema.name, "a+b + 22"); - -// ASSERT_STRCASEEQ(p2->base.colInfo.name, "t.1abc.a"); -// ASSERT_EQ(p1->base.colInfo.colId, 1); -// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p2->base.token, "a+b + 22"); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 3); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test) { - SSqlInfo info1 = doGenerateAST("select count(a) from `t.1abc`"); - 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); - - SArray* pExprList = pQueryInfo->exprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 1); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.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)"); - ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.a"); - ASSERT_EQ(p1->base.colInfo.colId, 1); - ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "count(a)"); - ASSERT_EQ(p1->base.interBytes, 8); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); -} - -TEST(testCase, function_Test2) { - SSqlInfo info1 = doGenerateAST("select count(a) abc from `t.1abc`"); - 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); - - SArray* pExprList = pQueryInfo->exprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 1); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "abc"); - ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.a"); - ASSERT_EQ(p1->base.colInfo.colId, 1); - ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "count(a)"); - ASSERT_EQ(p1->base.interBytes, 8); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); + setSchema(&pSchema[4], TSDB_DATA_TYPE_BINARY, 12, "c", 4); + setSchema(&pSchema[5], TSDB_DATA_TYPE_BINARY, 44, "d", 5); } -TEST(testCase, function_Test3) { - SSqlInfo info1 = doGenerateAST("select first(*) from `t.1abc`"); +void sqlCheck(const char* sql, bool valid) { + SSqlInfo info1 = doGenerateAST(sql); ASSERT_EQ(info1.valid, true); char msg[128] = {0}; @@ -239,118 +89,314 @@ TEST(testCase, function_Test3) { SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0); ret = validateSqlNode(pSqlNode, pQueryInfo, &buf); - SArray* pExprList = pQueryInfo->exprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 4); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.uid, 110); - ASSERT_EQ(p1->base.numOfParams, 0); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_TIMESTAMP); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "first(ts)"); - ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts"); - ASSERT_EQ(p1->base.colInfo.colId, 0); - ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "first(ts)"); - ASSERT_EQ(p1->base.interBytes, 24); - - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 4); + if (valid) { + ASSERT_EQ(ret, 0); + } else { + ASSERT_NE(ret, 0); + } destroyQueryInfo(pQueryInfo); qParserClearupMetaRequestInfo(&req); destroySqlInfo(&info1); } - -TEST(testCase, function_Test4) { - SSqlInfo info1 = doGenerateAST("select _block_dist() as a1 from `t.1abc`"); - 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); - - SArray* pExprList = pQueryInfo->exprList; - ASSERT_EQ(taosArrayGetSize(pExprList), 1); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.uid, 110); - ASSERT_EQ(p1->base.numOfParams, 1); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BINARY); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1"); -// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts"); -// ASSERT_EQ(p1->base.colInfo.colId, 0); - ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "_block_dist()"); - ASSERT_EQ(p1->base.interBytes, 0); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 1); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); } -TEST(testCase, function_Test5) { - SSqlInfo info1 = doGenerateAST("select sum(a) + avg(b) as a1 from `t.1abc`"); - 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), 3); - - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.uid, 0); - ASSERT_EQ(p1->base.numOfParams, 1); - ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); - ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1"); -// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts"); -// ASSERT_EQ(p1->base.colInfo.colId, 0); - ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); - ASSERT_STRCASEEQ(p1->base.token, "sum(a) + avg(b)"); - ASSERT_EQ(p1->base.interBytes, 0); - - ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); - - destroyQueryInfo(pQueryInfo); - qParserClearupMetaRequestInfo(&req); - destroySqlInfo(&info1); +//TEST(testCase, validateAST_test) { +// SSqlInfo info1 = doGenerateAST("select a a1111, a+b + 22, tbname from `t.1abc` where tsexprList; +// ASSERT_EQ(taosArrayGetSize(pExprList), 3); +// +// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); +// ASSERT_EQ(p1->base.pColumns->info.colId, 110); +// ASSERT_EQ(p1->base.numOfParams, 0); +// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_INT); +// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1111"); +// ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a"); +// ASSERT_EQ(p1->base.pColumns->info.colId, 1); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "a"); +// +// ASSERT_EQ(taosArrayGetSize(pExprList), 3); +// +// SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1); +// ASSERT_EQ(p2->base.pColumns->uid, 0); +// ASSERT_EQ(p2->base.numOfParams, 1); // it is the serialized binary string of expression. +// ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); +// ASSERT_STRCASEEQ(p2->base.resSchema.name, "a+b + 22"); +// +//// ASSERT_STRCASEEQ(p2->base.colInfo.name, "t.1abc.a"); +//// ASSERT_EQ(p1->base.colInfo.colId, 1); +//// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p2->base.token, "a+b + 22"); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 3); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} +// +//TEST(testCase, function_Test) { +// SSqlInfo info1 = doGenerateAST("select count(a) from `t.1abc`"); +// 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); +// +// SArray* pExprList = pQueryInfo->exprList; +// ASSERT_EQ(taosArrayGetSize(pExprList), 1); +// +// 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)"); +// ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a"); +// ASSERT_EQ(p1->base.pColumns->info.colId, 1); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "count(a)"); +// ASSERT_EQ(p1->base.interBytes, 8); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} +// +//TEST(testCase, function_Test2) { +// SSqlInfo info1 = doGenerateAST("select count(a) abc from `t.1abc`"); +// 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); +// +// SArray* pExprList = pQueryInfo->exprList; +// ASSERT_EQ(taosArrayGetSize(pExprList), 1); +// +// 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, "abc"); +// ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.a"); +// ASSERT_EQ(p1->base.pColumns->info.colId, 1); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "count(a)"); +// ASSERT_EQ(p1->base.interBytes, 8); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} +// +//TEST(testCase, function_Test3) { +// SSqlInfo info1 = doGenerateAST("select first(*) from `t.1abc`"); +// 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); +// +// SArray* pExprList = pQueryInfo->exprList; +// ASSERT_EQ(taosArrayGetSize(pExprList), 4); +// +// 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_TIMESTAMP); +// ASSERT_STRCASEEQ(p1->base.resSchema.name, "first(ts)"); +// ASSERT_STRCASEEQ(p1->base.pColumns->name, "t.1abc.ts"); +// ASSERT_EQ(p1->base.pColumns->info.colId, 0); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "first(ts)"); +// ASSERT_EQ(p1->base.interBytes, 24); +// +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 4); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} +// +//TEST(testCase, function_Test4) { +// SSqlInfo info1 = doGenerateAST("select _block_dist() as a1 from `t.1abc`"); +// 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); +// +// SArray* pExprList = pQueryInfo->exprList; +// ASSERT_EQ(taosArrayGetSize(pExprList), 1); +// +// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); +// ASSERT_EQ(p1->base.pColumns->uid, 110); +// ASSERT_EQ(p1->base.numOfParams, 1); +// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BINARY); +// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1"); +//// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts"); +//// ASSERT_EQ(p1->base.colInfo.colId, 0); +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "_block_dist()"); +// ASSERT_EQ(p1->base.interBytes, 0); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 1); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} + +//TEST(testCase, function_Test5) { +// //todo select concat(concat(a, b), concat(b, a)) from `t.1abc`; +// +// SSqlInfo info1 = doGenerateAST("select sum(a) + avg(b) as a1 from `t.1abc`"); +// 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), 3); +// +// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); +// ASSERT_EQ(p1->base.numOfCols, 2); +// 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, "a1"); +// +// ASSERT_EQ(p1->base.pColumns->flag, TSDB_COL_NORMAL); +// ASSERT_STRCASEEQ(p1->base.token, "sum(a) + avg(b)"); +// ASSERT_EQ(p1->base.interBytes, 0); +// +// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); +// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1); +// +// destroyQueryInfo(pQueryInfo); +// qParserClearupMetaRequestInfo(&req); +// destroySqlInfo(&info1); +//} + +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(sum(a+b)) from `t.1abc`", false); } TEST(testCase, function_Test6) { @@ -382,15 +428,15 @@ TEST(testCase, function_Test6) { ASSERT_EQ(taosArrayGetSize(pExprList), 5); SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.uid, 110); + 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.colInfo.flag, TSDB_COL_NORMAL); + 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->_node.functionId, FUNCTION_SUM); + ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_SUM); ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); tExprNode* pParam = p1->pExpr->_node.pLeft; @@ -404,15 +450,15 @@ TEST(testCase, function_Test6) { ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 5); SExprInfo* p2 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p2->base.uid, 110); + 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.colInfo.flag, TSDB_COL_NORMAL); + 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->_node.functionId, FUNCTION_FIRST); + ASSERT_EQ(p2->pExpr->_function.functionId, FUNCTION_FIRST); ASSERT_TRUE(p2->pExpr->_node.pRight == NULL); destroyQueryInfo(pQueryInfo); @@ -449,15 +495,15 @@ TEST(testCase, function_Test7) { ASSERT_EQ(taosArrayGetSize(pExprList), 2); SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); - ASSERT_EQ(p1->base.uid, 110); + 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.colInfo.flag, TSDB_COL_NORMAL); + 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->_node.functionId, FUNCTION_COUNT); + ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_COUNT); ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); tExprNode* pParam = p1->pExpr->_node.pLeft; @@ -504,16 +550,16 @@ TEST(testCase, function_Test8) { ASSERT_EQ(taosArrayGetSize(pExprList), 2); SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p1->base.uid, 110); + 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.colInfo.flag, TSDB_COL_NORMAL); + 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->_node.functionId, FUNCTION_TOP); + ASSERT_EQ(p1->pExpr->_function.functionId, FUNCTION_TOP); ASSERT_TRUE(p1->pExpr->_node.pRight == NULL); tExprNode* pParam = p1->pExpr->_node.pLeft; diff --git a/source/libs/parser/test/plannerTest.cpp b/source/libs/parser/test/plannerTest.cpp index 528116fc32932d56c860369cfb5b139f37ee48d3..c357d92b11bd5c6bdce9a1bc6e7cec9831e3ebfe 100644 --- a/source/libs/parser/test/plannerTest.cpp +++ b/source/libs/parser/test/plannerTest.cpp @@ -95,16 +95,16 @@ TEST(testCase, planner_test) { ASSERT_EQ(taosArrayGetSize(pExprList), 2); SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); - ASSERT_EQ(p1->base.uid, 110); + 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.colInfo.flag, TSDB_COL_NORMAL); + 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->_node.functionId, FUNCTION_TOP); + 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; diff --git a/source/libs/planner/src/planner.c b/source/libs/planner/src/planner.c index 969b2c7622d3f4fd87cd97e0de64d12af0a7432a..25e63507c222b7827108184d4dbba914f080284c 100644 --- a/source/libs/planner/src/planner.c +++ b/source/libs/planner/src/planner.c @@ -186,7 +186,7 @@ static SQueryPlanNode* doAddTableColumnNode(SQueryStmtInfo* pQueryInfo, STableMe for (int32_t i = 0; i < numOfCols; ++i) { SColumn* pCol = taosArrayGetP(tableCols, i); - SColumnIndex index = {.tableIndex = 0, .columnIndex = pCol->columnIndex}; + SColumnIndex index = {.tableIndex = 0, /*.columnIndex = pCol->columnIndex*/}; SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, i); SSchema resultSchema = *pSchema;