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

taosdata / TDengine / #3559

18 Dec 2024 12:59AM UTC coverage: 59.805% (+0.03%) from 59.778%
#3559

push

travis-ci

web-flow
Merge pull request #29187 from taosdata/merge/mainto3.0

merge: main to 3.0 branch

132705 of 287544 branches covered (46.15%)

Branch coverage included in aggregate %.

87 of 95 new or added lines in 19 files covered. (91.58%)

1132 existing lines in 133 files now uncovered.

209591 of 284807 relevant lines covered (73.59%)

8125235.78 hits per line

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

88.48
/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) {
287,028✔
37
  return calcConstQuery(pCxt, pTempTable->pSubquery, true);
287,028✔
38
}
39

40
static int32_t calcConstNode(SNode** pNode) {
2,553,649✔
41
  if (NULL == *pNode) {
2,553,649✔
42
    return TSDB_CODE_SUCCESS;
1,975,363✔
43
  }
44

45
  SNode*  pNew = NULL;
578,286✔
46
  int32_t code = scalarCalculateConstants(*pNode, &pNew);
578,286✔
47
  if (TSDB_CODE_SUCCESS == code) {
578,305✔
48
    *pNode = pNew;
578,302✔
49
  }
50
  return code;
578,305✔
51
}
52

53
static int32_t calcConstList(SNodeList* pList) {
4,096,554✔
54
  SNode* pNode = NULL;
4,096,554✔
55
  FOREACH(pNode, pList) {
4,734,683✔
56
    SNode*  pNew = NULL;
638,129✔
57
    int32_t code = scalarCalculateConstants(pNode, &pNew);
638,129✔
58
    if (TSDB_CODE_SUCCESS == code) {
638,129!
59
      REPLACE_NODE(pNew);
638,129✔
60
    } else {
61
      return code;
×
62
    }
63
  }
64
  return TSDB_CODE_SUCCESS;
4,096,554✔
65
}
66

67
static bool isCondition(const SNode* pNode) {
1,470,022✔
68
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
1,470,022✔
69
    return nodesIsComparisonOp((const SOperatorNode*)pNode);
1,111,854✔
70
  }
71
  return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
358,168✔
72
}
73

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

88
static EDealRes doRewriteCondition(SNode** pNode, void* pContext) {
7,249,235✔
89
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
7,249,235✔
90
    SNode* pParam = NULL;
358,170✔
91
    FOREACH(pParam, ((SLogicConditionNode*)*pNode)->pParameterList) {
1,284,182✔
92
      if (!isCondition(pParam)) {
926,011!
93
        SNode* pIsTrue = NULL;
×
94
        if (TSDB_CODE_SUCCESS != rewriteIsTrue(pParam, &pIsTrue)) {
×
95
          ((SCalcConstContext*)pContext)->code = TSDB_CODE_OUT_OF_MEMORY;
×
96
          return DEAL_RES_ERROR;
×
97
        }
98
        REPLACE_NODE(pIsTrue);
×
99
      }
100
    }
101
  }
102
  return DEAL_RES_CONTINUE;
7,249,236✔
103
}
104

105
static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) {
544,005✔
106
  if (!isCondition(*pNode)) {
544,005✔
107
    return rewriteIsTrue(*pNode, pNode);
30✔
108
  }
109
  nodesRewriteExprPostOrder(pNode, doRewriteCondition, pCxt);
543,978✔
110
  return pCxt->code;
543,991✔
111
}
112

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

121
static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) {
1,239,355✔
122
  int32_t code = TSDB_CODE_SUCCESS;
1,239,355✔
123
  switch (nodeType(pTable)) {
1,239,355✔
124
    case QUERY_NODE_TEMP_TABLE: {
287,028✔
125
      code = calcConstSubquery(pCxt, (STempTableNode*)pTable);
287,028✔
126
      break;
287,029✔
127
    }
128
    case QUERY_NODE_JOIN_TABLE: {
107,754✔
129
      SJoinTableNode* pJoin = (SJoinTableNode*)pTable;
107,754✔
130
      code = rewriteConditionForFromTable(pCxt, pJoin->pLeft);
107,754✔
131
      if (TSDB_CODE_SUCCESS == code) {
107,754!
132
        code = rewriteConditionForFromTable(pCxt, pJoin->pRight);
107,754✔
133
      }
134
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
107,754!
135
        code = calcConstCondition(pCxt, &pJoin->pOnCond);
41,058✔
136
      }
137
      // todo empty table
138
      break;
107,754✔
139
    }
140
    default:
844,573✔
141
      break;
844,573✔
142
  }
143
  return code;
1,239,356✔
144
}
145

146
static int32_t calcConstFromTable(SCalcConstContext* pCxt, SNode* pTable) {
1,023,844✔
147
  return rewriteConditionForFromTable(pCxt, pTable);
1,023,844✔
148
}
149

150
static void rewriteConstCondition(SNode** pCond, bool* pAlwaysFalse) {
502,958✔
151
  if (QUERY_NODE_VALUE != nodeType(*pCond)) {
502,958✔
152
    return;
479,915✔
153
  }
154
  if (((SValueNode*)*pCond)->datum.b) {
23,043✔
155
    nodesDestroyNode(*pCond);
22,542✔
156
    *pCond = NULL;
22,542✔
157
  } else {
158
    *pAlwaysFalse = true;
501✔
159
  }
160
}
161

162
static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bool* pAlwaysFalse) {
2,027,352✔
163
  if (NULL == *pCond) {
2,027,352✔
164
    return TSDB_CODE_SUCCESS;
1,524,406✔
165
  }
166

167
  int32_t code = rewriteCondition(pCxt, pCond);
502,946✔
168
  if (TSDB_CODE_SUCCESS == code) {
502,962✔
169
    code = calcConstNode(pCond);
502,961✔
170
  }
171
  if (TSDB_CODE_SUCCESS == code) {
502,961✔
172
    rewriteConstCondition(pCond, pAlwaysFalse);
502,958✔
173
  }
174
  return code;
502,960✔
175
}
176

177
static EDealRes doFindAndReplaceNode(SNode** pNode, void* pContext) {
6✔
178
  SCalcConstContext* pCxt = pContext;
6✔
179
  if (pCxt->replaceCxt.pTarget == *pNode) {
6!
180
    char aliasName[TSDB_COL_NAME_LEN] = {0};
6✔
181
    tstrncpy(aliasName, ((SExprNode*)*pNode)->aliasName, TSDB_COL_NAME_LEN);
6✔
182
    nodesDestroyNode(*pNode);
6✔
183
    *pNode = NULL;
6✔
184
    pCxt->code = nodesCloneNode(pCxt->replaceCxt.pNew, pNode);
6✔
185
    if (NULL == *pNode) {
6!
186
      return DEAL_RES_ERROR;
×
187
    }
188
    tstrncpy(((SExprNode*)*pNode)->aliasName, aliasName, TSDB_COL_NAME_LEN);
6✔
189

190
    pCxt->replaceCxt.replaced = true;
6✔
191
    return DEAL_RES_END;
6✔
192
  }
193
  return DEAL_RES_CONTINUE;
×
194
}
195

196
static int32_t findAndReplaceNode(SCalcConstContext* pCxt, SNode** pRoot, SNode* pTarget, SNode* pNew, bool strict) {
6✔
197
  pCxt->replaceCxt.pNew = pNew;
6✔
198
  pCxt->replaceCxt.pTarget = pTarget;
6✔
199

200
  nodesRewriteExprPostOrder(pRoot, doFindAndReplaceNode, pCxt);
6✔
201
  if (TSDB_CODE_SUCCESS == pCxt->code && strict && !pCxt->replaceCxt.replaced) {
6!
202
    parserError("target replace node not found, %p", pTarget);
×
203
    return TSDB_CODE_PAR_INTERNAL_ERROR;
×
204
  }
205
  return pCxt->code;
6✔
206
}
207

208
static int32_t calcConstProject(SCalcConstContext* pCxt, SNode* pProject, bool dual, SNode** pNew) {
2,914,756✔
209
  SArray* pAssociation = NULL;
2,914,756✔
210
  if (NULL != ((SExprNode*)pProject)->pAssociation) {
2,914,756✔
211
    pAssociation = taosArrayDup(((SExprNode*)pProject)->pAssociation, NULL);
570,847✔
212
    if (NULL == pAssociation) {
570,846!
UNCOV
213
      return terrno;
×
214
    }
215
  }
216

217
  char    aliasName[TSDB_COL_NAME_LEN] = {0};
2,914,757✔
218
  int32_t code = TSDB_CODE_SUCCESS;
2,914,757✔
219
  if (dual) {
2,914,757✔
220
    code = scalarCalculateConstantsFromDual(pProject, pNew);
100,647✔
221
  } else {
222
    code = scalarCalculateConstants(pProject, pNew);
2,814,110✔
223
  }
224
  if (TSDB_CODE_SUCCESS == code) {
2,914,769✔
225
    if (QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
2,914,756✔
226
      int32_t size = taosArrayGetSize(pAssociation);
24,498✔
227
      for (int32_t i = 0; i < size; ++i) {
48,996✔
228
        SAssociationNode* pAssNode = taosArrayGet(pAssociation, i);
24,498✔
229
        SNode**           pCol = pAssNode->pPlace;
24,498✔
230
        if (*pCol == pAssNode->pAssociationNode) {
24,498✔
231
          tstrncpy(aliasName, ((SExprNode*)*pCol)->aliasName, TSDB_COL_NAME_LEN);
24,492✔
232
          SArray* pOrigAss = NULL;
24,492✔
233
          TSWAP(((SExprNode*)*pCol)->pAssociation, pOrigAss);
24,492✔
234
          nodesDestroyNode(*pCol);
24,492✔
235
          *pCol = NULL;
24,492✔
236
          code = nodesCloneNode(*pNew, pCol);
24,492✔
237
          if (TSDB_CODE_SUCCESS == code) {
24,492!
238
            tstrncpy(((SExprNode*)*pCol)->aliasName, aliasName, TSDB_COL_NAME_LEN);
24,492✔
239
            TSWAP(pOrigAss, ((SExprNode*)*pCol)->pAssociation);
24,492✔
240
          }
241
          taosArrayDestroy(pOrigAss);
24,492✔
242
          if (TSDB_CODE_SUCCESS != code) {
24,492!
243
            break;
×
244
          }
245
        } else {
246
          code = findAndReplaceNode(pCxt, pCol, pAssNode->pAssociationNode, *pNew, true);
6✔
247
          if (TSDB_CODE_SUCCESS != code) {
6!
248
            break;
×
249
          }
250
        }
251
      }
252
    }
253
  }
254
  taosArrayDestroy(pAssociation);
2,914,769✔
255
  return code;
2,914,749✔
256
}
257

258
typedef struct SIsUselessColCtx {
259
  bool isUseless;
260
} SIsUselessColCtx;
261

262
EDealRes checkUselessCol(SNode* pNode, void* pContext) {
2,232,976✔
263
  SIsUselessColCtx* ctx = (SIsUselessColCtx*)pContext;
2,232,976✔
264
  if (QUERY_NODE_FUNCTION == nodeType(pNode) && !fmIsScalarFunc(((SFunctionNode*)pNode)->funcId) &&
2,232,976✔
265
      !fmIsPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)) {
186,414✔
266
    ctx->isUseless = false;
155,071✔
267
    return DEAL_RES_END;
155,071✔
268
  }
269

270
  return DEAL_RES_CONTINUE;
2,077,905✔
271
}
272

273
static bool isUselessCol(SExprNode* pProj) {
1,866,458✔
274
  SIsUselessColCtx ctx = {.isUseless = true};
1,866,458✔
275
  nodesWalkExpr((SNode*)pProj, checkUselessCol, (void*)&ctx);
1,866,458✔
276
  if (!ctx.isUseless) {
1,866,457✔
277
    return false;
155,071✔
278
  }
279
  return NULL == ((SExprNode*)pProj)->pAssociation;
1,711,386✔
280
}
281

282
static int32_t createConstantValue(SValueNode** ppNode) {
1,935✔
283
  SValueNode* pVal = NULL;
1,935✔
284
  int32_t     code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pVal);
1,935✔
285
  if (NULL == pVal) {
1,935!
286
    return code;
×
287
  }
288
  pVal->node.resType.type = TSDB_DATA_TYPE_INT;
1,935✔
289
  pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_INT].bytes;
1,935✔
290
  const int32_t val = 1;
1,935✔
291
  code = nodesSetValueNodeValue(pVal, (void*)&val);
1,935✔
292
  if (TSDB_CODE_SUCCESS == code) {
1,935!
293
    pVal->translate = true;
1,935✔
294
    *ppNode = pVal;
1,935✔
295
  } else {
296
    nodesDestroyNode((SNode*)pVal);
×
297
  }
298
  return code;
1,935✔
299
}
300

301
static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
1,101,420✔
302
  SNode* pProj = NULL;
1,101,420✔
303
  WHERE_EACH(pProj, pSelect->pProjectionList) {
5,238,070!
304
    if (subquery && !pSelect->isDistinct && !pSelect->tagScan && isUselessCol((SExprNode*)pProj)) {
4,136,666✔
305
      ERASE_NODE(pSelect->pProjectionList);
1,221,901✔
306
      continue;
1,221,901✔
307
    }
308
    SNode*  pNew = NULL;
2,914,764✔
309
    int32_t code = calcConstProject(pCxt, pProj, (NULL == pSelect->pFromTable), &pNew);
2,914,764✔
310
    if (TSDB_CODE_SUCCESS == code) {
2,914,760✔
311
      REPLACE_NODE(pNew);
2,914,749✔
312
    } else {
313
      return code;
11✔
314
    }
315
    WHERE_NEXT;
2,914,749✔
316
  }
317
  if (0 == LIST_LENGTH(pSelect->pProjectionList)) {
1,101,404!
318
    SValueNode* pVal = NULL;
1,911✔
319
    int32_t     code = createConstantValue(&pVal);
1,911✔
320
    if (TSDB_CODE_SUCCESS == code) {
1,926!
321
      return nodesListStrictAppend(pSelect->pProjectionList, (SNode*)pVal);
1,926✔
322
    }
323
  }
324
  return TSDB_CODE_SUCCESS;
1,099,493✔
325
}
326

327
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
1,004,826✔
328
  int32_t code = calcConstList(pSelect->pGroupByList);
1,004,826✔
329
  if (TSDB_CODE_SUCCESS == code) {
1,004,825!
330
    SNode* pNode = NULL;
1,004,827✔
331
    FOREACH(pNode, pSelect->pGroupByList) {
1,160,083✔
332
      bool   hasNotValue = false;
155,256✔
333
      SNode* pGroupPara = NULL;
155,256✔
334
      FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
166,995!
335
        if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
155,256✔
336
          hasNotValue = true;
143,517✔
337
          break;
143,517✔
338
        }
339
      }
340
      if (!hasNotValue) {
155,256✔
341
        if (pSelect->hasAggFuncs) {
11,739✔
342
          ERASE_NODE(pSelect->pGroupByList);
186✔
343
        } else {
344
          if (!cell->pPrev && !cell->pNext) continue;
11,553!
345
          ERASE_NODE(pSelect->pGroupByList);
×
346
        }
347
      }
348
    }
349
  }
350
  return code;
1,004,825✔
351
}
352

353
static int32_t calcConstSelectWithoutFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
96,603✔
354
  return calcConstProjections(pCxt, pSelect, subquery);
96,603✔
355
}
356

357
static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
1,006,017✔
358
  int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
1,006,017✔
359
  if (TSDB_CODE_SUCCESS == code && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
1,006,021!
360
      ((STempTableNode*)pSelect->pFromTable)->pSubquery != NULL &&
286,443!
361
      QUERY_NODE_SELECT_STMT == nodeType(((STempTableNode*)pSelect->pFromTable)->pSubquery) &&
286,443✔
362
      ((SSelectStmt*)((STempTableNode*)pSelect->pFromTable)->pSubquery)->isEmptyResult) {
252,336✔
363
    pSelect->isEmptyResult = true;
1,198✔
364
    return code;
1,198✔
365
  }
366
  if (pSelect->mixSysTableAndActualTable) {
1,004,823✔
367
    return code;
1✔
368
  }
369
  if (TSDB_CODE_SUCCESS == code) {
1,004,822✔
370
    code = calcConstProjections(pCxt, pSelect, subquery);
1,004,818✔
371
  }
372
  if (TSDB_CODE_SUCCESS == code) {
1,004,834✔
373
    code = calcConstStmtCondition(pCxt, &pSelect->pWhere, &pSelect->isEmptyResult);
1,004,830✔
374
  }
375
  if (TSDB_CODE_SUCCESS == code) {
1,004,832✔
376
    code = calcConstList(pSelect->pPartitionByList);
1,004,828✔
377
  }
378
  if (TSDB_CODE_SUCCESS == code) {
1,004,829✔
379
    code = calcConstList(pSelect->pTags);
1,004,825✔
380
  }
381
  if (TSDB_CODE_SUCCESS == code) {
1,004,833✔
382
    code = calcConstNode(&pSelect->pSubtable);
1,004,821✔
383
  }
384
  if (TSDB_CODE_SUCCESS == code) {
1,004,839✔
385
    code = calcConstNode(&pSelect->pWindow);
1,004,830✔
386
  }
387
  if (TSDB_CODE_SUCCESS == code) {
1,004,838✔
388
    code = calcConstGroupBy(pCxt, pSelect);
1,004,830✔
389
  }
390
  if (TSDB_CODE_SUCCESS == code) {
1,004,828✔
391
    code = calcConstStmtCondition(pCxt, &pSelect->pHaving, &pSelect->isEmptyResult);
1,004,827✔
392
  }
393
  if (TSDB_CODE_SUCCESS == code) {
1,004,831✔
394
    code = calcConstList(pSelect->pOrderByList);
1,004,830✔
395
  }
396
  return code;
1,004,830✔
397
}
398

399
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
1,102,621✔
400
  if (NULL == pSelect->pFromTable) {
1,102,621✔
401
    return calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
96,603✔
402
  } else {
403
    return calcConstSelectFrom(pCxt, pSelect, subquery);
1,006,018✔
404
  }
405
}
406

407
static int32_t calcConstDelete(SCalcConstContext* pCxt, SDeleteStmt* pDelete) {
17,711✔
408
  int32_t code = calcConstFromTable(pCxt, pDelete->pFromTable);
17,711✔
409
  if (TSDB_CODE_SUCCESS == code) {
17,711!
410
    code = calcConstStmtCondition(pCxt, &pDelete->pWhere, &pDelete->deleteZeroRows);
17,711✔
411
  }
412
  if (code == TSDB_CODE_SUCCESS && pDelete->timeRange.skey > pDelete->timeRange.ekey) {
17,710!
413
    pDelete->deleteZeroRows = true;
78✔
414
  }
415
  return code;
17,710✔
416
}
417

418
static int32_t calcConstInsert(SCalcConstContext* pCxt, SInsertStmt* pInsert) {
117✔
419
  int32_t code = calcConstFromTable(pCxt, pInsert->pTable);
117✔
420
  if (TSDB_CODE_SUCCESS == code) {
117!
421
    code = calcConstQuery(pCxt, pInsert->pQuery, false);
117✔
422
  }
423
  return code;
117✔
424
}
425

426
static SNodeList* getChildProjection(SNode* pStmt) {
60,514✔
427
  switch (nodeType(pStmt)) {
60,514!
428
    case QUERY_NODE_SELECT_STMT:
60,487✔
429
      return ((SSelectStmt*)pStmt)->pProjectionList;
60,487✔
430
    case QUERY_NODE_SET_OPERATOR:
27✔
431
      return ((SSetOperator*)pStmt)->pProjectionList;
27✔
432
    default:
×
433
      break;
×
434
  }
435
  return NULL;
×
436
}
437

438
static void eraseSetOpChildProjection(SSetOperator* pSetOp, int32_t index) {
15,034✔
439
  SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft);
15,034✔
440
  (void)nodesListErase(pLeftProjs, nodesListGetCell(pLeftProjs, index));
15,034✔
441
  if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pLeft)) {
15,034✔
442
    eraseSetOpChildProjection((SSetOperator*)pSetOp->pLeft, index);
12✔
443
  }
444
  SNodeList* pRightProjs = getChildProjection(pSetOp->pRight);
15,034✔
445
  (void)nodesListErase(pRightProjs, nodesListGetCell(pRightProjs, index));
15,034✔
446
  if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pRight)) {
15,034!
447
    eraseSetOpChildProjection((SSetOperator*)pSetOp->pRight, index);
×
448
  }
449
}
15,034✔
450

451
typedef struct SNotRefByOrderByCxt {
452
  SColumnNode* pCol;
453
  bool         hasThisCol;
454
} SNotRefByOrderByCxt;
455

456
static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) {
95,914✔
457
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
95,914✔
458
    SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext;
47,957✔
459
    if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) {
47,957✔
460
      pCxt->hasThisCol = true;
15,322✔
461
      return DEAL_RES_END;
15,322✔
462
    }
463
  }
464
  return DEAL_RES_CONTINUE;
80,592✔
465
}
466

467
static bool notRefByOrderBy(SColumnNode* pCol, SNodeList* pOrderByList) {
50,366✔
468
  SNotRefByOrderByCxt cxt = {.pCol = pCol, .hasThisCol = false};
50,366✔
469
  nodesWalkExprs(pOrderByList, notRefByOrderByImpl, &cxt);
50,366✔
470
  return !cxt.hasThisCol;
50,366✔
471
}
472

473
static bool isDistinctSubQuery(SNode* pNode) {
30,596✔
474
  if (NULL == pNode) {
30,596!
475
    return false;
×
476
  }
477
  switch (nodeType(pNode)) {
30,596!
478
    case QUERY_NODE_SELECT_STMT:
30,326✔
479
      return ((SSelectStmt*)pNode)->isDistinct;
30,326✔
480
    case QUERY_NODE_SET_OPERATOR:
270✔
481
      return isDistinctSubQuery((((SSetOperator*)pNode)->pLeft)) || isDistinctSubQuery((((SSetOperator*)pNode)->pLeft));
270!
482
    default:
×
483
      break;
×
484
  }
485
  return false;
×
486
}
487

488
static bool isSetUselessCol(SSetOperator* pSetOp, int32_t index, SExprNode* pProj) {
35,044✔
489
  if (!isUselessCol(pProj)) {
35,044✔
490
    return false;
19,632✔
491
  }
492

493
  SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft);
15,412✔
494
  if (!isUselessCol((SExprNode*)nodesListGetNode(pLeftProjs, index)) || isDistinctSubQuery(pSetOp->pLeft)) {
15,412!
495
    return false;
378✔
496
  }
497

498
  SNodeList* pRightProjs = getChildProjection(pSetOp->pRight);
15,034✔
499
  if (!isUselessCol((SExprNode*)nodesListGetNode(pRightProjs, index)) || isDistinctSubQuery(pSetOp->pLeft)) {
15,034!
500
    return false;
12✔
501
  }
502

503
  return true;
15,022✔
504
}
505

506
static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
77,260✔
507
  if (subquery && pSetOp->opType == SET_OP_TYPE_UNION) {
77,260✔
508
    return TSDB_CODE_SUCCESS;
16,797✔
509
  }
510
  int32_t index = 0;
60,463✔
511
  SNode*  pProj = NULL;
60,463✔
512
  WHERE_EACH(pProj, pSetOp->pProjectionList) {
197,335!
513
    if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) &&
171,916✔
514
        isSetUselessCol(pSetOp, index, (SExprNode*)pProj)) {
35,044✔
515
      ERASE_NODE(pSetOp->pProjectionList);
15,022✔
516
      eraseSetOpChildProjection(pSetOp, index);
15,022✔
517
      continue;
15,022✔
518
    }
519
    ++index;
121,850✔
520
    WHERE_NEXT;
121,850✔
521
  }
522
  if (0 == LIST_LENGTH(pSetOp->pProjectionList)) {
60,463!
523
    SValueNode* pVal = NULL;
9✔
524
    int32_t     code = createConstantValue(&pVal);
9✔
525
    if (TSDB_CODE_SUCCESS == code) {
9!
526
      return nodesListStrictAppend(pSetOp->pProjectionList, (SNode*)pVal);
9✔
527
    }
528
  }
529
  return TSDB_CODE_SUCCESS;
60,454✔
530
}
531

532
static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
77,260✔
533
  int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery);
77,260✔
534
  if (TSDB_CODE_SUCCESS == code) {
77,260!
535
    code = calcConstQuery(pCxt, pSetOp->pLeft, false);
77,260✔
536
  }
537
  if (TSDB_CODE_SUCCESS == code) {
77,260!
538
    code = calcConstQuery(pCxt, pSetOp->pRight, false);
77,260✔
539
  }
540
  if (TSDB_CODE_SUCCESS == code) {
77,260!
541
    code = calcConstList(pSetOp->pOrderByList);
77,260✔
542
  }
543
  return code;
77,260✔
544
}
545

546
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
1,397,295✔
547
  int32_t code = TSDB_CODE_SUCCESS;
1,397,295✔
548
  switch (nodeType(pStmt)) {
1,397,295✔
549
    case QUERY_NODE_SELECT_STMT:
1,102,629✔
550
      code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery);
1,102,629✔
551
      break;
1,102,631✔
552
    case QUERY_NODE_EXPLAIN_STMT:
105,659✔
553
      code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery);
105,659✔
554
      break;
105,659✔
555
    case QUERY_NODE_SET_OPERATOR: {
77,260✔
556
      code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery);
77,260✔
557
      break;
77,260✔
558
    }
559
    case QUERY_NODE_DELETE_STMT:
17,711✔
560
      code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
17,711✔
561
      break;
17,710✔
562
    case QUERY_NODE_INSERT_STMT:
117✔
563
      code = calcConstInsert(pCxt, (SInsertStmt*)pStmt);
117✔
564
      break;
117✔
565
    default:
93,919✔
566
      break;
93,919✔
567
  }
568
  return code;
1,397,296✔
569
}
570

571
static bool isEmptyResultQuery(SNode* pStmt) {
998,415✔
572
  bool isEmptyResult = false;
998,415✔
573
  switch (nodeType(pStmt)) {
998,415✔
574
    case QUERY_NODE_SELECT_STMT:
738,205✔
575
      isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult;
738,205✔
576
      break;
738,205✔
577
    case QUERY_NODE_EXPLAIN_STMT:
105,658✔
578
      isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery);
105,658✔
579
      break;
105,658✔
580
    case QUERY_NODE_SET_OPERATOR: {
42,800✔
581
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
42,800✔
582
      isEmptyResult = isEmptyResultQuery(pSetOp->pLeft);
42,800✔
583
      if (isEmptyResult) {
42,800!
584
        isEmptyResult = isEmptyResultQuery(pSetOp->pRight);
×
585
      }
586
      break;
42,800✔
587
    }
588
    case QUERY_NODE_DELETE_STMT:
17,710✔
589
      isEmptyResult = ((SDeleteStmt*)pStmt)->deleteZeroRows;
17,710✔
590
      break;
17,710✔
591
    default:
94,042✔
592
      break;
94,042✔
593
  }
594
  return isEmptyResult;
998,415✔
595
}
596

597
static void resetProjectNullTypeImpl(SNodeList* pProjects) {
698,811✔
598
  SNode* pProj = NULL;
698,811✔
599
  FOREACH(pProj, pProjects) {
2,434,711!
600
    SExprNode* pExpr = (SExprNode*)pProj;
1,735,900✔
601
    if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
1,735,900✔
602
      pExpr->resType.type = TSDB_DATA_TYPE_VARCHAR;
36✔
603
      pExpr->resType.bytes = VARSTR_HEADER_SIZE;
36✔
604
    }
605
  }
606
}
698,811✔
607

608
static void resetProjectNullType(SNode* pStmt) {
916,196✔
609
  switch (nodeType(pStmt)) {
916,196✔
610
    case QUERY_NODE_SELECT_STMT:
665,684✔
611
      resetProjectNullTypeImpl(((SSelectStmt*)pStmt)->pProjectionList);
665,684✔
612
      break;
665,689✔
613
    case QUERY_NODE_SET_OPERATOR: {
33,125✔
614
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
33,125✔
615
      resetProjectNullTypeImpl(pSetOp->pProjectionList);
33,125✔
616
      if (pSetOp->pLeft)
33,125!
617
        resetProjectNullType(pSetOp->pLeft);
33,125✔
618
      if (pSetOp->pRight)
33,125!
619
        resetProjectNullType(pSetOp->pRight);
33,125✔
620
      break;
33,125✔
621
    }
622
    default:
217,387✔
623
      break;
217,387✔
624
  }
625
}
916,201✔
626

627
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) {
849,971✔
628
  SCalcConstContext cxt = {.pParseCxt = pParseCxt,
849,971✔
629
                           .msgBuf.buf = pParseCxt->pMsg,
849,971✔
630
                           .msgBuf.len = pParseCxt->msgLen,
849,971✔
631
                           .code = TSDB_CODE_SUCCESS};
632

633
  int32_t code = calcConstQuery(&cxt, pQuery->pRoot, false);
849,971✔
634
  if (TSDB_CODE_SUCCESS == code) {
849,977✔
635
    resetProjectNullType(pQuery->pRoot);
849,964✔
636
    if (isEmptyResultQuery(pQuery->pRoot)) {
849,957✔
637
      pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
2,769✔
638
    }
639
  }
640
  return code;
849,975✔
641
}
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