enh: translate cols in clauses

This commit is contained in:
facetosea 2025-02-13 03:21:27 +00:00
parent 44f6859d65
commit e16b96db72
3 changed files with 85 additions and 43 deletions

View File

@ -461,7 +461,7 @@ This document details the server error codes that may be encountered when using
| 0x80002687 | Invalid using cols function | Illegal using cols function | Check and correct the SQL statement |
| 0x80002688 | Cols function's first param must be a select function | The first parameter of the cols function should be a selection function | Check and correct the SQL statement |
| 0x80002689 | Invalid using cols function with multiple output columns | Illegal using the cols function for multiple column output | Check and correct the SQL statement |
| 0x80002690 | Invalid using alias for cols function | Illegal cols function alias | Check and correct the SQL statement |
| 0x8000268A | Invalid using alias for cols function | Illegal cols function alias | Check and correct the SQL statement |
| 0x800026FF | Parser internal error | Internal error in parser | Preserve the scene and logs, report issue on GitHub |
| 0x80002700 | Planner internal error | Internal error in planner | Preserve the scene and logs, report issue on GitHub |
| 0x80002701 | Expect ts equal | JOIN condition validation failed | Preserve the scene and logs, report issue on GitHub |

View File

@ -478,7 +478,7 @@ description: TDengine 服务端的错误码列表和详细说明
| 0x80002687 | Invalid using cols function | cols函数使用错误 | 检查并修正SQL语句 |
| 0x80002688 | Cols function's first param must be a select function | cols函数第一个参数应该为选择函数 | 检查并修正SQL语句 |
| 0x80002689 | Invalid using cols function with multiple output columns | 多列输出的 cols 函数使用错误 | 检查并修正SQL语句 |
| 0x80002690 | Invalid using alias for cols function | cols 函数输出列重命名错误 | 检查并修正SQL语句 |
| 0x8000268A | Invalid using alias for cols function | cols 函数输出列重命名错误 | 检查并修正SQL语句 |
| 0x800026FF | Parser internal error | 解析器内部错误 | 保留现场和日志github上报issue |
| 0x80002700 | Planner internal error | 计划期内部错误 | 保留现场和日志github上报issue |
| 0x80002701 | Expect ts equal | JOIN条件校验失败 | 保留现场和日志github上报issue |

View File

@ -5460,9 +5460,83 @@ static int32_t translateClausePosition(STranslateContext* pCxt, SNodeList* pProj
return TSDB_CODE_SUCCESS;
}
static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList, SNodeList** selectFuncList);
static int32_t translateSelectColsFunction(STranslateContext* pCxt, SSelectStmt* pSelect) {
SNodeList* selectFuncList = NULL;
int32_t code = rewriteColsFunction(pCxt, &pSelect->pProjectionList, &selectFuncList);
if (TSDB_CODE_SUCCESS != code) {
goto _end;
}
if (selectFuncList != NULL) {
code = nodesListAppendList(pSelect->pProjectionList, selectFuncList);
if (TSDB_CODE_SUCCESS != code) {
goto _end;
}
selectFuncList = NULL;
}
_end:
if (selectFuncList) {
nodesDestroyList(selectFuncList);
}
return code;
}
static int32_t getBindedExprList(STranslateContext* pCxt, SNodeList* projectionList, SNodeList** selectFuncList) {
int32_t code = TSDB_CODE_SUCCESS;
for (int32_t i = 0; i < LIST_LENGTH(projectionList); ++i) {
SNode* pNode = nodesListGetNode(projectionList, i);
if (((SExprNode*)pNode)->bindTupleFuncIdx > 0) {
if (NULL == *selectFuncList) {
code = nodesMakeList(selectFuncList);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
}
code = nodesListStrictAppend(*selectFuncList, pNode);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
}
}
return code;
}
static int32_t translateOrderbyColsFunction(STranslateContext* pCxt, SSelectStmt* pSelect) {
SNodeList* selectFuncList = NULL;
int32_t code = getBindedExprList(pCxt, pSelect->pProjectionList, &selectFuncList);
if (TSDB_CODE_SUCCESS != code) {
goto _end;
}
int len = LIST_LENGTH(selectFuncList);
code = rewriteColsFunction(pCxt, &pSelect->pOrderByList, &selectFuncList);
if (TSDB_CODE_SUCCESS != code) {
goto _end;
}
if(LIST_LENGTH(selectFuncList) - len > 0) {
for (int i = len; i < LIST_LENGTH(selectFuncList); ++i) {
SNode* pNode = nodesListGetNode(selectFuncList, i);
int32_t code = nodesListStrictAppend(pSelect->pProjectionList, pNode);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
}
}
nodesClearList(selectFuncList);
return code;
_end:
if (selectFuncList) {
nodesDestroyList(selectFuncList);
}
return code;
}
static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
bool other;
int32_t code = translateClausePosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other);
int32_t code = translateOrderbyColsFunction(pCxt, pSelect);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
code = translateClausePosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other);
if (TSDB_CODE_SUCCESS == code) {
if (0 == LIST_LENGTH(pSelect->pOrderByList)) {
NODES_DESTORY_LIST(pSelect->pOrderByList);
@ -5681,7 +5755,11 @@ static int32_t translatePartitionByList(STranslateContext* pCxt, SSelectStmt* pS
static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) {
pCxt->currClause = SQL_CLAUSE_SELECT;
int32_t code = translateExprList(pCxt, pSelect->pProjectionList);
int32_t code = translateSelectColsFunction(pCxt, pSelect);
code = translateOrderbyColsFunction(pCxt, pSelect);
if (TSDB_CODE_SUCCESS == code) {
code = translateExprList(pCxt, pSelect->pProjectionList);
}
if (TSDB_CODE_SUCCESS == code) {
code = translateStar(pCxt, pSelect);
}
@ -7432,7 +7510,7 @@ static int32_t checkMultColsFuncParam(SNodeList* pParameterList) {
SNode* pNode = NULL;
FOREACH(pNode, pParameterList) {
if (index == 0) { // the first parameter is select function
if (QUERY_NODE_FUNCTION != nodeType(pNode)) {
if (QUERY_NODE_FUNCTION != nodeType(pNode) || isColsFuncByName((SFunctionNode*)pNode)) {
return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
}
SFunctionNode* pFunc = (SFunctionNode*)pNode;
@ -7474,7 +7552,7 @@ static EDealRes rewriteSingleColsFunc(SNode** pNode, void* pContext) {
}
SNode* pSelectFunc = nodesListGetNode(pFunc->pParameterList, 0);
SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 1);
if (nodeType(pSelectFunc) != QUERY_NODE_FUNCTION) {
if (nodeType(pSelectFunc) != QUERY_NODE_FUNCTION || isColsFuncByName((SFunctionNode*)pSelectFunc)) {
pCxt->status = TSDB_CODE_PAR_INVALID_COLS_SELECTFUNC;
parserError("%s Invalid cols function, the first parameter must be a select function", __func__);
return DEAL_RES_ERROR;
@ -7625,46 +7703,10 @@ static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList
return code;
}
static int32_t translateColsFunction(STranslateContext* pCxt, SSelectStmt* pSelect) {
if (pSelect->pFromTable && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable)) {
SNode* pSubquery = ((STempTableNode*)pSelect->pFromTable)->pSubquery;
if (QUERY_NODE_SELECT_STMT == nodeType(pSubquery)) {
SSelectStmt* pSubSelect = (SSelectStmt*)pSubquery;
int32_t code = translateColsFunction(pCxt, pSubSelect);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
}
}
SNodeList* selectFuncList = NULL;
int32_t code = rewriteColsFunction(pCxt, &pSelect->pProjectionList, &selectFuncList);
if (code == TSDB_CODE_SUCCESS) {
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;
}
static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect) {
pCxt->pCurrStmt = (SNode*)pSelect;
pCxt->dual = false;
int32_t code = translateColsFunction(pCxt, pSelect);
if (TSDB_CODE_SUCCESS == code) {
code = translateFrom(pCxt, &pSelect->pFromTable);
}
int32_t code = translateFrom(pCxt, &pSelect->pFromTable);
if (TSDB_CODE_SUCCESS == code) {
pSelect->precision = ((STableNode*)pSelect->pFromTable)->precision;
code = translateWhere(pCxt, pSelect);