未验证 提交 e00a9fa9 编写于 作者: X Xiaoyu Wang 提交者: GitHub

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

fix: some prblems of parser and planner
...@@ -228,23 +228,23 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t ...@@ -228,23 +228,23 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
taosPrintLog("QRY ", DEBUG_INFO, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \ taosPrintLog("QRY ", DEBUG_INFO, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
} \ } \
} while (0) } while (0)
#define qDebug(...) \ #define qDebug(...) \
do { \ do { \
if (qDebugFlag & DEBUG_DEBUG) { \ if (qDebugFlag & DEBUG_DEBUG) { \
taosPrintLog("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \ taosPrintLog("QRY ", DEBUG_DEBUG, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
} \ } \
} while (0) } while (0)
#define qTrace(...) \ #define qTrace(...) \
do { \ do { \
if (qDebugFlag & DEBUG_TRACE) { \ if (qDebugFlag & DEBUG_TRACE) { \
taosPrintLog("QRY ", DEBUG_TRACE, qDebugFlag, __VA_ARGS__); \ taosPrintLog("QRY ", DEBUG_TRACE, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
} \ } \
} while (0) } while (0)
#define qDebugL(...) \ #define qDebugL(...) \
do { \ do { \
if (qDebugFlag & DEBUG_DEBUG) { \ if (qDebugFlag & DEBUG_DEBUG) { \
taosPrintLongString("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \ taosPrintLongString("QRY ", DEBUG_DEBUG, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
} \ } \
} while (0) } while (0)
#define QRY_ERR_RET(c) \ #define QRY_ERR_RET(c) \
......
...@@ -241,7 +241,7 @@ alter_table_clause(A) ::= ...@@ -241,7 +241,7 @@ alter_table_clause(A) ::=
alter_table_clause(A) ::= alter_table_clause(A) ::=
full_table_name(B) RENAME TAG column_name(C) column_name(D). { A = createAlterTableRenameCol(pCxt, B, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, &C, &D); } full_table_name(B) RENAME TAG column_name(C) column_name(D). { A = createAlterTableRenameCol(pCxt, B, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, &C, &D); }
alter_table_clause(A) ::= alter_table_clause(A) ::=
full_table_name(B) SET TAG column_name(C) NK_EQ literal(D). { A = createAlterTableSetTag(pCxt, B, &C, releaseRawExprNode(pCxt, D)); } full_table_name(B) SET TAG column_name(C) NK_EQ signed_literal(D). { A = createAlterTableSetTag(pCxt, B, &C, D); }
%type multi_create_clause { SNodeList* } %type multi_create_clause { SNodeList* }
%destructor multi_create_clause { nodesDestroyList($$); } %destructor multi_create_clause { nodesDestroyList($$); }
...@@ -448,7 +448,7 @@ agg_func_opt(A) ::= AGGREGATE. ...@@ -448,7 +448,7 @@ agg_func_opt(A) ::= AGGREGATE.
%type bufsize_opt { int32_t } %type bufsize_opt { int32_t }
%destructor bufsize_opt { } %destructor bufsize_opt { }
bufsize_opt(A) ::= . { A = 0; } bufsize_opt(A) ::= . { A = 0; }
bufsize_opt(A) ::= BUFSIZE NK_INTEGER(B). { A = strtol(B.z, NULL, 10); } bufsize_opt(A) ::= BUFSIZE NK_INTEGER(B). { A = taosStr2Int32(B.z, NULL, 10); }
/************************************************ create/drop stream **************************************************/ /************************************************ create/drop stream **************************************************/
cmd ::= CREATE STREAM not_exists_opt(E) stream_name(A) cmd ::= CREATE STREAM not_exists_opt(E) stream_name(A)
......
...@@ -694,66 +694,110 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) { ...@@ -694,66 +694,110 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
return translateValueImpl(pCxt, pVal, pVal->node.resType); return translateValueImpl(pCxt, pVal, pVal->node.resType);
} }
static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) { static bool isMultiResFunc(SNode* pNode) {
if (nodesIsUnaryOp(pOp)) { if (NULL == pNode) {
if (OP_TYPE_MINUS == pOp->opType) { return false;
if (!IS_MATHABLE_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) { }
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName); if (QUERY_NODE_FUNCTION != nodeType(pNode) || !fmIsMultiResFunc(((SFunctionNode*)pNode)->funcId)) {
} return false;
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE; }
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes; SNodeList* pParameterList = ((SFunctionNode*)pNode)->pParameterList;
} else { if (LIST_LENGTH(pParameterList) > 1) {
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL; return true;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; }
SNode* pParam = nodesListGetNode(pParameterList, 0);
return (QUERY_NODE_COLUMN == nodeType(pParam) ? 0 == strcmp(((SColumnNode*)pParam)->colName, "*") : false);
}
static EDealRes translateUnaryOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
if (OP_TYPE_MINUS == pOp->opType) {
if (!IS_MATHABLE_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
} }
return DEAL_RES_CONTINUE; pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
} else {
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
} }
return DEAL_RES_CONTINUE;
}
static EDealRes translateArithmeticOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType; SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
SDataType rdt = ((SExprNode*)(pOp->pRight))->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 ||
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) {
TSDB_DATA_TYPE_BLOB == rdt.type) { return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); }
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_TIMESTAMP == rdt.type) ||
(TSDB_DATA_TYPE_TIMESTAMP == ldt.type && (IS_VAR_DATA_TYPE(rdt.type) || IS_FLOAT_TYPE(rdt.type))) ||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && (IS_VAR_DATA_TYPE(ldt.type) || IS_FLOAT_TYPE(ldt.type)))) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
}
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && IS_INTEGER_TYPE(rdt.type)) ||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && IS_INTEGER_TYPE(ldt.type)) ||
(TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_BOOL == rdt.type) ||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && TSDB_DATA_TYPE_BOOL == ldt.type)) {
pOp->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes;
} else {
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
}
return DEAL_RES_CONTINUE;
}
static EDealRes translateComparisonOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
}
if (OP_TYPE_IN == pOp->opType || OP_TYPE_NOT_IN == pOp->opType) {
((SExprNode*)pOp->pRight)->resType = ((SExprNode*)pOp->pLeft)->resType;
}
if (nodesIsRegularOp(pOp)) {
if (!IS_STR_DATA_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
} }
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_TIMESTAMP == rdt.type) || if (QUERY_NODE_VALUE != nodeType(pOp->pRight) || !IS_STR_DATA_TYPE(((SExprNode*)(pOp->pRight))->resType.type)) {
(TSDB_DATA_TYPE_TIMESTAMP == ldt.type && (IS_VAR_DATA_TYPE(rdt.type) || IS_FLOAT_TYPE(rdt.type))) ||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && (IS_VAR_DATA_TYPE(ldt.type) || IS_FLOAT_TYPE(ldt.type)))) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
} }
}
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
return DEAL_RES_CONTINUE;
}
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && IS_INTEGER_TYPE(rdt.type)) || static EDealRes translateJsonOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && IS_INTEGER_TYPE(ldt.type)) || SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
(TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_BOOL == rdt.type) || SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && TSDB_DATA_TYPE_BOOL == ldt.type)) { if (TSDB_DATA_TYPE_JSON != ldt.type || TSDB_DATA_TYPE_BINARY != rdt.type) {
pOp->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP; return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes; }
} else { pOp->node.resType.type = TSDB_DATA_TYPE_JSON;
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE; pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_JSON].bytes;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes; return DEAL_RES_CONTINUE;
} }
static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
if (isMultiResFunc(pOp->pLeft)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
}
if (isMultiResFunc(pOp->pRight)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
}
if (nodesIsUnaryOp(pOp)) {
return translateUnaryOperator(pCxt, pOp);
} else if (nodesIsArithmeticOp(pOp)) {
return translateArithmeticOperator(pCxt, pOp);
} else if (nodesIsComparisonOp(pOp)) { } else if (nodesIsComparisonOp(pOp)) {
if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) { return translateComparisonOperator(pCxt, pOp);
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
}
if (OP_TYPE_IN == pOp->opType || OP_TYPE_NOT_IN == pOp->opType) {
((SExprNode*)pOp->pRight)->resType = ((SExprNode*)pOp->pLeft)->resType;
}
if (nodesIsRegularOp(pOp)) {
if (!IS_STR_DATA_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
}
if (QUERY_NODE_VALUE != nodeType(pOp->pRight) || !IS_STR_DATA_TYPE(((SExprNode*)(pOp->pRight))->resType.type)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
}
}
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
} else if (nodesIsJsonOp(pOp)) { } else if (nodesIsJsonOp(pOp)) {
if (TSDB_DATA_TYPE_JSON != ldt.type || TSDB_DATA_TYPE_BINARY != rdt.type) { return translateJsonOperator(pCxt, pOp);
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
}
pOp->node.resType.type = TSDB_DATA_TYPE_JSON;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_JSON].bytes;
} }
return DEAL_RES_CONTINUE; return DEAL_RES_CONTINUE;
} }
...@@ -808,6 +852,13 @@ static bool hasInvalidFuncNesting(SNodeList* pParameterList) { ...@@ -808,6 +852,13 @@ static bool hasInvalidFuncNesting(SNodeList* pParameterList) {
} }
static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) { static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
SNode* pParam = NULL;
FOREACH(pParam, pFunc->pParameterList) {
if (isMultiResFunc(pParam)) {
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)pParam)->aliasName);
}
}
SFmGetFuncInfoParam param = {.pCtg = pCxt->pParseCxt->pCatalog, SFmGetFuncInfoParam param = {.pCtg = pCxt->pParseCxt->pCatalog,
.pRpc = pCxt->pParseCxt->pTransporter, .pRpc = pCxt->pParseCxt->pTransporter,
.pMgmtEps = &pCxt->pParseCxt->mgmtEpSet, .pMgmtEps = &pCxt->pParseCxt->mgmtEpSet,
...@@ -926,9 +977,10 @@ typedef struct SCheckExprForGroupByCxt { ...@@ -926,9 +977,10 @@ typedef struct SCheckExprForGroupByCxt {
STranslateContext* pTranslateCxt; STranslateContext* pTranslateCxt;
int32_t selectFuncNum; int32_t selectFuncNum;
bool hasSelectValFunc; bool hasSelectValFunc;
bool hasOtherAggFunc;
} SCheckExprForGroupByCxt; } SCheckExprForGroupByCxt;
static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSelectValFunc, SNode** pNode) { static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode) {
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION); SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
if (NULL == pFunc) { if (NULL == pFunc) {
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
...@@ -942,9 +994,6 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSel ...@@ -942,9 +994,6 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSel
} }
if (TSDB_CODE_SUCCESS == pCxt->errCode) { if (TSDB_CODE_SUCCESS == pCxt->errCode) {
*pNode = (SNode*)pFunc; *pNode = (SNode*)pFunc;
if (NULL != pHasSelectValFunc) {
*pHasSelectValFunc = true;
}
} else { } else {
nodesDestroyNode(pFunc); nodesDestroyNode(pFunc);
} }
...@@ -956,8 +1005,12 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { ...@@ -956,8 +1005,12 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) { if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) {
return DEAL_RES_CONTINUE; return DEAL_RES_CONTINUE;
} }
pCxt->selectFuncNum += isSelectFunc(*pNode) ? 1 : 0; if (isSelectFunc(*pNode)) {
if (pCxt->selectFuncNum > 1 && pCxt->hasSelectValFunc) { ++(pCxt->selectFuncNum);
} else if (isAggFunc(*pNode)) {
pCxt->hasOtherAggFunc = true;
}
if ((pCxt->selectFuncNum > 1 && pCxt->hasSelectValFunc) || (pCxt->hasOtherAggFunc && pCxt->hasSelectValFunc)) {
return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt)); return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
} }
if (isAggFunc(*pNode) && !isDistinctOrderBy(pCxt->pTranslateCxt)) { if (isAggFunc(*pNode) && !isDistinctOrderBy(pCxt->pTranslateCxt)) {
...@@ -970,10 +1023,11 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { ...@@ -970,10 +1023,11 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
} }
} }
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) { if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
if (pCxt->selectFuncNum > 1) { if (pCxt->selectFuncNum > 1 || pCxt->hasOtherAggFunc) {
return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt)); return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
} else { } else {
return rewriteColToSelectValFunc(pCxt->pTranslateCxt, &pCxt->hasSelectValFunc, pNode); pCxt->hasSelectValFunc = true;
return rewriteColToSelectValFunc(pCxt->pTranslateCxt, pNode);
} }
} }
if (isAggFunc(*pNode) && isDistinctOrderBy(pCxt->pTranslateCxt)) { if (isAggFunc(*pNode) && isDistinctOrderBy(pCxt->pTranslateCxt)) {
...@@ -983,7 +1037,8 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { ...@@ -983,7 +1037,8 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
} }
static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode** pNode) { static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode** pNode) {
SCheckExprForGroupByCxt cxt = {.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false}; SCheckExprForGroupByCxt cxt = {
.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false, .hasOtherAggFunc = false};
nodesRewriteExpr(pNode, doCheckExprForGroupBy, &cxt); nodesRewriteExpr(pNode, doCheckExprForGroupBy, &cxt);
if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) { if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt)); return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
...@@ -995,7 +1050,8 @@ static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList ...@@ -995,7 +1050,8 @@ static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList
if (NULL == getGroupByList(pCxt)) { if (NULL == getGroupByList(pCxt)) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
SCheckExprForGroupByCxt cxt = {.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false}; SCheckExprForGroupByCxt cxt = {
.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false, .hasOtherAggFunc = false};
nodesRewriteExprs(pList, doCheckExprForGroupBy, &cxt); nodesRewriteExprs(pList, doCheckExprForGroupBy, &cxt);
if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) { if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt)); return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
...@@ -1008,7 +1064,7 @@ static EDealRes rewriteColsToSelectValFuncImpl(SNode** pNode, void* pContext) { ...@@ -1008,7 +1064,7 @@ static EDealRes rewriteColsToSelectValFuncImpl(SNode** pNode, void* pContext) {
return DEAL_RES_IGNORE_CHILD; return DEAL_RES_IGNORE_CHILD;
} }
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) { if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
return rewriteColToSelectValFunc((STranslateContext*)pContext, NULL, pNode); return rewriteColToSelectValFunc((STranslateContext*)pContext, pNode);
} }
return DEAL_RES_CONTINUE; return DEAL_RES_CONTINUE;
} }
...@@ -1027,11 +1083,16 @@ typedef struct CheckAggColCoexistCxt { ...@@ -1027,11 +1083,16 @@ typedef struct CheckAggColCoexistCxt {
bool existCol; bool existCol;
bool existNonstdFunc; bool existNonstdFunc;
int32_t selectFuncNum; int32_t selectFuncNum;
bool existOtherAggFunc;
} CheckAggColCoexistCxt; } CheckAggColCoexistCxt;
static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) { static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) {
CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext; CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext;
pCxt->selectFuncNum += isSelectFunc(pNode) ? 1 : 0; if (isSelectFunc(pNode)) {
++(pCxt->selectFuncNum);
} else if (isAggFunc(pNode)) {
pCxt->existOtherAggFunc = true;
}
if (isAggFunc(pNode)) { if (isAggFunc(pNode)) {
pCxt->existAggFunc = true; pCxt->existAggFunc = true;
return DEAL_RES_IGNORE_CHILD; return DEAL_RES_IGNORE_CHILD;
...@@ -1050,13 +1111,17 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) ...@@ -1050,13 +1111,17 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
if (NULL != pSelect->pGroupByList) { if (NULL != pSelect->pGroupByList) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
CheckAggColCoexistCxt cxt = { CheckAggColCoexistCxt cxt = {.pTranslateCxt = pCxt,
.pTranslateCxt = pCxt, .existAggFunc = false, .existCol = false, .existNonstdFunc = false}; .existAggFunc = false,
.existCol = false,
.existNonstdFunc = false,
.selectFuncNum = 0,
.existOtherAggFunc = false};
nodesWalkExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt); nodesWalkExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt);
if (!pSelect->isDistinct) { if (!pSelect->isDistinct) {
nodesWalkExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt); nodesWalkExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt);
} }
if (1 == cxt.selectFuncNum) { if (1 == cxt.selectFuncNum && !cxt.existOtherAggFunc) {
return rewriteColsToSelectValFunc(pCxt, pSelect); return rewriteColsToSelectValFunc(pCxt, pSelect);
} }
if ((cxt.selectFuncNum > 1 || cxt.existAggFunc || NULL != pSelect->pWindow) && cxt.existCol) { if ((cxt.selectFuncNum > 1 || cxt.existAggFunc || NULL != pSelect->pWindow) && cxt.existCol) {
...@@ -1230,18 +1295,6 @@ static int32_t createAllColumns(STranslateContext* pCxt, SNodeList** pCols) { ...@@ -1230,18 +1295,6 @@ static int32_t createAllColumns(STranslateContext* pCxt, SNodeList** pCols) {
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
static bool isMultiResFunc(SNode* pNode) {
if (QUERY_NODE_FUNCTION != nodeType(pNode) || !fmIsMultiResFunc(((SFunctionNode*)pNode)->funcId)) {
return false;
}
SNodeList* pParameterList = ((SFunctionNode*)pNode)->pParameterList;
if (LIST_LENGTH(pParameterList) > 1) {
return true;
}
SNode* pParam = nodesListGetNode(pParameterList, 0);
return (QUERY_NODE_COLUMN == nodeType(pParam) ? 0 == strcmp(((SColumnNode*)pParam)->colName, "*") : false);
}
static SNode* createMultiResFunc(SFunctionNode* pSrcFunc, SExprNode* pExpr) { static SNode* createMultiResFunc(SFunctionNode* pSrcFunc, SExprNode* pExpr) {
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION); SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
if (NULL == pFunc) { if (NULL == pFunc) {
...@@ -1872,7 +1925,7 @@ static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) { ...@@ -1872,7 +1925,7 @@ static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
} }
static bool dataTypeEqual(const SDataType* l, const SDataType* r) { static bool dataTypeEqual(const SDataType* l, const SDataType* r) {
return (l->type == r->type && l->bytes == l->bytes && l->precision == r->precision && l->scale == l->scale); return (l->type == r->type && l->bytes == r->bytes && l->precision == r->precision && l->scale == r->scale);
} }
static int32_t createCastFunc(STranslateContext* pCxt, SNode* pExpr, SDataType dt, SNode** pCast) { static int32_t createCastFunc(STranslateContext* pCxt, SNode* pExpr, SDataType dt, SNode** pCast) {
...@@ -2726,8 +2779,11 @@ static int32_t buildCreateStbReq(STranslateContext* pCxt, SCreateTableStmt* pStm ...@@ -2726,8 +2779,11 @@ static int32_t buildCreateStbReq(STranslateContext* pCxt, SCreateTableStmt* pStm
SName tableName; SName tableName;
tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &tableName), pReq->name); tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &tableName), pReq->name);
int32_t code = collectUseTable(&tableName, pCxt->pTables);
return buildRollupAst(pCxt, pStmt, pReq); if (TSDB_CODE_SUCCESS == code) {
code = buildRollupAst(pCxt, pStmt, pReq);
}
return code;
} }
static int32_t translateCreateSuperTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) { static int32_t translateCreateSuperTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) {
...@@ -4032,13 +4088,18 @@ static int32_t createValueFromFunction(STranslateContext* pCxt, SFunctionNode* p ...@@ -4032,13 +4088,18 @@ static int32_t createValueFromFunction(STranslateContext* pCxt, SFunctionNode* p
return scalarCalculateConstants((SNode*)pFunc, (SNode**)pVal); return scalarCalculateConstants((SNode*)pFunc, (SNode**)pVal);
} }
static int32_t colDataBytesToValueDataBytes(uint8_t type, int32_t bytes) {
if (TSDB_DATA_TYPE_VARCHAR == type || TSDB_DATA_TYPE_BINARY == type || TSDB_DATA_TYPE_VARBINARY == type) {
return bytes - VARSTR_HEADER_SIZE;
} else if (TSDB_DATA_TYPE_NCHAR == type) {
return (bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
}
return bytes;
}
static SDataType schemaToDataType(SSchema* pSchema) { static SDataType schemaToDataType(SSchema* pSchema) {
SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes, .precision = 0, .scale = 0}; SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes, .precision = 0, .scale = 0};
if (TSDB_DATA_TYPE_VARCHAR == dt.type || TSDB_DATA_TYPE_BINARY == dt.type || TSDB_DATA_TYPE_VARBINARY == dt.type) { dt.bytes = colDataBytesToValueDataBytes(pSchema->type, pSchema->bytes);
dt.bytes -= VARSTR_HEADER_SIZE;
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
dt.bytes = (dt.bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
}
return dt; return dt;
} }
...@@ -4440,7 +4501,8 @@ static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt ...@@ -4440,7 +4501,8 @@ static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt
SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName); SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName);
if (NULL == pSchema) { if (NULL == pSchema) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName); return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName);
} else if (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->bytes >= pReq->colModBytes) { } else if (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type != pStmt->dataType.type ||
pSchema->bytes >= pReq->colModBytes) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_MODIFY_COL); return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_MODIFY_COL);
} }
......
此差异已折叠。
...@@ -239,6 +239,10 @@ TEST_F(ParserSelectTest, semanticError) { ...@@ -239,6 +239,10 @@ TEST_F(ParserSelectTest, semanticError) {
// TSDB_CODE_PAR_WRONG_VALUE_TYPE // TSDB_CODE_PAR_WRONG_VALUE_TYPE
run("SELECT timestamp '2010a' FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE); run("SELECT timestamp '2010a' FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
run("SELECT LAST(*) + SUM(c1) FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
run("SELECT CEIL(LAST(ts, c1)) FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
// TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION // TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
run("SELECT c2 FROM t1 tt1 join t1 tt2 on COUNT(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION, run("SELECT c2 FROM t1 tt1 join t1 tt2 on COUNT(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION,
PARSER_STAGE_TRANSLATE); PARSER_STAGE_TRANSLATE);
......
...@@ -248,6 +248,7 @@ static SLogicSubplan* unionCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode) ...@@ -248,6 +248,7 @@ static SLogicSubplan* unionCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode)
pSubplan->id.groupId = pCxt->groupId; pSubplan->id.groupId = pCxt->groupId;
pSubplan->subplanType = SUBPLAN_TYPE_SCAN; pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
pSubplan->pNode = pNode; pSubplan->pNode = pNode;
pNode->pParent = NULL;
return pSubplan; return pSubplan;
} }
...@@ -408,17 +409,30 @@ static const SSplitRule splitRuleSet[] = {{.pName = "SuperTableScan", .splitFunc ...@@ -408,17 +409,30 @@ static const SSplitRule splitRuleSet[] = {{.pName = "SuperTableScan", .splitFunc
static const int32_t splitRuleNum = (sizeof(splitRuleSet) / sizeof(SSplitRule)); static const int32_t splitRuleNum = (sizeof(splitRuleSet) / sizeof(SSplitRule));
static void dumpLogicSubplan(const char* pRuleName, SLogicSubplan* pSubplan) {
char* pStr = NULL;
nodesNodeToString(pSubplan, false, &pStr, NULL);
qDebugL("apply %s rule: %s", pRuleName, pStr);
taosMemoryFree(pStr);
}
static int32_t applySplitRule(SLogicSubplan* pSubplan) { static int32_t applySplitRule(SLogicSubplan* pSubplan) {
SSplitContext cxt = {.queryId = pSubplan->id.queryId, .groupId = pSubplan->id.groupId + 1, .split = false}; SSplitContext cxt = {.queryId = pSubplan->id.queryId, .groupId = pSubplan->id.groupId + 1, .split = false};
bool split = false;
do { do {
cxt.split = false; split = false;
for (int32_t i = 0; i < splitRuleNum; ++i) { for (int32_t i = 0; i < splitRuleNum; ++i) {
cxt.split = false;
int32_t code = splitRuleSet[i].splitFunc(&cxt, pSubplan); int32_t code = splitRuleSet[i].splitFunc(&cxt, pSubplan);
if (TSDB_CODE_SUCCESS != code) { if (TSDB_CODE_SUCCESS != code) {
return code; return code;
} }
if (cxt.split) {
split = true;
dumpLogicSubplan(splitRuleSet[i].pName, pSubplan);
}
} }
} while (cxt.split); } while (split);
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
......
...@@ -23,7 +23,12 @@ class PlanSetOpTest : public PlannerTestBase {}; ...@@ -23,7 +23,12 @@ class PlanSetOpTest : public PlannerTestBase {};
TEST_F(PlanSetOpTest, unionAll) { TEST_F(PlanSetOpTest, unionAll) {
useDb("root", "test"); useDb("root", "test");
// sql 1: single UNION ALL operator
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20"); run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20");
// sql 2: multi UNION ALL operator
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 "
"UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 "
"UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 30");
} }
TEST_F(PlanSetOpTest, unionAllSubquery) { TEST_F(PlanSetOpTest, unionAllSubquery) {
...@@ -44,7 +49,12 @@ TEST_F(PlanSetOpTest, unionAllWithSubquery) { ...@@ -44,7 +49,12 @@ TEST_F(PlanSetOpTest, unionAllWithSubquery) {
TEST_F(PlanSetOpTest, union) { TEST_F(PlanSetOpTest, union) {
useDb("root", "test"); useDb("root", "test");
// single UNION operator
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION SELECT c1, c2 FROM t1 WHERE c1 > 20"); run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION SELECT c1, c2 FROM t1 WHERE c1 > 20");
// multi UNION operator
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 "
"UNION SELECT c1, c2 FROM t1 WHERE c1 > 20 "
"UNION SELECT c1, c2 FROM t1 WHERE c1 > 30");
} }
TEST_F(PlanSetOpTest, unionContainJoin) { TEST_F(PlanSetOpTest, unionContainJoin) {
...@@ -62,3 +72,12 @@ TEST_F(PlanSetOpTest, unionSubquery) { ...@@ -62,3 +72,12 @@ TEST_F(PlanSetOpTest, unionSubquery) {
run("SELECT * FROM (SELECT c1, c2 FROM t1 UNION SELECT c1, c2 FROM t1)"); run("SELECT * FROM (SELECT c1, c2 FROM t1 UNION SELECT c1, c2 FROM t1)");
} }
TEST_F(PlanSetOpTest, bug001) {
useDb("root", "test");
run("SELECT c2 FROM t1 WHERE c1 IS NOT NULL GROUP BY c2 "
"UNION "
"SELECT 'abcdefghijklmnopqrstuvwxyz' FROM t1 "
"WHERE 'abcdefghijklmnopqrstuvwxyz' IS NOT NULL GROUP BY 'abcdefghijklmnopqrstuvwxyz'");
}
...@@ -23,9 +23,7 @@ class PlanSubqeuryTest : public PlannerTestBase {}; ...@@ -23,9 +23,7 @@ class PlanSubqeuryTest : public PlannerTestBase {};
TEST_F(PlanSubqeuryTest, basic) { TEST_F(PlanSubqeuryTest, basic) {
useDb("root", "test"); useDb("root", "test");
if (0 == g_skipSql) { run("SELECT * FROM (SELECT * FROM t1)");
run("SELECT * FROM (SELECT * FROM t1)");
}
run("SELECT LAST(c1) FROM (SELECT * FROM t1)"); run("SELECT LAST(c1) FROM (SELECT * FROM t1)");
} }
......
...@@ -35,18 +35,19 @@ class PlannerEnv : public testing::Environment { ...@@ -35,18 +35,19 @@ class PlannerEnv : public testing::Environment {
private: private:
void initLog(const char* path) { void initLog(const char* path) {
dDebugFlag = 143; int32_t logLevel = getLogLevel();
vDebugFlag = 0; dDebugFlag = logLevel;
mDebugFlag = 143; vDebugFlag = logLevel;
cDebugFlag = 0; mDebugFlag = logLevel;
jniDebugFlag = 0; cDebugFlag = logLevel;
tmrDebugFlag = 135; jniDebugFlag = logLevel;
uDebugFlag = 135; tmrDebugFlag = logLevel;
rpcDebugFlag = 143; uDebugFlag = logLevel;
qDebugFlag = 143; rpcDebugFlag = logLevel;
wDebugFlag = 0; qDebugFlag = logLevel;
sDebugFlag = 0; wDebugFlag = logLevel;
tsdbDebugFlag = 0; sDebugFlag = logLevel;
tsdbDebugFlag = logLevel;
tsLogEmbedded = 1; tsLogEmbedded = 1;
tsAsyncLog = 0; tsAsyncLog = 0;
...@@ -60,17 +61,26 @@ class PlannerEnv : public testing::Environment { ...@@ -60,17 +61,26 @@ class PlannerEnv : public testing::Environment {
}; };
static void parseArg(int argc, char* argv[]) { static void parseArg(int argc, char* argv[]) {
int opt = 0; int opt = 0;
const char* optstring = ""; const char* optstring = "";
// clang-format off
static struct option long_options[] = { static struct option long_options[] = {
{"dump", optional_argument, NULL, 'd'}, {"skipSql", optional_argument, NULL, 's'}, {0, 0, 0, 0}}; {"dump", optional_argument, NULL, 'd'},
{"skipSql", required_argument, NULL, 's'},
{"log", required_argument, NULL, 'l'},
{0, 0, 0, 0}
};
// clang-format on
while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
switch (opt) { switch (opt) {
case 'd': case 'd':
setDumpModule(optarg); setDumpModule(optarg);
break; break;
case 's': case 's':
g_skipSql = 1; setSkipSqlNum(optarg);
break;
case 'l':
setLogLevel(optarg);
break; break;
default: default:
break; break;
......
...@@ -48,6 +48,7 @@ enum DumpModule { ...@@ -48,6 +48,7 @@ enum DumpModule {
DumpModule g_dumpModule = DUMP_MODULE_NOTHING; DumpModule g_dumpModule = DUMP_MODULE_NOTHING;
int32_t g_skipSql = 0; int32_t g_skipSql = 0;
int32_t g_logLevel = 131;
void setDumpModule(const char* pModule) { void setDumpModule(const char* pModule) {
if (NULL == pModule) { if (NULL == pModule) {
...@@ -71,14 +72,26 @@ void setDumpModule(const char* pModule) { ...@@ -71,14 +72,26 @@ void setDumpModule(const char* pModule) {
} }
} }
void setSkipSqlNum(const char* pNum) { g_skipSql = stoi(optarg); }
void setLogLevel(const char* pLogLevel) { g_logLevel = stoi(pLogLevel); }
int32_t getLogLevel() { return g_logLevel; }
class PlannerTestBaseImpl { class PlannerTestBaseImpl {
public: public:
void useDb(const string& acctId, const string& db) { void useDb(const string& acctId, const string& db) {
caseEnv_.acctId_ = acctId; caseEnv_.acctId_ = acctId;
caseEnv_.db_ = db; caseEnv_.db_ = db;
caseEnv_.nsql_ = g_skipSql;
} }
void run(const string& sql) { void run(const string& sql) {
if (caseEnv_.nsql_ > 0) {
--(caseEnv_.nsql_);
return;
}
reset(); reset();
try { try {
SQuery* pQuery = nullptr; SQuery* pQuery = nullptr;
...@@ -109,6 +122,10 @@ class PlannerTestBaseImpl { ...@@ -109,6 +122,10 @@ class PlannerTestBaseImpl {
} }
void prepare(const string& sql) { void prepare(const string& sql) {
if (caseEnv_.nsql_ > 0) {
return;
}
reset(); reset();
try { try {
doParseSql(sql, &stmtEnv_.pQuery_, true); doParseSql(sql, &stmtEnv_.pQuery_, true);
...@@ -119,6 +136,10 @@ class PlannerTestBaseImpl { ...@@ -119,6 +136,10 @@ class PlannerTestBaseImpl {
} }
void bindParams(TAOS_MULTI_BIND* pParams, int32_t colIdx) { void bindParams(TAOS_MULTI_BIND* pParams, int32_t colIdx) {
if (caseEnv_.nsql_ > 0) {
return;
}
try { try {
doBindParams(stmtEnv_.pQuery_, pParams, colIdx); doBindParams(stmtEnv_.pQuery_, pParams, colIdx);
} catch (...) { } catch (...) {
...@@ -128,6 +149,11 @@ class PlannerTestBaseImpl { ...@@ -128,6 +149,11 @@ class PlannerTestBaseImpl {
} }
void exec() { void exec() {
if (caseEnv_.nsql_ > 0) {
--(caseEnv_.nsql_);
return;
}
try { try {
doParseBoundSql(stmtEnv_.pQuery_); doParseBoundSql(stmtEnv_.pQuery_);
...@@ -157,8 +183,9 @@ class PlannerTestBaseImpl { ...@@ -157,8 +183,9 @@ class PlannerTestBaseImpl {
private: private:
struct caseEnv { struct caseEnv {
string acctId_; string acctId_;
string db_; string db_;
int32_t nsql_;
}; };
struct stmtEnv { struct stmtEnv {
......
...@@ -37,8 +37,9 @@ class PlannerTestBase : public testing::Test { ...@@ -37,8 +37,9 @@ class PlannerTestBase : public testing::Test {
std::unique_ptr<PlannerTestBaseImpl> impl_; std::unique_ptr<PlannerTestBaseImpl> impl_;
}; };
extern int32_t g_skipSql; extern void setDumpModule(const char* pModule);
extern void setSkipSqlNum(const char* pNum);
extern void setDumpModule(const char* pModule); extern void setLogLevel(const char* pLogLevel);
extern int32_t getLogLevel();
#endif // PLAN_TEST_UTIL_H #endif // PLAN_TEST_UTIL_H
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册