提交 03771c84 编写于 作者: X Xiaoyu Wang

TD-14396 explain parser and planner implement

上级 c439f2fb
...@@ -138,55 +138,59 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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); ...@@ -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). ...@@ -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 ...@@ -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[] = { ...@@ -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[] = { ...@@ -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[] = { ...@@ -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[] = { ...@@ -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[] = { ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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) { ...@@ -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;
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -647,3 +647,16 @@ TEST_F(ParserTest, dropTopic) { ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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) { ...@@ -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 ...@@ -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) { ...@@ -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());
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册