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

taosdata / TDengine / #5049

11 May 2026 06:30AM UTC coverage: 73.313% (+0.09%) from 73.222%
#5049

push

travis-ci

web-flow
feat: refactor taosdump code to improve backup speed and compression ratio (#35292)

6625 of 8435 new or added lines in 28 files covered. (78.54%)

2491 existing lines in 142 files now uncovered.

281233 of 383605 relevant lines covered (73.31%)

132489999.79 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) {
60,718,762✔
37
  return calcConstQuery(pCxt, pTempTable->pSubquery, true);
60,718,762✔
38
}
39

40
static int32_t calcConstNode(SNode** pNode) {
1,559,341,703✔
41
  if (NULL == *pNode) {
1,559,341,703✔
42
    return TSDB_CODE_SUCCESS;
1,314,434,723✔
43
  }
44

45
  SNode*  pNew = NULL;
244,907,586✔
46
  int32_t code = scalarCalculateConstants(*pNode, &pNew);
244,907,346✔
47
  if (TSDB_CODE_SUCCESS == code) {
244,951,677✔
48
    *pNode = pNew;
244,871,913✔
49
  }
50
  return code;
244,951,677✔
51
}
52

53
static int32_t calcConstList(SNodeList* pList) {
1,380,494,528✔
54
  SNode* pNode = NULL;
1,380,494,528✔
55
  FOREACH(pNode, pList) {
1,583,694,274✔
56
    SNode*  pNew = NULL;
203,192,425✔
57
    int32_t code = scalarCalculateConstants(pNode, &pNew);
203,192,423✔
58
    if (TSDB_CODE_SUCCESS == code) {
203,199,671✔
59
      REPLACE_NODE(pNew);
203,199,750✔
60
    } else {
61
      return code;
×
62
    }
63
  }
64
  return TSDB_CODE_SUCCESS;
1,380,504,829✔
65
}
66

67
static bool isCondition(const SNode* pNode) {
315,938,169✔
68
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
315,938,169✔
69
    return nodesIsComparisonOp((const SOperatorNode*)pNode);
259,709,204✔
70
  }
71
  return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
56,229,496✔
72
}
73

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

88
static EDealRes doRewriteCondition(SNode** pNode, void* pContext) {
909,706,773✔
89
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
909,706,773✔
90
    SNode* pParam = NULL;
54,946,264✔
91
    FOREACH(pParam, ((SLogicConditionNode*)*pNode)->pParameterList) {
186,957,744✔
92
      if (!isCondition(pParam)) {
132,011,866✔
93
        SNode* pIsTrue = NULL;
299,023✔
94
        if (TSDB_CODE_SUCCESS != rewriteIsTrue(pParam, &pIsTrue)) {
299,023✔
95
          ((SCalcConstContext*)pContext)->code = TSDB_CODE_OUT_OF_MEMORY;
×
96
          return DEAL_RES_ERROR;
×
97
        }
98
        REPLACE_NODE(pIsTrue);
299,740✔
99
      }
100
    }
101
  }
102
  return DEAL_RES_CONTINUE;
909,707,692✔
103
}
104

105
static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) {
183,926,966✔
106
  if (!isCondition(*pNode)) {
183,926,966✔
107
    return rewriteIsTrue(*pNode, pNode);
997,427✔
108
  }
109
  nodesRewriteExprPostOrder(pNode, doRewriteCondition, pCxt);
182,933,085✔
110
  return pCxt->code;
182,937,630✔
111
}
112

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

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

126
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
35,409,032✔
127
    return DEAL_RES_CONTINUE;
5,505,383✔
128
  } else if (QUERY_NODE_OPERATOR == nodeType(*pNode)) {
29,903,649✔
129
    SOperatorNode* pOp = (SOperatorNode*)*pNode;
29,904,084✔
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,904,084✔
131
      code = calcConstNode(&pOp->pLeft);
23,601,389✔
132
      if (TSDB_CODE_SUCCESS == code) {
23,601,398✔
133
        code = calcConstNode(&pOp->pRight);
23,601,588✔
134
      }
135
      
136
      goto _end;
23,601,990✔
137
    }
138
  }
139

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

146
  if (code != TSDB_CODE_SUCCESS) {
29,903,693✔
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,903,693✔
152
}
153

154
static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) {
508,137,411✔
155
  int32_t code = TSDB_CODE_SUCCESS;
508,137,411✔
156
  switch (nodeType(pTable)) {
508,137,411✔
157
    case QUERY_NODE_TEMP_TABLE: {
60,719,102✔
158
      code = calcConstSubquery(pCxt, (STempTableNode*)pTable);
60,719,102✔
159
      break;
60,719,104✔
160
    }
161
    case QUERY_NODE_JOIN_TABLE: {
24,246,846✔
162
      SJoinTableNode* pJoin = (SJoinTableNode*)pTable;
24,246,846✔
163
      SNode* pCond = NULL;
24,246,846✔
164
      code = rewriteConditionForFromTable(pCxt, pJoin->pLeft);
24,246,846✔
165
      if (TSDB_CODE_SUCCESS == code) {
24,246,408✔
166
        code = rewriteConditionForFromTable(pCxt, pJoin->pRight);
24,246,579✔
167
      }
168
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
24,246,590✔
169
        code = rewriteCondition(pCxt, &pJoin->pOnCond);
23,877,313✔
170
      }
171
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
24,246,688✔
172
        nodesRewriteExpr(&pJoin->pOnCond, rewriteCalcConstValue, pCxt);
23,877,411✔
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,247,294✔
191
    }
192
    default:
423,172,606✔
193
      break;
423,172,606✔
194
  }
195
  return code;
508,139,004✔
196
}
197

198
static int32_t calcConstFromTable(SCalcConstContext* pCxt, SNode* pTable) {
459,635,096✔
199
  return rewriteConditionForFromTable(pCxt, pTable);
459,635,096✔
200
}
201

202
static void rewriteConstCondition(SNode** pCond, bool* pAlwaysFalse) {
153,676,471✔
203
  if (QUERY_NODE_VALUE != nodeType(*pCond)) {
153,676,471✔
204
    return;
141,746,461✔
205
  }
206
  if (((SValueNode*)*pCond)->datum.b) {
11,930,498✔
207
    nodesDestroyNode(*pCond);
2,857,810✔
208
    *pCond = NULL;
2,857,810✔
209
  } else {
210
    *pAlwaysFalse = true;
9,072,688✔
211
  }
212
}
213

214
static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bool* pAlwaysFalse) {
903,303,590✔
215
  if (NULL == *pCond) {
903,303,590✔
216
    return TSDB_CODE_SUCCESS;
749,560,605✔
217
  }
218

219
  int32_t code = rewriteCondition(pCxt, pCond);
153,743,550✔
220
  if (TSDB_CODE_SUCCESS == code) {
153,756,144✔
221
    code = calcConstNode(pCond);
153,755,847✔
222
  }
223
  if (TSDB_CODE_SUCCESS == code) {
153,755,896✔
224
    rewriteConstCondition(pCond, pAlwaysFalse);
153,676,767✔
225
  }
226
  return code;
153,757,068✔
227
}
228

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

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

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

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

260
static int32_t calcConstProject(SCalcConstContext* pCxt, SNode* pProject, bool dual, SNode** pNew) {
1,160,376,906✔
261
  SArray* pAssociation = NULL;
1,160,376,906✔
262
  
263
  if (NULL != ((SExprNode*)pProject)->pAssociation) {
1,160,376,906✔
264
    pAssociation = taosArrayDup(((SExprNode*)pProject)->pAssociation, NULL);
94,084,201✔
265
    if (NULL == pAssociation) {
94,084,068✔
UNCOV
266
      return terrno;
×
267
    }
268
  }
269

270
  char    aliasName[TSDB_COL_NAME_LEN] = {0}, srcTable[TSDB_TABLE_NAME_LEN] = {0};
1,160,379,210✔
271
  int32_t code = TSDB_CODE_SUCCESS;
1,160,379,663✔
272
  if (dual) {
1,160,379,663✔
273
    code = scalarCalculateConstantsFromDual(pProject, pNew);
15,135,832✔
274
  } else {
275
    code = scalarCalculateConstants(pProject, pNew);
1,145,243,831✔
276
  }
277
  if (TSDB_CODE_SUCCESS == code) {
1,160,409,799✔
278
    if (QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
1,160,314,753✔
279
      int32_t size = taosArrayGetSize(pAssociation);
3,089,655✔
280
      for (int32_t i = 0; i < size; ++i) {
6,309,471✔
281
        SAssociationNode* pAssNode = taosArrayGet(pAssociation, i);
3,219,816✔
282
        SNode**           pCol = pAssNode->pPlace;
3,219,816✔
283
        if (((SExprNode*)pAssNode->pAssociationNode)->joinSrc) {
3,219,816✔
284
          //((SExprNode*)pAssNode->pAssociationNode)->constValue = true;
285
          continue;
57,643✔
286
        }
287
        
288
        if (*pCol == pAssNode->pAssociationNode) {
3,162,173✔
289
          tstrncpy(aliasName, ((SExprNode*)*pCol)->aliasName, TSDB_COL_NAME_LEN);
3,158,339✔
290
          if (QUERY_NODE_COLUMN == nodeType(*pCol)) {
3,158,339✔
291
            tstrncpy(srcTable, ((SColumnNode*)*pCol)->tableAlias, TSDB_TABLE_NAME_LEN);
3,158,339✔
292
          }
293
          SArray* pOrigAss = NULL;
3,158,339✔
294
          TSWAP(((SExprNode*)*pCol)->pAssociation, pOrigAss);
3,158,339✔
295
          nodesDestroyNode(*pCol);
3,158,339✔
296
          *pCol = NULL;
3,158,339✔
297
          code = nodesCloneNode(*pNew, pCol);
3,158,339✔
298
          if (TSDB_CODE_SUCCESS == code) {
3,158,339✔
299
            tstrncpy(((SExprNode*)*pCol)->aliasName, aliasName, TSDB_COL_NAME_LEN);
3,158,339✔
300
            if (srcTable[0]) {
3,158,339✔
301
              tstrncpy(((SExprNode*)*pCol)->srcTable, srcTable, TSDB_TABLE_NAME_LEN);
3,158,339✔
302
            }
303
            TSWAP(pOrigAss, ((SExprNode*)*pCol)->pAssociation);
3,158,339✔
304
          }
305
          taosArrayDestroy(pOrigAss);
3,158,339✔
306
          if (TSDB_CODE_SUCCESS != code) {
3,158,339✔
307
            break;
×
308
          }
309
        } else {
310
          code = findAndReplaceNode(pCxt, pCol, pAssNode->pAssociationNode, *pNew, true);
3,834✔
311
          if (TSDB_CODE_SUCCESS != code) {
3,834✔
312
            break;
×
313
          }
314
        }
315
      }
316
    }
317
  }
318
  taosArrayDestroy(pAssociation);
1,160,409,356✔
319
  return code;
1,160,387,782✔
320
}
321

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

326
EDealRes checkUselessCol(SNode* pNode, void* pContext) {
288,686,433✔
327
  SIsUselessColCtx* ctx = (SIsUselessColCtx*)pContext;
288,686,433✔
328
  if (QUERY_NODE_FUNCTION == nodeType(pNode) &&
288,686,433✔
329
      !fmIsScalarFunc(((SFunctionNode*)pNode)->funcId) &&
43,119,059✔
330
      !fmIsPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)) {
22,176,541✔
331
    ctx->isUseless = false;
18,535,413✔
332
    return DEAL_RES_END;
18,535,413✔
333
  }
334

335
  return DEAL_RES_CONTINUE;
270,151,221✔
336
}
337

338
static bool isUselessCol(SExprNode* pProj) {
244,118,811✔
339
  SIsUselessColCtx ctx = {.isUseless = true};
244,118,811✔
340
  nodesWalkExpr((SNode*)pProj, checkUselessCol, (void*)&ctx);
244,118,843✔
341
  if (!ctx.isUseless) {
244,119,043✔
342
    return false;
18,535,410✔
343
  }
344
  return NULL == ((SExprNode*)pProj)->pAssociation;
225,583,633✔
345
}
346

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

366
static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
464,399,604✔
367
  SNode* pProj = NULL;
464,399,604✔
368
  WHERE_EACH(pProj, pSelect->pProjectionList) {
1,765,388,930✔
369
    if (subquery && !pSelect->isDistinct && !pSelect->tagScan && isUselessCol((SExprNode*)pProj) && (pSelect->pFromTable && nodeType(pSelect->pFromTable) != QUERY_NODE_VIRTUAL_TABLE)) {
1,301,062,776✔
370
      ERASE_NODE(pSelect->pProjectionList);
140,676,845✔
371
      continue;
140,676,845✔
372
    }
373
    SNode*  pNew = NULL;
1,160,385,912✔
374
    int32_t code = calcConstProject(pCxt, pProj, (NULL == pSelect->pFromTable), &pNew);
1,160,384,557✔
375
    if (TSDB_CODE_SUCCESS == code) {
1,160,393,976✔
376
      REPLACE_NODE(pNew);
1,160,315,142✔
377
    } else {
378
      return code;
84,154✔
379
    }
380
    WHERE_NEXT;
1,160,315,800✔
381
  }
382
  if (0 == LIST_LENGTH(pSelect->pProjectionList)) {
464,325,183✔
383
    SValueNode* pVal = NULL;
323,522✔
384
    int32_t     code = createConstantValue(&pVal);
323,474✔
385
    if (TSDB_CODE_SUCCESS == code) {
324,813✔
386
      return nodesListStrictAppend(pSelect->pProjectionList, (SNode*)pVal);
324,813✔
387
    }
388
  }
389
  return TSDB_CODE_SUCCESS;
463,998,862✔
390
}
391

392
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
450,699,143✔
393
  int32_t code = calcConstList(pSelect->pGroupByList);
450,699,143✔
394
  if (TSDB_CODE_SUCCESS == code) {
450,705,945✔
395
    SNode* pNode = NULL;
450,709,623✔
396
    FOREACH(pNode, pSelect->pGroupByList) {
489,950,139✔
397
      bool   hasNotValue = false;
39,239,958✔
398
      SNode* pGroupPara = NULL;
39,239,958✔
399
      FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
40,667,342✔
400
        if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
39,240,255✔
401
          hasNotValue = true;
37,812,864✔
402
          break;
37,812,864✔
403
        }
404
      }
405
      if (!hasNotValue) {
39,239,963✔
406
        if (pSelect->hasAggFuncs) {
1,427,396✔
407
          ERASE_NODE(pSelect->pGroupByList);
38,614✔
408
        } else {
409
          if (!cell->pPrev && !cell->pNext) continue;
1,388,782✔
410
          ERASE_NODE(pSelect->pGroupByList);
×
411
        }
412
      }
413
    }
414
  }
415
  return code;
450,707,467✔
416
}
417

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

422
static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
457,246,073✔
423
  int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
457,246,073✔
424
  if (TSDB_CODE_SUCCESS == code && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
457,261,744✔
425
      ((STempTableNode*)pSelect->pFromTable)->pSubquery != NULL &&
60,126,585✔
426
      QUERY_NODE_SELECT_STMT == nodeType(((STempTableNode*)pSelect->pFromTable)->pSubquery) &&
60,126,597✔
427
      ((SSelectStmt*)((STempTableNode*)pSelect->pFromTable)->pSubquery)->isEmptyResult) {
55,535,628✔
428
    pSelect->isEmptyResult = true;
6,387,883✔
429
    return code;
6,387,883✔
430
  }
431
  if (pSelect->mixSysTableAndActualTable) {
450,873,808✔
432
    return code;
404✔
433
  }
434
  if (TSDB_CODE_SUCCESS == code) {
450,870,639✔
435
    code = calcConstProjections(pCxt, pSelect, subquery);
450,860,106✔
436
  }
437
  if (TSDB_CODE_SUCCESS == code) {
450,882,865✔
438
    code = calcConstStmtCondition(pCxt, &pSelect->pWhere, &pSelect->isEmptyResult);
450,794,528✔
439
  }
440
  if (TSDB_CODE_SUCCESS == code) {
450,881,305✔
441
    code = calcConstList(pSelect->pPartitionByList);
450,704,094✔
442
  }
443
  if (TSDB_CODE_SUCCESS == code) {
450,882,233✔
444
    code = calcConstNode(&pSelect->pWindow);
450,711,722✔
445
  }
446
  if (TSDB_CODE_SUCCESS == code) {
450,881,414✔
447
    code = calcConstGroupBy(pCxt, pSelect);
450,711,570✔
448
  }
449
  if (TSDB_CODE_SUCCESS == code) {
450,874,290✔
450
    code = calcConstStmtCondition(pCxt, &pSelect->pHaving, &pSelect->isEmptyResult);
450,712,306✔
451
  }
452
  if (TSDB_CODE_SUCCESS == code) {
450,877,941✔
453
    code = calcConstList(pSelect->pOrderByList);
450,704,692✔
454
  }
455
  if (TSDB_CODE_SUCCESS == code) {
450,885,374✔
456
    code = calcConstNode(&pSelect->pFill);
450,715,155✔
457
  }
458
  if (TSDB_CODE_SUCCESS == code) {
450,886,789✔
459
    code = calcConstNode(&pSelect->pTimeRange);
450,717,717✔
460
  }
461
  return code;
450,878,214✔
462
}
463

464

465
static bool isEmptyResultQuery(SNode* pStmt) {
451,142,643✔
466
  bool isEmptyResult = false;
451,142,643✔
467
  switch (nodeType(pStmt)) {
451,142,643✔
468
    case QUERY_NODE_SELECT_STMT:
214,666,650✔
469
      isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult;
214,666,650✔
470
      break;
214,666,986✔
471
    case QUERY_NODE_EXPLAIN_STMT:
48,190,567✔
472
      isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery);
48,190,567✔
473
      break;
48,196,506✔
474
    case QUERY_NODE_SET_OPERATOR: {
8,202,803✔
475
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
8,202,803✔
476
      isEmptyResult = isEmptyResultQuery(pSetOp->pLeft);
8,202,803✔
477
      if (isEmptyResult) {
8,202,880✔
478
        isEmptyResult = isEmptyResultQuery(pSetOp->pRight);
552✔
479
      }
480
      break;
8,202,785✔
481
    }
482
    case QUERY_NODE_DELETE_STMT:
1,831,782✔
483
      isEmptyResult = ((SDeleteStmt*)pStmt)->deleteZeroRows;
1,831,782✔
484
      break;
1,819,271✔
485
    default:
178,259,147✔
486
      break;
178,259,147✔
487
  }
488
  return isEmptyResult;
451,144,695✔
489
}
490

491
static int32_t calcSubQueries(SCalcConstContext* pCxt, SNodeList* pSubQueries) {
80,922,959✔
492
  int32_t code = TSDB_CODE_SUCCESS;
80,922,959✔
493
  SNode* pNode = NULL;
80,922,959✔
494
  FOREACH(pNode, pSubQueries) {
247,178,777✔
495
    code = calcConstQuery(pCxt, pNode, false);
166,249,028✔
496
    if (code) {
166,255,818✔
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;
80,929,749✔
510
}
511

512
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
470,790,346✔
513
  int32_t code = TSDB_CODE_SUCCESS;
470,790,346✔
514
  
515
  if (NULL == pSelect->pFromTable) {
470,790,346✔
516
    code = calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
13,540,359✔
517
  } else {
518
    code = calcConstSelectFrom(pCxt, pSelect, subquery);
457,250,457✔
519
  }
520

521
  if (TSDB_CODE_SUCCESS == code && pSelect->pSubQueries && pSelect->pSubQueries->length > 0) {
470,805,876✔
522
    code = calcSubQueries(pCxt, pSelect->pSubQueries);
79,110,980✔
523
  }
524

525
  return code;
470,808,042✔
526
}
527

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

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

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

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

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

577
static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) {
12,397,458✔
578
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
12,397,458✔
579
    SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext;
6,198,729✔
580
    if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) {
6,198,729✔
581
      pCxt->hasThisCol = true;
2,035,322✔
582
      return DEAL_RES_END;
2,035,322✔
583
    }
584
  }
585
  return DEAL_RES_CONTINUE;
10,362,136✔
586
}
587

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

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

639
static bool isSetUselessCol(SSetOperator* pSetOp, int32_t index, SExprNode* pProj) {
4,832,810✔
640
  if (!isUselessCol(pProj)) {
4,832,810✔
641
    return false;
2,994,239✔
642
  }
643

644
  return isSubqueryProjUseless(pSetOp->pLeft, index) &&
3,630,964✔
645
         isSubqueryProjUseless(pSetOp->pRight, index);
1,792,393✔
646
}
647

648
static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
28,424,704✔
649
  if (subquery && pSetOp->opType == SET_OP_TYPE_UNION) {
28,424,704✔
650
    return TSDB_CODE_SUCCESS;
2,203,197✔
651
  }
652
  int32_t index = 0;
26,221,507✔
653
  SNode*  pProj = NULL;
26,221,507✔
654
  WHERE_EACH(pProj, pSetOp->pProjectionList) {
63,478,584✔
655
    if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) &&
42,088,489✔
656
        isSetUselessCol(pSetOp, index, (SExprNode*)pProj)) {
4,832,810✔
657
      ERASE_NODE(pSetOp->pProjectionList);
1,792,015✔
658
      eraseSetOpChildProjection(pSetOp, index);
1,792,393✔
659
      continue;
1,793,413✔
660
    }
661
    ++index;
35,463,664✔
662
    WHERE_NEXT;
35,463,664✔
663
  }
664
  if (0 == LIST_LENGTH(pSetOp->pProjectionList)) {
26,222,905✔
665
    SValueNode* pVal = NULL;
5,186✔
666
    int32_t     code = createConstantValue(&pVal);
5,186✔
667
    if (TSDB_CODE_SUCCESS == code) {
4,713✔
668
      return nodesListStrictAppend(pSetOp->pProjectionList, (SNode*)pVal);
4,713✔
669
    }
670
  }
671
  return TSDB_CODE_SUCCESS;
26,217,806✔
672
}
673

674
static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
28,425,426✔
675
  int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery);
28,425,426✔
676
  if (TSDB_CODE_SUCCESS == code) {
28,426,393✔
677
    code = calcConstQuery(pCxt, pSetOp->pLeft, false);
28,426,945✔
678
  }
679
  if (TSDB_CODE_SUCCESS == code) {
28,427,450✔
680
    code = calcConstQuery(pCxt, pSetOp->pRight, false);
28,425,923✔
681
  }
682
  if (TSDB_CODE_SUCCESS == code) {
28,429,754✔
683
    code = calcConstList(pSetOp->pOrderByList);
28,428,227✔
684
  }
685
  if (TSDB_CODE_SUCCESS == code && pSetOp->pSubQueries && pSetOp->pSubQueries->length > 0) {
28,429,564✔
686
    code = calcSubQueries(pCxt, pSetOp->pSubQueries);
1,831,286✔
687
  }
688
  
689
  return code;
28,427,901✔
690
}
691

692
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
727,503,597✔
693
  int32_t code = TSDB_CODE_SUCCESS;
727,503,597✔
694
  switch (nodeType(pStmt)) {
727,503,597✔
695
    case QUERY_NODE_SELECT_STMT:
470,804,434✔
696
      code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery);
470,804,434✔
697
      break;
470,807,682✔
698
    case QUERY_NODE_EXPLAIN_STMT:
48,195,816✔
699
      code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery);
48,195,816✔
700
      break;
48,190,560✔
701
    case QUERY_NODE_SET_OPERATOR: {
28,427,697✔
702
      code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery);
28,427,697✔
703
      break;
28,427,996✔
704
    }
705
    case QUERY_NODE_DELETE_STMT:
1,819,271✔
706
      code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
1,819,271✔
707
      break;
1,819,271✔
708
    case QUERY_NODE_INSERT_STMT:
571,332✔
709
      code = calcConstInsert(pCxt, (SInsertStmt*)pStmt);
571,332✔
710
      break;
569,236✔
711
    default:
177,688,137✔
712
      break;
177,688,137✔
713
  }
714
  return code;
727,502,515✔
715
}
716

717

718
static void resetProjectNullTypeImpl(SNodeList* pProjects) {
177,727,903✔
719
  SNode* pProj = NULL;
177,727,903✔
720
  FOREACH(pProj, pProjects) {
912,406,740✔
721
    SExprNode* pExpr = (SExprNode*)pProj;
734,679,757✔
722
    if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
734,679,757✔
723
      pExpr->resType.type = TSDB_DATA_TYPE_VARCHAR;
186,804✔
724
      pExpr->resType.bytes = VARSTR_HEADER_SIZE;
186,804✔
725
      if (QUERY_NODE_VALUE == nodeType(pExpr)) {
186,804✔
726
        ((SValueNode*)pExpr)->isNull = true;
28,151✔
727
      }
728
    }
729
  }
730
}
177,726,594✔
731

732
static void resetProjectNullType(SNode* pStmt) {
405,997,087✔
733
  switch (nodeType(pStmt)) {
405,997,087✔
734
    case QUERY_NODE_SELECT_STMT:
172,107,828✔
735
      resetProjectNullTypeImpl(((SSelectStmt*)pStmt)->pProjectionList);
172,107,828✔
736
      break;
172,106,020✔
737
    case QUERY_NODE_SET_OPERATOR: {
5,621,756✔
738
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
5,621,756✔
739
      resetProjectNullTypeImpl(pSetOp->pProjectionList);
5,621,756✔
740
      if (pSetOp->pLeft)
5,620,543✔
741
        resetProjectNullType(pSetOp->pLeft);
5,620,543✔
742
      if (pSetOp->pRight)
5,620,543✔
743
        resetProjectNullType(pSetOp->pRight);
5,620,543✔
744
      break;
5,620,543✔
745
    }
746
    default:
228,271,191✔
747
      break;
228,271,191✔
748
  }
749
}
405,997,754✔
750

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

756
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) {
394,919,185✔
757
  SCalcConstContext cxt = {.pParseCxt = pParseCxt,
394,919,185✔
758
                           .msgBuf.buf = pParseCxt->pMsg,
394,913,971✔
759
                           .msgBuf.len = pParseCxt->msgLen,
394,922,811✔
760
                           .code = TSDB_CODE_SUCCESS};
761

762
  int32_t code = TSDB_CODE_SUCCESS;
394,912,051✔
763

764
  if (TSDB_CODE_SUCCESS == code) {
394,912,051✔
765
    code = calcConstQuery(&cxt, pQuery->pRoot, false);
394,928,046✔
766
  }
767
  if (TSDB_CODE_SUCCESS == code) {
394,900,779✔
768
    resetProjectNullType(pQuery->pRoot);
394,754,568✔
769
    if (isEmptyResultQuery(pQuery->pRoot)) {
394,744,037✔
770
      pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
645,837✔
771
    }
772
    code = rewriteScalarSubQResValue(pParseCxt, pQuery);
394,742,569✔
773
  }
774
  
775
  return code;
394,913,744✔
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