explain.c 44.1 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_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 167 168 169 170 171 172 173 174 175
    case QUERY_NODE_PHYSICAL_PLAN_STATE_WINDOW: {
      SStateWinodwPhysiNode* pStateNode = (SStateWinodwPhysiNode*) pNode;
      pPhysiChildren = pStateNode->window.node.pChildren;
      break;
    }
    case QUERY_NODE_PHYSICAL_PLAN_PARTITION: {
      SPartitionPhysiNode* partitionPhysiNode = (SPartitionPhysiNode*) pNode;
      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 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
      // 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) {
          SExplainExecInfo *     execInfo = taosArrayGet(pResNode->pExecInfo, i);
          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));

432
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TIMERANGE_FORMAT, pTblScanNode->scanRange.skey, pTblScanNode->scanRange.ekey);
D
dapan1121 已提交
433 434 435 436 437
        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 已提交
438 439
          QRY_ERR_RET(nodesNodeToSQL(pTblScanNode->scan.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
440 441 442
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
443 444 445
      }
      break;
    }
X
Xiaoyu Wang 已提交
446
    case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN: {
D
dapan1121 已提交
447
      SSystemTableScanPhysiNode *pSTblScanNode = (SSystemTableScanPhysiNode *)pNode;
D
dapan1121 已提交
448 449
      EXPLAIN_ROW_NEW(level, EXPLAIN_SYSTBL_SCAN_FORMAT, pSTblScanNode->scan.tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
450
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
451
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
452
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
453
      }
D
dapan1121 已提交
454 455 456 457
      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 已提交
458
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
459 460
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
461

X
Xiaoyu Wang 已提交
462
      if (verbose) {
D
dapan1121 已提交
463
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
464 465
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pSTblScanNode->scan.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
466 467 468 469 470
        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 已提交
471 472
        if (pSTblScanNode->scan.node.pConditions) {
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
X
Xiaoyu Wang 已提交
473 474
          QRY_ERR_RET(nodesNodeToSQL(pSTblScanNode->scan.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
475 476 477
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
478
      }
D
dapan1121 已提交
479 480
      break;
    }
X
Xiaoyu Wang 已提交
481
    case QUERY_NODE_PHYSICAL_PLAN_PROJECT: {
D
dapan1121 已提交
482
      SProjectPhysiNode *pPrjNode = (SProjectPhysiNode *)pNode;
D
dapan1121 已提交
483 484
      EXPLAIN_ROW_NEW(level, EXPLAIN_PROJECTION_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
485
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
486
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
487
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
488
      }
D
dapan1121 已提交
489 490 491
      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 已提交
492
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
493 494
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
495

D
dapan1121 已提交
496
      if (verbose) {
D
dapan1121 已提交
497
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
498 499
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pPrjNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
500 501 502 503
        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 已提交
504

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

D
dapan1121 已提交
530
      if (verbose) {
D
dapan1121 已提交
531
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
532 533
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pJoinNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
534 535 536 537 538
        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 已提交
539
        if (pJoinNode->node.pConditions) {
X
Xiaoyu Wang 已提交
540 541 542
          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 已提交
543 544 545
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
X
Xiaoyu Wang 已提交
546 547 548 549

        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 已提交
550 551
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
D
dapan1121 已提交
552 553 554
      }
      break;
    }
X
Xiaoyu Wang 已提交
555
    case QUERY_NODE_PHYSICAL_PLAN_AGG: {
D
dapan1121 已提交
556
      SAggPhysiNode *pAggNode = (SAggPhysiNode *)pNode;
D
dapan1121 已提交
557 558
      EXPLAIN_ROW_NEW(level, EXPLAIN_AGG_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
559
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
560
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
561
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
562
      }
D
dapan1121 已提交
563 564 565 566 567 568
      EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pAggNode->pAggFuncs->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      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 已提交
569
      }
X
Xiaoyu Wang 已提交
570
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
571 572
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
573

D
dapan1121 已提交
574
      if (verbose) {
D
dapan1121 已提交
575
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
576 577
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pAggNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
578 579 580 581 582
        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 已提交
583
        if (pAggNode->node.pConditions) {
X
Xiaoyu Wang 已提交
584 585 586
          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 已提交
587 588 589
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
590 591 592
      }
      break;
    }
X
Xiaoyu Wang 已提交
593
    case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: {
D
dapan1121 已提交
594
      SExchangePhysiNode *pExchNode = (SExchangePhysiNode *)pNode;
X
Xiaoyu Wang 已提交
595
      SExplainGroup      *group = taosHashGet(ctx->groupHash, &pExchNode->srcGroupId, sizeof(pExchNode->srcGroupId));
D
dapan1121 已提交
596 597 598 599
      if (NULL == group) {
        qError("exchange src group %d not in groupHash", pExchNode->srcGroupId);
        QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
      }
X
Xiaoyu Wang 已提交
600

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

D
dapan1121 已提交
612
      if (verbose) {
D
dapan1121 已提交
613
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
614 615
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pExchNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
616 617 618 619 620
        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 已提交
621
        if (pExchNode->node.pConditions) {
X
Xiaoyu Wang 已提交
622 623 624
          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 已提交
625 626 627
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
628
      }
D
dapan1121 已提交
629

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

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

650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
      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);
        SSortExecInfo *   pExecInfo = (SSortExecInfo *)execInfo->verboseInfo;
        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 已提交
683
      if (verbose) {
D
dapan1121 已提交
684
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
685 686
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pSortNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
687 688 689 690 691
        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 已提交
692
        if (pSortNode->node.pConditions) {
X
Xiaoyu Wang 已提交
693 694 695
          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 已提交
696 697 698
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
699 700 701
      }
      break;
    }
X
Xiaoyu Wang 已提交
702
    case QUERY_NODE_PHYSICAL_PLAN_INTERVAL: {
D
dapan1121 已提交
703
      SIntervalPhysiNode *pIntNode = (SIntervalPhysiNode *)pNode;
704
      EXPLAIN_ROW_NEW(level, EXPLAIN_INTERVAL_FORMAT, nodesGetNameFromColumnNode(pIntNode->window.pTspk));
D
dapan1121 已提交
705
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
706
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
707
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
708
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
709
      }
D
dapan1121 已提交
710 711 712
      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);
713
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
714 715
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
716

D
dapan1121 已提交
717
      if (verbose) {
D
dapan1121 已提交
718
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
719 720
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pIntNode->window.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
721 722 723 724
        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 已提交
725
        uint8_t precision = getIntervalPrecision(pIntNode);
X
Xiaoyu Wang 已提交
726 727 728 729 730
        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 已提交
731 732
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
D
dapan1121 已提交
733 734

        if (pIntNode->window.node.pConditions) {
X
Xiaoyu Wang 已提交
735 736 737
          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 已提交
738 739 740
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
741 742 743
      }
      break;
    }
X
Xiaoyu Wang 已提交
744
    case QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW: {
D
dapan1121 已提交
745 746 747
      SSessionWinodwPhysiNode *pSessNode = (SSessionWinodwPhysiNode *)pNode;
      EXPLAIN_ROW_NEW(level, EXPLAIN_SESSION_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
748
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
749
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
750
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
751
      }
D
dapan1121 已提交
752 753 754 755
      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 已提交
756 757
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
758

D
dapan1121 已提交
759
      if (verbose) {
D
dapan1121 已提交
760
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
761 762
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pSessNode->window.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
763 764 765 766 767 768 769 770 771 772
        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 已提交
773 774 775
          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 已提交
776 777 778
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
779 780 781
      }
      break;
    }
782 783 784 785 786 787 788 789 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 828 829 830 831
    case QUERY_NODE_PHYSICAL_PLAN_STATE_WINDOW: {
      SStateWinodwPhysiNode *pStateNode = (SStateWinodwPhysiNode *)pNode;

      EXPLAIN_ROW_NEW(level, EXPLAIN_STATE_WINDOW_FORMAT, nodesGetNameFromColumnNode(((STargetNode*)pStateNode->pStateKey)->pExpr));
      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;

      SNode* p = nodesListGetNode(pPartNode->pPartitionKeys, 0);
      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);
832

833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
      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 已提交
856 857 858 859 860 861 862 863
    default:
      qError("not supported physical node type %d", pNode->type);
      return TSDB_CODE_QRY_APP_ERROR;
  }

  return TSDB_CODE_SUCCESS;
}

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

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

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

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
879
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level) {
D
dapan1121 已提交
880
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
881 882
  int32_t          code = 0;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
883

D
dapan1121 已提交
884 885 886 887
  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 已提交
888
  }
X
Xiaoyu Wang 已提交
889

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

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

D
dapan1121 已提交
898
  QRY_ERR_JRET(qExplainResNodeToRows(node, ctx, level));
D
dapan1121 已提交
899 900 901

_return:

D
dapan1121 已提交
902
  qExplainFreeResNode(node);
X
Xiaoyu Wang 已提交
903

D
dapan1121 已提交
904 905 906
  QRY_RET(code);
}

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

D
dapan1121 已提交
915
  int32_t colNum = 1;
X
Xiaoyu Wang 已提交
916 917
  int32_t rspSize = sizeof(SRetrieveTableRsp) + sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum +
                    sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
918 919 920 921 922 923 924
  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 已提交
925
  rsp->numOfRows = htonl(rowNum);
D
dapan1121 已提交
926

927
  // payload length
X
Xiaoyu Wang 已提交
928 929
  *(int32_t *)rsp->data =
      sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum + sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
930

931
  // group id
X
Xiaoyu Wang 已提交
932
  *(uint64_t *)(rsp->data + sizeof(int32_t)) = 0;
933 934

  // column length
X
Xiaoyu Wang 已提交
935
  int32_t *colLength = (int32_t *)(rsp->data + sizeof(int32_t) + sizeof(uint64_t));
936 937 938 939 940

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

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

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

948 949
    varDataCopy(data, row->buf);
    ASSERT(varDataTLen(row->buf) == row->len);
D
dapan1121 已提交
950 951 952
    data += row->len;
  }

953 954
  *colLength = htonl(data - start);
  rsp->compLen = htonl(rspSize);
D
dapan1121 已提交
955

956
  *pRsp = rsp;
D
dapan1121 已提交
957 958 959
  return TSDB_CODE_SUCCESS;
}

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

  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 已提交
978 979
  SHashObj *groupHash =
      taosHashInit(EXPLAIN_MAX_GROUP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
D
dapan1121 已提交
980 981 982 983 984
  if (NULL == groupHash) {
    qError("groupHash %d failed", EXPLAIN_MAX_GROUP_NUM);
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

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

  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 已提交
1010 1011 1012
      SExplainGroup group = {0};
      group.nodeNum = 1;
      group.plan = plan;
X
Xiaoyu Wang 已提交
1013

D
dapan1121 已提交
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
      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 已提交
1026
      ctx->rootGroupId = plan->id.groupId;
D
dapan1121 已提交
1027 1028 1029 1030 1031
    }

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

D
dapan1121 已提交
1032 1033 1034
  *pCtx = ctx;

  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
1035

D
dapan1121 已提交
1036 1037 1038 1039 1040 1041 1042
_return:

  qExplainFreeCtx(ctx);

  QRY_RET(code);
}

D
dapan1121 已提交
1043 1044 1045 1046 1047 1048
int32_t qExplainAppendPlanRows(SExplainCtx *pCtx) {
  if (EXPLAIN_MODE_ANALYZE != pCtx->mode) {
    return TSDB_CODE_SUCCESS;
  }

  int32_t tlen = 0;
X
Xiaoyu Wang 已提交
1049
  char   *tbuf = pCtx->tbuf;
D
dapan1121 已提交
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064

  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 已提交
1065

D
dapan1121 已提交
1066 1067
int32_t qExplainGenerateRsp(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  QRY_ERR_RET(qExplainAppendGroupResRows(pCtx, pCtx->rootGroupId, 0));
D
dapan1121 已提交
1068
  QRY_ERR_RET(qExplainAppendPlanRows(pCtx));
D
dapan1121 已提交
1069 1070 1071 1072 1073
  QRY_ERR_RET(qExplainGetRspFromCtx(pCtx, pRsp));

  return TSDB_CODE_SUCCESS;
}

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

D
dapan1121 已提交
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
  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 已提交
1094

D
dapan1121 已提交
1095 1096 1097 1098 1099
      QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
    }

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

D
dapan1121 已提交
1105 1106 1107 1108
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

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

D
dapan1121 已提交
1114 1115 1116 1117 1118
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

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

D
dapan1121 已提交
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
  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 已提交
1132 1133 1134
}

int32_t qExecStaticExplain(SQueryPlan *pDag, SRetrieveTableRsp **pRsp) {
X
Xiaoyu Wang 已提交
1135
  int32_t      code = 0;
D
dapan1121 已提交
1136 1137 1138
  SExplainCtx *pCtx = NULL;

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

D
dapan1121 已提交
1141
_return:
D
dapan1121 已提交
1142
  qExplainFreeCtx(pCtx);
D
dapan1121 已提交
1143 1144 1145
  QRY_RET(code);
}

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

D
dapan1121 已提交
1149
  (*pCtx)->reqStartTs = startTs;
D
dapan1121 已提交
1150
  (*pCtx)->jobStartTs = taosGetTimestampUs();
D
dapan1121 已提交
1151 1152 1153 1154

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
1155 1156
int32_t qExecExplainEnd(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  int32_t code = 0;
D
dapan1121 已提交
1157
  pCtx->jobDoneTs = taosGetTimestampUs();
X
Xiaoyu Wang 已提交
1158

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

D
dapan1121 已提交
1161 1162 1163 1164 1165 1166 1167
  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 已提交
1168 1169
  return TSDB_CODE_SUCCESS;
}