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

taosdata / TDengine / #5059

17 May 2026 01:15AM UTC coverage: 73.443% (+0.06%) from 73.387%
#5059

push

travis-ci

web-flow
feat (TDgpt): Dynamic Model Synchronization Enhancements (#35344)

* refactor: do some internal refactor.

* fix: fix multiprocess sync issue.

* feat: add dynamic anomaly detection and forecasting services

* fix: log error message for undeploying model in exception handling

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: handle undeploy when model exists only on disk

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/286aafa0-c3ce-4c27-b803-2707571e9dc1

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: guard dynamic registry concurrent access

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: tighten service list locking scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: restore prophet support and update tests per review feedback

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: improve test name and move copy inside lock scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* Potential fix for pull request finding

Co-au... (continued)

281870 of 383795 relevant lines covered (73.44%)

135516561.93 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,487,395✔
37
  return calcConstQuery(pCxt, pTempTable->pSubquery, true);
61,487,395✔
38
}
39

40
static int32_t calcConstNode(SNode** pNode) {
1,618,374,050✔
41
  if (NULL == *pNode) {
1,618,374,050✔
42
    return TSDB_CODE_SUCCESS;
1,365,452,467✔
43
  }
44

45
  SNode*  pNew = NULL;
252,921,849✔
46
  int32_t code = scalarCalculateConstants(*pNode, &pNew);
252,921,970✔
47
  if (TSDB_CODE_SUCCESS == code) {
252,959,133✔
48
    *pNode = pNew;
252,878,607✔
49
  }
50
  return code;
252,959,133✔
51
}
52

53
static int32_t calcConstList(SNodeList* pList) {
1,435,671,618✔
54
  SNode* pNode = NULL;
1,435,671,618✔
55
  FOREACH(pNode, pList) {
1,647,355,559✔
56
    SNode*  pNew = NULL;
211,676,919✔
57
    int32_t code = scalarCalculateConstants(pNode, &pNew);
211,676,891✔
58
    if (TSDB_CODE_SUCCESS == code) {
211,683,850✔
59
      REPLACE_NODE(pNew);
211,683,955✔
60
    } else {
61
      return code;
×
62
    }
63
  }
64
  return TSDB_CODE_SUCCESS;
1,435,678,909✔
65
}
66

67
static bool isCondition(const SNode* pNode) {
323,259,643✔
68
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
323,259,643✔
69
    return nodesIsComparisonOp((const SOperatorNode*)pNode);
265,998,018✔
70
  }
71
  return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
57,262,209✔
72
}
73

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

88
static EDealRes doRewriteCondition(SNode** pNode, void* pContext) {
931,080,939✔
89
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
931,080,939✔
90
    SNode* pParam = NULL;
55,903,459✔
91
    FOREACH(pParam, ((SLogicConditionNode*)*pNode)->pParameterList) {
190,595,831✔
92
      if (!isCondition(pParam)) {
134,691,885✔
93
        SNode* pIsTrue = NULL;
293,912✔
94
        if (TSDB_CODE_SUCCESS != rewriteIsTrue(pParam, &pIsTrue)) {
293,912✔
95
          ((SCalcConstContext*)pContext)->code = TSDB_CODE_OUT_OF_MEMORY;
×
96
          return DEAL_RES_ERROR;
×
97
        }
98
        REPLACE_NODE(pIsTrue);
294,625✔
99
      }
100
    }
101
  }
102
  return DEAL_RES_CONTINUE;
931,081,898✔
103
}
104

105
static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) {
188,570,159✔
106
  if (!isCondition(*pNode)) {
188,570,159✔
107
    return rewriteIsTrue(*pNode, pNode);
1,078,310✔
108
  }
109
  nodesRewriteExprPostOrder(pNode, doRewriteCondition, pCxt);
187,495,587✔
110
  return pCxt->code;
187,500,281✔
111
}
112

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

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

126
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
36,661,966✔
127
    return DEAL_RES_CONTINUE;
5,747,025✔
128
  } else if (QUERY_NODE_OPERATOR == nodeType(*pNode)) {
30,914,941✔
129
    SOperatorNode* pOp = (SOperatorNode*)*pNode;
30,915,790✔
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,915,790✔
131
      code = calcConstNode(&pOp->pLeft);
24,358,260✔
132
      if (TSDB_CODE_SUCCESS == code) {
24,359,032✔
133
        code = calcConstNode(&pOp->pRight);
24,359,127✔
134
      }
135
      
136
      goto _end;
24,359,301✔
137
    }
138
  }
139

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

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

154
static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) {
527,591,331✔
155
  int32_t code = TSDB_CODE_SUCCESS;
527,591,331✔
156
  switch (nodeType(pTable)) {
527,591,331✔
157
    case QUERY_NODE_TEMP_TABLE: {
61,488,148✔
158
      code = calcConstSubquery(pCxt, (STempTableNode*)pTable);
61,488,148✔
159
      break;
61,488,148✔
160
    }
161
    case QUERY_NODE_JOIN_TABLE: {
25,014,688✔
162
      SJoinTableNode* pJoin = (SJoinTableNode*)pTable;
25,014,688✔
163
      SNode* pCond = NULL;
25,014,688✔
164
      code = rewriteConditionForFromTable(pCxt, pJoin->pLeft);
25,014,688✔
165
      if (TSDB_CODE_SUCCESS == code) {
25,013,225✔
166
        code = rewriteConditionForFromTable(pCxt, pJoin->pRight);
25,014,254✔
167
      }
168
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
25,012,973✔
169
        code = rewriteCondition(pCxt, &pJoin->pOnCond);
24,637,307✔
170
      }
171
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
25,013,311✔
172
        nodesRewriteExpr(&pJoin->pOnCond, rewriteCalcConstValue, pCxt);
24,637,481✔
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;
25,014,880✔
191
    }
192
    default:
441,088,565✔
193
      break;
441,088,565✔
194
  }
195
  return code;
527,591,593✔
196
}
197

198
static int32_t calcConstFromTable(SCalcConstContext* pCxt, SNode* pTable) {
477,555,994✔
199
  return rewriteConditionForFromTable(pCxt, pTable);
477,555,994✔
200
}
201

202
static void rewriteConstCondition(SNode** pCond, bool* pAlwaysFalse) {
157,304,145✔
203
  if (QUERY_NODE_VALUE != nodeType(*pCond)) {
157,304,145✔
204
    return;
145,293,574✔
205
  }
206
  if (((SValueNode*)*pCond)->datum.b) {
12,010,571✔
207
    nodesDestroyNode(*pCond);
2,895,227✔
208
    *pCond = NULL;
2,895,227✔
209
  } else {
210
    *pAlwaysFalse = true;
9,115,344✔
211
  }
212
}
213

214
static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bool* pAlwaysFalse) {
939,063,009✔
215
  if (NULL == *pCond) {
939,063,009✔
216
    return TSDB_CODE_SUCCESS;
781,690,168✔
217
  }
218

219
  int32_t code = rewriteCondition(pCxt, pCond);
157,373,161✔
220
  if (TSDB_CODE_SUCCESS == code) {
157,384,160✔
221
    code = calcConstNode(pCond);
157,384,345✔
222
  }
223
  if (TSDB_CODE_SUCCESS == code) {
157,381,908✔
224
    rewriteConstCondition(pCond, pAlwaysFalse);
157,303,463✔
225
  }
226
  return code;
157,383,776✔
227
}
228

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

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

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

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

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

270
  char    aliasName[TSDB_COL_NAME_LEN] = {0}, srcTable[TSDB_TABLE_NAME_LEN] = {0};
1,184,944,695✔
271
  int32_t code = TSDB_CODE_SUCCESS;
1,184,945,230✔
272
  if (dual) {
1,184,945,230✔
273
    code = scalarCalculateConstantsFromDual(pProject, pNew);
15,816,017✔
274
  } else {
275
    code = scalarCalculateConstants(pProject, pNew);
1,169,129,213✔
276
  }
277
  if (TSDB_CODE_SUCCESS == code) {
1,184,963,665✔
278
    if (QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
1,184,865,234✔
279
      int32_t size = taosArrayGetSize(pAssociation);
3,332,438✔
280
      for (int32_t i = 0; i < size; ++i) {
6,796,836✔
281
        SAssociationNode* pAssNode = taosArrayGet(pAssociation, i);
3,464,398✔
282
        SNode**           pCol = pAssNode->pPlace;
3,464,398✔
283
        if (((SExprNode*)pAssNode->pAssociationNode)->joinSrc) {
3,464,398✔
284
          //((SExprNode*)pAssNode->pAssociationNode)->constValue = true;
285
          continue;
58,931✔
286
        }
287
        
288
        if (*pCol == pAssNode->pAssociationNode) {
3,405,467✔
289
          tstrncpy(aliasName, ((SExprNode*)*pCol)->aliasName, TSDB_COL_NAME_LEN);
3,401,588✔
290
          if (QUERY_NODE_COLUMN == nodeType(*pCol)) {
3,401,588✔
291
            tstrncpy(srcTable, ((SColumnNode*)*pCol)->tableAlias, TSDB_TABLE_NAME_LEN);
3,401,588✔
292
          }
293
          SArray* pOrigAss = NULL;
3,401,588✔
294
          TSWAP(((SExprNode*)*pCol)->pAssociation, pOrigAss);
3,401,588✔
295
          nodesDestroyNode(*pCol);
3,401,588✔
296
          *pCol = NULL;
3,401,588✔
297
          code = nodesCloneNode(*pNew, pCol);
3,401,588✔
298
          if (TSDB_CODE_SUCCESS == code) {
3,401,588✔
299
            tstrncpy(((SExprNode*)*pCol)->aliasName, aliasName, TSDB_COL_NAME_LEN);
3,401,588✔
300
            if (srcTable[0]) {
3,401,588✔
301
              tstrncpy(((SExprNode*)*pCol)->srcTable, srcTable, TSDB_TABLE_NAME_LEN);
3,401,588✔
302
            }
303
            TSWAP(pOrigAss, ((SExprNode*)*pCol)->pAssociation);
3,401,588✔
304
          }
305
          taosArrayDestroy(pOrigAss);
3,401,588✔
306
          if (TSDB_CODE_SUCCESS != code) {
3,401,588✔
307
            break;
×
308
          }
309
        } else {
310
          code = findAndReplaceNode(pCxt, pCol, pAssNode->pAssociationNode, *pNew, true);
3,879✔
311
          if (TSDB_CODE_SUCCESS != code) {
3,879✔
312
            break;
×
313
          }
314
        }
315
      }
316
    }
317
  }
318
  taosArrayDestroy(pAssociation);
1,184,965,091✔
319
  return code;
1,184,948,606✔
320
}
321

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

326
EDealRes checkUselessCol(SNode* pNode, void* pContext) {
293,210,441✔
327
  SIsUselessColCtx* ctx = (SIsUselessColCtx*)pContext;
293,210,441✔
328
  if (QUERY_NODE_FUNCTION == nodeType(pNode) &&
293,210,441✔
329
      !fmIsScalarFunc(((SFunctionNode*)pNode)->funcId) &&
43,128,123✔
330
      !fmIsPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)) {
22,016,241✔
331
    ctx->isUseless = false;
18,675,900✔
332
    return DEAL_RES_END;
18,675,900✔
333
  }
334

335
  return DEAL_RES_CONTINUE;
274,535,092✔
336
}
337

338
static bool isUselessCol(SExprNode* pProj) {
246,622,774✔
339
  SIsUselessColCtx ctx = {.isUseless = true};
246,622,774✔
340
  nodesWalkExpr((SNode*)pProj, checkUselessCol, (void*)&ctx);
246,622,774✔
341
  if (!ctx.isUseless) {
246,623,324✔
342
    return false;
18,675,914✔
343
  }
344
  return NULL == ((SExprNode*)pProj)->pAssociation;
227,947,410✔
345
}
346

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

366
static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
482,950,561✔
367
  SNode* pProj = NULL;
482,950,561✔
368
  WHERE_EACH(pProj, pSelect->pProjectionList) {
1,809,717,678✔
369
    if (subquery && !pSelect->isDistinct && !pSelect->tagScan && isUselessCol((SExprNode*)pProj) && (pSelect->pFromTable && nodeType(pSelect->pFromTable) != QUERY_NODE_VIRTUAL_TABLE)) {
1,326,850,197✔
370
      ERASE_NODE(pSelect->pProjectionList);
141,895,473✔
371
      continue;
141,895,473✔
372
    }
373
    SNode*  pNew = NULL;
1,184,954,675✔
374
    int32_t code = calcConstProject(pCxt, pProj, (NULL == pSelect->pFromTable), &pNew);
1,184,955,388✔
375
    if (TSDB_CODE_SUCCESS == code) {
1,184,952,017✔
376
      REPLACE_NODE(pNew);
1,184,872,707✔
377
    } else {
378
      return code;
84,791✔
379
    }
380
    WHERE_NEXT;
1,184,872,587✔
381
  }
382
  if (0 == LIST_LENGTH(pSelect->pProjectionList)) {
482,867,559✔
383
    SValueNode* pVal = NULL;
326,426✔
384
    int32_t     code = createConstantValue(&pVal);
326,689✔
385
    if (TSDB_CODE_SUCCESS == code) {
326,919✔
386
      return nodesListStrictAppend(pSelect->pProjectionList, (SNode*)pVal);
326,919✔
387
    }
388
  }
389
  return TSDB_CODE_SUCCESS;
482,541,023✔
390
}
391

392
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
468,579,242✔
393
  int32_t code = calcConstList(pSelect->pGroupByList);
468,579,242✔
394
  if (TSDB_CODE_SUCCESS == code) {
468,587,251✔
395
    SNode* pNode = NULL;
468,588,670✔
396
    FOREACH(pNode, pSelect->pGroupByList) {
508,894,320✔
397
      bool   hasNotValue = false;
40,304,385✔
398
      SNode* pGroupPara = NULL;
40,304,385✔
399
      FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
41,744,495✔
400
        if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
40,305,290✔
401
          hasNotValue = true;
38,865,180✔
402
          break;
38,865,180✔
403
        }
404
      }
405
      if (!hasNotValue) {
40,304,385✔
406
        if (pSelect->hasAggFuncs) {
1,440,110✔
407
          ERASE_NODE(pSelect->pGroupByList);
39,294✔
408
        } else {
409
          if (!cell->pPrev && !cell->pNext) continue;
1,400,816✔
410
          ERASE_NODE(pSelect->pGroupByList);
×
411
        }
412
      }
413
    }
414
  }
415
  return code;
468,587,893✔
416
}
417

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

422
static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
475,156,843✔
423
  int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
475,156,843✔
424
  if (TSDB_CODE_SUCCESS == code && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
475,162,654✔
425
      ((STempTableNode*)pSelect->pFromTable)->pSubquery != NULL &&
60,889,373✔
426
      QUERY_NODE_SELECT_STMT == nodeType(((STempTableNode*)pSelect->pFromTable)->pSubquery) &&
60,889,373✔
427
      ((SSelectStmt*)((STempTableNode*)pSelect->pFromTable)->pSubquery)->isEmptyResult) {
56,260,941✔
428
    pSelect->isEmptyResult = true;
6,416,303✔
429
    return code;
6,416,303✔
430
  }
431
  if (pSelect->mixSysTableAndActualTable) {
468,746,320✔
432
    return code;
417✔
433
  }
434
  if (TSDB_CODE_SUCCESS == code) {
468,747,873✔
435
    code = calcConstProjections(pCxt, pSelect, subquery);
468,741,503✔
436
  }
437
  if (TSDB_CODE_SUCCESS == code) {
468,755,030✔
438
    code = calcConstStmtCondition(pCxt, &pSelect->pWhere, &pSelect->isEmptyResult);
468,669,220✔
439
  }
440
  if (TSDB_CODE_SUCCESS == code) {
468,754,006✔
441
    code = calcConstList(pSelect->pPartitionByList);
468,578,884✔
442
  }
443
  if (TSDB_CODE_SUCCESS == code) {
468,757,996✔
444
    code = calcConstNode(&pSelect->pWindow);
468,587,677✔
445
  }
446
  if (TSDB_CODE_SUCCESS == code) {
468,758,810✔
447
    code = calcConstGroupBy(pCxt, pSelect);
468,589,207✔
448
  }
449
  if (TSDB_CODE_SUCCESS == code) {
468,752,953✔
450
    code = calcConstStmtCondition(pCxt, &pSelect->pHaving, &pSelect->isEmptyResult);
468,588,679✔
451
  }
452
  if (TSDB_CODE_SUCCESS == code) {
468,755,367✔
453
    code = calcConstList(pSelect->pOrderByList);
468,575,431✔
454
  }
455
  if (TSDB_CODE_SUCCESS == code) {
468,765,966✔
456
    code = calcConstNode(&pSelect->pFill);
468,588,902✔
457
  }
458
  if (TSDB_CODE_SUCCESS == code) {
468,769,513✔
459
    code = calcConstNode(&pSelect->pTimeRange);
468,592,916✔
460
  }
461
  return code;
468,754,127✔
462
}
463

464

465
static bool isEmptyResultQuery(SNode* pStmt) {
468,017,561✔
466
  bool isEmptyResult = false;
468,017,561✔
467
  switch (nodeType(pStmt)) {
468,017,561✔
468
    case QUERY_NODE_SELECT_STMT:
219,866,275✔
469
      isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult;
219,866,275✔
470
      break;
219,865,775✔
471
    case QUERY_NODE_EXPLAIN_STMT:
51,367,023✔
472
      isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery);
51,367,023✔
473
      break;
51,373,758✔
474
    case QUERY_NODE_SET_OPERATOR: {
8,415,457✔
475
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
8,415,457✔
476
      isEmptyResult = isEmptyResultQuery(pSetOp->pLeft);
8,415,457✔
477
      if (isEmptyResult) {
8,415,467✔
478
        isEmptyResult = isEmptyResultQuery(pSetOp->pRight);
556✔
479
      }
480
      break;
8,415,380✔
481
    }
482
    case QUERY_NODE_DELETE_STMT:
1,831,657✔
483
      isEmptyResult = ((SDeleteStmt*)pStmt)->deleteZeroRows;
1,831,657✔
484
      break;
1,826,178✔
485
    default:
186,544,978✔
486
      break;
186,544,978✔
487
  }
488
  return isEmptyResult;
468,026,069✔
489
}
490

491
static int32_t calcSubQueries(SCalcConstContext* pCxt, SNodeList* pSubQueries) {
84,726,267✔
492
  int32_t code = TSDB_CODE_SUCCESS;
84,726,267✔
493
  SNode* pNode = NULL;
84,726,267✔
494
  FOREACH(pNode, pSubQueries) {
262,033,893✔
495
    code = calcConstQuery(pCxt, pNode, false);
177,302,599✔
496
    if (code) {
177,307,626✔
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,731,294✔
510
}
511

512
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
489,368,445✔
513
  int32_t code = TSDB_CODE_SUCCESS;
489,368,445✔
514
  
515
  if (NULL == pSelect->pFromTable) {
489,368,445✔
516
    code = calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
14,211,441✔
517
  } else {
518
    code = calcConstSelectFrom(pCxt, pSelect, subquery);
475,158,278✔
519
  }
520

521
  if (TSDB_CODE_SUCCESS == code && pSelect->pSubQueries && pSelect->pSubQueries->length > 0) {
489,381,570✔
522
    code = calcSubQueries(pCxt, pSelect->pSubQueries);
82,767,771✔
523
  }
524

525
  return code;
489,383,934✔
526
}
527

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

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

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

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

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

577
static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) {
12,242,226✔
578
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
12,242,226✔
579
    SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext;
6,121,113✔
580
    if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) {
6,121,113✔
581
      pCxt->hasThisCol = true;
2,005,962✔
582
      return DEAL_RES_END;
2,005,962✔
583
    }
584
  }
585
  return DEAL_RES_CONTINUE;
10,236,264✔
586
}
587

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

612
  switch (nodeType(pStmt)) {
3,647,256✔
613
    case QUERY_NODE_SELECT_STMT: {
3,614,165✔
614
      SSelectStmt* pSelect = (SSelectStmt*)pStmt;
3,614,165✔
615
      if (pSelect->isDistinct) {
3,614,165✔
616
        return false;
×
617
      }
618
      SNode* pProj = nodesListGetNode(pSelect->pProjectionList, index);
3,614,165✔
619
      return (NULL != pProj) && isUselessCol((SExprNode*)pProj);
3,614,165✔
620
    }
621
    case QUERY_NODE_SET_OPERATOR: {
33,091✔
622
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
33,091✔
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,091✔
628
        return false;
×
629
      }
630
      return isSubqueryProjUseless(pSetOp->pLeft, index) &&
57,286✔
631
             isSubqueryProjUseless(pSetOp->pRight, index);
24,195✔
632
    }
633
    default:
×
634
      break;
×
635
  }
636
  return false;
×
637
}
638

639
static bool isSetUselessCol(SSetOperator* pSetOp, int32_t index, SExprNode* pProj) {
4,780,516✔
640
  if (!isUselessCol(pProj)) {
4,780,516✔
641
    return false;
2,961,171✔
642
  }
643

644
  return isSubqueryProjUseless(pSetOp->pLeft, index) &&
3,589,970✔
645
         isSubqueryProjUseless(pSetOp->pRight, index);
1,770,625✔
646
}
647

648
static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
29,972,043✔
649
  if (subquery && pSetOp->opType == SET_OP_TYPE_UNION) {
29,972,043✔
650
    return TSDB_CODE_SUCCESS;
2,282,657✔
651
  }
652
  int32_t index = 0;
27,689,386✔
653
  SNode*  pProj = NULL;
27,689,386✔
654
  WHERE_EACH(pProj, pSetOp->pProjectionList) {
66,450,556✔
655
    if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) &&
43,540,787✔
656
        isSetUselessCol(pSetOp, index, (SExprNode*)pProj)) {
4,780,516✔
657
      ERASE_NODE(pSetOp->pProjectionList);
1,770,331✔
658
      eraseSetOpChildProjection(pSetOp, index);
1,770,625✔
659
      continue;
1,771,230✔
660
    }
661
    ++index;
36,989,940✔
662
    WHERE_NEXT;
36,989,940✔
663
  }
664
  if (0 == LIST_LENGTH(pSetOp->pProjectionList)) {
27,690,285✔
665
    SValueNode* pVal = NULL;
5,019✔
666
    int32_t     code = createConstantValue(&pVal);
5,019✔
667
    if (TSDB_CODE_SUCCESS == code) {
4,788✔
668
      return nodesListStrictAppend(pSetOp->pProjectionList, (SNode*)pVal);
4,788✔
669
    }
670
  }
671
  return TSDB_CODE_SUCCESS;
27,685,306✔
672
}
673

674
static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
29,972,638✔
675
  int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery);
29,972,638✔
676
  if (TSDB_CODE_SUCCESS == code) {
29,973,417✔
677
    code = calcConstQuery(pCxt, pSetOp->pLeft, false);
29,974,617✔
678
  }
679
  if (TSDB_CODE_SUCCESS == code) {
29,974,531✔
680
    code = calcConstQuery(pCxt, pSetOp->pRight, false);
29,973,421✔
681
  }
682
  if (TSDB_CODE_SUCCESS == code) {
29,977,148✔
683
    code = calcConstList(pSetOp->pOrderByList);
29,975,690✔
684
  }
685
  if (TSDB_CODE_SUCCESS == code && pSetOp->pSubQueries && pSetOp->pSubQueries->length > 0) {
29,977,764✔
686
    code = calcSubQueries(pCxt, pSetOp->pSubQueries);
1,978,020✔
687
  }
688
  
689
  return code;
29,976,306✔
690
}
691

692
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
759,086,928✔
693
  int32_t code = TSDB_CODE_SUCCESS;
759,086,928✔
694
  switch (nodeType(pStmt)) {
759,086,928✔
695
    case QUERY_NODE_SELECT_STMT:
489,378,842✔
696
      code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery);
489,378,842✔
697
      break;
489,383,326✔
698
    case QUERY_NODE_EXPLAIN_STMT:
51,372,400✔
699
      code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery);
51,372,400✔
700
      break;
51,374,655✔
701
    case QUERY_NODE_SET_OPERATOR: {
29,976,055✔
702
      code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery);
29,976,055✔
703
      break;
29,976,219✔
704
    }
705
    case QUERY_NODE_DELETE_STMT:
1,826,178✔
706
      code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
1,826,178✔
707
      break;
1,826,178✔
708
    case QUERY_NODE_INSERT_STMT:
573,407✔
709
      code = calcConstInsert(pCxt, (SInsertStmt*)pStmt);
573,407✔
710
      break;
574,752✔
711
    default:
185,963,778✔
712
      break;
185,963,778✔
713
  }
714
  return code;
759,098,782✔
715
}
716

717

718
static void resetProjectNullTypeImpl(SNodeList* pProjects) {
179,895,771✔
719
  SNode* pProj = NULL;
179,895,771✔
720
  FOREACH(pProj, pProjects) {
919,012,814✔
721
    SExprNode* pExpr = (SExprNode*)pProj;
739,119,610✔
722
    if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
739,119,610✔
723
      pExpr->resType.type = TSDB_DATA_TYPE_VARCHAR;
193,681✔
724
      pExpr->resType.bytes = VARSTR_HEADER_SIZE;
193,681✔
725
      if (QUERY_NODE_VALUE == nodeType(pExpr)) {
193,681✔
726
        ((SValueNode*)pExpr)->isNull = true;
28,528✔
727
      }
728
    }
729
  }
730
}
179,893,821✔
731

732
static void resetProjectNullType(SNode* pStmt) {
419,625,624✔
733
  switch (nodeType(pStmt)) {
419,625,624✔
734
    case QUERY_NODE_SELECT_STMT:
174,202,646✔
735
      resetProjectNullTypeImpl(((SSelectStmt*)pStmt)->pProjectionList);
174,202,646✔
736
      break;
174,200,185✔
737
    case QUERY_NODE_SET_OPERATOR: {
5,694,788✔
738
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
5,694,788✔
739
      resetProjectNullTypeImpl(pSetOp->pProjectionList);
5,694,788✔
740
      if (pSetOp->pLeft)
5,693,628✔
741
        resetProjectNullType(pSetOp->pLeft);
5,693,628✔
742
      if (pSetOp->pRight)
5,693,628✔
743
        resetProjectNullType(pSetOp->pRight);
5,693,628✔
744
      break;
5,693,628✔
745
    }
746
    default:
239,731,592✔
747
      break;
239,731,592✔
748
  }
749
}
419,625,405✔
750

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

756
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) {
408,408,415✔
757
  SCalcConstContext cxt = {.pParseCxt = pParseCxt,
408,408,415✔
758
                           .msgBuf.buf = pParseCxt->pMsg,
408,399,861✔
759
                           .msgBuf.len = pParseCxt->msgLen,
408,417,045✔
760
                           .code = TSDB_CODE_SUCCESS};
761

762
  int32_t code = TSDB_CODE_SUCCESS;
408,401,533✔
763

764
  if (TSDB_CODE_SUCCESS == code) {
408,401,533✔
765
    code = calcConstQuery(&cxt, pQuery->pRoot, false);
408,406,857✔
766
  }
767
  if (TSDB_CODE_SUCCESS == code) {
408,395,839✔
768
    resetProjectNullType(pQuery->pRoot);
408,241,880✔
769
    if (isEmptyResultQuery(pQuery->pRoot)) {
408,228,528✔
770
      pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
651,675✔
771
    }
772
    code = rewriteScalarSubQResValue(pParseCxt, pQuery);
408,244,234✔
773
  }
774
  
775
  return code;
408,392,819✔
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