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

taosdata / TDengine / #5052

13 May 2026 12:00PM UTC coverage: 73.338% (-0.02%) from 73.358%
#5052

push

travis-ci

web-flow
feat: taosdump support stream backup/restore (#35326)

139 of 170 new or added lines in 3 files covered. (81.76%)

761 existing lines in 163 files now uncovered.

281469 of 383795 relevant lines covered (73.34%)

134502812.98 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) {
61,126,277✔
37
  return calcConstQuery(pCxt, pTempTable->pSubquery, true);
61,126,277✔
38
}
39

40
static int32_t calcConstNode(SNode** pNode) {
1,611,943,010✔
41
  if (NULL == *pNode) {
1,611,943,010✔
42
    return TSDB_CODE_SUCCESS;
1,359,472,633✔
43
  }
44

45
  SNode*  pNew = NULL;
252,470,508✔
46
  int32_t code = scalarCalculateConstants(*pNode, &pNew);
252,471,203✔
47
  if (TSDB_CODE_SUCCESS == code) {
252,511,852✔
48
    *pNode = pNew;
252,432,106✔
49
  }
50
  return code;
252,511,852✔
51
}
52

53
static int32_t calcConstList(SNodeList* pList) {
1,429,355,877✔
54
  SNode* pNode = NULL;
1,429,355,877✔
55
  FOREACH(pNode, pList) {
1,640,139,640✔
56
    SNode*  pNew = NULL;
210,774,577✔
57
    int32_t code = scalarCalculateConstants(pNode, &pNew);
210,774,577✔
58
    if (TSDB_CODE_SUCCESS == code) {
210,783,634✔
59
      REPLACE_NODE(pNew);
210,783,749✔
60
    } else {
UNCOV
61
      return code;
×
62
    }
63
  }
64
  return TSDB_CODE_SUCCESS;
1,429,364,908✔
65
}
66

67
static bool isCondition(const SNode* pNode) {
323,006,915✔
68
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
323,006,915✔
69
    return nodesIsComparisonOp((const SOperatorNode*)pNode);
265,700,404✔
70
  }
71
  return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
57,306,511✔
72
}
73

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

88
static EDealRes doRewriteCondition(SNode** pNode, void* pContext) {
930,625,187✔
89
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
930,625,187✔
90
    SNode* pParam = NULL;
55,941,553✔
91
    FOREACH(pParam, ((SLogicConditionNode*)*pNode)->pParameterList) {
190,587,484✔
92
      if (!isCondition(pParam)) {
134,646,465✔
93
        SNode* pIsTrue = NULL;
303,026✔
94
        if (TSDB_CODE_SUCCESS != rewriteIsTrue(pParam, &pIsTrue)) {
303,026✔
95
          ((SCalcConstContext*)pContext)->code = TSDB_CODE_OUT_OF_MEMORY;
×
96
          return DEAL_RES_ERROR;
×
97
        }
98
        REPLACE_NODE(pIsTrue);
303,218✔
99
      }
100
    }
101
  }
102
  return DEAL_RES_CONTINUE;
930,624,785✔
103
}
104

105
static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) {
188,360,760✔
106
  if (!isCondition(*pNode)) {
188,360,760✔
107
    return rewriteIsTrue(*pNode, pNode);
1,075,575✔
108
  }
109
  nodesRewriteExprPostOrder(pNode, doRewriteCondition, pCxt);
187,288,928✔
110
  return pCxt->code;
187,293,883✔
111
}
112

113
static int32_t calcConstCondition(SCalcConstContext* pCxt, SNode** pNode) {
6,540,554✔
114
  int32_t code = rewriteCondition(pCxt, pNode);
6,540,554✔
115
  if (TSDB_CODE_SUCCESS == code) {
6,540,736✔
116
    code = calcConstNode(pNode);
6,540,736✔
117
  }
118
  return code;
6,540,736✔
119
}
120

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

126
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
36,594,124✔
127
    return DEAL_RES_CONTINUE;
5,729,656✔
128
  } else if (QUERY_NODE_OPERATOR == nodeType(*pNode)) {
30,864,468✔
129
    SOperatorNode* pOp = (SOperatorNode*)*pNode;
30,865,219✔
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)) {
30,865,219✔
131
      code = calcConstNode(&pOp->pLeft);
24,323,732✔
132
      if (TSDB_CODE_SUCCESS == code) {
24,324,397✔
133
        code = calcConstNode(&pOp->pRight);
24,324,493✔
134
      }
135
      
136
      goto _end;
24,324,652✔
137
    }
138
  }
139

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

146
  if (code != TSDB_CODE_SUCCESS) {
30,865,388✔
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;
30,865,388✔
152
}
153

154
static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) {
525,422,900✔
155
  int32_t code = TSDB_CODE_SUCCESS;
525,422,900✔
156
  switch (nodeType(pTable)) {
525,422,900✔
157
    case QUERY_NODE_TEMP_TABLE: {
61,126,989✔
158
      code = calcConstSubquery(pCxt, (STempTableNode*)pTable);
61,126,989✔
159
      break;
61,127,101✔
160
    }
161
    case QUERY_NODE_JOIN_TABLE: {
24,980,562✔
162
      SJoinTableNode* pJoin = (SJoinTableNode*)pTable;
24,980,562✔
163
      SNode* pCond = NULL;
24,980,562✔
164
      code = rewriteConditionForFromTable(pCxt, pJoin->pLeft);
24,980,562✔
165
      if (TSDB_CODE_SUCCESS == code) {
24,979,583✔
166
        code = rewriteConditionForFromTable(pCxt, pJoin->pRight);
24,980,003✔
167
      }
168
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
24,979,597✔
169
        code = rewriteCondition(pCxt, &pJoin->pOnCond);
24,603,204✔
170
      }
171
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
24,979,875✔
172
        nodesRewriteExpr(&pJoin->pOnCond, rewriteCalcConstValue, pCxt);
24,603,569✔
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,980,787✔
191
    }
192
    default:
439,315,431✔
193
      break;
439,315,431✔
194
  }
195
  return code;
525,423,319✔
196
}
197

198
static int32_t calcConstFromTable(SCalcConstContext* pCxt, SNode* pTable) {
475,453,270✔
199
  return rewriteConditionForFromTable(pCxt, pTable);
475,453,270✔
200
}
201

202
static void rewriteConstCondition(SNode** pCond, bool* pAlwaysFalse) {
157,143,601✔
203
  if (QUERY_NODE_VALUE != nodeType(*pCond)) {
157,143,601✔
204
    return;
145,150,573✔
205
  }
206
  if (((SValueNode*)*pCond)->datum.b) {
11,993,611✔
207
    nodesDestroyNode(*pCond);
2,897,698✔
208
    *pCond = NULL;
2,897,698✔
209
  } else {
210
    *pAlwaysFalse = true;
9,095,913✔
211
  }
212
}
213

214
static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bool* pAlwaysFalse) {
934,942,063✔
215
  if (NULL == *pCond) {
934,942,063✔
216
    return TSDB_CODE_SUCCESS;
777,730,940✔
217
  }
218

219
  int32_t code = rewriteCondition(pCxt, pCond);
157,211,279✔
220
  if (TSDB_CODE_SUCCESS == code) {
157,225,053✔
221
    code = calcConstNode(pCond);
157,224,967✔
222
  }
223
  if (TSDB_CODE_SUCCESS == code) {
157,221,674✔
224
    rewriteConstCondition(pCond, pAlwaysFalse);
157,142,466✔
225
  }
226
  return code;
157,225,634✔
227
}
228

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

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

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

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

260
static int32_t calcConstProject(SCalcConstContext* pCxt, SNode* pProject, bool dual, SNode** pNew) {
1,184,690,991✔
261
  SArray* pAssociation = NULL;
1,184,690,991✔
262
  
263
  if (NULL != ((SExprNode*)pProject)->pAssociation) {
1,184,690,991✔
264
    pAssociation = taosArrayDup(((SExprNode*)pProject)->pAssociation, NULL);
95,015,886✔
265
    if (NULL == pAssociation) {
95,015,841✔
266
      return terrno;
×
267
    }
268
  }
269

270
  char    aliasName[TSDB_COL_NAME_LEN] = {0}, srcTable[TSDB_TABLE_NAME_LEN] = {0};
1,184,692,583✔
271
  int32_t code = TSDB_CODE_SUCCESS;
1,184,691,601✔
272
  if (dual) {
1,184,691,601✔
273
    code = scalarCalculateConstantsFromDual(pProject, pNew);
15,789,218✔
274
  } else {
275
    code = scalarCalculateConstants(pProject, pNew);
1,168,902,383✔
276
  }
277
  if (TSDB_CODE_SUCCESS == code) {
1,184,714,443✔
278
    if (QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
1,184,614,232✔
279
      int32_t size = taosArrayGetSize(pAssociation);
3,248,255✔
280
      for (int32_t i = 0; i < size; ++i) {
6,628,601✔
281
        SAssociationNode* pAssNode = taosArrayGet(pAssociation, i);
3,380,346✔
282
        SNode**           pCol = pAssNode->pPlace;
3,380,346✔
283
        if (((SExprNode*)pAssNode->pAssociationNode)->joinSrc) {
3,380,346✔
284
          //((SExprNode*)pAssNode->pAssociationNode)->constValue = true;
285
          continue;
58,951✔
286
        }
287
        
288
        if (*pCol == pAssNode->pAssociationNode) {
3,321,395✔
289
          tstrncpy(aliasName, ((SExprNode*)*pCol)->aliasName, TSDB_COL_NAME_LEN);
3,317,462✔
290
          if (QUERY_NODE_COLUMN == nodeType(*pCol)) {
3,317,462✔
291
            tstrncpy(srcTable, ((SColumnNode*)*pCol)->tableAlias, TSDB_TABLE_NAME_LEN);
3,317,462✔
292
          }
293
          SArray* pOrigAss = NULL;
3,317,462✔
294
          TSWAP(((SExprNode*)*pCol)->pAssociation, pOrigAss);
3,317,462✔
295
          nodesDestroyNode(*pCol);
3,317,462✔
296
          *pCol = NULL;
3,317,462✔
297
          code = nodesCloneNode(*pNew, pCol);
3,317,462✔
298
          if (TSDB_CODE_SUCCESS == code) {
3,317,462✔
299
            tstrncpy(((SExprNode*)*pCol)->aliasName, aliasName, TSDB_COL_NAME_LEN);
3,317,462✔
300
            if (srcTable[0]) {
3,317,462✔
301
              tstrncpy(((SExprNode*)*pCol)->srcTable, srcTable, TSDB_TABLE_NAME_LEN);
3,317,462✔
302
            }
303
            TSWAP(pOrigAss, ((SExprNode*)*pCol)->pAssociation);
3,317,462✔
304
          }
305
          taosArrayDestroy(pOrigAss);
3,317,462✔
306
          if (TSDB_CODE_SUCCESS != code) {
3,317,462✔
307
            break;
×
308
          }
309
        } else {
310
          code = findAndReplaceNode(pCxt, pCol, pAssNode->pAssociationNode, *pNew, true);
3,933✔
311
          if (TSDB_CODE_SUCCESS != code) {
3,933✔
312
            break;
×
313
          }
314
        }
315
      }
316
    }
317
  }
318
  taosArrayDestroy(pAssociation);
1,184,714,719✔
319
  return code;
1,184,698,059✔
320
}
321

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

326
EDealRes checkUselessCol(SNode* pNode, void* pContext) {
287,844,649✔
327
  SIsUselessColCtx* ctx = (SIsUselessColCtx*)pContext;
287,844,649✔
328
  if (QUERY_NODE_FUNCTION == nodeType(pNode) &&
287,844,649✔
329
      !fmIsScalarFunc(((SFunctionNode*)pNode)->funcId) &&
43,614,854✔
330
      !fmIsPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)) {
22,184,392✔
331
    ctx->isUseless = false;
18,701,057✔
332
    return DEAL_RES_END;
18,701,057✔
333
  }
334

335
  return DEAL_RES_CONTINUE;
269,143,790✔
336
}
337

338
static bool isUselessCol(SExprNode* pProj) {
241,313,799✔
339
  SIsUselessColCtx ctx = {.isUseless = true};
241,313,799✔
340
  nodesWalkExpr((SNode*)pProj, checkUselessCol, (void*)&ctx);
241,313,813✔
341
  if (!ctx.isUseless) {
241,314,263✔
342
    return false;
18,701,043✔
343
  }
344
  return NULL == ((SExprNode*)pProj)->pAssociation;
222,613,220✔
345
}
346

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

366
static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
480,851,776✔
367
  SNode* pProj = NULL;
480,851,776✔
368
  WHERE_EACH(pProj, pSelect->pProjectionList) {
1,802,094,956✔
369
    if (subquery && !pSelect->isDistinct && !pSelect->tagScan && isUselessCol((SExprNode*)pProj) && (pSelect->pFromTable && nodeType(pSelect->pFromTable) != QUERY_NODE_VIRTUAL_TABLE)) {
1,321,326,985✔
370
      ERASE_NODE(pSelect->pProjectionList);
136,623,124✔
371
      continue;
136,623,124✔
372
    }
373
    SNode*  pNew = NULL;
1,184,703,435✔
374
    int32_t code = calcConstProject(pCxt, pProj, (NULL == pSelect->pFromTable), &pNew);
1,184,702,631✔
375
    if (TSDB_CODE_SUCCESS == code) {
1,184,700,991✔
376
      REPLACE_NODE(pNew);
1,184,620,056✔
377
    } else {
378
      return code;
84,489✔
379
    }
380
    WHERE_NEXT;
1,184,620,902✔
381
  }
382
  if (0 == LIST_LENGTH(pSelect->pProjectionList)) {
480,768,407✔
383
    SValueNode* pVal = NULL;
326,982✔
384
    int32_t     code = createConstantValue(&pVal);
327,108✔
385
    if (TSDB_CODE_SUCCESS == code) {
327,092✔
386
      return nodesListStrictAppend(pSelect->pProjectionList, (SNode*)pVal);
327,092✔
387
    }
388
  }
389
  return TSDB_CODE_SUCCESS;
480,441,425✔
390
}
391

392
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
466,516,402✔
393
  int32_t code = calcConstList(pSelect->pGroupByList);
466,516,402✔
394
  if (TSDB_CODE_SUCCESS == code) {
466,525,740✔
395
    SNode* pNode = NULL;
466,527,829✔
396
    FOREACH(pNode, pSelect->pGroupByList) {
506,907,362✔
397
      bool   hasNotValue = false;
40,378,271✔
398
      SNode* pGroupPara = NULL;
40,378,271✔
399
      FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
41,818,883✔
400
        if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
40,379,040✔
401
          hasNotValue = true;
38,938,422✔
402
          break;
38,938,422✔
403
        }
404
      }
405
      if (!hasNotValue) {
40,378,257✔
406
        if (pSelect->hasAggFuncs) {
1,440,626✔
407
          ERASE_NODE(pSelect->pGroupByList);
39,282✔
408
        } else {
409
          if (!cell->pPrev && !cell->pNext) continue;
1,401,344✔
410
          ERASE_NODE(pSelect->pGroupByList);
×
411
        }
412
      }
413
    }
414
  }
415
  return code;
466,526,318✔
416
}
417

418
static int32_t calcConstSelectWithoutFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
14,173,540✔
419
  return calcConstProjections(pCxt, pSelect, subquery);
14,173,540✔
420
}
421

422
static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
473,084,753✔
423
  int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
473,084,753✔
424
  if (TSDB_CODE_SUCCESS == code && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
473,094,418✔
425
      ((STempTableNode*)pSelect->pFromTable)->pSubquery != NULL &&
60,523,358✔
426
      QUERY_NODE_SELECT_STMT == nodeType(((STempTableNode*)pSelect->pFromTable)->pSubquery) &&
60,523,364✔
427
      ((SSelectStmt*)((STempTableNode*)pSelect->pFromTable)->pSubquery)->isEmptyResult) {
55,894,091✔
428
    pSelect->isEmptyResult = true;
6,405,189✔
429
    return code;
6,405,189✔
430
  }
431
  if (pSelect->mixSysTableAndActualTable) {
466,689,293✔
432
    return code;
414✔
433
  }
434
  if (TSDB_CODE_SUCCESS == code) {
466,689,788✔
435
    code = calcConstProjections(pCxt, pSelect, subquery);
466,679,395✔
436
  }
437
  if (TSDB_CODE_SUCCESS == code) {
466,695,589✔
438
    code = calcConstStmtCondition(pCxt, &pSelect->pWhere, &pSelect->isEmptyResult);
466,607,502✔
439
  }
440
  if (TSDB_CODE_SUCCESS == code) {
466,695,082✔
441
    code = calcConstList(pSelect->pPartitionByList);
466,515,674✔
442
  }
443
  if (TSDB_CODE_SUCCESS == code) {
466,698,953✔
444
    code = calcConstNode(&pSelect->pWindow);
466,524,277✔
445
  }
446
  if (TSDB_CODE_SUCCESS == code) {
466,701,879✔
447
    code = calcConstGroupBy(pCxt, pSelect);
466,528,551✔
448
  }
449
  if (TSDB_CODE_SUCCESS == code) {
466,693,129✔
450
    code = calcConstStmtCondition(pCxt, &pSelect->pHaving, &pSelect->isEmptyResult);
466,525,909✔
451
  }
452
  if (TSDB_CODE_SUCCESS == code) {
466,697,532✔
453
    code = calcConstList(pSelect->pOrderByList);
466,514,175✔
454
  }
455
  if (TSDB_CODE_SUCCESS == code) {
466,708,529✔
456
    code = calcConstNode(&pSelect->pFill);
466,528,647✔
457
  }
458
  if (TSDB_CODE_SUCCESS == code) {
466,711,655✔
459
    code = calcConstNode(&pSelect->pTimeRange);
466,531,778✔
460
  }
461
  return code;
466,693,421✔
462
}
463

464

465
static bool isEmptyResultQuery(SNode* pStmt) {
469,843,111✔
466
  bool isEmptyResult = false;
469,843,111✔
467
  switch (nodeType(pStmt)) {
469,843,111✔
468
    case QUERY_NODE_SELECT_STMT:
219,294,392✔
469
      isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult;
219,294,392✔
470
      break;
219,294,458✔
471
    case QUERY_NODE_EXPLAIN_STMT:
50,979,045✔
472
      isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery);
50,979,045✔
473
      break;
50,984,950✔
474
    case QUERY_NODE_SET_OPERATOR: {
8,407,108✔
475
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
8,407,108✔
476
      isEmptyResult = isEmptyResultQuery(pSetOp->pLeft);
8,407,108✔
477
      if (isEmptyResult) {
8,406,948✔
478
        isEmptyResult = isEmptyResultQuery(pSetOp->pRight);
557✔
479
      }
480
      break;
8,406,949✔
481
    }
482
    case QUERY_NODE_DELETE_STMT:
1,834,830✔
483
      isEmptyResult = ((SDeleteStmt*)pStmt)->deleteZeroRows;
1,834,830✔
484
      break;
1,827,239✔
485
    default:
189,334,707✔
486
      break;
189,334,707✔
487
  }
488
  return isEmptyResult;
469,848,303✔
489
}
490

491
static int32_t calcSubQueries(SCalcConstContext* pCxt, SNodeList* pSubQueries) {
84,354,476✔
492
  int32_t code = TSDB_CODE_SUCCESS;
84,354,476✔
493
  SNode* pNode = NULL;
84,354,476✔
494
  FOREACH(pNode, pSubQueries) {
260,640,540✔
495
    code = calcConstQuery(pCxt, pNode, false);
176,280,003✔
496
    if (code) {
176,286,064✔
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;
84,360,537✔
510
}
511

512
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
487,258,639✔
513
  int32_t code = TSDB_CODE_SUCCESS;
487,258,639✔
514
  
515
  if (NULL == pSelect->pFromTable) {
487,258,639✔
516
    code = calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
14,173,540✔
517
  } else {
518
    code = calcConstSelectFrom(pCxt, pSelect, subquery);
473,084,432✔
519
  }
520

521
  if (TSDB_CODE_SUCCESS == code && pSelect->pSubQueries && pSelect->pSubQueries->length > 0) {
487,272,290✔
522
    code = calcSubQueries(pCxt, pSelect->pSubQueries);
82,409,253✔
523
  }
524

525
  return code;
487,272,707✔
526
}
527

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

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

547
static SNodeList* getChildProjection(SNode* pStmt) {
3,803,884✔
548
  switch (nodeType(pStmt)) {
3,803,884✔
549
    case QUERY_NODE_SELECT_STMT:
3,780,857✔
550
      return ((SSelectStmt*)pStmt)->pProjectionList;
3,780,857✔
551
    case QUERY_NODE_SET_OPERATOR:
23,027✔
552
      return ((SSetOperator*)pStmt)->pProjectionList;
23,027✔
553
    default:
×
554
      break;
×
555
  }
556
  return NULL;
×
557
}
558

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

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

577
static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) {
12,659,236✔
578
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
12,659,236✔
579
    SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext;
6,329,618✔
580
    if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) {
6,329,618✔
581
      pCxt->hasThisCol = true;
2,063,685✔
582
      return DEAL_RES_END;
2,063,685✔
583
    }
584
  }
585
  return DEAL_RES_CONTINUE;
10,595,551✔
586
}
587

588
static bool notRefByOrderBy(SColumnNode* pCol, SNodeList* pOrderByList) {
7,013,981✔
589
  SNotRefByOrderByCxt cxt = {.pCol = pCol, .hasThisCol = false};
7,013,981✔
590
  nodesWalkExprs(pOrderByList, notRefByOrderByImpl, &cxt);
7,013,981✔
591
  return !cxt.hasThisCol;
7,013,981✔
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,874,823✔
608
  if (NULL == pStmt || index < 0) {
3,874,823✔
609
    return false;
×
610
  }
611

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

639
static bool isSetUselessCol(SSetOperator* pSetOp, int32_t index, SExprNode* pProj) {
4,950,296✔
640
  if (!isUselessCol(pProj)) {
4,950,296✔
641
    return false;
3,011,582✔
642
  }
643

644
  return isSubqueryProjUseless(pSetOp->pLeft, index) &&
3,817,629✔
645
         isSubqueryProjUseless(pSetOp->pRight, index);
1,878,915✔
646
}
647

648
static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
29,847,711✔
649
  if (subquery && pSetOp->opType == SET_OP_TYPE_UNION) {
29,847,711✔
650
    return TSDB_CODE_SUCCESS;
2,215,099✔
651
  }
652
  int32_t index = 0;
27,632,612✔
653
  SNode*  pProj = NULL;
27,632,612✔
654
  WHERE_EACH(pProj, pSetOp->pProjectionList) {
66,492,686✔
655
    if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) &&
43,809,536✔
656
        isSetUselessCol(pSetOp, index, (SExprNode*)pProj)) {
4,950,296✔
657
      ERASE_NODE(pSetOp->pProjectionList);
1,878,667✔
658
      eraseSetOpChildProjection(pSetOp, index);
1,878,915✔
659
      continue;
1,879,501✔
660
    }
661
    ++index;
36,980,573✔
662
    WHERE_NEXT;
36,980,573✔
663
  }
664
  if (0 == LIST_LENGTH(pSetOp->pProjectionList)) {
27,633,446✔
665
    SValueNode* pVal = NULL;
4,949✔
666
    int32_t     code = createConstantValue(&pVal);
4,949✔
667
    if (TSDB_CODE_SUCCESS == code) {
4,801✔
668
      return nodesListStrictAppend(pSetOp->pProjectionList, (SNode*)pVal);
4,801✔
669
    }
670
  }
671
  return TSDB_CODE_SUCCESS;
27,628,502✔
672
}
673

674
static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
29,848,214✔
675
  int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery);
29,848,214✔
676
  if (TSDB_CODE_SUCCESS == code) {
29,849,113✔
677
    code = calcConstQuery(pCxt, pSetOp->pLeft, false);
29,849,762✔
678
  }
679
  if (TSDB_CODE_SUCCESS == code) {
29,850,587✔
680
    code = calcConstQuery(pCxt, pSetOp->pRight, false);
29,849,255✔
681
  }
682
  if (TSDB_CODE_SUCCESS == code) {
29,852,960✔
683
    code = calcConstList(pSetOp->pOrderByList);
29,851,628✔
684
  }
685
  if (TSDB_CODE_SUCCESS == code && pSetOp->pSubQueries && pSetOp->pSubQueries->length > 0) {
29,852,960✔
686
    code = calcSubQueries(pCxt, pSetOp->pSubQueries);
1,965,667✔
687
  }
688
  
689
  return code;
29,851,555✔
690
}
691

692
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
759,261,432✔
693
  int32_t code = TSDB_CODE_SUCCESS;
759,261,432✔
694
  switch (nodeType(pStmt)) {
759,261,432✔
695
    case QUERY_NODE_SELECT_STMT:
487,269,706✔
696
      code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery);
487,269,706✔
697
      break;
487,272,582✔
698
    case QUERY_NODE_EXPLAIN_STMT:
50,984,647✔
699
      code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery);
50,984,647✔
700
      break;
50,987,784✔
701
    case QUERY_NODE_SET_OPERATOR: {
29,850,881✔
702
      code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery);
29,850,881✔
703
      break;
29,851,628✔
704
    }
705
    case QUERY_NODE_DELETE_STMT:
1,827,239✔
706
      code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
1,827,239✔
707
      break;
1,827,239✔
708
    case QUERY_NODE_INSERT_STMT:
544,896✔
709
      code = calcConstInsert(pCxt, (SInsertStmt*)pStmt);
544,896✔
710
      break;
543,567✔
711
    default:
188,786,355✔
712
      break;
188,786,355✔
713
  }
714
  return code;
759,269,155✔
715
}
716

717

718
static void resetProjectNullTypeImpl(SNodeList* pProjects) {
179,729,544✔
719
  SNode* pProj = NULL;
179,729,544✔
720
  FOREACH(pProj, pProjects) {
921,568,798✔
721
    SExprNode* pExpr = (SExprNode*)pProj;
741,841,287✔
722
    if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
741,841,287✔
723
      pExpr->resType.type = TSDB_DATA_TYPE_VARCHAR;
195,153✔
724
      pExpr->resType.bytes = VARSTR_HEADER_SIZE;
195,153✔
725
      if (QUERY_NODE_VALUE == nodeType(pExpr)) {
195,153✔
726
        ((SValueNode*)pExpr)->isNull = true;
28,593✔
727
      }
728
    }
729
  }
730
}
179,728,704✔
731

732
static void resetProjectNullType(SNode* pStmt) {
421,865,486✔
733
  switch (nodeType(pStmt)) {
421,865,486✔
734
    case QUERY_NODE_SELECT_STMT:
174,027,966✔
735
      resetProjectNullTypeImpl(((SSelectStmt*)pStmt)->pProjectionList);
174,027,966✔
736
      break;
174,026,475✔
737
    case QUERY_NODE_SET_OPERATOR: {
5,705,400✔
738
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
5,705,400✔
739
      resetProjectNullTypeImpl(pSetOp->pProjectionList);
5,705,400✔
740
      if (pSetOp->pLeft)
5,702,165✔
741
        resetProjectNullType(pSetOp->pLeft);
5,702,165✔
742
      if (pSetOp->pRight)
5,702,165✔
743
        resetProjectNullType(pSetOp->pRight);
5,702,165✔
744
      break;
5,702,165✔
745
    }
746
    default:
242,135,113✔
747
      break;
242,135,113✔
748
  }
749
}
421,863,753✔
750

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

756
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) {
410,630,106✔
757
  SCalcConstContext cxt = {.pParseCxt = pParseCxt,
410,630,106✔
758
                           .msgBuf.buf = pParseCxt->pMsg,
410,608,926✔
759
                           .msgBuf.len = pParseCxt->msgLen,
410,633,616✔
760
                           .code = TSDB_CODE_SUCCESS};
761

762
  int32_t code = TSDB_CODE_SUCCESS;
410,606,326✔
763

764
  if (TSDB_CODE_SUCCESS == code) {
410,606,326✔
765
    code = calcConstQuery(&cxt, pQuery->pRoot, false);
410,631,294✔
766
  }
767
  if (TSDB_CODE_SUCCESS == code) {
410,610,613✔
768
    resetProjectNullType(pQuery->pRoot);
410,457,527✔
769
    if (isEmptyResultQuery(pQuery->pRoot)) {
410,447,178✔
770
      pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
647,113✔
771
    }
772
    code = rewriteScalarSubQResValue(pParseCxt, pQuery);
410,464,151✔
773
  }
774
  
775
  return code;
410,606,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