diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index ee986d5aab..44a034aa7b 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -236,6 +236,8 @@ typedef struct SSelectStmt { bool isTimeOrderQuery; bool hasAggFuncs; bool hasRepeatScanFuncs; + bool hasNonstdSQLFunc; + bool hasProjCol; } SSelectStmt; typedef enum ESetOperatorType { SET_OP_TYPE_UNION_ALL = 1, SET_OP_TYPE_UNION } ESetOperatorType; diff --git a/include/util/taoserror.h b/include/util/taoserror.h index fd3e008e67..5c251e7a27 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -649,6 +649,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_INVALID_TBNAME TAOS_DEF_ERROR_CODE(0, 0x264C) #define TSDB_CODE_PAR_INVALID_FUNCTION_NAME TAOS_DEF_ERROR_CODE(0, 0x264D) #define TSDB_CODE_PAR_COMMENT_TOO_LONG TAOS_DEF_ERROR_CODE(0, 0x264E) +#define TSDB_CODE_PAR_NOT_ALLOWED_FUNC TAOS_DEF_ERROR_CODE(0, 0x264F) //planner #define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700) diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 074a5bc30c..e6eda57cab 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -53,6 +53,8 @@ static bool afterGroupBy(ESqlClause clause) { return clause > SQL_CLAUSE_GROUP_B static bool beforeHaving(ESqlClause clause) { return clause < SQL_CLAUSE_HAVING; } +static bool afterHaving(ESqlClause clause) { return clause > SQL_CLAUSE_HAVING; } + static int32_t addNamespace(STranslateContext* pCxt, void* pTable) { size_t currTotalLevel = taosArrayGetSize(pCxt->pNsLevel); if (currTotalLevel > pCxt->currLevel) { @@ -276,6 +278,10 @@ static bool isScanPseudoColumnFunc(const SNode* pNode) { return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsScanPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)); } +static bool isNonstandardSQLFunc(const SNode* pNode) { + return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsNonstandardSQLFunc(((SFunctionNode*)pNode)->funcId)); +} + static bool isDistinctOrderBy(STranslateContext* pCxt) { return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct); } @@ -433,6 +439,7 @@ static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNod SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); size_t nums = taosArrayGetSize(pTables); bool found = false; + bool isInternalPk = isInternalPrimaryKey(pCol); for (size_t i = 0; i < nums; ++i) { STableNode* pTable = taosArrayGetP(pTables, i); if (findAndSetColumn(pCol, pTable)) { @@ -440,10 +447,13 @@ static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNod return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName); } found = true; + if (isInternalPk) { + break; + } } } if (!found) { - if (isInternalPrimaryKey(pCol)) { + if (isInternalPk) { return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_INTERNAL_PK); } else { return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName); @@ -481,6 +491,9 @@ static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode* pCol) { } res = (found ? DEAL_RES_CONTINUE : translateColumnWithoutPrefix(pCxt, pCol)); } + if (afterHaving(pCxt->currClause)) { + pCxt->pCurrStmt->hasProjCol = true; + } return res; } @@ -783,6 +796,16 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_TBNAME); } } + if (afterHaving(pCxt->currClause)) { + pCxt->pCurrStmt->hasProjCol = true; + } + } + if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsNonstandardSQLFunc(pFunc->funcId)) { + if (SQL_CLAUSE_SELECT != pCxt->currClause || pCxt->pCurrStmt->hasNonstdSQLFunc || pCxt->pCurrStmt->hasAggFuncs || + pCxt->pCurrStmt->hasProjCol) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_NOT_ALLOWED_FUNC, pFunc->functionName); + } + pCxt->pCurrStmt->hasNonstdSQLFunc = true; } return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR; } diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index 7b9147beab..d6ecf16521 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -164,6 +164,9 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "Invalid function name"; case TSDB_CODE_PAR_COMMENT_TOO_LONG: return "Comment too long"; + case TSDB_CODE_PAR_NOT_ALLOWED_FUNC: + return "%s are allowed only in the SELECT list of a query. " + "And, cannot be mixed with other non scalar functions or columns."; case TSDB_CODE_OUT_OF_MEMORY: return "Out of memory"; default: diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c index fb716af3e5..a87c00bea9 100644 --- a/source/libs/planner/src/planSpliter.c +++ b/source/libs/planner/src/planSpliter.c @@ -24,9 +24,9 @@ #define SPLIT_FLAG_TEST_MASK(val, mask) (((val) & (mask)) != 0) typedef struct SSplitContext { - int32_t queryId; - int32_t groupId; - bool split; + uint64_t queryId; + int32_t groupId; + bool split; } SSplitContext; typedef int32_t (*FSplit)(SSplitContext* pCxt, SLogicSubplan* pSubplan);