未验证 提交 bf40ca89 编写于 作者: X xiao-yu-wang 提交者: GitHub

Merge pull request #10230 from taosdata/feature/3.0_wxy

TD-13338 SELECT statement translate code
......@@ -457,6 +457,8 @@ int32_t* taosGetErrno();
#define TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION TAOS_DEF_ERROR_CODE(0, 0x2608) //There mustn't be aggregation
#define TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT TAOS_DEF_ERROR_CODE(0, 0x2609) //ORDER BY item must be the number of a SELECT-list expression
#define TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260A) //Not a GROUP BY expression
#define TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260B) //Not SELECTed expression
#define TSDB_CODE_PAR_NOT_SINGLE_GROUP TAOS_DEF_ERROR_CODE(0, 0x260C) //Not a single-group group function
#ifdef __cplusplus
}
......
......@@ -47,10 +47,11 @@ int32_t fmGetHandle(FuncMgtHandle* pHandle) {
int32_t fmGetFuncInfo(FuncMgtHandle handle, const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType) {
SFuncMgtService* pService = (SFuncMgtService*)handle;
pFuncId = taosHashGet(pService->pFuncNameHashTable, pFuncName, strlen(pFuncName));
if (NULL == pFuncId) {
void* pVal = taosHashGet(pService->pFuncNameHashTable, pFuncName, strlen(pFuncName));
if (NULL == pVal) {
return TSDB_CODE_FAILED;
}
*pFuncId = *(int32_t*)pVal;
if (*pFuncId < 0 || *pFuncId >= funcMgtBuiltinsNum) {
return TSDB_CODE_FAILED;
}
......
......@@ -288,6 +288,10 @@ static char* getSyntaxErrFormat(int32_t errCode) {
return "ORDER BY item must be the number of a SELECT-list expression";
case TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION:
return "Not a GROUP BY expression";
case TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION:
return "Not SELECTed expression";
case TSDB_CODE_PAR_NOT_SINGLE_GROUP:
return "Not a single-group group function";
default:
return "Unknown error";
}
......@@ -333,7 +337,7 @@ static bool belongTable(const char* currentDb, const SColumnNode* pCol, const ST
if ('\0' != pCol->dbName[0]) {
cmp = strcmp(pCol->dbName, pTable->dbName);
} else {
cmp = strcmp(currentDb, pTable->dbName);
cmp = (QUERY_NODE_REAL_TABLE == nodeType(pTable) ? strcmp(currentDb, pTable->dbName) : 0);
}
if (0 == cmp) {
cmp = strcmp(pCol->tableAlias, pTable->tableAlias);
......@@ -422,9 +426,11 @@ static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) {
static EDealRes translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode* pCol) {
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
size_t nums = taosArrayGetSize(pTables);
bool foundTable = false;
for (size_t i = 0; i < nums; ++i) {
STableNode* pTable = taosArrayGetP(pTables, i);
if (belongTable(pCxt->pParseCxt->db, pCol, pTable)) {
foundTable = true;
if (findAndSetColumn(pCol, pTable)) {
break;
}
......@@ -432,6 +438,10 @@ static EDealRes translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode*
return DEAL_RES_ERROR;
}
}
if (!foundTable) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_TABLE_NOT_EXIST, pCol->tableAlias);
return DEAL_RES_ERROR;
}
return DEAL_RES_CONTINUE;
}
......@@ -651,7 +661,28 @@ static bool isAliasColumn(SColumnNode* pCol) {
return ('\0' == pCol->tableAlias[0]);
}
static EDealRes doCheckkExprForGroupBy(SNode* pNode, void* pContext) {
static SNodeList* getGroupByList(STranslateContext* pCxt) {
if (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct) {
return pCxt->pCurrStmt->pProjectionList;
}
return pCxt->pCurrStmt->pGroupByList;
}
static SNode* getGroupByNode(SNode* pNode) {
if (QUERY_NODE_GROUPING_SET == nodeType(pNode)) {
return nodesListGetNode(((SGroupingSetNode*)pNode)->pParameterList, 0);
}
return pNode;
}
static int32_t getGroupByErrorCode(STranslateContext* pCxt) {
if (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct) {
return TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION;
}
return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION;
}
static EDealRes doCheckExprForGroupBy(SNode* pNode, void* pContext) {
STranslateContext* pCxt = (STranslateContext*)pContext;
if (!nodesIsExprNode(pNode) || (QUERY_NODE_COLUMN == nodeType(pNode) && isAliasColumn((SColumnNode*)pNode))) {
return DEAL_RES_CONTINUE;
......@@ -660,28 +691,64 @@ static EDealRes doCheckkExprForGroupBy(SNode* pNode, void* pContext) {
return DEAL_RES_IGNORE_CHILD;
}
SNode* pGroupNode;
FOREACH(pGroupNode, pCxt->pCurrStmt->pGroupByList) {
if (nodesEqualNode(nodesListGetNode(((SGroupingSetNode*)pGroupNode)->pParameterList, 0), pNode)) {
FOREACH(pGroupNode, getGroupByList(pCxt)) {
if (nodesEqualNode(getGroupByNode(pGroupNode), pNode)) {
return DEAL_RES_IGNORE_CHILD;
}
}
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
generateSyntaxErrMsg(pCxt, getGroupByErrorCode(pCxt));
return DEAL_RES_ERROR;
}
return DEAL_RES_CONTINUE;
}
static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode* pNode) {
nodesWalkNode(pNode, doCheckkExprForGroupBy, pCxt);
nodesWalkNode(pNode, doCheckExprForGroupBy, pCxt);
return pCxt->errCode;
}
static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList) {
nodesWalkList(pList, doCheckkExprForGroupBy, pCxt);
if (NULL == getGroupByList(pCxt)) {
return TSDB_CODE_SUCCESS;
}
nodesWalkList(pList, doCheckExprForGroupBy, pCxt);
return pCxt->errCode;
}
typedef struct CheckAggColCoexistCxt {
STranslateContext* pTranslateCxt;
bool existAggFunc;
bool existCol;
} CheckAggColCoexistCxt;
static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) {
CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext;
if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId)) {
pCxt->existAggFunc = true;
return DEAL_RES_IGNORE_CHILD;
}
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
pCxt->existCol = true;
}
return DEAL_RES_CONTINUE;
}
static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) {
if (NULL != pSelect->pGroupByList) {
return TSDB_CODE_SUCCESS;
}
CheckAggColCoexistCxt cxt = { .pTranslateCxt = pCxt, .existAggFunc = false, .existCol = false };
nodesWalkList(pSelect->pProjectionList, doCheckAggColCoexist, &cxt);
if (!pSelect->isDistinct) {
nodesWalkList(pSelect->pOrderByList, doCheckAggColCoexist, &cxt);
}
if (cxt.existAggFunc && cxt.existCol) {
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_NOT_SINGLE_GROUP);
}
return TSDB_CODE_SUCCESS;
}
static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pTable)) {
......@@ -809,7 +876,7 @@ static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
}
pCxt->currClause = SQL_CLAUSE_ORDER_BY;
int32_t code = translateExprList(pCxt, pSelect->pOrderByList);
if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pGroupByList) {
if (TSDB_CODE_SUCCESS == code) {
code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList);
}
return code;
......@@ -822,7 +889,7 @@ static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect
pCxt->currClause = SQL_CLAUSE_SELECT;
code = translateExprList(pCxt, pSelect->pProjectionList);
}
if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pGroupByList) {
if (TSDB_CODE_SUCCESS == code) {
code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList);
}
return code;
......@@ -895,6 +962,9 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
if (TSDB_CODE_SUCCESS == code) {
code = translateOrderBy(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
code = checkAggColCoexist(pCxt, pSelect);
}
return code;
}
......
......@@ -517,7 +517,7 @@ TEST_F(NewParserTest, selectClause) {
setDatabase("root", "test");
// GROUP BY clause
bind("SELECT count(*), c2 cnt FROM t1 WHERE c1 > 0");
bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0");
ASSERT_TRUE(run());
bind("SELECT count(*), c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c2");
......@@ -538,6 +538,16 @@ TEST_F(NewParserTest, selectClause) {
bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 ORDER BY 1");
ASSERT_TRUE(run());
// DISTINCT clause
bind("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 0 ORDER BY c1");
ASSERT_TRUE(run());
bind("SELECT DISTINCT c1 + 10, c2 FROM t1 WHERE c1 > 0 ORDER BY c1 + 10, c2");
ASSERT_TRUE(run());
bind("SELECT DISTINCT c1 + 10 cc1, c2 cc2 FROM t1 WHERE c1 > 0 ORDER BY cc1, c2");
ASSERT_TRUE(run());
}
TEST_F(NewParserTest, selectSyntaxError) {
......@@ -573,6 +583,9 @@ TEST_F(NewParserTest, selectSemanticError) {
bind("SELECT * FROM test.t10");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST));
bind("SELECT t2.c1 FROM t1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST));
// TSDB_CODE_PAR_AMBIGUOUS_COLUMN
bind("SELECT c2 FROM t1 tt1, t1 tt2 WHERE tt1.c1 = tt2.c1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_AMBIGUOUS_COLUMN));
......@@ -608,7 +621,7 @@ TEST_F(NewParserTest, selectSemanticError) {
bind("SELECT c2 FROM t1 ORDER BY 2");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT));
//TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
// TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
bind("SELECT count(*) cnt FROM t1 HAVING c1 > 0");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION));
......@@ -620,4 +633,18 @@ TEST_F(NewParserTest, selectSemanticError) {
bind("SELECT count(*) cnt FROM t1 GROUP BY c2 HAVING c2 > 0 ORDER BY c1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION));
// TSDB_CODE_PAR_NOT_SINGLE_GROUP
bind("SELECT count(*), c1 FROM t1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP));
bind("SELECT count(*) FROM t1 ORDER BY c1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP));
bind("SELECT c1 FROM t1 ORDER BY count(*)");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SINGLE_GROUP));
// TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION
bind("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 0 ORDER BY ts");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION));
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册