fix: some prblems of parser and planner
This commit is contained in:
parent
3d0a218105
commit
bec1c2463c
|
@ -225,19 +225,19 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
|
|||
#define qDebug(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_DEBUG) { \
|
||||
taosPrintLog("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \
|
||||
taosPrintLog("QRY ", DEBUG_DEBUG, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define qTrace(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_TRACE) { \
|
||||
taosPrintLog("QRY ", DEBUG_TRACE, qDebugFlag, __VA_ARGS__); \
|
||||
taosPrintLog("QRY ", DEBUG_TRACE, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define qDebugL(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_DEBUG) { \
|
||||
taosPrintLongString("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \
|
||||
taosPrintLongString("QRY ", DEBUG_DEBUG, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ 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); }
|
||||
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* }
|
||||
%destructor multi_create_clause { nodesDestroyList($$); }
|
||||
|
@ -448,7 +448,7 @@ agg_func_opt(A) ::= AGGREGATE.
|
|||
%type bufsize_opt { int32_t }
|
||||
%destructor bufsize_opt { }
|
||||
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 **************************************************/
|
||||
cmd ::= CREATE STREAM not_exists_opt(E) stream_name(A)
|
||||
|
|
|
@ -694,8 +694,22 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
|
|||
return translateValueImpl(pCxt, pVal, pVal->node.resType);
|
||||
}
|
||||
|
||||
static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
if (nodesIsUnaryOp(pOp)) {
|
||||
static bool isMultiResFunc(SNode* pNode) {
|
||||
if (NULL == pNode) {
|
||||
return false;
|
||||
}
|
||||
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 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);
|
||||
|
@ -707,10 +721,11 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
|||
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 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) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
|
@ -731,7 +746,12 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
|||
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
|
||||
}
|
||||
} else if (nodesIsComparisonOp(pOp)) {
|
||||
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);
|
||||
}
|
||||
|
@ -748,12 +768,36 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
|||
}
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
|
||||
} else if (nodesIsJsonOp(pOp)) {
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static EDealRes translateJsonOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
|
||||
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
|
||||
if (TSDB_DATA_TYPE_JSON != ldt.type || TSDB_DATA_TYPE_BINARY != rdt.type) {
|
||||
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;
|
||||
}
|
||||
|
||||
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)) {
|
||||
return translateComparisonOperator(pCxt, pOp);
|
||||
} else if (nodesIsJsonOp(pOp)) {
|
||||
return translateJsonOperator(pCxt, pOp);
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
@ -808,6 +852,13 @@ static bool hasInvalidFuncNesting(SNodeList* pParameterList) {
|
|||
}
|
||||
|
||||
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,
|
||||
.pRpc = pCxt->pParseCxt->pTransporter,
|
||||
.pMgmtEps = &pCxt->pParseCxt->mgmtEpSet,
|
||||
|
@ -926,9 +977,10 @@ typedef struct SCheckExprForGroupByCxt {
|
|||
STranslateContext* pTranslateCxt;
|
||||
int32_t selectFuncNum;
|
||||
bool hasSelectValFunc;
|
||||
bool hasOtherAggFunc;
|
||||
} SCheckExprForGroupByCxt;
|
||||
|
||||
static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSelectValFunc, SNode** pNode) {
|
||||
static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode) {
|
||||
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||
if (NULL == pFunc) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
@ -942,9 +994,6 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSel
|
|||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
*pNode = (SNode*)pFunc;
|
||||
if (NULL != pHasSelectValFunc) {
|
||||
*pHasSelectValFunc = true;
|
||||
}
|
||||
} else {
|
||||
nodesDestroyNode(pFunc);
|
||||
}
|
||||
|
@ -956,8 +1005,12 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) {
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
pCxt->selectFuncNum += isSelectFunc(*pNode) ? 1 : 0;
|
||||
if (pCxt->selectFuncNum > 1 && pCxt->hasSelectValFunc) {
|
||||
if (isSelectFunc(*pNode)) {
|
||||
++(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));
|
||||
}
|
||||
if (isAggFunc(*pNode) && !isDistinctOrderBy(pCxt->pTranslateCxt)) {
|
||||
|
@ -970,10 +1023,11 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
}
|
||||
}
|
||||
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));
|
||||
} else {
|
||||
return rewriteColToSelectValFunc(pCxt->pTranslateCxt, &pCxt->hasSelectValFunc, pNode);
|
||||
pCxt->hasSelectValFunc = true;
|
||||
return rewriteColToSelectValFunc(pCxt->pTranslateCxt, pNode);
|
||||
}
|
||||
}
|
||||
if (isAggFunc(*pNode) && isDistinctOrderBy(pCxt->pTranslateCxt)) {
|
||||
|
@ -983,7 +1037,8 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
}
|
||||
|
||||
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);
|
||||
if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
|
||||
|
@ -995,7 +1050,8 @@ static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList
|
|||
if (NULL == getGroupByList(pCxt)) {
|
||||
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);
|
||||
if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
|
||||
|
@ -1008,7 +1064,7 @@ static EDealRes rewriteColsToSelectValFuncImpl(SNode** pNode, void* pContext) {
|
|||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||
return rewriteColToSelectValFunc((STranslateContext*)pContext, NULL, pNode);
|
||||
return rewriteColToSelectValFunc((STranslateContext*)pContext, pNode);
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
@ -1027,11 +1083,16 @@ typedef struct CheckAggColCoexistCxt {
|
|||
bool existCol;
|
||||
bool existNonstdFunc;
|
||||
int32_t selectFuncNum;
|
||||
bool existOtherAggFunc;
|
||||
} CheckAggColCoexistCxt;
|
||||
|
||||
static EDealRes doCheckAggColCoexist(SNode* pNode, void* 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)) {
|
||||
pCxt->existAggFunc = true;
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
|
@ -1050,13 +1111,17 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
|
|||
if (NULL != pSelect->pGroupByList) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
CheckAggColCoexistCxt cxt = {
|
||||
.pTranslateCxt = pCxt, .existAggFunc = false, .existCol = false, .existNonstdFunc = false};
|
||||
CheckAggColCoexistCxt cxt = {.pTranslateCxt = pCxt,
|
||||
.existAggFunc = false,
|
||||
.existCol = false,
|
||||
.existNonstdFunc = false,
|
||||
.selectFuncNum = 0,
|
||||
.existOtherAggFunc = false};
|
||||
nodesWalkExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt);
|
||||
if (!pSelect->isDistinct) {
|
||||
nodesWalkExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt);
|
||||
}
|
||||
if (1 == cxt.selectFuncNum) {
|
||||
if (1 == cxt.selectFuncNum && !cxt.existOtherAggFunc) {
|
||||
return rewriteColsToSelectValFunc(pCxt, pSelect);
|
||||
}
|
||||
if ((cxt.selectFuncNum > 1 || cxt.existAggFunc || NULL != pSelect->pWindow) && cxt.existCol) {
|
||||
|
@ -1230,18 +1295,6 @@ static int32_t createAllColumns(STranslateContext* pCxt, SNodeList** pCols) {
|
|||
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) {
|
||||
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||
if (NULL == pFunc) {
|
||||
|
@ -1872,7 +1925,7 @@ static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -2726,8 +2779,11 @@ static int32_t buildCreateStbReq(STranslateContext* pCxt, SCreateTableStmt* pStm
|
|||
|
||||
SName tableName;
|
||||
tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &tableName), pReq->name);
|
||||
|
||||
return buildRollupAst(pCxt, pStmt, pReq);
|
||||
int32_t code = collectUseTable(&tableName, pCxt->pTables);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = buildRollupAst(pCxt, pStmt, pReq);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateCreateSuperTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) {
|
||||
|
@ -4032,13 +4088,18 @@ static int32_t createValueFromFunction(STranslateContext* pCxt, SFunctionNode* p
|
|||
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) {
|
||||
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 -= VARSTR_HEADER_SIZE;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
|
||||
dt.bytes = (dt.bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
}
|
||||
dt.bytes = colDataBytesToValueDataBytes(pSchema->type, pSchema->bytes);
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
@ -4440,7 +4501,8 @@ static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt
|
|||
SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName);
|
||||
if (NULL == pSchema) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -239,6 +239,10 @@ TEST_F(ParserSelectTest, semanticError) {
|
|||
// TSDB_CODE_PAR_WRONG_VALUE_TYPE
|
||||
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
|
||||
run("SELECT c2 FROM t1 tt1 join t1 tt2 on COUNT(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION,
|
||||
PARSER_STAGE_TRANSLATE);
|
||||
|
|
|
@ -248,6 +248,7 @@ static SLogicSubplan* unionCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode)
|
|||
pSubplan->id.groupId = pCxt->groupId;
|
||||
pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
|
||||
pSubplan->pNode = pNode;
|
||||
pNode->pParent = NULL;
|
||||
return pSubplan;
|
||||
}
|
||||
|
||||
|
@ -408,17 +409,30 @@ static const SSplitRule splitRuleSet[] = {{.pName = "SuperTableScan", .splitFunc
|
|||
|
||||
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) {
|
||||
SSplitContext cxt = {.queryId = pSubplan->id.queryId, .groupId = pSubplan->id.groupId + 1, .split = false};
|
||||
bool split = false;
|
||||
do {
|
||||
cxt.split = false;
|
||||
split = false;
|
||||
for (int32_t i = 0; i < splitRuleNum; ++i) {
|
||||
cxt.split = false;
|
||||
int32_t code = splitRuleSet[i].splitFunc(&cxt, pSubplan);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
if (cxt.split) {
|
||||
split = true;
|
||||
dumpLogicSubplan(splitRuleSet[i].pName, pSubplan);
|
||||
}
|
||||
} while (cxt.split);
|
||||
}
|
||||
} while (split);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,12 @@ class PlanSetOpTest : public PlannerTestBase {};
|
|||
TEST_F(PlanSetOpTest, unionAll) {
|
||||
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");
|
||||
// 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) {
|
||||
|
@ -44,7 +49,12 @@ TEST_F(PlanSetOpTest, unionAllWithSubquery) {
|
|||
TEST_F(PlanSetOpTest, union) {
|
||||
useDb("root", "test");
|
||||
|
||||
// single UNION operator
|
||||
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) {
|
||||
|
@ -62,3 +72,12 @@ TEST_F(PlanSetOpTest, unionSubquery) {
|
|||
|
||||
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 {};
|
|||
TEST_F(PlanSubqeuryTest, basic) {
|
||||
useDb("root", "test");
|
||||
|
||||
if (0 == g_skipSql) {
|
||||
run("SELECT * FROM (SELECT * FROM t1)");
|
||||
}
|
||||
|
||||
run("SELECT LAST(c1) FROM (SELECT * FROM t1)");
|
||||
}
|
||||
|
|
|
@ -35,18 +35,19 @@ class PlannerEnv : public testing::Environment {
|
|||
|
||||
private:
|
||||
void initLog(const char* path) {
|
||||
dDebugFlag = 143;
|
||||
vDebugFlag = 0;
|
||||
mDebugFlag = 143;
|
||||
cDebugFlag = 0;
|
||||
jniDebugFlag = 0;
|
||||
tmrDebugFlag = 135;
|
||||
uDebugFlag = 135;
|
||||
rpcDebugFlag = 143;
|
||||
qDebugFlag = 143;
|
||||
wDebugFlag = 0;
|
||||
sDebugFlag = 0;
|
||||
tsdbDebugFlag = 0;
|
||||
int32_t logLevel = getLogLevel();
|
||||
dDebugFlag = logLevel;
|
||||
vDebugFlag = logLevel;
|
||||
mDebugFlag = logLevel;
|
||||
cDebugFlag = logLevel;
|
||||
jniDebugFlag = logLevel;
|
||||
tmrDebugFlag = logLevel;
|
||||
uDebugFlag = logLevel;
|
||||
rpcDebugFlag = logLevel;
|
||||
qDebugFlag = logLevel;
|
||||
wDebugFlag = logLevel;
|
||||
sDebugFlag = logLevel;
|
||||
tsdbDebugFlag = logLevel;
|
||||
tsLogEmbedded = 1;
|
||||
tsAsyncLog = 0;
|
||||
|
||||
|
@ -62,15 +63,24 @@ class PlannerEnv : public testing::Environment {
|
|||
static void parseArg(int argc, char* argv[]) {
|
||||
int opt = 0;
|
||||
const char* optstring = "";
|
||||
// clang-format off
|
||||
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) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
setDumpModule(optarg);
|
||||
break;
|
||||
case 's':
|
||||
g_skipSql = 1;
|
||||
setSkipSqlNum(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
setLogLevel(optarg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -48,6 +48,7 @@ enum DumpModule {
|
|||
|
||||
DumpModule g_dumpModule = DUMP_MODULE_NOTHING;
|
||||
int32_t g_skipSql = 0;
|
||||
int32_t g_logLevel = 131;
|
||||
|
||||
void setDumpModule(const char* pModule) {
|
||||
if (NULL == 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 {
|
||||
public:
|
||||
void useDb(const string& acctId, const string& db) {
|
||||
caseEnv_.acctId_ = acctId;
|
||||
caseEnv_.db_ = db;
|
||||
caseEnv_.nsql_ = g_skipSql;
|
||||
}
|
||||
|
||||
void run(const string& sql) {
|
||||
if (caseEnv_.nsql_ > 0) {
|
||||
--(caseEnv_.nsql_);
|
||||
return;
|
||||
}
|
||||
|
||||
reset();
|
||||
try {
|
||||
SQuery* pQuery = nullptr;
|
||||
|
@ -109,6 +122,10 @@ class PlannerTestBaseImpl {
|
|||
}
|
||||
|
||||
void prepare(const string& sql) {
|
||||
if (caseEnv_.nsql_ > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
reset();
|
||||
try {
|
||||
doParseSql(sql, &stmtEnv_.pQuery_, true);
|
||||
|
@ -119,6 +136,10 @@ class PlannerTestBaseImpl {
|
|||
}
|
||||
|
||||
void bindParams(TAOS_MULTI_BIND* pParams, int32_t colIdx) {
|
||||
if (caseEnv_.nsql_ > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
doBindParams(stmtEnv_.pQuery_, pParams, colIdx);
|
||||
} catch (...) {
|
||||
|
@ -128,6 +149,11 @@ class PlannerTestBaseImpl {
|
|||
}
|
||||
|
||||
void exec() {
|
||||
if (caseEnv_.nsql_ > 0) {
|
||||
--(caseEnv_.nsql_);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
doParseBoundSql(stmtEnv_.pQuery_);
|
||||
|
||||
|
@ -159,6 +185,7 @@ class PlannerTestBaseImpl {
|
|||
struct caseEnv {
|
||||
string acctId_;
|
||||
string db_;
|
||||
int32_t nsql_;
|
||||
};
|
||||
|
||||
struct stmtEnv {
|
||||
|
|
|
@ -37,8 +37,9 @@ class PlannerTestBase : public testing::Test {
|
|||
std::unique_ptr<PlannerTestBaseImpl> impl_;
|
||||
};
|
||||
|
||||
extern int32_t g_skipSql;
|
||||
|
||||
extern void setDumpModule(const char* pModule);
|
||||
extern void setSkipSqlNum(const char* pNum);
|
||||
extern void setLogLevel(const char* pLogLevel);
|
||||
extern int32_t getLogLevel();
|
||||
|
||||
#endif // PLAN_TEST_UTIL_H
|
||||
|
|
Loading…
Reference in New Issue