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

taosdata / TDengine / #4815

17 Oct 2025 06:47AM UTC coverage: 61.177% (-0.03%) from 61.206%
#4815

push

travis-ci

web-flow
Merge pull request #33289 from taosdata/3.0

enh: Code Optimization (#33283)

155629 of 324369 branches covered (47.98%)

Branch coverage included in aggregate %.

207706 of 269535 relevant lines covered (77.06%)

127615938.53 hits per line

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

85.55
/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) {
18,007,836✔
37
  return calcConstQuery(pCxt, pTempTable->pSubquery, true);
18,007,836✔
38
}
39

40
static int32_t calcConstNode(SNode** pNode) {
468,710,903✔
41
  if (NULL == *pNode) {
468,710,903✔
42
    return TSDB_CODE_SUCCESS;
388,367,085✔
43
  }
44

45
  SNode*  pNew = NULL;
80,345,691✔
46
  int32_t code = scalarCalculateConstants(*pNode, &pNew);
80,347,185✔
47
  if (TSDB_CODE_SUCCESS == code) {
80,347,352!
48
    *pNode = pNew;
80,348,283✔
49
  }
50
  return code;
80,347,352✔
51
}
52

53
static int32_t calcConstList(SNodeList* pList) {
399,513,559✔
54
  SNode* pNode = NULL;
399,513,559✔
55
  FOREACH(pNode, pList) {
460,230,862✔
56
    SNode*  pNew = NULL;
60,717,303✔
57
    int32_t code = scalarCalculateConstants(pNode, &pNew);
60,717,303✔
58
    if (TSDB_CODE_SUCCESS == code) {
60,717,303!
59
      REPLACE_NODE(pNew);
60,717,303✔
60
    } else {
61
      return code;
×
62
    }
63
  }
64
  return TSDB_CODE_SUCCESS;
399,513,573✔
65
}
66

67
static bool isCondition(const SNode* pNode) {
138,090,501✔
68
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
138,090,501✔
69
    return nodesIsComparisonOp((const SOperatorNode*)pNode);
107,211,394✔
70
  }
71
  return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
30,878,496✔
72
}
73

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

88
static EDealRes doRewriteCondition(SNode** pNode, void* pContext) {
667,283,405✔
89
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
667,283,405✔
90
    SNode* pParam = NULL;
30,514,321✔
91
    FOREACH(pParam, ((SLogicConditionNode*)*pNode)->pParameterList) {
104,047,207!
92
      if (!isCondition(pParam)) {
73,533,915✔
93
        SNode* pIsTrue = NULL;
351,104✔
94
        if (TSDB_CODE_SUCCESS != rewriteIsTrue(pParam, &pIsTrue)) {
351,104!
95
          ((SCalcConstContext*)pContext)->code = TSDB_CODE_OUT_OF_MEMORY;
×
96
          return DEAL_RES_ERROR;
×
97
        }
98
        REPLACE_NODE(pIsTrue);
351,104✔
99
      }
100
    }
101
  }
102
  return DEAL_RES_CONTINUE;
667,283,794✔
103
}
104

105
static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) {
64,555,707✔
106
  if (!isCondition(*pNode)) {
64,555,707✔
107
    return rewriteIsTrue(*pNode, pNode);
20,700✔
108
  }
109
  nodesRewriteExprPostOrder(pNode, doRewriteCondition, pCxt);
64,534,943✔
110
  return pCxt->code;
64,533,479✔
111
}
112

113
static int32_t calcConstCondition(SCalcConstContext* pCxt, SNode** pNode) {
3,179,028✔
114
  int32_t code = rewriteCondition(pCxt, pNode);
3,179,028✔
115
  if (TSDB_CODE_SUCCESS == code) {
3,179,028!
116
    code = calcConstNode(pNode);
3,179,028✔
117
  }
118
  return code;
3,179,028✔
119
}
120

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

126
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
15,773,354✔
127
    return DEAL_RES_CONTINUE;
2,482,886✔
128
  } else if (QUERY_NODE_OPERATOR == nodeType(*pNode)) {
13,290,468!
129
    SOperatorNode* pOp = (SOperatorNode*)*pNode;
13,290,468✔
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)) {
13,290,468✔
131
      code = calcConstNode(&pOp->pLeft);
10,111,440✔
132
      if (TSDB_CODE_SUCCESS == code) {
10,111,440!
133
        code = calcConstNode(&pOp->pRight);
10,111,440✔
134
      }
135
      
136
      goto _end;
10,111,440✔
137
    }
138
  }
139

140
  if (TSDB_CODE_SUCCESS == code) {
3,179,028!
141
    code = calcConstCondition(pCtx, pNode);
3,179,028✔
142
  }
143
  
144
_end:
×
145

146
  if (code != TSDB_CODE_SUCCESS) {
13,290,468!
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;
13,290,468✔
152
}
153

154
static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) {
155,926,038✔
155
  int32_t code = TSDB_CODE_SUCCESS;
155,926,038✔
156
  switch (nodeType(pTable)) {
155,926,038✔
157
    case QUERY_NODE_TEMP_TABLE: {
18,007,836✔
158
      code = calcConstSubquery(pCxt, (STempTableNode*)pTable);
18,007,836✔
159
      break;
18,007,836✔
160
    }
161
    case QUERY_NODE_JOIN_TABLE: {
10,708,549✔
162
      SJoinTableNode* pJoin = (SJoinTableNode*)pTable;
10,708,549✔
163
      SNode* pCond = NULL;
10,708,549✔
164
      code = rewriteConditionForFromTable(pCxt, pJoin->pLeft);
10,708,549✔
165
      if (TSDB_CODE_SUCCESS == code) {
10,707,134!
166
        code = rewriteConditionForFromTable(pCxt, pJoin->pRight);
10,707,134✔
167
      }
168
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
10,707,134!
169
        code = rewriteCondition(pCxt, &pJoin->pOnCond);
10,234,404✔
170
      }
171
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
10,707,134!
172
        nodesRewriteExpr(&pJoin->pOnCond, rewriteCalcConstValue, pCxt);
10,234,404✔
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;
10,707,134✔
191
    }
192
    default:
127,210,952✔
193
      break;
127,210,952✔
194
  }
195
  return code;
155,925,922✔
196
}
197

198
static int32_t calcConstFromTable(SCalcConstContext* pCxt, SNode* pTable) {
134,512,516✔
199
  return rewriteConditionForFromTable(pCxt, pTable);
134,512,516✔
200
}
201

202
static void rewriteConstCondition(SNode** pCond, bool* pAlwaysFalse) {
51,142,950✔
203
  if (QUERY_NODE_VALUE != nodeType(*pCond)) {
51,142,950✔
204
    return;
49,114,420✔
205
  }
206
  if (((SValueNode*)*pCond)->datum.b) {
2,028,530✔
207
    nodesDestroyNode(*pCond);
1,984,381✔
208
    *pCond = NULL;
1,984,381✔
209
  } else {
210
    *pAlwaysFalse = true;
44,149✔
211
  }
212
}
213

214
static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bool* pAlwaysFalse) {
265,730,946✔
215
  if (NULL == *pCond) {
265,730,946✔
216
    return TSDB_CODE_SUCCESS;
214,592,932✔
217
  }
218

219
  int32_t code = rewriteCondition(pCxt, pCond);
51,140,155✔
220
  if (TSDB_CODE_SUCCESS == code) {
51,141,701!
221
    code = calcConstNode(pCond);
51,141,701✔
222
  }
223
  if (TSDB_CODE_SUCCESS == code) {
51,142,543!
224
    rewriteConstCondition(pCond, pAlwaysFalse);
51,142,950✔
225
  }
226
  return code;
51,142,314✔
227
}
228

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

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

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

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

260
static int32_t calcConstProject(SCalcConstContext* pCxt, SNode* pProject, bool dual, SNode** pNew) {
619,014,878✔
261
  SArray* pAssociation = NULL;
619,014,878✔
262
  
263
  if (NULL != ((SExprNode*)pProject)->pAssociation) {
619,014,878✔
264
    pAssociation = taosArrayDup(((SExprNode*)pProject)->pAssociation, NULL);
36,824,396✔
265
    if (NULL == pAssociation) {
36,824,396!
266
      return terrno;
×
267
    }
268
  }
269

270
  char    aliasName[TSDB_COL_NAME_LEN] = {0}, srcTable[TSDB_TABLE_NAME_LEN] = {0};
619,016,299✔
271
  int32_t code = TSDB_CODE_SUCCESS;
619,002,846✔
272
  if (dual) {
619,002,846✔
273
    code = scalarCalculateConstantsFromDual(pProject, pNew);
4,104,868✔
274
  } else {
275
    code = scalarCalculateConstants(pProject, pNew);
614,897,978✔
276
  }
277
  if (TSDB_CODE_SUCCESS == code) {
619,016,300✔
278
    if (QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
619,012,219✔
279
      int32_t size = taosArrayGetSize(pAssociation);
2,641,467✔
280
      for (int32_t i = 0; i < size; ++i) {
5,778,541✔
281
        SAssociationNode* pAssNode = taosArrayGet(pAssociation, i);
3,137,074✔
282
        SNode**           pCol = pAssNode->pPlace;
3,137,074✔
283
        if (((SExprNode*)pAssNode->pAssociationNode)->joinSrc) {
3,137,074!
284
          //((SExprNode*)pAssNode->pAssociationNode)->constValue = true;
285
          continue;
911,844✔
286
        }
287
        
288
        if (*pCol == pAssNode->pAssociationNode) {
2,225,230✔
289
          tstrncpy(aliasName, ((SExprNode*)*pCol)->aliasName, TSDB_COL_NAME_LEN);
2,219,884!
290
          if (QUERY_NODE_COLUMN == nodeType(*pCol)) {
2,219,884!
291
            tstrncpy(srcTable, ((SColumnNode*)*pCol)->tableAlias, TSDB_TABLE_NAME_LEN);
2,219,884!
292
          }
293
          SArray* pOrigAss = NULL;
2,219,884✔
294
          TSWAP(((SExprNode*)*pCol)->pAssociation, pOrigAss);
2,219,884✔
295
          nodesDestroyNode(*pCol);
2,219,884✔
296
          *pCol = NULL;
2,219,884✔
297
          code = nodesCloneNode(*pNew, pCol);
2,219,884✔
298
          if (TSDB_CODE_SUCCESS == code) {
2,219,884!
299
            tstrncpy(((SExprNode*)*pCol)->aliasName, aliasName, TSDB_COL_NAME_LEN);
2,219,884!
300
            if (srcTable[0]) {
2,219,884!
301
              tstrncpy(((SExprNode*)*pCol)->srcTable, srcTable, TSDB_TABLE_NAME_LEN);
2,219,884!
302
            }
303
            TSWAP(pOrigAss, ((SExprNode*)*pCol)->pAssociation);
2,219,884✔
304
          }
305
          taosArrayDestroy(pOrigAss);
2,219,884✔
306
          if (TSDB_CODE_SUCCESS != code) {
2,219,884!
307
            break;
×
308
          }
309
        } else {
310
          code = findAndReplaceNode(pCxt, pCol, pAssNode->pAssociationNode, *pNew, true);
5,346✔
311
          if (TSDB_CODE_SUCCESS != code) {
5,346!
312
            break;
×
313
          }
314
        }
315
      }
316
    }
317
  }
318
  taosArrayDestroy(pAssociation);
619,017,299✔
319
  return code;
619,016,204✔
320
}
321

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

326
EDealRes checkUselessCol(SNode* pNode, void* pContext) {
136,120,923✔
327
  SIsUselessColCtx* ctx = (SIsUselessColCtx*)pContext;
136,120,923✔
328
  if (QUERY_NODE_FUNCTION == nodeType(pNode) && !fmIsScalarFunc(((SFunctionNode*)pNode)->funcId) &&
136,120,923✔
329
      !fmIsPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)) {
10,824,582✔
330
    ctx->isUseless = false;
9,182,419✔
331
    return DEAL_RES_END;
9,182,419✔
332
  }
333

334
  return DEAL_RES_CONTINUE;
126,938,504✔
335
}
336

337
static bool isUselessCol(SExprNode* pProj) {
113,694,787✔
338
  SIsUselessColCtx ctx = {.isUseless = true};
113,694,787✔
339
  nodesWalkExpr((SNode*)pProj, checkUselessCol, (void*)&ctx);
113,694,787✔
340
  if (!ctx.isUseless) {
113,694,787✔
341
    return false;
9,182,419✔
342
  }
343
  return NULL == ((SExprNode*)pProj)->pAssociation;
104,512,368✔
344
}
345

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

365
static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
134,584,659✔
366
  SNode* pProj = NULL;
134,584,659✔
367
  WHERE_EACH(pProj, pSelect->pProjectionList) {
825,681,824!
368
    if (subquery && !pSelect->isDistinct && !pSelect->tagScan && isUselessCol((SExprNode*)pProj) && (pSelect->pFromTable && nodeType(pSelect->pFromTable) != QUERY_NODE_VIRTUAL_TABLE)) {
691,102,711✔
369
      ERASE_NODE(pSelect->pProjectionList);
72,086,925✔
370
      continue;
72,086,925✔
371
    }
372
    SNode*  pNew = NULL;
619,015,786✔
373
    int32_t code = calcConstProject(pCxt, pProj, (NULL == pSelect->pFromTable), &pNew);
619,016,561✔
374
    if (TSDB_CODE_SUCCESS == code) {
619,017,307✔
375
      REPLACE_NODE(pNew);
619,013,326✔
376
    } else {
377
      return code;
4,045✔
378
    }
379
    WHERE_NEXT;
619,014,779✔
380
  }
381
  if (0 == LIST_LENGTH(pSelect->pProjectionList)) {
134,580,602✔
382
    SValueNode* pVal = NULL;
142,623✔
383
    int32_t     code = createConstantValue(&pVal);
142,645✔
384
    if (TSDB_CODE_SUCCESS == code) {
143,133!
385
      return nodesListStrictAppend(pSelect->pProjectionList, (SNode*)pVal);
143,133✔
386
    }
387
  }
388
  return TSDB_CODE_SUCCESS;
134,438,322✔
389
}
390

391
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
131,392,983✔
392
  int32_t code = calcConstList(pSelect->pGroupByList);
131,392,983✔
393
  if (TSDB_CODE_SUCCESS == code) {
131,395,684✔
394
    SNode* pNode = NULL;
131,396,057✔
395
    FOREACH(pNode, pSelect->pGroupByList) {
152,098,694✔
396
      bool   hasNotValue = false;
20,702,637✔
397
      SNode* pGroupPara = NULL;
20,702,637✔
398
      FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
21,799,094!
399
        if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
20,702,637✔
400
          hasNotValue = true;
19,606,180✔
401
          break;
19,606,180✔
402
        }
403
      }
404
      if (!hasNotValue) {
20,702,637✔
405
        if (pSelect->hasAggFuncs) {
1,096,457!
406
          ERASE_NODE(pSelect->pGroupByList);
46,796✔
407
        } else {
408
          if (!cell->pPrev && !cell->pNext) continue;
1,049,661!
409
          ERASE_NODE(pSelect->pGroupByList);
×
410
        }
411
      }
412
    }
413
  }
414
  return code;
131,391,195✔
415
}
416

417
static int32_t calcConstSelectWithoutFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
3,188,284✔
418
  return calcConstProjections(pCxt, pSelect, subquery);
3,188,284✔
419
}
420

421
static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
131,474,139✔
422
  int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
131,474,139✔
423
  if (TSDB_CODE_SUCCESS == code && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
131,469,794!
424
      ((STempTableNode*)pSelect->pFromTable)->pSubquery != NULL &&
16,556,689!
425
      QUERY_NODE_SELECT_STMT == nodeType(((STempTableNode*)pSelect->pFromTable)->pSubquery) &&
16,556,689✔
426
      ((SSelectStmt*)((STempTableNode*)pSelect->pFromTable)->pSubquery)->isEmptyResult) {
14,469,731!
427
    pSelect->isEmptyResult = true;
75,754✔
428
    return code;
75,754✔
429
  }
430
  if (pSelect->mixSysTableAndActualTable) {
131,393,036!
431
    return code;
1,329✔
432
  }
433
  if (TSDB_CODE_SUCCESS == code) {
131,393,471✔
434
    code = calcConstProjections(pCxt, pSelect, subquery);
131,393,700✔
435
  }
436
  if (TSDB_CODE_SUCCESS == code) {
131,395,126✔
437
    code = calcConstStmtCondition(pCxt, &pSelect->pWhere, &pSelect->isEmptyResult);
131,395,798✔
438
  }
439
  if (TSDB_CODE_SUCCESS == code) {
131,393,297✔
440
    code = calcConstList(pSelect->pPartitionByList);
131,393,161✔
441
  }
442
  if (TSDB_CODE_SUCCESS == code) {
131,394,354✔
443
    code = calcConstNode(&pSelect->pWindow);
131,394,282✔
444
  }
445
  if (TSDB_CODE_SUCCESS == code) {
131,393,269✔
446
    code = calcConstGroupBy(pCxt, pSelect);
131,393,197✔
447
  }
448
  if (TSDB_CODE_SUCCESS == code) {
131,390,952!
449
    code = calcConstStmtCondition(pCxt, &pSelect->pHaving, &pSelect->isEmptyResult);
131,393,173✔
450
  }
451
  if (TSDB_CODE_SUCCESS == code) {
131,392,796✔
452
    code = calcConstList(pSelect->pOrderByList);
131,392,596✔
453
  }
454
  if (TSDB_CODE_SUCCESS == code) {
131,391,525✔
455
    code = calcConstNode(&pSelect->pFill);
131,391,253✔
456
  }
457
  if (TSDB_CODE_SUCCESS == code) {
131,394,556✔
458
    code = calcConstNode(&pSelect->pTimeRange);
131,394,284✔
459
  }
460
  return code;
131,390,788✔
461
}
462

463
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
134,662,244✔
464
  if (NULL == pSelect->pFromTable) {
134,662,244✔
465
    return calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
3,188,284✔
466
  } else {
467
    return calcConstSelectFrom(pCxt, pSelect, subquery);
131,473,818✔
468
  }
469
}
470

471
static int32_t calcConstDelete(SCalcConstContext* pCxt, SDeleteStmt* pDelete) {
2,943,111✔
472
  int32_t code = calcConstFromTable(pCxt, pDelete->pFromTable);
2,943,111✔
473
  if (TSDB_CODE_SUCCESS == code) {
2,943,111!
474
    code = calcConstStmtCondition(pCxt, &pDelete->pWhere, &pDelete->deleteZeroRows);
2,943,111✔
475
  }
476
  if (code == TSDB_CODE_SUCCESS && pDelete->timeRange.skey > pDelete->timeRange.ekey) {
2,943,111!
477
    pDelete->deleteZeroRows = true;
243,920✔
478
  }
479
  return code;
2,943,111✔
480
}
481

482
static int32_t calcConstInsert(SCalcConstContext* pCxt, SInsertStmt* pInsert) {
95,441✔
483
  int32_t code = calcConstFromTable(pCxt, pInsert->pTable);
95,441✔
484
  if (TSDB_CODE_SUCCESS == code) {
95,441!
485
    code = calcConstQuery(pCxt, pInsert->pQuery, false);
95,441✔
486
  }
487
  return code;
95,441✔
488
}
489

490
static SNodeList* getChildProjection(SNode* pStmt) {
3,443,680✔
491
  switch (nodeType(pStmt)) {
3,443,680!
492
    case QUERY_NODE_SELECT_STMT:
3,427,281✔
493
      return ((SSelectStmt*)pStmt)->pProjectionList;
3,427,281✔
494
    case QUERY_NODE_SET_OPERATOR:
16,399✔
495
      return ((SSetOperator*)pStmt)->pProjectionList;
16,399✔
496
    default:
×
497
      break;
×
498
  }
499
  return NULL;
×
500
}
501

502
static void eraseSetOpChildProjection(SSetOperator* pSetOp, int32_t index) {
857,551✔
503
  SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft);
857,551✔
504
  (void)nodesListErase(pLeftProjs, nodesListGetCell(pLeftProjs, index));
857,551✔
505
  if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pLeft)) {
857,551✔
506
    eraseSetOpChildProjection((SSetOperator*)pSetOp->pLeft, index);
8,091✔
507
  }
508
  SNodeList* pRightProjs = getChildProjection(pSetOp->pRight);
857,551✔
509
  (void)nodesListErase(pRightProjs, nodesListGetCell(pRightProjs, index));
857,551✔
510
  if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pRight)) {
857,551!
511
    eraseSetOpChildProjection((SSetOperator*)pSetOp->pRight, index);
×
512
  }
513
}
857,551✔
514

515
typedef struct SNotRefByOrderByCxt {
516
  SColumnNode* pCol;
517
  bool         hasThisCol;
518
} SNotRefByOrderByCxt;
519

520
static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) {
5,556,972✔
521
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
5,556,972✔
522
    SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext;
2,778,486✔
523
    if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) {
2,778,486✔
524
      pCxt->hasThisCol = true;
905,106✔
525
      return DEAL_RES_END;
905,106✔
526
    }
527
  }
528
  return DEAL_RES_CONTINUE;
4,651,866✔
529
}
530

531
static bool notRefByOrderBy(SColumnNode* pCol, SNodeList* pOrderByList) {
3,130,010✔
532
  SNotRefByOrderByCxt cxt = {.pCol = pCol, .hasThisCol = false};
3,130,010✔
533
  nodesWalkExprs(pOrderByList, notRefByOrderByImpl, &cxt);
3,130,010✔
534
  return !cxt.hasThisCol;
3,130,010!
535
}
536

537
static bool isDistinctSubQuery(SNode* pNode) {
1,767,740✔
538
  if (NULL == pNode) {
1,767,740!
539
    return false;
×
540
  }
541
  switch (nodeType(pNode)) {
1,767,740!
542
    case QUERY_NODE_SELECT_STMT:
1,733,764✔
543
      return ((SSelectStmt*)pNode)->isDistinct;
1,733,764!
544
    case QUERY_NODE_SET_OPERATOR:
33,976✔
545
      return isDistinctSubQuery((((SSetOperator*)pNode)->pLeft)) || isDistinctSubQuery((((SSetOperator*)pNode)->pLeft));
33,976!
546
    default:
×
547
      break;
×
548
  }
549
  return false;
×
550
}
551

552
static bool isSetUselessCol(SSetOperator* pSetOp, int32_t index, SExprNode* pProj) {
2,224,904✔
553
  if (!isUselessCol(pProj)) {
2,224,904✔
554
    return false;
1,346,654✔
555
  }
556

557
  SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft);
878,250✔
558
  if (!isUselessCol((SExprNode*)nodesListGetNode(pLeftProjs, index)) || isDistinctSubQuery(pSetOp->pLeft)) {
878,250!
559
    return false;
27,922✔
560
  }
561

562
  SNodeList* pRightProjs = getChildProjection(pSetOp->pRight);
850,328✔
563
  if (!isUselessCol((SExprNode*)nodesListGetNode(pRightProjs, index)) || isDistinctSubQuery(pSetOp->pLeft)) {
850,328!
564
    return false;
868✔
565
  }
566

567
  return true;
849,460✔
568
}
569

570
static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
5,332,960✔
571
  if (subquery && pSetOp->opType == SET_OP_TYPE_UNION) {
5,332,960✔
572
    return TSDB_CODE_SUCCESS;
1,013,744✔
573
  }
574
  int32_t index = 0;
4,319,216✔
575
  SNode*  pProj = NULL;
4,319,216✔
576
  WHERE_EACH(pProj, pSetOp->pProjectionList) {
13,845,816!
577
    if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) &&
11,751,504✔
578
        isSetUselessCol(pSetOp, index, (SExprNode*)pProj)) {
2,224,904✔
579
      ERASE_NODE(pSetOp->pProjectionList);
849,460✔
580
      eraseSetOpChildProjection(pSetOp, index);
849,460✔
581
      continue;
849,460✔
582
    }
583
    ++index;
8,677,140✔
584
    WHERE_NEXT;
8,677,140✔
585
  }
586
  if (0 == LIST_LENGTH(pSetOp->pProjectionList)) {
4,319,216!
587
    SValueNode* pVal = NULL;
4,309✔
588
    int32_t     code = createConstantValue(&pVal);
4,309✔
589
    if (TSDB_CODE_SUCCESS == code) {
4,309!
590
      return nodesListStrictAppend(pSetOp->pProjectionList, (SNode*)pVal);
4,309✔
591
    }
592
  }
593
  return TSDB_CODE_SUCCESS;
4,314,907✔
594
}
595

596
static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
5,332,960✔
597
  int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery);
5,332,960✔
598
  if (TSDB_CODE_SUCCESS == code) {
5,332,960!
599
    code = calcConstQuery(pCxt, pSetOp->pLeft, false);
5,332,960✔
600
  }
601
  if (TSDB_CODE_SUCCESS == code) {
5,332,960!
602
    code = calcConstQuery(pCxt, pSetOp->pRight, false);
5,332,960✔
603
  }
604
  if (TSDB_CODE_SUCCESS == code) {
5,332,960!
605
    code = calcConstList(pSetOp->pOrderByList);
5,332,960✔
606
  }
607
  return code;
5,332,960✔
608
}
609

610
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
218,073,696✔
611
  int32_t code = TSDB_CODE_SUCCESS;
218,073,696✔
612
  switch (nodeType(pStmt)) {
218,073,696✔
613
    case QUERY_NODE_SELECT_STMT:
134,663,007✔
614
      code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery);
134,663,007✔
615
      break;
134,653,043✔
616
    case QUERY_NODE_EXPLAIN_STMT:
6,598,151✔
617
      code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery);
6,598,151✔
618
      break;
6,601,277✔
619
    case QUERY_NODE_SET_OPERATOR: {
5,332,960✔
620
      code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery);
5,332,960✔
621
      break;
5,332,960✔
622
    }
623
    case QUERY_NODE_DELETE_STMT:
2,943,111✔
624
      code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
2,943,111✔
625
      break;
2,943,111✔
626
    case QUERY_NODE_INSERT_STMT:
98,965✔
627
      code = calcConstInsert(pCxt, (SInsertStmt*)pStmt);
98,965✔
628
      break;
95,441✔
629
    default:
68,443,323✔
630
      break;
68,443,323✔
631
  }
632
  return code;
218,069,155✔
633
}
634

635
static bool isEmptyResultQuery(SNode* pStmt) {
192,361,087✔
636
  bool isEmptyResult = false;
192,361,087✔
637
  switch (nodeType(pStmt)) {
192,361,087✔
638
    case QUERY_NODE_SELECT_STMT:
111,218,024✔
639
      isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult;
111,218,024!
640
      break;
111,219,077✔
641
    case QUERY_NODE_EXPLAIN_STMT:
6,598,151✔
642
      isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery);
6,598,151✔
643
      break;
6,596,424✔
644
    case QUERY_NODE_SET_OPERATOR: {
3,074,009✔
645
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
3,074,009✔
646
      isEmptyResult = isEmptyResultQuery(pSetOp->pLeft);
3,074,009✔
647
      if (isEmptyResult) {
3,074,009!
648
        isEmptyResult = isEmptyResultQuery(pSetOp->pRight);
×
649
      }
650
      break;
3,074,009✔
651
    }
652
    case QUERY_NODE_DELETE_STMT:
2,943,669✔
653
      isEmptyResult = ((SDeleteStmt*)pStmt)->deleteZeroRows;
2,943,669!
654
      break;
2,943,111✔
655
    default:
68,533,813✔
656
      break;
68,533,813✔
657
  }
658
  return isEmptyResult;
192,366,434✔
659
}
660

661
static void resetProjectNullTypeImpl(SNodeList* pProjects) {
109,454,986✔
662
  SNode* pProj = NULL;
109,454,986✔
663
  FOREACH(pProj, pProjects) {
661,755,103!
664
    SExprNode* pExpr = (SExprNode*)pProj;
552,301,037✔
665
    if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
552,301,037✔
666
      pExpr->resType.type = TSDB_DATA_TYPE_VARCHAR;
27,001✔
667
      pExpr->resType.bytes = VARSTR_HEADER_SIZE;
27,001✔
668
    }
669
  }
670
}
109,449,740✔
671

672
static void resetProjectNullType(SNode* pStmt) {
187,511,792✔
673
  switch (nodeType(pStmt)) {
187,511,792✔
674
    case QUERY_NODE_SELECT_STMT:
107,041,727✔
675
      resetProjectNullTypeImpl(((SSelectStmt*)pStmt)->pProjectionList);
107,041,727✔
676
      break;
107,042,599✔
677
    case QUERY_NODE_SET_OPERATOR: {
2,411,215✔
678
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
2,411,215✔
679
      resetProjectNullTypeImpl(pSetOp->pProjectionList);
2,411,215✔
680
      if (pSetOp->pLeft)
2,409,153!
681
        resetProjectNullType(pSetOp->pLeft);
2,409,153✔
682
      if (pSetOp->pRight)
2,409,153!
683
        resetProjectNullType(pSetOp->pRight);
2,409,153✔
684
      break;
2,409,153✔
685
    }
686
    default:
78,063,252✔
687
      break;
78,063,252✔
688
  }
689
}
187,515,004✔
690

691
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) {
182,705,868✔
692
  SCalcConstContext cxt = {.pParseCxt = pParseCxt,
182,705,868✔
693
                           .msgBuf.buf = pParseCxt->pMsg,
182,709,207✔
694
                           .msgBuf.len = pParseCxt->msgLen,
182,711,974✔
695
                           .code = TSDB_CODE_SUCCESS};
696

697
  int32_t code = calcConstQuery(&cxt, pQuery->pRoot, false);
182,709,918✔
698
  if (TSDB_CODE_SUCCESS == code) {
182,700,067✔
699
    resetProjectNullType(pQuery->pRoot);
182,699,336✔
700
    if (isEmptyResultQuery(pQuery->pRoot)) {
182,686,932✔
701
      pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
470,608✔
702
    }
703
  }
704
  return code;
182,674,526✔
705
}
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