nodesUtilFuncs.c 17.4 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/>.
 */

16
#include "cmdnodes.h"
X
Xiaoyu Wang 已提交
17
#include "nodesUtil.h"
X
Xiaoyu Wang 已提交
18
#include "plannodes.h"
19
#include "querynodes.h"
X
Xiaoyu Wang 已提交
20
#include "taos.h"
21
#include "taoserror.h"
X
Xiaoyu Wang 已提交
22
#include "thash.h"
23

24 25
static SNode* makeNode(ENodeType type, size_t size) {
  SNode* p = calloc(1, size);
26 27 28
  if (NULL == p) {
    return NULL;
  }
29 30 31
  setNodeType(p, type);
  return p;
}
32

X
Xiaoyu Wang 已提交
33
SNodeptr nodesMakeNode(ENodeType type) {
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
  switch (type) {
    case QUERY_NODE_COLUMN:
      return makeNode(type, sizeof(SColumnNode));
    case QUERY_NODE_VALUE:
      return makeNode(type, sizeof(SValueNode));
    case QUERY_NODE_OPERATOR:
      return makeNode(type, sizeof(SOperatorNode));
    case QUERY_NODE_LOGIC_CONDITION:
      return makeNode(type, sizeof(SLogicConditionNode));
    case QUERY_NODE_FUNCTION:
      return makeNode(type, sizeof(SFunctionNode));
    case QUERY_NODE_REAL_TABLE:
      return makeNode(type, sizeof(SRealTableNode));
    case QUERY_NODE_TEMP_TABLE:
      return makeNode(type, sizeof(STempTableNode));
    case QUERY_NODE_JOIN_TABLE:
      return makeNode(type, sizeof(SJoinTableNode));
    case QUERY_NODE_GROUPING_SET:
      return makeNode(type, sizeof(SGroupingSetNode));
    case QUERY_NODE_ORDER_BY_EXPR:
      return makeNode(type, sizeof(SOrderByExprNode));
    case QUERY_NODE_LIMIT:
      return makeNode(type, sizeof(SLimitNode));
    case QUERY_NODE_STATE_WINDOW:
      return makeNode(type, sizeof(SStateWindowNode));
    case QUERY_NODE_SESSION_WINDOW:
      return makeNode(type, sizeof(SSessionWindowNode));
    case QUERY_NODE_INTERVAL_WINDOW:
      return makeNode(type, sizeof(SIntervalWindowNode));
63 64 65 66 67 68
    case QUERY_NODE_NODE_LIST:
      return makeNode(type, sizeof(SNodeListNode));
    case QUERY_NODE_FILL:
      return makeNode(type, sizeof(SFillNode));
    case QUERY_NODE_RAW_EXPR:
      return makeNode(type, sizeof(SRawExprNode));
69 70 71 72 73 74 75 76
    case QUERY_NODE_TARGET:
      return makeNode(type, sizeof(STargetNode));
    case QUERY_NODE_DATABLOCK_DESC:
      return makeNode(type, sizeof(SDataBlockDescNode));
    case QUERY_NODE_SLOT_DESC:
      return makeNode(type, sizeof(SSlotDescNode));
    case QUERY_NODE_COLUMN_DEF:
      return makeNode(type, sizeof(SColumnDefNode));
X
Xiaoyu Wang 已提交
77 78
    case QUERY_NODE_DOWNSTREAM_SOURCE:
      return makeNode(type, sizeof(SDownstreamSourceNode));
79 80 81 82
    case QUERY_NODE_SET_OPERATOR:
      return makeNode(type, sizeof(SSetOperator));
    case QUERY_NODE_SELECT_STMT:
      return makeNode(type, sizeof(SSelectStmt));
83 84 85 86
    case QUERY_NODE_VNODE_MODIF_STMT:
      return makeNode(type, sizeof(SVnodeModifOpStmt));
    case QUERY_NODE_CREATE_DATABASE_STMT:
      return makeNode(type, sizeof(SCreateDatabaseStmt));
87 88 89
    case QUERY_NODE_DROP_DATABASE_STMT:
      return makeNode(type, sizeof(SDropDatabaseStmt));
    case QUERY_NODE_SHOW_DATABASES_STMT:
90
      return makeNode(type, sizeof(SShowStmt));
91 92
    case QUERY_NODE_CREATE_TABLE_STMT:
      return makeNode(type, sizeof(SCreateTableStmt));
93 94
    case QUERY_NODE_CREATE_SUBTABLE_CLAUSE:
      return makeNode(type, sizeof(SCreateSubTableClause));
95 96
    case QUERY_NODE_CREATE_MULTI_TABLE_STMT:
      return makeNode(type, sizeof(SCreateMultiTableStmt));
97 98 99 100
    case QUERY_NODE_DROP_TABLE_CLAUSE:
      return makeNode(type, sizeof(SDropTableClause));
    case QUERY_NODE_DROP_TABLE_STMT:
      return makeNode(type, sizeof(SDropTableStmt));
101 102
    case QUERY_NODE_DROP_SUPER_TABLE_STMT:
      return makeNode(type, sizeof(SDropSuperTableStmt));
103 104
    case QUERY_NODE_SHOW_TABLES_STMT:
    case QUERY_NODE_SHOW_STABLES_STMT:
105
      return makeNode(type, sizeof(SShowStmt));
106 107 108 109 110 111 112
    case QUERY_NODE_CREATE_USER_STMT:
      return makeNode(type, sizeof(SCreateUserStmt));
    case QUERY_NODE_ALTER_USER_STMT:
      return makeNode(type, sizeof(SAlterUserStmt));
    case QUERY_NODE_DROP_USER_STMT:
      return makeNode(type, sizeof(SDropUserStmt));
    case QUERY_NODE_SHOW_USERS_STMT:
113
      return makeNode(type, sizeof(SShowStmt));
114 115
    case QUERY_NODE_USE_DATABASE_STMT:
      return makeNode(type, sizeof(SUseDatabaseStmt));
116 117 118 119 120
    case QUERY_NODE_CREATE_DNODE_STMT:
      return makeNode(type, sizeof(SCreateDnodeStmt));
    case QUERY_NODE_DROP_DNODE_STMT:
      return makeNode(type, sizeof(SDropDnodeStmt));
    case QUERY_NODE_SHOW_DNODES_STMT:
121
      return makeNode(type, sizeof(SShowStmt));
122
    case QUERY_NODE_SHOW_VGROUPS_STMT:
X
Xiaoyu Wang 已提交
123
    case QUERY_NODE_SHOW_MNODES_STMT:
124
      return makeNode(type, sizeof(SShowStmt));
X
Xiaoyu Wang 已提交
125 126 127 128 129 130 131 132
    case QUERY_NODE_LOGIC_PLAN_SCAN:
      return makeNode(type, sizeof(SScanLogicNode));
    case QUERY_NODE_LOGIC_PLAN_JOIN:
      return makeNode(type, sizeof(SJoinLogicNode));
    case QUERY_NODE_LOGIC_PLAN_AGG:
      return makeNode(type, sizeof(SAggLogicNode));
    case QUERY_NODE_LOGIC_PLAN_PROJECT:
      return makeNode(type, sizeof(SProjectLogicNode));
133 134
    case QUERY_NODE_LOGIC_PLAN_VNODE_MODIF:
      return makeNode(type, sizeof(SVnodeModifLogicNode));
X
Xiaoyu Wang 已提交
135 136
    case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
      return makeNode(type, sizeof(SExchangeLogicNode));
X
Xiaoyu Wang 已提交
137 138
    case QUERY_NODE_LOGIC_PLAN_WINDOW:
      return makeNode(type, sizeof(SWindowLogicNode));
X
Xiaoyu Wang 已提交
139 140 141 142
    case QUERY_NODE_LOGIC_SUBPLAN:
      return makeNode(type, sizeof(SSubLogicPlan));
    case QUERY_NODE_LOGIC_PLAN:
      return makeNode(type, sizeof(SQueryLogicPlan));
X
Xiaoyu Wang 已提交
143 144 145 146
    case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
      return makeNode(type, sizeof(STagScanPhysiNode));
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
      return makeNode(type, sizeof(STableScanPhysiNode));
147 148 149 150
    case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
      return makeNode(type, sizeof(STableSeqScanPhysiNode));
    case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN:
      return makeNode(type, sizeof(SNode));
X
Xiaoyu Wang 已提交
151 152
    case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
      return makeNode(type, sizeof(SProjectPhysiNode));
X
Xiaoyu Wang 已提交
153 154 155 156
    case QUERY_NODE_PHYSICAL_PLAN_JOIN:
      return makeNode(type, sizeof(SJoinPhysiNode));
    case QUERY_NODE_PHYSICAL_PLAN_AGG:
      return makeNode(type, sizeof(SAggPhysiNode));
157 158 159 160
    case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE:
      return makeNode(type, sizeof(SExchangePhysiNode));
    case QUERY_NODE_PHYSICAL_PLAN_SORT:
      return makeNode(type, sizeof(SNode));
X
Xiaoyu Wang 已提交
161 162
    case QUERY_NODE_PHYSICAL_PLAN_INTERVAL:
      return makeNode(type, sizeof(SIntervalPhysiNode));
163 164 165 166
    case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
      return makeNode(type, sizeof(SDataDispatcherNode));
    case QUERY_NODE_PHYSICAL_PLAN_INSERT:
      return makeNode(type, sizeof(SDataInserterNode));
X
Xiaoyu Wang 已提交
167 168 169 170
    case QUERY_NODE_PHYSICAL_SUBPLAN:
      return makeNode(type, sizeof(SSubplan));
    case QUERY_NODE_PHYSICAL_PLAN:
      return makeNode(type, sizeof(SQueryPlan));
171 172 173
    default:
      break;
  }
174
  nodesError("nodesMakeNode unknown node = %s", nodesNodeName(type));
175
  return NULL;
176 177
}

X
Xiaoyu Wang 已提交
178 179
static EDealRes destroyNode(SNode** pNode, void* pContext) {
  switch (nodeType(*pNode)) {
D
dapan1121 已提交
180 181 182 183 184 185 186 187
    case QUERY_NODE_VALUE: {
      SValueNode* pValue = (SValueNode*)*pNode;
      
      tfree(pValue->literal);
      if (IS_VAR_DATA_TYPE(pValue->node.resType.type)) {
        tfree(pValue->datum.p);
      }
      
X
Xiaoyu Wang 已提交
188
      break;
D
dapan1121 已提交
189
    }
X
Xiaoyu Wang 已提交
190
    case QUERY_NODE_LOGIC_CONDITION:
X
Xiaoyu Wang 已提交
191
      nodesClearList(((SLogicConditionNode*)(*pNode))->pParameterList);
X
Xiaoyu Wang 已提交
192 193
      break;
    case QUERY_NODE_FUNCTION:
X
Xiaoyu Wang 已提交
194 195 196 197 198 199 200 201 202 203
      nodesClearList(((SFunctionNode*)(*pNode))->pParameterList);
      break;
    case QUERY_NODE_REAL_TABLE: {
      SRealTableNode* pReal = (SRealTableNode*)*pNode;
      tfree(pReal->pMeta);
      tfree(pReal->pVgroupList);
      break;
    }
    case QUERY_NODE_TEMP_TABLE:
      nodesDestroyNode(((STempTableNode*)(*pNode))->pSubquery);
X
Xiaoyu Wang 已提交
204 205
      break;
    case QUERY_NODE_GROUPING_SET:
X
Xiaoyu Wang 已提交
206
      nodesClearList(((SGroupingSetNode*)(*pNode))->pParameterList);
207
      break;
D
dapan1121 已提交
208
    case QUERY_NODE_NODE_LIST:
X
Xiaoyu Wang 已提交
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
      nodesClearList(((SNodeListNode*)(*pNode))->pNodeList);
      break;
    case QUERY_NODE_SELECT_STMT: {
      SSelectStmt* pStmt = (SSelectStmt*)*pNode;
      nodesDestroyList(pStmt->pProjectionList);
      nodesDestroyNode(pStmt->pFromTable);
      nodesDestroyNode(pStmt->pWhere);
      nodesDestroyList(pStmt->pPartitionByList);
      nodesDestroyNode(pStmt->pWindow);
      nodesDestroyList(pStmt->pGroupByList);
      nodesDestroyNode(pStmt->pHaving);
      nodesDestroyList(pStmt->pOrderByList);
      nodesDestroyNode(pStmt->pLimit);
      nodesDestroyNode(pStmt->pSlimit);
      break;
    }
X
Xiaoyu Wang 已提交
225 226 227 228 229 230 231 232 233 234 235
    case QUERY_NODE_VNODE_MODIF_STMT: {
      SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)*pNode;
      size_t size = taosArrayGetSize(pStmt->pDataBlocks);
      for (size_t i = 0; i < size; ++i) {
        SVgDataBlocks* pVg = taosArrayGetP(pStmt->pDataBlocks, i);
        tfree(pVg->pData);
        tfree(pVg);
      }
      taosArrayDestroy(pStmt->pDataBlocks);
      break;
    }
X
Xiaoyu Wang 已提交
236 237 238 239 240 241 242 243 244 245 246 247 248 249
    case QUERY_NODE_CREATE_TABLE_STMT: {
      SCreateTableStmt* pStmt = (SCreateTableStmt*)*pNode;
      nodesDestroyList(pStmt->pCols);
      nodesDestroyList(pStmt->pTags);
      break;
    }
    case QUERY_NODE_CREATE_SUBTABLE_CLAUSE: {
      SCreateSubTableClause* pStmt = (SCreateSubTableClause*)*pNode;
      nodesDestroyList(pStmt->pSpecificTags);
      nodesDestroyList(pStmt->pValsOfTags);
      break;
    }
    case QUERY_NODE_CREATE_MULTI_TABLE_STMT:
      nodesDestroyList(((SCreateMultiTableStmt*)(*pNode))->pSubTables);
250
      break;
251 252 253
    default:
      break;
  }
X
Xiaoyu Wang 已提交
254
  tfree(*pNode);
255
  return DEAL_RES_CONTINUE;
256
}
257

X
Xiaoyu Wang 已提交
258
void nodesDestroyNode(SNodeptr pNode) {
D
dapan1121 已提交
259 260 261
  if (NULL == pNode) {
    return;
  }
X
Xiaoyu Wang 已提交
262
  nodesRewriteNodePostOrder((SNode**)&pNode, destroyNode, NULL);
263 264
}

265 266 267 268 269 270 271 272
SNodeList* nodesMakeList() {
  SNodeList* p = calloc(1, sizeof(SNodeList));
  if (NULL == p) {
    return NULL;
  }
  return p;
}

X
Xiaoyu Wang 已提交
273
int32_t nodesListAppend(SNodeList* pList, SNodeptr pNode) {
274
  if (NULL == pList || NULL == pNode) {
X
Xiaoyu Wang 已提交
275
    return TSDB_CODE_SUCCESS;
276 277 278
  }
  SListCell* p = calloc(1, sizeof(SListCell));
  if (NULL == p) {
X
Xiaoyu Wang 已提交
279 280
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return TSDB_CODE_OUT_OF_MEMORY;
281 282
  }
  p->pNode = pNode;
283 284 285 286 287 288
  if (NULL == pList->pHead) {
    pList->pHead = p;
  }
  if (NULL != pList->pTail) {
    pList->pTail->pNext = p;
  }
289
  pList->pTail = p;
290
  ++(pList->length);
X
Xiaoyu Wang 已提交
291
  return TSDB_CODE_SUCCESS;
292 293
}

294 295 296 297 298 299 300 301 302 303 304
int32_t nodesListStrictAppend(SNodeList* pList, SNodeptr pNode) {
  if (NULL == pNode) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  int32_t code = nodesListAppend(pList, pNode);
  if (TSDB_CODE_SUCCESS != code) {
    nodesDestroyNode(pNode);
  }
  return code;
}

X
Xiaoyu Wang 已提交
305
int32_t nodesListAppendList(SNodeList* pTarget, SNodeList* pSrc) {
X
Xiaoyu Wang 已提交
306 307 308 309 310 311 312 313 314 315 316 317
  if (NULL == pTarget || NULL == pSrc) {
    return TSDB_CODE_SUCCESS;
  }

  if (NULL == pTarget->pHead) {
    pTarget->pHead = pSrc->pHead;
  } else {
    pTarget->pTail->pNext = pSrc->pHead;
    if (NULL != pSrc->pHead) {
      pSrc->pHead->pPrev = pTarget->pTail;
    }
  }
X
Xiaoyu Wang 已提交
318 319 320
  pTarget->pTail = pSrc->pTail;
  pTarget->length += pSrc->length;
  tfree(pSrc);
X
Xiaoyu Wang 已提交
321

X
Xiaoyu Wang 已提交
322 323 324
  return TSDB_CODE_SUCCESS;
}

325 326 327 328 329 330 331 332
SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) {
  if (NULL == pCell->pPrev) {
    pList->pHead = pCell->pNext;
  } else {
    pCell->pPrev->pNext = pCell->pNext;
    pCell->pNext->pPrev = pCell->pPrev;
  }
  SListCell* pNext = pCell->pNext;
X
Xiaoyu Wang 已提交
333
  nodesDestroyNode(pCell->pNode);
334 335 336 337 338
  tfree(pCell);
  --(pList->length);
  return pNext;
}

X
Xiaoyu Wang 已提交
339
SNodeptr nodesListGetNode(SNodeList* pList, int32_t index) {
340 341 342 343 344 345 346 347 348
  SNode* node;
  FOREACH(node, pList) {
    if (0 == index--) {
      return node;
    }
  }
  return NULL;
}

349
void nodesDestroyList(SNodeList* pList) {
350 351 352
  if (NULL == pList) {
    return;
  }
X
Xiaoyu Wang 已提交
353

X
Xiaoyu Wang 已提交
354 355 356
  SListCell* pNext = pList->pHead;
  while (NULL != pNext) {
    pNext = nodesListErase(pList, pNext);
357 358 359 360
  }
  tfree(pList);
}

X
Xiaoyu Wang 已提交
361 362 363 364 365 366 367 368 369 370 371 372 373 374
void nodesClearList(SNodeList* pList) {
  if (NULL == pList) {
    return;
  }

  SListCell* pNext = pList->pHead;
  while (NULL != pNext) {
    SListCell* tmp = pNext;
    pNext = pNext->pNext;
    tfree(tmp);
  }
  tfree(pList);
}

X
Xiaoyu Wang 已提交
375
void* nodesGetValueFromNode(SValueNode *pNode) {
D
dapan1121 已提交
376 377
  switch (pNode->node.resType.type) {
    case TSDB_DATA_TYPE_BOOL:
X
Xiaoyu Wang 已提交
378
      return (void*)&pNode->datum.b;
D
dapan1121 已提交
379 380 381 382 383
    case TSDB_DATA_TYPE_TINYINT:
    case TSDB_DATA_TYPE_SMALLINT:
    case TSDB_DATA_TYPE_INT:
    case TSDB_DATA_TYPE_BIGINT:
    case TSDB_DATA_TYPE_TIMESTAMP:
X
Xiaoyu Wang 已提交
384
      return (void*)&pNode->datum.i;
D
dapan1121 已提交
385 386 387 388
    case TSDB_DATA_TYPE_UTINYINT:
    case TSDB_DATA_TYPE_USMALLINT:
    case TSDB_DATA_TYPE_UINT:
    case TSDB_DATA_TYPE_UBIGINT:
X
Xiaoyu Wang 已提交
389
      return (void*)&pNode->datum.u;
D
dapan1121 已提交
390 391
    case TSDB_DATA_TYPE_FLOAT:
    case TSDB_DATA_TYPE_DOUBLE: 
X
Xiaoyu Wang 已提交
392
      return (void*)&pNode->datum.d;
D
dapan1121 已提交
393 394 395 396
    case TSDB_DATA_TYPE_BINARY:
    case TSDB_DATA_TYPE_NCHAR:
    case TSDB_DATA_TYPE_VARCHAR:
    case TSDB_DATA_TYPE_VARBINARY: 
X
Xiaoyu Wang 已提交
397
      return (void*)pNode->datum.p;
D
dapan1121 已提交
398 399 400 401 402 403 404
    default:
      break;
  }

  return NULL;
}

405 406 407 408 409
bool nodesIsExprNode(const SNode* pNode) {
  ENodeType type = nodeType(pNode);
  return (QUERY_NODE_COLUMN == type || QUERY_NODE_VALUE == type || QUERY_NODE_OPERATOR == type || QUERY_NODE_FUNCTION == type);
}

410 411 412 413 414 415 416 417 418 419 420 421 422
bool nodesIsArithmeticOp(const SOperatorNode* pOp) {
  switch (pOp->opType) {
    case OP_TYPE_ADD:
    case OP_TYPE_SUB:
    case OP_TYPE_MULTI:
    case OP_TYPE_DIV:
    case OP_TYPE_MOD:
      return true;
    default:
      break;
  }
  return false;
}
423

424 425 426 427 428 429 430 431 432 433 434 435 436 437
bool nodesIsComparisonOp(const SOperatorNode* pOp) {
  switch (pOp->opType) {
    case OP_TYPE_GREATER_THAN:
    case OP_TYPE_GREATER_EQUAL:
    case OP_TYPE_LOWER_THAN:
    case OP_TYPE_LOWER_EQUAL:
    case OP_TYPE_EQUAL:
    case OP_TYPE_NOT_EQUAL:
    case OP_TYPE_IN:
    case OP_TYPE_NOT_IN:
    case OP_TYPE_LIKE:
    case OP_TYPE_NOT_LIKE:
    case OP_TYPE_MATCH:
    case OP_TYPE_NMATCH:
X
Xiaoyu Wang 已提交
438 439 440 441 442 443 444 445
    case OP_TYPE_IS_NULL:
    case OP_TYPE_IS_NOT_NULL:
    case OP_TYPE_IS_TRUE:
    case OP_TYPE_IS_FALSE:
    case OP_TYPE_IS_UNKNOWN:
    case OP_TYPE_IS_NOT_TRUE:
    case OP_TYPE_IS_NOT_FALSE:
    case OP_TYPE_IS_NOT_UNKNOWN:
446 447 448 449 450
      return true;
    default:
      break;
  }
  return false;
451 452
}

453 454 455 456 457 458 459 460 461 462
bool nodesIsJsonOp(const SOperatorNode* pOp) {
  switch (pOp->opType) {
    case OP_TYPE_JSON_GET_VALUE:
    case OP_TYPE_JSON_CONTAINS:
      return true;
    default:
      break;
  }
  return false;
}
463

464 465
bool nodesIsTimeorderQuery(const SNode* pQuery) {
  return false;
466
}
467 468

bool nodesIsTimelineQuery(const SNode* pQuery) {
469
  return false;
D
dapan1121 已提交
470
}
X
Xiaoyu Wang 已提交
471 472 473

typedef struct SCollectColumnsCxt {
  int32_t errCode;
X
Xiaoyu Wang 已提交
474
  const char* pTableAlias;
X
Xiaoyu Wang 已提交
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
  SNodeList* pCols;
  SHashObj* pColIdHash;
} SCollectColumnsCxt;

static EDealRes doCollect(SCollectColumnsCxt* pCxt, int32_t id, SNode* pNode) {
  if (NULL == taosHashGet(pCxt->pColIdHash, &id, sizeof(id))) {
    pCxt->errCode = taosHashPut(pCxt->pColIdHash, &id, sizeof(id), NULL, 0);
    if (TSDB_CODE_SUCCESS == pCxt->errCode) {
      pCxt->errCode = nodesListAppend(pCxt->pCols, pNode);
    }
    return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
  }
  return DEAL_RES_CONTINUE;
}

static EDealRes collectColumns(SNode* pNode, void* pContext) {
  SCollectColumnsCxt* pCxt = (SCollectColumnsCxt*)pContext;
X
Xiaoyu Wang 已提交
492
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
X
Xiaoyu Wang 已提交
493 494
    SColumnNode* pCol = (SColumnNode*)pNode;
    int32_t colId = pCol->colId;
X
Xiaoyu Wang 已提交
495
    if (0 == strcmp(pCxt->pTableAlias, pCol->tableAlias)) {
X
Xiaoyu Wang 已提交
496 497 498 499 500 501
      return doCollect(pCxt, colId, pNode);
    }
  }
  return DEAL_RES_CONTINUE;
}

X
Xiaoyu Wang 已提交
502
int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* pTableAlias, SNodeList** pCols) {
X
Xiaoyu Wang 已提交
503 504 505 506 507 508
  if (NULL == pSelect || NULL == pCols) {
    return TSDB_CODE_SUCCESS;
  }

  SCollectColumnsCxt cxt = {
    .errCode = TSDB_CODE_SUCCESS,
X
Xiaoyu Wang 已提交
509
    .pTableAlias = pTableAlias,
X
Xiaoyu Wang 已提交
510 511 512 513 514 515 516 517 518 519 520 521 522
    .pCols = nodesMakeList(),
    .pColIdHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK)
  };
  if (NULL == cxt.pCols || NULL == cxt.pColIdHash) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  nodesWalkSelectStmt(pSelect, clause, collectColumns, &cxt);
  taosHashCleanup(cxt.pColIdHash);
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
    nodesDestroyList(cxt.pCols);
    return cxt.errCode;
  }
X
Xiaoyu Wang 已提交
523 524 525 526
  if (0 == LIST_LENGTH(cxt.pCols)) {
    nodesDestroyList(cxt.pCols);
    cxt.pCols = NULL;
  }
X
Xiaoyu Wang 已提交
527 528 529 530 531 532 533 534 535 536 537 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
  *pCols = cxt.pCols;
  return TSDB_CODE_SUCCESS;
}

typedef struct SCollectFuncsCxt {
  int32_t errCode;
  FFuncClassifier classifier;
  SNodeList* pFuncs;
} SCollectFuncsCxt;

static EDealRes collectFuncs(SNode* pNode, void* pContext) {
  SCollectFuncsCxt* pCxt = (SCollectFuncsCxt*)pContext;
  if (QUERY_NODE_FUNCTION == nodeType(pNode) && pCxt->classifier(((SFunctionNode*)pNode)->funcId)) {
    pCxt->errCode = nodesListAppend(pCxt->pFuncs, pNode);
    return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
  }
  return DEAL_RES_CONTINUE;
}

int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs) {
  if (NULL == pSelect || NULL == pFuncs) {
    return TSDB_CODE_SUCCESS;
  }

  SCollectFuncsCxt cxt = {
    .errCode = TSDB_CODE_SUCCESS,
    .classifier = classifier,
    .pFuncs = nodesMakeList()
  };
  if (NULL == cxt.pFuncs) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  nodesWalkSelectStmt(pSelect, SQL_CLAUSE_GROUP_BY, collectFuncs, &cxt);
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
    nodesDestroyList(cxt.pFuncs);
    return cxt.errCode;
  }
X
Xiaoyu Wang 已提交
564 565 566 567 568 569 570
  if (LIST_LENGTH(cxt.pFuncs) > 0) {
    *pFuncs = cxt.pFuncs;
  } else {
    nodesDestroyList(cxt.pFuncs);
    *pFuncs = NULL;
  }
  
X
Xiaoyu Wang 已提交
571 572
  return TSDB_CODE_SUCCESS;
}