planLogicCreater.c 22.1 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

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

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

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

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

225 226
  nodesClearList(pCols);

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

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

X
Xiaoyu Wang 已提交
236 237 238 239 240 241 242
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);
    }
243
  }
X
Xiaoyu Wang 已提交
244
  return code;
245 246
}

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

  pJoin->joinType = pJoinTable->joinType;

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

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

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

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

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

X
Xiaoyu Wang 已提交
287
  // set the output
X
Xiaoyu Wang 已提交
288 289 290 291 292 293 294 295 296 297 298 299
  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;
300
  } else {
X
Xiaoyu Wang 已提交
301
    nodesDestroyNode(pJoin);
302 303
  }

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

X
Xiaoyu Wang 已提交
307
static int32_t doCreateLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable, SLogicNode** pLogicNode) {
X
Xiaoyu Wang 已提交
308 309
  switch (nodeType(pTable)) {
    case QUERY_NODE_REAL_TABLE:
X
Xiaoyu Wang 已提交
310
      return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable, pLogicNode);
X
Xiaoyu Wang 已提交
311
    case QUERY_NODE_TEMP_TABLE:
X
Xiaoyu Wang 已提交
312
      return createSubqueryLogicNode(pCxt, pSelect, (STempTableNode*)pTable, pLogicNode);
X
Xiaoyu Wang 已提交
313
    case QUERY_NODE_JOIN_TABLE:
X
Xiaoyu Wang 已提交
314
      return createJoinLogicNode(pCxt, pSelect, (SJoinTableNode*)pTable, pLogicNode);
X
Xiaoyu Wang 已提交
315 316
    default:
      break;
317
  }
X
Xiaoyu Wang 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
  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 已提交
335
static SColumnNode* createColumnByExpr(const char* pStmtName, SExprNode* pExpr) {
X
Xiaoyu Wang 已提交
336 337 338 339 340 341
  SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN);
  if (NULL == pCol) {
    return NULL;
  }
  pCol->node.resType = pExpr->resType;
  strcpy(pCol->colName, pExpr->aliasName);
X
Xiaoyu Wang 已提交
342
  strcpy(pCol->tableAlias, pStmtName);
X
Xiaoyu Wang 已提交
343
  return pCol;
344 345
}

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

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

380 381 382 383 384
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;
  }
385

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

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

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

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

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

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

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

X
Xiaoyu Wang 已提交
442
  // set the output
443 444 445 446 447 448 449 450 451 452 453 454 455 456
  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 已提交
457
}
458

X
Xiaoyu Wang 已提交
459
static int32_t createWindowLogicNodeFinalize(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SWindowLogicNode* pWindow, SLogicNode** pLogicNode) {
460
  int32_t code = nodesCollectFuncs(pSelect, fmIsWindowClauseFunc, &pWindow->pFuncs);
X
Xiaoyu Wang 已提交
461 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

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

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

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

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

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

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

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

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

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

X
Xiaoyu Wang 已提交
538 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
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 已提交
573
static int32_t createColumnByProjections(SLogicPlanContext* pCxt, const char* pStmtName, SNodeList* pExprs, SNodeList** pCols) {
X
Xiaoyu Wang 已提交
574
  SNodeList* pList = nodesMakeList();
X
Xiaoyu Wang 已提交
575
  if (NULL == pList) {
576 577 578
    return TSDB_CODE_OUT_OF_MEMORY;
  }

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

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

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

597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
  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 已提交
613
  int32_t code = TSDB_CODE_SUCCESS;
614

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

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

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

631
  return code;
632 633
}

634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
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;
}

655 656 657 658 659
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);
660
  }
661 662 663
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createPartitionLogicNode, &pRoot);
  }
664 665
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createAggLogicNode, &pRoot);
X
Xiaoyu Wang 已提交
666
  }
667 668 669
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createDistinctLogicNode, &pRoot);
  }
X
Xiaoyu Wang 已提交
670 671 672
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createSortLogicNode, &pRoot);
  }
673 674
  if (TSDB_CODE_SUCCESS == code) {
    code = createChildLogicNode(pCxt, pSelect, createProjectLogicNode, &pRoot);
X
Xiaoyu Wang 已提交
675
  }
676 677 678 679 680

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

  return code;
684 685
}

686 687 688 689
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;
}

690 691 692 693 694
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;
  }
695
  pModif->pDataBlocks = pStmt->pDataBlocks;
696
  pModif->msgType = getMsgType(pStmt->sqlNodeType);
697 698
  *pLogicNode = (SLogicNode*)pModif;
  return TSDB_CODE_SUCCESS;
699 700
}

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

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