planLogicCreater.c 22.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 "planInt.h"
17

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

typedef struct SLogicPlanContext {
21
  SPlanContext* pPlanCxt;
X
Xiaoyu Wang 已提交
22 23
} SLogicPlanContext;

X
Xiaoyu Wang 已提交
24 25
typedef int32_t (*FCreateLogicNode)(SLogicPlanContext*, SSelectStmt*, SLogicNode**);

26 27
static int32_t doCreateLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable, SLogicNode** pLogicNode);
static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogicNode** pLogicNode);
X
Xiaoyu Wang 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

typedef struct SRewriteExprCxt {
  int32_t errCode;
  SNodeList* pExprs;
} SRewriteExprCxt;

static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
  switch (nodeType(*pNode)) {
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION:
    case QUERY_NODE_FUNCTION: {
      SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext;
      SNode* pExpr;
      int32_t index = 0;
      FOREACH(pExpr, pCxt->pExprs) {
        if (QUERY_NODE_GROUPING_SET == nodeType(pExpr)) {
          pExpr = nodesListGetNode(((SGroupingSetNode*)pExpr)->pParameterList, 0);
        }
        if (nodesEqualNode(pExpr, *pNode)) {
          SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
X
Xiaoyu Wang 已提交
48 49 50
          if (NULL == pCol) {
            return DEAL_RES_ERROR;
          }
X
Xiaoyu Wang 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64
          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;
      }
      break;
    }
    default:
      break;
H
Haojun Liao 已提交
65 66
  }

X
Xiaoyu Wang 已提交
67
  return DEAL_RES_CONTINUE;
X
Xiaoyu Wang 已提交
68 69
}

X
Xiaoyu Wang 已提交
70 71 72 73 74
static EDealRes doNameExpr(SNode* pNode, void* pContext) {
  switch (nodeType(pNode)) {
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION:
    case QUERY_NODE_FUNCTION: {
X
bugfix  
Xiaoyu Wang 已提交
75
      sprintf(((SExprNode*)pNode)->aliasName, "#expr_%p", pNode);
X
Xiaoyu Wang 已提交
76
      return DEAL_RES_IGNORE_CHILD;
X
Xiaoyu Wang 已提交
77 78
    }
    default:
X
Xiaoyu Wang 已提交
79
      break;
X
Xiaoyu Wang 已提交
80
  }
81

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

X
Xiaoyu Wang 已提交
85
static int32_t rewriteExpr(SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) {
X
bugfix  
Xiaoyu Wang 已提交
86
  nodesWalkList(pExprs, doNameExpr, NULL);
X
Xiaoyu Wang 已提交
87 88 89
  SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs };
  nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
  return cxt.errCode;
90 91
}

92 93 94 95 96
static int32_t pushLogicNode(SLogicPlanContext* pCxt, SLogicNode** pOldRoot, SLogicNode* pNewRoot) {
  if (NULL == pNewRoot->pChildren) {
    pNewRoot->pChildren = nodesMakeList();
    if (NULL == pNewRoot->pChildren) {
      return TSDB_CODE_OUT_OF_MEMORY;
H
Haojun Liao 已提交
97
    }
98
  }
99 100
  if (TSDB_CODE_SUCCESS != nodesListAppend(pNewRoot->pChildren, (SNode*)*pOldRoot)) {
    return TSDB_CODE_OUT_OF_MEMORY;
101 102
  }

103 104
  (*pOldRoot)->pParent = pNewRoot;
  *pOldRoot = pNewRoot;
105

106 107
  return TSDB_CODE_SUCCESS;
}
108

X
Xiaoyu Wang 已提交
109 110 111
static int32_t createChildLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, FCreateLogicNode func, SLogicNode** pRoot) {
  SLogicNode* pNode = NULL;
  int32_t code = func(pCxt, pSelect, &pNode);
X
Xiaoyu Wang 已提交
112
  if (TSDB_CODE_SUCCESS == code && NULL != pNode) {
X
Xiaoyu Wang 已提交
113
    code = pushLogicNode(pCxt, pRoot, pNode);
114
  }
X
Xiaoyu Wang 已提交
115 116
  if (TSDB_CODE_SUCCESS != code) {
    nodesDestroyNode(pNode);
X
Xiaoyu Wang 已提交
117
  }
X
Xiaoyu Wang 已提交
118
  return code;
119 120
}

X
Xiaoyu Wang 已提交
121 122 123 124 125
static EScanType getScanType(SLogicPlanContext* pCxt, SNodeList* pScanCols, STableMeta* pMeta) {
  if (pCxt->pPlanCxt->topicQuery || pCxt->pPlanCxt->streamQuery) {
    return SCAN_TYPE_STREAM;
  }

X
Xiaoyu Wang 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
  if (NULL == pScanCols) {
    // select count(*) from t
    return SCAN_TYPE_TABLE;
  }

  if (TSDB_SYSTEM_TABLE == pMeta->tableType) {
    return SCAN_TYPE_SYSTEM_TABLE;
  }

  SNode* pCol = NULL;
  FOREACH(pCol, pScanCols) {
    if (COLUMN_TYPE_COLUMN == ((SColumnNode*)pCol)->colType) {
      return SCAN_TYPE_TABLE;
    }
  }

  return SCAN_TYPE_TAG;
}

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
static SNodeptr createPrimaryKeyCol(uint64_t tableId) {
  SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN);
  if (NULL == pCol) {
    return NULL;
  }
  pCol->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP;
  pCol->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes;
  pCol->tableId = tableId;
  pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
  pCol->colType = COLUMN_TYPE_COLUMN;
  strcpy(pCol->colName, "#primarykey");
  return pCol;
}

static int32_t addPrimaryKeyCol(uint64_t tableId, SNodeList** pCols) {
  if (NULL == *pCols) {
    *pCols = nodesMakeList();
    if (NULL == *pCols) {
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  }

  bool found = false;
  SNode* pCol = NULL;
  FOREACH(pCol, *pCols) {
    if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pCol)->colId) {
      found = true;
      break;
    }
  }

  if (!found) {
    if (TSDB_CODE_SUCCESS != nodesListStrictAppend(*pCols, createPrimaryKeyCol(tableId))) {
      nodesDestroyList(*pCols);
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  }
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
185
static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
186
  SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN);
X
Xiaoyu Wang 已提交
187
  if (NULL == pScan) {
188
    return TSDB_CODE_OUT_OF_MEMORY;
189 190
  }

X
Xiaoyu Wang 已提交
191 192
  TSWAP(pScan->pMeta, pRealTable->pMeta, STableMeta*);
  TSWAP(pScan->pVgroupList, pRealTable->pVgroupList, SVgroupsInfo*);
X
Xiaoyu Wang 已提交
193 194 195 196 197 198
  pScan->scanFlag = MAIN_SCAN;
  pScan->scanRange = TSWINDOW_INITIALIZER;  
  pScan->tableName.type = TSDB_TABLE_NAME_T;
  pScan->tableName.acctId = pCxt->pPlanCxt->acctId;
  strcpy(pScan->tableName.dbname, pRealTable->table.dbName);
  strcpy(pScan->tableName.tname, pRealTable->table.tableName);
D
dapan1121 已提交
199
  pScan->showRewrite = pCxt->pPlanCxt->showRewrite;
200
  pScan->ratio = pRealTable->ratio;
201

X
Xiaoyu Wang 已提交
202 203
  // set columns to scan
  SNodeList* pCols = NULL;
X
Xiaoyu Wang 已提交
204
  int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols);
205 206 207 208 209
  if (TSDB_CODE_SUCCESS == code) {
    code = addPrimaryKeyCol(pScan->pMeta->uid, &pCols);
  }

  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
210
    pScan->pScanCols = nodesCloneList(pCols);
X
Xiaoyu Wang 已提交
211 212
    if (NULL == pScan) {
      code = TSDB_CODE_OUT_OF_MEMORY;
213
    }
214 215
  }

X
Xiaoyu Wang 已提交
216 217
  pScan->scanType = getScanType(pCxt, pCols, pScan->pMeta);

X
Xiaoyu Wang 已提交
218
  // set output
219
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
220
    pScan->node.pTargets = nodesCloneList(pCols);
X
Xiaoyu Wang 已提交
221 222 223
    if (NULL == pScan) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
224 225
  }

226 227
  nodesClearList(pCols);

X
Xiaoyu Wang 已提交
228 229 230 231 232
  if (TSDB_CODE_SUCCESS == code) {
    *pLogicNode = (SLogicNode*)pScan;
  } else {
    nodesDestroyNode(pScan);
  }
233

X
Xiaoyu Wang 已提交
234
  return code;
X
Xiaoyu Wang 已提交
235
}
236

X
Xiaoyu Wang 已提交
237 238 239 240 241 242 243
static int32_t createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable, SLogicNode** pLogicNode) {
  int32_t code = createQueryLogicNode(pCxt, pTable->pSubquery, pLogicNode);
  if (TSDB_CODE_SUCCESS == code) {
    SNode* pNode;
    FOREACH(pNode, (*pLogicNode)->pTargets) {
      strcpy(((SColumnNode*)pNode)->tableAlias, pTable->table.tableAlias);
    }
244
  }
X
Xiaoyu Wang 已提交
245
  return code;
246 247
}

X
Xiaoyu Wang 已提交
248
static int32_t createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
249
  SJoinLogicNode* pJoin = (SJoinLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_JOIN);
X
Xiaoyu Wang 已提交
250
  if (NULL == pJoin) {
251 252
    return TSDB_CODE_OUT_OF_MEMORY;
  }
X
Xiaoyu Wang 已提交
253 254 255

  pJoin->joinType = pJoinTable->joinType;

256
  int32_t code = TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
257 258 259

  // set left and right node
  pJoin->node.pChildren = nodesMakeList();
X
Xiaoyu Wang 已提交
260
  if (NULL == pJoin->node.pChildren) {
261
    code = TSDB_CODE_OUT_OF_MEMORY;
262 263
  }

X
Xiaoyu Wang 已提交
264
  SLogicNode* pLeft = NULL;
265
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
266 267 268 269
    code = doCreateLogicNodeByTable(pCxt, pSelect, pJoinTable->pLeft, &pLeft);
    if (TSDB_CODE_SUCCESS == code) {
      code = nodesListStrictAppend(pJoin->node.pChildren, (SNode*)pLeft);
    }
270
  }
271

X
Xiaoyu Wang 已提交
272
  SLogicNode* pRight = NULL;
273
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
274 275 276 277 278
    code = doCreateLogicNodeByTable(pCxt, pSelect, pJoinTable->pRight, &pRight);
    if (TSDB_CODE_SUCCESS == code) {
      code = nodesListStrictAppend(pJoin->node.pChildren, (SNode*)pRight);
    }
  }
X
Xiaoyu Wang 已提交
279 280

  // set on conditions
X
Xiaoyu Wang 已提交
281
  if (TSDB_CODE_SUCCESS == code && NULL != pJoinTable->pOnCond) {
X
Xiaoyu Wang 已提交
282
    pJoin->pOnConditions = nodesCloneNode(pJoinTable->pOnCond);
X
Xiaoyu Wang 已提交
283 284 285
    if (NULL == pJoin->pOnConditions) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
286 287
  }

X
Xiaoyu Wang 已提交
288
  // set the output
X
Xiaoyu Wang 已提交
289 290 291 292 293 294 295 296 297 298 299 300
  if (TSDB_CODE_SUCCESS == code) {
    pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
    if (NULL == pJoin->pOnConditions) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
    if (TSDB_CODE_SUCCESS == code) {
      code = nodesListStrictAppendList(pJoin->node.pTargets, nodesCloneList(pRight->pTargets));
    }
  }

  if (TSDB_CODE_SUCCESS == code) {
    *pLogicNode = (SLogicNode*)pJoin;
301
  } else {
X
Xiaoyu Wang 已提交
302
    nodesDestroyNode(pJoin);
303 304
  }

305
  return code;
X
Xiaoyu Wang 已提交
306
}
307

X
Xiaoyu Wang 已提交
308
static int32_t doCreateLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
309 310
  switch (nodeType(pTable)) {
    case QUERY_NODE_REAL_TABLE:
X
Xiaoyu Wang 已提交
311
      return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable, pLogicNode);
X
Xiaoyu Wang 已提交
312
    case QUERY_NODE_TEMP_TABLE:
X
Xiaoyu Wang 已提交
313
      return createSubqueryLogicNode(pCxt, pSelect, (STempTableNode*)pTable, pLogicNode);
X
Xiaoyu Wang 已提交
314
    case QUERY_NODE_JOIN_TABLE:
X
Xiaoyu Wang 已提交
315
      return createJoinLogicNode(pCxt, pSelect, (SJoinTableNode*)pTable, pLogicNode);
X
Xiaoyu Wang 已提交
316 317
    default:
      break;
318
  }
X
Xiaoyu Wang 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
  return TSDB_CODE_FAILED;
}

static int32_t createLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable, SLogicNode** pLogicNode) {
  SLogicNode* pNode = NULL;
  int32_t code = doCreateLogicNodeByTable(pCxt, pSelect, pTable, &pNode);
  if (TSDB_CODE_SUCCESS == code) {
    pNode->pConditions = nodesCloneNode(pSelect->pWhere);
    if (NULL != pSelect->pWhere && NULL == pNode->pConditions) {
      nodesDestroyNode(pNode);
      return TSDB_CODE_OUT_OF_MEMORY;
    }
    *pLogicNode = pNode;
  }
  return code;
}

X
Xiaoyu Wang 已提交
336
static SColumnNode* createColumnByExpr(const char* pStmtName, SExprNode* pExpr) {
X
Xiaoyu Wang 已提交
337 338 339 340 341 342
  SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN);
  if (NULL == pCol) {
    return NULL;
  }
  pCol->node.resType = pExpr->resType;
  strcpy(pCol->colName, pExpr->aliasName);
X
Xiaoyu Wang 已提交
343
  strcpy(pCol->tableAlias, pStmtName);
X
Xiaoyu Wang 已提交
344
  return pCol;
345 346
}

X
Xiaoyu Wang 已提交
347 348 349 350 351 352 353 354 355 356
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: {
      SNode* pCol = nodesCloneNode(pNode);
X
Xiaoyu Wang 已提交
357 358 359 360
      if (NULL == pCol) {
        return DEAL_RES_ERROR;
      }
      return (TSDB_CODE_SUCCESS == nodesListAppend(pCxt->pList, pCol) ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
361
    }
X
Xiaoyu Wang 已提交
362 363 364 365 366
    case QUERY_NODE_OPERATOR:
    case QUERY_NODE_LOGIC_CONDITION:
    case QUERY_NODE_FUNCTION: {
      SExprNode* pExpr = (SExprNode*)pNode;
      SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
X
Xiaoyu Wang 已提交
367 368 369
      if (NULL == pCol) {
        return DEAL_RES_ERROR;
      }
X
Xiaoyu Wang 已提交
370 371
      pCol->node.resType = pExpr->resType;
      strcpy(pCol->colName, pExpr->aliasName);
X
Xiaoyu Wang 已提交
372
      return (TSDB_CODE_SUCCESS == nodesListAppend(pCxt->pList, pCol) ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
373
    }
X
Xiaoyu Wang 已提交
374 375
    default:
      break;
376 377
  }

X
Xiaoyu Wang 已提交
378
  return DEAL_RES_CONTINUE;
379 380
}

381 382 383 384 385
static int32_t createColumnByRewriteExps(SLogicPlanContext* pCxt, SNodeList* pExprs, SNodeList** pList) {
  SCreateColumnCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .pList = (NULL == *pList ? nodesMakeList() : *pList) };
  if (NULL == cxt.pList) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
386

X
Xiaoyu Wang 已提交
387 388 389
  nodesWalkList(pExprs, doCreateColumn, &cxt);
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
    nodesDestroyList(cxt.pList);
390
    return cxt.errCode;
391
  }
392 393
  if (NULL == *pList) {
    *pList = cxt.pList;
394
  }
395
  return cxt.errCode;
X
Xiaoyu Wang 已提交
396
}
397

398
static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
399
  SNodeList* pAggFuncs = NULL;
400 401 402 403
  int32_t code = nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs);
  if (TSDB_CODE_SUCCESS != code) {
    return code;
  }
X
Xiaoyu Wang 已提交
404
  if (NULL == pAggFuncs && NULL == pSelect->pGroupByList) {
405
    return TSDB_CODE_SUCCESS;
406 407
  }

X
Xiaoyu Wang 已提交
408
  SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG);
409 410 411
  if (NULL == pAgg) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
412

X
Xiaoyu Wang 已提交
413 414 415
  // set grouyp keys, agg funcs and having conditions
  if (NULL != pSelect->pGroupByList) {
    pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
416 417 418
    if (NULL == pAgg->pGroupKeys) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }  
419
  }
420 421

  if (TSDB_CODE_SUCCESS == code && NULL != pAggFuncs) {
X
Xiaoyu Wang 已提交
422
    pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
423 424 425
    if (NULL == pAgg->pAggFuncs) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
426 427
  }

X
Xiaoyu Wang 已提交
428
  // rewrite the expression in subsequent clauses
429
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
430
    code = rewriteExpr(pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY);
431 432
  }
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
433
    code = rewriteExpr(pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY);
434
  }
435

436
  if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pHaving) {
X
Xiaoyu Wang 已提交
437
    pAgg->node.pConditions = nodesCloneNode(pSelect->pHaving);
438 439 440
    if (NULL == pAgg->node.pConditions) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
X
Xiaoyu Wang 已提交
441
  }
442

X
Xiaoyu Wang 已提交
443
  // set the output
444 445 446 447 448 449 450 451 452 453 454 455 456 457
  if (TSDB_CODE_SUCCESS == code && NULL != pAgg->pGroupKeys) {
    code = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys, &pAgg->node.pTargets);
  }
  if (TSDB_CODE_SUCCESS == code && NULL != pAgg->pAggFuncs) {
    code = createColumnByRewriteExps(pCxt, pAgg->pAggFuncs, &pAgg->node.pTargets);
  }

  if (TSDB_CODE_SUCCESS == code) {
    *pLogicNode = (SLogicNode*)pAgg;
  } else {
    nodesDestroyNode(pAgg);
  }

  return code;
X
Xiaoyu Wang 已提交
458
}
459

X
Xiaoyu Wang 已提交
460
static int32_t createWindowLogicNodeFinalize(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SWindowLogicNode* pWindow, SLogicNode** pLogicNode) {
461
  int32_t code = nodesCollectFuncs(pSelect, fmIsWindowClauseFunc, &pWindow->pFuncs);
X
Xiaoyu Wang 已提交
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491

  if (TSDB_CODE_SUCCESS == code) {
    code = rewriteExpr(pWindow->pFuncs, pSelect, SQL_CLAUSE_WINDOW);
  }

  if (TSDB_CODE_SUCCESS == code) {
    code = createColumnByRewriteExps(pCxt, pWindow->pFuncs, &pWindow->node.pTargets);
  }

  if (TSDB_CODE_SUCCESS == code) {
    *pLogicNode = (SLogicNode*)pWindow;
  } else {
    nodesDestroyNode(pWindow);
  }

  return code;
}

static int32_t createWindowLogicNodeBySession(SLogicPlanContext* pCxt, SSessionWindowNode* pSession, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
  SWindowLogicNode* pWindow = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW);
  if (NULL == pWindow) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  pWindow->winType = WINDOW_TYPE_SESSION;
  pWindow->sessionGap = ((SValueNode*)pSession->pGap)->datum.i;

  return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
}

492
static int32_t createWindowLogicNodeByInterval(SLogicPlanContext* pCxt, SIntervalWindowNode* pInterval, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
493
  SWindowLogicNode* pWindow = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW);
494 495 496
  if (NULL == pWindow) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
X
Xiaoyu Wang 已提交
497 498 499

  pWindow->winType = WINDOW_TYPE_INTERVAL;
  pWindow->interval = ((SValueNode*)pInterval->pInterval)->datum.i;
X
Xiaoyu Wang 已提交
500
  pWindow->intervalUnit = ((SValueNode*)pInterval->pInterval)->unit;
X
Xiaoyu Wang 已提交
501
  pWindow->offset = (NULL != pInterval->pOffset ? ((SValueNode*)pInterval->pOffset)->datum.i : 0);
502
  pWindow->sliding = (NULL != pInterval->pSliding ? ((SValueNode*)pInterval->pSliding)->datum.i : pWindow->interval);
X
Xiaoyu Wang 已提交
503
  pWindow->slidingUnit = (NULL != pInterval->pSliding ? ((SValueNode*)pInterval->pSliding)->unit : pWindow->intervalUnit);
504

X
bugfix  
Xiaoyu Wang 已提交
505 506 507 508 509 510
  pWindow->pTspk = nodesCloneNode(pInterval->pCol);
  if (NULL == pWindow->pTspk) {
    nodesDestroyNode(pWindow);
    return TSDB_CODE_OUT_OF_MEMORY;
  }

X
Xiaoyu Wang 已提交
511 512
  if (NULL != pInterval->pFill) {
    pWindow->pFill = nodesCloneNode(pInterval->pFill);
513
    if (NULL == pWindow->pFill) {
X
Xiaoyu Wang 已提交
514 515
      nodesDestroyNode(pWindow);
      return TSDB_CODE_OUT_OF_MEMORY;
516
    }
X
Xiaoyu Wang 已提交
517 518
  }

X
Xiaoyu Wang 已提交
519
  return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
X
Xiaoyu Wang 已提交
520 521
}

522
static int32_t createWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
523
  if (NULL == pSelect->pWindow) {
524
    return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
525 526 527
  }

  switch (nodeType(pSelect->pWindow)) {
X
Xiaoyu Wang 已提交
528 529
    case QUERY_NODE_SESSION_WINDOW:
      return createWindowLogicNodeBySession(pCxt, (SSessionWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
X
Xiaoyu Wang 已提交
530
    case QUERY_NODE_INTERVAL_WINDOW:
X
Xiaoyu Wang 已提交
531
      return createWindowLogicNodeByInterval(pCxt, (SIntervalWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
X
Xiaoyu Wang 已提交
532 533 534 535
    default:
      break;
  }

536
  return TSDB_CODE_FAILED;
X
Xiaoyu Wang 已提交
537 538
}

X
Xiaoyu Wang 已提交
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
static int32_t createSortLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
  if (NULL == pSelect->pOrderByList) {
    return TSDB_CODE_SUCCESS;
  }

  SSortLogicNode* pSort = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SORT);
  if (NULL == pSort) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  SNodeList* pCols = NULL;
  int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_ORDER_BY, NULL, &pCols);
  if (TSDB_CODE_SUCCESS == code && NULL != pCols) {
    pSort->node.pTargets = nodesCloneList(pCols);
    if (NULL == pSort->node.pTargets) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
  }

  if (TSDB_CODE_SUCCESS == code) {
    pSort->pSortKeys = nodesCloneList(pSelect->pOrderByList);
    if (NULL == pSort->pSortKeys) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
  }

  if (TSDB_CODE_SUCCESS == code) {
    *pLogicNode = (SLogicNode*)pSort;
  } else {
    nodesDestroyNode(pSort);
  }

  return code;
}

X
Xiaoyu Wang 已提交
574
static int32_t createColumnByProjections(SLogicPlanContext* pCxt, const char* pStmtName, SNodeList* pExprs, SNodeList** pCols) {
X
Xiaoyu Wang 已提交
575
  SNodeList* pList = nodesMakeList();
X
Xiaoyu Wang 已提交
576
  if (NULL == pList) {
577 578 579
    return TSDB_CODE_OUT_OF_MEMORY;
  }

X
Xiaoyu Wang 已提交
580
  SNode* pNode;
X
Xiaoyu Wang 已提交
581
  FOREACH(pNode, pExprs) {    
X
Xiaoyu Wang 已提交
582
    if (TSDB_CODE_SUCCESS != nodesListAppend(pList, createColumnByExpr(pStmtName, (SExprNode*)pNode))) {
X
Xiaoyu Wang 已提交
583 584
      nodesDestroyList(pList);
      return TSDB_CODE_OUT_OF_MEMORY;
585 586
    }
  }
587

X
Xiaoyu Wang 已提交
588 589
  *pCols = pList;
  return TSDB_CODE_SUCCESS;
590 591
}

X
Xiaoyu Wang 已提交
592
static int32_t createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
593
  SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
X
Xiaoyu Wang 已提交
594
  if (NULL == pProject) {
595 596 597
    return TSDB_CODE_OUT_OF_MEMORY;
  }

598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
  if (NULL != pSelect->pLimit) {
    pProject->limit = ((SLimitNode*)pSelect->pLimit)->limit;
    pProject->offset = ((SLimitNode*)pSelect->pLimit)->offset;
  } else {
    pProject->limit = -1;
    pProject->offset = -1;
  }

  if (NULL != pSelect->pSlimit) {
    pProject->slimit = ((SLimitNode*)pSelect->pSlimit)->limit;
    pProject->soffset = ((SLimitNode*)pSelect->pSlimit)->offset;
  } else {
    pProject->slimit = -1;
    pProject->soffset = -1;
  }

X
Xiaoyu Wang 已提交
614
  int32_t code = TSDB_CODE_SUCCESS;
615

X
Xiaoyu Wang 已提交
616
  pProject->pProjections = nodesCloneList(pSelect->pProjectionList);
X
Xiaoyu Wang 已提交
617 618
  if (NULL == pProject->pProjections) {
    code = TSDB_CODE_OUT_OF_MEMORY;
619
  }
X
Xiaoyu Wang 已提交
620
  strcpy(pProject->stmtName, pSelect->stmtName);
621 622

  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
623
    code = createColumnByProjections(pCxt, pSelect->stmtName, pSelect->pProjectionList, &pProject->node.pTargets);
624
  }
625

626
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
627 628 629
    *pLogicNode = (SLogicNode*)pProject;
  } else {
    nodesDestroyNode(pProject);
630
  }
631

632
  return code;
633 634
}

635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
static int32_t createPartitionLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
  if (NULL == pSelect->pPartitionByList) {
    return TSDB_CODE_SUCCESS;
  }

  SPartitionLogicNode* pPartition = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PARTITION);
  if (NULL == pPartition) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  return TSDB_CODE_SUCCESS;
}

static int32_t createDistinctLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
  if (!pSelect->isDistinct) {
    return TSDB_CODE_SUCCESS;
  }

  return TSDB_CODE_SUCCESS;
}

656 657 658 659 660
static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
  SLogicNode* pRoot = NULL;
  int32_t code = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable, &pRoot);
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createWindowLogicNode, &pRoot);
661
  }
662 663 664
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createPartitionLogicNode, &pRoot);
  }
665 666
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createAggLogicNode, &pRoot);
X
Xiaoyu Wang 已提交
667
  }
668 669 670
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createDistinctLogicNode, &pRoot);
  }
X
Xiaoyu Wang 已提交
671 672 673
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createSortLogicNode, &pRoot);
  }
674 675
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createProjectLogicNode, &pRoot);
X
Xiaoyu Wang 已提交
676
  }
677 678 679 680 681

  if (TSDB_CODE_SUCCESS == code) {
    *pLogicNode = pRoot;
  } else {
    nodesDestroyNode(pRoot);
X
Xiaoyu Wang 已提交
682
  }
683 684

  return code;
685 686
}

687 688 689 690
static int32_t getMsgType(ENodeType sqlType) {
  return (QUERY_NODE_CREATE_TABLE_STMT == sqlType || QUERY_NODE_CREATE_MULTI_TABLE_STMT == sqlType) ? TDMT_VND_CREATE_TABLE : TDMT_VND_SUBMIT;
}

691 692 693 694 695
static int32_t createVnodeModifLogicNode(SLogicPlanContext* pCxt, SVnodeModifOpStmt* pStmt, SLogicNode** pLogicNode) {
  SVnodeModifLogicNode* pModif = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VNODE_MODIF);
  if (NULL == pModif) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
X
bugfix  
Xiaoyu Wang 已提交
696
  TSWAP(pModif->pDataBlocks, pStmt->pDataBlocks, SArray*);
697
  pModif->msgType = getMsgType(pStmt->sqlNodeType);
698 699
  *pLogicNode = (SLogicNode*)pModif;
  return TSDB_CODE_SUCCESS;
700 701
}

702
static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
703 704
  switch (nodeType(pStmt)) {
    case QUERY_NODE_SELECT_STMT:
705
      return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt, pLogicNode);
706
    case QUERY_NODE_VNODE_MODIF_STMT:
707
      return createVnodeModifLogicNode(pCxt, (SVnodeModifOpStmt*)pStmt, pLogicNode);
708 709
    case QUERY_NODE_EXPLAIN_STMT:
      return createQueryLogicNode(pCxt, ((SExplainStmt*)pStmt)->pQuery, pLogicNode);
X
Xiaoyu Wang 已提交
710 711 712
    default:
      break;
  }
713
  return TSDB_CODE_FAILED;
714 715
}

X
Xiaoyu Wang 已提交
716
int32_t createLogicPlan(SPlanContext* pCxt, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
717
  SLogicPlanContext cxt = { .pPlanCxt = pCxt };
718 719 720
  int32_t code = createQueryLogicNode(&cxt, pCxt->pAstRoot, pLogicNode);
  if (TSDB_CODE_SUCCESS != code) {
    return code;
X
Xiaoyu Wang 已提交
721 722
  }
  return TSDB_CODE_SUCCESS;
723
}