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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return TSDB_CODE_SUCCESS;

_return:

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

  QRY_RET(code);
}

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

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

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

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

  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
197 198
}

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

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

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

  ++group->physiPlanExecIdx;

  return TSDB_CODE_SUCCESS;
}

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

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

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

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

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

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

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

  return TSDB_CODE_SUCCESS;

_return:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return TSDB_CODE_SUCCESS;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if (pPartNode->node.pConditions) {
          EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
          QRY_ERR_RET(nodesNodeToSQL(pPartNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
                                     TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
          EXPLAIN_ROW_END();
          QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
        }
      }
      break;
    }
D
dapan1121 已提交
860 861 862 863 864 865 866 867 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
    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 已提交
904 905 906 907 908 909 910 911
    default:
      qError("not supported physical node type %d", pNode->type);
      return TSDB_CODE_QRY_APP_ERROR;
  }

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
912
int32_t qExplainResNodeToRows(SExplainResNode *pResNode, SExplainCtx *ctx, int32_t level) {
D
dapan1121 已提交
913 914 915 916 917 918
  if (NULL == pResNode) {
    qError("explain res node is NULL");
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

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

X
Xiaoyu Wang 已提交
921 922
  SNode *pNode = NULL;
  FOREACH(pNode, pResNode->pChildren) { QRY_ERR_RET(qExplainResNodeToRows((SExplainResNode *)pNode, ctx, level + 1)); }
D
dapan1121 已提交
923 924 925 926

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
927
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level) {
D
dapan1121 已提交
928
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
929 930
  int32_t          code = 0;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
931

D
dapan1121 已提交
932 933 934 935
  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 已提交
936
  }
X
Xiaoyu Wang 已提交
937

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

D
dapan1121 已提交
940
  if ((EXPLAIN_MODE_ANALYZE == ctx->mode) && (group->physiPlanNum != group->physiPlanExecNum)) {
X
Xiaoyu Wang 已提交
941 942
    qError("physiPlanNum %d mismatch with physiExecNum %d in group %d", group->physiPlanNum, group->physiPlanExecNum,
           groupId);
D
dapan1121 已提交
943 944
    QRY_ERR_JRET(TSDB_CODE_QRY_APP_ERROR);
  }
D
dapan1121 已提交
945

D
dapan1121 已提交
946
  QRY_ERR_JRET(qExplainResNodeToRows(node, ctx, level));
D
dapan1121 已提交
947 948 949

_return:

D
dapan1121 已提交
950
  qExplainFreeResNode(node);
X
Xiaoyu Wang 已提交
951

D
dapan1121 已提交
952 953 954
  QRY_RET(code);
}

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

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

975
  // payload length
X
Xiaoyu Wang 已提交
976 977
  *(int32_t *)rsp->data =
      sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t) * colNum + sizeof(int32_t) * rowNum + pCtx->dataSize;
D
dapan1121 已提交
978

979
  // group id
X
Xiaoyu Wang 已提交
980
  *(uint64_t *)(rsp->data + sizeof(int32_t)) = 0;
981 982

  // column length
X
Xiaoyu Wang 已提交
983
  int32_t *colLength = (int32_t *)(rsp->data + sizeof(int32_t) + sizeof(uint64_t));
984 985 986 987 988

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

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

X
Xiaoyu Wang 已提交
991
  char *start = data;
D
dapan1121 已提交
992 993
  for (int32_t i = 0; i < rowNum; ++i) {
    SQueryExplainRowInfo *row = taosArrayGet(pCtx->rows, i);
994
    offset[i] = data - start;
D
dapan1121 已提交
995

996 997
    varDataCopy(data, row->buf);
    ASSERT(varDataTLen(row->buf) == row->len);
D
dapan1121 已提交
998 999 1000
    data += row->len;
  }

1001 1002
  *colLength = htonl(data - start);
  rsp->compLen = htonl(rspSize);
D
dapan1121 已提交
1003

1004
  *pRsp = rsp;
D
dapan1121 已提交
1005 1006 1007
  return TSDB_CODE_SUCCESS;
}

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

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

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

  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 已提交
1058 1059 1060
      SExplainGroup group = {0};
      group.nodeNum = 1;
      group.plan = plan;
X
Xiaoyu Wang 已提交
1061

D
dapan1121 已提交
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
      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 已提交
1074
      ctx->rootGroupId = plan->id.groupId;
D
dapan1121 已提交
1075 1076 1077 1078 1079
    }

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

D
dapan1121 已提交
1080 1081 1082
  *pCtx = ctx;

  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
1083

D
dapan1121 已提交
1084 1085 1086 1087 1088 1089 1090
_return:

  qExplainFreeCtx(ctx);

  QRY_RET(code);
}

D
dapan1121 已提交
1091 1092 1093 1094 1095 1096
int32_t qExplainAppendPlanRows(SExplainCtx *pCtx) {
  if (EXPLAIN_MODE_ANALYZE != pCtx->mode) {
    return TSDB_CODE_SUCCESS;
  }

  int32_t tlen = 0;
X
Xiaoyu Wang 已提交
1097
  char   *tbuf = pCtx->tbuf;
D
dapan1121 已提交
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112

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

D
dapan1121 已提交
1114 1115
int32_t qExplainGenerateRsp(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  QRY_ERR_RET(qExplainAppendGroupResRows(pCtx, pCtx->rootGroupId, 0));
D
dapan1121 已提交
1116
  QRY_ERR_RET(qExplainAppendPlanRows(pCtx));
D
dapan1121 已提交
1117 1118 1119 1120 1121
  QRY_ERR_RET(qExplainGetRspFromCtx(pCtx, pRsp));

  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
1122
int32_t qExplainUpdateExecInfo(SExplainCtx *pCtx, SExplainRsp *pRspMsg, int32_t groupId, SRetrieveTableRsp **pRsp) {
D
dapan1121 已提交
1123
  SExplainResNode *node = NULL;
X
Xiaoyu Wang 已提交
1124 1125 1126
  int32_t          code = 0;
  bool             groupDone = false;
  SExplainCtx     *ctx = (SExplainCtx *)pCtx;
D
dapan1121 已提交
1127

D
dapan1121 已提交
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
  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 已提交
1142

D
dapan1121 已提交
1143 1144 1145 1146 1147
      QRY_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
    }

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

D
dapan1121 已提交
1153 1154 1155 1156
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

  if (group->physiPlanExecNum != pRspMsg->numOfPlans) {
X
Xiaoyu Wang 已提交
1157 1158
    qError("physiPlanExecNum %d mismatch with others %d in group %d", pRspMsg->numOfPlans, group->physiPlanExecNum,
           groupId);
D
dapan1121 已提交
1159 1160
    taosMemoryFreeClear(pRspMsg->subplanInfo);
    taosWUnLockLatch(&group->lock);
X
Xiaoyu Wang 已提交
1161

D
dapan1121 已提交
1162 1163 1164 1165 1166
    QRY_ERR_RET(TSDB_CODE_QRY_APP_ERROR);
  }

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

D
dapan1121 已提交
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
  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 已提交
1180 1181 1182
}

int32_t qExecStaticExplain(SQueryPlan *pDag, SRetrieveTableRsp **pRsp) {
X
Xiaoyu Wang 已提交
1183
  int32_t      code = 0;
D
dapan1121 已提交
1184 1185 1186
  SExplainCtx *pCtx = NULL;

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

D
dapan1121 已提交
1189
_return:
D
dapan1121 已提交
1190
  qExplainFreeCtx(pCtx);
D
dapan1121 已提交
1191 1192 1193
  QRY_RET(code);
}

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

D
dapan1121 已提交
1197
  (*pCtx)->reqStartTs = startTs;
D
dapan1121 已提交
1198
  (*pCtx)->jobStartTs = taosGetTimestampUs();
D
dapan1121 已提交
1199 1200 1201 1202

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
1203 1204
int32_t qExecExplainEnd(SExplainCtx *pCtx, SRetrieveTableRsp **pRsp) {
  int32_t code = 0;
D
dapan1121 已提交
1205
  pCtx->jobDoneTs = taosGetTimestampUs();
X
Xiaoyu Wang 已提交
1206

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

D
dapan1121 已提交
1209 1210 1211 1212 1213 1214 1215
  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 已提交
1216 1217
  return TSDB_CODE_SUCCESS;
}