From 103418bfc50edd85a823b6b3e52ac31e8fa2b976 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Mon, 25 Apr 2022 20:28:14 +0800 Subject: [PATCH] fix: some problems of udf and 'create table' --- include/libs/nodes/querynodes.h | 3 +- source/client/src/clientMain.c | 2 +- source/libs/nodes/src/nodesCodeFuncs.c | 11 +- source/libs/parser/src/parCalcConst.c | 323 +++++++++++++------------ source/libs/parser/src/parTranslater.c | 5 +- source/libs/scalar/src/scalar.c | 4 + 6 files changed, 181 insertions(+), 167 deletions(-) diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 87c95413d7..c71fb266b1 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -46,7 +46,7 @@ typedef struct SExprNode { ENodeType type; SDataType resType; char aliasName[TSDB_COL_NAME_LEN]; - SNodeList* pAssociationList; + SArray* pAssociation; } SExprNode; typedef enum EColumnType { @@ -81,7 +81,6 @@ typedef struct SValueNode { char* literal; bool isDuration; bool translate; - bool genByCalc; int16_t placeholderNo; union { bool b; diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 27efcee76e..a9efcced40 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -120,7 +120,7 @@ const char *taos_errstr(TAOS_RES *res) { return (const char *)tstrerror(terrno); } - if (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR) { + if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) { return pRequest->msgBuf; } else { return (const char *)tstrerror(pRequest->code); diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index 046a5368d9..1d54448e55 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -1663,7 +1663,7 @@ static int32_t jsonToColumnNode(const SJson* pJson, void* pObj) { return code; } -static const char* jkValueGenByCalc = "GenByCalc"; +static const char* jkValueLiteralSize = "LiteralSize"; static const char* jkValueLiteral = "Literal"; static const char* jkValueDuration = "Duration"; static const char* jkValueTranslate = "Translate"; @@ -1717,9 +1717,9 @@ static int32_t valueNodeToJson(const void* pObj, SJson* pJson) { int32_t code = exprNodeToJson(pObj, pJson); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddBoolToObject(pJson, jkValueGenByCalc, pNode->genByCalc); + code = tjsonAddIntegerToObject(pJson, jkValueLiteralSize, NULL != pNode->literal ? strlen(pNode->literal) : 0); } - if (TSDB_CODE_SUCCESS == code && !pNode->genByCalc) { + if (TSDB_CODE_SUCCESS == code && NULL != pNode->literal) { code = tjsonAddStringToObject(pJson, jkValueLiteral, pNode->literal); } if (TSDB_CODE_SUCCESS == code) { @@ -1789,10 +1789,11 @@ static int32_t jsonToValueNode(const SJson* pJson, void* pObj) { SValueNode* pNode = (SValueNode*)pObj; int32_t code = jsonToExprNode(pJson, pObj); + int32_t literalSize = 0; if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetBoolValue(pJson, jkValueGenByCalc, &pNode->genByCalc); + code = tjsonGetIntValue(pJson, jkValueLiteralSize, &literalSize); } - if (TSDB_CODE_SUCCESS == code && !pNode->genByCalc) { + if (TSDB_CODE_SUCCESS == code && literalSize > 0) { code = tjsonDupStringValue(pJson, jkValueLiteral, &pNode->literal); } if (TSDB_CODE_SUCCESS == code) { diff --git a/source/libs/parser/src/parCalcConst.c b/source/libs/parser/src/parCalcConst.c index 51e0daf4ad..bd1ed32acd 100644 --- a/source/libs/parser/src/parCalcConst.c +++ b/source/libs/parser/src/parCalcConst.c @@ -24,109 +24,37 @@ typedef struct SCalcConstContext { int32_t code; } SCalcConstContext; -static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt); +static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery); + +static int32_t calcConstSubquery(SCalcConstContext* pCxt, STempTableNode* pTempTable) { + return calcConstQuery(pCxt, pTempTable->pSubquery, true); +} + +static int32_t calcConstNode(SNode** pNode) { + if (NULL == *pNode) { + return TSDB_CODE_SUCCESS; + } -static EDealRes doCalcConst(SNode** pNode, SCalcConstContext* pCxt) { SNode* pNew = NULL; - pCxt->code = scalarCalculateConstants(*pNode, &pNew); - if (TSDB_CODE_SUCCESS != pCxt->code) { - return DEAL_RES_ERROR; + int32_t code = scalarCalculateConstants(*pNode, &pNew); + if (TSDB_CODE_SUCCESS == code) { + *pNode = pNew; } - ((SValueNode*)pNew)->genByCalc = true; - ((SValueNode*)pNew)->translate = true; - *pNode = pNew; - return DEAL_RES_CONTINUE; + return code; } -static bool isTimestampCol(SNode* pNode) { - if (NULL == pNode) { - return false; - } - return (QUERY_NODE_COLUMN == nodeType(pNode) && TSDB_DATA_TYPE_TIMESTAMP == ((SExprNode*)pNode)->resType.type); -} - -static EDealRes stringToTimestamp(SCalcConstContext* pCxt, uint8_t precision, SValueNode* pVal) { - switch (pVal->node.resType.type) { - case TSDB_DATA_TYPE_VARCHAR: - case TSDB_DATA_TYPE_NCHAR: - case TSDB_DATA_TYPE_VARBINARY: { - int64_t val = 0; - if (TSDB_CODE_SUCCESS != convertStringToTimestamp(pVal->node.resType.type, pVal->datum.p, precision, &val)) { - pCxt->code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INCORRECT_TIMESTAMP_VAL, varDataVal(pVal->datum.p)); - return DEAL_RES_ERROR; - } - pVal->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP; - pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes; - taosMemoryFreeClear(pVal->datum.p); - pVal->datum.i = val; - break; - } - default: - break; - } - return DEAL_RES_CONTINUE; -} - -static EDealRes calcConstOperator(SOperatorNode** pNode, void* pContext) { - SCalcConstContext* pCxt = pContext; - SOperatorNode* pOp = *pNode; - if (QUERY_NODE_VALUE == nodeType(pOp->pLeft) && (NULL == pOp->pRight || QUERY_NODE_VALUE == nodeType(pOp->pRight))) { - return doCalcConst((SNode**)pNode, pCxt); - } - if (isTimestampCol(pOp->pLeft) && (NULL == pOp->pRight || QUERY_NODE_VALUE == nodeType(pOp->pRight))) { - return stringToTimestamp(pCxt, ((SColumnNode*)pOp->pLeft)->node.resType.precision, (SValueNode*)pOp->pRight); - } else if (isTimestampCol(pOp->pRight) && QUERY_NODE_VALUE == nodeType(pOp->pLeft)) { - return stringToTimestamp(pCxt, ((SColumnNode*)pOp->pRight)->node.resType.precision, (SValueNode*)pOp->pLeft); - } - return DEAL_RES_CONTINUE; -} - -static EDealRes calcConstFunction(SFunctionNode** pNode, void* pContext) { - SFunctionNode* pFunc = *pNode; - if (!fmIsScalarFunc(pFunc->funcId) || fmIsUserDefinedFunc(pFunc->funcId)) { - return DEAL_RES_CONTINUE; - } - SNode* pParam = NULL; - FOREACH(pParam, pFunc->pParameterList) { - if (QUERY_NODE_VALUE != nodeType(pParam)) { - return DEAL_RES_CONTINUE; +static int32_t calcConstList(SNodeList* pList) { + SNode* pNode = NULL; + FOREACH(pNode, pList) { + SNode* pNew = NULL; + int32_t code = scalarCalculateConstants(pNode, &pNew); + if (TSDB_CODE_SUCCESS == code) { + REPLACE_NODE(pNew); + } else { + return code; } } - return doCalcConst((SNode**)pNode, (SCalcConstContext*)pContext); -} - -static EDealRes calcConstLogicCond(SLogicConditionNode** pNode, void* pContext) { - SLogicConditionNode* pCond = *pNode; - SNode* pParam = NULL; - FOREACH(pParam, pCond->pParameterList) { - // todo calc "true and c1 > 10" - if (QUERY_NODE_VALUE != nodeType(pParam)) { - return DEAL_RES_CONTINUE; - } - } - return doCalcConst((SNode**)pNode, (SCalcConstContext*)pContext); -} - -static EDealRes calcConstSubquery(STempTableNode** pNode, void* pContext) { - SCalcConstContext* pCxt = pContext; - pCxt->code = calcConstQuery(pCxt, (*pNode)->pSubquery); - return (TSDB_CODE_SUCCESS == pCxt->code ? DEAL_RES_CONTINUE : DEAL_RES_ERROR); -} - -static EDealRes calcConst(SNode** pNode, void* pContext) { - switch (nodeType(*pNode)) { - case QUERY_NODE_OPERATOR: - return calcConstOperator((SOperatorNode**)pNode, pContext); - case QUERY_NODE_FUNCTION: - return calcConstFunction((SFunctionNode**)pNode, pContext); - case QUERY_NODE_LOGIC_CONDITION: - return calcConstLogicCond((SLogicConditionNode**)pNode, pContext); - case QUERY_NODE_TEMP_TABLE: - return calcConstSubquery((STempTableNode**)pNode, pContext); - default: - break; - } - return DEAL_RES_CONTINUE; + return TSDB_CODE_SUCCESS; } static bool isCondition(const SNode* pNode) { @@ -174,18 +102,41 @@ static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) { return pCxt->code; } -static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) { - if (QUERY_NODE_JOIN_TABLE == nodeType(pTable)) { - SJoinTableNode* pJoin = (SJoinTableNode*)pTable; - pCxt->code = rewriteConditionForFromTable(pCxt, pJoin->pLeft); - if (TSDB_CODE_SUCCESS == pCxt->code) { - pCxt->code = rewriteConditionForFromTable(pCxt, pJoin->pRight); - } - if (TSDB_CODE_SUCCESS == pCxt->code && NULL != pJoin->pOnCond) { - pCxt->code = rewriteCondition(pCxt, &pJoin->pOnCond); - } +static int32_t calcConstCondition(SCalcConstContext* pCxt, SNode** pNode) { + int32_t code = rewriteCondition(pCxt, pNode); + if (TSDB_CODE_SUCCESS == code) { + code = calcConstNode(pNode); } - return pCxt->code; + return code; +} + +static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) { + int32_t code = TSDB_CODE_SUCCESS; + switch (nodeType(pTable)) { + case QUERY_NODE_TEMP_TABLE: { + code = calcConstSubquery(pCxt, (STempTableNode*)pTable); + break; + } + case QUERY_NODE_JOIN_TABLE: { + SJoinTableNode* pJoin = (SJoinTableNode*)pTable; + code = rewriteConditionForFromTable(pCxt, pJoin->pLeft); + if (TSDB_CODE_SUCCESS == code) { + code = rewriteConditionForFromTable(pCxt, pJoin->pRight); + } + if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) { + code = calcConstCondition(pCxt, &pJoin->pOnCond); + } + // todo empty table + break; + } + default: + break; + } + return code; +} + +static int32_t calcConstFromTable(SCalcConstContext* pCxt, SSelectStmt* pSelect) { + return rewriteConditionForFromTable(pCxt, pSelect->pFromTable); } static void rewriteConstCondition(SSelectStmt* pSelect, SNode** pCond) { @@ -200,77 +151,133 @@ static void rewriteConstCondition(SSelectStmt* pSelect, SNode** pCond) { } } -static int32_t calcConstFromTable(SCalcConstContext* pCxt, SSelectStmt* pSelect) { - pCxt->code = rewriteConditionForFromTable(pCxt, pSelect->pFromTable); - if (TSDB_CODE_SUCCESS == pCxt->code) { - nodesRewriteExprPostOrder(&pSelect->pFromTable, calcConst, pCxt); - } - return pCxt->code; -} - -static int32_t calcConstCondition(SCalcConstContext* pCxt, SSelectStmt* pSelect, SNode** pCond) { +static int32_t calcConstSelectCondition(SCalcConstContext* pCxt, SSelectStmt* pSelect, SNode** pCond) { if (NULL == *pCond) { return TSDB_CODE_SUCCESS; } - pCxt->code = rewriteCondition(pCxt, pCond); - if (TSDB_CODE_SUCCESS == pCxt->code) { - nodesRewriteExprPostOrder(pCond, calcConst, pCxt); + int32_t code = rewriteCondition(pCxt, pCond); + if (TSDB_CODE_SUCCESS == code) { + code = calcConstNode(pCond); } - if (TSDB_CODE_SUCCESS == pCxt->code) { + if (TSDB_CODE_SUCCESS == code) { rewriteConstCondition(pSelect, pCond); } - return pCxt->code; + return code; } -static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect) { - nodesRewriteExprsPostOrder(pSelect->pProjectionList, calcConst, pCxt); - if (TSDB_CODE_SUCCESS == pCxt->code) { - pCxt->code = calcConstFromTable(pCxt, pSelect); +static int32_t calcConstProject(SNode* pProject, SNode** pNew) { + SArray* pAssociation = NULL; + if (NULL != ((SExprNode*)pProject)->pAssociation) { + pAssociation == taosArrayDup(((SExprNode*)pProject)->pAssociation); + if (NULL == pAssociation) { + return TSDB_CODE_OUT_OF_MEMORY; + } } - if (TSDB_CODE_SUCCESS == pCxt->code) { - pCxt->code = calcConstCondition(pCxt, pSelect, &pSelect->pWhere); + + int32_t code = scalarCalculateConstants(pProject, pNew); + if (TSDB_CODE_SUCCESS == code && QUERY_NODE_VALUE == nodeType(pNew) && NULL != pAssociation) { + int32_t size = taosArrayGetSize(pAssociation); + for (int32_t i = 0; i < size; ++i) { + SNode** pCol = taosArrayGet(pAssociation, i); + *pCol = nodesCloneNode(pNew); + if (NULL == *pCol) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } } - if (TSDB_CODE_SUCCESS == pCxt->code) { - nodesRewriteExprsPostOrder(pSelect->pPartitionByList, calcConst, pCxt); - } - if (TSDB_CODE_SUCCESS == pCxt->code) { - nodesRewriteExprPostOrder(&pSelect->pWindow, calcConst, pCxt); - } - if (TSDB_CODE_SUCCESS == pCxt->code) { - nodesRewriteExprsPostOrder(pSelect->pGroupByList, calcConst, pCxt); - } - if (TSDB_CODE_SUCCESS == pCxt->code) { - pCxt->code = calcConstCondition(pCxt, pSelect, &pSelect->pHaving); - } - if (TSDB_CODE_SUCCESS == pCxt->code) { - nodesRewriteExprsPostOrder(pSelect->pOrderByList, calcConst, pCxt); - } - return pCxt->code; + return code; } -static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt) { - switch (nodeType(pStmt)) { - case QUERY_NODE_SELECT_STMT: - return calcConstSelect(pCxt, (SSelectStmt*)pStmt); - case QUERY_NODE_EXPLAIN_STMT: - return calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery); - default: - break; +static int32_t calcConstProjections(SCalcConstContext* pCxt, SNodeList* pProjections, bool subquery) { + SNode* pProj = NULL; + WHERE_EACH(pProj, pProjections) { + if (subquery && NULL == ((SExprNode*)pProj)->pAssociation) { + ERASE_NODE(pProjections); + continue; + } + SNode* pNew = NULL; + int32_t code = calcConstProject(pProj, &pNew); + if (TSDB_CODE_SUCCESS == code) { + REPLACE_NODE(pNew); + } else { + return code; + } + WHERE_NEXT; } return TSDB_CODE_SUCCESS; } -static bool isEmptyResultQuery(SNode* pStmt) { +static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) { + int32_t code = calcConstProjections(pCxt, pSelect->pProjectionList, subquery); + if (TSDB_CODE_SUCCESS == code) { + code = calcConstFromTable(pCxt, pSelect); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstSelectCondition(pCxt, pSelect, &pSelect->pWhere); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstList(pSelect->pPartitionByList); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstNode(&pSelect->pWindow); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstList(pSelect->pGroupByList); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstSelectCondition(pCxt, pSelect, &pSelect->pHaving); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstList(pSelect->pOrderByList); + } + return code; +} + +static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) { + int32_t code = TSDB_CODE_SUCCESS; switch (nodeType(pStmt)) { case QUERY_NODE_SELECT_STMT: - return ((SSelectStmt*)pStmt)->isEmptyResult; + code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery); + break; case QUERY_NODE_EXPLAIN_STMT: - return isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery); + code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery); + break; + case QUERY_NODE_SET_OPERATOR: { + SSetOperator* pSetOp = (SSetOperator*)pStmt; + code = calcConstQuery(pCxt, pSetOp->pLeft, subquery); + if (TSDB_CODE_SUCCESS == code) { + code = calcConstQuery(pCxt, pSetOp->pRight, subquery); + } + break; + } default: break; } - return false; + return code; +} + +static bool isEmptyResultQuery(SNode* pStmt) { + bool isEmptyResult = false; + switch (nodeType(pStmt)) { + case QUERY_NODE_SELECT_STMT: + isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult; + break; + case QUERY_NODE_EXPLAIN_STMT: + isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery); + break; + case QUERY_NODE_SET_OPERATOR: { + SSetOperator* pSetOp = (SSetOperator*)pStmt; + isEmptyResult = isEmptyResultQuery(pSetOp->pLeft); + if (isEmptyResult) { + isEmptyResult = isEmptyResultQuery(pSetOp->pRight); + } + break; + } + default: + break; + } + return isEmptyResult; } int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) { @@ -280,9 +287,9 @@ int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) { .msgBuf.len = pParseCxt->msgLen, .code = TSDB_CODE_SUCCESS }; - int32_t code = calcConstQuery(&cxt, pQuery->pRoot); - if (TSDB_CODE_SUCCESS == code) { - pQuery->execMode = isEmptyResultQuery(pQuery->pRoot) ? QUERY_EXEC_MODE_EMPTY_RESULT : pQuery->execMode; + int32_t code = calcConstQuery(&cxt, pQuery->pRoot, false); + if (TSDB_CODE_SUCCESS == code && isEmptyResultQuery(pQuery->pRoot)) { + pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT; } return code; } diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index afbd0b416d..a2a12e84b1 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -306,7 +306,10 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SColumnNode* pCol) { pCol->pProjectRef = (SNode*)pExpr; - nodesListAppend(pExpr->pAssociationList, (SNode*)pCol); + if (NULL == pExpr->pAssociation) { + pExpr->pAssociation = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); + } + taosArrayPush(pExpr->pAssociation, &pCol); if (NULL != pTable) { strcpy(pCol->tableAlias, pTable->tableAlias); } else if (QUERY_NODE_COLUMN == nodeType(pExpr)) { diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index 820a4894b5..11a76a38ea 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -511,6 +511,8 @@ EDealRes sclRewriteFunction(SNode** pNode, SScalarCtx *ctx) { return DEAL_RES_ERROR; } + res->translate = true; + if (colDataIsNull_s(output.columnData, 0)) { res->node.resType.type = TSDB_DATA_TYPE_NULL; } else { @@ -553,6 +555,7 @@ EDealRes sclRewriteLogic(SNode** pNode, SScalarCtx *ctx) { } res->node.resType = node->node.resType; + res->translate = true; int32_t type = output.columnData->info.type; if (IS_VAR_DATA_TYPE(type)) { @@ -595,6 +598,7 @@ EDealRes sclRewriteOperator(SNode** pNode, SScalarCtx *ctx) { } res->node.resType = node->node.resType; + res->translate = true; int32_t type = output.columnData->info.type; if (IS_VAR_DATA_TYPE(type)) { // todo refactor