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

taosdata / TDengine / #5011

03 Apr 2026 03:59PM UTC coverage: 72.3% (+0.008%) from 72.292%
#5011

push

travis-ci

web-flow
merge: from main to 3.0 branch #35067

4053 of 5985 new or added lines in 68 files covered. (67.72%)

732 existing lines in 143 files now uncovered.

257430 of 356056 relevant lines covered (72.3%)

131834103.52 hits per line

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

80.74
/source/libs/planner/src/planLogicCreater.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 "filter.h"
17
#include "functionMgt.h"
18
#include "parser.h"
19
#include "planInt.h"
20
#include "planner.h"
21
#include "plannodes.h"
22
#include "querynodes.h"
23
#include "systable.h"
24
#include "tglobal.h"
25

26
#include <stdarg.h>
27

28
// primary key column always the second column if exists
29
#define PRIMARY_COLUMN_SLOT 1
30

31
typedef struct SLogicPlanContext {
32
  SPlanContext* pPlanCxt;
33
  SLogicNode*   pCurrRoot;
34
  SSHashObj*    pChildTables;
35
  bool          containsOuterJoin;
36
} SLogicPlanContext;
37

38
typedef int32_t (*FCreateLogicNode)(SLogicPlanContext*, void*, SLogicNode**);
39
typedef int32_t (*FCreateSelectLogicNode)(SLogicPlanContext*, SSelectStmt*, SLogicNode**);
40
typedef int32_t (*FCreateSetOpLogicNode)(SLogicPlanContext*, SSetOperator*, SLogicNode**);
41
typedef int32_t (*FCreateDeleteLogicNode)(SLogicPlanContext*, SDeleteStmt*, SLogicNode**);
42
typedef int32_t (*FCreateInsertLogicNode)(SLogicPlanContext*, SInsertStmt*, SLogicNode**);
43

44
static int32_t doCreateLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable,
45
                                        SLogicNode** pLogicNode);
46
static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogicNode** pLogicNode);
47

48
typedef struct SRewriteExprCxt {
49
  int32_t    errCode;
50
  SNodeList* pExprs;
51
  bool*      pOutputs;
52
  bool       isPartitionBy;
53
  SNode*     pOrderByFirstExpr;  // May be invalid after rewriting, use getOrderByFirstExpr() instead
54
  SSelectStmt* pSelect;  // Used to get the current first order by expr after rewriting
55
} SRewriteExprCxt;
56

57
// Helper function to safely get the first order by expression after rewriting
58
static SNode* getOrderByFirstExpr(SRewriteExprCxt* pCxt) {
399,851,472✔
59
  if (pCxt->pSelect && pCxt->pSelect->pOrderByList && pCxt->pSelect->pOrderByList->length > 0) {
399,851,472✔
60
    SOrderByExprNode* pOrderByExpr = (SOrderByExprNode*)nodesListGetNode(pCxt->pSelect->pOrderByList, 0);
141,273,812✔
61
    if (pOrderByExpr && pOrderByExpr->pExpr) {
141,274,227✔
62
      return pOrderByExpr->pExpr;
141,274,227✔
63
    }
64
  }
65
  return NULL;
258,577,494✔
66
}
67

68
static void setColumnInfo(SFunctionNode* pFunc, SColumnNode* pCol, bool isPartitionBy, SRewriteExprCxt* pCxt) {
399,876,664✔
69
  // Get the current first order by expression (may have been rewritten)
70
  SNode* pOrderByFirstExpr = getOrderByFirstExpr(pCxt);
399,876,664✔
71
  
72
  switch (pFunc->funcType) {
399,872,035✔
73
    case FUNCTION_TYPE_TBNAME:
50,909,511✔
74
      pCol->colType = COLUMN_TYPE_TBNAME;
50,909,511✔
75
      SValueNode* pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 0);
50,909,511✔
76
      if (pVal) {
50,892,328✔
77
        snprintf(pCol->tableName, sizeof(pCol->tableName), "%s", pVal->literal);
1,082,243✔
78
        snprintf(pCol->tableAlias, sizeof(pCol->tableAlias), "%s", pVal->literal);
1,082,243✔
79
      }
80
      break;
50,892,328✔
81
    case FUNCTION_TYPE_WSTART:
6,658,976✔
82
      pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
6,658,976✔
83
      pCol->colType = COLUMN_TYPE_WINDOW_START;
6,658,976✔
84
      break;
6,658,976✔
85
    case FUNCTION_TYPE_WEND:
1,986,888✔
86
      pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
1,986,888✔
87
      pCol->colType = COLUMN_TYPE_WINDOW_END;
1,986,888✔
88
      break;
1,986,888✔
89
    case FUNCTION_TYPE_WDURATION:
459,510✔
90
      pCol->colType = COLUMN_TYPE_WINDOW_DURATION;
459,510✔
91
      break;
459,510✔
92
    case FUNCTION_TYPE_GROUP_KEY:
22,385,636✔
93
      pCol->colType = COLUMN_TYPE_GROUP_KEY;
22,385,636✔
94
      break;
22,385,636✔
95
    case FUNCTION_TYPE_IS_WINDOW_FILLED:
×
96
      pCol->colType = COLUMN_TYPE_IS_WINDOW_FILLED;
×
97
      break;
×
98
    case FUNCTION_TYPE_TPREV_TS:
312,440✔
99
    case FUNCTION_TYPE_TCURRENT_TS:
100
    case FUNCTION_TYPE_TNEXT_TS:
101
    case FUNCTION_TYPE_TWSTART:
102
    case FUNCTION_TYPE_TWEND:
103
    case FUNCTION_TYPE_TPREV_LOCALTIME:
104
    case FUNCTION_TYPE_TNEXT_LOCALTIME:
105
    case FUNCTION_TYPE_TLOCALTIME:
106
    case FUNCTION_TYPE_TIDLESTART:
107
    case FUNCTION_TYPE_TIDLEEND:
108
      pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
312,440✔
109
      pCol->isPrimTs = true;
312,440✔
110
      break;
312,440✔
111
    default:
317,158,288✔
112
      break;
317,158,288✔
113
  }
114
  if (fmIsKeepOrderFunc(pFunc) && isPrimaryKeyImpl((SNode*)pFunc)) {
399,854,066✔
115
    if (!isPartitionBy || (pOrderByFirstExpr && ((SExprNode*)pOrderByFirstExpr)->projIdx == pCol->node.projIdx &&
28,071,377✔
116
                           isPrimaryKeyImpl(pOrderByFirstExpr))) {
1,525,505✔
117
      pCol->isPrimTs = true;
24,168,808✔
118
    }
119
  }
120
}
399,887,068✔
121

122
static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
2,147,483,647✔
123
  SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext;
2,147,483,647✔
124
  switch (nodeType(*pNode)) {
2,147,483,647✔
125
    case QUERY_NODE_COLUMN: {
2,015,122,673✔
126
      if (NULL != pCxt->pOutputs) {
2,015,122,673✔
127
        SNode*  pExpr;
128
        int32_t index = 0;
254,239,319✔
129
        FOREACH(pExpr, pCxt->pExprs) {
321,598,286✔
130
          if (QUERY_NODE_GROUPING_SET == nodeType(pExpr)) {
85,894,622✔
131
            pExpr = nodesListGetNode(((SGroupingSetNode*)pExpr)->pParameterList, 0);
85,628,352✔
132
          }
133
          if (nodesEqualNode(pExpr, *pNode)) {
85,894,648✔
134
            pCxt->pOutputs[index] = true;
18,537,757✔
135
            break;
18,537,757✔
136
          }
137
          index++;
67,358,967✔
138
        }
139
      }
140
      break;
2,015,123,844✔
141
    }
142
    case QUERY_NODE_OPERATOR:
1,579,267,297✔
143
    case QUERY_NODE_LOGIC_CONDITION:
144
    case QUERY_NODE_FUNCTION:
145
    case QUERY_NODE_CASE_WHEN: {
146
      SNode*  pExpr;
147
      int32_t index = 0;
1,579,267,297✔
148
      FOREACH(pExpr, pCxt->pExprs) {
2,147,483,647✔
149
        if (QUERY_NODE_GROUPING_SET == nodeType(pExpr)) {
2,147,483,647✔
150
          pExpr = nodesListGetNode(((SGroupingSetNode*)pExpr)->pParameterList, 0);
60,446,587✔
151
        }
152
        if (nodesEqualNode(pExpr, *pNode)) {
2,147,483,647✔
153
          SColumnNode* pCol = NULL;
405,837,384✔
154
          pCxt->errCode = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
405,837,384✔
155
          if (NULL == pCol) {
405,856,267✔
156
            return DEAL_RES_ERROR;
×
157
          }
158
          SExprNode* pToBeRewrittenExpr = (SExprNode*)(*pNode);
405,856,267✔
159
          pCol->node.resType = pToBeRewrittenExpr->resType;
405,855,026✔
160
          tstrncpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName, TSDB_COL_NAME_LEN);
405,855,570✔
161
          tstrncpy(pCol->node.userAlias, ((SExprNode*)pExpr)->userAlias, TSDB_COL_NAME_LEN);
405,854,429✔
162
          tstrncpy(pCol->colName, ((SExprNode*)pExpr)->aliasName, TSDB_COL_NAME_LEN);
405,855,171✔
163
          pCol->node.projIdx = ((SExprNode*)(*pNode))->projIdx;
405,854,453✔
164
          pCol->node.relatedTo = ((SExprNode*)(*pNode))->relatedTo;
405,856,187✔
165
          if (QUERY_NODE_FUNCTION == nodeType(pExpr)) {
405,854,364✔
166
            setColumnInfo((SFunctionNode*)pExpr, pCol, pCxt->isPartitionBy, pCxt);
399,885,151✔
167
          }
168
          nodesDestroyNode(*pNode);
405,852,678✔
169
          *pNode = (SNode*)pCol;
405,854,954✔
170
          if (NULL != pCxt->pOutputs) {
405,855,356✔
171
            pCxt->pOutputs[index] = true;
22,750,552✔
172
          }
173
          return DEAL_RES_IGNORE_CHILD;
405,854,738✔
174
        }
175
        ++index;
2,000,440,785✔
176
      }
177
      break;
1,173,400,905✔
178
    }
179
    default:
1,614,780,014✔
180
      break;
1,614,780,014✔
181
  }
182

183
  return DEAL_RES_CONTINUE;
2,147,483,647✔
184
}
185

186
static EDealRes doNameExpr(SNode* pNode, void* pContext) {
533,920,267✔
187
  switch (nodeType(pNode)) {
533,920,267✔
188
    case QUERY_NODE_OPERATOR:
345,722,246✔
189
    case QUERY_NODE_LOGIC_CONDITION:
190
    case QUERY_NODE_FUNCTION: {
191
      if ('\0' == ((SExprNode*)pNode)->aliasName[0]) {
345,722,246✔
192
        rewriteExprAliasName((SExprNode*)pNode, (int64_t)pNode);
53,963,601✔
193
      }
194
      return DEAL_RES_IGNORE_CHILD;
345,724,174✔
195
    }
196
    default:
188,199,011✔
197
      break;
188,199,011✔
198
  }
199

200
  return DEAL_RES_CONTINUE;
188,199,011✔
201
}
202

203
static int32_t generatePlanErrMsg(SLogicPlanContext* pCxt, int32_t errCode, const char* pFormat, ...) {
818✔
204
  if (pCxt && pCxt->pPlanCxt && pCxt->pPlanCxt->pMsg && pCxt->pPlanCxt->msgLen > 0 && pFormat) {
818✔
205
    va_list args;
818✔
206
    va_start(args, pFormat);
818✔
207
    (void)vsnprintf(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, pFormat, args);
818✔
208
    va_end(args);
818✔
209
  }
210
  return errCode;
818✔
211
}
212

213
static int32_t rewriteExprForSelect(SNode* pExpr, SSelectStmt* pSelect, ESqlClause clause) {
4,384,252✔
214
  nodesWalkExpr(pExpr, doNameExpr, NULL);
4,384,252✔
215
  bool isPartitionBy = (pSelect->pPartitionByList && pSelect->pPartitionByList->length > 0) ? true : false;
4,385,843✔
216
  SNode*          pOrderByFirstExpr = (pSelect->pOrderByList && pSelect->pOrderByList->length > 0)
1,303,567✔
217
                                          ? ((SOrderByExprNode*)nodesListGetNode(pSelect->pOrderByList, 0))->pExpr
105,697✔
218
                                          : NULL;
4,491,540✔
219
  SRewriteExprCxt cxt = {.errCode = TSDB_CODE_SUCCESS,
4,385,843✔
220
                         .pExprs = NULL,
221
                         .pOutputs = NULL,
222
                         .isPartitionBy = isPartitionBy,
223
                         .pOrderByFirstExpr = pOrderByFirstExpr,
224
                         .pSelect = pSelect};
225
  cxt.errCode = nodesListMakeAppend(&cxt.pExprs, pExpr);
4,385,843✔
226
  if (TSDB_CODE_SUCCESS == cxt.errCode) {
4,385,899✔
227
    nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
4,385,992✔
228
    nodesClearList(cxt.pExprs);
4,386,173✔
229
  }
230
  return cxt.errCode;
4,385,812✔
231
}
232

233
static int32_t cloneRewriteExprs(SNodeList* pExprs, bool* pOutputs, SNodeList** pRewriteExpr) {
118,895,776✔
234
  int32_t code = TSDB_CODE_SUCCESS;
118,895,776✔
235
  int32_t index = 0;
118,895,776✔
236
  SNode*  pExpr = NULL;
118,895,776✔
237
  FOREACH(pExpr, pExprs) {
156,316,582✔
238
    if (pOutputs[index]) {
37,419,203✔
239
      SNode* pNew = NULL;
24,009,413✔
240
      code = nodesCloneNode(pExpr, &pNew);
24,009,413✔
241
      if (TSDB_CODE_SUCCESS == code) {
24,011,016✔
242
        code = nodesListMakeStrictAppend(pRewriteExpr, pNew);
24,011,016✔
243
      }
244
      if (TSDB_CODE_SUCCESS != code) {
24,011,016✔
245
        NODES_DESTORY_LIST(*pRewriteExpr);
×
246
        break;
×
247
      }
248
    }
249
    index++;
37,420,806✔
250
  }
251
  return code;
118,897,418✔
252
}
253

254
static int32_t rewriteExprsForSelect(SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause,
699,317,007✔
255
                                     SNodeList** pRewriteExprs) {
256
  nodesWalkExprs(pExprs, doNameExpr, NULL);
699,317,007✔
257
  bool isPartitionBy = (pSelect->pPartitionByList && pSelect->pPartitionByList->length > 0) ? true : false;
699,378,019✔
258
  SNode*     pOrderByFirstExpr =
699,380,638✔
259
      (pSelect->pOrderByList && pSelect->pOrderByList->length > 0)
530,752,070✔
260
          ? ((SOrderByExprNode*)nodesListGetNode(pSelect->pOrderByList, 0))->pExpr : NULL;
831,243,202✔
261

262
  SRewriteExprCxt cxt = {.errCode = TSDB_CODE_SUCCESS,
699,380,638✔
263
                         .pExprs = pExprs,
264
                         .pOutputs = NULL,
265
                         .isPartitionBy = isPartitionBy,
266
                         .pOrderByFirstExpr = pOrderByFirstExpr,
267
                         .pSelect = pSelect};
268
  if (NULL != pRewriteExprs) {
699,380,813✔
269
    cxt.pOutputs = taosMemoryCalloc(LIST_LENGTH(pExprs), sizeof(bool));
118,911,032✔
270
    if (NULL == cxt.pOutputs) {
118,909,403✔
271
      return terrno;
×
272
    }
273
  }
274
  nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt);
699,379,184✔
275
  if (TSDB_CODE_SUCCESS == cxt.errCode && NULL != pRewriteExprs) {
699,375,056✔
276
    cxt.errCode = cloneRewriteExprs(pExprs, cxt.pOutputs, pRewriteExprs);
118,913,505✔
277
  }
278
  taosMemoryFree(cxt.pOutputs);
699,360,684✔
279
  return cxt.errCode;
699,396,587✔
280
}
281

282
static int32_t rewriteExpr(SNodeList* pExprs, SNode** pTarget) {
4,409,370✔
283
  nodesWalkExprs(pExprs, doNameExpr, NULL);
4,409,370✔
284
  SRewriteExprCxt cxt = {.errCode = TSDB_CODE_SUCCESS,
4,409,370✔
285
                         .pExprs = pExprs,
286
                         .pOutputs = NULL,
287
                         .isPartitionBy = false,
288
                         .pOrderByFirstExpr = NULL,
289
                         .pSelect = NULL};
290
  nodesRewriteExpr(pTarget, doRewriteExpr, &cxt);
4,409,370✔
291
  return cxt.errCode;
4,409,370✔
292
}
293

294
static int32_t rewriteExprs(SNodeList* pExprs, SNodeList* pTarget) {
12,782,560✔
295
  nodesWalkExprs(pExprs, doNameExpr, NULL);
12,782,560✔
296
  SRewriteExprCxt cxt = {.errCode = TSDB_CODE_SUCCESS,
12,784,163✔
297
                         .pExprs = pExprs,
298
                         .pOutputs = NULL,
299
                         .isPartitionBy = false,
300
                         .pOrderByFirstExpr = NULL,
301
                         .pSelect = NULL};
302
  nodesRewriteExprs(pTarget, doRewriteExpr, &cxt);
12,784,163✔
303
  return cxt.errCode;
12,782,532✔
304
}
305

306
static int32_t pushLogicNode(SLogicPlanContext* pCxt, SLogicNode** pOldRoot, SLogicNode* pNewRoot) {
753,016,869✔
307
  if (NULL == pNewRoot->pChildren) {
753,016,869✔
308
    int32_t code = nodesMakeList(&pNewRoot->pChildren);
753,038,682✔
309
    if (NULL == pNewRoot->pChildren) {
753,067,675✔
310
      return code;
×
311
    }
312
  }
313
  if (TSDB_CODE_SUCCESS != nodesListAppend(pNewRoot->pChildren, (SNode*)*pOldRoot)) {
753,046,645✔
314
    return TSDB_CODE_OUT_OF_MEMORY;
×
315
  }
316

317
  (*pOldRoot)->pParent = pNewRoot;
753,073,723✔
318
  *pOldRoot = pNewRoot;
753,072,604✔
319

320
  return TSDB_CODE_SUCCESS;
753,072,565✔
321
}
322

323
static int32_t createRootLogicNode(SLogicPlanContext* pCxt, void* pStmt, uint8_t precision, FCreateLogicNode func,
2,147,483,647✔
324
                                   SLogicNode** pRoot) {
325
  SLogicNode* pNode = NULL;
2,147,483,647✔
326
  int32_t     code = func(pCxt, pStmt, &pNode);
2,147,483,647✔
327
  if (TSDB_CODE_SUCCESS == code && NULL != pNode) {
2,147,483,647✔
328
    pNode->precision = precision;
753,054,868✔
329
    code = pushLogicNode(pCxt, pRoot, pNode);
753,055,091✔
330
    pCxt->pCurrRoot = pNode;
753,072,397✔
331
  }
332
  if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
333
    nodesDestroyNode((SNode*)pNode);
×
334
  }
335
  return code;
2,147,483,647✔
336
}
337

338
static int32_t createSelectRootLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, FCreateSelectLogicNode func,
2,147,483,647✔
339
                                         SLogicNode** pRoot) {
340
  return createRootLogicNode(pCxt, pSelect, pSelect->precision, (FCreateLogicNode)func, pRoot);
2,147,483,647✔
341
}
342

343
static EScanType getScanType(SLogicPlanContext* pCxt, SNodeList* pScanPseudoCols, SNodeList* pScanCols,
426,298,895✔
344
                             int8_t tableType, bool tagScan) {
345
  if (pCxt->pPlanCxt->topicQuery) {
426,298,895✔
346
    return SCAN_TYPE_STREAM;
102,979✔
347
  }
348

349
  if (TSDB_SYSTEM_TABLE == tableType) {
426,197,353✔
350
    return SCAN_TYPE_SYSTEM_TABLE;
11,709,386✔
351
  }
352

353
  if (tagScan && 0 == LIST_LENGTH(pScanCols) && 0 != LIST_LENGTH(pScanPseudoCols)) {
414,487,967✔
354
    return SCAN_TYPE_TAG;
24,577✔
355
  }
356

357
  if (NULL == pScanCols) {
414,463,390✔
358
    if (NULL == pScanPseudoCols) {
60,568,710✔
359
      return (!tagScan) ? SCAN_TYPE_TABLE : SCAN_TYPE_TAG;
54,282,025✔
360
    }
361
    return FUNCTION_TYPE_BLOCK_DIST_INFO == ((SFunctionNode*)nodesListGetNode(pScanPseudoCols, 0))->funcType
6,286,685✔
362
               ? SCAN_TYPE_BLOCK_INFO
363
               : SCAN_TYPE_TABLE;
6,291,794✔
364
  }
365

366
  return SCAN_TYPE_TABLE;
353,894,680✔
367
}
368

369
static bool hasPkInTable(const STableMeta* pTableMeta) {
667,254,767✔
370
  return pTableMeta->tableInfo.numOfColumns >= 2 && pTableMeta->schema[1].flags & COL_IS_KEY;
667,254,767✔
371
}
372

373
static SNode* createFirstCol(SRealTableNode* pTable, const SSchema* pSchema) {
251,184,898✔
374
  SColumnNode* pCol = NULL;
251,184,898✔
375
  terrno = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
251,184,898✔
376
  if (NULL == pCol) {
251,218,819✔
377
    return NULL;
×
378
  }
379
  pCol->node.resType.type = pSchema->type;
251,218,819✔
380
  pCol->node.resType.bytes = pSchema->bytes;
251,218,819✔
381
  pCol->tableId = pTable->pMeta->uid;
251,218,819✔
382
  pCol->colId = pSchema->colId;
251,218,819✔
383
  pCol->colType = COLUMN_TYPE_COLUMN;
251,218,819✔
384
  tstrncpy(pCol->tableAlias, pTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
251,218,819✔
385
  tstrncpy(pCol->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
251,218,819✔
386
  pCol->isPk = pSchema->flags & COL_IS_KEY;
251,218,819✔
387
  pCol->tableHasPk = hasPkInTable(pTable->pMeta);
251,218,819✔
388
  pCol->numOfPKs = pTable->pMeta->tableInfo.numOfPKs;
251,220,664✔
389
  tstrncpy(pCol->colName, pSchema->name, TSDB_COL_NAME_LEN);
251,220,664✔
390
  return (SNode*)pCol;
251,220,664✔
391
}
392

393
static SNode* createInsColsScanCol(SRealTableNode* pTable, const SSchema* pSchema) {
33,068,624✔
394
  SColumnNode* pCol = NULL;
33,068,624✔
395
  terrno = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
33,068,624✔
396
  if (NULL == pCol) {
33,068,624✔
397
    return NULL;
×
398
  }
399
  pCol->node.resType.type = pSchema->type;
33,068,624✔
400
  pCol->node.resType.bytes = pSchema->bytes;
33,068,624✔
401
  pCol->tableId = pTable->pMeta->uid;
33,068,624✔
402
  pCol->colId = pSchema->colId;
33,068,624✔
403
  pCol->colType = COLUMN_TYPE_COLUMN;
33,068,624✔
404
  tstrncpy(pCol->tableAlias, pTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
33,068,624✔
405
  tstrncpy(pCol->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
33,068,624✔
406
  tstrncpy(pCol->colName, pSchema->name, TSDB_COL_NAME_LEN);
33,068,624✔
407
  return (SNode*)pCol;
33,068,624✔
408
}
409

410
static SNode* createVtbFirstCol(SVirtualTableNode* pTable, const SSchema* pSchema) {
1,223,938✔
411
  SColumnNode* pCol = NULL;
1,223,938✔
412
  terrno = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
1,223,938✔
413
  if (NULL == pCol) {
1,223,938✔
414
    return NULL;
×
415
  }
416
  pCol->node.resType.type = pSchema->type;
1,223,938✔
417
  pCol->node.resType.bytes = pSchema->bytes;
1,223,938✔
418
  pCol->tableId = pTable->pMeta->uid;
1,223,938✔
419
  pCol->colId = pSchema->colId;
1,223,938✔
420
  pCol->colType = COLUMN_TYPE_COLUMN;
1,223,938✔
421
  tstrncpy(pCol->tableAlias, pTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
1,223,938✔
422
  tstrncpy(pCol->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
1,223,938✔
423
  pCol->isPk = pSchema->flags & COL_IS_KEY;
1,223,938✔
424
  pCol->tableHasPk = false;
1,223,938✔
425
  pCol->numOfPKs = 0;
1,223,938✔
426
  pCol->isPrimTs = true;
1,223,938✔
427
  tstrncpy(pCol->colName, pSchema->name, TSDB_COL_NAME_LEN);
1,223,938✔
428
  return (SNode*)pCol;
1,223,938✔
429
}
430

431
static int32_t addVtbPrimaryTsCol(SVirtualTableNode* pTable, SNodeList** pCols) {
4,133,578✔
432
  bool     found = false;
4,133,578✔
433
  SNode*   pCol = NULL;
4,133,578✔
434
  SSchema* pSchema = &pTable->pMeta->schema[0];
4,133,578✔
435
  FOREACH(pCol, *pCols) {
10,413,841✔
436
    if (pSchema->colId == ((SColumnNode*)pCol)->colId) {
9,189,903✔
437
      found = true;
2,909,640✔
438
      break;
2,909,640✔
439
    }
440
  }
441

442
  if (!found) {
4,133,578✔
443
    return nodesListMakeStrictAppend(pCols, createVtbFirstCol(pTable, pSchema));
1,223,938✔
444
  }
445
  return TSDB_CODE_SUCCESS;
2,909,640✔
446
}
447

448
static int32_t addInsColumnScanCol(SRealTableNode* pTable, SNodeList** pCols) {
4,133,578✔
449
  for (int32_t i = 1; i <= 8; i++) {
37,202,202✔
450
    PLAN_ERR_RET(nodesListMakeStrictAppend(pCols, createInsColsScanCol(pTable, &pTable->pMeta->schema[i])));
33,068,624✔
451
  }
452
  return TSDB_CODE_SUCCESS;
4,133,578✔
453
}
454

455
static int32_t addPrimaryTsCol(SRealTableNode* pTable, SNodeList** pCols) {
414,566,752✔
456
  bool   found = false;
414,566,752✔
457
  SNode* pCol = NULL;
414,566,752✔
458
  FOREACH(pCol, *pCols) {
687,356,683✔
459
    if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pCol)->colId) {
441,716,039✔
460
      found = true;
168,926,757✔
461
      break;
168,926,757✔
462
    }
463
  }
464

465
  if (!found) {
414,566,802✔
466
    return nodesListMakeStrictAppend(pCols, createFirstCol(pTable, pTable->pMeta->schema));
245,682,122✔
467
  }
468
  return TSDB_CODE_SUCCESS;
168,884,680✔
469
}
470

471
static int32_t addSystableFirstCol(SRealTableNode* pTable, SNodeList** pCols) {
11,709,349✔
472
  if (LIST_LENGTH(*pCols) > 0) {
11,709,349✔
473
    return TSDB_CODE_SUCCESS;
7,571,118✔
474
  }
475
  return nodesListMakeStrictAppend(pCols, createFirstCol(pTable, pTable->pMeta->schema));
4,138,231✔
476
}
477

478
static int32_t addPrimaryKeyCol(SRealTableNode* pTable, SNodeList** pCols) {
9,743,926✔
479
  bool     found = false;
9,743,926✔
480
  SNode*   pCol = NULL;
9,743,926✔
481
  SSchema* pSchema = &pTable->pMeta->schema[PRIMARY_COLUMN_SLOT];
9,743,926✔
482
  FOREACH(pCol, *pCols) {
18,163,081✔
483
    if (pSchema->colId == ((SColumnNode*)pCol)->colId) {
16,777,218✔
484
      found = true;
8,358,063✔
485
      break;
8,358,063✔
486
    }
487
  }
488

489
  if (!found) {
9,743,926✔
490
    return nodesListMakeStrictAppend(pCols, createFirstCol(pTable, pSchema));
1,385,863✔
491
  }
492
  return TSDB_CODE_SUCCESS;
8,358,063✔
493
}
494

495
static int32_t addDefaultScanCol(SRealTableNode* pTable, SNodeList** pCols) {
426,332,450✔
496
  if (TSDB_SYSTEM_TABLE == pTable->pMeta->tableType) {
426,332,450✔
497
    return addSystableFirstCol(pTable, pCols);
11,709,347✔
498
  }
499
  int32_t code = addPrimaryTsCol(pTable, pCols);
414,624,069✔
500
  if (code == TSDB_CODE_SUCCESS && hasPkInTable(pTable->pMeta)) {
414,638,862✔
501
    code = addPrimaryKeyCol(pTable, pCols);
9,696,156✔
502
  }
503
  return code;
414,641,201✔
504
}
505

506
static int32_t makeScanLogicNode(SLogicPlanContext* pCxt, SRealTableNode* pRealTable, bool hasRepeatScanFuncs,
427,724,866✔
507
                                 SLogicNode** pLogicNode) {
508
  SScanLogicNode* pScan = NULL;
427,724,866✔
509
  int32_t         code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN, (SNode**)&pScan);
427,726,184✔
510
  if (NULL == pScan) {
427,795,618✔
511
    return code;
×
512
  }
513

514
  TSWAP(pScan->pVgroupList, pRealTable->pVgroupList);
427,795,618✔
515
  TSWAP(pScan->pSmaIndexes, pRealTable->pSmaIndexes);
427,791,664✔
516
  TSWAP(pScan->pTsmas, pRealTable->pTsmas);
427,795,964✔
517
  TSWAP(pScan->pTsmaTargetTbVgInfo, pRealTable->tsmaTargetTbVgInfo);
427,795,311✔
518
  TSWAP(pScan->pTsmaTargetTbInfo, pRealTable->tsmaTargetTbInfo);
427,793,172✔
519
  pScan->tableId = pRealTable->pMeta->uid;
427,791,987✔
520
  pScan->stableId = pRealTable->pMeta->suid;
427,792,830✔
521
  pScan->tableType = pRealTable->pMeta->tableType;
427,793,933✔
522
  pScan->scanSeq[0] = hasRepeatScanFuncs ? 2 : 1;
427,790,149✔
523
  pScan->scanSeq[1] = 0;
427,793,629✔
524
  TAOS_SET_OBJ_ALIGNED(&pScan->scanRange, TSWINDOW_INITIALIZER);
427,793,866✔
525
  pScan->tableName.type = TSDB_TABLE_NAME_T;
427,790,438✔
526
  pScan->tableName.acctId = pCxt->pPlanCxt->acctId;
427,795,048✔
527
  tstrncpy(pScan->tableName.dbname, pRealTable->table.dbName, TSDB_DB_NAME_LEN);
427,790,402✔
528
  tstrncpy(pScan->tableName.tname, pRealTable->table.tableName, TSDB_TABLE_NAME_LEN);
427,793,361✔
529
  pScan->showRewrite = pCxt->pPlanCxt->showRewrite;
427,793,508✔
530
  pScan->ratio = pRealTable->ratio;
427,792,978✔
531
  pScan->dataRequired = FUNC_DATA_REQUIRED_DATA_LOAD;
427,793,101✔
532
  pScan->cacheLastMode = pRealTable->cacheLastMode;
427,790,230✔
533

534
  *pLogicNode = (SLogicNode*)pScan;
427,789,931✔
535

536
  return TSDB_CODE_SUCCESS;
427,794,589✔
537
}
538

539
static bool needScanDefaultCol(EScanType scanType) { return SCAN_TYPE_TABLE_COUNT != scanType; }
413,424,061✔
540

541
static int32_t updateScanNoPseudoRefAfterGrp(SSelectStmt* pSelect, SScanLogicNode* pScan, SRealTableNode* pRealTable) {
413,434,005✔
542
  if (NULL == pScan->pScanPseudoCols || pScan->pScanPseudoCols->length <= 0) {
413,434,005✔
543
    return TSDB_CODE_SUCCESS;
364,292,801✔
544
  }
545

546
  SNodeList* pList = NULL;
49,141,201✔
547
  int32_t code = 0;
49,141,201✔
548
  if (NULL == pSelect->pPartitionByList || pSelect->pPartitionByList->length <= 0) {
49,141,201✔
549
    if (NULL == pSelect->pGroupByList || pSelect->pGroupByList->length <= 0) {
30,552,773✔
550
      return TSDB_CODE_SUCCESS;
19,929,438✔
551
    }
552

553
    code = nodesCollectColumns(pSelect, SQL_CLAUSE_GROUP_BY, pRealTable->table.tableAlias, COLLECT_COL_TYPE_TAG,
10,623,335✔
554
                               &pList);
555
    if (TSDB_CODE_SUCCESS == code) {
10,623,335✔
556
      code = nodesCollectFuncs(pSelect, SQL_CLAUSE_GROUP_BY, pRealTable->table.tableAlias, fmIsScanPseudoColumnFunc,
10,623,335✔
557
                               &pList);
558
    }
559
    if (TSDB_CODE_SUCCESS == code && (NULL == pList || pList->length <= 0)) {
10,623,335✔
560
      pScan->noPseudoRefAfterGrp = true;
3,066,339✔
561
    }    
562
    goto _return;    
10,623,335✔
563
  }
564

565
  code = nodesCollectColumns(pSelect, SQL_CLAUSE_PARTITION_BY, pRealTable->table.tableAlias, COLLECT_COL_TYPE_TAG,
18,588,428✔
566
                             &pList);
567
  if (TSDB_CODE_SUCCESS == code) {
18,590,322✔
568
    code = nodesCollectFuncs(pSelect, SQL_CLAUSE_PARTITION_BY, pRealTable->table.tableAlias, fmIsScanPseudoColumnFunc,
18,590,415✔
569
                             &pList);
570
  }
571
  
572
  if (TSDB_CODE_SUCCESS == code && (NULL == pList || pList->length <= 0)) {
18,590,776✔
573
    pScan->noPseudoRefAfterGrp = true;
10,337,908✔
574
  }    
575

576
_return:
23,634,253✔
577

578
  nodesDestroyList(pList);
29,214,111✔
579
  return code;
29,213,928✔
580
}
581

582
bool hasExternalWindowDerivedFromSubquery(SSelectStmt* pSelect);
583

584
static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable,
413,360,662✔
585
                                   SLogicNode** pLogicNode) {
586
  SScanLogicNode* pScan = NULL;
413,360,662✔
587
  int32_t         code = makeScanLogicNode(pCxt, pRealTable, pSelect->hasRepeatScanFuncs, (SLogicNode**)&pScan);
413,362,529✔
588

589
  pScan->placeholderType = pRealTable->placeholderType;
413,411,108✔
590
  pScan->phTbnameScan = (pRealTable->pMeta->tableType == TSDB_SUPER_TABLE && pRealTable->placeholderType == SP_PARTITION_TBNAME);
413,417,522✔
591
  pScan->node.groupAction = GROUP_ACTION_NONE;
413,418,869✔
592
  pScan->node.resultDataOrder = (pRealTable->pMeta->tableType == TSDB_SUPER_TABLE) ? DATA_ORDER_LEVEL_IN_BLOCK : DATA_ORDER_LEVEL_GLOBAL;
413,417,182✔
593

594
  if (TSDB_CODE_SUCCESS == code) {
413,419,535✔
595
    code = nodesCloneNode(pSelect->pTimeRange, (SNode**)&pScan->pTimeRange);
413,406,093✔
596
  }
597

598
  if (pRealTable->placeholderType == SP_PARTITION_ROWS) {
413,430,843✔
599
    code = nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, COLLECT_COL_TYPE_ALL,
115,669✔
600
                               &pCxt->pPlanCxt->streamCxt.triggerScanList);
115,669✔
601
  }
602
  // set columns to scan
603
  if (TSDB_CODE_SUCCESS == code) {
413,431,211✔
604
    code = nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, COLLECT_COL_TYPE_COL,
413,434,815✔
605
                               &pScan->pScanCols);
413,433,756✔
606
  }
607

608
  if (TSDB_CODE_SUCCESS == code) {
413,449,865✔
609
    code = nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, COLLECT_COL_TYPE_TAG,
413,458,416✔
610
                               &pScan->pScanPseudoCols);
413,457,356✔
611
  }
612

613
  if (TSDB_CODE_SUCCESS == code) {
413,440,060✔
614
    code = nodesCollectFuncs(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, fmIsScanPseudoColumnFunc,
413,451,198✔
615
                             &pScan->pScanPseudoCols);
413,451,622✔
616
  }
617

618
  if (TSDB_CODE_SUCCESS == code) {
413,441,707✔
619
    code = updateScanNoPseudoRefAfterGrp(pSelect, pScan, pRealTable);
413,454,698✔
620
  }
621

622
  if (TSDB_CODE_SUCCESS == code) {
413,436,544✔
623
    pScan->scanType = getScanType(pCxt, pScan->pScanPseudoCols, pScan->pScanCols, pScan->tableType, pSelect->tagScan);
413,452,702✔
624
    if (pScan->scanType == SCAN_TYPE_SYSTEM_TABLE) {
413,417,247✔
625
      SET_SYS_SCAN_FLAG(pCxt->pPlanCxt->sysScanFlag);
11,709,347✔
626

627
      if (strcmp(tNameGetTableName(&pScan->tableName), TSDB_INS_TABLE_DATABASES) == 0 ||
11,709,308✔
628
          strcmp(tNameGetTableName(&pScan->tableName), TSDB_INS_TABLE_LICENCES) == 0 ||
11,194,956✔
629
          strcmp(tNameGetTableName(&pScan->tableName), TSDB_PERFS_TABLE_QUERIES) == 0) {
11,226,264✔
630
        SET_HSYS_SCAN_FLAG(pCxt->pPlanCxt->sysScanFlag);
522,156✔
631
      }
632
    }
633

634
    pCxt->pPlanCxt->hasScan = true;
413,381,969✔
635
  }
636

637
  // rewrite the expression in subsequent clauses
638
  if (TSDB_CODE_SUCCESS == code) {
413,366,248✔
639
    code = rewriteExprsForSelect(pScan->pScanPseudoCols, pSelect, SQL_CLAUSE_FROM, NULL);
413,410,999✔
640
    /*
641
        if (TSDB_CODE_SUCCESS == code && NULL != pScan->pScanPseudoCols) {
642
          code = createColumnByRewriteExprs(pScan->pScanPseudoCols, &pNewScanPseudoCols);
643
          if (TSDB_CODE_SUCCESS == code) {
644
            nodesDestroyList(pScan->pScanPseudoCols);
645
            pScan->pScanPseudoCols = pNewScanPseudoCols;
646
          }
647
        }
648
    */
649
  }
650

651
  if (NULL != pScan->pScanCols) {
413,403,842✔
652
    pScan->hasNormalCols = true;
348,678,477✔
653
  }
654

655
  if (TSDB_CODE_SUCCESS == code && needScanDefaultCol(pScan->scanType)) {
413,404,168✔
656
    code = addDefaultScanCol(pRealTable, &pScan->pScanCols);
413,438,691✔
657
  }
658

659
  // set output
660
  if (TSDB_CODE_SUCCESS == code) {
413,422,691✔
661
    code = createColumnByRewriteExprs(pScan->pScanCols, &pScan->node.pTargets);
413,458,148✔
662
  }
663
  if (TSDB_CODE_SUCCESS == code) {
413,425,728✔
664
    code = createColumnByRewriteExprs(pScan->pScanPseudoCols, &pScan->node.pTargets);
413,461,716✔
665
  }
666

667
  if (pScan->scanType == SCAN_TYPE_TAG) {
413,401,651✔
668
    code = tagScanSetExecutionMode(pScan);
5,942,563✔
669
  }
670

671
  bool isCountByTag = false;
413,418,373✔
672
  if (pSelect->hasCountFunc && NULL == pSelect->pWindow) {
413,418,373✔
673
    if (pSelect->pGroupByList) {
26,315,580✔
674
      isCountByTag = !keysHasCol(pSelect->pGroupByList);
8,327,359✔
675
    } else if (pSelect->pPartitionByList) {
17,988,041✔
676
      isCountByTag = !keysHasCol(pSelect->pPartitionByList);
5,477,713✔
677
    }
678
    if (pScan->tableType == TSDB_CHILD_TABLE) {
26,315,702✔
679
      isCountByTag = true;
6,098,781✔
680
    }
681
  }
682
  pScan->isCountByTag = isCountByTag;
413,417,551✔
683

684
  if (TSDB_CODE_SUCCESS == code) {
413,418,465✔
685
    *pLogicNode = (SLogicNode*)pScan;
413,418,465✔
686
    pScan->paraTablesSort = getParaTablesSortOptHint(pSelect->pHint);
413,418,411✔
687
    pScan->smallDataTsSort = getSmallDataTsSortOptHint(pSelect->pHint);
413,407,355✔
688
    // pCxt->hasScan = true;
689
  } else {
690
    nodesDestroyNode((SNode*)pScan);
×
691
  }
692

693
  pScan->virtualStableScan = false;
413,416,177✔
694
  return code;
413,414,418✔
695
}
696

697
static int32_t createRefScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable,
12,895,748✔
698
                                      SLogicNode** pLogicNode) {
699
  SScanLogicNode* pScan = NULL;
12,895,748✔
700
  int32_t         code = TSDB_CODE_SUCCESS;
12,895,748✔
701

702
  PLAN_ERR_RET(makeScanLogicNode(pCxt, pRealTable, pSelect->hasRepeatScanFuncs, (SLogicNode**)&pScan));
12,895,748✔
703
  pScan->node.groupAction = GROUP_ACTION_NONE;
12,895,748✔
704
  pScan->node.resultDataOrder = DATA_ORDER_LEVEL_GLOBAL;
12,895,748✔
705

706
  PLAN_ERR_RET(addDefaultScanCol(pRealTable, &pScan->pScanCols));
12,895,748✔
707

708
  pScan->scanType = getScanType(pCxt, pScan->pScanPseudoCols, pScan->pScanCols, pScan->tableType, pSelect->tagScan);
12,895,748✔
709

710
  PLAN_ERR_RET(nodesCloneNode(pSelect->pTimeRange, (SNode**)&pScan->pTimeRange));
12,895,748✔
711

712
  SNode *pTsCol = nodesListGetNode(pScan->pScanCols, 0);
12,895,748✔
713
  ((SColumnNode*)pTsCol)->hasDep = true;
12,895,748✔
714
  tstrncpy(((SColumnNode*)pTsCol)->dbName, pRealTable->table.dbName, TSDB_DB_NAME_LEN);
12,895,748✔
715
  *pLogicNode = (SLogicNode*)pScan;
12,895,748✔
716
  // pCxt->hasScan = true;
717

718
  return code;
12,895,748✔
719
}
720

721
static int32_t createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable,
55,869,349✔
722
                                       SLogicNode** pLogicNode) {
723
  return createQueryLogicNode(pCxt, pTable->pSubquery, pLogicNode);
55,869,349✔
724
}
725

726
int32_t collectJoinResColumns(SSelectStmt* pSelect, SJoinLogicNode* pJoin, SNodeList** pCols) {
23,290,696✔
727
  SSHashObj* pTables = NULL;
23,290,696✔
728
  int32_t    code = collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 0), &pTables);
23,290,696✔
729
  if (TSDB_CODE_SUCCESS != code) {
23,291,062✔
730
    return code;
×
731
  }
732
  code = collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 1), &pTables);
23,291,062✔
733
  if (TSDB_CODE_SUCCESS != code) {
23,292,600✔
734
    tSimpleHashCleanup(pTables);
×
735
    return code;
×
736
  } else {
737
    code = nodesCollectColumnsExt(pSelect, SQL_CLAUSE_WHERE, pTables, COLLECT_COL_TYPE_ALL, pCols);
23,292,600✔
738
  }
739

740
  tSimpleHashCleanup(pTables);
23,292,798✔
741

742
  return code;
23,292,903✔
743
}
744

745
static int32_t createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SJoinTableNode* pJoinTable,
23,290,355✔
746
                                   SLogicNode** pLogicNode) {
747
  int32_t         code = TSDB_CODE_SUCCESS;
23,290,355✔
748
  SJoinLogicNode* pJoin = NULL;
23,290,355✔
749
  code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_JOIN, (SNode**)&pJoin);
23,290,355✔
750
  if (NULL == pJoin) {
23,291,641✔
751
    return code;
×
752
  }
753

754
  pJoin->joinType = pJoinTable->joinType;
23,291,641✔
755
  pJoin->subType = pJoinTable->subType;
23,291,641✔
756
  pJoin->joinAlgo = JOIN_ALGO_UNKNOWN;
23,291,641✔
757
  pJoin->isSingleTableJoin = pJoinTable->table.singleTable;
23,291,641✔
758
  pJoin->hasSubQuery = pJoinTable->hasSubQuery;
23,291,641✔
759
  pJoin->node.inputTsOrder = ORDER_ASC;
23,291,641✔
760
  pJoin->node.groupAction = GROUP_ACTION_CLEAR;
23,291,641✔
761
  pJoin->hashJoinHint = getHashJoinOptHint(pSelect->pHint);
23,291,641✔
762
  pJoin->batchScanHint = getBatchScanOptionFromHint(pSelect->pHint);
23,290,768✔
763
  pJoin->node.requireDataOrder = (pJoin->hashJoinHint || pJoinTable->leftNoOrderedSubQuery || pJoinTable->rightNoOrderedSubQuery) ? DATA_ORDER_LEVEL_NONE : DATA_ORDER_LEVEL_GLOBAL;
23,291,360✔
764
  pJoin->node.resultDataOrder = DATA_ORDER_LEVEL_NONE;
23,291,360✔
765
  pJoin->isLowLevelJoin = pJoinTable->isLowLevelJoin;
23,291,360✔
766
  pJoin->leftNoOrderedSubQuery = pJoinTable->leftNoOrderedSubQuery;
23,291,360✔
767
  pJoin->rightNoOrderedSubQuery = pJoinTable->rightNoOrderedSubQuery;
23,291,360✔
768
  
769
  code = nodesCloneNode(pJoinTable->pWindowOffset, &pJoin->pWindowOffset);
23,291,360✔
770
  if (TSDB_CODE_SUCCESS == code) {
23,290,329✔
771
    code = nodesCloneNode(pJoinTable->pJLimit, &pJoin->pJLimit);
23,291,130✔
772
  }
773
  if (TSDB_CODE_SUCCESS == code) {
23,290,831✔
774
    code = nodesCloneNode(pJoinTable->addPrimCond, &pJoin->addPrimEqCond);
23,292,165✔
775
  }
776
  if (TSDB_CODE_SUCCESS == code) {
23,291,253✔
777
    code = nodesMakeList(&pJoin->node.pChildren);
23,292,501✔
778
  }
779
  pJoin->seqWinGroup =
23,291,050✔
780
      (JOIN_STYPE_WIN == pJoinTable->subType) && (pSelect->hasAggFuncs || pSelect->hasIndefiniteRowsFunc);
23,291,050✔
781

782
  SLogicNode* pLeft = NULL;
23,291,050✔
783
  if (TSDB_CODE_SUCCESS == code) {
23,291,050✔
784
    code = doCreateLogicNodeByTable(pCxt, pSelect, pJoinTable->pLeft, &pLeft);
23,292,343✔
785
    if (TSDB_CODE_SUCCESS == code) {
23,290,812✔
786
      code = nodesListStrictAppend(pJoin->node.pChildren, (SNode*)pLeft);
23,291,122✔
787
    }
788
    if (TSDB_CODE_SUCCESS != code) {
23,292,492✔
789
      pLeft = NULL;
×
790
    }
791
  }
792

793
  SLogicNode* pRight = NULL;
23,291,199✔
794
  if (TSDB_CODE_SUCCESS == code) {
23,291,199✔
795
    code = doCreateLogicNodeByTable(pCxt, pSelect, pJoinTable->pRight, &pRight);
23,292,802✔
796
    if (TSDB_CODE_SUCCESS == code) {
23,291,240✔
797
      code = nodesListStrictAppend(pJoin->node.pChildren, (SNode*)pRight);
23,291,749✔
798
    }
799
  }
800

801
  // set on conditions
802
  if (TSDB_CODE_SUCCESS == code && NULL != pJoinTable->pOnCond) {
23,290,842✔
803
    code = nodesCloneNode(pJoinTable->pOnCond, &pJoin->pFullOnCond);
22,954,495✔
804
  }
805

806
#if 0
807
  // set the output
808
  if (TSDB_CODE_SUCCESS == code) {
809
    SNodeList* pColList = NULL;
810
//    if (QUERY_NODE_REAL_TABLE == nodeType(pJoinTable->pLeft) && !pJoin->isLowLevelJoin) {
811
    if (QUERY_NODE_REAL_TABLE == nodeType(pJoinTable->pLeft)) {
812
      code = nodesCollectColumns(pSelect, SQL_CLAUSE_WHERE, ((SRealTableNode*)pJoinTable->pLeft)->table.tableAlias, COLLECT_COL_TYPE_ALL, &pColList);
813
    } else {
814
      pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
815
      if (NULL == pJoin->node.pTargets) {
816
        code = TSDB_CODE_OUT_OF_MEMORY;
817
      }
818
    }
819
    if (TSDB_CODE_SUCCESS == code && NULL != pColList) {
820
      code = createColumnByRewriteExprs(pColList, &pJoin->node.pTargets);
821
    }
822
    nodesDestroyList(pColList);
823
  }
824

825
  if (TSDB_CODE_SUCCESS == code) {
826
    SNodeList* pColList = NULL;
827
//    if (QUERY_NODE_REAL_TABLE == nodeType(pJoinTable->pRight) && !pJoin->isLowLevelJoin) {
828
    if (QUERY_NODE_REAL_TABLE == nodeType(pJoinTable->pRight)) {
829
      code = nodesCollectColumns(pSelect, SQL_CLAUSE_WHERE, ((SRealTableNode*)pJoinTable->pRight)->table.tableAlias, COLLECT_COL_TYPE_ALL, &pColList);
830
    } else {
831
      if (pJoin->node.pTargets) {
832
        nodesListStrictAppendList(pJoin->node.pTargets, nodesCloneList(pRight->pTargets));
833
      } else {
834
        pJoin->node.pTargets = nodesCloneList(pRight->pTargets);
835
        if (NULL == pJoin->node.pTargets) {
836
          code = TSDB_CODE_OUT_OF_MEMORY;
837
        }
838
      }
839
    }
840
    if (TSDB_CODE_SUCCESS == code && NULL != pColList) {
841
      code = createColumnByRewriteExprs(pColList, &pJoin->node.pTargets);
842
    }
843
    nodesDestroyList(pColList);
844
  }
845

846
  if (NULL == pJoin->node.pTargets && NULL != pLeft) {
847
    pJoin->node.pTargets = nodesCloneList(pLeft->pTargets);
848
    if (NULL == pJoin->node.pTargets) {
849
      code = TSDB_CODE_OUT_OF_MEMORY;
850
    }
851
  }
852

853
#else
854
  // set the output
855
  if (TSDB_CODE_SUCCESS == code) {
23,290,575✔
856
    SNodeList* pColList = NULL;
23,292,867✔
857
    code = collectJoinResColumns(pSelect, pJoin, &pColList);
23,292,867✔
858
    if (TSDB_CODE_SUCCESS == code && NULL != pColList) {
23,292,568✔
859
      code = createColumnByRewriteExprs(pColList, &pJoin->node.pTargets);
21,939,981✔
860
    }
861
    nodesDestroyList(pColList);
23,293,069✔
862
  }
863

864
  if (TSDB_CODE_SUCCESS == code) {
23,290,068✔
865
    rewriteTargetsWithResId(pJoin->node.pTargets);
23,292,447✔
866
  }
867

868
  if (NULL == pJoin->node.pTargets && NULL != pLeft) {
23,289,722✔
869
    code = nodesCloneList(pLeft->pTargets, &pJoin->node.pTargets);
1,351,707✔
870
  }
871

872
#endif
873

874
  if (TSDB_CODE_SUCCESS == code) {
23,292,455✔
875
    *pLogicNode = (SLogicNode*)pJoin;
23,292,455✔
876
  } else {
877
    nodesDestroyNode((SNode*)pJoin);
×
878
  }
879

880
  return code;
23,292,256✔
881
}
882

883
static void buildRefTableKey(char* buf, size_t bufSize, const char* dbName, const char* tableName) {
62,579,292✔
884
  size_t dbLen = strnlen(dbName, TSDB_DB_NAME_LEN);
62,579,292✔
885
  size_t tbLen = strnlen(tableName, TSDB_TABLE_NAME_LEN);
62,579,292✔
886
  if (dbLen + 1 + tbLen >= bufSize) {
62,579,292✔
887
    buf[0] = '\0';
×
888
    return;
×
889
  }
890
  if (snprintf(buf, bufSize, "%.*s.%.*s", (int)dbLen, dbName, (int)tbLen, tableName) >= (int)bufSize) {
62,579,292✔
891
    buf[0] = '\0';
×
892
  }
893
}
894

895
static int32_t findRefTableNode(SHashObj* pRefTableMap, const char* dbName, const char* tableName,
47,224,877✔
896
                                SNode** pRefTable) {
897
  char tableNameKey[TSDB_TABLE_FNAME_LEN] = {0};
47,224,877✔
898
  buildRefTableKey(tableNameKey, sizeof(tableNameKey), dbName, tableName);
47,224,877✔
899
  if (tableNameKey[0] == '\0') {
47,224,877✔
900
    return TSDB_CODE_NOT_FOUND;
×
901
  }
902
  SNode** ppRefTable = (SNode**)taosHashGet(pRefTableMap, tableNameKey, strlen(tableNameKey));
47,224,877✔
903
  if (NULL == ppRefTable) {
47,224,877✔
904
    return TSDB_CODE_NOT_FOUND;
×
905
  }
906
  return nodesCloneNode(*ppRefTable, pRefTable);
47,224,877✔
907
}
908

909
static int32_t findRefColId(SNode *pRefTable, const char *colName, col_id_t *colId, int32_t *colIdx) {
47,224,877✔
910
  SRealTableNode *pRealTable = (SRealTableNode*)pRefTable;
47,224,877✔
911
  for (int32_t i = 0; i < pRealTable->pMeta->tableInfo.numOfColumns; ++i) {
2,147,483,647✔
912
    if (0 == strcasecmp(pRealTable->pMeta->schema[i].name, colName)) {
2,147,483,647✔
913
      *colId = pRealTable->pMeta->schema[i].colId;
47,224,877✔
914
      *colIdx = i;
47,224,877✔
915
      return TSDB_CODE_SUCCESS;
47,224,877✔
916
    }
917
  }
918
  return TSDB_CODE_NOT_FOUND;
×
919
}
920

921
static int32_t scanAddCol(SLogicNode* pLogicNode, SColRef* colRef, STableNode* pVirtualTableNode, const SSchema* pSchema,
53,147,288✔
922
                          col_id_t colId, const SSchema* pRefSchema) {
923
  int32_t         code = TSDB_CODE_SUCCESS;
53,147,288✔
924
  SColumnNode    *pRefTableScanCol = NULL;
53,147,288✔
925
  SScanLogicNode *pLogicScan = (SScanLogicNode*)pLogicNode;
53,147,288✔
926
  PLAN_ERR_JRET(nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pRefTableScanCol));
53,147,288✔
927
  if (colRef) {
53,147,288✔
928
    tstrncpy(pRefTableScanCol->tableAlias, colRef->refTableName, sizeof(pRefTableScanCol->tableAlias));
47,224,877✔
929
    tstrncpy(pRefTableScanCol->dbName, colRef->refDbName, sizeof(pRefTableScanCol->dbName));
47,224,877✔
930
    tstrncpy(pRefTableScanCol->tableName, colRef->refTableName, sizeof(pRefTableScanCol->tableName));
47,224,877✔
931
    tstrncpy(pRefTableScanCol->colName, colRef->refColName, sizeof(pRefTableScanCol->colName));
47,224,877✔
932
  } else {
933
    tstrncpy(pRefTableScanCol->tableAlias, pVirtualTableNode->tableAlias, sizeof(pRefTableScanCol->tableAlias));
5,922,411✔
934
    tstrncpy(pRefTableScanCol->dbName, pVirtualTableNode->dbName, sizeof(pRefTableScanCol->dbName));
5,922,411✔
935
    tstrncpy(pRefTableScanCol->tableName, pVirtualTableNode->tableName, sizeof(pRefTableScanCol->tableName));
5,922,411✔
936
    tstrncpy(pRefTableScanCol->colName, pSchema->name, sizeof(pRefTableScanCol->colName));
5,922,411✔
937
  }
938

939
  if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
53,147,288✔
940
    SNode *pTsCol = nodesListGetNode(pLogicScan->pScanCols, 0);
5,145✔
941
    tstrncpy(((SColumnNode*)pTsCol)->dbName, pRefTableScanCol->dbName, sizeof(((SColumnNode*)pTsCol)->dbName));
5,145✔
942
    ((SColumnNode*)pTsCol)->hasRef = false;
5,145✔
943
    ((SColumnNode*)pTsCol)->hasDep = true;
5,145✔
944
    goto _return;
5,145✔
945
  }
946

947
  // eliminate duplicate scan cols.
948
  SNode *pCol = NULL;
53,142,143✔
949
  FOREACH(pCol, pLogicScan->pScanCols) {
2,147,483,647✔
950
    if (0 == strncmp(((SColumnNode*)pCol)->colName, pRefTableScanCol->colName, TSDB_COL_NAME_LEN) &&
2,147,483,647✔
951
        0 == strncmp(((SColumnNode*)pCol)->tableName, pRefTableScanCol->tableName, TSDB_TABLE_NAME_LEN) &&
×
952
        0 == strncmp(((SColumnNode*)pCol)->dbName, pRefTableScanCol->dbName, TSDB_DB_NAME_LEN)) {
×
953
      nodesDestroyNode((SNode*)pRefTableScanCol);
×
954
      return TSDB_CODE_SUCCESS;
×
955
    }
956
  }
957
  pRefTableScanCol->colId = colId;
53,142,143✔
958
  pRefTableScanCol->tableId = pLogicScan->tableId;
53,142,143✔
959
  pRefTableScanCol->tableType = pLogicScan->tableType;
53,142,143✔
960
  pRefTableScanCol->node.resType.type = pSchema->type;
53,142,143✔
961
  // For variable-length types (BINARY/NCHAR/VARCHAR), use the source table's bytes when available.
962
  // This ensures the TSDB reader allocates enough buffer for source data that may be longer
963
  // than the virtual table's defined column length.
964
  if (pRefSchema && IS_VAR_DATA_TYPE(pSchema->type)) {
53,142,143✔
965
    pRefTableScanCol->node.resType.bytes = TMAX(pSchema->bytes, pRefSchema->bytes);
5,099,397✔
966
    planDebug("scanAddCol: col %s, vtb bytes=%d, ref bytes=%d, final bytes=%d",
5,099,397✔
967
              pRefTableScanCol->colName, pSchema->bytes, pRefSchema->bytes, pRefTableScanCol->node.resType.bytes);
968
  } else {
969
    pRefTableScanCol->node.resType.bytes = pSchema->bytes;
48,042,746✔
970
  }
971
  pRefTableScanCol->colType = COLUMN_TYPE_COLUMN;
53,142,143✔
972
  pRefTableScanCol->isPk = false;
53,142,143✔
973
  pRefTableScanCol->tableHasPk = false;
53,142,143✔
974
  pRefTableScanCol->numOfPKs = 0;
53,142,143✔
975
  pRefTableScanCol->hasRef = false;
53,142,143✔
976
  pRefTableScanCol->hasDep = true;
53,142,143✔
977

978
  PLAN_ERR_JRET(nodesListMakeAppend(&pLogicScan->pScanCols, (SNode*)pRefTableScanCol));
53,142,143✔
979
  return code;
53,142,143✔
980
_return:
5,145✔
981
  nodesDestroyNode((SNode*)pRefTableScanCol);
5,145✔
982
  return code;
5,145✔
983
}
984

985
static int32_t checkColRefType(const SSchema* vtbSchema, const SSchema* refSchema) {
47,224,877✔
986
  if (vtbSchema->type != refSchema->type) {
47,224,877✔
987
    qError("virtual table column:%s type mismatch, virtual table column type:%d, bytes:%d, "
×
988
        "ref table column:%s, type:%d, bytes:%d",
989
        vtbSchema->name, vtbSchema->type, vtbSchema->bytes, refSchema->name, refSchema->type, refSchema->bytes);
990
    return TSDB_CODE_PAR_INVALID_REF_COLUMN_TYPE;
×
991
  }
992
  if (!IS_VAR_DATA_TYPE(vtbSchema->type) && vtbSchema->bytes != refSchema->bytes) {
47,224,877✔
993
    qError("virtual table column:%s bytes mismatch, virtual table column type:%d, bytes:%d, "
×
994
        "ref table column:%s, type:%d, bytes:%d",
995
        vtbSchema->name, vtbSchema->type, vtbSchema->bytes, refSchema->name, refSchema->type, refSchema->bytes);
996
    return TSDB_CODE_PAR_INVALID_REF_COLUMN_TYPE;
×
997
  }
998
  return TSDB_CODE_SUCCESS;
47,224,877✔
999
}
1000

1001
static int32_t addSubScanNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SVirtualTableNode* pVirtualTable,
47,224,877✔
1002
                              int32_t colRefIndex, int32_t schemaIndex, SHashObj* refTablesMap,
1003
                              SHashObj* refTableNodeMap) {
1004
  int32_t     code = TSDB_CODE_SUCCESS;
47,224,877✔
1005
  col_id_t    colId = 0;
47,224,877✔
1006
  int32_t     colIdx = 0;
47,224,877✔
1007
  SColRef    *pColRef = &pVirtualTable->pMeta->colRef[colRefIndex];
47,224,877✔
1008
  SNode      *pRefTable = NULL;
47,224,877✔
1009
  SLogicNode *pRefScan = NULL;
47,224,877✔
1010
  bool        put = false;
47,224,877✔
1011

1012
  PLAN_ERR_JRET(findRefTableNode(refTableNodeMap, pColRef->refDbName, pColRef->refTableName, &pRefTable));
47,224,877✔
1013
  PLAN_ERR_JRET(findRefColId(pRefTable, pColRef->refColName, &colId, &colIdx));
47,224,877✔
1014

1015
  char tableNameKey[TSDB_TABLE_FNAME_LEN] = {0};
47,224,877✔
1016
  TSlice tableNameBuf = {0};
47,224,877✔
1017
  sliceInit(&tableNameBuf, tableNameKey, sizeof(tableNameKey));
47,224,877✔
1018
  PLAN_ERR_JRET(sliceAppend(&tableNameBuf, pColRef->refDbName, strlen(pColRef->refDbName)));
47,224,877✔
1019
  PLAN_ERR_JRET(sliceAppend(&tableNameBuf, ".", 1));
47,224,877✔
1020
  PLAN_ERR_JRET(sliceAppend(&tableNameBuf, pColRef->refTableName, strlen(pColRef->refTableName)));
47,224,877✔
1021

1022
  SLogicNode **ppRefScan = (SLogicNode **)taosHashGet(refTablesMap, &tableNameKey, strlen(tableNameKey));
47,224,877✔
1023
  const SSchema* pRefColSchema = &((SRealTableNode*)pRefTable)->pMeta->schema[colIdx];
47,224,877✔
1024
  if (NULL == ppRefScan) {
47,224,877✔
1025
    PLAN_ERR_JRET(createRefScanLogicNode(pCxt, pSelect, (SRealTableNode*)pRefTable, &pRefScan));
12,895,748✔
1026
    PLAN_ERR_JRET(checkColRefType(&pVirtualTable->pMeta->schema[schemaIndex], pRefColSchema));
12,895,748✔
1027
    PLAN_ERR_JRET(scanAddCol(pRefScan, pColRef, &pVirtualTable->table, &pVirtualTable->pMeta->schema[schemaIndex], colId, pRefColSchema));
12,895,748✔
1028
    PLAN_ERR_JRET(taosHashPut(refTablesMap, &tableNameKey, strlen(tableNameKey), &pRefScan, POINTER_BYTES));
12,895,748✔
1029
    put = true;
12,895,748✔
1030
  } else {
1031
    pRefScan = *ppRefScan;
34,329,129✔
1032
    PLAN_ERR_JRET(checkColRefType(&pVirtualTable->pMeta->schema[schemaIndex], pRefColSchema));
34,329,129✔
1033
    PLAN_ERR_JRET(scanAddCol(pRefScan, pColRef, &pVirtualTable->table, &pVirtualTable->pMeta->schema[schemaIndex], colId, pRefColSchema));
34,329,129✔
1034
  }
1035

1036
  nodesDestroyNode((SNode*)pRefTable);
47,224,877✔
1037
  return code;
47,224,877✔
1038
_return:
×
1039
  nodesDestroyNode((SNode*)pRefTable);
×
1040
  if (!put) {
×
1041
    nodesDestroyNode((SNode*)pRefScan);
×
1042
  }
1043
  return code;
×
1044
}
1045

1046
static int32_t makeVirtualScanLogicNode(SLogicPlanContext* pCxt, SVirtualTableNode* pVirtualTable,
7,324,396✔
1047
                                        SVirtualScanLogicNode* pScan) {
1048
  TSWAP(pScan->pVgroupList, pVirtualTable->pVgroupList);
7,324,396✔
1049
  pScan->tableId = pVirtualTable->pMeta->uid;
7,324,396✔
1050
  pScan->stableId = pVirtualTable->pMeta->suid;
7,324,396✔
1051
  pScan->tableType = pVirtualTable->pMeta->tableType;
7,324,396✔
1052
  pScan->tableName.type = TSDB_TABLE_NAME_T;
7,324,396✔
1053
  pScan->tableName.acctId = pCxt->pPlanCxt->acctId;
7,324,396✔
1054
  tstrncpy(pScan->tableName.dbname, pVirtualTable->table.dbName, TSDB_DB_NAME_LEN);
7,324,396✔
1055
  tstrncpy(pScan->tableName.tname, pVirtualTable->table.tableName, TSDB_TABLE_NAME_LEN);
7,324,396✔
1056
  return TSDB_CODE_SUCCESS;
7,324,396✔
1057
}
1058

1059
static void destroyScanLogicNode(void* data) {
×
1060
  if (data == NULL) {
×
1061
    return;
×
1062
  }
1063
  SScanLogicNode* pNode = *(SScanLogicNode **)data;
×
1064
  nodesDestroyNode((SNode*)pNode);
×
1065
}
1066

1067
static int32_t findColRefIndex(SColRef* pColRef, SVirtualTableNode* pVirtualTable, col_id_t colId) {
50,406,762✔
1068
  for (int32_t i = 0; i < pVirtualTable->pMeta->numOfColRefs; i++) {
2,147,483,647✔
1069
    if (pColRef[i].hasRef && pColRef[i].id == colId) {
2,147,483,647✔
1070
      return i;
47,330,573✔
1071
    }
1072
  }
1073
  return -1;
3,076,189✔
1074
}
1075

1076
static int32_t findSchemaIndex(const SSchema* pSchema, int32_t numOfColumns, col_id_t colId) {
40,569,403✔
1077
  for (int32_t i = 0; i < numOfColumns; i++) {
2,147,483,647✔
1078
    if (pSchema[i].colId == colId) {
2,147,483,647✔
1079
      return i;
40,569,403✔
1080
    }
1081
  }
1082
  return -1;
×
1083
}
1084

1085
static int32_t eliminateDupScanCols(SNodeList* pScanCols) {
3,190,818✔
1086
  int32_t   code = TSDB_CODE_SUCCESS;
3,190,818✔
1087
  SNode*    pCols = NULL;
3,190,818✔
1088
  SHashObj* colsMap = taosHashInit(LIST_LENGTH(pScanCols), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
3,190,818✔
1089
  if (NULL == colsMap) {
3,190,818✔
1090
    return terrno;
×
1091
  }
1092

1093
  FOREACH(pCols, pScanCols) {
76,047,198✔
1094
    SColumnNode* pCol = (SColumnNode*)pCols;
72,856,380✔
1095
    if (!pCol->hasRef) {
72,856,380✔
1096
      continue;
2,940,466✔
1097
    }
1098
    char         key[TSDB_COL_FNAME_EX_LEN] = {0};
69,915,914✔
1099
    TSlice       keyBuf = {0};
69,915,914✔
1100

1101
    sliceInit(&keyBuf, key, sizeof(key));
69,915,914✔
1102
    PLAN_ERR_JRET(sliceAppend(&keyBuf, pCol->refDbName, strlen(pCol->refDbName)));
69,915,914✔
1103
    PLAN_ERR_JRET(sliceAppend(&keyBuf, ".", 1));
69,915,914✔
1104
    PLAN_ERR_JRET(sliceAppend(&keyBuf, pCol->refTableName, strlen(pCol->refTableName)));
69,915,914✔
1105
    PLAN_ERR_JRET(sliceAppend(&keyBuf, ".", 1));
69,915,914✔
1106
    PLAN_ERR_JRET(sliceAppend(&keyBuf, pCol->refColName, strlen(pCol->refColName)));
69,915,914✔
1107

1108
    if (NULL != taosHashGet(colsMap, key, strlen(key))) {
69,915,914✔
1109
      ERASE_NODE(pScanCols);
32,286,977✔
1110
    } else {
1111
      PLAN_ERR_JRET(taosHashPut(colsMap, key, strlen(key), NULL, 0));
37,628,937✔
1112
    }
1113
  }
1114

1115
_return:
3,190,818✔
1116
  taosHashCleanup(colsMap);
3,190,818✔
1117
  return code;
3,190,818✔
1118
}
1119

1120
static int32_t cloneVgroups(SVgroupsInfo **pDst, SVgroupsInfo* pSrc) {
3,557,902✔
1121
  if (pSrc == NULL) {
3,557,902✔
1122
    *pDst = NULL;
×
1123
    return TSDB_CODE_SUCCESS;
×
1124
  }
1125
  int32_t len = VGROUPS_INFO_SIZE(pSrc);
3,557,902✔
1126
  *pDst = taosMemoryMalloc(len);
3,557,902✔
1127
  if (NULL == *pDst) {
3,557,902✔
1128
    return terrno;
×
1129
  }
1130
  memcpy(*pDst, pSrc, len);
3,557,902✔
1131
  return TSDB_CODE_SUCCESS;
3,557,902✔
1132
}
1133

1134
static int32_t createTagScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SVirtualScanLogicNode* pVirtualScan,
3,557,902✔
1135
                                      SLogicNode** pLogicNode) {
1136
  SScanLogicNode* pScan = NULL;
3,557,902✔
1137
  int32_t         code = TSDB_CODE_SUCCESS;
3,557,902✔
1138

1139
  PLAN_ERR_JRET(nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN, (SNode**)&pScan));
3,557,902✔
1140

1141
  PLAN_ERR_JRET(cloneVgroups(&pScan->pVgroupList, pVirtualScan->pVgroupList));
3,557,902✔
1142
  pScan->tableId = pVirtualScan->tableId;
3,557,902✔
1143
  pScan->stableId = pVirtualScan->stableId;
3,557,902✔
1144
  pScan->tableType = pVirtualScan->tableType;
3,557,902✔
1145
  pScan->scanSeq[0] = 1;
3,557,902✔
1146
  pScan->scanSeq[1] = 0;
3,557,902✔
1147
  TAOS_SET_OBJ_ALIGNED(&pScan->scanRange, TSWINDOW_INITIALIZER);
3,557,902✔
1148
  pScan->tableName.type = TSDB_TABLE_NAME_T;
3,557,902✔
1149
  pScan->tableName.acctId = pCxt->pPlanCxt->acctId;
3,557,902✔
1150
  tstrncpy(pScan->tableName.dbname, pVirtualScan->tableName.dbname, TSDB_DB_NAME_LEN);
3,557,902✔
1151
  tstrncpy(pScan->tableName.tname, pVirtualScan->tableName.tname, TSDB_TABLE_NAME_LEN);
3,557,902✔
1152
  pScan->showRewrite = pCxt->pPlanCxt->showRewrite;
3,557,902✔
1153
  pScan->dataRequired = FUNC_DATA_REQUIRED_DATA_LOAD;
3,557,902✔
1154
  pScan->node.groupAction = GROUP_ACTION_NONE;
3,557,902✔
1155
  pScan->node.resultDataOrder = DATA_ORDER_LEVEL_GLOBAL;
3,557,902✔
1156

1157
  PLAN_ERR_JRET(nodesCloneList(pVirtualScan->pScanPseudoCols, &pScan->pScanPseudoCols));
3,557,902✔
1158

1159
  pScan->scanType = SCAN_TYPE_TAG;
3,557,902✔
1160

1161
  PLAN_ERR_JRET(createColumnByRewriteExprs(pScan->pScanPseudoCols, &pScan->node.pTargets));
3,557,902✔
1162

1163
  pScan->onlyMetaCtbIdx = false;
3,557,902✔
1164
  // pCxt->hasScan = true;
1165
  pCxt->pPlanCxt->hasScan = true;
3,557,902✔
1166
  *pLogicNode = (SLogicNode*)pScan;
3,557,902✔
1167
  return code;
3,557,902✔
1168
_return:
×
1169
  planError("%s faild since %d", __func__ , code);
×
1170
  nodesDestroyNode((SNode*)pScan);
×
1171
  return code;
×
1172
}
1173

1174
static int32_t createVirtualSuperTableLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
4,133,578✔
1175
                                                SVirtualTableNode* pVirtualTable, SVirtualScanLogicNode* pVtableScan,
1176
                                                SLogicNode** pLogicNode) {
1177
  int32_t                 code = TSDB_CODE_SUCCESS;
4,133,578✔
1178
  SLogicNode*             pRealTableScan = NULL;
4,133,578✔
1179
  SLogicNode*             pInsColumnsScan = NULL;
4,133,578✔
1180
  SDynQueryCtrlLogicNode* pDynCtrl = NULL;
4,133,578✔
1181
  SNode*                  pNode = NULL;
4,133,578✔
1182
  bool                    scanAllCols = true;
4,133,578✔
1183
  SNode*                  pTagScan = NULL;
4,133,578✔
1184
  bool                    useTagScan = false;
4,133,578✔
1185

1186
  // Virtual table scan node -> Real table scan node
1187
  PLAN_ERR_JRET(createScanLogicNode(pCxt, pSelect, (SRealTableNode*)nodesListGetNode(pVirtualTable->refTables, 0), &pRealTableScan));
4,133,578✔
1188

1189
  if (LIST_LENGTH(pVtableScan->pScanCols) == 0 && LIST_LENGTH(pVtableScan->pScanPseudoCols) == 0) {
4,133,578✔
1190
    scanAllCols = false;
1,235✔
1191
  }
1192
  if (((SScanLogicNode*)pRealTableScan)->scanType == SCAN_TYPE_TAG) {
4,133,578✔
1193
    useTagScan = true;
8,890✔
1194
    ((SScanLogicNode*)pRealTableScan)->scanType = SCAN_TYPE_TABLE;
8,890✔
1195
  }
1196

1197
  PLAN_ERR_JRET(addVtbPrimaryTsCol(pVirtualTable, &pVtableScan->pScanCols));
4,133,578✔
1198

1199
  FOREACH(pNode, pVtableScan->pScanCols) {
28,742,966✔
1200
    SColumnNode *pCol = (SColumnNode*)pNode;
24,609,388✔
1201
    if (pCol->isPrimTs || pCol->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
24,609,388✔
1202
      // do nothing
1203
    } else {
1204
      scanAllCols &= false;
20,475,810✔
1205
    }
1206
  }
1207

1208
  if (scanAllCols) {
4,133,578✔
1209
    nodesDestroyList(((SScanLogicNode*)pRealTableScan)->node.pTargets);
465,751✔
1210
    ((SScanLogicNode*)pRealTableScan)->node.pTargets = NULL;
465,751✔
1211
    pVtableScan->scanAllCols = true;
465,751✔
1212
    for (int32_t i = 0; i < pVirtualTable->pMeta->tableInfo.numOfColumns; i++) {
6,853,913✔
1213
      if (pVirtualTable->pMeta->schema[i].colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
6,388,162✔
1214
        continue;
465,751✔
1215
      } else {
1216
        PLAN_ERR_JRET(scanAddCol(pRealTableScan, NULL, &pVirtualTable->table, &pVirtualTable->pMeta->schema[i], pVirtualTable->pMeta->schema[i].colId, NULL));
5,922,411✔
1217
      }
1218
    }
1219
    PLAN_ERR_JRET(createColumnByRewriteExprs(((SScanLogicNode*)pRealTableScan)->pScanCols, &((SScanLogicNode*)pRealTableScan)->node.pTargets));
465,751✔
1220
  }
1221

1222
  if (pVtableScan->pScanPseudoCols) {
4,133,578✔
1223
    PLAN_ERR_JRET(createTagScanLogicNode(pCxt, pSelect, pVtableScan, (SLogicNode**)&pTagScan));
3,248,702✔
1224
  }
1225

1226
  ((SScanLogicNode *)pRealTableScan)->node.dynamicOp = true;
4,133,578✔
1227
  ((SScanLogicNode *)pRealTableScan)->virtualStableScan = true;
4,133,578✔
1228
  if (pTagScan) {
4,133,578✔
1229
    ((SScanLogicNode*)pTagScan)->node.dynamicOp = true;
3,248,702✔
1230
    ((SScanLogicNode*)pTagScan)->virtualStableScan = true;
3,248,702✔
1231
    ((SLogicNode *)pTagScan)->pParent = (SLogicNode *)pVtableScan;
3,248,702✔
1232
    PLAN_ERR_JRET(nodesListStrictAppend(pVtableScan->node.pChildren, pTagScan));
3,248,702✔
1233
  }
1234
  PLAN_ERR_JRET(nodesListStrictAppend(pVtableScan->node.pChildren, (SNode*)(pRealTableScan)));
4,133,578✔
1235
  pRealTableScan->pParent = (SLogicNode *)pVtableScan;
4,133,578✔
1236

1237
  PLAN_ERR_JRET(createColumnByRewriteExprs(pVtableScan->pScanCols, &pVtableScan->node.pTargets));
4,133,578✔
1238
  PLAN_ERR_JRET(createColumnByRewriteExprs(pVtableScan->pScanPseudoCols, &pVtableScan->node.pTargets));
4,133,578✔
1239

1240
  // Virtual child table uid and ref col scan on ins_columns
1241
  // TODO(smj) : create a fake logic node, no need to collect column
1242
  PLAN_ERR_JRET(createScanLogicNode(pCxt, pSelect, (SRealTableNode*)nodesListGetNode(pVirtualTable->refTables, 1), &pInsColumnsScan));
4,133,578✔
1243
  nodesDestroyList(((SScanLogicNode*)pInsColumnsScan)->node.pTargets);
4,133,578✔
1244
  ((SScanLogicNode*)pInsColumnsScan)->node.pTargets = NULL;  // Set to NULL after destroy to avoid use-after-free
4,133,578✔
1245
  PLAN_ERR_JRET(addInsColumnScanCol((SRealTableNode*)nodesListGetNode(pVirtualTable->refTables, 1), &((SScanLogicNode*)pInsColumnsScan)->pScanCols));
4,133,578✔
1246
  PLAN_ERR_JRET(createColumnByRewriteExprs(((SScanLogicNode*)pInsColumnsScan)->pScanCols, &((SScanLogicNode*)pInsColumnsScan)->node.pTargets));
4,133,578✔
1247
  ((SScanLogicNode *)pInsColumnsScan)->virtualStableScan = true;
4,133,578✔
1248
  ((SScanLogicNode *)pInsColumnsScan)->stableId = pVtableScan->stableId;
4,133,578✔
1249

1250
  // Dynamic query control node -> Virtual table scan node -> Real table scan node
1251
  PLAN_ERR_JRET(nodesMakeNode(QUERY_NODE_LOGIC_PLAN_DYN_QUERY_CTRL, (SNode**)&pDynCtrl));
4,133,578✔
1252
  pDynCtrl->qType = DYN_QTYPE_VTB_SCAN;
4,133,578✔
1253
  pDynCtrl->vtbScan.scanAllCols = pVtableScan->scanAllCols;
4,133,578✔
1254
  pDynCtrl->vtbScan.useTagScan = useTagScan;
4,133,578✔
1255
  if (pVtableScan->tableType == TSDB_SUPER_TABLE) {
4,133,578✔
1256
    pDynCtrl->vtbScan.isSuperTable = true;
4,090,877✔
1257
    pDynCtrl->vtbScan.suid = pVtableScan->stableId;
4,090,877✔
1258
    pDynCtrl->vtbScan.rversion = 0;
4,090,877✔
1259
  } else {
1260
    pDynCtrl->vtbScan.isSuperTable = false;
42,701✔
1261
    pDynCtrl->vtbScan.uid = pVtableScan->tableId;
42,701✔
1262
    pDynCtrl->vtbScan.rversion = pVirtualTable->pMeta->rversion;
42,701✔
1263
  }
1264
  for (int32_t i = 0; i < ((SScanLogicNode*)pRealTableScan)->pVgroupList->numOfVgroups; i++) {
21,325,090✔
1265
    int32_t    vgId = ((SScanLogicNode*)pRealTableScan)->pVgroupList->vgroups[i].vgId;
17,191,512✔
1266
    SValueNode *pVal = NULL;
17,191,512✔
1267
    PLAN_ERR_JRET(nodesMakeValueNodeFromInt32(vgId, (SNode**)&pVal));
17,191,512✔
1268
    PLAN_ERR_JRET(nodesListMakeStrictAppend(&pDynCtrl->vtbScan.pOrgVgIds, (SNode*)pVal));
17,191,512✔
1269
  }
1270

1271
  pDynCtrl->dynTbname = ((SScanLogicNode*)pRealTableScan)->phTbnameScan;
4,133,578✔
1272
  ((SScanLogicNode*)pRealTableScan)->phTbnameScan = false;  // reset phTbnameQuery, it is only used for vtable scan
4,133,578✔
1273

1274
  tstrncpy(pDynCtrl->vtbScan.dbName, pVtableScan->tableName.dbname, TSDB_DB_NAME_LEN);
4,133,578✔
1275
  tstrncpy(pDynCtrl->vtbScan.tbName, pVtableScan->tableName.tname, TSDB_TABLE_NAME_LEN);
4,133,578✔
1276
  PLAN_ERR_JRET(nodesListMakeStrictAppend(&pDynCtrl->node.pChildren, (SNode*)pVtableScan));
4,133,578✔
1277
  PLAN_ERR_JRET(nodesListMakeStrictAppend(&pDynCtrl->node.pChildren, (SNode*)pInsColumnsScan));
4,133,578✔
1278
  PLAN_ERR_JRET(nodesCloneList(pVtableScan->node.pTargets, &pDynCtrl->node.pTargets));
4,133,578✔
1279

1280
  TSWAP(pVtableScan->pVgroupList, pDynCtrl->vtbScan.pVgroupList);
4,133,578✔
1281
  pVtableScan->node.pParent = (SLogicNode*)pDynCtrl;
4,133,578✔
1282
  ((SScanLogicNode*)pInsColumnsScan)->node.pParent = (SLogicNode*)pDynCtrl;
4,133,578✔
1283
  pVtableScan->node.dynamicOp = true;
4,133,578✔
1284
  *pLogicNode = (SLogicNode*)pDynCtrl;
4,133,578✔
1285

1286
  return code;
4,133,578✔
1287
_return:
×
1288
  planError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1289
  nodesDestroyNode((SNode*)pRealTableScan);
×
1290
  nodesDestroyNode((SNode*)pDynCtrl);
×
1291
  return code;
×
1292
}
1293

1294
static int32_t createVirtualNormalChildTableLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
3,190,818✔
1295
                                                      SVirtualTableNode* pVirtualTable, SVirtualScanLogicNode* pVtableScan,
1296
                                                      SLogicNode** pLogicNode) {
1297
  int32_t   code = TSDB_CODE_SUCCESS;
3,190,818✔
1298
  SNode*    pNode = NULL;
3,190,818✔
1299
  bool      scanAllCols = true;
3,190,818✔
1300
  SHashObj* pRefTablesMap = NULL;
3,190,818✔
1301
  SHashObj* pRefTableNodeMap = NULL;
3,190,818✔
1302
  SNode*    pTagScan = NULL;
3,190,818✔
1303

1304
  pRefTablesMap = taosHashInit(LIST_LENGTH(pVtableScan->pScanCols), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
3,190,818✔
1305
  if (NULL == pRefTablesMap) {
3,190,818✔
1306
    PLAN_ERR_JRET(terrno);
×
1307
  }
1308
  pRefTableNodeMap =
1309
      taosHashInit(LIST_LENGTH(pVirtualTable->refTables), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true,
3,190,818✔
1310
                   HASH_ENTRY_LOCK);
1311
  if (NULL == pRefTableNodeMap) {
3,190,818✔
1312
    PLAN_ERR_JRET(terrno);
×
1313
  }
1314

1315
  SNode* pRefNode = NULL;
3,190,818✔
1316
  FOREACH(pRefNode, pVirtualTable->refTables) {
18,545,233✔
1317
    SRealTableNode* pRefTable = (SRealTableNode*)pRefNode;
15,354,415✔
1318
    char            tableNameKey[TSDB_TABLE_FNAME_LEN] = {0};
15,354,415✔
1319
    buildRefTableKey(tableNameKey, sizeof(tableNameKey), pRefTable->table.dbName, pRefTable->table.tableName);
15,354,415✔
1320
    if (tableNameKey[0] == '\0') {
15,354,415✔
1321
      PLAN_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1322
    }
1323
    PLAN_ERR_JRET(taosHashPut(pRefTableNodeMap, tableNameKey, strlen(tableNameKey), &pRefNode, POINTER_BYTES));
15,354,415✔
1324
  }
1325

1326
  if (inStreamCalcClause(pCxt->pPlanCxt) && pSelect->pTimeRange != NULL) {
3,190,818✔
1327
    // ts column might be extract from where to time range. So, ts column won't be collected into pVtableScan->pScanCols.
1328
    PLAN_ERR_JRET(addVtbPrimaryTsCol(pVirtualTable, &pVtableScan->pScanCols));
×
1329
  }
1330

1331
  PLAN_ERR_JRET(eliminateDupScanCols(pVtableScan->pScanCols));
3,190,818✔
1332

1333
  FOREACH(pNode, pVtableScan->pScanCols) {
43,760,221✔
1334
    SColumnNode *pCol = (SColumnNode*)pNode;
40,569,403✔
1335
    int32_t colRefIndex = findColRefIndex(pVirtualTable->pMeta->colRef, pVirtualTable, pCol->colId);
40,569,403✔
1336
    int32_t schemaIndex = findSchemaIndex(pVirtualTable->pMeta->schema, pVirtualTable->pMeta->tableInfo.numOfColumns, pCol->colId);
40,569,403✔
1337
    if (colRefIndex != -1 && pVirtualTable->pMeta->colRef[colRefIndex].hasRef) {
40,569,403✔
1338
      if (pCol->isPrimTs || pCol->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
37,628,937✔
1339
        continue;
105,696✔
1340
      }
1341
      scanAllCols &= false;
37,523,241✔
1342
      PLAN_ERR_JRET(addSubScanNode(pCxt, pSelect, pVirtualTable, colRefIndex, schemaIndex, pRefTablesMap,
37,523,241✔
1343
                                   pRefTableNodeMap));
1344
    } else if (pCol->isPrimTs || pCol->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
2,940,466✔
1345
      // do nothing
1346
    } else {
1347
      scanAllCols &= false;
338,313✔
1348
    }
1349
  }
1350

1351
  if (pVtableScan->pScanPseudoCols) {
3,190,818✔
1352
    PLAN_ERR_JRET(createTagScanLogicNode(pCxt, pSelect, pVtableScan, (SLogicNode**)&pTagScan));
309,200✔
1353
  }
1354

1355
  if (scanAllCols) {
3,190,818✔
1356
    pVtableScan->scanAllCols = true;
661,461✔
1357
    taosHashClear(pRefTablesMap);
661,461✔
1358
    for (int32_t i = 0; i < pVirtualTable->pMeta->tableInfo.numOfColumns; i++) {
11,160,281✔
1359
      if (pVirtualTable->pMeta->schema[i].colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
10,498,820✔
1360
        continue;
661,461✔
1361
      } else {
1362
        col_id_t colRefIndex = (col_id_t)findColRefIndex(pVirtualTable->pMeta->colRef, pVirtualTable, pVirtualTable->pMeta->schema[i].colId);
9,837,359✔
1363
        if (colRefIndex != -1 && pVirtualTable->pMeta->colRef[colRefIndex].hasRef) {
9,837,359✔
1364
          PLAN_ERR_JRET(addSubScanNode(pCxt, pSelect, pVirtualTable, colRefIndex, i, pRefTablesMap, pRefTableNodeMap));
9,701,636✔
1365
        }
1366
      }
1367
    }
1368
  }
1369

1370
  // Iterate the table map, build scan logic node for each origin table and add these node to vtable scan's child list.
1371
  void* pIter = NULL;
3,190,818✔
1372
  while ((pIter = taosHashIterate(pRefTablesMap, pIter))) {
16,086,566✔
1373
    SScanLogicNode **pRefScanNode = (SScanLogicNode**)pIter;
12,895,748✔
1374
    PLAN_ERR_JRET(createColumnByRewriteExprs((*pRefScanNode)->pScanCols, &(*pRefScanNode)->node.pTargets));
12,895,748✔
1375
    PLAN_ERR_JRET(nodesListStrictAppend(pVtableScan->node.pChildren, (SNode*)(*pRefScanNode)));
12,895,748✔
1376
  }
1377

1378
  if (pTagScan) {
3,190,818✔
1379
    PLAN_ERR_JRET(nodesListStrictAppend(pVtableScan->node.pChildren, pTagScan));
309,200✔
1380
  }
1381

1382
  // set output
1383
  PLAN_ERR_JRET(createColumnByRewriteExprs(pVtableScan->pScanCols, &pVtableScan->node.pTargets));
3,190,818✔
1384
  PLAN_ERR_JRET(createColumnByRewriteExprs(pVtableScan->pScanPseudoCols, &pVtableScan->node.pTargets));
3,190,818✔
1385

1386
  *pLogicNode = (SLogicNode*)pVtableScan;
3,190,818✔
1387
  taosHashCleanup(pRefTablesMap);
3,190,818✔
1388
  taosHashCleanup(pRefTableNodeMap);
3,190,818✔
1389
  return code;
3,190,818✔
1390
_return:
×
1391
  planError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1392
  taosHashSetFreeFp(pRefTablesMap, destroyScanLogicNode);
×
1393
  taosHashCleanup(pRefTablesMap);
×
1394
  taosHashCleanup(pRefTableNodeMap);
×
1395
  return code;
×
1396
}
1397

1398

1399
static int32_t createVirtualTableLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
7,324,396✔
1400
                                           SVirtualTableNode* pVirtualTable, SLogicNode** pLogicNode) {
1401
  int32_t                 code = TSDB_CODE_SUCCESS;
7,324,396✔
1402
  SVirtualScanLogicNode  *pVtableScan = NULL;
7,324,396✔
1403

1404
  PLAN_ERR_JRET(nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VIRTUAL_TABLE_SCAN, (SNode**)&pVtableScan));
7,324,396✔
1405

1406
  PLAN_ERR_JRET(nodesMakeList(&pVtableScan->node.pChildren));
7,324,396✔
1407

1408
  PLAN_ERR_JRET(makeVirtualScanLogicNode(pCxt, pVirtualTable, pVtableScan));
7,324,396✔
1409

1410
  PLAN_ERR_JRET(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pVirtualTable->table.tableAlias, COLLECT_COL_TYPE_COL,
7,324,396✔
1411
                                    &pVtableScan->pScanCols));
1412

1413
  PLAN_ERR_JRET(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pVirtualTable->table.tableAlias, COLLECT_COL_TYPE_TAG,
7,324,396✔
1414
                                    &pVtableScan->pScanPseudoCols));
1415

1416
  PLAN_ERR_JRET(nodesCollectFuncs(pSelect, SQL_CLAUSE_FROM, pVirtualTable->table.tableAlias, fmIsScanPseudoColumnFunc,
7,324,396✔
1417
                                  &pVtableScan->pScanPseudoCols));
1418

1419
  PLAN_ERR_JRET(rewriteExprsForSelect(pVtableScan->pScanPseudoCols, pSelect, SQL_CLAUSE_FROM, NULL));
7,324,396✔
1420

1421
  switch (pVtableScan->tableType) {
7,324,396✔
1422
    case TSDB_SUPER_TABLE:
4,090,877✔
1423
      PLAN_ERR_JRET(createVirtualSuperTableLogicNode(pCxt, pSelect, pVirtualTable, pVtableScan, pLogicNode));
4,090,877✔
1424
      break;
4,090,877✔
1425
    case TSDB_VIRTUAL_NORMAL_TABLE:
3,233,519✔
1426
    case TSDB_VIRTUAL_CHILD_TABLE: {
1427
      if (inStreamCalcClause(pCxt->pPlanCxt)) {
3,233,519✔
1428
        PLAN_ERR_JRET(createVirtualSuperTableLogicNode(pCxt, pSelect, pVirtualTable, pVtableScan, pLogicNode));
42,701✔
1429
      } else {
1430
        PLAN_ERR_JRET(createVirtualNormalChildTableLogicNode(pCxt, pSelect, pVirtualTable, pVtableScan, pLogicNode));
3,190,818✔
1431
      }
1432
      break;
3,233,519✔
1433
    }
1434
    default:
×
1435
      PLAN_ERR_JRET(TSDB_CODE_PLAN_INVALID_TABLE_TYPE);
×
1436
  }
1437
  pCxt->pPlanCxt->streamCxt.isVtableCalc = true;
7,324,396✔
1438

1439
  return code;
7,324,396✔
1440
_return:
×
1441
  planError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1442
  nodesDestroyNode((SNode*)pVtableScan);
×
1443
  return code;
×
1444
}
1445

1446
static int32_t doCreateLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable,
491,564,091✔
1447
                                        SLogicNode** pLogicNode) {
1448
  int32_t code = TSDB_CODE_SUCCESS;
491,564,091✔
1449
  switch (nodeType(pTable)) {
491,564,091✔
1450
    case QUERY_NODE_REAL_TABLE:
405,151,513✔
1451
      return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable, pLogicNode);
405,151,513✔
1452
    case QUERY_NODE_TEMP_TABLE:
55,869,625✔
1453
      return createSubqueryLogicNode(pCxt, pSelect, (STempTableNode*)pTable, pLogicNode);
55,869,625✔
1454
    case QUERY_NODE_JOIN_TABLE:
23,290,856✔
1455
      return createJoinLogicNode(pCxt, pSelect, (SJoinTableNode*)pTable, pLogicNode);
23,290,856✔
1456
    case QUERY_NODE_VIRTUAL_TABLE:
7,326,022✔
1457
      return createVirtualTableLogicNode(pCxt, pSelect, (SVirtualTableNode*)pTable, pLogicNode);
7,326,022✔
1458
    default:
×
1459
      code = TSDB_CODE_PLAN_INVALID_TABLE_TYPE;
×
1460
      break;
×
1461
  }
1462
  planError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1463
  return code;
×
1464
}
1465

1466
static int32_t createLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable,
444,995,267✔
1467
                                      SLogicNode** pLogicNode) {
1468
  SLogicNode* pNode = NULL;
444,995,267✔
1469
  int32_t     code = TSDB_CODE_SUCCESS;
444,997,302✔
1470
  PLAN_ERR_JRET(doCreateLogicNodeByTable(pCxt, pSelect, pTable, &pNode));
444,997,302✔
1471
  pNode->pConditions = NULL;
445,030,647✔
1472
  PLAN_ERR_JRET(nodesCloneNode(pSelect->pWhere, &pNode->pConditions));
445,031,486✔
1473
  pNode->precision = pSelect->precision;
445,074,772✔
1474
  *pLogicNode = pNode;
445,074,678✔
1475
  pCxt->pCurrRoot = pNode;
445,074,928✔
1476
  return code;
445,075,622✔
1477

1478
_return:
×
1479
  planError("%s failed since %s", __func__, tstrerror(code));
×
1480
  nodesDestroyNode((SNode*)pNode);
×
1481
  return code;
×
1482
}
1483

1484
static int32_t createGroupingSetNode(SNode* pExpr, SNode** ppNode) {
14,053,837✔
1485
  SGroupingSetNode* pGroupingSet = NULL;
14,053,837✔
1486
  int32_t           code = 0;
14,053,837✔
1487
  *ppNode = NULL;
14,053,837✔
1488
  code = nodesMakeNode(QUERY_NODE_GROUPING_SET, (SNode**)&pGroupingSet);
14,053,837✔
1489
  if (NULL == pGroupingSet) {
14,057,028✔
1490
    return code;
×
1491
  }
1492
  pGroupingSet->groupingSetType = GP_TYPE_NORMAL;
14,057,028✔
1493
  SNode* pNew = NULL;
14,057,028✔
1494
  code = nodesCloneNode(pExpr, &pNew);
14,057,028✔
1495
  if (TSDB_CODE_SUCCESS == code) {
14,055,932✔
1496
    code = nodesListMakeStrictAppend(&pGroupingSet->pParameterList, pNew);
14,056,095✔
1497
  }
1498
  if (TSDB_CODE_SUCCESS == code) {
14,058,026✔
1499
    *ppNode = (SNode*)pGroupingSet;
14,058,026✔
1500
  }
1501
  return code;
14,058,026✔
1502
}
1503

1504
static bool isWindowJoinStmt(SSelectStmt* pSelect) {
118,848,659✔
1505
  return (QUERY_NODE_JOIN_TABLE == nodeType(pSelect->pFromTable) &&
127,448,886✔
1506
          IS_WINDOW_JOIN(((SJoinTableNode*)pSelect->pFromTable)->subType));
8,600,456✔
1507
}
1508

1509
static EGroupAction getGroupAction(SLogicPlanContext* pCxt, SSelectStmt* pSelect) {
164,265,233✔
1510
  return ((NULL != pSelect->pLimit || NULL != pSelect->pSlimit) && !pSelect->isDistinct)
264,446,442✔
1511
             ? GROUP_ACTION_KEEP
1512
             : GROUP_ACTION_NONE;
328,530,272✔
1513
}
1514

1515
static EDataOrderLevel getRequireDataOrder(bool needTimeline, SSelectStmt* pSelect) {
165,003,134✔
1516
  return needTimeline ? (NULL != pSelect->pPartitionByList ? DATA_ORDER_LEVEL_IN_GROUP : DATA_ORDER_LEVEL_GLOBAL)
45,121,627✔
1517
                      : DATA_ORDER_LEVEL_NONE;
181,663,687✔
1518
}
1519

1520
static int32_t addWinJoinPrimKeyToAggFuncs(SSelectStmt* pSelect, SNodeList** pList) {
×
1521
  SNodeList* pTargets = *pList;
×
1522
  int32_t    code = 0;
×
1523
  if (pTargets) {
×
1524
    code = nodesMakeList(&pTargets);
×
1525
  }
1526
  if (TSDB_CODE_SUCCESS != code) {
×
1527
    return code;
×
1528
  }
1529
  SJoinTableNode* pJoinTable = (SJoinTableNode*)pSelect->pFromTable;
×
1530
  SRealTableNode* pProbeTable = NULL;
×
1531
  switch (pJoinTable->joinType) {
×
1532
    case JOIN_TYPE_LEFT:
×
1533
      pProbeTable = (SRealTableNode*)pJoinTable->pLeft;
×
1534
      break;
×
1535
    case JOIN_TYPE_RIGHT:
×
1536
      pProbeTable = (SRealTableNode*)pJoinTable->pRight;
×
1537
      break;
×
1538
    default:
×
1539
      if (!*pList) nodesDestroyList(pTargets);
×
1540
      return TSDB_CODE_PLAN_INTERNAL_ERROR;
×
1541
  }
1542

1543
  SColumnNode* pCol = NULL;
×
1544
  code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
×
1545
  if (NULL == pCol) {
×
1546
    if (!*pList) nodesDestroyList(pTargets);
×
1547
    return code;
×
1548
  }
1549

1550
  SSchema* pColSchema = &pProbeTable->pMeta->schema[0];
×
1551
  tstrncpy(pCol->dbName, pProbeTable->table.dbName, TSDB_DB_NAME_LEN);
×
1552
  tstrncpy(pCol->tableAlias, pProbeTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
×
1553
  tstrncpy(pCol->tableName, pProbeTable->table.tableName, TSDB_TABLE_NAME_LEN);
×
1554
  tstrncpy(pCol->colName, pColSchema->name, TSDB_COL_NAME_LEN);
×
1555
  tstrncpy(pCol->node.aliasName, pColSchema->name, TSDB_COL_NAME_LEN);
×
1556
  tstrncpy(pCol->node.userAlias, pColSchema->name, TSDB_COL_NAME_LEN);
×
1557
  pCol->tableId = pProbeTable->pMeta->uid;
×
1558
  pCol->tableType = pProbeTable->pMeta->tableType;
×
1559
  pCol->colId = pColSchema->colId;
×
1560
  pCol->colType = COLUMN_TYPE_COLUMN;
×
1561
  pCol->hasIndex = (pColSchema != NULL && IS_IDX_ON(pColSchema));
×
1562
  pCol->node.resType.type = pColSchema->type;
×
1563
  pCol->node.resType.bytes = pColSchema->bytes;
×
1564
  pCol->node.resType.precision = pProbeTable->pMeta->tableInfo.precision;
×
1565

1566
  SNode* pFunc = (SNode*)createGroupKeyAggFunc(pCol);
×
1567
  if (!pFunc) {
×
1568
    nodesDestroyList(pTargets);
×
1569
    return terrno;
×
1570
  }
1571

1572
  code = nodesListStrictAppend(pTargets, pFunc);
×
1573
  if (TSDB_CODE_SUCCESS != code) {
×
1574
    nodesDestroyList(pTargets);
×
1575
  }
1576

1577
  return code;
×
1578
}
1579

1580
static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
444,991,737✔
1581
  if (!pSelect->hasAggFuncs && NULL == pSelect->pGroupByList) {
444,991,737✔
1582
    return TSDB_CODE_SUCCESS;
326,210,069✔
1583
  }
1584

1585
  SAggLogicNode* pAgg = NULL;
118,782,253✔
1586
  int32_t        code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG, (SNode**)&pAgg);
118,780,905✔
1587
  if (NULL == pAgg) {
118,865,961✔
1588
    return code;
×
1589
  }
1590

1591
  bool winJoin = isWindowJoinStmt(pSelect);
118,865,961✔
1592
  pAgg->hasLastRow = pSelect->hasLastRowFunc;
118,856,677✔
1593
  pAgg->hasLast = pSelect->hasLastFunc;
118,856,634✔
1594
  pAgg->hasTimeLineFunc = pSelect->hasTimeLineFunc;
118,857,060✔
1595
  pAgg->hasGroupKeyOptimized = false;
118,856,493✔
1596
  pAgg->onlyHasKeepOrderFunc = pSelect->onlyHasKeepOrderFunc;
118,856,928✔
1597
  pAgg->node.groupAction = winJoin ? GROUP_ACTION_NONE : getGroupAction(pCxt, pSelect);
118,856,787✔
1598
  pAgg->node.requireDataOrder = getRequireDataOrder(pAgg->hasTimeLineFunc, pSelect);
118,858,847✔
1599
  pAgg->node.resultDataOrder = pAgg->onlyHasKeepOrderFunc ? pAgg->node.requireDataOrder : DATA_ORDER_LEVEL_NONE;
118,850,395✔
1600
  pAgg->node.forceCreateNonBlockingOptr = winJoin ? true : false;
118,850,444✔
1601

1602
  // set grouyp keys, agg funcs and having conditions
1603
  if (TSDB_CODE_SUCCESS == code) {
118,849,974✔
1604
    code = nodesCollectFuncs(pSelect, SQL_CLAUSE_GROUP_BY, NULL, fmIsAggFunc, &pAgg->pAggFuncs);
118,864,672✔
1605
  }
1606

1607
  // rewrite the expression in subsequent clauses
1608
  if (TSDB_CODE_SUCCESS == code && NULL != pAgg->pAggFuncs) {
118,855,386✔
1609
    code = rewriteExprsForSelect(pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY, NULL);
104,164,640✔
1610
  }
1611

1612
  if (NULL != pSelect->pGroupByList) {
118,853,863✔
1613
    code = nodesListDeduplicate(&pSelect->pGroupByList);
33,705,689✔
1614
    if (TSDB_CODE_SUCCESS == code) {
33,703,166✔
1615
      pAgg->pGroupKeys = NULL;
33,703,879✔
1616
      code = nodesCloneList(pSelect->pGroupByList, &pAgg->pGroupKeys);
33,703,879✔
1617
    }
1618
  }
1619

1620
  // rewrite the expression in subsequent clauses
1621
  SNodeList* pOutputGroupKeys = NULL;
118,853,541✔
1622
  if (TSDB_CODE_SUCCESS == code) {
118,853,335✔
1623
    code = rewriteExprsForSelect(pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY, &pOutputGroupKeys);
118,863,118✔
1624
  }
1625

1626
  if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pHaving) {
118,857,292✔
1627
    pAgg->node.pConditions = NULL;
20,724,513✔
1628
    code = nodesCloneNode(pSelect->pHaving, &pAgg->node.pConditions);
20,724,513✔
1629
  }
1630

1631
  // set the output
1632
  if (TSDB_CODE_SUCCESS == code && NULL != pAgg->pAggFuncs) {
118,856,981✔
1633
    code = createColumnByRewriteExprs(pAgg->pAggFuncs, &pAgg->node.pTargets);
104,157,821✔
1634
  }
1635

1636
  if (TSDB_CODE_SUCCESS == code) {
118,862,673✔
1637
    if (NULL != pOutputGroupKeys) {
118,869,013✔
1638
      code = createColumnByRewriteExprs(pOutputGroupKeys, &pAgg->node.pTargets);
23,890,469✔
1639
    } else if (NULL == pAgg->node.pTargets && NULL != pAgg->pGroupKeys) {
94,978,544✔
1640
      code = createColumnByRewriteExprs(pAgg->pGroupKeys, &pAgg->node.pTargets);
1,277,652✔
1641
    }
1642
  }
1643
  nodesDestroyList(pOutputGroupKeys);
118,862,596✔
1644

1645
  pAgg->isGroupTb = pAgg->pGroupKeys ? keysHasTbname(pAgg->pGroupKeys) : 0;
118,855,769✔
1646
  pAgg->isPartTb = pSelect->pPartitionByList ? keysHasTbname(pSelect->pPartitionByList) : 0;
118,862,386✔
1647
  pAgg->hasGroup = pAgg->pGroupKeys || pSelect->pPartitionByList;
118,862,816✔
1648

1649
  if (TSDB_CODE_SUCCESS == code) {
118,862,528✔
1650
    *pLogicNode = (SLogicNode*)pAgg;
118,864,618✔
1651
  } else {
1652
    nodesDestroyNode((SNode*)pAgg);
×
1653
  }
1654

1655
  return code;
118,864,804✔
1656
}
1657

1658
static int32_t createIndefRowsFuncLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,021,350✔
1659
  // top/bottom are both an aggregate function and a indefinite rows function
1660
  if (!pSelect->hasIndefiniteRowsFunc || pSelect->hasAggFuncs || NULL != pSelect->pWindow) {
445,021,350✔
1661
    return TSDB_CODE_SUCCESS;
437,780,712✔
1662
  }
1663

1664
  SIndefRowsFuncLogicNode* pIdfRowsFunc = NULL;
7,240,565✔
1665
  int32_t                  code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC, (SNode**)&pIdfRowsFunc);
7,240,565✔
1666
  if (NULL == pIdfRowsFunc) {
7,240,565✔
1667
    return code;
×
1668
  }
1669

1670
  pIdfRowsFunc->isTailFunc = pSelect->hasTailFunc;
7,240,565✔
1671
  pIdfRowsFunc->isUniqueFunc = pSelect->hasUniqueFunc;
7,240,565✔
1672
  pIdfRowsFunc->isTimeLineFunc = pSelect->hasTimeLineFunc;
7,240,565✔
1673
  pIdfRowsFunc->node.groupAction = getGroupAction(pCxt, pSelect);
7,240,565✔
1674
  pIdfRowsFunc->node.requireDataOrder = getRequireDataOrder(pIdfRowsFunc->isTimeLineFunc, pSelect);
7,240,565✔
1675
  pIdfRowsFunc->node.resultDataOrder = pIdfRowsFunc->node.requireDataOrder;
7,240,565✔
1676

1677
  // indefinite rows functions and _select_values functions
1678
  code = nodesCollectFuncs(pSelect, SQL_CLAUSE_SELECT, NULL, fmIsVectorFunc, &pIdfRowsFunc->pFuncs);
7,240,565✔
1679
  if (TSDB_CODE_SUCCESS == code) {
7,240,565✔
1680
    code = rewriteExprsForSelect(pIdfRowsFunc->pFuncs, pSelect, SQL_CLAUSE_SELECT, NULL);
7,240,565✔
1681
  }
1682

1683
  // set the output
1684
  if (TSDB_CODE_SUCCESS == code) {
7,240,565✔
1685
    code = createColumnByRewriteExprs(pIdfRowsFunc->pFuncs, &pIdfRowsFunc->node.pTargets);
7,240,565✔
1686
  }
1687

1688
  if (TSDB_CODE_SUCCESS == code) {
7,240,565✔
1689
    *pLogicNode = (SLogicNode*)pIdfRowsFunc;
7,240,565✔
1690
  } else {
1691
    nodesDestroyNode((SNode*)pIdfRowsFunc);
×
1692
  }
1693

1694
  return code;
7,240,565✔
1695
}
1696

1697
static bool isInterpFunc(int32_t funcId) {
17,207,684✔
1698
  return fmIsInterpFunc(funcId) || fmIsInterpPseudoColumnFunc(funcId) || fmIsGroupKeyFunc(funcId) ||
17,232,870✔
1699
         fmisSelectGroupConstValueFunc(funcId);
26,136✔
1700
}
1701

1702
static int32_t createInterpFuncLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,009,473✔
1703
  if (!pSelect->hasInterpFunc) {
445,009,473✔
1704
    return TSDB_CODE_SUCCESS;
441,350,761✔
1705
  }
1706

1707
  SInterpFuncLogicNode* pInterpFunc = NULL;
3,689,955✔
1708
  int32_t               code = TSDB_CODE_SUCCESS;
3,689,334✔
1709

1710
  PLAN_ERR_JRET(nodesMakeNode(QUERY_NODE_LOGIC_PLAN_INTERP_FUNC, (SNode**)&pInterpFunc));
3,689,334✔
1711

1712
  pInterpFunc->node.groupAction = getGroupAction(pCxt, pSelect);
3,693,648✔
1713
  pInterpFunc->node.requireDataOrder = getRequireDataOrder(true, pSelect);
3,693,648✔
1714
  pInterpFunc->node.resultDataOrder = pInterpFunc->node.requireDataOrder;
3,694,598✔
1715

1716
  // interp functions and _group_key functions
1717
  PLAN_ERR_JRET(nodesCollectFuncs(pSelect, SQL_CLAUSE_SELECT, NULL, isInterpFunc, &pInterpFunc->pFuncs));
3,693,569✔
1718

1719
  PLAN_ERR_JRET(rewriteExprsForSelect(pInterpFunc->pFuncs, pSelect, SQL_CLAUSE_SELECT, NULL));
3,694,166✔
1720

1721
  if (NULL != pSelect->pFill) {
3,693,648✔
1722
    SFillNode* pFill = (SFillNode*)pSelect->pFill;
3,693,648✔
1723
    pInterpFunc->timeRange = pFill->timeRange;
3,693,648✔
1724
    TSWAP(pInterpFunc->pTimeRange, pFill->pTimeRange);    
3,694,166✔
1725
    pInterpFunc->fillMode = pFill->mode;
3,693,648✔
1726
    pInterpFunc->pTimeSeries = NULL;
3,693,648✔
1727
    PLAN_ERR_JRET(nodesCloneNode(pFill->pWStartTs, &pInterpFunc->pTimeSeries));
3,693,648✔
1728
    PLAN_ERR_JRET(nodesCloneNode(pFill->pValues, &pInterpFunc->pFillValues));
3,694,598✔
1729
    if (NULL != pFill->pSurroundingTime &&
3,694,598✔
1730
        nodeType(pFill->pSurroundingTime) == QUERY_NODE_VALUE) {
37,242✔
1731
      SValueNode* pSurroundingTime = (SValueNode*)pFill->pSurroundingTime;
37,242✔
1732
      pInterpFunc->surroundingTime = pSurroundingTime->datum.i;
37,242✔
1733
    }
1734
  }
1735

1736
  if (NULL != pSelect->pEvery) {
3,694,080✔
1737
    pInterpFunc->interval = ((SValueNode*)pSelect->pEvery)->datum.i;
3,694,080✔
1738
    pInterpFunc->intervalUnit = ((SValueNode*)pSelect->pEvery)->unit;
3,694,080✔
1739
    pInterpFunc->precision = pSelect->precision;
3,694,166✔
1740
  }
1741

1742
  if (pSelect->pRangeAround) {
3,694,598✔
1743
    SNode* pRangeInterval = ((SRangeAroundNode*)pSelect->pRangeAround)->pInterval;
1,548,696✔
1744
    if (!pRangeInterval || nodeType(pRangeInterval) != QUERY_NODE_VALUE) {
1,549,128✔
1745
      planError("%s failed at line %d since range interval is invalid", __func__, __LINE__);
950✔
1746
      PLAN_ERR_JRET(TSDB_CODE_PLAN_INTERNAL_ERROR);
×
1747
    } else {
1748
      pInterpFunc->surroundingTime = ((SValueNode*)pRangeInterval)->datum.i;
1,548,178✔
1749
    }
1750
  }
1751

1752

1753
  // set the output
1754
  PLAN_ERR_JRET(createColumnByRewriteExprs(pInterpFunc->pFuncs, &pInterpFunc->node.pTargets));
3,693,648✔
1755

1756
  *pLogicNode = (SLogicNode*)pInterpFunc;
3,694,598✔
1757
  return code;
3,693,648✔
1758

1759
_return:
×
1760
  planError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1761
  nodesDestroyNode((SNode*)pInterpFunc);
×
1762
  return code;
×
1763
}
1764

1765
static bool isForecastFunc(int32_t funcId) {
×
1766
  return fmIsForecastFunc(funcId) || fmIsAnalysisPseudoColumnFunc(funcId) || fmIsGroupKeyFunc(funcId) ||
×
1767
         fmisSelectGroupConstValueFunc(funcId);
×
1768
}
1769

1770
static int32_t createForecastFuncLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,004,615✔
1771
  if (!pSelect->hasForecastFunc) {
445,004,615✔
1772
    return TSDB_CODE_SUCCESS;
445,038,689✔
1773
  }
1774

1775
  SForecastFuncLogicNode* pForecastFunc = NULL;
489✔
1776
  int32_t                 code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC, (SNode**)&pForecastFunc);
×
1777
  if (NULL == pForecastFunc) {
×
1778
    return code;
×
1779
  }
1780

1781
  pForecastFunc->node.groupAction = getGroupAction(pCxt, pSelect);
×
1782
  pForecastFunc->node.requireDataOrder = getRequireDataOrder(true, pSelect);
×
1783
  pForecastFunc->node.resultDataOrder = pForecastFunc->node.requireDataOrder;
×
1784

1785
  // interp functions and _group_key functions
1786
  code = nodesCollectFuncs(pSelect, SQL_CLAUSE_SELECT, NULL, isForecastFunc, &pForecastFunc->pFuncs);
×
1787
  if (TSDB_CODE_SUCCESS == code) {
×
1788
    code = rewriteExprsForSelect(pForecastFunc->pFuncs, pSelect, SQL_CLAUSE_SELECT, NULL);
×
1789
  }
1790

1791
  // set the output
1792
  if (TSDB_CODE_SUCCESS == code) {
×
1793
    code = createColumnByRewriteExprs(pForecastFunc->pFuncs, &pForecastFunc->node.pTargets);
×
1794
  }
1795

1796
  if (TSDB_CODE_SUCCESS == code) {
×
1797
    *pLogicNode = (SLogicNode*)pForecastFunc;
×
1798
  } else {
1799
    nodesDestroyNode((SNode*)pForecastFunc);
×
1800
  }
1801

1802
  return code;
×
1803
}
1804

1805
static bool isGenericAnalysisFunc(int32_t funcId) {
×
1806
  return fmIsImputationCorrelationFunc(funcId) || fmIsGroupKeyFunc(funcId) || fmisSelectGroupConstValueFunc(funcId) ||
×
1807
         fmIsAnalysisPseudoColumnFunc(funcId);
×
1808
}
1809

1810
static int32_t createGenericAnalysisLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,005,428✔
1811
  if (!pSelect->hasGenericAnalysisFunc) {
445,005,428✔
1812
    return TSDB_CODE_SUCCESS;
445,040,248✔
1813
  }
1814

1815
  SGenericAnalysisLogicNode * pFunc = NULL;
266✔
1816
  int32_t                 code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_ANALYSIS_FUNC, (SNode**)&pFunc);
×
1817
  if (NULL == pFunc) {
×
1818
    return code;
×
1819
  }
1820

1821
  pFunc->node.groupAction = getGroupAction(pCxt, pSelect);
×
1822
  pFunc->node.requireDataOrder = getRequireDataOrder(true, pSelect);
×
1823
  pFunc->node.resultDataOrder = pFunc->node.requireDataOrder;
×
1824

1825
  // interp functions and _group_key functions
1826
  code = nodesCollectFuncs(pSelect, SQL_CLAUSE_SELECT, NULL, isGenericAnalysisFunc, &pFunc->pFuncs);
×
1827
  if (TSDB_CODE_SUCCESS == code) {
×
1828
    code = rewriteExprsForSelect(pFunc->pFuncs, pSelect, SQL_CLAUSE_SELECT, NULL);
×
1829
  }
1830

1831
  // set the output
1832
  if (TSDB_CODE_SUCCESS == code) {
×
1833
    code = createColumnByRewriteExprs(pFunc->pFuncs, &pFunc->node.pTargets);
×
1834
  }
1835

1836
  if (TSDB_CODE_SUCCESS == code) {
×
1837
    *pLogicNode = (SLogicNode*)pFunc;
×
1838
  } else {
1839
    nodesDestroyNode((SNode*)pFunc);
×
1840
  }
1841

1842
  return code;
×
1843
}
1844

1845
static int32_t createWindowLogicNodeFinalize(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SWindowLogicNode* pWindow,
34,574,219✔
1846
                                             SLogicNode** pLogicNode) {
1847
  pWindow->node.inputTsOrder = ORDER_UNKNOWN;
34,574,219✔
1848
  pWindow->node.outputTsOrder = ORDER_ASC;
34,574,219✔
1849

1850
  int32_t code = nodesCollectFuncs(pSelect, SQL_CLAUSE_WINDOW, NULL, fmIsWindowClauseFunc, &pWindow->pFuncs);
34,574,219✔
1851
  if (TSDB_CODE_SUCCESS == code) {
34,584,993✔
1852
    code = rewriteExprsForSelect(pWindow->pFuncs, pSelect, SQL_CLAUSE_WINDOW, NULL);
34,585,571✔
1853
  }
1854

1855
  if (TSDB_CODE_SUCCESS == code) {
34,584,043✔
1856
    code = createColumnByRewriteExprs(pWindow->pFuncs, &pWindow->node.pTargets);
34,584,974✔
1857
  }
1858

1859
  if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pHaving) {
34,584,760✔
1860
    code = nodesCloneNode(pSelect->pHaving, &pWindow->node.pConditions);
20,816✔
1861
  }
1862

1863
  pSelect->hasAggFuncs = false;
34,579,597✔
1864

1865
  if (TSDB_CODE_SUCCESS == code) {
34,579,597✔
1866
    *pLogicNode = (SLogicNode*)pWindow;
34,579,597✔
1867
  } else {
1868
    nodesDestroyNode((SNode*)pWindow);
×
1869
  }
1870

1871
  return code;
34,582,059✔
1872
}
1873

1874
static int32_t createExternalWindowLogicNodeFinalize(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SWindowLogicNode* pWindow,
208,967✔
1875
                                                     SLogicNode** pLogicNode) {
1876
  pWindow->node.inputTsOrder = ORDER_ASC;
208,967✔
1877
  pWindow->node.outputTsOrder = ORDER_ASC;
208,967✔
1878

1879
  int32_t code = TSDB_CODE_SUCCESS;
208,967✔
1880
  SNodeList* pOutputPartitionKeys = NULL;
208,967✔
1881
  // no agg func
1882
  if (pSelect->pWindow && nodeType(pSelect->pWindow) != QUERY_NODE_EXTERNAL_WINDOW) {
208,967✔
1883
    // just copy targets from child node, since the window node will process the functions
NEW
1884
    PLAN_ERR_RET(nodesCloneList(pCxt->pCurrRoot->pTargets, &pWindow->node.pTargets));
×
NEW
1885
    pWindow->node.requireDataOrder = pCxt->pCurrRoot->resultDataOrder;
×
NEW
1886
    pWindow->node.resultDataOrder = pCxt->pCurrRoot->resultDataOrder;
×
1887
  } else {
1888
    if (!pSelect->hasAggFuncs) {
208,967✔
1889
      if (pSelect->hasIndefiniteRowsFunc) {
27,383✔
1890
        pWindow->node.requireDataOrder = getRequireDataOrder(pSelect->hasTimeLineFunc, pSelect);
3,605✔
1891
        pWindow->node.resultDataOrder = pWindow->node.requireDataOrder;
3,605✔
1892
        nodesDestroyList(pWindow->pFuncs);
3,605✔
1893
        pWindow->pFuncs = NULL;
3,605✔
1894
        PLAN_ERR_RET(nodesCollectFuncs(pSelect, SQL_CLAUSE_EXT_WINDOW, NULL, fmIsStreamVectorFunc, &pWindow->pFuncs));
3,605✔
1895
        PLAN_ERR_RET(rewriteExprsForSelect(pWindow->pFuncs, pSelect, SQL_CLAUSE_EXT_WINDOW, NULL));
3,605✔
1896
        PLAN_ERR_RET(createColumnByRewriteExprs(pWindow->pFuncs, &pWindow->node.pTargets));
3,605✔
1897
        pWindow->indefRowsFunc = true;
3,605✔
1898
        pSelect->hasIndefiniteRowsFunc = false;
3,605✔
1899
      } else {
1900
        pWindow->node.requireDataOrder = DATA_ORDER_LEVEL_NONE;
23,778✔
1901
        pWindow->node.resultDataOrder = DATA_ORDER_LEVEL_NONE;
23,778✔
1902
        PLAN_ERR_RET(nodesCloneList(pSelect->pProjectionList, &pWindow->pProjs));
23,778✔
1903
        PLAN_ERR_RET(rewriteExprsForSelect(pWindow->pProjs, pSelect, SQL_CLAUSE_EXT_WINDOW, NULL));
23,778✔
1904

1905
        // Supplement projection with ORDER BY simple columns (COLUMN) as hidden columns,
1906
        // so upper Sort can bind keys above external_window using child output slots.
1907
        if (pSelect->pOrderByList && LIST_LENGTH(pSelect->pOrderByList) > 0) {
23,778✔
1908
          SNode* pOB = NULL;
13,158✔
1909
          FOREACH(pOB, pSelect->pOrderByList) {
38,620✔
1910
            SNode* pExpr = (nodeType(pOB) == QUERY_NODE_ORDER_BY_EXPR) ? ((SOrderByExprNode*)pOB)->pExpr : pOB;
25,462✔
1911
            if (pExpr == NULL || QUERY_NODE_COLUMN != nodeType(pExpr)) {
25,462✔
NEW
1912
              continue;
×
1913
            }
1914

1915
            SColumnNode* pCol = (SColumnNode*)pExpr;
25,462✔
1916
            if (0 == strcmp(pCol->colName, "*")) {
25,462✔
NEW
1917
              continue;
×
1918
            }
1919

1920
            // Deduplicate: skip when pProjs already contains same column name or alias.
1921
            bool exists = false;
25,462✔
1922
            SNode* pProj = NULL;
25,462✔
1923
            FOREACH(pProj, pWindow->pProjs) {
57,147✔
1924
              if (!nodesIsExprNode(pProj)) {
52,614✔
NEW
1925
                continue;
×
1926
              }
1927

1928
              const char* a1 = ((SExprNode*)pProj)->aliasName;
52,614✔
1929
              const char* a2 = ((SExprNode*)pExpr)->aliasName;
52,614✔
1930
              if (a1[0] != '\0' && a2[0] != '\0' && strcasecmp(a1, a2) == 0) {
52,614✔
1931
                exists = true;
18,059✔
1932
                break;
18,059✔
1933
              }
1934

1935
              if (QUERY_NODE_COLUMN == nodeType(pProj)) {
34,555✔
1936
                const char* c1 = ((SColumnNode*)pProj)->colName;
11,489✔
1937
                if (strcasecmp(c1, pCol->colName) == 0) {
11,489✔
1938
                  exists = true;
2,870✔
1939
                  break;
2,870✔
1940
                }
1941
              }
1942
            }
1943

1944
            if (exists) {
25,462✔
1945
              continue;
20,929✔
1946
            }
1947

1948
            // Append a cloned column and backfill stable aliases.
1949
            SNode* pClone = NULL;
4,533✔
1950
            PLAN_ERR_RET(nodesCloneNode(pExpr, &pClone));
4,533✔
1951
            if (nodesIsExprNode(pClone)) {
4,533✔
1952
              SExprNode* pE = (SExprNode*)pClone;
4,533✔
1953
              if (pE->aliasName[0] == '\0') {
4,533✔
NEW
1954
                tstrncpy(pE->aliasName, ((SColumnNode*)pClone)->colName, TSDB_COL_NAME_LEN);
×
1955
              }
1956
              if (pE->userAlias[0] == '\0') {
4,533✔
NEW
1957
                tstrncpy(pE->userAlias, ((SColumnNode*)pClone)->colName, TSDB_COL_NAME_LEN);
×
1958
              }
1959
            }
1960

1961
            PLAN_ERR_RET(nodesListMakeStrictAppend(&pWindow->pProjs, pClone));
4,533✔
1962
          }
1963
        }
1964

1965
        PLAN_ERR_RET(createColumnByRewriteExprs(pWindow->pProjs, &pWindow->node.pTargets));
23,778✔
1966
      }
1967
    } else {
1968
      // has agg func, collect again with placeholder func
1969
      pWindow->node.requireDataOrder = getRequireDataOrder(pSelect->hasTimeLineFunc, pSelect);
181,584✔
1970
      pWindow->node.resultDataOrder = pSelect->onlyHasKeepOrderFunc ? pWindow->node.requireDataOrder : DATA_ORDER_LEVEL_NONE;
181,584✔
1971
      nodesDestroyList(pWindow->pFuncs);
181,584✔
1972
      pWindow->pFuncs = NULL;
181,584✔
1973
      PLAN_ERR_RET(nodesCollectFuncs(pSelect, SQL_CLAUSE_EXT_WINDOW, NULL, fmIsStreamWindowClauseFunc, &pWindow->pFuncs));
181,584✔
1974
      PLAN_ERR_RET(rewriteExprsForSelect(pWindow->pFuncs, pSelect, SQL_CLAUSE_EXT_WINDOW, NULL));
181,584✔
1975

1976
      if (NULL != pSelect->pPartitionByList) {
181,584✔
1977
        SNodeList* pPartKeys = NULL;
43,578✔
1978
        PLAN_ERR_RET(nodesCloneList(pSelect->pPartitionByList, &pPartKeys));
43,578✔
1979
        code = rewriteExprsForSelect(pPartKeys, pSelect, SQL_CLAUSE_EXT_WINDOW, &pOutputPartitionKeys);
43,578✔
1980
        nodesDestroyList(pPartKeys);
43,578✔
1981
        PLAN_ERR_RET(code);
43,578✔
1982

1983
        if (NULL != pOutputPartitionKeys) {
43,578✔
1984
          SNode* pPartKey = NULL;
37,422✔
1985
          FOREACH(pPartKey, pOutputPartitionKeys) {
74,844✔
1986
            if (QUERY_NODE_COLUMN != nodeType(pPartKey)) {
37,422✔
NEW
1987
              planError("external window partition key must be column node, nodeType:%d", nodeType(pPartKey));
×
NEW
1988
              PLAN_ERR_RET(TSDB_CODE_PLAN_INTERNAL_ERROR);
×
1989
            }
1990

1991
            SFunctionNode* pGroupKey = createGroupKeyAggFunc((SColumnNode*)pPartKey);
37,422✔
1992
            if (NULL == pGroupKey) {
37,422✔
NEW
1993
              PLAN_ERR_RET(terrno);
×
1994
            }
1995
            tstrncpy(pGroupKey->node.aliasName, ((SExprNode*)pPartKey)->aliasName, TSDB_COL_NAME_LEN);
37,422✔
1996
            tstrncpy(pGroupKey->node.userAlias, ((SExprNode*)pPartKey)->userAlias, TSDB_COL_NAME_LEN);
37,422✔
1997
            PLAN_ERR_RET(nodesListMakeStrictAppend(&pWindow->pFuncs, (SNode*)pGroupKey));
37,422✔
1998
          }
1999
        }
2000
      }
2001

2002
      // Keep logic targets aligned with the physical external-window output order:
2003
      // function outputs are materialized before projection outputs, and split Exchange
2004
      // nodes clone targets from the logic child.
2005
      PLAN_ERR_RET(createColumnByRewriteExprs(pWindow->pFuncs, &pWindow->node.pTargets));
181,584✔
2006

2007
      SNodeList* pProjTargets = NULL;
181,584✔
2008
      PLAN_ERR_RET(nodesCloneList(pWindow->pProjs, &pProjTargets));
181,584✔
2009
      PLAN_ERR_RET(rewriteExprsForSelect(pProjTargets, pSelect, SQL_CLAUSE_EXT_WINDOW, NULL));
181,584✔
2010
      PLAN_ERR_RET(createColumnByRewriteExprs(pProjTargets, &pWindow->node.pTargets));
181,584✔
2011
      nodesDestroyList(pProjTargets);
181,584✔
2012
      
2013
      pSelect->hasAggFuncs = false;
181,584✔
2014
    }
2015
  }
2016

2017
  pWindow->inputHasOrder = (pWindow->isSingleTable || pWindow->node.requireDataOrder == DATA_ORDER_LEVEL_GLOBAL);
208,967✔
2018

2019
  if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pHaving) {
208,967✔
2020
    pWindow->node.pConditions = NULL;
9,836✔
2021
    code = nodesCloneNode(pSelect->pHaving, &pWindow->node.pConditions);
9,836✔
2022
  }
2023

2024
  nodesDestroyList(pOutputPartitionKeys);
208,967✔
2025

2026
  *pLogicNode = (SLogicNode*)pWindow;
208,967✔
2027

2028
  return code;
208,967✔
2029
}
2030

2031
static int32_t createWindowLogicNodeByState(SLogicPlanContext* pCxt, SStateWindowNode* pState, SSelectStmt* pSelect,
4,383,509✔
2032
                                            SLogicNode** pLogicNode) {
2033
  SWindowLogicNode* pWindow = NULL;
4,383,509✔
2034
  int32_t           code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow);
4,383,509✔
2035
  if (NULL == pWindow) {
4,385,491✔
2036
    return code;
×
2037
  }
2038

2039
  pWindow->winType = WINDOW_TYPE_STATE;
4,385,491✔
2040
  pWindow->node.groupAction = getGroupAction(pCxt, pSelect);
4,385,491✔
2041
  pWindow->node.requireDataOrder = getRequireDataOrder(true, pSelect);
4,384,365✔
2042
  pWindow->node.resultDataOrder = pWindow->node.requireDataOrder;
4,384,384✔
2043
  pWindow->pStateExpr = NULL;
4,384,384✔
2044
  pWindow->partType |= (pSelect->pPartitionByList && pSelect->pPartitionByList->length > 0) ? WINDOW_PART_HAS : 0;
4,384,384✔
2045
  pWindow->partType |= (pSelect->pPartitionByList && keysHasTbname(pSelect->pPartitionByList)) ? WINDOW_PART_TB : 0;
4,384,384✔
2046
  code = nodesCloneNode(pState->pExpr, &pWindow->pStateExpr);
4,384,384✔
2047
  if (TSDB_CODE_SUCCESS != code) {
4,385,573✔
2048
    nodesDestroyNode((SNode*)pWindow);
×
2049
    return code;
×
2050
  }
2051
  code = nodesCloneNode(pState->pCol, &pWindow->pTspk);
4,385,573✔
2052
  if (TSDB_CODE_SUCCESS != code) {
4,385,260✔
2053
    nodesDestroyNode((SNode*)pWindow);
×
2054
    return code;
×
2055
  }
2056
  if (pState->pExtend) {
4,385,260✔
2057
    pWindow->extendOption = ((SValueNode*)pState->pExtend)->datum.i;
410,458✔
2058
  }
2059
  if (pState->pTrueForLimit) {
4,385,260✔
2060
    if (QUERY_NODE_VALUE == nodeType(pState->pTrueForLimit)) {
6,000✔
2061
      pWindow->trueForType = TRUE_FOR_DURATION_ONLY;
1,500✔
2062
      pWindow->trueForCount = 0;
1,500✔
2063
      pWindow->trueForDuration = ((SValueNode*)pState->pTrueForLimit)->datum.i;
1,500✔
2064
    } else {
2065
      pWindow->trueForType = ((STrueForNode*)pState->pTrueForLimit)->trueForType;
4,500✔
2066
      pWindow->trueForCount = ((STrueForNode*)pState->pTrueForLimit)->count;
4,500✔
2067
      SNode* pDuration = ((STrueForNode*)pState->pTrueForLimit)->pDuration;
4,500✔
2068
      pWindow->trueForDuration = pDuration ? ((SValueNode*)pDuration)->datum.i : 0;
4,500✔
2069
    }
2070
  }
2071
  // rewrite the expression in subsequent clauses
2072
  code = rewriteExprForSelect(pWindow->pStateExpr, pSelect, SQL_CLAUSE_WINDOW);
4,385,260✔
2073
  if (TSDB_CODE_SUCCESS == code) {
4,384,737✔
2074
    code = createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
4,385,527✔
2075
  } else {
2076
    nodesDestroyNode((SNode*)pWindow);
×
2077
  }
2078

2079
  return code;
4,385,578✔
2080
}
2081

2082
static int32_t createWindowLogicNodeBySession(SLogicPlanContext* pCxt, SSessionWindowNode* pSession,
5,324,505✔
2083
                                              SSelectStmt* pSelect, SLogicNode** pLogicNode) {
2084
  SWindowLogicNode* pWindow = NULL;
5,324,505✔
2085
  int32_t           code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow);
5,324,505✔
2086
  if (NULL == pWindow) {
5,326,751✔
2087
    return code;
×
2088
  }
2089

2090
  pWindow->winType = WINDOW_TYPE_SESSION;
5,326,751✔
2091
  pWindow->sessionGap = ((SValueNode*)pSession->pGap)->datum.i;
5,326,751✔
2092

2093
  pWindow->node.groupAction = getGroupAction(pCxt, pSelect);
5,326,751✔
2094
  pWindow->node.requireDataOrder = getRequireDataOrder(true, pSelect);
5,325,565✔
2095
  pWindow->node.resultDataOrder = pWindow->node.requireDataOrder;
5,326,393✔
2096
  pWindow->partType |= (pSelect->pPartitionByList && pSelect->pPartitionByList->length > 0) ? WINDOW_PART_HAS : 0;
5,326,393✔
2097
  pWindow->partType |= (pSelect->pPartitionByList && keysHasTbname(pSelect->pPartitionByList)) ? WINDOW_PART_TB : 0;
5,326,393✔
2098

2099
  pWindow->pTspk = NULL;
5,326,393✔
2100
  code = nodesCloneNode((SNode*)pSession->pCol, &pWindow->pTspk);
5,326,393✔
2101
  if (NULL == pWindow->pTspk) {
5,326,156✔
2102
    nodesDestroyNode((SNode*)pWindow);
×
2103
    return code;
×
2104
  }
2105
  pWindow->pTsEnd = NULL;
5,326,156✔
2106
  code = nodesCloneNode((SNode*)pSession->pCol, &pWindow->pTsEnd);
5,326,156✔
2107
  if (TSDB_CODE_SUCCESS != code) {
5,327,477✔
2108
    nodesDestroyNode((SNode*)pWindow);
×
2109
    return code;
×
2110
  }
2111

2112
  return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
5,327,477✔
2113
}
2114

2115
static int32_t createWindowLogicNodeByInterval(SLogicPlanContext* pCxt, SIntervalWindowNode* pInterval,
17,438,417✔
2116
                                               SSelectStmt* pSelect, SLogicNode** pLogicNode) {
2117
  SWindowLogicNode* pWindow = NULL;
17,438,417✔
2118
  int32_t           code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow);
17,438,417✔
2119
  if (NULL == pWindow) {
17,446,018✔
2120
    return code;
×
2121
  }
2122

2123
  pWindow->winType = WINDOW_TYPE_INTERVAL;
17,446,018✔
2124
  pWindow->interval = ((SValueNode*)pInterval->pInterval)->datum.i;
17,446,018✔
2125
  pWindow->intervalUnit = ((SValueNode*)pInterval->pInterval)->unit;
17,446,018✔
2126
  pWindow->offset = (NULL != pInterval->pOffset ? ((SValueNode*)pInterval->pOffset)->datum.i : 0);
17,446,018✔
2127
  pWindow->sliding = (NULL != pInterval->pSliding ? ((SValueNode*)pInterval->pSliding)->datum.i : pWindow->interval);
17,446,018✔
2128
  pWindow->slidingUnit =
45,640,448✔
2129
      (NULL != pInterval->pSliding ? ((SValueNode*)pInterval->pSliding)->unit : pWindow->intervalUnit);
17,446,018✔
2130
  pWindow->windowAlgo = INTERVAL_ALGO_HASH;
17,446,018✔
2131
  pWindow->node.groupAction = (NULL != pInterval->pFill ? GROUP_ACTION_KEEP : getGroupAction(pCxt, pSelect));
17,446,018✔
2132
  pWindow->node.requireDataOrder = (pSelect->hasTimeLineFunc ? getRequireDataOrder(true, pSelect) : DATA_ORDER_LEVEL_NONE);
17,443,323✔
2133
  pWindow->node.resultDataOrder = getRequireDataOrder(true, pSelect);
17,443,323✔
2134
  pWindow->pTspk = NULL;
17,444,120✔
2135
  code = nodesCloneNode(pInterval->pCol, &pWindow->pTspk);
17,444,120✔
2136
  if (NULL == pWindow->pTspk) {
17,444,756✔
2137
    nodesDestroyNode((SNode*)pWindow);
×
2138
    return code;
×
2139
  }
2140
  pWindow->partType |= (pSelect->pPartitionByList && pSelect->pPartitionByList->length > 0) ? WINDOW_PART_HAS : 0;
17,444,756✔
2141
  pWindow->partType |= (pSelect->pPartitionByList && keysHasTbname(pSelect->pPartitionByList)) ? WINDOW_PART_TB : 0;
17,444,756✔
2142
  pWindow->timeRange = pInterval->timeRange;
17,445,109✔
2143

2144
  return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
17,445,109✔
2145
}
2146

2147
static int32_t createWindowLogicNodeByEvent(SLogicPlanContext* pCxt, SEventWindowNode* pEvent, SSelectStmt* pSelect,
3,884,770✔
2148
                                            SLogicNode** pLogicNode) {
2149
  SWindowLogicNode* pWindow = NULL;
3,884,770✔
2150
  int32_t           code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow);
3,884,770✔
2151
  if (NULL == pWindow) {
3,886,637✔
2152
    return code;
×
2153
  }
2154

2155
  pWindow->winType = WINDOW_TYPE_EVENT;
3,886,637✔
2156
  pWindow->node.groupAction = getGroupAction(pCxt, pSelect);
3,886,637✔
2157
  pWindow->node.requireDataOrder = getRequireDataOrder(true, pSelect);
3,885,940✔
2158
  pWindow->node.resultDataOrder =  pWindow->node.requireDataOrder;
3,886,681✔
2159
  pWindow->pStartCond = NULL;
3,886,681✔
2160
  code = nodesCloneNode(pEvent->pStartCond, &pWindow->pStartCond);
3,886,681✔
2161
  if (TSDB_CODE_SUCCESS != code) {
3,886,601✔
2162
    nodesDestroyNode((SNode*)pWindow);
×
2163
    return code;
×
2164
  }
2165
  code = nodesCloneNode(pEvent->pEndCond, &pWindow->pEndCond);
3,886,601✔
2166
  if (TSDB_CODE_SUCCESS != code) {
3,886,252✔
2167
    nodesDestroyNode((SNode*)pWindow);
×
2168
    return code;
×
2169
  }
2170
  code = nodesCloneNode(pEvent->pCol, &pWindow->pTspk);
3,886,252✔
2171
  if (TSDB_CODE_SUCCESS != code) {
3,886,712✔
2172
    nodesDestroyNode((SNode*)pWindow);
×
2173
    return code;
×
2174
  }
2175
  if (NULL == pWindow->pStartCond || NULL == pWindow->pEndCond || NULL == pWindow->pTspk) {
3,886,712✔
2176
    nodesDestroyNode((SNode*)pWindow);
511✔
2177
    return TSDB_CODE_OUT_OF_MEMORY;
×
2178
  }
2179
  if (pEvent->pTrueForLimit) {
3,886,201✔
2180
    if (QUERY_NODE_VALUE == nodeType(pEvent->pTrueForLimit)) {
66,108✔
2181
      pWindow->trueForType = TRUE_FOR_DURATION_ONLY;
16,527✔
2182
      pWindow->trueForCount = 0;
16,527✔
2183
      pWindow->trueForDuration = ((SValueNode*)pEvent->pTrueForLimit)->datum.i;
16,527✔
2184
    } else {
2185
      pWindow->trueForType = ((STrueForNode*)pEvent->pTrueForLimit)->trueForType;
49,581✔
2186
      pWindow->trueForCount = ((STrueForNode*)pEvent->pTrueForLimit)->count;
49,581✔
2187
      SNode* pDuration = ((STrueForNode*)pEvent->pTrueForLimit)->pDuration;
49,581✔
2188
      pWindow->trueForDuration = pDuration ? ((SValueNode*)pDuration)->datum.i : 0;
49,581✔
2189
    }
2190
  }
2191
  pWindow->partType |= (pSelect->pPartitionByList && pSelect->pPartitionByList->length > 0) ? WINDOW_PART_HAS : 0;
3,886,201✔
2192
  pWindow->partType |= (pSelect->pPartitionByList && keysHasTbname(pSelect->pPartitionByList)) ? WINDOW_PART_TB : 0;
3,886,201✔
2193

2194
  return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
3,886,201✔
2195
}
2196

2197
static int32_t createWindowLogicNodeByCount(SLogicPlanContext* pCxt, SCountWindowNode* pCount, SSelectStmt* pSelect,
3,536,674✔
2198
                                            SLogicNode** pLogicNode) {
2199
  SWindowLogicNode* pWindow = NULL;
3,536,674✔
2200
  int32_t           code = TSDB_CODE_SUCCESS;
3,536,674✔
2201

2202
  PLAN_ERR_JRET(nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow));
3,536,674✔
2203

2204
  pWindow->winType = WINDOW_TYPE_COUNT;
3,537,965✔
2205
  pWindow->node.groupAction = getGroupAction(pCxt, pSelect);
3,537,965✔
2206
  pWindow->node.requireDataOrder = getRequireDataOrder(true, pSelect);
3,537,269✔
2207
  pWindow->node.resultDataOrder = pWindow->node.requireDataOrder;
3,537,155✔
2208
  pWindow->windowCount = pCount->windowCount;
3,537,155✔
2209
  pWindow->windowSliding = pCount->windowSliding;
3,537,155✔
2210
  pWindow->pTspk = NULL;
3,537,155✔
2211
  pWindow->partType |= (pSelect->pPartitionByList && pSelect->pPartitionByList->length > 0) ? WINDOW_PART_HAS : 0;
3,537,155✔
2212
  pWindow->partType |= (pSelect->pPartitionByList && keysHasTbname(pSelect->pPartitionByList)) ? WINDOW_PART_TB : 0;
3,537,155✔
2213

2214
  PLAN_ERR_JRET(nodesCloneNode(pCount->pCol, &pWindow->pTspk));
3,537,155✔
2215
  if (pCount->pColList != NULL) {
3,538,123✔
2216
    PLAN_ERR_JRET(nodesCloneList(pCount->pColList, &pWindow->pColList));
25,089✔
2217
  }
2218

2219
  PLAN_ERR_JRET(createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode));
3,538,123✔
2220
  return code;
3,537,174✔
2221

2222
_return:
×
2223
  planError("%s failed, code:%d", __func__, code);
×
2224
  nodesDestroyNode((SNode*)pWindow);
×
2225
  return code;
×
2226
}
2227

2228
static int32_t createWindowLogicNodeByAnomaly(SLogicPlanContext* pCxt, SAnomalyWindowNode* pAnomaly,
×
2229
                                              SSelectStmt* pSelect, SLogicNode** pLogicNode) {
2230
  SWindowLogicNode* pWindow = NULL;
×
2231
  int32_t           code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow);
×
2232
  if (NULL == pWindow) {
×
2233
    return code;
×
2234
  }
2235

2236
  pWindow->winType = WINDOW_TYPE_ANOMALY;
×
2237
  pWindow->node.groupAction = getGroupAction(pCxt, pSelect);
×
2238
  pWindow->node.requireDataOrder = getRequireDataOrder(true, pSelect);
×
2239
  pWindow->node.resultDataOrder = pWindow->node.requireDataOrder;
×
2240

2241
  pWindow->pAnomalyExpr = NULL;
×
2242
  code = nodesCloneList(pAnomaly->pExpr, &pWindow->pAnomalyExpr);
×
2243
  if (TSDB_CODE_SUCCESS != code) {
×
2244
    nodesDestroyNode((SNode*)pWindow);
×
2245
    return code;
×
2246
  }
2247

2248
  tstrncpy(pWindow->anomalyOpt, pAnomaly->anomalyOpt, sizeof(pWindow->anomalyOpt));
×
2249

2250
  pWindow->pTspk = NULL;
×
2251
  code = nodesCloneNode(pAnomaly->pCol, &pWindow->pTspk);
×
2252
  if (NULL == pWindow->pTspk) {
×
2253
    nodesDestroyNode((SNode*)pWindow);
×
2254
    return code;
×
2255
  }
2256

2257
  // rewrite the expression in subsequent clauses
2258
  code = rewriteExprsForSelect(pWindow->pAnomalyExpr, pSelect, SQL_CLAUSE_WINDOW, NULL);
×
2259
  if (TSDB_CODE_SUCCESS == code) {
×
2260
    code = createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
×
2261
  } else {
2262
    nodesDestroyNode((SNode*)pWindow);
×
2263
  }
2264

2265
  return code;
×
2266
}
2267

NEW
2268
static int32_t setColTableInfo(SNode* pFromTable, SColumnNode* pCol) {
×
NEW
2269
  if (NULL == pFromTable || NULL == pCol) {
×
NEW
2270
    return TSDB_CODE_SUCCESS;
×
2271
  }
2272

2273
  // Default to a normal column
NEW
2274
  pCol->colType = COLUMN_TYPE_COLUMN;
×
2275

NEW
2276
  switch (nodeType(pFromTable)) {
×
NEW
2277
    case QUERY_NODE_REAL_TABLE: {
×
NEW
2278
      SRealTableNode* pTable = (SRealTableNode*)pFromTable;
×
NEW
2279
      tstrncpy(pCol->dbName, pTable->table.dbName, TSDB_DB_NAME_LEN);
×
NEW
2280
      tstrncpy(pCol->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
×
NEW
2281
      tstrncpy(pCol->tableAlias, pTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
×
NEW
2282
      if (pTable->pMeta) {
×
NEW
2283
        pCol->tableId = pTable->pMeta->uid;
×
NEW
2284
        pCol->tableType = pTable->pMeta->tableType;
×
2285
      }
NEW
2286
      break;
×
2287
    }
NEW
2288
    case QUERY_NODE_VIRTUAL_TABLE: {
×
NEW
2289
      SVirtualTableNode* pTable = (SVirtualTableNode*)pFromTable;
×
NEW
2290
      tstrncpy(pCol->dbName, pTable->table.dbName, TSDB_DB_NAME_LEN);
×
NEW
2291
      tstrncpy(pCol->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
×
NEW
2292
      tstrncpy(pCol->tableAlias, pTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
×
NEW
2293
      if (pTable->pMeta) {
×
NEW
2294
        pCol->tableId = pTable->pMeta->uid;
×
NEW
2295
        pCol->tableType = pTable->pMeta->tableType;
×
2296
      }
NEW
2297
      break;
×
2298
    }
NEW
2299
    case QUERY_NODE_PLACE_HOLDER_TABLE: {
×
NEW
2300
      SPlaceHolderTableNode* pTable = (SPlaceHolderTableNode*)pFromTable;
×
NEW
2301
      tstrncpy(pCol->dbName, pTable->table.dbName, TSDB_DB_NAME_LEN);
×
NEW
2302
      tstrncpy(pCol->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
×
NEW
2303
      tstrncpy(pCol->tableAlias, pTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
×
NEW
2304
      if (pTable->pMeta) {
×
NEW
2305
        pCol->tableId = pTable->pMeta->uid;
×
NEW
2306
        pCol->tableType = pTable->pMeta->tableType;
×
2307
      }
NEW
2308
      break;
×
2309
    }
NEW
2310
    case QUERY_NODE_TEMP_TABLE: {
×
NEW
2311
      STempTableNode* pTable = (STempTableNode*)pFromTable;
×
NEW
2312
      tstrncpy(pCol->dbName, pTable->table.dbName, TSDB_DB_NAME_LEN);
×
NEW
2313
      tstrncpy(pCol->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
×
NEW
2314
      tstrncpy(pCol->tableAlias, pTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
×
2315
      // temp table may not have meta; leave tableId/tableType unset
NEW
2316
      break;
×
2317
    }
NEW
2318
    case QUERY_NODE_JOIN_TABLE: {
×
2319
      // External window does not apply to joins; minimal alias propagation
NEW
2320
      SJoinTableNode* pTable = (SJoinTableNode*)pFromTable;
×
NEW
2321
      tstrncpy(pCol->dbName, pTable->table.dbName, TSDB_DB_NAME_LEN);
×
NEW
2322
      tstrncpy(pCol->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
×
NEW
2323
      tstrncpy(pCol->tableAlias, pTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
×
NEW
2324
      break;
×
2325
    }
NEW
2326
    default: {
×
2327
      // Fallback: try to copy common table fields if layout matches STableNode
2328
      // No-op if not applicable
NEW
2329
      break;
×
2330
    }
2331
  }
2332

NEW
2333
  return TSDB_CODE_SUCCESS;
×
2334
}
2335

2336
// Helper: create a timestamp comparison operator with a placeholder function on the right
NEW
2337
static int32_t makeTsPlaceholderOp(SNode* pFromTable, EOperatorType opType, const char* funcName, const char* alias,
×
2338
                                   SOperatorNode** pOutOp) {
NEW
2339
  int32_t        code = TSDB_CODE_SUCCESS;
×
NEW
2340
  SFunctionNode* pFunc = NULL;
×
NEW
2341
  SOperatorNode* pOper = NULL;
×
2342

NEW
2343
  code = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&pFunc);
×
NEW
2344
  if (TSDB_CODE_SUCCESS != code || NULL == pFunc) return code;
×
NEW
2345
  tstrncpy(pFunc->functionName, funcName, TSDB_FUNC_NAME_LEN);
×
NEW
2346
  tstrncpy(pFunc->node.userAlias, alias, TSDB_FUNC_NAME_LEN);
×
2347

NEW
2348
  code = nodesMakeNode(QUERY_NODE_OPERATOR, (SNode**)&pOper);
×
NEW
2349
  if (TSDB_CODE_SUCCESS != code || NULL == pOper) {
×
NEW
2350
    nodesDestroyNode((SNode*)pFunc);
×
NEW
2351
    return code;
×
2352
  }
2353

NEW
2354
  pOper->opType = opType;
×
NEW
2355
  code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pOper->pLeft);
×
NEW
2356
  if (TSDB_CODE_SUCCESS != code || NULL == pOper->pLeft) {
×
NEW
2357
    nodesDestroyNode((SNode*)pOper);
×
NEW
2358
    nodesDestroyNode((SNode*)pFunc);
×
NEW
2359
    return code;
×
2360
  }
NEW
2361
  ((SColumnNode*)pOper->pLeft)->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
×
NEW
2362
  ((SColumnNode*)pOper->pLeft)->isPrimTs = true;
×
NEW
2363
  snprintf(((SColumnNode*)pOper->pLeft)->colName, sizeof(((SColumnNode*)pOper->pLeft)->colName), "%s", "_c0");
×
NEW
2364
  setColTableInfo(pFromTable, (SColumnNode*)pOper->pLeft);
×
2365

2366

NEW
2367
  code = nodesCloneNode((SNode*)pFunc, &pOper->pRight);
×
NEW
2368
  nodesDestroyNode((SNode*)pFunc); // function node no longer needed after clone
×
NEW
2369
  if (TSDB_CODE_SUCCESS != code) {
×
NEW
2370
    nodesDestroyNode((SNode*)pOper);
×
NEW
2371
    return code;
×
2372
  }
2373

NEW
2374
  *pOutOp = pOper;
×
NEW
2375
  return TSDB_CODE_SUCCESS;
×
2376
}
2377

NEW
2378
static int32_t buildDefaultTimeRangeForExternalWindow(SLogicPlanContext* pCxt, SSelectStmt* pSelect) {
×
NEW
2379
  if (pSelect->pWindow == NULL || nodeType(pSelect->pWindow) != QUERY_NODE_EXTERNAL_WINDOW ||
×
NEW
2380
      pSelect->pTimeRange != NULL) {
×
NEW
2381
    return TSDB_CODE_SUCCESS;
×
2382
  }
NEW
2383
  int32_t         code = TSDB_CODE_SUCCESS;
×
NEW
2384
  STimeRangeNode* pTimeRange = NULL;
×
NEW
2385
  SOperatorNode*  pStartOp = NULL;
×
NEW
2386
  SOperatorNode*  pEndOp = NULL;
×
2387

NEW
2388
  code = nodesMakeNode(QUERY_NODE_TIME_RANGE, (SNode**)&pTimeRange);
×
NEW
2389
  if (TSDB_CODE_SUCCESS != code || NULL == pTimeRange) return code;
×
2390

NEW
2391
  pTimeRange->pStart = NULL;
×
NEW
2392
  pTimeRange->pEnd = NULL;
×
NEW
2393
  pTimeRange->needCalc = false;
×
2394

2395
  // ts >= _twstart, ts < _twend
NEW
2396
  code = makeTsPlaceholderOp(pSelect->pFromTable, OP_TYPE_GREATER_EQUAL, "_twstart", "_twstart", &pStartOp);
×
NEW
2397
  if (TSDB_CODE_SUCCESS != code || NULL == pStartOp) {
×
NEW
2398
    nodesDestroyNode((SNode*)pTimeRange);
×
NEW
2399
    return code;
×
2400
  }
NEW
2401
  code = makeTsPlaceholderOp(pSelect->pFromTable, OP_TYPE_LOWER_THAN, "_twend", "_twend", &pEndOp);
×
NEW
2402
  if (TSDB_CODE_SUCCESS != code || NULL == pEndOp) {
×
NEW
2403
    nodesDestroyNode((SNode*)pStartOp);
×
NEW
2404
    nodesDestroyNode((SNode*)pTimeRange);
×
NEW
2405
    return code;
×
2406
  }
2407

NEW
2408
  pTimeRange->pStart = (SNode*)pStartOp;
×
NEW
2409
  pTimeRange->pEnd = (SNode*)pEndOp;
×
NEW
2410
  pSelect->pTimeRange = (SNode*)pTimeRange;
×
NEW
2411
  return TSDB_CODE_SUCCESS;
×
2412
}
2413

2414
static int32_t createWindowLogicNodeByExternal(SLogicPlanContext* pCxt, SExternalWindowNode* pExternal,
119,953✔
2415
                                               SSelectStmt* pSelect, SLogicNode** pLogicNode) {
2416
  pCxt->pPlanCxt->streamCxt.hasExtWindow = true;
119,953✔
2417

2418
  SWindowLogicNode* pWindow = NULL;
119,953✔
2419
  int32_t           code = TSDB_CODE_SUCCESS;
119,953✔
2420

2421
  PLAN_ERR_JRET(nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow));
119,953✔
2422

2423
  pWindow->winType = WINDOW_TYPE_EXTERNAL;
119,953✔
2424
  pWindow->node.groupAction = GROUP_ACTION_NONE;
119,953✔
2425
  pWindow->node.requireDataOrder = DATA_ORDER_LEVEL_GLOBAL;
119,953✔
2426
  pWindow->node.resultDataOrder = (NULL != pSelect->pPartitionByList ? DATA_ORDER_LEVEL_IN_GROUP : DATA_ORDER_LEVEL_GLOBAL);
119,953✔
2427
  pWindow->calcWithPartition = (NULL != pSelect->pPartitionByList);
119,953✔
2428
  pWindow->needGroupSort = false;
119,953✔
2429
  pWindow->partType = 0;
119,953✔
2430
  pWindow->pTspk = NULL;
119,953✔
2431
  bool isPartTb = pSelect->pPartitionByList ? keysHasTbname(pSelect->pPartitionByList) : 0;
119,953✔
2432
  if (nodeType(pSelect->pFromTable) == QUERY_NODE_REAL_TABLE) {
119,953✔
2433
    SRealTableNode* pTable = (SRealTableNode*)pSelect->pFromTable;
114,227✔
2434
    if (pTable->pMeta->tableType == TSDB_NORMAL_TABLE || pTable->pMeta->tableType == TSDB_CHILD_TABLE || isPartTb) {
114,227✔
2435
      pWindow->isSingleTable = true;
37,922✔
2436
    } else {
2437
      pWindow->isSingleTable = false;
76,305✔
2438
    }
2439
  } else if (nodeType(pSelect->pFromTable) == QUERY_NODE_VIRTUAL_TABLE) {
5,726✔
2440
    SVirtualTableNode* pTable = (SVirtualTableNode*)pSelect->pFromTable;
5,726✔
2441
    if (pTable->pMeta->tableType == TSDB_VIRTUAL_NORMAL_TABLE || pTable->pMeta->tableType == TSDB_VIRTUAL_CHILD_TABLE || isPartTb) {
5,726✔
2442
      pWindow->isSingleTable = true;
2,045✔
2443
    } else {
2444
      pWindow->isSingleTable = false;
3,681✔
2445
    }
2446
  } else {
NEW
2447
    pWindow->isSingleTable = false;
×
2448
  }
2449
  PLAN_ERR_RET(nodesCloneNode(pSelect->pTimeRange, &pWindow->pTimeRange));
119,953✔
2450

2451
  if (NULL == pExternal->pCol) {
119,953✔
NEW
2452
    planError("%s failed, External window can not find pk column", __func__);
×
NEW
2453
    nodesDestroyNode((SNode*)pWindow);
×
NEW
2454
    return TSDB_CODE_PLAN_INTERNAL_ERROR;
×
2455
  }
2456

2457
  PLAN_ERR_RET(nodesCloneNode(pExternal->pCol, &pWindow->pTspk));
119,953✔
2458

2459
  pWindow->pSubquery = pExternal->pSubquery;
119,953✔
2460
  return createExternalWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
119,953✔
2461

NEW
2462
_return:
×
NEW
2463
  planError("%s failed, code:%d", __func__, code);
×
NEW
2464
  nodesDestroyNode((SNode*)pWindow);
×
NEW
2465
  return code;
×
2466
}
2467

2468
static int32_t createWindowLogicNodeByStreamExternal(SLogicPlanContext* pCxt, SExternalWindowNode* pExternal,
89,014✔
2469
                                               SSelectStmt* pSelect, SLogicNode** pLogicNode) {
2470
  SWindowLogicNode* pWindow = NULL;
89,014✔
2471
  int32_t           code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow);
89,014✔
2472
  if (NULL == pWindow) {
89,014✔
2473
    return code;
×
2474
  }
2475

2476
  pWindow->winType = WINDOW_TYPE_EXTERNAL;
89,014✔
2477
  pWindow->node.groupAction = GROUP_ACTION_NONE;
89,014✔
2478
  pWindow->node.requireDataOrder = DATA_ORDER_LEVEL_GLOBAL;
89,014✔
2479
  pWindow->node.resultDataOrder = DATA_ORDER_LEVEL_GLOBAL;
89,014✔
2480
  pWindow->partType = 0;
89,014✔
2481
  pWindow->pTspk = NULL;
89,014✔
2482
  if (nodeType(pSelect->pFromTable) == QUERY_NODE_REAL_TABLE) {
89,014✔
2483
    SRealTableNode* pTable = (SRealTableNode*)pSelect->pFromTable;
60,167✔
2484
    if (pTable->pMeta->tableType == TSDB_NORMAL_TABLE || pTable->pMeta->tableType == TSDB_CHILD_TABLE) {
60,167✔
2485
      pWindow->isSingleTable = true;
11,260✔
2486
    } else {
2487
      pWindow->isSingleTable = false;
48,907✔
2488
    }
2489
  } else if (nodeType(pSelect->pFromTable) == QUERY_NODE_VIRTUAL_TABLE) {
28,847✔
2490
    SVirtualTableNode* pTable = (SVirtualTableNode*)pSelect->pFromTable;
28,847✔
2491
    if (pTable->pMeta->tableType == TSDB_VIRTUAL_NORMAL_TABLE || pTable->pMeta->tableType == TSDB_VIRTUAL_CHILD_TABLE) {
28,847✔
2492
      pWindow->isSingleTable = true;
27,080✔
2493
    } else {
2494
      pWindow->isSingleTable = false;
1,767✔
2495
    }
2496
  } else {
2497
    pWindow->isSingleTable = false;
×
2498
  }
2499
  PLAN_ERR_RET(nodesCloneNode(pSelect->pTimeRange, &pWindow->pTimeRange));
89,014✔
2500

2501
  SNode* pNode = NULL;
89,014✔
2502
  FOREACH(pNode, pCxt->pCurrRoot->pTargets) {
131,686✔
2503
    if (QUERY_NODE_COLUMN == nodeType(pNode)) {
131,686✔
2504
      SColumnNode* pCol = (SColumnNode*)pNode;
131,686✔
2505
      
2506
      if (pCol->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
131,686✔
2507
        PLAN_ERR_RET(nodesCloneNode(pNode, &pWindow->pTspk));
89,014✔
2508
        break;
89,014✔
2509
      }
2510
    }
2511
  }
2512

2513
  if (pWindow->pTspk == NULL) {
89,014✔
2514
    nodesDestroyNode((SNode*)pWindow);
×
2515
    planError("External window can not find pk column, listSize:%d", pCxt->pCurrRoot->pTargets->length);
×
2516
    // TODO(smj): proper error code;
2517
    return TSDB_CODE_PLAN_INTERNAL_ERROR;
×
2518
  }
2519

2520
  pWindow->pSubquery = pExternal->pSubquery;
89,014✔
2521
  return createExternalWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
89,014✔
2522
}
2523
static int32_t createWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,004,789✔
2524
  if (NULL == pSelect->pWindow) {
445,004,789✔
2525
    return TSDB_CODE_SUCCESS;
410,259,831✔
2526
  }
2527
  switch (nodeType(pSelect->pWindow)) {
34,745,864✔
2528
    case QUERY_NODE_STATE_WINDOW:
4,384,478✔
2529
      return createWindowLogicNodeByState(pCxt, (SStateWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
4,384,478✔
2530
    case QUERY_NODE_SESSION_WINDOW:
5,325,171✔
2531
      return createWindowLogicNodeBySession(pCxt, (SSessionWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
5,325,171✔
2532
    case QUERY_NODE_INTERVAL_WINDOW:
17,438,804✔
2533
      return createWindowLogicNodeByInterval(pCxt, (SIntervalWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
17,438,804✔
2534
    case QUERY_NODE_EVENT_WINDOW:
3,884,856✔
2535
      return createWindowLogicNodeByEvent(pCxt, (SEventWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
3,884,856✔
2536
    case QUERY_NODE_COUNT_WINDOW:
3,536,674✔
2537
      return createWindowLogicNodeByCount(pCxt, (SCountWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
3,536,674✔
2538
    case QUERY_NODE_ANOMALY_WINDOW:
×
2539
      return createWindowLogicNodeByAnomaly(pCxt, (SAnomalyWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
×
2540
    case QUERY_NODE_EXTERNAL_WINDOW:
208,967✔
2541
      return TSDB_CODE_SUCCESS;
208,967✔
2542
    default:
×
2543
      break;
×
2544
  }
2545

NEW
2546
  planError("%s failed, unsupported window node type:%d", __func__, nodeType(pSelect->pWindow));
×
NEW
2547
  return TSDB_CODE_PLAN_INVALID_WINDOW_TYPE;
×
2548
}
2549

2550
typedef struct SConditionCheckContext {
2551
  bool    hasNotBasicOp;
2552
  bool    hasNegativeConst;
2553
  bool    hasOtherFunc;
2554
  bool    placeholderAtRight;
2555
  bool    hasPlaceHolder;
2556
  int32_t placeholderType;
2557
} SConditionCheckContext;
2558

2559
static EDealRes conditionOnlyPhAndConstImpl(SNode* pNode, void* pContext) {
448,714,556✔
2560
  SConditionCheckContext* pCxt = (SConditionCheckContext*)pContext;
448,714,556✔
2561
  if (nodeType(pNode) == QUERY_NODE_VALUE) {
448,714,556✔
2562
    SValueNode *pVal = (SValueNode*)pNode;
96,939,985✔
2563
    if (pVal->datum.i < 0) {
96,939,985✔
2564
      pCxt->hasNegativeConst = true;
17,654,004✔
2565
    }
2566
  } else if (nodeType(pNode) == QUERY_NODE_FUNCTION) {
351,774,571✔
2567
    SFunctionNode *pFunc = (SFunctionNode*)pNode;
6,682,252✔
2568
    if(fmIsPlaceHolderFunc(pFunc->funcId)) {
6,682,252✔
2569
      pCxt->hasPlaceHolder = true;
223,447✔
2570
    }
2571
    if (pFunc->funcType == FUNCTION_TYPE_TWSTART ||
6,682,252✔
2572
      pFunc->funcType == FUNCTION_TYPE_TWEND ||
6,579,058✔
2573
      pFunc->funcType == FUNCTION_TYPE_TPREV_TS ||
6,504,769✔
2574
      pFunc->funcType == FUNCTION_TYPE_TNEXT_TS ||
6,504,387✔
2575
      pFunc->funcType == FUNCTION_TYPE_TCURRENT_TS ||
6,504,339✔
2576
      pFunc->funcType == FUNCTION_TYPE_TPREV_LOCALTIME ||
6,501,747✔
2577
      pFunc->funcType == FUNCTION_TYPE_TNEXT_LOCALTIME ||
6,501,574✔
2578
      pFunc->funcType == FUNCTION_TYPE_TLOCALTIME ||
6,500,789✔
2579
      pFunc->funcType == FUNCTION_TYPE_TIDLESTART ||
6,492,906✔
2580
      pFunc->funcType == FUNCTION_TYPE_TIDLEEND) {
6,492,906✔
2581
      pCxt->placeholderType = pFunc->funcType;
189,433✔
2582
    } else if (pFunc->funcType != FUNCTION_TYPE_NOW &&
6,492,819✔
2583
      pFunc->funcType != FUNCTION_TYPE_TODAY &&
6,492,819✔
2584
      pFunc->funcType != FUNCTION_TYPE_CAST) {
6,493,000✔
2585
      pCxt->hasOtherFunc = true;
5,137,812✔
2586
    }
2587
  } else if (nodeType(pNode) == QUERY_NODE_OPERATOR) {
345,092,319✔
2588
    SOperatorNode *pOp = (SOperatorNode*)pNode;
140,131,885✔
2589
    if (!nodesIsBasicArithmeticOp(pOp)) {
140,131,885✔
2590
      pCxt->hasNotBasicOp = true;
137,704,402✔
2591
    }
2592
    if (pOp->opType == OP_TYPE_SUB || pOp->opType == OP_TYPE_DIV) {
140,136,574✔
2593
      if (pOp->pRight) {
46,768✔
2594
        SConditionCheckContext cxt = {.placeholderType = 0};
48,203✔
2595
        nodesWalkExpr(pOp->pRight, conditionOnlyPhAndConstImpl, &cxt);
48,203✔
2596
        pCxt->placeholderAtRight = (cxt.placeholderType != 0);
48,203✔
2597
      }
2598
    }
2599
  }
2600
  return DEAL_RES_CONTINUE;
448,719,245✔
2601
}
2602

2603
static bool placeHolderCanMakeExternalWindow(int32_t startType, int32_t endType) {
×
2604
  switch (startType) {
×
2605
    case FUNCTION_TYPE_TPREV_TS: {
×
2606
      return endType == FUNCTION_TYPE_TCURRENT_TS || endType == FUNCTION_TYPE_TNEXT_TS;
×
2607
    }
2608
    case FUNCTION_TYPE_TCURRENT_TS: {
×
2609
      return endType == FUNCTION_TYPE_TNEXT_TS;
×
2610
    }
2611
    case FUNCTION_TYPE_TWSTART: {
×
2612
      return endType == FUNCTION_TYPE_TWEND;
×
2613
    }
2614
    case FUNCTION_TYPE_TPREV_LOCALTIME: {
×
2615
      return endType == FUNCTION_TYPE_TNEXT_LOCALTIME || endType == FUNCTION_TYPE_TLOCALTIME;
×
2616
    }
2617
    case FUNCTION_TYPE_TLOCALTIME: {
×
2618
      return endType == FUNCTION_TYPE_TNEXT_LOCALTIME;
×
2619
    }
2620
    case FUNCTION_TYPE_TIDLESTART: {
×
2621
      return endType == FUNCTION_TYPE_TIDLEEND;
×
2622
    }
2623
    default: {
×
2624
      return false;
×
2625
    }
2626
  }
2627
}
2628

2629
static bool filterHasPlaceHolderRange(SOperatorNode *pOperator) {
178,132✔
2630
  SNode* pOpLeft = pOperator->pLeft;
178,132✔
2631
  SNode* pOpRight = pOperator->pRight;
178,132✔
2632

2633
  if (pOpLeft == NULL || pOpRight == NULL) {
178,132✔
2634
    return false;
×
2635
  }
2636

2637
  if (nodeType(pOpLeft) == QUERY_NODE_COLUMN) {
178,132✔
2638
    SColumnNode* pTsCol = (SColumnNode*)pOpLeft;
178,132✔
2639
    if (pTsCol->colType != COLUMN_TYPE_COLUMN || pTsCol->colId != PRIMARYKEY_TIMESTAMP_COL_ID) {
178,132✔
2640
      return false;
×
2641
    }
2642
  } else {
2643
    return false;
×
2644
  }
2645

2646
  SConditionCheckContext opCxt = {.hasNotBasicOp = false,
178,132✔
2647
                                  .hasNegativeConst = false,
2648
                                  .hasOtherFunc = false,
2649
                                  .placeholderAtRight = false,
2650
                                  .placeholderType = 0};
2651

2652
  nodesWalkExpr(pOpRight, conditionOnlyPhAndConstImpl, &opCxt);
178,132✔
2653
  if (opCxt.hasNotBasicOp || opCxt.hasNegativeConst || opCxt.hasOtherFunc || opCxt.placeholderAtRight) {
178,132✔
2654
    return false;
×
2655
  }
2656
  return true;
178,132✔
2657
}
2658

2659
static bool logicConditionSatisfyExternalWindow(SLogicConditionNode *pLogicCond) {
104✔
2660
  if (pLogicCond->condType != LOGIC_COND_TYPE_AND || LIST_LENGTH(pLogicCond->pParameterList) == 0) {
104✔
2661
    return false;
×
2662
  }
2663
  SNode *pOperator = NULL;
104✔
2664
  FOREACH(pOperator, pLogicCond->pParameterList) {
312✔
2665
    if (nodeType(pOperator) != QUERY_NODE_OPERATOR) {
208✔
2666
      return false;
×
2667
    }
2668
    if (!filterHasPlaceHolderRange((SOperatorNode*)pOperator)) {
208✔
2669
      return false;
×
2670
    }
2671
  }
2672
  return true;
104✔
2673
}
2674

2675

2676
static bool timeRangeSatisfyExternalWindow(STimeRangeNode* pTimeRange) {
330,778✔
2677
  if (!pTimeRange || !pTimeRange->pStart || !pTimeRange->pEnd) {
330,778✔
2678
    return false;
241,764✔
2679
  }
2680

2681
  if (nodeType(pTimeRange->pStart) == QUERY_NODE_OPERATOR) {
89,014✔
2682
    if (!filterHasPlaceHolderRange((SOperatorNode*)pTimeRange->pStart)) {
88,910✔
2683
      return false;
×
2684
    }
2685
  } else if (nodeType(pTimeRange->pStart) == QUERY_NODE_LOGIC_CONDITION) {
104✔
2686
    if (!logicConditionSatisfyExternalWindow((SLogicConditionNode*)pTimeRange->pStart)) {
104✔
2687
      return false;
×
2688
    }
2689
  } else {
2690
    return false;
×
2691
  }
2692

2693
  if (nodeType(pTimeRange->pEnd) == QUERY_NODE_OPERATOR) {
89,014✔
2694
    if (!filterHasPlaceHolderRange((SOperatorNode*)pTimeRange->pEnd)) {
89,014✔
2695
      return false;
×
2696
    }
2697
  } else if (nodeType(pTimeRange->pEnd) == QUERY_NODE_LOGIC_CONDITION) {
×
2698
    if (!logicConditionSatisfyExternalWindow((SLogicConditionNode*)pTimeRange->pEnd)) {
×
2699
      return false;
×
2700
    }
2701
  } else {
2702
    return false;
×
2703
  }
2704

2705
  return true;
89,014✔
2706
}
2707

2708
static int32_t conditionHasPlaceHolder(SNode* pNode, bool* pHasPlaceHolder) {
444,870,995✔
2709
  int32_t code = TSDB_CODE_SUCCESS;
444,870,995✔
2710
  SNode*  pCond = NULL;
444,870,995✔
2711
  SNode*  pOtherCond = NULL;
444,870,923✔
2712

2713
  if (!pNode) {
444,870,915✔
2714
    *pHasPlaceHolder = false;
327,202,855✔
2715
    return code;
327,202,403✔
2716
  }
2717

2718
  PAR_ERR_JRET(nodesCloneNode(pNode, &pCond));
117,668,060✔
2719

2720
  PAR_ERR_JRET(filterPartitionCond(&pCond, NULL, NULL, NULL, &pOtherCond));
117,712,254✔
2721

2722
  SConditionCheckContext cxt = {.hasPlaceHolder = false};
117,709,433✔
2723
  nodesWalkExpr(pOtherCond, conditionOnlyPhAndConstImpl, &cxt);
117,709,433✔
2724
  *pHasPlaceHolder = cxt.hasPlaceHolder;
117,708,882✔
2725
_return:
117,708,450✔
2726
  nodesDestroyNode(pOtherCond);
117,708,882✔
2727
  nodesDestroyNode(pCond);
117,711,695✔
2728
  return code;
117,707,049✔
2729
}
2730

2731
/**
2732
 * Determines whether the given external window is produced by a subquery
2733
 * rather than by stream processing.
2734
 *
2735
 * In the query planning stage, an external window may originate from two
2736
 * different sources:
2737
 * 1. Generated by a subquery (e.g., derived from a relational subquery result).
2738
 * 2. Generated by streaming computation (e.g., time window over a stream).
2739
 *
2740
 * This function checks if the external window belongs to the first case,
2741
 * meaning it is derived from a subquery instead of being created by
2742
 * stream-based window computation.
2743
 *
2744
 * @param pSelect The select statement containing the external window to check.
2745
 * @return true if the window is produced by a subquery; false if it comes
2746
 *         from stream computation.
2747
 */
2748
bool hasExternalWindowDerivedFromSubquery(SSelectStmt* pSelect) {
1,345,849,169✔
2749
  if (pSelect->pWindow && QUERY_NODE_EXTERNAL_WINDOW == nodeType(pSelect->pWindow) &&
1,345,849,169✔
2750
      ((SExternalWindowNode*)pSelect->pWindow)->pSubquery != NULL) {
449,691✔
2751
    return true;
360,677✔
2752
  }
2753
  return false;
1,345,488,443✔
2754
}
2755

2756
static int32_t checkExprListForExternalWin(SLogicPlanContext* pCxt, SSelectStmt* pSelect) {
120,771✔
2757
  if (pSelect->hasIndefiniteRowsFunc) {
120,771✔
NEW
2758
    return generatePlanErrMsg(pCxt, TSDB_CODE_PAR_NOT_ALLOWED_FUNC,
×
2759
                              "Indefinite rows functions are not allowed in EXTERNAL_WINDOW query");
2760
  }
2761
  if (pSelect->hasMultiRowsFunc) {
120,771✔
2762
    return generatePlanErrMsg(pCxt, TSDB_CODE_PAR_NOT_ALLOWED_FUNC,
818✔
2763
                              "Multi-rows functions are not allowed in EXTERNAL_WINDOW query");
2764
  }
2765
  return TSDB_CODE_SUCCESS;
119,953✔
2766
}
2767

2768
static int32_t checkExternalWindow(SLogicPlanContext* pCxt, SSelectStmt* pSelect) {
445,008,986✔
2769
  if (hasExternalWindowDerivedFromSubquery(pSelect)) {
445,008,986✔
2770
    return checkExprListForExternalWin(pCxt, pSelect);
120,771✔
2771
  }
2772

2773
  bool hasPlaceHolderCond = false;
444,894,252✔
2774
  PAR_ERR_RET(conditionHasPlaceHolder(pSelect->pWhere, &hasPlaceHolderCond));
444,894,837✔
2775

2776
  pCxt->pPlanCxt->streamCxt.hasExtWindow = true;
444,909,135✔
2777
  if (NULL != pSelect->pWindow || NULL != pSelect->pPartitionByList || NULL != pSelect->pGroupByList ||
444,909,594✔
2778
      !inStreamCalcClause(pCxt->pPlanCxt) || pCxt->containsOuterJoin || hasPlaceHolderCond ||
343,611,562✔
2779
      nodeType(pSelect->pFromTable) == QUERY_NODE_TEMP_TABLE ||
375,941✔
2780
      nodeType(pSelect->pFromTable) == QUERY_NODE_JOIN_TABLE ||
368,298✔
2781
      NULL != pSelect->pSlimit || NULL != pSelect->pLimit || pSelect->hasInterpFunc ||
368,298✔
2782
      pSelect->hasUniqueFunc || pSelect->hasTailFunc || pSelect->hasForecastFunc ||
331,499✔
2783
      (pSelect->pOrderByList != NULL && pCxt->pPlanCxt->streamCxt.hasForceOutput) ||
330,778✔
2784
      !timeRangeSatisfyExternalWindow((STimeRangeNode*)pSelect->pTimeRange)) {
321,481✔
2785
    pCxt->pPlanCxt->streamCxt.hasExtWindow = false;
444,789,505✔
2786
  }
2787

2788
  if (pCxt->pPlanCxt->streamCxt.hasNotify || pCxt->pPlanCxt->streamCxt.hasForceOutput) {
444,887,723✔
2789
    // stream has notify or force output, external window node must be the root node, if not, do not use external window
2790
    if (pSelect->pFill || pSelect->hasInterpFunc || pSelect->hasForecastFunc || pSelect->hasGenericAnalysisFunc ||
57,602✔
2791
        pSelect->isDistinct || pSelect->pOrderByList) {
62,219✔
NEW
2792
      pCxt->pPlanCxt->streamCxt.hasExtWindow = false;
×
2793
    }
2794
  }
2795

2796
  return TSDB_CODE_SUCCESS;
444,887,652✔
2797
}
2798

2799
static int32_t createExternalWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,032,090✔
2800
  if (hasExternalWindowDerivedFromSubquery(pSelect)) {
445,032,090✔
2801
    return createWindowLogicNodeByExternal(pCxt, (SExternalWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
119,954✔
2802
  }
2803
  if (!pCxt->pPlanCxt->streamCxt.hasExtWindow) {
444,964,188✔
2804
    return TSDB_CODE_SUCCESS;
444,874,135✔
2805
  }
2806

2807
  PLAN_ERR_RET(nodesMakeNode(QUERY_NODE_EXTERNAL_WINDOW, &pSelect->pWindow));
89,014✔
2808
  PLAN_RET(createWindowLogicNodeByStreamExternal(pCxt, (SExternalWindowNode*)pSelect->pWindow, pSelect, pLogicNode));
89,014✔
2809

2810
  return TSDB_CODE_SUCCESS;
2811
}
2812

2813
typedef struct SCollectFillExprsCtx {
2814
  SHashObj*  pPseudoCols;
2815
  SNodeList* pFillExprs;
2816
  SNodeList* pNotFillExprs;
2817
  bool       collectAggFuncs;
2818
  SNodeList* pAggFuncCols;
2819
} SCollectFillExprsCtx;
2820

2821
typedef struct SWalkFillSubExprCtx {
2822
  bool                  hasFillCol;
2823
  bool                  hasPseudoWinCol;
2824
  bool                  hasGroupKeyCol;
2825
  SCollectFillExprsCtx* pCollectFillCtx;
2826
  int32_t               code;
2827
} SWalkFillSubExprCtx;
2828

2829
static bool nodeAlreadyContained(SNodeList* pList, SNode* pNode) {
46,538✔
2830
  SNode* pExpr = NULL;
46,538✔
2831
  FOREACH(pExpr, pList) {
80,408✔
2832
    if (nodesEqualNode(pExpr, pNode)) {
66,469✔
2833
      return true;
32,599✔
2834
    }
2835
  }
2836
  return false;
13,939✔
2837
}
2838

2839
static EDealRes needFillValueImpl(SNode* pNode, void* pContext) {
2,799,261✔
2840
  SWalkFillSubExprCtx* pCtx = pContext;
2,799,261✔
2841
  EDealRes             res = DEAL_RES_CONTINUE;
2,799,261✔
2842
  if (QUERY_NODE_COLUMN == nodeType(pNode)) {
2,799,261✔
2843
    SColumnNode* pCol = (SColumnNode*)pNode;
2,430,292✔
2844
    if (COLUMN_TYPE_WINDOW_START == pCol->colType || COLUMN_TYPE_WINDOW_END == pCol->colType ||
2,430,292✔
2845
        COLUMN_TYPE_WINDOW_DURATION == pCol->colType || COLUMN_TYPE_IS_WINDOW_FILLED == pCol->colType) {
1,830,825✔
2846
      pCtx->hasPseudoWinCol = true;
600,414✔
2847
      pCtx->code =
600,414✔
2848
          taosHashPut(pCtx->pCollectFillCtx->pPseudoCols, pCol->colName, TSDB_COL_NAME_LEN, &pNode, POINTER_BYTES);
600,414✔
2849
    } else if (COLUMN_TYPE_GROUP_KEY == pCol->colType || COLUMN_TYPE_TBNAME == pCol->colType ||
1,829,878✔
2850
               COLUMN_TYPE_TAG == pCol->colType) {
1,623,210✔
2851
      pCtx->hasGroupKeyCol = true;
206,668✔
2852
      pCtx->code =
206,668✔
2853
          taosHashPut(pCtx->pCollectFillCtx->pPseudoCols, pCol->colName, TSDB_COL_NAME_LEN, &pNode, POINTER_BYTES);
206,668✔
2854
    } else {
2855
      pCtx->hasFillCol = true;
1,623,210✔
2856
      if (pCtx->pCollectFillCtx->collectAggFuncs) {
1,623,210✔
2857
        // Agg funcs has already been rewriten to columns by Interval
2858
        // Here, we return DEAL_RES_CONTINUE cause we need to collect all agg funcs
2859
        if (!nodeAlreadyContained(pCtx->pCollectFillCtx->pFillExprs, pNode) &&
38,940✔
2860
            !nodeAlreadyContained(pCtx->pCollectFillCtx->pAggFuncCols, pNode))
7,598✔
2861
          pCtx->code = nodesListMakeStrictAppend(&pCtx->pCollectFillCtx->pAggFuncCols, pNode);
6,341✔
2862
      } else {
2863
        res = DEAL_RES_END;
1,584,270✔
2864
      }
2865
    }
2866
  }
2867
  if (pCtx->code != TSDB_CODE_SUCCESS) res = DEAL_RES_ERROR;
2,799,261✔
2868
  return res;
2,799,261✔
2869
}
2870

2871
static void needFillValue(SNode* pNode, SWalkFillSubExprCtx* pCtx) { nodesWalkExpr(pNode, needFillValueImpl, pCtx); }
2,856,052✔
2872

2873
static int32_t collectFillExpr(SNode* pNode, SCollectFillExprsCtx* pCollectFillCtx) {
2,856,052✔
2874
  SNode*              pNew = NULL;
2,856,052✔
2875
  SWalkFillSubExprCtx collectFillSubExprCtx = {
2,856,052✔
2876
      .hasFillCol = false, .hasPseudoWinCol = false, .hasGroupKeyCol = false, .pCollectFillCtx = pCollectFillCtx};
2877
  needFillValue(pNode, &collectFillSubExprCtx);
2,856,052✔
2878
  if (collectFillSubExprCtx.code != TSDB_CODE_SUCCESS) {
2,856,052✔
2879
    return collectFillSubExprCtx.code;
×
2880
  }
2881

2882
  if (collectFillSubExprCtx.hasFillCol && !pCollectFillCtx->collectAggFuncs) {
2,856,052✔
2883
    if (nodeType(pNode) == QUERY_NODE_ORDER_BY_EXPR) {
1,584,270✔
2884
      collectFillSubExprCtx.code = nodesCloneNode(((SOrderByExprNode*)pNode)->pExpr, &pNew);
×
2885
    } else {
2886
      collectFillSubExprCtx.code = nodesCloneNode(pNode, &pNew);
1,584,270✔
2887
    }
2888
    if (collectFillSubExprCtx.code == TSDB_CODE_SUCCESS) {
1,584,270✔
2889
      collectFillSubExprCtx.code = nodesListMakeStrictAppend(&pCollectFillCtx->pFillExprs, pNew);
1,584,270✔
2890
    }
2891
  }
2892
  return collectFillSubExprCtx.code;
2,856,052✔
2893
}
2894

2895
static int32_t collectFillExprs(SSelectStmt* pSelect, SNodeList** pFillExprs, SNodeList** pNotFillExprs,
435,885✔
2896
                                SNodeList** pPossibleFillNullCols) {
2897
  int32_t              code = TSDB_CODE_SUCCESS;
435,885✔
2898
  SCollectFillExprsCtx collectFillCtx = {0};
435,885✔
2899
  SNode*               pNode = NULL;
435,885✔
2900
  collectFillCtx.pPseudoCols = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
435,885✔
2901
  if (!collectFillCtx.pPseudoCols) return terrno;
435,885✔
2902

2903
  FOREACH(pNode, pSelect->pProjectionList) {
2,582,896✔
2904
    code = collectFillExpr(pNode, &collectFillCtx);
2,147,011✔
2905
    if (code != TSDB_CODE_SUCCESS) break;
2,147,011✔
2906
  }
2907
  collectFillCtx.collectAggFuncs = true;
435,885✔
2908
  if (code == TSDB_CODE_SUCCESS) {
435,885✔
2909
    code = collectFillExpr(pSelect->pHaving, &collectFillCtx);
435,885✔
2910
  }
2911
  if (code == TSDB_CODE_SUCCESS) {
435,885✔
2912
    FOREACH(pNode, pSelect->pOrderByList) {
709,041✔
2913
      code = collectFillExpr(pNode, &collectFillCtx);
273,156✔
2914
      if (code != TSDB_CODE_SUCCESS) break;
273,156✔
2915
    }
2916
  }
2917
  if (code == TSDB_CODE_SUCCESS) {
435,885✔
2918
    void* pIter = taosHashIterate(collectFillCtx.pPseudoCols, 0);
435,885✔
2919
    while (pIter) {
951,014✔
2920
      SNode *pNode = *(SNode**)pIter, *pNew = NULL;
515,129✔
2921
      code = nodesCloneNode(pNode, &pNew);
515,129✔
2922
      if (code == TSDB_CODE_SUCCESS) {
515,129✔
2923
        code = nodesListMakeStrictAppend(&collectFillCtx.pNotFillExprs, pNew);
515,129✔
2924
      }
2925
      if (code == TSDB_CODE_SUCCESS) {
515,129✔
2926
        pIter = taosHashIterate(collectFillCtx.pPseudoCols, pIter);
515,129✔
2927
      } else {
2928
        taosHashCancelIterate(collectFillCtx.pPseudoCols, pIter);
×
2929
        break;
×
2930
      }
2931
    }
2932
    if (code == TSDB_CODE_SUCCESS) {
435,885✔
2933
      TSWAP(*pFillExprs, collectFillCtx.pFillExprs);
435,885✔
2934
      TSWAP(*pNotFillExprs, collectFillCtx.pNotFillExprs);
435,885✔
2935
      TSWAP(*pPossibleFillNullCols, collectFillCtx.pAggFuncCols);
435,885✔
2936
    }
2937
  }
2938
  if (code != TSDB_CODE_SUCCESS) {
435,885✔
2939
    if (collectFillCtx.pFillExprs) nodesDestroyList(collectFillCtx.pFillExprs);
×
2940
    if (collectFillCtx.pNotFillExprs) nodesDestroyList(collectFillCtx.pNotFillExprs);
×
2941
    if (collectFillCtx.pAggFuncCols) nodesDestroyList(collectFillCtx.pAggFuncCols);
×
2942
  }
2943
  taosHashCleanup(collectFillCtx.pPseudoCols);
435,885✔
2944
  return code;
435,885✔
2945
}
2946

2947
static int32_t createFillLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,000,873✔
2948
  if (NULL == pSelect->pWindow || QUERY_NODE_INTERVAL_WINDOW != nodeType(pSelect->pWindow) ||
445,000,873✔
2949
      NULL == ((SIntervalWindowNode*)pSelect->pWindow)->pFill) {
17,445,440✔
2950
    return TSDB_CODE_SUCCESS;
444,563,823✔
2951
  }
2952

2953
  SFillNode* pFillNode = (SFillNode*)(((SIntervalWindowNode*)pSelect->pWindow)->pFill);
437,181✔
2954
  if (FILL_MODE_NONE == pFillNode->mode) {
437,181✔
2955
    return TSDB_CODE_SUCCESS;
1,296✔
2956
  }
2957

2958
  SFillLogicNode* pFill = NULL;
435,885✔
2959
  int32_t         code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_FILL, (SNode**)&pFill);
435,885✔
2960
  if (NULL == pFill) {
435,885✔
2961
    return code;
×
2962
  }
2963

2964
  pFill->node.groupAction = getGroupAction(pCxt, pSelect);
435,885✔
2965
  pFill->node.requireDataOrder = getRequireDataOrder(true, pSelect);
435,885✔
2966
  pFill->node.resultDataOrder = pFill->node.requireDataOrder;
435,885✔
2967
  pFill->node.inputTsOrder = TSDB_ORDER_ASC;
435,885✔
2968

2969
  code = collectFillExprs(pSelect, &pFill->pFillExprs, &pFill->pNotFillExprs, &pFill->pFillNullExprs);
435,885✔
2970
  if (TSDB_CODE_SUCCESS == code) {
435,885✔
2971
    code = rewriteExprsForSelect(pFill->pFillExprs, pSelect, SQL_CLAUSE_FILL, NULL);
435,885✔
2972
  }
2973
  if (TSDB_CODE_SUCCESS == code) {
435,885✔
2974
    code = rewriteExprsForSelect(pFill->pNotFillExprs, pSelect, SQL_CLAUSE_FILL, NULL);
435,885✔
2975
  }
2976
  if (TSDB_CODE_SUCCESS == code && LIST_LENGTH(pFill->pFillNullExprs) > 0) {
435,885✔
2977
    code = createColumnByRewriteExprs(pFill->pFillNullExprs, &pFill->node.pTargets);
6,341✔
2978
  }
2979
  if (TSDB_CODE_SUCCESS == code) {
435,885✔
2980
    code = createColumnByRewriteExprs(pFill->pFillExprs, &pFill->node.pTargets);
435,885✔
2981
  }
2982
  if (TSDB_CODE_SUCCESS == code) {
435,885✔
2983
    code = createColumnByRewriteExprs(pFill->pNotFillExprs, &pFill->node.pTargets);
435,885✔
2984
  }
2985

2986
  pFill->mode = pFillNode->mode;
435,885✔
2987
  pFill->timeRange = pFillNode->timeRange;
435,885✔
2988
  TSWAP(pFill->pTimeRange, pFillNode->pTimeRange);
435,885✔
2989
  pFill->pValues = NULL;
435,885✔
2990
  code = nodesCloneNode(pFillNode->pValues, &pFill->pValues);
435,885✔
2991
  if (TSDB_CODE_SUCCESS == code) {
435,885✔
2992
    code = nodesCloneNode(pFillNode->pWStartTs, &pFill->pWStartTs);
435,885✔
2993
  }
2994
  if (TSDB_CODE_SUCCESS == code) {
435,885✔
2995
    code = nodesCloneNode(pFillNode->pSurroundingTime,
435,885✔
2996
                          &pFill->pSurroundingTime);
435,885✔
2997
  }
2998

2999
  if (TSDB_CODE_SUCCESS == code && 0 == LIST_LENGTH(pFill->node.pTargets)) {
435,885✔
3000
    code = createColumnByRewriteExpr(pFill->pWStartTs, &pFill->node.pTargets);
×
3001
  }
3002

3003
  if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pHaving) {
435,885✔
3004
    code = nodesCloneNode(pSelect->pHaving, &pFill->node.pConditions);
5,152✔
3005
  }
3006

3007
  if (TSDB_CODE_SUCCESS == code) {
435,885✔
3008
    *pLogicNode = (SLogicNode*)pFill;
435,885✔
3009
  } else {
3010
    nodesDestroyNode((SNode*)pFill);
×
3011
  }
3012

3013
  return code;
435,885✔
3014
}
3015

3016
static bool isPrimaryKeySort(SNodeList* pOrderByList) {
78,445,121✔
3017
  SNode* pExpr = ((SOrderByExprNode*)nodesListGetNode(pOrderByList, 0))->pExpr;
78,445,121✔
3018
  if (QUERY_NODE_COLUMN != nodeType(pExpr)) {
78,450,815✔
3019
    return false;
1,045,330✔
3020
  }
3021
  return isPrimaryKeyImpl(pExpr);
77,405,485✔
3022
}
3023

3024
static int32_t createSortLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,027,856✔
3025
  if (NULL == pSelect->pOrderByList || pSelect->pOrderByList->length == 0) {
445,027,856✔
3026
    return TSDB_CODE_SUCCESS;
366,577,847✔
3027
  }
3028

3029
  SSortLogicNode* pSort = NULL;
78,450,421✔
3030
  int32_t         code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SORT, (SNode**)&pSort);
78,450,421✔
3031
  if (NULL == pSort) {
78,450,442✔
3032
    return code;
×
3033
  }
3034

3035
  pSort->groupSort = pSelect->groupSort;
78,450,442✔
3036
  pSort->node.groupAction = pSort->groupSort ? GROUP_ACTION_KEEP : GROUP_ACTION_CLEAR;
78,450,442✔
3037
  pSort->node.requireDataOrder = DATA_ORDER_LEVEL_NONE;
78,450,010✔
3038

3039
  pSort->node.resultDataOrder = isPrimaryKeySort(pSelect->pOrderByList)
122,418,456✔
3040
                                    ? (pSort->groupSort ? DATA_ORDER_LEVEL_IN_GROUP : DATA_ORDER_LEVEL_GLOBAL)
28,222,971✔
3041
                                    : DATA_ORDER_LEVEL_NONE;
99,350,946✔
3042
  if (inStreamCalcClause(pCxt->pPlanCxt) && nodeType(pSelect->pFromTable) == QUERY_NODE_REAL_TABLE &&
78,447,313✔
3043
      ((SRealTableNode*)pSelect->pFromTable)->placeholderType == SP_PARTITION_ROWS) {
36,426✔
3044
    pSort->skipPKSortOpt = true;
969✔
3045
  }
3046

3047
  code = nodesCollectColumns(pSelect, SQL_CLAUSE_ORDER_BY, NULL, COLLECT_COL_TYPE_ALL, &pSort->node.pTargets);
78,446,591✔
3048
  if (TSDB_CODE_SUCCESS == code) {
78,447,201✔
3049
    rewriteTargetsWithResId(pSort->node.pTargets);
78,448,726✔
3050
  }
3051
  if (TSDB_CODE_SUCCESS == code && NULL == pSort->node.pTargets) {
78,441,151✔
3052
    SNode* pNew = NULL;
8,006,674✔
3053
    code = nodesCloneNode(nodesListGetNode(pCxt->pCurrRoot->pTargets, 0), &pNew);
8,006,674✔
3054
    if (TSDB_CODE_SUCCESS == code) {
8,007,864✔
3055
      code = nodesListMakeStrictAppend(&pSort->node.pTargets, pNew);
8,007,864✔
3056
    }
3057
  }
3058

3059
  if (TSDB_CODE_SUCCESS == code) {
78,442,065✔
3060
    pSort->pSortKeys = NULL;
78,441,927✔
3061
    code = nodesCloneList(pSelect->pOrderByList, &pSort->pSortKeys);
78,441,927✔
3062
    if (TSDB_CODE_SUCCESS == code) {
78,454,158✔
3063
      SNode*            pNode = NULL;
78,454,158✔
3064
      SOrderByExprNode* firstSortKey = (SOrderByExprNode*)nodesListGetNode(pSort->pSortKeys, 0);
78,454,158✔
3065

3066
      if (isPrimaryKeyImpl(firstSortKey->pExpr)) pSort->node.outputTsOrder = firstSortKey->order;
78,453,227✔
3067
      if (firstSortKey->pExpr->type == QUERY_NODE_COLUMN) {
78,453,848✔
3068
        SColumnNode* pCol = (SColumnNode*)firstSortKey->pExpr;
77,407,747✔
3069
        int16_t      projIdx = 1;
77,407,747✔
3070
        FOREACH(pNode, pSelect->pProjectionList) {
154,528,552✔
3071
          SExprNode* pExpr = (SExprNode*)pNode;
123,123,840✔
3072
          if (0 == strcmp(pCol->node.aliasName, pExpr->aliasName)) {
123,123,840✔
3073
            pCol->projIdx = projIdx; break;
46,002,994✔
3074
          }
3075
          projIdx++;
77,120,805✔
3076
        }
3077
      }
3078
    }
3079
  }
3080

3081
  if (TSDB_CODE_SUCCESS == code) {
78,453,081✔
3082
    *pLogicNode = (SLogicNode*)pSort;
78,453,081✔
3083
  } else {
3084
    nodesDestroyNode((SNode*)pSort);
×
3085
  }
3086

3087
  return code;
78,453,641✔
3088
}
3089

3090
static int32_t createColumnByProjections(SLogicPlanContext* pCxt, const char* pStmtName, SNodeList* pExprs,
471,595,167✔
3091
                                         SNodeList** pCols) {
3092
  SNodeList* pList = NULL;
471,595,167✔
3093
  int32_t    code = nodesMakeList(&pList);
471,595,359✔
3094
  if (NULL == pList) {
471,626,680✔
3095
    return code;
×
3096
  }
3097

3098
  SNode*  pNode;
3099
  int32_t projIdx = 1;
471,626,680✔
3100
  FOREACH(pNode, pExprs) {
1,599,918,879✔
3101
    SColumnNode* pCol = createColumnByExpr(pStmtName, (SExprNode*)pNode);
1,128,305,703✔
3102
    if (TSDB_CODE_SUCCESS != (code = nodesListStrictAppend(pList, (SNode*)pCol))) {
1,128,272,255✔
3103
      nodesDestroyList(pList);
×
3104
      return code;
×
3105
    }
3106
    pCol->resIdx = ((SExprNode*)pNode)->projIdx;
1,128,295,010✔
3107
  }
3108

3109
  *pCols = pList;
471,613,520✔
3110
  return TSDB_CODE_SUCCESS;
471,613,558✔
3111
}
3112

3113
static int32_t createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
455,780,181✔
3114
  SProjectLogicNode* pProject = NULL;
455,780,181✔
3115
  int32_t            code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT, (SNode**)&pProject);
455,780,730✔
3116
  if (NULL == pProject) {
455,855,215✔
3117
    return code;
×
3118
  }
3119

3120
  TSWAP(pProject->node.pLimit, pSelect->pLimit);
455,855,215✔
3121
  TSWAP(pProject->node.pSlimit, pSelect->pSlimit);
455,854,568✔
3122
  pProject->ignoreGroupId = pSelect->isSubquery ? true : (NULL == pSelect->pPartitionByList);
455,853,681✔
3123
  pProject->node.groupAction = (hasExternalWindowDerivedFromSubquery(pSelect) ||
1,169,035,806✔
3124
                                (inStreamCalcClause(pCxt->pPlanCxt) && pCxt->pPlanCxt->streamCxt.hasExtWindow))
456,199,061✔
3125
                                   ? GROUP_ACTION_KEEP
3126
                                   : GROUP_ACTION_CLEAR;
911,546,008✔
3127
  pProject->node.requireDataOrder = DATA_ORDER_LEVEL_NONE;
455,806,671✔
3128
  pProject->node.resultDataOrder = DATA_ORDER_LEVEL_NONE;
455,806,494✔
3129

3130
  pProject->pProjections = NULL;
455,806,074✔
3131
  code = nodesCloneList(pSelect->pProjectionList, &pProject->pProjections);
455,806,390✔
3132
  tstrncpy(pProject->stmtName, pSelect->stmtName, TSDB_TABLE_NAME_LEN);
455,867,896✔
3133

3134
  if (TSDB_CODE_SUCCESS == code) {
455,867,351✔
3135
    code = createColumnByProjections(pCxt, pSelect->stmtName, pSelect->pProjectionList, &pProject->node.pTargets);
455,858,030✔
3136
  }
3137

3138
  if (TSDB_CODE_SUCCESS == code) {
455,853,022✔
3139
    *pLogicNode = (SLogicNode*)pProject;
455,853,022✔
3140
  } else {
3141
    nodesDestroyNode((SNode*)pProject);
×
3142
  }
3143

3144
  return code;
455,853,402✔
3145
}
3146

3147
static int32_t createPartitionLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
444,981,961✔
3148
  if (NULL == pSelect->pPartitionByList) {
444,981,961✔
3149
    return TSDB_CODE_SUCCESS;
404,556,861✔
3150
  }
3151

3152
  SPartitionLogicNode* pPartition = NULL;
40,425,333✔
3153
  int32_t              code = TSDB_CODE_SUCCESS;
40,425,333✔
3154

3155
  PLAN_ERR_JRET(nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PARTITION, (SNode**)&pPartition));
40,425,333✔
3156

3157
  pPartition->node.groupAction = GROUP_ACTION_SET;
40,473,972✔
3158
  pPartition->node.requireDataOrder = DATA_ORDER_LEVEL_NONE;
40,473,972✔
3159
  pPartition->node.resultDataOrder = DATA_ORDER_LEVEL_NONE;
40,473,972✔
3160

3161
  PLAN_ERR_JRET(nodesCollectColumns(pSelect, SQL_CLAUSE_PARTITION_BY, NULL, COLLECT_COL_TYPE_ALL, &pPartition->node.pTargets));
40,473,972✔
3162

3163
  if (NULL == pPartition->node.pTargets) {
40,478,005✔
3164
    SNode* pNew = NULL;
2,722,082✔
3165
    PLAN_ERR_JRET(nodesCloneNode(nodesListGetNode(pCxt->pCurrRoot->pTargets, 0), &pNew));
2,722,082✔
3166
    PLAN_ERR_JRET(nodesListMakeStrictAppend(&pPartition->node.pTargets, pNew));
2,722,082✔
3167
  }
3168

3169
  rewriteTargetsWithResId(pPartition->node.pTargets);
40,478,255✔
3170

3171
  PLAN_ERR_JRET(nodesCollectFuncs(pSelect, SQL_CLAUSE_PARTITION_BY, NULL, fmIsAggFunc, &pPartition->pAggFuncs));
40,466,689✔
3172

3173
  pPartition->pPartitionKeys = NULL;
40,477,532✔
3174
  PLAN_ERR_JRET(nodesCloneList(pSelect->pPartitionByList, &pPartition->pPartitionKeys));
40,477,532✔
3175

3176
  if (keysHasCol(pPartition->pPartitionKeys) && pSelect->pWindow &&
40,478,001✔
3177
      nodeType(pSelect->pWindow) == QUERY_NODE_INTERVAL_WINDOW) {
3,533,287✔
3178
    pPartition->needBlockOutputTsOrder = true;
3,385,728✔
3179
    SIntervalWindowNode* pInterval = (SIntervalWindowNode*)pSelect->pWindow;
3,385,728✔
3180
    SColumnNode*         pTsCol = (SColumnNode*)pInterval->pCol;
3,385,728✔
3181
    pPartition->pkTsColId = pTsCol->colId;
3,385,728✔
3182
    pPartition->pkTsColTbId = pTsCol->tableId;
3,385,728✔
3183
  }
3184

3185
  if (NULL != pSelect->pHaving && !pSelect->hasAggFuncs && NULL == pSelect->pGroupByList &&
40,476,536✔
3186
      NULL == pSelect->pWindow) {
3,248,216✔
3187
    pPartition->node.pConditions = NULL;
3,247,968✔
3188
    PLAN_ERR_JRET(nodesCloneNode(pSelect->pHaving, &pPartition->node.pConditions));
3,247,968✔
3189
  }
3190

3191
  *pLogicNode = (SLogicNode*)pPartition;
40,467,243✔
3192
  return code;
40,467,243✔
3193

NEW
3194
_return:
×
NEW
3195
  planError("%s failed ,code %d since %s", __func__, code, tstrerror(code));
×
NEW
3196
  nodesDestroyNode((SNode*)pPartition);
×
UNCOV
3197
  return code;
×
3198
}
3199

3200
static int32_t createDistinctLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,036,509✔
3201
  if (!pSelect->isDistinct) {
445,036,509✔
3202
    return TSDB_CODE_SUCCESS;
436,296,503✔
3203
  }
3204

3205
  SAggLogicNode* pAgg = NULL;
8,740,464✔
3206
  int32_t        code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG, (SNode**)&pAgg);
8,740,682✔
3207
  if (NULL == pAgg) {
8,774,074✔
3208
    return code;
×
3209
  }
3210

3211
  pAgg->node.groupAction = GROUP_ACTION_CLEAR;  // getDistinctGroupAction(pCxt, pSelect);
8,774,074✔
3212
  pAgg->node.requireDataOrder = DATA_ORDER_LEVEL_NONE;
8,774,605✔
3213
  pAgg->node.resultDataOrder = DATA_ORDER_LEVEL_NONE;
8,774,074✔
3214

3215
  // set grouyp keys, agg funcs and having conditions
3216
  SNodeList* pGroupKeys = NULL;
8,774,605✔
3217
  SNode*     pProjection = NULL;
8,774,605✔
3218
  FOREACH(pProjection, pSelect->pProjectionList) {
22,832,527✔
3219
    SNode* pNew = NULL;
14,054,946✔
3220
    code = createGroupingSetNode(pProjection, &pNew);
14,054,946✔
3221
    if (TSDB_CODE_SUCCESS == code) {
14,058,026✔
3222
      code = nodesListMakeStrictAppend(&pGroupKeys, pNew);
14,058,026✔
3223
    }
3224
    if (TSDB_CODE_SUCCESS != code) {
14,057,922✔
3225
      nodesDestroyList(pGroupKeys);
×
3226
      break;
×
3227
    }
3228
  }
3229
  if (TSDB_CODE_SUCCESS == code) {
8,777,050✔
3230
    pAgg->pGroupKeys = pGroupKeys;
8,772,989✔
3231
  }
3232

3233
  // rewrite the expression in subsequent clauses
3234
  if (TSDB_CODE_SUCCESS == code) {
8,777,050✔
3235
    code = rewriteExprsForSelect(pAgg->pGroupKeys, pSelect, SQL_CLAUSE_DISTINCT, NULL);
8,773,938✔
3236
  }
3237

3238
  // set the output
3239
  if (TSDB_CODE_SUCCESS == code) {
8,778,386✔
3240
    code = createColumnByRewriteExprs(pAgg->pGroupKeys, &pAgg->node.pTargets);
8,775,188✔
3241
  }
3242

3243
  if (TSDB_CODE_SUCCESS == code) {
8,775,777✔
3244
    *pLogicNode = (SLogicNode*)pAgg;
8,775,777✔
3245
  } else {
3246
    nodesDestroyNode((SNode*)pAgg);
×
3247
  }
3248

3249
  return code;
8,775,777✔
3250
}
3251

3252
static int32_t createSelectWithoutFromLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
10,771,275✔
3253
                                                SLogicNode** pLogicNode) {
3254
  return createProjectLogicNode(pCxt, pSelect, pLogicNode);
10,771,275✔
3255
}
3256

3257
static int32_t createSelectFromLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
445,014,030✔
3258
  SLogicNode* pRoot = NULL;
445,014,030✔
3259
  int32_t     code = TSDB_CODE_SUCCESS;
445,014,753✔
3260

3261
  PLAN_ERR_JRET(createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable, &pRoot));
445,014,753✔
3262

3263
  PLAN_ERR_JRET(checkExternalWindow(pCxt, pSelect));
445,070,163✔
3264

3265
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createPartitionLogicNode, &pRoot));
445,017,400✔
3266

3267
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createExternalWindowLogicNode, &pRoot));
445,066,473✔
3268

3269
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createWindowLogicNode, &pRoot));
445,049,242✔
3270

3271
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createFillLogicNode, &pRoot));
445,074,495✔
3272

3273
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createAggLogicNode, &pRoot));
445,044,953✔
3274

3275
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createIndefRowsFuncLogicNode, &pRoot));
445,088,537✔
3276

3277
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createInterpFuncLogicNode, &pRoot));
445,073,176✔
3278

3279
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createForecastFuncLogicNode, &pRoot));
445,045,458✔
3280

3281
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createGenericAnalysisLogicNode, &pRoot));
445,074,104✔
3282

3283
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createDistinctLogicNode, &pRoot));
445,076,619✔
3284

3285
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createSortLogicNode, &pRoot));
445,071,395✔
3286

3287
  PLAN_ERR_JRET(createSelectRootLogicNode(pCxt, pSelect, createProjectLogicNode, &pRoot));
445,075,653✔
3288

3289
  *pLogicNode = pRoot;
445,086,088✔
3290

3291
  return code;
445,084,300✔
3292
_return:
818✔
3293
  planError("%s failed ,code %d since %s", __func__, code, tstrerror(code));
818✔
3294
  nodesDestroyNode((SNode*)pRoot);
818✔
3295
  return code;
818✔
3296
}
3297

3298
static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
455,773,166✔
3299
  int32_t code = TSDB_CODE_SUCCESS;
455,773,166✔
3300
  bool    oldContainsOuterJoin = pCxt->containsOuterJoin;
455,773,166✔
3301
  pCxt->containsOuterJoin = pCxt->containsOuterJoin || pSelect->joinContains;
455,774,478✔
3302

3303
  if (NULL == pSelect->pFromTable) {
455,774,076✔
3304
    code = createSelectWithoutFromLogicNode(pCxt, pSelect, pLogicNode);
10,772,396✔
3305
  } else {
3306
    code = createSelectFromLogicNode(pCxt, pSelect, pLogicNode);
445,001,144✔
3307
  }
3308
  if (TSDB_CODE_SUCCESS == code && NULL != *pLogicNode) {
455,859,149✔
3309
    (*pLogicNode)->stmtRoot = true;
455,856,602✔
3310
    TSWAP((*pLogicNode)->pHint, pSelect->pHint);
455,856,023✔
3311
  }
3312

3313
  pCxt->containsOuterJoin = oldContainsOuterJoin;
455,857,126✔
3314
  return code;
455,858,030✔
3315
}
3316

3317
static int32_t createSetOpRootLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetOperator, FCreateSetOpLogicNode func,
28,537,013✔
3318
                                        SLogicNode** pRoot) {
3319
  return createRootLogicNode(pCxt, pSetOperator, pSetOperator->precision, (FCreateLogicNode)func, pRoot);
28,537,013✔
3320
}
3321

3322
static int32_t createSetOpSortLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetOperator, SLogicNode** pLogicNode) {
28,536,116✔
3323
  if (NULL == pSetOperator->pOrderByList) {
28,536,116✔
3324
    return TSDB_CODE_SUCCESS;
16,774,264✔
3325
  }
3326

3327
  SSortLogicNode* pSort = NULL;
11,761,852✔
3328
  int32_t         code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SORT, (SNode**)&pSort);
11,761,852✔
3329
  if (NULL == pSort) {
11,764,059✔
3330
    return code;
×
3331
  }
3332

3333
  TSWAP(pSort->node.pLimit, pSetOperator->pLimit);
11,764,059✔
3334

3335
  pSort->node.pTargets = NULL;
11,764,059✔
3336
  code = nodesCloneList(pSetOperator->pProjectionList, &pSort->node.pTargets);
11,764,059✔
3337

3338
  if (TSDB_CODE_SUCCESS == code) {
11,763,879✔
3339
    pSort->pSortKeys = NULL;
11,763,966✔
3340
    code = nodesCloneList(pSetOperator->pOrderByList, &pSort->pSortKeys);
11,763,966✔
3341
  }
3342

3343
  if (TSDB_CODE_SUCCESS == code) {
11,764,059✔
3344
    *pLogicNode = (SLogicNode*)pSort;
11,764,059✔
3345
  } else {
3346
    nodesDestroyNode((SNode*)pSort);
×
3347
  }
3348

3349
  return code;
11,764,059✔
3350
}
3351

3352
static int32_t createSetOpProjectLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetOperator,
15,752,801✔
3353
                                           SLogicNode** pLogicNode) {
3354
  SProjectLogicNode* pProject = NULL;
15,752,801✔
3355
  int32_t            code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT, (SNode**)&pProject);
15,752,801✔
3356
  if (NULL == pProject) {
15,755,093✔
3357
    return code;
×
3358
  }
3359

3360
  if (NULL == pSetOperator->pOrderByList) {
15,755,093✔
3361
    TSWAP(pProject->node.pLimit, pSetOperator->pLimit);
9,797,413✔
3362
  }
3363
  pProject->ignoreGroupId = true;
15,755,093✔
3364
  pProject->isSetOpProj = true;
15,755,093✔
3365

3366
  pProject->pProjections = NULL;
15,755,093✔
3367
  code = nodesCloneList(pSetOperator->pProjectionList, &pProject->pProjections);
15,755,093✔
3368

3369
  if (TSDB_CODE_SUCCESS == code) {
15,755,913✔
3370
    code = createColumnByProjections(pCxt, pSetOperator->stmtName, pSetOperator->pProjectionList,
15,756,000✔
3371
                                     &pProject->node.pTargets);
15,756,000✔
3372
  }
3373

3374
  if (TSDB_CODE_SUCCESS == code) {
15,755,559✔
3375
    *pLogicNode = (SLogicNode*)pProject;
15,755,559✔
3376
  } else {
3377
    nodesDestroyNode((SNode*)pProject);
×
3378
  }
3379

3380
  return code;
15,753,679✔
3381
}
3382

3383
static int32_t createSetOpAggLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetOperator, SLogicNode** pLogicNode) {
12,781,298✔
3384
  SAggLogicNode* pAgg = NULL;
12,781,298✔
3385
  int32_t        code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG, (SNode**)&pAgg);
12,781,298✔
3386
  if (NULL == pAgg) {
12,782,975✔
3387
    return code;
×
3388
  }
3389

3390
  if (NULL == pSetOperator->pOrderByList) {
12,782,975✔
3391
    TSWAP(pAgg->node.pSlimit, pSetOperator->pLimit);
6,978,045✔
3392
  }
3393

3394
  pAgg->pGroupKeys = NULL;
12,782,975✔
3395
  code = nodesCloneList(pSetOperator->pProjectionList, &pAgg->pGroupKeys);
12,782,975✔
3396

3397
  // rewrite the expression in subsequent clauses
3398
  if (TSDB_CODE_SUCCESS == code) {
12,783,178✔
3399
    code = rewriteExprs(pAgg->pGroupKeys, pSetOperator->pOrderByList);
12,783,705✔
3400
  }
3401

3402
  // set the output
3403
  if (TSDB_CODE_SUCCESS == code) {
12,782,495✔
3404
    code = createColumnByRewriteExprs(pAgg->pGroupKeys, &pAgg->node.pTargets);
12,783,618✔
3405
  }
3406

3407
  if (TSDB_CODE_SUCCESS == code) {
12,784,413✔
3408
    *pLogicNode = (SLogicNode*)pAgg;
12,784,413✔
3409
  } else {
3410
    nodesDestroyNode((SNode*)pAgg);
×
3411
  }
3412

3413
  return code;
12,784,413✔
3414
}
3415

3416
static int32_t createSetOpLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetOperator, SLogicNode** pLogicNode) {
28,532,363✔
3417
  SLogicNode* pSetOp = NULL;
28,532,363✔
3418
  int32_t     code = TSDB_CODE_SUCCESS;
28,532,363✔
3419
  switch (pSetOperator->opType) {
28,532,363✔
3420
    case SET_OP_TYPE_UNION_ALL:
15,753,614✔
3421
      code = createSetOpProjectLogicNode(pCxt, pSetOperator, &pSetOp);
15,753,614✔
3422
      break;
15,753,748✔
3423
    case SET_OP_TYPE_UNION:
12,782,435✔
3424
      code = createSetOpAggLogicNode(pCxt, pSetOperator, &pSetOp);
12,782,435✔
3425
      break;
12,782,980✔
3426
    default:
×
3427
      code = TSDB_CODE_FAILED;
×
3428
      break;
×
3429
  }
3430

3431
  SLogicNode* pLeft = NULL;
28,533,042✔
3432
  if (TSDB_CODE_SUCCESS == code) {
28,533,042✔
3433
    code = createQueryLogicNode(pCxt, pSetOperator->pLeft, &pLeft);
28,536,744✔
3434
  }
3435
  if (TSDB_CODE_SUCCESS == code) {
28,533,687✔
3436
    code = nodesListMakeStrictAppend(&pSetOp->pChildren, (SNode*)pLeft);
28,538,178✔
3437
  }
3438
  SLogicNode* pRight = NULL;
28,535,736✔
3439
  if (TSDB_CODE_SUCCESS == code) {
28,535,736✔
3440
    code = createQueryLogicNode(pCxt, pSetOperator->pRight, &pRight);
28,540,227✔
3441
  }
3442
  if (TSDB_CODE_SUCCESS == code) {
28,535,535✔
3443
    code = nodesListStrictAppend(pSetOp->pChildren, (SNode*)pRight);
28,540,373✔
3444
  }
3445

3446
  if (TSDB_CODE_SUCCESS == code) {
28,539,254✔
3447
    pSetOp->precision = pSetOperator->precision;
28,539,254✔
3448
    *pLogicNode = (SLogicNode*)pSetOp;
28,539,254✔
3449
  } else {
3450
    nodesDestroyNode((SNode*)pSetOp);
×
3451
  }
3452

3453
  return code;
28,539,892✔
3454
}
3455

3456
static int32_t createSetOperatorLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetOperator,
28,531,885✔
3457
                                          SLogicNode** pLogicNode) {
3458
  SLogicNode* pRoot = NULL;
28,531,885✔
3459
  int32_t     code = createSetOpLogicNode(pCxt, pSetOperator, &pRoot);
28,531,885✔
3460
  if (TSDB_CODE_SUCCESS == code) {
28,540,227✔
3461
    code = createSetOpRootLogicNode(pCxt, pSetOperator, createSetOpSortLogicNode, &pRoot);
28,540,383✔
3462
  }
3463

3464
  if (TSDB_CODE_SUCCESS == code) {
28,539,626✔
3465
    *pLogicNode = pRoot;
28,539,626✔
3466
  } else {
3467
    nodesDestroyNode((SNode*)pRoot);
×
3468
  }
3469

3470
  return code;
28,539,206✔
3471
}
3472

3473
static int32_t getMsgType(ENodeType sqlType) {
545,782,450✔
3474
  switch (sqlType) {
545,782,450✔
3475
    case QUERY_NODE_CREATE_TABLE_STMT:
44,359,995✔
3476
    case QUERY_NODE_CREATE_MULTI_TABLES_STMT:
3477
    case QUERY_NODE_CREATE_SUBTABLE_FROM_FILE_CLAUSE:
3478
    case QUERY_NODE_CREATE_VIRTUAL_TABLE_STMT:
3479
    case QUERY_NODE_CREATE_VIRTUAL_SUBTABLE_STMT:
3480
      return TDMT_VND_CREATE_TABLE;
44,359,995✔
3481
    case QUERY_NODE_DROP_TABLE_STMT:
1,546,354✔
3482
    case QUERY_NODE_DROP_VIRTUAL_TABLE_STMT:
3483
      return TDMT_VND_DROP_TABLE;
1,546,354✔
3484
    case QUERY_NODE_ALTER_TABLE_STMT:
12,757,548✔
3485
    case QUERY_NODE_ALTER_VIRTUAL_TABLE_STMT:
3486
      return TDMT_VND_ALTER_TABLE;
12,757,548✔
3487
    case QUERY_NODE_FLUSH_DATABASE_STMT:
1,943,110✔
3488
      return TDMT_VND_COMMIT;
1,943,110✔
3489
    default:
485,175,443✔
3490
      break;
485,175,443✔
3491
  }
3492
  return TDMT_VND_SUBMIT;
485,175,443✔
3493
}
3494

3495
static int32_t createVnodeModifLogicNode(SLogicPlanContext* pCxt, SVnodeModifyOpStmt* pStmt, SLogicNode** pLogicNode) {
545,780,070✔
3496
  SVnodeModifyLogicNode* pModif = NULL;
545,780,070✔
3497
  int32_t                code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY, (SNode**)&pModif);
545,794,382✔
3498
  if (NULL == pModif) {
545,806,609✔
3499
    return code;
×
3500
  }
3501
  pModif->modifyType = MODIFY_TABLE_TYPE_INSERT;
545,806,609✔
3502
  TSWAP(pModif->pDataBlocks, pStmt->pDataBlocks);
545,802,479✔
3503
  pModif->msgType = getMsgType(pStmt->sqlNodeType);
545,795,146✔
3504
  *pLogicNode = (SLogicNode*)pModif;
545,738,981✔
3505
  return TSDB_CODE_SUCCESS;
545,763,373✔
3506
}
3507

3508
static int32_t createDeleteRootLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* pDelete, FCreateDeleteLogicNode func,
2,939,580✔
3509
                                         SLogicNode** pRoot) {
3510
  return createRootLogicNode(pCxt, pDelete, pDelete->precision, (FCreateLogicNode)func, pRoot);
2,939,580✔
3511
}
3512

3513
static int32_t createDeleteScanLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* pDelete, SLogicNode** pLogicNode) {
1,469,790✔
3514
  SScanLogicNode* pScan = NULL;
1,469,790✔
3515
  int32_t         code = makeScanLogicNode(pCxt, (SRealTableNode*)pDelete->pFromTable, false, (SLogicNode**)&pScan);
1,469,790✔
3516

3517
  // set columns to scan
3518
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3519
    pScan->scanType = SCAN_TYPE_TABLE;
1,469,790✔
3520
    pScan->scanRange = pDelete->timeRange;
1,469,790✔
3521
    pScan->pScanCols = NULL;
1,469,790✔
3522
    code = nodesCloneList(((SFunctionNode*)pDelete->pCountFunc)->pParameterList, &pScan->pScanCols);
1,469,790✔
3523
  }
3524

3525
  STableMeta* pMeta = ((SRealTableNode*)pDelete->pFromTable)->pMeta;
1,469,790✔
3526
  if (TSDB_CODE_SUCCESS == code && hasPkInTable(pMeta)) {
1,469,790✔
3527
    code = addPrimaryKeyCol((SRealTableNode*)pDelete->pFromTable, &pScan->pScanCols);
47,770✔
3528
  }
3529

3530
  if (TSDB_CODE_SUCCESS == code && NULL != pDelete->pTagCond) {
1,469,790✔
3531
    code = nodesCloneNode(pDelete->pTagCond, &pScan->pTagCond);
90,832✔
3532
  }
3533

3534
  // set output
3535
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3536
    code = createColumnByRewriteExprs(pScan->pScanCols, &pScan->node.pTargets);
1,469,790✔
3537
  }
3538

3539
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3540
    *pLogicNode = (SLogicNode*)pScan;
1,469,790✔
3541
  } else {
3542
    nodesDestroyNode((SNode*)pScan);
×
3543
  }
3544

3545
  return code;
1,469,790✔
3546
}
3547

3548
static int32_t createDeleteAggLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* pDelete, SLogicNode** pLogicNode) {
1,469,790✔
3549
  SAggLogicNode* pAgg = NULL;
1,469,790✔
3550
  int32_t        code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG, (SNode**)&pAgg);
1,469,790✔
3551
  if (NULL == pAgg) {
1,469,790✔
3552
    return code;
×
3553
  }
3554

3555
  SNode* pNew = NULL;
1,469,790✔
3556
  code = nodesCloneNode(pDelete->pCountFunc, &pNew);
1,469,790✔
3557
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3558
    code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, pNew);
1,469,790✔
3559
  }
3560
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3561
    SNode* pNew = NULL;
1,469,790✔
3562
    code = nodesCloneNode(pDelete->pFirstFunc, &pNew);
1,469,790✔
3563
    if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3564
      code = nodesListStrictAppend(pAgg->pAggFuncs, pNew);
1,469,790✔
3565
    }
3566
  }
3567
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3568
    SNode* pNew = NULL;
1,469,790✔
3569
    code = nodesCloneNode(pDelete->pLastFunc, &pNew);
1,469,790✔
3570
    if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3571
      code = nodesListStrictAppend(pAgg->pAggFuncs, pNew);
1,469,790✔
3572
    }
3573
  }
3574
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3575
    code = rewriteExpr(pAgg->pAggFuncs, &pDelete->pCountFunc);
1,469,790✔
3576
  }
3577
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3578
    code = rewriteExpr(pAgg->pAggFuncs, &pDelete->pFirstFunc);
1,469,790✔
3579
  }
3580
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3581
    code = rewriteExpr(pAgg->pAggFuncs, &pDelete->pLastFunc);
1,469,790✔
3582
  }
3583
  // set the output
3584
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3585
    code = createColumnByRewriteExprs(pAgg->pAggFuncs, &pAgg->node.pTargets);
1,469,790✔
3586
  }
3587

3588
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3589
    *pLogicNode = (SLogicNode*)pAgg;
1,469,790✔
3590
  } else {
3591
    nodesDestroyNode((SNode*)pAgg);
×
3592
  }
3593

3594
  return code;
1,469,790✔
3595
}
3596

3597
static int32_t createVnodeModifLogicNodeByDelete(SLogicPlanContext* pCxt, SDeleteStmt* pDelete,
1,469,790✔
3598
                                                 SLogicNode** pLogicNode) {
3599
  SVnodeModifyLogicNode* pModify = NULL;
1,469,790✔
3600
  int32_t                code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY, (SNode**)&pModify);
1,469,790✔
3601
  if (NULL == pModify) {
1,469,790✔
3602
    return code;
×
3603
  }
3604

3605
  SRealTableNode* pRealTable = (SRealTableNode*)pDelete->pFromTable;
1,469,790✔
3606

3607
  pModify->modifyType = MODIFY_TABLE_TYPE_DELETE;
1,469,790✔
3608
  pModify->tableId = pRealTable->pMeta->uid;
1,469,790✔
3609
  pModify->tableType = pRealTable->pMeta->tableType;
1,469,790✔
3610
  snprintf(pModify->tableName, sizeof(pModify->tableName), "%s", pRealTable->table.tableName);
1,469,790✔
3611
  tstrncpy(pModify->tsColName, pRealTable->pMeta->schema->name, TSDB_COL_NAME_LEN);
1,469,790✔
3612
  pModify->deleteTimeRange = pDelete->timeRange;
1,469,790✔
3613
  // merge: statement-level SECURE_DELETE keyword OR super table/db secureDelete metadata
3614
  pModify->secureDelete = pDelete->secureDelete | pRealTable->pMeta->secureDelete;
1,469,790✔
3615
  pModify->pAffectedRows = NULL;
1,469,790✔
3616
  code = nodesCloneNode(pDelete->pCountFunc, &pModify->pAffectedRows);
1,469,790✔
3617
  if (TSDB_CODE_SUCCESS != code) {
1,469,790✔
3618
    nodesDestroyNode((SNode*)pModify);
×
3619
    return code;
×
3620
  }
3621
  code = nodesCloneNode(pDelete->pFirstFunc, &pModify->pStartTs);
1,469,790✔
3622
  if (TSDB_CODE_SUCCESS != code) {
1,469,790✔
3623
    nodesDestroyNode((SNode*)pModify);
×
3624
    return code;
×
3625
  }
3626
  code = nodesCloneNode(pDelete->pLastFunc, &pModify->pEndTs);
1,469,790✔
3627
  if (TSDB_CODE_SUCCESS != code) {
1,469,790✔
3628
    nodesDestroyNode((SNode*)pModify);
×
3629
    return code;
×
3630
  }
3631

3632
  *pLogicNode = (SLogicNode*)pModify;
1,469,790✔
3633
  return TSDB_CODE_SUCCESS;
1,469,790✔
3634
}
3635

3636
static int32_t createDeleteLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* pDelete, SLogicNode** pLogicNode) {
1,469,790✔
3637
  SLogicNode* pRoot = NULL;
1,469,790✔
3638
  int32_t     code = createDeleteScanLogicNode(pCxt, pDelete, &pRoot);
1,469,790✔
3639
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3640
    code = createDeleteRootLogicNode(pCxt, pDelete, createDeleteAggLogicNode, &pRoot);
1,469,790✔
3641
  }
3642
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3643
    code = createDeleteRootLogicNode(pCxt, pDelete, createVnodeModifLogicNodeByDelete, &pRoot);
1,469,790✔
3644
  }
3645

3646
  if (TSDB_CODE_SUCCESS == code) {
1,469,790✔
3647
    *pLogicNode = pRoot;
1,469,790✔
3648
  } else {
3649
    nodesDestroyNode((SNode*)pRoot);
×
3650
  }
3651

3652
  return code;
1,469,790✔
3653
}
3654

3655
static int32_t creatInsertRootLogicNode(SLogicPlanContext* pCxt, SInsertStmt* pInsert, FCreateInsertLogicNode func,
536,870✔
3656
                                        SLogicNode** pRoot) {
3657
  return createRootLogicNode(pCxt, pInsert, pInsert->precision, (FCreateLogicNode)func, pRoot);
536,870✔
3658
}
3659

3660
static int32_t createVnodeModifLogicNodeByInsert(SLogicPlanContext* pCxt, SInsertStmt* pInsert,
536,870✔
3661
                                                 SLogicNode** pLogicNode) {
3662
  SVnodeModifyLogicNode* pModify = NULL;
536,870✔
3663
  int32_t                code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY, (SNode**)&pModify);
536,870✔
3664
  if (NULL == pModify) {
536,870✔
3665
    return code;
×
3666
  }
3667

3668
  SRealTableNode* pRealTable = (SRealTableNode*)pInsert->pTable;
536,870✔
3669

3670
  pModify->modifyType = MODIFY_TABLE_TYPE_INSERT;
536,870✔
3671
  pModify->tableId = pRealTable->pMeta->uid;
536,870✔
3672
  pModify->stableId = pRealTable->pMeta->suid;
536,870✔
3673
  pModify->tableType = pRealTable->pMeta->tableType;
536,870✔
3674
  snprintf(pModify->tableName, sizeof(pModify->tableName), "%s", pRealTable->table.tableName);
536,870✔
3675
  TSWAP(pModify->pVgroupList, pRealTable->pVgroupList);
536,870✔
3676
  pModify->pInsertCols = NULL;
536,870✔
3677
  code = nodesCloneList(pInsert->pCols, &pModify->pInsertCols);
536,870✔
3678
  if (NULL == pModify->pInsertCols) {
536,870✔
3679
    nodesDestroyNode((SNode*)pModify);
×
3680
    return code;
×
3681
  }
3682

3683
  *pLogicNode = (SLogicNode*)pModify;
536,870✔
3684
  return TSDB_CODE_SUCCESS;
536,870✔
3685
}
3686

3687
static int32_t createInsertLogicNode(SLogicPlanContext* pCxt, SInsertStmt* pInsert, SLogicNode** pLogicNode) {
536,870✔
3688
  SLogicNode* pRoot = NULL;
536,870✔
3689
  int32_t     code = createQueryLogicNode(pCxt, pInsert->pQuery, &pRoot);
536,870✔
3690
  if (TSDB_CODE_SUCCESS == code) {
536,870✔
3691
    code = creatInsertRootLogicNode(pCxt, pInsert, createVnodeModifLogicNodeByInsert, &pRoot);
536,870✔
3692
  }
3693

3694
  if (TSDB_CODE_SUCCESS == code) {
536,870✔
3695
    *pLogicNode = pRoot;
536,870✔
3696
  } else {
3697
    nodesDestroyNode((SNode*)pRoot);
×
3698
  }
3699

3700
  return code;
536,870✔
3701
}
3702

3703
static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogicNode** pLogicNode) {
1,081,281,520✔
3704
  switch (nodeType(pStmt)) {
1,081,281,520✔
3705
    case QUERY_NODE_SELECT_STMT:
455,829,123✔
3706
      return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt, pLogicNode);
455,829,123✔
3707
    case QUERY_NODE_VNODE_MODIFY_STMT:
545,781,843✔
3708
      return createVnodeModifLogicNode(pCxt, (SVnodeModifyOpStmt*)pStmt, pLogicNode);
545,781,843✔
3709
    case QUERY_NODE_EXPLAIN_STMT:
49,200,649✔
3710
      return createQueryLogicNode(pCxt, ((SExplainStmt*)pStmt)->pQuery, pLogicNode);
49,200,649✔
3711
    case QUERY_NODE_SET_OPERATOR:
28,536,958✔
3712
      return createSetOperatorLogicNode(pCxt, (SSetOperator*)pStmt, pLogicNode);
28,536,958✔
3713
    case QUERY_NODE_DELETE_STMT:
1,469,790✔
3714
      return createDeleteLogicNode(pCxt, (SDeleteStmt*)pStmt, pLogicNode);
1,469,790✔
3715
    case QUERY_NODE_INSERT_STMT:
545,964✔
3716
      return createInsertLogicNode(pCxt, (SInsertStmt*)pStmt, pLogicNode);
545,964✔
3717
    default:
×
3718
      break;
×
3719
  }
3720
  return TSDB_CODE_FAILED;
×
3721
}
3722

3723
static void doSetLogicNodeParent(SLogicNode* pNode, SLogicNode* pParent) {
1,804,167,231✔
3724
  pNode->pParent = pParent;
1,804,167,231✔
3725
  SNode* pChild;
3726
  FOREACH(pChild, pNode->pChildren) { doSetLogicNodeParent((SLogicNode*)pChild, pNode); }
2,147,483,647✔
3727
}
1,804,194,628✔
3728

3729
static void setLogicNodeParent(SLogicNode* pNode) { doSetLogicNodeParent(pNode, NULL); }
918,621,225✔
3730

3731
static void setLogicSubplanType(SPlanContext* pCxt, SLogicSubplan* pSubplan) {
918,671,777✔
3732
  if (QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY != nodeType(pSubplan->pNode)) {
918,671,777✔
3733
    if (pCxt->hasScan) {
370,918,238✔
3734
      pSubplan->subplanType = (IS_HSYS_SCAN(pCxt->sysScanFlag))? SUBPLAN_TYPE_HSYSSCAN:SUBPLAN_TYPE_SCAN;
357,735,365✔
3735
    } else {
3736
      pSubplan->subplanType = SUBPLAN_TYPE_MERGE; // todo: sys-merge????
13,182,657✔
3737
    }
3738
  } else {
3739
    SVnodeModifyLogicNode* pModify = (SVnodeModifyLogicNode*)pSubplan->pNode;
547,766,032✔
3740
    pSubplan->subplanType = (MODIFY_TABLE_TYPE_INSERT == pModify->modifyType && NULL != pModify->node.pChildren)
1,638,687,983✔
3741
                                ? SUBPLAN_TYPE_SCAN
3742
                                : SUBPLAN_TYPE_MODIFY;
1,094,095,429✔
3743
  }
3744
}
918,707,299✔
3745

3746
int32_t createLogicPlan(SPlanContext* pCxt, SLogicSubplan** pLogicSubplan) {
918,610,081✔
3747
  SLogicPlanContext cxt = {.pPlanCxt = pCxt, .pCurrRoot = NULL};
918,610,081✔
3748

3749
  SLogicSubplan* pSubplan = NULL;
918,628,929✔
3750
  int32_t        code = nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN, (SNode**)&pSubplan);
918,617,932✔
3751
  if (NULL == pSubplan) {
918,693,404✔
3752
    return code;
×
3753
  }
3754
  pSubplan->id.queryId = pCxt->queryId;
918,693,404✔
3755
  pSubplan->id.groupId = ++pCxt->groupId;
918,677,443✔
3756
  pSubplan->id.subplanId = 1;
918,687,550✔
3757

3758
  code = createQueryLogicNode(&cxt, pCxt->pAstRoot, &pSubplan->pNode);
918,684,182✔
3759
  if (TSDB_CODE_SUCCESS == code) {
918,627,192✔
3760
    setLogicNodeParent(pSubplan->pNode);
918,610,790✔
3761
    setLogicSubplanType(pCxt, pSubplan);
918,673,354✔
3762
    code = adjustLogicNodeDataRequirement(pSubplan->pNode, DATA_ORDER_LEVEL_NONE);
918,675,621✔
3763
  }
3764

3765
  if (TSDB_CODE_SUCCESS == code) {
918,691,664✔
3766
    *pLogicSubplan = pSubplan;
918,690,846✔
3767
  } else {
3768
    nodesDestroyNode((SNode*)pSubplan);
818✔
3769
  }
3770

3771
  return code;
918,694,818✔
3772
}
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