Merge pull request #12667 from taosdata/feature/3.0_wxy
fix: some problems of parser and planner
This commit is contained in:
commit
ee76009a8f
|
@ -248,6 +248,7 @@ typedef struct SSetOperator {
|
|||
SNode* pRight;
|
||||
SNodeList* pOrderByList; // SOrderByExprNode
|
||||
SNode* pLimit;
|
||||
char stmtName[TSDB_TABLE_NAME_LEN];
|
||||
} SSetOperator;
|
||||
|
||||
typedef enum ESqlClause {
|
||||
|
|
|
@ -646,6 +646,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_PAR_INVALID_ALTER_TABLE TAOS_DEF_ERROR_CODE(0, 0x2649)
|
||||
#define TSDB_CODE_PAR_CANNOT_DROP_PRIMARY_KEY TAOS_DEF_ERROR_CODE(0, 0x264A)
|
||||
#define TSDB_CODE_PAR_INVALID_MODIFY_COL TAOS_DEF_ERROR_CODE(0, 0x264B)
|
||||
#define TSDB_CODE_PAR_INVALID_TBNAME TAOS_DEF_ERROR_CODE(0, 0x264C)
|
||||
|
||||
//planner
|
||||
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
|
||||
|
|
|
@ -621,6 +621,7 @@ column_reference(A) ::= table_name(B) NK_DOT column_name(C).
|
|||
|
||||
pseudo_column(A) ::= ROWTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= TBNAME(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= table_name(B) NK_DOT TBNAME(C). { A = createRawExprNodeExt(pCxt, &B, &C, createFunctionNode(pCxt, &C, createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &B)))); }
|
||||
pseudo_column(A) ::= QSTARTTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= QENDTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= WSTARTTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
|
|
|
@ -155,9 +155,9 @@ static bool checkPort(SAstCreateContext* pCxt, const SToken* pPortToken, int32_t
|
|||
return TSDB_CODE_SUCCESS == pCxt->errCode;
|
||||
}
|
||||
|
||||
static bool checkDbName(SAstCreateContext* pCxt, SToken* pDbName, bool query) {
|
||||
static bool checkDbName(SAstCreateContext* pCxt, SToken* pDbName, bool demandDb) {
|
||||
if (NULL == pDbName) {
|
||||
if (query && NULL == pCxt->pQueryCxt->db) {
|
||||
if (demandDb && NULL == pCxt->pQueryCxt->db) {
|
||||
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DB_NOT_SPECIFIED);
|
||||
}
|
||||
} else {
|
||||
|
@ -457,6 +457,8 @@ SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const STok
|
|||
}
|
||||
if (QUERY_NODE_SELECT_STMT == nodeType(pSubquery)) {
|
||||
strcpy(((SSelectStmt*)pSubquery)->stmtName, tempTable->table.tableAlias);
|
||||
} else if (QUERY_NODE_SET_OPERATOR == nodeType(pSubquery)) {
|
||||
strcpy(((SSetOperator*)pSubquery)->stmtName, tempTable->table.tableAlias);
|
||||
}
|
||||
return (SNode*)tempTable;
|
||||
}
|
||||
|
@ -637,6 +639,7 @@ SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode*
|
|||
setOp->opType = type;
|
||||
setOp->pLeft = pLeft;
|
||||
setOp->pRight = pRight;
|
||||
sprintf(setOp->stmtName, "%p", setOp);
|
||||
return (SNode*)setOp;
|
||||
}
|
||||
|
||||
|
@ -1140,7 +1143,7 @@ SNode* createAlterDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode, const
|
|||
|
||||
SNode* createCreateIndexStmt(SAstCreateContext* pCxt, EIndexType type, bool ignoreExists, SToken* pIndexName,
|
||||
SToken* pTableName, SNodeList* pCols, SNode* pOptions) {
|
||||
if (!checkIndexName(pCxt, pIndexName) || !checkTableName(pCxt, pTableName)) {
|
||||
if (!checkIndexName(pCxt, pIndexName) || !checkTableName(pCxt, pTableName) || !checkDbName(pCxt, NULL, true)) {
|
||||
return NULL;
|
||||
}
|
||||
SCreateIndexStmt* pStmt = nodesMakeNode(QUERY_NODE_CREATE_INDEX_STMT);
|
||||
|
|
|
@ -766,6 +766,20 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
|
|||
pCxt->pCurrStmt->hasRepeatScanFuncs = true;
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsScanPseudoColumnFunc(pFunc->funcId)) {
|
||||
if (0 == LIST_LENGTH(pFunc->pParameterList)) {
|
||||
if (QUERY_NODE_REAL_TABLE != nodeType(pCxt->pCurrStmt->pFromTable)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_TBNAME);
|
||||
}
|
||||
} else {
|
||||
SValueNode* pVal = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
STableNode* pTable = NULL;
|
||||
pCxt->errCode = findTable(pCxt, pVal->literal, &pTable);
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode && (NULL == pTable || QUERY_NODE_REAL_TABLE != nodeType(pTable))) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_TBNAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
|
||||
}
|
||||
|
||||
|
@ -1758,12 +1772,13 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static SNode* createSetOperProject(SNode* pNode) {
|
||||
static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
|
||||
SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN);
|
||||
if (NULL == pCol) {
|
||||
return NULL;
|
||||
}
|
||||
pCol->node.resType = ((SExprNode*)pNode)->resType;
|
||||
strcpy(pCol->tableAlias, pTableAlias);
|
||||
strcpy(pCol->colName, ((SExprNode*)pNode)->aliasName);
|
||||
strcpy(pCol->node.aliasName, pCol->colName);
|
||||
return (SNode*)pCol;
|
||||
|
@ -1817,7 +1832,8 @@ static int32_t translateSetOperatorImpl(STranslateContext* pCxt, SSetOperator* p
|
|||
}
|
||||
strcpy(pRightExpr->aliasName, pLeftExpr->aliasName);
|
||||
pRightExpr->aliasName[strlen(pLeftExpr->aliasName)] = '\0';
|
||||
if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pSetOperator->pProjectionList, createSetOperProject(pLeft))) {
|
||||
if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pSetOperator->pProjectionList,
|
||||
createSetOperProject(pSetOperator->stmtName, pLeft))) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,6 +158,8 @@ static char* getSyntaxErrFormat(int32_t errCode) {
|
|||
return "Primary timestamp column cannot be dropped";
|
||||
case TSDB_CODE_PAR_INVALID_MODIFY_COL:
|
||||
return "Only binary/nchar column length could be modified";
|
||||
case TSDB_CODE_PAR_INVALID_TBNAME:
|
||||
return "Invalid tbname pseudo column";
|
||||
case TSDB_CODE_OUT_OF_MEMORY:
|
||||
return "Out of memory";
|
||||
default:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -70,6 +70,12 @@ TEST_F(ParserSelectTest, pseudoColumn) {
|
|||
run("SELECT _WSTARTTS, _WENDTS, COUNT(*) FROM t1 INTERVAL(10s)");
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, pseudoColumnSemanticCheck) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT TBNAME FROM (SELECT * FROM st1s1)", TSDB_CODE_PAR_INVALID_TBNAME, PARSER_STAGE_TRANSLATE);
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, multiResFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
|
|
|
@ -27,12 +27,13 @@ extern "C" {
|
|||
#define QUERY_POLICY_HYBRID 2
|
||||
#define QUERY_POLICY_QNODE 3
|
||||
|
||||
#define planFatal(param, ...) qFatal("PLAN: " param, __VA_ARGS__)
|
||||
#define planError(param, ...) qError("PLAN: " param, __VA_ARGS__)
|
||||
#define planWarn(param, ...) qWarn("PLAN: " param, __VA_ARGS__)
|
||||
#define planInfo(param, ...) qInfo("PLAN: " param, __VA_ARGS__)
|
||||
#define planDebug(param, ...) qDebug("PLAN: " param, __VA_ARGS__)
|
||||
#define planTrace(param, ...) qTrace("PLAN: " param, __VA_ARGS__)
|
||||
#define planFatal(param, ...) qFatal("PLAN: " param, __VA_ARGS__)
|
||||
#define planError(param, ...) qError("PLAN: " param, __VA_ARGS__)
|
||||
#define planWarn(param, ...) qWarn("PLAN: " param, __VA_ARGS__)
|
||||
#define planInfo(param, ...) qInfo("PLAN: " param, __VA_ARGS__)
|
||||
#define planDebug(param, ...) qDebug("PLAN: " param, __VA_ARGS__)
|
||||
#define planDebugL(param, ...) qDebugL("PLAN: " param, __VA_ARGS__)
|
||||
#define planTrace(param, ...) qTrace("PLAN: " param, __VA_ARGS__)
|
||||
|
||||
int32_t generateUsageErrMsg(char* pBuf, int32_t len, int32_t errCode, ...);
|
||||
|
||||
|
|
|
@ -310,12 +310,7 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
|
|||
|
||||
static int32_t createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable,
|
||||
SLogicNode** pLogicNode) {
|
||||
int32_t code = createQueryLogicNode(pCxt, pTable->pSubquery, pLogicNode);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
SNode* pNode;
|
||||
FOREACH(pNode, (*pLogicNode)->pTargets) { strcpy(((SColumnNode*)pNode)->tableAlias, pTable->table.tableAlias); }
|
||||
}
|
||||
return code;
|
||||
return createQueryLogicNode(pCxt, pTable->pSubquery, pLogicNode);
|
||||
}
|
||||
|
||||
static int32_t createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable,
|
||||
|
@ -879,7 +874,8 @@ static int32_t createSetOpProjectLogicNode(SLogicPlanContext* pCxt, SSetOperator
|
|||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createColumnByProjections(pCxt, NULL, pSetOperator->pProjectionList, &pProject->node.pTargets);
|
||||
code = createColumnByProjections(pCxt, pSetOperator->stmtName, pSetOperator->pProjectionList,
|
||||
&pProject->node.pTargets);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -933,7 +929,7 @@ static int32_t createSetOpLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetO
|
|||
code = createSetOpAggLogicNode(pCxt, pSetOperator, &pSetOp);
|
||||
break;
|
||||
default:
|
||||
code = -1;
|
||||
code = TSDB_CODE_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -598,39 +598,63 @@ static bool cpdIsPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int32_t cpdCheckOpCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode* pOnCond) {
|
||||
if (!cpdIsPrimaryKeyEqualCond(pJoin, pOnCond)) {
|
||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
static bool cpdContainPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pCond)) {
|
||||
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)pCond;
|
||||
if (LOGIC_COND_TYPE_AND != pLogicCond->condType) {
|
||||
return false;
|
||||
}
|
||||
bool hasPrimaryKeyEqualCond = false;
|
||||
SNode* pCond = NULL;
|
||||
FOREACH(pCond, pLogicCond->pParameterList) {
|
||||
if (cpdContainPrimaryKeyEqualCond(pJoin, pCond)) {
|
||||
hasPrimaryKeyEqualCond = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hasPrimaryKeyEqualCond;
|
||||
} else {
|
||||
return cpdIsPrimaryKeyEqualCond(pJoin, pCond);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t cpdCheckLogicCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SLogicConditionNode* pOnCond) {
|
||||
if (LOGIC_COND_TYPE_AND != pOnCond->condType) {
|
||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
}
|
||||
bool hasPrimaryKeyEqualCond = false;
|
||||
SNode* pCond = NULL;
|
||||
FOREACH(pCond, pOnCond->pParameterList) {
|
||||
if (cpdIsPrimaryKeyEqualCond(pJoin, pCond)) {
|
||||
hasPrimaryKeyEqualCond = true;
|
||||
}
|
||||
}
|
||||
if (!hasPrimaryKeyEqualCond) {
|
||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
// static int32_t cpdCheckOpCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode* pOnCond) {
|
||||
// if (!cpdIsPrimaryKeyEqualCond(pJoin, pOnCond)) {
|
||||
// return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
// }
|
||||
// return TSDB_CODE_SUCCESS;
|
||||
// }
|
||||
|
||||
// static int32_t cpdCheckLogicCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SLogicConditionNode* pOnCond) {
|
||||
// if (LOGIC_COND_TYPE_AND != pOnCond->condType) {
|
||||
// return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
// }
|
||||
// bool hasPrimaryKeyEqualCond = false;
|
||||
// SNode* pCond = NULL;
|
||||
// FOREACH(pCond, pOnCond->pParameterList) {
|
||||
// if (cpdIsPrimaryKeyEqualCond(pJoin, pCond)) {
|
||||
// hasPrimaryKeyEqualCond = true;
|
||||
// }
|
||||
// }
|
||||
// if (!hasPrimaryKeyEqualCond) {
|
||||
// return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
// }
|
||||
// return TSDB_CODE_SUCCESS;
|
||||
// }
|
||||
|
||||
static int32_t cpdCheckJoinOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
|
||||
if (NULL == pJoin->pOnConditions) {
|
||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN);
|
||||
}
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pOnConditions)) {
|
||||
return cpdCheckLogicCond(pCxt, pJoin, (SLogicConditionNode*)pJoin->pOnConditions);
|
||||
} else {
|
||||
return cpdCheckOpCond(pCxt, pJoin, pJoin->pOnConditions);
|
||||
if (!cpdContainPrimaryKeyEqualCond(pJoin, pJoin->pOnConditions)) {
|
||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
// if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pOnConditions)) {
|
||||
// return cpdCheckLogicCond(pCxt, pJoin, (SLogicConditionNode*)pJoin->pOnConditions);
|
||||
// } else {
|
||||
// return cpdCheckOpCond(pCxt, pJoin, pJoin->pOnConditions);
|
||||
// }
|
||||
}
|
||||
|
||||
static int32_t cpdPushJoinCondition(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
|
||||
|
|
|
@ -204,6 +204,75 @@ static int32_t ctjSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static bool unionIsChildSubplan(SLogicNode* pLogicNode, int32_t groupId) {
|
||||
if (QUERY_NODE_LOGIC_PLAN_EXCHANGE == nodeType(pLogicNode)) {
|
||||
return ((SExchangeLogicNode*)pLogicNode)->srcGroupId == groupId;
|
||||
}
|
||||
|
||||
SNode* pChild;
|
||||
FOREACH(pChild, pLogicNode->pChildren) {
|
||||
bool isChild = unionIsChildSubplan((SLogicNode*)pChild, groupId);
|
||||
if (isChild) {
|
||||
return isChild;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int32_t unionMountSubplan(SLogicSubplan* pParent, SNodeList* pChildren) {
|
||||
SNode* pChild = NULL;
|
||||
WHERE_EACH(pChild, pChildren) {
|
||||
if (unionIsChildSubplan(pParent->pNode, ((SLogicSubplan*)pChild)->id.groupId)) {
|
||||
int32_t code = nodesListMakeAppend(&pParent->pChildren, pChild);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
REPLACE_NODE(NULL);
|
||||
ERASE_NODE(pChildren);
|
||||
continue;
|
||||
} else {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
WHERE_NEXT;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static SLogicSubplan* unionCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode) {
|
||||
SLogicSubplan* pSubplan = nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN);
|
||||
if (NULL == pSubplan) {
|
||||
return NULL;
|
||||
}
|
||||
pSubplan->id.groupId = pCxt->groupId;
|
||||
pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
|
||||
pSubplan->pNode = pNode;
|
||||
return pSubplan;
|
||||
}
|
||||
|
||||
static int32_t unionSplitSubplan(SSplitContext* pCxt, SLogicSubplan* pUnionSubplan, SLogicNode* pSplitNode) {
|
||||
SNodeList* pSubplanChildren = pUnionSubplan->pChildren;
|
||||
pUnionSubplan->pChildren = NULL;
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
SNode* pChild = NULL;
|
||||
FOREACH(pChild, pSplitNode->pChildren) {
|
||||
SLogicSubplan* pNewSubplan = unionCreateSubplan(pCxt, (SLogicNode*)pChild);
|
||||
code = nodesListMakeStrictAppend(&pUnionSubplan->pChildren, pNewSubplan);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
REPLACE_NODE(NULL);
|
||||
code = unionMountSubplan(pNewSubplan, pSubplanChildren);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
nodesDestroyList(pSubplanChildren);
|
||||
DESTORY_LIST(pSplitNode->pChildren);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static SLogicNode* uaMatchByNode(SLogicNode* pNode) {
|
||||
if (QUERY_NODE_LOGIC_PLAN_PROJECT == nodeType(pNode) && LIST_LENGTH(pNode->pChildren) > 1) {
|
||||
return pNode;
|
||||
|
@ -227,17 +296,6 @@ static bool uaFindSplitNode(SLogicSubplan* pSubplan, SUaInfo* pInfo) {
|
|||
return NULL != pSplitNode;
|
||||
}
|
||||
|
||||
static SLogicSubplan* uaCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode) {
|
||||
SLogicSubplan* pSubplan = nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN);
|
||||
if (NULL == pSubplan) {
|
||||
return NULL;
|
||||
}
|
||||
pSubplan->id.groupId = pCxt->groupId;
|
||||
pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
|
||||
pSubplan->pNode = pNode;
|
||||
return pSubplan;
|
||||
}
|
||||
|
||||
static int32_t uaCreateExchangeNode(SSplitContext* pCxt, SLogicSubplan* pSubplan, SProjectLogicNode* pProject) {
|
||||
SExchangeLogicNode* pExchange = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_EXCHANGE);
|
||||
if (NULL == pExchange) {
|
||||
|
@ -276,20 +334,8 @@ static int32_t uaSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
SNode* pChild = NULL;
|
||||
FOREACH(pChild, info.pProject->node.pChildren) {
|
||||
code = nodesListMakeStrictAppend(&info.pSubplan->pChildren, uaCreateSubplan(pCxt, (SLogicNode*)pChild));
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
REPLACE_NODE(NULL);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int32_t code = unionSplitSubplan(pCxt, info.pSubplan, (SLogicNode*)info.pProject);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
nodesClearList(info.pProject->node.pChildren);
|
||||
info.pProject->node.pChildren = NULL;
|
||||
code = uaCreateExchangeNode(pCxt, info.pSubplan, info.pProject);
|
||||
}
|
||||
++(pCxt->groupId);
|
||||
|
@ -343,20 +389,8 @@ static int32_t unSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
SNode* pChild = NULL;
|
||||
FOREACH(pChild, info.pAgg->node.pChildren) {
|
||||
code = nodesListMakeStrictAppend(&info.pSubplan->pChildren, uaCreateSubplan(pCxt, (SLogicNode*)pChild));
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
REPLACE_NODE(NULL);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int32_t code = unionSplitSubplan(pCxt, info.pSubplan, (SLogicNode*)info.pAgg);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
nodesClearList(info.pAgg->node.pChildren);
|
||||
info.pAgg->node.pChildren = NULL;
|
||||
code = unCreateExchangeNode(pCxt, info.pSubplan, info.pAgg);
|
||||
}
|
||||
++(pCxt->groupId);
|
||||
|
|
|
@ -30,6 +30,14 @@ TEST_F(PlanJoinTest, basic) {
|
|||
run("SELECT t1.c1, t2.c1 FROM st1s1 t1 JOIN st1s2 t2 ON t1.ts = t2.ts");
|
||||
}
|
||||
|
||||
TEST_F(PlanJoinTest, complex) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT t1.c1, t2.c2 FROM st1s1 t1, st1s2 t2 "
|
||||
"WHERE t1.ts = t2.ts AND t1.c1 BETWEEN -10 AND 10 AND t2.c1 BETWEEN -100 AND 100 AND "
|
||||
"(t1.c2 LIKE 'nchar%' OR t1.c1 = 0 OR t2.c2 LIKE 'nchar%' OR t2.c1 = 0)");
|
||||
}
|
||||
|
||||
TEST_F(PlanJoinTest, withWhere) {
|
||||
useDb("root", "test");
|
||||
|
||||
|
|
|
@ -23,11 +23,33 @@ class PlanSetOpTest : public PlannerTestBase {};
|
|||
TEST_F(PlanSetOpTest, unionAll) {
|
||||
useDb("root", "test");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, unionAllSubquery) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT * FROM (SELECT c1, c2 FROM t1 UNION ALL SELECT c1, c2 FROM t1)");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, union) {
|
||||
useDb("root", "test");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, unionContainJoin) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT t1.c1 FROM st1s1 t1 join st1s2 t2 on t1.ts = t2.ts "
|
||||
"WHERE t1.c1 IS NOT NULL GROUP BY t1.c1 HAVING t1.c1 IS NOT NULL "
|
||||
"UNION "
|
||||
"SELECT t1.c1 FROM st1s1 t1 join st1s2 t2 on t1.ts = t2.ts "
|
||||
"WHERE t1.c1 IS NOT NULL GROUP BY t1.c1 HAVING t1.c1 IS NOT NULL");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, unionSubquery) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT * FROM (SELECT c1, c2 FROM t1 UNION SELECT c1, c2 FROM t1)");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue