提交 a5e9d8f5 编写于 作者: X Xiaoyu Wang

TD-13338 SELECT statement translate code

上级 655b7ec5
......@@ -31,16 +31,7 @@ extern "C" {
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)); cell = cell->pNext)
// only be use in FOREACH
#define ERASE_NODE(list) \
if (NULL == cell->pPrev) { \
(list)->pHead = cell->pNext; \
} else { \
cell->pPrev->pNext = cell->pNext; \
cell->pNext->pPrev = cell->pPrev; \
} \
SListCell* tmp = cell; \
cell = cell->pNext; \
tfree(tmp);
#define ERASE_NODE(list) cell = nodesListErase(list, cell);
#define REPLACE_NODE(newNode) cell->pNode = (SNode*)(newNode)
......@@ -343,18 +334,22 @@ void nodesDestroyNode(SNode* pNode);
SNodeList* nodesMakeList();
SNodeList* nodesListAppend(SNodeList* pList, SNode* pNode);
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell);
SNode* nodesListGetNode(SNodeList* pList, int32_t index);
void nodesDestroyList(SNodeList* pList);
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
typedef enum EDealRes {
DEAL_RES_CONTINUE = 1,
DEAL_RES_IGNORE_CHILD,
DEAL_RES_ERROR,
} EDealRes;
typedef EDealRes (*FQueryNodeWalker)(SNode* pNode, void* pContext);
void nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext);
void nodesWalkList(SNodeList* pList, FQueryNodeWalker walker, void* pContext);
void nodesWalkNodePostOrder(SNode* pNode, FQueryNodeWalker walker, void* pContext);
void nodesWalkListPostOrder(SNodeList* pList, FQueryNodeWalker walker, void* pContext);
bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext);
bool nodesEqualNode(const SNode* a, const SNode* b);
void nodesCloneNode(const SNode* pNode);
......@@ -362,6 +357,8 @@ void nodesCloneNode(const SNode* pNode);
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
bool nodesIsExprNode(const SNode* pNode);
bool nodesIsArithmeticOp(const SOperatorNode* pOp);
bool nodesIsComparisonOp(const SOperatorNode* pOp);
bool nodesIsJsonOp(const SOperatorNode* pOp);
......
......@@ -453,6 +453,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_PAR_FUNTION_PARA_TYPE TAOS_DEF_ERROR_CODE(0, 0x2607) //Inconsistent datatypes
#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
#ifdef __cplusplus
}
......
......@@ -55,6 +55,7 @@ SNode* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, const SToke
SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pCol);
SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding, SNode* pFill);
SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues);
SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode);
SNode* addWhereClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pWhere);
SNode* addPartitionByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pPartitionByList);
......
......@@ -238,6 +238,7 @@ joined_table(A) ::=
%type join_type { EJoinType }
%destructor join_type { PARSER_DESTRUCTOR_TRACE; }
join_type(A) ::= . { PARSER_TRACE; A = JOIN_TYPE_INNER; }
join_type(A) ::= INNER. { PARSER_TRACE; A = JOIN_TYPE_INNER; }
/************************************************ query_specification *************************************************/
......@@ -315,7 +316,12 @@ fill_mode(A) ::= NEXT.
%type group_by_clause_opt { SNodeList* }
%destructor group_by_clause_opt { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); }
group_by_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; }
group_by_clause_opt(A) ::= GROUP BY expression_list(B). { PARSER_TRACE; A = B; }
group_by_clause_opt(A) ::= GROUP BY group_by_list(B). { PARSER_TRACE; A = B; }
%type group_by_list { SNodeList* }
%destructor group_by_list { PARSER_DESTRUCTOR_TRACE; nodesDestroyList($$); }
group_by_list(A) ::= expression(B). { PARSER_TRACE; A = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, B))); }
group_by_list(A) ::= group_by_list(B) NK_COMMA expression(C). { PARSER_TRACE; A = addNodeToList(pCxt, B, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, C))); }
having_clause_opt(A) ::= . { PARSER_TRACE; A = NULL; }
having_clause_opt(A) ::= HAVING search_condition(B). { PARSER_TRACE; A = B; }
......
......@@ -242,6 +242,9 @@ SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order
CHECK_OUT_OF_MEM(orderByExpr);
orderByExpr->pExpr = pExpr;
orderByExpr->order = order;
if (NULL_ORDER_DEFAULT == nullOrder) {
nullOrder = (ORDER_ASC == order ? NULL_ORDER_FIRST : NULL_ORDER_LAST);
}
orderByExpr->nullOrder = nullOrder;
return (SNode*)orderByExpr;
}
......@@ -279,6 +282,15 @@ SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues) {
return (SNode*)fill;
}
SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode) {
SGroupingSetNode* groupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
CHECK_OUT_OF_MEM(groupingSet);
groupingSet->groupingSetType = GP_TYPE_NORMAL;
groupingSet->pParameterList = nodesMakeList();
nodesListAppend(groupingSet->pParameterList, pNode);
return (SNode*)groupingSet;
}
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) {
strncpy(((SExprNode*)pNode)->aliasName, pAlias->z, pAlias->n);
return pNode;
......
此差异已折叠。
......@@ -116,10 +116,6 @@ static uint32_t toNewTokenId(uint32_t tokenId) {
return NEW_TK_FROM;
case TK_JOIN:
return NEW_TK_JOIN;
// case TK_ON:
// return NEW_TK_ON;
// case TK_INNER:
// return NEW_TK_INNER;
// case TK_PARTITION:
// return NEW_TK_PARTITION;
case TK_SESSION:
......@@ -163,6 +159,8 @@ static uint32_t toNewTokenId(uint32_t tokenId) {
case TK_OFFSET:
return NEW_TK_OFFSET;
case TK_SPACE:
case NEW_TK_ON:
case NEW_TK_INNER:
break;
default:
printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!tokenId = %d\n", tokenId);
......@@ -248,6 +246,10 @@ typedef enum ESqlClause {
} ESqlClause;
static bool afterGroupBy(ESqlClause clause) {
return clause > SQL_CLAUSE_GROUP_BY;
}
static bool beforeHaving(ESqlClause clause) {
return clause < SQL_CLAUSE_HAVING;
}
......@@ -259,7 +261,7 @@ typedef struct STranslateContext {
SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode*
int32_t currLevel;
ESqlClause currClause;
void* pExt;
SSelectStmt* pCurrStmt;
} STranslateContext;
static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode);
......@@ -284,6 +286,8 @@ static char* getSyntaxErrFormat(int32_t errCode) {
return "There mustn't be aggregation";
case TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT:
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";
default:
return "Unknown error";
}
......@@ -415,7 +419,7 @@ static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) {
return found;
}
static bool translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode* pCol) {
static EDealRes translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode* pCol) {
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
size_t nums = taosArrayGetSize(pTables);
for (size_t i = 0; i < nums; ++i) {
......@@ -425,13 +429,13 @@ static bool translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode* pCol
break;
}
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName);
return false;
return DEAL_RES_ERROR;
}
}
return true;
return DEAL_RES_CONTINUE;
}
static bool translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNode* pCol) {
static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNode* pCol) {
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
size_t nums = taosArrayGetSize(pTables);
bool found = false;
......@@ -440,20 +444,20 @@ static bool translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNode* p
if (findAndSetColumn(pCol, pTable)) {
if (found) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName);
return false;
return DEAL_RES_ERROR;
}
found = true;
}
}
if (!found) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName);
return false;
return DEAL_RES_ERROR;
}
return true;
return DEAL_RES_CONTINUE;
}
static bool translateColumnUseAlias(STranslateContext* pCxt, SColumnNode* pCol) {
SNodeList* pProjectionList = pCxt->pExt;
SNodeList* pProjectionList = pCxt->pCurrStmt->pProjectionList;
SNode* pNode;
FOREACH(pNode, pProjectionList) {
SExprNode* pExpr = (SExprNode*)pNode;
......@@ -465,10 +469,10 @@ static bool translateColumnUseAlias(STranslateContext* pCxt, SColumnNode* pCol)
return false;
}
static bool translateColumn(STranslateContext* pCxt, SColumnNode* pCol) {
static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode* pCol) {
// count(*)/first(*)/last(*)
if (0 == strcmp(pCol->colName, "*")) {
return true;
return DEAL_RES_CONTINUE;
}
if ('\0' != pCol->tableAlias[0]) {
return translateColumnWithPrefix(pCxt, pCol);
......@@ -477,7 +481,7 @@ static bool translateColumn(STranslateContext* pCxt, SColumnNode* pCol) {
if (SQL_CLAUSE_ORDER_BY == pCxt->currClause) {
found = translateColumnUseAlias(pCxt, pCol);
}
return found ? true : translateColumnWithoutPrefix(pCxt, pCol);
return found ? DEAL_RES_CONTINUE : translateColumnWithoutPrefix(pCxt, pCol);
}
static int32_t trimStringCopy(const char* src, int32_t len, char* dst) {
......@@ -500,12 +504,12 @@ static int32_t trimStringCopy(const char* src, int32_t len, char* dst) {
return j;
}
static bool translateValue(STranslateContext* pCxt, SValueNode* pVal) {
static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
if (pVal->isDuration) {
char unit = 0;
if (parseAbsoluteDuration(pVal->literal, strlen(pVal->literal), &pVal->datum.i, &unit, pVal->node.resType.precision) != TSDB_CODE_SUCCESS) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
return false;
return DEAL_RES_ERROR;
}
} else {
switch (pVal->node.resType.type) {
......@@ -552,7 +556,7 @@ static bool translateValue(STranslateContext* pCxt, SValueNode* pVal) {
if (taosParseTime(tmp, &pVal->datum.u, len, pVal->node.resType.precision, tsDaylight) != TSDB_CODE_SUCCESS) {
tfree(tmp);
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
return false;
return DEAL_RES_ERROR;
}
tfree(tmp);
break;
......@@ -565,55 +569,56 @@ static bool translateValue(STranslateContext* pCxt, SValueNode* pVal) {
break;
}
}
return true;
return DEAL_RES_CONTINUE;
}
static bool translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
if (nodesIsArithmeticOp(pOp)) {
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type ||
TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
return false;
return DEAL_RES_ERROR;
}
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
return true;
} else if (nodesIsComparisonOp(pOp)) {
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type ||
TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
return false;
return DEAL_RES_ERROR;
}
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
return true;
} else {
// todo json operator
return true;
}
return true;
return DEAL_RES_CONTINUE;
}
static bool translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pCxt->fmgt, pFunc->functionName, &pFunc->funcId, &pFunc->funcType)) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_FUNTION, pFunc->functionName);
return false;
return DEAL_RES_ERROR;
}
int32_t code = fmGetFuncResultType(pFunc);
if (TSDB_CODE_SUCCESS != code) {
generateSyntaxErrMsg(pCxt, code, pFunc->functionName);
return false;
return DEAL_RES_ERROR;
}
if (fmIsAggFunc(pFunc->funcId) && afterGroupBy(pCxt->currClause)) {
if (fmIsAggFunc(pFunc->funcId) && beforeHaving(pCxt->currClause)) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
return false;
return DEAL_RES_ERROR;
}
return true;
return DEAL_RES_CONTINUE;
}
static EDealRes translateExprSubquery(STranslateContext* pCxt, SNode* pNode) {
return (TSDB_CODE_SUCCESS == translateSubquery(pCxt, pNode) ? DEAL_RES_CONTINUE : DEAL_RES_ERROR);
}
static bool doTranslateExpr(SNode* pNode, void* pContext) {
static EDealRes doTranslateExpr(SNode* pNode, void* pContext) {
STranslateContext* pCxt = (STranslateContext*)pContext;
switch (nodeType(pNode)) {
case QUERY_NODE_COLUMN:
......@@ -625,11 +630,11 @@ static bool doTranslateExpr(SNode* pNode, void* pContext) {
case QUERY_NODE_FUNCTION:
return translateFunction(pCxt, (SFunctionNode*)pNode);
case QUERY_NODE_TEMP_TABLE:
return translateSubquery(pCxt, ((STempTableNode*)pNode)->pSubquery);
return translateExprSubquery(pCxt, ((STempTableNode*)pNode)->pSubquery);
default:
break;
}
return true;
return DEAL_RES_CONTINUE;
}
static int32_t translateExpr(STranslateContext* pCxt, SNode* pNode) {
......@@ -642,6 +647,41 @@ static int32_t translateExprList(STranslateContext* pCxt, SNodeList* pList) {
return pCxt->errCode;
}
static bool isAliasColumn(SColumnNode* pCol) {
return ('\0' == pCol->tableAlias[0]);
}
static EDealRes doCheckkExprForGroupBy(SNode* pNode, void* pContext) {
STranslateContext* pCxt = (STranslateContext*)pContext;
if (!nodesIsExprNode(pNode) || (QUERY_NODE_COLUMN == nodeType(pNode) && isAliasColumn((SColumnNode*)pNode))) {
return DEAL_RES_CONTINUE;
}
if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId)) {
return DEAL_RES_IGNORE_CHILD;
}
SNode* pGroupNode;
FOREACH(pGroupNode, pCxt->pCurrStmt->pGroupByList) {
if (nodesEqualNode(nodesListGetNode(((SGroupingSetNode*)pGroupNode)->pParameterList, 0), pNode)) {
return DEAL_RES_IGNORE_CHILD;
}
}
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
return DEAL_RES_ERROR;
}
return DEAL_RES_CONTINUE;
}
static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode* pNode) {
nodesWalkNode(pNode, doCheckkExprForGroupBy, pCxt);
return pCxt->errCode;
}
static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList) {
nodesWalkList(pList, doCheckkExprForGroupBy, pCxt);
return pCxt->errCode;
}
static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pTable)) {
......@@ -732,12 +772,13 @@ static bool translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjec
*pOther = false;
SNode* pNode;
FOREACH(pNode, pOrderByList) {
if (QUERY_NODE_VALUE == nodeType(pNode)) {
SValueNode* pVal = (SValueNode*)pNode;
if (translateValue(pCxt, pVal)) {
SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr;
if (QUERY_NODE_VALUE == nodeType(pExpr)) {
SValueNode* pVal = (SValueNode*)pExpr;
if (!translateValue(pCxt, pVal)) {
return false;
}
int32_t pos = getPositionValue((SValueNode*)pNode);
int32_t pos = getPositionValue((SValueNode*)pExpr);
if (pos < 0) {
ERASE_NODE(pOrderByList);
nodesDestroyNode(pNode);
......@@ -747,9 +788,9 @@ static bool translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjec
return false;
} else {
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
setColumnInfoByExpr(NULL, (SExprNode*)nodesListGetNode(pProjectionList, pos), pCol);
REPLACE_NODE(pCol);
nodesDestroyNode(pNode);
setColumnInfoByExpr(NULL, (SExprNode*)nodesListGetNode(pProjectionList, pos - 1), pCol);
((SOrderByExprNode*)pNode)->pExpr = (SNode*)pCol;
nodesDestroyNode(pExpr);
}
} else {
*pOther = true;
......@@ -758,17 +799,20 @@ static bool translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjec
return true;
}
static int32_t translateOrderBy(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList) {
static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
bool other;
if (!translateOrderByPosition(pCxt, pProjectionList, pOrderByList, &other)) {
if (!translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other)) {
return pCxt->errCode;
}
if (!other) {
return TSDB_CODE_SUCCESS;
}
pCxt->currClause = SQL_CLAUSE_ORDER_BY;
pCxt->pExt = pProjectionList;
return translateExprList(pCxt, pOrderByList);
int32_t code = translateExprList(pCxt, pSelect->pOrderByList);
if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pGroupByList) {
code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList);
}
return code;
}
static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) {
......@@ -778,12 +822,22 @@ 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) {
code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList);
}
return code;
}
static int32_t translateHaving(STranslateContext* pCxt, SNode* pHaving) {
static int32_t translateHaving(STranslateContext* pCxt, SSelectStmt* pSelect) {
if (NULL == pSelect->pGroupByList && NULL != pSelect->pHaving) {
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
}
pCxt->currClause = SQL_CLAUSE_HAVING;
return translateExpr(pCxt, pHaving);
int32_t code = translateExpr(pCxt, pSelect->pHaving);
if (TSDB_CODE_SUCCESS == code) {
code = checkExprForGroupBy(pCxt, pSelect->pHaving);
}
return code;
}
static int32_t translateGroupBy(STranslateContext* pCxt, SNodeList* pGroupByList) {
......@@ -818,8 +872,8 @@ static int32_t translateFrom(STranslateContext* pCxt, SNode* pTable) {
// } SSelectStmt;
static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
int32_t code = TSDB_CODE_SUCCESS;
code = translateFrom(pCxt, pSelect->pFromTable);
pCxt->pCurrStmt = pSelect;
int32_t code = translateFrom(pCxt, pSelect->pFromTable);
if (TSDB_CODE_SUCCESS == code) {
code = translateWhere(pCxt, pSelect->pWhere);
}
......@@ -833,15 +887,14 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
code = translateGroupBy(pCxt, pSelect->pGroupByList);
}
if (TSDB_CODE_SUCCESS == code) {
code = translateHaving(pCxt, pSelect->pHaving);
code = translateHaving(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
code = translateSelectList(pCxt, pSelect);
}
if (TSDB_CODE_SUCCESS == code) {
code = translateOrderBy(pCxt, pSelect->pProjectionList, pSelect->pOrderByList);
code = translateOrderBy(pCxt, pSelect);
}
// printf("%s:%d code = %d\n", __FUNCTION__, __LINE__, code);
return code;
}
......@@ -860,11 +913,11 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) {
++(pCxt->currLevel);
ESqlClause currClause = pCxt->currClause;
void* pExt = pCxt->pExt;
SSelectStmt* pCurrStmt = pCxt->pCurrStmt;
int32_t code = translateQuery(pCxt, pNode);
--(pCxt->currLevel);
pCxt->currClause = currClause;
pCxt->pExt = pExt;
pCxt->pCurrStmt = pCurrStmt;
return code;
}
......
......@@ -227,7 +227,9 @@ static SKeyword keywordTable[] = {
{"OUTPUTTYPE", TK_OUTPUTTYPE},
{"AGGREGATE", TK_AGGREGATE},
{"BUFSIZE", TK_BUFSIZE},
{"PORT", TK_PORT},
{"PORT", TK_PORT},
{"INNER", NEW_TK_INNER},
{"ON", NEW_TK_ON},
};
static const char isIdChar[] = {
......
......@@ -53,8 +53,8 @@ protected:
code = doTranslate(&cxt_, &query_);
// cout << "doTranslate return " << code << endl;
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
return (TSDB_CODE_SUCCESS != translateCode);
cout << "sql:[" << cxt_.pSql << "] code:" << code << ", " << translateCode << ", msg:" << errMagBuf_ << endl;
return (code == translateCode);
}
if (NULL != query_.pRoot && QUERY_NODE_SELECT_STMT == nodeType(query_.pRoot)) {
cout << "input sql : [" << cxt_.pSql << "]" << endl;
......@@ -71,6 +71,24 @@ protected:
private:
static const int max_err_len = 1024;
void exprNodeToStr(const SNode* node, string& str, bool isProject) {
switch (nodeType(node)) {
case QUERY_NODE_COLUMN:
case QUERY_NODE_VALUE:
case QUERY_NODE_OPERATOR:
case QUERY_NODE_FUNCTION: {
SExprNode* pExpr = (SExprNode*)node;
str.append(" [" + dataTypeToStr(pExpr->resType) + "]");
if (isProject) {
str.append(" AS " + string(pExpr->aliasName));
}
break;
}
default:
break;
}
}
string dataTypeToStr(const SDataType& dt) {
switch (dt.type) {
case TSDB_DATA_TYPE_NULL:
......@@ -119,7 +137,7 @@ private:
return "Unknown Data Type " + to_string(dt.type);
}
void valueNodeToStr(const SValueNode* pVal, string& str, bool isProject) {
void valueNodeToStr(const SValueNode* pVal, string& str) {
switch (pVal->node.resType.type) {
case TSDB_DATA_TYPE_NULL:
str.append("null");
......@@ -160,10 +178,41 @@ private:
default:
break;
}
str.append(" [" + dataTypeToStr(pVal->node.resType) + "]");
if (isProject) {
str.append(" AS " + string(pVal->node.aliasName));
}
void columnNodeToStr(const SColumnNode* pCol, string& str) {
if ('\0' != pCol->dbName[0]) {
str.append(pCol->dbName);
str.append(".");
}
if ('\0' != pCol->tableAlias[0]) {
str.append(pCol->tableAlias);
str.append(".");
}
str.append(pCol->colName);
}
void operatorToStr(const SOperatorNode* pOp, string& str) {
nodeToStr(pOp->pLeft, str, false);
str.append(opTypeToStr(pOp->opType));
nodeToStr(pOp->pRight, str, false);
}
void functionToStr(const SFunctionNode* pFunc, string& str) {
str.append(pFunc->functionName);
str.append("(");
nodeListToStr(pFunc->pParameterList, "", str, false, ", ");
str.append(")");
}
void groupingSetToStr(SGroupingSetNode* pGroup, string& str) {
nodeToStr(nodesListGetNode(pGroup->pParameterList, 0), str, false);
}
void orderByExprToStr(SOrderByExprNode* pOrderBy, string& str) {
nodeToStr(pOrderBy->pExpr, str, false);
str.append((ORDER_ASC == pOrderBy->order ? " ASC" : " DESC"));
str.append((NULL_ORDER_FIRST == pOrderBy->nullOrder ? " NULLS FIRST" : " NULLS LAST"));
}
void nodeToStr(const SNode* node, string& str, bool isProject) {
......@@ -173,48 +222,41 @@ private:
switch (nodeType(node)) {
case QUERY_NODE_COLUMN: {
SColumnNode* pCol = (SColumnNode*)node;
if ('\0' != pCol->dbName[0]) {
str.append(pCol->dbName);
str.append(".");
}
if ('\0' != pCol->tableAlias[0]) {
str.append(pCol->tableAlias);
str.append(".");
}
str.append(pCol->colName);
str.append(" [" + dataTypeToStr(pCol->node.resType) + "]");
if (isProject) {
str.append(" AS " + string(pCol->node.aliasName));
}
columnNodeToStr((SColumnNode*)node, str);
break;
}
case QUERY_NODE_VALUE: {
valueNodeToStr((SValueNode*)node, str, isProject);
valueNodeToStr((SValueNode*)node, str);
break;
}
case QUERY_NODE_OPERATOR: {
SOperatorNode* pOp = (SOperatorNode*)node;
nodeToStr(pOp->pLeft, str, false);
str.append(opTypeToStr(pOp->opType));
nodeToStr(pOp->pRight, str, false);
str.append(" [" + dataTypeToStr(pOp->node.resType) + "]");
if (isProject) {
str.append(" AS " + string(pOp->node.aliasName));
}
operatorToStr((SOperatorNode*)node, str);
break;
}
case QUERY_NODE_FUNCTION: {
functionToStr((SFunctionNode*)node, str);
break;
}
case QUERY_NODE_GROUPING_SET: {
groupingSetToStr((SGroupingSetNode*)node, str);
break;
}
case QUERY_NODE_ORDER_BY_EXPR: {
orderByExprToStr((SOrderByExprNode*)node, str);
break;
}
default:
break;
}
exprNodeToStr(node, str, isProject);
}
void nodeListToStr(const SNodeList* nodelist, const string& prefix, string& str, bool isProject = false) {
void nodeListToStr(const SNodeList* nodelist, const string& prefix, string& str, bool isProject = false, const string& sep = string("\n")) {
SNode* node = nullptr;
FOREACH(node, nodelist) {
str.append(prefix);
nodeToStr(node, str, isProject);
str.append("\n");
str.append(sep);
}
}
......@@ -265,8 +307,20 @@ private:
}
str.append("\n");
nodeListToStr(select->pProjectionList, prefix + "\t", str, true);
str.append("\n" + prefix + "FROM\n");
str.append(prefix + "FROM\n");
tableToStr(select->pFromTable, prefix + "\t", str);
if (nullptr != select->pWhere) {
str.append("\n" + prefix + "WHERE\n\t");
nodeToStr(select->pWhere, str, false);
}
if (nullptr != select->pGroupByList) {
str.append("\n" + prefix + "GROUP BY\n");
nodeListToStr(select->pGroupByList, prefix + "\t", str, true);
}
if (nullptr != select->pOrderByList) {
str.append(prefix + "ORDER BY\n");
nodeListToStr(select->pOrderByList, prefix + "\t", str, true);
}
}
void selectToSql(const SNode* node, string& sql) {
......@@ -332,15 +386,23 @@ private:
case OP_TYPE_SUB:
return " - ";
case OP_TYPE_MULTI:
return " * ";
case OP_TYPE_DIV:
return " / ";
case OP_TYPE_MOD:
return " % ";
case OP_TYPE_GREATER_THAN:
return " > ";
case OP_TYPE_GREATER_EQUAL:
return " >= ";
case OP_TYPE_LOWER_THAN:
return " < ";
case OP_TYPE_LOWER_EQUAL:
return " <= ";
case OP_TYPE_EQUAL:
return " = ";
case OP_TYPE_NOT_EQUAL:
return " != ";
case OP_TYPE_IN:
case OP_TYPE_NOT_IN:
case OP_TYPE_LIKE:
......@@ -454,6 +516,23 @@ TEST_F(NewParserTest, selectExpression) {
TEST_F(NewParserTest, selectClause) {
setDatabase("root", "test");
// GROUP BY clause
bind("SELECT count(*), c2 cnt FROM t1 WHERE c1 > 0");
ASSERT_TRUE(run());
bind("SELECT count(*), c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c2");
ASSERT_TRUE(run());
bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 HAVING count(c1) > 10");
ASSERT_TRUE(run());
bind("SELECT count(*), c1, c2 + 10, c1 + c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c2, c1");
ASSERT_TRUE(run());
bind("SELECT count(*), c1 + 10, c2 cnt FROM t1 WHERE c1 > 0 GROUP BY c1 + 10, c2");
ASSERT_TRUE(run());
// ORDER BY clause
bind("SELECT count(*) cnt FROM t1 WHERE c1 > 0 GROUP BY c2 ORDER BY cnt");
ASSERT_TRUE(run());
......@@ -480,15 +559,65 @@ TEST_F(NewParserTest, selectSyntaxError) {
TEST_F(NewParserTest, selectSemanticError) {
setDatabase("root", "test");
// TSDB_CODE_PAR_INVALID_COLUMN
bind("SELECT c1, c3 FROM t1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_COLUMN));
bind("SELECT t1.c1, t1.c3 FROM t1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_COLUMN));
// TSDB_CODE_PAR_TABLE_NOT_EXIST
bind("SELECT * FROM t10");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_FAILED));
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_TABLE_NOT_EXIST));
bind("SELECT c1, c3 FROM t1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_FAILED));
bind("SELECT * FROM test.t10");
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_FAILED));
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_AMBIGUOUS_COLUMN));
// TSDB_CODE_PAR_WRONG_VALUE_TYPE
bind("SELECT 10n FROM t1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_VALUE_TYPE));
bind("SELECT TIMESTAMP '2010' FROM t1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_VALUE_TYPE));
// TSDB_CODE_PAR_INVALID_FUNTION
bind("SELECT cnt(*) FROM t1");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_INVALID_FUNTION));
// TSDB_CODE_PAR_FUNTION_PARA_NUM
// TSDB_CODE_PAR_FUNTION_PARA_TYPE
// TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
bind("SELECT c2 FROM t1 tt1 JOIN t1 tt2 ON count(*) > 0");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION));
bind("SELECT c2 FROM t1 where count(*) > 0");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_FAILED));
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION));
bind("SELECT c2 FROM t1 GROUP BY count(*)");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION));
// TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT
bind("SELECT c2 FROM t1 ORDER BY 0");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT));
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
bind("SELECT count(*) cnt FROM t1 HAVING c1 > 0");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION));
bind("SELECT count(*) cnt FROM t1 GROUP BY c2 HAVING c1 > 0");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION));
bind("SELECT count(*), c1 cnt FROM t1 GROUP BY c2 HAVING c2 > 0");
ASSERT_TRUE(run(TSDB_CODE_SUCCESS, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION));
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));
}
......@@ -20,18 +20,22 @@ typedef enum ETraversalOrder {
TRAVERSAL_POSTORDER
} ETraversalOrder;
static bool walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNodeWalker walker, void* pContext);
static EDealRes walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNodeWalker walker, void* pContext);
static bool walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker walker, void* pContext) {
static EDealRes walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker walker, void* pContext) {
if (NULL == pNode) {
return true;
return DEAL_RES_CONTINUE;
}
if (TRAVERSAL_PREORDER == order && !walker(pNode, pContext)) {
return false;
EDealRes res = DEAL_RES_CONTINUE;
if (TRAVERSAL_PREORDER == order) {
res = walker(pNode, pContext);
if (DEAL_RES_CONTINUE != res) {
return res;
}
}
bool res = true;
switch (nodeType(pNode)) {
case QUERY_NODE_COLUMN:
case QUERY_NODE_VALUE:
......@@ -41,7 +45,7 @@ static bool walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker walke
case QUERY_NODE_OPERATOR: {
SOperatorNode* pOpNode = (SOperatorNode*)pNode;
res = walkNode(pOpNode->pLeft, order, walker, pContext);
if (res) {
if (DEAL_RES_ERROR != res) {
res = walkNode(pOpNode->pRight, order, walker, pContext);
}
break;
......@@ -61,10 +65,10 @@ static bool walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker walke
case QUERY_NODE_JOIN_TABLE: {
SJoinTableNode* pJoinTableNode = (SJoinTableNode*)pNode;
res = walkNode(pJoinTableNode->pLeft, order, walker, pContext);
if (res) {
if (DEAL_RES_ERROR != res) {
res = walkNode(pJoinTableNode->pRight, order, walker, pContext);
}
if (res) {
if (DEAL_RES_ERROR != res) {
res = walkNode(pJoinTableNode->pOnCond, order, walker, pContext);
}
break;
......@@ -84,13 +88,13 @@ static bool walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker walke
case QUERY_NODE_INTERVAL_WINDOW: {
SIntervalWindowNode* pInterval = (SIntervalWindowNode*)pNode;
res = walkNode(pInterval->pInterval, order, walker, pContext);
if (res) {
if (DEAL_RES_ERROR != res) {
res = walkNode(pInterval->pOffset, order, walker, pContext);
}
if (res) {
if (DEAL_RES_ERROR != res) {
res = walkNode(pInterval->pSliding, order, walker, pContext);
}
if (res) {
if (DEAL_RES_ERROR != res) {
res = walkNode(pInterval->pFill, order, walker, pContext);
}
break;
......@@ -108,21 +112,21 @@ static bool walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker walke
break;
}
if (res && TRAVERSAL_POSTORDER == order) {
if (DEAL_RES_ERROR != res && TRAVERSAL_POSTORDER == order) {
res = walker(pNode, pContext);
}
return res;
}
static bool walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNodeWalker walker, void* pContext) {
static EDealRes walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNodeWalker walker, void* pContext) {
SNode* node;
FOREACH(node, pNodeList) {
if (!walkNode(node, order, walker, pContext)) {
return false;
if (DEAL_RES_ERROR == walkNode(node, order, walker, pContext)) {
return DEAL_RES_ERROR;
}
}
return true;
return DEAL_RES_CONTINUE;
}
void nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
......@@ -140,7 +144,3 @@ void nodesWalkNodePostOrder(SNode* pNode, FQueryNodeWalker walker, void* pContex
void nodesWalkListPostOrder(SNodeList* pList, FQueryNodeWalker walker, void* pContext) {
(void)walkList(pList, TRAVERSAL_POSTORDER, walker, pContext);
}
bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
}
......@@ -76,7 +76,7 @@ SNode* nodesMakeNode(ENodeType type) {
return NULL;
}
static bool destroyNode(SNode* pNode, void* pContext) {
static EDealRes destroyNode(SNode* pNode, void* pContext) {
switch (nodeType(pNode)) {
case QUERY_NODE_VALUE:
tfree(((SValueNode*)pNode)->literal);
......@@ -85,6 +85,7 @@ static bool destroyNode(SNode* pNode, void* pContext) {
break;
}
tfree(pNode);
return DEAL_RES_CONTINUE;
}
void nodesDestroyNode(SNode* pNode) {
......@@ -116,9 +117,23 @@ SNodeList* nodesListAppend(SNodeList* pList, SNode* pNode) {
pList->pTail->pNext = p;
}
pList->pTail = p;
++(pList->length);
return pList;
}
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) {
if (NULL == pCell->pPrev) {
pList->pHead = pCell->pNext;
} else {
pCell->pPrev->pNext = pCell->pNext;
pCell->pNext->pPrev = pCell->pPrev;
}
SListCell* pNext = pCell->pNext;
tfree(pCell);
--(pList->length);
return pNext;
}
SNode* nodesListGetNode(SNodeList* pList, int32_t index) {
SNode* node;
FOREACH(node, pList) {
......@@ -137,6 +152,11 @@ void nodesDestroyList(SNodeList* pList) {
tfree(pList);
}
bool nodesIsExprNode(const SNode* pNode) {
ENodeType type = nodeType(pNode);
return (QUERY_NODE_COLUMN == type || QUERY_NODE_VALUE == type || QUERY_NODE_OPERATOR == type || QUERY_NODE_FUNCTION == type);
}
bool nodesIsArithmeticOp(const SOperatorNode* pOp) {
switch (pOp->opType) {
case OP_TYPE_ADD:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册