explain.c 46.5 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;
    }
136
    case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN: {
D
dapan1121 已提交
137 138 139 140
      SJoinPhysiNode *pJoinNode = (SJoinPhysiNode *)pNode;
      pPhysiChildren = pJoinNode->node.pChildren;
      break;
    }
141
    case QUERY_NODE_PHYSICAL_PLAN_HASH_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;
    }
161
    case QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION: {
D
dapan1121 已提交
162 163 164 165
      SSessionWinodwPhysiNode *pSessNode = (SSessionWinodwPhysiNode *)pNode;
      pPhysiChildren = pSessNode->window.node.pChildren;
      break;
    }
166
    case QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE: {
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
    case QUERY_NODE_PHYSICAL_PLAN_MERGE: {
      SMergePhysiNode *mergePhysiNode = (SMergePhysiNode *)pNode;
      pPhysiChildren = mergePhysiNode->node.pChildren;
      break;
    }
D
dapan1121 已提交
181 182 183 184 185 186 187 188 189 190 191 192
    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 已提交
193

X
Xiaoyu Wang 已提交
194
  SNode           *node = NULL;
D
dapan1121 已提交
195 196
  SExplainResNode *pResNode = NULL;
  FOREACH(node, pPhysiChildren) {
D
dapan1121 已提交
197
    QRY_ERR_RET(qExplainGenerateResNode((SPhysiNode *)node, group, &pResNode));
D
dapan1121 已提交
198 199 200 201
    QRY_ERR_RET(nodesListAppend(*pChildren, pResNode));
  }

  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
202 203
}

D
dapan1121 已提交
204 205 206 207 208 209 210
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 已提交
211
  SExplainRsp *rsp = NULL;
D
dapan1121 已提交
212 213 214 215 216 217
  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 已提交
218

D
dapan1121 已提交
219 220 221 222 223 224 225 226 227
    taosArrayPush(*pExecInfo, rsp->subplanInfo + group->physiPlanExecIdx);
  }

  ++group->physiPlanExecIdx;

  return TSDB_CODE_SUCCESS;
}

int32_t qExplainGenerateResNode(SPhysiNode *pNode, SExplainGroup *group, SExplainResNode **pResNode) {
D
dapan1121 已提交
228
  if (NULL == pNode) {
D
dapan1121 已提交
229
    *pResNode = NULL;
D
dapan1121 已提交
230 231 232
    qError("physical node is NULL");
    return TSDB_CODE_QRY_APP_ERROR;
  }
X
Xiaoyu Wang 已提交
233

D
dapan1121 已提交
234 235
  SExplainResNode *resNode = taosMemoryCalloc(1, sizeof(SExplainResNode));
  if (NULL == resNode) {
D
dapan1121 已提交
236 237 238 239 240
    qError("calloc SPhysiNodeExplainRes failed");
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

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

D
dapan1121 已提交
243 244 245
  if (group->nodeExecInfo) {
    QRY_ERR_JRET(qExplainGenerateResNodeExecInfo(&resNode->pExecInfo, group));
  }
X
Xiaoyu Wang 已提交
246

D
dapan1121 已提交
247 248 249
  QRY_ERR_JRET(qExplainGenerateResChildren(pNode, group, &resNode->pChildren));

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

D
dapan1121 已提交
251
  *pResNode = resNode;
D
dapan1121 已提交
252 253 254 255 256

  return TSDB_CODE_SUCCESS;

_return:

D
dapan1121 已提交
257
  qExplainFreeResNode(resNode);
X
Xiaoyu Wang 已提交
258

D
dapan1121 已提交
259 260 261
  QRY_RET(code);
}

D
dapan1121 已提交
262
int32_t qExplainBufAppendExecInfo(SArray *pExecInfo, char *tbuf, int32_t *len) {
X
Xiaoyu Wang 已提交
263 264
  int32_t          tlen = *len;
  int32_t          nodeNum = taosArrayGetSize(pExecInfo);
D
dapan1121 已提交
265
  SExplainExecInfo maxExecInfo = {0};
X
Xiaoyu Wang 已提交
266

D
dapan1121 已提交
267 268 269 270 271 272 273 274 275 276 277 278
  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 已提交
279

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

D
dapan1121 已提交
282
  *len = tlen;
X
Xiaoyu Wang 已提交
283

D
dapan1121 已提交
284
  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
285 286
}

D
dapan1121 已提交
287
int32_t qExplainBufAppendVerboseExecInfo(SArray *pExecInfo, char *tbuf, int32_t *len) {
X
Xiaoyu Wang 已提交
288 289 290
  int32_t          tlen = 0;
  bool             gotVerbose = false;
  int32_t          nodeNum = taosArrayGetSize(pExecInfo);
D
dapan1121 已提交
291
  SExplainExecInfo maxExecInfo = {0};
X
Xiaoyu Wang 已提交
292

D
dapan1121 已提交
293 294 295 296 297 298 299 300 301 302 303 304
  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 已提交
305

D
dapan1121 已提交
306 307 308
  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
309
int32_t qExplainResAppendRow(SExplainCtx *ctx, char *tbuf, int32_t len, int32_t level) {
D
dapan1121 已提交
310
  SQueryExplainRowInfo row = {0};
D
dapan1121 已提交
311
  row.buf = taosMemoryMalloc(len);
D
dapan1121 已提交
312
  if (NULL == row.buf) {
D
dapan1121 已提交
313
    qError("taosMemoryMalloc %d failed", len);
D
dapan1121 已提交
314 315 316
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

D
dapan1121 已提交
317
  memcpy(row.buf, tbuf, len);
D
dapan1121 已提交
318
  row.level = level;
X
Xiaoyu Wang 已提交
319
  row.len = len;
320
  ctx->dataSize += row.len;
D
dapan1121 已提交
321

D
dapan1121 已提交
322
  if (NULL == taosArrayPush(ctx->rows, &row)) {
D
dapan1121 已提交
323 324 325 326 327 328 329 330
    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 已提交
331 332
static uint8_t getIntervalPrecision(SIntervalPhysiNode *pIntNode) {
  return ((SColumnNode *)pIntNode->window.pTspk)->node.resType.precision;
X
Xiaoyu Wang 已提交
333
}
D
dapan1121 已提交
334

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

D
dapan1121 已提交
346 347 348
  switch (pNode->type) {
    case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: {
      STagScanPhysiNode *pTagScanNode = (STagScanPhysiNode *)pNode;
D
dapan1121 已提交
349 350
      EXPLAIN_ROW_NEW(level, EXPLAIN_TAG_SCAN_FORMAT, pTagScanNode->tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
351
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
352
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
353
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
354
      }
D
dapan1121 已提交
355 356 357 358
      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 已提交
359 360
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
361 362

      if (verbose) {
D
dapan1121 已提交
363
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
364 365
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pTagScanNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
366 367 368 369
        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 已提交
370

D
dapan1121 已提交
371 372 373 374 375 376
        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 已提交
377
        }
D
dapan1121 已提交
378
      }
D
dapan1121 已提交
379
      break;
D
dapan1121 已提交
380 381
    }
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
X
Xiaoyu Wang 已提交
382
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: {
D
dapan1121 已提交
383
      STableScanPhysiNode *pTblScanNode = (STableScanPhysiNode *)pNode;
D
dapan1121 已提交
384 385
      EXPLAIN_ROW_NEW(level, EXPLAIN_TBL_SCAN_FORMAT, pTblScanNode->scan.tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
386
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
387
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
388
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
389
      }
D
dapan1121 已提交
390 391 392 393
      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);
394
      EXPLAIN_ROW_APPEND(EXPLAIN_TABLE_SCAN_FORMAT, pTblScanNode->scanSeq[0], pTblScanNode->scanSeq[1]);
X
Xiaoyu Wang 已提交
395
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
396 397
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
398

399 400 401 402 403 404
      // 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 已提交
405
          SExplainExecInfo      *execInfo = taosArrayGet(pResNode->pExecInfo, i);
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
          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 已提交
428
      if (verbose) {
D
dapan1121 已提交
429
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
430 431
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pTblScanNode->scan.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
432 433 434 435 436
        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 已提交
437 438
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TIMERANGE_FORMAT, pTblScanNode->scanRange.skey,
                        pTblScanNode->scanRange.ekey);
D
dapan1121 已提交
439 440 441 442 443
        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 已提交
444 445
          QRY_ERR_RET(nodesNodeToSQL(pTblScanNode->scan.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
D
dapan1121 已提交
446 447 448
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
449 450 451
      }
      break;
    }
X
Xiaoyu Wang 已提交
452
    case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN: {
D
dapan1121 已提交
453
      SSystemTableScanPhysiNode *pSTblScanNode = (SSystemTableScanPhysiNode *)pNode;
D
dapan1121 已提交
454 455
      EXPLAIN_ROW_NEW(level, EXPLAIN_SYSTBL_SCAN_FORMAT, pSTblScanNode->scan.tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
456
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
457
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
458
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
459
      }
D
dapan1121 已提交
460 461 462 463
      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 已提交
464
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
465 466
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
467

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

D
dapan1121 已提交
502
      if (verbose) {
D
dapan1121 已提交
503
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
504 505
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pPrjNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
506 507 508 509
        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 已提交
510

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

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

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

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

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

D
dapan1121 已提交
620
      if (verbose) {
D
dapan1121 已提交
621
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
622 623
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pExchNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
624 625 626 627 628
        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 已提交
629
        if (pExchNode->node.pConditions) {
X
Xiaoyu Wang 已提交
630 631 632
          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 已提交
633 634 635
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
636
      }
D
dapan1121 已提交
637

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

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

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

D
dapan1121 已提交
725
      if (verbose) {
D
dapan1121 已提交
726
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
727 728
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pIntNode->window.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
729 730 731 732
        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 已提交
733
        uint8_t precision = getIntervalPrecision(pIntNode);
X
Xiaoyu Wang 已提交
734 735 736 737 738
        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 已提交
739 740
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
D
dapan1121 已提交
741 742

        if (pIntNode->window.node.pConditions) {
X
Xiaoyu Wang 已提交
743 744 745
          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 已提交
746 747 748
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
749 750 751
      }
      break;
    }
752
    case QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION: {
D
dapan1121 已提交
753 754 755
      SSessionWinodwPhysiNode *pSessNode = (SSessionWinodwPhysiNode *)pNode;
      EXPLAIN_ROW_NEW(level, EXPLAIN_SESSION_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
756
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
757
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
758
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
759
      }
D
dapan1121 已提交
760 761 762 763
      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 已提交
764 765
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
766

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

X
Xiaoyu Wang 已提交
793 794
      EXPLAIN_ROW_NEW(level, EXPLAIN_STATE_WINDOW_FORMAT,
                      nodesGetNameFromColumnNode(((STargetNode *)pStateNode->pStateKey)->pExpr));
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 832
      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 已提交
833
      SNode *p = nodesListGetNode(pPartNode->pPartitionKeys, 0);
834 835 836 837 838 839 840
      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);
841

842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
      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 已提交
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908
    case QUERY_NODE_PHYSICAL_PLAN_MERGE: {
      SMergePhysiNode *pMergeNode = (SMergePhysiNode *)pNode;
      EXPLAIN_ROW_NEW(level, EXPLAIN_MERGE_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
      if (pResNode->pExecInfo) {
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      }

      SDataBlockDescNode *pDescNode = pMergeNode->node.pOutputDataBlockDesc;
      EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, nodesGetOutputNumFromSlotList(pDescNode->pSlots));
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pDescNode->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(pMergeNode->node.pOutputDataBlockDesc->pSlots));
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
        EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pMergeNode->node.pOutputDataBlockDesc->outputRowSize);
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_MERGE_KEYS_FORMAT);
        for (int32_t i = 0; i < LIST_LENGTH(pMergeNode->pMergeKeys); ++i) {
          SOrderByExprNode *ptn = nodesListGetNode(pMergeNode->pMergeKeys, i);
          EXPLAIN_ROW_APPEND("%s ", nodesGetNameFromColumnNode(ptn->pExpr));
        }
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));

        if (pMergeNode->node.pConditions) {
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pMergeNode->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 已提交
909 910 911 912 913 914 915 916
    default:
      qError("not supported physical node type %d", pNode->type);
      return TSDB_CODE_QRY_APP_ERROR;
  }

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
917
int32_t qExplainResNodeToRows(SExplainResNode *pResNode, SExplainCtx *ctx, int32_t level) {
D
dapan1121 已提交
918 919 920 921 922 923
  if (NULL == pResNode) {
    qError("explain res node is NULL");
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

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

X
Xiaoyu Wang 已提交
926 927
  SNode *pNode = NULL;
  FOREACH(pNode, pResNode->pChildren) { QRY_ERR_RET(qExplainResNodeToRows((SExplainResNode *)pNode, ctx, level + 1)); }
D
dapan1121 已提交
928 929 930 931

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
932
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level) {
D
dapan1121 已提交
933
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
934 935
  int32_t          code = 0;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
936

D
dapan1121 已提交
937 938 939 940
  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 已提交
941
  }
X
Xiaoyu Wang 已提交
942

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

D
dapan1121 已提交
945
  if ((EXPLAIN_MODE_ANALYZE == ctx->mode) && (group->physiPlanNum != group->physiPlanExecNum)) {
X
Xiaoyu Wang 已提交
946 947
    qError("physiPlanNum %d mismatch with physiExecNum %d in group %d", group->physiPlanNum, group->physiPlanExecNum,
           groupId);
D
dapan1121 已提交
948 949
    QRY_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
  }
D
dapan1121 已提交
950

D
dapan1121 已提交
951
  QRY_ERR_JRET(qExplainResNodeToRows(node, ctx, level));
D
dapan1121 已提交
952 953 954

_return:

D
dapan1121 已提交
955
  qExplainFreeResNode(node);
X
Xiaoyu Wang 已提交
956

D
dapan1121 已提交
957 958 959
  QRY_RET(code);
}

D
dapan1121 已提交
960
int32_t qExplainGetRspFromCtx(void *ctx, SRetrieveTableRsp **pRsp) {
D
dapan1121 已提交
961
  SExplainCtx *pCtx = (SExplainCtx *)ctx;
X
Xiaoyu Wang 已提交
962
  int32_t      rowNum = taosArrayGetSize(pCtx->rows);
D
dapan1121 已提交
963 964 965 966
  if (rowNum <= 0) {
    qError("empty explain res rows");
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }
X
Xiaoyu Wang 已提交
967

D
dapan1121 已提交
968
  int32_t colNum = 1;
X
Xiaoyu Wang 已提交
969 970
  int32_t rspSize = sizeof(SRetrieveTableRsp) + sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum +
                    sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
971 972 973 974 975 976 977
  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 已提交
978
  rsp->numOfRows = htonl(rowNum);
D
dapan1121 已提交
979

980
  // payload length
X
Xiaoyu Wang 已提交
981 982
  *(int32_t *)rsp->data =
      sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum + sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
983

984
  // group id
X
Xiaoyu Wang 已提交
985
  *(uint64_t *)(rsp->data + sizeof(int32_t)) = 0;
986 987

  // column length
X
Xiaoyu Wang 已提交
988
  int32_t *colLength = (int32_t *)(rsp->data + sizeof(int32_t) + sizeof(uint64_t));
989 990 991 992 993

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

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

X
Xiaoyu Wang 已提交
996
  char *start = data;
D
dapan1121 已提交
997 998
  for (int32_t i = 0; i < rowNum; ++i) {
    SQueryExplainRowInfo *row = taosArrayGet(pCtx->rows, i);
999
    offset[i] = data - start;
D
dapan1121 已提交
1000

1001 1002
    varDataCopy(data, row->buf);
    ASSERT(varDataTLen(row->buf) == row->len);
D
dapan1121 已提交
1003 1004 1005
    data += row->len;
  }

1006 1007
  *colLength = htonl(data - start);
  rsp->compLen = htonl(rspSize);
D
dapan1121 已提交
1008

1009
  *pRsp = rsp;
D
dapan1121 已提交
1010 1011 1012
  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
1013
int32_t qExplainPrepareCtx(SQueryPlan *pDag, SExplainCtx **pCtx) {
X
Xiaoyu Wang 已提交
1014
  int32_t        code = 0;
D
dapan1121 已提交
1015 1016 1017
  SNodeListNode *plans = NULL;
  int32_t        taskNum = 0;
  SExplainGroup *pGroup = NULL;
X
Xiaoyu Wang 已提交
1018
  SExplainCtx   *ctx = NULL;
D
dapan1121 已提交
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030

  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 已提交
1031 1032
  SHashObj *groupHash =
      taosHashInit(EXPLAIN_MAX_GROUP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
D
dapan1121 已提交
1033 1034 1035 1036 1037
  if (NULL == groupHash) {
    qError("groupHash %d failed", EXPLAIN_MAX_GROUP_NUM);
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

X
Xiaoyu Wang 已提交
1038 1039
  QRY_ERR_JRET(
      qExplainInitCtx(&ctx, groupHash, pDag->explainInfo.verbose, pDag->explainInfo.ratio, pDag->explainInfo.mode));
D
dapan1121 已提交
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062

  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 已提交
1063 1064 1065
      SExplainGroup group = {0};
      group.nodeNum = 1;
      group.plan = plan;
X
Xiaoyu Wang 已提交
1066

D
dapan1121 已提交
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
      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 已提交
1079
      ctx->rootGroupId = plan->id.groupId;
D
dapan1121 已提交
1080 1081 1082 1083 1084
    }

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

D
dapan1121 已提交
1085 1086 1087
  *pCtx = ctx;

  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
1088

D
dapan1121 已提交
1089 1090 1091 1092 1093 1094 1095
_return:

  qExplainFreeCtx(ctx);

  QRY_RET(code);
}

D
dapan1121 已提交
1096 1097 1098 1099 1100 1101
int32_t qExplainAppendPlanRows(SExplainCtx *pCtx) {
  if (EXPLAIN_MODE_ANALYZE != pCtx->mode) {
    return TSDB_CODE_SUCCESS;
  }

  int32_t tlen = 0;
X
Xiaoyu Wang 已提交
1102
  char   *tbuf = pCtx->tbuf;
D
dapan1121 已提交
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117

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

D
dapan1121 已提交
1119 1120
int32_t qExplainGenerateRsp(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  QRY_ERR_RET(qExplainAppendGroupResRows(pCtx, pCtx->rootGroupId, 0));
D
dapan1121 已提交
1121
  QRY_ERR_RET(qExplainAppendPlanRows(pCtx));
D
dapan1121 已提交
1122 1123 1124 1125 1126
  QRY_ERR_RET(qExplainGetRspFromCtx(pCtx, pRsp));

  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
1127
int32_t qExplainUpdateExecInfo(SExplainCtx *pCtx, SExplainRsp *pRspMsg, int32_t groupId, SRetrieveTableRsp **pRsp) {
D
dapan1121 已提交
1128
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
1129 1130 1131
  int32_t          code = 0;
  bool             groupDone = false;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
1132

D
dapan1121 已提交
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
  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 已提交
1147

D
dapan1121 已提交
1148 1149 1150 1151 1152
      QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
    }

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

D
dapan1121 已提交
1158 1159 1160 1161
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

  if (group->physiPlanExecNum != pRspMsg->numOfPlans) {
X
Xiaoyu Wang 已提交
1162 1163
    qError("physiPlanExecNum %d mismatch with others %d in group %d", pRspMsg->numOfPlans, group->physiPlanExecNum,
           groupId);
D
dapan1121 已提交
1164 1165
    taosMemoryFreeClear(pRspMsg->subplanInfo);
    taosWUnLockLatch(&group->lock);
X
Xiaoyu Wang 已提交
1166

D
dapan1121 已提交
1167 1168 1169 1170 1171
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

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

D
dapan1121 已提交
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
  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 已提交
1185 1186 1187
}

int32_t qExecStaticExplain(SQueryPlan *pDag, SRetrieveTableRsp **pRsp) {
X
Xiaoyu Wang 已提交
1188
  int32_t      code = 0;
D
dapan1121 已提交
1189 1190 1191
  SExplainCtx *pCtx = NULL;

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

D
dapan1121 已提交
1194
_return:
D
dapan1121 已提交
1195
  qExplainFreeCtx(pCtx);
D
dapan1121 已提交
1196 1197 1198
  QRY_RET(code);
}

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

D
dapan1121 已提交
1202
  (*pCtx)->reqStartTs = startTs;
D
dapan1121 已提交
1203
  (*pCtx)->jobStartTs = taosGetTimestampUs();
D
dapan1121 已提交
1204 1205 1206 1207

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
1208 1209
int32_t qExecExplainEnd(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  int32_t code = 0;
D
dapan1121 已提交
1210
  pCtx->jobDoneTs = taosGetTimestampUs();
X
Xiaoyu Wang 已提交
1211

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

D
dapan1121 已提交
1214 1215 1216 1217 1218 1219 1220
  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 已提交
1221 1222
  return TSDB_CODE_SUCCESS;
}