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

taosdata / TDengine / #5044

06 May 2026 02:35AM UTC coverage: 73.169% (+0.06%) from 73.107%
#5044

push

travis-ci

web-flow
feat: [6659794715] cpu limit (#35153)

244 of 275 new or added lines in 23 files covered. (88.73%)

526 existing lines in 141 files now uncovered.

277745 of 379596 relevant lines covered (73.17%)

133740972.66 hits per line

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

93.98
/source/libs/parser/src/parCalcConst.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 "parInt.h"
18
#include "scalar.h"
19
#include "ttime.h"
20

21
typedef struct SNodeReplaceContext {
22
  SNode* pTarget;
23
  SNode* pNew;
24
  bool   replaced;
25
} SNodeReplaceContext;
26

27
typedef struct SCalcConstContext {
28
  SParseContext*      pParseCxt;
29
  SNodeReplaceContext replaceCxt;
30
  SMsgBuf             msgBuf;
31
  int32_t             code;
32
} SCalcConstContext;
33

34
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery);
35

36
static int32_t calcConstSubquery(SCalcConstContext* pCxt, STempTableNode* pTempTable) {
58,765,952✔
37
  return calcConstQuery(pCxt, pTempTable->pSubquery, true);
58,765,952✔
38
}
39

40
static int32_t calcConstNode(SNode** pNode) {
1,567,440,258✔
41
  if (NULL == *pNode) {
1,567,440,258✔
42
    return TSDB_CODE_SUCCESS;
1,323,631,435✔
43
  }
44

45
  SNode*  pNew = NULL;
243,808,851✔
46
  int32_t code = scalarCalculateConstants(*pNode, &pNew);
243,809,306✔
47
  if (TSDB_CODE_SUCCESS == code) {
243,837,111✔
48
    *pNode = pNew;
243,760,411✔
49
  }
50
  return code;
243,837,111✔
51
}
52

53
static int32_t calcConstList(SNodeList* pList) {
1,392,204,578✔
54
  SNode* pNode = NULL;
1,392,204,578✔
55
  FOREACH(pNode, pList) {
1,597,517,721✔
56
    SNode*  pNew = NULL;
205,304,039✔
57
    int32_t code = scalarCalculateConstants(pNode, &pNew);
205,304,039✔
58
    if (TSDB_CODE_SUCCESS == code) {
205,312,961✔
59
      REPLACE_NODE(pNew);
205,313,143✔
60
    } else {
UNCOV
61
      return code;
×
62
    }
63
  }
64
  return TSDB_CODE_SUCCESS;
1,392,213,016✔
65
}
66

67
static bool isCondition(const SNode* pNode) {
309,838,384✔
68
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
309,838,384✔
69
    return nodesIsComparisonOp((const SOperatorNode*)pNode);
254,845,392✔
70
  }
71
  return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
54,992,992✔
72
}
73

74
static int32_t rewriteIsTrue(SNode* pSrc, SNode** pIsTrue) {
1,352,215✔
75
  SOperatorNode* pOp = NULL;
1,352,215✔
76
  int32_t        code = nodesMakeNode(QUERY_NODE_OPERATOR, (SNode**)&pOp);
1,352,215✔
77
  if (NULL == pOp) {
1,352,215✔
78
    return code;
×
79
  }
80
  pOp->opType = OP_TYPE_IS_TRUE;
1,352,215✔
81
  pOp->pLeft = pSrc;
1,352,215✔
82
  pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
1,352,215✔
83
  pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
1,352,215✔
84
  *pIsTrue = (SNode*)pOp;
1,352,215✔
85
  return TSDB_CODE_SUCCESS;
1,352,215✔
86
}
87

88
static EDealRes doRewriteCondition(SNode** pNode, void* pContext) {
891,447,881✔
89
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
891,447,881✔
90
    SNode* pParam = NULL;
53,652,965✔
91
    FOREACH(pParam, ((SLogicConditionNode*)*pNode)->pParameterList) {
182,297,421✔
92
      if (!isCondition(pParam)) {
128,644,474✔
93
        SNode* pIsTrue = NULL;
270,083✔
94
        if (TSDB_CODE_SUCCESS != rewriteIsTrue(pParam, &pIsTrue)) {
270,083✔
95
          ((SCalcConstContext*)pContext)->code = TSDB_CODE_OUT_OF_MEMORY;
×
96
          return DEAL_RES_ERROR;
×
97
        }
98
        REPLACE_NODE(pIsTrue);
270,516✔
99
      }
100
    }
101
  }
102
  return DEAL_RES_CONTINUE;
891,448,496✔
103
}
104

105
static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) {
181,194,715✔
106
  if (!isCondition(*pNode)) {
181,194,715✔
107
    return rewriteIsTrue(*pNode, pNode);
1,081,605✔
108
  }
109
  nodesRewriteExprPostOrder(pNode, doRewriteCondition, pCxt);
180,114,190✔
110
  return pCxt->code;
180,121,792✔
111
}
112

113
static int32_t calcConstCondition(SCalcConstContext* pCxt, SNode** pNode) {
6,320,536✔
114
  int32_t code = rewriteCondition(pCxt, pNode);
6,320,536✔
115
  if (TSDB_CODE_SUCCESS == code) {
6,321,167✔
116
    code = calcConstNode(pNode);
6,321,167✔
117
  }
118
  return code;
6,321,079✔
119
}
120

121
static EDealRes rewriteCalcConstValue(SNode** pNode, void* pContext) {
35,367,901✔
122
  int32_t                code = TSDB_CODE_SUCCESS;
35,367,901✔
123
  int32_t                lino = 0;
35,367,901✔
124
  SCalcConstContext* pCtx = (SCalcConstContext*)pContext;
35,367,901✔
125

126
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
35,367,901✔
127
    return DEAL_RES_CONTINUE;
5,557,349✔
128
  } else if (QUERY_NODE_OPERATOR == nodeType(*pNode)) {
29,810,552✔
129
    SOperatorNode* pOp = (SOperatorNode*)*pNode;
29,811,489✔
130
    if (OP_TYPE_EQUAL == pOp->opType && (TSDB_DATA_TYPE_TIMESTAMP == ((SExprNode*)pOp->pLeft)->resType.type || TSDB_DATA_TYPE_TIMESTAMP == ((SExprNode*)pOp->pRight)->resType.type)) {
29,811,489✔
131
      code = calcConstNode(&pOp->pLeft);
23,489,470✔
132
      if (TSDB_CODE_SUCCESS == code) {
23,490,774✔
133
        code = calcConstNode(&pOp->pRight);
23,490,774✔
134
      }
135
      
136
      goto _end;
23,490,774✔
137
    }
138
  }
139

140
  if (TSDB_CODE_SUCCESS == code) {
6,321,082✔
141
    code = calcConstCondition(pCtx, pNode);
6,321,082✔
142
  }
143
  
144
_end:
×
145

146
  if (code != TSDB_CODE_SUCCESS) {
29,811,677✔
147
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
148
    return DEAL_RES_ERROR;
×
149
  }
150
  
151
  return DEAL_RES_IGNORE_CHILD;
29,811,677✔
152
}
153

154
static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) {
511,097,111✔
155
  int32_t code = TSDB_CODE_SUCCESS;
511,097,111✔
156
  switch (nodeType(pTable)) {
511,097,111✔
157
    case QUERY_NODE_TEMP_TABLE: {
58,766,608✔
158
      code = calcConstSubquery(pCxt, (STempTableNode*)pTable);
58,766,608✔
159
      break;
58,766,608✔
160
    }
161
    case QUERY_NODE_JOIN_TABLE: {
24,108,788✔
162
      SJoinTableNode* pJoin = (SJoinTableNode*)pTable;
24,108,788✔
163
      SNode* pCond = NULL;
24,108,788✔
164
      code = rewriteConditionForFromTable(pCxt, pJoin->pLeft);
24,108,788✔
165
      if (TSDB_CODE_SUCCESS == code) {
24,106,923✔
166
        code = rewriteConditionForFromTable(pCxt, pJoin->pRight);
24,107,287✔
167
      }
168
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
24,107,440✔
169
        code = rewriteCondition(pCxt, &pJoin->pOnCond);
23,751,040✔
170
      }
171
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
24,107,680✔
172
        nodesRewriteExpr(&pJoin->pOnCond, rewriteCalcConstValue, pCxt);
23,751,366✔
173
      }
174

175
/*
176
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
177
        code = nodesCloneNode(pJoin->pOnCond, &pCond);
178
      }
179
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
180
        code = calcConstCondition(pCxt, &pJoin->pOnCond);
181
      }
182
      if (TSDB_CODE_SUCCESS == code && pJoin->pOnCond && QUERY_NODE_VALUE == nodeType(pJoin->pOnCond)) {
183
        nodesDestroyNode(pJoin->pOnCond);
184
        pJoin->pOnCond = pCond;
185
        pCond = NULL;
186
      }
187
      nodesDestroyNode(pCond);
188
*/
189
      // todo empty table
190
      break;
24,108,226✔
191
    }
192
    default:
428,222,361✔
193
      break;
428,222,361✔
194
  }
195
  return code;
511,097,195✔
196
}
197

198
static int32_t calcConstFromTable(SCalcConstContext* pCxt, SNode* pTable) {
462,870,727✔
199
  return rewriteConditionForFromTable(pCxt, pTable);
462,870,727✔
200
}
201

202
static void rewriteConstCondition(SNode** pCond, bool* pAlwaysFalse) {
151,054,234✔
203
  if (QUERY_NODE_VALUE != nodeType(*pCond)) {
151,054,234✔
204
    return;
139,621,244✔
205
  }
206
  if (((SValueNode*)*pCond)->datum.b) {
11,433,025✔
207
    nodesDestroyNode(*pCond);
2,752,368✔
208
    *pCond = NULL;
2,752,368✔
209
  } else {
210
    *pAlwaysFalse = true;
8,680,657✔
211
  }
212
}
213

214
static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bool* pAlwaysFalse) {
910,505,677✔
215
  if (NULL == *pCond) {
910,505,677✔
216
    return TSDB_CODE_SUCCESS;
759,388,060✔
217
  }
218

219
  int32_t code = rewriteCondition(pCxt, pCond);
151,118,110✔
220
  if (TSDB_CODE_SUCCESS == code) {
151,131,091✔
221
    code = calcConstNode(pCond);
151,131,169✔
222
  }
223
  if (TSDB_CODE_SUCCESS == code) {
151,128,479✔
224
    rewriteConstCondition(pCond, pAlwaysFalse);
151,053,295✔
225
  }
226
  return code;
151,131,942✔
227
}
228

229
static EDealRes doFindAndReplaceNode(SNode** pNode, void* pContext) {
3,708✔
230
  SCalcConstContext* pCxt = pContext;
3,708✔
231
  if (pCxt->replaceCxt.pTarget == *pNode) {
3,708✔
232
    char aliasName[TSDB_COL_NAME_LEN] = {0};
3,708✔
233
    tstrncpy(aliasName, ((SExprNode*)*pNode)->aliasName, TSDB_COL_NAME_LEN);
3,708✔
234
    nodesDestroyNode(*pNode);
3,708✔
235
    *pNode = NULL;
3,708✔
236
    pCxt->code = nodesCloneNode(pCxt->replaceCxt.pNew, pNode);
3,708✔
237
    if (NULL == *pNode) {
3,708✔
238
      return DEAL_RES_ERROR;
×
239
    }
240
    tstrncpy(((SExprNode*)*pNode)->aliasName, aliasName, TSDB_COL_NAME_LEN);
3,708✔
241

242
    pCxt->replaceCxt.replaced = true;
3,708✔
243
    return DEAL_RES_END;
3,708✔
244
  }
245
  return DEAL_RES_CONTINUE;
×
246
}
247

248
static int32_t findAndReplaceNode(SCalcConstContext* pCxt, SNode** pRoot, SNode* pTarget, SNode* pNew, bool strict) {
3,708✔
249
  pCxt->replaceCxt.pNew = pNew;
3,708✔
250
  pCxt->replaceCxt.pTarget = pTarget;
3,708✔
251

252
  nodesRewriteExprPostOrder(pRoot, doFindAndReplaceNode, pCxt);
3,708✔
253
  if (TSDB_CODE_SUCCESS == pCxt->code && strict && !pCxt->replaceCxt.replaced) {
3,708✔
254
    parserError("target replace node not found, %p", pTarget);
×
255
    return TSDB_CODE_PAR_INTERNAL_ERROR;
×
256
  }
257
  return pCxt->code;
3,708✔
258
}
259

260
static int32_t calcConstProject(SCalcConstContext* pCxt, SNode* pProject, bool dual, SNode** pNew) {
1,141,365,371✔
261
  SArray* pAssociation = NULL;
1,141,365,371✔
262
  
263
  if (NULL != ((SExprNode*)pProject)->pAssociation) {
1,141,365,371✔
264
    pAssociation = taosArrayDup(((SExprNode*)pProject)->pAssociation, NULL);
90,975,109✔
265
    if (NULL == pAssociation) {
90,975,109✔
266
      return terrno;
×
267
    }
268
  }
269

270
  char    aliasName[TSDB_COL_NAME_LEN] = {0}, srcTable[TSDB_TABLE_NAME_LEN] = {0};
1,141,368,001✔
271
  int32_t code = TSDB_CODE_SUCCESS;
1,141,367,870✔
272
  if (dual) {
1,141,367,870✔
273
    code = scalarCalculateConstantsFromDual(pProject, pNew);
15,406,481✔
274
  } else {
275
    code = scalarCalculateConstants(pProject, pNew);
1,125,961,389✔
276
  }
277
  if (TSDB_CODE_SUCCESS == code) {
1,141,394,328✔
278
    if (QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
1,141,297,007✔
279
      int32_t size = taosArrayGetSize(pAssociation);
2,579,259✔
280
      for (int32_t i = 0; i < size; ++i) {
5,284,466✔
281
        SAssociationNode* pAssNode = taosArrayGet(pAssociation, i);
2,705,207✔
282
        SNode**           pCol = pAssNode->pPlace;
2,705,207✔
283
        if (((SExprNode*)pAssNode->pAssociationNode)->joinSrc) {
2,705,207✔
284
          //((SExprNode*)pAssNode->pAssociationNode)->constValue = true;
285
          continue;
55,956✔
286
        }
287
        
288
        if (*pCol == pAssNode->pAssociationNode) {
2,649,251✔
289
          tstrncpy(aliasName, ((SExprNode*)*pCol)->aliasName, TSDB_COL_NAME_LEN);
2,645,543✔
290
          if (QUERY_NODE_COLUMN == nodeType(*pCol)) {
2,645,543✔
291
            tstrncpy(srcTable, ((SColumnNode*)*pCol)->tableAlias, TSDB_TABLE_NAME_LEN);
2,645,543✔
292
          }
293
          SArray* pOrigAss = NULL;
2,645,543✔
294
          TSWAP(((SExprNode*)*pCol)->pAssociation, pOrigAss);
2,645,543✔
295
          nodesDestroyNode(*pCol);
2,645,543✔
296
          *pCol = NULL;
2,645,543✔
297
          code = nodesCloneNode(*pNew, pCol);
2,645,543✔
298
          if (TSDB_CODE_SUCCESS == code) {
2,645,543✔
299
            tstrncpy(((SExprNode*)*pCol)->aliasName, aliasName, TSDB_COL_NAME_LEN);
2,645,543✔
300
            if (srcTable[0]) {
2,645,543✔
301
              tstrncpy(((SExprNode*)*pCol)->srcTable, srcTable, TSDB_TABLE_NAME_LEN);
2,645,543✔
302
            }
303
            TSWAP(pOrigAss, ((SExprNode*)*pCol)->pAssociation);
2,645,543✔
304
          }
305
          taosArrayDestroy(pOrigAss);
2,645,543✔
306
          if (TSDB_CODE_SUCCESS != code) {
2,645,543✔
307
            break;
×
308
          }
309
        } else {
310
          code = findAndReplaceNode(pCxt, pCol, pAssNode->pAssociationNode, *pNew, true);
3,708✔
311
          if (TSDB_CODE_SUCCESS != code) {
3,708✔
312
            break;
×
313
          }
314
        }
315
      }
316
    }
317
  }
318
  taosArrayDestroy(pAssociation);
1,141,394,380✔
319
  return code;
1,141,376,526✔
320
}
321

322
typedef struct SIsUselessColCtx {
323
  bool isUseless;
324
} SIsUselessColCtx;
325

326
EDealRes checkUselessCol(SNode* pNode, void* pContext) {
282,593,163✔
327
  SIsUselessColCtx* ctx = (SIsUselessColCtx*)pContext;
282,593,163✔
328
  if (QUERY_NODE_FUNCTION == nodeType(pNode) &&
282,593,163✔
329
      !fmIsScalarFunc(((SFunctionNode*)pNode)->funcId) &&
41,077,850✔
330
      !fmIsPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)) {
20,999,857✔
331
    ctx->isUseless = false;
17,801,652✔
332
    return DEAL_RES_END;
17,801,652✔
333
  }
334

335
  return DEAL_RES_CONTINUE;
264,791,795✔
336
}
337

338
static bool isUselessCol(SExprNode* pProj) {
237,763,942✔
339
  SIsUselessColCtx ctx = {.isUseless = true};
237,763,942✔
340
  nodesWalkExpr((SNode*)pProj, checkUselessCol, (void*)&ctx);
237,763,942✔
341
  if (!ctx.isUseless) {
237,764,412✔
342
    return false;
17,801,652✔
343
  }
344
  return NULL == ((SExprNode*)pProj)->pAssociation;
219,962,760✔
345
}
346

347
static int32_t createConstantValue(SValueNode** ppNode) {
317,775✔
348
  SValueNode* pVal = NULL;
317,775✔
349
  int32_t     code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pVal);
317,775✔
350
  if (NULL == pVal) {
317,775✔
351
    return code;
×
352
  }
353
  pVal->node.resType.type = TSDB_DATA_TYPE_INT;
317,775✔
354
  pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_INT].bytes;
317,775✔
355
  const int32_t val = 1;
317,775✔
356
  code = nodesSetValueNodeValue(pVal, (void*)&val);
317,775✔
357
  if (TSDB_CODE_SUCCESS == code) {
317,775✔
358
    pVal->translate = true;
317,775✔
359
    *ppNode = pVal;
317,775✔
360
  } else {
361
    nodesDestroyNode((SNode*)pVal);
×
362
  }
363
  return code;
317,775✔
364
}
365

366
static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
468,360,839✔
367
  SNode* pProj = NULL;
468,360,839✔
368
  WHERE_EACH(pProj, pSelect->pProjectionList) {
1,747,929,687✔
369
    if (subquery && !pSelect->isDistinct && !pSelect->tagScan && isUselessCol((SExprNode*)pProj) && (pSelect->pFromTable && nodeType(pSelect->pFromTable) != QUERY_NODE_VIRTUAL_TABLE)) {
1,279,646,931✔
370
      ERASE_NODE(pSelect->pProjectionList);
138,267,077✔
371
      continue;
138,267,077✔
372
    }
373
    SNode*  pNew = NULL;
1,141,379,858✔
374
    int32_t code = calcConstProject(pCxt, pProj, (NULL == pSelect->pFromTable), &pNew);
1,141,379,867✔
375
    if (TSDB_CODE_SUCCESS == code) {
1,141,379,178✔
376
      REPLACE_NODE(pNew);
1,141,303,574✔
377
    } else {
378
      return code;
80,527✔
379
    }
380
    WHERE_NEXT;
1,141,304,045✔
381
  }
382
  if (0 == LIST_LENGTH(pSelect->pProjectionList)) {
468,284,928✔
383
    SValueNode* pVal = NULL;
313,197✔
384
    int32_t     code = createConstantValue(&pVal);
312,638✔
385
    if (TSDB_CODE_SUCCESS == code) {
313,225✔
386
      return nodesListStrictAppend(pSelect->pProjectionList, (SNode*)pVal);
313,225✔
387
    }
388
  }
389
  return TSDB_CODE_SUCCESS;
467,972,324✔
390
}
391

392
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
454,337,498✔
393
  int32_t code = calcConstList(pSelect->pGroupByList);
454,337,498✔
394
  if (TSDB_CODE_SUCCESS == code) {
454,347,750✔
395
    SNode* pNode = NULL;
454,350,993✔
396
    FOREACH(pNode, pSelect->pGroupByList) {
493,280,999✔
397
      bool   hasNotValue = false;
38,928,661✔
398
      SNode* pGroupPara = NULL;
38,928,661✔
399
      FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
40,303,643✔
400
        if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
38,929,747✔
401
          hasNotValue = true;
37,554,765✔
402
          break;
37,554,765✔
403
        }
404
      }
405
      if (!hasNotValue) {
38,928,661✔
406
        if (pSelect->hasAggFuncs) {
1,374,982✔
407
          ERASE_NODE(pSelect->pGroupByList);
37,498✔
408
        } else {
409
          if (!cell->pPrev && !cell->pNext) continue;
1,337,484✔
410
          ERASE_NODE(pSelect->pGroupByList);
×
411
        }
412
      }
413
    }
414
  }
415
  return code;
454,347,908✔
416
}
417

418
static int32_t calcConstSelectWithoutFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
13,870,479✔
419
  return calcConstProjections(pCxt, pSelect, subquery);
13,870,479✔
420
}
421

422
static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
460,606,590✔
423
  int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
460,606,590✔
424
  if (TSDB_CODE_SUCCESS == code && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
460,611,880✔
425
      ((STempTableNode*)pSelect->pFromTable)->pSubquery != NULL &&
58,203,172✔
426
      QUERY_NODE_SELECT_STMT == nodeType(((STempTableNode*)pSelect->pFromTable)->pSubquery) &&
58,203,172✔
427
      ((SSelectStmt*)((STempTableNode*)pSelect->pFromTable)->pSubquery)->isEmptyResult) {
53,784,033✔
428
    pSelect->isEmptyResult = true;
6,112,556✔
429
    return code;
6,112,556✔
430
  }
431
  if (pSelect->mixSysTableAndActualTable) {
454,499,358✔
432
    return code;
376✔
433
  }
434
  if (TSDB_CODE_SUCCESS == code) {
454,498,609✔
435
    code = calcConstProjections(pCxt, pSelect, subquery);
454,494,654✔
436
  }
437
  if (TSDB_CODE_SUCCESS == code) {
454,505,050✔
438
    code = calcConstStmtCondition(pCxt, &pSelect->pWhere, &pSelect->isEmptyResult);
454,427,084✔
439
  }
440
  if (TSDB_CODE_SUCCESS == code) {
454,503,768✔
441
    code = calcConstList(pSelect->pPartitionByList);
454,341,028✔
442
  }
443
  if (TSDB_CODE_SUCCESS == code) {
454,505,092✔
444
    code = calcConstNode(&pSelect->pWindow);
454,346,691✔
445
  }
446
  if (TSDB_CODE_SUCCESS == code) {
454,506,721✔
447
    code = calcConstGroupBy(pCxt, pSelect);
454,350,988✔
448
  }
449
  if (TSDB_CODE_SUCCESS == code) {
454,499,022✔
450
    code = calcConstStmtCondition(pCxt, &pSelect->pHaving, &pSelect->isEmptyResult);
454,347,835✔
451
  }
452
  if (TSDB_CODE_SUCCESS == code) {
454,505,806✔
453
    code = calcConstList(pSelect->pOrderByList);
454,337,798✔
454
  }
455
  if (TSDB_CODE_SUCCESS == code) {
454,516,222✔
456
    code = calcConstNode(&pSelect->pFill);
454,351,548✔
457
  }
458
  if (TSDB_CODE_SUCCESS == code) {
454,518,664✔
459
    code = calcConstNode(&pSelect->pTimeRange);
454,355,206✔
460
  }
461
  return code;
454,508,820✔
462
}
463

464

465
static bool isEmptyResultQuery(SNode* pStmt) {
452,793,397✔
466
  bool isEmptyResult = false;
452,793,397✔
467
  switch (nodeType(pStmt)) {
452,793,397✔
468
    case QUERY_NODE_SELECT_STMT:
211,786,292✔
469
      isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult;
211,786,292✔
470
      break;
211,786,775✔
471
    case QUERY_NODE_EXPLAIN_STMT:
50,316,142✔
472
      isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery);
50,316,142✔
473
      break;
50,308,862✔
474
    case QUERY_NODE_SET_OPERATOR: {
8,093,062✔
475
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
8,093,062✔
476
      isEmptyResult = isEmptyResultQuery(pSetOp->pLeft);
8,093,062✔
477
      if (isEmptyResult) {
8,092,977✔
478
        isEmptyResult = isEmptyResultQuery(pSetOp->pRight);
530✔
479
      }
480
      break;
8,092,905✔
481
    }
482
    case QUERY_NODE_DELETE_STMT:
1,753,555✔
483
      isEmptyResult = ((SDeleteStmt*)pStmt)->deleteZeroRows;
1,753,555✔
484
      break;
1,746,033✔
485
    default:
180,852,038✔
486
      break;
180,852,038✔
487
  }
488
  return isEmptyResult;
452,786,613✔
489
}
490

491
static int32_t calcSubQueries(SCalcConstContext* pCxt, SNodeList* pSubQueries) {
82,433,128✔
492
  int32_t code = TSDB_CODE_SUCCESS;
82,433,128✔
493
  SNode* pNode = NULL;
82,433,128✔
494
  FOREACH(pNode, pSubQueries) {
256,454,566✔
495
    code = calcConstQuery(pCxt, pNode, false);
174,016,196✔
496
    if (code) {
174,021,438✔
497
      break;
×
498
    }
499
/*
500
    if (isEmptyResultQuery(pNode) && nodesIsScalarSubQuery(pNode)) {
501
      // TODO
502
      parserError("%" PRIx64 " scalar subquery got empty result", pCxt->pParseCxt->requestId);
503
      code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_ROWS;
504
      break;
505
    }
506
*/
507
  }
508

509
  return code;
82,438,370✔
510
}
511

512
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
474,476,622✔
513
  int32_t code = TSDB_CODE_SUCCESS;
474,476,622✔
514
  
515
  if (NULL == pSelect->pFromTable) {
474,476,622✔
516
    code = calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
13,870,407✔
517
  } else {
518
    code = calcConstSelectFrom(pCxt, pSelect, subquery);
460,606,666✔
519
  }
520

521
  if (TSDB_CODE_SUCCESS == code && pSelect->pSubQueries && pSelect->pSubQueries->length > 0) {
474,490,437✔
522
    code = calcSubQueries(pCxt, pSelect->pSubQueries);
80,498,712✔
523
  }
524

525
  return code;
474,491,836✔
526
}
527

528
static int32_t calcConstDelete(SCalcConstContext* pCxt, SDeleteStmt* pDelete) {
1,746,033✔
529
  int32_t code = calcConstFromTable(pCxt, pDelete->pFromTable);
1,746,033✔
530
  if (TSDB_CODE_SUCCESS == code) {
1,746,033✔
531
    code = calcConstStmtCondition(pCxt, &pDelete->pWhere, &pDelete->deleteZeroRows);
1,746,033✔
532
  }
533
  if (code == TSDB_CODE_SUCCESS && pDelete->timeRange.skey > pDelete->timeRange.ekey) {
1,746,033✔
534
    pDelete->deleteZeroRows = true;
202,406✔
535
  }
536
  return code;
1,746,033✔
537
}
538

539
static int32_t calcConstInsert(SCalcConstContext* pCxt, SInsertStmt* pInsert) {
519,745✔
540
  int32_t code = calcConstFromTable(pCxt, pInsert->pTable);
519,745✔
541
  if (TSDB_CODE_SUCCESS == code) {
519,745✔
542
    code = calcConstQuery(pCxt, pInsert->pQuery, false);
519,745✔
543
  }
544
  return code;
519,745✔
545
}
546

547
static SNodeList* getChildProjection(SNode* pStmt) {
3,261,240✔
548
  switch (nodeType(pStmt)) {
3,261,240✔
549
    case QUERY_NODE_SELECT_STMT:
3,239,150✔
550
      return ((SSelectStmt*)pStmt)->pProjectionList;
3,239,150✔
551
    case QUERY_NODE_SET_OPERATOR:
22,090✔
552
      return ((SSetOperator*)pStmt)->pProjectionList;
22,090✔
553
    default:
×
554
      break;
×
555
  }
556
  return NULL;
×
557
}
558

559
static void eraseSetOpChildProjection(SSetOperator* pSetOp, int32_t index) {
1,630,620✔
560
  SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft);
1,630,620✔
561
  (void)nodesListErase(pLeftProjs, nodesListGetCell(pLeftProjs, index));
1,630,620✔
562
  if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pLeft)) {
1,630,620✔
563
    eraseSetOpChildProjection((SSetOperator*)pSetOp->pLeft, index);
22,090✔
564
  }
565
  SNodeList* pRightProjs = getChildProjection(pSetOp->pRight);
1,630,620✔
566
  (void)nodesListErase(pRightProjs, nodesListGetCell(pRightProjs, index));
1,630,620✔
567
  if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pRight)) {
1,630,620✔
568
    eraseSetOpChildProjection((SSetOperator*)pSetOp->pRight, index);
×
569
  }
570
}
1,630,620✔
571

572
typedef struct SNotRefByOrderByCxt {
573
  SColumnNode* pCol;
574
  bool         hasThisCol;
575
} SNotRefByOrderByCxt;
576

577
static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) {
11,430,388✔
578
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
11,430,388✔
579
    SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext;
5,715,194✔
580
    if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) {
5,715,194✔
581
      pCxt->hasThisCol = true;
1,903,606✔
582
      return DEAL_RES_END;
1,903,606✔
583
    }
584
  }
585
  return DEAL_RES_CONTINUE;
9,526,782✔
586
}
587

588
static bool notRefByOrderBy(SColumnNode* pCol, SNodeList* pOrderByList) {
6,301,087✔
589
  SNotRefByOrderByCxt cxt = {.pCol = pCol, .hasThisCol = false};
6,301,087✔
590
  nodesWalkExprs(pOrderByList, notRefByOrderByImpl, &cxt);
6,301,087✔
591
  return !cxt.hasThisCol;
6,301,087✔
592
}
593

594
/*
595
 * @brief Check whether the projection column at `index` can be treated as
596
 * useless for a subquery output. Rules:
597
 *   SELECT: useless only when the statement is not DISTINCT and the indexed
598
 *     projection is useless.
599
 *   SET_OPERATOR:
600
 *     UNION (distinct): never useless, because output depends on all
601
 *       projected columns.
602
 *     UNION ALL: useless only when both left and right branches are useless
603
 *       at the same index (checked recursively).
604
 * @param pStmt subquery node, expected to be SELECT or SET_OPERATOR.
605
 * @param index zero-based projection position to check.
606
 */
607
static bool isSubqueryProjUseless(SNode* pStmt, int32_t index) {
3,318,547✔
608
  if (NULL == pStmt || index < 0) {
3,318,547✔
609
    return false;
×
610
  }
611

612
  switch (nodeType(pStmt)) {
3,318,547✔
613
    case QUERY_NODE_SELECT_STMT: {
3,286,917✔
614
      SSelectStmt* pSelect = (SSelectStmt*)pStmt;
3,286,917✔
615
      if (pSelect->isDistinct) {
3,286,917✔
616
        return false;
×
617
      }
618
      SNode* pProj = nodesListGetNode(pSelect->pProjectionList, index);
3,286,917✔
619
      return (NULL != pProj) && isUselessCol((SExprNode*)pProj);
3,286,917✔
620
    }
621
    case QUERY_NODE_SET_OPERATOR: {
31,630✔
622
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
31,630✔
623
      /*
624
       * UNION (distinct) depends on all output columns,
625
       * projection pruning is unsafe here.
626
       */
627
      if (pSetOp->opType == SET_OP_TYPE_UNION) {
31,630✔
628
        return false;
×
629
      }
630
      return isSubqueryProjUseless(pSetOp->pLeft, index) &&
54,780✔
631
             isSubqueryProjUseless(pSetOp->pRight, index);
23,150✔
632
    }
633
    default:
×
634
      break;
×
635
  }
636
  return false;
×
637
}
638

639
static bool isSetUselessCol(SSetOperator* pSetOp, int32_t index, SExprNode* pProj) {
4,397,481✔
640
  if (!isUselessCol(pProj)) {
4,397,481✔
641
    return false;
2,742,244✔
642
  }
643

644
  return isSubqueryProjUseless(pSetOp->pLeft, index) &&
3,263,767✔
645
         isSubqueryProjUseless(pSetOp->pRight, index);
1,608,530✔
646
}
647

648
static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
29,233,661✔
649
  if (subquery && pSetOp->opType == SET_OP_TYPE_UNION) {
29,233,661✔
650
    return TSDB_CODE_SUCCESS;
2,236,507✔
651
  }
652
  int32_t index = 0;
26,997,154✔
653
  SNode*  pProj = NULL;
26,997,154✔
654
  WHERE_EACH(pProj, pSetOp->pProjectionList) {
64,434,703✔
655
    if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) &&
41,834,064✔
656
        isSetUselessCol(pSetOp, index, (SExprNode*)pProj)) {
4,397,481✔
657
      ERASE_NODE(pSetOp->pProjectionList);
1,608,167✔
658
      eraseSetOpChildProjection(pSetOp, index);
1,608,530✔
659
      continue;
1,609,133✔
660
    }
661
    ++index;
35,828,416✔
662
    WHERE_NEXT;
35,828,416✔
663
  }
664
  if (0 == LIST_LENGTH(pSetOp->pProjectionList)) {
26,998,120✔
665
    SValueNode* pVal = NULL;
5,294✔
666
    int32_t     code = createConstantValue(&pVal);
5,294✔
667
    if (TSDB_CODE_SUCCESS == code) {
4,550✔
668
      return nodesListStrictAppend(pSetOp->pProjectionList, (SNode*)pVal);
4,550✔
669
    }
670
  }
671
  return TSDB_CODE_SUCCESS;
26,992,830✔
672
}
673

674
static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
29,234,049✔
675
  int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery);
29,234,049✔
676
  if (TSDB_CODE_SUCCESS == code) {
29,234,552✔
677
    code = calcConstQuery(pCxt, pSetOp->pLeft, false);
29,235,842✔
678
  }
679
  if (TSDB_CODE_SUCCESS == code) {
29,236,057✔
680
    code = calcConstQuery(pCxt, pSetOp->pRight, false);
29,235,041✔
681
  }
682
  if (TSDB_CODE_SUCCESS == code) {
29,238,818✔
683
    code = calcConstList(pSetOp->pOrderByList);
29,237,802✔
684
  }
685
  if (TSDB_CODE_SUCCESS == code && pSetOp->pSubQueries && pSetOp->pSubQueries->length > 0) {
29,238,905✔
686
    code = calcSubQueries(pCxt, pSetOp->pSubQueries);
1,955,738✔
687
  }
688
  
689
  return code;
29,237,975✔
690
}
691

692
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
736,641,695✔
693
  int32_t code = TSDB_CODE_SUCCESS;
736,641,695✔
694
  switch (nodeType(pStmt)) {
736,641,695✔
695
    case QUERY_NODE_SELECT_STMT:
474,490,559✔
696
      code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery);
474,490,559✔
697
      break;
474,491,517✔
698
    case QUERY_NODE_EXPLAIN_STMT:
50,321,626✔
699
      code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery);
50,321,626✔
700
      break;
50,327,083✔
701
    case QUERY_NODE_SET_OPERATOR: {
29,236,908✔
702
      code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery);
29,236,908✔
703
      break;
29,237,975✔
704
    }
705
    case QUERY_NODE_DELETE_STMT:
1,746,033✔
706
      code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
1,746,033✔
707
      break;
1,746,033✔
708
    case QUERY_NODE_INSERT_STMT:
522,030✔
709
      code = calcConstInsert(pCxt, (SInsertStmt*)pStmt);
522,030✔
710
      break;
519,745✔
711
    default:
180,327,016✔
712
      break;
180,327,016✔
713
  }
714
  return code;
736,649,369✔
715
}
716

717

718
static void resetProjectNullTypeImpl(SNodeList* pProjects) {
172,369,817✔
719
  SNode* pProj = NULL;
172,369,817✔
720
  FOREACH(pProj, pProjects) {
880,966,801✔
721
    SExprNode* pExpr = (SExprNode*)pProj;
708,597,338✔
722
    if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
708,597,338✔
723
      pExpr->resType.type = TSDB_DATA_TYPE_VARCHAR;
181,068✔
724
      pExpr->resType.bytes = VARSTR_HEADER_SIZE;
181,068✔
725
      if (QUERY_NODE_VALUE == nodeType(pExpr)) {
181,068✔
726
        ((SValueNode*)pExpr)->isNull = true;
22,128✔
727
      }
728
    }
729
  }
730
}
172,370,650✔
731

732
static void resetProjectNullType(SNode* pStmt) {
405,277,632✔
733
  switch (nodeType(pStmt)) {
405,277,632✔
734
    case QUERY_NODE_SELECT_STMT:
166,924,728✔
735
      resetProjectNullTypeImpl(((SSelectStmt*)pStmt)->pProjectionList);
166,924,728✔
736
      break;
166,924,533✔
737
    case QUERY_NODE_SET_OPERATOR: {
5,444,880✔
738
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
5,444,880✔
739
      resetProjectNullTypeImpl(pSetOp->pProjectionList);
5,444,880✔
740
      if (pSetOp->pLeft)
5,446,117✔
741
        resetProjectNullType(pSetOp->pLeft);
5,446,117✔
742
      if (pSetOp->pRight)
5,446,117✔
743
        resetProjectNullType(pSetOp->pRight);
5,446,117✔
744
      break;
5,446,117✔
745
    }
746
    default:
232,904,362✔
747
      break;
232,904,362✔
748
  }
749
}
405,275,012✔
750

751
static int32_t rewriteScalarSubQResValue(SParseContext* pParseCxt, SQuery* pQuery) {
394,384,212✔
752
  // TODO
753
  return TSDB_CODE_SUCCESS;
394,384,212✔
754
}
755

756
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) {
394,542,732✔
757
  SCalcConstContext cxt = {.pParseCxt = pParseCxt,
394,542,732✔
758
                           .msgBuf.buf = pParseCxt->pMsg,
394,535,724✔
759
                           .msgBuf.len = pParseCxt->msgLen,
394,547,564✔
760
                           .code = TSDB_CODE_SUCCESS};
761

762
  int32_t code = TSDB_CODE_SUCCESS;
394,536,559✔
763

764
  if (TSDB_CODE_SUCCESS == code) {
394,536,559✔
765
    code = calcConstQuery(&cxt, pQuery->pRoot, false);
394,545,790✔
766
  }
767
  if (TSDB_CODE_SUCCESS == code) {
394,537,720✔
768
    resetProjectNullType(pQuery->pRoot);
394,395,959✔
769
    if (isEmptyResultQuery(pQuery->pRoot)) {
394,371,141✔
770
      pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
621,276✔
771
    }
772
    code = rewriteScalarSubQResValue(pParseCxt, pQuery);
394,384,357✔
773
  }
774
  
775
  return code;
394,521,769✔
776
}
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

© 2026 Coveralls, Inc