• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #4473

08 Jul 2025 09:38AM UTC coverage: 62.922% (+0.7%) from 62.22%
#4473

push

travis-ci

web-flow
Merge pull request #31712 from taosdata/merge/mainto3.0

merge: from main to 3.0 branch

158525 of 321496 branches covered (49.31%)

Branch coverage included in aggregate %.

56 of 60 new or added lines in 13 files covered. (93.33%)

1333 existing lines in 67 files now uncovered.

245526 of 320647 relevant lines covered (76.57%)

17689640.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.09
/source/libs/planner/src/planUtil.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#include "functionMgt.h"
17
#include "planInt.h"
18
#include "scalar.h"
19
#include "filter.h"
20

21
static char* getUsageErrFormat(int32_t errCode) {
671✔
22
  switch (errCode) {
671!
23
    case TSDB_CODE_PLAN_EXPECTED_TS_EQUAL:
×
24
      return "primary timestamp equal condition is expected in join conditions";
×
25
    case TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN:
15✔
26
      return "not support cross join";
15✔
27
    case TSDB_CODE_PLAN_NOT_SUPPORT_JOIN_COND:
215✔
28
      return "Not supported join conditions";
215✔
29
    case TSDB_CODE_PAR_NOT_SUPPORT_JOIN:
441✔
30
      return "Not supported join since '%s'";
441✔
31
    case TSDB_CODE_PLAN_SLOT_NOT_FOUND:
×
32
      return "not found slot id by slot key";
×
33
    case TSDB_CODE_PLAN_INVALID_TABLE_TYPE:
×
34
      return "Planner invalid table type";
×
35
    case TSDB_CODE_PLAN_INVALID_DYN_CTRL_TYPE:
×
36
      return "Planner invalid query control plan type";
×
37
    default:
×
38
      break;
×
39
  }
40
  return "Unknown error";
×
41
}
42

43
int32_t generateUsageErrMsg(char* pBuf, int32_t len, int32_t errCode, ...) {
671✔
44
  va_list vArgList;
45
  va_start(vArgList, errCode);
671✔
46
  (void)vsnprintf(pBuf, len, getUsageErrFormat(errCode), vArgList);
671✔
47
  va_end(vArgList);
671✔
48
  return errCode;
671✔
49
}
50

51
typedef struct SCreateColumnCxt {
52
  int32_t    errCode;
53
  SNodeList* pList;
54
} SCreateColumnCxt;
55

56
static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
8,243,976✔
57
  SCreateColumnCxt* pCxt = (SCreateColumnCxt*)pContext;
8,243,976✔
58
  switch (nodeType(pNode)) {
8,243,976✔
59
    case QUERY_NODE_COLUMN: {
5,760,884✔
60
      SNode* pCol = NULL;
5,760,884✔
61
      pCxt->errCode = nodesCloneNode(pNode, &pCol);
5,760,884✔
62
      if (NULL == pCol) {
5,760,926!
63
        return DEAL_RES_ERROR;
×
64
      }
65
      return (TSDB_CODE_SUCCESS == nodesListAppend(pCxt->pList, pCol) ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
5,760,926!
66
    }
67
    case QUERY_NODE_VALUE:
2,226,558✔
68
    case QUERY_NODE_OPERATOR:
69
    case QUERY_NODE_LOGIC_CONDITION:
70
    case QUERY_NODE_FUNCTION:
71
    case QUERY_NODE_CASE_WHEN: {
72
      SExprNode*   pExpr = (SExprNode*)pNode;
2,226,558✔
73
      SColumnNode* pCol = NULL;
2,226,558✔
74
      pCxt->errCode = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
2,226,558✔
75
      if (NULL == pCol) {
2,226,566!
76
        return DEAL_RES_ERROR;
×
77
      }
78
      pCol->node.resType = pExpr->resType;
2,226,566✔
79
      tstrncpy(pCol->colName, pExpr->aliasName, TSDB_COL_NAME_LEN);
2,226,566✔
80
      if (QUERY_NODE_FUNCTION == nodeType(pNode)) {
2,226,566✔
81
        SFunctionNode* pFunc = (SFunctionNode*)pNode;
2,202,742✔
82
        if (pFunc->funcType == FUNCTION_TYPE_TBNAME) {
2,202,742✔
83
          SValueNode* pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 0);
140,791✔
84
          if (NULL != pVal) {
140,791✔
85
            tstrncpy(pCol->tableAlias, pVal->literal, TSDB_TABLE_NAME_LEN);
3,828✔
86
            tstrncpy(pCol->tableName, pVal->literal, TSDB_TABLE_NAME_LEN);
3,828✔
87
          }
88
        }
89
      }
90
      pCol->node.relatedTo = pExpr->relatedTo;
2,226,566✔
91
      return (TSDB_CODE_SUCCESS == nodesListStrictAppend(pCxt->pList, (SNode*)pCol) ? DEAL_RES_IGNORE_CHILD
2,226,566✔
92
                                                                                    : DEAL_RES_ERROR);
2,226,564!
93
    }
94
    default:
256,534✔
95
      break;
256,534✔
96
  }
97

98
  return DEAL_RES_CONTINUE;
256,534✔
99
}
100

101
int32_t createColumnByRewriteExprs(SNodeList* pExprs, SNodeList** pList) {
3,430,252✔
102
  SCreateColumnCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pList = *pList};
3,430,252✔
103
  if (!cxt.pList) {
3,430,252✔
104
    int32_t code = nodesMakeList(&cxt.pList);
2,235,967✔
105
    if (TSDB_CODE_SUCCESS != code) {
2,235,986!
106
      return code;
×
107
    }
108
  }
109

110
  nodesWalkExprs(pExprs, doCreateColumn, &cxt);
3,430,271✔
111
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
3,430,360!
112
    nodesDestroyList(cxt.pList);
×
113
    return cxt.errCode;
×
114
  }
115
  if (NULL == *pList) {
3,430,364✔
116
    *pList = cxt.pList;
2,236,033✔
117
  }
118
  return cxt.errCode;
3,430,364✔
119
}
120

121
int32_t createColumnByRewriteExpr(SNode* pExpr, SNodeList** pList) {
151,728✔
122
  SCreateColumnCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pList = *pList};
151,728✔
123
  if (!cxt.pList) {
151,728✔
124
    int32_t code = nodesMakeList(&cxt.pList);
18,964✔
125
    if (TSDB_CODE_SUCCESS != code) {
18,964!
126
      return code;
×
127
    }
128
  }
129

130
  nodesWalkExpr(pExpr, doCreateColumn, &cxt);
151,728✔
131
  if (TSDB_CODE_SUCCESS != cxt.errCode) {
151,728!
132
    nodesDestroyList(cxt.pList);
×
133
    return cxt.errCode;
×
134
  }
135
  if (NULL == *pList) {
151,728✔
136
    *pList = cxt.pList;
18,964✔
137
  }
138
  return cxt.errCode;
151,728✔
139
}
140

141
int32_t replaceLogicNode(SLogicSubplan* pSubplan, SLogicNode* pOld, SLogicNode* pNew) {
1,458,256✔
142
  pNew->stmtRoot = pOld->stmtRoot;
1,458,256✔
143
  if (NULL == pOld->pParent) {
1,458,256✔
144
    pSubplan->pNode = (SLogicNode*)pNew;
544,185✔
145
    pNew->pParent = NULL;
544,185✔
146
    return TSDB_CODE_SUCCESS;
544,185✔
147
  }
148

149
  SNode* pNode;
150
  FOREACH(pNode, pOld->pParent->pChildren) {
1,122,906!
151
    if (nodesEqualNode(pNode, (SNode*)pOld)) {
1,122,960✔
152
      REPLACE_NODE(pNew);
914,126✔
153
      pNew->pParent = pOld->pParent;
914,126✔
154
      return TSDB_CODE_SUCCESS;
914,126✔
155
    }
156
  }
157
  return TSDB_CODE_PLAN_INTERNAL_ERROR;
×
158
}
159

160
SLogicNode* getLogicNodeRootNode(SLogicNode* pCurr) {
47,278✔
161
  while (pCurr) {
144,655!
162
    if (pCurr->stmtRoot || NULL == pCurr->pParent) {
144,655!
163
      return pCurr;
47,278✔
164
    }
165

166
    pCurr = pCurr->pParent;
97,377✔
167
  }
168

169
  return NULL;
×
170
}
171

172

173
static int32_t adjustScanDataRequirement(SScanLogicNode* pScan, EDataOrderLevel requirement) {
1,258,762✔
174
  if ((SCAN_TYPE_TABLE != pScan->scanType && SCAN_TYPE_TABLE_MERGE != pScan->scanType) ||
1,258,762✔
175
      DATA_ORDER_LEVEL_GLOBAL == pScan->node.requireDataOrder) {
1,233,109!
176
    return TSDB_CODE_SUCCESS;
25,640✔
177
  }
178
  // The lowest sort level of scan output data is DATA_ORDER_LEVEL_IN_BLOCK
179
  if (requirement < DATA_ORDER_LEVEL_IN_BLOCK) {
1,233,122✔
180
    requirement = DATA_ORDER_LEVEL_IN_BLOCK;
866,811✔
181
  }
182
  if (DATA_ORDER_LEVEL_IN_BLOCK == requirement) {
1,233,122✔
183
    pScan->scanType = SCAN_TYPE_TABLE;
903,826✔
184
  } else if (TSDB_SUPER_TABLE == pScan->tableType) {
329,296✔
185
    pScan->scanType = SCAN_TYPE_TABLE_MERGE;
122,741✔
186
    pScan->filesetDelimited = true;
122,741✔
187
  }
188

189
  if (TSDB_NORMAL_TABLE != pScan->tableType && TSDB_CHILD_TABLE != pScan->tableType) {
1,233,122✔
190
    pScan->node.resultDataOrder = requirement;
510,462✔
191
  }
192
  return TSDB_CODE_SUCCESS;
1,233,122✔
193
}
194

195
static int32_t adjustJoinDataRequirement(SJoinLogicNode* pJoin, EDataOrderLevel requirement) {
129,823✔
196
  // The lowest sort level of join input and output data is DATA_ORDER_LEVEL_GLOBAL
197
  return TSDB_CODE_SUCCESS;
129,823✔
198
}
199

200
static int32_t adjustAggDataRequirement(SAggLogicNode* pAgg, EDataOrderLevel requirement) {
665,026✔
201
  // The sort level of agg with group by output data can only be DATA_ORDER_LEVEL_NONE
202
  if (requirement > DATA_ORDER_LEVEL_NONE && (NULL != pAgg->pGroupKeys || !pAgg->onlyHasKeepOrderFunc)) {
665,026!
203
    planError(
38!
204
        "The output of aggregate cannot meet the requirements(%s) of the upper operator. "
205
        "Illegal statement, should be intercepted in parser",
206
        dataOrderStr(requirement));
207
    return TSDB_CODE_PLAN_INTERNAL_ERROR;
×
208
  }
209
  pAgg->node.resultDataOrder = requirement;
664,988✔
210
  if (pAgg->hasTimeLineFunc) {
664,988✔
211
    pAgg->node.requireDataOrder = requirement < DATA_ORDER_LEVEL_IN_GROUP ? DATA_ORDER_LEVEL_IN_GROUP : requirement;
17,046✔
212
  }
213
  return TSDB_CODE_SUCCESS;
664,988✔
214
}
215

216
static int32_t adjustProjectDataRequirement(SProjectLogicNode* pProject, EDataOrderLevel requirement) {
1,333,493✔
217
  pProject->node.resultDataOrder = requirement;
1,333,493✔
218
  pProject->node.requireDataOrder = requirement;
1,333,493✔
219
  return TSDB_CODE_SUCCESS;
1,333,493✔
220
}
221

222
static int32_t adjustIntervalDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
26,937✔
223
  // The lowest sort level of interval output data is DATA_ORDER_LEVEL_IN_GROUP
224
  if (requirement < DATA_ORDER_LEVEL_IN_GROUP) {
26,937✔
225
    requirement = DATA_ORDER_LEVEL_IN_GROUP;
17,629✔
226
  }
227
  // The sort level of interval input data is always DATA_ORDER_LEVEL_IN_BLOCK
228
  pWindow->node.resultDataOrder = requirement;
26,937✔
229
  return TSDB_CODE_SUCCESS;
26,937✔
230
}
231

232
static int32_t adjustSessionDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
6,857✔
233
  if (requirement <= pWindow->node.resultDataOrder) {
6,857!
234
    return TSDB_CODE_SUCCESS;
6,857✔
235
  }
236
  pWindow->node.resultDataOrder = requirement;
×
237
  pWindow->node.requireDataOrder = requirement;
×
238
  return TSDB_CODE_SUCCESS;
×
239
}
240

241
static int32_t adjustStateDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
6,810✔
242
  if (requirement <= pWindow->node.resultDataOrder) {
6,810!
243
    return TSDB_CODE_SUCCESS;
6,810✔
244
  }
245
  pWindow->node.resultDataOrder = requirement;
×
246
  pWindow->node.requireDataOrder = requirement;
×
247
  return TSDB_CODE_SUCCESS;
×
248
}
249

250
static int32_t adjustEventDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
1,094✔
251
  if (requirement <= pWindow->node.resultDataOrder) {
1,094!
252
    return TSDB_CODE_SUCCESS;
1,094✔
253
  }
254
  pWindow->node.resultDataOrder = requirement;
×
255
  pWindow->node.requireDataOrder = requirement;
×
256
  return TSDB_CODE_SUCCESS;
×
257
}
258

259
static int32_t adjustCountDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
1,042✔
260
  if (requirement <= pWindow->node.resultDataOrder) {
1,042!
261
    return TSDB_CODE_SUCCESS;
1,042✔
262
  }
263
  pWindow->node.resultDataOrder = requirement;
×
264
  pWindow->node.requireDataOrder = requirement;
×
265
  return TSDB_CODE_SUCCESS;
×
266
}
267

268
static int32_t adjustAnomalyDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
12✔
269
  if (requirement <= pWindow->node.resultDataOrder) {
12!
270
    return TSDB_CODE_SUCCESS;
12✔
271
  }
272
  pWindow->node.resultDataOrder = requirement;
×
273
  pWindow->node.requireDataOrder = requirement;
×
274
  return TSDB_CODE_SUCCESS;
×
275
}
276

277
static int32_t adjustWindowDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
42,752✔
278
  switch (pWindow->winType) {
42,752!
279
    case WINDOW_TYPE_INTERVAL:
26,937✔
280
      return adjustIntervalDataRequirement(pWindow, requirement);
26,937✔
281
    case WINDOW_TYPE_SESSION:
6,857✔
282
      return adjustSessionDataRequirement(pWindow, requirement);
6,857✔
283
    case WINDOW_TYPE_STATE:
6,810✔
284
      return adjustStateDataRequirement(pWindow, requirement);
6,810✔
285
    case WINDOW_TYPE_EVENT:
1,094✔
286
      return adjustEventDataRequirement(pWindow, requirement);
1,094✔
287
    case WINDOW_TYPE_COUNT:
1,042✔
288
      return adjustCountDataRequirement(pWindow, requirement);
1,042✔
289
    case WINDOW_TYPE_ANOMALY:
12✔
290
      return adjustAnomalyDataRequirement(pWindow, requirement);
12✔
291
    default:
×
292
      break;
×
293
  }
294
  return TSDB_CODE_PLAN_INTERNAL_ERROR;
×
295
}
296

297
static int32_t adjustFillDataRequirement(SFillLogicNode* pFill, EDataOrderLevel requirement) {
9,275✔
298
  if (requirement <= pFill->node.requireDataOrder) {
9,275!
299
    return TSDB_CODE_SUCCESS;
9,275✔
300
  }
301
  pFill->node.resultDataOrder = requirement;
×
302
  pFill->node.requireDataOrder = requirement;
×
303
  return TSDB_CODE_SUCCESS;
×
304
}
305

306
static int32_t adjustSortDataRequirement(SSortLogicNode* pSort, EDataOrderLevel requirement) {
335,246✔
307
  return TSDB_CODE_SUCCESS;
335,246✔
308
}
309

310
static int32_t adjustPartitionDataRequirement(SPartitionLogicNode* pPart, EDataOrderLevel requirement) {
95,783✔
311
  if (DATA_ORDER_LEVEL_GLOBAL == requirement) {
95,783!
312
    planError(
×
313
        "The output of partition cannot meet the requirements(%s) of the upper operator. "
314
        "Illegal statement, should be intercepted in parser",
315
        dataOrderStr(requirement));
316
    return TSDB_CODE_PLAN_INTERNAL_ERROR;
×
317
  }
318
  pPart->node.resultDataOrder = requirement;
95,783✔
319
  pPart->node.requireDataOrder = requirement;
95,783✔
320
  return TSDB_CODE_SUCCESS;
95,783✔
321
}
322

323
static int32_t adjustIndefRowsDataRequirement(SIndefRowsFuncLogicNode* pIndef, EDataOrderLevel requirement) {
58,315✔
324
  if (requirement <= pIndef->node.resultDataOrder) {
58,315!
325
    return TSDB_CODE_SUCCESS;
58,315✔
326
  }
327
  pIndef->node.resultDataOrder = requirement;
×
328
  pIndef->node.requireDataOrder = requirement;
×
329
  return TSDB_CODE_SUCCESS;
×
330
}
331

332
static int32_t adjustInterpDataRequirement(SInterpFuncLogicNode* pInterp, EDataOrderLevel requirement) {
14,481✔
333
  if (requirement <= pInterp->node.requireDataOrder) {
14,481!
334
    return TSDB_CODE_SUCCESS;
14,485✔
335
  }
336
  pInterp->node.resultDataOrder = requirement;
×
337
  pInterp->node.requireDataOrder = requirement;
×
338
  return TSDB_CODE_SUCCESS;
×
339
}
340

341
static int32_t adjustForecastDataRequirement(SForecastFuncLogicNode* pForecast, EDataOrderLevel requirement) {
41✔
342
  if (requirement <= pForecast->node.requireDataOrder) {
41!
343
    return TSDB_CODE_SUCCESS;
41✔
344
  }
345
  pForecast->node.resultDataOrder = requirement;
×
346
  pForecast->node.requireDataOrder = requirement;
×
347
  return TSDB_CODE_SUCCESS;
×
348
}
349

350
int32_t adjustLogicNodeDataRequirement(SLogicNode* pNode, EDataOrderLevel requirement) {
13,833,525✔
351
  int32_t code = TSDB_CODE_SUCCESS;
13,833,525✔
352
  switch (nodeType(pNode)) {
13,833,525!
353
    case QUERY_NODE_LOGIC_PLAN_SCAN:
1,258,764✔
354
      code = adjustScanDataRequirement((SScanLogicNode*)pNode, requirement);
1,258,764✔
355
      break;
1,258,778✔
356
    case QUERY_NODE_LOGIC_PLAN_JOIN:
129,823✔
357
      code = adjustJoinDataRequirement((SJoinLogicNode*)pNode, requirement);
129,823✔
358
      break;
129,823✔
359
    case QUERY_NODE_LOGIC_PLAN_AGG:
665,045✔
360
      code = adjustAggDataRequirement((SAggLogicNode*)pNode, requirement);
665,045✔
361
      break;
664,995✔
362
    case QUERY_NODE_LOGIC_PLAN_PROJECT:
1,333,516✔
363
      code = adjustProjectDataRequirement((SProjectLogicNode*)pNode, requirement);
1,333,516✔
364
      break;
1,333,494✔
365
    case QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY:
9,893,868✔
366
    case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
367
    case QUERY_NODE_LOGIC_PLAN_MERGE:
368
      break;
9,893,868✔
369
    case QUERY_NODE_LOGIC_PLAN_WINDOW:
42,751✔
370
      code = adjustWindowDataRequirement((SWindowLogicNode*)pNode, requirement);
42,751✔
371
      break;
42,752✔
372
    case QUERY_NODE_LOGIC_PLAN_FILL:
9,275✔
373
      code = adjustFillDataRequirement((SFillLogicNode*)pNode, requirement);
9,275✔
374
      break;
9,275✔
375
    case QUERY_NODE_LOGIC_PLAN_SORT:
335,248✔
376
      code = adjustSortDataRequirement((SSortLogicNode*)pNode, requirement);
335,248✔
377
      break;
335,247✔
378
    case QUERY_NODE_LOGIC_PLAN_PARTITION:
95,783✔
379
      code = adjustPartitionDataRequirement((SPartitionLogicNode*)pNode, requirement);
95,783✔
380
      break;
95,783✔
381
    case QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC:
58,315✔
382
      code = adjustIndefRowsDataRequirement((SIndefRowsFuncLogicNode*)pNode, requirement);
58,315✔
383
      break;
58,315✔
384
    case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
14,482✔
385
      code = adjustInterpDataRequirement((SInterpFuncLogicNode*)pNode, requirement);
14,482✔
386
      break;
14,484✔
387
    case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
41✔
388
      code = adjustForecastDataRequirement((SForecastFuncLogicNode*)pNode, requirement);
41✔
389
      break;
41✔
UNCOV
390
    default:
×
UNCOV
391
      break;
×
392
  }
393
  if (TSDB_CODE_SUCCESS == code) {
13,833,469✔
394
    SNode* pChild = NULL;
13,826,093✔
395
    FOREACH(pChild, pNode->pChildren) {
16,806,630✔
396
      code = adjustLogicNodeDataRequirement((SLogicNode*)pChild, pNode->requireDataOrder);
2,980,501✔
397
      if (TSDB_CODE_SUCCESS != code) {
2,980,537!
398
        break;
×
399
      }
400
    }
401
  }
402
  return code;
13,833,505✔
403
}
404

405
static bool stbNotSystemScan(SLogicNode* pNode) {
1,416✔
406
  if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
1,416✔
407
    return SCAN_TYPE_SYSTEM_TABLE != ((SScanLogicNode*)pNode)->scanType;
1,316✔
408
  } else if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode)) {
100!
409
    return stbNotSystemScan((SLogicNode*)nodesListGetNode(pNode->pChildren, 0));
×
410
  } else {
411
    return true;
100✔
412
  }
413
}
414

415
bool keysHasTbname(SNodeList* pKeys) {
500,248✔
416
  if (NULL == pKeys) {
500,248✔
417
    return false;
126,648✔
418
  }
419
  SNode* pPartKey = NULL;
373,600✔
420
  FOREACH(pPartKey, pKeys) {
611,597!
421
    if (QUERY_NODE_GROUPING_SET == nodeType(pPartKey)) {
412,765✔
422
      pPartKey = nodesListGetNode(((SGroupingSetNode*)pPartKey)->pParameterList, 0);
248,863✔
423
    }
424
    if ((QUERY_NODE_FUNCTION == nodeType(pPartKey) && FUNCTION_TYPE_TBNAME == ((SFunctionNode*)pPartKey)->funcType) ||
412,765✔
425
        (QUERY_NODE_COLUMN == nodeType(pPartKey) && COLUMN_TYPE_TBNAME == ((SColumnNode*)pPartKey)->colType)) {
352,943✔
426
      return true;
174,768✔
427
    }
428
  }
429
  return false;
198,832✔
430
}
431

432
static SNodeList* stbGetPartKeys(SLogicNode* pNode) {
242,737✔
433
  if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
242,737✔
434
    return ((SScanLogicNode*)pNode)->pGroupTags;
163,703✔
435
  } else if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode)) {
79,034✔
436
    return ((SPartitionLogicNode*)pNode)->pPartitionKeys;
7,522✔
437
  } else {
438
    return NULL;
71,512✔
439
  }
440
}
441

442
bool isPartTableAgg(SAggLogicNode* pAgg) {
277,826✔
443
  if (1 != LIST_LENGTH(pAgg->node.pChildren)) {
277,826!
444
    return false;
×
445
  }
446
  if (NULL != pAgg->pGroupKeys) {
277,826✔
447
    return (pAgg->isGroupTb || keysHasTbname(pAgg->pGroupKeys)) &&
36,796✔
448
           stbNotSystemScan((SLogicNode*)nodesListGetNode(pAgg->node.pChildren, 0));
1,332✔
449
  }
450
  return pAgg->isPartTb || keysHasTbname(stbGetPartKeys((SLogicNode*)nodesListGetNode(pAgg->node.pChildren, 0)));
242,363✔
451
}
452

453
static bool stbHasPartTag(SNodeList* pPartKeys) {
42,167✔
454
  if (NULL == pPartKeys) {
42,167✔
455
    return false;
28,996✔
456
  }
457
  SNode* pPartKey = NULL;
13,171✔
458
  FOREACH(pPartKey, pPartKeys) {
26,519!
459
    if (QUERY_NODE_GROUPING_SET == nodeType(pPartKey)) {
19,866✔
460
      pPartKey = nodesListGetNode(((SGroupingSetNode*)pPartKey)->pParameterList, 0);
6,342✔
461
    }
462
    if ((QUERY_NODE_FUNCTION == nodeType(pPartKey) && FUNCTION_TYPE_TAGS == ((SFunctionNode*)pPartKey)->funcType) ||
19,866!
463
        (QUERY_NODE_COLUMN == nodeType(pPartKey) && COLUMN_TYPE_TAG == ((SColumnNode*)pPartKey)->colType)) {
19,866✔
464
      return true;
6,518✔
465
    }
466
  }
467
  return false;
6,653✔
468
}
469

470
bool getBatchScanOptionFromHint(SNodeList* pList) {
164,819✔
471
  SNode* pNode = NULL;
164,819✔
472
  bool batchScan = true;
164,819✔
473
  FOREACH(pNode, pList) {
171,429✔
474
    SHintNode* pHint = (SHintNode*)pNode;
6,682✔
475
    if (pHint->option == HINT_BATCH_SCAN) {
6,682✔
476
      batchScan = true;
36✔
477
      break;
36✔
478
    } else if (pHint->option == HINT_NO_BATCH_SCAN) {
6,646✔
479
      batchScan = false;
36✔
480
      break;
36✔
481
    }
482
  }
483

484
  return batchScan;
164,819✔
485
}
486

487
bool getSortForGroupOptHint(SNodeList* pList) {
492✔
488
  if (!pList) return false;
492!
489
  SNode* pNode;
490
  FOREACH(pNode, pList) {
500!
491
    SHintNode* pHint = (SHintNode*)pNode;
492✔
492
    if (pHint->option == HINT_SORT_FOR_GROUP) {
492✔
493
      return true;
484✔
494
    }
495
  }
496
  return false;
8✔
497
}
498

499
bool getOptHint(SNodeList* pList, EHintOption hint) {
3,587✔
500
  if (!pList) return false;
3,587✔
501
  SNode* pNode;
502
  FOREACH(pNode, pList) {
8!
503
    SHintNode* pHint = (SHintNode*)pNode;
8✔
504
    if (pHint->option == hint) {
8!
505
      return true;
8✔
506
    }
507
  }
508
  return false;
×
509
}
510

511
bool getParaTablesSortOptHint(SNodeList* pList) {
1,091,343✔
512
  if (!pList) return false;
1,091,343✔
513
  SNode* pNode;
514
  FOREACH(pNode, pList) {
23,182!
515
    SHintNode* pHint = (SHintNode*)pNode;
22,665✔
516
    if (pHint->option == HINT_PARA_TABLES_SORT) {
22,665✔
517
      return true;
22,105✔
518
    }
519
  }
520
  return false;
517✔
521
}
522

523
bool getSmallDataTsSortOptHint(SNodeList* pList) {
1,091,348✔
524
  if (!pList) return false;
1,091,348✔
525
  SNode* pNode;
526
  FOREACH(pNode, pList) {
45,312!
527
    SHintNode* pHint = (SHintNode*)pNode;
22,665✔
528
    if (pHint->option == HINT_SMALLDATA_TS_SORT) {
22,665!
529
      return true;
×
530
    }
531
  }
532
  return false;
22,647✔
533
}
534

535
bool getHashJoinOptHint(SNodeList* pList) {
126,891✔
536
  if (!pList) return false;
126,891✔
537
  SNode* pNode;
538
  FOREACH(pNode, pList) {
8,716!
539
    SHintNode* pHint = (SHintNode*)pNode;
4,362✔
540
    if (pHint->option == HINT_HASH_JOIN) {
4,362!
541
      return true;
×
542
    }
543
  }
544
  return false;
4,354✔
545
}
546

547

548
int32_t collectTableAliasFromNodes(SNode* pNode, SSHashObj** ppRes) {
1,372,683✔
549
  int32_t code = TSDB_CODE_SUCCESS;
1,372,683✔
550
  SLogicNode* pCurr = (SLogicNode*)pNode;
1,372,683✔
551
  FOREACH(pNode, pCurr->pTargets) {
5,247,900!
552
    SColumnNode* pCol = (SColumnNode*)pNode;
3,875,217✔
553
    if (NULL == *ppRes) {
3,875,217✔
554
      *ppRes = tSimpleHashInit(5, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY));
1,177,671✔
555
      if (NULL == *ppRes) {
1,177,671!
556
        return TSDB_CODE_OUT_OF_MEMORY;
×
557
      }
558
    }
559

560
    code = tSimpleHashPut(*ppRes, pCol->tableAlias, strlen(pCol->tableAlias), NULL, 0);
3,875,217✔
561
    if (TSDB_CODE_SUCCESS != code) {
3,875,217!
562
      break;
×
563
    }
564
  }
565
  
566
  if (TSDB_CODE_SUCCESS == code) {
1,372,683!
567
    FOREACH(pNode, pCurr->pChildren) {
1,440,714✔
568
      code = collectTableAliasFromNodes(pNode, ppRes);
68,031✔
569
      if (TSDB_CODE_SUCCESS != code) {
68,031!
570
        break;
×
571
      }
572
    }
573
  }
574
  if (TSDB_CODE_SUCCESS != code) {
1,372,683!
575
    tSimpleHashCleanup(*ppRes);
×
576
    *ppRes = NULL;
×
577
  }
578

579
  return code;
1,372,683✔
580
}
581

582
bool isPartTagAgg(SAggLogicNode* pAgg) {
42,167✔
583
  if (1 != LIST_LENGTH(pAgg->node.pChildren)) {
42,167!
584
    return false;
×
585
  }
586
  if (pAgg->pGroupKeys) {
42,167✔
587
    return stbHasPartTag(pAgg->pGroupKeys) &&
5,640!
588
      stbNotSystemScan((SLogicNode*)nodesListGetNode(pAgg->node.pChildren, 0));
83✔
589
  }
590
  return stbHasPartTag(stbGetPartKeys((SLogicNode*)nodesListGetNode(pAgg->node.pChildren, 0)));
36,610✔
591
}
592

593
bool isPartTableWinodw(SWindowLogicNode* pWindow) {
18,923✔
594
  return pWindow->isPartTb || keysHasTbname(stbGetPartKeys((SLogicNode*)nodesListGetNode(pWindow->node.pChildren, 0)));
18,923✔
595
}
596

597
int32_t cloneLimit(SLogicNode* pParent, SLogicNode* pChild, uint8_t cloneWhat, bool* pCloned) {
61,657✔
598
  SLimitNode* pLimit = NULL, *pSlimit = NULL;
61,657✔
599
  int32_t     code = 0;
61,657✔
600
  bool        cloned = false;
61,657✔
601
  if (pParent->pLimit && (cloneWhat & CLONE_LIMIT)) {
61,657✔
602
    code = nodesCloneNode(pParent->pLimit, (SNode**)&pLimit);
53,222✔
603
    if (TSDB_CODE_SUCCESS == code) {
53,222!
604
      if (pLimit->limit && pLimit->offset) {
53,222!
605
        pLimit->limit->datum.i += pLimit->offset->datum.i;
21,929✔
606
      }
607
      if (pLimit->offset) {
53,222✔
608
        pLimit->offset->datum.i = 0;
21,929✔
609
      }
610
      cloned = true;
53,222✔
611
    }
612
  }
613

614
  if (pParent->pSlimit && (cloneWhat & CLONE_SLIMIT)) {
61,657!
615
    code = nodesCloneNode(pParent->pSlimit, (SNode**)&pSlimit);
4,296✔
616
    if (TSDB_CODE_SUCCESS == code) {
4,296!
617
      if (pSlimit->limit && pSlimit->offset) {
4,296!
618
        pSlimit->limit->datum.i += pSlimit->offset->datum.i;
1,064✔
619
      }
620
      if (pSlimit->offset) {
4,296✔
621
        pSlimit->offset->datum.i = 0;
1,064✔
622
      }
623
      cloned = true;
4,296✔
624
    }
625
  }
626
  if (TSDB_CODE_SUCCESS == code) {
61,657!
627
    pChild->pLimit = (SNode*)pLimit;
61,657✔
628
    pChild->pSlimit = (SNode*)pSlimit;
61,657✔
629
    *pCloned = cloned;
61,657✔
630
  } else {
631
    nodesDestroyNode((SNode*)pLimit);
×
632
  }
633
  return code;
61,657✔
634
}
635

636
static EDealRes partTagsOptHasColImpl(SNode* pNode, void* pContext) {
647,246✔
637
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
647,246✔
638
    if (COLUMN_TYPE_TAG != ((SColumnNode*)pNode)->colType && COLUMN_TYPE_TBNAME != ((SColumnNode*)pNode)->colType) {
467,682✔
639
      *(bool*)pContext = true;
46,413✔
640
      return DEAL_RES_END;
46,413✔
641
    }
642
  }
643
  return DEAL_RES_CONTINUE;
600,833✔
644
}
645

646
bool keysHasCol(SNodeList* pKeys) {
385,526✔
647
  bool hasCol = false;
385,526✔
648
  nodesWalkExprs(pKeys, partTagsOptHasColImpl, &hasCol);
385,526✔
649
  return hasCol;
385,526✔
650
}
651

652
SFunctionNode* createGroupKeyAggFunc(SColumnNode* pGroupCol) {
×
653
  SFunctionNode* pFunc = NULL;
×
654
  int32_t code = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&pFunc);
×
655
  if (pFunc) {
×
656
    tstrncpy(pFunc->functionName, "_group_key", TSDB_FUNC_NAME_LEN);
×
657
    tstrncpy(pFunc->node.aliasName, pGroupCol->node.aliasName, TSDB_COL_NAME_LEN);
×
658
    tstrncpy(pFunc->node.userAlias, pGroupCol->node.userAlias, TSDB_COL_NAME_LEN);
×
659
    SNode* pNew = NULL;
×
660
    code = nodesCloneNode((SNode*)pGroupCol, &pNew);
×
661
    if (TSDB_CODE_SUCCESS == code) {
×
662
      code = nodesListMakeStrictAppend(&pFunc->pParameterList, pNew);
×
663
    }
664
    if (code == TSDB_CODE_SUCCESS) {
×
665
      code = fmGetFuncInfo(pFunc, NULL, 0);
×
666
    }
667
    if (TSDB_CODE_SUCCESS != code) {
×
668
      nodesDestroyNode((SNode*)pFunc);
×
669
      pFunc = NULL;
×
670
    }
671
    if (TSDB_CODE_SUCCESS == code) {
×
672
      char    name[TSDB_FUNC_NAME_LEN + TSDB_NAME_DELIMITER_LEN + TSDB_POINTER_PRINT_BYTES + 1] = {0};
×
673
      int32_t len = tsnprintf(name, sizeof(name) - 1, "%s.%p", pFunc->functionName, pFunc);
×
674
      (void)taosHashBinary(name, len);
675
      tstrncpy(pFunc->node.aliasName, name, TSDB_COL_NAME_LEN);
×
676
    }
677
  }
678
  if (TSDB_CODE_SUCCESS != code) {
×
679
    terrno = code;
×
680
    nodesDestroyNode((SNode*)pFunc);
×
681
    pFunc = NULL;
×
682
  }
683
  return pFunc;
×
684
}
685

686
int32_t getTimeRangeFromNode(SNode** pPrimaryKeyCond, STimeWindow* pTimeRange, bool* pIsStrict) {
×
687
  SNode*  pNew = NULL;
×
688
  int32_t code = scalarCalculateConstants(*pPrimaryKeyCond, &pNew);
×
689
  if (TSDB_CODE_SUCCESS == code) {
×
690
    *pPrimaryKeyCond = pNew;
×
691
    code = filterGetTimeRange(*pPrimaryKeyCond, pTimeRange, pIsStrict);
×
692
  }
693
  return code;
×
694
}
695

696

697
static EDealRes tagScanNodeHasTbnameFunc(SNode* pNode, void* pContext) {
160,022✔
698
  if (QUERY_NODE_FUNCTION == nodeType(pNode) && FUNCTION_TYPE_TBNAME == ((SFunctionNode*)pNode)->funcType ||
160,022✔
699
        (QUERY_NODE_COLUMN == nodeType(pNode) && COLUMN_TYPE_TBNAME == ((SColumnNode*)pNode)->colType)) {
159,926!
700
    *(bool*)pContext = true;
96✔
701
    return DEAL_RES_END;
96✔
702
  }
703
  return DEAL_RES_CONTINUE;
159,926✔
704
}
705

706
static bool tagScanNodeListHasTbname(SNodeList* pCols) {
37,955✔
707
  bool hasTbname = false;
37,955✔
708
  nodesWalkExprs(pCols, tagScanNodeHasTbnameFunc, &hasTbname);
37,955✔
709
  return hasTbname;
37,955✔
710
}
711

712
static bool tagScanNodeHasTbname(SNode* pKeys) {
×
713
  bool hasTbname = false;
×
714
  nodesWalkExpr(pKeys, tagScanNodeHasTbnameFunc, &hasTbname);
×
715
  return hasTbname;
×
716
}
717

718

719

720
int32_t tagScanSetExecutionMode(SScanLogicNode* pScan) {
37,965✔
721
  pScan->onlyMetaCtbIdx = false;
37,965✔
722

723
  if (pScan->tableType == TSDB_CHILD_TABLE) {
37,965✔
724
    pScan->onlyMetaCtbIdx = false;
10✔
725
    return TSDB_CODE_SUCCESS;
10✔
726
  }
727

728
  if (tagScanNodeListHasTbname(pScan->pScanPseudoCols)) {
37,955✔
729
    pScan->onlyMetaCtbIdx = false;
96✔
730
    return TSDB_CODE_SUCCESS;
96✔
731
  }
732

733
  if (pScan->node.pConditions == NULL) {
37,859!
734
    pScan->onlyMetaCtbIdx = true;
37,859✔
735
    return TSDB_CODE_SUCCESS;
37,859✔
736
  }
737

738
  SNode* pCond = NULL;
×
739
  int32_t code = nodesCloneNode(pScan->node.pConditions, &pCond);
×
740
  if (TSDB_CODE_SUCCESS != code) {
×
741
    return code;
×
742
  }
743
  SNode* pTagCond = NULL;
×
744
  SNode* pTagIndexCond = NULL;
×
745
  code = filterPartitionCond(&pCond, NULL, &pTagIndexCond, &pTagCond, NULL);
×
746
  if (TSDB_CODE_SUCCESS == code) {
×
747
    if (pTagIndexCond || tagScanNodeHasTbname(pTagCond)) {
×
748
      pScan->onlyMetaCtbIdx = false;
×
749
    } else {
750
      pScan->onlyMetaCtbIdx = true;
×
751
    }
752
  }
753
  nodesDestroyNode(pCond);
×
754
  nodesDestroyNode(pTagIndexCond);
×
755
  nodesDestroyNode(pTagCond);
×
756
  return TSDB_CODE_SUCCESS;
×
757
}
758

759
bool isColRefExpr(const SColumnNode* pCol, const SExprNode* pExpr) {
9,257,067✔
760
  if (pCol->projRefIdx > 0) return pCol->projRefIdx == pExpr->projIdx;
9,257,067✔
761

762
  return 0 == strcmp(pCol->colName, pExpr->aliasName);
648,298✔
763
}
764

765
void rewriteTargetsWithResId(SNodeList* pTargets) {
516,972✔
766
  SNode* pNode;
767
  FOREACH(pNode, pTargets) {
2,141,696✔
768
    SColumnNode* pCol = (SColumnNode*)pNode;
1,624,724✔
769
    pCol->resIdx = pCol->projRefIdx;
1,624,724✔
770
  }
771
}
516,972✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc