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;
|
SNode* pRight;
|
||||||
SNodeList* pOrderByList; // SOrderByExprNode
|
SNodeList* pOrderByList; // SOrderByExprNode
|
||||||
SNode* pLimit;
|
SNode* pLimit;
|
||||||
|
char stmtName[TSDB_TABLE_NAME_LEN];
|
||||||
} SSetOperator;
|
} SSetOperator;
|
||||||
|
|
||||||
typedef enum ESqlClause {
|
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_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_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_MODIFY_COL TAOS_DEF_ERROR_CODE(0, 0x264B)
|
||||||
|
#define TSDB_CODE_PAR_INVALID_TBNAME TAOS_DEF_ERROR_CODE(0, 0x264C)
|
||||||
|
|
||||||
//planner
|
//planner
|
||||||
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
|
#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) ::= 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) ::= 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) ::= 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) ::= QENDTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||||
pseudo_column(A) ::= WSTARTTS(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;
|
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 (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);
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DB_NOT_SPECIFIED);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -457,6 +457,8 @@ SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const STok
|
||||||
}
|
}
|
||||||
if (QUERY_NODE_SELECT_STMT == nodeType(pSubquery)) {
|
if (QUERY_NODE_SELECT_STMT == nodeType(pSubquery)) {
|
||||||
strcpy(((SSelectStmt*)pSubquery)->stmtName, tempTable->table.tableAlias);
|
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;
|
return (SNode*)tempTable;
|
||||||
}
|
}
|
||||||
|
@ -637,6 +639,7 @@ SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode*
|
||||||
setOp->opType = type;
|
setOp->opType = type;
|
||||||
setOp->pLeft = pLeft;
|
setOp->pLeft = pLeft;
|
||||||
setOp->pRight = pRight;
|
setOp->pRight = pRight;
|
||||||
|
sprintf(setOp->stmtName, "%p", setOp);
|
||||||
return (SNode*)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,
|
SNode* createCreateIndexStmt(SAstCreateContext* pCxt, EIndexType type, bool ignoreExists, SToken* pIndexName,
|
||||||
SToken* pTableName, SNodeList* pCols, SNode* pOptions) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
SCreateIndexStmt* pStmt = nodesMakeNode(QUERY_NODE_CREATE_INDEX_STMT);
|
SCreateIndexStmt* pStmt = nodesMakeNode(QUERY_NODE_CREATE_INDEX_STMT);
|
||||||
|
|
|
@ -766,6 +766,20 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
|
||||||
pCxt->pCurrStmt->hasRepeatScanFuncs = true;
|
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;
|
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;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SNode* createSetOperProject(SNode* pNode) {
|
static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
|
||||||
SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN);
|
SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN);
|
||||||
if (NULL == pCol) {
|
if (NULL == pCol) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
pCol->node.resType = ((SExprNode*)pNode)->resType;
|
pCol->node.resType = ((SExprNode*)pNode)->resType;
|
||||||
|
strcpy(pCol->tableAlias, pTableAlias);
|
||||||
strcpy(pCol->colName, ((SExprNode*)pNode)->aliasName);
|
strcpy(pCol->colName, ((SExprNode*)pNode)->aliasName);
|
||||||
strcpy(pCol->node.aliasName, pCol->colName);
|
strcpy(pCol->node.aliasName, pCol->colName);
|
||||||
return (SNode*)pCol;
|
return (SNode*)pCol;
|
||||||
|
@ -1817,7 +1832,8 @@ static int32_t translateSetOperatorImpl(STranslateContext* pCxt, SSetOperator* p
|
||||||
}
|
}
|
||||||
strcpy(pRightExpr->aliasName, pLeftExpr->aliasName);
|
strcpy(pRightExpr->aliasName, pLeftExpr->aliasName);
|
||||||
pRightExpr->aliasName[strlen(pLeftExpr->aliasName)] = '\0';
|
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;
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,8 @@ static char* getSyntaxErrFormat(int32_t errCode) {
|
||||||
return "Primary timestamp column cannot be dropped";
|
return "Primary timestamp column cannot be dropped";
|
||||||
case TSDB_CODE_PAR_INVALID_MODIFY_COL:
|
case TSDB_CODE_PAR_INVALID_MODIFY_COL:
|
||||||
return "Only binary/nchar column length could be modified";
|
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:
|
case TSDB_CODE_OUT_OF_MEMORY:
|
||||||
return "Out of memory";
|
return "Out of memory";
|
||||||
default:
|
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)");
|
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) {
|
TEST_F(ParserSelectTest, multiResFunc) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,13 @@ extern "C" {
|
||||||
#define QUERY_POLICY_HYBRID 2
|
#define QUERY_POLICY_HYBRID 2
|
||||||
#define QUERY_POLICY_QNODE 3
|
#define QUERY_POLICY_QNODE 3
|
||||||
|
|
||||||
#define planFatal(param, ...) qFatal("PLAN: " param, __VA_ARGS__)
|
#define planFatal(param, ...) qFatal("PLAN: " param, __VA_ARGS__)
|
||||||
#define planError(param, ...) qError("PLAN: " param, __VA_ARGS__)
|
#define planError(param, ...) qError("PLAN: " param, __VA_ARGS__)
|
||||||
#define planWarn(param, ...) qWarn("PLAN: " param, __VA_ARGS__)
|
#define planWarn(param, ...) qWarn("PLAN: " param, __VA_ARGS__)
|
||||||
#define planInfo(param, ...) qInfo("PLAN: " param, __VA_ARGS__)
|
#define planInfo(param, ...) qInfo("PLAN: " param, __VA_ARGS__)
|
||||||
#define planDebug(param, ...) qDebug("PLAN: " param, __VA_ARGS__)
|
#define planDebug(param, ...) qDebug("PLAN: " param, __VA_ARGS__)
|
||||||
#define planTrace(param, ...) qTrace("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, ...);
|
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,
|
static int32_t createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable,
|
||||||
SLogicNode** pLogicNode) {
|
SLogicNode** pLogicNode) {
|
||||||
int32_t code = createQueryLogicNode(pCxt, pTable->pSubquery, pLogicNode);
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable,
|
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) {
|
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) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
@ -933,7 +929,7 @@ static int32_t createSetOpLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetO
|
||||||
code = createSetOpAggLogicNode(pCxt, pSetOperator, &pSetOp);
|
code = createSetOpAggLogicNode(pCxt, pSetOperator, &pSetOp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
code = -1;
|
code = TSDB_CODE_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -598,39 +598,63 @@ static bool cpdIsPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t cpdCheckOpCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode* pOnCond) {
|
static bool cpdContainPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
|
||||||
if (!cpdIsPrimaryKeyEqualCond(pJoin, pOnCond)) {
|
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pCond)) {
|
||||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
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) {
|
// static int32_t cpdCheckOpCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode* pOnCond) {
|
||||||
if (LOGIC_COND_TYPE_AND != pOnCond->condType) {
|
// if (!cpdIsPrimaryKeyEqualCond(pJoin, pOnCond)) {
|
||||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
// return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||||
}
|
// }
|
||||||
bool hasPrimaryKeyEqualCond = false;
|
// return TSDB_CODE_SUCCESS;
|
||||||
SNode* pCond = NULL;
|
// }
|
||||||
FOREACH(pCond, pOnCond->pParameterList) {
|
|
||||||
if (cpdIsPrimaryKeyEqualCond(pJoin, pCond)) {
|
// static int32_t cpdCheckLogicCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SLogicConditionNode* pOnCond) {
|
||||||
hasPrimaryKeyEqualCond = true;
|
// if (LOGIC_COND_TYPE_AND != pOnCond->condType) {
|
||||||
}
|
// return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||||
}
|
// }
|
||||||
if (!hasPrimaryKeyEqualCond) {
|
// bool hasPrimaryKeyEqualCond = false;
|
||||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
// SNode* pCond = NULL;
|
||||||
}
|
// FOREACH(pCond, pOnCond->pParameterList) {
|
||||||
return TSDB_CODE_SUCCESS;
|
// 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) {
|
static int32_t cpdCheckJoinOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
|
||||||
if (NULL == pJoin->pOnConditions) {
|
if (NULL == pJoin->pOnConditions) {
|
||||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN);
|
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN);
|
||||||
}
|
}
|
||||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pOnConditions)) {
|
if (!cpdContainPrimaryKeyEqualCond(pJoin, pJoin->pOnConditions)) {
|
||||||
return cpdCheckLogicCond(pCxt, pJoin, (SLogicConditionNode*)pJoin->pOnConditions);
|
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||||
} else {
|
|
||||||
return cpdCheckOpCond(pCxt, pJoin, pJoin->pOnConditions);
|
|
||||||
}
|
}
|
||||||
|
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) {
|
static int32_t cpdPushJoinCondition(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
|
||||||
|
|
|
@ -204,6 +204,75 @@ static int32_t ctjSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
|
||||||
return code;
|
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) {
|
static SLogicNode* uaMatchByNode(SLogicNode* pNode) {
|
||||||
if (QUERY_NODE_LOGIC_PLAN_PROJECT == nodeType(pNode) && LIST_LENGTH(pNode->pChildren) > 1) {
|
if (QUERY_NODE_LOGIC_PLAN_PROJECT == nodeType(pNode) && LIST_LENGTH(pNode->pChildren) > 1) {
|
||||||
return pNode;
|
return pNode;
|
||||||
|
@ -227,17 +296,6 @@ static bool uaFindSplitNode(SLogicSubplan* pSubplan, SUaInfo* pInfo) {
|
||||||
return NULL != pSplitNode;
|
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) {
|
static int32_t uaCreateExchangeNode(SSplitContext* pCxt, SLogicSubplan* pSubplan, SProjectLogicNode* pProject) {
|
||||||
SExchangeLogicNode* pExchange = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_EXCHANGE);
|
SExchangeLogicNode* pExchange = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_EXCHANGE);
|
||||||
if (NULL == pExchange) {
|
if (NULL == pExchange) {
|
||||||
|
@ -276,20 +334,8 @@ static int32_t uaSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = unionSplitSubplan(pCxt, info.pSubplan, (SLogicNode*)info.pProject);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
nodesClearList(info.pProject->node.pChildren);
|
|
||||||
info.pProject->node.pChildren = NULL;
|
|
||||||
code = uaCreateExchangeNode(pCxt, info.pSubplan, info.pProject);
|
code = uaCreateExchangeNode(pCxt, info.pSubplan, info.pProject);
|
||||||
}
|
}
|
||||||
++(pCxt->groupId);
|
++(pCxt->groupId);
|
||||||
|
@ -343,20 +389,8 @@ static int32_t unSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = unionSplitSubplan(pCxt, info.pSubplan, (SLogicNode*)info.pAgg);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
nodesClearList(info.pAgg->node.pChildren);
|
|
||||||
info.pAgg->node.pChildren = NULL;
|
|
||||||
code = unCreateExchangeNode(pCxt, info.pSubplan, info.pAgg);
|
code = unCreateExchangeNode(pCxt, info.pSubplan, info.pAgg);
|
||||||
}
|
}
|
||||||
++(pCxt->groupId);
|
++(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");
|
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) {
|
TEST_F(PlanJoinTest, withWhere) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,33 @@ class PlanSetOpTest : public PlannerTestBase {};
|
||||||
TEST_F(PlanSetOpTest, unionAll) {
|
TEST_F(PlanSetOpTest, unionAll) {
|
||||||
useDb("root", "test");
|
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) {
|
TEST_F(PlanSetOpTest, union) {
|
||||||
useDb("root", "test");
|
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