diff --git a/include/libs/function/function.h b/include/libs/function/function.h index a8872ad3235a2129d1da5013dbe0fc3a1a42e3c2..8599b2a6f83e72545b15f56afcd07168b7a2ba83 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -78,6 +78,8 @@ extern "C" { #define FUNCTION_MODE 36 #define FUNCTION_SAMPLE 37 +#define FUNCTION_COV 38 + // determine the real data need to calculated the result enum { BLK_DATA_NO_NEEDED = 0x0, diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 7b8d50bf160ad7c001e9d074090997defa4917c9..5457f0b957d588236732db8cba946ff785314cc9 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -166,7 +166,16 @@ void columnListCopy(SArray* dst, const SArray* src, uint64_t uid); void columnListDestroy(SArray* pColumnList); void dropAllExprInfo(SArray** pExprInfo, int32_t numOfLevel); -SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SColumnIndex* pColIndex, struct tExprNode* pParamExpr, SSchema* pResSchema, int16_t interSize); + +typedef struct SSourceParam { +// struct tExprNode **pExprNode; + SArray *pExprNodeList; //Array +// SColumn *pCols; + SArray *pColumnList; //Array + int32_t num; +} SSourceParam; + +SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SSourceParam* pSource, SSchema* pResSchema, int16_t interSize); int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy); STableMetaInfo* getMetaInfo(SQueryStmtInfo* pQueryInfo, int32_t tableIndex); diff --git a/source/libs/function/inc/taggfunction.h b/source/libs/function/inc/taggfunction.h index c3bc63cf6ffa60cd13b95ebd1af201feb16d292a..41c7309a18d3ef702663f60ee25fffc0def7c7c2 100644 --- a/source/libs/function/inc/taggfunction.h +++ b/source/libs/function/inc/taggfunction.h @@ -28,7 +28,7 @@ extern "C" { #include "function.h" #include "tudf.h" -extern SAggFunctionInfo aggFunc[34]; +extern SAggFunctionInfo aggFunc[35]; typedef struct SResultRowEntryInfo { int8_t hasResult; // result generated, not NULL value diff --git a/source/libs/function/src/taggfunction.c b/source/libs/function/src/taggfunction.c index a2e6c3d3aced5c71a41d94e3ca49070d56b1155a..3bf307d475211579b8c2a9db9d1e82e76ee22283 100644 --- a/source/libs/function/src/taggfunction.c +++ b/source/libs/function/src/taggfunction.c @@ -4379,7 +4379,7 @@ int32_t functionCompatList[] = { 6, 8, 7, }; -SAggFunctionInfo aggFunc[34] = {{ +SAggFunctionInfo aggFunc[35] = {{ // 0, count function does not invoke the finalize function "count", FUNCTION_TYPE_AGG, @@ -4820,4 +4820,18 @@ SAggFunctionInfo aggFunc[34] = {{ blockinfo_func_finalizer, block_func_merge, dataBlockRequired, - }}; + }, + { + // 34 + "cov", // return table id and the corresponding tags for join match and subscribe + FUNCTION_TYPE_AGG, + FUNCTION_COV, + FUNCTION_COV, + FUNCSTATE_SO | FUNCSTATE_STABLE, + function_setup, + sum_function, + function_finalizer, + sum_func_merge, + statisRequired, + } + }; diff --git a/source/libs/parser/inc/parserUtil.h b/source/libs/parser/inc/parserUtil.h index 0f5acf5bccab7b4eaba99c9eb57fd8090713bae3..f567f6553b3bcfdca8bb962d2e25fcd4234ac762 100644 --- a/source/libs/parser/inc/parserUtil.h +++ b/source/libs/parser/inc/parserUtil.h @@ -39,6 +39,9 @@ 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); +SColumn createColumn(uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema); + +SSourceParam addIntoSourceParam(SSourceParam* pSourceParam, tExprNode* pNode, SColumn* pColumn); SInternalField* insertFieldInfo(SFieldInfo* pFieldInfo, int32_t index, SSchema* field); int32_t getNumOfFields(SFieldInfo* pFieldInfo); diff --git a/source/libs/parser/inc/queryInfoUtil.h b/source/libs/parser/inc/queryInfoUtil.h index 6edcc4b225521e8cf75a6373d66eab588647c7a7..448b742dd8d2588761e5ddb1cfe9bc8f6cb61af8 100644 --- a/source/libs/parser/inc/queryInfoUtil.h +++ b/source/libs/parser/inc/queryInfoUtil.h @@ -28,7 +28,8 @@ int32_t getNumOfTags(const STableMeta* pTableMeta); SSchema *getTableColumnSchema(const STableMeta *pTableMeta); SSchema *getTableTagSchema(const STableMeta* pTableMeta); -size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo); +SArray *getCurrentExprList(SQueryStmtInfo* pQueryInfo); +size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo); SExprInfo* createBinaryExprInfo(struct tExprNode* pNode, SSchema* pResSchema); void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level); diff --git a/source/libs/parser/src/astValidate.c b/source/libs/parser/src/astValidate.c index d7e367cd0f61340f20043dcdf5cbf773d1a9cc89..8ef2479a30144fc6197bd3c19e064790f05dafd5 100644 --- a/source/libs/parser/src/astValidate.c +++ b/source/libs/parser/src/astValidate.c @@ -1708,35 +1708,37 @@ void setResultColName(char* name, tSqlExprItem* pItem, SToken* pToken, SToken* f } } -SArray* getCurrentExprList(SQueryStmtInfo* pQueryInfo) { - assert(pQueryInfo != NULL && pQueryInfo->exprListLevelIndex >= 0 && pQueryInfo->exprListLevelIndex < 10); - return pQueryInfo->exprList[pQueryInfo->exprListLevelIndex]; -} - -SExprInfo* doAddOneExprInfo(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId, SColumnIndex* pIndex, - SSchema* pColSchema, SSchema* pResultSchema, tExprNode* pExprNode, int32_t interSize, const char* token, bool finalResult) { - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); - SExprInfo* pExpr = createExprInfo(pTableMetaInfo, functionId, pIndex, pExprNode, pResultSchema, interSize); +SExprInfo* doAddOneExprInfo(SQueryStmtInfo* pQueryInfo, int16_t functionId, SSourceParam* pSourceParam, int32_t outputIndex, + STableMetaInfo* pTableMetaInfo, SSchema* pResultSchema, int32_t interSize, const char* token, bool finalResult) { + SExprInfo* pExpr = createExprInfo(pTableMetaInfo, functionId, pSourceParam, pResultSchema, interSize); SArray* pExprList = getCurrentExprList(pQueryInfo); - addExprInfo(pExprList, outputColIndex, pExpr, pQueryInfo->exprListLevelIndex); + addExprInfo(pExprList, outputIndex, pExpr, pQueryInfo->exprListLevelIndex); tstrncpy(pExpr->base.token, token, sizeof(pExpr->base.token)); uint64_t uid = pTableMetaInfo->pTableMeta->uid; - if (pIndex->columnIndex != COLUMN_INDEX_INITIAL_VAL) { - SArray* p = TSDB_COL_IS_TAG(pIndex->type) ? pTableMetaInfo->tagColList : pQueryInfo->colList; - columnListInsert(p, uid, pColSchema, pIndex->type); - } + if (pSourceParam->pColumnList != NULL) { + SColumn* pCol = taosArrayGetP(pSourceParam->pColumnList, 0); + + if (pCol->flag != COLUMN_INDEX_INITIAL_VAL) { + SArray* p = TSDB_COL_IS_TAG(pCol->flag) ? pTableMetaInfo->tagColList : pQueryInfo->colList; - pExpr->base.pColumns->flag = pIndex->type; - if (TSDB_COL_IS_NORMAL_COL(pIndex->type)) { - insertPrimaryTsColumn(pQueryInfo->colList, uid); + for (int32_t i = 0; i < pSourceParam->num; ++i) { + SColumn* pColumn = taosArrayGetP(pSourceParam->pColumnList, i); + SSchema s = createSchema(pColumn->info.type, pColumn->info.bytes, pColumn->info.colId, pColumn->name) ; + columnListInsert(p, uid, &s, pCol->flag); + } + } + + if (TSDB_COL_IS_NORMAL_COL(pCol->flag)) { + insertPrimaryTsColumn(pQueryInfo->colList, uid); + } } if (finalResult) { - addResColumnInfo(pQueryInfo, outputColIndex, pResultSchema, pExpr); + addResColumnInfo(pQueryInfo, outputIndex, pResultSchema, pExpr); } return pExpr; @@ -1758,7 +1760,15 @@ static int32_t addOneExprInfo(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, i getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &resInfo, 0, false); SSchema resultSchema = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), name); - doAddOneExprInfo(pQueryInfo, outputIndex, functionId, pColIndex, pSchema, &resultSchema, pNode, resInfo.intermediateBytes, name, finalResult); + + STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pColIndex->tableIndex); + + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pSchema->name, pColIndex->type, pSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, pNode, &c); + + doAddOneExprInfo(pQueryInfo, functionId, ¶m, outputIndex, pTableMetaInfo, &resultSchema, resInfo.intermediateBytes, name, finalResult); return TSDB_CODE_SUCCESS; } @@ -1799,7 +1809,12 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab SColumnIndex indexTS = {.tableIndex = tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_ID, .type = TSDB_COL_NORMAL}; SSchema s = createSchema(TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, getNewResColId(), "ts"); - SExprInfo* pExpr = createExprInfo(pTableMetaInfo, FUNCTION_TS_DUMMY, &indexTS, NULL, &s, TSDB_KEYSIZE); + SColumn col = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_NORMAL, &s); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, NULL, &col); + + SExprInfo* pExpr = createExprInfo(pTableMetaInfo, FUNCTION_TS_DUMMY, ¶m, &s, TSDB_KEYSIZE); strncpy(pExpr->base.token, "ts", tListLen(pExpr->base.token)); SArray* pExprList = getCurrentExprList(pQueryInfo); @@ -1909,7 +1924,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); +static int32_t addScalarExprAndResColumn(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, @@ -1943,7 +1958,7 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId // todo extract the table uid pIndex->tableIndex = 0; - int32_t code = createComplexExpr(pQueryInfo, n, pParamElem, pMsgBuf); + int32_t code = addScalarExprAndResColumn(pQueryInfo, n, pParamElem, pMsgBuf); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -1971,7 +1986,7 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId SArray* pExprList = getCurrentExprList(pQueryInfo); size_t n = taosArrayGetSize(pExprList); - int32_t code = createComplexExpr(pQueryInfo, n, pParamElem, pMsgBuf); + int32_t code = addScalarExprAndResColumn(pQueryInfo, n, pParamElem, pMsgBuf); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2048,8 +2063,13 @@ int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSq char token[TSDB_COL_NAME_LEN] = {0}; setTokenAndResColumnName(pItem, s.name, token,sizeof(s.name) - 1); + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &columnSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, pNode, &c); + int32_t outputIndex = getNumOfFields(&pQueryInfo->fieldsInfo); - doAddOneExprInfo(pQueryInfo, outputIndex, functionId, &index, &columnSchema, &s, pNode, size, token, finalResult); + doAddOneExprInfo(pQueryInfo, functionId, ¶m, outputIndex, pTableMetaInfo, &s, size, token, finalResult); return TSDB_CODE_SUCCESS; } @@ -2116,7 +2136,15 @@ int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSq char token[TSDB_COL_NAME_LEN] = {0}; setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, numOfOutput, functionId, &index, &columnSchema, &s, pNode, resInfo.intermediateBytes, token, finalResult); + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &columnSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, pNode, &c); + + SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, functionId, ¶m, numOfOutput, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); + if (finalResult) { + addResColumnInfo(pQueryInfo, numOfOutput, &s, pExpr); + } if (functionId == FUNCTION_LEASTSQR) { // set the leastsquares parameters char val[8] = {0}; @@ -2251,7 +2279,13 @@ int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSq char token[TSDB_COL_NAME_LEN] = {0}; setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, colIndex, functionId, &index, &columnSchema, &s, pNode, resInfo.intermediateBytes, token, finalResult); + + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &columnSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, pNode, &c); + + SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, functionId, ¶m, colIndex, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); SToken* pParamToken = &pParamElem[1].pNode->exprToken; pExpr->base.numOfParams += 1; @@ -2325,23 +2359,19 @@ int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSq columnListInsert(pTableMetaInfo->tagColList, pTableMetaInfo->pTableMeta->uid, &pSchema[index.columnIndex], TSDB_COL_TAG); SSchema* pTagSchema = getTableTagSchema(pTableMetaInfo->pTableMeta); - SSchema s = {0}; - if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - s = *getTbnameColumnSchema(); - } else { - s = pTagSchema[index.columnIndex]; - } + SSchema s = (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX)? *getTbnameColumnSchema(): pTagSchema[index.columnIndex]; SResultDataInfo resInfo = {0}; int32_t ret = getResultDataInfo(s.type, s.bytes, FUNCTION_TID_TAG, 0, &resInfo, 0, 0); assert(ret == TSDB_CODE_SUCCESS); - s.type = (uint8_t)resInfo.type; - s.bytes = resInfo.bytes; - s.colId = getNewResColId(); - TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY); - - doAddOneExprInfo(pQueryInfo, 0, FUNCTION_TID_TAG, &index, &s, &s, NULL, 0, s.name, true); + SSchema result = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), s.name); + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &result); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, NULL, &c); + + /*SExprInfo* pExpr = */doAddOneExprInfo(pQueryInfo, FUNCTION_TID_TAG, ¶m, 0, pTableMetaInfo, &result, 0, s.name, true); return TSDB_CODE_SUCCESS; } @@ -2362,14 +2392,81 @@ int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSq char token[TSDB_COL_NAME_LEN] = {0}; setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, colIndex, functionId, &index, &colSchema, &s, NULL, resInfo.intermediateBytes, token, finalResult); + + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &colSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, NULL, &c); + + SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, functionId, ¶m, colIndex, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); int64_t rowSize = pTableMetaInfo->pTableMeta->tableInfo.rowSize; addExprInfoParam(&pExpr->base, (char*) &rowSize, TSDB_DATA_TYPE_BIGINT, 8); return TSDB_CODE_SUCCESS; } + case FUNCTION_COV: { + // 1. valid the number of parameters + // no parameters or more than one parameter for function + if ((code = checkForkParam(pItem->pNode, 2, pMsgBuf)) != TSDB_CODE_SUCCESS) { + return code; + } + + tSqlExprItem* p1 = taosArrayGet(pItem->pNode->Expr.paramList, 0); + tSqlExprItem* p2 = taosArrayGet(pItem->pNode->Expr.paramList, 1); + int32_t p1Type = p1->pNode->tokenId, p2Type = p2->pNode->tokenId; + if (p1Type != TK_ID || p2Type != TK_ID) { + return buildInvalidOperationMsg(pMsgBuf, msg2); + } + + // validate the first parameter + tExprNode* pNode1 = NULL; + int32_t tokenId1 = p1->pNode->tokenId; + SColumnIndex index1 = COLUMN_INDEX_INITIALIZER; + SSchema columnSchema1 = {0}; + + pQueryInfo->exprListLevelIndex += 1; + + code = extractFunctionParameterInfo(pQueryInfo, tokenId1, &pTableMetaInfo, &columnSchema1, &pNode1, &index1, p1, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + // validate the second parameter + tExprNode* pNode2 = NULL; + int32_t tokenId2 = p1->pNode->tokenId; + SColumnIndex index2 = COLUMN_INDEX_INITIALIZER; + SSchema columnSchema2 = {0}; + code = extractFunctionParameterInfo(pQueryInfo, tokenId2, &pTableMetaInfo, &columnSchema2, &pNode2, &index2, p1, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + pQueryInfo->exprListLevelIndex -= 1; + + int32_t srcType1 = columnSchema1.type, srcType2 = columnSchema2.type; + if (IS_VAR_DATA_TYPE(srcType1) || IS_VAR_DATA_TYPE(columnSchema2.type) || srcType1 == TSDB_DATA_TYPE_TIMESTAMP || + srcType1 == TSDB_DATA_TYPE_BOOL || srcType2 == TSDB_DATA_TYPE_TIMESTAMP || srcType2 == TSDB_DATA_TYPE_BOOL) { + return buildInvalidOperationMsg(pMsgBuf, msg2); + } + + SResultDataInfo resInfo = {.type = TSDB_DATA_TYPE_DOUBLE, .bytes = sizeof(double), .intermediateBytes = 0}; + SSchema s = createSchema(resInfo.type, resInfo.bytes, getNewResColId(), ""); + + char token[TSDB_COL_NAME_LEN] = {0}; + setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); + + SColumn c1 = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index1.type, &columnSchema1); + SColumn c2 = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index2.type, &columnSchema2); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, pNode1, &c1); + addIntoSourceParam(¶m, pNode2, &c2); + + doAddOneExprInfo(pQueryInfo, functionId, ¶m, colIndex, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); + return TSDB_CODE_SUCCESS; + } default: { // pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n); @@ -2406,7 +2503,13 @@ int32_t addAggExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSq char token[TSDB_COL_NAME_LEN] = {0}; setTokenAndResColumnName(pItem, s.name, token, sizeof(s.name) - 1); - doAddOneExprInfo(pQueryInfo, colIndex, functionId, &index, colSchema, &s, NULL, resInfo.intermediateBytes, token, finalResult); + + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, colSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, NULL, &c); + + doAddOneExprInfo(pQueryInfo, functionId, ¶m, colIndex, pTableMetaInfo, &s, resInfo.intermediateBytes, token, finalResult); return TSDB_CODE_SUCCESS; } } @@ -2429,8 +2532,7 @@ static int32_t validateExprLeafColumnNode(SQueryStmtInfo *pQueryInfo, SToken* pC return TSDB_CODE_TSC_INVALID_OPERATION; } - SColumn c = {0}; - setColumn(&c, pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema); + SColumn c = createColumn(pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema); taosArrayPush(pList, &c); return TSDB_CODE_SUCCESS; @@ -2451,7 +2553,7 @@ static int32_t validateExprLeafFunctionNode(SQueryStmtInfo* pQueryInfo, tSqlExpr if (scalar) { printf("scalar function found!\n"); -// if (createComplexExpr(pQueryInfo, outputIndex, &item, pMsgBuf) != TSDB_CODE_SUCCESS) { +// if (addScalarExprAndResColumn(pQueryInfo, outputIndex, &item, pMsgBuf) != TSDB_CODE_SUCCESS) { // return TSDB_CODE_TSC_INVALID_OPERATION; // } } else { @@ -2544,7 +2646,14 @@ SExprInfo* doAddProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, S const char* name = (aliasName == NULL)? pSchema->name:aliasName; SSchema s = createSchema(pSchema->type, pSchema->bytes, colId, name); - return doAddOneExprInfo(pQueryInfo, outputColIndex, functionId, &index, pSchema, &s, NULL, 0, pSchema->name, true); + + STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, NULL, &c); + + return doAddOneExprInfo(pQueryInfo, functionId, ¶m, outputColIndex, pTableMetaInfo, &s, 0, s.name, true); } static int32_t doAddProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex, int32_t startPos) { @@ -2636,7 +2745,13 @@ static int32_t handleTbnameProjection(SQueryStmtInfo* pQueryInfo, tSqlExprItem* 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); + STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, pIndex->type, &colSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, NULL, &c); + + doAddOneExprInfo(pQueryInfo, functionId, ¶m, startPos, pTableMetaInfo, &colSchema, 0, rawName, true); return TSDB_CODE_SUCCESS; } @@ -2671,7 +2786,7 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* } // add the primary timestamp column even though it is not required by user - STableMeta* pTableMeta = pQueryInfo->pTableMetaInfo[index.tableIndex]->pTableMeta; + STableMeta* pTableMeta = getMetaInfo(pQueryInfo, index.tableIndex)->pTableMeta; if (pTableMeta->tableType != TSDB_TEMP_TABLE) { insertPrimaryTsColumn(pQueryInfo->colList, pTableMeta->uid); } @@ -2681,8 +2796,14 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* char token[TSDB_COL_NAME_LEN] = {0}; tstrncpy(token, pItem->pNode->exprToken.z, MIN(TSDB_COL_NAME_LEN, TSDB_COL_NAME_LEN)); - SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, startPos, FUNCTION_PRJ, &index, &colSchema, &colSchema, NULL, 0, token, true); + STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); + SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, &colSchema); + + SSourceParam param = {0}; + addIntoSourceParam(¶m, NULL, &c); + + SExprInfo* pExpr = doAddOneExprInfo(pQueryInfo, FUNCTION_PRJ, ¶m, startPos, pTableMetaInfo, &colSchema, 0, token, true); // 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); @@ -2801,25 +2922,6 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt tExprNode* pLeft = NULL; tExprNode* pRight= NULL; -// if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { -// // assert it is a scalar function -// *pExpr = calloc(1, sizeof(tExprNode)); -// (*pExpr)->nodeType = TEXPR_FUNCTION_NODE; -// (*pExpr)->_function.num = 1; -// (*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n); -// -// SArray* pParamList = pSqlExpr->Expr.paramList; -// size_t num = taosArrayGetSize(pParamList); -// (*pExpr)->_function.pChild = calloc(num, POINTER_BYTES); -// -// for(int32_t i = 0; i < num; ++i) { -// tSqlExprItem* pItem = taosArrayGet(pParamList, i); -// sqlExprToExprNode(&(((*pExpr)->_function.pChild)[0]), pItem->pNode, pQueryInfo, pCols, pMsgBuf); -// } -// -// return TSDB_CODE_SUCCESS; -// } - SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (pSqlExpr->type == SQL_NODE_EXPR) { if (pSqlExpr->pLeft != NULL) { @@ -2877,7 +2979,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt (*pExpr)->_function.pChild = p; (*pExpr)->_function.functionId = functionId; - (*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n + 1); + (*pExpr)->_function.functionName = strndup(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n); return TSDB_CODE_SUCCESS; } else { printf("agg function found, %s\n", pSqlExpr->exprToken.z); @@ -2941,8 +3043,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt assert(found); if (pCols != NULL) { // record the involved columns - SColumn c = {0}; - setColumn(&c, uid, NULL, TSDB_COL_NORMAL, (*pExpr)->pSchema); + SColumn c = createColumn(uid, NULL, TSDB_COL_NORMAL, (*pExpr)->pSchema); taosArrayPush(pCols, &c); } @@ -3042,23 +3143,20 @@ static int32_t multiColumnListInsert(SQueryStmtInfo* pQueryInfo, SArray* pColumn return TSDB_CODE_SUCCESS; } -static int32_t createComplexExpr(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { +static int32_t addScalarExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { 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"; int32_t arithmeticType = NON_ARITHMEIC_EXPR; SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); -// if (validateComplexExpr(pItem->pNode, pQueryInfo, pColumnList, &arithmeticType, pMsgBuf) != TSDB_CODE_SUCCESS) { -// return buildInvalidOperationMsg(pMsgBuf, msg1); -// } - if (arithmeticType == NORMAL_ARITHMETIC) { // expr string is set as the parameter of function SSchema s = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), ""); tExprNode* pNode = NULL; SArray* colList = taosArrayInit(10, sizeof(SColumn)); + int32_t ret = sqlExprToExprNode(&pNode, pItem->pNode, pQueryInfo, colList, pMsgBuf); if (ret != TSDB_CODE_SUCCESS) { taosArrayDestroy(colList); @@ -3198,7 +3296,7 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, } if (scalarFunc) { // scalar function - if ((code = createComplexExpr(pQueryInfo, outputIndex, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { + if ((code = addScalarExprAndResColumn(pQueryInfo, outputIndex, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { return code; } } else { // aggregate function @@ -3214,7 +3312,7 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, return code; } } else if (type == SQL_NODE_EXPR) { - if ((code = createComplexExpr(pQueryInfo, i, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { + if ((code = addScalarExprAndResColumn(pQueryInfo, i, pItem, pMsgBuf)) != TSDB_CODE_SUCCESS) { return code; } } else { diff --git a/source/libs/parser/src/parserUtil.c b/source/libs/parser/src/parserUtil.c index c8e668f2095dca6a91e621831bf01bf99d6b8ed0..a3a6e587852557dce37b9ef08404fd48d328a773 100644 --- a/source/libs/parser/src/parserUtil.c +++ b/source/libs/parser/src/parserUtil.c @@ -527,6 +527,44 @@ void setColumn(SColumn* pColumn, uint64_t uid, const char* tableName, int8_t fla } } +SColumn createColumn(uint64_t uid, const char* tableName, int8_t flag, const SSchema* pSchema) { + SColumn c; + c.uid = uid; + c.flag = flag; + c.info.colId = pSchema->colId; + c.info.bytes = pSchema->bytes; + c.info.type = pSchema->type; + + if (tableName != NULL) { + snprintf(c.name, tListLen(c.name), "%s.%s", tableName, pSchema->name); + } else { + tstrncpy(c.name, pSchema->name, tListLen(c.name)); + } + + return c; +} + +SSourceParam addIntoSourceParam(SSourceParam* pSourceParam, tExprNode* pNode, SColumn* pColumn) { + assert(pSourceParam != NULL); + pSourceParam->num += 1; + + if (pSourceParam->pExprNodeList != NULL) { + assert(pNode != NULL && pColumn == NULL); + if (pSourceParam->pExprNodeList == NULL) { + pSourceParam->pExprNodeList = taosArrayInit(4, POINTER_BYTES); + } + + taosArrayPush(pSourceParam->pExprNodeList, &pNode); + } else { + assert(pColumn != NULL); + if (pSourceParam->pColumnList == NULL) { + pSourceParam->pColumnList = taosArrayInit(4, POINTER_BYTES); + } + + taosArrayPush(pSourceParam->pColumnList, &pColumn); + } +} + int32_t getNumOfFields(SFieldInfo* pFieldInfo) { return pFieldInfo->numOfOutput; } diff --git a/source/libs/parser/src/queryInfoUtil.c b/source/libs/parser/src/queryInfoUtil.c index df5865117917b33e57795db887e01a9055fe9ea2..8d5fc9e9dcbe8b30755beba28b25fe397140e522 100644 --- a/source/libs/parser/src/queryInfoUtil.c +++ b/source/libs/parser/src/queryInfoUtil.c @@ -18,8 +18,14 @@ SSchema* getTbnameColumnSchema() { return &_s; } +SArray* getCurrentExprList(SQueryStmtInfo* pQueryInfo) { + assert(pQueryInfo != NULL && pQueryInfo->exprListLevelIndex >= 0 && pQueryInfo->exprListLevelIndex < 10); + return pQueryInfo->exprList[pQueryInfo->exprListLevelIndex]; +} + size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo) { - return taosArrayGetSize(pQueryInfo->exprList[0]); + SArray* pExprList = getCurrentExprList(pQueryInfo); + return taosArrayGetSize(pExprList); } SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) { @@ -55,21 +61,29 @@ SSchema* getTableTagSchema(const STableMeta* pTableMeta) { return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns); } -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; - pColumnNode->pSchema = calloc(1, sizeof(SSchema)); - memcpy(pColumnNode->pSchema, pSchema, sizeof(SSchema)); +static tExprNode* createFunctionExprNode(int32_t functionId, struct SSourceParam *pParam) {//SSchema* pSchema, tExprNode* pColumnNode, int32_t numOfCols) { + tExprNode** p = malloc(pParam->num * POINTER_BYTES); + + if (pParam->pColumnList != NULL) { + for(int32_t i = 0; i < pParam->num; ++i) { + p[i] = calloc(1, sizeof(tExprNode)); + p[i]->nodeType = TEXPR_COL_NODE; + p[i]->pSchema = calloc(1, sizeof(SSchema)); + memcpy(p[i]->pSchema, taosArrayGetP(pParam->pColumnList, i), sizeof(SSchema)); + } } else { - assert(pSchema == NULL); + assert(pParam->pColumnList == NULL); + for(int32_t i = 0; i < pParam->num; ++i) { + p[i] = taosArrayGetP(pParam->pExprNodeList, i); + } } tExprNode* pNode = calloc(1, sizeof(tExprNode)); + pNode->nodeType = TEXPR_FUNCTION_NODE; pNode->_function.functionId = functionId; - pNode->_function.pChild = pColumnNode; - pNode->_function.num = numOfCols; + pNode->_function.pChild = p; + pNode->_function.num = pParam->num; return pNode; } @@ -87,7 +101,7 @@ SExprInfo* createBinaryExprInfo(tExprNode* pNode, SSchema* pResSchema) { return pExpr; } -SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SColumnIndex* pColIndex, tExprNode* pParamExpr, SSchema* pResSchema, int16_t interSize) { +SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SSourceParam* pSourceParam, SSchema* pResSchema, int16_t interSize) { SExprInfo* pExpr = calloc(1, sizeof(SExprInfo)); if (pExpr == NULL) { return NULL; @@ -99,43 +113,36 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC } SSqlExpr* p = &pExpr->base; - p->pColumns = calloc(1, sizeof(SColumn)); - p->numOfCols = 1; - if (pParamExpr != NULL) { - pExpr->pExpr = createFunctionExprNode(functionId, NULL, pParamExpr, 1); - // todo set the correct number of columns - } else if (pColIndex->columnIndex == TSDB_TBNAME_COLUMN_INDEX) { - assert(pParamExpr == NULL); + p->pColumns = calloc(pSourceParam->num, sizeof(SColumn)); + p->numOfCols = pSourceParam->num; + p->interBytes = interSize; + memcpy(&p->resSchema, pResSchema, sizeof(SSchema)); + + if (pSourceParam->pExprNodeList != NULL) { + pExpr->pExpr = createFunctionExprNode(functionId, pSourceParam); + return pExpr; + } + + SColumn* pCol = taosArrayGetP(pSourceParam->pColumnList, 0); + if (pCol->info.colId == TSDB_TBNAME_COLUMN_INDEX) { + assert(pSourceParam->num == 1); SSchema* s = getTbnameColumnSchema(); 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); + pExpr->pExpr = createFunctionExprNode(functionId, pSourceParam); + } else if (TSDB_COL_IS_UD_COL(pCol->flag) || functionId == FUNCTION_BLKINFO) { setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_UDC, pResSchema); - - SSchema s = createSchema(pResSchema->type, pResSchema->bytes, pColIndex->columnIndex, pResSchema->name); - pExpr->pExpr = createFunctionExprNode(functionId, &s, pParamExpr, 1); + pExpr->pExpr = createFunctionExprNode(functionId, pSourceParam); } else { - if (TSDB_COL_IS_TAG(pColIndex->type)) { - SSchema* pSchema = getTableTagSchema(pTableMetaInfo->pTableMeta); - 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); - setColumn(p->pColumns, uid, pTableMetaInfo->aliasName, TSDB_COL_NORMAL, pSchema); - - pExpr->pExpr = createFunctionExprNode(functionId, pSchema, pParamExpr, 1); + for(int32_t i = 0; i < pSourceParam->num; ++i) { + SColumn* c = taosArrayGetP(pSourceParam->pColumnList, i); + p->pColumns[i] = *c; } + pExpr->pExpr = createFunctionExprNode(functionId, pSourceParam); } - p->pColumns->flag = pColIndex->type; - p->interBytes = interSize; - memcpy(&p->resSchema, pResSchema, sizeof(SSchema)); - return pExpr; } @@ -149,7 +156,7 @@ void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t taosArrayInsert(pExprList, index, &pExprInfo); } - printf("add function, id:%d, level:%d\n", pExprInfo->pExpr->_function.functionId, level); + printf("add function, id:%d, level:%d, total:%ld\n", pExprInfo->pExpr->_function.functionId, level, taosArrayGetSize(pExprList)); } void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize) { diff --git a/source/libs/parser/test/parserTests.cpp b/source/libs/parser/test/parserTests.cpp index 24b62d1313594398605042ecc20aef26f99af04c..a3916bbc06888c5a9e517e8c560408e53541f700 100644 --- a/source/libs/parser/test/parserTests.cpp +++ b/source/libs/parser/test/parserTests.cpp @@ -394,14 +394,14 @@ void sqlCheck(const char* sql, bool valid) { //} TEST(testCase, function_Test10) { -// sqlCheck("select c from `t.1abc`", true); -// sqlCheck("select length(c) from `t.1abc`", true); -// sqlCheck("select sum(length(a+b)) from `t.1abc`", true); -// sqlCheck("select sum(sum(a+b)) from `t.1abc`", false); -// sqlCheck("select sum(length(a) + length(b)) from `t.1abc`", true); -// sqlCheck("select length(sum(a) + sum(b)) + length(sum(a) + sum(b)) from `t.1abc`", true); -// sqlCheck("select sum(length(sum(a))) from `t.1abc`", true); - sqlCheck("select concat(a,b) from `t.1abc`", true); + sqlCheck("select c from `t.1abc`", true); + sqlCheck("select length(c) from `t.1abc`", true); + sqlCheck("select sum(length(a+b)) from `t.1abc`", true); + sqlCheck("select sum(sum(a+b)) from `t.1abc`", false); + sqlCheck("select sum(length(a) + length(b)) from `t.1abc`", true); + sqlCheck("select length(sum(a) + sum(b)) + length(sum(a) + sum(b)) from `t.1abc`", true); + sqlCheck("select sum(length(sum(a))) from `t.1abc`", true); + sqlCheck("select cov(a, b) from `t.1abc`", true); // sqlCheck("select concat(concat(a,b), concat(a,b)) from `t.1abc`", true); // sqlCheck("select length(length(length(a))) from `t.1abc`", true); } diff --git a/source/libs/planner/src/planner.c b/source/libs/planner/src/planner.c index 53631fc9f1ff9b2bf082e51acf83b42b232168de..81404d74ca8586b67c7832f7358bc196c8189f27 100644 --- a/source/libs/planner/src/planner.c +++ b/source/libs/planner/src/planner.c @@ -191,7 +191,7 @@ static SQueryPlanNode* doAddTableColumnNode(SQueryStmtInfo* pQueryInfo, STableMe SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, i); SSchema resultSchema = *pSchema; - SExprInfo* p = createExprInfo(pTableMetaInfo1, FUNCTION_PRJ, &index, NULL, &resultSchema, 0); + SExprInfo* p = NULL;//createExprInfo(pTableMetaInfo1, FUNCTION_PRJ, &index, NULL, &resultSchema, 0); pExpr[i] = p; }