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

taosdata / TDengine / #3533

20 Nov 2024 07:11AM UTC coverage: 58.848% (-1.9%) from 60.78%
#3533

push

travis-ci

web-flow
Merge pull request #28823 from taosdata/fix/3.0/TD-32587

fix:[TD-32587]fix stmt segmentation fault

115578 of 252434 branches covered (45.79%)

Branch coverage included in aggregate %.

1 of 4 new or added lines in 1 file covered. (25.0%)

8038 existing lines in 233 files now uncovered.

194926 of 275199 relevant lines covered (70.83%)

1494459.59 hits per line

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

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

40
static int32_t calcConstNode(SNode** pNode) {
785,177✔
41
  if (NULL == *pNode) {
785,177✔
42
    return TSDB_CODE_SUCCESS;
626,102✔
43
  }
44

45
  SNode*  pNew = NULL;
159,075✔
46
  int32_t code = scalarCalculateConstants(*pNode, &pNew);
159,075✔
47
  if (TSDB_CODE_SUCCESS == code) {
159,076✔
48
    *pNode = pNew;
159,074✔
49
  }
50
  return code;
159,076✔
51
}
52

53
static int32_t calcConstList(SNodeList* pList) {
1,277,255✔
54
  SNode* pNode = NULL;
1,277,255✔
55
  FOREACH(pNode, pList) {
1,432,839✔
56
    SNode*  pNew = NULL;
155,584✔
57
    int32_t code = scalarCalculateConstants(pNode, &pNew);
155,584✔
58
    if (TSDB_CODE_SUCCESS == code) {
155,584!
59
      REPLACE_NODE(pNew);
155,584✔
60
    } else {
UNCOV
61
      return code;
×
62
    }
63
  }
64
  return TSDB_CODE_SUCCESS;
1,277,255✔
65
}
66

67
static bool isCondition(const SNode* pNode) {
280,529✔
68
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
280,529✔
69
    return nodesIsComparisonOp((const SOperatorNode*)pNode);
235,409✔
70
  }
71
  return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
45,120✔
72
}
73

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

88
static EDealRes doRewriteCondition(SNode** pNode, void* pContext) {
1,275,056✔
89
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
1,275,056✔
90
    SNode* pParam = NULL;
45,111✔
91
    FOREACH(pParam, ((SLogicConditionNode*)*pNode)->pParameterList) {
173,344!
92
      if (!isCondition(pParam)) {
128,233!
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;
1,275,056✔
103
}
104

105
static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) {
152,296✔
106
  if (!isCondition(*pNode)) {
152,296✔
107
    return rewriteIsTrue(*pNode, pNode);
22✔
108
  }
109
  nodesRewriteExprPostOrder(pNode, doRewriteCondition, pCxt);
152,273✔
110
  return pCxt->code;
152,275✔
111
}
112

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

121
static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) {
378,245✔
122
  int32_t code = TSDB_CODE_SUCCESS;
378,245✔
123
  switch (nodeType(pTable)) {
378,245✔
124
    case QUERY_NODE_TEMP_TABLE: {
31,146✔
125
      code = calcConstSubquery(pCxt, (STempTableNode*)pTable);
31,146✔
126
      break;
31,146✔
127
    }
128
    case QUERY_NODE_JOIN_TABLE: {
29,960✔
129
      SJoinTableNode* pJoin = (SJoinTableNode*)pTable;
29,960✔
130
      code = rewriteConditionForFromTable(pCxt, pJoin->pLeft);
29,960✔
131
      if (TSDB_CODE_SUCCESS == code) {
29,960!
132
        code = rewriteConditionForFromTable(pCxt, pJoin->pRight);
29,960✔
133
      }
134
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
29,960!
135
        code = calcConstCondition(pCxt, &pJoin->pOnCond);
21,138✔
136
      }
137
      // todo empty table
138
      break;
29,960✔
139
    }
140
    default:
317,139✔
141
      break;
317,139✔
142
  }
143
  return code;
378,245✔
144
}
145

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

150
static void rewriteConstCondition(SNode** pCond, bool* pAlwaysFalse) {
131,158✔
151
  if (QUERY_NODE_VALUE != nodeType(*pCond)) {
131,158✔
152
    return;
126,864✔
153
  }
154
  if (((SValueNode*)*pCond)->datum.b) {
4,294✔
155
    nodesDestroyNode(*pCond);
4,209✔
156
    *pCond = NULL;
4,209✔
157
  } else {
158
    *pAlwaysFalse = true;
85✔
159
  }
160
}
161

162
static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bool* pAlwaysFalse) {
634,547✔
163
  if (NULL == *pCond) {
634,547✔
164
    return TSDB_CODE_SUCCESS;
503,387✔
165
  }
166

167
  int32_t code = rewriteCondition(pCxt, pCond);
131,160✔
168
  if (TSDB_CODE_SUCCESS == code) {
131,159!
169
    code = calcConstNode(pCond);
131,159✔
170
  }
171
  if (TSDB_CODE_SUCCESS == code) {
131,160✔
172
    rewriteConstCondition(pCond, pAlwaysFalse);
131,158✔
173
  }
174
  return code;
131,160✔
175
}
176

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

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

196
static int32_t findAndReplaceNode(SCalcConstContext* pCxt, SNode** pRoot, SNode* pTarget, SNode* pNew, bool strict) {
7✔
197
  pCxt->replaceCxt.pNew = pNew;
7✔
198
  pCxt->replaceCxt.pTarget = pTarget;
7✔
199
  
200
  nodesRewriteExprPostOrder(pRoot, doFindAndReplaceNode, pCxt);
7✔
201
  if (TSDB_CODE_SUCCESS == pCxt->code && strict && !pCxt->replaceCxt.replaced) {
7!
202
    parserError("target replace node not found, %p", pTarget);
×
203
    return TSDB_CODE_PAR_INTERNAL_ERROR;
×
204
  }
205
  return pCxt->code;
7✔
206
}
207

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

217
  char aliasName[TSDB_COL_NAME_LEN] = {0};
2,286,789✔
218
  int32_t code = TSDB_CODE_SUCCESS;
2,286,789✔
219
  if (dual) {
2,286,789✔
220
    code = scalarCalculateConstantsFromDual(pProject, pNew);
51,019✔
221
  } else {
222
    code = scalarCalculateConstants(pProject, pNew);
2,235,770✔
223
  }
224
  if (TSDB_CODE_SUCCESS == code) {
2,286,792✔
225
    if (QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
2,286,776✔
226
      int32_t size = taosArrayGetSize(pAssociation);
4,105✔
227
      for (int32_t i = 0; i < size; ++i) {
8,236✔
228
        SAssociationNode* pAssNode = taosArrayGet(pAssociation, i);
4,131✔
229
        SNode** pCol = pAssNode->pPlace;
4,131✔
230
        if (*pCol == pAssNode->pAssociationNode) {
4,131✔
231
          strcpy(aliasName, ((SExprNode*)*pCol)->aliasName);
4,124✔
232
          SArray* pOrigAss = NULL;
4,124✔
233
          TSWAP(((SExprNode*)*pCol)->pAssociation, pOrigAss);
4,124✔
234
          nodesDestroyNode(*pCol);
4,124✔
235
          *pCol = NULL;
4,124✔
236
          code = nodesCloneNode(*pNew, pCol);
4,124✔
237
          if (TSDB_CODE_SUCCESS == code) {
4,124!
238
            strcpy(((SExprNode*)*pCol)->aliasName, aliasName);
4,124✔
239
            TSWAP(pOrigAss, ((SExprNode*)*pCol)->pAssociation);
4,124✔
240
          }
241
          taosArrayDestroy(pOrigAss);
4,124✔
242
          if (TSDB_CODE_SUCCESS != code) {
4,124!
243
            break;
×
244
          }
245
        } else {
246
          code = findAndReplaceNode(pCxt, pCol, pAssNode->pAssociationNode, *pNew, true);
7✔
247
          if (TSDB_CODE_SUCCESS != code) {
7!
248
            break;
×
249
          }
250
        }
251
      }
252
    }
253
  }
254
  taosArrayDestroy(pAssociation);
2,286,792✔
255
  return code;
2,286,791✔
256
}
257

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

262
EDealRes checkUselessCol(SNode *pNode, void *pContext) {
228,942✔
263
  SIsUselessColCtx  *ctx = (SIsUselessColCtx *)pContext;
228,942✔
264
  if (QUERY_NODE_FUNCTION == nodeType(pNode) && !fmIsScalarFunc(((SFunctionNode*)pNode)->funcId) &&
228,942✔
265
      !fmIsPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)) {
20,539✔
266
    ctx->isUseless = false;  
17,311✔
267
    return DEAL_RES_END;
17,311✔
268
  }
269

270
  return DEAL_RES_CONTINUE;
211,631✔
271
}
272

273
static bool isUselessCol(SExprNode* pProj) {
186,350✔
274
  SIsUselessColCtx ctx = {.isUseless = true};
186,350✔
275
  nodesWalkExpr((SNode*)pProj, checkUselessCol, (void *)&ctx);
186,350✔
276
  if (!ctx.isUseless) {
186,350✔
277
    return false;
17,311✔
278
  }
279
  return NULL == ((SExprNode*)pProj)->pAssociation;
169,039✔
280
}
281

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

301
static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
367,437✔
302
  SNode* pProj = NULL;
367,437✔
303
  WHERE_EACH(pProj, pSelect->pProjectionList) {
2,767,475!
304
    if (subquery && !pSelect->isDistinct && !pSelect->tagScan && isUselessCol((SExprNode*)pProj)) {
2,400,054✔
305
      ERASE_NODE(pSelect->pProjectionList);
113,264✔
306
      continue;
113,264✔
307
    }
308
    SNode*  pNew = NULL;
2,286,790✔
309
    int32_t code = calcConstProject(pCxt, pProj, (NULL == pSelect->pFromTable), &pNew);
2,286,790✔
310
    if (TSDB_CODE_SUCCESS == code) {
2,286,791✔
311
      REPLACE_NODE(pNew);
2,286,774✔
312
    } else {
313
      return code;
17✔
314
    }
315
    WHERE_NEXT;
2,286,774✔
316
  }
317
  if (0 == LIST_LENGTH(pSelect->pProjectionList)) {
367,421!
318
    SValueNode* pVal = NULL;
106✔
319
    int32_t code = createConstantValue(&pVal);
106✔
320
    if (TSDB_CODE_SUCCESS == code) {
107!
321
      return nodesListStrictAppend(pSelect->pProjectionList, (SNode*)pVal);
107✔
322
    }
323
  }
324
  return TSDB_CODE_SUCCESS;
367,315✔
325
}
326

327
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
316,440✔
328
  int32_t code = calcConstList(pSelect->pGroupByList);
316,440✔
329
  if (TSDB_CODE_SUCCESS == code) {
316,440!
330
    SNode* pNode = NULL;
316,440✔
331
    FOREACH(pNode, pSelect->pGroupByList) {
318,011✔
332
      SNode* pGroupPara = NULL;
77,154✔
333
      FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
78,725!
334
        if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
77,154✔
335
          return code;
75,583✔
336
        }
337
      }
338
    }
339
    NODES_DESTORY_LIST(pSelect->pGroupByList);
240,857✔
340
  }
341
  return code;
240,855✔
342
}
343

344
static int32_t calcConstSelectWithoutFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
50,997✔
345
  return calcConstProjections(pCxt, pSelect, subquery);
50,997✔
346
}
347

348
static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
316,548✔
349
  int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
316,548✔
350
  if (TSDB_CODE_SUCCESS == code && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
316,546!
351
      ((STempTableNode*)pSelect->pFromTable)->pSubquery != NULL &&
30,643!
352
      QUERY_NODE_SELECT_STMT == nodeType(((STempTableNode*)pSelect->pFromTable)->pSubquery) &&
30,643✔
353
      ((SSelectStmt*)((STempTableNode*)pSelect->pFromTable)->pSubquery)->isEmptyResult){
27,415✔
354
    pSelect->isEmptyResult = true;
108✔
355
    return code;
108✔
356
  }      
357
  if (TSDB_CODE_SUCCESS == code) {
316,438!
358
    code = calcConstProjections(pCxt, pSelect, subquery);
316,441✔
359
  }
360
  if (TSDB_CODE_SUCCESS == code) {
316,439!
361
    code = calcConstStmtCondition(pCxt, &pSelect->pWhere, &pSelect->isEmptyResult);
316,442✔
362
  }
363
  if (TSDB_CODE_SUCCESS == code) {
316,439!
364
    code = calcConstList(pSelect->pPartitionByList);
316,440✔
365
  }
366
  if (TSDB_CODE_SUCCESS == code) {
316,437!
367
    code = calcConstList(pSelect->pTags);
316,440✔
368
  }
369
  if (TSDB_CODE_SUCCESS == code) {
316,437!
370
    code = calcConstNode(&pSelect->pSubtable);
316,440✔
371
  }
372
  if (TSDB_CODE_SUCCESS == code) {
316,437!
373
    code = calcConstNode(&pSelect->pWindow);
316,440✔
374
  }
375
  if (TSDB_CODE_SUCCESS == code) {
316,437!
376
    code = calcConstGroupBy(pCxt, pSelect);
316,440✔
377
  }
378
  if (TSDB_CODE_SUCCESS == code) {
316,435!
379
    code = calcConstStmtCondition(pCxt, &pSelect->pHaving, &pSelect->isEmptyResult);
316,439✔
380
  }
381
  if (TSDB_CODE_SUCCESS == code) {
316,435!
382
    code = calcConstList(pSelect->pOrderByList);
316,439✔
383
  }
384
  return code;
316,441✔
385
}
386

387
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
367,545✔
388
  if (NULL == pSelect->pFromTable) {
367,545✔
389
    return calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
50,997✔
390
  } else {
391
    return calcConstSelectFrom(pCxt, pSelect, subquery);
316,548✔
392
  }
393
}
394

395
static int32_t calcConstDelete(SCalcConstContext* pCxt, SDeleteStmt* pDelete) {
1,666✔
396
  int32_t code = calcConstFromTable(pCxt, pDelete->pFromTable);
1,666✔
397
  if (TSDB_CODE_SUCCESS == code) {
1,666!
398
    code = calcConstStmtCondition(pCxt, &pDelete->pWhere, &pDelete->deleteZeroRows);
1,666✔
399
  }
400
  if (code == TSDB_CODE_SUCCESS && pDelete->timeRange.skey > pDelete->timeRange.ekey) {
1,666!
401
    pDelete->deleteZeroRows = true;
17✔
402
  }
403
  return code;
1,666✔
404
}
405

406
static int32_t calcConstInsert(SCalcConstContext* pCxt, SInsertStmt* pInsert) {
112✔
407
  int32_t code = calcConstFromTable(pCxt, pInsert->pTable);
112✔
408
  if (TSDB_CODE_SUCCESS == code) {
112!
409
    code = calcConstQuery(pCxt, pInsert->pQuery, false);
112✔
410
  }
411
  return code;
112✔
412
}
413

414
static SNodeList* getChildProjection(SNode* pStmt) {
6,734✔
415
  switch (nodeType(pStmt)) {
6,734!
416
    case QUERY_NODE_SELECT_STMT:
6,669✔
417
      return ((SSelectStmt*)pStmt)->pProjectionList;
6,669✔
418
    case QUERY_NODE_SET_OPERATOR:
65✔
419
      return ((SSetOperator*)pStmt)->pProjectionList;
65✔
420
    default:
×
421
      break;
×
422
  }
423
  return NULL;
×
424
}
425

426
static void eraseSetOpChildProjection(SSetOperator* pSetOp, int32_t index) {
1,694✔
427
  SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft);
1,694✔
428
  (void)nodesListErase(pLeftProjs, nodesListGetCell(pLeftProjs, index));
1,694✔
429
  if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pLeft)) {
1,694✔
430
    eraseSetOpChildProjection((SSetOperator*)pSetOp->pLeft, index);
31✔
431
  }
432
  SNodeList* pRightProjs = getChildProjection(pSetOp->pRight);
1,694✔
433
  (void)nodesListErase(pRightProjs, nodesListGetCell(pRightProjs, index));
1,694✔
434
  if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pRight)) {
1,694!
435
    eraseSetOpChildProjection((SSetOperator*)pSetOp->pRight, index);
×
436
  }
437
}
1,694✔
438

439
typedef struct SNotRefByOrderByCxt {
440
  SColumnNode* pCol;
441
  bool         hasThisCol;
442
} SNotRefByOrderByCxt;
443

444
static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) {
10,392✔
445
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
10,392✔
446
    SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext;
5,196✔
447
    if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) {
5,196✔
448
      pCxt->hasThisCol = true;
1,583✔
449
      return DEAL_RES_END;
1,583✔
450
    }
451
  }
452
  return DEAL_RES_CONTINUE;
8,809✔
453
}
454

455
static bool notRefByOrderBy(SColumnNode* pCol, SNodeList* pOrderByList) {
5,461✔
456
  SNotRefByOrderByCxt cxt = {.pCol = pCol, .hasThisCol = false};
5,461✔
457
  nodesWalkExprs(pOrderByList, notRefByOrderByImpl, &cxt);
5,461✔
458
  return !cxt.hasThisCol;
5,461✔
459
}
460

461
static bool isDistinctSubQuery(SNode* pNode) {
3,543✔
462
  if (NULL == pNode) {
3,543!
463
    return false;
×
464
  }
465
  switch (nodeType(pNode)) {
3,543!
466
    case QUERY_NODE_SELECT_STMT:
3,436✔
467
      return ((SSelectStmt*)pNode)->isDistinct;
3,436✔
468
    case QUERY_NODE_SET_OPERATOR:
107✔
469
      return isDistinctSubQuery((((SSetOperator*)pNode)->pLeft)) || isDistinctSubQuery((((SSetOperator*)pNode)->pLeft));
107!
470
    default:
×
471
      break;
×
472
  }
473
  return false;
×
474
}
475

476
static bool isSetUselessCol(SSetOperator* pSetOp, int32_t index, SExprNode* pProj) {
3,878✔
477
  if (!isUselessCol(pProj)) {
3,878✔
478
    return false;
2,198✔
479
  }
480

481
  SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft);
1,680✔
482
  if (!isUselessCol((SExprNode*)nodesListGetNode(pLeftProjs, index)) || isDistinctSubQuery(pSetOp->pLeft)) {
1,680!
483
    return false;
14✔
484
  }
485

486
  SNodeList* pRightProjs = getChildProjection(pSetOp->pRight);
1,666✔
487
  if (!isUselessCol((SExprNode*)nodesListGetNode(pRightProjs, index)) || isDistinctSubQuery(pSetOp->pLeft)) {
1,666!
488
    return false;
3✔
489
  }
490

491
  return true;
1,663✔
492
}
493

494
static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
11,499✔
495
  if (subquery && pSetOp->opType == SET_OP_TYPE_UNION) {
11,499✔
496
    return TSDB_CODE_SUCCESS;
1,597✔
497
  }
498
  int32_t index = 0;
9,902✔
499
  SNode*  pProj = NULL;
9,902✔
500
  WHERE_EACH(pProj, pSetOp->pProjectionList) {
31,038!
501
    if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) &&
25,014✔
502
        isSetUselessCol(pSetOp, index, (SExprNode*)pProj)) {
3,878✔
503
      ERASE_NODE(pSetOp->pProjectionList);
1,663✔
504
      eraseSetOpChildProjection(pSetOp, index);
1,663✔
505
      continue;
1,663✔
506
    }
507
    ++index;
19,473✔
508
    WHERE_NEXT;
19,473✔
509
  }
510
  if (0 == LIST_LENGTH(pSetOp->pProjectionList)) {
9,902!
511
    SValueNode* pVal = NULL;
2✔
512
    int32_t code = createConstantValue(&pVal);
2✔
513
    if (TSDB_CODE_SUCCESS == code) {
2!
514
      return nodesListStrictAppend(pSetOp->pProjectionList, (SNode*)pVal);
2✔
515
    }
516
  }
517
  return TSDB_CODE_SUCCESS;
9,900✔
518
}
519

520
static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) {
11,499✔
521
  int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery);
11,499✔
522
  if (TSDB_CODE_SUCCESS == code) {
11,499!
523
    code = calcConstQuery(pCxt, pSetOp->pLeft, false);
11,499✔
524
  }
525
  if (TSDB_CODE_SUCCESS == code) {
11,499!
526
    code = calcConstQuery(pCxt, pSetOp->pRight, false);
11,499✔
527
  }
528
  if (TSDB_CODE_SUCCESS == code) {
11,499!
529
    code = calcConstList(pSetOp->pOrderByList);
11,499✔
530
  }
531
  return code;
11,499✔
532
}
533

534
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
450,857✔
535
  int32_t code = TSDB_CODE_SUCCESS;
450,857✔
536
  switch (nodeType(pStmt)) {
450,857✔
537
    case QUERY_NODE_SELECT_STMT:
367,547✔
538
      code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery);
367,547✔
539
      break;
367,545✔
540
    case QUERY_NODE_EXPLAIN_STMT:
13,734✔
541
      code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery);
13,734✔
542
      break;
13,734✔
543
    case QUERY_NODE_SET_OPERATOR: {
11,499✔
544
      code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery);
11,499✔
545
      break;
11,499✔
546
    }
547
    case QUERY_NODE_DELETE_STMT:
1,666✔
548
      code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
1,666✔
549
      break;
1,666✔
550
    case QUERY_NODE_INSERT_STMT:
112✔
551
      code = calcConstInsert(pCxt, (SInsertStmt*)pStmt);
112✔
552
      break;
112✔
553
    default:
56,299✔
554
      break;
56,299✔
555
  }
556
  return code;
450,855✔
557
}
558

559
static bool isEmptyResultQuery(SNode* pStmt) {
404,780✔
560
  bool isEmptyResult = false;
404,780✔
561
  switch (nodeType(pStmt)) {
404,780✔
562
    case QUERY_NODE_SELECT_STMT:
324,770✔
563
      isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult;
324,770✔
564
      break;
324,770✔
565
    case QUERY_NODE_EXPLAIN_STMT:
13,733✔
566
      isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery);
13,733✔
567
      break;
13,733✔
568
    case QUERY_NODE_SET_OPERATOR: {
8,201✔
569
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
8,201✔
570
      isEmptyResult = isEmptyResultQuery(pSetOp->pLeft);
8,201✔
571
      if (isEmptyResult) {
8,201!
572
        isEmptyResult = isEmptyResultQuery(pSetOp->pRight);
×
573
      }
574
      break;
8,201✔
575
    }
576
    case QUERY_NODE_DELETE_STMT:
1,666✔
577
      isEmptyResult = ((SDeleteStmt*)pStmt)->deleteZeroRows;
1,666✔
578
      break;
1,666✔
579
    default:
56,410✔
580
      break;
56,410✔
581
  }
582
  return isEmptyResult;
404,780✔
583
}
584

585
static void resetProjectNullTypeImpl(SNodeList* pProjects) {
311,056✔
586
  SNode* pProj = NULL;
311,056✔
587
  FOREACH(pProj, pProjects) {
2,365,644!
588
    SExprNode* pExpr = (SExprNode*)pProj;
2,054,588✔
589
    if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
2,054,588✔
590
      pExpr->resType.type = TSDB_DATA_TYPE_VARCHAR;
9✔
591
      pExpr->resType.bytes = VARSTR_HEADER_SIZE;
9✔
592
    }
593
  }
594
}
311,056✔
595

596
static void resetProjectNullType(SNode* pStmt) {
382,847✔
597
  switch (nodeType(pStmt)) {
382,847✔
598
    case QUERY_NODE_SELECT_STMT:
304,666✔
599
      resetProjectNullTypeImpl(((SSelectStmt*)pStmt)->pProjectionList);
304,666✔
600
      break;
304,667✔
601
    case QUERY_NODE_SET_OPERATOR: {
6,390✔
602
      resetProjectNullTypeImpl(((SSetOperator*)pStmt)->pProjectionList);
6,390✔
603
      break;
6,390✔
604
    }
605
    default:
71,791✔
606
      break;
71,791✔
607
  }
608
}
382,848✔
609

610
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) {
382,867✔
611
  SCalcConstContext cxt = {.pParseCxt = pParseCxt,
382,867✔
612
                           .msgBuf.buf = pParseCxt->pMsg,
382,867✔
613
                           .msgBuf.len = pParseCxt->msgLen,
382,867✔
614
                           .code = TSDB_CODE_SUCCESS};
615
  int32_t           code = calcConstQuery(&cxt, pQuery->pRoot, false);
382,867✔
616
  if (TSDB_CODE_SUCCESS == code) {
382,867✔
617
    resetProjectNullType(pQuery->pRoot);
382,850✔
618
    if (isEmptyResultQuery(pQuery->pRoot)) {
382,847✔
619
      pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
344✔
620
    }
621
  }
622
  return code;
382,866✔
623
}
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