planLogicCreater.c 24.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
Xiaoyu Wang 已提交
86
  nodesWalkExprs(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
  if (TSDB_CODE_SUCCESS == code) {
    pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
D
dapan1121 已提交
291
    if (NULL == pJoin->node.pTargets) {
X
Xiaoyu Wang 已提交
292 293 294 295 296 297 298 299 300
      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
  nodesWalkExprs(pExprs, doCreateColumn, &cxt);
X
Xiaoyu Wang 已提交
388 389
  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

  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;
}

480 481 482 483 484 485 486 487 488 489 490 491
static int32_t createWindowLogicNodeByState(SLogicPlanContext* pCxt, SStateWindowNode* pState, 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_STATE;
  pWindow->pStateExpr = nodesCloneNode(pState->pExpr);

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

X
Xiaoyu Wang 已提交
492 493 494 495 496 497 498 499 500 501 502 503
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);
}

504
static int32_t createWindowLogicNodeByInterval(SLogicPlanContext* pCxt, SIntervalWindowNode* pInterval, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
505
  SWindowLogicNode* pWindow = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW);
506 507 508
  if (NULL == pWindow) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
X
Xiaoyu Wang 已提交
509 510 511

  pWindow->winType = WINDOW_TYPE_INTERVAL;
  pWindow->interval = ((SValueNode*)pInterval->pInterval)->datum.i;
X
Xiaoyu Wang 已提交
512
  pWindow->intervalUnit = ((SValueNode*)pInterval->pInterval)->unit;
X
Xiaoyu Wang 已提交
513
  pWindow->offset = (NULL != pInterval->pOffset ? ((SValueNode*)pInterval->pOffset)->datum.i : 0);
514
  pWindow->sliding = (NULL != pInterval->pSliding ? ((SValueNode*)pInterval->pSliding)->datum.i : pWindow->interval);
X
Xiaoyu Wang 已提交
515
  pWindow->slidingUnit = (NULL != pInterval->pSliding ? ((SValueNode*)pInterval->pSliding)->unit : pWindow->intervalUnit);
516

X
bugfix  
Xiaoyu Wang 已提交
517 518 519 520 521 522
  pWindow->pTspk = nodesCloneNode(pInterval->pCol);
  if (NULL == pWindow->pTspk) {
    nodesDestroyNode(pWindow);
    return TSDB_CODE_OUT_OF_MEMORY;
  }

X
Xiaoyu Wang 已提交
523 524
  if (NULL != pInterval->pFill) {
    pWindow->pFill = nodesCloneNode(pInterval->pFill);
525
    if (NULL == pWindow->pFill) {
X
Xiaoyu Wang 已提交
526 527
      nodesDestroyNode(pWindow);
      return TSDB_CODE_OUT_OF_MEMORY;
528
    }
X
Xiaoyu Wang 已提交
529 530
  }

X
Xiaoyu Wang 已提交
531
  return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
X
Xiaoyu Wang 已提交
532 533
}

534
static int32_t createWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
535
  if (NULL == pSelect->pWindow) {
536
    return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
537 538 539
  }

  switch (nodeType(pSelect->pWindow)) {
540 541
    case QUERY_NODE_STATE_WINDOW:
      return createWindowLogicNodeByState(pCxt, (SStateWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
X
Xiaoyu Wang 已提交
542 543
    case QUERY_NODE_SESSION_WINDOW:
      return createWindowLogicNodeBySession(pCxt, (SSessionWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
X
Xiaoyu Wang 已提交
544
    case QUERY_NODE_INTERVAL_WINDOW:
X
Xiaoyu Wang 已提交
545
      return createWindowLogicNodeByInterval(pCxt, (SIntervalWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
X
Xiaoyu Wang 已提交
546 547 548 549
    default:
      break;
  }

550
  return TSDB_CODE_FAILED;
X
Xiaoyu Wang 已提交
551 552
}

X
Xiaoyu Wang 已提交
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
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 已提交
588
static int32_t createColumnByProjections(SLogicPlanContext* pCxt, const char* pStmtName, SNodeList* pExprs, SNodeList** pCols) {
X
Xiaoyu Wang 已提交
589
  SNodeList* pList = nodesMakeList();
X
Xiaoyu Wang 已提交
590
  if (NULL == pList) {
591 592 593
    return TSDB_CODE_OUT_OF_MEMORY;
  }

X
Xiaoyu Wang 已提交
594
  SNode* pNode;
X
Xiaoyu Wang 已提交
595
  FOREACH(pNode, pExprs) {    
X
Xiaoyu Wang 已提交
596
    if (TSDB_CODE_SUCCESS != nodesListAppend(pList, createColumnByExpr(pStmtName, (SExprNode*)pNode))) {
X
Xiaoyu Wang 已提交
597 598
      nodesDestroyList(pList);
      return TSDB_CODE_OUT_OF_MEMORY;
599 600
    }
  }
601

X
Xiaoyu Wang 已提交
602 603
  *pCols = pList;
  return TSDB_CODE_SUCCESS;
604 605
}

X
Xiaoyu Wang 已提交
606
static int32_t createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
607
  SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
X
Xiaoyu Wang 已提交
608
  if (NULL == pProject) {
609 610 611
    return TSDB_CODE_OUT_OF_MEMORY;
  }

612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
  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 已提交
628
  int32_t code = TSDB_CODE_SUCCESS;
629

X
Xiaoyu Wang 已提交
630
  pProject->pProjections = nodesCloneList(pSelect->pProjectionList);
X
Xiaoyu Wang 已提交
631 632
  if (NULL == pProject->pProjections) {
    code = TSDB_CODE_OUT_OF_MEMORY;
633
  }
X
Xiaoyu Wang 已提交
634
  strcpy(pProject->stmtName, pSelect->stmtName);
635 636

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

640
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
641 642 643
    *pLogicNode = (SLogicNode*)pProject;
  } else {
    nodesDestroyNode(pProject);
644
  }
645

646
  return code;
647 648
}

649 650 651 652 653 654 655 656 657 658
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;
  }

659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
  SNodeList* pCols = NULL;
  int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_PARTITION_BY, NULL, &pCols);
  if (TSDB_CODE_SUCCESS == code && NULL != pCols) {
    pPartition->node.pTargets = nodesCloneList(pCols);
    if (NULL == pPartition->node.pTargets) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
  }

  if (TSDB_CODE_SUCCESS == code) {
    pPartition->pPartitionKeys = nodesCloneList(pSelect->pPartitionByList);
    if (NULL == pPartition->pPartitionKeys) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
  }

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

  return code;
682 683 684 685 686 687 688 689
  return TSDB_CODE_SUCCESS;
}

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

690 691 692 693 694 695 696 697 698 699 700 701 702 703
  SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG);
  if (NULL == pAgg) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  int32_t code = TSDB_CODE_SUCCESS;
  // set grouyp keys, agg funcs and having conditions
  pAgg->pGroupKeys = nodesCloneList(pSelect->pProjectionList);
  if (NULL == pAgg->pGroupKeys) {
    code = TSDB_CODE_OUT_OF_MEMORY;
  }

  // rewrite the expression in subsequent clauses
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
704
    code = rewriteExpr(pAgg->pGroupKeys, pSelect, SQL_CLAUSE_DISTINCT);
705 706 707 708 709 710 711 712 713 714 715 716 717 718
  }

  // set the output
  if (TSDB_CODE_SUCCESS == code) {
    code = createColumnByRewriteExps(pCxt, pAgg->pGroupKeys, &pAgg->node.pTargets);
  }

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

  return code;
719 720
}

721 722 723 724 725
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);
726
  }
727 728 729
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createPartitionLogicNode, &pRoot);
  }
730 731
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createAggLogicNode, &pRoot);
X
Xiaoyu Wang 已提交
732
  }
733 734 735
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createDistinctLogicNode, &pRoot);
  }
X
Xiaoyu Wang 已提交
736 737 738
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createSortLogicNode, &pRoot);
  }
739 740
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createProjectLogicNode, &pRoot);
X
Xiaoyu Wang 已提交
741
  }
742 743 744 745 746

  if (TSDB_CODE_SUCCESS == code) {
    *pLogicNode = pRoot;
  } else {
    nodesDestroyNode(pRoot);
X
Xiaoyu Wang 已提交
747
  }
748 749

  return code;
750 751
}

752 753 754 755
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;
}

756 757 758 759 760
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 已提交
761
  TSWAP(pModif->pDataBlocks, pStmt->pDataBlocks, SArray*);
762
  pModif->msgType = getMsgType(pStmt->sqlNodeType);
763 764
  *pLogicNode = (SLogicNode*)pModif;
  return TSDB_CODE_SUCCESS;
765 766
}

767
static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
768 769
  switch (nodeType(pStmt)) {
    case QUERY_NODE_SELECT_STMT:
770
      return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt, pLogicNode);
771
    case QUERY_NODE_VNODE_MODIF_STMT:
772
      return createVnodeModifLogicNode(pCxt, (SVnodeModifOpStmt*)pStmt, pLogicNode);
773 774
    case QUERY_NODE_EXPLAIN_STMT:
      return createQueryLogicNode(pCxt, ((SExplainStmt*)pStmt)->pQuery, pLogicNode);
X
Xiaoyu Wang 已提交
775 776 777
    default:
      break;
  }
778
  return TSDB_CODE_FAILED;
779 780
}

X
Xiaoyu Wang 已提交
781
int32_t createLogicPlan(SPlanContext* pCxt, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
782
  SLogicPlanContext cxt = { .pPlanCxt = pCxt };
783 784 785
  int32_t code = createQueryLogicNode(&cxt, pCxt->pAstRoot, pLogicNode);
  if (TSDB_CODE_SUCCESS != code) {
    return code;
X
Xiaoyu Wang 已提交
786 787
  }
  return TSDB_CODE_SUCCESS;
788
}