explain.c 44.2 KB
Newer Older
D
dapan1121 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

D
dapan1121 已提交
16
#include "commandInt.h"
X
Xiaoyu Wang 已提交
17 18
#include "plannodes.h"
#include "query.h"
19
#include "tcommon.h"
D
dapan1121 已提交
20

D
dapan1121 已提交
21
int32_t qExplainGenerateResNode(SPhysiNode *pNode, SExplainGroup *group, SExplainResNode **pRes);
D
dapan1121 已提交
22
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level);
D
dapan1121 已提交
23

D
dapan1121 已提交
24 25
void qExplainFreeResNode(SExplainResNode *resNode) {
  if (NULL == resNode) {
D
dapan1121 已提交
26 27 28
    return;
  }

D
dapan1121 已提交
29
  taosMemoryFreeClear(resNode->pExecInfo);
D
dapan1121 已提交
30

X
Xiaoyu Wang 已提交
31 32
  SNode *node = NULL;
  FOREACH(node, resNode->pChildren) { qExplainFreeResNode((SExplainResNode *)node); }
D
dapan1121 已提交
33
  nodesClearList(resNode->pChildren);
X
Xiaoyu Wang 已提交
34

D
dapan1121 已提交
35
  taosMemoryFreeClear(resNode);
D
dapan1121 已提交
36 37
}

D
dapan1121 已提交
38 39
void qExplainFreeCtx(SExplainCtx *pCtx) {
  if (NULL == pCtx) {
D
dapan1121 已提交
40 41 42 43 44 45 46 47 48
    return;
  }

  int32_t rowSize = taosArrayGetSize(pCtx->rows);
  for (int32_t i = 0; i < rowSize; ++i) {
    SQueryExplainRowInfo *row = taosArrayGet(pCtx->rows, i);
    taosMemoryFreeClear(row->buf);
  }

D
dapan1121 已提交
49 50 51 52
  if (EXPLAIN_MODE_ANALYZE == pCtx->mode && pCtx->groupHash) {
    void *pIter = taosHashIterate(pCtx->groupHash, NULL);
    while (pIter) {
      SExplainGroup *group = (SExplainGroup *)pIter;
D
dapan1121 已提交
53 54 55 56 57 58
      if (group->nodeExecInfo) {
        int32_t num = taosArrayGetSize(group->nodeExecInfo);
        for (int32_t i = 0; i < num; ++i) {
          SExplainRsp *rsp = taosArrayGet(group->nodeExecInfo, i);
          taosMemoryFreeClear(rsp->subplanInfo);
        }
D
dapan1121 已提交
59
      }
X
Xiaoyu Wang 已提交
60

D
dapan1121 已提交
61 62 63
      pIter = taosHashIterate(pCtx->groupHash, pIter);
    }
  }
X
Xiaoyu Wang 已提交
64

D
dapan1121 已提交
65
  taosHashCleanup(pCtx->groupHash);
D
dapan1121 已提交
66 67
  taosArrayDestroy(pCtx->rows);
  taosMemoryFree(pCtx);
D
dapan1121 已提交
68 69
}

D
dapan1121 已提交
70
int32_t qExplainInitCtx(SExplainCtx **pCtx, SHashObj *groupHash, bool verbose, double ratio, EExplainMode mode) {
X
Xiaoyu Wang 已提交
71
  int32_t      code = 0;
D
dapan1121 已提交
72 73 74 75 76
  SExplainCtx *ctx = taosMemoryCalloc(1, sizeof(SExplainCtx));
  if (NULL == ctx) {
    qError("calloc SExplainCtx failed");
    QRY_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }
X
Xiaoyu Wang 已提交
77

D
dapan1121 已提交
78 79 80 81 82 83 84 85 86 87 88 89
  SArray *rows = taosArrayInit(10, sizeof(SQueryExplainRowInfo));
  if (NULL == rows) {
    qError("taosArrayInit SQueryExplainRowInfo failed");
    QRY_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

  char *tbuf = taosMemoryMalloc(TSDB_EXPLAIN_RESULT_ROW_SIZE);
  if (NULL == tbuf) {
    qError("malloc size %d failed", TSDB_EXPLAIN_RESULT_ROW_SIZE);
    QRY_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

D
dapan1121 已提交
90
  ctx->mode = mode;
D
dapan1121 已提交
91
  ctx->verbose = verbose;
D
dapan1121 已提交
92
  ctx->ratio = ratio;
D
dapan1121 已提交
93 94 95
  ctx->tbuf = tbuf;
  ctx->rows = rows;
  ctx->groupHash = groupHash;
X
Xiaoyu Wang 已提交
96

D
dapan1121 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109
  *pCtx = ctx;

  return TSDB_CODE_SUCCESS;

_return:

  taosArrayDestroy(rows);
  taosHashCleanup(groupHash);
  taosMemoryFree(ctx);

  QRY_RET(code);
}

D
dapan1121 已提交
110
int32_t qExplainGenerateResChildren(SPhysiNode *pNode, SExplainGroup *group, SNodeList **pChildren) {
X
Xiaoyu Wang 已提交
111
  int32_t    tlen = 0;
D
dapan1121 已提交
112
  SNodeList *pPhysiChildren = NULL;
X
Xiaoyu Wang 已提交
113

D
dapan1121 已提交
114 115 116 117 118 119 120
  switch (pNode->type) {
    case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: {
      STagScanPhysiNode *pTagScanNode = (STagScanPhysiNode *)pNode;
      pPhysiChildren = pTagScanNode->node.pChildren;
      break;
    }
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
X
Xiaoyu Wang 已提交
121
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: {
D
dapan1121 已提交
122 123 124 125
      STableScanPhysiNode *pTblScanNode = (STableScanPhysiNode *)pNode;
      pPhysiChildren = pTblScanNode->scan.node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
126
    case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN: {
D
dapan1121 已提交
127 128 129 130
      SSystemTableScanPhysiNode *pSTblScanNode = (SSystemTableScanPhysiNode *)pNode;
      pPhysiChildren = pSTblScanNode->scan.node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
131
    case QUERY_NODE_PHYSICAL_PLAN_PROJECT: {
D
dapan1121 已提交
132 133 134 135
      SProjectPhysiNode *pPrjNode = (SProjectPhysiNode *)pNode;
      pPhysiChildren = pPrjNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
136
    case QUERY_NODE_PHYSICAL_PLAN_JOIN: {
D
dapan1121 已提交
137 138 139 140
      SJoinPhysiNode *pJoinNode = (SJoinPhysiNode *)pNode;
      pPhysiChildren = pJoinNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
141
    case QUERY_NODE_PHYSICAL_PLAN_AGG: {
D
dapan1121 已提交
142 143 144 145
      SAggPhysiNode *pAggNode = (SAggPhysiNode *)pNode;
      pPhysiChildren = pAggNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
146
    case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: {
D
dapan1121 已提交
147 148 149 150
      SExchangePhysiNode *pExchNode = (SExchangePhysiNode *)pNode;
      pPhysiChildren = pExchNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
151
    case QUERY_NODE_PHYSICAL_PLAN_SORT: {
D
dapan1121 已提交
152 153 154 155
      SSortPhysiNode *pSortNode = (SSortPhysiNode *)pNode;
      pPhysiChildren = pSortNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
156
    case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL: {
D
dapan1121 已提交
157 158 159 160
      SIntervalPhysiNode *pIntNode = (SIntervalPhysiNode *)pNode;
      pPhysiChildren = pIntNode->window.node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
161
    case QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW: {
D
dapan1121 已提交
162 163 164 165
      SSessionWinodwPhysiNode *pSessNode = (SSessionWinodwPhysiNode *)pNode;
      pPhysiChildren = pSessNode->window.node.pChildren;
      break;
    }
166
    case QUERY_NODE_PHYSICAL_PLAN_STATE_WINDOW: {
X
Xiaoyu Wang 已提交
167
      SStateWinodwPhysiNode *pStateNode = (SStateWinodwPhysiNode *)pNode;
168 169 170 171
      pPhysiChildren = pStateNode->window.node.pChildren;
      break;
    }
    case QUERY_NODE_PHYSICAL_PLAN_PARTITION: {
X
Xiaoyu Wang 已提交
172
      SPartitionPhysiNode *partitionPhysiNode = (SPartitionPhysiNode *)pNode;
173 174 175
      pPhysiChildren = partitionPhysiNode->node.pChildren;
      break;
    }
D
dapan1121 已提交
176 177 178 179 180 181 182 183 184 185 186 187
    default:
      qError("not supported physical node type %d", pNode->type);
      QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

  if (pPhysiChildren) {
    *pChildren = nodesMakeList();
    if (NULL == *pChildren) {
      qError("nodesMakeList failed");
      QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
    }
  }
D
dapan1121 已提交
188

X
Xiaoyu Wang 已提交
189
  SNode           *node = NULL;
D
dapan1121 已提交
190 191
  SExplainResNode *pResNode = NULL;
  FOREACH(node, pPhysiChildren) {
D
dapan1121 已提交
192
    QRY_ERR_RET(qExplainGenerateResNode((SPhysiNode *)node, group, &pResNode));
D
dapan1121 已提交
193 194 195 196
    QRY_ERR_RET(nodesListAppend(*pChildren, pResNode));
  }

  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
197 198
}

D
dapan1121 已提交
199 200 201 202 203 204 205
int32_t qExplainGenerateResNodeExecInfo(SArray **pExecInfo, SExplainGroup *group) {
  *pExecInfo = taosArrayInit(group->nodeNum, sizeof(SExplainExecInfo));
  if (NULL == (*pExecInfo)) {
    qError("taosArrayInit %d explainExecInfo failed", group->nodeNum);
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

X
Xiaoyu Wang 已提交
206
  SExplainRsp *rsp = NULL;
D
dapan1121 已提交
207 208 209 210 211 212
  for (int32_t i = 0; i < group->nodeNum; ++i) {
    rsp = taosArrayGet(group->nodeExecInfo, i);
    if (group->physiPlanExecIdx >= rsp->numOfPlans) {
      qError("physiPlanIdx %d exceed plan num %d", group->physiPlanExecIdx, rsp->numOfPlans);
      return TSDB_CODE_QRY_APP_ERROR;
    }
X
Xiaoyu Wang 已提交
213

D
dapan1121 已提交
214 215 216 217 218 219 220 221 222
    taosArrayPush(*pExecInfo, rsp->subplanInfo + group->physiPlanExecIdx);
  }

  ++group->physiPlanExecIdx;

  return TSDB_CODE_SUCCESS;
}

int32_t qExplainGenerateResNode(SPhysiNode *pNode, SExplainGroup *group, SExplainResNode **pResNode) {
D
dapan1121 已提交
223
  if (NULL == pNode) {
D
dapan1121 已提交
224
    *pResNode = NULL;
D
dapan1121 已提交
225 226 227
    qError("physical node is NULL");
    return TSDB_CODE_QRY_APP_ERROR;
  }
X
Xiaoyu Wang 已提交
228

D
dapan1121 已提交
229 230
  SExplainResNode *resNode = taosMemoryCalloc(1, sizeof(SExplainResNode));
  if (NULL == resNode) {
D
dapan1121 已提交
231 232 233 234 235
    qError("calloc SPhysiNodeExplainRes failed");
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

  int32_t code = 0;
D
dapan1121 已提交
236
  resNode->pNode = pNode;
X
Xiaoyu Wang 已提交
237

D
dapan1121 已提交
238 239 240
  if (group->nodeExecInfo) {
    QRY_ERR_JRET(qExplainGenerateResNodeExecInfo(&resNode->pExecInfo, group));
  }
X
Xiaoyu Wang 已提交
241

D
dapan1121 已提交
242 243 244
  QRY_ERR_JRET(qExplainGenerateResChildren(pNode, group, &resNode->pChildren));

  ++group->physiPlanNum;
X
Xiaoyu Wang 已提交
245

D
dapan1121 已提交
246
  *pResNode = resNode;
D
dapan1121 已提交
247 248 249 250 251

  return TSDB_CODE_SUCCESS;

_return:

D
dapan1121 已提交
252
  qExplainFreeResNode(resNode);
X
Xiaoyu Wang 已提交
253

D
dapan1121 已提交
254 255 256
  QRY_RET(code);
}

D
dapan1121 已提交
257
int32_t qExplainBufAppendExecInfo(SArray *pExecInfo, char *tbuf, int32_t *len) {
X
Xiaoyu Wang 已提交
258 259
  int32_t          tlen = *len;
  int32_t          nodeNum = taosArrayGetSize(pExecInfo);
D
dapan1121 已提交
260
  SExplainExecInfo maxExecInfo = {0};
X
Xiaoyu Wang 已提交
261

D
dapan1121 已提交
262 263 264 265 266 267 268 269 270 271 272 273
  for (int32_t i = 0; i < nodeNum; ++i) {
    SExplainExecInfo *execInfo = taosArrayGet(pExecInfo, i);
    if (execInfo->startupCost > maxExecInfo.startupCost) {
      maxExecInfo.startupCost = execInfo->startupCost;
    }
    if (execInfo->totalCost > maxExecInfo.totalCost) {
      maxExecInfo.totalCost = execInfo->totalCost;
    }
    if (execInfo->numOfRows > maxExecInfo.numOfRows) {
      maxExecInfo.numOfRows = execInfo->numOfRows;
    }
  }
X
Xiaoyu Wang 已提交
274

D
dapan1121 已提交
275 276
  EXPLAIN_ROW_APPEND(EXPLAIN_EXECINFO_FORMAT, maxExecInfo.startupCost, maxExecInfo.totalCost, maxExecInfo.numOfRows);

D
dapan1121 已提交
277
  *len = tlen;
X
Xiaoyu Wang 已提交
278

D
dapan1121 已提交
279
  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
280 281
}

D
dapan1121 已提交
282
int32_t qExplainBufAppendVerboseExecInfo(SArray *pExecInfo, char *tbuf, int32_t *len) {
X
Xiaoyu Wang 已提交
283 284 285
  int32_t          tlen = 0;
  bool             gotVerbose = false;
  int32_t          nodeNum = taosArrayGetSize(pExecInfo);
D
dapan1121 已提交
286
  SExplainExecInfo maxExecInfo = {0};
X
Xiaoyu Wang 已提交
287

D
dapan1121 已提交
288 289 290 291 292 293 294 295 296 297 298 299
  for (int32_t i = 0; i < nodeNum; ++i) {
    SExplainExecInfo *execInfo = taosArrayGet(pExecInfo, i);
    if (execInfo->verboseInfo) {
      gotVerbose = true;
    }
  }

  if (gotVerbose) {
    EXPLAIN_ROW_APPEND("exec verbose info");
  }

  *len = tlen;
X
Xiaoyu Wang 已提交
300

D
dapan1121 已提交
301 302 303
  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
304
int32_t qExplainResAppendRow(SExplainCtx *ctx, char *tbuf, int32_t len, int32_t level) {
D
dapan1121 已提交
305
  SQueryExplainRowInfo row = {0};
D
dapan1121 已提交
306
  row.buf = taosMemoryMalloc(len);
D
dapan1121 已提交
307
  if (NULL == row.buf) {
D
dapan1121 已提交
308
    qError("taosMemoryMalloc %d failed", len);
D
dapan1121 已提交
309 310 311
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

D
dapan1121 已提交
312
  memcpy(row.buf, tbuf, len);
D
dapan1121 已提交
313
  row.level = level;
X
Xiaoyu Wang 已提交
314
  row.len = len;
315
  ctx->dataSize += row.len;
D
dapan1121 已提交
316

D
dapan1121 已提交
317
  if (NULL == taosArrayPush(ctx->rows, &row)) {
D
dapan1121 已提交
318 319 320 321 322 323 324 325
    qError("taosArrayPush row to explain res rows failed");
    taosMemoryFree(row.buf);
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
326 327
static uint8_t getIntervalPrecision(SIntervalPhysiNode *pIntNode) {
  return ((SColumnNode *)pIntNode->window.pTspk)->node.resType.precision;
X
Xiaoyu Wang 已提交
328
}
D
dapan1121 已提交
329

D
dapan1121 已提交
330
int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, int32_t level) {
X
Xiaoyu Wang 已提交
331 332 333 334 335
  int32_t     tlen = 0;
  bool        isVerboseLine = false;
  char       *tbuf = ctx->tbuf;
  bool        verbose = ctx->verbose;
  SPhysiNode *pNode = pResNode->pNode;
D
dapan1121 已提交
336 337 338 339
  if (NULL == pNode) {
    qError("pyhsical node in explain res node is NULL");
    return TSDB_CODE_QRY_APP_ERROR;
  }
X
Xiaoyu Wang 已提交
340

D
dapan1121 已提交
341 342 343
  switch (pNode->type) {
    case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: {
      STagScanPhysiNode *pTagScanNode = (STagScanPhysiNode *)pNode;
D
dapan1121 已提交
344 345
      EXPLAIN_ROW_NEW(level, EXPLAIN_TAG_SCAN_FORMAT, pTagScanNode->tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
346
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
347
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
348
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
349
      }
D
dapan1121 已提交
350 351 352 353
      EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pTagScanNode->pScanCols->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pTagScanNode->node.pOutputDataBlockDesc->totalRowSize);
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
354 355
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
356 357

      if (verbose) {
D
dapan1121 已提交
358
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
359 360
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pTagScanNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
361 362 363 364
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pTagScanNode->node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
X
Xiaoyu Wang 已提交
365

D
dapan1121 已提交
366 367 368 369 370 371
        if (pResNode->pExecInfo) {
          QRY_ERR_RET(qExplainBufAppendVerboseExecInfo(pResNode->pExecInfo, tbuf, &tlen));
          if (tlen) {
            EXPLAIN_ROW_END();
            QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
          }
X
Xiaoyu Wang 已提交
372
        }
D
dapan1121 已提交
373
      }
D
dapan1121 已提交
374
      break;
D
dapan1121 已提交
375 376
    }
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
X
Xiaoyu Wang 已提交
377
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: {
D
dapan1121 已提交
378
      STableScanPhysiNode *pTblScanNode = (STableScanPhysiNode *)pNode;
D
dapan1121 已提交
379 380
      EXPLAIN_ROW_NEW(level, EXPLAIN_TBL_SCAN_FORMAT, pTblScanNode->scan.tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
381
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
382
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
383
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
384
      }
D
dapan1121 已提交
385 386 387 388
      EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pTblScanNode->scan.pScanCols->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pTblScanNode->scan.node.pOutputDataBlockDesc->totalRowSize);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
389
      EXPLAIN_ROW_APPEND(EXPLAIN_TABLE_SCAN_FORMAT, pTblScanNode->scanSeq[0], pTblScanNode->scanSeq[1]);
X
Xiaoyu Wang 已提交
390
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
391 392
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
393

394 395 396 397 398 399
      // basic analyze output
      if (EXPLAIN_MODE_ANALYZE == ctx->mode) {
        EXPLAIN_ROW_NEW(level + 1, "I/O: ");

        int32_t nodeNum = taosArrayGetSize(pResNode->pExecInfo);
        for (int32_t i = 0; i < nodeNum; ++i) {
X
Xiaoyu Wang 已提交
400
          SExplainExecInfo      *execInfo = taosArrayGet(pResNode->pExecInfo, i);
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
          STableScanAnalyzeInfo *pScanInfo = (STableScanAnalyzeInfo *)execInfo->verboseInfo;

          EXPLAIN_ROW_APPEND("total_blocks=%d", pScanInfo->totalBlocks);
          EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);

          EXPLAIN_ROW_APPEND("load_blocks=%d", pScanInfo->loadBlocks);
          EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);

          EXPLAIN_ROW_APPEND("load_block_SMAs=%d", pScanInfo->loadBlockStatis);
          EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);

          EXPLAIN_ROW_APPEND("total_rows=%" PRIu64, pScanInfo->totalRows);
          EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);

          EXPLAIN_ROW_APPEND("check_rows=%" PRIu64, pScanInfo->totalCheckedRows);
          EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        }

        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
      }

X
Xiaoyu Wang 已提交
423
      if (verbose) {
D
dapan1121 已提交
424
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
425 426
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pTblScanNode->scan.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
427 428 429 430 431
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pTblScanNode->scan.node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

X
Xiaoyu Wang 已提交
432 433
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TIMERANGE_FORMAT, pTblScanNode->scanRange.skey,
                        pTblScanNode->scanRange.ekey);
D
dapan1121 已提交
434 435 436 437 438
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

        if (pTblScanNode->scan.node.pConditions) {
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
X
Xiaoyu Wang 已提交
439 440
          QRY_ERR_RET(nodesNodeToSQL(pTblScanNode->scan.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
441 442 443
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
444 445 446
      }
      break;
    }
X
Xiaoyu Wang 已提交
447
    case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN: {
D
dapan1121 已提交
448
      SSystemTableScanPhysiNode *pSTblScanNode = (SSystemTableScanPhysiNode *)pNode;
D
dapan1121 已提交
449 450
      EXPLAIN_ROW_NEW(level, EXPLAIN_SYSTBL_SCAN_FORMAT, pSTblScanNode->scan.tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
451
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
452
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
453
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
454
      }
D
dapan1121 已提交
455 456 457 458
      EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pSTblScanNode->scan.pScanCols->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pSTblScanNode->scan.node.pOutputDataBlockDesc->totalRowSize);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
459
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
460 461
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
462

X
Xiaoyu Wang 已提交
463
      if (verbose) {
D
dapan1121 已提交
464
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
465 466
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pSTblScanNode->scan.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
467 468 469 470 471
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pSTblScanNode->scan.node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

D
dapan1121 已提交
472 473
        if (pSTblScanNode->scan.node.pConditions) {
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
X
Xiaoyu Wang 已提交
474 475
          QRY_ERR_RET(nodesNodeToSQL(pSTblScanNode->scan.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
476 477 478
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
479
      }
D
dapan1121 已提交
480 481
      break;
    }
X
Xiaoyu Wang 已提交
482
    case QUERY_NODE_PHYSICAL_PLAN_PROJECT: {
D
dapan1121 已提交
483
      SProjectPhysiNode *pPrjNode = (SProjectPhysiNode *)pNode;
D
dapan1121 已提交
484 485
      EXPLAIN_ROW_NEW(level, EXPLAIN_PROJECTION_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
486
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
487
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
488
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
489
      }
D
dapan1121 已提交
490 491 492
      EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pPrjNode->pProjections->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pPrjNode->node.pOutputDataBlockDesc->totalRowSize);
X
Xiaoyu Wang 已提交
493
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
494 495
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
496

D
dapan1121 已提交
497
      if (verbose) {
D
dapan1121 已提交
498
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
499 500
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pPrjNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
501 502 503 504
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pPrjNode->node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
X
Xiaoyu Wang 已提交
505

D
dapan1121 已提交
506
        if (pPrjNode->node.pConditions) {
X
Xiaoyu Wang 已提交
507 508 509
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pPrjNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
510 511 512
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
513 514 515
      }
      break;
    }
X
Xiaoyu Wang 已提交
516
    case QUERY_NODE_PHYSICAL_PLAN_JOIN: {
D
dapan1121 已提交
517
      SJoinPhysiNode *pJoinNode = (SJoinPhysiNode *)pNode;
D
dapan1121 已提交
518 519
      EXPLAIN_ROW_NEW(level, EXPLAIN_JOIN_FORMAT, EXPLAIN_JOIN_STRING(pJoinNode->joinType));
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
520
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
521
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
522
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
523
      }
D
dapan1121 已提交
524 525 526
      EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pJoinNode->pTargets->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pJoinNode->node.pOutputDataBlockDesc->totalRowSize);
X
Xiaoyu Wang 已提交
527
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
528 529
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
530

D
dapan1121 已提交
531
      if (verbose) {
D
dapan1121 已提交
532
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
533 534
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pJoinNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
535 536 537 538 539
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pJoinNode->node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

D
dapan1121 已提交
540
        if (pJoinNode->node.pConditions) {
X
Xiaoyu Wang 已提交
541 542 543
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pJoinNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
544 545 546
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
X
Xiaoyu Wang 已提交
547 548 549 550

        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_ON_CONDITIONS_FORMAT);
        QRY_ERR_RET(
            nodesNodeToSQL(pJoinNode->pOnConditions, tbuf + VARSTR_HEADER_SIZE, TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
551 552
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
D
dapan1121 已提交
553 554 555
      }
      break;
    }
X
Xiaoyu Wang 已提交
556
    case QUERY_NODE_PHYSICAL_PLAN_AGG: {
D
dapan1121 已提交
557
      SAggPhysiNode *pAggNode = (SAggPhysiNode *)pNode;
D
dapan1121 已提交
558 559
      EXPLAIN_ROW_NEW(level, EXPLAIN_AGG_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
560
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
561
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
562
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
563
      }
D
dapan1121 已提交
564 565 566 567
      if (pAggNode->pAggFuncs) {
        EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pAggNode->pAggFuncs->length);
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      }
D
dapan1121 已提交
568 569 570 571
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pAggNode->node.pOutputDataBlockDesc->totalRowSize);
      if (pAggNode->pGroupKeys) {
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_GROUPS_FORMAT, pAggNode->pGroupKeys->length);
D
dapan1121 已提交
572
      }
X
Xiaoyu Wang 已提交
573
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
574 575
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
576

D
dapan1121 已提交
577
      if (verbose) {
D
dapan1121 已提交
578
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
579 580
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pAggNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
581 582 583 584 585
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pAggNode->node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

D
dapan1121 已提交
586
        if (pAggNode->node.pConditions) {
X
Xiaoyu Wang 已提交
587 588 589
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pAggNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
590 591 592
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
593 594 595
      }
      break;
    }
X
Xiaoyu Wang 已提交
596
    case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: {
D
dapan1121 已提交
597
      SExchangePhysiNode *pExchNode = (SExchangePhysiNode *)pNode;
X
Xiaoyu Wang 已提交
598
      SExplainGroup      *group = taosHashGet(ctx->groupHash, &pExchNode->srcGroupId, sizeof(pExchNode->srcGroupId));
D
dapan1121 已提交
599 600 601 602
      if (NULL == group) {
        qError("exchange src group %d not in groupHash", pExchNode->srcGroupId);
        QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
      }
X
Xiaoyu Wang 已提交
603

D
dapan1121 已提交
604 605
      EXPLAIN_ROW_NEW(level, EXPLAIN_EXCHANGE_FORMAT, group->nodeNum);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
606
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
607
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
608
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
609
      }
D
dapan1121 已提交
610
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pExchNode->node.pOutputDataBlockDesc->totalRowSize);
X
Xiaoyu Wang 已提交
611
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
612 613
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
614

D
dapan1121 已提交
615
      if (verbose) {
D
dapan1121 已提交
616
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
617 618
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pExchNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
619 620 621 622 623
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pExchNode->node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

D
dapan1121 已提交
624
        if (pExchNode->node.pConditions) {
X
Xiaoyu Wang 已提交
625 626 627
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pExchNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
628 629 630
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
631
      }
D
dapan1121 已提交
632

D
dapan1121 已提交
633
      QRY_ERR_RET(qExplainAppendGroupResRows(ctx, pExchNode->srcGroupId, level + 1));
D
dapan1121 已提交
634 635
      break;
    }
X
Xiaoyu Wang 已提交
636
    case QUERY_NODE_PHYSICAL_PLAN_SORT: {
D
dapan1121 已提交
637
      SSortPhysiNode *pSortNode = (SSortPhysiNode *)pNode;
D
dapan1121 已提交
638 639
      EXPLAIN_ROW_NEW(level, EXPLAIN_SORT_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
640
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
641
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
642
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
643
      }
644

X
Xiaoyu Wang 已提交
645
      SDataBlockDescNode *pDescNode = pSortNode->node.pOutputDataBlockDesc;
646
      EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, nodesGetOutputNumFromSlotList(pDescNode->pSlots));
D
dapan1121 已提交
647
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
648
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pDescNode->totalRowSize);
D
dapan1121 已提交
649
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
650 651
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
652

653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
      if (EXPLAIN_MODE_ANALYZE == ctx->mode) {
        // sort key
        EXPLAIN_ROW_NEW(level, "Sort Key: ");
        if (pResNode->pExecInfo) {
          for (int32_t i = 0; i < LIST_LENGTH(pSortNode->pSortKeys); ++i) {
            SOrderByExprNode *ptn = nodesListGetNode(pSortNode->pSortKeys, i);
            EXPLAIN_ROW_APPEND("%s ", nodesGetNameFromColumnNode(ptn->pExpr));
          }
        }

        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));

        // sort method
        EXPLAIN_ROW_NEW(level, "Sort Method: ");

        int32_t           nodeNum = taosArrayGetSize(pResNode->pExecInfo);
        SExplainExecInfo *execInfo = taosArrayGet(pResNode->pExecInfo, 0);
X
Xiaoyu Wang 已提交
671
        SSortExecInfo    *pExecInfo = (SSortExecInfo *)execInfo->verboseInfo;
672 673 674 675 676 677 678 679 680 681 682 683 684 685
        EXPLAIN_ROW_APPEND("%s", pExecInfo->sortMethod == SORT_QSORT_T ? "quicksort" : "merge sort");
        if (pExecInfo->sortBuffer > 1024 * 1024) {
          EXPLAIN_ROW_APPEND("  Buffers:%.2f Mb", pExecInfo->sortBuffer / (1024 * 1024.0));
        } else if (pExecInfo->sortBuffer > 1024) {
          EXPLAIN_ROW_APPEND("  Buffers:%.2f Kb", pExecInfo->sortBuffer / (1024.0));
        } else {
          EXPLAIN_ROW_APPEND("  Buffers:%d b", pExecInfo->sortBuffer);
        }

        EXPLAIN_ROW_APPEND("  loops:%d", pExecInfo->loops);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
      }

D
dapan1121 已提交
686
      if (verbose) {
D
dapan1121 已提交
687
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
688 689
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pSortNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
690 691 692 693 694
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pSortNode->node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

D
dapan1121 已提交
695
        if (pSortNode->node.pConditions) {
X
Xiaoyu Wang 已提交
696 697 698
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pSortNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
699 700 701
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
702 703 704
      }
      break;
    }
X
Xiaoyu Wang 已提交
705
    case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL: {
D
dapan1121 已提交
706
      SIntervalPhysiNode *pIntNode = (SIntervalPhysiNode *)pNode;
707
      EXPLAIN_ROW_NEW(level, EXPLAIN_INTERVAL_FORMAT, nodesGetNameFromColumnNode(pIntNode->window.pTspk));
D
dapan1121 已提交
708
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
709
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
710
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
711
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
712
      }
D
dapan1121 已提交
713 714 715
      EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pIntNode->window.pFuncs->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pIntNode->window.node.pOutputDataBlockDesc->totalRowSize);
716
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
717 718
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
719

D
dapan1121 已提交
720
      if (verbose) {
D
dapan1121 已提交
721
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
722 723
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pIntNode->window.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
724 725 726 727
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pIntNode->window.node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
X
Xiaoyu Wang 已提交
728
        uint8_t precision = getIntervalPrecision(pIntNode);
X
Xiaoyu Wang 已提交
729 730 731 732 733
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TIME_WINDOWS_FORMAT,
                        INVERAL_TIME_FROM_PRECISION_TO_UNIT(pIntNode->interval, pIntNode->intervalUnit, precision),
                        pIntNode->intervalUnit, pIntNode->offset, getPrecisionUnit(precision),
                        INVERAL_TIME_FROM_PRECISION_TO_UNIT(pIntNode->sliding, pIntNode->slidingUnit, precision),
                        pIntNode->slidingUnit);
D
dapan1121 已提交
734 735
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
D
dapan1121 已提交
736 737

        if (pIntNode->window.node.pConditions) {
X
Xiaoyu Wang 已提交
738 739 740
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pIntNode->window.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
741 742 743
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
744 745 746
      }
      break;
    }
X
Xiaoyu Wang 已提交
747
    case QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW: {
D
dapan1121 已提交
748 749 750
      SSessionWinodwPhysiNode *pSessNode = (SSessionWinodwPhysiNode *)pNode;
      EXPLAIN_ROW_NEW(level, EXPLAIN_SESSION_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
751
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
752
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
753
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
754
      }
D
dapan1121 已提交
755 756 757 758
      EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pSessNode->window.pFuncs->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pSessNode->window.node.pOutputDataBlockDesc->totalRowSize);
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
759 760
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
761

D
dapan1121 已提交
762
      if (verbose) {
D
dapan1121 已提交
763
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
764 765
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pSessNode->window.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
766 767 768 769 770 771 772 773 774 775
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pSessNode->window.node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_WINDOW_FORMAT, pSessNode->gap);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

        if (pSessNode->window.node.pConditions) {
X
Xiaoyu Wang 已提交
776 777 778
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pSessNode->window.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
779 780 781
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
782 783 784
      }
      break;
    }
785 786 787
    case QUERY_NODE_PHYSICAL_PLAN_STATE_WINDOW: {
      SStateWinodwPhysiNode *pStateNode = (SStateWinodwPhysiNode *)pNode;

X
Xiaoyu Wang 已提交
788 789
      EXPLAIN_ROW_NEW(level, EXPLAIN_STATE_WINDOW_FORMAT,
                      nodesGetNameFromColumnNode(((STargetNode *)pStateNode->pStateKey)->pExpr));
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
      if (pResNode->pExecInfo) {
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      }

      EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pStateNode->window.pFuncs->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pStateNode->window.node.pOutputDataBlockDesc->totalRowSize);
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));

      if (verbose) {
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pStateNode->window.node.pOutputDataBlockDesc->pSlots));
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pStateNode->window.node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

        if (pStateNode->window.node.pConditions) {
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pStateNode->window.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
      }
      break;
    }
    case QUERY_NODE_PHYSICAL_PLAN_PARTITION: {
      SPartitionPhysiNode *pPartNode = (SPartitionPhysiNode *)pNode;

X
Xiaoyu Wang 已提交
828
      SNode *p = nodesListGetNode(pPartNode->pPartitionKeys, 0);
829 830 831 832 833 834 835
      EXPLAIN_ROW_NEW(level, EXPLAIN_PARITION_FORMAT, nodesGetNameFromColumnNode(p));
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
      if (pResNode->pExecInfo) {
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      }
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pPartNode->node.pOutputDataBlockDesc->totalRowSize);
836

837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));

      if (verbose) {
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pPartNode->node.pOutputDataBlockDesc->pSlots));
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pPartNode->node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

        if (pPartNode->node.pConditions) {
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pPartNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
      }
      break;
    }
D
dapan1121 已提交
860 861 862 863 864 865 866 867
    default:
      qError("not supported physical node type %d", pNode->type);
      return TSDB_CODE_QRY_APP_ERROR;
  }

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
868
int32_t qExplainResNodeToRows(SExplainResNode *pResNode, SExplainCtx *ctx, int32_t level) {
D
dapan1121 已提交
869 870 871 872 873 874
  if (NULL == pResNode) {
    qError("explain res node is NULL");
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

  int32_t code = 0;
D
dapan1121 已提交
875
  QRY_ERR_RET(qExplainResNodeToRowsImpl(pResNode, ctx, level));
D
dapan1121 已提交
876

X
Xiaoyu Wang 已提交
877 878
  SNode *pNode = NULL;
  FOREACH(pNode, pResNode->pChildren) { QRY_ERR_RET(qExplainResNodeToRows((SExplainResNode *)pNode, ctx, level + 1)); }
D
dapan1121 已提交
879 880 881 882

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
883
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level) {
D
dapan1121 已提交
884
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
885 886
  int32_t          code = 0;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
887

D
dapan1121 已提交
888 889 890 891
  SExplainGroup *group = taosHashGet(ctx->groupHash, &groupId, sizeof(groupId));
  if (NULL == group) {
    qError("group %d not in groupHash", groupId);
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
D
dapan1121 已提交
892
  }
X
Xiaoyu Wang 已提交
893

D
dapan1121 已提交
894 895
  QRY_ERR_RET(qExplainGenerateResNode(group->plan->pNode, group, &node));

D
dapan1121 已提交
896
  if ((EXPLAIN_MODE_ANALYZE == ctx->mode) && (group->physiPlanNum != group->physiPlanExecNum)) {
X
Xiaoyu Wang 已提交
897 898
    qError("physiPlanNum %d mismatch with physiExecNum %d in group %d", group->physiPlanNum, group->physiPlanExecNum,
           groupId);
D
dapan1121 已提交
899 900
    QRY_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
  }
D
dapan1121 已提交
901

D
dapan1121 已提交
902
  QRY_ERR_JRET(qExplainResNodeToRows(node, ctx, level));
D
dapan1121 已提交
903 904 905

_return:

D
dapan1121 已提交
906
  qExplainFreeResNode(node);
X
Xiaoyu Wang 已提交
907

D
dapan1121 已提交
908 909 910
  QRY_RET(code);
}

D
dapan1121 已提交
911
int32_t qExplainGetRspFromCtx(void *ctx, SRetrieveTableRsp **pRsp) {
D
dapan1121 已提交
912
  SExplainCtx *pCtx = (SExplainCtx *)ctx;
X
Xiaoyu Wang 已提交
913
  int32_t      rowNum = taosArrayGetSize(pCtx->rows);
D
dapan1121 已提交
914 915 916 917
  if (rowNum <= 0) {
    qError("empty explain res rows");
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }
X
Xiaoyu Wang 已提交
918

D
dapan1121 已提交
919
  int32_t colNum = 1;
X
Xiaoyu Wang 已提交
920 921
  int32_t rspSize = sizeof(SRetrieveTableRsp) + sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum +
                    sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
922 923 924 925 926 927 928
  SRetrieveTableRsp *rsp = (SRetrieveTableRsp *)taosMemoryCalloc(1, rspSize);
  if (NULL == rsp) {
    qError("malloc SRetrieveTableRsp failed, size:%d", rspSize);
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

  rsp->completed = 1;
D
dapan1121 已提交
929
  rsp->numOfRows = htonl(rowNum);
D
dapan1121 已提交
930

931
  // payload length
X
Xiaoyu Wang 已提交
932 933
  *(int32_t *)rsp->data =
      sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum + sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
934

935
  // group id
X
Xiaoyu Wang 已提交
936
  *(uint64_t *)(rsp->data + sizeof(int32_t)) = 0;
937 938

  // column length
X
Xiaoyu Wang 已提交
939
  int32_t *colLength = (int32_t *)(rsp->data + sizeof(int32_t) + sizeof(uint64_t));
940 941 942 943 944

  // varchar column offset segment
  int32_t *offset = (int32_t *)((char *)colLength + sizeof(int32_t));

  // varchar data real payload
D
dapan1121 已提交
945
  char *data = (char *)(offset + rowNum);
946

X
Xiaoyu Wang 已提交
947
  char *start = data;
D
dapan1121 已提交
948 949
  for (int32_t i = 0; i < rowNum; ++i) {
    SQueryExplainRowInfo *row = taosArrayGet(pCtx->rows, i);
950
    offset[i] = data - start;
D
dapan1121 已提交
951

952 953
    varDataCopy(data, row->buf);
    ASSERT(varDataTLen(row->buf) == row->len);
D
dapan1121 已提交
954 955 956
    data += row->len;
  }

957 958
  *colLength = htonl(data - start);
  rsp->compLen = htonl(rspSize);
D
dapan1121 已提交
959

960
  *pRsp = rsp;
D
dapan1121 已提交
961 962 963
  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
964
int32_t qExplainPrepareCtx(SQueryPlan *pDag, SExplainCtx **pCtx) {
X
Xiaoyu Wang 已提交
965
  int32_t        code = 0;
D
dapan1121 已提交
966 967 968
  SNodeListNode *plans = NULL;
  int32_t        taskNum = 0;
  SExplainGroup *pGroup = NULL;
X
Xiaoyu Wang 已提交
969
  SExplainCtx   *ctx = NULL;
D
dapan1121 已提交
970 971 972 973 974 975 976 977 978 979 980 981

  if (pDag->numOfSubplans <= 0) {
    qError("invalid subplan num:%d", pDag->numOfSubplans);
    QRY_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
  }

  int32_t levelNum = (int32_t)LIST_LENGTH(pDag->pSubplans);
  if (levelNum <= 0) {
    qError("invalid level num:%d", levelNum);
    QRY_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
  }

X
Xiaoyu Wang 已提交
982 983
  SHashObj *groupHash =
      taosHashInit(EXPLAIN_MAX_GROUP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
D
dapan1121 已提交
984 985 986 987 988
  if (NULL == groupHash) {
    qError("groupHash %d failed", EXPLAIN_MAX_GROUP_NUM);
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

X
Xiaoyu Wang 已提交
989 990
  QRY_ERR_JRET(
      qExplainInitCtx(&ctx, groupHash, pDag->explainInfo.verbose, pDag->explainInfo.ratio, pDag->explainInfo.mode));
D
dapan1121 已提交
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013

  for (int32_t i = 0; i < levelNum; ++i) {
    plans = (SNodeListNode *)nodesListGetNode(pDag->pSubplans, i);
    if (NULL == plans) {
      qError("empty level plan, level:%d", i);
      QRY_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
    }

    taskNum = (int32_t)LIST_LENGTH(plans->pNodeList);
    if (taskNum <= 0) {
      qError("invalid level plan number:%d, level:%d", taskNum, i);
      QRY_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
    }

    SSubplan *plan = NULL;
    for (int32_t n = 0; n < taskNum; ++n) {
      plan = (SSubplan *)nodesListGetNode(plans->pNodeList, n);
      pGroup = taosHashGet(groupHash, &plan->id.groupId, sizeof(plan->id.groupId));
      if (pGroup) {
        ++pGroup->nodeNum;
        continue;
      }

D
dapan1121 已提交
1014 1015 1016
      SExplainGroup group = {0};
      group.nodeNum = 1;
      group.plan = plan;
X
Xiaoyu Wang 已提交
1017

D
dapan1121 已提交
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
      if (0 != taosHashPut(groupHash, &plan->id.groupId, sizeof(plan->id.groupId), &group, sizeof(group))) {
        qError("taosHashPut to explainGroupHash failed, taskIdx:%d", n);
        QRY_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY);
      }
    }

    if (0 == i) {
      if (taskNum > 1) {
        qError("invalid taskNum %d for level 0", taskNum);
        QRY_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
      }

D
dapan1121 已提交
1030
      ctx->rootGroupId = plan->id.groupId;
D
dapan1121 已提交
1031 1032 1033 1034 1035
    }

    qDebug("level %d group handled, taskNum:%d", i, taskNum);
  }

D
dapan1121 已提交
1036 1037 1038
  *pCtx = ctx;

  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
1039

D
dapan1121 已提交
1040 1041 1042 1043 1044 1045 1046
_return:

  qExplainFreeCtx(ctx);

  QRY_RET(code);
}

D
dapan1121 已提交
1047 1048 1049 1050 1051 1052
int32_t qExplainAppendPlanRows(SExplainCtx *pCtx) {
  if (EXPLAIN_MODE_ANALYZE != pCtx->mode) {
    return TSDB_CODE_SUCCESS;
  }

  int32_t tlen = 0;
X
Xiaoyu Wang 已提交
1053
  char   *tbuf = pCtx->tbuf;
D
dapan1121 已提交
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068

  EXPLAIN_SUM_ROW_NEW(EXPLAIN_RATIO_TIME_FORMAT, pCtx->ratio);
  EXPLAIN_SUM_ROW_END();
  QRY_ERR_RET(qExplainResAppendRow(pCtx, tbuf, tlen, 0));

  EXPLAIN_SUM_ROW_NEW(EXPLAIN_PLANNING_TIME_FORMAT, (double)(pCtx->jobStartTs - pCtx->reqStartTs) / 1000.0);
  EXPLAIN_SUM_ROW_END();
  QRY_ERR_RET(qExplainResAppendRow(pCtx, tbuf, tlen, 0));

  EXPLAIN_SUM_ROW_NEW(EXPLAIN_EXEC_TIME_FORMAT, (double)(pCtx->jobDoneTs - pCtx->jobStartTs) / 1000.0);
  EXPLAIN_SUM_ROW_END();
  QRY_ERR_RET(qExplainResAppendRow(pCtx, tbuf, tlen, 0));

  return TSDB_CODE_SUCCESS;
}
D
dapan1121 已提交
1069

D
dapan1121 已提交
1070 1071
int32_t qExplainGenerateRsp(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  QRY_ERR_RET(qExplainAppendGroupResRows(pCtx, pCtx->rootGroupId, 0));
D
dapan1121 已提交
1072
  QRY_ERR_RET(qExplainAppendPlanRows(pCtx));
D
dapan1121 已提交
1073 1074 1075 1076 1077
  QRY_ERR_RET(qExplainGetRspFromCtx(pCtx, pRsp));

  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
1078
int32_t qExplainUpdateExecInfo(SExplainCtx *pCtx, SExplainRsp *pRspMsg, int32_t groupId, SRetrieveTableRsp **pRsp) {
D
dapan1121 已提交
1079
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
1080 1081 1082
  int32_t          code = 0;
  bool             groupDone = false;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
1083

D
dapan1121 已提交
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
  SExplainGroup *group = taosHashGet(ctx->groupHash, &groupId, sizeof(groupId));
  if (NULL == group) {
    qError("group %d not in groupHash", groupId);
    taosMemoryFreeClear(pRspMsg->subplanInfo);
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

  taosWLockLatch(&group->lock);
  if (NULL == group->nodeExecInfo) {
    group->nodeExecInfo = taosArrayInit(group->nodeNum, sizeof(SExplainRsp));
    if (NULL == group->nodeExecInfo) {
      qError("taosArrayInit %d explainExecInfo failed", group->nodeNum);
      taosMemoryFreeClear(pRspMsg->subplanInfo);
      taosWUnLockLatch(&group->lock);
X
Xiaoyu Wang 已提交
1098

D
dapan1121 已提交
1099 1100 1101 1102 1103
      QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
    }

    group->physiPlanExecNum = pRspMsg->numOfPlans;
  } else if (taosArrayGetSize(group->nodeExecInfo) >= group->nodeNum) {
X
Xiaoyu Wang 已提交
1104 1105
    qError("group execInfo already full, size:%d, nodeNum:%d", (int32_t)taosArrayGetSize(group->nodeExecInfo),
           group->nodeNum);
D
dapan1121 已提交
1106 1107
    taosMemoryFreeClear(pRspMsg->subplanInfo);
    taosWUnLockLatch(&group->lock);
X
Xiaoyu Wang 已提交
1108

D
dapan1121 已提交
1109 1110 1111 1112
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

  if (group->physiPlanExecNum != pRspMsg->numOfPlans) {
X
Xiaoyu Wang 已提交
1113 1114
    qError("physiPlanExecNum %d mismatch with others %d in group %d", pRspMsg->numOfPlans, group->physiPlanExecNum,
           groupId);
D
dapan1121 已提交
1115 1116
    taosMemoryFreeClear(pRspMsg->subplanInfo);
    taosWUnLockLatch(&group->lock);
X
Xiaoyu Wang 已提交
1117

D
dapan1121 已提交
1118 1119 1120 1121 1122
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

  taosArrayPush(group->nodeExecInfo, pRspMsg);
  groupDone = (taosArrayGetSize(group->nodeExecInfo) >= group->nodeNum);
X
Xiaoyu Wang 已提交
1123

D
dapan1121 已提交
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
  taosWUnLockLatch(&group->lock);

  if (groupDone && (taosHashGetSize(pCtx->groupHash) == atomic_add_fetch_32(&pCtx->groupDoneNum, 1))) {
    if (atomic_load_8((int8_t *)&pCtx->execDone)) {
      if (0 == taosWTryLockLatch(&pCtx->lock)) {
        QRY_ERR_RET(qExplainGenerateRsp(pCtx, pRsp));
        // LEAVE LOCK THERE
      }
    }
  }

  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
1136 1137 1138
}

int32_t qExecStaticExplain(SQueryPlan *pDag, SRetrieveTableRsp **pRsp) {
X
Xiaoyu Wang 已提交
1139
  int32_t      code = 0;
D
dapan1121 已提交
1140 1141 1142
  SExplainCtx *pCtx = NULL;

  QRY_ERR_RET(qExplainPrepareCtx(pDag, &pCtx));
D
dapan1121 已提交
1143
  QRY_ERR_JRET(qExplainGenerateRsp(pCtx, pRsp));
X
Xiaoyu Wang 已提交
1144

D
dapan1121 已提交
1145
_return:
D
dapan1121 已提交
1146
  qExplainFreeCtx(pCtx);
D
dapan1121 已提交
1147 1148 1149
  QRY_RET(code);
}

D
dapan1121 已提交
1150
int32_t qExecExplainBegin(SQueryPlan *pDag, SExplainCtx **pCtx, int64_t startTs) {
D
dapan1121 已提交
1151
  QRY_ERR_RET(qExplainPrepareCtx(pDag, pCtx));
X
Xiaoyu Wang 已提交
1152

D
dapan1121 已提交
1153
  (*pCtx)->reqStartTs = startTs;
D
dapan1121 已提交
1154
  (*pCtx)->jobStartTs = taosGetTimestampUs();
D
dapan1121 已提交
1155 1156 1157 1158

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
1159 1160
int32_t qExecExplainEnd(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  int32_t code = 0;
D
dapan1121 已提交
1161
  pCtx->jobDoneTs = taosGetTimestampUs();
X
Xiaoyu Wang 已提交
1162

D
dapan1121 已提交
1163 1164
  atomic_store_8((int8_t *)&pCtx->execDone, true);

D
dapan1121 已提交
1165 1166 1167 1168 1169 1170 1171
  if (taosHashGetSize(pCtx->groupHash) == atomic_load_32(&pCtx->groupDoneNum)) {
    if (0 == taosWTryLockLatch(&pCtx->lock)) {
      QRY_ERR_RET(qExplainGenerateRsp(pCtx, pRsp));
      // LEAVE LOCK THERE
    }
  }

D
dapan1121 已提交
1172 1173
  return TSDB_CODE_SUCCESS;
}