cols
This commit is contained in:
parent
d3fa16b998
commit
d3e86d9854
|
@ -907,6 +907,9 @@ int32_t taosGetErrSize();
|
|||
#define TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE TAOS_DEF_ERROR_CODE(0, 0x2685)
|
||||
#define TSDB_CODE_PAR_INVALID_VGID_LIST TAOS_DEF_ERROR_CODE(0, 0x2686)
|
||||
#define TSDB_CODE_PAR_INVALID_COLS_FUNCTION TAOS_DEF_ERROR_CODE(0, 0x2687)
|
||||
#define TSDB_CODE_PAR_INVALID_COLS_SELECTFUNC TAOS_DEF_ERROR_CODE(0, 0x2688)
|
||||
#define TSDB_CODE_INVALID_MULITI_COLS_FUNC TAOS_DEF_ERROR_CODE(0, 0x2688)
|
||||
#define TSDB_CODE_INVALID_COLS_ALIAS TAOS_DEF_ERROR_CODE(0, 0x2689)
|
||||
#define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x26FF)
|
||||
|
||||
//planner
|
||||
|
|
|
@ -1696,6 +1696,10 @@ static int32_t translateOutVarchar(SFunctionNode* pFunc, char* pErrBuf, int32_t
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateColsFunction(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
}
|
||||
|
||||
static int32_t translateHistogramImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
FUNC_ERR_RET(validateParam(pFunc, pErrBuf, len));
|
||||
int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
|
||||
|
@ -5644,6 +5648,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
},
|
||||
{
|
||||
.name = "cols",
|
||||
.translateFunc = translateColsFunction,
|
||||
},
|
||||
};
|
||||
// clang-format on
|
||||
|
|
|
@ -1076,6 +1076,14 @@ static bool isForecastPseudoColumnFunc(const SNode* pNode) {
|
|||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsForecastPseudoColumnFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
static bool isColsFunctionResult(const SNode* pNode) {
|
||||
return ((nodesIsExprNode(pNode)) && ((SExprNode*)pNode)->bindTupleFuncIdx > 0);
|
||||
}
|
||||
|
||||
static bool isInvalidColsBindFunction(const SFunctionNode* pFunc) {
|
||||
return (!fmIsSelectFunc(pFunc->funcId) && pFunc->node.tupleFuncIdx != 0);
|
||||
}
|
||||
|
||||
#ifdef BUILD_NO_CALL
|
||||
static bool isTimelineFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsTimelineFunc(((SFunctionNode*)pNode)->funcId));
|
||||
|
@ -2311,7 +2319,7 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
|||
|
||||
static EDealRes haveVectorFunction(SNode* pNode, void* pContext) {
|
||||
if (isAggFunc(pNode) || isIndefiniteRowsFunc(pNode) || isWindowPseudoColumnFunc(pNode) ||
|
||||
isInterpPseudoColumnFunc(pNode) || isForecastPseudoColumnFunc(pNode)) {
|
||||
isInterpPseudoColumnFunc(pNode) || isForecastPseudoColumnFunc(pNode) || isColsFunctionResult(pNode)) {
|
||||
*((bool*)pContext) = true;
|
||||
return DEAL_RES_END;
|
||||
}
|
||||
|
@ -3298,6 +3306,10 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode** pFunc
|
|||
pCxt->errCode = TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION;
|
||||
}
|
||||
}
|
||||
if (isInvalidColsBindFunction(*pFunc)) {
|
||||
pCxt->errCode = TSDB_CODE_PAR_INVALID_COLS_SELECTFUNC;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
pCxt->errCode = translateFunctionImpl(pCxt, pFunc);
|
||||
}
|
||||
|
@ -3813,7 +3825,7 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
if (isVectorFunc(*pNode) && !isDistinctOrderBy(pCxt)) {
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
if (isColsFunc(*pNode)) {
|
||||
if (isColsFunctionResult(*pNode)) {
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
SNode* pGroupNode = NULL;
|
||||
|
@ -3918,10 +3930,10 @@ static EDealRes doCheckAggColCoexist(SNode** pNode, void* pContext) {
|
|||
if (isVectorFunc(*pNode)) {
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
if(isColsFunc(*pNode)) {
|
||||
if(isColsFunctionResult(*pNode)) {
|
||||
pCxt->hasColFunc = true;
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
|
||||
SNode* pPartKey = NULL;
|
||||
bool partionByTbname = false;
|
||||
if (fromSingleTable(((SSelectStmt*)pCxt->pTranslateCxt->pCurrStmt)->pFromTable) ||
|
||||
|
@ -7300,7 +7312,8 @@ static int32_t translateSelectWithoutFrom(STranslateContext* pCxt, SSelectStmt*
|
|||
}
|
||||
typedef struct SCheckColsFuncCxt {
|
||||
bool hasColsFunc;
|
||||
bool hasMultiColsFunc;
|
||||
SNodeList** selectFuncList;
|
||||
int32_t status;
|
||||
} SCheckColsFuncCxt;
|
||||
|
||||
static bool isColsFuncByName(SFunctionNode* pFunc) {
|
||||
|
@ -7310,26 +7323,16 @@ static bool isColsFuncByName(SFunctionNode* pFunc) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool isMultiColsFunc(SFunctionNode* pFunc) {
|
||||
if (strcasecmp(pFunc->functionName, "cols") != 0) {
|
||||
return false;
|
||||
}
|
||||
return pFunc->pParameterList->length > 2;
|
||||
}
|
||||
|
||||
static EDealRes isMultiColsFuncNode(SNode** pNode, void* pContext) {
|
||||
SCheckColsFuncCxt* pCxt = pContext;
|
||||
if (QUERY_NODE_FUNCTION == nodeType(*pNode)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)*pNode;
|
||||
static bool isMultiColsFuncNode(SNode* pNode) {
|
||||
if (QUERY_NODE_FUNCTION == nodeType(pNode)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)pNode;
|
||||
if (isColsFuncByName(pFunc)) {
|
||||
pCxt->hasColsFunc = true;
|
||||
if (pFunc->pParameterList->length > 2) {
|
||||
pCxt->hasMultiColsFunc = true;
|
||||
return DEAL_RES_END;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef struct SBindTupleFuncCxt {
|
||||
|
@ -7347,16 +7350,6 @@ static EDealRes pushDownBindSelectFunc(SNode** pNode, void* pContext) {
|
|||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static void checkColsFuncInList(SNodeList* nodeList, SCheckColsFuncCxt* pCheckouColsFuncCxt) {
|
||||
nodesRewriteExprs(nodeList, isMultiColsFuncNode, pCheckouColsFuncCxt);
|
||||
return;
|
||||
}
|
||||
|
||||
static void checkColsFunc(SNode** pNode, SCheckColsFuncCxt* pCheckouColsFuncCxt) {
|
||||
nodesRewriteExpr(pNode, isMultiColsFuncNode, pCheckouColsFuncCxt);
|
||||
return;
|
||||
}
|
||||
|
||||
static bool invalidColsAlias(SFunctionNode* pFunc) {
|
||||
if (pFunc->node.asAlias) {
|
||||
if (pFunc->pParameterList->length > 2) {
|
||||
|
@ -7374,37 +7367,6 @@ static bool invalidColsAlias(SFunctionNode* pFunc) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int32_t hasInvalidColsFunction(STranslateContext* pCxt, SNodeList* nodeList,
|
||||
SCheckColsFuncCxt* pCheckouColsFuncCxt) {
|
||||
SNode* pTmpNode = NULL;
|
||||
FOREACH(pTmpNode, nodeList) {
|
||||
if (QUERY_NODE_FUNCTION == nodeType(pTmpNode)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)pTmpNode;
|
||||
if (isColsFuncByName(pFunc)) {
|
||||
pCheckouColsFuncCxt->hasColsFunc = true;
|
||||
if (invalidColsAlias(pFunc)) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLS_FUNCTION,
|
||||
"Invalid using alias for cols function");
|
||||
}
|
||||
}
|
||||
checkColsFuncInList(pFunc->pParameterList, pCheckouColsFuncCxt);
|
||||
if (pCheckouColsFuncCxt->hasMultiColsFunc) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLS_FUNCTION,
|
||||
"Invalid cols function in function %s", pFunc->functionName);
|
||||
}
|
||||
} else {
|
||||
checkColsFunc(&pTmpNode, pCheckouColsFuncCxt);
|
||||
if (pCheckouColsFuncCxt->hasMultiColsFunc) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLS_FUNCTION,
|
||||
"Invalid cols function, can't be used at here");
|
||||
}
|
||||
}
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int32_t getSelectFuncIndex(SNodeList* FuncNodeList, SNode* pSelectFunc) {
|
||||
SNode* pNode = NULL;
|
||||
int32_t selectFuncIndex = 0;
|
||||
|
@ -7417,47 +7379,178 @@ static int32_t getSelectFuncIndex(SNodeList* FuncNodeList, SNode* pSelectFunc) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList) {
|
||||
SCheckColsFuncCxt pCheckouColsFuncCxt = {false, false};
|
||||
int32_t code = hasInvalidColsFunction(pCxt, *nodeList, &pCheckouColsFuncCxt);
|
||||
static EDealRes checkHasColsFunc(SNode** pNode, void* pContext){
|
||||
if (QUERY_NODE_FUNCTION == nodeType(*pNode)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)*pNode;
|
||||
if (isColsFuncByName(pFunc)) {
|
||||
*(bool*)pContext = true;
|
||||
return DEAL_RES_END;
|
||||
}
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static int32_t checkMultColsFuncParam(SNodeList* pParameterList) {
|
||||
if (!pParameterList || pParameterList->length < 2) {
|
||||
return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
}
|
||||
int32_t index = 0;
|
||||
SNode* pNode = NULL;
|
||||
FOREACH(pNode, pParameterList) {
|
||||
if (index == 0) { // the first parameter is select function
|
||||
if (QUERY_NODE_FUNCTION != nodeType(pNode)) {
|
||||
return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
}
|
||||
SFunctionNode* pFunc = (SFunctionNode*)pNode;
|
||||
// pFunc->funcId is zero at here, so need to check at * step
|
||||
// if(!fmIsSelectFunc(pFunc->funcId)) {
|
||||
// return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
// }
|
||||
SNode* pTmpNode = NULL;
|
||||
FOREACH(pTmpNode, pFunc->pParameterList) {
|
||||
bool hasColsFunc = false;
|
||||
nodesRewriteExpr(&pTmpNode, checkHasColsFunc, (void*)&hasColsFunc);
|
||||
if (hasColsFunc) {
|
||||
return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bool hasColsFunc = false;
|
||||
nodesRewriteExpr(&pNode, checkHasColsFunc, &hasColsFunc);
|
||||
if (hasColsFunc) {
|
||||
return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
}
|
||||
}
|
||||
++index;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static EDealRes rewriteSingleColsFunc(SNode** pNode, void* pContext) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (QUERY_NODE_FUNCTION != nodeType(*pNode)) {
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
SCheckColsFuncCxt* pCxt = pContext;
|
||||
SFunctionNode* pFunc = (SFunctionNode*)*pNode;
|
||||
if (isColsFuncByName(pFunc)) {
|
||||
if(pFunc->pParameterList->length > 2) {
|
||||
pCxt->status = TSDB_CODE_PAR_INVALID_COLS_SELECTFUNC;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
SNode* pSelectFunc = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 1);
|
||||
if (nodeType(pSelectFunc) != QUERY_NODE_FUNCTION) {
|
||||
pCxt->status = TSDB_CODE_PAR_INVALID_COLS_SELECTFUNC;
|
||||
parserError("Invalid cols function, the first parameter must be a select function");
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
if (pFunc->node.asAlias) {
|
||||
if (((SExprNode*)pExpr)->asAlias) {
|
||||
pCxt->status = TSDB_CODE_INVALID_COLS_ALIAS;
|
||||
parserError("Invalid using alias for cols function");
|
||||
return DEAL_RES_ERROR;
|
||||
} else {
|
||||
((SExprNode*)pExpr)->asAlias = true;
|
||||
tstrncpy(((SExprNode*)pExpr)->userAlias, pFunc->node.userAlias, TSDB_COL_NAME_LEN + TSDB_COL_NAME_EXLEN);
|
||||
}
|
||||
}
|
||||
if(*pCxt->selectFuncList == NULL) {
|
||||
nodesMakeList(pCxt->selectFuncList);
|
||||
if (NULL == *pCxt->selectFuncList) {
|
||||
pCxt->status = terrno;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
}
|
||||
int32_t selectFuncCount = (*pCxt->selectFuncList)->length;
|
||||
int32_t selectFuncIndex = getSelectFuncIndex(*pCxt->selectFuncList, pSelectFunc);
|
||||
if (selectFuncIndex == 0) {
|
||||
++selectFuncCount;
|
||||
selectFuncIndex = selectFuncCount;
|
||||
SNode* pNewNode = NULL;
|
||||
code = nodesCloneNode(pSelectFunc, &pNewNode);
|
||||
((SExprNode*)pNewNode)->tupleFuncIdx = selectFuncIndex;
|
||||
nodesListMakeStrictAppend(pCxt->selectFuncList, pNewNode);
|
||||
}
|
||||
|
||||
SNode* pNewNode = NULL;
|
||||
code = nodesCloneNode(pExpr, &pNewNode);
|
||||
if (nodesIsExprNode(pNewNode)) {
|
||||
SBindTupleFuncCxt pCxt = {selectFuncIndex};
|
||||
nodesRewriteExpr(&pNewNode, pushDownBindSelectFunc, &pCxt);
|
||||
} else {
|
||||
pCxt->status = TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
parserError("Invalid cols function, the first parameter must be a select function");
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
nodesDestroyNode(*pNode);
|
||||
*pNode = pNewNode;
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
_end:
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList, SNodeList** selectFuncList) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
bool needRewrite = false;
|
||||
SNode** pNode = NULL;
|
||||
FOREACH_FOR_REWRITE(pNode, *nodeList) {
|
||||
if (isMultiColsFuncNode(*pNode)) {
|
||||
code = checkMultColsFuncParam(((SFunctionNode*)*pNode)->pParameterList);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
bool needRewrite = false;
|
||||
if (pCheckouColsFuncCxt.hasColsFunc) {
|
||||
needRewrite = true;
|
||||
} else {
|
||||
SCheckColsFuncCxt pSelectFuncCxt = {false, selectFuncList, TSDB_CODE_SUCCESS};
|
||||
nodesRewriteExpr(pNode, rewriteSingleColsFunc, &pSelectFuncCxt);
|
||||
if (pSelectFuncCxt.status != TSDB_CODE_SUCCESS) {
|
||||
return pSelectFuncCxt.status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SNodeList* pNewNodeList = NULL;
|
||||
SNodeList* tmpFuncNodeList = NULL;
|
||||
if (needRewrite) {
|
||||
code = nodesMakeList(&pNewNodeList);
|
||||
if (NULL == pNewNodeList) {
|
||||
return code;
|
||||
}
|
||||
code = nodesMakeList(&tmpFuncNodeList);
|
||||
if (NULL == tmpFuncNodeList) {
|
||||
if (*selectFuncList == NULL) {
|
||||
code = nodesMakeList(selectFuncList);
|
||||
if (NULL == *selectFuncList) {
|
||||
nodesDestroyList(pNewNodeList);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
SNode* pNewNode = NULL;
|
||||
int32_t nums = 0;
|
||||
int32_t selectFuncCount = 0;
|
||||
int32_t selectFuncCount = (*selectFuncList)->length;
|
||||
SNode* pTmpNode = NULL;
|
||||
FOREACH(pTmpNode, *nodeList) {
|
||||
if (QUERY_NODE_FUNCTION == nodeType(pTmpNode)) {
|
||||
if (isMultiColsFuncNode(pTmpNode)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)pTmpNode;
|
||||
if (strcasecmp(pFunc->functionName, "cols") == 0) {
|
||||
if(pFunc->node.asAlias) {
|
||||
code = TSDB_CODE_INVALID_COLS_ALIAS;
|
||||
parserError("Invalid using alias for cols function");
|
||||
goto _end;
|
||||
}
|
||||
|
||||
SNode* pSelectFunc = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
if (nodeType(pSelectFunc) != QUERY_NODE_FUNCTION) {
|
||||
code = TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
parserError("Invalid cols function, the first parameter must be a select function");
|
||||
goto _end;
|
||||
}
|
||||
int32_t selectFuncIndex = getSelectFuncIndex(tmpFuncNodeList, pSelectFunc);
|
||||
int32_t selectFuncIndex = getSelectFuncIndex(*selectFuncList, pSelectFunc);
|
||||
if (selectFuncIndex == 0) {
|
||||
++selectFuncCount;
|
||||
selectFuncIndex = selectFuncCount;
|
||||
nodesListMakeStrictAppend(&tmpFuncNodeList, pSelectFunc);
|
||||
code = nodesCloneNode(pSelectFunc, &pNewNode);
|
||||
((SExprNode*)pNewNode)->tupleFuncIdx = selectFuncIndex;
|
||||
nodesListMakeStrictAppend(selectFuncList, pNewNode);
|
||||
}
|
||||
// start from index 1, because the first parameter is select function which needn't to output.
|
||||
for (int i = 1; i < pFunc->pParameterList->length; ++i) {
|
||||
|
@ -7478,48 +7571,43 @@ static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList
|
|||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
code = nodesCloneNode(pTmpNode, &pNewNode);
|
||||
if (TSDB_CODE_SUCCESS != code) goto _end;
|
||||
code = nodesListMakeStrictAppend(&pNewNodeList, pNewNode);
|
||||
if (TSDB_CODE_SUCCESS != code) goto _end;
|
||||
}
|
||||
SNode* pNode = NULL;
|
||||
int32_t pNewSelectFuncIds = 0;
|
||||
FOREACH(pNode, tmpFuncNodeList) {
|
||||
++pNewSelectFuncIds;
|
||||
code = nodesCloneNode(pNode, &pNewNode);
|
||||
if (TSDB_CODE_SUCCESS != code) goto _end;
|
||||
if (nodesIsExprNode(pNewNode)) {
|
||||
SExprNode* pExprNode = (SExprNode*)pNewNode;
|
||||
pExprNode->tupleFuncIdx = pNewSelectFuncIds;
|
||||
} else {
|
||||
code = TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
parserError("Invalid cols function, the first parameter must be a select function");
|
||||
goto _end;
|
||||
}
|
||||
code = nodesListMakeStrictAppend(&pNewNodeList, pNewNode);
|
||||
if (TSDB_CODE_SUCCESS != code) goto _end;
|
||||
}
|
||||
nodesDestroyList(*nodeList);
|
||||
nodesDestroyList(tmpFuncNodeList);
|
||||
*nodeList = pNewNodeList;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
_end:
|
||||
}
|
||||
_end:
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
nodesDestroyList(pNewNodeList);
|
||||
nodesDestroyList(tmpFuncNodeList);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateColsFunction(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
int32_t code = rewriteColsFunction(pCxt, &pSelect->pProjectionList);
|
||||
SNodeList* selectFuncList = NULL;
|
||||
int32_t code = rewriteColsFunction(pCxt, &pSelect->pProjectionList, &selectFuncList);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
code = rewriteColsFunction(pCxt, &pSelect->pOrderByList);
|
||||
code = rewriteColsFunction(pCxt, &pSelect->pOrderByList, &selectFuncList);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
goto _end;
|
||||
}
|
||||
|
||||
if (selectFuncList != NULL) {
|
||||
nodesListAppendList(pSelect->pProjectionList, selectFuncList);
|
||||
selectFuncList = NULL;
|
||||
}
|
||||
|
||||
_end:
|
||||
if (selectFuncList) {
|
||||
nodesDestroyList(selectFuncList);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
|
|
@ -751,6 +751,10 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE, "Invalid forecast cl
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR, "Syntax error in regular expression")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_VGID_LIST, "Invalid vgid list")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_COLS_FUNCTION, "Invalid cols function")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_COLS_SELECTFUNC, "cols function's first param must be a select function")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_MULITI_COLS_FUNC, "Improper use of cols function with multiple output columns")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_COLS_ALIAS, "Invalid using alias for cols function")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INTERNAL_ERROR, "Parser internal error")
|
||||
|
||||
//planner
|
||||
|
|
|
@ -233,6 +233,7 @@ class TDTestCase:
|
|||
tdSql.error(f'select cols(last(ts), ts t1) tt from {self.dbname}.meters')
|
||||
tdSql.error(f'select cols(first(ts+1), c0+2 cc0, c1 cc1) cc from {self.dbname}.meters')
|
||||
tdSql.error(f'select cols(last(ts)+1, c0+2 as cc0) as cc from {self.dbname}.meters')
|
||||
tdSql.error(f'select cols(ABS(c0), c1) from {self.dbname}.meters group by tbname')
|
||||
|
||||
tdSql.error(f'select cols(last(ts)+1, ts) from {self.dbname}.meters')
|
||||
tdSql.error(f'select cols(last(ts)+10, c1+10) from {self.dbname}.meters group by tbname')
|
||||
|
|
Loading…
Reference in New Issue