TD-14396 explain parser and planner implement
This commit is contained in:
parent
c439f2fb37
commit
03771c84f5
|
@ -138,55 +138,59 @@
|
||||||
#define TK_INTERVAL 120
|
#define TK_INTERVAL 120
|
||||||
#define TK_TOPIC 121
|
#define TK_TOPIC 121
|
||||||
#define TK_AS 122
|
#define TK_AS 122
|
||||||
#define TK_NK_BOOL 123
|
#define TK_EXPLAIN 123
|
||||||
#define TK_NULL 124
|
#define TK_ANALYZE 124
|
||||||
#define TK_NK_VARIABLE 125
|
#define TK_VERBOSE 125
|
||||||
#define TK_NK_UNDERLINE 126
|
#define TK_NK_BOOL 126
|
||||||
#define TK_ROWTS 127
|
#define TK_RATIO 127
|
||||||
#define TK_TBNAME 128
|
#define TK_NULL 128
|
||||||
#define TK_QSTARTTS 129
|
#define TK_NK_VARIABLE 129
|
||||||
#define TK_QENDTS 130
|
#define TK_NK_UNDERLINE 130
|
||||||
#define TK_WSTARTTS 131
|
#define TK_ROWTS 131
|
||||||
#define TK_WENDTS 132
|
#define TK_TBNAME 132
|
||||||
#define TK_WDURATION 133
|
#define TK_QSTARTTS 133
|
||||||
#define TK_BETWEEN 134
|
#define TK_QENDTS 134
|
||||||
#define TK_IS 135
|
#define TK_WSTARTTS 135
|
||||||
#define TK_NK_LT 136
|
#define TK_WENDTS 136
|
||||||
#define TK_NK_GT 137
|
#define TK_WDURATION 137
|
||||||
#define TK_NK_LE 138
|
#define TK_BETWEEN 138
|
||||||
#define TK_NK_GE 139
|
#define TK_IS 139
|
||||||
#define TK_NK_NE 140
|
#define TK_NK_LT 140
|
||||||
#define TK_MATCH 141
|
#define TK_NK_GT 141
|
||||||
#define TK_NMATCH 142
|
#define TK_NK_LE 142
|
||||||
#define TK_IN 143
|
#define TK_NK_GE 143
|
||||||
#define TK_JOIN 144
|
#define TK_NK_NE 144
|
||||||
#define TK_INNER 145
|
#define TK_MATCH 145
|
||||||
#define TK_SELECT 146
|
#define TK_NMATCH 146
|
||||||
#define TK_DISTINCT 147
|
#define TK_IN 147
|
||||||
#define TK_WHERE 148
|
#define TK_JOIN 148
|
||||||
#define TK_PARTITION 149
|
#define TK_INNER 149
|
||||||
#define TK_BY 150
|
#define TK_SELECT 150
|
||||||
#define TK_SESSION 151
|
#define TK_DISTINCT 151
|
||||||
#define TK_STATE_WINDOW 152
|
#define TK_WHERE 152
|
||||||
#define TK_SLIDING 153
|
#define TK_PARTITION 153
|
||||||
#define TK_FILL 154
|
#define TK_BY 154
|
||||||
#define TK_VALUE 155
|
#define TK_SESSION 155
|
||||||
#define TK_NONE 156
|
#define TK_STATE_WINDOW 156
|
||||||
#define TK_PREV 157
|
#define TK_SLIDING 157
|
||||||
#define TK_LINEAR 158
|
#define TK_FILL 158
|
||||||
#define TK_NEXT 159
|
#define TK_VALUE 159
|
||||||
#define TK_GROUP 160
|
#define TK_NONE 160
|
||||||
#define TK_HAVING 161
|
#define TK_PREV 161
|
||||||
#define TK_ORDER 162
|
#define TK_LINEAR 162
|
||||||
#define TK_SLIMIT 163
|
#define TK_NEXT 163
|
||||||
#define TK_SOFFSET 164
|
#define TK_GROUP 164
|
||||||
#define TK_LIMIT 165
|
#define TK_HAVING 165
|
||||||
#define TK_OFFSET 166
|
#define TK_ORDER 166
|
||||||
#define TK_ASC 167
|
#define TK_SLIMIT 167
|
||||||
#define TK_DESC 168
|
#define TK_SOFFSET 168
|
||||||
#define TK_NULLS 169
|
#define TK_LIMIT 169
|
||||||
#define TK_FIRST 170
|
#define TK_OFFSET 170
|
||||||
#define TK_LAST 171
|
#define TK_ASC 171
|
||||||
|
#define TK_DESC 172
|
||||||
|
#define TK_NULLS 173
|
||||||
|
#define TK_FIRST 174
|
||||||
|
#define TK_LAST 175
|
||||||
|
|
||||||
#define TK_NK_SPACE 300
|
#define TK_NK_SPACE 300
|
||||||
#define TK_NK_COMMENT 301
|
#define TK_NK_COMMENT 301
|
||||||
|
|
|
@ -70,6 +70,7 @@ typedef enum ENodeType {
|
||||||
QUERY_NODE_DATABASE_OPTIONS,
|
QUERY_NODE_DATABASE_OPTIONS,
|
||||||
QUERY_NODE_TABLE_OPTIONS,
|
QUERY_NODE_TABLE_OPTIONS,
|
||||||
QUERY_NODE_INDEX_OPTIONS,
|
QUERY_NODE_INDEX_OPTIONS,
|
||||||
|
QUERY_NODE_EXPLAIN_OPTIONS,
|
||||||
|
|
||||||
// Statement nodes are used in parser and planner module.
|
// Statement nodes are used in parser and planner module.
|
||||||
QUERY_NODE_SET_OPERATOR,
|
QUERY_NODE_SET_OPERATOR,
|
||||||
|
@ -99,6 +100,7 @@ typedef enum ENodeType {
|
||||||
QUERY_NODE_CREATE_TOPIC_STMT,
|
QUERY_NODE_CREATE_TOPIC_STMT,
|
||||||
QUERY_NODE_DROP_TOPIC_STMT,
|
QUERY_NODE_DROP_TOPIC_STMT,
|
||||||
QUERY_NODE_ALTER_LOCAL_STMT,
|
QUERY_NODE_ALTER_LOCAL_STMT,
|
||||||
|
QUERY_NODE_EXPLAIN_STMT,
|
||||||
QUERY_NODE_SHOW_DATABASES_STMT,
|
QUERY_NODE_SHOW_DATABASES_STMT,
|
||||||
QUERY_NODE_SHOW_TABLES_STMT,
|
QUERY_NODE_SHOW_TABLES_STMT,
|
||||||
QUERY_NODE_SHOW_STABLES_STMT,
|
QUERY_NODE_SHOW_STABLES_STMT,
|
||||||
|
|
|
@ -49,6 +49,7 @@ typedef struct SScanLogicNode {
|
||||||
STimeWindow scanRange;
|
STimeWindow scanRange;
|
||||||
SName tableName;
|
SName tableName;
|
||||||
bool showRewrite;
|
bool showRewrite;
|
||||||
|
double ratio;
|
||||||
} SScanLogicNode;
|
} SScanLogicNode;
|
||||||
|
|
||||||
typedef struct SJoinLogicNode {
|
typedef struct SJoinLogicNode {
|
||||||
|
@ -197,6 +198,7 @@ typedef struct STableScanPhysiNode {
|
||||||
SScanPhysiNode scan;
|
SScanPhysiNode scan;
|
||||||
uint8_t scanFlag; // denotes reversed scan of data or not
|
uint8_t scanFlag; // denotes reversed scan of data or not
|
||||||
STimeWindow scanRange;
|
STimeWindow scanRange;
|
||||||
|
double ratio;
|
||||||
} STableScanPhysiNode;
|
} STableScanPhysiNode;
|
||||||
|
|
||||||
typedef STableScanPhysiNode STableSeqScanPhysiNode;
|
typedef STableScanPhysiNode STableSeqScanPhysiNode;
|
||||||
|
@ -297,18 +299,23 @@ typedef struct SSubplan {
|
||||||
SDataSinkNode* pDataSink; // data of the subplan flow into the datasink
|
SDataSinkNode* pDataSink; // data of the subplan flow into the datasink
|
||||||
} SSubplan;
|
} SSubplan;
|
||||||
|
|
||||||
typedef enum EQueryMode {
|
typedef enum EExplainMode {
|
||||||
QUERY_MODE_NORMAL = 1,
|
EXPLAIN_MODE_DISABLE = 1,
|
||||||
QUERY_MODE_EXPLAIN,
|
EXPLAIN_MODE_STATIC,
|
||||||
QUERY_MODE_EXPLAIN_AN
|
EXPLAIN_MODE_ANALYZE
|
||||||
} EQueryMode;
|
} EExplainMode;
|
||||||
|
|
||||||
|
typedef struct SExplainInfo {
|
||||||
|
EExplainMode mode;
|
||||||
|
bool verbose;
|
||||||
|
} SExplainInfo;
|
||||||
|
|
||||||
typedef struct SQueryPlan {
|
typedef struct SQueryPlan {
|
||||||
ENodeType type;
|
ENodeType type;
|
||||||
uint64_t queryId;
|
uint64_t queryId;
|
||||||
int32_t numOfSubplans;
|
int32_t numOfSubplans;
|
||||||
|
|
||||||
SNodeList* pSubplans; // Element is SNodeListNode. The execution level of subplan, starting from 0.
|
SNodeList* pSubplans; // Element is SNodeListNode. The execution level of subplan, starting from 0.
|
||||||
|
SExplainInfo explainInfo;
|
||||||
} SQueryPlan;
|
} SQueryPlan;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -131,6 +131,7 @@ typedef struct SRealTableNode {
|
||||||
struct STableMeta* pMeta;
|
struct STableMeta* pMeta;
|
||||||
SVgroupsInfo* pVgroupList;
|
SVgroupsInfo* pVgroupList;
|
||||||
char useDbName[TSDB_DB_NAME_LEN];
|
char useDbName[TSDB_DB_NAME_LEN];
|
||||||
|
double ratio;
|
||||||
} SRealTableNode;
|
} SRealTableNode;
|
||||||
|
|
||||||
typedef struct STempTableNode {
|
typedef struct STempTableNode {
|
||||||
|
@ -282,6 +283,19 @@ typedef struct SVnodeModifOpStmt {
|
||||||
const char* sql; // current sql statement position
|
const char* sql; // current sql statement position
|
||||||
} SVnodeModifOpStmt;
|
} SVnodeModifOpStmt;
|
||||||
|
|
||||||
|
typedef struct SExplainOptions {
|
||||||
|
ENodeType type;
|
||||||
|
bool verbose;
|
||||||
|
double ratio;
|
||||||
|
} SExplainOptions;
|
||||||
|
|
||||||
|
typedef struct SExplainStmt {
|
||||||
|
ENodeType type;
|
||||||
|
bool analyze;
|
||||||
|
SExplainOptions* pOptions;
|
||||||
|
SNode* pQuery;
|
||||||
|
} SExplainStmt;
|
||||||
|
|
||||||
void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext);
|
void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext);
|
||||||
void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext);
|
void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext);
|
||||||
|
|
||||||
|
|
|
@ -381,6 +381,14 @@ typedef enum ELogicConditionType {
|
||||||
#define TSDB_MAX_DB_DELAY 10
|
#define TSDB_MAX_DB_DELAY 10
|
||||||
#define TSDB_DEFAULT_DB_DELAY 2
|
#define TSDB_DEFAULT_DB_DELAY 2
|
||||||
|
|
||||||
|
#define TSDB_DEFAULT_EXPLAIN_VERBOSE false
|
||||||
|
|
||||||
|
#define TSDB_MIN_EXPLAIN_RATIO 0
|
||||||
|
#define TSDB_MAX_EXPLAIN_RATIO 1
|
||||||
|
#define TSDB_DEFAULT_EXPLAIN_RATIO 0.001
|
||||||
|
|
||||||
|
#define TSDB_EXPLAIN_RESULT_ROW_SIZE 1024
|
||||||
|
|
||||||
#define TSDB_MAX_JOIN_TABLE_NUM 10
|
#define TSDB_MAX_JOIN_TABLE_NUM 10
|
||||||
#define TSDB_MAX_UNION_CLAUSE 5
|
#define TSDB_MAX_UNION_CLAUSE 5
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@ SNodeptr nodesMakeNode(ENodeType type) {
|
||||||
return makeNode(type, sizeof(STableOptions));
|
return makeNode(type, sizeof(STableOptions));
|
||||||
case QUERY_NODE_INDEX_OPTIONS:
|
case QUERY_NODE_INDEX_OPTIONS:
|
||||||
return makeNode(type, sizeof(SIndexOptions));
|
return makeNode(type, sizeof(SIndexOptions));
|
||||||
|
case QUERY_NODE_EXPLAIN_OPTIONS:
|
||||||
|
return makeNode(type, sizeof(SExplainOptions));
|
||||||
case QUERY_NODE_SET_OPERATOR:
|
case QUERY_NODE_SET_OPERATOR:
|
||||||
return makeNode(type, sizeof(SSetOperator));
|
return makeNode(type, sizeof(SSetOperator));
|
||||||
case QUERY_NODE_SELECT_STMT:
|
case QUERY_NODE_SELECT_STMT:
|
||||||
|
@ -132,6 +134,8 @@ SNodeptr nodesMakeNode(ENodeType type) {
|
||||||
return makeNode(type, sizeof(SCreateTopicStmt));
|
return makeNode(type, sizeof(SCreateTopicStmt));
|
||||||
case QUERY_NODE_DROP_TOPIC_STMT:
|
case QUERY_NODE_DROP_TOPIC_STMT:
|
||||||
return makeNode(type, sizeof(SDropTopicStmt));
|
return makeNode(type, sizeof(SDropTopicStmt));
|
||||||
|
case QUERY_NODE_EXPLAIN_STMT:
|
||||||
|
return makeNode(type, sizeof(SExplainStmt));
|
||||||
case QUERY_NODE_SHOW_DATABASES_STMT:
|
case QUERY_NODE_SHOW_DATABASES_STMT:
|
||||||
case QUERY_NODE_SHOW_TABLES_STMT:
|
case QUERY_NODE_SHOW_TABLES_STMT:
|
||||||
case QUERY_NODE_SHOW_STABLES_STMT:
|
case QUERY_NODE_SHOW_STABLES_STMT:
|
||||||
|
|
|
@ -159,6 +159,10 @@ SNode* createDropQnodeStmt(SAstCreateContext* pCxt, const SToken* pDnodeId);
|
||||||
SNode* createCreateTopicStmt(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName, SNode* pQuery, const SToken* pSubscribeDbName);
|
SNode* createCreateTopicStmt(SAstCreateContext* pCxt, bool ignoreExists, const SToken* pTopicName, SNode* pQuery, const SToken* pSubscribeDbName);
|
||||||
SNode* createDropTopicStmt(SAstCreateContext* pCxt, bool ignoreNotExists, const SToken* pTopicName);
|
SNode* createDropTopicStmt(SAstCreateContext* pCxt, bool ignoreNotExists, const SToken* pTopicName);
|
||||||
SNode* createAlterLocalStmt(SAstCreateContext* pCxt, const SToken* pConfig, const SToken* pValue);
|
SNode* createAlterLocalStmt(SAstCreateContext* pCxt, const SToken* pConfig, const SToken* pValue);
|
||||||
|
SNode* createDefaultExplainOptions(SAstCreateContext* pCxt);
|
||||||
|
SNode* setExplainVerbose(SAstCreateContext* pCxt, SNode* pOptions, const SToken* pVal);
|
||||||
|
SNode* setExplainRatio(SAstCreateContext* pCxt, SNode* pOptions, const SToken* pVal);
|
||||||
|
SNode* createExplainStmt(SAstCreateContext* pCxt, bool analyze, SNode* pOptions, SNode* pQuery);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -339,6 +339,18 @@ cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B) AS query_expression(C).
|
||||||
cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B) AS db_name(C). { pCxt->pRootNode = createCreateTopicStmt(pCxt, A, &B, NULL, &C); }
|
cmd ::= CREATE TOPIC not_exists_opt(A) topic_name(B) AS db_name(C). { pCxt->pRootNode = createCreateTopicStmt(pCxt, A, &B, NULL, &C); }
|
||||||
cmd ::= DROP TOPIC exists_opt(A) topic_name(B). { pCxt->pRootNode = createDropTopicStmt(pCxt, A, &B); }
|
cmd ::= DROP TOPIC exists_opt(A) topic_name(B). { pCxt->pRootNode = createDropTopicStmt(pCxt, A, &B); }
|
||||||
|
|
||||||
|
/************************************************ select **************************************************************/
|
||||||
|
cmd ::= EXPLAIN analyze_opt(A) explain_options(B) query_expression(C). { pCxt->pRootNode = createExplainStmt(pCxt, A, B, C); }
|
||||||
|
|
||||||
|
%type analyze_opt { bool }
|
||||||
|
%destructor analyze_opt { }
|
||||||
|
analyze_opt(A) ::= . { A = false; }
|
||||||
|
analyze_opt(A) ::= ANALYZE. { A = true; }
|
||||||
|
|
||||||
|
explain_options(A) ::= . { A = createDefaultExplainOptions(pCxt); }
|
||||||
|
explain_options(A) ::= explain_options(B) VERBOSE NK_BOOL(C). { A = setExplainVerbose(pCxt, B, &C); }
|
||||||
|
explain_options(A) ::= explain_options(B) RATIO NK_FLOAT(C). { A = setExplainRatio(pCxt, B, &C); }
|
||||||
|
|
||||||
/************************************************ select **************************************************************/
|
/************************************************ select **************************************************************/
|
||||||
cmd ::= query_expression(A). { pCxt->pRootNode = A; }
|
cmd ::= query_expression(A). { pCxt->pRootNode = A; }
|
||||||
|
|
||||||
|
|
|
@ -1316,3 +1316,30 @@ SNode* createAlterLocalStmt(SAstCreateContext* pCxt, const SToken* pConfig, cons
|
||||||
}
|
}
|
||||||
return (SNode*)pStmt;
|
return (SNode*)pStmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SNode* createDefaultExplainOptions(SAstCreateContext* pCxt) {
|
||||||
|
SExplainOptions* pOptions = nodesMakeNode(QUERY_NODE_EXPLAIN_OPTIONS);
|
||||||
|
CHECK_OUT_OF_MEM(pOptions);
|
||||||
|
pOptions->verbose = TSDB_DEFAULT_EXPLAIN_VERBOSE;
|
||||||
|
pOptions->ratio = TSDB_DEFAULT_EXPLAIN_RATIO;
|
||||||
|
return (SNode*)pOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNode* setExplainVerbose(SAstCreateContext* pCxt, SNode* pOptions, const SToken* pVal) {
|
||||||
|
((SExplainOptions*)pOptions)->verbose = (0 == strncasecmp(pVal->z, "true", pVal->n));
|
||||||
|
return pOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNode* setExplainRatio(SAstCreateContext* pCxt, SNode* pOptions, const SToken* pVal) {
|
||||||
|
((SExplainOptions*)pOptions)->ratio = strtod(pVal->z, NULL);
|
||||||
|
return pOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNode* createExplainStmt(SAstCreateContext* pCxt, bool analyze, SNode* pOptions, SNode* pQuery) {
|
||||||
|
SExplainStmt* pStmt = nodesMakeNode(QUERY_NODE_EXPLAIN_STMT);
|
||||||
|
CHECK_OUT_OF_MEM(pStmt);
|
||||||
|
pStmt->analyze = analyze;
|
||||||
|
pStmt->pOptions = (SExplainOptions*)pOptions;
|
||||||
|
pStmt->pQuery = pQuery;
|
||||||
|
return (SNode*)pStmt;
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ static SKeyword keywordTable[] = {
|
||||||
{"ACCOUNT", TK_ACCOUNT},
|
{"ACCOUNT", TK_ACCOUNT},
|
||||||
{"ALL", TK_ALL},
|
{"ALL", TK_ALL},
|
||||||
{"ALTER", TK_ALTER},
|
{"ALTER", TK_ALTER},
|
||||||
|
{"ANALYZE", TK_ANALYZE},
|
||||||
{"AND", TK_AND},
|
{"AND", TK_AND},
|
||||||
{"AS", TK_AS},
|
{"AS", TK_AS},
|
||||||
{"ASC", TK_ASC},
|
{"ASC", TK_ASC},
|
||||||
|
@ -56,6 +57,7 @@ static SKeyword keywordTable[] = {
|
||||||
{"DOUBLE", TK_DOUBLE},
|
{"DOUBLE", TK_DOUBLE},
|
||||||
{"DROP", TK_DROP},
|
{"DROP", TK_DROP},
|
||||||
{"EXISTS", TK_EXISTS},
|
{"EXISTS", TK_EXISTS},
|
||||||
|
{"EXPLAIN", TK_EXPLAIN},
|
||||||
{"FILE_FACTOR", TK_FILE_FACTOR},
|
{"FILE_FACTOR", TK_FILE_FACTOR},
|
||||||
{"FILL", TK_FILL},
|
{"FILL", TK_FILL},
|
||||||
{"FLOAT", TK_FLOAT},
|
{"FLOAT", TK_FLOAT},
|
||||||
|
@ -110,6 +112,7 @@ static SKeyword keywordTable[] = {
|
||||||
{"QNODES", TK_QNODES},
|
{"QNODES", TK_QNODES},
|
||||||
{"QSTARTTS", TK_QSTARTTS},
|
{"QSTARTTS", TK_QSTARTTS},
|
||||||
{"QUORUM", TK_QUORUM},
|
{"QUORUM", TK_QUORUM},
|
||||||
|
{"RATIO", TK_RATIO},
|
||||||
{"REPLICA", TK_REPLICA},
|
{"REPLICA", TK_REPLICA},
|
||||||
{"RETENTIONS", TK_RETENTIONS},
|
{"RETENTIONS", TK_RETENTIONS},
|
||||||
{"ROLLUP", TK_ROLLUP},
|
{"ROLLUP", TK_ROLLUP},
|
||||||
|
@ -144,6 +147,7 @@ static SKeyword keywordTable[] = {
|
||||||
{"USING", TK_USING},
|
{"USING", TK_USING},
|
||||||
{"VALUES", TK_VALUES},
|
{"VALUES", TK_VALUES},
|
||||||
{"VARCHAR", TK_VARCHAR},
|
{"VARCHAR", TK_VARCHAR},
|
||||||
|
{"VERBOSE", TK_VERBOSE},
|
||||||
{"VGROUPS", TK_VGROUPS},
|
{"VGROUPS", TK_VGROUPS},
|
||||||
{"WAL", TK_WAL},
|
{"WAL", TK_WAL},
|
||||||
{"WDURATION", TK_WDURATION},
|
{"WDURATION", TK_WDURATION},
|
||||||
|
@ -224,7 +228,6 @@ static SKeyword keywordTable[] = {
|
||||||
// {"DETACH", TK_DETACH},
|
// {"DETACH", TK_DETACH},
|
||||||
// {"EACH", TK_EACH},
|
// {"EACH", TK_EACH},
|
||||||
// {"END", TK_END},
|
// {"END", TK_END},
|
||||||
// {"EXPLAIN", TK_EXPLAIN},
|
|
||||||
// {"FAIL", TK_FAIL},
|
// {"FAIL", TK_FAIL},
|
||||||
// {"FOR", TK_FOR},
|
// {"FOR", TK_FOR},
|
||||||
// {"IGNORE", TK_IGNORE},
|
// {"IGNORE", TK_IGNORE},
|
||||||
|
|
|
@ -32,6 +32,7 @@ typedef struct STranslateContext {
|
||||||
SCmdMsgInfo* pCmdMsg;
|
SCmdMsgInfo* pCmdMsg;
|
||||||
SHashObj* pDbs;
|
SHashObj* pDbs;
|
||||||
SHashObj* pTables;
|
SHashObj* pTables;
|
||||||
|
SExplainOptions* pExplainOpt;
|
||||||
} STranslateContext;
|
} STranslateContext;
|
||||||
|
|
||||||
typedef struct SFullDatabaseName {
|
typedef struct SFullDatabaseName {
|
||||||
|
@ -673,6 +674,7 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
|
||||||
switch (nodeType(pTable)) {
|
switch (nodeType(pTable)) {
|
||||||
case QUERY_NODE_REAL_TABLE: {
|
case QUERY_NODE_REAL_TABLE: {
|
||||||
SRealTableNode* pRealTable = (SRealTableNode*)pTable;
|
SRealTableNode* pRealTable = (SRealTableNode*)pTable;
|
||||||
|
pRealTable->ratio = (NULL != pCxt->pExplainOpt ? pCxt->pExplainOpt->ratio : 1.0);
|
||||||
SName name;
|
SName name;
|
||||||
code = getTableMetaImpl(pCxt,
|
code = getTableMetaImpl(pCxt,
|
||||||
toName(pCxt->pParseCxt->acctId, pRealTable->table.dbName, pRealTable->table.tableName, &name), &(pRealTable->pMeta));
|
toName(pCxt->pParseCxt->acctId, pRealTable->table.dbName, pRealTable->table.tableName, &name), &(pRealTable->pMeta));
|
||||||
|
@ -680,10 +682,9 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
|
||||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TABLE_NOT_EXIST, pRealTable->table.tableName);
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TABLE_NOT_EXIST, pRealTable->table.tableName);
|
||||||
}
|
}
|
||||||
code = setTableVgroupList(pCxt, &name, pRealTable);
|
code = setTableVgroupList(pCxt, &name, pRealTable);
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
return code;
|
code = addNamespace(pCxt, pRealTable);
|
||||||
}
|
}
|
||||||
code = addNamespace(pCxt, pRealTable);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QUERY_NODE_TEMP_TABLE: {
|
case QUERY_NODE_TEMP_TABLE: {
|
||||||
|
@ -1804,6 +1805,13 @@ static int32_t translateAlterLocal(STranslateContext* pCxt, SAlterLocalStmt* pSt
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t translateExplain(STranslateContext* pCxt, SExplainStmt* pStmt) {
|
||||||
|
if (pStmt->analyze) {
|
||||||
|
pCxt->pExplainOpt = pStmt->pOptions;
|
||||||
|
}
|
||||||
|
return translateQuery(pCxt, pStmt->pQuery);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
|
static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
switch (nodeType(pNode)) {
|
switch (nodeType(pNode)) {
|
||||||
|
@ -1885,6 +1893,9 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
|
||||||
case QUERY_NODE_ALTER_LOCAL_STMT:
|
case QUERY_NODE_ALTER_LOCAL_STMT:
|
||||||
code = translateAlterLocal(pCxt, (SAlterLocalStmt*)pNode);
|
code = translateAlterLocal(pCxt, (SAlterLocalStmt*)pNode);
|
||||||
break;
|
break;
|
||||||
|
case QUERY_NODE_EXPLAIN_STMT:
|
||||||
|
code = translateExplain(pCxt, (SExplainStmt*)pNode);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1903,7 +1914,11 @@ static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t qExtractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema) {
|
int32_t qExtractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema) {
|
||||||
if (NULL != pRoot && QUERY_NODE_SELECT_STMT == nodeType(pRoot)) {
|
if (NULL == pRoot) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_SELECT_STMT == nodeType(pRoot)) {
|
||||||
SSelectStmt* pSelect = (SSelectStmt*) pRoot;
|
SSelectStmt* pSelect = (SSelectStmt*) pRoot;
|
||||||
*numOfCols = LIST_LENGTH(pSelect->pProjectionList);
|
*numOfCols = LIST_LENGTH(pSelect->pProjectionList);
|
||||||
*pSchema = taosMemoryCalloc((*numOfCols), sizeof(SSchema));
|
*pSchema = taosMemoryCalloc((*numOfCols), sizeof(SSchema));
|
||||||
|
@ -1921,6 +1936,14 @@ int32_t qExtractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** p
|
||||||
strcpy((*pSchema)[index].name, pExpr->aliasName);
|
strcpy((*pSchema)[index].name, pExpr->aliasName);
|
||||||
index +=1;
|
index +=1;
|
||||||
}
|
}
|
||||||
|
} else if (QUERY_NODE_EXPLAIN_STMT == nodeType(pRoot)) {
|
||||||
|
*numOfCols = 1;
|
||||||
|
*pSchema = taosMemoryCalloc((*numOfCols), sizeof(SSchema));
|
||||||
|
if (NULL == (*pSchema)) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
(*pSchema)[0].type = TSDB_DATA_TYPE_BINARY;
|
||||||
|
(*pSchema)[0].bytes = TSDB_EXPLAIN_RESULT_ROW_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -2505,6 +2528,7 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
|
||||||
static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) {
|
static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) {
|
||||||
switch (nodeType(pQuery->pRoot)) {
|
switch (nodeType(pQuery->pRoot)) {
|
||||||
case QUERY_NODE_SELECT_STMT:
|
case QUERY_NODE_SELECT_STMT:
|
||||||
|
case QUERY_NODE_EXPLAIN_STMT:
|
||||||
pQuery->haveResultSet = true;
|
pQuery->haveResultSet = true;
|
||||||
pQuery->directRpc = false;
|
pQuery->directRpc = false;
|
||||||
pQuery->msgType = TDMT_VND_QUERY;
|
pQuery->msgType = TDMT_VND_QUERY;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -647,3 +647,16 @@ TEST_F(ParserTest, dropTopic) {
|
||||||
bind("drop topic if exists tp1");
|
bind("drop topic if exists tp1");
|
||||||
ASSERT_TRUE(run());
|
ASSERT_TRUE(run());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserTest, explain) {
|
||||||
|
setDatabase("root", "test");
|
||||||
|
|
||||||
|
bind("explain SELECT * FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("explain analyze SELECT * FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("explain analyze verbose true ratio 0.01 SELECT * FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
}
|
||||||
|
|
|
@ -197,6 +197,7 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
|
||||||
strcpy(pScan->tableName.dbname, pRealTable->table.dbName);
|
strcpy(pScan->tableName.dbname, pRealTable->table.dbName);
|
||||||
strcpy(pScan->tableName.tname, pRealTable->table.tableName);
|
strcpy(pScan->tableName.tname, pRealTable->table.tableName);
|
||||||
pScan->showRewrite = pCxt->pPlanCxt->showRewrite;
|
pScan->showRewrite = pCxt->pPlanCxt->showRewrite;
|
||||||
|
pScan->ratio = pRealTable->ratio;
|
||||||
|
|
||||||
// set columns to scan
|
// set columns to scan
|
||||||
SNodeList* pCols = NULL;
|
SNodeList* pCols = NULL;
|
||||||
|
@ -704,6 +705,8 @@ static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogi
|
||||||
return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt, pLogicNode);
|
return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt, pLogicNode);
|
||||||
case QUERY_NODE_VNODE_MODIF_STMT:
|
case QUERY_NODE_VNODE_MODIF_STMT:
|
||||||
return createVnodeModifLogicNode(pCxt, (SVnodeModifOpStmt*)pStmt, pLogicNode);
|
return createVnodeModifLogicNode(pCxt, (SVnodeModifOpStmt*)pStmt, pLogicNode);
|
||||||
|
case QUERY_NODE_EXPLAIN_STMT:
|
||||||
|
return createQueryLogicNode(pCxt, ((SExplainStmt*)pStmt)->pQuery, pLogicNode);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,6 +398,7 @@ static int32_t createTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubp
|
||||||
|
|
||||||
pTableScan->scanFlag = pScanLogicNode->scanFlag;
|
pTableScan->scanFlag = pScanLogicNode->scanFlag;
|
||||||
pTableScan->scanRange = pScanLogicNode->scanRange;
|
pTableScan->scanRange = pScanLogicNode->scanRange;
|
||||||
|
pTableScan->ratio = pScanLogicNode->ratio;
|
||||||
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
||||||
taosArrayPush(pCxt->pExecNodeList, &pSubplan->execNode);
|
taosArrayPush(pCxt->pExecNodeList, &pSubplan->execNode);
|
||||||
pSubplan->execNodeStat.tableNum = pScanLogicNode->pVgroupList->vgroups[0].numOfTable;
|
pSubplan->execNodeStat.tableNum = pScanLogicNode->pVgroupList->vgroups[0].numOfTable;
|
||||||
|
@ -1095,6 +1096,16 @@ static void destoryPhysiPlanContext(SPhysiPlanContext* pCxt) {
|
||||||
taosArrayDestroyEx(pCxt->pLocationHelper, destoryLocationHash);
|
taosArrayDestroyEx(pCxt->pLocationHelper, destoryLocationHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setExplainInfo(SPlanContext* pCxt, SQueryPlan* pPlan) {
|
||||||
|
if (QUERY_NODE_EXPLAIN_STMT == nodeType(pCxt->pAstRoot)) {
|
||||||
|
SExplainStmt* pStmt = (SExplainStmt*)pCxt->pAstRoot;
|
||||||
|
pPlan->explainInfo.mode = pStmt->analyze ? EXPLAIN_MODE_ANALYZE : EXPLAIN_MODE_STATIC;
|
||||||
|
pPlan->explainInfo.verbose = pStmt->pOptions->verbose;
|
||||||
|
} else {
|
||||||
|
pPlan->explainInfo.mode = EXPLAIN_MODE_DISABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32_t createPhysiPlan(SPlanContext* pCxt, SQueryLogicPlan* pLogicPlan, SQueryPlan** pPlan, SArray* pExecNodeList) {
|
int32_t createPhysiPlan(SPlanContext* pCxt, SQueryLogicPlan* pLogicPlan, SQueryPlan** pPlan, SArray* pExecNodeList) {
|
||||||
SPhysiPlanContext cxt = {
|
SPhysiPlanContext cxt = {
|
||||||
.pPlanCxt = pCxt,
|
.pPlanCxt = pCxt,
|
||||||
|
@ -1106,7 +1117,12 @@ int32_t createPhysiPlan(SPlanContext* pCxt, SQueryLogicPlan* pLogicPlan, SQueryP
|
||||||
if (NULL == cxt.pLocationHelper) {
|
if (NULL == cxt.pLocationHelper) {
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t code = doCreatePhysiPlan(&cxt, pLogicPlan, pPlan);
|
int32_t code = doCreatePhysiPlan(&cxt, pLogicPlan, pPlan);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
setExplainInfo(pCxt, *pPlan);
|
||||||
|
}
|
||||||
|
|
||||||
destoryPhysiPlanContext(&cxt);
|
destoryPhysiPlanContext(&cxt);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,3 +282,16 @@ TEST_F(PlannerTest, createSmaIndex) {
|
||||||
bind("create sma index index1 on t1 function(max(c1), min(c3 + 10), sum(c4)) INTERVAL(10s)");
|
bind("create sma index index1 on t1 function(max(c1), min(c3 + 10), sum(c4)) INTERVAL(10s)");
|
||||||
ASSERT_TRUE(run());
|
ASSERT_TRUE(run());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PlannerTest, explain) {
|
||||||
|
setDatabase("root", "test");
|
||||||
|
|
||||||
|
bind("explain SELECT * FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("explain analyze SELECT * FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("explain analyze verbose true ratio 0.01 SELECT * FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue