plannerImpl.c 30.3 KB
Newer Older
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/>.
 */

X
Xiaoyu Wang 已提交
16 17
#include "plannerImpl.h"
#include "functionMgt.h"
18

X
Xiaoyu Wang 已提交
19 20
#define CHECK_ALLOC(p, res) \
  do { \
X
Xiaoyu Wang 已提交
21
    if (NULL == (p)) { \
X
Xiaoyu Wang 已提交
22
      pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \
X
Xiaoyu Wang 已提交
23
      return (res); \
X
Xiaoyu Wang 已提交
24 25 26 27 28
    } \
  } while (0)

#define CHECK_CODE(exec, res) \
  do { \
X
Xiaoyu Wang 已提交
29
    int32_t code = (exec); \
X
Xiaoyu Wang 已提交
30 31
    if (TSDB_CODE_SUCCESS != code) { \
      pCxt->errCode = code; \
X
Xiaoyu Wang 已提交
32
      return (res); \
X
Xiaoyu Wang 已提交
33 34 35 36 37 38 39
    } \
  } while (0)

typedef struct SPlanContext {
  int32_t errCode;
  int32_t planNodeId;
} SPlanContext;
X
Xiaoyu Wang 已提交
40

X
Xiaoyu Wang 已提交
41 42 43
static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt);
static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable);

X
Xiaoyu Wang 已提交
44
typedef struct SRewriteExprCxt {
X
Xiaoyu Wang 已提交
45
  int32_t errCode;
X
Xiaoyu Wang 已提交
46
  SNodeList* pExprs;
X
Xiaoyu Wang 已提交
47 48 49
} SRewriteExprCxt;

static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
X
Xiaoyu Wang 已提交
50 51 52 53
  switch (nodeType(*pNode)) {
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION:
    case QUERY_NODE_FUNCTION: {
X
Xiaoyu Wang 已提交
54 55 56 57
      SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext;
      SNode* pExpr;
      int32_t index = 0;
      FOREACH(pExpr, pCxt->pExprs) {
X
Xiaoyu Wang 已提交
58 59 60
        if (QUERY_NODE_GROUPING_SET == nodeType(pExpr)) {
          pExpr = nodesListGetNode(((SGroupingSetNode*)pExpr)->pParameterList, 0);
        }
X
Xiaoyu Wang 已提交
61 62
        if (nodesEqualNode(pExpr, *pNode)) {
          SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
X
Xiaoyu Wang 已提交
63
          CHECK_ALLOC(pCol, DEAL_RES_ERROR);
X
Xiaoyu Wang 已提交
64 65 66 67 68 69 70 71 72 73
          SExprNode* pToBeRewrittenExpr = (SExprNode*)(*pNode);
          pCol->node.resType = pToBeRewrittenExpr->resType;
          strcpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName);
          strcpy(pCol->colName, ((SExprNode*)pExpr)->aliasName);
          nodesDestroyNode(*pNode);
          *pNode = (SNode*)pCol;
          return DEAL_RES_IGNORE_CHILD;
        }
        ++index;
      }
X
Xiaoyu Wang 已提交
74 75 76 77 78
      break;
    }
    default:
      break;
  }
X
Xiaoyu Wang 已提交
79

X
Xiaoyu Wang 已提交
80 81 82
  return DEAL_RES_CONTINUE;
}

X
Xiaoyu Wang 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95
typedef struct SNameExprCxt {
  int32_t planNodeId;
  int32_t rewriteId;
} SNameExprCxt;

static EDealRes doNameExpr(SNode* pNode, void* pContext) {
  switch (nodeType(pNode)) {
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION:
    case QUERY_NODE_FUNCTION: {
      SNameExprCxt* pCxt = (SNameExprCxt*)pContext;
      sprintf(((SExprNode*)pNode)->aliasName, "#expr_%d_%d", pCxt->planNodeId, pCxt->rewriteId++);
      return DEAL_RES_IGNORE_CHILD;
X
Xiaoyu Wang 已提交
96
    }
X
Xiaoyu Wang 已提交
97 98
    default:
      break;
X
Xiaoyu Wang 已提交
99
  }
X
Xiaoyu Wang 已提交
100 101 102 103 104 105 106

  return DEAL_RES_CONTINUE;
}

static int32_t rewriteExpr(int32_t planNodeId, int32_t rewriteId, SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
  SNameExprCxt nameCxt = { .planNodeId = planNodeId, .rewriteId = rewriteId };
  nodesWalkList(pExprs, doNameExpr, &nameCxt);
X
Xiaoyu Wang 已提交
107
  SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs };
X
Xiaoyu Wang 已提交
108 109
  nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
  return cxt.errCode;
X
Xiaoyu Wang 已提交
110 111
}

X
Xiaoyu Wang 已提交
112 113 114 115 116
static SLogicNode* pushLogicNode(SPlanContext* pCxt, SLogicNode* pRoot, SLogicNode* pNode) {
  if (TSDB_CODE_SUCCESS != pCxt->errCode) {
    goto error;
  }

X
Xiaoyu Wang 已提交
117 118 119
  if (NULL == pRoot) {
    return pNode;
  }
X
Xiaoyu Wang 已提交
120

X
Xiaoyu Wang 已提交
121 122 123
  if (NULL == pNode) {
    return pRoot;
  }
X
Xiaoyu Wang 已提交
124

X
Xiaoyu Wang 已提交
125 126
  if (NULL == pNode->pChildren) {
    pNode->pChildren = nodesMakeList();
X
Xiaoyu Wang 已提交
127 128 129
    if (NULL == pNode->pChildren) {
      goto error;
    }
X
Xiaoyu Wang 已提交
130
  }
X
Xiaoyu Wang 已提交
131 132 133 134
  if (TSDB_CODE_SUCCESS != nodesListAppend(pNode->pChildren, (SNode*)pRoot)) {
    goto error;
  }
  pRoot->pParent = pNode;
X
Xiaoyu Wang 已提交
135
  return pNode;
X
Xiaoyu Wang 已提交
136 137 138
error:
  nodesDestroyNode((SNode*)pNode);
  return pRoot;
X
Xiaoyu Wang 已提交
139 140
}

X
Xiaoyu Wang 已提交
141
static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable) {
X
Xiaoyu Wang 已提交
142
  SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN);
X
Xiaoyu Wang 已提交
143 144 145
  CHECK_ALLOC(pScan, NULL);
  pScan->node.id = pCxt->planNodeId++;

X
Xiaoyu Wang 已提交
146
  pScan->pMeta = pRealTable->pMeta;
X
Xiaoyu Wang 已提交
147 148 149

  // set columns to scan
  SNodeList* pCols = NULL;
X
Xiaoyu Wang 已提交
150
  CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols), (SLogicNode*)pScan);
X
Xiaoyu Wang 已提交
151 152 153 154
  if (NULL != pCols) {
    pScan->pScanCols = nodesCloneList(pCols);
    CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan);
  }
X
Xiaoyu Wang 已提交
155 156

  // set output
X
Xiaoyu Wang 已提交
157 158 159 160
  if (NULL != pCols) {
    pScan->node.pTargets = nodesCloneList(pCols);
    CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan);
  }
X
Xiaoyu Wang 已提交
161

X
Xiaoyu Wang 已提交
162 163 164 165
  pScan->scanType = SCAN_TYPE_TABLE;
  pScan->scanFlag = MAIN_SCAN;
  pScan->scanRange = TSWINDOW_INITIALIZER;

X
Xiaoyu Wang 已提交
166 167 168
  return (SLogicNode*)pScan;
}

X
Xiaoyu Wang 已提交
169
static SLogicNode* createSubqueryLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) {
X
Xiaoyu Wang 已提交
170 171 172 173 174 175 176
  SLogicNode* pRoot = createQueryLogicNode(pCxt, pTable->pSubquery);
  CHECK_ALLOC(pRoot, NULL);
  SNode* pNode;
  FOREACH(pNode, pRoot->pTargets) {
    strcpy(((SColumnNode*)pNode)->tableAlias, pTable->table.tableAlias);
  }
  return pRoot;
X
Xiaoyu Wang 已提交
177 178
}

X
Xiaoyu Wang 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
static SLogicNode* createJoinLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable) {
  SJoinLogicNode* pJoin = (SJoinLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_JOIN);
  CHECK_ALLOC(pJoin, NULL);
  pJoin->node.id = pCxt->planNodeId++;

  pJoin->joinType = pJoinTable->joinType;

  // set left and right node
  pJoin->node.pChildren = nodesMakeList();
  CHECK_ALLOC(pJoin->node.pChildren, (SLogicNode*)pJoin);
  SLogicNode* pLeft = createLogicNodeByTable(pCxt, pSelect, pJoinTable->pLeft);
  CHECK_ALLOC(pLeft, (SLogicNode*)pJoin);
  CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pLeft), (SLogicNode*)pJoin);
  SLogicNode* pRight = createLogicNodeByTable(pCxt, pSelect, pJoinTable->pRight);
  CHECK_ALLOC(pRight, (SLogicNode*)pJoin);
  CHECK_CODE(nodesListAppend(pJoin->node.pChildren, (SNode*)pRight), (SLogicNode*)pJoin);

  // set on conditions
X
Xiaoyu Wang 已提交
197 198 199 200
  if (NULL != pJoinTable->pOnCond) {
    pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
    CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
  }
X
Xiaoyu Wang 已提交
201

X
Xiaoyu Wang 已提交
202 203
  // set the output
  pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
X
Xiaoyu Wang 已提交
204
  CHECK_ALLOC(pJoin->node.pTargets, (SLogicNode*)pJoin);
X
Xiaoyu Wang 已提交
205 206 207
  SNodeList* pTargets = nodesCloneList(pRight->pTargets);
  CHECK_ALLOC(pTargets, (SLogicNode*)pJoin);
  nodesListAppendList(pJoin->node.pTargets, pTargets);
X
Xiaoyu Wang 已提交
208 209 210 211

  return (SLogicNode*)pJoin;
}

X
Xiaoyu Wang 已提交
212
static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable) {
X
Xiaoyu Wang 已提交
213 214
  switch (nodeType(pTable)) {
    case QUERY_NODE_REAL_TABLE:
X
Xiaoyu Wang 已提交
215
      return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable);
X
Xiaoyu Wang 已提交
216
    case QUERY_NODE_TEMP_TABLE:
X
Xiaoyu Wang 已提交
217
      return createSubqueryLogicNode(pCxt, pSelect, (STempTableNode*)pTable);
X
Xiaoyu Wang 已提交
218
    case QUERY_NODE_JOIN_TABLE:
X
Xiaoyu Wang 已提交
219
      return createJoinLogicNode(pCxt, pSelect, (SJoinTableNode*)pTable);
X
Xiaoyu Wang 已提交
220 221 222 223 224 225
    default:
      break;
  }
  return NULL;
}

X
Xiaoyu Wang 已提交
226 227 228 229 230 231 232 233 234
typedef struct SCreateColumnCxt {
  int32_t errCode;
  SNodeList* pList;
} SCreateColumnCxt;

static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
  SCreateColumnCxt* pCxt = (SCreateColumnCxt*)pContext;
  switch (nodeType(pNode)) {
    case QUERY_NODE_COLUMN: {
X
Xiaoyu Wang 已提交
235
      SNode* pCol = nodesCloneNode(pNode);
X
Xiaoyu Wang 已提交
236 237
      CHECK_ALLOC(pCol, DEAL_RES_ERROR);
      CHECK_CODE(nodesListAppend(pCxt->pList, pCol), DEAL_RES_ERROR);
X
Xiaoyu Wang 已提交
238 239 240 241 242
      return DEAL_RES_IGNORE_CHILD;
    }
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION:
    case QUERY_NODE_FUNCTION: {
X
Xiaoyu Wang 已提交
243 244
      SExprNode* pExpr = (SExprNode*)pNode;
      SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
X
Xiaoyu Wang 已提交
245
      CHECK_ALLOC(pCol, DEAL_RES_ERROR);
X
Xiaoyu Wang 已提交
246 247
      pCol->node.resType = pExpr->resType;
      strcpy(pCol->colName, pExpr->aliasName);
X
Xiaoyu Wang 已提交
248
      CHECK_CODE(nodesListAppend(pCxt->pList, (SNode*)pCol), DEAL_RES_ERROR);
X
Xiaoyu Wang 已提交
249
      return DEAL_RES_IGNORE_CHILD;
X
Xiaoyu Wang 已提交
250
    }
X
Xiaoyu Wang 已提交
251 252
    default:
      break;
X
Xiaoyu Wang 已提交
253
  }
X
Xiaoyu Wang 已提交
254 255 256 257 258 259

  return DEAL_RES_CONTINUE;
}

static SNodeList* createColumnByRewriteExps(SPlanContext* pCxt, SNodeList* pExprs) {
  SCreateColumnCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pList = nodesMakeList() };
X
Xiaoyu Wang 已提交
260 261
  CHECK_ALLOC(cxt.pList, NULL);

X
Xiaoyu Wang 已提交
262 263 264 265 266 267
  nodesWalkList(pExprs, doCreateColumn, &cxt);
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
    nodesDestroyList(cxt.pList);
    return NULL;
  }
  return cxt.pList;
X
Xiaoyu Wang 已提交
268 269
}

X
Xiaoyu Wang 已提交
270
static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
X
Xiaoyu Wang 已提交
271 272
  SNodeList* pAggFuncs = NULL;
  CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs), NULL);
X
Xiaoyu Wang 已提交
273
  if (NULL == pAggFuncs && NULL == pSelect->pGroupByList) {
X
Xiaoyu Wang 已提交
274 275
    return NULL;
  }
X
Xiaoyu Wang 已提交
276

X
Xiaoyu Wang 已提交
277
  SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG);
X
Xiaoyu Wang 已提交
278 279 280 281
  CHECK_ALLOC(pAgg, NULL);
  pAgg->node.id = pCxt->planNodeId++;

  // set grouyp keys, agg funcs and having conditions
X
Xiaoyu Wang 已提交
282 283 284 285 286 287 288 289
  if (NULL != pSelect->pGroupByList) {
    pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
    CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg);
  }
  if (NULL != pAggFuncs) {
    pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
    CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg);
  }
X
Xiaoyu Wang 已提交
290 291 292 293 294

  // rewrite the expression in subsequent clauses
  CHECK_CODE(rewriteExpr(pAgg->node.id, 1, pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);
  CHECK_CODE(rewriteExpr(pAgg->node.id, 1 + LIST_LENGTH(pAgg->pGroupKeys), pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY), (SLogicNode*)pAgg);

X
Xiaoyu Wang 已提交
295 296 297 298
  if (NULL != pSelect->pHaving) {
    pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
    CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
  }
X
Xiaoyu Wang 已提交
299

X
Xiaoyu Wang 已提交
300
  // set the output
X
Xiaoyu Wang 已提交
301
  pAgg->node.pTargets = nodesMakeList();
X
Xiaoyu Wang 已提交
302
  CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
X
Xiaoyu Wang 已提交
303 304 305 306 307 308 309 310 311 312
  if (NULL != pAgg->pGroupKeys) {
    SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys);
    CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
    nodesListAppendList(pAgg->node.pTargets, pTargets);
  }
  if (NULL != pAgg->pAggFuncs) {
    SNodeList* pTargets = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs);
    CHECK_ALLOC(pTargets, (SLogicNode*)pAgg);
    nodesListAppendList(pAgg->node.pTargets, pTargets);
  }
X
Xiaoyu Wang 已提交
313
  
X
Xiaoyu Wang 已提交
314 315 316
  return (SLogicNode*)pAgg;
}

X
Xiaoyu Wang 已提交
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
static SNodeList* createColumnByProjections(SPlanContext* pCxt, SNodeList* pExprs) {
  SNodeList* pList = nodesMakeList();
  CHECK_ALLOC(pList, NULL);
  SNode* pNode;
  FOREACH(pNode, pExprs) {
    SExprNode* pExpr = (SExprNode*)pNode;
    SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
    if (NULL == pCol) {
      goto error;
    }
    pCol->node.resType = pExpr->resType;
    strcpy(pCol->colName, pExpr->aliasName);
    if (TSDB_CODE_SUCCESS != nodesListAppend(pList, (SNode*)pCol)) {
      goto error;
    }
  }
  return pList;
error:
  nodesDestroyList(pList);
  return NULL;
}

X
Xiaoyu Wang 已提交
339 340 341 342 343
static SLogicNode* createProjectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
  SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
  CHECK_ALLOC(pProject, NULL);
  pProject->node.id = pCxt->planNodeId++;

X
Xiaoyu Wang 已提交
344 345 346
  pProject->pProjections = nodesCloneList(pSelect->pProjectionList);

  pProject->node.pTargets = createColumnByProjections(pCxt,pSelect->pProjectionList);
X
Xiaoyu Wang 已提交
347 348 349 350 351
  CHECK_ALLOC(pProject->node.pTargets, (SLogicNode*)pProject);

  return (SLogicNode*)pProject;
}

X
Xiaoyu Wang 已提交
352 353
static SLogicNode* createSelectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) {
  SLogicNode* pRoot = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable);
X
Xiaoyu Wang 已提交
354 355 356
  if (TSDB_CODE_SUCCESS == pCxt->errCode && NULL != pSelect->pWhere) {
    pRoot->pConditions = nodesCloneNode(pSelect->pWhere);
    CHECK_ALLOC(pRoot->pConditions, pRoot);
X
Xiaoyu Wang 已提交
357 358 359
  }
  if (TSDB_CODE_SUCCESS == pCxt->errCode) {
    pRoot = pushLogicNode(pCxt, pRoot, createAggLogicNode(pCxt, pSelect));
X
Xiaoyu Wang 已提交
360 361
  }
  if (TSDB_CODE_SUCCESS == pCxt->errCode) {
X
Xiaoyu Wang 已提交
362
    pRoot = pushLogicNode(pCxt, pRoot, createProjectLogicNode(pCxt, pSelect));
X
Xiaoyu Wang 已提交
363
  }
X
Xiaoyu Wang 已提交
364 365 366
  return pRoot;
}

X
Xiaoyu Wang 已提交
367
static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) {
X
Xiaoyu Wang 已提交
368 369
  switch (nodeType(pStmt)) {
    case QUERY_NODE_SELECT_STMT:
X
Xiaoyu Wang 已提交
370
      return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt);    
X
Xiaoyu Wang 已提交
371 372 373 374 375 376
    default:
      break;
  }
}

int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
377
  SPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 1 };
X
Xiaoyu Wang 已提交
378 379 380 381 382 383
  SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode);
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
    nodesDestroyNode((SNode*)pRoot);
    return cxt.errCode;
  }
  *pLogicNode = pRoot;
X
Xiaoyu Wang 已提交
384 385
  return TSDB_CODE_SUCCESS;
}
X
Xiaoyu Wang 已提交
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403

int32_t optimize(SLogicNode* pLogicNode) {
  // todo
  return TSDB_CODE_SUCCESS;
}

typedef struct SSubLogicPlan {
  SNode* pRoot; // SLogicNode
  bool haveSuperTable;
  bool haveSystemTable;
} SSubLogicPlan;

int32_t splitLogicPlan(SSubLogicPlan* pLogicPlan) {
  // todo
  return TSDB_CODE_SUCCESS;
}

typedef struct SSlotIndex {
X
Xiaoyu Wang 已提交
404
  int16_t dataBlockId;
X
Xiaoyu Wang 已提交
405 406 407 408 409
  int16_t slotId;
} SSlotIndex;

typedef struct SPhysiPlanContext {
  int32_t errCode;
X
Xiaoyu Wang 已提交
410 411
  int16_t nextDataBlockId;
  SArray* pLocationHelper;
X
Xiaoyu Wang 已提交
412 413 414 415
} SPhysiPlanContext;

static int32_t getSlotKey(SNode* pNode, char* pKey) {
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
X
Xiaoyu Wang 已提交
416 417 418 419 420
    SColumnNode* pCol = (SColumnNode*)pNode;
    if ('\0' == pCol->tableAlias[0]) {
      return sprintf(pKey, "%s", pCol->colName);
    }
    return sprintf(pKey, "%s.%s", pCol->tableAlias, pCol->colName);
X
Xiaoyu Wang 已提交
421
  }
X
Xiaoyu Wang 已提交
422
  return sprintf(pKey, "%s", ((SExprNode*)pNode)->aliasName);
X
Xiaoyu Wang 已提交
423 424 425 426 427 428 429 430
}

static SNode* createSlotDesc(SPhysiPlanContext* pCxt, const SNode* pNode, int16_t slotId) {
  SSlotDescNode* pSlot = (SSlotDescNode*)nodesMakeNode(QUERY_NODE_SLOT_DESC);
  CHECK_ALLOC(pSlot, NULL);
  pSlot->slotId = slotId;
  pSlot->dataType = ((SExprNode*)pNode)->resType;
  pSlot->reserve = false;
X
Xiaoyu Wang 已提交
431
  pSlot->output = false;
X
Xiaoyu Wang 已提交
432 433 434
  return (SNode*)pSlot;
}

X
Xiaoyu Wang 已提交
435
static SNode* createTarget(SNode* pNode, int16_t dataBlockId, int16_t slotId) {
X
Xiaoyu Wang 已提交
436 437 438 439
  STargetNode* pTarget = (STargetNode*)nodesMakeNode(QUERY_NODE_TARGET);
  if (NULL == pTarget) {
    return NULL;
  }
X
Xiaoyu Wang 已提交
440
  pTarget->dataBlockId = dataBlockId;
X
Xiaoyu Wang 已提交
441
  pTarget->slotId = slotId;
X
Xiaoyu Wang 已提交
442
  pTarget->pExpr = pNode;
X
Xiaoyu Wang 已提交
443 444 445
  return (SNode*)pTarget;
}

X
Xiaoyu Wang 已提交
446
static int32_t addDataBlockDesc(SPhysiPlanContext* pCxt, SNodeList* pList, SDataBlockDescNode* pDataBlockDesc) {
X
Xiaoyu Wang 已提交
447
  SHashObj* pHash = NULL;
X
Xiaoyu Wang 已提交
448 449 450
  if (NULL == pDataBlockDesc->pSlots) {
    pDataBlockDesc->pSlots = nodesMakeList();
    CHECK_ALLOC(pDataBlockDesc->pSlots, TSDB_CODE_OUT_OF_MEMORY);
X
Xiaoyu Wang 已提交
451 452 453

    pHash = taosHashInit(LIST_LENGTH(pList), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
    CHECK_ALLOC(pHash, TSDB_CODE_OUT_OF_MEMORY);
X
Xiaoyu Wang 已提交
454
    if (NULL == taosArrayInsert(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId, &pHash)) {
X
Xiaoyu Wang 已提交
455 456 457 458
      taosHashCleanup(pHash);
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  } else {
X
Xiaoyu Wang 已提交
459
    pHash = taosArrayGetP(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId);
X
Xiaoyu Wang 已提交
460 461 462
  }
  
  SNode* pNode = NULL;
X
Xiaoyu Wang 已提交
463
  int16_t slotId = taosHashGetSize(pHash);
X
Xiaoyu Wang 已提交
464 465 466
  FOREACH(pNode, pList) {
    SNode* pSlot = createSlotDesc(pCxt, pNode, slotId);
    CHECK_ALLOC(pSlot, TSDB_CODE_OUT_OF_MEMORY);
X
Xiaoyu Wang 已提交
467
    if (TSDB_CODE_SUCCESS != nodesListAppend(pDataBlockDesc->pSlots, (SNode*)pSlot)) {
X
Xiaoyu Wang 已提交
468 469 470 471
      nodesDestroyNode(pSlot);
      return TSDB_CODE_OUT_OF_MEMORY;
    }

X
Xiaoyu Wang 已提交
472
    SSlotIndex index = { .dataBlockId = pDataBlockDesc->dataBlockId, .slotId = slotId };
X
Xiaoyu Wang 已提交
473 474 475 476
    char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN];
    int32_t len = getSlotKey(pNode, name);
    CHECK_CODE(taosHashPut(pHash, name, len, &index, sizeof(SSlotIndex)), TSDB_CODE_OUT_OF_MEMORY);

X
Xiaoyu Wang 已提交
477
    SNode* pTarget = createTarget(pNode, pDataBlockDesc->dataBlockId, slotId);
X
Xiaoyu Wang 已提交
478 479 480
    CHECK_ALLOC(pTarget, TSDB_CODE_OUT_OF_MEMORY);
    REPLACE_NODE(pTarget);
  
X
Xiaoyu Wang 已提交
481 482 483 484 485
    ++slotId;
  }
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
486
typedef struct SSetSlotIdCxt {
X
Xiaoyu Wang 已提交
487
  int32_t errCode;
X
Xiaoyu Wang 已提交
488 489 490
  SHashObj* pLeftHash;
  SHashObj* pRightHash;
} SSetSlotIdCxt;
X
Xiaoyu Wang 已提交
491

X
Xiaoyu Wang 已提交
492 493 494
static EDealRes doSetSlotId(SNode* pNode, void* pContext) {
  if (QUERY_NODE_COLUMN == nodeType(pNode) && 0 != strcmp(((SColumnNode*)pNode)->colName, "*")) {
    SSetSlotIdCxt* pCxt = (SSetSlotIdCxt*)pContext;
X
Xiaoyu Wang 已提交
495
    char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN];
X
Xiaoyu Wang 已提交
496 497 498 499
    int32_t len = getSlotKey(pNode, name);
    SSlotIndex* pIndex = taosHashGet(pCxt->pLeftHash, name, len);
    if (NULL == pIndex) {
      pIndex = taosHashGet(pCxt->pRightHash, name, len);
X
Xiaoyu Wang 已提交
500
    }
X
Xiaoyu Wang 已提交
501
    // pIndex is definitely not NULL, otherwise it is a bug
X
Xiaoyu Wang 已提交
502
    ((SColumnNode*)pNode)->dataBlockId = pIndex->dataBlockId;
X
Xiaoyu Wang 已提交
503 504 505
    ((SColumnNode*)pNode)->slotId = pIndex->slotId;
    CHECK_ALLOC(pNode, DEAL_RES_ERROR);
    return DEAL_RES_IGNORE_CHILD;
X
Xiaoyu Wang 已提交
506 507 508 509
  }
  return DEAL_RES_CONTINUE;
}

X
Xiaoyu Wang 已提交
510
static SNode* setNodeSlotId(SPhysiPlanContext* pCxt, int16_t leftDataBlockId, int16_t rightDataBlockId, SNode* pNode) {
X
Xiaoyu Wang 已提交
511 512
  SNode* pRes = nodesCloneNode(pNode);
  CHECK_ALLOC(pRes, NULL);
X
Xiaoyu Wang 已提交
513 514
  SSetSlotIdCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pLeftHash = taosArrayGetP(pCxt->pLocationHelper, leftDataBlockId),
      .pRightHash = (rightDataBlockId < 0 ? NULL : taosArrayGetP(pCxt->pLocationHelper, rightDataBlockId)) };
X
Xiaoyu Wang 已提交
515
  nodesWalkNode(pRes, doSetSlotId, &cxt);
X
Xiaoyu Wang 已提交
516 517 518 519 520 521 522
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
    nodesDestroyNode(pRes);
    return NULL;
  }
  return pRes;
}

X
Xiaoyu Wang 已提交
523
static SNodeList* setListSlotId(SPhysiPlanContext* pCxt, int16_t leftDataBlockId, int16_t rightDataBlockId, SNodeList* pList) {
X
Xiaoyu Wang 已提交
524 525
  SNodeList* pRes = nodesCloneList(pList);
  CHECK_ALLOC(pRes, NULL);
X
Xiaoyu Wang 已提交
526 527
  SSetSlotIdCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pLeftHash = taosArrayGetP(pCxt->pLocationHelper, leftDataBlockId),
      .pRightHash = (rightDataBlockId < 0 ? NULL : taosArrayGetP(pCxt->pLocationHelper, rightDataBlockId)) };
X
Xiaoyu Wang 已提交
528
  nodesWalkList(pRes, doSetSlotId, &cxt);
X
Xiaoyu Wang 已提交
529 530 531 532 533 534 535
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
    nodesDestroyList(pRes);
    return NULL;
  }
  return pRes;
}

X
Xiaoyu Wang 已提交
536
static SPhysiNode* makePhysiNode(SPhysiPlanContext* pCxt, ENodeType type) {
X
Xiaoyu Wang 已提交
537 538 539 540
  SPhysiNode* pPhysiNode = (SPhysiNode*)nodesMakeNode(type);
  if (NULL == pPhysiNode) {
    return NULL;
  }
X
Xiaoyu Wang 已提交
541 542
  pPhysiNode->outputDataBlockDesc.dataBlockId = pCxt->nextDataBlockId++;
  pPhysiNode->outputDataBlockDesc.type = QUERY_NODE_DATABLOCK_DESC;
X
Xiaoyu Wang 已提交
543 544 545
  return pPhysiNode;
}

X
Xiaoyu Wang 已提交
546 547
static int32_t setConditionsSlotId(SPhysiPlanContext* pCxt, const SLogicNode* pLogicNode, SPhysiNode* pPhysiNode) {
  if (NULL != pLogicNode->pConditions) {
X
Xiaoyu Wang 已提交
548
    pPhysiNode->pConditions = setNodeSlotId(pCxt, pPhysiNode->outputDataBlockDesc.dataBlockId, -1, pLogicNode->pConditions);
X
Xiaoyu Wang 已提交
549 550 551 552
    CHECK_ALLOC(pPhysiNode->pConditions, TSDB_CODE_OUT_OF_MEMORY);
  }
  return TSDB_CODE_SUCCESS;
}
X
Xiaoyu Wang 已提交
553

X
Xiaoyu Wang 已提交
554 555
static int32_t setSlotOutput(SPhysiPlanContext* pCxt, SNodeList* pTargets, SDataBlockDescNode* pDataBlockDesc) {
  SHashObj* pHash = taosArrayGetP(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId);
X
Xiaoyu Wang 已提交
556 557 558 559 560
  char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN];
  SNode* pNode;
  FOREACH(pNode, pTargets) {
    int32_t len = getSlotKey(pNode, name);
    SSlotIndex* pIndex = taosHashGet(pHash, name, len);
X
Xiaoyu Wang 已提交
561
    ((SSlotDescNode*)nodesListGetNode(pDataBlockDesc->pSlots, pIndex->slotId))->output = true;
X
Xiaoyu Wang 已提交
562
  }
X
Xiaoyu Wang 已提交
563 564 565 566 567 568 569 570 571
  
  return TSDB_CODE_SUCCESS;
}

static int32_t initScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode, SScanPhysiNode* pScanPhysiNode) {
  if (NULL != pScanLogicNode->pScanCols) {
    pScanPhysiNode->pScanCols = nodesCloneList(pScanLogicNode->pScanCols);
    CHECK_ALLOC(pScanPhysiNode->pScanCols, TSDB_CODE_OUT_OF_MEMORY);
  }
X
Xiaoyu Wang 已提交
572 573
  // Data block describe also needs to be set without scanning column, such as SELECT COUNT(*) FROM t
  CHECK_CODE(addDataBlockDesc(pCxt, pScanPhysiNode->pScanCols, &pScanPhysiNode->node.outputDataBlockDesc), TSDB_CODE_OUT_OF_MEMORY);
X
Xiaoyu Wang 已提交
574 575 576

  CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pScanLogicNode, (SPhysiNode*)pScanPhysiNode), TSDB_CODE_OUT_OF_MEMORY);

X
Xiaoyu Wang 已提交
577
  CHECK_CODE(setSlotOutput(pCxt, pScanLogicNode->node.pTargets, &pScanPhysiNode->node.outputDataBlockDesc), TSDB_CODE_OUT_OF_MEMORY);
X
Xiaoyu Wang 已提交
578 579 580 581 582 583 584 585 586 587 588

  pScanPhysiNode->uid = pScanLogicNode->pMeta->uid;
  pScanPhysiNode->tableType = pScanLogicNode->pMeta->tableType;
  pScanPhysiNode->order = TSDB_ORDER_ASC;
  pScanPhysiNode->count = 1;
  pScanPhysiNode->reverse = 0;

  return TSDB_CODE_SUCCESS;
}

static SPhysiNode* createTagScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode) {
X
Xiaoyu Wang 已提交
589
  STagScanPhysiNode* pTagScan = (STagScanPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN);
X
Xiaoyu Wang 已提交
590 591 592 593 594 595
  CHECK_ALLOC(pTagScan, NULL);
  CHECK_CODE(initScanPhysiNode(pCxt, pScanLogicNode, (SScanPhysiNode*)pTagScan), (SPhysiNode*)pTagScan);
  return (SPhysiNode*)pTagScan;
}

static SPhysiNode* createTableScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode) {
X
Xiaoyu Wang 已提交
596
  STableScanPhysiNode* pTableScan = (STableScanPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN);
X
Xiaoyu Wang 已提交
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
  CHECK_ALLOC(pTableScan, NULL);
  CHECK_CODE(initScanPhysiNode(pCxt, pScanLogicNode, (SScanPhysiNode*)pTableScan), (SPhysiNode*)pTableScan);
  pTableScan->scanFlag = pScanLogicNode->scanFlag;
  pTableScan->scanRange = pScanLogicNode->scanRange;
  return (SPhysiNode*)pTableScan;
}

static SPhysiNode* createScanPhysiNode(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode) {
  switch (pScanLogicNode->scanType) {
    case SCAN_TYPE_TAG:
      return createTagScanPhysiNode(pCxt, pScanLogicNode);
    case SCAN_TYPE_TABLE:
      return createTableScanPhysiNode(pCxt, pScanLogicNode);
    case SCAN_TYPE_STABLE:
    case SCAN_TYPE_STREAM:
      break;
    default:
      break;
  }
X
Xiaoyu Wang 已提交
616
  return NULL;
X
Xiaoyu Wang 已提交
617 618
}

X
Xiaoyu Wang 已提交
619
static SNodeList* createJoinOutputCols(SPhysiPlanContext* pCxt, SDataBlockDescNode* pLeftDesc, SDataBlockDescNode* pRightDesc) {
X
Xiaoyu Wang 已提交
620 621 622
  SNodeList* pCols = nodesMakeList();
  CHECK_ALLOC(pCols, NULL);
  SNode* pNode;
X
Xiaoyu Wang 已提交
623
  FOREACH(pNode, pLeftDesc->pSlots) {
X
Xiaoyu Wang 已提交
624 625 626 627 628 629
    SSlotDescNode* pSlot = (SSlotDescNode*)pNode;
    SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
    if (NULL == pCol) {
      goto error;
    }
    pCol->node.resType = pSlot->dataType;
X
Xiaoyu Wang 已提交
630
    pCol->dataBlockId = pLeftDesc->dataBlockId;
X
Xiaoyu Wang 已提交
631 632 633 634 635 636
    pCol->slotId = pSlot->slotId;
    pCol->colId = -1;
    if (TSDB_CODE_SUCCESS != nodesListAppend(pCols, (SNode*)pCol)) {
      goto error;
    }
  }
X
Xiaoyu Wang 已提交
637
  FOREACH(pNode, pRightDesc->pSlots) {
X
Xiaoyu Wang 已提交
638 639 640 641 642 643
    SSlotDescNode* pSlot = (SSlotDescNode*)pNode;
    SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
    if (NULL == pCol) {
      goto error;
    }
    pCol->node.resType = pSlot->dataType;
X
Xiaoyu Wang 已提交
644
    pCol->dataBlockId = pRightDesc->dataBlockId;
X
Xiaoyu Wang 已提交
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
    pCol->slotId = pSlot->slotId;
    pCol->colId = -1;
    if (TSDB_CODE_SUCCESS != nodesListAppend(pCols, (SNode*)pCol)) {
      goto error;
    }
  }
  return pCols;
error:
  nodesDestroyList(pCols);
  return NULL;
}

static SPhysiNode* createJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SJoinLogicNode* pJoinLogicNode) {
  SJoinPhysiNode* pJoin = (SJoinPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_JOIN);
  CHECK_ALLOC(pJoin, NULL);

X
Xiaoyu Wang 已提交
661 662 663
  SDataBlockDescNode* pLeftDesc = &((SPhysiNode*)nodesListGetNode(pChildren, 0))->outputDataBlockDesc;
  SDataBlockDescNode* pRightDesc = &((SPhysiNode*)nodesListGetNode(pChildren, 1))->outputDataBlockDesc;
  pJoin->pOnConditions = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pOnConditions);
X
Xiaoyu Wang 已提交
664 665
  CHECK_ALLOC(pJoin->pOnConditions, (SPhysiNode*)pJoin);

X
Xiaoyu Wang 已提交
666
  pJoin->pTargets = createJoinOutputCols(pCxt, pLeftDesc, pRightDesc);
X
Xiaoyu Wang 已提交
667
  CHECK_ALLOC(pJoin->pTargets, (SPhysiNode*)pJoin);
X
Xiaoyu Wang 已提交
668
  CHECK_CODE(addDataBlockDesc(pCxt, pJoin->pTargets, &pJoin->node.outputDataBlockDesc), (SPhysiNode*)pJoin);
X
Xiaoyu Wang 已提交
669 670

  CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pJoinLogicNode, (SPhysiNode*)pJoin), (SPhysiNode*)pJoin);
X
Xiaoyu Wang 已提交
671

X
Xiaoyu Wang 已提交
672
  CHECK_CODE(setSlotOutput(pCxt, pJoinLogicNode->node.pTargets, &pJoin->node.outputDataBlockDesc), (SPhysiNode*)pJoin);
X
Xiaoyu Wang 已提交
673

X
Xiaoyu Wang 已提交
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
  return (SPhysiNode*)pJoin;
}

typedef struct SRewritePrecalcExprsCxt {
  int32_t errCode;
  int32_t planNodeId;
  int32_t rewriteId;
  SNodeList* pPrecalcExprs;
} SRewritePrecalcExprsCxt;

static EDealRes collectAndRewrite(SRewritePrecalcExprsCxt* pCxt, SNode** pNode) {
  SNode* pExpr = nodesCloneNode(*pNode);
  CHECK_ALLOC(pExpr, DEAL_RES_ERROR);
  if (nodesListAppend(pCxt->pPrecalcExprs, pExpr)) {
    nodesDestroyNode(pExpr);
    return DEAL_RES_ERROR;
  }
  SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
  if (NULL == pCol) {
    nodesDestroyNode(pExpr);
    return DEAL_RES_ERROR;
X
Xiaoyu Wang 已提交
695
  }
X
Xiaoyu Wang 已提交
696 697 698 699 700 701 702 703
  SExprNode* pRewrittenExpr = (SExprNode*)pExpr;
  pCol->node.resType = pRewrittenExpr->resType;
  if ('\0' != pRewrittenExpr->aliasName[0]) {
    strcpy(pCol->colName, pRewrittenExpr->aliasName);
  } else {
    snprintf(pRewrittenExpr->aliasName, sizeof(pRewrittenExpr->aliasName), "#expr_%d_%d", pCxt->planNodeId, pCxt->rewriteId);
    strcpy(pCol->colName, pRewrittenExpr->aliasName);
  }
X
Xiaoyu Wang 已提交
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
  nodesDestroyNode(*pNode);
  *pNode = (SNode*)pCol;
  return DEAL_RES_IGNORE_CHILD;
}

static EDealRes doRewritePrecalcExprs(SNode** pNode, void* pContext) {
  SRewritePrecalcExprsCxt* pCxt = (SRewritePrecalcExprsCxt*)pContext;
  switch (nodeType(*pNode)) {
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION: {
      return collectAndRewrite(pContext, pNode);
    }
    case QUERY_NODE_FUNCTION: {
      if (!fmIsAggFunc(((SFunctionNode*)(*pNode))->funcId)) {
        return collectAndRewrite(pContext, pNode);
      }
    }
    default:
      break;
  }
  return DEAL_RES_CONTINUE;
}

static int32_t rewritePrecalcExprs(SPhysiPlanContext* pCxt, SNodeList* pList, SNodeList** pPrecalcExprs, SNodeList** pRewrittenList) {
  if (NULL == pList) {
    return TSDB_CODE_SUCCESS;
  }

  if (NULL == *pPrecalcExprs) {
    *pPrecalcExprs = nodesMakeList();
    CHECK_ALLOC(*pPrecalcExprs, TSDB_CODE_OUT_OF_MEMORY);
  }
  if (NULL == *pRewrittenList) {
    *pRewrittenList = nodesMakeList();
    CHECK_ALLOC(*pRewrittenList, TSDB_CODE_OUT_OF_MEMORY);
  }
  SNode* pNode = NULL;
  FOREACH(pNode, pList) {
    SNode* pNew = NULL;
    if (QUERY_NODE_GROUPING_SET == nodeType(pNode)) {
      pNew = nodesCloneNode(nodesListGetNode(((SGroupingSetNode*)pNode)->pParameterList, 0));
    } else {
      pNew = nodesCloneNode(pNode);
    }
    CHECK_ALLOC(pNew, TSDB_CODE_OUT_OF_MEMORY);
    CHECK_CODE(nodesListAppend(*pRewrittenList, pNew), TSDB_CODE_OUT_OF_MEMORY);
  }
  SRewritePrecalcExprsCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pPrecalcExprs = *pPrecalcExprs };
  nodesRewriteList(*pRewrittenList, doRewritePrecalcExprs, &cxt);
  if (0 == LIST_LENGTH(cxt.pPrecalcExprs)) {
    nodesDestroyList(cxt.pPrecalcExprs);
    *pPrecalcExprs = NULL;
  }
  return cxt.errCode;
}

static SPhysiNode* createAggPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SAggLogicNode* pAggLogicNode) {
  SAggPhysiNode* pAgg = (SAggPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_AGG);
  CHECK_ALLOC(pAgg, NULL);

  SNodeList* pPrecalcExprs = NULL;
  SNodeList* pGroupKeys = NULL;
  SNodeList* pAggFuncs = NULL;
  CHECK_CODE(rewritePrecalcExprs(pCxt, pAggLogicNode->pGroupKeys, &pPrecalcExprs, &pGroupKeys), (SPhysiNode*)pAgg);
  CHECK_CODE(rewritePrecalcExprs(pCxt, pAggLogicNode->pAggFuncs, &pPrecalcExprs, &pAggFuncs), (SPhysiNode*)pAgg);

X
Xiaoyu Wang 已提交
770 771
  SDataBlockDescNode* pChildTupe = &(((SPhysiNode*)nodesListGetNode(pChildren, 0))->outputDataBlockDesc);
  // push down expression to outputDataBlockDesc of child node
X
Xiaoyu Wang 已提交
772
  if (NULL != pPrecalcExprs) {
X
Xiaoyu Wang 已提交
773
    pAgg->pExprs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pPrecalcExprs);
X
Xiaoyu Wang 已提交
774
    CHECK_ALLOC(pAgg->pExprs, (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
775
    CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pExprs, pChildTupe), (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
776 777 778
  }

  if (NULL != pGroupKeys) {
X
Xiaoyu Wang 已提交
779
    pAgg->pGroupKeys = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pGroupKeys);
X
Xiaoyu Wang 已提交
780
    CHECK_ALLOC(pAgg->pGroupKeys, (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
781
    CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pGroupKeys, &pAgg->node.outputDataBlockDesc), (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
782 783 784
  }

  if (NULL != pAggFuncs) {
X
Xiaoyu Wang 已提交
785
    pAgg->pAggFuncs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pAggFuncs);
X
Xiaoyu Wang 已提交
786
    CHECK_ALLOC(pAgg->pAggFuncs, (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
787
    CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pAggFuncs, &pAgg->node.outputDataBlockDesc), (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
788 789 790 791
  }

  CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pAggLogicNode, (SPhysiNode*)pAgg), (SPhysiNode*)pAgg);

X
Xiaoyu Wang 已提交
792
  CHECK_CODE(setSlotOutput(pCxt, pAggLogicNode->node.pTargets, &pAgg->node.outputDataBlockDesc), (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
793 794 795 796 797 798 799 800

  return (SPhysiNode*)pAgg;
}

static SPhysiNode* createProjectPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SProjectLogicNode* pProjectLogicNode) {
  SProjectPhysiNode* pProject = (SProjectPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_PROJECT);
  CHECK_ALLOC(pProject, NULL);

X
Xiaoyu Wang 已提交
801
  pProject->pProjections = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->outputDataBlockDesc.dataBlockId, -1, pProjectLogicNode->pProjections);
X
Xiaoyu Wang 已提交
802
  CHECK_ALLOC(pProject->pProjections, (SPhysiNode*)pProject);
X
Xiaoyu Wang 已提交
803
  CHECK_CODE(addDataBlockDesc(pCxt, pProject->pProjections, &pProject->node.outputDataBlockDesc), (SPhysiNode*)pProject);
X
Xiaoyu Wang 已提交
804 805

  CHECK_CODE(setConditionsSlotId(pCxt, (const SLogicNode*)pProjectLogicNode, (SPhysiNode*)pProject), (SPhysiNode*)pProject);
X
Xiaoyu Wang 已提交
806 807 808 809 810

  return (SPhysiNode*)pProject;
}

static SPhysiNode* createPhysiNode(SPhysiPlanContext* pCxt, SLogicNode* pLogicPlan) {
X
Xiaoyu Wang 已提交
811 812
  SNodeList* pChildren = nodesMakeList();
  CHECK_ALLOC(pChildren, NULL);
X
Xiaoyu Wang 已提交
813 814 815 816

  SNode* pLogicChild;
  FOREACH(pLogicChild, pLogicPlan->pChildren) {
    SNode* pChildPhyNode = (SNode*)createPhysiNode(pCxt, (SLogicNode*)pLogicChild);
X
Xiaoyu Wang 已提交
817
    if (TSDB_CODE_SUCCESS != nodesListAppend(pChildren, pChildPhyNode)) {
X
Xiaoyu Wang 已提交
818
      pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
X
Xiaoyu Wang 已提交
819
      nodesDestroyList(pChildren);
X
Xiaoyu Wang 已提交
820 821 822 823 824 825 826 827 828 829
      return NULL;
    }
  }

  SPhysiNode* pPhyNode = NULL;
  switch (nodeType(pLogicPlan)) {
    case QUERY_NODE_LOGIC_PLAN_SCAN:
      pPhyNode = createScanPhysiNode(pCxt, (SScanLogicNode*)pLogicPlan);
      break;
    case QUERY_NODE_LOGIC_PLAN_JOIN:
X
Xiaoyu Wang 已提交
830
      pPhyNode = createJoinPhysiNode(pCxt, pChildren, (SJoinLogicNode*)pLogicPlan);
X
Xiaoyu Wang 已提交
831 832
      break;
    case QUERY_NODE_LOGIC_PLAN_AGG:
X
Xiaoyu Wang 已提交
833
      pPhyNode = createAggPhysiNode(pCxt, pChildren, (SAggLogicNode*)pLogicPlan);
X
Xiaoyu Wang 已提交
834 835
      break;
    case QUERY_NODE_LOGIC_PLAN_PROJECT:
X
Xiaoyu Wang 已提交
836
      pPhyNode = createProjectPhysiNode(pCxt, pChildren, (SProjectLogicNode*)pLogicPlan);
X
Xiaoyu Wang 已提交
837 838 839 840 841
      break;
    default:
      break;
  }

X
Xiaoyu Wang 已提交
842 843 844 845
  pPhyNode->pChildren = pChildren;
  SNode* pChild;
  FOREACH(pChild, pPhyNode->pChildren) {
    ((SPhysiNode*)pChild)->pParent = pPhyNode;
X
Xiaoyu Wang 已提交
846 847 848 849 850 851
  }

  return pPhyNode;
}

int32_t createPhysiPlan(SLogicNode* pLogicNode, SPhysiNode** pPhyNode) {
X
Xiaoyu Wang 已提交
852 853
  SPhysiPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .nextDataBlockId = 0, .pLocationHelper = taosArrayInit(32, POINTER_BYTES) };
  if (NULL == cxt.pLocationHelper) {
X
Xiaoyu Wang 已提交
854 855 856 857 858 859 860 861 862 863 864 865 866
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  *pPhyNode = createPhysiNode(&cxt, pLogicNode);
  return cxt.errCode;
}

int32_t buildPhysiPlan(SLogicNode* pLogicNode, SPhysiNode** pPhyNode) {
  // split
  // scale out
  // maping
  // create
  return TSDB_CODE_SUCCESS;
}