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

taosdata / TDengine / #4821

22 Oct 2025 06:02AM UTC coverage: 61.242% (-0.1%) from 61.353%
#4821

push

travis-ci

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

fix(stream): reset tableScan operator (#33225)

156089 of 324573 branches covered (48.09%)

Branch coverage included in aggregate %.

184 of 244 new or added lines in 9 files covered. (75.41%)

789 existing lines in 124 files now uncovered.

207891 of 269759 relevant lines covered (77.07%)

244003752.29 hits per line

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

56.13
/source/libs/executor/src/scanoperator.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 "executorInt.h"
17
#include "filter.h"
18
#include "function.h"
19
#include "functionMgt.h"
20
#include "os.h"
21
#include "querynodes.h"
22
#include "streamexecutorInt.h"
23
#include "systable.h"
24
#include "tname.h"
25

26
#include "tdatablock.h"
27
#include "tmsg.h"
28
#include "ttime.h"
29

30
#include "operator.h"
31
#include "query.h"
32
#include "querytask.h"
33
#include "tcompare.h"
34
#include "thash.h"
35
#include "ttypes.h"
36

37
#include "function.h"
38
#include "storageapi.h"
39
#include "wal.h"
40

41
int32_t scanDebug = 0;
42

43
#define MULTI_READER_MAX_TABLE_NUM     5000
44
#define SET_REVERSE_SCAN_FLAG(_info)   ((_info)->scanFlag = REVERSE_SCAN)
45
#define SWITCH_ORDER(n)                (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
46
#define STREAM_SCAN_OP_NAME            "StreamScanOperator"
47
#define STREAM_SCAN_OP_STATE_NAME      "StreamScanFillHistoryState"
48
#define STREAM_SCAN_OP_CHECKPOINT_NAME "StreamScanOperator_Checkpoint"
49

50
typedef struct STableMergeScanExecInfo {
51
  SFileBlockLoadRecorder blockRecorder;
52
  SSortExecInfo          sortExecInfo;
53
} STableMergeScanExecInfo;
54

55
typedef struct STableMergeScanSortSourceParam {
56
  SOperatorInfo* pOperator;
57
  int32_t        readerIdx;
58
  uint64_t       uid;
59
  STsdbReader*   reader;
60
} STableMergeScanSortSourceParam;
61

62
typedef struct STableCountScanOperatorInfo {
63
  SReadHandle  readHandle;
64
  SSDataBlock* pRes;
65

66
  STableCountScanSupp supp;
67

68
  int32_t currGrpIdx;
69
  SArray* stbUidList;  // when group by db_name and/or stable_name
70
} STableCountScanOperatorInfo;
71

72
static bool    processBlockWithProbability(const SSampleExecInfo* pInfo);
73
static int32_t doTableCountScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes);
74

75
bool processBlockWithProbability(const SSampleExecInfo* pInfo) {
2,147,483,647✔
76
#if 0
77
  if (pInfo->sampleRatio == 1) {
78
    return true;
79
  }
80

81
  uint32_t val = taosRandR((uint32_t*) &pInfo->seed);
82
  return (val % ((uint32_t)(1/pInfo->sampleRatio))) == 0;
83
#else
84
  return true;
2,147,483,647✔
85
#endif
86
}
87

88
static void switchCtxOrder(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
268,066✔
89
  for (int32_t i = 0; i < numOfOutput; ++i) {
268,066!
90
    SWITCH_ORDER(pCtx[i].order);
×
91
  }
92
}
268,066✔
93

94
static int32_t overlapWithTimeWindow(SInterval* pInterval, SDataBlockInfo* pBlockInfo, int32_t order, bool* overlap) {
2,147,483,647✔
95
  int32_t     code = TSDB_CODE_SUCCESS;
2,147,483,647✔
96
  STimeWindow w = {0};
2,147,483,647✔
97

98
  // 0 by default, which means it is not a interval operator of the upstream operator.
99
  if (pInterval->interval == 0) {
2,147,483,647✔
100
    *overlap = false;
2,147,483,647✔
101
    return code;
2,147,483,647✔
102
  }
103

104
  if (order == TSDB_ORDER_ASC) {
302,469,697✔
105
    w = getAlignQueryTimeWindow(pInterval, pBlockInfo->window.skey);
287,182,705✔
106
    if (w.ekey < pBlockInfo->window.skey) {
287,179,560!
107
      qError("w.ekey:%" PRId64 " < pBlockInfo->window.skey:%" PRId64, w.ekey, pBlockInfo->window.skey);
×
108
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
109
    }
110

111
    if (w.ekey < pBlockInfo->window.ekey) {
287,149,534✔
112
      *overlap = true;
250,566,662✔
113
      return code;
250,567,352✔
114
    }
115

116
    while (1) {
117
      getNextTimeWindow(pInterval, &w, order);
36,596,071✔
118
      if (w.skey > pBlockInfo->window.ekey) {
36,614,882✔
119
        break;
35,615,951✔
120
      }
121

122
      if (w.ekey <= pBlockInfo->window.ekey) {
993,420!
123
        qError("w.ekey:%" PRId64 " <= pBlockInfo->window.ekey:%" PRId64, w.ekey, pBlockInfo->window.ekey);
×
124
        return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
125
      }
126
      if (TMAX(w.skey, pBlockInfo->window.skey) <= pBlockInfo->window.ekey) {
993,420!
127
        *overlap = true;
993,420✔
128
        return code;
993,420✔
129
      }
130
    }
131
  } else {
132
    w = getAlignQueryTimeWindow(pInterval, pBlockInfo->window.ekey);
15,286,992✔
133
    if (w.skey > pBlockInfo->window.ekey) {
15,288,260!
134
      qError("w.skey:%" PRId64 " > pBlockInfo->window.skey:%" PRId64, w.skey, pBlockInfo->window.ekey);
×
135
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
136
    }
137

138
    if (w.skey > pBlockInfo->window.skey) {
15,284,462✔
139
      *overlap = true;
14,186,673✔
140
      return code;
14,185,550✔
141
    }
142

143
    while (1) {
144
      getNextTimeWindow(pInterval, &w, order);
1,099,952✔
145
      if (w.ekey < pBlockInfo->window.skey) {
1,102,710✔
146
        break;
1,088,964✔
147
      }
148

149
      if (w.skey >= pBlockInfo->window.skey) {
13,746!
150
        qError("w.skey:%" PRId64 " >= pBlockInfo->window.skey:%" PRId64, w.skey, pBlockInfo->window.skey);
×
151
        return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
152
      }
153
      if (pBlockInfo->window.skey <= TMIN(w.ekey, pBlockInfo->window.ekey)) {
13,746!
154
        *overlap = true;
13,746✔
155
        return code;
13,746✔
156
      }
157
    }
158
  }
159

160
  *overlap = false;
36,704,915✔
161
  return code;
36,693,672✔
162
}
163

164
// this function is for table scanner to extract temporary results of upstream aggregate results.
165
static SResultRow* getTableGroupOutputBuf(SOperatorInfo* pOperator, uint64_t groupId, SFilePage** pPage) {
452,012,449✔
166
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) {
452,012,449!
167
    return NULL;
×
168
  }
169

170
  int64_t buf[2] = {0};
452,040,139✔
171
  SET_RES_WINDOW_KEY((char*)buf, &groupId, sizeof(groupId), groupId);
452,012,501✔
172

173
  STableScanInfo* pTableScanInfo = pOperator->info;
452,007,636✔
174

175
  SResultRowPosition* p1 = (SResultRowPosition*)tSimpleHashGet(pTableScanInfo->base.pdInfo.pAggSup->pResultRowHashTable,
452,032,484✔
176
                                                               buf, GET_RES_WINDOW_KEY_LEN(sizeof(groupId)));
177

178
  if (p1 == NULL) {
452,056,631✔
179
    return NULL;
205,324,613✔
180
  }
181

182
  *pPage = getBufPage(pTableScanInfo->base.pdInfo.pAggSup->pResultBuf, p1->pageId);
246,732,018✔
183
  if (NULL == *pPage) {
246,723,742!
184
    return NULL;
×
185
  }
186

187
  return (SResultRow*)((char*)(*pPage) + p1->offset);
246,720,376✔
188
}
189

190
static int32_t insertTableToScanIgnoreList(STableScanInfo* pTableScanInfo, uint64_t uid) {
29,435,274✔
191
  if (NULL == pTableScanInfo->pIgnoreTables) {
29,435,274✔
192
    int32_t tableNum = taosArrayGetSize(pTableScanInfo->base.pTableListInfo->pTableList);
1,280,384✔
193
    pTableScanInfo->pIgnoreTables =
1,280,384✔
194
        taosHashInit(tableNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
1,280,384✔
195
    if (NULL == pTableScanInfo->pIgnoreTables) {
1,280,384!
196
      return terrno;
×
197
    }
198
  }
199

200
  int32_t tempRes = taosHashPut(pTableScanInfo->pIgnoreTables, &uid, sizeof(uid), &pTableScanInfo->scanTimes,
29,435,825✔
201
                                sizeof(pTableScanInfo->scanTimes));
202
  if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
29,434,409!
203
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(tempRes));
×
204
    return tempRes;
×
205
  }
206
  return TSDB_CODE_SUCCESS;
29,434,409✔
207
}
208

209
static int32_t doDynamicPruneDataBlock(SOperatorInfo* pOperator, SDataBlockInfo* pBlockInfo, uint32_t* status) {
2,147,483,647✔
210
  STableScanInfo* pTableScanInfo = pOperator->info;
2,147,483,647✔
211
  int32_t         code = TSDB_CODE_SUCCESS;
2,147,483,647✔
212

213
  if (pTableScanInfo->base.pdInfo.pExprSup == NULL) {
2,147,483,647✔
214
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
215
  }
216

217
  SExprSupp* pSup1 = pTableScanInfo->base.pdInfo.pExprSup;
452,029,777✔
218

219
  SFilePage*  pPage = NULL;
452,026,285✔
220
  SResultRow* pRow = getTableGroupOutputBuf(pOperator, pBlockInfo->id.groupId, &pPage);
452,012,856✔
221

222
  if (pRow == NULL) {
452,025,466✔
223
    return TSDB_CODE_SUCCESS;
205,313,853✔
224
  }
225

226
  bool notLoadBlock = true;
246,711,613✔
227
  for (int32_t i = 0; i < pSup1->numOfExprs; ++i) {
2,147,483,647✔
228
    int32_t functionId = pSup1->pCtx[i].functionId;
2,147,483,647✔
229

230
    SResultRowEntryInfo* pEntry = getResultEntryInfo(pRow, i, pTableScanInfo->base.pdInfo.pExprSup->rowEntryInfoOffset);
2,147,483,647✔
231

232
    EFuncDataRequired reqStatus = fmFuncDynDataRequired(functionId, pEntry, pBlockInfo);
2,147,483,647✔
233
    if (reqStatus != FUNC_DATA_REQUIRED_NOT_LOAD) {
2,147,483,647✔
234
      notLoadBlock = false;
217,264,628✔
235
      break;
217,264,628✔
236
    }
237
  }
238

239
  // release buffer pages
240
  releaseBufPage(pTableScanInfo->base.pdInfo.pAggSup->pResultBuf, pPage);
245,867,089✔
241

242
  if (notLoadBlock) {
246,709,884✔
243
    *status = FUNC_DATA_REQUIRED_NOT_LOAD;
29,434,611✔
244
    code = insertTableToScanIgnoreList(pTableScanInfo, pBlockInfo->id.uid);
29,434,611✔
245
  }
246

247
  return code;
246,710,750✔
248
}
249

250
static int32_t doFilterByBlockSMA(SFilterInfo* pFilterInfo, SColumnDataAgg* pColsAgg, int32_t numOfCols,
41,508,766✔
251
                                  int32_t numOfRows, bool* keep) {
252
  if (pColsAgg == NULL || pFilterInfo == NULL) {
41,508,766!
253
    *keep = true;
×
254
    return TSDB_CODE_SUCCESS;
×
255
  }
256

257
  return filterRangeExecute(pFilterInfo, pColsAgg, numOfCols, numOfRows, keep);
41,508,766✔
258
}
259

260
static int32_t doLoadBlockSMA(STableScanBase* pTableScanInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo,
616,945,526✔
261
                              bool* pLoad) {
262
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
616,945,526✔
263
  bool         allColumnsHaveAgg = true;
616,999,544✔
264
  bool         hasNullSMA = false;
617,017,385✔
265
  if (pLoad != NULL) {
616,979,885!
266
    *pLoad = false;
617,042,202✔
267
  }
268

269
  int32_t code = pAPI->tsdReader.tsdReaderRetrieveBlockSMAInfo(pTableScanInfo->dataReader, pBlock, &allColumnsHaveAgg,
616,960,733✔
270
                                                               &hasNullSMA);
271
  if (code != TSDB_CODE_SUCCESS) {
616,927,785!
272
    return code;
×
273
  }
274

275
  if (!allColumnsHaveAgg || hasNullSMA) {
616,927,785!
276
    *pLoad = false;
538,152,860✔
277
  } else {
278
    *pLoad = true;
78,774,925✔
279
  }
280

281
  return code;
616,921,544✔
282
}
283

284
static int32_t doSetTagColumnData(STableScanBase* pTableScanInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo,
2,147,483,647✔
285
                                  int32_t rows) {
286
  int32_t    code = 0;
2,147,483,647✔
287
  SExprSupp* pSup = &pTableScanInfo->pseudoSup;
2,147,483,647✔
288
  if (pSup->numOfExprs > 0) {
2,147,483,647✔
289
    code = addTagPseudoColumnData(&pTableScanInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pBlock, rows,
1,417,044,623✔
290
                                  pTaskInfo, &pTableScanInfo->metaCache);
291
    // ignore the table not exists error, since this table may have been dropped during the scan procedure.
292
    if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) {
1,417,125,729!
293
      if (pTaskInfo->streamInfo.pState) blockDataCleanup(pBlock);
121!
294
      code = 0;
×
295
    }
296
  }
297

298
  return code;
2,147,483,647✔
299
}
300

301
bool applyLimitOffset(SLimitInfo* pLimitInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo) {
2,147,483,647✔
302
  SLimit*     pLimit = &pLimitInfo->limit;
2,147,483,647✔
303
  const char* id = GET_TASKID(pTaskInfo);
2,147,483,647✔
304

305
  if (pLimitInfo->remainOffset > 0) {
2,147,483,647✔
306
    if (pLimitInfo->remainOffset >= pBlock->info.rows) {
29,723,490✔
307
      pLimitInfo->remainOffset -= pBlock->info.rows;
12,080,858✔
308
      blockDataEmpty(pBlock);
12,080,858✔
309
      qDebug("current block ignore due to offset, current:%" PRId64 ", %s", pLimitInfo->remainOffset, id);
12,080,858✔
310
      return false;
12,080,858✔
311
    } else {
312
      int32_t code = blockDataTrimFirstRows(pBlock, pLimitInfo->remainOffset);
17,642,632✔
313
      if (code != TSDB_CODE_SUCCESS) {
17,642,632!
314
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
315
        pTaskInfo->code = code;
×
316
        T_LONG_JMP(pTaskInfo->env, code);
×
317
      }
318
      pLimitInfo->remainOffset = 0;
17,642,632✔
319
    }
320
  }
321

322
  if (pLimit->limit != -1 && pLimit->limit <= (pLimitInfo->numOfOutputRows + pBlock->info.rows)) {
2,147,483,647✔
323
    // limit the output rows
324
    int32_t keep = (int32_t)(pLimit->limit - pLimitInfo->numOfOutputRows);
142,164,942✔
325
    blockDataKeepFirstNRows(pBlock, keep);
142,163,633✔
326

327
    pLimitInfo->numOfOutputRows += pBlock->info.rows;
142,161,077✔
328
    qDebug("output limit %" PRId64 " has reached, %s", pLimit->limit, id);
142,160,856✔
329
    return true;
142,162,712✔
330
  }
331

332
  pLimitInfo->numOfOutputRows += pBlock->info.rows;
2,147,483,647✔
333
  return false;
2,147,483,647✔
334
}
335

336
static bool isDynVtbScan(SOperatorInfo* pOperator) {
67,170,265✔
337
  return pOperator->dynamicTask && ((STableScanInfo*)(pOperator->info))->virtualStableScan;
67,170,265!
338
}
339

340
static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableScanInfo, SSDataBlock* pBlock,
2,147,483,647✔
341
                             uint32_t* status) {
342
  int32_t        code = TSDB_CODE_SUCCESS;
2,147,483,647✔
343
  int32_t        lino = 0;
2,147,483,647✔
344
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
2,147,483,647✔
345
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
2,147,483,647✔
346
  bool           loadSMA = false;
2,147,483,647✔
347

348
  SFileBlockLoadRecorder* pCost = &pTableScanInfo->readRecorder;
2,147,483,647✔
349

350
  pCost->totalBlocks += 1;
2,147,483,647✔
351
  pCost->totalRows += pBlock->info.rows;
2,147,483,647✔
352
  *status = pTableScanInfo->dataBlockLoadFlag;
2,147,483,647✔
353

354
  if (pOperator->exprSupp.pFilterInfo != NULL) {
2,147,483,647✔
355
    (*status) = FUNC_DATA_REQUIRED_DATA_LOAD;
441,358,669✔
356
  } else {
357
    bool overlap = false;
2,147,483,647✔
358
    int  ret =
359
        overlapWithTimeWindow(&pTableScanInfo->pdInfo.interval, &pBlock->info, pTableScanInfo->cond.order, &overlap);
2,147,483,647✔
360
    if (ret != TSDB_CODE_SUCCESS) {
2,147,483,647!
361
      return ret;
×
362
    }
363
    if (overlap) {
2,147,483,647!
364
      (*status) = FUNC_DATA_REQUIRED_DATA_LOAD;
265,718,746✔
365
    }
366
  }
367

368
  SDataBlockInfo* pBlockInfo = &pBlock->info;
2,147,483,647✔
369
  taosMemoryFreeClear(pBlock->pBlockAgg);
2,147,483,647!
370

371
  if (*status == FUNC_DATA_REQUIRED_FILTEROUT) {
2,147,483,647!
372
    qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, GET_TASKID(pTaskInfo),
×
373
           pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
374
    pCost->filterOutBlocks += 1;
×
375
    pCost->totalRows += pBlock->info.rows;
×
376
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
377
    return TSDB_CODE_SUCCESS;
×
378
  } else if (*status == FUNC_DATA_REQUIRED_NOT_LOAD) {
2,147,483,647✔
379
    qDebug("%s data block skipped, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64 ", uid:%" PRIu64,
157,125,091✔
380
           GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows,
381
           pBlockInfo->id.uid);
382
    code = doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows);
157,142,863✔
383
    pCost->skipBlocks += 1;
157,156,541✔
384
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
157,157,664✔
385
    return code;
157,156,541✔
386
  } else if (*status == FUNC_DATA_REQUIRED_SMA_LOAD) {
2,147,483,647✔
387
    pCost->loadBlockStatis += 1;
175,600,433✔
388
    loadSMA = true;  // mark the operation of load sma;
175,609,008✔
389
    bool success = true;
175,609,008✔
390
    code = doLoadBlockSMA(pTableScanInfo, pBlock, pTaskInfo, &success);
175,605,466✔
391
    if (code) {
175,586,883!
392
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
393
      qError("%s failed to retrieve sma info", GET_TASKID(pTaskInfo));
×
394
      QUERY_CHECK_CODE(code, lino, _end);
1,455!
395
    }
396

397
    if (success) {  // failed to load the block sma data, data block statistics does not exist, load data block instead
175,588,004!
398
      qDebug("%s data block SMA loaded, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, GET_TASKID(pTaskInfo),
37,266,159✔
399
             pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
400
      code = doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows);
37,266,159✔
401
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
37,266,159✔
402
      return code;
37,266,159✔
403
    } else {
404
      qDebug("%s failed to load SMA, since not all columns have SMA", GET_TASKID(pTaskInfo));
138,321,845✔
405
      *status = FUNC_DATA_REQUIRED_DATA_LOAD;
138,357,093✔
406
    }
407
  }
408

409
  if (*status != FUNC_DATA_REQUIRED_DATA_LOAD) {
2,147,483,647!
410
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
411
    qError("%s loadDataBlock invalid status:%d", GET_TASKID(pTaskInfo), *status);
×
412
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
413
  }
414

415
  // try to filter data block according to sma info
416
  if (pOperator->exprSupp.pFilterInfo != NULL && (!loadSMA)) {
2,147,483,647✔
417
    bool success = true;
441,360,037✔
418
    code = doLoadBlockSMA(pTableScanInfo, pBlock, pTaskInfo, &success);
441,373,658✔
419
    if (code) {
441,284,287!
420
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
421
      qError("%s failed to retrieve sma info", GET_TASKID(pTaskInfo));
×
422
      QUERY_CHECK_CODE(code, lino, _end);
47,826!
423
    }
424

425
    if (success) {
441,332,082!
426
      size_t size = taosArrayGetSize(pBlock->pDataBlock);
41,508,766✔
427
      bool   keep = false;
41,508,766✔
428
      code = doFilterByBlockSMA(pOperator->exprSupp.pFilterInfo, pBlock->pBlockAgg, size, pBlockInfo->rows, &keep);
41,508,766✔
429
      if (code) {
41,508,766!
430
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
431
        qError("%s failed to do filter by block sma, code:%s", GET_TASKID(pTaskInfo), tstrerror(code));
×
432
        QUERY_CHECK_CODE(code, lino, _end);
×
433
      }
434

435
      if (!keep) {
41,508,766!
436
        qDebug("%s data block filter out by block SMA, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64,
4,315,127!
437
               GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
438
        pCost->filterOutBlocks += 1;
4,315,127✔
439
        (*status) = FUNC_DATA_REQUIRED_FILTEROUT;
4,315,127✔
440
        taosMemoryFreeClear(pBlock->pBlockAgg);
4,315,127!
441

442
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
4,315,127✔
443
        return TSDB_CODE_SUCCESS;
4,315,127✔
444
      }
445
    }
446
  }
447

448
  // free the sma info, since it should not be involved in *later computing process.
449
  taosMemoryFreeClear(pBlock->pBlockAgg);
2,147,483,647!
450

451
  // try to filter data block according to current results
452
  code = doDynamicPruneDataBlock(pOperator, pBlockInfo, status);
2,147,483,647✔
453
  if (code) {
2,147,483,647!
454
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
455
    QUERY_CHECK_CODE(code, lino, _end);
×
456
  }
457

458
  if (*status == FUNC_DATA_REQUIRED_NOT_LOAD) {
2,147,483,647✔
459
    qDebug("%s data block skipped due to dynamic prune, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64,
29,434,409!
460
           GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
461
    pCost->skipBlocks += 1;
29,435,825✔
462
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
29,435,825✔
463

464
    STableScanInfo* p1 = pOperator->info;
29,435,825✔
465
    if (taosHashGetSize(p1->pIgnoreTables) == taosArrayGetSize(p1->base.pTableListInfo->pTableList)) {
29,435,825✔
466
      *status = FUNC_DATA_REQUIRED_ALL_FILTEROUT;
762,936✔
467
    } else {
468
      *status = FUNC_DATA_REQUIRED_FILTEROUT;
28,672,889✔
469
    }
470
    return TSDB_CODE_SUCCESS;
29,435,825✔
471
  }
472

473
  pCost->totalCheckedRows += pBlock->info.rows;
2,147,483,647✔
474
  pCost->loadBlocks += 1;
2,147,483,647✔
475

476
  SSDataBlock* p = NULL;
2,147,483,647✔
477
  code = pAPI->tsdReader.tsdReaderRetrieveDataBlock(pTableScanInfo->dataReader, &p, NULL);
2,147,483,647✔
478
  if (p == NULL || code != TSDB_CODE_SUCCESS || p != pBlock) {
2,147,483,647!
479
    return code;
×
480
  }
481

482
  if ((pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) &&
2,147,483,647✔
483
      ((STableScanInfo*)pOperator->info)->ignoreTag) {
2,147,483,647!
484
    // do nothing
485
  } else {
486
    // dyn vtb scan do not read tag from origin tables.
487
    code = doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows);
2,147,483,647✔
488
    if (code) {
2,147,483,647!
489
      return code;
×
490
    }
491
  }
492

493
  // restore the previous value
494
  pCost->totalRows -= pBlock->info.rows;
2,147,483,647✔
495

496
  if (pOperator->exprSupp.pFilterInfo != NULL) {
2,147,483,647✔
497
    code = doFilter(pBlock, pOperator->exprSupp.pFilterInfo, &pTableScanInfo->matchInfo, NULL);
436,950,283✔
498
    QUERY_CHECK_CODE(code, lino, _end);
436,882,032✔
499

500
    int64_t st = taosGetTimestampUs();
436,951,058✔
501
    double  el = (taosGetTimestampUs() - st) / 1000.0;
436,966,940✔
502
    pTableScanInfo->readRecorder.filterTime += el;
436,966,940✔
503

504
    if (pBlock->info.rows == 0) {
436,926,332✔
505
      pCost->filterOutBlocks += 1;
62,198,340✔
506
      qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64 ", elapsed time:%.2f ms",
62,217,682✔
507
             GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, el);
508
    } else {
509
      qDebug("%s data block filter applied, elapsed time:%.2f ms", GET_TASKID(pTaskInfo), el);
374,672,536✔
510
    }
511
  }
512

513
  bool limitReached = applyLimitOffset(&pTableScanInfo->limitInfo, pBlock, pTaskInfo);
2,147,483,647✔
514
  if (limitReached) {  // set operator flag is done
2,147,483,647✔
515
    setOperatorCompleted(pOperator);
21,654,713✔
516
  }
517

518
  pCost->totalRows += pBlock->info.rows;
2,147,483,647✔
519

520
_end:
2,147,483,647✔
521
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
522
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
1,542!
523
  }
524
  return code;
2,147,483,647✔
525
}
526

527
static void prepareForDescendingScan(STableScanBase* pTableScanInfo, SqlFunctionCtx* pCtx, int32_t numOfOutput) {
268,066✔
528
  SET_REVERSE_SCAN_FLAG(pTableScanInfo);
268,066✔
529

530
  switchCtxOrder(pCtx, numOfOutput);
268,066✔
531
  pTableScanInfo->cond.order = TSDB_ORDER_DESC;
268,066✔
532
  // STimeWindow* pTWindow = &pTableScanInfo->cond.twindows;
533
  // TSWAP(pTWindow->skey, pTWindow->ekey);
534
}
268,066✔
535

536
typedef struct STableCachedVal {
537
  const char* pName;
538
  STag*       pTags;
539
} STableCachedVal;
540

541
static void freeTableCachedVal(void* param) {
1,080,243,096✔
542
  if (param == NULL) {
1,080,243,096!
543
    return;
×
544
  }
545

546
  STableCachedVal* pVal = param;
1,080,243,096✔
547
  taosMemoryFree((void*)pVal->pName);
1,080,243,096✔
548
  taosMemoryFree(pVal->pTags);
1,080,266,771✔
549
  taosMemoryFree(pVal);
1,080,259,790✔
550
}
551

552
static int32_t createTableCacheVal(const SMetaReader* pMetaReader, STableCachedVal** ppResVal) {
1,079,834,625✔
553
  int32_t          code = TSDB_CODE_SUCCESS;
1,079,834,625✔
554
  int32_t          lino = 0;
1,079,834,625✔
555
  STableCachedVal* pVal = taosMemoryMalloc(sizeof(STableCachedVal));
1,079,834,625✔
556
  QUERY_CHECK_NULL(pVal, code, lino, _end, terrno);
1,079,910,692!
557

558
  pVal->pTags = NULL;
1,079,910,692✔
559
  pVal->pName = taosStrdup(pMetaReader->me.name);
1,079,892,042✔
560
  QUERY_CHECK_NULL(pVal->pName, code, lino, _end, terrno);
1,079,810,033!
561

562
  // only child table has tag value
563
  if (pMetaReader->me.type == TSDB_CHILD_TABLE || pMetaReader->me.type == TSDB_VIRTUAL_CHILD_TABLE) {
1,079,851,235!
564
    STag* pTag = (STag*)pMetaReader->me.ctbEntry.pTags;
1,078,776,556✔
565
    pVal->pTags = taosMemoryMalloc(pTag->len);
1,078,881,976✔
566
    QUERY_CHECK_NULL(pVal->pTags, code, lino, _end, terrno);
1,078,872,475!
567
    memcpy(pVal->pTags, pTag, pTag->len);
1,078,859,386!
568
  }
569

570
  (*ppResVal) = pVal;
1,079,891,520✔
571

572
_end:
1,080,024,373✔
573
  if (code != TSDB_CODE_SUCCESS) {
1,080,024,373!
574
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
575
    freeTableCachedVal(pVal);
×
576
  }
577
  return code;
1,079,809,661✔
578
}
579

580
// const void *key, size_t keyLen, void *value
581
static void freeCachedMetaItem(const void* key, size_t keyLen, void* value, void* ud) {
1,080,249,654✔
582
  (void)key;
583
  (void)keyLen;
584
  (void)ud;
585
  freeTableCachedVal(value);
1,080,249,654✔
586
}
1,080,272,523✔
587

588
static void doSetNullValue(SSDataBlock* pBlock, const SExprInfo* pExpr, int32_t numOfExpr) {
×
589
  for (int32_t j = 0; j < numOfExpr; ++j) {
×
590
    int32_t dstSlotId = pExpr[j].base.resSchema.slotId;
×
591

592
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, dstSlotId);
×
593
    colDataSetNNULL(pColInfoData, 0, pBlock->info.rows);
×
594
  }
595
}
×
596

597
static void freeTableCachedValObj(STableCachedVal* pVal) {
×
598
  taosMemoryFree((void*)pVal->pName);
×
599
  taosMemoryFree(pVal->pTags);
×
600
}
×
601

602
int32_t addTagPseudoColumnData(SReadHandle* pHandle, const SExprInfo* pExpr, int32_t numOfExpr, SSDataBlock* pBlock,
1,524,515,927✔
603
                               int32_t rows, SExecTaskInfo* pTask, STableMetaCacheInfo* pCache) {
604
  int32_t          code = TSDB_CODE_SUCCESS;
1,524,515,927✔
605
  int32_t          lino = 0;
1,524,515,927✔
606
  bool             freeReader = false;
1,524,515,927✔
607
  LRUHandle*       h = NULL;
1,524,515,927✔
608
  STableCachedVal  val = {0};
1,524,515,927✔
609
  SMetaReader      mr = {0};
1,524,515,927✔
610
  const char*      idStr = pTask->id.str;
1,524,628,466✔
611
  int32_t          insertRet = TAOS_LRU_STATUS_OK;
1,524,677,518✔
612
  STableCachedVal* pVal = NULL;
1,524,677,518✔
613

614
  // currently only the tbname pseudo column
615
  if (numOfExpr <= 0) {
1,524,781,302✔
616
    return TSDB_CODE_SUCCESS;
1,652,324✔
617
  }
618

619
  // todo: opt if only require the vgId and the vgVer;
620

621
  // backup the rows
622
  int32_t backupRows = pBlock->info.rows;
1,523,128,978✔
623
  pBlock->info.rows = rows;
1,523,204,891✔
624

625
  // todo refactor: extract method
626
  // the handling of the null data should be packed in the extracted method
627

628
  // 1. check if it is existed in meta cache
629
  if (pCache == NULL) {
1,522,896,897✔
630
    pHandle->api.metaReaderFn.initReader(&mr, pHandle->vnode, META_READER_LOCK, &pHandle->api.metaFn);
723,028✔
631
    code = pHandle->api.metaReaderFn.getEntryGetUidCache(&mr, pBlock->info.id.uid);
723,028✔
632
    if (code != TSDB_CODE_SUCCESS) {
723,028!
633
      // when encounter the TSDB_CODE_PAR_TABLE_NOT_EXIST error, we proceed.
634
      if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) {
×
635
        qWarn("failed to get table meta, table may have been dropped, uid:0x%" PRIx64 ", code:%s, %s",
×
636
              pBlock->info.id.uid, tstrerror(code), idStr);
637

638
        // append null value before return to caller, since the caller will ignore this error code and proceed
639
        doSetNullValue(pBlock, pExpr, numOfExpr);
×
640
      } else {
641
        qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", pBlock->info.id.uid, tstrerror(code), idStr);
×
642
      }
643
      pHandle->api.metaReaderFn.clearReader(&mr);
×
644
      return code;
×
645
    }
646

647
    pHandle->api.metaReaderFn.readerReleaseLock(&mr);
723,028✔
648

649
    val.pName = mr.me.name;
721,596✔
650
    val.pTags = (STag*)mr.me.ctbEntry.pTags;
721,596✔
651

652
    freeReader = true;
721,596✔
653
  } else {
654
    pCache->metaFetch += 1;
1,522,173,869✔
655

656
    h = taosLRUCacheLookup(pCache->pTableMetaEntryCache, &pBlock->info.id.uid, sizeof(pBlock->info.id.uid));
1,522,473,869✔
657
    if (h == NULL) {
1,522,600,084✔
658
      pHandle->api.metaReaderFn.initReader(&mr, pHandle->vnode, META_READER_LOCK, &pHandle->api.metaFn);
1,080,277,932✔
659
      freeReader = true;
1,080,258,755✔
660
      code = pHandle->api.metaReaderFn.getEntryGetUidCache(&mr, pBlock->info.id.uid);
1,080,258,755✔
661
      if (code != TSDB_CODE_SUCCESS) {
1,079,773,510!
662
        if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) {
×
663
          qWarn("failed to get table meta, table may have been dropped, uid:0x%" PRIx64 ", code:%s, %s",
×
664
                pBlock->info.id.uid, tstrerror(code), idStr);
665
          // append null value before return to caller, since the caller will ignore this error code and proceed
666
          doSetNullValue(pBlock, pExpr, numOfExpr);
×
667
        } else {
668
          qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", pBlock->info.id.uid, tstrerror(code),
×
669
                 idStr);
670
        }
671
        pHandle->api.metaReaderFn.clearReader(&mr);
×
672
        return code;
×
673
      }
674

675
      pHandle->api.metaReaderFn.readerReleaseLock(&mr);
1,079,773,510✔
676

677
      code = createTableCacheVal(&mr, &pVal);
1,080,049,958✔
678
      QUERY_CHECK_CODE(code, lino, _end);
1,079,929,809!
679

680
      val = *pVal;
1,079,929,809✔
681
    } else {
682
      pCache->cacheHit += 1;
442,322,152✔
683
      STableCachedVal* pValTmp = taosLRUCacheValue(pCache->pTableMetaEntryCache, h);
442,319,084✔
684
      val = *pValTmp;
442,370,896✔
685

686
      bool bRes = taosLRUCacheRelease(pCache->pTableMetaEntryCache, h, false);
442,387,558✔
687
      qTrace("release LRU cache, res %d", bRes);
442,382,432!
688
    }
689

690
    qDebug("retrieve table meta from cache:%" PRIu64 ", hit:%" PRIu64 " miss:%" PRIu64 ", %s", pCache->metaFetch,
1,522,323,139✔
691
           pCache->cacheHit, (pCache->metaFetch - pCache->cacheHit), idStr);
692
  }
693

694
  for (int32_t j = 0; j < numOfExpr; ++j) {
2,147,483,647✔
695
    const SExprInfo* pExpr1 = &pExpr[j];
2,147,483,647✔
696
    int32_t          dstSlotId = pExpr1->base.resSchema.slotId;
2,147,483,647✔
697

698
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, dstSlotId);
2,147,483,647✔
699
    colInfoDataCleanup(pColInfoData, pBlock->info.rows);
2,147,483,647✔
700

701
    int32_t functionId = pExpr1->pExpr->_function.functionId;
2,147,483,647✔
702

703
    // this is to handle the tbname
704
    if (fmIsScanPseudoColumnFunc(functionId)) {
2,147,483,647✔
705
      int32_t fType = pExpr1->pExpr->_function.functionType;
611,960,436✔
706
      if (fType == FUNCTION_TYPE_TBNAME) {
611,964,456!
707
        code = setTbNameColData(pBlock, pColInfoData, functionId, val.pName);
611,964,456✔
708
        QUERY_CHECK_CODE(code, lino, _end);
611,940,769!
709
      } else if (fType == FUNCTION_TYPE_VGID) {
×
710
        code = setVgIdColData(pBlock, pColInfoData, functionId, pTask->id.vgId);
×
711
        QUERY_CHECK_CODE(code, lino, _end);
×
712
      } else if (fType == FUNCTION_TYPE_VGVER) {
×
713
        code = setVgVerColData(pBlock, pColInfoData, functionId, pBlock->info.version);
×
714
        QUERY_CHECK_CODE(code, lino, _end);
×
715
      }
716
    } else {  // these are tags
717
      STagVal tagVal = {0};
2,147,483,647✔
718
      tagVal.cid = pExpr1->base.pParam[0].pCol->colId;
2,147,483,647✔
719
      const char* p = pHandle->api.metaFn.extractTagVal(val.pTags, pColInfoData->info.type, &tagVal);
2,147,483,647✔
720

721
      char* data = NULL;
2,147,483,647✔
722
      if (pColInfoData->info.type != TSDB_DATA_TYPE_JSON && p != NULL) {
2,147,483,647✔
723
        data = tTagValToData((const STagVal*)p, false);
2,147,483,647✔
724
      } else {
725
        data = (char*)p;
29,599,250✔
726
      }
727

728
      bool isNullVal = (data == NULL) || (pColInfoData->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data));
2,147,483,647✔
729
      if (isNullVal) {
2,147,483,647✔
730
        colDataSetNNULL(pColInfoData, 0, pBlock->info.rows);
27,608,986!
731
      } else if (pColInfoData->info.type != TSDB_DATA_TYPE_JSON) {
2,147,483,647✔
732
        code = colDataSetNItems(pColInfoData, 0, data, pBlock->info.rows, 1, false);
2,147,483,647✔
733
        if (IS_VAR_DATA_TYPE(((const STagVal*)p)->type)) {
2,147,483,647!
734
          char* tmp = taosMemoryCalloc(1, varDataLen(data) + 1);
1,107,421,606✔
735
          if (tmp != NULL) {
1,107,434,902!
736
            memcpy(tmp, varDataVal(data), varDataLen(data));
1,107,434,902!
737
            qDebug("get tag value:%s, cid:%d, table name:%s, uid%" PRId64, tmp, tagVal.cid, val.pName,
1,107,438,465✔
738
                   pBlock->info.id.uid);
739
            taosMemoryFree(tmp);
1,107,450,488✔
740
          }
741
          taosMemoryFree(data);
1,107,453,730✔
742
        }
743
        QUERY_CHECK_CODE(code, lino, _end);
2,147,483,647!
744
      } else {  // todo opt for json tag
745
        for (int32_t i = 0; i < pBlock->info.rows; ++i) {
8,716,940✔
746
          code = colDataSetVal(pColInfoData, i, data, false);
6,726,676✔
747
          QUERY_CHECK_CODE(code, lino, _end);
6,726,676!
748
        }
749
      }
750
    }
751
  }
752

753
  // restore the rows
754
  pBlock->info.rows = backupRows;
1,523,532,858✔
755

756
_end:
1,523,444,395✔
757

758
  if (NULL != pVal) {
1,523,414,849✔
759
    insertRet =
1,080,254,272✔
760
        taosLRUCacheInsert(pCache->pTableMetaEntryCache, &pBlock->info.id.uid, sizeof(uint64_t), pVal,
1,080,278,165✔
761
                           sizeof(STableCachedVal), freeCachedMetaItem, NULL, NULL, TAOS_LRU_PRIORITY_LOW, NULL);
762
    if (insertRet != TAOS_LRU_STATUS_OK) {
1,080,254,272!
763
      qWarn("failed to put meta into lru cache, code:%d, %s", insertRet, idStr);
×
764
    }
765
  }
766

767
  if (freeReader) {
1,523,390,956✔
768
    pHandle->api.metaReaderFn.clearReader(&mr);
1,080,924,338✔
769
  }
770
  if (code != TSDB_CODE_SUCCESS) {
1,523,387,168!
771
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
772
  }
773
  return code;
1,523,394,875✔
774
}
775

776
int32_t setTbNameColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId,
611,943,436✔
777
                         const char* name) {
778
  int32_t                     code = TSDB_CODE_SUCCESS;
611,943,436✔
779
  int32_t                     lino = 0;
611,943,436✔
780
  struct SScalarFuncExecFuncs fpSet = {0};
611,943,436✔
781
  code = fmGetScalarFuncExecFuncs(functionId, &fpSet);
611,967,007✔
782
  QUERY_CHECK_CODE(code, lino, _end);
611,963,244!
783

784
  size_t len = TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE;
611,963,244✔
785
  char   buf[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
611,963,244✔
786
  STR_TO_VARSTR(buf, name)
611,966,756!
787

788
  SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, len, 1);
611,968,857✔
789

790
  code = colInfoDataEnsureCapacity(&infoData, 1, false);
611,964,274✔
791
  QUERY_CHECK_CODE(code, lino, _end);
611,965,540!
792

793
  code = colDataSetVal(&infoData, 0, buf, false);
611,965,540✔
794
  QUERY_CHECK_CODE(code, lino, _end);
611,964,626!
795

796
  SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .columnData = &infoData};
611,964,626✔
797
  SScalarParam param = {.columnData = pColInfoData};
611,962,326✔
798

799
  if (fpSet.process != NULL) {
611,957,534!
800
    code = fpSet.process(&srcParam, 1, &param);
611,957,534✔
801
    QUERY_CHECK_CODE(code, lino, _end);
611,949,254!
802
  } else {
803
    qError("failed to get the corresponding callback function, functionId:%d", functionId);
×
804
  }
805

806
  colDataDestroy(&infoData);
611,949,254✔
807

808
_end:
611,927,820✔
809
  if (code != TSDB_CODE_SUCCESS) {
611,949,651!
810
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
811
  }
812
  return code;
611,949,651✔
813
}
814

815
int32_t setVgIdColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId, int32_t vgId) {
×
816
  int32_t                     code = TSDB_CODE_SUCCESS;
×
817
  int32_t                     lino = 0;
×
818
  struct SScalarFuncExecFuncs fpSet = {0};
×
819
  code = fmGetScalarFuncExecFuncs(functionId, &fpSet);
×
820
  QUERY_CHECK_CODE(code, lino, _end);
×
821

822
  SColumnInfoData infoData = createColumnInfoData(pColInfoData->info.type, pColInfoData->info.bytes, 1);
×
823

824
  code = colInfoDataEnsureCapacity(&infoData, 1, false);
×
825
  QUERY_CHECK_CODE(code, lino, _end);
×
826

827
  code = colDataSetVal(&infoData, 0, (const char*)&vgId, false);
×
828
  QUERY_CHECK_CODE(code, lino, _end);
×
829

830
  SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .columnData = &infoData};
×
831
  SScalarParam param = {.columnData = pColInfoData};
×
832

833
  if (fpSet.process != NULL) {
×
834
    code = fpSet.process(&srcParam, 1, &param);
×
835
    QUERY_CHECK_CODE(code, lino, _end);
×
836
  } else {
837
    qError("failed to get the corresponding callback function, functionId:%d", functionId);
×
838
  }
839

840
_end:
×
841
  colDataDestroy(&infoData);
×
842
  if (code != TSDB_CODE_SUCCESS) {
×
843
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
844
  }
845
  return code;
×
846
}
847

848
int32_t setVgVerColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId, int64_t vgVer) {
×
849
  int32_t                     code = TSDB_CODE_SUCCESS;
×
850
  int32_t                     lino = 0;
×
851
  struct SScalarFuncExecFuncs fpSet = {0};
×
852
  code = fmGetScalarFuncExecFuncs(functionId, &fpSet);
×
853
  QUERY_CHECK_CODE(code, lino, _end);
×
854

855
  SColumnInfoData infoData = createColumnInfoData(pColInfoData->info.type, pColInfoData->info.bytes, 1);
×
856

857
  code = colInfoDataEnsureCapacity(&infoData, 1, false);
×
858
  QUERY_CHECK_CODE(code, lino, _end);
×
859

860
  code = colDataSetVal(&infoData, 0, (const char*)&vgVer, false);
×
861
  QUERY_CHECK_CODE(code, lino, _end);
×
862

863
  SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .columnData = &infoData};
×
864
  SScalarParam param = {.columnData = pColInfoData};
×
865

866
  if (fpSet.process != NULL) {
×
867
    code = fpSet.process(&srcParam, 1, &param);
×
868
    QUERY_CHECK_CODE(code, lino, _end);
×
869
  } else {
870
    qError("failed to get the corresponding callback function, functionId:%d", functionId);
×
871
  }
872

873
_end:
×
874
  colDataDestroy(&infoData);
×
875
  if (code != TSDB_CODE_SUCCESS) {
×
876
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
877
  }
878
  return code;
×
879
}
880

881
static int32_t initNextGroupScan(STableScanInfo* pInfo, STableKeyInfo** pKeyInfo, int32_t* size) {
812,559,093✔
882
  int32_t code = TSDB_CODE_SUCCESS;
812,559,093✔
883
  int32_t lino = 0;
812,559,093✔
884
  code = tableListGetGroupList(pInfo->base.pTableListInfo, pInfo->currentGroupId, pKeyInfo, size);
812,559,093✔
885
  QUERY_CHECK_CODE(code, lino, _end);
812,525,576!
886

887
  pInfo->tableStartIndex = TARRAY_ELEM_IDX(pInfo->base.pTableListInfo->pTableList, *pKeyInfo);
812,525,576!
888
  pInfo->tableEndIndex = (pInfo->tableStartIndex + (*size) - 1);
812,603,785✔
889
  pInfo->pResBlock->info.blankFill = false;
812,206,132✔
890
  taosMemoryFreeClear(pInfo->pResBlock->pBlockAgg);
812,533,749!
891

892
  if (!pInfo->needCountEmptyTable) {
812,364,906✔
893
    pInfo->countState = TABLE_COUNT_STATE_END;
726,530,985✔
894
  } else {
895
    pInfo->countState = TABLE_COUNT_STATE_SCAN;
85,997,373✔
896
  }
897

898
_end:
812,451,259✔
899
  if (code != TSDB_CODE_SUCCESS) {
812,451,259!
900
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
901
  }
902
  return code;
812,523,739✔
903
}
904

905
void markGroupProcessed(STableScanInfo* pInfo, uint64_t groupId) {
2,147,483,647✔
906
  if (pInfo->countState == TABLE_COUNT_STATE_END) {
2,147,483,647✔
907
    return;
2,147,483,647✔
908
  }
909
  if (pInfo->base.pTableListInfo->groupOffset) {
456,316,242✔
910
    pInfo->countState = TABLE_COUNT_STATE_PROCESSED;
989,596✔
911
  } else {
912
    int32_t code = taosHashRemove(pInfo->base.pTableListInfo->remainGroups, &groupId, sizeof(groupId));
455,313,371✔
913
    if (code != TSDB_CODE_SUCCESS) {
455,337,634✔
914
      qDebug("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
60,071,862!
915
    }
916
  }
917
}
918

919
static SSDataBlock* getOneRowResultBlock(SExecTaskInfo* pTaskInfo, STableScanBase* pBase, SSDataBlock* pBlock,
321,404,644✔
920
                                         const STableKeyInfo* tbInfo) {
921
  blockDataEmpty(pBlock);
321,404,644✔
922
  pBlock->info.rows = 1;
321,425,558✔
923
  pBlock->info.id.uid = tbInfo->uid;
321,428,186✔
924
  pBlock->info.id.groupId = tbInfo->groupId;
321,423,935✔
925
  pBlock->info.blankFill = true;
321,428,186✔
926

927
  // only one row: set all col data to null & hasNull
928
  int32_t col_num = blockDataGetNumOfCols(pBlock);
321,421,445✔
929
  for (int32_t i = 0; i < col_num; ++i) {
1,305,757,175✔
930
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
984,329,599✔
931
    colDataSetNULL(pColInfoData, 0);
932
  }
933

934
  // set tag/tbname
935
  terrno = doSetTagColumnData(pBase, pBlock, pTaskInfo, 1);
321,427,576✔
936

937
  return pBlock;
321,422,574✔
938
}
939

940
static SSDataBlock* getBlockForEmptyTable(SOperatorInfo* pOperator, const STableKeyInfo* tbInfo) {
308,879,326✔
941
  STableScanInfo* pTableScanInfo = pOperator->info;
308,879,326✔
942
  SSDataBlock*    pBlock =
943
      getOneRowResultBlock(pOperator->pTaskInfo, &pTableScanInfo->base, pTableScanInfo->pResBlock, tbInfo);
308,891,298✔
944

945
  pOperator->resultInfo.totalRows++;
308,890,379✔
946
  return pBlock;
308,898,871✔
947
}
948

949
static int32_t doTableScanImplNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
2,147,483,647✔
950
  int32_t         code = TSDB_CODE_SUCCESS;
2,147,483,647✔
951
  int32_t         lino = 0;
2,147,483,647✔
952
  STableScanInfo* pTableScanInfo = pOperator->info;
2,147,483,647✔
953
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
2,147,483,647✔
954
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
2,147,483,647✔
955
  SSDataBlock*    pBlock = pTableScanInfo->pResBlock;
2,147,483,647✔
956
  bool            hasNext = false;
2,147,483,647✔
957
  int64_t         st = taosGetTimestampUs();
2,147,483,647✔
958

959
  QRY_PARAM_CHECK(ppRes);
2,147,483,647!
960
  pBlock->info.dataLoad = false;
2,147,483,647✔
961

962
  while (true) {
82,937,932✔
963
    code = pAPI->tsdReader.tsdNextDataBlock(pTableScanInfo->base.dataReader, &hasNext);
2,147,483,647✔
964
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
965
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
3,084✔
UNCOV
966
      QUERY_CHECK_CODE(code, lino, _end);
×
967
    }
968

969
    if (!hasNext) {
2,147,483,647✔
970
      break;
676,107,975✔
971
    }
972

973
    if (isTaskKilled(pTaskInfo)) {
2,147,483,647✔
974
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
152,836✔
975
      code = pTaskInfo->code;
152,836✔
976
      goto _end;
152,836✔
977
    }
978

979
    if (pOperator->status == OP_EXEC_DONE) {
2,147,483,647✔
980
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
1,293,824✔
981
      break;
1,293,824✔
982
    }
983

984
    // process this data block based on the probabilities
985
    bool processThisBlock = processBlockWithProbability(&pTableScanInfo->sample);
2,147,483,647✔
986
    if (!processThisBlock) {
2,147,483,647!
987
      continue;
×
988
    }
989

990
    if (pBlock->info.id.uid) {
2,147,483,647✔
991
      pBlock->info.id.groupId = tableListGetTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid);
2,147,483,647✔
992
    }
993

994
    uint32_t status = 0;
2,147,483,647✔
995
    code = loadDataBlock(pOperator, &pTableScanInfo->base, pBlock, &status);
2,147,483,647✔
996
    QUERY_CHECK_CODE(code, lino, _end);
2,147,483,647✔
997

998
    if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
2,147,483,647✔
999
      break;
762,936✔
1000
    }
1001

1002
    // current block is filter out according to filter condition, continue load the next block
1003
    if (status == FUNC_DATA_REQUIRED_FILTEROUT || pBlock->info.rows == 0) {
2,147,483,647✔
1004
      continue;
82,937,932✔
1005
    }
1006

1007
    pOperator->resultInfo.totalRows = pTableScanInfo->base.readRecorder.totalRows;
2,147,483,647✔
1008
    pTableScanInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
2,147,483,647✔
1009

1010
    pOperator->cost.totalCost = pTableScanInfo->base.readRecorder.elapsedTime;
2,147,483,647✔
1011
    pBlock->info.scanFlag = pTableScanInfo->base.scanFlag;
2,147,483,647✔
1012

1013
    (*ppRes) = pBlock;
2,147,483,647✔
1014
    return code;
2,147,483,647✔
1015
  }
1016

1017
_end:
678,325,440✔
1018
  if (code != TSDB_CODE_SUCCESS) {
678,350,906✔
1019
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
194,472!
1020
    pTaskInfo->code = code;
194,472✔
1021
    T_LONG_JMP(pTaskInfo->env, code);
157,462!
1022
  }
1023
  return code;
678,156,434✔
1024
}
1025

1026
static int32_t doGroupedTableScan(SOperatorInfo* pOperator, SSDataBlock** pBlock) {
2,147,483,647✔
1027
  int32_t         code = TSDB_CODE_SUCCESS;
2,147,483,647✔
1028
  int32_t         lino = 0;
2,147,483,647✔
1029
  STableScanInfo* pTableScanInfo = pOperator->info;
2,147,483,647✔
1030
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
2,147,483,647✔
1031
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
2,147,483,647✔
1032

1033
  QRY_PARAM_CHECK(pBlock);
2,147,483,647!
1034

1035
  // The read handle is not initialized yet, since no qualified tables exists
1036
  if (pTableScanInfo->base.dataReader == NULL || pOperator->status == OP_EXEC_DONE) {
2,147,483,647!
1037
    return code;
11,059,383✔
1038
  }
1039

1040
  // do the ascending order traverse in the first place.
1041
  while (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) {
2,147,483,647✔
1042
    SSDataBlock* p = NULL;
2,147,483,647✔
1043
    code = doTableScanImplNext(pOperator, &p);
2,147,483,647✔
1044
    QUERY_CHECK_CODE(code, lino, _end);
2,147,483,647!
1045

1046
    if (p != NULL) {
2,147,483,647✔
1047
      markGroupProcessed(pTableScanInfo, p->info.id.groupId);
2,147,483,647✔
1048
      *pBlock = p;
2,147,483,647✔
1049
      return code;
2,147,483,647✔
1050
    }
1051

1052
    pTableScanInfo->scanTimes += 1;
642,468,754✔
1053
    taosHashClear(pTableScanInfo->pIgnoreTables);
642,481,952✔
1054

1055
    if (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) {
642,496,893✔
1056
      setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED);
315,045✔
1057
      pTableScanInfo->base.scanFlag = MAIN_SCAN;
315,045✔
1058
      pTableScanInfo->base.dataBlockLoadFlag = FUNC_DATA_REQUIRED_DATA_LOAD;
315,045✔
1059
      qDebug("start to repeat ascending order scan data blocks due to query func required, %s", GET_TASKID(pTaskInfo));
315,045!
1060

1061
      // do prepare for the next round table scan operation
1062
      code = pAPI->tsdReader.tsdReaderResetStatus(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond);
315,045✔
1063
      QUERY_CHECK_CODE(code, lino, _end);
318,847!
1064
    }
1065
  }
1066

1067
  int32_t total = pTableScanInfo->scanInfo.numOfAsc + pTableScanInfo->scanInfo.numOfDesc;
1,139,953,607✔
1068
  if (pTableScanInfo->scanTimes < total) {
1,139,975,571✔
1069
    if (pTableScanInfo->base.cond.order == TSDB_ORDER_ASC) {
189,135,654✔
1070
      prepareForDescendingScan(&pTableScanInfo->base, pOperator->exprSupp.pCtx, 0);
268,066✔
1071
      code = pAPI->tsdReader.tsdReaderResetStatus(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond);
268,066✔
1072
      QUERY_CHECK_CODE(code, lino, _end);
268,066!
1073
      qDebug("%s start to descending order scan data blocks due to query func required", GET_TASKID(pTaskInfo));
268,066!
1074
    }
1075

1076
    while (pTableScanInfo->scanTimes < total) {
224,804,756✔
1077
      SSDataBlock* p = NULL;
189,140,710✔
1078
      code = doTableScanImplNext(pOperator, &p);
189,119,068✔
1079
      QUERY_CHECK_CODE(code, lino, _end);
189,131,780!
1080

1081
      if (p != NULL) {
189,131,780✔
1082
        markGroupProcessed(pTableScanInfo, p->info.id.groupId);
153,467,957✔
1083
        *pBlock = p;
153,457,293✔
1084
        return code;
153,469,057✔
1085
      }
1086

1087
      pTableScanInfo->scanTimes += 1;
35,663,823✔
1088
      taosHashClear(pTableScanInfo->pIgnoreTables);
35,671,072✔
1089

1090
      if (pTableScanInfo->scanTimes < total) {
35,669,225!
1091
        setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED);
×
1092
        pTableScanInfo->base.scanFlag = MAIN_SCAN;
×
1093

1094
        qDebug("%s start to repeat descending order scan data blocks", GET_TASKID(pTaskInfo));
×
1095
        code = pAPI->tsdReader.tsdReaderResetStatus(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond);
×
1096
        QUERY_CHECK_CODE(code, lino, _end);
3,535!
1097
      }
1098
    }
1099
  }
1100

1101
  if (pTableScanInfo->countState < TABLE_COUNT_STATE_END) {
986,490,605✔
1102
    STableListInfo* pTableListInfo = pTableScanInfo->base.pTableListInfo;
389,667,561✔
1103
    if (pTableListInfo->groupOffset) {  // group by tbname, group by tag + sort
389,668,525✔
1104
      if (pTableScanInfo->countState < TABLE_COUNT_STATE_PROCESSED) {
375,896✔
1105
        pTableScanInfo->countState = TABLE_COUNT_STATE_PROCESSED;
14,178✔
1106
        STableKeyInfo* pStart =
1107
            (STableKeyInfo*)tableListGetInfo(pTableScanInfo->base.pTableListInfo, pTableScanInfo->tableStartIndex);
14,178✔
1108

1109
        if (NULL == pStart) {
14,178!
1110
          return code;
×
1111
        }
1112

1113
        *pBlock = getBlockForEmptyTable(pOperator, pStart);
14,178✔
1114
        return code;
14,178✔
1115
      }
1116
    } else {  // group by tag + no sort
1117
      int32_t numOfTables = 0;
389,291,969✔
1118
      code = tableListGetSize(pTableListInfo, &numOfTables);
389,300,582✔
1119
      QUERY_CHECK_CODE(code, lino, _end);
389,298,284!
1120

1121
      if (pTableScanInfo->tableEndIndex + 1 >= numOfTables) {
389,298,284✔
1122
        // get empty group, mark processed & rm from hash
1123
        void* pIte = taosHashIterate(pTableListInfo->remainGroups, NULL);
387,887,968✔
1124
        if (pIte != NULL) {
387,885,179✔
1125
          size_t        keySize = 0;
308,880,092✔
1126
          uint64_t*     pGroupId = taosHashGetKey(pIte, &keySize);
308,881,716✔
1127
          STableKeyInfo info = {.uid = *(uint64_t*)pIte, .groupId = *pGroupId};
308,869,212✔
1128
          taosHashCancelIterate(pTableListInfo->remainGroups, pIte);
308,870,975✔
1129
          markGroupProcessed(pTableScanInfo, *pGroupId);
308,883,589✔
1130
          *pBlock = getBlockForEmptyTable(pOperator, &info);
308,873,503✔
1131

1132
          return code;
308,885,441✔
1133
        }
1134
      }
1135
    }
1136
    pTableScanInfo->countState = TABLE_COUNT_STATE_END;
80,781,555✔
1137
  }
1138

1139
_end:
596,814,771✔
1140
  if (code != TSDB_CODE_SUCCESS) {
677,582,632!
1141
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1142
    pTaskInfo->code = code;
×
1143
  }
1144

1145
  return code;
677,582,632✔
1146
}
1147

1148
static int32_t createTableListInfoFromParam(SOperatorInfo* pOperator) {
1,233,590✔
1149
  STableScanInfo*          pInfo = pOperator->info;
1,233,590✔
1150
  SExecTaskInfo*           pTaskInfo = pOperator->pTaskInfo;
1,233,590✔
1151
  int32_t                  code = 0;
1,233,590✔
1152
  STableListInfo*          pListInfo = pInfo->base.pTableListInfo;
1,233,590✔
1153
  STableScanOperatorParam* pParam = (STableScanOperatorParam*)pOperator->pOperatorGetParam->value;
1,233,590✔
1154
  int32_t                  num = taosArrayGetSize(pParam->pUidList);
1,233,590✔
1155
  if (num <= 0) {
1,233,590!
1156
    qError("empty table scan uid list");
×
1157
    return TSDB_CODE_INVALID_PARA;
×
1158
  }
1159

1160
  qDebug("vgId:%d add total %d dynamic tables to scan, tableSeq:%d, exist num:%" PRId64 ", operator status:%d",
1,233,590!
1161
         pTaskInfo->id.vgId, num, pParam->tableSeq, (int64_t)taosArrayGetSize(pListInfo->pTableList),
1162
         pOperator->status);
1163

1164
  if (pParam->tableSeq) {
1,233,590!
1165
    pListInfo->oneTableForEachGroup = true;
51,112✔
1166
    if (taosArrayGetSize(pListInfo->pTableList) > 0) {
51,112!
1167
      taosHashClear(pListInfo->map);
×
1168
      taosArrayClear(pListInfo->pTableList);
×
1169
      pOperator->status = OP_EXEC_DONE;
×
1170
    }
1171
  } else {
1172
    pListInfo->oneTableForEachGroup = false;
1,182,478✔
1173
    pListInfo->numOfOuputGroups = 1;
1,182,478✔
1174
  }
1175

1176
  STableKeyInfo info = {.groupId = 0};
1,233,590✔
1177
  int32_t       tableIdx = 0;
1,233,590✔
1178
  for (int32_t i = 0; i < num; ++i) {
47,777,434✔
1179
    uint64_t* pUid = taosArrayGet(pParam->pUidList, i);
46,543,844✔
1180
    if (!pUid) {
46,540,902!
1181
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1182
      return terrno;
×
1183
    }
1184

1185
    if (taosHashPut(pListInfo->map, pUid, sizeof(uint64_t), &tableIdx, sizeof(int32_t))) {
46,540,902✔
1186
      if (TSDB_CODE_DUP_KEY == terrno) {
43,391,721!
1187
        continue;
43,392,849✔
1188
      }
1189
      return terrno;
×
1190
    }
1191

1192
    info.uid = *pUid;
3,154,155✔
1193
    void* p = taosArrayPush(pListInfo->pTableList, &info);
3,154,155✔
1194
    if (p == NULL) {
3,154,155!
1195
      return terrno;
×
1196
    }
1197

1198
    tableIdx++;
3,154,155✔
1199
    qDebug("add dynamic table scan uid:%" PRIu64 ", %s", info.uid, GET_TASKID(pTaskInfo));
3,154,155✔
1200
  }
1201

1202
  return code;
1,233,590✔
1203
}
1204

1205
static int32_t doInitReader(STableScanInfo* pInfo, SExecTaskInfo* pTaskInfo, SStorageAPI* pAPI, int32_t* pNum,
745,332,492✔
1206
                            STableKeyInfo** pList) {
1207
  const char* idStr = GET_TASKID(pTaskInfo);
745,332,492✔
1208
  int32_t     code = initNextGroupScan(pInfo, pList, pNum);
745,423,534✔
1209
  if (code) {
744,999,923!
1210
    qError("%s failed to init groupScan Info, code:%s at line:%d", idStr, tstrerror(code), __LINE__);
×
1211
    return code;
×
1212
  }
1213

1214
  if (pInfo->base.dataReader != NULL) {
744,999,923!
1215
    qError("%s tsdb reader should be null", idStr);
×
1216
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1217
  }
1218

1219
  code = pAPI->tsdReader.tsdReaderOpen(pInfo->base.readHandle.vnode, &pInfo->base.cond, *pList, *pNum, pInfo->pResBlock,
1,490,294,806✔
1220
                                       (void**)&pInfo->base.dataReader, idStr, &pInfo->pIgnoreTables);
745,285,775✔
1221
  if (code) {
745,184,909✔
1222
    qError("%s failed to open tsdbReader, code:%s at line:%d", idStr, tstrerror(code), __LINE__);
18,520!
1223
  }
1224

1225
  return code;
745,234,964✔
1226
}
1227

1228
int compareColIdPair(const void* elem1, const void* elem2) {
442,860,554✔
1229
  SColIdPair* node1 = (SColIdPair*)elem1;
442,860,554✔
1230
  SColIdPair* node2 = (SColIdPair*)elem2;
442,860,554✔
1231

1232
  if (node1->orgColId < node2->orgColId) {
442,860,554✔
1233
    return -1;
442,486,874✔
1234
  }
1235

1236
  return node1->orgColId > node2->orgColId;
373,680✔
1237
}
1238

1239
static int32_t createVTableScanInfoFromParam(SOperatorInfo* pOperator) {
65,936,675✔
1240
  int32_t                  code = 0;
65,936,675✔
1241
  int32_t                  lino = 0;
65,936,675✔
1242
  STableScanInfo*          pInfo = pOperator->info;
65,936,675✔
1243
  SExecTaskInfo*           pTaskInfo = pOperator->pTaskInfo;
65,936,675✔
1244
  SStorageAPI*             pAPI = &pTaskInfo->storageAPI;
65,936,675✔
1245
  STableListInfo*          pListInfo = pInfo->base.pTableListInfo;
65,936,675✔
1246
  STableScanOperatorParam* pParam = (STableScanOperatorParam*)pOperator->pOperatorGetParam->value;
65,936,675✔
1247
  SMetaReader              orgTable = {0};
65,936,675✔
1248
  SMetaReader              superTable = {0};
65,936,675✔
1249
  SSchemaWrapper*          schema = NULL;
65,936,675✔
1250
  SArray*                  pColArray = NULL;
65,936,675✔
1251
  SArray*                  pBlockColArray = NULL;
65,936,675✔
1252
  int32_t                  num = 0;
65,936,675✔
1253
  STableKeyInfo*           pList = NULL;
65,936,675✔
1254

1255
  cleanupQueryTableDataCond(&pInfo->base.cond);
65,936,675✔
1256
  if (pAPI->tsdReader.tsdReaderClose) {
65,936,675!
1257
    pAPI->tsdReader.tsdReaderClose(pInfo->base.dataReader);
65,936,675✔
1258
  }
1259
  pInfo->base.dataReader = NULL;
65,936,675✔
1260

1261
  pAPI->metaReaderFn.initReader(&orgTable, pInfo->base.readHandle.vnode, META_READER_LOCK, &pAPI->metaFn);
65,936,675✔
1262
  code = pAPI->metaReaderFn.getTableEntryByName(&orgTable, strstr(pParam->pOrgTbInfo->tbName, ".") + 1);
65,936,675!
1263
  pAPI->metaReaderFn.readerReleaseLock(&orgTable);
65,936,675✔
1264
  qDebug("dynamic vtable scan for origin table:%s, %s", pParam->pOrgTbInfo->tbName, GET_TASKID(pTaskInfo));
65,936,675✔
1265
  QUERY_CHECK_CODE(code, lino, _return);
65,936,675!
1266
  switch (orgTable.me.type) {
65,936,675!
1267
    case TSDB_CHILD_TABLE:
24,184,907✔
1268
      pAPI->metaReaderFn.initReader(&superTable, pInfo->base.readHandle.vnode, META_READER_LOCK, &pAPI->metaFn);
24,184,907✔
1269
      code = pAPI->metaReaderFn.getTableEntryByUid(&superTable, orgTable.me.ctbEntry.suid);
24,184,907✔
1270
      pAPI->metaReaderFn.readerReleaseLock(&superTable);
24,184,907✔
1271
      QUERY_CHECK_CODE(code, lino, _return);
24,184,907!
1272
      schema = &superTable.me.stbEntry.schemaRow;
24,184,907✔
1273
      break;
24,184,907✔
1274
    case TSDB_NORMAL_TABLE:
41,751,768✔
1275
      schema = &orgTable.me.ntbEntry.schemaRow;
41,751,768✔
1276
      break;
41,751,768✔
1277
    default:
×
1278
      qError("invalid table type:%d", orgTable.me.type);
×
1279
      return TSDB_CODE_INVALID_PARA;
×
1280
      break;
1281
  }
1282

1283
  pColArray = taosArrayInit(schema->nCols, sizeof(SColIdPair));
65,936,675✔
1284
  QUERY_CHECK_NULL(pColArray, code, lino, _return, terrno);
65,936,675!
1285
  pBlockColArray = taosArrayInit(schema->nCols, sizeof(int32_t));
65,936,675✔
1286
  QUERY_CHECK_NULL(pBlockColArray, code, lino, _return, terrno);
65,936,675!
1287

1288
  // virtual table's origin table scan do not has ts column.
1289
  SColIdPair tsPair = {.vtbColId = PRIMARYKEY_TIMESTAMP_COL_ID, .orgColId = PRIMARYKEY_TIMESTAMP_COL_ID};
65,936,675✔
1290
  QUERY_CHECK_NULL(taosArrayPush(pColArray, &tsPair), code, lino, _return, terrno);
65,936,675!
1291

1292
  for (int32_t i = 0; i < taosArrayGetSize(pParam->pOrgTbInfo->colMap); ++i) {
169,417,114✔
1293
    SColIdNameKV* kv = taosArrayGet(pParam->pOrgTbInfo->colMap, i);
103,480,439✔
1294
    for (int32_t j = 0; j < schema->nCols; j++) {
807,788,763!
1295
      if (strcmp(kv->colName, schema->pSchema[j].name) == 0) {
807,788,763!
1296
        SColIdPair pPair = {.vtbColId = kv->colId, .orgColId = (col_id_t)(j + 1)};
103,480,439✔
1297
        QUERY_CHECK_NULL(taosArrayPush(pColArray, &pPair), code, lino, _return, terrno);
103,480,439!
1298
        break;
103,480,439✔
1299
      }
1300
    }
1301
  }
1302

1303
  for (int32_t i = 0; i < taosArrayGetSize(pColArray); i++) {
235,353,789✔
1304
    SColIdPair* pPair = (SColIdPair*)taosArrayGet(pColArray, i);
169,417,114✔
1305
    for (int32_t j = 0; j < taosArrayGetSize(pInfo->base.matchInfo.pList); j++) {
840,630,882!
1306
      SColMatchItem* pItem = taosArrayGet(pInfo->base.matchInfo.pList, j);
840,630,882✔
1307
      if (pItem->colId == pPair->vtbColId) {
840,630,882✔
1308
        SColIdPair tmpPair = {.orgColId = pPair->orgColId, .vtbColId = pItem->dstSlotId};
169,417,114✔
1309
        QUERY_CHECK_NULL(taosArrayPush(pBlockColArray, &tmpPair), code, lino, _return, terrno);
169,417,114!
1310
        break;
169,417,114✔
1311
      }
1312
    }
1313
  }
1314

1315
  if (pInfo->pResBlock) {
65,936,675✔
1316
    blockDataDestroy(pInfo->pResBlock);
60,468,007✔
1317
    pInfo->pResBlock = NULL;
60,468,007✔
1318
  }
1319
  taosArraySort(pColArray, compareColIdPair);
65,936,675✔
1320
  taosArraySort(pBlockColArray, compareColIdPair);
65,936,675✔
1321
  code = createOneDataBlockWithColArray(pInfo->pOrgBlock, pBlockColArray, &pInfo->pResBlock);
65,936,675✔
1322
  QUERY_CHECK_CODE(code, lino, _return);
65,936,675!
1323
  code =
1324
      initQueryTableDataCondWithColArray(&pInfo->base.cond, &pInfo->base.orgCond, &pInfo->base.readHandle, pColArray);
65,936,675✔
1325
  QUERY_CHECK_CODE(code, lino, _return);
65,936,675!
1326
  if (pParam->window.ekey > 0) {
65,936,675✔
1327
    pInfo->base.cond.twindows.skey = pParam->window.ekey + 1;
49,096,791✔
1328
  }
1329
  pInfo->base.cond.suid = orgTable.me.type == TSDB_CHILD_TABLE ? superTable.me.uid : 0;
65,936,675✔
1330
  pInfo->currentGroupId = 0;
65,936,675✔
1331
  pInfo->ignoreTag = true;
65,936,675✔
1332

1333
  pListInfo->oneTableForEachGroup = true;
65,936,675✔
1334
  taosHashClear(pListInfo->map);
65,936,675✔
1335
  taosArrayClear(pListInfo->pTableList);
65,936,675✔
1336

1337
  uint64_t      pUid = orgTable.me.uid;
65,936,675✔
1338
  STableKeyInfo info = {.groupId = 0, .uid = pUid};
65,936,675✔
1339
  int32_t       tableIdx = 0;
65,936,675✔
1340
  code = taosHashPut(pListInfo->map, &pUid, sizeof(uint64_t), &tableIdx, sizeof(int32_t));
65,936,675✔
1341
  QUERY_CHECK_CODE(code, lino, _return);
65,936,675!
1342
  QUERY_CHECK_NULL(taosArrayPush(pListInfo->pTableList, &info), code, lino, _return, terrno);
131,873,350!
1343
  qDebug("add dynamic table scan uid:%" PRIu64 ", %s", info.uid, GET_TASKID(pTaskInfo));
65,936,675✔
1344

1345
  pOperator->status = OP_OPENED;
65,936,675✔
1346

1347
  taosRLockLatch(&pTaskInfo->lock);
65,936,675✔
1348
  code = doInitReader(pInfo, pTaskInfo, pAPI, &num, &pList);
65,936,675✔
1349
  taosRUnLockLatch(&pTaskInfo->lock);
65,936,675✔
1350
  QUERY_CHECK_CODE(code, lino, _return);
65,936,675!
1351

1352
  if (pInfo->pResBlock->info.capacity > pOperator->resultInfo.capacity) {
65,936,675!
1353
    pOperator->resultInfo.capacity = pInfo->pResBlock->info.capacity;
×
1354
  }
1355

1356
  pInfo->currentGroupId = -1;
65,936,675✔
1357
_return:
65,936,675✔
1358
  if (code) {
65,936,675!
1359
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1360
  }
1361
  taosArrayDestroy(pColArray);
65,936,675✔
1362
  taosArrayDestroy(pBlockColArray);
65,936,675✔
1363
  pAPI->metaReaderFn.clearReader(&superTable);
65,936,675✔
1364
  pAPI->metaReaderFn.clearReader(&orgTable);
65,936,675✔
1365
  return code;
65,936,675✔
1366
}
1367

1368
static int32_t startNextGroupScan(SOperatorInfo* pOperator, SSDataBlock** pResult) {
738,793,469✔
1369
  int32_t         code = TSDB_CODE_SUCCESS;
738,793,469✔
1370
  int32_t         lino = 0;
738,793,469✔
1371
  STableScanInfo* pInfo = pOperator->info;
738,793,469✔
1372
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
738,809,015✔
1373
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
738,800,575✔
1374
  int32_t         numOfTables = 0;
738,783,542✔
1375

1376
  QRY_PARAM_CHECK(pResult);
738,771,615!
1377

1378
  code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
738,786,848✔
1379
  QUERY_CHECK_CODE(code, lino, _end);
738,815,612!
1380

1381
  if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) {
738,815,612✔
1382
    setOperatorCompleted(pOperator);
671,729,002✔
1383
    if (pOperator->dynamicTask) {
671,752,159!
1384
      taosArrayClear(pInfo->base.pTableListInfo->pTableList);
17,914,314✔
1385
      taosHashClear(pInfo->base.pTableListInfo->map);
17,912,916✔
1386
    }
1387
    return code;
671,765,664✔
1388
  }
1389

1390
  // reset value for the next group data output
1391
  pOperator->status = OP_OPENED;
67,024,464✔
1392
  resetLimitInfoForNextGroup(&pInfo->base.limitInfo);
67,025,906✔
1393

1394
  int32_t        num = 0;
67,023,192✔
1395
  STableKeyInfo* pList = NULL;
67,023,192✔
1396
  code = initNextGroupScan(pInfo, &pList, &num);
67,023,192✔
1397
  QUERY_CHECK_CODE(code, lino, _end);
67,025,906!
1398

1399
  code = pAPI->tsdReader.tsdSetQueryTableList(pInfo->base.dataReader, pList, num);
67,025,906✔
1400
  QUERY_CHECK_CODE(code, lino, _end);
67,025,906!
1401

1402
  code = pAPI->tsdReader.tsdReaderResetStatus(pInfo->base.dataReader, &pInfo->base.cond);
67,025,906✔
1403
  QUERY_CHECK_CODE(code, lino, _end);
67,024,464!
1404
  pInfo->scanTimes = 0;
67,024,464✔
1405

1406
  code = doGroupedTableScan(pOperator, pResult);
67,024,464✔
1407
  QUERY_CHECK_CODE(code, lino, _end);
67,025,906!
1408

1409
  if (*pResult != NULL) {
67,025,906✔
1410
    if (pOperator->dynamicTask) {
50,181,498!
1411
      (*pResult)->info.id.groupId = (*pResult)->info.id.uid;
49,241,819✔
1412
    }
1413
    return code;
50,181,498✔
1414
  }
1415

1416
_end:
16,844,408✔
1417
  if (code != TSDB_CODE_SUCCESS) {
16,844,408!
1418
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1419
    pTaskInfo->code = code;
×
1420
  }
1421
  return code;
16,844,408✔
1422
}
1423

1424
static int32_t groupSeqTableScan(SOperatorInfo* pOperator, SSDataBlock** pResBlock) {
2,147,483,647✔
1425
  int32_t         code = TSDB_CODE_SUCCESS;
2,147,483,647✔
1426
  int32_t         lino = 0;
2,147,483,647✔
1427
  STableScanInfo* pInfo = pOperator->info;
2,147,483,647✔
1428
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
2,147,483,647✔
1429
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
2,147,483,647✔
1430
  int32_t         num = 0;
2,147,483,647✔
1431
  STableKeyInfo*  pList = NULL;
2,147,483,647✔
1432
  SSDataBlock*    pResult = NULL;
2,147,483,647✔
1433
  const char*     idStr = GET_TASKID(pTaskInfo);
2,147,483,647✔
1434

1435
  QRY_PARAM_CHECK(pResBlock);
2,147,483,647!
1436

1437
  if (pInfo->currentGroupId == -1) {
2,147,483,647✔
1438
    if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) {
679,375,949!
1439
      setOperatorCompleted(pOperator);
×
1440
      return code;
×
1441
    }
1442

1443
    taosRLockLatch(&pTaskInfo->lock);
679,422,139✔
1444
    code = doInitReader(pInfo, pTaskInfo, pAPI, &num, &pList);
679,482,084✔
1445
    taosRUnLockLatch(&pTaskInfo->lock);
679,287,908✔
1446
    QUERY_CHECK_CODE(code, lino, _end);
679,411,105✔
1447

1448
    if (pInfo->filesetDelimited) {
679,392,585!
1449
      pAPI->tsdReader.tsdSetFilesetDelimited(pInfo->base.dataReader);
1,202,478✔
1450
    }
1451

1452
    if (pInfo->pResBlock->info.capacity > pOperator->resultInfo.capacity) {
679,283,431!
1453
      pOperator->resultInfo.capacity = pInfo->pResBlock->info.capacity;
×
1454
    }
1455
  }
1456

1457
  code = doGroupedTableScan(pOperator, &pResult);
2,147,483,647✔
1458
  QUERY_CHECK_CODE(code, lino, _end);
2,147,483,647!
1459

1460
  if (pResult != NULL) {
2,147,483,647✔
1461
    if (pOperator->dynamicTask) {
2,147,483,647!
1462
      pResult->info.id.groupId = pResult->info.id.uid;
2,954,848✔
1463
    }
1464

1465
    *pResBlock = pResult;
2,147,483,647✔
1466
    return code;
2,147,483,647✔
1467
  }
1468

1469
  while (true) {
1470
    code = startNextGroupScan(pOperator, &pResult);
655,707,807✔
1471
    QUERY_CHECK_CODE(code, lino, _end);
656,186,466!
1472

1473
    if (pResult || pOperator->status == OP_EXEC_DONE) {
656,186,466✔
1474
      *pResBlock = pResult;
656,046,043✔
1475
      return code;
656,010,542✔
1476
    }
1477
  }
1478

1479
_end:
18,520✔
1480
  if (code != TSDB_CODE_SUCCESS) {
18,520!
1481
    qError("%s %s failed at line %d since %s", idStr, __func__, lino, tstrerror(code));
18,520!
1482
    pTaskInfo->code = code;
18,520✔
1483
  }
1484

1485
  return code;
18,520✔
1486
}
1487

1488
static bool isEmptyQueryTimeWindow(STimeWindow* pWindow) {
65,936,675✔
1489
  return (pWindow == NULL) || (pWindow->skey > pWindow->ekey);
65,936,675!
1490
}
1491

1492
int32_t doTableScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
2,147,483,647✔
1493
  int32_t         code = TSDB_CODE_SUCCESS;
2,147,483,647✔
1494
  int32_t         lino = 0;
2,147,483,647✔
1495
  STableScanInfo* pInfo = pOperator->info;
2,147,483,647✔
1496
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
2,147,483,647✔
1497
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
2,147,483,647✔
1498
  QRY_PARAM_CHECK(ppRes);
2,147,483,647!
1499
  qTrace("%s call", __FUNCTION__);
2,147,483,647!
1500
  if (pOperator->pOperatorGetParam) {
2,147,483,647✔
1501
    pOperator->dynamicTask = true;
67,170,265✔
1502
    if (isDynVtbScan(pOperator)) {
67,170,265✔
1503
      code = createVTableScanInfoFromParam(pOperator);
65,936,675✔
1504

1505
      freeOperatorParam(pOperator->pOperatorGetParam, OP_GET_PARAM);
65,936,675✔
1506
      pOperator->pOperatorGetParam = NULL;
65,936,675✔
1507
      QUERY_CHECK_CODE(code, lino, _end);
65,936,675!
1508

1509
      SSDataBlock* result = NULL;
65,936,675✔
1510
      if (isEmptyQueryTimeWindow(&pInfo->base.cond.twindows) && pInfo->base.cond.type == TIMEWINDOW_RANGE_CONTAINED) {
65,936,675!
1511
        (*ppRes) = result;
33,422✔
1512
        return code;
33,422✔
1513
      }
1514
      while (true) {
1515
        code = startNextGroupScan(pOperator, &result);
82,590,243✔
1516
        QUERY_CHECK_CODE(code, lino, _end);
82,590,243!
1517

1518
        if (result || pOperator->status == OP_EXEC_DONE) {
82,590,243✔
1519
          SSDataBlock* res = NULL;
65,903,253✔
1520
          if (result) {
65,903,253✔
1521
            code = createOneDataBlockWithTwoBlock(result, pInfo->pOrgBlock, &res);
49,216,263✔
1522
            QUERY_CHECK_CODE(code, lino, _end);
49,216,263!
1523
            pInfo->pResBlock = res;
49,216,263✔
1524
            blockDataDestroy(result);
49,216,263✔
1525
          }
1526
          (*ppRes) = res;
65,903,253✔
1527
          return code;
65,903,253✔
1528
        }
1529
      }
1530
    } else {
1531
      code = createTableListInfoFromParam(pOperator);
1,233,590✔
1532
      freeOperatorParam(pOperator->pOperatorGetParam, OP_GET_PARAM);
1,233,590✔
1533
      pOperator->pOperatorGetParam = NULL;
1,233,590✔
1534
      QUERY_CHECK_CODE(code, lino, _end);
1,233,590!
1535

1536
      if (pOperator->status == OP_EXEC_DONE) {
1,233,590✔
1537
        pInfo->currentGroupId = -1;
25,556✔
1538
        pOperator->status = OP_OPENED;
25,556✔
1539
        SSDataBlock* result = NULL;
25,556✔
1540

1541
        while (true) {
1542
          code = startNextGroupScan(pOperator, &result);
25,556✔
1543
          QUERY_CHECK_CODE(code, lino, _end);
25,556!
1544

1545
          if (result || pOperator->status == OP_EXEC_DONE) {
25,556!
1546
            (*ppRes) = result;
25,556✔
1547
            return code;
25,556✔
1548
          }
1549
        }
1550
      }
1551
    }
1552
  }
1553

1554
  // scan table one by one sequentially
1555
  if (pInfo->scanMode == TABLE_SCAN__TABLE_ORDER) {
2,147,483,647✔
1556
    int32_t       numOfTables = 0;
16,767,055✔
1557
    STableKeyInfo tInfo = {0};
16,767,055✔
1558
    pInfo->countState = TABLE_COUNT_STATE_END;
16,767,055✔
1559

1560
    while (1) {
15,637,552✔
1561
      SSDataBlock* result = NULL;
32,404,607✔
1562
      code = doGroupedTableScan(pOperator, &result);
32,408,935✔
1563
      QUERY_CHECK_CODE(code, lino, _end);
32,397,637!
1564

1565
      if (result || (pOperator->status == OP_EXEC_DONE) || isTaskKilled(pTaskInfo)) {
32,397,637!
1566
        (*ppRes) = result;
16,622,961✔
1567
        return code;
16,636,900✔
1568
      }
1569

1570
      // if no data, switch to next table and continue scan
1571
      pInfo->currentTable++;
15,776,419✔
1572

1573
      taosRLockLatch(&pTaskInfo->lock);
15,772,079✔
1574
      numOfTables = 0;
15,781,633✔
1575
      code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
15,781,633✔
1576
      if (code != TSDB_CODE_SUCCESS) {
15,775,535!
1577
        taosRUnLockLatch(&pTaskInfo->lock);
×
1578
        TSDB_CHECK_CODE(code, lino, _end);
×
1579
      }
1580

1581
      if (pInfo->currentTable >= numOfTables) {
15,775,535✔
1582
        qDebug("all table checked in table list, total:%d, return NULL, %s", numOfTables, GET_TASKID(pTaskInfo));
129,298!
1583
        taosRUnLockLatch(&pTaskInfo->lock);
129,298✔
1584
        (*ppRes) = NULL;
129,298✔
1585
        return code;
129,298✔
1586
      }
1587

1588
      STableKeyInfo* tmp = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->currentTable);
15,629,757✔
1589
      if (!tmp) {
15,641,882!
1590
        taosRUnLockLatch(&pTaskInfo->lock);
×
1591
        (*ppRes) = NULL;
×
1592
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
×
1593
      }
1594

1595
      tInfo = *tmp;
15,641,882✔
1596
      taosRUnLockLatch(&pTaskInfo->lock);
15,640,164✔
1597

1598
      code = pAPI->tsdReader.tsdSetQueryTableList(pInfo->base.dataReader, &tInfo, 1);
15,652,321✔
1599
      QUERY_CHECK_CODE(code, lino, _end);
15,638,437!
1600
      qDebug("set uid:%" PRIu64 " into scanner, total tables:%d, index:%d/%d %s", tInfo.uid, numOfTables,
15,638,437✔
1601
             pInfo->currentTable, numOfTables, GET_TASKID(pTaskInfo));
1602

1603
      code = pAPI->tsdReader.tsdReaderResetStatus(pInfo->base.dataReader, &pInfo->base.cond);
15,661,889✔
1604
      QUERY_CHECK_CODE(code, lino, _end);
15,639,294!
1605
      pInfo->scanTimes = 0;
15,639,294✔
1606
    }
1607
  } else {  // scan table group by group sequentially
1608
    code = groupSeqTableScan(pOperator, ppRes);
2,147,483,647✔
1609
    QUERY_CHECK_CODE(code, lino, _end);
2,147,483,647✔
1610
  }
1611

1612
_end:
2,147,483,647✔
1613
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
1614
    qError("%s %s failed at line %d since %s", GET_TASKID(pTaskInfo), __func__, lino, tstrerror(code));
18,520!
1615
    pTaskInfo->code = code;
18,520✔
1616
    T_LONG_JMP(pTaskInfo->env, code);
18,520!
1617
  }
1618

1619
  return code;
2,147,483,647✔
1620
}
1621

1622
static int32_t getTableScannerExecInfo(struct SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
11,362,372✔
1623
  SFileBlockLoadRecorder* pRecorder = taosMemoryCalloc(1, sizeof(SFileBlockLoadRecorder));
11,362,372!
1624
  if (!pRecorder) {
11,362,170!
1625
    return terrno;
×
1626
  }
1627
  STableScanInfo* pTableScanInfo = pOptr->info;
11,362,170✔
1628
  *pRecorder = pTableScanInfo->base.readRecorder;
11,362,372✔
1629
  *pOptrExplain = pRecorder;
11,362,372✔
1630
  *len = sizeof(SFileBlockLoadRecorder);
11,362,170✔
1631
  return 0;
11,360,777✔
1632
}
1633

1634
static void destroyTableScanBase(STableScanBase* pBase, TsdReader* pAPI) {
854,078,155✔
1635
  cleanupQueryTableDataCond(&pBase->cond);
854,078,155✔
1636
  cleanupQueryTableDataCond(&pBase->orgCond);
854,063,454✔
1637

1638
  if (pAPI->tsdReaderClose) {
854,093,254!
1639
    pAPI->tsdReaderClose(pBase->dataReader);
854,104,786✔
1640
  }
1641
  pBase->dataReader = NULL;
853,955,222✔
1642

1643
  if (pBase->matchInfo.pList != NULL) {
853,968,653✔
1644
    taosArrayDestroy(pBase->matchInfo.pList);
854,002,441✔
1645
  }
1646

1647
  tableListDestroy(pBase->pTableListInfo);
853,937,226✔
1648
  taosLRUCacheCleanup(pBase->metaCache.pTableMetaEntryCache);
854,074,319✔
1649
  cleanupExprSupp(&pBase->pseudoSup);
854,127,572✔
1650
}
854,119,227✔
1651

1652
static void destroyTableScanOperatorInfo(void* param) {
718,811,091✔
1653
  STableScanInfo* pTableScanInfo = (STableScanInfo*)param;
718,811,091✔
1654
  blockDataDestroy(pTableScanInfo->pResBlock);
718,811,091✔
1655
  blockDataDestroy(pTableScanInfo->pOrgBlock);
718,781,747✔
1656
  taosHashCleanup(pTableScanInfo->pIgnoreTables);
718,785,914✔
1657
  destroyTableScanBase(&pTableScanInfo->base, &pTableScanInfo->base.readerAPI);
718,767,246✔
1658
  taosMemoryFreeClear(param);
718,802,523!
1659
}
718,793,176✔
1660

1661
static void resetClolumnReserve(SSDataBlock* pBlock, int32_t dataRequireFlag) {
718,546,606✔
1662
  if (pBlock && dataRequireFlag == FUNC_DATA_REQUIRED_NOT_LOAD) {
718,546,606!
1663
    int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
41,874,157✔
1664
    for (int32_t i = 0; i < numOfCols; ++i) {
104,625,540✔
1665
      SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
62,784,316✔
1666
      if (pCol) {
62,766,553!
1667
        pCol->info.noData = true;
62,766,553✔
1668
      }
1669
    }
1670
  }
1671
}
718,513,673✔
1672

1673
static int32_t resetTableScanOperatorState(SOperatorInfo* pOper) {
1,127,380✔
1674
  int32_t         code = TSDB_CODE_SUCCESS;
1,127,380✔
1675
  STableScanInfo*   pInfo = pOper->info;
1,127,380✔
1676
  pOper->status = OP_NOT_OPENED;
1,127,380✔
1677

1678
  pInfo->scanTimes = 0;
1,127,380✔
1679
  pInfo->currentGroupId = -1;
1,127,380✔
1680
  pInfo->tableEndIndex = -1;
1,127,380✔
1681
  pInfo->tableStartIndex = 0;
1,127,380✔
1682
  pInfo->currentTable = 0;
1,127,380✔
1683
  pInfo->scanMode = 0;
1,127,380✔
1684
  pInfo->countState = 0;
1,127,380✔
1685
  pInfo->base.scanFlag = (pInfo->scanInfo.numOfAsc > 1) ? PRE_SCAN : MAIN_SCAN;
1,127,380!
1686

1687
  tableListDestroy(pInfo->base.pTableListInfo);
1,127,380✔
1688
  pInfo->base.pTableListInfo = tableListCreate();
1,127,380✔
1689
  if (!pInfo->base.pTableListInfo) {
1,127,380!
NEW
1690
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
NEW
1691
    return terrno;
×
1692
  }
1693
  SExecTaskInfo*         pTaskInfo = pOper->pTaskInfo;
1,127,380✔
1694
  
1695
  STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pTaskInfo->pSubplan->pNode;
1,127,380✔
1696
  if (!pTableScanNode->scan.node.dynamicOp) {
1,127,380✔
1697
    code = createScanTableListInfo(&pTableScanNode->scan, pTableScanNode->pGroupTags, pTableScanNode->groupSort,
398,407!
1698
                                    &pInfo->base.readHandle, pInfo->base.pTableListInfo, 
1699
                                    pTaskInfo->pSubplan->pTagCond, pTaskInfo->pSubplan->pTagIndexCond, pTaskInfo, NULL);
398,407✔
1700
    if (code) {
199,748!
NEW
1701
      qError("%s failed to createScanTableListInfo, code:%s", __func__, tstrerror(code));
×
NEW
1702
      return code;
×
1703
    }
1704
  }
1705

1706
  initLimitInfo(pTableScanNode->scan.node.pLimit, pTableScanNode->scan.node.pSlimit, &pInfo->base.limitInfo);
1,127,380✔
1707
  cleanupQueryTableDataCond(&pInfo->base.cond);
1,127,380✔
1708
  code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, &pInfo->base.readHandle, true);
1,127,380✔
1709
  if (code) {
1,127,380!
NEW
1710
    qError("%s failed to initQueryTableDataCond, code:%s", __func__, tstrerror(code));
×
NEW
1711
    return code;
×
1712
  }
1713
  pInfo->base.cond.startVersion = 0;
1,127,380✔
1714
  pInfo->base.cond.endVersion = pInfo->base.readHandle.version;
1,127,380✔
1715
  if (pTableScanNode->scan.node.dynamicOp && pTableScanNode->scan.virtualStableScan) {
1,127,380!
1716
    cleanupQueryTableDataCond(&pInfo->base.orgCond);
927,632✔
1717
    memcpy(&pInfo->base.orgCond, &pInfo->base.cond, sizeof(SQueryTableDataCond));
927,632!
1718
    memset(&pInfo->base.cond, 0, sizeof(SQueryTableDataCond));
927,632!
1719
    if (pInfo->base.readerAPI.tsdReaderClose) {
927,632!
1720
      pInfo->base.readerAPI.tsdReaderClose(pInfo->base.dataReader);
927,632✔
1721
    }
1722
    pInfo->base.dataReader = NULL;
927,632✔
1723
  } else {
1724
    // reuse tsdb reader
1725
    if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) {
199,748!
NEW
1726
      setOperatorCompleted(pOper);
×
NEW
1727
      return code;
×
1728
    }
1729

1730
    taosRLockLatch(&pTaskInfo->lock);
199,748✔
1731
    do {
1732
      int32_t        num = 0;
199,748✔
1733
      STableKeyInfo* pList = NULL;
199,748✔
1734
      code = initNextGroupScan(pInfo, &pList, &num);
199,748✔
1735
      if (code) {
199,748!
NEW
1736
        qError("%s failed to initNextGroupScan, code:%s", __func__, tstrerror(code));
×
NEW
1737
        break;
×
1738
      }
1739
      code = pInfo->base.readerAPI.tsdSetQueryTableList(pInfo->base.dataReader, pList, num);
199,748✔
1740
      if (code) {
199,748!
NEW
1741
        qError("%s failed to tsdSetQueryTableList, code:%s", __func__, tstrerror(code));
×
NEW
1742
        break;
×
1743
      }
1744
      code = pInfo->base.readerAPI.tsdReaderResetStatus(pInfo->base.dataReader, &pInfo->base.cond);
199,748✔
1745
      if (code) {
199,748✔
1746
        qError("%s failed to tsdReaderResetStatus, code:%s", __func__, tstrerror(code));
5,392!
1747
        break;
5,392✔
1748
      }
1749
      pInfo->base.readerAPI.tsdReaderResetVer(pInfo->base.dataReader, &pInfo->base.cond);
194,356✔
1750
      code = pInfo->base.readerAPI.tsdReaderResetExTimeWindow(pInfo->base.dataReader, &pInfo->base.cond);
194,356✔
1751
      if (code) {
194,252!
NEW
1752
        qError("%s failed to tsdReaderResetStatus, code:%s", __func__, tstrerror(code));
×
NEW
1753
        break;
×
1754
      }
1755
        
1756
    } while (0);
1757
    taosRUnLockLatch(&pTaskInfo->lock);
199,748✔
1758
    if (code) return code;
199,748✔
1759

1760
    if (pInfo->filesetDelimited) {
194,356!
NEW
1761
      pInfo->base.readerAPI.tsdSetFilesetDelimited(pInfo->base.dataReader);
×
1762
    }
1763

1764
    if (pInfo->pResBlock->info.capacity > pOper->resultInfo.capacity) {
194,356!
NEW
1765
      pOper->resultInfo.capacity = pInfo->pResBlock->info.capacity;
×
1766
    }
1767
  }
1768

1769
  pOper->resultInfo.totalRows = 0;
1,121,988✔
1770
  blockDataEmpty(pInfo->pResBlock);
1,121,988✔
1771
  blockDataEmpty(pInfo->pOrgBlock);
1,121,988✔
1772
  taosHashClear(pInfo->pIgnoreTables);
1,121,988✔
1773
  return code;
1,121,988✔
1774
}
1775

1776
int32_t createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle,
718,767,278✔
1777
                                    STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo,
1778
                                    SOperatorInfo** pOptrInfo) {
1779
  QRY_PARAM_CHECK(pOptrInfo);
718,767,278!
1780

1781
  int32_t         code = TSDB_CODE_SUCCESS;
718,788,959✔
1782
  int32_t         lino = 0;
718,788,959✔
1783
  STableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableScanInfo));
718,788,959✔
1784
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
718,722,654✔
1785
  if (pInfo == NULL || pOperator == NULL) {
718,704,972!
1786
    code = terrno;
2,793✔
1787
    goto _error;
×
1788
  }
1789
  pOperator->pPhyNode = pTableScanNode;
718,702,179✔
1790
  SScanPhysiNode*     pScanNode = &pTableScanNode->scan;
718,714,481✔
1791
  SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc;
718,722,061✔
1792

1793
  int32_t numOfCols = 0;
718,733,755✔
1794
  code =
1795
      extractColMatchInfo(pScanNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID, &pInfo->base.matchInfo);
718,748,230✔
1796
  QUERY_CHECK_CODE(code, lino, _error);
718,694,768!
1797

1798
  initLimitInfo(pScanNode->node.pLimit, pScanNode->node.pSlimit, &pInfo->base.limitInfo);
718,694,768✔
1799
  code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, readHandle, true);
718,587,773✔
1800
  QUERY_CHECK_CODE(code, lino, _error);
718,559,688!
1801

1802
  if (pScanNode->pScanPseudoCols != NULL) {
718,559,688✔
1803
    SExprSupp* pSup = &pInfo->base.pseudoSup;
268,106,502✔
1804
    pSup->pExprInfo = NULL;
268,127,086✔
1805
    code = createExprInfo(pScanNode->pScanPseudoCols, NULL, &pSup->pExprInfo, &pSup->numOfExprs);
268,117,031✔
1806
    QUERY_CHECK_CODE(code, lino, _error);
268,068,227!
1807

1808
    pSup->pCtx = createSqlFunctionCtx(pSup->pExprInfo, pSup->numOfExprs, &pSup->rowEntryInfoOffset,
268,068,227✔
1809
                                      &pTaskInfo->storageAPI.functionStore);
1810
    QUERY_CHECK_NULL(pSup->pCtx, code, lino, _error, terrno);
267,972,705!
1811
  }
1812

1813
  pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]};
718,582,805✔
1814
  pInfo->base.scanFlag = (pInfo->scanInfo.numOfAsc > 1) ? PRE_SCAN : MAIN_SCAN;
718,300,103✔
1815

1816
  pInfo->base.pdInfo.interval = extractIntervalInfo(pTableScanNode);
718,516,549✔
1817
  pInfo->base.readHandle = *readHandle;
718,043,041✔
1818
  pInfo->base.dataBlockLoadFlag = pTableScanNode->dataRequired;
718,150,647✔
1819

1820
  pInfo->sample.sampleRatio = pTableScanNode->ratio;
718,644,066✔
1821
  pInfo->sample.seed = taosGetTimestampSec();
718,374,240✔
1822

1823
  pInfo->base.readerAPI = pTaskInfo->storageAPI.tsdReader;
718,481,598✔
1824
  initResultSizeInfo(&pOperator->resultInfo, 4096);
718,173,740✔
1825
  pInfo->pResBlock = createDataBlockFromDescNode(pDescNode);
718,396,341✔
1826
  resetClolumnReserve(pInfo->pResBlock, pInfo->base.dataBlockLoadFlag);
718,660,821✔
1827
  QUERY_CHECK_NULL(pInfo->pResBlock, code, lino, _error, terrno);
718,532,603!
1828

1829
  code = prepareDataBlockBuf(pInfo->pResBlock, &pInfo->base.matchInfo);
718,137,414✔
1830
  QUERY_CHECK_CODE(code, lino, _error);
718,643,277!
1831

1832
  pInfo->virtualStableScan = pScanNode->virtualStableScan;
718,643,277!
1833
  if (pScanNode->node.dynamicOp && pScanNode->virtualStableScan) {
718,519,479!
1834
    TSWAP(pInfo->pOrgBlock, pInfo->pResBlock);
8,239,493✔
1835
    pInfo->pResBlock = NULL;
8,236,515✔
1836
    memcpy(&pInfo->base.orgCond, &pInfo->base.cond, sizeof(SQueryTableDataCond));
8,235,424!
1837
    memset(&pInfo->base.cond, 0, sizeof(SQueryTableDataCond));
8,239,493!
1838
  }
1839

1840
  code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0,
718,582,993✔
1841
                            pTaskInfo->pStreamRuntimeInfo);
718,390,964✔
1842
  QUERY_CHECK_CODE(code, lino, _error);
718,268,099✔
1843

1844
  pInfo->currentGroupId = -1;
718,246,631✔
1845

1846
  pInfo->tableEndIndex = -1;
718,458,977✔
1847
  pInfo->assignBlockUid = pTableScanNode->assignBlockUid;
718,409,653!
1848
  pInfo->hasGroupByTag = pTableScanNode->pGroupTags ? true : false;
718,233,503✔
1849

1850
  setOperatorInfo(pOperator, "TableScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, false, OP_NOT_OPENED, pInfo,
718,550,945✔
1851
                  pTaskInfo);
1852
  pOperator->exprSupp.numOfExprs = numOfCols;
717,978,476✔
1853

1854
  pInfo->needCountEmptyTable = tsCountAlwaysReturnValue && pTableScanNode->needCountEmptyTable;
718,498,286!
1855
  pInfo->ignoreTag = false;
718,572,807✔
1856

1857
  pInfo->base.pTableListInfo = pTableListInfo;
718,279,751✔
1858
  pInfo->base.metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024 * 128, -1, .5);
718,099,118✔
1859
  if (pInfo->base.metaCache.pTableMetaEntryCache == NULL) {
718,715,460!
1860
    code = terrno;
×
1861
    QUERY_CHECK_CODE(code, lino, _error);
×
1862
  }
1863

1864
  pInfo->filesetDelimited = pTableScanNode->filesetDelimited;
718,681,264!
1865

1866
  taosLRUCacheSetStrictCapacity(pInfo->base.metaCache.pTableMetaEntryCache, false);
718,598,398✔
1867
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableScanNext, NULL, destroyTableScanOperatorInfo,
718,660,996✔
1868
                                         optrDefaultBufFn, getTableScannerExecInfo, optrDefaultGetNextExtFn, NULL);
1869
  setOperatorResetStateFn(pOperator, resetTableScanOperatorState);                                    
718,522,755✔
1870
  // for non-blocking operator, the open cost is always 0
1871
  pOperator->cost.openCost = 0;
718,320,257✔
1872
  *pOptrInfo = pOperator;
718,345,157✔
1873
  return TSDB_CODE_SUCCESS;
718,173,169✔
1874

1875
_error:
21,468✔
1876
  if (pInfo != NULL) {
21,468!
1877
    pInfo->base.pTableListInfo = NULL;  // this attribute will be destroy outside of this function
21,468✔
1878
    destroyTableScanOperatorInfo(pInfo);
21,468✔
1879
  }
1880

1881
  if (pOperator != NULL) {
21,468!
1882
    pOperator->info = NULL;
21,468✔
1883
    destroyOperator(pOperator);
21,468✔
1884
  }
1885
  pTaskInfo->code = code;
21,468✔
1886
  return code;
21,468✔
1887
}
1888

1889
int32_t createTableSeqScanOperatorInfo(void* pReadHandle, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
×
1890
  QRY_PARAM_CHECK(pOptrInfo);
×
1891

1892
  int32_t         code = 0;
×
1893
  STableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableScanInfo));
×
1894
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
×
1895
  if (pInfo == NULL || pOperator == NULL) {
×
1896
    code = terrno;
×
1897
    goto _end;
×
1898
  }
1899

1900
  pInfo->base.dataReader = pReadHandle;
×
1901
  //  pInfo->prevGroupId       = -1;
1902

1903
  setOperatorInfo(pOperator, "TableSeqScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN, false, OP_NOT_OPENED,
×
1904
                  pInfo, pTaskInfo);
1905
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableScanImplNext, NULL, NULL, optrDefaultBufFn, NULL,
×
1906
                                         optrDefaultGetNextExtFn, NULL);
1907
  *pOptrInfo = pOperator;
×
1908
  return code;
×
1909

1910
_end:
×
1911
  if (pInfo != NULL) {
×
1912
    taosMemoryFree(pInfo);
×
1913
  }
1914

1915
  if (pOperator != NULL) {
×
1916
    taosMemoryFree(pOperator);
×
1917
  }
1918

1919
  pTaskInfo->code = code;
×
1920
  return code;
×
1921
}
1922

1923
static int32_t doBlockDataPrimaryKeyFilter(SSDataBlock* pBlock, STqOffsetVal* offset) {
×
1924
  int32_t code = TSDB_CODE_SUCCESS;
×
1925
  int32_t lino = 0;
×
1926
  if (pBlock->info.window.skey != offset->ts || offset->primaryKey.type == 0) {
×
1927
    return code;
×
1928
  }
1929
  bool* p = taosMemoryCalloc(pBlock->info.rows, sizeof(bool));
×
1930
  QUERY_CHECK_NULL(p, code, lino, _end, terrno);
×
1931
  bool hasUnqualified = false;
×
1932

1933
  SColumnInfoData* pColTs = taosArrayGet(pBlock->pDataBlock, 0);
×
1934
  SColumnInfoData* pColPk = taosArrayGet(pBlock->pDataBlock, 1);
×
1935

1936
  qDebug("doBlockDataWindowFilter primary key, ts:%" PRId64 " %" PRId64, offset->ts,
×
1937
         VALUE_GET_TRIVIAL_DATUM(&offset->primaryKey));
1938
  QUERY_CHECK_CONDITION((pColPk->info.type == offset->primaryKey.type), code, lino, _end,
×
1939
                        TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
1940

1941
  __compar_fn_t func = getComparFunc(pColPk->info.type, 0);
×
1942
  QUERY_CHECK_NULL(func, code, lino, _end, terrno);
×
1943
  for (int32_t i = 0; i < pBlock->info.rows; ++i) {
×
1944
    int64_t* ts = (int64_t*)colDataGetData(pColTs, i);
×
1945
    void*    data = colDataGetData(pColPk, i);
×
1946
    if (IS_VAR_DATA_TYPE(pColPk->info.type)) {
×
1947
      if (IS_STR_DATA_BLOB(pColPk->info.type)) {
×
1948
        QUERY_CHECK_CODE(code = TSDB_CODE_BLOB_NOT_SUPPORT_PRIMARY_KEY, lino, _end);
×
1949
      }
1950
      void* tmq = taosMemoryMalloc(offset->primaryKey.nData + VARSTR_HEADER_SIZE);
×
1951
      QUERY_CHECK_NULL(tmq, code, lino, _end, terrno);
×
1952
      memcpy(varDataVal(tmq), offset->primaryKey.pData, offset->primaryKey.nData);
×
1953
      varDataLen(tmq) = offset->primaryKey.nData;
×
1954
      p[i] = (*ts > offset->ts) || (func(data, tmq) > 0);
×
1955
      taosMemoryFree(tmq);
×
1956
    } else {
1957
      p[i] = (*ts > offset->ts) || (func(data, VALUE_GET_DATUM(&offset->primaryKey, pColPk->info.type)) > 0);
×
1958
    }
1959

1960
    if (!p[i]) {
×
1961
      hasUnqualified = true;
×
1962
    }
1963
  }
1964

1965
  if (hasUnqualified) {
×
1966
    code = trimDataBlock(pBlock, pBlock->info.rows, p);
×
1967
    QUERY_CHECK_CODE(code, lino, _end);
×
1968
  }
1969

1970
_end:
×
1971
  taosMemoryFree(p);
×
1972
  if (code != TSDB_CODE_SUCCESS) {
×
1973
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1974
  }
1975
  return code;
×
1976
}
1977

1978
int32_t colIdComparFn(const void* param1, const void* param2) {
2,147,483,647✔
1979
  int32_t p1 = *(int32_t*)param1;
2,147,483,647✔
1980
  int32_t p2 = *(int32_t*)param2;
2,147,483,647✔
1981

1982
  if (p1 == p2) {
2,147,483,647!
1983
    return 0;
×
1984
  } else {
1985
    return (p1 < p2) ? -1 : 1;
2,147,483,647✔
1986
  }
1987
}
1988

1989
static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock) {
204,647,645✔
1990
  int32_t         code = TSDB_CODE_SUCCESS;
204,647,645✔
1991
  int32_t         lino = 0;
204,647,645✔
1992
  SDataBlockInfo* pBlockInfo = &pInfo->pRes->info;
204,647,645✔
1993
  SOperatorInfo*  pOperator = pInfo->pStreamScanOp;
204,647,645✔
1994
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
204,606,785✔
1995
  const char*     id = GET_TASKID(pTaskInfo);
204,646,737✔
1996
  bool            isVtableSourceScan = (pTaskInfo->pSubplan->pVTables != NULL);
204,647,645✔
1997

1998
  code = blockDataEnsureCapacity(pInfo->pRes, pBlock->info.rows);
204,648,553✔
1999
  QUERY_CHECK_CODE(code, lino, _end);
204,646,737!
2000

2001
  pBlockInfo->rows = pBlock->info.rows;
204,646,737✔
2002
  pBlockInfo->id.uid = pBlock->info.id.uid;
204,622,637✔
2003
  pBlockInfo->type = STREAM_NORMAL;
204,644,013✔
2004
  pBlockInfo->version = pBlock->info.version;
204,640,381✔
2005

2006
  STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info;
204,641,289✔
2007
  if (!isVtableSourceScan) {
204,644,013!
2008
    pBlockInfo->id.groupId = tableListGetTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid);
204,644,013✔
2009
  } else {
2010
    // use original table uid as groupId for vtable
2011
    pBlockInfo->id.groupId = pBlock->info.id.groupId;
×
2012
  }
2013

2014
  SArray* pColList = taosArrayInit(4, sizeof(int32_t));
204,644,921✔
2015
  QUERY_CHECK_NULL(pColList, code, lino, _end, terrno);
204,620,441!
2016

2017
  // todo extract method
2018
  for (int32_t i = 0; i < taosArrayGetSize(pInfo->matchInfo.pList); ++i) {
1,150,672,400✔
2019
    SColMatchItem* pColMatchInfo = taosArrayGet(pInfo->matchInfo.pList, i);
946,027,701✔
2020
    if (!pColMatchInfo->needOutput) {
945,948,854!
2021
      continue;
1,688✔
2022
    }
2023

2024
    bool colExists = false;
945,954,061✔
2025
    for (int32_t j = 0; j < blockDataGetNumOfCols(pBlock); ++j) {
2,147,483,647✔
2026
      SColumnInfoData* pResCol = NULL;
2,147,483,647✔
2027
      code = bdGetColumnInfoData(pBlock, j, &pResCol);
2,147,483,647✔
2028
      QUERY_CHECK_CODE(code, lino, _end);
2,147,483,647!
2029

2030
      if (pResCol->info.colId == pColMatchInfo->colId) {
2,147,483,647✔
2031
        SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->dstSlotId);
946,046,985✔
2032
        code = colDataAssign(pDst, pResCol, pBlock->info.rows, &pInfo->pRes->info);
946,043,670✔
2033
        QUERY_CHECK_CODE(code, lino, _end);
945,752,268!
2034

2035
        colExists = true;
945,752,268✔
2036
        void* tmp = taosArrayPush(pColList, &pColMatchInfo->dstSlotId);
945,752,268✔
2037
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
946,032,298!
2038
        break;
946,032,298✔
2039
      }
2040
    }
2041

2042
    // the required column does not exists in submit block, let's set it to be all null value
2043
    if (!colExists) {
946,026,663✔
2044
      SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->dstSlotId);
3,372✔
2045
      colDataSetNNULL(pDst, 0, pBlockInfo->rows);
3,372!
2046
      void* tmp = taosArrayPush(pColList, &pColMatchInfo->dstSlotId);
3,372✔
2047
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
3,372!
2048
    }
2049
  }
2050

2051
  // currently only the tbname pseudo column
2052
  if (pInfo->numOfPseudoExpr > 0 && !isVtableSourceScan) {
204,647,649!
2053
    code = addTagPseudoColumnData(&pInfo->readHandle, pInfo->pPseudoExpr, pInfo->numOfPseudoExpr, pInfo->pRes,
211,067,706✔
2054
                                  pBlockInfo->rows, pTaskInfo, &pTableScanInfo->base.metaCache);
105,533,465✔
2055
    // ignore the table not exists error, since this table may have been dropped during the scan procedure.
2056
    if (code) {
105,528,994!
2057
      QUERY_CHECK_CODE(code, lino, _end);
×
2058
    }
2059

2060
    // reset the error code.
2061
    terrno = 0;
105,528,994✔
2062

2063
    for (int32_t i = 0; i < pInfo->numOfPseudoExpr; ++i) {
536,221,711✔
2064
      void* tmp = taosArrayPush(pColList, &pInfo->pPseudoExpr[i].base.resSchema.slotId);
430,679,936✔
2065
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
430,694,533!
2066
    }
2067
  }
2068

2069
  taosArraySort(pColList, colIdComparFn);
204,595,965✔
2070

2071
  int32_t i = 0, j = 0;
204,636,749✔
2072
  while (i < taosArrayGetSize(pColList)) {
1,581,006,677✔
2073
    int32_t slot1 = *(int32_t*)taosArrayGet(pColList, i);
1,376,390,932✔
2074
    if (slot1 > j) {
1,376,369,928!
2075
      SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, j);
×
2076
      colDataSetNNULL(pDst, 0, pBlockInfo->rows);
×
2077
      j += 1;
×
2078
    } else {
2079
      i += 1;
1,376,369,928✔
2080
      j += 1;
1,376,369,928✔
2081
    }
2082
  }
2083

2084
  while (j < taosArrayGetSize(pInfo->pRes->pDataBlock)) {
204,643,889✔
2085
    SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, j);
1,688✔
2086
    colDataSetNNULL(pDst, 0, pBlockInfo->rows);
1,688!
2087
    j += 1;
1,688✔
2088
  }
2089

2090
  taosArrayDestroy(pColList);
204,642,204✔
2091

2092
  code = doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL, NULL);
204,641,372✔
2093
  QUERY_CHECK_CODE(code, lino, _end);
204,643,163!
2094

2095
  code = blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex);
204,643,163✔
2096
  QUERY_CHECK_CODE(code, lino, _end);
204,638,159!
2097
  if (pInfo->pRes->info.rows == 0) {
204,638,159✔
2098
    return 0;
2,078,350✔
2099
  }
2100

2101
_end:
202,562,522✔
2102
  if (code != TSDB_CODE_SUCCESS) {
201,804,371!
2103
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2104
  }
2105
  return code;
202,543,973✔
2106
}
2107

2108
static int32_t processPrimaryKey(SSDataBlock* pBlock, bool hasPrimaryKey, STqOffsetVal* offset) {
18,725,627✔
2109
  int32_t code = TSDB_CODE_SUCCESS;
18,725,627✔
2110
  int32_t lino = 0;
18,725,627✔
2111
  SValue  val = {0};
18,725,627✔
2112
  if (hasPrimaryKey) {
18,729,954!
2113
    code = doBlockDataPrimaryKeyFilter(pBlock, offset);
×
2114
    if (code != TSDB_CODE_SUCCESS) {
×
2115
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
2116
      return code;
×
2117
    }
2118
    SColumnInfoData* pColPk = taosArrayGet(pBlock->pDataBlock, 1);
×
2119

2120
    if (pBlock->info.rows < 1) {
×
2121
      return code;
×
2122
    }
2123
    void* tmp = colDataGetData(pColPk, pBlock->info.rows - 1);
×
2124
    val.type = pColPk->info.type;
×
2125
    if (IS_VAR_DATA_TYPE(pColPk->info.type)) {
×
2126
      if (IS_STR_DATA_BLOB(pColPk->info.type)) {
×
2127
        return TSDB_CODE_BLOB_NOT_SUPPORT_PRIMARY_KEY;
×
2128
      }
2129
      val.pData = taosMemoryMalloc(varDataLen(tmp));
×
2130
      QUERY_CHECK_NULL(val.pData, code, lino, _end, terrno);
×
2131
      val.nData = varDataLen(tmp);
×
2132
      memcpy(val.pData, varDataVal(tmp), varDataLen(tmp));
×
2133
    } else {
2134
      valueSetDatum(&val, pColPk->info.type, tmp, pColPk->info.bytes);
×
2135
    }
2136
  }
2137
  tqOffsetResetToData(offset, pBlock->info.id.uid, pBlock->info.window.ekey, val);
18,729,954!
2138

2139
_end:
18,725,698✔
2140
  if (code != TSDB_CODE_SUCCESS) {
18,726,569!
2141
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2142
  }
2143
  return code;
18,726,555✔
2144
}
2145

2146
static int32_t doQueueScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
261,117,900✔
2147
  int32_t        code = TSDB_CODE_SUCCESS;
261,117,900✔
2148
  int32_t        lino = 0;
261,117,900✔
2149
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
261,117,900✔
2150
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
261,127,896✔
2151

2152
  SStreamScanInfo* pInfo = pOperator->info;
261,130,556✔
2153
  const char*      id = GET_TASKID(pTaskInfo);
261,119,890✔
2154

2155
  qDebug("start to exec queue scan, %s", id);
261,122,473✔
2156

2157
  if (isTaskKilled(pTaskInfo)) {
261,133,136!
2158
    (*ppRes) = NULL;
×
2159
    return pTaskInfo->code;
×
2160
  }
2161

2162
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) {
261,131,391✔
2163
    while (1) {
×
2164
      SSDataBlock* pResult = NULL;
16,767,055✔
2165
      code = doTableScanNext(pInfo->pTableScanOp, &pResult);
16,767,055✔
2166
      QUERY_CHECK_CODE(code, lino, _end);
16,765,327!
2167

2168
      if (pResult && pResult->info.rows > 0) {
16,765,327!
2169
        bool hasPrimaryKey = pAPI->tqReaderFn.tqGetTablePrimaryKey(pInfo->tqReader);
16,635,157✔
2170
        code = processPrimaryKey(pResult, hasPrimaryKey, &pTaskInfo->streamInfo.currentOffset);
16,636,014✔
2171
        QUERY_CHECK_CODE(code, lino, _end);
16,629,960!
2172
        qDebug("tmqsnap doQueueScan get data utid:%" PRId64, pResult->info.id.uid);
16,629,960!
2173
        if (pResult->info.rows > 0) {
16,637,757!
2174
          (*ppRes) = pResult;
16,637,757✔
2175
          return code;
16,637,757✔
2176
        }
2177
      } else {
2178
        break;
2179
      }
2180
    }
2181

2182
    STableScanInfo* pTSInfo = pInfo->pTableScanOp->info;
129,298✔
2183
    pAPI->tsdReader.tsdReaderClose(pTSInfo->base.dataReader);
129,298✔
2184

2185
    pTSInfo->base.dataReader = NULL;
129,298✔
2186
    int64_t validVer = pTaskInfo->streamInfo.snapshotVer + 1;
129,298✔
2187
    qDebug("queue scan tsdb over, switch to wal ver %" PRId64, validVer);
129,298!
2188
    if (pAPI->tqReaderFn.tqReaderSeek(pInfo->tqReader, validVer, pTaskInfo->id.str) < 0) {
129,298✔
2189
      (*ppRes) = NULL;
39,830✔
2190
      return code;
39,830✔
2191
    }
2192

2193
    tqOffsetResetToLog(&pTaskInfo->streamInfo.currentOffset, validVer);
89,468✔
2194
  }
2195

2196
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__LOG) {
244,452,896!
2197
    while (1) {
2,078,350✔
2198
      bool hasResult =
2199
          pAPI->tqReaderFn.tqReaderNextBlockInWal(pInfo->tqReader, id, pTaskInfo->streamInfo.sourceExcluded);
246,530,338✔
2200

2201
      SSDataBlock*       pRes = pAPI->tqReaderFn.tqGetResultBlock(pInfo->tqReader);
246,507,741✔
2202
      struct SWalReader* pWalReader = pAPI->tqReaderFn.tqReaderGetWalReader(pInfo->tqReader);
246,521,309✔
2203

2204
      // curVersion move to next
2205
      tqOffsetResetToLog(&pTaskInfo->streamInfo.currentOffset, pWalReader->curVersion);
246,523,121✔
2206

2207
      // use ts to pass time when replay, because ts not used if type is log
2208
      pTaskInfo->streamInfo.currentOffset.ts = pAPI->tqReaderFn.tqGetResultBlockTime(pInfo->tqReader);
246,514,995✔
2209

2210
      if (hasResult) {
246,520,433✔
2211
        qDebug("doQueueScan get data from log %" PRId64 " rows, version:%" PRId64, pRes->info.rows,
204,635,016✔
2212
               pTaskInfo->streamInfo.currentOffset.version);
2213
        blockDataCleanup(pInfo->pRes);
204,651,243✔
2214
        code = setBlockIntoRes(pInfo, pRes);
204,646,737✔
2215
        QUERY_CHECK_CODE(code, lino, _end);
204,637,759!
2216
        qDebug("doQueueScan after filter get data from log %" PRId64 " rows, version:%" PRId64, pInfo->pRes->info.rows,
204,637,759!
2217
               pTaskInfo->streamInfo.currentOffset.version);
2218
        if (pInfo->pRes->info.rows > 0) {
204,636,017✔
2219
          (*ppRes) = pInfo->pRes;
202,568,387✔
2220
          return code;
202,565,663✔
2221
        }
2222
      } else {
2223
        qDebug("doQueueScan get none from log, return, version:%" PRId64, pTaskInfo->streamInfo.currentOffset.version);
41,885,417!
2224
        (*ppRes) = NULL;
41,885,417✔
2225
        return code;
41,885,417✔
2226
      }
2227
    }
2228
  } else {
2229
    qError("unexpected streamInfo prepare type: %d", pTaskInfo->streamInfo.currentOffset.type);
×
2230
    (*ppRes) = NULL;
×
2231
    return code;
×
2232
  }
2233

2234
_end:
×
2235
  if (code != TSDB_CODE_SUCCESS) {
×
2236
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2237
    pTaskInfo->code = code;
×
2238
    T_LONG_JMP(pTaskInfo->env, code);
×
2239
  }
2240
  (*ppRes) = NULL;
×
2241
  return code;
×
2242
}
2243

2244
static SSDataBlock* doQueueScan(SOperatorInfo* pOperator) {
×
2245
  SSDataBlock* pRes = NULL;
×
2246
  int32_t      code = doQueueScanNext(pOperator, &pRes);
×
2247
  return pRes;
×
2248
}
2249

2250
int32_t extractTableIdList(const STableListInfo* pTableListInfo, SArray** ppArrayRes) {
919,671✔
2251
  int32_t code = TSDB_CODE_SUCCESS;
919,671✔
2252
  int32_t lino = 0;
919,671✔
2253
  SArray* tableIdList = taosArrayInit(4, sizeof(uint64_t));
919,671✔
2254
  QUERY_CHECK_NULL(tableIdList, code, lino, _end, terrno);
923,104!
2255

2256
  // Transfer the Array of STableKeyInfo into uid list.
2257
  int32_t size = 0;
923,104✔
2258
  code = tableListGetSize(pTableListInfo, &size);
923,104✔
2259
  QUERY_CHECK_CODE(code, lino, _end);
921,324!
2260
  for (int32_t i = 0; i < size; ++i) {
28,066,779✔
2261
    STableKeyInfo* pkeyInfo = tableListGetInfo(pTableListInfo, i);
27,170,665✔
2262
    QUERY_CHECK_NULL(pkeyInfo, code, lino, _end, terrno);
27,164,647!
2263
    void* tmp = taosArrayPush(tableIdList, &pkeyInfo->uid);
27,164,647✔
2264
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
27,145,455!
2265
  }
2266

2267
  (*ppArrayRes) = tableIdList;
896,114✔
2268

2269
_end:
923,104✔
2270
  if (code != TSDB_CODE_SUCCESS) {
922,276!
2271
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2272
  }
2273
  return code;
922,276✔
2274
}
2275

2276
static int32_t doRawScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
4,347,940✔
2277
  int32_t        code = TSDB_CODE_SUCCESS;
4,347,940✔
2278
  int32_t        lino = 0;
4,347,940✔
2279
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
4,347,940✔
2280
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
4,347,940✔
2281

2282
  SStreamRawScanInfo* pInfo = pOperator->info;
4,347,940✔
2283
  pTaskInfo->streamInfo.btMetaRsp.batchMetaReq = NULL;  // use batchMetaReq != NULL to judge if data is meta
4,347,940✔
2284
  pTaskInfo->streamInfo.btMetaRsp.batchMetaLen = NULL;
4,347,940✔
2285

2286
  qDebug("tmqsnap doRawScan called");
4,347,940!
2287
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) {
4,347,940✔
2288
    bool hasNext = false;
4,332,487✔
2289
    if (pInfo->dataReader && pInfo->sContext->withMeta != ONLY_META) {
4,332,487!
2290
      code = pAPI->tsdReader.tsdNextDataBlock(pInfo->dataReader, &hasNext);
4,329,097✔
2291
      if (code != TSDB_CODE_SUCCESS) {
4,323,098!
2292
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->dataReader);
×
2293
        QUERY_CHECK_CODE(code, lino, _end);
×
2294
      }
2295
    }
2296

2297
    if (pInfo->dataReader && hasNext) {
4,326,488!
2298
      if (isTaskKilled(pTaskInfo)) {
2,105,193!
2299
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->dataReader);
×
2300
        return code;
×
2301
      }
2302

2303
      SSDataBlock* pBlock = NULL;
2,104,336✔
2304
      code = pAPI->tsdReader.tsdReaderRetrieveDataBlock(pInfo->dataReader, &pBlock, NULL);
2,103,479✔
2305
      QUERY_CHECK_CODE(code, lino, _end);
2,099,194!
2306

2307
      if (pBlock && pBlock->info.rows > 0) {
2,099,194!
2308
        bool hasPrimaryKey = pAPI->snapshotFn.taosXGetTablePrimaryKey(pInfo->sContext);
2,101,765✔
2309
        code = processPrimaryKey(pBlock, hasPrimaryKey, &pTaskInfo->streamInfo.currentOffset);
2,101,723✔
2310
        QUERY_CHECK_CODE(code, lino, _end);
2,097,480!
2311
        qDebug("tmqsnap doRawScan get data uid:%" PRId64, pBlock->info.id.uid);
2,097,480!
2312
        (*ppRes) = pBlock;
2,105,193✔
2313
        return code;
2,105,193✔
2314
      }
2315
    }
2316

2317
    SMetaTableInfo mtInfo = {0};
2,221,283✔
2318
    code = pAPI->snapshotFn.getMetaTableInfoFromSnapshot(pInfo->sContext, &mtInfo);
2,227,294✔
2319
    QUERY_CHECK_CODE(code, lino, _end);
2,223,866!
2320
    if (code != 0) {
2,223,866!
2321
      destroyMetaTableInfo(&mtInfo);
2322
      QUERY_CHECK_CODE(code, lino, _end);
×
2323
    }
2324
    STqOffsetVal offset = {0};
2,223,866✔
2325
    if (mtInfo.uid == 0 || pInfo->sContext->withMeta == ONLY_META) {  // read snapshot done, change to get data from wal
2,223,866✔
2326
      qDebug("tmqsnap read snapshot done, change to get data from wal");
32,797✔
2327
      tqOffsetResetToLog(&offset, pInfo->sContext->snapVersion + 1);
32,797✔
2328
    } else {
2329
      SValue val = {0};
2,192,783✔
2330
      tqOffsetResetToData(&offset, mtInfo.uid, INT64_MIN, val);
2,192,783!
2331
      qDebug("tmqsnap change get data uid:%" PRId64, mtInfo.uid);
2,192,795✔
2332
    }
2333
    destroyMetaTableInfo(&mtInfo);
2334
    code = qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType);
2,227,294✔
2335
    QUERY_CHECK_CODE(code, lino, _end);
2,227,294!
2336
    (*ppRes) = NULL;
2,227,294✔
2337
    return code;
2,227,294✔
2338
  } else if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_META) {
15,453!
2339
    SSnapContext* sContext = pInfo->sContext;
15,453✔
2340
    for (int32_t i = 0; i < tmqRowSize; i++) {
129,122!
2341
      void*   data = NULL;
129,951✔
2342
      int32_t dataLen = 0;
129,951✔
2343
      int16_t type = 0;
129,951✔
2344
      int64_t uid = 0;
129,951✔
2345
      if (pAPI->snapshotFn.getTableInfoFromSnapshot(sContext, &data, &dataLen, &type, &uid) < 0) {
129,951!
2346
        qError("tmqsnap getTableInfoFromSnapshot error");
×
2347
        taosMemoryFreeClear(data);
×
2348
        break;
×
2349
      }
2350

2351
      if (!sContext->queryMeta) {  // change to get data next poll request
129,951✔
2352
        STqOffsetVal offset = {0};
15,453✔
2353
        SValue       val = {0};
15,453!
2354
        tqOffsetResetToData(&offset, 0, INT64_MIN, val);
×
2355
        code = qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType);
15,453✔
2356
        QUERY_CHECK_CODE(code, lino, _end);
15,453!
2357
        break;
15,453✔
2358
      } else {
2359
        tqOffsetResetToMeta(&pTaskInfo->streamInfo.currentOffset, uid);
114,498✔
2360
        SMqMetaRsp tmpMetaRsp = {0};
114,498✔
2361
        tmpMetaRsp.resMsgType = type;
114,498✔
2362
        tmpMetaRsp.metaRspLen = dataLen;
114,498✔
2363
        tmpMetaRsp.metaRsp = data;
114,498✔
2364
        if (!pTaskInfo->streamInfo.btMetaRsp.batchMetaReq) {
114,498✔
2365
          pTaskInfo->streamInfo.btMetaRsp.batchMetaReq = taosArrayInit(4, POINTER_BYTES);
13,795✔
2366
          QUERY_CHECK_NULL(pTaskInfo->streamInfo.btMetaRsp.batchMetaReq, code, lino, _end, terrno);
13,795!
2367

2368
          pTaskInfo->streamInfo.btMetaRsp.batchMetaLen = taosArrayInit(4, sizeof(int32_t));
13,795✔
2369
          QUERY_CHECK_NULL(pTaskInfo->streamInfo.btMetaRsp.batchMetaLen, code, lino, _end, terrno);
13,795!
2370
        }
2371
        int32_t  tempRes = TSDB_CODE_SUCCESS;
114,498✔
2372
        uint32_t len = 0;
114,498✔
2373
        tEncodeSize(tEncodeMqMetaRsp, &tmpMetaRsp, len, tempRes);
114,498!
2374
        if (TSDB_CODE_SUCCESS != tempRes) {
114,498!
2375
          qError("tmqsnap tEncodeMqMetaRsp error");
×
2376
          taosMemoryFreeClear(data);
×
2377
          break;
×
2378
        }
2379

2380
        int32_t tLen = sizeof(SMqRspHead) + len;
114,498✔
2381
        void*   tBuf = taosMemoryCalloc(1, tLen);
114,498!
2382
        QUERY_CHECK_NULL(tBuf, code, lino, _end, terrno);
114,498!
2383

2384
        void*    metaBuff = POINTER_SHIFT(tBuf, sizeof(SMqRspHead));
114,498✔
2385
        SEncoder encoder = {0};
114,498✔
2386
        tEncoderInit(&encoder, metaBuff, len);
114,498✔
2387
        int32_t tempLen = tEncodeMqMetaRsp(&encoder, &tmpMetaRsp);
114,498✔
2388
        if (tempLen < 0) {
114,498!
2389
          qError("tmqsnap tEncodeMqMetaRsp error");
×
2390
          tEncoderClear(&encoder);
×
2391
          taosMemoryFreeClear(tBuf);
×
2392
          taosMemoryFreeClear(data);
×
2393
          break;
×
2394
        }
2395
        taosMemoryFreeClear(data);
114,498!
2396
        void* tmp = taosArrayPush(pTaskInfo->streamInfo.btMetaRsp.batchMetaReq, &tBuf);
114,498✔
2397
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
114,498!
2398

2399
        tmp = taosArrayPush(pTaskInfo->streamInfo.btMetaRsp.batchMetaLen, &tLen);
114,498✔
2400
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
114,498!
2401
      }
2402
    }
2403

2404
    (*ppRes) = NULL;
15,453✔
2405
    return code;
15,453✔
2406
  }
2407

2408
_end:
×
2409
  if (code != TSDB_CODE_SUCCESS) {
×
2410
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2411
    pTaskInfo->code = code;
×
2412
    T_LONG_JMP(pTaskInfo->env, code);
×
2413
  }
2414

2415
  (*ppRes) = NULL;
×
2416
  return code;
×
2417
}
2418

2419
static void destroyTmqRawScanOperatorInfo(void* param) {
294,710✔
2420
  SStreamRawScanInfo* pRawScan = (SStreamRawScanInfo*)param;
294,710✔
2421
  pRawScan->pAPI->tsdReader.tsdReaderClose(pRawScan->dataReader);
294,710✔
2422
  pRawScan->pAPI->snapshotFn.destroySnapshot(pRawScan->sContext);
294,710✔
2423
  tableListDestroy(pRawScan->pTableListInfo);
293,806✔
2424
  taosMemoryFree(pRawScan);
294,710!
2425
}
294,710✔
2426

2427
// for subscribing db or stb (not including column),
2428
// if this scan is used, meta data can be return
2429
// and schemas are decided when scanning
2430
int32_t createTmqRawScanOperatorInfo(SReadHandle* pHandle, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
293,841✔
2431
  // create operator
2432
  // create tb reader
2433
  // create meta reader
2434
  // create tq reader
2435

2436
  QRY_PARAM_CHECK(pOptrInfo);
293,841!
2437
  int32_t code = TSDB_CODE_SUCCESS;
294,710✔
2438
  int32_t lino = 0;
294,710✔
2439

2440
  SStreamRawScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamRawScanInfo));
294,710!
2441
  SOperatorInfo*      pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
294,710!
2442
  if (pInfo == NULL || pOperator == NULL) {
294,710!
2443
    code = terrno;
×
2444
    lino = __LINE__;
×
2445
    goto _end;
×
2446
  }
2447

2448
  pInfo->pTableListInfo = tableListCreate();
294,710✔
2449
  QUERY_CHECK_NULL(pInfo->pTableListInfo, code, lino, _end, terrno);
294,710!
2450
  pInfo->vnode = pHandle->vnode;
293,820✔
2451
  pInfo->pAPI = &pTaskInfo->storageAPI;
293,820✔
2452

2453
  pInfo->sContext = pHandle->sContext;
293,820✔
2454
  setOperatorInfo(pOperator, "RawScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, false, OP_NOT_OPENED, pInfo,
294,710✔
2455
                  pTaskInfo);
2456

2457
  pOperator->fpSet = createOperatorFpSet(NULL, doRawScanNext, NULL, destroyTmqRawScanOperatorInfo, optrDefaultBufFn,
294,710✔
2458
                                         NULL, optrDefaultGetNextExtFn, NULL);
2459
  *pOptrInfo = pOperator;
293,820✔
2460
  return code;
294,710✔
2461

2462
_end:
×
2463
  if (code != TSDB_CODE_SUCCESS) {
×
2464
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2465
  }
2466
  taosMemoryFree(pInfo);
×
2467
  taosMemoryFree(pOperator);
×
2468
  pTaskInfo->code = code;
×
2469
  return code;
×
2470
}
2471

2472
void destroyTmqScanOperatorInfo(void* param) {
923,104✔
2473
  if (param == NULL) {
923,104!
2474
    return;
×
2475
  }
2476

2477
  SStreamScanInfo* pStreamScan = (SStreamScanInfo*)param;
923,104✔
2478
  if (pStreamScan->pTableScanOp && pStreamScan->pTableScanOp->info) {
923,104!
2479
    destroyOperator(pStreamScan->pTableScanOp);
923,104✔
2480
  }
2481

2482
  if (pStreamScan->tqReader != NULL && pStreamScan->readerFn.tqReaderClose != NULL) {
923,104!
2483
    pStreamScan->readerFn.tqReaderClose(pStreamScan->tqReader);
923,104✔
2484
  }
2485
  if (pStreamScan->pVtableMergeHandles) {
924,005!
2486
    taosHashCleanup(pStreamScan->pVtableMergeHandles);
×
2487
    pStreamScan->pVtableMergeHandles = NULL;
×
2488
  }
2489
  if (pStreamScan->pVtableMergeBuf) {
923,104!
2490
    destroyDiskbasedBuf(pStreamScan->pVtableMergeBuf);
×
2491
    pStreamScan->pVtableMergeBuf = NULL;
×
2492
  }
2493
  if (pStreamScan->pVtableReadyHandles) {
923,104!
2494
    taosArrayDestroy(pStreamScan->pVtableReadyHandles);
×
2495
    pStreamScan->pVtableReadyHandles = NULL;
×
2496
  }
2497
  if (pStreamScan->pTableListInfo) {
923,104!
2498
    tableListDestroy(pStreamScan->pTableListInfo);
×
2499
    pStreamScan->pTableListInfo = NULL;
×
2500
  }
2501
  if (pStreamScan->matchInfo.pList) {
923,104!
2502
    taosArrayDestroy(pStreamScan->matchInfo.pList);
923,104✔
2503
  }
2504
  if (pStreamScan->pPseudoExpr) {
923,104✔
2505
    destroyExprInfo(pStreamScan->pPseudoExpr, pStreamScan->numOfPseudoExpr);
535,759✔
2506
    taosMemoryFree(pStreamScan->pPseudoExpr);
535,759!
2507
  }
2508

2509
  cleanupExprSupp(&pStreamScan->tbnameCalSup);
923,104✔
2510
  cleanupExprSupp(&pStreamScan->tagCalSup);
923,104✔
2511

2512
  blockDataDestroy(pStreamScan->pRes);
923,104✔
2513
  blockDataDestroy(pStreamScan->pUpdateRes);
923,104✔
2514
  blockDataDestroy(pStreamScan->pDeleteDataRes);
923,104✔
2515
  blockDataDestroy(pStreamScan->pUpdateDataRes);
923,104✔
2516
  blockDataDestroy(pStreamScan->pCreateTbRes);
923,104✔
2517
  taosArrayDestroy(pStreamScan->pBlockLists);
923,104✔
2518
  blockDataDestroy(pStreamScan->pCheckpointRes);
923,104✔
2519

2520
  taosMemoryFree(pStreamScan);
923,104!
2521
}
2522

2523
int32_t addPrimaryKeyCol(SSDataBlock* pBlock, uint8_t type, int32_t bytes) {
×
2524
  int32_t code = TSDB_CODE_SUCCESS;
×
2525
  int32_t lino = 0;
×
2526
  pBlock->info.rowSize += bytes;
×
2527
  SColumnInfoData infoData = {0};
×
2528
  infoData.info.type = type;
×
2529
  infoData.info.bytes = bytes;
×
2530
  void* tmp = taosArrayPush(pBlock->pDataBlock, &infoData);
×
2531
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
×
2532

2533
_end:
×
2534
  if (code != TSDB_CODE_SUCCESS) {
×
2535
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2536
  }
2537
  return code;
×
2538
}
2539

2540
static SSDataBlock* createStreamVtableBlock(SColMatchInfo* pMatchInfo, const char* idstr) {
×
2541
  int32_t      code = TSDB_CODE_SUCCESS;
×
2542
  int32_t      lino = 0;
×
2543
  SSDataBlock* pRes = NULL;
×
2544

2545
  QUERY_CHECK_NULL(pMatchInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
2546

2547
  code = createDataBlock(&pRes);
×
2548
  QUERY_CHECK_CODE(code, lino, _end);
×
2549
  int32_t numOfOutput = taosArrayGetSize(pMatchInfo->pList);
×
2550
  for (int32_t i = 0; i < numOfOutput; ++i) {
×
2551
    SColMatchItem* pItem = taosArrayGet(pMatchInfo->pList, i);
×
2552
    if (!pItem->needOutput) {
×
2553
      continue;
×
2554
    }
2555
    SColumnInfoData colInfo = createColumnInfoData(pItem->dataType.type, pItem->dataType.bytes, pItem->colId);
×
2556
    code = blockDataAppendColInfo(pRes, &colInfo);
×
2557
    QUERY_CHECK_CODE(code, lino, _end);
×
2558
  }
2559

2560
_end:
×
2561
  if (code != TSDB_CODE_SUCCESS) {
×
2562
    qError("%s failed at line %d since %s, id: %s", __func__, lino, tstrerror(code), idstr);
×
2563
    if (pRes != NULL) {
×
2564
      blockDataDestroy(pRes);
×
2565
    }
2566
    pRes = NULL;
×
2567
    terrno = code;
×
2568
  }
2569
  return pRes;
×
2570
}
2571

2572
 int32_t createTmqScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode,
922,214✔
2573
                                                  SNode* pTagCond, STableListInfo* pTableListInfo,
2574
                                                  SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
2575
  QRY_PARAM_CHECK(pOptrInfo);
922,214!
2576

2577
  int32_t          code = TSDB_CODE_SUCCESS;
923,104✔
2578
  int32_t          lino = 0;
923,104✔
2579
  SArray*          pColIds = NULL;
923,104✔
2580
  SStreamScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamScanInfo));
923,104!
2581
  SOperatorInfo*   pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
923,104!
2582
  SStorageAPI*     pAPI = &pTaskInfo->storageAPI;
923,104✔
2583
  const char*      idstr = pTaskInfo->id.str;
923,104✔
2584
  SSHashObj*       pVtableInfos = pTaskInfo->pSubplan->pVTables;
923,104✔
2585

2586
  if (pInfo == NULL || pOperator == NULL) {
923,104!
2587
    code = terrno;
×
2588
    goto _error;
×
2589
  }
2590

2591
  SScanPhysiNode*     pScanPhyNode = &pTableScanNode->scan;
923,104✔
2592
  SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc;
923,104✔
2593

2594
  pInfo->pTagCond = pTagCond;
923,104✔
2595
  pInfo->pGroupTags = pTableScanNode->pGroupTags;
923,104✔
2596

2597
  int32_t numOfCols = 0;
923,104✔
2598
  code = extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo);
923,104✔
2599
  if (code != TSDB_CODE_SUCCESS) {
923,104!
2600
    goto _error;
×
2601
  }
2602

2603
  SDataType pkType = {0};
923,104✔
2604
  pInfo->primaryKeyIndex = -1;
923,104✔
2605
  pInfo->basic.primaryPkIndex = -1;
923,104✔
2606
  int32_t numOfOutput = taosArrayGetSize(pInfo->matchInfo.pList);
923,104✔
2607
  pColIds = taosArrayInit(numOfOutput, sizeof(int16_t));
923,104✔
2608
  QUERY_CHECK_NULL(pColIds, code, lino, _error, terrno);
923,104!
2609

2610
  for (int32_t i = 0; i < numOfOutput; ++i) {
6,814,338✔
2611
    SColMatchItem* id = taosArrayGet(pInfo->matchInfo.pList, i);
5,891,234✔
2612
    QUERY_CHECK_NULL(id, code, lino, _error, terrno);
5,891,234!
2613

2614
    int16_t colId = id->colId;
5,891,234✔
2615
    void*   tmp = taosArrayPush(pColIds, &colId);
5,891,234✔
2616
    QUERY_CHECK_NULL(tmp, code, lino, _error, terrno);
5,891,234!
2617

2618
    if (id->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
5,891,234✔
2619
      pInfo->primaryTsIndex = id->dstSlotId;
923,104✔
2620
    }
2621
    if (id->isPk) {
5,891,234!
2622
      pInfo->primaryKeyIndex = id->dstSlotId;
×
2623
      pInfo->basic.primaryPkIndex = id->dstSlotId;
×
2624
      pkType = id->dataType;
×
2625
    }
2626
  }
2627

2628
  pInfo->pPartTbnameSup = NULL;
923,104✔
2629
  if (pTableScanNode->pSubtable != NULL) {
923,104!
2630
    SExprInfo* pSubTableExpr = taosMemoryCalloc(1, sizeof(SExprInfo));
×
2631
    if (pSubTableExpr == NULL) {
×
2632
      code = terrno;
×
2633
      goto _error;
×
2634
    }
2635

2636
    pInfo->tbnameCalSup.pExprInfo = pSubTableExpr;
×
2637
    code = createExprFromOneNode(pSubTableExpr, pTableScanNode->pSubtable, 0);
×
2638
    QUERY_CHECK_CODE(code, lino, _error);
×
2639

2640
    if (initExprSupp(&pInfo->tbnameCalSup, pSubTableExpr, 1, &pTaskInfo->storageAPI.functionStore) != 0) {
×
2641
      goto _error;
×
2642
    }
2643
  }
2644

2645
  if (pTableScanNode->pTags != NULL) {
923,104!
2646
    int32_t    numOfTags;
×
2647
    SExprInfo* pTagExpr = createExpr(pTableScanNode->pTags, &numOfTags);
×
2648
    if (pTagExpr == NULL) {
×
2649
      goto _error;
×
2650
    }
2651
    code = initExprSupp(&pInfo->tagCalSup, pTagExpr, numOfTags, &pTaskInfo->storageAPI.functionStore);
×
2652
    if (code != 0) {
×
2653
      goto _error;
×
2654
    }
2655
  }
2656

2657
  pInfo->pBlockLists = taosArrayInit(4, sizeof(SPackedData));
923,104✔
2658
  TSDB_CHECK_NULL(pInfo->pBlockLists, code, lino, _error, terrno);
923,104!
2659

2660
  if (pHandle->vnode) {
923,104!
2661
    SOperatorInfo* pTableScanOp = NULL;
923,104✔
2662
    code = createTableScanOperatorInfo(pTableScanNode, pHandle, pTableListInfo, pTaskInfo, &pTableScanOp);
923,104✔
2663
    if (pTableScanOp == NULL || code != 0) {
920,009!
2664
      qError("createTableScanOperatorInfo error, code:%d", pTaskInfo->code);
1,819!
2665
      goto _error;
×
2666
    }
2667

2668
    STableScanInfo* pTSInfo = (STableScanInfo*)pTableScanOp->info;
918,190✔
2669
    if (pHandle->version > 0) {
919,937✔
2670
      pTSInfo->base.cond.endVersion = pHandle->version;
919,920✔
2671
    }
2672

2673
    STableKeyInfo* pList = NULL;
920,478✔
2674
    int32_t        num = 0;
921,332✔
2675
    code = tableListGetGroupList(pTableListInfo, 0, &pList, &num);
919,909✔
2676
    QUERY_CHECK_CODE(code, lino, _error);
920,838!
2677

2678
    if (pHandle->initTableReader) {
920,838!
2679
      pTSInfo->scanMode = TABLE_SCAN__TABLE_ORDER;
920,838✔
2680
      pTSInfo->base.dataReader = NULL;
920,838✔
2681
    }
2682

2683
    if (pHandle->initTqReader) {
919,937✔
2684
      pInfo->tqReader = pAPI->tqReaderFn.tqReaderOpen(pHandle->vnode);
920,810✔
2685
      QUERY_CHECK_NULL(pInfo->tqReader, code, lino, _error, terrno);
923,104!
2686
    } else {
2687
      pInfo->tqReader = pHandle->tqReader;
17✔
2688
      QUERY_CHECK_NULL(pInfo->tqReader, code, lino, _error, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
2689
    }
2690

2691
    if (pVtableInfos != NULL) {
923,104!
2692
      // save vtable info into tqReader for vtable source scan
2693
      SSDataBlock* pResBlock = createStreamVtableBlock(&pInfo->matchInfo, idstr);
×
2694
      QUERY_CHECK_CODE(code, lino, _error);
×
2695
      code = pAPI->tqReaderFn.tqReaderSetVtableInfo(pInfo->tqReader, pHandle->vnode, pAPI, pVtableInfos, &pResBlock,
×
2696
                                                    idstr);
2697
      QUERY_CHECK_CODE(code, lino, _error);
×
2698
    }
2699

2700
    pInfo->pUpdateInfo = NULL;
923,104✔
2701
    pInfo->pTableScanOp = pTableScanOp;
923,104✔
2702
    if (pInfo->pTableScanOp->pTaskInfo->streamInfo.pState) {
923,104!
2703
      pAPI->stateStore.streamStateSetNumber(pInfo->pTableScanOp->pTaskInfo->streamInfo.pState, -1,
×
2704
                                            pInfo->primaryTsIndex);
2705
    }
2706

2707
    pInfo->readHandle = *pHandle;
923,104✔
2708
    pTaskInfo->streamInfo.snapshotVer = pHandle->version;
923,104✔
2709
    pInfo->pCreateTbRes = buildCreateTableBlock(&pInfo->tbnameCalSup, &pInfo->tagCalSup);
923,104✔
2710
    QUERY_CHECK_NULL(pInfo->pCreateTbRes, code, lino, _error, terrno);
921,370!
2711
    pInfo->hasPart = false;
922,275✔
2712

2713
    code = blockDataEnsureCapacity(pInfo->pCreateTbRes, 8);
923,104✔
2714
    QUERY_CHECK_CODE(code, lino, _error);
919,610!
2715

2716
    // set the extract column id to streamHandle
2717
    code = pAPI->tqReaderFn.tqReaderSetColIdList(pInfo->tqReader, pColIds, idstr);
919,610✔
2718
    QUERY_CHECK_CODE(code, lino, _error);
920,571!
2719

2720
    SArray* tableIdList = NULL;
920,571✔
2721
    code = extractTableIdList(((STableScanInfo*)(pInfo->pTableScanOp->info))->base.pTableListInfo, &tableIdList);
920,571✔
2722
    QUERY_CHECK_CODE(code, lino, _error);
921,375!
2723
    code = pAPI->tqReaderFn.tqReaderSetQueryTableList(pInfo->tqReader, tableIdList, idstr);
921,375✔
2724
    QUERY_CHECK_CODE(code, lino, _error);
923,104!
2725
    taosArrayDestroy(tableIdList);
923,104✔
2726
    memcpy(&pTaskInfo->streamInfo.tableCond, &pTSInfo->base.cond, sizeof(SQueryTableDataCond));
923,104!
2727
  } else {
2728
    taosArrayDestroy(pColIds);
×
2729
    tableListDestroy(pTableListInfo);
×
2730
  }
2731

2732
  // clear the local variable to avoid repeatly free
2733
  pColIds = NULL;
923,104✔
2734

2735
  // create the pseduo columns info
2736
  if (pTableScanNode->scan.pScanPseudoCols != NULL) {
923,104✔
2737
    code = createExprInfo(pTableScanNode->scan.pScanPseudoCols, NULL, &pInfo->pPseudoExpr, &pInfo->numOfPseudoExpr);
535,759✔
2738
    QUERY_CHECK_CODE(code, lino, _error);
535,759!
2739
  }
2740

2741
  code = filterInitFromNode((SNode*)pScanPhyNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0, NULL);
923,104✔
2742
  QUERY_CHECK_CODE(code, lino, _error);
923,104!
2743

2744
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
923,104✔
2745
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
923,104!
2746
  code = createSpecialDataBlock(STREAM_CLEAR, &pInfo->pUpdateRes);
923,104✔
2747
  QUERY_CHECK_CODE(code, lino, _error);
923,104!
2748

2749
  pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
923,104✔
2750
  pInfo->windowSup = (SWindowSupporter){.pStreamAggSup = NULL, .gap = -1, .parentType = QUERY_NODE_PHYSICAL_PLAN};
923,104✔
2751
  pInfo->groupId = 0;
923,104✔
2752
  pInfo->igCheckGroupId = false;
923,104✔
2753
  pInfo->pStreamScanOp = pOperator;
922,247✔
2754
  pInfo->deleteDataIndex = 0;
923,104✔
2755
  code = createSpecialDataBlock(STREAM_DELETE_DATA, &pInfo->pDeleteDataRes);
923,104✔
2756
  QUERY_CHECK_CODE(code, lino, _error);
923,104!
2757

2758
  pInfo->updateWin = (STimeWindow){.skey = INT64_MAX, .ekey = INT64_MAX};
923,104✔
2759
  code = createSpecialDataBlock(STREAM_CLEAR, &pInfo->pUpdateDataRes);
923,104✔
2760
  QUERY_CHECK_CODE(code, lino, _error);
923,104!
2761

2762
  pInfo->assignBlockUid = pTableScanNode->assignBlockUid;
923,104!
2763
  pInfo->partitionSup.needCalc = false;
923,104✔
2764
  pInfo->igCheckUpdate = pTableScanNode->igCheckUpdate;
923,104✔
2765
  pInfo->igExpired = pTableScanNode->igExpired;
923,104✔
2766
  pInfo->twAggSup.maxTs = INT64_MIN;
922,214✔
2767
  pInfo->pState = pTaskInfo->streamInfo.pState;
923,104✔
2768
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
923,104✔
2769
  pInfo->readerFn = pTaskInfo->storageAPI.tqReaderFn;
922,214✔
2770
  pInfo->pFillSup = NULL;
923,104✔
2771
  pInfo->useGetResultRange = false;
922,214✔
2772
  pInfo->pRangeScanRes = NULL;
923,104✔
2773

2774
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
922,214✔
2775
  QUERY_CHECK_CODE(code, lino, _error);
923,104!
2776

2777
  setOperatorInfo(pOperator, STREAM_SCAN_OP_NAME, QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, false, OP_NOT_OPENED, pInfo,
923,104✔
2778
                  pTaskInfo);
2779
  pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pRes->pDataBlock);
923,104✔
2780

2781
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doQueueScanNext, NULL, destroyTmqScanOperatorInfo, optrDefaultBufFn,
922,214✔
2782
                                         NULL, optrDefaultGetNextExtFn, NULL);
2783

2784
  *pOptrInfo = pOperator;
923,104✔
2785
  return code;
922,214✔
2786

2787
_error:
×
2788
  if (pColIds != NULL) {
×
2789
    taosArrayDestroy(pColIds);
×
2790
  }
2791

2792
  if (pInfo != NULL && pInfo->pTableScanOp != NULL) {
×
2793
    STableScanInfo* p = (STableScanInfo*)pInfo->pTableScanOp->info;
×
2794
    if (p != NULL) {
×
2795
      p->base.pTableListInfo = NULL;
×
2796
    }
2797
    destroyTmqScanOperatorInfo(pInfo);
×
2798
  }
2799

2800
  if (pOperator != NULL) {
×
2801
    pOperator->info = NULL;
×
2802
    destroyOperator(pOperator);
×
2803
  }
2804
  pTaskInfo->code = code;
×
2805
  return code;
×
2806
}
2807

2808
static int32_t doTagScanOneTable(SOperatorInfo* pOperator, SSDataBlock* pRes, SMetaReader* mr, SStorageAPI* pAPI) {
14,980,475✔
2809
  int32_t        code = TSDB_CODE_SUCCESS;
14,980,475✔
2810
  int32_t        lino = 0;
14,980,475✔
2811
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
14,980,475✔
2812
  STagScanInfo*  pInfo = pOperator->info;
14,983,547✔
2813
  SExprInfo*     pExprInfo = &pOperator->exprSupp.pExprInfo[0];
14,983,600✔
2814
  int32_t        count = pRes->info.rows;
14,983,600✔
2815

2816
  STableKeyInfo* item = tableListGetInfo(pInfo->pTableListInfo, pInfo->curPos);
14,983,600✔
2817
  if (!item) {
14,983,600!
2818
    qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
×
2819
           GET_TASKID(pTaskInfo));
2820
    tDecoderClear(&(*mr).coder);
×
2821
    goto _end;
×
2822
  }
2823

2824
  code = pAPI->metaReaderFn.getTableEntryByUid(mr, item->uid);
14,983,600✔
2825
  tDecoderClear(&(*mr).coder);
14,982,934✔
2826
  if (code != TSDB_CODE_SUCCESS) {
14,981,280!
2827
    qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
×
2828
           GET_TASKID(pTaskInfo));
2829
    goto _end;
×
2830
  }
2831

2832
  char str[512];
14,981,280✔
2833
  for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
38,379,305✔
2834
    SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
23,396,977✔
2835

2836
    // refactor later
2837
    if (FUNCTION_TYPE_TBNAME == pExprInfo[j].pExpr->_function.functionType) {
23,395,039✔
2838
      STR_TO_VARSTR(str, (*mr).me.name);
10,027,946!
2839
      code = colDataSetVal(pDst, (count), str, false);
10,026,638✔
2840
      QUERY_CHECK_CODE(code, lino, _end);
10,028,612!
2841
    } else if (FUNCTION_TYPE_TBUID == pExprInfo[j].pExpr->_function.functionType) {
13,369,685✔
2842
      code = colDataSetVal(pDst, (count), (char*)&(*mr).me.uid, false);
105,838✔
2843
      QUERY_CHECK_CODE(code, lino, _end);
105,838!
2844
    } else if (FUNCTION_TYPE_VGID == pExprInfo[j].pExpr->_function.functionType) {
13,262,575✔
2845
      code = colDataSetVal(pDst, (count), (char*)&pTaskInfo->id.vgId, false);
105,838✔
2846
      QUERY_CHECK_CODE(code, lino, _end);
105,838!
2847
    } else {  // it is a tag value
2848
      STagVal val = {0};
13,156,737✔
2849
      val.cid = pExprInfo[j].base.pParam[0].pCol->colId;
13,156,737✔
2850
      const char* p = pAPI->metaFn.extractTagVal((*mr).me.ctbEntry.pTags, pDst->info.type, &val);
13,158,009✔
2851

2852
      char* data = NULL;
13,158,009✔
2853
      if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL) {
13,158,009!
2854
        data = tTagValToData((const STagVal*)p, false);
13,158,009✔
2855
      } else {
2856
        data = (char*)p;
×
2857
      }
2858

2859
      code = colDataSetVal(pDst, (count), data,
13,156,737✔
2860
                           (data == NULL) || (pDst->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data)));
13,156,737!
2861
      QUERY_CHECK_CODE(code, lino, _end);
13,158,009!
2862

2863
      if ((pDst->info.type != TSDB_DATA_TYPE_JSON) && (p != NULL) && IS_VAR_DATA_TYPE(((const STagVal*)p)->type) &&
13,158,009!
2864
          (data != NULL)) {
2865
        taosMemoryFree(data);
2,943,678!
2866
      }
2867
    }
2868
  }
2869

2870
_end:
14,983,600✔
2871
  if (code != TSDB_CODE_SUCCESS) {
14,982,934!
2872
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2873
    pTaskInfo->code = code;
×
2874
  } else {
2875
    pRes->info.rows++;
14,982,934✔
2876
  }
2877

2878
  return code;
14,982,328✔
2879
}
2880

2881
static void tagScanFreeUidTag(void* p) {
48,008,704✔
2882
  STUidTagInfo* pInfo = p;
48,008,704✔
2883
  if (pInfo->pTagVal != NULL) {
48,008,704✔
2884
    taosMemoryFree(pInfo->pTagVal);
48,009,719!
2885
  }
2886
}
48,010,905✔
2887

2888
static int32_t tagScanCreateResultData(SDataType* pType, int32_t numOfRows, SScalarParam* pParam) {
10,807,256✔
2889
  SColumnInfoData* pColumnData = taosMemoryCalloc(1, sizeof(SColumnInfoData));
10,807,256!
2890
  if (pColumnData == NULL) {
10,806,685!
2891
    return terrno;
×
2892
  }
2893

2894
  pColumnData->info.type = pType->type;
10,806,685✔
2895
  pColumnData->info.bytes = pType->bytes;
10,805,047✔
2896
  pColumnData->info.scale = pType->scale;
10,808,758✔
2897
  pColumnData->info.precision = pType->precision;
10,805,730✔
2898

2899
  int32_t code = colInfoDataEnsureCapacity(pColumnData, numOfRows, true);
10,805,762✔
2900
  if (code != TSDB_CODE_SUCCESS) {
10,800,792!
2901
    terrno = code;
×
2902
    taosMemoryFree(pColumnData);
×
2903
    return terrno;
×
2904
  }
2905

2906
  pParam->columnData = pColumnData;
10,800,792✔
2907
  pParam->colAlloced = true;
10,804,505✔
2908
  return TSDB_CODE_SUCCESS;
10,809,612✔
2909
}
2910

2911
static EDealRes tagScanRewriteTagColumn(SNode** pNode, void* pContext) {
68,122,354✔
2912
  int32_t                code = TSDB_CODE_SUCCESS;
68,122,354✔
2913
  int32_t                lino = 0;
68,122,354✔
2914
  STagScanFilterContext* pCtx = (STagScanFilterContext*)pContext;
68,122,354✔
2915
  SColumnNode*           pSColumnNode = NULL;
68,122,354✔
2916
  if (QUERY_NODE_COLUMN == nodeType((*pNode))) {
68,128,198✔
2917
    pSColumnNode = *(SColumnNode**)pNode;
19,069,161✔
2918
  } else if (QUERY_NODE_FUNCTION == nodeType((*pNode))) {
49,088,125!
2919
    SFunctionNode* pFuncNode = *(SFunctionNode**)(pNode);
×
2920
    if (pFuncNode->funcType == FUNCTION_TYPE_TBNAME) {
×
2921
      pSColumnNode = NULL;
×
2922
      pCtx->code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pSColumnNode);
×
2923
      if (NULL == pSColumnNode) {
×
2924
        return DEAL_RES_ERROR;
×
2925
      }
2926
      pSColumnNode->colId = -1;
×
2927
      pSColumnNode->colType = COLUMN_TYPE_TBNAME;
×
2928
      pSColumnNode->node.resType.type = TSDB_DATA_TYPE_VARCHAR;
×
2929
      pSColumnNode->node.resType.bytes = TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE;
×
2930
      nodesDestroyNode(*pNode);
×
2931
      *pNode = (SNode*)pSColumnNode;
×
2932
    } else {
2933
      return DEAL_RES_CONTINUE;
×
2934
    }
2935
  } else {
2936
    return DEAL_RES_CONTINUE;
49,077,900✔
2937
  }
2938

2939
  void* data = taosHashGet(pCtx->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId));
19,069,088✔
2940
  if (!data) {
19,064,952✔
2941
    code = taosHashPut(pCtx->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId), pNode, sizeof((*pNode)));
10,812,883✔
2942
    if (code == TSDB_CODE_DUP_KEY) {
10,819,063!
2943
      code = TSDB_CODE_SUCCESS;
×
2944
    }
2945
    QUERY_CHECK_CODE(code, lino, _end);
10,819,063!
2946
    pSColumnNode->slotId = pCtx->index++;
10,819,063✔
2947
    SColumnInfo cInfo = {.colId = pSColumnNode->colId,
10,818,454✔
2948
                         .type = pSColumnNode->node.resType.type,
10,818,281✔
2949
                         .bytes = pSColumnNode->node.resType.bytes};
10,813,640✔
2950
    void*       tmp = taosArrayPush(pCtx->cInfoList, &cInfo);
10,815,579✔
2951
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
10,821,040!
2952
  } else {
2953
    SColumnNode* col = *(SColumnNode**)data;
8,252,069✔
2954
    pSColumnNode->slotId = col->slotId;
8,252,076✔
2955
  }
2956

2957
_end:
19,066,370✔
2958
  if (code != TSDB_CODE_SUCCESS) {
19,066,370✔
2959
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
10,498!
2960
    return DEAL_RES_ERROR;
×
2961
  }
2962
  return DEAL_RES_CONTINUE;
19,055,872✔
2963
}
2964

2965
static int32_t tagScanFilterByTagCond(SArray* aUidTags, SNode* pTagCond, SArray* aFilterIdxs, void* pVnode,
10,810,684✔
2966
                                      SStorageAPI* pAPI, STagScanInfo* pInfo) {
2967
  int32_t code = TSDB_CODE_SUCCESS;
10,810,684✔
2968
  int32_t lino = 0;
10,810,684✔
2969
  int32_t numOfTables = taosArrayGetSize(aUidTags);
10,810,684✔
2970
  SArray* pBlockList = NULL;
10,810,684✔
2971

2972
  SSDataBlock* pResBlock = createTagValBlockForFilter(pInfo->filterCtx.cInfoList, numOfTables, aUidTags, pVnode, pAPI);
10,810,684✔
2973
  QUERY_CHECK_NULL(pResBlock, code, lino, _end, terrno);
10,803,085!
2974

2975
  pBlockList = taosArrayInit(1, POINTER_BYTES);
10,803,085✔
2976
  QUERY_CHECK_NULL(pBlockList, code, lino, _end, terrno);
10,804,018!
2977

2978
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
10,809,601✔
2979
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
10,809,601!
2980

2981
  SDataType type = {.type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)};
10,809,601✔
2982

2983
  SScalarParam output = {0};
10,807,902✔
2984
  code = tagScanCreateResultData(&type, numOfTables, &output);
10,806,967✔
2985
  QUERY_CHECK_CODE(code, lino, _end);
10,805,777!
2986

2987
  code = scalarCalculate(pTagCond, pBlockList, &output, NULL, NULL);
10,805,777✔
2988
  QUERY_CHECK_CODE(code, lino, _end);
10,785,586!
2989

2990
  bool* result = (bool*)output.columnData->pData;
10,785,586✔
2991
  for (int32_t i = 0; i < numOfTables; ++i) {
27,029,903✔
2992
    if (result[i]) {
16,236,564!
2993
      void* tmp = taosArrayPush(aFilterIdxs, &i);
15,511,196✔
2994
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
15,511,196!
2995
    }
2996
  }
2997

2998
  colDataDestroy(output.columnData);
10,807,083✔
2999
  taosMemoryFreeClear(output.columnData);
10,785,759!
3000

3001
_end:
10,775,558✔
3002
  blockDataDestroy(pResBlock);
10,779,387✔
3003
  taosArrayDestroy(pBlockList);
10,779,365✔
3004
  if (code != TSDB_CODE_SUCCESS) {
10,775,301!
3005
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3006
  }
3007
  return code;
10,775,301✔
3008
}
3009

3010
static int32_t tagScanFillOneCellWithTag(SOperatorInfo* pOperator, const STUidTagInfo* pUidTagInfo,
198,318,636✔
3011
                                         SExprInfo* pExprInfo, SColumnInfoData* pColInfo, int rowIndex,
3012
                                         const SStorageAPI* pAPI, void* pVnode) {
3013
  int32_t code = TSDB_CODE_SUCCESS;
198,318,636✔
3014
  int32_t lino = 0;
198,318,636✔
3015
  if (QUERY_NODE_FUNCTION == pExprInfo->pExpr->nodeType) {
198,318,636✔
3016
    if (FUNCTION_TYPE_TBNAME == pExprInfo->pExpr->_function.functionType) {  // tbname
94,574,945!
3017
      char str[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
×
3018
      STR_TO_VARSTR(str, "ctbidx");
×
3019

3020
      code = colDataSetVal(pColInfo, rowIndex, str, false);
×
3021
      QUERY_CHECK_CODE(code, lino, _end);
×
3022
    } else if (FUNCTION_TYPE_TBUID == pExprInfo->pExpr->_function.functionType) {
94,520,191✔
3023
      code = colDataSetVal(pColInfo, rowIndex, (char*)&pUidTagInfo->uid, false);
47,262,230✔
3024
      QUERY_CHECK_CODE(code, lino, _end);
47,286,688!
3025
    } else if (FUNCTION_TYPE_VGID == pExprInfo->pExpr->_function.functionType) {
47,288,433✔
3026
      code = colDataSetVal(pColInfo, rowIndex, (char*)&pOperator->pTaskInfo->id.vgId, false);
47,267,944✔
3027
      QUERY_CHECK_CODE(code, lino, _end);
47,288,057!
3028
    }
3029
  } else {
3030
    STagVal tagVal = {0};
103,748,758✔
3031
    tagVal.cid = pExprInfo->base.pParam[0].pCol->colId;
103,755,917✔
3032
    if (pUidTagInfo->pTagVal == NULL) {
103,761,225!
3033
      colDataSetNULL(pColInfo, rowIndex);
×
3034
    } else {
3035
      const char* p = pAPI->metaFn.extractTagVal(pUidTagInfo->pTagVal, pColInfo->info.type, &tagVal);
103,717,825✔
3036

3037
      if (p == NULL || (pColInfo->info.type == TSDB_DATA_TYPE_JSON && ((STag*)p)->nTag == 0)) {
103,766,475!
3038
        colDataSetNULL(pColInfo, rowIndex);
31,487!
3039
      } else if (pColInfo->info.type == TSDB_DATA_TYPE_JSON) {
103,734,308!
3040
        code = colDataSetVal(pColInfo, rowIndex, p, false);
×
3041
        QUERY_CHECK_CODE(code, lino, _end);
×
3042
      } else if (IS_VAR_DATA_TYPE(pColInfo->info.type)) {
128,642,376!
3043
        if (IS_STR_DATA_BLOB(pColInfo->info.type)) {
24,944,704✔
3044
          QUERY_CHECK_CODE(code = TSDB_CODE_BLOB_NOT_SUPPORT_TAG, lino, _end);
×
3045
        }
3046
        char* tmp = taosMemoryMalloc(tagVal.nData + VARSTR_HEADER_SIZE + 1);
24,932,924!
3047
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
24,916,797!
3048

3049
        varDataSetLen(tmp, tagVal.nData);
24,916,797✔
3050
        memcpy(tmp + VARSTR_HEADER_SIZE, tagVal.pData, tagVal.nData);
24,903,724!
3051
        code = colDataSetVal(pColInfo, rowIndex, tmp, false);
24,933,288✔
3052
        taosMemoryFree(tmp);
24,928,121!
3053
        QUERY_CHECK_CODE(code, lino, _end);
24,924,709!
3054
      } else {
3055
        code = colDataSetVal(pColInfo, rowIndex, (const char*)&tagVal.i64, false);
78,785,417✔
3056
        QUERY_CHECK_CODE(code, lino, _end);
78,804,239!
3057
      }
3058
    }
3059
  }
3060

3061
_end:
198,348,299✔
3062
  if (code != TSDB_CODE_SUCCESS) {
198,348,299!
3063
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3064
  }
3065
  return code;
198,313,619✔
3066
}
3067

3068
static int32_t tagScanFillResultBlock(SOperatorInfo* pOperator, SSDataBlock* pRes, SArray* aUidTags,
30,866,899✔
3069
                                      SArray* aFilterIdxs, bool ignoreFilterIdx, SStorageAPI* pAPI) {
3070
  int32_t       code = TSDB_CODE_SUCCESS;
30,866,899✔
3071
  int32_t       lino = 0;
30,866,899✔
3072
  STagScanInfo* pInfo = pOperator->info;
30,866,899✔
3073
  SExprInfo*    pExprInfo = &pOperator->exprSupp.pExprInfo[0];
30,876,568✔
3074
  if (!ignoreFilterIdx) {
30,860,944✔
3075
    size_t szTables = taosArrayGetSize(aFilterIdxs);
10,780,798✔
3076
    for (int i = 0; i < szTables; ++i) {
26,289,194✔
3077
      int32_t       idx = *(int32_t*)taosArrayGet(aFilterIdxs, i);
15,493,683✔
3078
      STUidTagInfo* pUidTagInfo = taosArrayGet(aUidTags, idx);
15,499,454✔
3079
      QUERY_CHECK_NULL(pUidTagInfo, code, lino, _end, terrno);
15,494,875!
3080
      for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
88,339,370✔
3081
        SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
72,835,382✔
3082
        QUERY_CHECK_NULL(pDst, code, lino, _end, terrno);
72,854,185!
3083
        code = tagScanFillOneCellWithTag(pOperator, pUidTagInfo, &pExprInfo[j], pDst, i, pAPI, pInfo->readHandle.vnode);
72,854,185✔
3084
        QUERY_CHECK_CODE(code, lino, _end);
72,844,495!
3085
      }
3086
    }
3087
  } else {
3088
    size_t szTables = taosArrayGetSize(aUidTags);
20,080,146✔
3089
    for (int i = 0; i < szTables; ++i) {
51,874,046✔
3090
      STUidTagInfo* pUidTagInfo = taosArrayGet(aUidTags, i);
31,793,658✔
3091
      QUERY_CHECK_NULL(pUidTagInfo, code, lino, _end, terrno);
31,794,657✔
3092
      for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
157,242,431✔
3093
        SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
125,453,529✔
3094
        QUERY_CHECK_NULL(pDst, code, lino, _end, terrno);
125,465,238!
3095
        code = tagScanFillOneCellWithTag(pOperator, pUidTagInfo, &pExprInfo[j], pDst, i, pAPI, pInfo->readHandle.vnode);
125,465,238✔
3096
        QUERY_CHECK_CODE(code, lino, _end);
125,448,531!
3097
      }
3098
    }
3099
  }
3100

3101
_end:
20,080,388✔
3102
  if (code != TSDB_CODE_SUCCESS) {
30,875,899!
3103
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3104
  }
3105
  return code;
30,881,540✔
3106
}
3107

3108
static int32_t doTagScanFromCtbIdxNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
61,548,643✔
3109
  int32_t        code = TSDB_CODE_SUCCESS;
61,548,643✔
3110
  int32_t        lino = 0;
61,548,643✔
3111
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
61,548,643✔
3112
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
61,554,882✔
3113

3114
  STagScanInfo* pInfo = pOperator->info;
61,549,652✔
3115
  SSDataBlock*  pRes = pInfo->pRes;
61,534,888✔
3116

3117
  QRY_PARAM_CHECK(ppRes);
61,550,232!
3118

3119
  if (pOperator->status == OP_EXEC_DONE) {
61,553,643✔
3120
    return TSDB_CODE_SUCCESS;
30,415,201✔
3121
  }
3122
  blockDataCleanup(pRes);
31,127,753✔
3123

3124
  if (pInfo->pCtbCursor == NULL) {
31,143,130!
3125
    pInfo->pCtbCursor = pAPI->metaFn.openCtbCursor(pInfo->readHandle.vnode, pInfo->suid, 1);
31,141,116✔
3126
    QUERY_CHECK_NULL(pInfo->pCtbCursor, code, lino, _end, terrno);
31,149,727!
3127
  } else {
3128
    code = pAPI->metaFn.resumeCtbCursor(pInfo->pCtbCursor, 0);
×
3129
    QUERY_CHECK_CODE(code, lino, _end);
×
3130
  }
3131

3132
  SArray* aUidTags = pInfo->aUidTags;
31,146,687✔
3133
  SArray* aFilterIdxs = pInfo->aFilterIdxs;
31,146,415✔
3134
  int32_t count = 0;
31,146,149✔
3135
  bool    ctbCursorFinished = false;
31,146,149✔
3136
  while (1) {
466,629✔
3137
    taosArrayClearEx(aUidTags, tagScanFreeUidTag);
31,612,778✔
3138
    taosArrayClear(aFilterIdxs);
31,603,701✔
3139

3140
    int32_t numTables = 0;
31,600,542✔
3141
    while (numTables < pOperator->resultInfo.capacity) {
79,682,030✔
3142
      SMCtbCursor* pCur = pInfo->pCtbCursor;
79,636,014✔
3143
      tb_uid_t     uid = pAPI->metaFn.ctbCursorNext(pInfo->pCtbCursor);
79,638,823✔
3144
      if (uid == 0) {
79,638,873✔
3145
        ctbCursorFinished = true;
31,613,180✔
3146
        break;
31,613,180✔
3147
      }
3148
      STUidTagInfo info = {.uid = uid, .pTagVal = pCur->pVal};
48,025,693✔
3149
      info.pTagVal = taosMemoryMalloc(pCur->vLen);
48,005,768!
3150
      QUERY_CHECK_NULL(info.pTagVal, code, lino, _end, terrno);
48,010,662!
3151

3152
      memcpy(info.pTagVal, pCur->pVal, pCur->vLen);
48,010,662!
3153
      void* tmp = taosArrayPush(aUidTags, &info);
48,038,301✔
3154
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
48,038,301!
3155
      ++numTables;
48,038,301✔
3156
    }
3157

3158
    if (numTables == 0) {
31,613,180✔
3159
      break;
722,423✔
3160
    }
3161
    bool ignoreFilterIdx = true;
30,890,757✔
3162
    if (pInfo->pTagCond != NULL) {
30,890,757✔
3163
      ignoreFilterIdx = false;
10,810,684✔
3164
      code = tagScanFilterByTagCond(aUidTags, pInfo->pTagCond, aFilterIdxs, pInfo->readHandle.vnode, pAPI, pInfo);
10,810,684✔
3165
      QUERY_CHECK_CODE(code, lino, _end);
10,777,315!
3166
    } else {
3167
      ignoreFilterIdx = true;
20,080,073✔
3168
    }
3169

3170
    code = tagScanFillResultBlock(pOperator, pRes, aUidTags, aFilterIdxs, ignoreFilterIdx, pAPI);
30,857,388✔
3171
    QUERY_CHECK_CODE(code, lino, _end);
30,878,756!
3172

3173
    count = ignoreFilterIdx ? taosArrayGetSize(aUidTags) : taosArrayGetSize(aFilterIdxs);
30,878,756✔
3174

3175
    if (count != 0) {
30,882,955✔
3176
      break;
30,416,326✔
3177
    }
3178
  }
3179

3180
  if (count > 0) {
31,138,749✔
3181
    pAPI->metaFn.pauseCtbCursor(pInfo->pCtbCursor);
30,422,795✔
3182
  }
3183
  if (count == 0 || ctbCursorFinished) {
31,141,226!
3184
    pAPI->metaFn.closeCtbCursor(pInfo->pCtbCursor);
31,143,996✔
3185
    pInfo->pCtbCursor = NULL;
31,124,261✔
3186
    setOperatorCompleted(pOperator);
31,121,563✔
3187
  }
3188

3189
  pRes->info.rows = count;
31,128,311✔
3190
  bool bLimitReached = applyLimitOffset(&pInfo->limitInfo, pRes, pTaskInfo);
31,129,995✔
3191
  if (bLimitReached) {
31,128,289!
3192
    setOperatorCompleted(pOperator);
×
3193
  }
3194

3195
  pOperator->resultInfo.totalRows += pRes->info.rows;
31,128,289✔
3196
  (*ppRes) = (pRes->info.rows == 0) ? NULL : pInfo->pRes;
31,124,723✔
3197

3198
_end:
31,100,475✔
3199
  if (code != TSDB_CODE_SUCCESS) {
31,100,475!
3200
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3201
    pTaskInfo->code = code;
×
3202
    T_LONG_JMP(pTaskInfo->env, code);
×
3203
  }
3204

3205
  return code;
31,100,475✔
3206
}
3207

3208
static int32_t createTagScanTableListInfoFromParam(SOperatorInfo* pOperator) {
4,891,774✔
3209
  STagScanInfo*          pInfo = pOperator->info;
4,891,774✔
3210
  SExecTaskInfo*         pTaskInfo = pOperator->pTaskInfo;
4,891,774✔
3211
  int32_t                code = 0;
4,891,774✔
3212
  STableListInfo*        pListInfo = pInfo->pTableListInfo;
4,891,774✔
3213
  STagScanOperatorParam* pParam = (STagScanOperatorParam*)pOperator->pOperatorGetParam->value;
4,891,774✔
3214
  tb_uid_t               pUid = pParam->vcUid;
4,891,774✔
3215

3216
  // qDebug("vgId:%d add total %d dynamic tables to scan, tableSeq:%d, exist num:%" PRId64 ", operator status:%d",
3217
  //        pTaskInfo->id.vgId, num, pParam->tableSeq, (int64_t)taosArrayGetSize(pListInfo->pTableList),
3218
  //        pOperator->status);
3219

3220
  STableKeyInfo info = {.groupId = 0};
4,891,774✔
3221

3222
  int32_t tableIdx = 0;
4,891,774✔
3223
  taosHashClear(pListInfo->map);
4,891,774✔
3224
  taosArrayClear(pListInfo->pTableList);
4,891,774✔
3225

3226
  if (taosHashPut(pListInfo->map, &pUid, sizeof(uint64_t), &tableIdx, sizeof(int32_t))) {
4,891,774!
3227
    if (TSDB_CODE_DUP_KEY == terrno) {
×
3228
    } else {
3229
      return terrno;
×
3230
    }
3231
  }
3232

3233
  info.uid = pUid;
4,891,774✔
3234
  void* p = taosArrayPush(pListInfo->pTableList, &info);
4,891,774✔
3235
  if (p == NULL) {
4,891,774!
3236
    return terrno;
×
3237
  }
3238

3239
  qDebug("add dynamic table scan uid:%" PRIu64 ", %s", info.uid, GET_TASKID(pTaskInfo));
4,891,774✔
3240

3241
  return code;
4,891,774✔
3242
}
3243

3244
static int32_t doTagScanFromMetaEntryNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
7,126,843✔
3245
  int32_t       code = TSDB_CODE_SUCCESS;
7,126,843✔
3246
  int32_t       lino = 0;
7,126,843✔
3247
  STagScanInfo* pInfo = pOperator->info;
7,126,843✔
3248
  if (pOperator->pOperatorGetParam) {
7,126,843✔
3249
    pOperator->resultInfo.totalRows = 0;
4,891,774✔
3250
    pOperator->dynamicTask = true;
4,891,774✔
3251
    pInfo->curPos = 0;
4,891,774✔
3252
    code = createTagScanTableListInfoFromParam(pOperator);
4,891,774✔
3253
    freeOperatorParam(pOperator->pOperatorGetParam, OP_GET_PARAM);
4,891,774✔
3254
    pOperator->pOperatorGetParam = NULL;
4,891,774✔
3255
    QUERY_CHECK_CODE(code, lino, _end);
4,891,774!
3256

3257
    if (pOperator->status == OP_EXEC_DONE) {
4,891,774✔
3258
      pOperator->status = OP_OPENED;
2,435,164✔
3259
    }
3260
  }
3261

3262
  if (pOperator->status == OP_EXEC_DONE) {
7,126,843✔
3263
    (*ppRes) = NULL;
1,064,071✔
3264
    return code;
1,064,071✔
3265
  }
3266

3267
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
6,062,772✔
3268
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
6,062,772✔
3269

3270
  SExprInfo*   pExprInfo = &pOperator->exprSupp.pExprInfo[0];
6,062,772✔
3271
  SSDataBlock* pRes = pInfo->pRes;
6,062,772✔
3272
  blockDataCleanup(pRes);
6,062,772✔
3273

3274
  int32_t size = 0;
6,062,772✔
3275
  code = tableListGetSize(pInfo->pTableListInfo, &size);
6,062,772✔
3276
  QUERY_CHECK_CODE(code, lino, _end);
6,062,772!
3277

3278
  if (size == 0) {
6,062,772✔
3279
    setTaskStatus(pTaskInfo, TASK_COMPLETED);
106,927✔
3280
    (*ppRes) = NULL;
106,927✔
3281
    return code;
106,927✔
3282
  }
3283

3284
  SMetaReader mr = {0};
5,955,845✔
3285
  pAPI->metaReaderFn.initReader(&mr, pInfo->readHandle.vnode, META_READER_LOCK, &pAPI->metaFn);
5,955,845✔
3286
  pRes->info.rows = 0;
5,955,845✔
3287

3288
  while (pInfo->curPos < size && pRes->info.rows < pOperator->resultInfo.capacity) {
20,939,445!
3289
    code = doTagScanOneTable(pOperator, pRes, &mr, &pTaskInfo->storageAPI);
14,983,600✔
3290
    if (code != TSDB_CODE_OUT_OF_MEMORY && code != TSDB_CODE_QRY_REACH_QMEM_THRESHOLD &&
14,983,600!
3291
        code != TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED) {
3292
      // ignore other error
3293
      code = TSDB_CODE_SUCCESS;
14,982,600✔
3294
    }
3295
    QUERY_CHECK_CODE(code, lino, _end);
14,983,600!
3296

3297
    if (++pInfo->curPos >= size) {
14,983,600✔
3298
      setOperatorCompleted(pOperator);
5,955,845✔
3299
    }
3300
  }
3301

3302
  pAPI->metaReaderFn.clearReader(&mr);
5,957,117✔
3303
  bool bLimitReached = applyLimitOffset(&pInfo->limitInfo, pRes, pTaskInfo);
5,955,845✔
3304
  if (bLimitReached) {
5,955,845!
3305
    setOperatorCompleted(pOperator);
×
3306
  }
3307

3308
  // qDebug("QInfo:0x%" PRIx64 ", create tag values results completed, rows:%d", GET_TASKID(pRuntimeEnv), count);
3309
  if (pOperator->status == OP_EXEC_DONE) {
5,955,845!
3310
    setTaskStatus(pTaskInfo, TASK_COMPLETED);
5,955,845✔
3311
  }
3312

3313
  pOperator->resultInfo.totalRows += pRes->info.rows;
5,955,845✔
3314

3315
  (*ppRes) = (pRes->info.rows == 0) ? NULL : pInfo->pRes;
5,955,845!
3316
_end:
5,955,845✔
3317
  if (code != TSDB_CODE_SUCCESS) {
5,955,845!
3318
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3319
    pTaskInfo->code = code;
×
3320
    T_LONG_JMP(pTaskInfo->env, code);
×
3321
  }
3322
  return code;
5,955,845✔
3323
}
3324

3325
static SSDataBlock* doTagScanFromMetaEntry(SOperatorInfo* pOperator) {
×
3326
  SSDataBlock* pRes = NULL;
×
3327
  int32_t      code = doTagScanFromMetaEntryNext(pOperator, &pRes);
×
3328
  return pRes;
×
3329
}
3330

3331
static void destroyTagScanOperatorInfo(void* param) {
34,768,836✔
3332
  STagScanInfo* pInfo = (STagScanInfo*)param;
34,768,836✔
3333
  if (pInfo->pCtbCursor != NULL && pInfo->pStorageAPI != NULL) {
34,768,836!
3334
    pInfo->pStorageAPI->metaFn.closeCtbCursor(pInfo->pCtbCursor);
×
3335
  }
3336
  taosHashCleanup(pInfo->filterCtx.colHash);
34,780,250✔
3337
  taosArrayDestroy(pInfo->filterCtx.cInfoList);
34,733,135✔
3338
  taosArrayDestroy(pInfo->aFilterIdxs);
34,744,912✔
3339
  taosArrayDestroyEx(pInfo->aUidTags, tagScanFreeUidTag);
34,735,859✔
3340

3341
  blockDataDestroy(pInfo->pRes);
34,773,847✔
3342
  taosArrayDestroy(pInfo->matchInfo.pList);
34,768,380✔
3343
  tableListDestroy(pInfo->pTableListInfo);
34,749,774✔
3344

3345
  pInfo->pRes = NULL;
34,784,603✔
3346
  pInfo->pTableListInfo = NULL;
34,787,208✔
3347
  taosMemoryFreeClear(param);
34,790,045!
3348
}
34,782,597✔
3349

3350
int32_t createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pTagScanNode,
34,773,864✔
3351
                                  STableListInfo* pTableListInfo, SNode* pTagCond, SNode* pTagIndexCond,
3352
                                  SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
3353
  QRY_PARAM_CHECK(pOptrInfo);
34,773,864!
3354

3355
  int32_t         code = TSDB_CODE_SUCCESS;
34,787,937✔
3356
  int32_t         lino = 0;
34,787,937✔
3357
  SScanPhysiNode* pPhyNode = (SScanPhysiNode*)pTagScanNode;
34,787,937✔
3358
  STagScanInfo*   pInfo = taosMemoryCalloc(1, sizeof(STagScanInfo));
34,787,937!
3359
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
34,731,711!
3360
  if (pInfo == NULL || pOperator == NULL) {
34,735,001!
3361
    code = terrno;
×
3362
    goto _error;
×
3363
  }
3364

3365
  SDataBlockDescNode* pDescNode = pPhyNode->node.pOutputDataBlockDesc;
34,738,232✔
3366

3367
  int32_t    numOfExprs = 0;
34,740,142✔
3368
  SExprInfo* pExprInfo = NULL;
34,741,022✔
3369

3370
  code = createExprInfo(pPhyNode->pScanPseudoCols, NULL, &pExprInfo, &numOfExprs);
34,757,305✔
3371
  QUERY_CHECK_CODE(code, lino, _error);
34,793,475!
3372

3373
  code = initExprSupp(&pOperator->exprSupp, pExprInfo, numOfExprs, &pTaskInfo->storageAPI.functionStore);
34,793,475✔
3374
  QUERY_CHECK_CODE(code, lino, _error);
34,738,229!
3375

3376
  int32_t num = 0;
34,738,229✔
3377
  code = extractColMatchInfo(pPhyNode->pScanPseudoCols, pDescNode, &num, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo);
34,742,207✔
3378
  QUERY_CHECK_CODE(code, lino, _error);
34,779,612!
3379

3380
  pInfo->pTagCond = pTagCond;
34,779,612✔
3381
  pInfo->pTagIndexCond = pTagIndexCond;
34,791,760✔
3382
  pInfo->suid = pPhyNode->suid;
34,774,242✔
3383
  pInfo->pStorageAPI = &pTaskInfo->storageAPI;
34,776,641✔
3384

3385
  pInfo->pTableListInfo = pTableListInfo;
34,750,304✔
3386
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
34,727,626✔
3387
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
34,791,302!
3388

3389
  pInfo->readHandle = *pReadHandle;
34,728,398✔
3390
  pInfo->curPos = 0;
34,779,945✔
3391

3392
  initLimitInfo(pPhyNode->node.pLimit, pPhyNode->node.pSlimit, &pInfo->limitInfo);
34,713,811✔
3393
  setOperatorInfo(pOperator, "TagScanOperator", QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN, false, OP_NOT_OPENED, pInfo,
34,733,774✔
3394
                  pTaskInfo);
3395
  initResultSizeInfo(&pOperator->resultInfo, 4096);
34,724,364✔
3396
  code = blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
34,725,787✔
3397
  QUERY_CHECK_CODE(code, lino, _error);
34,793,950!
3398

3399
  if (pTagScanNode->onlyMetaCtbIdx) {
34,793,950!
3400
    pInfo->aUidTags = taosArrayInit(pOperator->resultInfo.capacity, sizeof(STUidTagInfo));
31,146,773✔
3401
    QUERY_CHECK_NULL(pInfo->aUidTags, code, lino, _error, terrno);
31,149,727!
3402

3403
    pInfo->aFilterIdxs = taosArrayInit(pOperator->resultInfo.capacity, sizeof(int32_t));
31,147,036✔
3404
    QUERY_CHECK_NULL(pInfo->aFilterIdxs, code, lino, _error, terrno);
31,149,727!
3405

3406
    pInfo->filterCtx.colHash =
31,139,206✔
3407
        taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK);
31,146,887✔
3408
    QUERY_CHECK_NULL(pInfo->filterCtx.colHash, code, lino, _error, terrno);
31,135,293!
3409

3410
    pInfo->filterCtx.cInfoList = taosArrayInit(4, sizeof(SColumnInfo));
31,137,348✔
3411
    QUERY_CHECK_NULL(pInfo->filterCtx.cInfoList, code, lino, _error, terrno);
31,140,983!
3412

3413
    if (pInfo->pTagCond != NULL) {
31,136,428✔
3414
      nodesRewriteExprPostOrder(&pTagCond, tagScanRewriteTagColumn, (void*)&pInfo->filterCtx);
10,821,296✔
3415
    }
3416
  }
3417
  __optr_fn_t tagScanNextFn = (pTagScanNode->onlyMetaCtbIdx) ? doTagScanFromCtbIdxNext : doTagScanFromMetaEntryNext;
34,791,251!
3418
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, tagScanNextFn, NULL, destroyTagScanOperatorInfo,
34,798,330✔
3419
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
3420
  *pOptrInfo = pOperator;
34,785,074✔
3421
  return code;
34,786,071✔
3422

3423
_error:
×
3424
  if (pInfo) {
×
3425
    pInfo->pTableListInfo = NULL;
×
3426
  }
3427

3428
  if (pInfo != NULL) destroyTagScanOperatorInfo(pInfo);
×
3429
  if (pOperator != NULL) {
×
3430
    pOperator->info = NULL;
×
3431
    destroyOperator(pOperator);
×
3432
  }
3433
  return code;
×
3434
}
3435

3436
// table merge scan operator
3437

3438
static int32_t subTblRowCompareTsFn(const void* pLeft, const void* pRight, void* param) {
1,250,104,322✔
3439
  int32_t                 left = *(int32_t*)pLeft;
1,250,104,322✔
3440
  int32_t                 right = *(int32_t*)pRight;
1,250,107,264✔
3441
  STmsSubTablesMergeInfo* pInfo = (STmsSubTablesMergeInfo*)param;
1,250,101,834✔
3442

3443
  int32_t leftIdx = pInfo->aInputs[left].rowIdx;
1,250,101,834✔
3444
  int32_t rightIdx = pInfo->aInputs[right].rowIdx;
1,250,108,488✔
3445

3446
  if (leftIdx == -1) {
1,250,072,752✔
3447
    return 1;
1,070,793,712✔
3448
  } else if (rightIdx == -1) {
179,279,040✔
3449
    return -1;
1,775,040✔
3450
  }
3451

3452
  int64_t leftTs = pInfo->aInputs[left].aTs[leftIdx];
177,504,000✔
3453
  int64_t rightTs = pInfo->aInputs[right].aTs[rightIdx];
177,504,000✔
3454
  int32_t ret = leftTs > rightTs ? 1 : ((leftTs < rightTs) ? -1 : 0);
177,504,000!
3455
  if (pInfo->pTsOrderInfo->order == TSDB_ORDER_DESC) {
177,504,000!
3456
    ret = -1 * ret;
×
3457
  }
3458
  return ret;
177,504,000✔
3459
}
3460

3461
static int32_t subTblRowCompareTsPkFn(const void* pLeft, const void* pRight, void* param) {
×
3462
  int32_t                 left = *(int32_t*)pLeft;
×
3463
  int32_t                 right = *(int32_t*)pRight;
×
3464
  STmsSubTablesMergeInfo* pInfo = (STmsSubTablesMergeInfo*)param;
×
3465

3466
  int32_t leftIdx = pInfo->aInputs[left].rowIdx;
×
3467
  int32_t rightIdx = pInfo->aInputs[right].rowIdx;
×
3468

3469
  if (leftIdx == -1) {
×
3470
    return 1;
×
3471
  } else if (rightIdx == -1) {
×
3472
    return -1;
×
3473
  }
3474

3475
  int64_t leftTs = pInfo->aInputs[left].aTs[leftIdx];
×
3476
  int64_t rightTs = pInfo->aInputs[right].aTs[rightIdx];
×
3477
  int32_t ret = leftTs > rightTs ? 1 : ((leftTs < rightTs) ? -1 : 0);
×
3478
  if (pInfo->pTsOrderInfo->order == TSDB_ORDER_DESC) {
×
3479
    ret = -1 * ret;
×
3480
  }
3481
  if (ret == 0 && pInfo->pPkOrderInfo) {
×
3482
    ret = tsortComparBlockCell(pInfo->aInputs[left].pInputBlock, pInfo->aInputs[right].pInputBlock, leftIdx, rightIdx,
×
3483
                               pInfo->pPkOrderInfo);
×
3484
  }
3485
  return ret;
×
3486
}
3487

3488
int32_t dumpQueryTableCond(const SQueryTableDataCond* src, SQueryTableDataCond* dst) {
15,891,897✔
3489
  int32_t code = TSDB_CODE_SUCCESS;
15,891,897✔
3490
  int32_t lino = 0;
15,891,897✔
3491
  memcpy((void*)dst, (void*)src, sizeof(SQueryTableDataCond));
15,891,897!
3492
  dst->colList = taosMemoryCalloc(src->numOfCols, sizeof(SColumnInfo));
15,891,897!
3493
  QUERY_CHECK_NULL(dst->colList, code, lino, _end, terrno);
15,885,108!
3494
  for (int i = 0; i < src->numOfCols; i++) {
53,428,467✔
3495
    dst->colList[i] = src->colList[i];
37,598,960✔
3496
  }
3497

3498
_end:
15,874,954✔
3499
  if (code != TSDB_CODE_SUCCESS) {
15,874,954!
3500
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3501
  }
3502
  return code;
15,852,919✔
3503
}
3504

3505
static int32_t fetchNextSubTableBlockFromReader(SOperatorInfo* pOperator, STmsSubTableInput* pInput,
23,844,286✔
3506
                                                bool* pSubTableHasBlock) {
3507
  int32_t code = 0;
23,844,286✔
3508

3509
  STableMergeScanInfo*    pInfo = pOperator->info;
23,844,286✔
3510
  SReadHandle*            pHandle = &pInfo->base.readHandle;
23,842,618✔
3511
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
23,844,912✔
3512
  SExecTaskInfo*          pTaskInfo = pOperator->pTaskInfo;
23,832,721✔
3513
  const SStorageAPI*      pAPI = &pTaskInfo->storageAPI;
23,843,974✔
3514

3515
  blockDataCleanup(pInput->pReaderBlock);
23,850,169✔
3516
  if (!pInput->bInMemReader) {
23,844,736!
3517
    code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInput->tblCond, pInput->pKeyInfo, 1, pInput->pReaderBlock,
23,950,819✔
3518
                                         (void**)&pInput->pReader, GET_TASKID(pTaskInfo), NULL);
11,983,901✔
3519
    if (code != 0) {
11,980,969!
3520
      return code;
×
3521
    }
3522
  }
3523

3524
  pInfo->base.dataReader = pInput->pReader;
23,854,957✔
3525

3526
  while (true) {
31,236✔
3527
    bool hasNext = false;
23,862,274✔
3528
    code = pAPI->tsdReader.tsdNextDataBlock(pInfo->base.dataReader, &hasNext);
23,869,369✔
3529
    if (code != 0) {
23,894,366!
3530
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->base.dataReader);
×
3531
      pInfo->base.dataReader = NULL;
×
3532
      return code;
×
3533
    }
3534

3535
    if (!hasNext || isTaskKilled(pTaskInfo)) {
23,894,366!
3536
      if (isTaskKilled(pTaskInfo)) {
15,927,524!
3537
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->base.dataReader);
×
3538
        pInfo->base.dataReader = NULL;
×
3539
        return code;
×
3540
      }
3541

3542
      *pSubTableHasBlock = false;
15,926,441✔
3543
      break;
15,926,438✔
3544
    }
3545

3546
    if (pInput->tblCond.order == TSDB_ORDER_ASC) {
7,966,842✔
3547
      pInput->tblCond.twindows.skey = pInput->pReaderBlock->info.window.ekey + 1;
7,814,512✔
3548
    } else {
3549
      pInput->tblCond.twindows.ekey = pInput->pReaderBlock->info.window.skey - 1;
152,330✔
3550
    }
3551

3552
    uint32_t status = 0;
7,966,842✔
3553
    code = loadDataBlock(pOperator, &pInfo->base, pInput->pReaderBlock, &status);
7,966,076✔
3554
    if (code != 0) {
7,966,842!
3555
      pInfo->base.dataReader = NULL;
×
3556
      return code;
×
3557
    }
3558

3559
    if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
7,966,842!
3560
      *pSubTableHasBlock = false;
×
3561
      break;
×
3562
    }
3563
    if (status == FUNC_DATA_REQUIRED_FILTEROUT || pInput->pReaderBlock->info.rows == 0) {
7,966,842✔
3564
      continue;
31,236✔
3565
    }
3566

3567
    *pSubTableHasBlock = true;
7,934,523✔
3568
    break;
7,933,437✔
3569
  }
3570

3571
  if (*pSubTableHasBlock) {
23,860,961!
3572
    pInput->pReaderBlock->info.id.groupId =
15,869,040✔
3573
        tableListGetTableGroupId(pInfo->base.pTableListInfo, pInput->pReaderBlock->info.id.uid);
15,867,960✔
3574
    pOperator->resultInfo.totalRows += pInput->pReaderBlock->info.rows;
7,934,520✔
3575
  }
3576
  if (!pInput->bInMemReader || !*pSubTableHasBlock) {
23,863,130!
3577
    pAPI->tsdReader.tsdReaderClose(pInput->pReader);
17,940,272✔
3578
    pInput->pReader = NULL;
17,934,082✔
3579
  }
3580

3581
  pInfo->base.dataReader = NULL;
23,856,937✔
3582
  return TSDB_CODE_SUCCESS;
23,855,851✔
3583
}
3584

3585
static int32_t setGroupStartEndIndex(STableMergeScanInfo* pInfo) {
9,941,718✔
3586
  pInfo->bGroupProcessed = false;
9,941,718✔
3587

3588
  int32_t numOfTables = 0;
9,951,935✔
3589
  int32_t code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
9,882,653✔
3590
  if (code != TSDB_CODE_SUCCESS) {
9,838,998!
3591
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
3592
    return code;
×
3593
  }
3594

3595
  int32_t i = pInfo->tableStartIndex + 1;
9,838,998✔
3596
  for (; i < numOfTables; ++i) {
15,812,803✔
3597
    STableKeyInfo* tableKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i);
6,250,984✔
3598
    if (!tableKeyInfo) {
6,253,156!
3599
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3600
      return terrno;
×
3601
    }
3602
    if (tableKeyInfo->groupId != pInfo->groupId) {
6,253,156✔
3603
      break;
312,824✔
3604
    }
3605
  }
3606
  pInfo->tableEndIndex = i - 1;
9,874,643✔
3607
  return TSDB_CODE_SUCCESS;
9,958,339✔
3608
}
3609

3610
static int32_t openSubTablesMergeSort(STmsSubTablesMergeInfo* pSubTblsInfo) {
9,979,771✔
3611
  for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
25,901,868✔
3612
    STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
15,926,438✔
3613
    if (pInput->rowIdx == -1) {
15,918,722✔
3614
      continue;
7,989,300✔
3615
    }
3616

3617
    if (pInput->type == SUB_TABLE_MEM_BLOCK) {
7,935,606✔
3618
      pInput->rowIdx = 0;
7,931,582✔
3619
      pInput->pageIdx = -1;
7,933,754✔
3620
    }
3621

3622
    pInput->pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
7,939,630!
3623
    SColumnInfoData* col = taosArrayGet(pInput->pInputBlock->pDataBlock, pSubTblsInfo->pTsOrderInfo->slotId);
7,934,520✔
3624
    if (!col) {
7,930,816!
3625
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3626
      return terrno;
×
3627
    }
3628
    pInput->aTs = (int64_t*)col->pData;
7,930,816✔
3629
  }
3630

3631
  __merge_compare_fn_t mergeCompareFn = (!pSubTblsInfo->pPkOrderInfo) ? subTblRowCompareTsFn : subTblRowCompareTsPkFn;
9,978,682!
3632
  return tMergeTreeCreate(&pSubTblsInfo->pTree, pSubTblsInfo->numSubTables, pSubTblsInfo, mergeCompareFn);
9,979,768✔
3633
}
3634

3635
static int32_t initSubTablesMergeInfo(STableMergeScanInfo* pInfo) {
9,947,537✔
3636
  int32_t code = setGroupStartEndIndex(pInfo);
9,947,537✔
3637
  if (code != TSDB_CODE_SUCCESS) {
9,937,502!
3638
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
3639
    return code;
×
3640
  }
3641
  STmsSubTablesMergeInfo* pSubTblsInfo = taosMemoryCalloc(1, sizeof(STmsSubTablesMergeInfo));
9,937,502!
3642
  if (pSubTblsInfo == NULL) {
9,916,505!
3643
    return terrno;
×
3644
  }
3645
  pSubTblsInfo->pTsOrderInfo = taosArrayGet(pInfo->pSortInfo, 0);
9,916,505✔
3646
  if (!pSubTblsInfo->pTsOrderInfo) {
9,938,262!
3647
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3648
    return terrno;
×
3649
  }
3650
  if (taosArrayGetSize(pInfo->pSortInfo) == 2) {
9,907,675!
3651
    pSubTblsInfo->pPkOrderInfo = taosArrayGet(pInfo->pSortInfo, 1);
×
3652
    if (!pSubTblsInfo->pPkOrderInfo) {
×
3653
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3654
      return terrno;
×
3655
    }
3656
  } else {
3657
    pSubTblsInfo->pPkOrderInfo = NULL;
9,874,603✔
3658
  }
3659
  pSubTblsInfo->numSubTables = pInfo->tableEndIndex - pInfo->tableStartIndex + 1;
9,957,619✔
3660
  pSubTblsInfo->aInputs = taosMemoryCalloc(pSubTblsInfo->numSubTables, sizeof(STmsSubTableInput));
9,853,480!
3661
  if (pSubTblsInfo->aInputs == NULL) {
9,890,020!
3662
    taosMemoryFree(pSubTblsInfo);
×
3663
    return terrno;
×
3664
  }
3665
  int32_t bufPageSize = pInfo->bufPageSize;
9,910,915✔
3666
  int32_t inMemSize = (pSubTblsInfo->numSubTables - pSubTblsInfo->numTableBlocksInMem) * bufPageSize;
9,948,037✔
3667
  code = createDiskbasedBuf(&pSubTblsInfo->pBlocksBuf, pInfo->bufPageSize, inMemSize, "blocksExternalBuf", tsTempDir);
9,957,875✔
3668
  if (code != TSDB_CODE_SUCCESS) {
9,894,517!
3669
    taosMemoryFree(pSubTblsInfo->aInputs);
×
3670
    taosMemoryFree(pSubTblsInfo);
×
3671
    return code;
×
3672
  }
3673
  pSubTblsInfo->numTableBlocksInMem = pSubTblsInfo->numSubTables;
9,894,517✔
3674
  pSubTblsInfo->numInMemReaders = pSubTblsInfo->numSubTables;
9,962,531✔
3675

3676
  pInfo->pSubTablesMergeInfo = pSubTblsInfo;
9,921,644✔
3677
  return TSDB_CODE_SUCCESS;
9,879,571✔
3678
}
3679

3680
static int32_t initSubTableInputs(SOperatorInfo* pOperator, STableMergeScanInfo* pInfo) {
9,930,293✔
3681
  int32_t        code = TSDB_CODE_SUCCESS;
9,930,293✔
3682
  int32_t        lino = 0;
9,930,293✔
3683
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
9,930,293✔
3684
  SReadHandle*   pHandle = &pInfo->base.readHandle;
9,926,454✔
3685
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
9,942,037✔
3686

3687
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
9,951,414✔
3688

3689
  for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
25,820,953✔
3690
    STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
15,852,761✔
3691
    pInput->type = SUB_TABLE_MEM_BLOCK;
15,842,892✔
3692

3693
    code = dumpQueryTableCond(&pInfo->base.cond, &pInput->tblCond);
15,903,965✔
3694
    QUERY_CHECK_CODE(code, lino, _end);
15,853,689!
3695

3696
    code = createOneDataBlock(pInfo->pResBlock, false, &pInput->pReaderBlock);
15,853,689✔
3697
    QUERY_CHECK_CODE(code, lino, _end);
15,922,283!
3698

3699
    code = createOneDataBlock(pInfo->pResBlock, false, &pInput->pPageBlock);
15,922,283✔
3700
    QUERY_CHECK_CODE(code, lino, _end);
15,927,524!
3701

3702
    STableKeyInfo* keyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i + pInfo->tableStartIndex);
15,927,524✔
3703
    pInput->pKeyInfo = keyInfo;
15,923,052✔
3704

3705
    if (isTaskKilled(pTaskInfo)) {
15,916,423!
3706
      T_LONG_JMP(pTaskInfo->env, pTaskInfo->code);
×
3707
    }
3708

3709
    if (i + 1 < pSubTblsInfo->numInMemReaders) {
15,888,192✔
3710
      code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInput->tblCond, keyInfo, 1, pInput->pReaderBlock,
11,873,378✔
3711
                                           (void**)&pInput->pReader, GET_TASKID(pTaskInfo), NULL);
5,943,728✔
3712
      QUERY_CHECK_CODE(code, lino, _end);
5,935,218!
3713
      pInput->bInMemReader = true;
5,935,218✔
3714
    } else {
3715
      pInput->pReader = NULL;
9,970,523✔
3716
      pInput->bInMemReader = false;
9,968,984✔
3717
    }
3718
    bool hasNext = true;
15,906,684✔
3719
    code = fetchNextSubTableBlockFromReader(pOperator, pInput, &hasNext);
15,893,365✔
3720
    QUERY_CHECK_CODE(code, lino, _end);
15,923,503!
3721
    if (!hasNext) {
15,923,503!
3722
      pInput->rowIdx = -1;
7,987,897✔
3723
      ++pSubTblsInfo->numSubTablesCompleted;
7,990,832✔
3724
      continue;
7,988,217✔
3725
    } else {
3726
      pInput->rowIdx = 0;
7,935,606✔
3727
      pInput->pageIdx = -1;
7,935,606✔
3728
    }
3729
  }
3730

3731
_end:
9,976,833✔
3732
  if (code != TSDB_CODE_SUCCESS) {
9,974,664!
3733
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3734
  }
3735
  return code;
9,974,981✔
3736
}
3737

3738
static void adjustSubTableFromMemBlock(SOperatorInfo* pOperatorInfo, STmsSubTablesMergeInfo* pSubTblsInfo) {
7,935,606✔
3739
  int32_t              code = TSDB_CODE_SUCCESS;
7,935,606✔
3740
  int32_t              lino = 0;
7,935,606✔
3741
  SExecTaskInfo*       pTaskInfo = pOperatorInfo->pTaskInfo;
7,935,606✔
3742
  STableMergeScanInfo* pInfo = pOperatorInfo->info;
7,935,606✔
3743
  STmsSubTableInput*   pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
7,935,606✔
3744
  bool                 hasNext = true;
7,935,606✔
3745
  code = fetchNextSubTableBlockFromReader(pOperatorInfo, pInput, &hasNext);
7,935,606✔
3746
  QUERY_CHECK_CODE(code, lino, _end);
7,935,606!
3747

3748
  if (!hasNext) {
7,935,606!
3749
    pInput->rowIdx = -1;
7,935,606✔
3750
    ++pSubTblsInfo->numSubTablesCompleted;
7,934,520✔
3751
  } else {
3752
    pInput->rowIdx = 0;
×
3753
  }
3754

3755
_end:
7,935,606✔
3756
  if (code != TSDB_CODE_SUCCESS) {
7,935,606!
3757
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3758
    pTaskInfo->code = code;
×
3759
    T_LONG_JMP(pTaskInfo->env, code);
×
3760
  }
3761
}
7,934,520✔
3762

3763
static int32_t adjustSubTableForNextRow(SOperatorInfo* pOperatorInfo, STmsSubTablesMergeInfo* pSubTblsInfo) {
1,445,011,055✔
3764
  STableMergeScanInfo* pInfo = pOperatorInfo->info;
1,445,011,055✔
3765
  STmsSubTableInput*   pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
1,445,012,583✔
3766

3767
  SSDataBlock* pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
1,444,999,763!
3768
  if (pInput->rowIdx < pInputBlock->info.rows - 1) {
1,445,093,049✔
3769
    ++pInput->rowIdx;
1,437,141,231✔
3770
  } else if (pInput->rowIdx == pInputBlock->info.rows - 1) {
7,935,606!
3771
    if (pInput->type == SUB_TABLE_MEM_BLOCK) {
7,935,606!
3772
      adjustSubTableFromMemBlock(pOperatorInfo, pSubTblsInfo);
7,935,606✔
3773
    }
3774
    if (pInput->rowIdx != -1) {
7,934,520!
3775
      SColumnInfoData* col = taosArrayGet(pInputBlock->pDataBlock, pSubTblsInfo->pTsOrderInfo->slotId);
×
3776
      if (!col) {
×
3777
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3778
        return terrno;
×
3779
      }
3780
      pInput->pInputBlock = pInputBlock;
×
3781
      pInput->aTs = (int64_t*)col->pData;
×
3782
    }
3783
  }
3784

3785
  return tMergeTreeAdjust(pSubTblsInfo->pTree, tMergeTreeGetAdjustIndex(pSubTblsInfo->pTree));
1,445,076,683✔
3786
}
3787

3788
static int32_t appendChosenRowToDataBlock(STmsSubTablesMergeInfo* pSubTblsInfo, SSDataBlock* pBlock) {
1,444,587,175✔
3789
  int32_t            code = TSDB_CODE_SUCCESS;
1,444,587,175✔
3790
  int32_t            lino = 0;
1,444,587,175✔
3791
  STmsSubTableInput* pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
1,444,587,175✔
3792
  SSDataBlock*       pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
1,444,696,531!
3793

3794
  for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); ++i) {
2,147,483,647✔
3795
    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
3796
    QUERY_CHECK_NULL(pColInfo, code, lino, _end, terrno);
2,147,483,647!
3797

3798
    SColumnInfoData* pSrcColInfo = taosArrayGet(pInputBlock->pDataBlock, i);
2,147,483,647✔
3799
    QUERY_CHECK_NULL(pSrcColInfo, code, lino, _end, terrno);
2,147,483,647!
3800
    bool isNull = colDataIsNull(pSrcColInfo, pInputBlock->info.rows, pInput->rowIdx, NULL);
2,147,483,647!
3801

3802
    if (isNull) {
2,147,483,647✔
3803
      code = colDataSetVal(pColInfo, pBlock->info.rows, NULL, true);
404,075,052✔
3804
      QUERY_CHECK_CODE(code, lino, _end);
404,067,450!
3805
    } else {
3806
      if (pSrcColInfo->pData != NULL) {
2,147,483,647!
3807
        char* pData = colDataGetData(pSrcColInfo, pInput->rowIdx);
2,147,483,647!
3808
        code = colDataSetVal(pColInfo, pBlock->info.rows, pData, false);
2,147,483,647✔
3809
        QUERY_CHECK_CODE(code, lino, _end);
2,147,483,647!
3810
      }
3811
    }
3812
  }
3813
  pBlock->info.dataLoad = 1;
1,445,017,507✔
3814
  pBlock->info.scanFlag = pInputBlock->info.scanFlag;
1,445,018,593✔
3815
  pBlock->info.rows += 1;
1,445,019,820✔
3816

3817
_end:
1,445,035,119✔
3818
  if (code != TSDB_CODE_SUCCESS) {
1,445,035,119!
3819
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3820
  }
3821
  return code;
1,445,026,181✔
3822
}
3823

3824
static int32_t getSubTablesSortedBlock(SOperatorInfo* pOperator, SSDataBlock* pBlock, int32_t capacity,
16,138,165✔
3825
                                       SSDataBlock** pResBlock) {
3826
  int32_t                 code = TSDB_CODE_SUCCESS;
16,138,165✔
3827
  int32_t                 lino = 0;
16,138,165✔
3828
  STableMergeScanInfo*    pInfo = pOperator->info;
16,138,165✔
3829
  SExecTaskInfo*          pTaskInfo = pOperator->pTaskInfo;
16,139,564✔
3830
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
16,139,571✔
3831
  bool                    finished = false;
16,136,629✔
3832

3833
  QRY_PARAM_CHECK(pResBlock);
16,136,629!
3834

3835
  blockDataCleanup(pBlock);
16,126,287✔
3836

3837
  while (true) {
×
3838
    while (true) {
3839
      if (pSubTblsInfo->numSubTablesCompleted >= pSubTblsInfo->numSubTables) {
1,460,745,556✔
3840
        finished = true;
16,141,420✔
3841
        break;
16,141,420✔
3842
      }
3843

3844
      code = appendChosenRowToDataBlock(pSubTblsInfo, pBlock);
1,444,605,659✔
3845
      QUERY_CHECK_CODE(code, lino, _end);
1,445,022,609!
3846

3847
      code = adjustSubTableForNextRow(pOperator, pSubTblsInfo);
1,445,022,609✔
3848
      QUERY_CHECK_CODE(code, lino, _end);
1,444,608,755!
3849

3850
      if (pBlock->info.rows >= capacity) {
1,444,608,755!
3851
        break;
×
3852
      }
3853
    }
3854

3855
    if (isTaskKilled(pTaskInfo)) {
16,141,420!
3856
      return pTaskInfo->code;
×
3857
    }
3858

3859
    bool limitReached = applyLimitOffset(&pInfo->limitInfo, pBlock, pTaskInfo);
16,139,254✔
3860
    if (finished || limitReached || pBlock->info.rows > 0) {
16,136,636!
3861
      break;
3862
    }
3863
  }
3864

3865
  if (pBlock->info.rows > 0) {
16,136,636✔
3866
    *pResBlock = pBlock;
6,159,480✔
3867
  }
3868

3869
_end:
9,978,685✔
3870
  if (code != TSDB_CODE_SUCCESS) {
16,138,165!
3871
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3872
    pTaskInfo->code = code;
×
3873
  }
3874
  return code;
16,137,399✔
3875
}
3876

3877
static int32_t startSubTablesTableMergeScan(SOperatorInfo* pOperator) {
9,947,397✔
3878
  int32_t              code = TSDB_CODE_SUCCESS;
9,947,397✔
3879
  int32_t              lino = 0;
9,947,397✔
3880
  STableMergeScanInfo* pInfo = pOperator->info;
9,947,397✔
3881

3882
  code = initSubTablesMergeInfo(pInfo);
9,974,850✔
3883
  QUERY_CHECK_CODE(code, lino, _end);
9,871,727!
3884

3885
  code = initSubTableInputs(pOperator, pInfo);
9,871,727✔
3886
  QUERY_CHECK_CODE(code, lino, _end);
9,977,919!
3887

3888
  code = openSubTablesMergeSort(pInfo->pSubTablesMergeInfo);
9,977,919✔
3889
  QUERY_CHECK_CODE(code, lino, _end);
9,978,685!
3890

3891
_end:
9,978,685✔
3892
  if (code != TSDB_CODE_SUCCESS) {
9,978,685!
3893
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3894
  }
3895
  return code;
9,979,771✔
3896
}
3897

3898
static void stopSubTablesTableMergeScan(STableMergeScanInfo* pInfo) {
164,601,073✔
3899
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
164,601,073✔
3900
  if (pSubTblsInfo != NULL) {
164,608,406✔
3901
    tMergeTreeDestroy(&pSubTblsInfo->pTree);
9,977,919✔
3902

3903
    for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
25,900,348✔
3904
      STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
15,925,355✔
3905
      taosMemoryFree(pInput->tblCond.colList);
15,915,027!
3906
      blockDataDestroy(pInput->pReaderBlock);
15,925,992✔
3907
      blockDataDestroy(pInput->pPageBlock);
15,925,358✔
3908
      taosArrayDestroy(pInput->aBlockPages);
15,923,506✔
3909
      pInfo->base.readerAPI.tsdReaderClose(pInput->pReader);
15,925,675✔
3910
      pInput->pReader = NULL;
15,924,909✔
3911
    }
3912

3913
    destroyDiskbasedBuf(pSubTblsInfo->pBlocksBuf);
9,978,239✔
3914
    taosMemoryFree(pSubTblsInfo->aInputs);
9,975,307!
3915

3916
    taosMemoryFree(pSubTblsInfo);
9,972,821!
3917
    pInfo->pSubTablesMergeInfo = NULL;
9,978,239✔
3918

3919
    // taosMemoryTrim(0);
3920
  }
3921
}
164,608,726✔
3922

3923
int32_t doTableMergeScanParaSubTablesNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
15,996,277✔
3924
  QRY_PARAM_CHECK(ppRes);
15,996,277!
3925

3926
  int32_t lino = 0;
15,990,470✔
3927
  int32_t tableListSize = 0;
15,990,470✔
3928
  int64_t st = taosGetTimestampUs();
15,971,604✔
3929

3930
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
15,971,604✔
3931
  STableMergeScanInfo* pInfo = pOperator->info;
15,991,803✔
3932

3933
  if (pOperator->status == OP_EXEC_DONE) {
15,996,844!
3934
    return TSDB_CODE_SUCCESS;
×
3935
  }
3936

3937
  int32_t code = pOperator->fpSet._openFn(pOperator);
15,934,737✔
3938
  QUERY_CHECK_CODE(code, lino, _end);
15,985,806!
3939

3940
  code = tableListGetSize(pInfo->base.pTableListInfo, &tableListSize);
15,985,806✔
3941
  QUERY_CHECK_CODE(code, lino, _end);
15,981,643!
3942

3943
  if (!pInfo->hasGroupId) {
15,981,643!
3944
    pInfo->hasGroupId = true;
9,827,991✔
3945

3946
    if (tableListSize == 0) {
9,765,911✔
3947
      setOperatorCompleted(pOperator);
202,856✔
3948
      (*ppRes) = NULL;
201,000✔
3949
      return code;
201,000✔
3950
    }
3951

3952
    pInfo->tableStartIndex = 0;
9,563,055✔
3953
    STableKeyInfo* pTmpGpId = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
9,570,767✔
3954
    QUERY_CHECK_NULL(pTmpGpId, code, lino, _end, terrno);
9,579,882!
3955
    pInfo->groupId = pTmpGpId->groupId;
9,579,882✔
3956
    code = startSubTablesTableMergeScan(pOperator);
9,635,526✔
3957
    QUERY_CHECK_CODE(code, lino, _end);
9,663,239!
3958
  }
3959

3960
  SSDataBlock* pBlock = NULL;
15,819,834✔
3961
  while (pInfo->tableStartIndex < tableListSize) {
16,138,485✔
3962
    if (isTaskKilled(pTaskInfo)) {
16,138,485!
3963
      break;
×
3964
    }
3965

3966
    code = getSubTablesSortedBlock(pOperator, pInfo->pResBlock, pOperator->resultInfo.capacity, &pBlock);
16,132,931✔
3967
    QUERY_CHECK_CODE(code, lino, _end);
16,137,399!
3968

3969
    if (pBlock == NULL && !pInfo->bGroupProcessed && pInfo->needCountEmptyTable) {
16,137,399!
3970
      STableKeyInfo* tbInfo = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
×
3971
      QUERY_CHECK_NULL(tbInfo, code, lino, _end, terrno);
×
3972

3973
      pBlock = getOneRowResultBlock(pTaskInfo, &pInfo->base, pInfo->pResBlock, tbInfo);
×
3974
    }
3975

3976
    if (pBlock != NULL) {
16,138,165✔
3977
      pBlock->info.id.groupId = pInfo->groupId;
6,159,480✔
3978
      pOperator->resultInfo.totalRows += pBlock->info.rows;
6,160,566✔
3979
      pInfo->bGroupProcessed = true;
6,160,566✔
3980
      break;
6,160,566✔
3981
    } else {
3982
      // Data of this group are all dumped, let's try the next group
3983
      stopSubTablesTableMergeScan(pInfo);
9,978,685✔
3984
      if (pInfo->tableEndIndex >= tableListSize - 1) {
9,977,922✔
3985
        setOperatorCompleted(pOperator);
9,655,975✔
3986
        break;
9,657,510✔
3987
      }
3988

3989
      pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
314,680✔
3990
      STableKeyInfo* pTmpGpId = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
314,680✔
3991
      QUERY_CHECK_NULL(pTmpGpId, code, lino, _end, terrno);
314,680!
3992

3993
      pInfo->groupId = pTmpGpId->groupId;
314,680✔
3994
      code = startSubTablesTableMergeScan(pOperator);
314,680✔
3995
      QUERY_CHECK_CODE(code, lino, _end);
314,680!
3996
      resetLimitInfoForNextGroup(&pInfo->limitInfo);
314,680✔
3997
    }
3998
  }
3999

4000
  pOperator->cost.totalCost += (taosGetTimestampUs() - st) / 1000.0;
15,821,325✔
4001

4002
_end:
15,820,110✔
4003
  if (code != TSDB_CODE_SUCCESS) {
15,824,571!
4004
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4005
    pTaskInfo->code = code;
×
4006
    T_LONG_JMP(pTaskInfo->env, code);
×
4007
  } else {
4008
    (*ppRes) = pBlock;
15,824,571✔
4009
  }
4010

4011
  return code;
15,820,556✔
4012
}
4013

4014
static void tableMergeScanDoSkipTable(uint64_t uid, void* pTableMergeOpInfo) {
28,834,126✔
4015
  int32_t              code = TSDB_CODE_SUCCESS;
28,834,126✔
4016
  int32_t              lino = 0;
28,834,126✔
4017
  SOperatorInfo*       pOperator = (SOperatorInfo*)pTableMergeOpInfo;
28,834,126✔
4018
  STableMergeScanInfo* pInfo = pOperator->info;
28,834,126✔
4019
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
28,834,126✔
4020

4021
  if (pInfo->mSkipTables == NULL) {
28,834,126✔
4022
    pInfo->mSkipTables = taosHashInit(pInfo->tableEndIndex - pInfo->tableStartIndex + 1,
2,574,134✔
4023
                                      taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_NO_LOCK);
4024
    QUERY_CHECK_NULL(pInfo->mSkipTables, code, lino, _end, terrno);
2,574,134!
4025
  }
4026
  int bSkip = 1;
28,834,126✔
4027
  if (pInfo->mSkipTables != NULL) {
28,834,126!
4028
    code = taosHashPut(pInfo->mSkipTables, &uid, sizeof(uid), &bSkip, sizeof(bSkip));
28,834,126✔
4029
    if (code == TSDB_CODE_DUP_KEY) {
28,834,126!
4030
      code = TSDB_CODE_SUCCESS;
×
4031
    }
4032
    QUERY_CHECK_CODE(code, lino, _end);
28,834,126!
4033
  }
4034

4035
_end:
28,834,126✔
4036
  if (code != TSDB_CODE_SUCCESS) {
28,834,126!
4037
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4038
    pTaskInfo->code = code;
×
4039
    T_LONG_JMP(pTaskInfo->env, code);
×
4040
  }
4041
}
28,834,126✔
4042

4043
static int32_t doGetBlockForTableMergeScan(SOperatorInfo* pOperator, bool* pFinished, bool* pSkipped) {
745,220,206✔
4044
  STableMergeScanInfo* pInfo = pOperator->info;
745,220,206✔
4045
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
745,288,096✔
4046
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
745,259,394✔
4047
  SSDataBlock*         pBlock = pInfo->pReaderBlock;
745,305,317✔
4048
  int32_t              code = 0;
745,257,799✔
4049
  bool                 hasNext = false;
745,257,799✔
4050
  STsdbReader*         reader = pInfo->base.dataReader;
745,256,730✔
4051

4052
  code = pAPI->tsdReader.tsdNextDataBlock(reader, &hasNext);
745,247,157✔
4053
  if (code != 0) {
745,221,109!
4054
    pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
×
4055
    qError("table merge scan fetch next data block error code: %d, %s", code, GET_TASKID(pTaskInfo));
×
4056
    pTaskInfo->code = code;
×
4057
    return code;
×
4058
  }
4059

4060
  if (!hasNext || isTaskKilled(pTaskInfo)) {
745,221,109!
4061
    if (isTaskKilled(pTaskInfo)) {
171,893,535✔
4062
      qInfo("table merge scan fetch next data block found task killed. %s", GET_TASKID(pTaskInfo));
1,221!
4063
      pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
1,221✔
4064
    }
4065
    *pFinished = true;
171,750,282✔
4066
    return code;
171,747,784✔
4067
  }
4068

4069
  uint32_t status = 0;
573,510,057✔
4070
  code = loadDataBlock(pOperator, &pInfo->base, pBlock, &status);
573,508,427✔
4071

4072
  if (code != TSDB_CODE_SUCCESS) {
573,411,280!
4073
    qInfo("table merge scan load datablock code %d, %s", code, GET_TASKID(pTaskInfo));
×
4074
    pTaskInfo->code = code;
×
4075
    return code;
×
4076
  }
4077

4078
  if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
573,411,280!
4079
    *pFinished = true;
×
4080
    return code;
×
4081
  }
4082

4083
  // current block is filter out according to filter condition, continue load the next block
4084
  if (status == FUNC_DATA_REQUIRED_FILTEROUT || pBlock->info.rows == 0) {
573,411,280!
4085
    *pSkipped = true;
15,984,093✔
4086
    return code;
16,148,932✔
4087
  }
4088

4089
  return code;
557,370,301✔
4090
}
4091

4092
static int32_t getBlockForTableMergeScan(void* param, SSDataBlock** ppBlock) {
750,410,892✔
4093
  STableMergeScanSortSourceParam* source = param;
750,410,892✔
4094

4095
  SOperatorInfo*       pOperator = source->pOperator;
750,410,892✔
4096
  STableMergeScanInfo* pInfo = pOperator->info;
750,502,798✔
4097
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
750,517,238✔
4098
  SSDataBlock*         pBlock = NULL;
750,466,308✔
4099
  int64_t              st = taosGetTimestampUs();
750,476,940✔
4100
  int32_t              code = TSDB_CODE_SUCCESS;
750,476,940✔
4101

4102
  while (true) {
4103
    if (pInfo->rtnNextDurationBlocks) {
786,230,569!
4104
      qDebug("%s table merge scan return already fetched new duration blocks. index %d num of blocks %d",
40,972,004✔
4105
             GET_TASKID(pTaskInfo), pInfo->nextDurationBlocksIdx, pInfo->numNextDurationBlocks);
4106

4107
      if (pInfo->nextDurationBlocksIdx < pInfo->numNextDurationBlocks) {
40,975,303✔
4108
        pBlock = pInfo->nextDurationBlocks[pInfo->nextDurationBlocksIdx];
19,606,517✔
4109
        ++pInfo->nextDurationBlocksIdx;
19,607,065✔
4110
      } else {
4111
        for (int32_t i = 0; i < pInfo->numNextDurationBlocks; ++i) {
40,971,282✔
4112
          blockDataDestroy(pInfo->nextDurationBlocks[i]);
19,604,697✔
4113
          pInfo->nextDurationBlocks[i] = NULL;
19,603,317✔
4114
        }
4115

4116
        pInfo->rtnNextDurationBlocks = false;
21,367,965✔
4117
        pInfo->nextDurationBlocksIdx = 0;
21,367,965✔
4118
        pInfo->numNextDurationBlocks = 0;
21,366,585✔
4119
        continue;
21,366,585✔
4120
      }
4121
    } else {
4122
      bool bFinished = false;
745,275,958✔
4123
      bool bSkipped = false;
745,265,134✔
4124

4125
      code = doGetBlockForTableMergeScan(pOperator, &bFinished, &bSkipped);
745,320,256✔
4126
      if (code != 0) {
745,085,560!
4127
        return code;
×
4128
      }
4129

4130
      pBlock = pInfo->pReaderBlock;
745,085,560✔
4131
      qDebug("%s table merge scan fetch block. finished %d skipped %d next-duration-block %d new-fileset %d",
745,263,343!
4132
             GET_TASKID(pTaskInfo), bFinished, bSkipped, pInfo->bNextDurationBlockEvent, pInfo->bNewFilesetEvent);
4133
      if (bFinished) {
745,347,413!
4134
        pInfo->bNewFilesetEvent = false;
171,766,036✔
4135
        break;
171,758,888✔
4136
      }
4137

4138
      if (pInfo->bNextDurationBlockEvent || pInfo->bNewFilesetEvent) {
573,581,377!
4139
        if (!bSkipped) {
21,432,535!
4140
          code = createOneDataBlock(pBlock, true, &pInfo->nextDurationBlocks[pInfo->numNextDurationBlocks]);
19,607,065✔
4141
          if (code) {
19,605,685!
4142
            *ppBlock = NULL;
×
4143
            return code;
×
4144
          }
4145

4146
          ++pInfo->numNextDurationBlocks;
19,605,685✔
4147
          if (pInfo->numNextDurationBlocks > 2) {
19,607,065!
4148
            qError("%s table merge scan prefetch %d next duration blocks. end early.", GET_TASKID(pTaskInfo),
×
4149
                   pInfo->numNextDurationBlocks);
4150
            pInfo->bNewFilesetEvent = false;
×
4151
            break;
×
4152
          }
4153
        }
4154

4155
        if (pInfo->bNewFilesetEvent) {
21,431,987!
4156
          pInfo->rtnNextDurationBlocks = true;
21,370,333✔
4157
          *ppBlock = NULL;
21,370,333✔
4158
          return code;
21,368,405✔
4159
        }
4160

4161
        if (pInfo->bNextDurationBlockEvent) {
×
4162
          pInfo->bNextDurationBlockEvent = false;
×
4163
          continue;
×
4164
        }
4165
      }
4166
      if (bSkipped) continue;
552,155,245!
4167
    }
4168

4169
    pBlock->info.id.groupId = tableListGetTableGroupId(pInfo->base.pTableListInfo, pBlock->info.id.uid);
557,434,530✔
4170

4171
    pOperator->resultInfo.totalRows += pBlock->info.rows;
557,426,794✔
4172
    pInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
557,428,433✔
4173
    *ppBlock = pBlock;
557,432,483✔
4174

4175
    return code;
557,429,142✔
4176
  }
4177

4178
  *ppBlock = NULL;
171,760,992✔
4179
  return code;
171,765,794✔
4180
}
4181

4182
int32_t generateSortByTsPkInfo(SArray* colMatchInfo, int32_t order, SArray** ppSortArray) {
135,249,689✔
4183
  int32_t code = TSDB_CODE_SUCCESS;
135,249,689✔
4184
  int32_t lino = 0;
135,249,689✔
4185
  SArray* pSortInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
135,249,689✔
4186
  QUERY_CHECK_NULL(pSortInfo, code, lino, _end, terrno);
135,147,710!
4187
  SBlockOrderInfo biTs = {0};
135,147,710✔
4188
  SBlockOrderInfo biPk = {0};
135,150,076✔
4189

4190
  int32_t tsTargetSlotId = 0;
135,145,380✔
4191
  int32_t pkTargetSlotId = -1;
135,145,380✔
4192
  for (int32_t i = 0; i < taosArrayGetSize(colMatchInfo); ++i) {
519,883,027✔
4193
    SColMatchItem* colInfo = taosArrayGet(colMatchInfo, i);
384,889,870✔
4194
    QUERY_CHECK_NULL(colInfo, code, lino, _end, terrno);
384,889,586!
4195
    if (colInfo->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
384,889,586✔
4196
      tsTargetSlotId = colInfo->dstSlotId;
135,245,360✔
4197
      biTs.order = order;
135,257,287✔
4198
      biTs.slotId = tsTargetSlotId;
135,257,287✔
4199
      biTs.nullFirst = (order == TSDB_ORDER_ASC);
135,257,287✔
4200
      biTs.compFn = getKeyComparFunc(TSDB_DATA_TYPE_TIMESTAMP, order);
135,257,287✔
4201
    }
4202
    // TODO: order by just ts
4203
    if (colInfo->isPk) {
384,842,621!
4204
      pkTargetSlotId = colInfo->dstSlotId;
5,323,314✔
4205
      biPk.order = order;
5,322,763✔
4206
      biPk.slotId = pkTargetSlotId;
5,322,763✔
4207
      biPk.nullFirst = (order == TSDB_ORDER_ASC);
5,322,763✔
4208
      biPk.compFn = getKeyComparFunc(colInfo->dataType.type, order);
5,322,763✔
4209
    }
4210
  }
4211

4212
  void* tmp = taosArrayPush(pSortInfo, &biTs);
135,290,349✔
4213
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
135,290,349!
4214
  if (pkTargetSlotId != -1) {
135,290,349✔
4215
    tmp = taosArrayPush(pSortInfo, &biPk);
5,323,314✔
4216
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
5,323,314!
4217
  }
4218

4219
  (*ppSortArray) = pSortInfo;
135,288,790✔
4220

4221
_end:
135,217,809✔
4222
  if (code != TSDB_CODE_SUCCESS) {
135,219,101!
4223
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4224
  }
4225
  return code;
135,219,101✔
4226
}
4227

4228
void tableMergeScanTsdbNotifyCb(ETsdReaderNotifyType type, STsdReaderNotifyInfo* info, void* param) {
50,024,374✔
4229
  STableMergeScanInfo* pTmsInfo = param;
50,024,374✔
4230
  if (type == TSD_READER_NOTIFY_DURATION_START) {
50,024,374!
4231
    pTmsInfo->bNewFilesetEvent = true;
50,048,572✔
4232
  } else if (type == TSD_READER_NOTIFY_NEXT_DURATION_BLOCK) {
×
4233
    pTmsInfo->bNextDurationBlockEvent = true;
×
4234
  }
4235
  qDebug("table merge scan receive notification. type %d, fileset %d", type, info->duration.filesetId);
50,006,786!
4236

4237
  return;
50,059,531✔
4238
}
4239

4240
int32_t startDurationForGroupTableMergeScan(SOperatorInfo* pOperator) {
194,800,247✔
4241
  STableMergeScanInfo* pInfo = pOperator->info;
194,800,247✔
4242
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
194,853,737✔
4243

4244
  int32_t code = TSDB_CODE_SUCCESS;
194,868,514✔
4245
  int32_t lino = 0;
194,868,514✔
4246
  int32_t numOfTable = pInfo->tableEndIndex - pInfo->tableStartIndex + 1;
194,868,514✔
4247

4248
  qDebug("%s table merge scan start duration ", GET_TASKID(pTaskInfo));
194,832,793✔
4249
  pInfo->bNewFilesetEvent = false;
194,879,052✔
4250
  pInfo->bNextDurationBlockEvent = false;
194,884,729✔
4251

4252
  pInfo->sortBufSize = 2048 * pInfo->bufPageSize;
194,863,682✔
4253
  int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
194,889,016!
4254

4255
  pInfo->pSortHandle = NULL;
194,862,210✔
4256
  code = tsortCreateSortHandle(pInfo->pSortInfo, SORT_BLOCK_TS_MERGE, pInfo->bufPageSize, numOfBufPage,
389,767,433✔
4257
                               pInfo->pSortInputBlock, pTaskInfo->id.str, 0, 0, 0, &pInfo->pSortHandle);
194,866,174✔
4258
  if (code) {
194,771,933!
4259
    return code;
×
4260
  }
4261

4262
  if (pInfo->bSortRowId && numOfTable != 1) {
194,771,933!
4263
    int32_t memSize = 512 * 1024 * 1024;
13,699,726✔
4264
    code = tsortSetSortByRowId(pInfo->pSortHandle, memSize);
13,699,726✔
4265
    QUERY_CHECK_CODE(code, lino, _end);
13,703,305!
4266
  }
4267

4268
  tsortSetMergeLimit(pInfo->pSortHandle, pInfo->mergeLimit);
194,786,427✔
4269
  tsortSetMergeLimitReachedFp(pInfo->pSortHandle, tableMergeScanDoSkipTable, pOperator);
194,789,680✔
4270
  tsortSetAbortCheckFn(pInfo->pSortHandle, isTaskKilled, pOperator->pTaskInfo);
194,769,266✔
4271

4272
  tsortSetFetchRawDataFp(pInfo->pSortHandle, getBlockForTableMergeScan, NULL, NULL);
194,839,164✔
4273
  QUERY_CHECK_CODE(code, lino, _end);
194,776,719!
4274

4275
  STableMergeScanSortSourceParam* param = taosMemoryCalloc(1, sizeof(STableMergeScanSortSourceParam));
194,776,719!
4276
  QUERY_CHECK_NULL(param, code, lino, _end, terrno);
194,733,665!
4277
  param->pOperator = pOperator;
194,733,665✔
4278

4279
  SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
194,797,298!
4280
  if (ps == NULL) {
194,716,363!
4281
    taosMemoryFree(param);
×
4282
    QUERY_CHECK_NULL(ps, code, lino, _end, terrno);
×
4283
  }
4284

4285
  ps->param = param;
194,716,363✔
4286
  ps->onlyRef = false;
194,813,812✔
4287
  code = tsortAddSource(pInfo->pSortHandle, ps);
194,838,796✔
4288
  QUERY_CHECK_CODE(code, lino, _end);
194,842,671!
4289

4290
  if (numOfTable == 1) {
194,842,671✔
4291
    tsortSetSingleTableMerge(pInfo->pSortHandle);
133,300,737✔
4292
  } else {
4293
    code = tsortOpen(pInfo->pSortHandle);
61,541,934✔
4294
    QUERY_CHECK_CODE(code, lino, _end);
61,569,552!
4295
  }
4296

4297
_end:
61,569,552✔
4298
  if (code != TSDB_CODE_SUCCESS) {
194,869,013!
4299
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4300
  }
4301
  return code;
194,882,056✔
4302
}
4303

4304
void stopDurationForGroupTableMergeScan(SOperatorInfo* pOperator) {
194,892,103✔
4305
  STableMergeScanInfo* pInfo = pOperator->info;
194,892,103✔
4306
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
194,891,083✔
4307
  qDebug("%s table merge scan stop duration ", GET_TASKID(pTaskInfo));
194,883,508✔
4308

4309
  SSortExecInfo sortExecInfo = tsortGetSortExecInfo(pInfo->pSortHandle);
194,883,508✔
4310
  pInfo->sortExecInfo.sortMethod = sortExecInfo.sortMethod;
194,882,134✔
4311
  pInfo->sortExecInfo.sortBuffer = sortExecInfo.sortBuffer;
194,881,928✔
4312
  pInfo->sortExecInfo.loops += sortExecInfo.loops;
194,883,323✔
4313
  pInfo->sortExecInfo.readBytes += sortExecInfo.readBytes;
194,886,120✔
4314
  pInfo->sortExecInfo.writeBytes += sortExecInfo.writeBytes;
194,881,181✔
4315

4316
  tsortDestroySortHandle(pInfo->pSortHandle);
194,884,588✔
4317
  pInfo->pSortHandle = NULL;
194,886,791✔
4318
}
194,884,567✔
4319

4320
void startGroupTableMergeScan(SOperatorInfo* pOperator) {
173,490,189✔
4321
  int32_t              code = TSDB_CODE_SUCCESS;
173,490,189✔
4322
  int32_t              lino = 0;
173,490,189✔
4323
  STableMergeScanInfo* pInfo = pOperator->info;
173,490,189✔
4324
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
173,451,002✔
4325
  SReadHandle*         pHandle = &pInfo->base.readHandle;
173,431,282✔
4326
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
173,397,344✔
4327
  qDebug("%s table merge scan start group %" PRIu64, GET_TASKID(pTaskInfo), pInfo->groupId);
173,484,537✔
4328

4329
  {
4330
    int32_t numOfTables = 0;
173,489,314✔
4331
    code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
173,395,325✔
4332
    QUERY_CHECK_CODE(code, lino, _end);
173,465,001!
4333

4334
    int32_t i = pInfo->tableStartIndex + 1;
173,465,001✔
4335
    for (; i < numOfTables; ++i) {
637,808,634✔
4336
      STableKeyInfo* tableKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i);
504,236,450✔
4337
      QUERY_CHECK_NULL(tableKeyInfo, code, lino, _end, terrno);
504,229,524!
4338
      if (tableKeyInfo->groupId != pInfo->groupId) {
504,229,524✔
4339
        break;
39,890,382✔
4340
      }
4341
    }
4342
    pInfo->tableEndIndex = i - 1;
173,462,566✔
4343
  }
4344
  pInfo->bGroupProcessed = false;
173,533,552✔
4345
  int32_t tableStartIdx = pInfo->tableStartIndex;
173,527,021✔
4346
  int32_t tableEndIdx = pInfo->tableEndIndex;
173,505,415✔
4347

4348
  int32_t        numOfTable = tableEndIdx - tableStartIdx + 1;
173,538,456✔
4349
  STableKeyInfo* startKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, tableStartIdx);
173,538,456✔
4350
  code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInfo->base.cond, startKeyInfo, numOfTable, pInfo->pReaderBlock,
346,986,934✔
4351
                                       (void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), &pInfo->mSkipTables);
173,492,131✔
4352
  QUERY_CHECK_CODE(code, lino, _end);
173,465,915!
4353
  if (pInfo->filesetDelimited) {
173,465,915!
4354
    pAPI->tsdReader.tsdSetFilesetDelimited(pInfo->base.dataReader);
173,463,100✔
4355
  }
4356
  pAPI->tsdReader.tsdSetSetNotifyCb(pInfo->base.dataReader, tableMergeScanTsdbNotifyCb, pInfo);
173,507,040✔
4357

4358
  code = startDurationForGroupTableMergeScan(pOperator);
173,404,496✔
4359
  QUERY_CHECK_CODE(code, lino, _end);
173,474,801!
4360

4361
_end:
173,474,801✔
4362
  if (code != TSDB_CODE_SUCCESS) {
173,477,058!
4363
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4364
    pTaskInfo->code = code;
×
4365
    T_LONG_JMP(pTaskInfo->env, code);
×
4366
  }
4367
}
173,477,058✔
4368

4369
void stopGroupTableMergeScan(SOperatorInfo* pOperator) {
173,520,727✔
4370
  STableMergeScanInfo* pInfo = pOperator->info;
173,520,727✔
4371
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
173,525,872✔
4372
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
173,519,993✔
4373

4374
  stopDurationForGroupTableMergeScan(pOperator);
173,523,476✔
4375

4376
  if (pInfo->base.dataReader != NULL) {
173,516,914!
4377
    pAPI->tsdReader.tsdReaderClose(pInfo->base.dataReader);
173,517,979✔
4378
    pInfo->base.dataReader = NULL;
173,465,125✔
4379
  }
4380
  for (int32_t i = 0; i < pInfo->numNextDurationBlocks; ++i) {
173,466,810✔
4381
    if (pInfo->nextDurationBlocks[i]) {
2,368!
4382
      blockDataDestroy(pInfo->nextDurationBlocks[i]);
2,368✔
4383
      pInfo->nextDurationBlocks[i] = NULL;
2,368✔
4384
    }
4385
    pInfo->numNextDurationBlocks = 0;
2,368✔
4386
    pInfo->nextDurationBlocksIdx = 0;
2,368✔
4387
  }
4388
  resetLimitInfoForNextGroup(&pInfo->limitInfo);
173,495,298✔
4389
  taosHashCleanup(pInfo->mSkipTables);
173,463,649✔
4390
  pInfo->mSkipTables = NULL;
173,466,504✔
4391
  qDebug("%s table merge scan stop group %" PRIu64, GET_TASKID(pTaskInfo), pInfo->groupId);
173,462,995✔
4392
}
173,501,922✔
4393

4394
// all data produced by this function only belongs to one group
4395
// slimit/soffset does not need to be concerned here, since this function only deal with data within one group.
4396
SSDataBlock* getSortedTableMergeScanBlockData(SSortHandle* pHandle, SSDataBlock* pResBlock, int32_t capacity,
373,944,035✔
4397
                                              SOperatorInfo* pOperator) {
4398
  STableMergeScanInfo* pInfo = pOperator->info;
373,944,035✔
4399
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
373,962,157✔
4400
  STupleHandle*        pTupleHandle = NULL;
373,946,897✔
4401

4402
  blockDataCleanup(pResBlock);
373,969,810✔
4403

4404
  while (1) {
×
4405
    while (1) {
2,147,483,647✔
4406
      pTupleHandle = NULL;
2,147,483,647✔
4407
      int32_t code = tsortNextTuple(pHandle, &pTupleHandle);
2,147,483,647✔
4408
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
4409
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
21!
4410
        T_LONG_JMP(pOperator->pTaskInfo->env, code);
21!
4411
      }
4412
      if (pTupleHandle == NULL) {
2,147,483,647✔
4413
        break;
305,278,205✔
4414
      }
4415

4416
      code = tsortAppendTupleToBlock(pInfo->pSortHandle, pResBlock, pTupleHandle);
2,147,483,647✔
4417
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647!
4418
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
4419
        T_LONG_JMP(pOperator->pTaskInfo->env, terrno);
×
4420
      }
4421

4422
      if (pResBlock->info.rows >= capacity) {
2,147,483,647✔
4423
        break;
68,706,631✔
4424
      }
4425
    }
4426

4427
    if (tsortIsClosed(pHandle)) {
373,984,836!
4428
      terrno = TSDB_CODE_TSC_QUERY_CANCELLED;
×
4429
      T_LONG_JMP(pOperator->pTaskInfo->env, terrno);
×
4430
    }
4431

4432
    bool limitReached = applyLimitOffset(&pInfo->limitInfo, pResBlock, pTaskInfo);
373,983,221✔
4433
    qDebug("%s get sorted row block, rows:%" PRId64 ", limit:%" PRId64, GET_TASKID(pTaskInfo), pResBlock->info.rows,
373,981,784✔
4434
           pInfo->limitInfo.numOfOutputRows);
4435
    if (pTupleHandle == NULL || limitReached || pResBlock->info.rows > 0) {
373,986,711!
4436
      break;
4437
    }
4438
  }
4439
  return (pResBlock->info.rows > 0) ? pResBlock : NULL;
373,986,711✔
4440
}
4441

4442
int32_t doTableMergeScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
323,885,173✔
4443
  if (pOperator->status == OP_EXEC_DONE) {
323,885,173✔
4444
    (*ppRes) = NULL;
105,345✔
4445
    return TSDB_CODE_SUCCESS;
105,345✔
4446
  }
4447

4448
  int32_t              code = TSDB_CODE_SUCCESS;
323,727,080✔
4449
  int32_t              lino = 0;
323,727,080✔
4450
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
323,727,080✔
4451
  STableMergeScanInfo* pInfo = pOperator->info;
323,780,845✔
4452

4453
  code = pOperator->fpSet._openFn(pOperator);
323,751,129✔
4454
  QUERY_CHECK_CODE(code, lino, _end);
323,773,300!
4455

4456
  int64_t st = taosGetTimestampUs();
323,800,121✔
4457

4458
  int32_t tableListSize = 0;
323,800,121✔
4459
  code = tableListGetSize(pInfo->base.pTableListInfo, &tableListSize);
323,760,208✔
4460
  QUERY_CHECK_CODE(code, lino, _end);
323,763,318!
4461

4462
  if (!pInfo->hasGroupId) {
323,763,318!
4463
    pInfo->hasGroupId = true;
144,687,305✔
4464

4465
    if (tableListSize == 0) {
144,605,791✔
4466
      setOperatorCompleted(pOperator);
11,085,570✔
4467
      (*ppRes) = NULL;
11,086,327✔
4468
      return code;
11,087,326✔
4469
    }
4470
    pInfo->tableStartIndex = 0;
133,520,221✔
4471
    STableKeyInfo* tmp = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
133,599,226✔
4472
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
133,515,892!
4473
    pInfo->groupId = tmp->groupId;
133,515,892✔
4474
    startGroupTableMergeScan(pOperator);
133,604,383✔
4475
  }
4476

4477
  SSDataBlock* pBlock = NULL;
312,703,111✔
4478
  while (pInfo->tableStartIndex < tableListSize) {
373,959,971!
4479
    if (isTaskKilled(pTaskInfo)) {
373,983,664✔
4480
      goto _end;
27,038✔
4481
    }
4482

4483
    pBlock = getSortedTableMergeScanBlockData(pInfo->pSortHandle, pInfo->pResBlock, pOperator->resultInfo.capacity,
373,940,864✔
4484
                                              pOperator);
4485
    if (pBlock == NULL && !pInfo->bGroupProcessed && pInfo->needCountEmptyTable) {
373,988,492!
4486
      STableKeyInfo* tbInfo = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
12,525,803✔
4487
      QUERY_CHECK_NULL(tbInfo, code, lino, _end, terrno);
12,525,803!
4488
      pBlock = getOneRowResultBlock(pTaskInfo, &pInfo->base, pInfo->pResBlock, tbInfo);
12,525,803✔
4489
    }
4490
    if (pBlock != NULL) {
373,981,573✔
4491
      pBlock->info.id.groupId = pInfo->groupId;
179,093,411✔
4492
      pOperator->resultInfo.totalRows += pBlock->info.rows;
179,099,921✔
4493
      pInfo->bGroupProcessed = true;
179,099,921✔
4494
      break;
179,099,218✔
4495
    } else {
4496
      if (pInfo->bNewFilesetEvent) {
194,888,162!
4497
        stopDurationForGroupTableMergeScan(pOperator);
21,370,333✔
4498
        code = startDurationForGroupTableMergeScan(pOperator);
21,370,333✔
4499
        QUERY_CHECK_CODE(code, lino, _end);
21,366,867!
4500
      } else {
4501
        // Data of this group are all dumped, let's try the next group
4502
        stopGroupTableMergeScan(pOperator);
173,521,770✔
4503
        if (pInfo->tableEndIndex >= tableListSize - 1) {
173,518,705✔
4504
          setOperatorCompleted(pOperator);
133,625,478✔
4505
          break;
133,615,747✔
4506
        }
4507

4508
        pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
39,889,993✔
4509
        STableKeyInfo* tmp = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
39,889,993✔
4510
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
39,889,993!
4511
        pInfo->groupId = tmp->groupId;
39,889,993✔
4512
        startGroupTableMergeScan(pOperator);
39,889,993✔
4513
        resetLimitInfoForNextGroup(&pInfo->limitInfo);
39,889,369✔
4514
      }
4515
    }
4516
  }
4517

4518
  pOperator->cost.totalCost += (taosGetTimestampUs() - st) / 1000.0;
312,719,959✔
4519

4520
_end:
312,745,494✔
4521
  if (code != TSDB_CODE_SUCCESS) {
312,749,006!
4522
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4523
    pTaskInfo->code = code;
×
4524
    T_LONG_JMP(pTaskInfo->env, code);
×
4525
  } else {
4526
    (*ppRes) = pBlock;
312,749,006✔
4527
  }
4528

4529
  return code;
312,754,114✔
4530
}
4531

4532
static SSDataBlock* doTableMergeScan(SOperatorInfo* pOperator) {
×
4533
  SSDataBlock* pRes = NULL;
×
4534
  int32_t      code = doTableMergeScanNext(pOperator, &pRes);
×
4535
  return pRes;
×
4536
}
4537

4538
void destroyTableMergeScanOperatorInfo(void* param) {
135,305,421✔
4539
  STableMergeScanInfo* pTableScanInfo = (STableMergeScanInfo*)param;
135,305,421✔
4540

4541
  // start one reader variable
4542
  if (pTableScanInfo->base.readerAPI.tsdReaderClose != NULL) {
135,305,421✔
4543
    pTableScanInfo->base.readerAPI.tsdReaderClose(pTableScanInfo->base.dataReader);
135,305,884✔
4544
    pTableScanInfo->base.dataReader = NULL;
135,287,772✔
4545
  }
4546

4547
  for (int32_t i = 0; i < pTableScanInfo->numNextDurationBlocks; ++i) {
135,289,705!
4548
    if (pTableScanInfo->nextDurationBlocks[i] != NULL) {
×
4549
      blockDataDestroy(pTableScanInfo->nextDurationBlocks[i]);
×
4550
      pTableScanInfo->nextDurationBlocks[i] = NULL;
×
4551
    }
4552
  }
4553

4554
  tsortDestroySortHandle(pTableScanInfo->pSortHandle);
135,297,958✔
4555
  pTableScanInfo->pSortHandle = NULL;
135,286,207✔
4556
  taosHashCleanup(pTableScanInfo->mSkipTables);
135,299,924✔
4557
  pTableScanInfo->mSkipTables = NULL;
135,278,129✔
4558
  blockDataDestroy(pTableScanInfo->pSortInputBlock);
135,282,120✔
4559
  pTableScanInfo->pSortInputBlock = NULL;
135,293,383✔
4560
  // end one reader variable
4561

4562
  destroyTableScanBase(&pTableScanInfo->base, &pTableScanInfo->base.readerAPI);
135,293,531✔
4563

4564
  blockDataDestroy(pTableScanInfo->pResBlock);
135,312,120✔
4565
  pTableScanInfo->pResBlock = NULL;
135,312,646✔
4566

4567
  // remove it from the task->result list
4568
  blockDataDestroy(pTableScanInfo->pReaderBlock);
135,312,646✔
4569
  pTableScanInfo->pReaderBlock = NULL;
135,313,556✔
4570
  taosArrayDestroy(pTableScanInfo->pSortInfo);
135,314,326✔
4571

4572
  stopSubTablesTableMergeScan(pTableScanInfo);
135,312,790✔
4573

4574
  taosMemoryFreeClear(param);
135,309,960!
4575
}
135,308,389✔
4576

4577
int32_t getTableMergeScanExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
4,505,271✔
4578
  if (pOptr == NULL) {
4,505,271!
4579
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_INVALID_PARA));
×
4580
    return TSDB_CODE_INVALID_PARA;
×
4581
  }
4582
  // TODO: merge these two info into one struct
4583
  STableMergeScanExecInfo* execInfo = taosMemoryCalloc(1, sizeof(STableMergeScanExecInfo));
4,505,271!
4584
  if (!execInfo) {
4,505,271!
4585
    return terrno;
×
4586
  }
4587
  STableMergeScanInfo* pInfo = pOptr->info;
4,505,271✔
4588
  execInfo->blockRecorder = pInfo->base.readRecorder;
4,505,271✔
4589
  execInfo->sortExecInfo = pInfo->sortExecInfo;
4,505,271✔
4590

4591
  *pOptrExplain = execInfo;
4,505,271✔
4592
  *len = sizeof(STableMergeScanExecInfo);
4,505,271✔
4593

4594
  return TSDB_CODE_SUCCESS;
4,505,271✔
4595
}
4596

4597
static int32_t resetTableMergeScanOperatorState(SOperatorInfo* pOper) {
19,312,938✔
4598
  int32_t         code = TSDB_CODE_SUCCESS;
19,312,938✔
4599
  STableMergeScanInfo*   pInfo = pOper->info;
19,312,938✔
4600
  pOper->status = OP_NOT_OPENED;
19,312,938✔
4601

4602
  pInfo->tableEndIndex = 0;
19,314,312✔
4603
  pInfo->tableStartIndex = 0;
19,314,312✔
4604
  pInfo->hasGroupId = false;
19,312,938✔
4605
  if (pInfo->base.readerAPI.tsdReaderClose) {
19,314,312!
4606
    pInfo->base.readerAPI.tsdReaderClose(pInfo->base.dataReader);
19,314,312✔
4607
  }
4608
  pInfo->base.dataReader = NULL;
19,314,312✔
4609
  pInfo->base.scanFlag = MAIN_SCAN;
19,314,312✔
4610

4611
  pInfo->base.limitInfo = (SLimitInfo){0};
19,314,312✔
4612
  pInfo->base.limitInfo.limit.limit = -1;
19,312,938✔
4613
  pInfo->base.limitInfo.slimit.limit = -1;
19,312,938✔
4614

4615
  tableListDestroy(pInfo->base.pTableListInfo);
19,312,938✔
4616
  pInfo->base.pTableListInfo = tableListCreate();
19,314,312✔
4617
  if (!pInfo->base.pTableListInfo) {
19,314,312!
NEW
4618
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
NEW
4619
    return terrno;
×
4620
  }
4621
  SExecTaskInfo*         pTaskInfo = pOper->pTaskInfo;
19,314,312✔
4622
  
4623
  STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pTaskInfo->pSubplan->pNode;
19,314,312✔
4624
  code = createScanTableListInfo(&pTableScanNode->scan, pTableScanNode->pGroupTags, pTableScanNode->groupSort,
38,628,624!
4625
                                  &pInfo->base.readHandle, pInfo->base.pTableListInfo, 
4626
                                  pTaskInfo->pSubplan->pTagCond, pTaskInfo->pSubplan->pTagIndexCond, pTaskInfo, NULL);
38,628,624✔
4627
  if (code) {
19,314,312!
NEW
4628
    qError("%s failed to createScanTableListInfo, code:%s", __func__, tstrerror(code));
×
NEW
4629
    return code;
×
4630
  }
4631

4632
  initLimitInfo(pTableScanNode->scan.node.pLimit, pTableScanNode->scan.node.pSlimit, &pInfo->limitInfo);
19,314,312✔
4633
  cleanupQueryTableDataCond(&pInfo->base.cond);
19,314,312✔
4634
  code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, &pInfo->base.readHandle, false);
19,314,312✔
4635
  if (code) {
19,312,942!
NEW
4636
    qError("%s failed to initQueryTableDataCond, code:%s", __func__, tstrerror(code));
×
NEW
4637
    return code;
×
4638
  }
4639

4640
  tsortDestroySortHandle(pInfo->pSortHandle);
19,312,942✔
4641
  pInfo->pSortHandle = NULL;
19,312,942✔
4642

4643
  taosHashCleanup(pInfo->mSkipTables);
19,312,942✔
4644
  pInfo->mSkipTables = NULL;
19,314,312✔
4645
  pOper->resultInfo.totalRows = 0;
19,314,312✔
4646

4647
  pInfo->bGroupProcessed = false;
19,311,573✔
4648
  pInfo->bNewFilesetEvent = false;
19,314,312✔
4649
  pInfo->bNextDurationBlockEvent = false;
19,311,568✔
4650
  pInfo->rtnNextDurationBlocks = false;
19,312,938✔
4651
  pInfo->nextDurationBlocksIdx = 0;
19,311,568✔
4652
  pInfo->bSortRowId = false;
19,312,938✔
4653

4654
  for (int32_t i = 0; i < pInfo->numNextDurationBlocks; ++i) {
19,311,568!
NEW
4655
    if (pInfo->nextDurationBlocks[i] != NULL) {
×
NEW
4656
      blockDataDestroy(pInfo->nextDurationBlocks[i]);
×
NEW
4657
      pInfo->nextDurationBlocks[i] = NULL;
×
4658
    }
4659
  }
4660
  pInfo->numNextDurationBlocks = 0;
19,311,568✔
4661

4662
  stopSubTablesTableMergeScan(pInfo);
19,311,568✔
4663
  return code;
19,312,942✔
4664
}
4665

4666
int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle,
135,180,351✔
4667
                                         STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo,
4668
                                         SOperatorInfo** pOptrInfo) {
4669
  QRY_PARAM_CHECK(pOptrInfo);
135,180,351!
4670

4671
  int32_t              code = TSDB_CODE_SUCCESS;
135,205,838✔
4672
  int32_t              lino = 0;
135,205,838✔
4673
  STableMergeScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableMergeScanInfo));
135,205,838!
4674
  SOperatorInfo*       pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
134,972,787!
4675
  if (pInfo == NULL || pOperator == NULL) {
134,966,024!
UNCOV
4676
    code = terrno;
×
4677
    goto _error;
×
4678
  }
4679

4680
  pOperator->pPhyNode = pTableScanNode;
134,975,614✔
4681
  SDataBlockDescNode* pDescNode = pTableScanNode->scan.node.pOutputDataBlockDesc;
134,979,968✔
4682

4683
  int32_t numOfCols = 0;
135,099,531✔
4684
  code = extractColMatchInfo(pTableScanNode->scan.pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID,
135,136,746✔
4685
                             &pInfo->base.matchInfo);
4686
  QUERY_CHECK_CODE(code, lino, _error);
135,189,339!
4687

4688
  code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, readHandle, false);
135,189,339✔
4689
  QUERY_CHECK_CODE(code, lino, _error);
135,194,962!
4690

4691
  if (pTableScanNode->scan.pScanPseudoCols != NULL) {
135,194,962✔
4692
    SExprSupp* pSup = &pInfo->base.pseudoSup;
60,226,573✔
4693
    code = createExprInfo(pTableScanNode->scan.pScanPseudoCols, NULL, &pSup->pExprInfo, &pSup->numOfExprs);
60,240,946✔
4694
    QUERY_CHECK_CODE(code, lino, _error);
60,244,856!
4695

4696
    pSup->pCtx = createSqlFunctionCtx(pSup->pExprInfo, pSup->numOfExprs, &pSup->rowEntryInfoOffset,
60,244,856✔
4697
                                      &pTaskInfo->storageAPI.functionStore);
4698
    QUERY_CHECK_NULL(pSup->pCtx, code, lino, _error, terrno);
60,235,103!
4699
  }
4700

4701
  pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]};
135,080,821✔
4702

4703
  pInfo->base.metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024 * 128, -1, .5);
134,930,020✔
4704
  QUERY_CHECK_NULL(pInfo->base.metaCache.pTableMetaEntryCache, code, lino, _error, terrno);
135,241,840!
4705

4706
  pInfo->base.readerAPI = pTaskInfo->storageAPI.tsdReader;
135,151,881✔
4707
  pInfo->base.dataBlockLoadFlag = FUNC_DATA_REQUIRED_DATA_LOAD;
135,227,414✔
4708
  pInfo->base.scanFlag = MAIN_SCAN;
134,973,673✔
4709
  pInfo->base.readHandle = *readHandle;
135,056,091✔
4710

4711
  pInfo->readIdx = -1;
135,212,929✔
4712

4713
  pInfo->base.limitInfo.limit.limit = -1;
135,009,670✔
4714
  pInfo->base.limitInfo.slimit.limit = -1;
135,092,507✔
4715
  pInfo->base.pTableListInfo = pTableListInfo;
135,006,557✔
4716

4717
  pInfo->sample.sampleRatio = pTableScanNode->ratio;
135,228,088✔
4718
  pInfo->sample.seed = taosGetTimestampSec();
135,197,038✔
4719

4720
  code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0,
135,170,707✔
4721
                            pTaskInfo->pStreamRuntimeInfo);
135,164,038✔
4722
  QUERY_CHECK_CODE(code, lino, _error);
135,091,946!
4723

4724
  initLimitInfo(pTableScanNode->scan.node.pLimit, pTableScanNode->scan.node.pSlimit, &pInfo->limitInfo);
135,091,946✔
4725

4726
  pInfo->mergeLimit = -1;
135,050,540✔
4727
  bool hasLimit = pInfo->limitInfo.limit.limit != -1 || pInfo->limitInfo.limit.offset != -1;
135,192,859✔
4728
  if (hasLimit) {
135,044,129✔
4729
    pInfo->mergeLimit = pInfo->limitInfo.limit.offset != -1
30,309,761✔
4730
                            ? pInfo->limitInfo.limit.limit + pInfo->limitInfo.limit.offset
5,741,225✔
4731
                            : pInfo->limitInfo.limit.limit;
20,883,162✔
4732
    pInfo->mSkipTables = NULL;
15,156,976✔
4733
  }
4734

4735
  initResultSizeInfo(&pOperator->resultInfo, 1024);
135,027,262✔
4736
  pInfo->pResBlock = createDataBlockFromDescNode(pDescNode);
135,130,820✔
4737
  QUERY_CHECK_NULL(pInfo->pResBlock, code, lino, _error, terrno);
135,254,071!
4738
  code = blockDataEnsureCapacity(pInfo->pResBlock, pOperator->resultInfo.capacity);
134,973,565✔
4739
  QUERY_CHECK_CODE(code, lino, _error);
135,284,403!
4740
  if (!hasLimit && blockDataGetRowSize(pInfo->pResBlock) >= 256 && !pTableScanNode->smallDataTsSort) {
135,284,403!
4741
    pInfo->bSortRowId = true;
31,571,604✔
4742
  } else {
4743
    pInfo->bSortRowId = false;
103,685,505✔
4744
  }
4745

4746
  code = prepareDataBlockBuf(pInfo->pResBlock, &pInfo->base.matchInfo);
135,203,835✔
4747
  QUERY_CHECK_CODE(code, lino, _error);
135,293,728!
4748

4749
  code = generateSortByTsPkInfo(pInfo->base.matchInfo.pList, pInfo->base.cond.order, &pInfo->pSortInfo);
135,293,728✔
4750
  QUERY_CHECK_CODE(code, lino, _error);
135,172,826!
4751

4752
  code = createOneDataBlock(pInfo->pResBlock, false, &pInfo->pReaderBlock);
135,172,826✔
4753
  QUERY_CHECK_CODE(code, lino, _error);
135,191,297!
4754

4755
  pInfo->needCountEmptyTable = tsCountAlwaysReturnValue && pTableScanNode->needCountEmptyTable;
135,191,297!
4756

4757
  int32_t  rowSize = pInfo->pResBlock->info.rowSize;
135,242,842✔
4758
  uint32_t nCols = taosArrayGetSize(pInfo->pResBlock->pDataBlock);
135,203,848✔
4759

4760
  pInfo->bufPageSize = getProperSortPageSize(rowSize, nCols);
135,124,903✔
4761

4762
  // start one reader variable
4763
  code = createOneDataBlock(pInfo->pResBlock, false, &pInfo->pSortInputBlock);
135,244,241✔
4764
  QUERY_CHECK_CODE(code, lino, _error);
135,235,180!
4765

4766
  if (!tsExperimental) {
135,235,180!
4767
    pInfo->filesetDelimited = false;
×
4768
  } else {
4769
    pInfo->filesetDelimited = pTableScanNode->filesetDelimited;
135,235,180!
4770
  }
4771
  // end one reader variable
4772
  setOperatorInfo(pOperator, "TableMergeScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN, false, OP_NOT_OPENED,
135,184,914✔
4773
                  pInfo, pTaskInfo);
4774
  pOperator->exprSupp.numOfExprs = numOfCols;
135,103,393✔
4775

4776
  pOperator->fpSet = createOperatorFpSet(
135,061,926✔
4777
      optrDummyOpenFn, pTableScanNode->paraTablesSort ? doTableMergeScanParaSubTablesNext : doTableMergeScanNext, NULL,
135,223,785!
4778
      destroyTableMergeScanOperatorInfo, optrDefaultBufFn, getTableMergeScanExplainExecInfo, optrDefaultGetNextExtFn,
4779
      NULL);
4780
  setOperatorResetStateFn(pOperator, resetTableMergeScanOperatorState);                                    
135,117,264✔
4781
  pOperator->cost.openCost = 0;
135,197,469✔
4782

4783
  *pOptrInfo = pOperator;
135,226,886✔
4784
  return code;
134,999,974✔
4785

4786
_error:
×
4787
  if (code != TSDB_CODE_SUCCESS) {
×
4788
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4789
  }
4790
  pTaskInfo->code = code;
×
4791
  if (pInfo != NULL) {
×
4792
    pInfo->base.pTableListInfo = NULL;
×
4793
    destroyTableMergeScanOperatorInfo(pInfo);
×
4794
  }
4795
  if (pOperator != NULL) {
×
4796
    pOperator->info = NULL;
×
4797
    destroyOperator(pOperator);
×
4798
  }
4799
  return code;
×
4800
}
4801

4802
// ====================================================================================================================
4803
// TableCountScanOperator
4804
static void        destoryTableCountScanOperator(void* param);
4805
static int32_t     buildVnodeGroupedStbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
4806
                                                  SSDataBlock* pRes, char* dbName, tb_uid_t stbUid, SStorageAPI* pAPI);
4807
static int32_t     buildVnodeGroupedNtbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
4808
                                                  SSDataBlock* pRes, char* dbName, SStorageAPI* pAPI);
4809
static int32_t     buildVnodeFilteredTbCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
4810
                                             STableCountScanSupp* pSupp, SSDataBlock* pRes, char* dbName);
4811
static int32_t     buildVnodeGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
4812
                                               STableCountScanSupp* pSupp, SSDataBlock* pRes, int32_t vgId, char* dbName);
4813
static int32_t     buildVnodeDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
4814
                                          STableCountScanSupp* pSupp, SSDataBlock* pRes);
4815
static void        buildSysDbGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
4816
                                               STableCountScanSupp* pSupp, SSDataBlock* pRes, size_t infodbTableNum,
4817
                                               size_t perfdbTableNum);
4818
static void        buildSysDbFilterTableCount(SOperatorInfo* pOperator, STableCountScanSupp* pSupp, SSDataBlock* pRes,
4819
                                              size_t infodbTableNum, size_t perfdbTableNum);
4820
static const char* GROUP_TAG_DB_NAME = "db_name";
4821
static const char* GROUP_TAG_STABLE_NAME = "stable_name";
4822

4823
int32_t tblCountScanGetGroupTagsSlotId(const SNodeList* scanCols, STableCountScanSupp* supp) {
×
4824
  if (scanCols != NULL) {
×
4825
    SNode* pNode = NULL;
×
4826
    FOREACH(pNode, scanCols) {
×
4827
      if (nodeType(pNode) != QUERY_NODE_TARGET) {
×
4828
        return TSDB_CODE_QRY_SYS_ERROR;
×
4829
      }
4830
      STargetNode* targetNode = (STargetNode*)pNode;
×
4831
      if (nodeType(targetNode->pExpr) != QUERY_NODE_COLUMN) {
×
4832
        return TSDB_CODE_QRY_SYS_ERROR;
×
4833
      }
4834
      SColumnNode* colNode = (SColumnNode*)(targetNode->pExpr);
×
4835
      if (strcmp(colNode->colName, GROUP_TAG_DB_NAME) == 0) {
×
4836
        supp->dbNameSlotId = targetNode->slotId;
×
4837
      } else if (strcmp(colNode->colName, GROUP_TAG_STABLE_NAME) == 0) {
×
4838
        supp->stbNameSlotId = targetNode->slotId;
×
4839
      }
4840
    }
4841
  }
4842
  return TSDB_CODE_SUCCESS;
×
4843
}
4844

4845
int32_t tblCountScanGetCountSlotId(const SNodeList* pseudoCols, STableCountScanSupp* supp) {
×
4846
  if (pseudoCols != NULL) {
×
4847
    SNode* pNode = NULL;
×
4848
    FOREACH(pNode, pseudoCols) {
×
4849
      if (nodeType(pNode) != QUERY_NODE_TARGET) {
×
4850
        return TSDB_CODE_QRY_SYS_ERROR;
×
4851
      }
4852
      STargetNode* targetNode = (STargetNode*)pNode;
×
4853
      if (nodeType(targetNode->pExpr) != QUERY_NODE_FUNCTION) {
×
4854
        return TSDB_CODE_QRY_SYS_ERROR;
×
4855
      }
4856
      SFunctionNode* funcNode = (SFunctionNode*)(targetNode->pExpr);
×
4857
      if (funcNode->funcType == FUNCTION_TYPE_TABLE_COUNT) {
×
4858
        supp->tbCountSlotId = targetNode->slotId;
×
4859
      }
4860
    }
4861
  }
4862
  return TSDB_CODE_SUCCESS;
×
4863
}
4864

4865
int32_t tblCountScanGetInputs(SNodeList* groupTags, SName* tableName, STableCountScanSupp* supp) {
×
4866
  if (groupTags != NULL) {
×
4867
    SNode* pNode = NULL;
×
4868
    FOREACH(pNode, groupTags) {
×
4869
      if (nodeType(pNode) != QUERY_NODE_COLUMN) {
×
4870
        return TSDB_CODE_QRY_SYS_ERROR;
×
4871
      }
4872
      SColumnNode* colNode = (SColumnNode*)pNode;
×
4873
      if (strcmp(colNode->colName, GROUP_TAG_DB_NAME) == 0) {
×
4874
        supp->groupByDbName = true;
×
4875
      }
4876
      if (strcmp(colNode->colName, GROUP_TAG_STABLE_NAME) == 0) {
×
4877
        supp->groupByStbName = true;
×
4878
      }
4879
    }
4880
  } else {
4881
    tstrncpy(supp->dbNameFilter, tNameGetDbNameP(tableName), TSDB_DB_NAME_LEN);
×
4882
    tstrncpy(supp->stbNameFilter, tNameGetTableName(tableName), TSDB_TABLE_NAME_LEN);
×
4883
  }
4884
  return TSDB_CODE_SUCCESS;
×
4885
}
4886

4887
int32_t getTableCountScanSupp(SNodeList* groupTags, SName* tableName, SNodeList* scanCols, SNodeList* pseudoCols,
×
4888
                              STableCountScanSupp* supp, SExecTaskInfo* taskInfo) {
4889
  int32_t code = 0;
×
4890
  code = tblCountScanGetInputs(groupTags, tableName, supp);
×
4891
  if (code != TSDB_CODE_SUCCESS) {
×
4892
    qError("%s get table count scan supp. get inputs error", GET_TASKID(taskInfo));
×
4893
    return code;
×
4894
  }
4895

4896
  supp->dbNameSlotId = -1;
×
4897
  supp->stbNameSlotId = -1;
×
4898
  supp->tbCountSlotId = -1;
×
4899

4900
  code = tblCountScanGetGroupTagsSlotId(scanCols, supp);
×
4901
  if (code != TSDB_CODE_SUCCESS) {
×
4902
    qError("%s get table count scan supp. get group tags slot id error", GET_TASKID(taskInfo));
×
4903
    return code;
×
4904
  }
4905

4906
  code = tblCountScanGetCountSlotId(pseudoCols, supp);
×
4907
  if (code != TSDB_CODE_SUCCESS) {
×
4908
    qError("%s get table count scan supp. get count error", GET_TASKID(taskInfo));
×
4909
    return code;
×
4910
  }
4911
  return code;
×
4912
}
4913

4914
int32_t createTableCountScanOperatorInfo(SReadHandle* readHandle, STableCountScanPhysiNode* pTblCountScanNode,
×
4915
                                         SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
4916
  QRY_PARAM_CHECK(pOptrInfo);
×
4917

4918
  int32_t                      code = TSDB_CODE_SUCCESS;
×
4919
  int32_t                      lino = 0;
×
4920
  SScanPhysiNode*              pScanNode = &pTblCountScanNode->scan;
×
4921
  STableCountScanOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(STableCountScanOperatorInfo));
×
4922
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
×
4923
  if (!pInfo || !pOperator) {
×
4924
    code = terrno;
×
4925
    goto _error;
×
4926
  }
4927

4928
  pInfo->readHandle = *readHandle;
×
4929

4930
  SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc;
×
4931
  initResultSizeInfo(&pOperator->resultInfo, 1);
×
4932
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
×
4933
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
×
4934

4935
  code = blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
×
4936
  QUERY_CHECK_CODE(code, lino, _error);
×
4937

4938
  code = getTableCountScanSupp(pTblCountScanNode->pGroupTags, &pTblCountScanNode->scan.tableName,
×
4939
                               pTblCountScanNode->scan.pScanCols, pTblCountScanNode->scan.pScanPseudoCols, &pInfo->supp,
4940
                               pTaskInfo);
4941
  QUERY_CHECK_CODE(code, lino, _error);
×
4942

4943
  setOperatorInfo(pOperator, "TableCountScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN, false, OP_NOT_OPENED,
×
4944
                  pInfo, pTaskInfo);
4945
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableCountScanNext, NULL, destoryTableCountScanOperator,
×
4946
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
4947
  *pOptrInfo = pOperator;
×
4948
  return code;
×
4949

4950
_error:
×
4951
  if (pInfo != NULL) {
×
4952
    destoryTableCountScanOperator(pInfo);
×
4953
  }
4954
  if (pOperator != NULL) {
×
4955
    pOperator->info = NULL;
×
4956
    destroyOperator(pOperator);
×
4957
  }
4958
  pTaskInfo->code = code;
×
4959
  return code;
×
4960
}
4961

4962
int32_t fillTableCountScanDataBlock(STableCountScanSupp* pSupp, char* dbName, char* stbName, int64_t count,
×
4963
                                    SSDataBlock* pRes) {
4964
  int32_t code = TSDB_CODE_SUCCESS;
×
4965
  int32_t lino = 0;
×
4966
  if (pSupp->dbNameSlotId != -1) {
×
4967
    QUERY_CHECK_CONDITION((strlen(dbName) > 0), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
4968
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->dbNameSlotId);
×
4969
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
×
4970

4971
    char varDbName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
×
4972
    tstrncpy(varDataVal(varDbName), dbName, TSDB_DB_NAME_LEN);
×
4973

4974
    varDataSetLen(varDbName, strlen(dbName));
×
4975
    code = colDataSetVal(colInfoData, 0, varDbName, false);
×
4976
    QUERY_CHECK_CODE(code, lino, _end);
×
4977
  }
4978

4979
  if (pSupp->stbNameSlotId != -1) {
×
4980
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->stbNameSlotId);
×
4981
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
×
4982
    if (strlen(stbName) != 0) {
×
4983
      char varStbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
×
4984
      tstrncpy(varDataVal(varStbName), stbName, TSDB_TABLE_NAME_LEN);
×
4985
      varDataSetLen(varStbName, strlen(stbName));
×
4986
      code = colDataSetVal(colInfoData, 0, varStbName, false);
×
4987
      QUERY_CHECK_CODE(code, lino, _end);
×
4988
    } else {
4989
      colDataSetNULL(colInfoData, 0);
4990
    }
4991
  }
4992

4993
  if (pSupp->tbCountSlotId != -1) {
×
4994
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->tbCountSlotId);
×
4995
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
×
4996
    code = colDataSetVal(colInfoData, 0, (char*)&count, false);
×
4997
    QUERY_CHECK_CODE(code, lino, _end);
×
4998
  }
4999
  pRes->info.rows = 1;
×
5000

5001
_end:
×
5002
  if (code != TSDB_CODE_SUCCESS) {
×
5003
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5004
  }
5005
  return code;
×
5006
}
5007

5008
static SSDataBlock* buildSysDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo) {
×
5009
  STableCountScanSupp* pSupp = &pInfo->supp;
×
5010
  SSDataBlock*         pRes = pInfo->pRes;
×
5011

5012
  size_t infodbTableNum;
×
5013
  getInfosDbMeta(NULL, &infodbTableNum);
×
5014
  infodbTableNum -= 1;
×
5015
  size_t perfdbTableNum;
×
5016
  getPerfDbMeta(NULL, &perfdbTableNum);
×
5017

5018
  if (pSupp->groupByDbName || pSupp->groupByStbName) {
×
5019
    buildSysDbGroupedTableCount(pOperator, pInfo, pSupp, pRes, infodbTableNum, perfdbTableNum);
×
5020
    return (pRes->info.rows > 0) ? pRes : NULL;
×
5021
  } else {
5022
    buildSysDbFilterTableCount(pOperator, pSupp, pRes, infodbTableNum, perfdbTableNum);
×
5023
    return (pRes->info.rows > 0) ? pRes : NULL;
×
5024
  }
5025
}
5026

5027
static void buildSysDbFilterTableCount(SOperatorInfo* pOperator, STableCountScanSupp* pSupp, SSDataBlock* pRes,
×
5028
                                       size_t infodbTableNum, size_t perfdbTableNum) {
5029
  int32_t        code = TSDB_CODE_SUCCESS;
×
5030
  int32_t        lino = 0;
×
5031
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
5032
  if (strcmp(pSupp->dbNameFilter, TSDB_INFORMATION_SCHEMA_DB) == 0) {
×
5033
    code = fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes);
×
5034
    QUERY_CHECK_CODE(code, lino, _end);
×
5035
  } else if (strcmp(pSupp->dbNameFilter, TSDB_PERFORMANCE_SCHEMA_DB) == 0) {
×
5036
    code = fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes);
×
5037
    QUERY_CHECK_CODE(code, lino, _end);
×
5038
  } else if (strlen(pSupp->dbNameFilter) == 0) {
×
5039
    code = fillTableCountScanDataBlock(pSupp, "", "", infodbTableNum + perfdbTableNum, pRes);
×
5040
    QUERY_CHECK_CODE(code, lino, _end);
×
5041
  }
5042

5043
_end:
×
5044
  if (code != TSDB_CODE_SUCCESS) {
×
5045
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5046
    pTaskInfo->code = code;
×
5047
    T_LONG_JMP(pTaskInfo->env, code);
×
5048
  }
5049
  setOperatorCompleted(pOperator);
×
5050
}
×
5051

5052
static void buildSysDbGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
5053
                                        STableCountScanSupp* pSupp, SSDataBlock* pRes, size_t infodbTableNum,
5054
                                        size_t perfdbTableNum) {
5055
  int32_t        code = TSDB_CODE_SUCCESS;
×
5056
  int32_t        lino = 0;
×
5057
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
5058
  if (pInfo->currGrpIdx == 0) {
×
5059
    uint64_t groupId = 0;
×
5060
    if (pSupp->groupByDbName) {
×
5061
      groupId = calcGroupId(TSDB_INFORMATION_SCHEMA_DB, strlen(TSDB_INFORMATION_SCHEMA_DB));
×
5062
    } else {
5063
      groupId = calcGroupId("", 0);
×
5064
    }
5065

5066
    pRes->info.id.groupId = groupId;
×
5067
    code = fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes);
×
5068
    QUERY_CHECK_CODE(code, lino, _end);
×
5069
  } else if (pInfo->currGrpIdx == 1) {
×
5070
    uint64_t groupId = 0;
×
5071
    if (pSupp->groupByDbName) {
×
5072
      groupId = calcGroupId(TSDB_PERFORMANCE_SCHEMA_DB, strlen(TSDB_PERFORMANCE_SCHEMA_DB));
×
5073
    } else {
5074
      groupId = calcGroupId("", 0);
×
5075
    }
5076

5077
    pRes->info.id.groupId = groupId;
×
5078
    code = fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes);
×
5079
    QUERY_CHECK_CODE(code, lino, _end);
×
5080
  } else {
5081
    setOperatorCompleted(pOperator);
×
5082
  }
5083
  pInfo->currGrpIdx++;
×
5084

5085
_end:
×
5086
  if (code != TSDB_CODE_SUCCESS) {
×
5087
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5088
    pTaskInfo->code = code;
×
5089
    T_LONG_JMP(pTaskInfo->env, code);
×
5090
  }
5091
}
×
5092

5093
static int32_t doTableCountScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
×
5094
  int32_t                      code = TSDB_CODE_SUCCESS;
×
5095
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
5096
  STableCountScanOperatorInfo* pInfo = pOperator->info;
×
5097
  STableCountScanSupp*         pSupp = &pInfo->supp;
×
5098
  SSDataBlock*                 pRes = pInfo->pRes;
×
5099

5100
  blockDataCleanup(pRes);
×
5101
  QRY_PARAM_CHECK(ppRes);
×
5102

5103
  if (pOperator->status == OP_EXEC_DONE) {
×
5104
    return code;
×
5105
  }
5106

5107
  if (pInfo->readHandle.mnd != NULL) {
×
5108
    (*ppRes) = buildSysDbTableCount(pOperator, pInfo);
×
5109
    return code;
×
5110
  }
5111

5112
  code = buildVnodeDbTableCount(pOperator, pInfo, pSupp, pRes);
×
5113
  if (code != TSDB_CODE_SUCCESS) {
×
5114
    qError("%s failed since %s", __func__, tstrerror(code));
×
5115
    pTaskInfo->code = code;
×
5116
    T_LONG_JMP(pTaskInfo->env, code);
×
5117
  }
5118
  if (pRes->info.rows > 0) {
×
5119
    *ppRes = pRes;
×
5120
  }
5121

5122
  return code;
×
5123
}
5124

5125
static int32_t buildVnodeDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
5126
                                      STableCountScanSupp* pSupp, SSDataBlock* pRes) {
5127
  int32_t        code = TSDB_CODE_SUCCESS;
×
5128
  int32_t        lino = 0;
×
5129
  const char*    db = NULL;
×
5130
  int32_t        vgId = 0;
×
5131
  char           dbName[TSDB_DB_NAME_LEN] = {0};
×
5132
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
5133
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
5134

5135
  // get dbname
5136
  pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, &db, &vgId, NULL, NULL);
×
5137
  SName sn = {0};
×
5138

5139
  code = tNameFromString(&sn, db, T_NAME_ACCT | T_NAME_DB);
×
5140
  QUERY_CHECK_CODE(code, lino, _end);
×
5141

5142
  code = tNameGetDbName(&sn, dbName);
×
5143
  QUERY_CHECK_CODE(code, lino, _end);
×
5144

5145
  if (pSupp->groupByDbName || pSupp->groupByStbName) {
×
5146
    code = buildVnodeGroupedTableCount(pOperator, pInfo, pSupp, pRes, vgId, dbName);
×
5147
  } else {
5148
    code = buildVnodeFilteredTbCount(pOperator, pInfo, pSupp, pRes, dbName);
×
5149
  }
5150

5151
_end:
×
5152
  if (code != TSDB_CODE_SUCCESS) {
×
5153
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5154
    pTaskInfo->code = code;
×
5155
  }
5156

5157
  return code;
×
5158
}
5159

5160
static int32_t buildVnodeGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
5161
                                           STableCountScanSupp* pSupp, SSDataBlock* pRes, int32_t vgId, char* dbName) {
5162
  int32_t        code = TSDB_CODE_SUCCESS;
×
5163
  int32_t        lino = 0;
×
5164
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
5165
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
5166

5167
  if (pSupp->groupByStbName) {
×
5168
    if (pInfo->stbUidList == NULL) {
×
5169
      pInfo->stbUidList = taosArrayInit(16, sizeof(tb_uid_t));
×
5170
      QUERY_CHECK_NULL(pInfo->stbUidList, code, lino, _end, terrno);
×
5171
      code = pAPI->metaFn.storeGetTableList(pInfo->readHandle.vnode, TSDB_SUPER_TABLE, pInfo->stbUidList);
×
5172
      QUERY_CHECK_CODE(code, lino, _end);
×
5173
    }
5174

5175
    if (pInfo->currGrpIdx < taosArrayGetSize(pInfo->stbUidList)) {
×
5176
      tb_uid_t stbUid = *(tb_uid_t*)taosArrayGet(pInfo->stbUidList, pInfo->currGrpIdx);
×
5177
      code = buildVnodeGroupedStbTableCount(pInfo, pSupp, pRes, dbName, stbUid, pAPI);
×
5178
      QUERY_CHECK_CODE(code, lino, _end);
×
5179

5180
      pInfo->currGrpIdx++;
×
5181
    } else if (pInfo->currGrpIdx == taosArrayGetSize(pInfo->stbUidList)) {
×
5182
      code = buildVnodeGroupedNtbTableCount(pInfo, pSupp, pRes, dbName, pAPI);
×
5183
      QUERY_CHECK_CODE(code, lino, _end);
×
5184

5185
      pInfo->currGrpIdx++;
×
5186
    } else {
5187
      setOperatorCompleted(pOperator);
×
5188
    }
5189
  } else {
5190
    uint64_t groupId = calcGroupId(dbName, strlen(dbName));
×
5191
    pRes->info.id.groupId = groupId;
×
5192

5193
    int64_t dbTableCount = 0;
×
5194
    pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &dbTableCount, NULL);
×
5195
    code = fillTableCountScanDataBlock(pSupp, dbName, "", dbTableCount, pRes);
×
5196
    QUERY_CHECK_CODE(code, lino, _end);
×
5197
    setOperatorCompleted(pOperator);
×
5198
  }
5199

5200
_end:
×
5201
  if (code != TSDB_CODE_SUCCESS) {
×
5202
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5203
    pTaskInfo->code = code;
×
5204
  }
5205
  return code;
×
5206
}
5207

5208
static int32_t buildVnodeFilteredTbCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
5209
                                         STableCountScanSupp* pSupp, SSDataBlock* pRes, char* dbName) {
5210
  int32_t        code = TSDB_CODE_SUCCESS;
×
5211
  int32_t        lino = 0;
×
5212
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
5213
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
5214

5215
  if (strlen(pSupp->dbNameFilter) != 0) {
×
5216
    if (strlen(pSupp->stbNameFilter) != 0) {
×
5217
      uint64_t uid = 0;
×
5218
      code = pAPI->metaFn.getTableUidByName(pInfo->readHandle.vnode, pSupp->stbNameFilter, &uid);
×
5219
      QUERY_CHECK_CODE(code, lino, _end);
×
5220

5221
      int64_t numOfChildTables = 0;
×
5222
      code = pAPI->metaFn.getNumOfChildTables(pInfo->readHandle.vnode, uid, &numOfChildTables, NULL, NULL);
×
5223
      QUERY_CHECK_CODE(code, lino, _end);
×
5224

5225
      code = fillTableCountScanDataBlock(pSupp, dbName, pSupp->stbNameFilter, numOfChildTables, pRes);
×
5226
      QUERY_CHECK_CODE(code, lino, _end);
×
5227
    } else {
5228
      int64_t tbNumVnode = 0;
×
5229
      pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &tbNumVnode, NULL);
×
5230
      code = fillTableCountScanDataBlock(pSupp, dbName, "", tbNumVnode, pRes);
×
5231
      QUERY_CHECK_CODE(code, lino, _end);
×
5232
    }
5233
  } else {
5234
    int64_t tbNumVnode = 0;
×
5235
    pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &tbNumVnode, NULL);
×
5236
    code = fillTableCountScanDataBlock(pSupp, dbName, "", tbNumVnode, pRes);
×
5237
    QUERY_CHECK_CODE(code, lino, _end);
×
5238
  }
5239

5240
_end:
×
5241
  if (code != TSDB_CODE_SUCCESS) {
×
5242
    pTaskInfo->code = code;
×
5243
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5244
  }
5245

5246
  setOperatorCompleted(pOperator);
×
5247
  return code;
×
5248
}
5249

5250
static int32_t buildVnodeGroupedNtbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
×
5251
                                              SSDataBlock* pRes, char* dbName, SStorageAPI* pAPI) {
5252
  int32_t code = TSDB_CODE_SUCCESS;
×
5253
  int32_t lino = 0;
×
5254
  char    fullStbName[TSDB_TABLE_FNAME_LEN] = {0};
×
5255
  if (pSupp->groupByDbName) {
×
5256
    snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, "");
×
5257
  }
5258

5259
  uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName));
×
5260
  pRes->info.id.groupId = groupId;
×
5261

5262
  int64_t numOfTables = 0;
×
5263
  pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, NULL, &numOfTables);
×
5264

5265
  if (numOfTables != 0) {
×
5266
    code = fillTableCountScanDataBlock(pSupp, dbName, "", numOfTables, pRes);
×
5267
  }
5268

5269
_end:
×
5270
  if (code != TSDB_CODE_SUCCESS) {
×
5271
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5272
  }
5273
  return code;
×
5274
}
5275

5276
static int32_t buildVnodeGroupedStbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
×
5277
                                              SSDataBlock* pRes, char* dbName, tb_uid_t stbUid, SStorageAPI* pAPI) {
5278
  int32_t code = TSDB_CODE_SUCCESS;
×
5279
  int32_t lino = 0;
×
5280
  char    stbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
×
5281
  code = pAPI->metaFn.getTableNameByUid(pInfo->readHandle.vnode, stbUid, stbName);
×
5282
  QUERY_CHECK_CODE(code, lino, _end);
×
5283

5284
  char fullStbName[TSDB_TABLE_FNAME_LEN] = {0};
×
5285
  if (pSupp->groupByDbName) {
×
5286
    (void)snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, varDataVal(stbName));
×
5287
  } else {
5288
    (void)snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s", varDataVal(stbName));
×
5289
  }
5290

5291
  uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName));
×
5292
  pRes->info.id.groupId = groupId;
×
5293

5294
  int64_t ctbNum = 0;
×
5295
  code = pAPI->metaFn.getNumOfChildTables(pInfo->readHandle.vnode, stbUid, &ctbNum, NULL, NULL);
×
5296
  QUERY_CHECK_CODE(code, lino, _end);
×
5297
  code = fillTableCountScanDataBlock(pSupp, dbName, varDataVal(stbName), ctbNum, pRes);
×
5298
  QUERY_CHECK_CODE(code, lino, _end);
×
5299

5300
_end:
×
5301
  if (code != TSDB_CODE_SUCCESS) {
×
5302
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5303
  }
5304
  return code;
×
5305
}
5306

5307
static void destoryTableCountScanOperator(void* param) {
×
5308
  STableCountScanOperatorInfo* pTableCountScanInfo = param;
×
5309
  blockDataDestroy(pTableCountScanInfo->pRes);
×
5310

5311
  taosArrayDestroy(pTableCountScanInfo->stbUidList);
×
5312
  taosMemoryFreeClear(param);
×
5313
}
×
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