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
#include "plannerImpl.h"
X
Xiaoyu Wang 已提交
17

X
Xiaoyu Wang 已提交
18
#include "functionMgt.h"
X
Xiaoyu Wang 已提交
19
#include "query.h"
20

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

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

X
Xiaoyu Wang 已提交
38
typedef struct SLogicPlanContext {
X
Xiaoyu Wang 已提交
39 40
  int32_t errCode;
  int32_t planNodeId;
X
Xiaoyu Wang 已提交
41
} SLogicPlanContext;
X
Xiaoyu Wang 已提交
42

X
Xiaoyu Wang 已提交
43 44
static SLogicNode* createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt);
static SLogicNode* createLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable);
X
Xiaoyu Wang 已提交
45

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

static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
X
Xiaoyu Wang 已提交
52 53 54 55
  switch (nodeType(*pNode)) {
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION:
    case QUERY_NODE_FUNCTION: {
X
Xiaoyu Wang 已提交
56 57 58 59
      SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext;
      SNode* pExpr;
      int32_t index = 0;
      FOREACH(pExpr, pCxt->pExprs) {
X
Xiaoyu Wang 已提交
60 61 62
        if (QUERY_NODE_GROUPING_SET == nodeType(pExpr)) {
          pExpr = nodesListGetNode(((SGroupingSetNode*)pExpr)->pParameterList, 0);
        }
X
Xiaoyu Wang 已提交
63 64
        if (nodesEqualNode(pExpr, *pNode)) {
          SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
X
Xiaoyu Wang 已提交
65
          CHECK_ALLOC(pCol, DEAL_RES_ERROR);
X
Xiaoyu Wang 已提交
66 67 68 69 70 71 72 73 74 75
          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 已提交
76 77 78 79 80
      break;
    }
    default:
      break;
  }
X
Xiaoyu Wang 已提交
81

X
Xiaoyu Wang 已提交
82 83 84
  return DEAL_RES_CONTINUE;
}

X
Xiaoyu Wang 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97
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 已提交
98
    }
X
Xiaoyu Wang 已提交
99 100
    default:
      break;
X
Xiaoyu Wang 已提交
101
  }
X
Xiaoyu Wang 已提交
102 103 104 105 106 107 108

  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 已提交
109
  SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs };
X
Xiaoyu Wang 已提交
110 111
  nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
  return cxt.errCode;
X
Xiaoyu Wang 已提交
112 113
}

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

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

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

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

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

X
Xiaoyu Wang 已提交
148
  pScan->pMeta = pRealTable->pMeta;
X
Xiaoyu Wang 已提交
149 150 151

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

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

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

X
Xiaoyu Wang 已提交
168 169 170
  return (SLogicNode*)pScan;
}

X
Xiaoyu Wang 已提交
171
static SLogicNode* createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) {
X
Xiaoyu Wang 已提交
172 173 174 175 176 177 178
  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 已提交
179 180
}

X
Xiaoyu Wang 已提交
181
static SLogicNode* createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable) {
X
Xiaoyu Wang 已提交
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
  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 已提交
199 200 201 202
  if (NULL != pJoinTable->pOnCond) {
    pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
    CHECK_ALLOC(pJoin->pOnConditions, (SLogicNode*)pJoin);
  }
X
Xiaoyu Wang 已提交
203

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

  return (SLogicNode*)pJoin;
}

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

X
Xiaoyu Wang 已提交
228 229 230 231 232 233 234 235 236
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 已提交
237
      SNode* pCol = nodesCloneNode(pNode);
X
Xiaoyu Wang 已提交
238 239
      CHECK_ALLOC(pCol, DEAL_RES_ERROR);
      CHECK_CODE(nodesListAppend(pCxt->pList, pCol), DEAL_RES_ERROR);
X
Xiaoyu Wang 已提交
240 241 242 243 244
      return DEAL_RES_IGNORE_CHILD;
    }
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION:
    case QUERY_NODE_FUNCTION: {
X
Xiaoyu Wang 已提交
245 246
      SExprNode* pExpr = (SExprNode*)pNode;
      SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
X
Xiaoyu Wang 已提交
247
      CHECK_ALLOC(pCol, DEAL_RES_ERROR);
X
Xiaoyu Wang 已提交
248 249
      pCol->node.resType = pExpr->resType;
      strcpy(pCol->colName, pExpr->aliasName);
X
Xiaoyu Wang 已提交
250
      CHECK_CODE(nodesListAppend(pCxt->pList, (SNode*)pCol), DEAL_RES_ERROR);
X
Xiaoyu Wang 已提交
251
      return DEAL_RES_IGNORE_CHILD;
X
Xiaoyu Wang 已提交
252
    }
X
Xiaoyu Wang 已提交
253 254
    default:
      break;
X
Xiaoyu Wang 已提交
255
  }
X
Xiaoyu Wang 已提交
256 257 258 259

  return DEAL_RES_CONTINUE;
}

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

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

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

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

  // set grouyp keys, agg funcs and having conditions
X
Xiaoyu Wang 已提交
284 285 286 287 288 289 290 291
  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 已提交
292 293 294 295 296

  // 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 已提交
297 298 299 300
  if (NULL != pSelect->pHaving) {
    pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
    CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg);
  }
X
Xiaoyu Wang 已提交
301

X
Xiaoyu Wang 已提交
302
  // set the output
X
Xiaoyu Wang 已提交
303
  pAgg->node.pTargets = nodesMakeList();
X
Xiaoyu Wang 已提交
304
  CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg);
X
Xiaoyu Wang 已提交
305 306 307 308 309 310 311 312 313 314
  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 已提交
315
  
X
Xiaoyu Wang 已提交
316 317 318
  return (SLogicNode*)pAgg;
}

X
Xiaoyu Wang 已提交
319
static SNodeList* createColumnByProjections(SLogicPlanContext* pCxt, SNodeList* pExprs) {
X
Xiaoyu Wang 已提交
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
  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 已提交
341
static SLogicNode* createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect) {
X
Xiaoyu Wang 已提交
342 343 344 345
  SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
  CHECK_ALLOC(pProject, NULL);
  pProject->node.id = pCxt->planNodeId++;

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

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

  return (SLogicNode*)pProject;
}

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

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

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

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 已提交
406
  int16_t dataBlockId;
X
Xiaoyu Wang 已提交
407 408 409 410 411
  int16_t slotId;
} SSlotIndex;

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

static int32_t getSlotKey(SNode* pNode, char* pKey) {
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
X
Xiaoyu Wang 已提交
418 419 420 421 422
    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 已提交
423
  }
X
Xiaoyu Wang 已提交
424
  return sprintf(pKey, "%s", ((SExprNode*)pNode)->aliasName);
X
Xiaoyu Wang 已提交
425 426 427 428 429 430 431 432
}

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 已提交
433
  pSlot->output = false;
X
Xiaoyu Wang 已提交
434 435 436
  return (SNode*)pSlot;
}

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

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

    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 已提交
456
    if (NULL == taosArrayInsert(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId, &pHash)) {
X
Xiaoyu Wang 已提交
457 458 459 460
      taosHashCleanup(pHash);
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  } else {
X
Xiaoyu Wang 已提交
461
    pHash = taosArrayGetP(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId);
X
Xiaoyu Wang 已提交
462 463 464
  }
  
  SNode* pNode = NULL;
X
Xiaoyu Wang 已提交
465
  int16_t slotId = taosHashGetSize(pHash);
X
Xiaoyu Wang 已提交
466 467 468
  FOREACH(pNode, pList) {
    SNode* pSlot = createSlotDesc(pCxt, pNode, slotId);
    CHECK_ALLOC(pSlot, TSDB_CODE_OUT_OF_MEMORY);
X
Xiaoyu Wang 已提交
469
    if (TSDB_CODE_SUCCESS != nodesListAppend(pDataBlockDesc->pSlots, (SNode*)pSlot)) {
X
Xiaoyu Wang 已提交
470 471 472 473
      nodesDestroyNode(pSlot);
      return TSDB_CODE_OUT_OF_MEMORY;
    }

X
Xiaoyu Wang 已提交
474
    SSlotIndex index = { .dataBlockId = pDataBlockDesc->dataBlockId, .slotId = slotId };
X
Xiaoyu Wang 已提交
475 476 477 478
    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 已提交
479
    SNode* pTarget = createTarget(pNode, pDataBlockDesc->dataBlockId, slotId);
X
Xiaoyu Wang 已提交
480 481 482
    CHECK_ALLOC(pTarget, TSDB_CODE_OUT_OF_MEMORY);
    REPLACE_NODE(pTarget);
  
X
Xiaoyu Wang 已提交
483 484 485 486 487
    ++slotId;
  }
  return TSDB_CODE_SUCCESS;
}

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

X
Xiaoyu Wang 已提交
494 495 496
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 已提交
497
    char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN];
X
Xiaoyu Wang 已提交
498 499 500 501
    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 已提交
502
    }
X
Xiaoyu Wang 已提交
503
    // pIndex is definitely not NULL, otherwise it is a bug
X
Xiaoyu Wang 已提交
504
    ((SColumnNode*)pNode)->dataBlockId = pIndex->dataBlockId;
X
Xiaoyu Wang 已提交
505 506 507
    ((SColumnNode*)pNode)->slotId = pIndex->slotId;
    CHECK_ALLOC(pNode, DEAL_RES_ERROR);
    return DEAL_RES_IGNORE_CHILD;
X
Xiaoyu Wang 已提交
508 509 510 511
  }
  return DEAL_RES_CONTINUE;
}

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

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

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

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

X
Xiaoyu Wang 已提交
556 557
static int32_t setSlotOutput(SPhysiPlanContext* pCxt, SNodeList* pTargets, SDataBlockDescNode* pDataBlockDesc) {
  SHashObj* pHash = taosArrayGetP(pCxt->pLocationHelper, pDataBlockDesc->dataBlockId);
X
Xiaoyu Wang 已提交
558 559 560 561 562
  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 已提交
563
    ((SSlotDescNode*)nodesListGetNode(pDataBlockDesc->pSlots, pIndex->slotId))->output = true;
X
Xiaoyu Wang 已提交
564
  }
X
Xiaoyu Wang 已提交
565 566 567 568 569 570 571 572 573
  
  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 已提交
574 575
  // 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 已提交
576 577 578

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

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

  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 已提交
591
  STagScanPhysiNode* pTagScan = (STagScanPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN);
X
Xiaoyu Wang 已提交
592 593 594 595 596 597
  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 已提交
598
  STableScanPhysiNode* pTableScan = (STableScanPhysiNode*)makePhysiNode(pCxt, QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN);
X
Xiaoyu Wang 已提交
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
  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 已提交
618
  return NULL;
X
Xiaoyu Wang 已提交
619 620
}

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

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

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

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

X
Xiaoyu Wang 已提交
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
  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 已提交
697
  }
X
Xiaoyu Wang 已提交
698 699 700 701 702 703 704 705
  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 已提交
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 770 771
  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 已提交
772 773
  SDataBlockDescNode* pChildTupe = &(((SPhysiNode*)nodesListGetNode(pChildren, 0))->outputDataBlockDesc);
  // push down expression to outputDataBlockDesc of child node
X
Xiaoyu Wang 已提交
774
  if (NULL != pPrecalcExprs) {
X
Xiaoyu Wang 已提交
775
    pAgg->pExprs = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pPrecalcExprs);
X
Xiaoyu Wang 已提交
776
    CHECK_ALLOC(pAgg->pExprs, (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
777
    CHECK_CODE(addDataBlockDesc(pCxt, pAgg->pExprs, pChildTupe), (SPhysiNode*)pAgg);
X
Xiaoyu Wang 已提交
778 779 780
  }

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

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

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

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

  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 已提交
803
  pProject->pProjections = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->outputDataBlockDesc.dataBlockId, -1, pProjectLogicNode->pProjections);
X
Xiaoyu Wang 已提交
804
  CHECK_ALLOC(pProject->pProjections, (SPhysiNode*)pProject);
X
Xiaoyu Wang 已提交
805
  CHECK_CODE(addDataBlockDesc(pCxt, pProject->pProjections, &pProject->node.outputDataBlockDesc), (SPhysiNode*)pProject);
X
Xiaoyu Wang 已提交
806 807

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

  return (SPhysiNode*)pProject;
}

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

  SNode* pLogicChild;
  FOREACH(pLogicChild, pLogicPlan->pChildren) {
    SNode* pChildPhyNode = (SNode*)createPhysiNode(pCxt, (SLogicNode*)pLogicChild);
X
Xiaoyu Wang 已提交
819
    if (TSDB_CODE_SUCCESS != nodesListAppend(pChildren, pChildPhyNode)) {
X
Xiaoyu Wang 已提交
820
      pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
X
Xiaoyu Wang 已提交
821
      nodesDestroyList(pChildren);
X
Xiaoyu Wang 已提交
822 823 824 825 826 827 828 829 830 831
      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 已提交
832
      pPhyNode = createJoinPhysiNode(pCxt, pChildren, (SJoinLogicNode*)pLogicPlan);
X
Xiaoyu Wang 已提交
833 834
      break;
    case QUERY_NODE_LOGIC_PLAN_AGG:
X
Xiaoyu Wang 已提交
835
      pPhyNode = createAggPhysiNode(pCxt, pChildren, (SAggLogicNode*)pLogicPlan);
X
Xiaoyu Wang 已提交
836 837
      break;
    case QUERY_NODE_LOGIC_PLAN_PROJECT:
X
Xiaoyu Wang 已提交
838
      pPhyNode = createProjectPhysiNode(pCxt, pChildren, (SProjectLogicNode*)pLogicPlan);
X
Xiaoyu Wang 已提交
839 840 841 842 843
      break;
    default:
      break;
  }

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

  return pPhyNode;
}

int32_t createPhysiPlan(SLogicNode* pLogicNode, SPhysiNode** pPhyNode) {
X
Xiaoyu Wang 已提交
854 855
  SPhysiPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .nextDataBlockId = 0, .pLocationHelper = taosArrayInit(32, POINTER_BYTES) };
  if (NULL == cxt.pLocationHelper) {
X
Xiaoyu Wang 已提交
856 857 858 859 860 861 862 863 864 865 866 867 868
    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;
}