explain.c 38.8 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"
D
dapan1121 已提交
19

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

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

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

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

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

D
dapan1121 已提交
37 38
void qExplainFreeCtx(SExplainCtx *pCtx) {
  if (NULL == pCtx) {
D
dapan1121 已提交
39 40 41 42 43 44 45 46 47
    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 已提交
48 49 50 51
  if (EXPLAIN_MODE_ANALYZE == pCtx->mode && pCtx->groupHash) {
    void *pIter = taosHashIterate(pCtx->groupHash, NULL);
    while (pIter) {
      SExplainGroup *group = (SExplainGroup *)pIter;
D
dapan1121 已提交
52 53 54 55 56 57
      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 已提交
58
      }
X
Xiaoyu Wang 已提交
59

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

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

D
dapan1121 已提交
69
int32_t qExplainInitCtx(SExplainCtx **pCtx, SHashObj *groupHash, bool verbose, double ratio, EExplainMode mode) {
X
Xiaoyu Wang 已提交
70
  int32_t      code = 0;
D
dapan1121 已提交
71 72 73 74 75
  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 已提交
76

D
dapan1121 已提交
77 78 79 80 81 82 83 84 85 86 87 88
  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 已提交
89
  ctx->mode = mode;
D
dapan1121 已提交
90
  ctx->verbose = verbose;
D
dapan1121 已提交
91
  ctx->ratio = ratio;
D
dapan1121 已提交
92 93 94
  ctx->tbuf = tbuf;
  ctx->rows = rows;
  ctx->groupHash = groupHash;
X
Xiaoyu Wang 已提交
95

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

  return TSDB_CODE_SUCCESS;

_return:

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

  QRY_RET(code);
}

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

D
dapan1121 已提交
113 114 115 116 117 118 119
  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 已提交
120
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: {
D
dapan1121 已提交
121 122 123 124
      STableScanPhysiNode *pTblScanNode = (STableScanPhysiNode *)pNode;
      pPhysiChildren = pTblScanNode->scan.node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
125
    case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN: {
D
dapan1121 已提交
126 127 128 129
      SSystemTableScanPhysiNode *pSTblScanNode = (SSystemTableScanPhysiNode *)pNode;
      pPhysiChildren = pSTblScanNode->scan.node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
130
    case QUERY_NODE_PHYSICAL_PLAN_PROJECT: {
D
dapan1121 已提交
131 132 133 134
      SProjectPhysiNode *pPrjNode = (SProjectPhysiNode *)pNode;
      pPhysiChildren = pPrjNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
135
    case QUERY_NODE_PHYSICAL_PLAN_JOIN: {
D
dapan1121 已提交
136 137 138 139
      SJoinPhysiNode *pJoinNode = (SJoinPhysiNode *)pNode;
      pPhysiChildren = pJoinNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
140
    case QUERY_NODE_PHYSICAL_PLAN_AGG: {
D
dapan1121 已提交
141 142 143 144
      SAggPhysiNode *pAggNode = (SAggPhysiNode *)pNode;
      pPhysiChildren = pAggNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
145
    case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: {
D
dapan1121 已提交
146 147 148 149
      SExchangePhysiNode *pExchNode = (SExchangePhysiNode *)pNode;
      pPhysiChildren = pExchNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
150
    case QUERY_NODE_PHYSICAL_PLAN_SORT: {
D
dapan1121 已提交
151 152 153 154
      SSortPhysiNode *pSortNode = (SSortPhysiNode *)pNode;
      pPhysiChildren = pSortNode->node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
155
    case QUERY_NODE_PHYSICAL_PLAN_INTERVAL: {
D
dapan1121 已提交
156 157 158 159
      SIntervalPhysiNode *pIntNode = (SIntervalPhysiNode *)pNode;
      pPhysiChildren = pIntNode->window.node.pChildren;
      break;
    }
X
Xiaoyu Wang 已提交
160
    case QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW: {
D
dapan1121 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
      SSessionWinodwPhysiNode *pSessNode = (SSessionWinodwPhysiNode *)pNode;
      pPhysiChildren = pSessNode->window.node.pChildren;
      break;
    }
    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 已提交
177

X
Xiaoyu Wang 已提交
178
  SNode           *node = NULL;
D
dapan1121 已提交
179 180
  SExplainResNode *pResNode = NULL;
  FOREACH(node, pPhysiChildren) {
D
dapan1121 已提交
181
    QRY_ERR_RET(qExplainGenerateResNode((SPhysiNode *)node, group, &pResNode));
D
dapan1121 已提交
182 183 184 185
    QRY_ERR_RET(nodesListAppend(*pChildren, pResNode));
  }

  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
186 187
}

D
dapan1121 已提交
188 189 190 191 192 193 194
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 已提交
195
  SExplainRsp *rsp = NULL;
D
dapan1121 已提交
196 197 198 199 200 201
  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 已提交
202

D
dapan1121 已提交
203 204 205 206 207 208 209 210 211
    taosArrayPush(*pExecInfo, rsp->subplanInfo + group->physiPlanExecIdx);
  }

  ++group->physiPlanExecIdx;

  return TSDB_CODE_SUCCESS;
}

int32_t qExplainGenerateResNode(SPhysiNode *pNode, SExplainGroup *group, SExplainResNode **pResNode) {
D
dapan1121 已提交
212
  if (NULL == pNode) {
D
dapan1121 已提交
213
    *pResNode = NULL;
D
dapan1121 已提交
214 215 216
    qError("physical node is NULL");
    return TSDB_CODE_QRY_APP_ERROR;
  }
X
Xiaoyu Wang 已提交
217

D
dapan1121 已提交
218 219
  SExplainResNode *resNode = taosMemoryCalloc(1, sizeof(SExplainResNode));
  if (NULL == resNode) {
D
dapan1121 已提交
220 221 222 223 224
    qError("calloc SPhysiNodeExplainRes failed");
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

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

D
dapan1121 已提交
227 228 229
  if (group->nodeExecInfo) {
    QRY_ERR_JRET(qExplainGenerateResNodeExecInfo(&resNode->pExecInfo, group));
  }
X
Xiaoyu Wang 已提交
230

D
dapan1121 已提交
231 232 233
  QRY_ERR_JRET(qExplainGenerateResChildren(pNode, group, &resNode->pChildren));

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

D
dapan1121 已提交
235
  *pResNode = resNode;
D
dapan1121 已提交
236 237 238 239 240

  return TSDB_CODE_SUCCESS;

_return:

D
dapan1121 已提交
241
  qExplainFreeResNode(resNode);
X
Xiaoyu Wang 已提交
242

D
dapan1121 已提交
243 244 245
  QRY_RET(code);
}

D
dapan1121 已提交
246
int32_t qExplainBufAppendExecInfo(SArray *pExecInfo, char *tbuf, int32_t *len) {
X
Xiaoyu Wang 已提交
247 248
  int32_t          tlen = *len;
  int32_t          nodeNum = taosArrayGetSize(pExecInfo);
D
dapan1121 已提交
249
  SExplainExecInfo maxExecInfo = {0};
X
Xiaoyu Wang 已提交
250

D
dapan1121 已提交
251 252 253 254 255 256 257 258 259 260 261 262
  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 已提交
263

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

D
dapan1121 已提交
266
  *len = tlen;
X
Xiaoyu Wang 已提交
267

D
dapan1121 已提交
268
  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
269 270
}

D
dapan1121 已提交
271
int32_t qExplainBufAppendVerboseExecInfo(SArray *pExecInfo, char *tbuf, int32_t *len) {
X
Xiaoyu Wang 已提交
272 273 274
  int32_t          tlen = 0;
  bool             gotVerbose = false;
  int32_t          nodeNum = taosArrayGetSize(pExecInfo);
D
dapan1121 已提交
275
  SExplainExecInfo maxExecInfo = {0};
X
Xiaoyu Wang 已提交
276

D
dapan1121 已提交
277 278 279 280 281 282 283 284 285 286 287 288
  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 已提交
289

D
dapan1121 已提交
290 291 292
  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
293
int32_t qExplainResAppendRow(SExplainCtx *ctx, char *tbuf, int32_t len, int32_t level) {
D
dapan1121 已提交
294
  SQueryExplainRowInfo row = {0};
D
dapan1121 已提交
295
  row.buf = taosMemoryMalloc(len);
D
dapan1121 已提交
296
  if (NULL == row.buf) {
D
dapan1121 已提交
297
    qError("taosMemoryMalloc %d failed", len);
D
dapan1121 已提交
298 299 300
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

D
dapan1121 已提交
301
  memcpy(row.buf, tbuf, len);
D
dapan1121 已提交
302
  row.level = level;
X
Xiaoyu Wang 已提交
303
  row.len = len;
304
  ctx->dataSize += row.len;
D
dapan1121 已提交
305

D
dapan1121 已提交
306
  if (NULL == taosArrayPush(ctx->rows, &row)) {
D
dapan1121 已提交
307 308 309 310 311 312 313 314
    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 已提交
315 316
static uint8_t getIntervalPrecision(SIntervalPhysiNode *pIntNode) {
  return ((SColumnNode *)pIntNode->window.pTspk)->node.resType.precision;
X
Xiaoyu Wang 已提交
317
}
D
dapan1121 已提交
318

D
dapan1121 已提交
319
int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, int32_t level) {
X
Xiaoyu Wang 已提交
320 321 322 323 324
  int32_t     tlen = 0;
  bool        isVerboseLine = false;
  char       *tbuf = ctx->tbuf;
  bool        verbose = ctx->verbose;
  SPhysiNode *pNode = pResNode->pNode;
D
dapan1121 已提交
325 326 327 328
  if (NULL == pNode) {
    qError("pyhsical node in explain res node is NULL");
    return TSDB_CODE_QRY_APP_ERROR;
  }
X
Xiaoyu Wang 已提交
329

D
dapan1121 已提交
330 331 332
  switch (pNode->type) {
    case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: {
      STagScanPhysiNode *pTagScanNode = (STagScanPhysiNode *)pNode;
D
dapan1121 已提交
333 334
      EXPLAIN_ROW_NEW(level, EXPLAIN_TAG_SCAN_FORMAT, pTagScanNode->tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
335
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
336
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
337
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
338
      }
D
dapan1121 已提交
339 340 341 342 343
      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_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
344 345
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
346 347

      if (verbose) {
D
dapan1121 已提交
348
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
349 350
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pTagScanNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
351 352 353 354
        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 已提交
355

D
dapan1121 已提交
356 357 358 359 360 361
        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 已提交
362
        }
D
dapan1121 已提交
363
      }
D
dapan1121 已提交
364
      break;
D
dapan1121 已提交
365 366
    }
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
X
Xiaoyu Wang 已提交
367
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: {
D
dapan1121 已提交
368
      STableScanPhysiNode *pTblScanNode = (STableScanPhysiNode *)pNode;
D
dapan1121 已提交
369 370
      EXPLAIN_ROW_NEW(level, EXPLAIN_TBL_SCAN_FORMAT, pTblScanNode->scan.tableName.tname);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
371
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
372
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
373
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
374
      }
D
dapan1121 已提交
375 376 377 378
      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);
379
      EXPLAIN_ROW_APPEND(EXPLAIN_TABLE_SCAN_FORMAT, pTblScanNode->scanSeq[0], pTblScanNode->scanSeq[1]);
X
Xiaoyu Wang 已提交
380
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
381 382
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
383

384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
      // 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 已提交
413
      if (verbose) {
D
dapan1121 已提交
414
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
415 416
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pTblScanNode->scan.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
417 418 419 420 421
        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));

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

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

D
dapan1121 已提交
486
      if (verbose) {
D
dapan1121 已提交
487
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
488 489
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pPrjNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
490 491 492 493
        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 已提交
494

D
dapan1121 已提交
495
        if (pPrjNode->node.pConditions) {
X
Xiaoyu Wang 已提交
496 497 498
          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 已提交
499 500 501
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
502 503 504
      }
      break;
    }
X
Xiaoyu Wang 已提交
505
    case QUERY_NODE_PHYSICAL_PLAN_JOIN: {
D
dapan1121 已提交
506
      SJoinPhysiNode *pJoinNode = (SJoinPhysiNode *)pNode;
D
dapan1121 已提交
507 508
      EXPLAIN_ROW_NEW(level, EXPLAIN_JOIN_FORMAT, EXPLAIN_JOIN_STRING(pJoinNode->joinType));
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
509
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
510
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
511
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
512
      }
D
dapan1121 已提交
513 514 515
      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 已提交
516
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
517 518
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
519

D
dapan1121 已提交
520
      if (verbose) {
D
dapan1121 已提交
521
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
522 523
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pJoinNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
524 525 526 527 528
        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 已提交
529
        if (pJoinNode->node.pConditions) {
X
Xiaoyu Wang 已提交
530 531 532
          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 已提交
533 534 535
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
X
Xiaoyu Wang 已提交
536 537 538 539

        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 已提交
540 541
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
D
dapan1121 已提交
542 543 544
      }
      break;
    }
X
Xiaoyu Wang 已提交
545
    case QUERY_NODE_PHYSICAL_PLAN_AGG: {
D
dapan1121 已提交
546
      SAggPhysiNode *pAggNode = (SAggPhysiNode *)pNode;
D
dapan1121 已提交
547 548
      EXPLAIN_ROW_NEW(level, EXPLAIN_AGG_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
549
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
550
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
551
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
552
      }
D
dapan1121 已提交
553 554 555 556 557 558
      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 已提交
559
      }
X
Xiaoyu Wang 已提交
560
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
561 562
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
563

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

D
dapan1121 已提交
591 592
      EXPLAIN_ROW_NEW(level, EXPLAIN_EXCHANGE_FORMAT, group->nodeNum);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
593
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
594
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
595
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
596
      }
D
dapan1121 已提交
597
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pExchNode->node.pOutputDataBlockDesc->totalRowSize);
X
Xiaoyu Wang 已提交
598
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
599 600
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
601

D
dapan1121 已提交
602
      if (verbose) {
D
dapan1121 已提交
603
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
604 605
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pExchNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
606 607 608 609 610
        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 已提交
611
        if (pExchNode->node.pConditions) {
X
Xiaoyu Wang 已提交
612 613 614
          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 已提交
615 616 617
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
618
      }
D
dapan1121 已提交
619

D
dapan1121 已提交
620
      QRY_ERR_RET(qExplainAppendGroupResRows(ctx, pExchNode->srcGroupId, level + 1));
D
dapan1121 已提交
621 622
      break;
    }
X
Xiaoyu Wang 已提交
623
    case QUERY_NODE_PHYSICAL_PLAN_SORT: {
D
dapan1121 已提交
624
      SSortPhysiNode *pSortNode = (SSortPhysiNode *)pNode;
D
dapan1121 已提交
625 626
      EXPLAIN_ROW_NEW(level, EXPLAIN_SORT_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
627
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
628
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
629
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
630
      }
D
dapan1121 已提交
631 632 633 634
      EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pSortNode->pSortKeys->length);
      EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pSortNode->node.pOutputDataBlockDesc->totalRowSize);
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
635 636
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
637

D
dapan1121 已提交
638
      if (verbose) {
D
dapan1121 已提交
639
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
640 641
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pSortNode->node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
642 643 644 645 646
        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 已提交
647
        if (pSortNode->node.pConditions) {
X
Xiaoyu Wang 已提交
648 649 650
          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 已提交
651 652 653
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
654 655 656
      }
      break;
    }
X
Xiaoyu Wang 已提交
657
    case QUERY_NODE_PHYSICAL_PLAN_INTERVAL: {
D
dapan1121 已提交
658
      SIntervalPhysiNode *pIntNode = (SIntervalPhysiNode *)pNode;
659
      EXPLAIN_ROW_NEW(level, EXPLAIN_INTERVAL_FORMAT, nodesGetNameFromColumnNode(pIntNode->window.pTspk));
D
dapan1121 已提交
660
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
661
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
662
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
663
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
664
      }
D
dapan1121 已提交
665 666 667
      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);
668
      EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
669 670
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
671

D
dapan1121 已提交
672
      if (verbose) {
D
dapan1121 已提交
673
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
674 675
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pIntNode->window.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
676 677 678 679
        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 已提交
680
        uint8_t precision = getIntervalPrecision(pIntNode);
X
Xiaoyu Wang 已提交
681 682 683 684 685
        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 已提交
686 687
        EXPLAIN_ROW_END();
        QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
D
dapan1121 已提交
688 689

        if (pIntNode->window.node.pConditions) {
X
Xiaoyu Wang 已提交
690 691 692
          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 已提交
693 694 695
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
696 697 698
      }
      break;
    }
X
Xiaoyu Wang 已提交
699
    case QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW: {
D
dapan1121 已提交
700 701 702
      SSessionWinodwPhysiNode *pSessNode = (SSessionWinodwPhysiNode *)pNode;
      EXPLAIN_ROW_NEW(level, EXPLAIN_SESSION_FORMAT);
      EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
D
dapan1121 已提交
703
      if (pResNode->pExecInfo) {
D
dapan1121 已提交
704
        QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
D
dapan1121 已提交
705
        EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
X
Xiaoyu Wang 已提交
706
      }
D
dapan1121 已提交
707 708 709 710
      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 已提交
711 712
      EXPLAIN_ROW_END();
      QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
D
dapan1121 已提交
713

D
dapan1121 已提交
714
      if (verbose) {
D
dapan1121 已提交
715
        EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
X
Xiaoyu Wang 已提交
716 717
        EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
                           nodesGetOutputNumFromSlotList(pSessNode->window.node.pOutputDataBlockDesc->pSlots));
D
dapan1121 已提交
718 719 720 721 722 723 724 725 726 727
        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 已提交
728 729 730
          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 已提交
731 732 733
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
D
dapan1121 已提交
734 735 736
      }
      break;
    }
D
dapan1121 已提交
737 738 739 740 741 742 743 744
    default:
      qError("not supported physical node type %d", pNode->type);
      return TSDB_CODE_QRY_APP_ERROR;
  }

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
745
int32_t qExplainResNodeToRows(SExplainResNode *pResNode, SExplainCtx *ctx, int32_t level) {
D
dapan1121 已提交
746 747 748 749 750 751
  if (NULL == pResNode) {
    qError("explain res node is NULL");
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

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

X
Xiaoyu Wang 已提交
754 755
  SNode *pNode = NULL;
  FOREACH(pNode, pResNode->pChildren) { QRY_ERR_RET(qExplainResNodeToRows((SExplainResNode *)pNode, ctx, level + 1)); }
D
dapan1121 已提交
756 757 758 759

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
760
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level) {
D
dapan1121 已提交
761
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
762 763
  int32_t          code = 0;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
764

D
dapan1121 已提交
765 766 767 768
  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 已提交
769
  }
X
Xiaoyu Wang 已提交
770

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

D
dapan1121 已提交
773
  if ((EXPLAIN_MODE_ANALYZE == ctx->mode) && (group->physiPlanNum != group->physiPlanExecNum)) {
X
Xiaoyu Wang 已提交
774 775
    qError("physiPlanNum %d mismatch with physiExecNum %d in group %d", group->physiPlanNum, group->physiPlanExecNum,
           groupId);
D
dapan1121 已提交
776 777
    QRY_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
  }
D
dapan1121 已提交
778

D
dapan1121 已提交
779
  QRY_ERR_JRET(qExplainResNodeToRows(node, ctx, level));
D
dapan1121 已提交
780 781 782

_return:

D
dapan1121 已提交
783
  qExplainFreeResNode(node);
X
Xiaoyu Wang 已提交
784

D
dapan1121 已提交
785 786 787
  QRY_RET(code);
}

D
dapan1121 已提交
788
int32_t qExplainGetRspFromCtx(void *ctx, SRetrieveTableRsp **pRsp) {
D
dapan1121 已提交
789
  SExplainCtx *pCtx = (SExplainCtx *)ctx;
X
Xiaoyu Wang 已提交
790
  int32_t      rowNum = taosArrayGetSize(pCtx->rows);
D
dapan1121 已提交
791 792 793 794
  if (rowNum <= 0) {
    qError("empty explain res rows");
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }
X
Xiaoyu Wang 已提交
795

D
dapan1121 已提交
796
  int32_t colNum = 1;
X
Xiaoyu Wang 已提交
797 798
  int32_t rspSize = sizeof(SRetrieveTableRsp) + sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum +
                    sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
799 800 801 802 803 804 805
  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 已提交
806
  rsp->numOfRows = htonl(rowNum);
D
dapan1121 已提交
807

808
  // payload length
X
Xiaoyu Wang 已提交
809 810
  *(int32_t *)rsp->data =
      sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum + sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
811

812
  // group id
X
Xiaoyu Wang 已提交
813
  *(uint64_t *)(rsp->data + sizeof(int32_t)) = 0;
814 815

  // column length
X
Xiaoyu Wang 已提交
816
  int32_t *colLength = (int32_t *)(rsp->data + sizeof(int32_t) + sizeof(uint64_t));
817 818 819 820 821

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

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

X
Xiaoyu Wang 已提交
824
  char *start = data;
D
dapan1121 已提交
825 826
  for (int32_t i = 0; i < rowNum; ++i) {
    SQueryExplainRowInfo *row = taosArrayGet(pCtx->rows, i);
827
    offset[i] = data - start;
D
dapan1121 已提交
828

829 830
    varDataCopy(data, row->buf);
    ASSERT(varDataTLen(row->buf) == row->len);
D
dapan1121 已提交
831 832 833
    data += row->len;
  }

834 835
  *colLength = htonl(data - start);
  rsp->compLen = htonl(rspSize);
D
dapan1121 已提交
836

837
  *pRsp = rsp;
D
dapan1121 已提交
838 839 840
  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
841
int32_t qExplainPrepareCtx(SQueryPlan *pDag, SExplainCtx **pCtx) {
X
Xiaoyu Wang 已提交
842
  int32_t        code = 0;
D
dapan1121 已提交
843 844 845
  SNodeListNode *plans = NULL;
  int32_t        taskNum = 0;
  SExplainGroup *pGroup = NULL;
X
Xiaoyu Wang 已提交
846
  SExplainCtx   *ctx = NULL;
D
dapan1121 已提交
847 848 849 850 851 852 853 854 855 856 857 858

  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 已提交
859 860
  SHashObj *groupHash =
      taosHashInit(EXPLAIN_MAX_GROUP_NUM, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
D
dapan1121 已提交
861 862 863 864 865
  if (NULL == groupHash) {
    qError("groupHash %d failed", EXPLAIN_MAX_GROUP_NUM);
    QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }

X
Xiaoyu Wang 已提交
866 867
  QRY_ERR_JRET(
      qExplainInitCtx(&ctx, groupHash, pDag->explainInfo.verbose, pDag->explainInfo.ratio, pDag->explainInfo.mode));
D
dapan1121 已提交
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890

  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 已提交
891 892 893
      SExplainGroup group = {0};
      group.nodeNum = 1;
      group.plan = plan;
X
Xiaoyu Wang 已提交
894

D
dapan1121 已提交
895 896 897 898 899 900 901 902 903 904 905 906
      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 已提交
907
      ctx->rootGroupId = plan->id.groupId;
D
dapan1121 已提交
908 909 910 911 912
    }

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

D
dapan1121 已提交
913 914 915
  *pCtx = ctx;

  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
916

D
dapan1121 已提交
917 918 919 920 921 922 923
_return:

  qExplainFreeCtx(ctx);

  QRY_RET(code);
}

D
dapan1121 已提交
924 925 926 927 928 929
int32_t qExplainAppendPlanRows(SExplainCtx *pCtx) {
  if (EXPLAIN_MODE_ANALYZE != pCtx->mode) {
    return TSDB_CODE_SUCCESS;
  }

  int32_t tlen = 0;
X
Xiaoyu Wang 已提交
930
  char   *tbuf = pCtx->tbuf;
D
dapan1121 已提交
931 932 933 934 935 936 937 938 939 940 941 942 943 944 945

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

D
dapan1121 已提交
947 948
int32_t qExplainGenerateRsp(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  QRY_ERR_RET(qExplainAppendGroupResRows(pCtx, pCtx->rootGroupId, 0));
D
dapan1121 已提交
949
  QRY_ERR_RET(qExplainAppendPlanRows(pCtx));
D
dapan1121 已提交
950 951 952 953 954
  QRY_ERR_RET(qExplainGetRspFromCtx(pCtx, pRsp));

  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
955
int32_t qExplainUpdateExecInfo(SExplainCtx *pCtx, SExplainRsp *pRspMsg, int32_t groupId, SRetrieveTableRsp **pRsp) {
D
dapan1121 已提交
956
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
957 958 959
  int32_t          code = 0;
  bool             groupDone = false;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
960

D
dapan1121 已提交
961 962 963 964 965 966 967 968 969 970 971 972 973 974
  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 已提交
975

D
dapan1121 已提交
976 977 978 979 980
      QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
    }

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

D
dapan1121 已提交
986 987 988 989
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

  if (group->physiPlanExecNum != pRspMsg->numOfPlans) {
X
Xiaoyu Wang 已提交
990 991
    qError("physiPlanExecNum %d mismatch with others %d in group %d", pRspMsg->numOfPlans, group->physiPlanExecNum,
           groupId);
D
dapan1121 已提交
992 993
    taosMemoryFreeClear(pRspMsg->subplanInfo);
    taosWUnLockLatch(&group->lock);
X
Xiaoyu Wang 已提交
994

D
dapan1121 已提交
995 996 997 998 999
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

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

D
dapan1121 已提交
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
  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 已提交
1013 1014 1015
}

int32_t qExecStaticExplain(SQueryPlan *pDag, SRetrieveTableRsp **pRsp) {
X
Xiaoyu Wang 已提交
1016
  int32_t      code = 0;
D
dapan1121 已提交
1017 1018 1019
  SExplainCtx *pCtx = NULL;

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

D
dapan1121 已提交
1022
_return:
D
dapan1121 已提交
1023
  qExplainFreeCtx(pCtx);
D
dapan1121 已提交
1024 1025 1026
  QRY_RET(code);
}

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

D
dapan1121 已提交
1030
  (*pCtx)->reqStartTs = startTs;
D
dapan1121 已提交
1031
  (*pCtx)->jobStartTs = taosGetTimestampUs();
D
dapan1121 已提交
1032 1033 1034 1035

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
1036 1037
int32_t qExecExplainEnd(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  int32_t code = 0;
D
dapan1121 已提交
1038
  pCtx->jobDoneTs = taosGetTimestampUs();
X
Xiaoyu Wang 已提交
1039

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

D
dapan1121 已提交
1042 1043 1044 1045 1046 1047 1048
  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 已提交
1049 1050
  return TSDB_CODE_SUCCESS;
}