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

taosdata / TDengine / #4790

15 Oct 2025 05:45AM UTC coverage: 60.906% (-0.004%) from 60.91%
#4790

push

travis-ci

web-flow
Merge b5da8883b into 01668ff4e

154696 of 324376 branches covered (47.69%)

Branch coverage included in aggregate %.

186 of 217 new or added lines in 11 files covered. (85.71%)

2655 existing lines in 9 files now uncovered.

206920 of 269356 relevant lines covered (76.82%)

125086749.75 hits per line

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

55.86
/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) {
480,691,607✔
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;
480,691,607✔
85
#endif
86
}
87

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

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

98
  // 0 by default, which means it is not a interval operator of the upstream operator.
99
  if (pInterval->interval == 0) {
499,025,978✔
100
    *overlap = false;
475,829,536✔
101
    return code;
475,879,031✔
102
  }
103

104
  if (order == TSDB_ORDER_ASC) {
23,253,069✔
105
    w = getAlignQueryTimeWindow(pInterval, pBlockInfo->window.skey);
21,524,569✔
106
    if (w.ekey < pBlockInfo->window.skey) {
21,522,695!
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) {
21,522,721✔
112
      *overlap = true;
18,733,930✔
113
      return code;
18,734,954✔
114
    }
115

116
    while (1) {
117
      getNextTimeWindow(pInterval, &w, order);
2,789,217✔
118
      if (w.skey > pBlockInfo->window.ekey) {
2,790,640✔
119
        break;
2,514,361✔
120
      }
121

122
      if (w.ekey <= pBlockInfo->window.ekey) {
274,567!
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) {
274,567!
127
        *overlap = true;
274,567✔
128
        return code;
274,567✔
129
      }
130
    }
131
  } else {
132
    w = getAlignQueryTimeWindow(pInterval, pBlockInfo->window.ekey);
1,728,500✔
133
    if (w.skey > pBlockInfo->window.ekey) {
1,728,303!
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) {
1,727,890✔
139
      *overlap = true;
1,514,235✔
140
      return code;
1,514,235✔
141
    }
142

143
    while (1) {
144
      getNextTimeWindow(pInterval, &w, order);
214,265✔
145
      if (w.ekey < pBlockInfo->window.skey) {
215,320✔
146
        break;
213,730✔
147
      }
148

149
      if (w.skey >= pBlockInfo->window.skey) {
1,590!
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)) {
1,590!
154
        *overlap = true;
1,590✔
155
        return code;
1,590✔
156
      }
157
    }
158
  }
159

160
  *overlap = false;
2,728,091✔
161
  return code;
2,728,347✔
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) {
93,623,338✔
166
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) {
93,623,338!
167
    return NULL;
×
168
  }
169

170
  int64_t buf[2] = {0};
93,668,454✔
171
  SET_RES_WINDOW_KEY((char*)buf, &groupId, sizeof(groupId), groupId);
93,669,471✔
172

173
  STableScanInfo* pTableScanInfo = pOperator->info;
93,698,077✔
174

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

178
  if (p1 == NULL) {
93,716,278✔
179
    return NULL;
34,293,728✔
180
  }
181

182
  *pPage = getBufPage(pTableScanInfo->base.pdInfo.pAggSup->pResultBuf, p1->pageId);
59,422,550✔
183
  if (NULL == *pPage) {
59,413,646!
184
    return NULL;
×
185
  }
186

187
  return (SResultRow*)((char*)(*pPage) + p1->offset);
59,419,118✔
188
}
189

190
static int32_t insertTableToScanIgnoreList(STableScanInfo* pTableScanInfo, uint64_t uid) {
11,376,279✔
191
  if (NULL == pTableScanInfo->pIgnoreTables) {
11,376,279✔
192
    int32_t tableNum = taosArrayGetSize(pTableScanInfo->base.pTableListInfo->pTableList);
241,610✔
193
    pTableScanInfo->pIgnoreTables =
241,612✔
194
        taosHashInit(tableNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
242,265✔
195
    if (NULL == pTableScanInfo->pIgnoreTables) {
241,612!
196
      return terrno;
×
197
    }
198
  }
199

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

209
static int32_t doDynamicPruneDataBlock(SOperatorInfo* pOperator, SDataBlockInfo* pBlockInfo, uint32_t* status) {
554,979,427✔
210
  STableScanInfo* pTableScanInfo = pOperator->info;
554,979,427✔
211
  int32_t         code = TSDB_CODE_SUCCESS;
555,360,817✔
212

213
  if (pTableScanInfo->base.pdInfo.pExprSup == NULL) {
555,360,817✔
214
    return TSDB_CODE_SUCCESS;
461,732,946✔
215
  }
216

217
  SExprSupp* pSup1 = pTableScanInfo->base.pdInfo.pExprSup;
93,685,489✔
218

219
  SFilePage*  pPage = NULL;
93,713,522✔
220
  SResultRow* pRow = getTableGroupOutputBuf(pOperator, pBlockInfo->id.groupId, &pPage);
93,711,290✔
221

222
  if (pRow == NULL) {
93,701,763✔
223
    return TSDB_CODE_SUCCESS;
34,297,582✔
224
  }
225

226
  bool notLoadBlock = true;
59,404,181✔
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;
48,019,577✔
235
      break;
48,019,577✔
236
    }
237
  }
238

239
  // release buffer pages
240
  releaseBufPage(pTableScanInfo->base.pdInfo.pAggSup->pResultBuf, pPage);
59,013,866✔
241

242
  if (notLoadBlock) {
59,399,809✔
243
    *status = FUNC_DATA_REQUIRED_NOT_LOAD;
11,376,254✔
244
    code = insertTableToScanIgnoreList(pTableScanInfo, pBlockInfo->id.uid);
11,376,254✔
245
  }
246

247
  return code;
59,294,858✔
248
}
249

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

257
  return filterRangeExecute(pFilterInfo, pColsAgg, numOfCols, numOfRows, keep);
6,982,680✔
258
}
259

260
static int32_t doLoadBlockSMA(STableScanBase* pTableScanInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo,
109,268,263✔
261
                              bool* pLoad) {
262
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
109,268,263✔
263
  bool         allColumnsHaveAgg = true;
109,295,062✔
264
  bool         hasNullSMA = false;
109,296,706✔
265
  if (pLoad != NULL) {
109,284,224✔
266
    *pLoad = false;
109,278,262✔
267
  }
268

269
  int32_t code = pAPI->tsdReader.tsdReaderRetrieveBlockSMAInfo(pTableScanInfo->dataReader, pBlock, &allColumnsHaveAgg,
109,283,196✔
270
                                                               &hasNullSMA);
271
  if (code != TSDB_CODE_SUCCESS) {
109,269,198!
272
    return code;
×
273
  }
274

275
  if (!allColumnsHaveAgg || hasNullSMA) {
109,269,198!
276
    *pLoad = false;
95,263,778✔
277
  } else {
278
    *pLoad = true;
14,005,420✔
279
  }
280

281
  return code;
109,270,019✔
282
}
283

284
static int32_t doSetTagColumnData(STableScanBase* pTableScanInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo,
569,718,083✔
285
                                  int32_t rows) {
286
  int32_t    code = 0;
569,718,083✔
287
  SExprSupp* pSup = &pTableScanInfo->pseudoSup;
569,718,083✔
288
  if (pSup->numOfExprs > 0) {
570,151,409✔
289
    code = addTagPseudoColumnData(&pTableScanInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pBlock, rows,
239,136,695✔
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) {
239,111,505!
293
      if (pTaskInfo->streamInfo.pState) blockDataCleanup(pBlock);
×
294
      code = 0;
×
295
    }
296
  }
297

298
  return code;
570,114,366✔
299
}
300

301
bool applyLimitOffset(SLimitInfo* pLimitInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo) {
978,816,730✔
302
  SLimit*     pLimit = &pLimitInfo->limit;
978,816,730✔
303
  const char* id = GET_TASKID(pTaskInfo);
978,898,771✔
304

305
  if (pLimitInfo->remainOffset > 0) {
978,995,581✔
306
    if (pLimitInfo->remainOffset >= pBlock->info.rows) {
4,578,960✔
307
      pLimitInfo->remainOffset -= pBlock->info.rows;
2,794,884✔
308
      blockDataEmpty(pBlock);
2,794,884✔
309
      qDebug("current block ignore due to offset, current:%" PRId64 ", %s", pLimitInfo->remainOffset, id);
2,794,884✔
310
      return false;
2,794,884✔
311
    } else {
312
      int32_t code = blockDataTrimFirstRows(pBlock, pLimitInfo->remainOffset);
1,784,076✔
313
      if (code != TSDB_CODE_SUCCESS) {
1,784,076!
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;
1,784,076✔
319
    }
320
  }
321

322
  if (pLimit->limit != -1 && pLimit->limit <= (pLimitInfo->numOfOutputRows + pBlock->info.rows)) {
976,205,581✔
323
    // limit the output rows
324
    int32_t keep = (int32_t)(pLimit->limit - pLimitInfo->numOfOutputRows);
22,513,869✔
325
    blockDataKeepFirstNRows(pBlock, keep);
22,513,869✔
326

327
    pLimitInfo->numOfOutputRows += pBlock->info.rows;
22,513,461✔
328
    qDebug("output limit %" PRId64 " has reached, %s", pLimit->limit, id);
22,513,665✔
329
    return true;
22,513,461✔
330
  }
331

332
  pLimitInfo->numOfOutputRows += pBlock->info.rows;
953,510,522✔
333
  return false;
953,684,017✔
334
}
335

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

340
static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableScanInfo, SSDataBlock* pBlock,
582,705,262✔
341
                             uint32_t* status) {
342
  int32_t        code = TSDB_CODE_SUCCESS;
582,705,262✔
343
  int32_t        lino = 0;
582,705,262✔
344
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
582,705,262✔
345
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
582,825,932✔
346
  bool           loadSMA = false;
582,793,010✔
347

348
  SFileBlockLoadRecorder* pCost = &pTableScanInfo->readRecorder;
582,793,010✔
349

350
  pCost->totalBlocks += 1;
582,818,807✔
351
  pCost->totalRows += pBlock->info.rows;
582,762,135✔
352
  *status = pTableScanInfo->dataBlockLoadFlag;
582,823,291✔
353

354
  if (pOperator->exprSupp.pFilterInfo != NULL) {
582,742,398✔
355
    (*status) = FUNC_DATA_REQUIRED_DATA_LOAD;
83,585,681✔
356
  } else {
357
    bool overlap = false;
499,131,343✔
358
    int  ret =
359
        overlapWithTimeWindow(&pTableScanInfo->pdInfo.interval, &pBlock->info, pTableScanInfo->cond.order, &overlap);
499,194,438✔
360
    if (ret != TSDB_CODE_SUCCESS) {
498,895,893!
361
      return ret;
×
362
    }
363
    if (overlap) {
498,895,893!
364
      (*status) = FUNC_DATA_REQUIRED_DATA_LOAD;
20,521,184✔
365
    }
366
  }
367

368
  SDataBlockInfo* pBlockInfo = &pBlock->info;
582,438,238✔
369
  taosMemoryFreeClear(pBlock->pBlockAgg);
582,592,849!
370

371
  if (*status == FUNC_DATA_REQUIRED_FILTEROUT) {
582,780,253!
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) {
582,275,066✔
379
    qDebug("%s data block skipped, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64 ", uid:%" PRIu64,
18,855,227✔
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);
18,857,603✔
383
    pCost->skipBlocks += 1;
18,858,154✔
384
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
18,858,154✔
385
    return code;
18,858,154✔
386
  } else if (*status == FUNC_DATA_REQUIRED_SMA_LOAD) {
563,393,583✔
387
    pCost->loadBlockStatis += 1;
25,701,094✔
388
    loadSMA = true;  // mark the operation of load sma;
25,697,042✔
389
    bool success = true;
25,697,042✔
390
    code = doLoadBlockSMA(pTableScanInfo, pBlock, pTaskInfo, &success);
25,699,871✔
391
    if (code) {
25,693,779!
392
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
393
      qError("%s failed to retrieve sma info", GET_TASKID(pTaskInfo));
×
394
      QUERY_CHECK_CODE(code, lino, _end);
2,656!
395
    }
396

397
    if (success) {  // failed to load the block sma data, data block statistics does not exist, load data block instead
25,696,382!
398
      qDebug("%s data block SMA loaded, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, GET_TASKID(pTaskInfo),
7,023,417✔
399
             pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
400
      code = doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows);
7,023,824✔
401
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
7,024,231✔
402
      return code;
7,024,231✔
403
    } else {
404
      qDebug("%s failed to load SMA, since not all columns have SMA", GET_TASKID(pTaskInfo));
18,672,965✔
405
      *status = FUNC_DATA_REQUIRED_DATA_LOAD;
18,680,635✔
406
    }
407
  }
408

409
  if (*status != FUNC_DATA_REQUIRED_DATA_LOAD) {
556,358,723!
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)) {
556,352,003!
417
    bool success = true;
83,586,102✔
418
    code = doLoadBlockSMA(pTableScanInfo, pBlock, pTaskInfo, &success);
83,594,488✔
419
    if (code) {
83,562,120!
420
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
421
      qError("%s failed to retrieve sma info", GET_TASKID(pTaskInfo));
×
422
      QUERY_CHECK_CODE(code, lino, _end);
9,657!
423
    }
424

425
    if (success) {
83,571,777!
426
      size_t size = taosArrayGetSize(pBlock->pDataBlock);
6,982,680✔
427
      bool   keep = false;
6,982,680✔
428
      code = doFilterByBlockSMA(pOperator->exprSupp.pFilterInfo, pBlock->pBlockAgg, size, pBlockInfo->rows, &keep);
6,982,680✔
429
      if (code) {
6,982,680!
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) {
6,982,680!
436
        qDebug("%s data block filter out by block SMA, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64,
1,349,685!
437
               GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
438
        pCost->filterOutBlocks += 1;
1,349,685✔
439
        (*status) = FUNC_DATA_REQUIRED_FILTEROUT;
1,349,685✔
440
        taosMemoryFreeClear(pBlock->pBlockAgg);
1,349,685!
441

442
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
1,349,685✔
443
        return TSDB_CODE_SUCCESS;
1,349,685✔
444
      }
445
    }
446
  }
447

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

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

458
  if (*status == FUNC_DATA_REQUIRED_NOT_LOAD) {
555,118,395✔
459
    qDebug("%s data block skipped due to dynamic prune, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64,
11,375,649!
460
           GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
461
    pCost->skipBlocks += 1;
11,376,909✔
462
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
11,376,909✔
463

464
    STableScanInfo* p1 = pOperator->info;
11,376,909✔
465
    if (taosHashGetSize(p1->pIgnoreTables) == taosArrayGetSize(p1->base.pTableListInfo->pTableList)) {
11,376,909✔
466
      *status = FUNC_DATA_REQUIRED_ALL_FILTEROUT;
45,942✔
467
    } else {
468
      *status = FUNC_DATA_REQUIRED_FILTEROUT;
11,330,967✔
469
    }
470
    return TSDB_CODE_SUCCESS;
11,376,909✔
471
  }
472

473
  pCost->totalCheckedRows += pBlock->info.rows;
543,584,331✔
474
  pCost->loadBlocks += 1;
544,074,116✔
475

476
  SSDataBlock* p = NULL;
543,961,340✔
477
  code = pAPI->tsdReader.tsdReaderRetrieveDataBlock(pTableScanInfo->dataReader, &p, NULL);
543,763,664✔
478
  if (p == NULL || code != TSDB_CODE_SUCCESS || p != pBlock) {
543,954,358!
479
    return code;
×
480
  }
481

482
  if ((pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) &&
543,954,358✔
483
      ((STableScanInfo*)pOperator->info)->ignoreTag) {
442,457,980!
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);
523,128,437✔
488
    if (code) {
523,354,813!
489
      return code;
×
490
    }
491
  }
492

493
  // restore the previous value
494
  pCost->totalRows -= pBlock->info.rows;
544,054,031✔
495

496
  if (pOperator->exprSupp.pFilterInfo != NULL) {
544,102,900✔
497
    code = doFilter(pBlock, pOperator->exprSupp.pFilterInfo, &pTableScanInfo->matchInfo, NULL);
82,206,195✔
498
    QUERY_CHECK_CODE(code, lino, _end);
82,187,614✔
499

500
    int64_t st = taosGetTimestampUs();
82,204,862✔
501
    double  el = (taosGetTimestampUs() - st) / 1000.0;
82,200,110✔
502
    pTableScanInfo->readRecorder.filterTime += el;
82,200,110✔
503

504
    if (pBlock->info.rows == 0) {
82,196,367✔
505
      pCost->filterOutBlocks += 1;
15,106,967✔
506
      qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64 ", elapsed time:%.2f ms",
15,109,710✔
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);
67,068,011✔
510
    }
511
  }
512

513
  bool limitReached = applyLimitOffset(&pTableScanInfo->limitInfo, pBlock, pTaskInfo);
544,032,127✔
514
  if (limitReached) {  // set operator flag is done
544,128,790✔
515
    setOperatorCompleted(pOperator);
2,363,340✔
516
  }
517

518
  pCost->totalRows += pBlock->info.rows;
544,128,093✔
519

520
_end:
544,178,394✔
521
  if (code != TSDB_CODE_SUCCESS) {
544,148,135✔
522
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
255!
523
  }
524
  return code;
543,973,274✔
525
}
526

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

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

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

541
static void freeTableCachedVal(void* param) {
221,913,939✔
542
  if (param == NULL) {
221,913,939!
543
    return;
×
544
  }
545

546
  STableCachedVal* pVal = param;
221,913,939✔
547
  taosMemoryFree((void*)pVal->pName);
221,913,939✔
548
  taosMemoryFree(pVal->pTags);
221,911,543✔
549
  taosMemoryFree(pVal);
221,909,470✔
550
}
551

552
static int32_t createTableCacheVal(const SMetaReader* pMetaReader, STableCachedVal** ppResVal) {
221,471,237✔
553
  int32_t          code = TSDB_CODE_SUCCESS;
221,471,237✔
554
  int32_t          lino = 0;
221,471,237✔
555
  STableCachedVal* pVal = taosMemoryMalloc(sizeof(STableCachedVal));
221,471,237✔
556
  QUERY_CHECK_NULL(pVal, code, lino, _end, terrno);
221,820,744!
557

558
  pVal->pTags = NULL;
221,820,744✔
559
  pVal->pName = taosStrdup(pMetaReader->me.name);
221,792,447✔
560
  QUERY_CHECK_NULL(pVal->pName, code, lino, _end, terrno);
221,690,792!
561

562
  // only child table has tag value
563
  if (pMetaReader->me.type == TSDB_CHILD_TABLE || pMetaReader->me.type == TSDB_VIRTUAL_CHILD_TABLE) {
221,655,305!
564
    STag* pTag = (STag*)pMetaReader->me.ctbEntry.pTags;
221,650,591✔
565
    pVal->pTags = taosMemoryMalloc(pTag->len);
221,543,953✔
566
    QUERY_CHECK_NULL(pVal->pTags, code, lino, _end, terrno);
221,646,536!
567
    memcpy(pVal->pTags, pTag, pTag->len);
221,551,054!
568
  }
569

570
  (*ppResVal) = pVal;
221,777,022✔
571

572
_end:
221,794,901✔
573
  if (code != TSDB_CODE_SUCCESS) {
221,794,901!
574
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
575
    freeTableCachedVal(pVal);
×
576
  }
577
  return code;
221,535,472✔
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) {
221,914,316✔
582
  (void)key;
583
  (void)keyLen;
584
  (void)ud;
585
  freeTableCachedVal(value);
221,914,316✔
586
}
221,913,371✔
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,
251,803,370✔
603
                               int32_t rows, SExecTaskInfo* pTask, STableMetaCacheInfo* pCache) {
604
  int32_t          code = TSDB_CODE_SUCCESS;
251,803,370✔
605
  int32_t          lino = 0;
251,803,370✔
606
  bool             freeReader = false;
251,803,370✔
607
  LRUHandle*       h = NULL;
251,803,370✔
608
  STableCachedVal  val = {0};
251,803,370✔
609
  SMetaReader      mr = {0};
251,803,370✔
610
  const char*      idStr = pTask->id.str;
251,904,208✔
611
  int32_t          insertRet = TAOS_LRU_STATUS_OK;
251,953,915✔
612
  STableCachedVal* pVal = NULL;
251,953,915✔
613

614
  // currently only the tbname pseudo column
615
  if (numOfExpr <= 0) {
251,933,012✔
616
    return TSDB_CODE_SUCCESS;
227,982✔
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;
251,705,030✔
623
  pBlock->info.rows = rows;
251,887,851✔
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) {
251,568,099✔
630
    pHandle->api.metaReaderFn.initReader(&mr, pHandle->vnode, META_READER_LOCK, &pHandle->api.metaFn);
223,812✔
631
    code = pHandle->api.metaReaderFn.getEntryGetUidCache(&mr, pBlock->info.id.uid);
223,812✔
632
    if (code != TSDB_CODE_SUCCESS) {
223,167!
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);
223,167✔
648

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

652
    freeReader = true;
223,812✔
653
  } else {
654
    pCache->metaFetch += 1;
251,344,287✔
655

656
    h = taosLRUCacheLookup(pCache->pTableMetaEntryCache, &pBlock->info.id.uid, sizeof(pBlock->info.id.uid));
251,560,762✔
657
    if (h == NULL) {
251,737,853✔
658
      pHandle->api.metaReaderFn.initReader(&mr, pHandle->vnode, META_READER_LOCK, &pHandle->api.metaFn);
221,912,771✔
659
      freeReader = true;
221,902,826✔
660
      code = pHandle->api.metaReaderFn.getEntryGetUidCache(&mr, pBlock->info.id.uid);
221,902,826✔
661
      if (code != TSDB_CODE_SUCCESS) {
221,497,172!
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);
221,497,172✔
676

677
      code = createTableCacheVal(&mr, &pVal);
221,868,348✔
678
      QUERY_CHECK_CODE(code, lino, _end);
221,643,310!
679

680
      val = *pVal;
221,643,310✔
681
    } else {
682
      pCache->cacheHit += 1;
29,825,082✔
683
      STableCachedVal* pValTmp = taosLRUCacheValue(pCache->pTableMetaEntryCache, h);
29,827,118✔
684
      val = *pValTmp;
29,828,499✔
685

686
      bool bRes = taosLRUCacheRelease(pCache->pTableMetaEntryCache, h, false);
29,828,755✔
687
      qTrace("release LRU cache, res %d", bRes);
29,825,582!
688
    }
689

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

694
  for (int32_t j = 0; j < numOfExpr; ++j) {
832,108,840✔
695
    const SExprInfo* pExpr1 = &pExpr[j];
580,094,282✔
696
    int32_t          dstSlotId = pExpr1->base.resSchema.slotId;
580,109,537✔
697

698
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, dstSlotId);
580,135,109✔
699
    colInfoDataCleanup(pColInfoData, pBlock->info.rows);
580,134,859✔
700

701
    int32_t functionId = pExpr1->pExpr->_function.functionId;
580,131,307✔
702

703
    // this is to handle the tbname
704
    if (fmIsScanPseudoColumnFunc(functionId)) {
580,136,677✔
705
      int32_t fType = pExpr1->pExpr->_function.functionType;
41,641,244✔
706
      if (fType == FUNCTION_TYPE_TBNAME) {
41,641,244!
707
        code = setTbNameColData(pBlock, pColInfoData, functionId, val.pName);
41,641,244✔
708
        QUERY_CHECK_CODE(code, lino, _end);
41,640,386!
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};
538,486,296✔
718
      tagVal.cid = pExpr1->base.pParam[0].pCol->colId;
538,485,945✔
719
      const char* p = pHandle->api.metaFn.extractTagVal(val.pTags, pColInfoData->info.type, &tagVal);
538,489,607✔
720

721
      char* data = NULL;
538,493,614✔
722
      if (pColInfoData->info.type != TSDB_DATA_TYPE_JSON && p != NULL) {
538,493,614✔
723
        data = tTagValToData((const STagVal*)p, false);
533,920,037✔
724
      } else {
725
        data = (char*)p;
4,590,239✔
726
      }
727

728
      bool isNullVal = (data == NULL) || (pColInfoData->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data));
538,506,193✔
729
      if (isNullVal) {
538,503,506✔
730
        colDataSetNNULL(pColInfoData, 0, pBlock->info.rows);
4,157,040!
731
      } else if (pColInfoData->info.type != TSDB_DATA_TYPE_JSON) {
534,346,466✔
732
        code = colDataSetNItems(pColInfoData, 0, data, pBlock->info.rows, 1, false);
533,912,397✔
733
        if (IS_VAR_DATA_TYPE(((const STagVal*)p)->type)) {
533,905,350✔
734
          char* tmp = taosMemoryCalloc(1, varDataLen(data) + 1);
184,656,539✔
735
          if (tmp != NULL) {
184,646,143!
736
            memcpy(tmp, varDataVal(data), varDataLen(data));
184,646,143!
737
            qDebug("get tag value:%s, cid:%d, table name:%s, uid%" PRId64, tmp, tagVal.cid, val.pName,
184,658,447✔
738
                   pBlock->info.id.uid);
739
            taosMemoryFree(tmp);
184,668,242✔
740
          }
741
          taosMemoryFree(data);
184,666,305✔
742
        }
743
        QUERY_CHECK_CODE(code, lino, _end);
533,905,391!
744
      } else {  // todo opt for json tag
745
        for (int32_t i = 0; i < pBlock->info.rows; ++i) {
2,593,820✔
746
          code = colDataSetVal(pColInfoData, i, data, false);
2,160,621✔
747
          QUERY_CHECK_CODE(code, lino, _end);
2,160,621!
748
        }
749
      }
750
    }
751
  }
752

753
  // restore the rows
754
  pBlock->info.rows = backupRows;
252,014,558✔
755

756
_end:
251,967,828✔
757

758
  if (NULL != pVal) {
251,970,041✔
759
    insertRet =
221,911,429✔
760
        taosLRUCacheInsert(pCache->pTableMetaEntryCache, &pBlock->info.id.uid, sizeof(uint64_t), pVal,
221,918,568✔
761
                           sizeof(STableCachedVal), freeCachedMetaItem, NULL, NULL, TAOS_LRU_PRIORITY_LOW, NULL);
762
    if (insertRet != TAOS_LRU_STATUS_OK) {
221,911,429!
763
      qWarn("failed to put meta into lru cache, code:%d, %s", insertRet, idStr);
×
764
    }
765
  }
766

767
  if (freeReader) {
251,962,902✔
768
    pHandle->api.metaReaderFn.clearReader(&mr);
222,107,729✔
769
  }
770
  if (code != TSDB_CODE_SUCCESS) {
251,956,975!
771
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
772
  }
773
  return code;
251,936,761✔
774
}
775

776
int32_t setTbNameColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId,
41,641,686✔
777
                         const char* name) {
778
  int32_t                     code = TSDB_CODE_SUCCESS;
41,641,686✔
779
  int32_t                     lino = 0;
41,641,686✔
780
  struct SScalarFuncExecFuncs fpSet = {0};
41,641,686✔
781
  code = fmGetScalarFuncExecFuncs(functionId, &fpSet);
41,641,686✔
782
  QUERY_CHECK_CODE(code, lino, _end);
41,641,397!
783

784
  size_t len = TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE;
41,641,397✔
785
  char   buf[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
41,641,397✔
786
  STR_TO_VARSTR(buf, name)
41,641,686!
787

788
  SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, len, 1);
41,641,686✔
789

790
  code = colInfoDataEnsureCapacity(&infoData, 1, false);
41,641,465✔
791
  QUERY_CHECK_CODE(code, lino, _end);
41,641,244!
792

793
  code = colDataSetVal(&infoData, 0, buf, false);
41,641,244✔
794
  QUERY_CHECK_CODE(code, lino, _end);
41,641,244!
795

796
  SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .columnData = &infoData};
41,641,244✔
797
  SScalarParam param = {.columnData = pColInfoData};
41,641,053✔
798

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

806
  colDataDestroy(&infoData);
41,639,931✔
807

808
_end:
41,640,832✔
809
  if (code != TSDB_CODE_SUCCESS) {
41,639,936!
810
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
811
  }
812
  return code;
41,639,936✔
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) {
181,165,199✔
882
  int32_t code = TSDB_CODE_SUCCESS;
181,165,199✔
883
  int32_t lino = 0;
181,165,199✔
884
  code = tableListGetGroupList(pInfo->base.pTableListInfo, pInfo->currentGroupId, pKeyInfo, size);
181,165,199✔
885
  QUERY_CHECK_CODE(code, lino, _end);
181,153,771!
886

887
  pInfo->tableStartIndex = TARRAY_ELEM_IDX(pInfo->base.pTableListInfo->pTableList, *pKeyInfo);
181,153,771!
888
  pInfo->tableEndIndex = (pInfo->tableStartIndex + (*size) - 1);
181,143,057✔
889
  pInfo->pResBlock->info.blankFill = false;
181,153,463✔
890
  taosMemoryFreeClear(pInfo->pResBlock->pBlockAgg);
181,151,613!
891

892
  if (!pInfo->needCountEmptyTable) {
181,184,877✔
893
    pInfo->countState = TABLE_COUNT_STATE_END;
171,508,503✔
894
  } else {
895
    pInfo->countState = TABLE_COUNT_STATE_SCAN;
9,650,468✔
896
  }
897

898
_end:
181,157,375✔
899
  if (code != TSDB_CODE_SUCCESS) {
181,157,375!
900
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
901
  }
902
  return code;
181,126,228✔
903
}
904

905
void markGroupProcessed(STableScanInfo* pInfo, uint64_t groupId) {
476,437,282✔
906
  if (pInfo->countState == TABLE_COUNT_STATE_END) {
476,437,282✔
907
    return;
442,045,378✔
908
  }
909
  if (pInfo->base.pTableListInfo->groupOffset) {
34,483,347✔
910
    pInfo->countState = TABLE_COUNT_STATE_PROCESSED;
401,587✔
911
  } else {
912
    int32_t code = taosHashRemove(pInfo->base.pTableListInfo->remainGroups, &groupId, sizeof(groupId));
34,081,857✔
913
    if (code != TSDB_CODE_SUCCESS) {
34,085,183✔
914
      qDebug("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
5,520,389!
915
    }
916
  }
917
}
918

919
static SSDataBlock* getOneRowResultBlock(SExecTaskInfo* pTaskInfo, STableScanBase* pBase, SSDataBlock* pBlock,
20,927,520✔
920
                                         const STableKeyInfo* tbInfo) {
921
  blockDataEmpty(pBlock);
20,927,520✔
922
  pBlock->info.rows = 1;
20,929,288✔
923
  pBlock->info.id.uid = tbInfo->uid;
20,929,288✔
924
  pBlock->info.id.groupId = tbInfo->groupId;
20,929,288✔
925
  pBlock->info.blankFill = true;
20,928,404✔
926

927
  // only one row: set all col data to null & hasNull
928
  int32_t col_num = blockDataGetNumOfCols(pBlock);
20,928,183✔
929
  for (int32_t i = 0; i < col_num; ++i) {
85,654,848✔
930
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
64,726,444✔
931
    colDataSetNULL(pColInfoData, 0);
932
  }
933

934
  // set tag/tbname
935
  terrno = doSetTagColumnData(pBase, pBlock, pTaskInfo, 1);
20,928,404✔
936

937
  return pBlock;
20,928,404✔
938
}
939

940
static SSDataBlock* getBlockForEmptyTable(SOperatorInfo* pOperator, const STableKeyInfo* tbInfo) {
20,113,728✔
941
  STableScanInfo* pTableScanInfo = pOperator->info;
20,113,728✔
942
  SSDataBlock*    pBlock =
943
      getOneRowResultBlock(pOperator->pTaskInfo, &pTableScanInfo->base, pTableScanInfo->pResBlock, tbInfo);
20,118,148✔
944

945
  pOperator->resultInfo.totalRows++;
20,117,706✔
946
  return pBlock;
20,119,253✔
947
}
948

949
static int32_t doTableScanImplNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
586,887,221✔
950
  int32_t         code = TSDB_CODE_SUCCESS;
586,887,221✔
951
  int32_t         lino = 0;
586,887,221✔
952
  STableScanInfo* pTableScanInfo = pOperator->info;
586,887,221✔
953
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
586,919,779✔
954
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
586,929,793✔
955
  SSDataBlock*    pBlock = pTableScanInfo->pResBlock;
586,891,498✔
956
  bool            hasNext = false;
586,905,077✔
957
  int64_t         st = taosGetTimestampUs();
587,159,637✔
958

959
  QRY_PARAM_CHECK(ppRes);
587,159,637!
960
  pBlock->info.dataLoad = false;
587,117,756✔
961

962
  while (true) {
24,471,002✔
963
    code = pAPI->tsdReader.tsdNextDataBlock(pTableScanInfo->base.dataReader, &hasNext);
611,546,140✔
964
    if (code != TSDB_CODE_SUCCESS) {
611,250,325!
965
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
×
966
      QUERY_CHECK_CODE(code, lino, _end);
27!
967
    }
968

969
    if (!hasNext) {
611,179,112✔
970
      break;
130,468,377✔
971
    }
972

973
    if (isTaskKilled(pTaskInfo)) {
480,710,735✔
974
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
53,511✔
975
      code = pTaskInfo->code;
53,511✔
976
      goto _end;
53,511✔
977
    }
978

979
    if (pOperator->status == OP_EXEC_DONE) {
481,084,015✔
980
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
81,480✔
981
      break;
81,480✔
982
    }
983

984
    // process this data block based on the probabilities
985
    bool processThisBlock = processBlockWithProbability(&pTableScanInfo->sample);
480,970,470✔
986
    if (!processThisBlock) {
480,793,285!
987
      continue;
×
988
    }
989

990
    if (pBlock->info.id.uid) {
480,793,285!
991
      pBlock->info.id.groupId = tableListGetTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid);
480,986,438✔
992
    }
993

994
    uint32_t status = 0;
481,042,782✔
995
    code = loadDataBlock(pOperator, &pTableScanInfo->base, pBlock, &status);
481,118,121✔
996
    QUERY_CHECK_CODE(code, lino, _end);
480,968,428✔
997

998
    if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
480,968,173✔
999
      break;
45,942✔
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) {
480,922,231✔
1004
      continue;
24,471,002✔
1005
    }
1006

1007
    pOperator->resultInfo.totalRows = pTableScanInfo->base.readRecorder.totalRows;
456,566,035✔
1008
    pTableScanInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
456,544,041✔
1009

1010
    pOperator->cost.totalCost = pTableScanInfo->base.readRecorder.elapsedTime;
456,576,457✔
1011
    pBlock->info.scanFlag = pTableScanInfo->base.scanFlag;
456,576,296✔
1012

1013
    (*ppRes) = pBlock;
456,561,001✔
1014
    return code;
456,505,439✔
1015
  }
1016

1017
_end:
130,643,703✔
1018
  if (code != TSDB_CODE_SUCCESS) {
130,646,274✔
1019
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
54,558!
1020
    pTaskInfo->code = code;
54,558✔
1021
    T_LONG_JMP(pTaskInfo->env, code);
53,766!
1022
  }
1023
  return code;
130,591,790✔
1024
}
1025

1026
static int32_t doGroupedTableScan(SOperatorInfo* pOperator, SSDataBlock** pBlock) {
609,414,366✔
1027
  int32_t         code = TSDB_CODE_SUCCESS;
609,414,366✔
1028
  int32_t         lino = 0;
609,414,366✔
1029
  STableScanInfo* pTableScanInfo = pOperator->info;
609,414,366✔
1030
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
609,579,417✔
1031
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
609,550,362✔
1032

1033
  QRY_PARAM_CHECK(pBlock);
609,511,665!
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) {
609,417,292✔
1037
    return code;
2,589,112✔
1038
  }
1039

1040
  // do the ascending order traverse in the first place.
1041
  while (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) {
725,064,194✔
1042
    SSDataBlock* p = NULL;
531,743,882✔
1043
    code = doTableScanImplNext(pOperator, &p);
531,737,454✔
1044
    QUERY_CHECK_CODE(code, lino, _end);
531,696,823!
1045

1046
    if (p != NULL) {
531,696,823✔
1047
      markGroupProcessed(pTableScanInfo, p->info.id.groupId);
413,665,977✔
1048
      *pBlock = p;
413,695,020✔
1049
      return code;
413,716,874✔
1050
    }
1051

1052
    pTableScanInfo->scanTimes += 1;
118,030,846✔
1053
    taosHashClear(pTableScanInfo->pIgnoreTables);
118,037,587✔
1054

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

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

1067
  int32_t total = pTableScanInfo->scanInfo.numOfAsc + pTableScanInfo->scanInfo.numOfDesc;
193,232,828✔
1068
  if (pTableScanInfo->scanTimes < total) {
193,231,638✔
1069
    if (pTableScanInfo->base.cond.order == TSDB_ORDER_ASC) {
55,294,145✔
1070
      prepareForDescendingScan(&pTableScanInfo->base, pOperator->exprSupp.pCtx, 0);
114,021✔
1071
      code = pAPI->tsdReader.tsdReaderResetStatus(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond);
114,021✔
1072
      QUERY_CHECK_CODE(code, lino, _end);
114,021!
1073
      qDebug("%s start to descending order scan data blocks due to query func required", GET_TASKID(pTaskInfo));
114,021!
1074
    }
1075

1076
    while (pTableScanInfo->scanTimes < total) {
67,835,324✔
1077
      SSDataBlock* p = NULL;
55,282,535✔
1078
      code = doTableScanImplNext(pOperator, &p);
55,285,243✔
1079
      QUERY_CHECK_CODE(code, lino, _end);
55,199,017!
1080

1081
      if (p != NULL) {
55,199,017✔
1082
        markGroupProcessed(pTableScanInfo, p->info.id.groupId);
42,640,987✔
1083
        *pBlock = p;
42,676,383✔
1084
        return code;
42,733,251✔
1085
      }
1086

1087
      pTableScanInfo->scanTimes += 1;
12,558,030✔
1088
      taosHashClear(pTableScanInfo->pIgnoreTables);
12,557,427✔
1089

1090
      if (pTableScanInfo->scanTimes < total) {
12,556,560!
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);
1,456!
1097
      }
1098
    }
1099
  }
1100

1101
  if (pTableScanInfo->countState < TABLE_COUNT_STATE_END) {
150,490,898✔
1102
    STableListInfo* pTableListInfo = pTableScanInfo->base.pTableListInfo;
28,200,637✔
1103
    if (pTableListInfo->groupOffset) {  // group by tbname, group by tag + sort
28,200,295✔
1104
      if (pTableScanInfo->countState < TABLE_COUNT_STATE_PROCESSED) {
156,610✔
1105
        pTableScanInfo->countState = TABLE_COUNT_STATE_PROCESSED;
1,156✔
1106
        STableKeyInfo* pStart =
1107
            (STableKeyInfo*)tableListGetInfo(pTableScanInfo->base.pTableListInfo, pTableScanInfo->tableStartIndex);
1,156✔
1108

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

1113
        *pBlock = getBlockForEmptyTable(pOperator, pStart);
1,156✔
1114
        return code;
1,156✔
1115
      }
1116
    } else {  // group by tag + no sort
1117
      int32_t numOfTables = 0;
28,046,856✔
1118
      code = tableListGetSize(pTableListInfo, &numOfTables);
28,047,298✔
1119
      QUERY_CHECK_CODE(code, lino, _end);
28,048,592!
1120

1121
      if (pTableScanInfo->tableEndIndex + 1 >= numOfTables) {
28,048,592✔
1122
        // get empty group, mark processed & rm from hash
1123
        void* pIte = taosHashIterate(pTableListInfo->remainGroups, NULL);
27,841,331✔
1124
        if (pIte != NULL) {
27,840,600✔
1125
          size_t        keySize = 0;
20,116,550✔
1126
          uint64_t*     pGroupId = taosHashGetKey(pIte, &keySize);
20,116,771✔
1127
          STableKeyInfo info = {.uid = *(uint64_t*)pIte, .groupId = *pGroupId};
20,114,119✔
1128
          taosHashCancelIterate(pTableListInfo->remainGroups, pIte);
20,117,213✔
1129
          markGroupProcessed(pTableScanInfo, *pGroupId);
20,115,887✔
1130
          *pBlock = getBlockForEmptyTable(pOperator, &info);
20,113,014✔
1131

1132
          return code;
20,117,655✔
1133
        }
1134
      }
1135
    }
1136
    pTableScanInfo->countState = TABLE_COUNT_STATE_END;
8,086,802✔
1137
  }
1138

1139
_end:
122,267,737✔
1140
  if (code != TSDB_CODE_SUCCESS) {
130,349,119!
1141
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1142
    pTaskInfo->code = code;
×
1143
  }
1144

1145
  return code;
130,349,119✔
1146
}
1147

1148
static int32_t createTableListInfoFromParam(SOperatorInfo* pOperator) {
361,984✔
1149
  STableScanInfo*          pInfo = pOperator->info;
361,984✔
1150
  SExecTaskInfo*           pTaskInfo = pOperator->pTaskInfo;
361,984✔
1151
  int32_t                  code = 0;
361,984✔
1152
  STableListInfo*          pListInfo = pInfo->base.pTableListInfo;
361,984✔
1153
  STableScanOperatorParam* pParam = (STableScanOperatorParam*)pOperator->pOperatorGetParam->value;
361,984✔
1154
  int32_t                  num = taosArrayGetSize(pParam->pUidList);
361,984✔
1155
  if (num <= 0) {
361,984!
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",
361,984!
1161
         pTaskInfo->id.vgId, num, pParam->tableSeq, (int64_t)taosArrayGetSize(pListInfo->pTableList),
1162
         pOperator->status);
1163

1164
  if (pParam->tableSeq) {
361,984!
1165
    pListInfo->oneTableForEachGroup = true;
3,684✔
1166
    if (taosArrayGetSize(pListInfo->pTableList) > 0) {
3,684!
1167
      taosHashClear(pListInfo->map);
×
1168
      taosArrayClear(pListInfo->pTableList);
×
1169
      pOperator->status = OP_EXEC_DONE;
×
1170
    }
1171
  } else {
1172
    pListInfo->oneTableForEachGroup = false;
358,300✔
1173
    pListInfo->numOfOuputGroups = 1;
358,300✔
1174
  }
1175

1176
  STableKeyInfo info = {.groupId = 0};
361,984✔
1177
  int32_t       tableIdx = 0;
361,984✔
1178
  for (int32_t i = 0; i < num; ++i) {
4,932,265✔
1179
    uint64_t* pUid = taosArrayGet(pParam->pUidList, i);
4,570,281✔
1180
    if (!pUid) {
4,570,566!
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))) {
4,570,566✔
1186
      if (TSDB_CODE_DUP_KEY == terrno) {
3,845,427!
1187
        continue;
3,845,427✔
1188
      }
1189
      return terrno;
×
1190
    }
1191

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

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

1202
  return code;
361,984✔
1203
}
1204

1205
static int32_t doInitReader(STableScanInfo* pInfo, SExecTaskInfo* pTaskInfo, SStorageAPI* pAPI, int32_t* pNum,
153,123,672✔
1206
                            STableKeyInfo** pList) {
1207
  const char* idStr = GET_TASKID(pTaskInfo);
153,123,672✔
1208
  int32_t     code = initNextGroupScan(pInfo, pList, pNum);
153,146,012✔
1209
  if (code) {
153,110,731!
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) {
153,110,731!
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,
306,228,027✔
1220
                                       (void**)&pInfo->base.dataReader, idStr, &pInfo->pIgnoreTables);
153,115,978✔
1221
  if (code) {
153,096,626✔
1222
    qError("%s failed to open tsdbReader, code:%s at line:%d", idStr, tstrerror(code), __LINE__);
6,775!
1223
  }
1224

1225
  return code;
153,068,519✔
1226
}
1227

1228
int compareColIdPair(const void* elem1, const void* elem2) {
172,721,706✔
1229
  SColIdPair* node1 = (SColIdPair*)elem1;
172,721,706✔
1230
  SColIdPair* node2 = (SColIdPair*)elem2;
172,721,706✔
1231

1232
  if (node1->orgColId < node2->orgColId) {
172,721,706✔
1233
    return -1;
172,537,626✔
1234
  }
1235

1236
  return node1->orgColId > node2->orgColId;
184,080✔
1237
}
1238

1239
static bool isNewScanParam(STableScanOperatorParam* pParam) {
27,727,798✔
1240
  return pParam->window.skey == INT64_MAX && pParam->window.ekey == INT64_MIN;
27,727,798✔
1241
}
27,727,798✔
1242

27,727,798✔
1243
static int32_t createVTableScanInfoFromParam(SOperatorInfo* pOperator) {
27,727,798✔
1244
  int32_t                  code = 0;
27,727,798✔
1245
  int32_t                  lino = 0;
27,728,342✔
1246
  STableScanInfo*          pInfo = pOperator->info;
27,728,342✔
1247
  SExecTaskInfo*           pTaskInfo = pOperator->pTaskInfo;
27,727,798✔
1248
  SStorageAPI*             pAPI = &pTaskInfo->storageAPI;
27,728,342✔
1249
  STableListInfo*          pListInfo = pInfo->base.pTableListInfo;
27,727,798✔
1250
  STableScanOperatorParam* pParam = (STableScanOperatorParam*)pOperator->pOperatorGetParam->value;
27,727,798✔
1251
  SMetaReader              orgTable = {0};
27,727,798✔
1252
  SMetaReader              superTable = {0};
27,727,798✔
1253
  SSchemaWrapper*          schema = NULL;
27,727,798✔
1254
  SArray*                  pColArray = NULL;
1255
  SArray*                  pBlockColArray = NULL;
27,727,798✔
1256
  int32_t                  num = 0;
27,727,798!
1257
  STableKeyInfo*           pList = NULL;
27,728,342✔
1258

1259
  cleanupQueryTableDataCond(&pInfo->base.cond);
27,727,798✔
1260

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

1283
  pListInfo->oneTableForEachGroup = true;
27,728,342✔
1284
  taosHashClear(pListInfo->map);
27,728,342!
1285
  taosArrayClear(pListInfo->pTableList);
27,728,342✔
1286

27,728,342!
1287
  uint64_t      pUid = orgTable.me.uid;
1288
  STableKeyInfo info = {.groupId = 0, .uid = pUid};
1289
  int32_t       tableIdx = 0;
27,728,342✔
1290
  code = taosHashPut(pListInfo->map, &pUid, sizeof(uint64_t), &tableIdx, sizeof(int32_t));
27,728,342!
1291
  QUERY_CHECK_CODE(code, lino, _return);
1292
  QUERY_CHECK_NULL(taosArrayPush(pListInfo->pTableList, &info), code, lino, _return, terrno);
68,592,330✔
1293
  qDebug("add dynamic table scan uid:%" PRIu64 ", %s", info.uid, GET_TASKID(pTaskInfo));
40,864,532✔
1294

318,938,518!
1295
  pColArray = taosArrayInit(schema->nCols, sizeof(SColIdPair));
318,938,518!
1296
  QUERY_CHECK_NULL(pColArray, code, lino, _return, terrno);
40,864,532✔
1297
  pBlockColArray = taosArrayInit(schema->nCols, sizeof(int32_t));
40,863,988!
1298
  QUERY_CHECK_NULL(pBlockColArray, code, lino, _return, terrno);
40,863,988✔
1299

1300
  // virtual table's origin table scan do not has ts column.
1301
  SColIdPair tsPair = {.vtbColId = PRIMARYKEY_TIMESTAMP_COL_ID, .orgColId = PRIMARYKEY_TIMESTAMP_COL_ID};
1302
  QUERY_CHECK_NULL(taosArrayPush(pColArray, &tsPair), code, lino, _return, terrno);
1303

96,321,216✔
1304
  for (int32_t i = 0; i < taosArrayGetSize(pParam->pOrgTbInfo->colMap); ++i) {
68,592,874✔
1305
    SColIdNameKV* kv = taosArrayGet(pParam->pOrgTbInfo->colMap, i);
333,706,844!
1306
    for (int32_t j = 0; j < schema->nCols; j++) {
333,706,844✔
1307
      if (strcmp(kv->colName, schema->pSchema[j].name) == 0) {
333,706,844✔
1308
        SColIdPair pPair = {.vtbColId = kv->colId, .orgColId = (col_id_t)(j + 1)};
68,592,874✔
1309
        QUERY_CHECK_NULL(taosArrayPush(pColArray, &pPair), code, lino, _return, terrno);
68,592,874!
1310
        break;
68,592,874✔
1311
      }
1312
    }
1313
  }
1314

1315
  for (int32_t i = 0; i < taosArrayGetSize(pColArray); i++) {
27,728,342✔
1316
    SColIdPair* pPair = (SColIdPair*)taosArrayGet(pColArray, i);
25,032,729✔
1317
    for (int32_t j = 0; j < taosArrayGetSize(pInfo->base.matchInfo.pList); j++) {
25,032,729✔
1318
      SColMatchItem* pItem = taosArrayGet(pInfo->base.matchInfo.pList, j);
1319
      if (pItem->colId == pPair->vtbColId) {
27,728,342✔
1320
        SColIdPair tmpPair = {.orgColId = pPair->orgColId, .vtbColId = pItem->dstSlotId};
27,728,342✔
1321
        QUERY_CHECK_NULL(taosArrayPush(pBlockColArray, &tmpPair), code, lino, _return, terrno);
27,728,342✔
1322
        break;
27,728,342!
1323
      }
1324
    }
27,728,342✔
1325
  }
27,728,342!
1326

27,728,342✔
1327
  taosArraySort(pColArray, compareColIdPair);
20,648,908✔
1328
  taosArraySort(pBlockColArray, compareColIdPair);
1329

27,728,342✔
1330
  code = initQueryTableDataCondWithColArray(&pInfo->base.cond, &pInfo->base.orgCond, &pInfo->base.readHandle, pColArray);
27,728,342✔
1331
  QUERY_CHECK_CODE(code, lino, _return);
27,728,342✔
1332

1333
  if (pInfo->pResBlock) {
27,728,342✔
1334
    blockDataDestroy(pInfo->pResBlock);
27,728,342✔
1335
    pInfo->pResBlock = NULL;
27,728,342✔
1336
  }
1337

27,728,342✔
1338
  if (pParam->window.ekey > 0) {
27,728,342✔
1339
    pInfo->base.cond.twindows.skey = pParam->window.ekey + 1;
27,728,342✔
1340
  } else if (isNewScanParam(pParam)) {
27,728,342✔
1341
    pInfo->base.cond.twindows.skey = pInfo->base.orgCond.twindows.skey;
27,728,342!
1342
    pInfo->base.cond.twindows.ekey = pInfo->base.orgCond.twindows.ekey;
55,456,684!
1343
  }
27,728,342✔
1344
  pInfo->base.cond.suid = orgTable.me.type == TSDB_CHILD_TABLE ? superTable.me.uid : 0;
1345
  pInfo->currentGroupId = 0;
27,728,342✔
1346
  pInfo->ignoreTag = true;
1347

27,728,342✔
1348
  code = createOneDataBlockWithColArray(pInfo->pOrgBlock, pBlockColArray, &pInfo->pResBlock);
27,728,342✔
1349
  QUERY_CHECK_CODE(code, lino, _return);
27,728,342✔
1350

27,727,798!
1351
  void **reader = taosHashGet(pInfo->readerCache, &pUid, sizeof(uint64_t));
1352
  if (reader) {
27,727,798!
NEW
1353
    if (isNewScanParam(pParam)) {
×
1354
      pAPI->tsdReader.tsdReaderClose(*reader);
1355
      pInfo->base.dataReader = NULL;
1356

27,728,342✔
1357
      code = taosHashRemove(pInfo->readerCache, &pUid, sizeof(uint64_t));
27,727,254✔
1358
      QUERY_CHECK_CODE(code, lino, _return);
27,728,342!
NEW
1359

×
1360
      taosRLockLatch(&pTaskInfo->lock);
1361
      code = doInitReader(pInfo, pTaskInfo, pAPI, &num, &pList);
27,728,342✔
1362
      taosRUnLockLatch(&pTaskInfo->lock);
27,727,254✔
1363
      QUERY_CHECK_CODE(code, lino, _return);
27,727,798✔
1364

27,727,798✔
1365
      code = taosHashPut(pInfo->readerCache, &pUid, sizeof(uint64_t), &pInfo->base.dataReader, POINTER_BYTES);
27,728,342✔
1366
      QUERY_CHECK_CODE(code, lino, _return);
1367
      pInfo->newReader = true;
1368
    } else {
159,242,418✔
1369
      pInfo->base.dataReader = *reader;
159,242,418✔
1370
      code = blockDataEnsureCapacity(pInfo->pResBlock, pOperator->resultInfo.capacity);
159,242,418✔
1371
      QUERY_CHECK_CODE(code, lino, _return);
159,242,418✔
1372

159,245,434✔
1373
      pAPI->tsdReader.tsdReaderSetDatablock(pInfo->base.dataReader, pInfo->pResBlock);
159,240,848✔
1374
      pInfo->newReader = false;
159,252,802✔
1375
      pInfo->scanTimes = 0;
1376
    }
159,238,442!
1377
  } else {
1378
    pInfo->base.dataReader = NULL;
159,232,093✔
1379

159,236,762!
1380
    taosRLockLatch(&pTaskInfo->lock);
1381
    code = doInitReader(pInfo, pTaskInfo, pAPI, &num, &pList);
159,236,762✔
1382
    taosRUnLockLatch(&pTaskInfo->lock);
131,196,184✔
1383
    QUERY_CHECK_CODE(code, lino, _return);
131,185,426!
1384

7,374,875✔
1385
    code = taosHashPut(pInfo->readerCache, &pUid, sizeof(uint64_t), &pInfo->base.dataReader, POINTER_BYTES);
7,376,049✔
1386
    QUERY_CHECK_CODE(code, lino, _return);
1387
    pInfo->newReader = true;
131,191,611✔
1388
  }
1389
  pOperator->status = OP_OPENED;
1390
  
1391
  if (pInfo->pResBlock->info.capacity > pOperator->resultInfo.capacity) {
28,045,596✔
1392
    pOperator->resultInfo.capacity = pInfo->pResBlock->info.capacity;
28,046,140✔
1393
  }
1394

28,046,140✔
1395
  pInfo->currentGroupId = -1;
28,046,140✔
1396
_return:
28,046,140✔
1397
  if (code) {
28,046,140!
1398
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
1399
  }
28,046,140✔
1400
  taosArrayDestroy(pColArray);
28,046,684!
1401
  taosArrayDestroy(pBlockColArray);
1402
  pAPI->metaReaderFn.clearReader(&superTable);
28,046,684✔
1403
  pAPI->metaReaderFn.clearReader(&orgTable);
28,046,684!
1404
  return code;
28,046,684✔
1405
}
1406

28,046,684✔
1407
static int32_t startNextGroupScan(SOperatorInfo* pOperator, SSDataBlock** pResult) {
28,046,684!
1408
  int32_t         code = TSDB_CODE_SUCCESS;
1409
  int32_t         lino = 0;
28,046,684✔
1410
  STableScanInfo* pInfo = pOperator->info;
20,965,929!
1411
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
20,701,060✔
1412
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
1413
  int32_t         numOfTables = 0;
20,965,929✔
1414

1415
  QRY_PARAM_CHECK(pResult);
1416

7,080,755✔
1417
  code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
7,080,755!
UNCOV
1418
  QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
1419

×
1420
  if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) {
1421
    setOperatorCompleted(pOperator);
7,080,755✔
1422
    if (pOperator->dynamicTask) {
1423
      taosArrayClear(pInfo->base.pTableListInfo->pTableList);
1424
      taosHashClear(pInfo->base.pTableListInfo->map);
578,490,145✔
1425
    }
578,490,145✔
1426
    return code;
578,490,145✔
1427
  }
578,490,145✔
1428

578,646,691✔
1429
  // reset value for the next group data output
578,646,881✔
1430
  pOperator->status = OP_OPENED;
578,634,027✔
1431
  resetLimitInfoForNextGroup(&pInfo->base.limitInfo);
578,699,098✔
1432

578,549,766✔
1433
  int32_t        num = 0;
578,724,288✔
1434
  STableKeyInfo* pList = NULL;
1435
  code = initNextGroupScan(pInfo, &pList, &num);
578,710,048!
1436
  QUERY_CHECK_CODE(code, lino, _end);
1437

578,725,322✔
1438
  code = pAPI->tsdReader.tsdSetQueryTableList(pInfo->base.dataReader, pList, num);
125,404,654!
UNCOV
1439
  QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
1440

×
1441
  code = pAPI->tsdReader.tsdReaderResetStatus(pInfo->base.dataReader, &pInfo->base.cond);
1442
  QUERY_CHECK_CODE(code, lino, _end);
1443
  pInfo->scanTimes = 0;
125,408,711✔
1444

125,418,595✔
1445
  code = doGroupedTableScan(pOperator, pResult);
125,366,229✔
1446
  QUERY_CHECK_CODE(code, lino, _end);
125,404,212✔
1447

1448
  if (*pResult != NULL) {
125,397,437!
1449
    if (pOperator->dynamicTask) {
358,364✔
1450
      (*pResult)->info.id.groupId = (*pResult)->info.id.uid;
1451
    }
1452
    return code;
125,397,255!
UNCOV
1453
  }
×
1454

1455
_end:
1456
  if (code != TSDB_CODE_SUCCESS) {
1457
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
578,694,976✔
1458
    pTaskInfo->code = code;
578,393,774!
1459
  }
1460
  return code;
578,393,774✔
1461
}
454,208,670!
1462

668,473✔
1463
static int32_t groupSeqTableScan(SOperatorInfo* pOperator, SSDataBlock** pResBlock) {
1464
  int32_t         code = TSDB_CODE_SUCCESS;
1465
  int32_t         lino = 0;
454,222,732✔
1466
  STableScanInfo* pInfo = pOperator->info;
453,987,530✔
1467
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
1468
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
1469
  int32_t         num = 0;
1470
  STableKeyInfo*  pList = NULL;
124,250,659✔
1471
  SSDataBlock*    pResult = NULL;
124,514,107!
1472
  const char*     idStr = GET_TASKID(pTaskInfo);
1473

124,514,107✔
1474
  QRY_PARAM_CHECK(pResBlock);
124,445,547✔
1475

124,437,814✔
1476
  if (pInfo->currentGroupId == -1) {
1477
    if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) {
1478
      setOperatorCompleted(pOperator);
1479
      return code;
6,775✔
1480
    }
6,775!
1481

6,775!
1482
    taosRLockLatch(&pTaskInfo->lock);
6,775✔
1483
    code = doInitReader(pInfo, pTaskInfo, pAPI, &num, &pList);
1484
    taosRUnLockLatch(&pTaskInfo->lock);
1485
    QUERY_CHECK_CODE(code, lino, _end);
6,775✔
1486

1487
    if (pInfo->filesetDelimited) {
1488
      pAPI->tsdReader.tsdSetFilesetDelimited(pInfo->base.dataReader);
27,728,342✔
1489
    }
27,728,342!
1490

1491
    if (pInfo->pResBlock->info.capacity > pOperator->resultInfo.capacity) {
1492
      pOperator->resultInfo.capacity = pInfo->pResBlock->info.capacity;
607,829,853✔
1493
    }
607,829,853✔
1494
  }
607,829,853✔
1495

607,829,853✔
1496
  code = doGroupedTableScan(pOperator, &pResult);
607,940,824✔
1497
  QUERY_CHECK_CODE(code, lino, _end);
607,952,335✔
1498

607,971,459!
1499
  if (pResult != NULL) {
607,906,119!
1500
    if (pOperator->dynamicTask) {
607,906,119✔
1501
      pResult->info.id.groupId = pResult->info.id.uid;
28,089,782✔
1502
    }
28,090,326✔
1503

27,728,342✔
1504
    *pResBlock = pResult;
1505
    return code;
27,727,798✔
1506
  }
27,728,342✔
1507

27,727,798!
1508
  while (true) {
1509
    code = startNextGroupScan(pOperator, &pResult);
27,727,798✔
1510
    QUERY_CHECK_CODE(code, lino, _end);
27,728,342!
1511

13,924✔
1512
    if (pResult || pOperator->status == OP_EXEC_DONE) {
13,924✔
1513
      *pResBlock = pResult;
1514
      return code;
1515
    }
34,729,074✔
1516
  }
34,729,618!
1517

1518
_end:
34,729,618✔
1519
  if (code != TSDB_CODE_SUCCESS) {
27,714,418✔
1520
    qError("%s %s failed at line %d since %s", idStr, __func__, lino, tstrerror(code));
27,714,418✔
1521
    pTaskInfo->code = code;
20,699,218✔
1522
  }
20,699,218!
1523

20,699,218✔
1524
  return code;
20,699,218✔
1525
}
1526

27,714,418✔
1527
static bool isEmptyQueryTimeWindow(STimeWindow* pWindow) {
27,714,418✔
1528
  return (pWindow == NULL) || (pWindow->skey > pWindow->ekey);
1529
}
1530

1531
int32_t doTableScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
361,984✔
1532
  int32_t         code = TSDB_CODE_SUCCESS;
361,984✔
1533
  int32_t         lino = 0;
361,984✔
1534
  STableScanInfo* pInfo = pOperator->info;
361,984!
1535
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
1536
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
361,984✔
1537
  QRY_PARAM_CHECK(ppRes);
1,842✔
1538
  qTrace("%s call", __FUNCTION__);
1,842✔
1539
  if (pOperator->pOperatorGetParam) {
1,842✔
1540
    pOperator->dynamicTask = true;
1541
    if (isDynVtbScan(pOperator)) {
1542
      code = createVTableScanInfoFromParam(pOperator);
1,842✔
1543

1,842!
1544
      freeOperatorParam(pOperator->pOperatorGetParam, OP_GET_PARAM);
1545
      pOperator->pOperatorGetParam = NULL;
1,842!
1546
      QUERY_CHECK_CODE(code, lino, _end);
1,842✔
1547

1,842✔
1548
      SSDataBlock* result = NULL;
1549
      if (isEmptyQueryTimeWindow(&pInfo->base.cond.twindows) && pInfo->base.cond.type == TIMEWINDOW_RANGE_CONTAINED) {
1550
        (*ppRes) = result;
1551
        return code;
1552
      }
1553

1554
      if (pInfo->newReader) {
1555
        code = startNextGroupScan(pOperator, &result);
580,204,905✔
1556
        QUERY_CHECK_CODE(code, lino, _end);
1,504,316✔
1557
      } else {
1,504,316✔
1558
        code = doGroupedTableScan(pOperator, &result);
1,504,316✔
1559
        QUERY_CHECK_CODE(code, lino, _end);
1560
      }
1,399,657✔
1561

2,903,973✔
1562
      if (result) {
2,903,964✔
1563
        SSDataBlock* res = NULL;
2,900,893!
1564
        pAPI->tsdReader.tsdReaderSetDatablock(pInfo->base.dataReader, NULL);
1565
        code = createOneDataBlockWithTwoBlock(result, pInfo->pOrgBlock, &res);
2,900,893!
1566
        QUERY_CHECK_CODE(code, lino, _end);
1,488,429✔
1567
        pInfo->pResBlock = res;
1,489,385✔
1568
        blockDataDestroy(result);
1569
        (*ppRes) = res;
1570
      } else {
1571
        STableKeyInfo *keyInfo = taosArrayGet(pInfo->base.pTableListInfo->pTableList, 0);
1,414,001✔
1572
        QUERY_CHECK_NULL(keyInfo, code, lino, _end, terrno)
1573

1,413,628✔
1574
        blockDataDestroy(pInfo->pResBlock);
1,414,397✔
1575
        pInfo->pResBlock = NULL;
1,414,397✔
1576

1,412,827!
NEW
1577
        void** reader = taosHashGet(pInfo->readerCache, &keyInfo->uid, sizeof(uint64_t));
×
NEW
1578
        if (reader) {
×
1579
          if (*reader == pInfo->base.dataReader) {
1580
            pAPI->tsdReader.tsdReaderSetDatablock(pInfo->base.dataReader, NULL);
1581
            pInfo->base.dataReader = NULL;
1,412,827✔
1582
          }
13,971!
1583
          if (pAPI->tsdReader.tsdReaderClose) {
13,971✔
1584
            pAPI->tsdReader.tsdReaderClose(*reader);
13,971✔
1585
          }
13,971✔
1586
        }
1587

1588
        code = taosHashRemove(pInfo->readerCache, &keyInfo->uid, sizeof(uint64_t));
1,398,712✔
1589
        QUERY_CHECK_CODE(code, lino, _end);
1,398,141!
UNCOV
1590
      }
×
NEW
1591
      return code;
×
UNCOV
1592
    } else {
×
1593
      code = createTableListInfoFromParam(pOperator);
1594
      freeOperatorParam(pOperator->pOperatorGetParam, OP_GET_PARAM);
1595
      pOperator->pOperatorGetParam = NULL;
1,398,141✔
1596
      QUERY_CHECK_CODE(code, lino, _end);
1,397,855✔
1597

1598
      if (pOperator->status == OP_EXEC_DONE) {
1,400,745✔
1599
        pInfo->currentGroupId = -1;
1,400,027!
1600
        pOperator->status = OP_OPENED;
1,400,027✔
1601
        SSDataBlock* result = NULL;
1602

1603
        while (true) {
1,402,696✔
1604
          code = startNextGroupScan(pOperator, &result);
1,399,646!
1605
          QUERY_CHECK_CODE(code, lino, _end);
1,399,646✔
1606

1607
          if (result || pOperator->status == OP_EXEC_DONE) {
1608
            (*ppRes) = result;
578,578,282✔
1609
            return code;
578,395,741✔
1610
          }
1611
        }
1612
      }
578,388,966✔
1613
    }
578,409,273✔
1614
  }
6,775!
1615

6,775✔
1616
  // scan table one by one sequentially
6,775!
1617
  if (pInfo->scanMode == TABLE_SCAN__TABLE_ORDER) {
1618
    int32_t       numOfTables = 0;
1619
    STableKeyInfo tInfo = {0};
578,402,498✔
1620
    pInfo->countState = TABLE_COUNT_STATE_END;
1621

1622
    while (1) {
1,048,046✔
1623
      SSDataBlock* result = NULL;
1,048,046!
1624
      code = doGroupedTableScan(pOperator, &result);
1,048,046!
UNCOV
1625
      QUERY_CHECK_CODE(code, lino, _end);
×
1626

1627
      if (result || (pOperator->status == OP_EXEC_DONE) || isTaskKilled(pTaskInfo)) {
1,048,046✔
1628
        (*ppRes) = result;
1,048,046✔
1629
        return code;
1,048,046✔
1630
      }
1,048,046✔
1631

1,048,046✔
1632
      // if no data, switch to next table and continue scan
1633
      pInfo->currentTable++;
1634

161,758,710✔
1635
      taosRLockLatch(&pTaskInfo->lock);
161,758,710✔
1636
      numOfTables = 0;
161,764,140✔
1637
      code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
1638
      if (code != TSDB_CODE_SUCCESS) {
161,765,442!
1639
        taosRUnLockLatch(&pTaskInfo->lock);
161,767,372✔
1640
        TSDB_CHECK_CODE(code, lino, _end);
1641
      }
161,717,270✔
1642

1643
      if (pInfo->currentTable >= numOfTables) {
161,728,242✔
1644
        qDebug("all table checked in table list, total:%d, return NULL, %s", numOfTables, GET_TASKID(pTaskInfo));
161,738,843✔
1645
        taosRUnLockLatch(&pTaskInfo->lock);
1646
        (*ppRes) = NULL;
1647
        return code;
161,723,380✔
1648
      }
161,758,785✔
1649

161,769,560✔
1650
      STableKeyInfo* tmp = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->currentTable);
161,766,712✔
1651
      if (!tmp) {
1652
        taosRUnLockLatch(&pTaskInfo->lock);
132,166,951✔
1653
        (*ppRes) = NULL;
132,166,951✔
1654
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
132,166,951✔
1655
      }
132,162,688✔
1656

132,163,944✔
1657
      tInfo = *tmp;
132,159,937✔
1658
      taosRUnLockLatch(&pTaskInfo->lock);
132,165,764!
1659

132,160,919✔
1660
      code = pAPI->tsdReader.tsdSetQueryTableList(pInfo->base.dataReader, &tInfo, 1);
1661
      QUERY_CHECK_CODE(code, lino, _end);
132,117,015✔
1662
      qDebug("set uid:%" PRIu64 " into scanner, total tables:%d, index:%d/%d %s", tInfo.uid, numOfTables,
132,117,015!
1663
             pInfo->currentTable, numOfTables, GET_TASKID(pTaskInfo));
6,625,330✔
1664

15,585,577✔
1665
      code = pAPI->tsdReader.tsdReaderResetStatus(pInfo->base.dataReader, &pInfo->base.cond);
8,963,700✔
1666
      QUERY_CHECK_CODE(code, lino, _end);
8,960,689!
1667
      pInfo->scanTimes = 0;
8,960,689✔
1668
    }
1669
  } else {  // scan table group by group sequentially
1670
    code = groupSeqTableScan(pOperator, ppRes);
1671
    QUERY_CHECK_CODE(code, lino, _end);
132,113,562✔
1672
  }
1673

132,158,822✔
1674
_end:
1675
  if (code != TSDB_CODE_SUCCESS) {
1676
    qError("%s %s failed at line %d since %s", GET_TASKID(pTaskInfo), __func__, lino, tstrerror(code));
132,158,822!
1677
    pTaskInfo->code = code;
1678
    T_LONG_JMP(pTaskInfo->env, code);
132,162,620✔
1679
  }
132,162,620✔
1680

132,162,620✔
1681
  return code;
132,155,709✔
1682
}
132,152,907!
UNCOV
1683

×
UNCOV
1684
static int32_t getTableScannerExecInfo(struct SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
×
1685
  SFileBlockLoadRecorder* pRecorder = taosMemoryCalloc(1, sizeof(SFileBlockLoadRecorder));
1686
  if (!pRecorder) {
1687
    return terrno;
132,153,023✔
1688
  }
132,153,426✔
1689
  STableScanInfo* pTableScanInfo = pOptr->info;
1690
  *pRecorder = pTableScanInfo->base.readRecorder;
132,154,672✔
1691
  *pOptrExplain = pRecorder;
1692
  *len = sizeof(SFileBlockLoadRecorder);
132,155,456✔
1693
  return 0;
132,150,407!
1694
}
1695

132,150,407✔
1696
static void destroyTableScanBase(STableScanBase* pBase, TsdReader* pAPI) {
132,132,850✔
1697
  cleanupQueryTableDataCond(&pBase->cond);
132,136,037!
1698
  cleanupQueryTableDataCond(&pBase->orgCond);
1699

132,136,037✔
1700
  if (pAPI->tsdReaderClose) {
39,366,255✔
1701
    pAPI->tsdReaderClose(pBase->dataReader);
39,371,556✔
1702
  }
39,369,143✔
1703
  pBase->dataReader = NULL;
39,355,925!
1704

1705
  if (pBase->matchInfo.pList != NULL) {
39,355,925✔
1706
    taosArrayDestroy(pBase->matchInfo.pList);
1707
  }
39,347,741!
1708

1709
  tableListDestroy(pBase->pTableListInfo);
1710
  taosLRUCacheCleanup(pBase->metaCache.pTableMetaEntryCache);
132,092,824✔
1711
  cleanupExprSupp(&pBase->pseudoSup);
132,137,679✔
1712
}
1713

132,082,290✔
1714
static void destroyTableScanOperatorInfo(void* param) {
132,068,199✔
1715
  STableScanInfo* pTableScanInfo = (STableScanInfo*)param;
132,066,455✔
1716
  blockDataDestroy(pTableScanInfo->pResBlock);
1717
  blockDataDestroy(pTableScanInfo->pOrgBlock);
132,111,383✔
1718
  taosHashCleanup(pTableScanInfo->pIgnoreTables);
132,064,694✔
1719
  if (pTableScanInfo->virtualStableScan && pTableScanInfo->readerCache) {
1720
    void *pIter = taosHashIterate(pTableScanInfo->readerCache, NULL);
132,103,809✔
1721
    while (pIter != NULL) {
132,107,531✔
1722
      void **reader = pIter;
132,103,381✔
1723
      if (*reader && pTableScanInfo->base.readerAPI.tsdReaderClose) {
132,143,514✔
1724
        if (*reader == pTableScanInfo->base.dataReader) {
132,106,614!
1725
          pTableScanInfo->base.dataReader = NULL;
1726
        }
132,090,439✔
1727
        pTableScanInfo->base.readerAPI.tsdReaderClose(*reader);
132,024,813!
1728
      }
1729
      pIter = taosHashIterate(pTableScanInfo->readerCache, pIter);
132,024,813!
1730
    }
132,050,772!
1731
    taosHashCleanup(pTableScanInfo->readerCache);
3,969,446✔
1732
  }
3,970,256✔
1733
  destroyTableScanBase(&pTableScanInfo->base, &pTableScanInfo->base.readerAPI);
3,970,256!
1734
  taosMemoryFreeClear(param);
3,967,955!
1735
}
1736

1737
static void resetClolumnReserve(SSDataBlock* pBlock, int32_t dataRequireFlag) {
132,087,041✔
1738
  if (pBlock && dataRequireFlag == FUNC_DATA_REQUIRED_NOT_LOAD) {
132,044,752✔
1739
    int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
132,062,587✔
1740
    for (int32_t i = 0; i < numOfCols; ++i) {
1741
      SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
132,053,476✔
1742
      if (pCol) {
1743
        pCol->info.noData = true;
132,058,244✔
1744
      }
132,098,243!
1745
    }
132,070,680✔
1746
  }
1747
}
132,103,758✔
1748

1749
int32_t createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle,
132,039,488✔
1750
                                    STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo,
1751
                                    SOperatorInfo** pOptrInfo) {
132,020,738!
1752
  QRY_PARAM_CHECK(pOptrInfo);
132,111,563✔
1753

1754
  int32_t         code = TSDB_CODE_SUCCESS;
132,092,022✔
1755
  int32_t         lino = 0;
132,062,744✔
1756
  STableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableScanInfo));
132,107,490!
UNCOV
1757
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
×
UNCOV
1758
  if (pInfo == NULL || pOperator == NULL) {
×
1759
    code = terrno;
1760
    goto _error;
1761
  }
132,136,718!
1762

1763
  SScanPhysiNode*     pScanNode = &pTableScanNode->scan;
132,138,929✔
1764
  SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc;
132,139,186✔
1765

1766
  int32_t numOfCols = 0;
1767
  code =
1768
      extractColMatchInfo(pScanNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID, &pInfo->base.matchInfo);
132,108,780✔
1769
  QUERY_CHECK_CODE(code, lino, _error);
132,082,359✔
1770

132,011,137✔
1771
  initLimitInfo(pScanNode->node.pLimit, pScanNode->node.pSlimit, &pInfo->base.limitInfo);
1772
  code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, readHandle);
9,111✔
1773
  QUERY_CHECK_CODE(code, lino, _error);
9,111!
1774

9,366✔
1775
  if (pScanNode->pScanPseudoCols != NULL) {
9,366✔
1776
    SExprSupp* pSup = &pInfo->base.pseudoSup;
1777
    pSup->pExprInfo = NULL;
1778
    code = createExprInfo(pScanNode->pScanPseudoCols, NULL, &pSup->pExprInfo, &pSup->numOfExprs);
9,111!
1779
    QUERY_CHECK_CODE(code, lino, _error);
9,111✔
1780

9,366✔
1781
    pSup->pCtx = createSqlFunctionCtx(pSup->pExprInfo, pSup->numOfExprs, &pSup->rowEntryInfoOffset,
1782
                                      &pTaskInfo->storageAPI.functionStore);
9,366✔
1783
    QUERY_CHECK_NULL(pSup->pCtx, code, lino, _error, terrno);
9,111✔
1784
  }
1785

UNCOV
1786
  pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]};
×
UNCOV
1787
  pInfo->base.scanFlag = (pInfo->scanInfo.numOfAsc > 1) ? PRE_SCAN : MAIN_SCAN;
×
1788

UNCOV
1789
  pInfo->base.pdInfo.interval = extractIntervalInfo(pTableScanNode);
×
UNCOV
1790
  pInfo->base.readHandle = *readHandle;
×
UNCOV
1791
  pInfo->base.dataBlockLoadFlag = pTableScanNode->dataRequired;
×
UNCOV
1792

×
UNCOV
1793
  pInfo->sample.sampleRatio = pTableScanNode->ratio;
×
UNCOV
1794
  pInfo->sample.seed = taosGetTimestampSec();
×
1795

1796
  pInfo->base.readerAPI = pTaskInfo->storageAPI.tsdReader;
UNCOV
1797
  initResultSizeInfo(&pOperator->resultInfo, 4096);
×
1798
  pInfo->pResBlock = createDataBlockFromDescNode(pDescNode);
1799
  resetClolumnReserve(pInfo->pResBlock, pInfo->base.dataBlockLoadFlag);
UNCOV
1800
  QUERY_CHECK_NULL(pInfo->pResBlock, code, lino, _error, terrno);
×
1801

UNCOV
1802
  code = prepareDataBlockBuf(pInfo->pResBlock, &pInfo->base.matchInfo);
×
1803
  QUERY_CHECK_CODE(code, lino, _error);
UNCOV
1804

×
UNCOV
1805
  pInfo->virtualStableScan = pScanNode->virtualStableScan;
×
1806
  if (pScanNode->node.dynamicOp && pScanNode->virtualStableScan) {
UNCOV
1807
    TSWAP(pInfo->pOrgBlock, pInfo->pResBlock);
×
UNCOV
1808
    pInfo->pResBlock = NULL;
×
UNCOV
1809
    memcpy(&pInfo->base.orgCond, &pInfo->base.cond, sizeof(SQueryTableDataCond));
×
1810
    memset(&pInfo->base.cond, 0, sizeof(SQueryTableDataCond));
1811
  }
UNCOV
1812

×
NEW
1813
  if (pInfo->virtualStableScan) {
×
1814
    pInfo->readerCache = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
1815
    QUERY_CHECK_NULL(pInfo->readerCache, code, lino, _error, terrno);
NEW
1816
  }
×
NEW
1817

×
1818
  code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0,
1819
                            pTaskInfo->pStreamRuntimeInfo);
UNCOV
1820
  QUERY_CHECK_CODE(code, lino, _error);
×
UNCOV
1821

×
UNCOV
1822
  pInfo->currentGroupId = -1;
×
UNCOV
1823

×
UNCOV
1824
  pInfo->tableEndIndex = -1;
×
1825
  pInfo->assignBlockUid = pTableScanNode->assignBlockUid;
UNCOV
1826
  pInfo->hasGroupByTag = pTableScanNode->pGroupTags ? true : false;
×
UNCOV
1827

×
UNCOV
1828
  setOperatorInfo(pOperator, "TableScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, false, OP_NOT_OPENED, pInfo,
×
1829
                  pTaskInfo);
UNCOV
1830
  pOperator->exprSupp.numOfExprs = numOfCols;
×
UNCOV
1831

×
1832
  pInfo->needCountEmptyTable = tsCountAlwaysReturnValue && pTableScanNode->needCountEmptyTable;
UNCOV
1833
  pInfo->ignoreTag = false;
×
1834

UNCOV
1835
  pInfo->base.pTableListInfo = pTableListInfo;
×
1836
  pInfo->base.metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024 * 128, -1, .5);
1837
  if (pInfo->base.metaCache.pTableMetaEntryCache == NULL) {
1838
    code = terrno;
×
1839
    QUERY_CHECK_CODE(code, lino, _error);
×
UNCOV
1840
  }
×
UNCOV
1841

×
UNCOV
1842
  pInfo->filesetDelimited = pTableScanNode->filesetDelimited;
×
UNCOV
1843

×
UNCOV
1844
  taosLRUCacheSetStrictCapacity(pInfo->base.metaCache.pTableMetaEntryCache, false);
×
UNCOV
1845
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableScanNext, NULL, destroyTableScanOperatorInfo,
×
1846
                                         optrDefaultBufFn, getTableScannerExecInfo, optrDefaultGetNextExtFn, NULL);
UNCOV
1847

×
UNCOV
1848
  // for non-blocking operator, the open cost is always 0
×
UNCOV
1849
  pOperator->cost.openCost = 0;
×
UNCOV
1850
  *pOptrInfo = pOperator;
×
UNCOV
1851
  return TSDB_CODE_SUCCESS;
×
UNCOV
1852

×
1853
_error:
UNCOV
1854
  if (pInfo != NULL) {
×
1855
    pInfo->base.pTableListInfo = NULL;  // this attribute will be destroy outside of this function
1856
    destroyTableScanOperatorInfo(pInfo);
UNCOV
1857
  }
×
UNCOV
1858

×
1859
  if (pOperator != NULL) {
1860
    pOperator->info = NULL;
1861
    destroyOperator(pOperator);
UNCOV
1862
  }
×
UNCOV
1863
  pTaskInfo->code = code;
×
UNCOV
1864
  return code;
×
1865
}
1866

1867
int32_t createTableSeqScanOperatorInfo(void* pReadHandle, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
×
1868
  QRY_PARAM_CHECK(pOptrInfo);
×
UNCOV
1869

×
1870
  int32_t         code = 0;
×
1871
  STableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableScanInfo));
1872
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
×
1873
  if (pInfo == NULL || pOperator == NULL) {
1874
    code = terrno;
1875
    goto _end;
355,246,064✔
1876
  }
355,246,064✔
1877

355,261,234✔
1878
  pInfo->base.dataReader = pReadHandle;
1879
  //  pInfo->prevGroupId       = -1;
355,261,100!
UNCOV
1880

×
1881
  setOperatorInfo(pOperator, "TableSeqScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN, false, OP_NOT_OPENED,
1882
                  pInfo, pTaskInfo);
355,261,100✔
1883
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableScanImplNext, NULL, NULL, optrDefaultBufFn, NULL,
1884
                                         optrDefaultGetNextExtFn, NULL);
1885
  *pOptrInfo = pOperator;
1886
  return code;
23,176,048✔
1887

23,176,048✔
1888
_end:
23,176,048✔
1889
  if (pInfo != NULL) {
23,176,048✔
1890
    taosMemoryFree(pInfo);
23,178,190✔
1891
  }
23,178,071✔
1892

23,177,357✔
1893
  if (pOperator != NULL) {
23,178,190✔
1894
    taosMemoryFree(pOperator);
1895
  }
23,178,071✔
1896

23,177,952!
1897
  pTaskInfo->code = code;
1898
  return code;
23,177,952✔
1899
}
23,177,714✔
1900

23,177,952✔
1901
static int32_t doBlockDataPrimaryKeyFilter(SSDataBlock* pBlock, STqOffsetVal* offset) {
23,177,874✔
1902
  int32_t code = TSDB_CODE_SUCCESS;
1903
  int32_t lino = 0;
23,177,238✔
1904
  if (pBlock->info.window.skey != offset->ts || offset->primaryKey.type == 0) {
23,177,840!
1905
    return code;
23,177,840✔
1906
  }
1907
  bool* p = taosMemoryCalloc(pBlock->info.rows, sizeof(bool));
1908
  QUERY_CHECK_NULL(p, code, lino, _end, terrno);
×
1909
  bool hasUnqualified = false;
1910

1911
  SColumnInfoData* pColTs = taosArrayGet(pBlock->pDataBlock, 0);
23,177,833✔
1912
  SColumnInfoData* pColPk = taosArrayGet(pBlock->pDataBlock, 1);
23,176,309!
1913

1914
  qDebug("doBlockDataWindowFilter primary key, ts:%" PRId64 " %" PRId64, offset->ts,
1915
         VALUE_GET_TRIVIAL_DATUM(&offset->primaryKey));
131,563,831✔
1916
  QUERY_CHECK_CONDITION((pColPk->info.type == offset->primaryKey.type), code, lino, _end,
108,387,140✔
1917
                        TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
108,383,298!
1918

126✔
1919
  __compar_fn_t func = getComparFunc(pColPk->info.type, 0);
1920
  QUERY_CHECK_NULL(func, code, lino, _end, terrno);
1921
  for (int32_t i = 0; i < pBlock->info.rows; ++i) {
108,382,596✔
1922
    int64_t* ts = (int64_t*)colDataGetData(pColTs, i);
377,413,312!
1923
    void*    data = colDataGetData(pColPk, i);
377,263,360✔
1924
    if (IS_VAR_DATA_TYPE(pColPk->info.type)) {
377,235,169✔
1925
      if (IS_STR_DATA_BLOB(pColPk->info.type)) {
377,265,594!
1926
        QUERY_CHECK_CODE(code = TSDB_CODE_BLOB_NOT_SUPPORT_PRIMARY_KEY, lino, _end);
1927
      }
377,265,594✔
1928
      void* tmq = taosMemoryMalloc(offset->primaryKey.nData + VARSTR_HEADER_SIZE);
108,394,169✔
1929
      QUERY_CHECK_NULL(tmq, code, lino, _end, terrno);
108,390,670✔
1930
      memcpy(varDataVal(tmq), offset->primaryKey.pData, offset->primaryKey.nData);
108,344,722!
1931
      varDataLen(tmq) = offset->primaryKey.nData;
1932
      p[i] = (*ts > offset->ts) || (func(data, tmq) > 0);
108,344,722✔
1933
      taosMemoryFree(tmq);
108,344,722✔
1934
    } else {
108,388,896!
1935
      p[i] = (*ts > offset->ts) || (func(data, VALUE_GET_DATUM(&offset->primaryKey, pColPk->info.type)) > 0);
108,388,896✔
1936
    }
1937

1938
    if (!p[i]) {
1939
      hasUnqualified = true;
1940
    }
108,386,206✔
1941
  }
252✔
1942

252!
1943
  if (hasUnqualified) {
252✔
1944
    code = trimDataBlock(pBlock, pBlock->info.rows, p);
252!
1945
    QUERY_CHECK_CODE(code, lino, _end);
1946
  }
1947

1948
_end:
1949
  taosMemoryFree(p);
23,177,638!
1950
  if (code != TSDB_CODE_SUCCESS) {
24,927,624✔
1951
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
12,463,833✔
1952
  }
1953
  return code;
12,463,714!
UNCOV
1954
}
×
1955

1956
int32_t colIdComparFn(const void* param1, const void* param2) {
1957
  int32_t p1 = *(int32_t*)param1;
1958
  int32_t p2 = *(int32_t*)param2;
12,463,714✔
1959

1960
  if (p1 == p2) {
59,976,568✔
1961
    return 0;
47,513,092✔
1962
  } else {
47,513,568!
1963
    return (p1 < p2) ? -1 : 1;
1964
  }
1965
}
1966

23,168,856✔
1967
static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock) {
1968
  int32_t         code = TSDB_CODE_SUCCESS;
23,175,438✔
1969
  int32_t         lino = 0;
179,025,143✔
1970
  SDataBlockInfo* pBlockInfo = &pInfo->pRes->info;
155,859,735✔
1971
  SOperatorInfo*  pOperator = pInfo->pStreamScanOp;
155,849,705!
UNCOV
1972
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
×
UNCOV
1973
  const char*     id = GET_TASKID(pTaskInfo);
×
UNCOV
1974
  bool            isVtableSourceScan = (pTaskInfo->pSubplan->pVTables != NULL);
×
1975

1976
  code = blockDataEnsureCapacity(pInfo->pRes, pBlock->info.rows);
155,849,705✔
1977
  QUERY_CHECK_CODE(code, lino, _end);
155,849,705✔
1978

1979
  pBlockInfo->rows = pBlock->info.rows;
1980
  pBlockInfo->id.uid = pBlock->info.id.uid;
1981
  pBlockInfo->type = STREAM_NORMAL;
23,177,085✔
1982
  pBlockInfo->version = pBlock->info.version;
126✔
1983

126!
1984
  STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info;
126✔
1985
  if (!isVtableSourceScan) {
1986
    pBlockInfo->id.groupId = tableListGetTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid);
1987
  } else {
23,177,441✔
1988
    // use original table uid as groupId for vtable
1989
    pBlockInfo->id.groupId = pBlock->info.id.groupId;
23,177,942✔
1990
  }
23,176,585!
1991

1992
  SArray* pColList = taosArrayInit(4, sizeof(int32_t));
23,176,585✔
1993
  QUERY_CHECK_NULL(pColList, code, lino, _end, terrno);
23,176,415!
1994

23,176,415✔
1995
  // todo extract method
230,190✔
1996
  for (int32_t i = 0; i < taosArrayGetSize(pInfo->matchInfo.pList); ++i) {
1997
    SColMatchItem* pColMatchInfo = taosArrayGet(pInfo->matchInfo.pList, i);
1998
    if (!pColMatchInfo->needOutput) {
22,947,122✔
1999
      continue;
22,765,014!
UNCOV
2000
    }
×
2001

2002
    bool colExists = false;
22,945,755✔
2003
    for (int32_t j = 0; j < blockDataGetNumOfCols(pBlock); ++j) {
2004
      SColumnInfoData* pResCol = NULL;
2005
      code = bdGetColumnInfoData(pBlock, j, &pResCol);
1,671,224✔
2006
      QUERY_CHECK_CODE(code, lino, _end);
1,671,224✔
2007

1,671,224✔
2008
      if (pResCol->info.colId == pColMatchInfo->colId) {
1,671,224✔
2009
        SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->dstSlotId);
1,671,584!
UNCOV
2010
        code = colDataAssign(pDst, pResCol, pBlock->info.rows, &pInfo->pRes->info);
×
UNCOV
2011
        QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
2012

×
UNCOV
2013
        colExists = true;
×
2014
        void* tmp = taosArrayPush(pColList, &pColMatchInfo->dstSlotId);
UNCOV
2015
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
×
2016
        break;
UNCOV
2017
      }
×
UNCOV
2018
    }
×
2019

UNCOV
2020
    // the required column does not exists in submit block, let's set it to be all null value
×
UNCOV
2021
    if (!colExists) {
×
UNCOV
2022
      SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->dstSlotId);
×
UNCOV
2023
      colDataSetNNULL(pDst, 0, pBlockInfo->rows);
×
UNCOV
2024
      void* tmp = taosArrayPush(pColList, &pColMatchInfo->dstSlotId);
×
2025
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
UNCOV
2026
    }
×
UNCOV
2027
  }
×
UNCOV
2028

×
UNCOV
2029
  // currently only the tbname pseudo column
×
2030
  if (pInfo->numOfPseudoExpr > 0 && !isVtableSourceScan) {
UNCOV
2031
    code = addTagPseudoColumnData(&pInfo->readHandle, pInfo->pPseudoExpr, pInfo->numOfPseudoExpr, pInfo->pRes,
×
2032
                                  pBlockInfo->rows, pTaskInfo, &pTableScanInfo->base.metaCache);
2033
    // ignore the table not exists error, since this table may have been dropped during the scan procedure.
2034
    if (code) {
1,671,584!
2035
      QUERY_CHECK_CODE(code, lino, _end);
2036
    }
1,671,392✔
2037

1,671,464!
UNCOV
2038
    // reset the error code.
×
2039
    terrno = 0;
2040

1,670,600✔
2041
    for (int32_t i = 0; i < pInfo->numOfPseudoExpr; ++i) {
2042
      void* tmp = taosArrayPush(pColList, &pInfo->pPseudoExpr[i].base.resSchema.slotId);
2043
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
28,143,826✔
2044
    }
28,143,826✔
2045
  }
28,143,826✔
2046

28,143,826✔
2047
  taosArraySort(pColList, colIdComparFn);
28,146,607✔
2048

2049
  int32_t i = 0, j = 0;
28,147,075✔
2050
  while (i < taosArrayGetSize(pColList)) {
28,146,097✔
2051
    int32_t slot1 = *(int32_t*)taosArrayGet(pColList, i);
2052
    if (slot1 > j) {
28,145,648✔
2053
      SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, j);
2054
      colDataSetNNULL(pDst, 0, pBlockInfo->rows);
28,147,692!
2055
      j += 1;
×
UNCOV
2056
    } else {
×
2057
      i += 1;
2058
      j += 1;
2059
    }
28,147,914✔
UNCOV
2060
  }
×
2061

1,504,316✔
2062
  while (j < taosArrayGetSize(pInfo->pRes->pDataBlock)) {
1,504,316✔
2063
    SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, j);
1,503,756!
2064
    colDataSetNNULL(pDst, 0, pBlockInfo->rows);
2065
    j += 1;
1,503,756!
2066
  }
1,489,865✔
2067

1,490,025✔
2068
  taosArrayDestroy(pColList);
1,489,625!
2069

1,489,625!
2070
  code = doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL, NULL);
1,490,105!
2071
  QUERY_CHECK_CODE(code, lino, _end);
1,490,345✔
2072

1,490,345✔
2073
  code = blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex);
2074
  QUERY_CHECK_CODE(code, lino, _end);
2075
  if (pInfo->pRes->info.rows == 0) {
2076
    return 0;
2077
  }
2078

2079
_end:
13,971✔
2080
  if (code != TSDB_CODE_SUCCESS) {
13,971✔
2081
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
2082
  }
13,971✔
2083
  return code;
13,971✔
2084
}
13,971!
2085

13,971✔
2086
static int32_t processPrimaryKey(SSDataBlock* pBlock, bool hasPrimaryKey, STqOffsetVal* offset) {
5,105✔
2087
  int32_t code = TSDB_CODE_SUCCESS;
5,105✔
2088
  int32_t lino = 0;
2089
  SValue  val = {0};
2090
  if (hasPrimaryKey) {
8,866✔
2091
    code = doBlockDataPrimaryKeyFilter(pBlock, offset);
2092
    if (code != TSDB_CODE_SUCCESS) {
2093
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
26,652,345!
2094
      return code;
230,190✔
2095
    }
2096
    SColumnInfoData* pColPk = taosArrayGet(pBlock->pDataBlock, 1);
26,882,535✔
2097

2098
    if (pBlock->info.rows < 1) {
26,879,537✔
2099
      return code;
26,881,780✔
2100
    }
2101
    void* tmp = colDataGetData(pColPk, pBlock->info.rows - 1);
2102
    val.type = pColPk->info.type;
26,881,393✔
2103
    if (IS_VAR_DATA_TYPE(pColPk->info.type)) {
2104
      if (IS_STR_DATA_BLOB(pColPk->info.type)) {
2105
        return TSDB_CODE_BLOB_NOT_SUPPORT_PRIMARY_KEY;
26,880,754✔
2106
      }
2107
      val.pData = taosMemoryMalloc(varDataLen(tmp));
26,881,283✔
2108
      QUERY_CHECK_NULL(val.pData, code, lino, _end, terrno);
23,176,614✔
2109
      val.nData = varDataLen(tmp);
2110
      memcpy(val.pData, varDataVal(tmp), varDataLen(tmp));
23,176,251✔
2111
    } else {
23,177,714✔
2112
      valueSetDatum(&val, pColPk->info.type, tmp, pColPk->info.bytes);
23,174,413!
2113
    }
23,174,413!
2114
  }
2115
  tqOffsetResetToData(offset, pBlock->info.id.uid, pBlock->info.window.ekey, val);
23,176,593✔
2116

22,948,119✔
2117
_end:
22,947,052✔
2118
  if (code != TSDB_CODE_SUCCESS) {
2119
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
2120
  }
3,704,669!
2121
  return code;
3,704,702✔
2122
}
3,704,702✔
2123

2124
static int32_t doQueueScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
2125
  int32_t        code = TSDB_CODE_SUCCESS;
UNCOV
2126
  int32_t        lino = 0;
×
UNCOV
2127
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
UNCOV
2128
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
2129

2130
  SStreamScanInfo* pInfo = pOperator->info;
UNCOV
2131
  const char*      id = GET_TASKID(pTaskInfo);
×
UNCOV
2132

×
UNCOV
2133
  qDebug("start to exec queue scan, %s", id);
×
UNCOV
2134

×
UNCOV
2135
  if (isTaskKilled(pTaskInfo)) {
×
2136
    (*ppRes) = NULL;
2137
    return pTaskInfo->code;
×
UNCOV
2138
  }
×
2139

2140
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) {
2141
    while (1) {
×
UNCOV
2142
      SSDataBlock* pResult = NULL;
×
UNCOV
2143
      code = doTableScanNext(pInfo->pTableScanOp, &pResult);
×
UNCOV
2144
      QUERY_CHECK_CODE(code, lino, _end);
×
2145

2146
      if (pResult && pResult->info.rows > 0) {
2147
        bool hasPrimaryKey = pAPI->tqReaderFn.tqGetTablePrimaryKey(pInfo->tqReader);
124,644✔
2148
        code = processPrimaryKey(pResult, hasPrimaryKey, &pTaskInfo->streamInfo.currentOffset);
124,644✔
2149
        QUERY_CHECK_CODE(code, lino, _end);
124,644✔
2150
        qDebug("tmqsnap doQueueScan get data utid:%" PRId64, pResult->info.id.uid);
124,644✔
2151
        if (pResult->info.rows > 0) {
124,969!
2152
          (*ppRes) = pResult;
2153
          return code;
2154
        }
124,969✔
2155
      } else {
124,936✔
2156
        break;
124,889!
2157
      }
3,501,328✔
2158
    }
3,376,276✔
2159

3,376,359!
2160
    STableScanInfo* pTSInfo = pInfo->pTableScanOp->info;
3,376,359✔
2161
    pAPI->tsdReader.tsdReaderClose(pTSInfo->base.dataReader);
3,376,439!
2162

2163
    pTSInfo->base.dataReader = NULL;
2164
    int64_t validVer = pTaskInfo->streamInfo.snapshotVer + 1;
125,052✔
2165
    qDebug("queue scan tsdb over, switch to wal ver %" PRId64, validVer);
2166
    if (pAPI->tqReaderFn.tqReaderSeek(pInfo->tqReader, validVer, pTaskInfo->id.str) < 0) {
124,969✔
2167
      (*ppRes) = NULL;
124,969!
UNCOV
2168
      return code;
×
2169
    }
2170

124,969✔
2171
    tqOffsetResetToLog(&pTaskInfo->streamInfo.currentOffset, validVer);
2172
  }
2173

365,551✔
2174
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__LOG) {
365,551✔
2175
    while (1) {
365,551✔
2176
      bool hasResult =
365,551✔
2177
          pAPI->tqReaderFn.tqReaderNextBlockInWal(pInfo->tqReader, id, pTaskInfo->streamInfo.sourceExcluded);
365,551✔
2178

2179
      SSDataBlock*       pRes = pAPI->tqReaderFn.tqGetResultBlock(pInfo->tqReader);
365,551✔
2180
      struct SWalReader* pWalReader = pAPI->tqReaderFn.tqReaderGetWalReader(pInfo->tqReader);
365,551✔
2181

365,551✔
2182
      // curVersion move to next
2183
      tqOffsetResetToLog(&pTaskInfo->streamInfo.currentOffset, pWalReader->curVersion);
365,551!
2184

365,551✔
2185
      // use ts to pass time when replay, because ts not used if type is log
364,380✔
2186
      pTaskInfo->streamInfo.currentOffset.ts = pAPI->tqReaderFn.tqGetResultBlockTime(pInfo->tqReader);
364,380!
2187

364,157✔
2188
      if (hasResult) {
363,581!
UNCOV
2189
        qDebug("doQueueScan get data from log %" PRId64 " rows, version:%" PRId64, pRes->info.rows,
×
UNCOV
2190
               pTaskInfo->streamInfo.currentOffset.version);
×
2191
        blockDataCleanup(pInfo->pRes);
2192
        code = setBlockIntoRes(pInfo, pRes);
2193
        QUERY_CHECK_CODE(code, lino, _end);
2194
        qDebug("doQueueScan after filter get data from log %" PRId64 " rows, version:%" PRId64, pInfo->pRes->info.rows,
363,804!
2195
               pTaskInfo->streamInfo.currentOffset.version);
182,263!
UNCOV
2196
        if (pInfo->pRes->info.rows > 0) {
×
UNCOV
2197
          (*ppRes) = pInfo->pRes;
×
2198
          return code;
2199
        }
2200
      } else {
182,191✔
2201
        qDebug("doQueueScan get none from log, return, version:%" PRId64, pTaskInfo->streamInfo.currentOffset.version);
182,191✔
2202
        (*ppRes) = NULL;
181,903!
2203
        return code;
2204
      }
181,903!
2205
    }
181,975✔
2206
  } else {
182,335✔
2207
    qError("unexpected streamInfo prepare type: %d", pTaskInfo->streamInfo.currentOffset.type);
181,615!
2208
    (*ppRes) = NULL;
181,615!
2209
    return code;
182,335✔
2210
  }
182,335✔
2211

2212
_end:
2213
  if (code != TSDB_CODE_SUCCESS) {
2214
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
181,757✔
2215
    pTaskInfo->code = code;
182,045✔
2216
    T_LONG_JMP(pTaskInfo->env, code);
181,671!
2217
  }
181,671!
2218
  (*ppRes) = NULL;
2219
  return code;
×
2220
}
2221

181,671✔
2222
static SSDataBlock* doQueueScan(SOperatorInfo* pOperator) {
181,678✔
2223
  SSDataBlock* pRes = NULL;
2,509✔
2224
  int32_t      code = doQueueScanNext(pOperator, &pRes);
2,509✔
2225
  return pRes;
2226
}
179,464✔
2227

179,464!
2228
int32_t extractTableIdList(const STableListInfo* pTableListInfo, SArray** ppArrayRes) {
179,320!
2229
  int32_t code = TSDB_CODE_SUCCESS;
2230
  int32_t lino = 0;
2231
  SArray* tableIdList = taosArrayInit(4, sizeof(uint64_t));
182,045✔
2232
  QUERY_CHECK_NULL(tableIdList, code, lino, _end, terrno);
182,045!
2233

182,045✔
2234
  // Transfer the Array of STableKeyInfo into uid list.
182,045✔
2235
  int32_t size = 0;
1,171!
2236
  code = tableListGetSize(pTableListInfo, &size);
1,171✔
2237
  QUERY_CHECK_CODE(code, lino, _end);
7,512!
2238
  for (int32_t i = 0; i < size; ++i) {
7,512✔
2239
    STableKeyInfo* pkeyInfo = tableListGetInfo(pTableListInfo, i);
7,512✔
2240
    QUERY_CHECK_NULL(pkeyInfo, code, lino, _end, terrno);
7,512✔
2241
    void* tmp = taosArrayPush(tableIdList, &pkeyInfo->uid);
7,512✔
2242
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
7,512!
UNCOV
2243
  }
×
UNCOV
2244

×
UNCOV
2245
  (*ppArrayRes) = tableIdList;
×
2246

2247
_end:
2248
  if (code != TSDB_CODE_SUCCESS) {
7,512✔
2249
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
1,171✔
2250
  }
1,171!
UNCOV
2251
  return code;
×
2252
}
1,171✔
2253

1,171!
2254
static int32_t doRawScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
1,171✔
2255
  int32_t        code = TSDB_CODE_SUCCESS;
2256
  int32_t        lino = 0;
6,263✔
2257
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
6,341✔
2258
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
6,341✔
2259

6,341✔
2260
  SStreamRawScanInfo* pInfo = pOperator->info;
6,341✔
2261
  pTaskInfo->streamInfo.btMetaRsp.batchMetaReq = NULL;  // use batchMetaReq != NULL to judge if data is meta
6,341✔
2262
  pTaskInfo->streamInfo.btMetaRsp.batchMetaLen = NULL;
948✔
2263

1,105!
2264
  qDebug("tmqsnap doRawScan called");
2265
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) {
1,105✔
2266
    bool hasNext = false;
1,105!
2267
    if (pInfo->dataReader && pInfo->sContext->withMeta != ONLY_META) {
2268
      code = pAPI->tsdReader.tsdNextDataBlock(pInfo->dataReader, &hasNext);
6,341✔
2269
      if (code != TSDB_CODE_SUCCESS) {
6,341✔
2270
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->dataReader);
6,341!
2271
        QUERY_CHECK_CODE(code, lino, _end);
6,184!
UNCOV
2272
      }
×
UNCOV
2273
    }
×
UNCOV
2274

×
2275
    if (pInfo->dataReader && hasNext) {
2276
      if (isTaskKilled(pTaskInfo)) {
2277
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->dataReader);
6,184✔
2278
        return code;
6,184!
2279
      }
6,341!
2280

2281
      SSDataBlock* pBlock = NULL;
6,341✔
2282
      code = pAPI->tsdReader.tsdReaderRetrieveDataBlock(pInfo->dataReader, &pBlock, NULL);
6,341✔
2283
      QUERY_CHECK_CODE(code, lino, _end);
6,341✔
2284

6,341✔
2285
      if (pBlock && pBlock->info.rows > 0) {
6,262!
UNCOV
2286
        bool hasPrimaryKey = pAPI->snapshotFn.taosXGetTablePrimaryKey(pInfo->sContext);
×
UNCOV
2287
        code = processPrimaryKey(pBlock, hasPrimaryKey, &pTaskInfo->streamInfo.currentOffset);
×
UNCOV
2288
        QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
2289
        qDebug("tmqsnap doRawScan get data uid:%" PRId64, pBlock->info.id.uid);
×
UNCOV
2290
        (*ppRes) = pBlock;
×
2291
        return code;
2292
      }
6,262!
2293
    }
6,341✔
2294

6,341!
2295
    SMetaTableInfo mtInfo = {0};
2296
    code = pAPI->snapshotFn.getMetaTableInfoFromSnapshot(pInfo->sContext, &mtInfo);
6,341✔
2297
    QUERY_CHECK_CODE(code, lino, _end);
6,341!
2298
    if (code != 0) {
2299
      destroyMetaTableInfo(&mtInfo);
2300
      QUERY_CHECK_CODE(code, lino, _end);
2301
    }
1,171✔
2302
    STqOffsetVal offset = {0};
1,171✔
2303
    if (mtInfo.uid == 0 || pInfo->sContext->withMeta == ONLY_META) {  // read snapshot done, change to get data from wal
2304
      qDebug("tmqsnap read snapshot done, change to get data from wal");
UNCOV
2305
      tqOffsetResetToLog(&offset, pInfo->sContext->snapVersion + 1);
×
UNCOV
2306
    } else {
×
UNCOV
2307
      SValue val = {0};
×
UNCOV
2308
      tqOffsetResetToData(&offset, mtInfo.uid, INT64_MIN, val);
×
UNCOV
2309
      qDebug("tmqsnap change get data uid:%" PRId64, mtInfo.uid);
×
2310
    }
2311
    destroyMetaTableInfo(&mtInfo);
UNCOV
2312
    code = qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType);
×
UNCOV
2313
    QUERY_CHECK_CODE(code, lino, _end);
×
2314
    (*ppRes) = NULL;
2315
    return code;
2316
  } else if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_META) {
25,425✔
2317
    SSnapContext* sContext = pInfo->sContext;
25,425✔
2318
    for (int32_t i = 0; i < tmqRowSize; i++) {
25,425✔
2319
      void*   data = NULL;
25,425✔
2320
      int32_t dataLen = 0;
25,346✔
2321
      int16_t type = 0;
25,425!
2322
      int64_t uid = 0;
25,315✔
2323
      if (pAPI->snapshotFn.getTableInfoFromSnapshot(sContext, &data, &dataLen, &type, &uid) < 0) {
2324
        qError("tmqsnap getTableInfoFromSnapshot error");
2325
        taosMemoryFreeClear(data);
2326
        break;
2327
      }
25,155✔
2328

2329
      if (!sContext->queryMeta) {  // change to get data next poll request
2330
        STqOffsetVal offset = {0};
2331
        SValue       val = {0};
2332
        tqOffsetResetToData(&offset, 0, INT64_MIN, val);
2333
        code = qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType);
25,155!
2334
        QUERY_CHECK_CODE(code, lino, _end);
25,425✔
2335
        break;
25,425✔
2336
      } else {
2337
        tqOffsetResetToMeta(&pTaskInfo->streamInfo.currentOffset, uid);
25,425!
2338
        SMqMetaRsp tmpMetaRsp = {0};
25,334!
2339
        tmpMetaRsp.resMsgType = type;
25,425!
UNCOV
2340
        tmpMetaRsp.metaRspLen = dataLen;
×
UNCOV
2341
        tmpMetaRsp.metaRsp = data;
×
UNCOV
2342
        if (!pTaskInfo->streamInfo.btMetaRsp.batchMetaReq) {
×
2343
          pTaskInfo->streamInfo.btMetaRsp.batchMetaReq = taosArrayInit(4, POINTER_BYTES);
2344
          QUERY_CHECK_NULL(pTaskInfo->streamInfo.btMetaRsp.batchMetaReq, code, lino, _end, terrno);
2345

25,425✔
2346
          pTaskInfo->streamInfo.btMetaRsp.batchMetaLen = taosArrayInit(4, sizeof(int32_t));
25,425!
2347
          QUERY_CHECK_NULL(pTaskInfo->streamInfo.btMetaRsp.batchMetaLen, code, lino, _end, terrno);
25,425✔
2348
        }
25,425✔
2349
        int32_t  tempRes = TSDB_CODE_SUCCESS;
2350
        uint32_t len = 0;
25,425✔
2351
        tEncodeSize(tEncodeMqMetaRsp, &tmpMetaRsp, len, tempRes);
25,425✔
2352
        if (TSDB_CODE_SUCCESS != tempRes) {
2353
          qError("tmqsnap tEncodeMqMetaRsp error");
2354
          taosMemoryFreeClear(data);
25,315✔
2355
          break;
2356
        }
25,315✔
2357

25,315✔
2358
        int32_t tLen = sizeof(SMqRspHead) + len;
UNCOV
2359
        void*   tBuf = taosMemoryCalloc(1, tLen);
×
UNCOV
2360
        QUERY_CHECK_NULL(tBuf, code, lino, _end, terrno);
×
UNCOV
2361

×
2362
        void*    metaBuff = POINTER_SHIFT(tBuf, sizeof(SMqRspHead));
UNCOV
2363
        SEncoder encoder = {0};
×
UNCOV
2364
        tEncoderInit(&encoder, metaBuff, len);
×
UNCOV
2365
        int32_t tempLen = tEncodeMqMetaRsp(&encoder, &tmpMetaRsp);
×
UNCOV
2366
        if (tempLen < 0) {
×
2367
          qError("tmqsnap tEncodeMqMetaRsp error");
2368
          tEncoderClear(&encoder);
2369
          taosMemoryFreeClear(tBuf);
124,969✔
2370
          taosMemoryFreeClear(data);
124,969!
2371
          break;
×
2372
        }
2373
        taosMemoryFreeClear(data);
2374
        void* tmp = taosArrayPush(pTaskInfo->streamInfo.btMetaRsp.batchMetaReq, &tBuf);
124,969✔
2375
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
124,969!
2376

124,969✔
2377
        tmp = taosArrayPush(pTaskInfo->streamInfo.btMetaRsp.batchMetaLen, &tLen);
2378
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
2379
      }
124,969!
2380
    }
124,969✔
2381

2382
    (*ppRes) = NULL;
124,969!
UNCOV
2383
    return code;
×
UNCOV
2384
  }
×
2385

2386
_end:
124,969!
2387
  if (code != TSDB_CODE_SUCCESS) {
×
2388
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2389
    pTaskInfo->code = code;
2390
    T_LONG_JMP(pTaskInfo->env, code);
124,969!
UNCOV
2391
  }
×
UNCOV
2392

×
2393
  (*ppRes) = NULL;
2394
  return code;
124,969!
UNCOV
2395
}
×
UNCOV
2396

×
2397
static void destroyTmqRawScanOperatorInfo(void* param) {
2398
  SStreamRawScanInfo* pRawScan = (SStreamRawScanInfo*)param;
124,969✔
2399
  pRawScan->pAPI->tsdReader.tsdReaderClose(pRawScan->dataReader);
124,891✔
2400
  pRawScan->pAPI->snapshotFn.destroySnapshot(pRawScan->sContext);
2401
  tableListDestroy(pRawScan->pTableListInfo);
125,047✔
2402
  taosMemoryFree(pRawScan);
85,084✔
2403
}
85,135!
2404

2405
// for subscribing db or stb (not including column),
2406
// if this scan is used, meta data can be return
125,020✔
2407
// and schemas are decided when scanning
124,969✔
2408
int32_t createTmqRawScanOperatorInfo(SReadHandle* pHandle, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
2409
  // create operator
124,969✔
2410
  // create tb reader
124,969✔
2411
  // create meta reader
124,969✔
2412
  // create tq reader
124,969✔
2413

124,969✔
2414
  QRY_PARAM_CHECK(pOptrInfo);
124,969✔
2415
  int32_t code = TSDB_CODE_SUCCESS;
124,886✔
2416
  int32_t lino = 0;
2417

124,969!
2418
  SStreamRawScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamRawScanInfo));
2419
  SOperatorInfo*      pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
UNCOV
2420
  if (pInfo == NULL || pOperator == NULL) {
×
2421
    code = terrno;
×
2422
    lino = __LINE__;
×
2423
    goto _end;
×
UNCOV
2424
  }
×
UNCOV
2425

×
UNCOV
2426
  pInfo->pTableListInfo = tableListCreate();
×
UNCOV
2427
  QUERY_CHECK_NULL(pInfo->pTableListInfo, code, lino, _end, terrno);
×
UNCOV
2428
  pInfo->vnode = pHandle->vnode;
×
2429
  pInfo->pAPI = &pTaskInfo->storageAPI;
UNCOV
2430

×
UNCOV
2431
  pInfo->sContext = pHandle->sContext;
×
UNCOV
2432
  setOperatorInfo(pOperator, "RawScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, false, OP_NOT_OPENED, pInfo,
×
2433
                  pTaskInfo);
UNCOV
2434

×
2435
  pOperator->fpSet = createOperatorFpSet(NULL, doRawScanNext, NULL, destroyTmqRawScanOperatorInfo, optrDefaultBufFn,
2436
                                         NULL, optrDefaultGetNextExtFn, NULL);
UNCOV
2437
  *pOptrInfo = pOperator;
×
UNCOV
2438
  return code;
×
UNCOV
2439

×
2440
_end:
×
2441
  if (code != TSDB_CODE_SUCCESS) {
2442
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2443
  }
2444
  taosMemoryFree(pInfo);
×
2445
  taosMemoryFree(pOperator);
×
2446
  pTaskInfo->code = code;
×
2447
  return code;
×
UNCOV
2448
}
×
UNCOV
2449

×
UNCOV
2450
void destroyTmqScanOperatorInfo(void* param) {
×
2451
  if (param == NULL) {
2452
    return;
×
UNCOV
2453
  }
×
UNCOV
2454

×
2455
  SStreamScanInfo* pStreamScan = (SStreamScanInfo*)param;
2456
  if (pStreamScan->pTableScanOp && pStreamScan->pTableScanOp->info) {
UNCOV
2457
    destroyOperator(pStreamScan->pTableScanOp);
×
UNCOV
2458
  }
×
UNCOV
2459

×
UNCOV
2460
  if (pStreamScan->tqReader != NULL && pStreamScan->readerFn.tqReaderClose != NULL) {
×
UNCOV
2461
    pStreamScan->readerFn.tqReaderClose(pStreamScan->tqReader);
×
2462
  }
UNCOV
2463
  if (pStreamScan->pVtableMergeHandles) {
×
2464
    taosHashCleanup(pStreamScan->pVtableMergeHandles);
×
2465
    pStreamScan->pVtableMergeHandles = NULL;
UNCOV
2466
  }
×
2467
  if (pStreamScan->pVtableMergeBuf) {
2468
    destroyDiskbasedBuf(pStreamScan->pVtableMergeBuf);
2469
    pStreamScan->pVtableMergeBuf = NULL;
124,856✔
2470
  }
2471
  if (pStreamScan->pVtableReadyHandles) {
2472
    taosArrayDestroy(pStreamScan->pVtableReadyHandles);
124,856!
2473
    pStreamScan->pVtableReadyHandles = NULL;
2474
  }
124,969✔
2475
  if (pStreamScan->pTableListInfo) {
124,969✔
2476
    tableListDestroy(pStreamScan->pTableListInfo);
124,969✔
2477
    pStreamScan->pTableListInfo = NULL;
124,969!
2478
  }
124,969!
2479
  if (pStreamScan->matchInfo.pList) {
124,969✔
2480
    taosArrayDestroy(pStreamScan->matchInfo.pList);
124,969✔
2481
  }
124,969✔
2482
  if (pStreamScan->pPseudoExpr) {
2483
    destroyExprInfo(pStreamScan->pPseudoExpr, pStreamScan->numOfPseudoExpr);
124,969!
UNCOV
2484
    taosMemoryFree(pStreamScan->pPseudoExpr);
×
UNCOV
2485
  }
×
2486

2487
  cleanupExprSupp(&pStreamScan->tbnameCalSup);
2488
  cleanupExprSupp(&pStreamScan->tagCalSup);
124,969✔
2489

124,969✔
2490
  blockDataDestroy(pStreamScan->pRes);
2491
  blockDataDestroy(pStreamScan->pUpdateRes);
124,969✔
2492
  blockDataDestroy(pStreamScan->pDeleteDataRes);
124,969✔
2493
  blockDataDestroy(pStreamScan->pUpdateDataRes);
2494
  blockDataDestroy(pStreamScan->pCreateTbRes);
124,969✔
2495
  taosArrayDestroy(pStreamScan->pBlockLists);
124,969✔
2496
  blockDataDestroy(pStreamScan->pCheckpointRes);
124,969!
UNCOV
2497

×
2498
  taosMemoryFree(pStreamScan);
2499
}
2500

124,969✔
2501
int32_t addPrimaryKeyCol(SSDataBlock* pBlock, uint8_t type, int32_t bytes) {
124,969✔
2502
  int32_t code = TSDB_CODE_SUCCESS;
124,969✔
2503
  int32_t lino = 0;
124,969✔
2504
  pBlock->info.rowSize += bytes;
124,969✔
2505
  SColumnInfoData infoData = {0};
124,969!
2506
  infoData.info.type = type;
2507
  infoData.info.bytes = bytes;
1,432,745✔
2508
  void* tmp = taosArrayPush(pBlock->pDataBlock, &infoData);
1,307,776✔
2509
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,307,776!
2510

2511
_end:
1,307,776✔
2512
  if (code != TSDB_CODE_SUCCESS) {
1,307,776✔
2513
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
1,307,776!
2514
  }
2515
  return code;
1,307,776✔
2516
}
124,969✔
2517

2518
static SSDataBlock* createStreamVtableBlock(SColMatchInfo* pMatchInfo, const char* idstr) {
1,307,776!
2519
  int32_t      code = TSDB_CODE_SUCCESS;
×
2520
  int32_t      lino = 0;
×
2521
  SSDataBlock* pRes = NULL;
×
2522

2523
  QUERY_CHECK_NULL(pMatchInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
2524

2525
  code = createDataBlock(&pRes);
124,969✔
2526
  QUERY_CHECK_CODE(code, lino, _end);
124,969!
2527
  int32_t numOfOutput = taosArrayGetSize(pMatchInfo->pList);
×
2528
  for (int32_t i = 0; i < numOfOutput; ++i) {
×
2529
    SColMatchItem* pItem = taosArrayGet(pMatchInfo->pList, i);
×
2530
    if (!pItem->needOutput) {
×
2531
      continue;
2532
    }
2533
    SColumnInfoData colInfo = createColumnInfoData(pItem->dataType.type, pItem->dataType.bytes, pItem->colId);
×
2534
    code = blockDataAppendColInfo(pRes, &colInfo);
×
2535
    QUERY_CHECK_CODE(code, lino, _end);
×
2536
  }
UNCOV
2537

×
2538
_end:
×
2539
  if (code != TSDB_CODE_SUCCESS) {
2540
    qError("%s failed at line %d since %s, id: %s", __func__, lino, tstrerror(code), idstr);
2541
    if (pRes != NULL) {
2542
      blockDataDestroy(pRes);
124,969!
UNCOV
2543
    }
×
2544
    pRes = NULL;
×
2545
    terrno = code;
×
UNCOV
2546
  }
×
2547
  return pRes;
UNCOV
2548
}
×
UNCOV
2549

×
UNCOV
2550
 int32_t createTmqScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode,
×
2551
                                                  SNode* pTagCond, STableListInfo* pTableListInfo,
2552
                                                  SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
2553
  QRY_PARAM_CHECK(pOptrInfo);
2554

124,969✔
2555
  int32_t          code = TSDB_CODE_SUCCESS;
124,969!
2556
  int32_t          lino = 0;
2557
  SArray*          pColIds = NULL;
124,969!
2558
  SStreamScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamScanInfo));
124,969✔
2559
  SOperatorInfo*   pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
124,969✔
2560
  SStorageAPI*     pAPI = &pTaskInfo->storageAPI;
124,969!
2561
  const char*      idstr = pTaskInfo->id.str;
193!
UNCOV
2562
  SSHashObj*       pVtableInfos = pTaskInfo->pSubplan->pVTables;
×
2563

2564
  if (pInfo == NULL || pOperator == NULL) {
2565
    code = terrno;
124,776✔
2566
    goto _error;
124,889!
2567
  }
124,969✔
2568

2569
  SScanPhysiNode*     pScanPhyNode = &pTableScanNode->scan;
2570
  SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc;
124,663✔
2571

124,856✔
2572
  pInfo->pTagCond = pTagCond;
124,856✔
2573
  pInfo->pGroupTags = pTableScanNode->pGroupTags;
124,889!
2574

2575
  int32_t numOfCols = 0;
124,889!
2576
  code = extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo);
124,889✔
2577
  if (code != TSDB_CODE_SUCCESS) {
124,889✔
2578
    goto _error;
2579
  }
2580

124,776✔
2581
  SDataType pkType = {0};
124,776✔
2582
  pInfo->primaryKeyIndex = -1;
124,969!
2583
  pInfo->basic.primaryPkIndex = -1;
2584
  int32_t numOfOutput = taosArrayGetSize(pInfo->matchInfo.pList);
113✔
UNCOV
2585
  pColIds = taosArrayInit(numOfOutput, sizeof(int16_t));
×
2586
  QUERY_CHECK_NULL(pColIds, code, lino, _error, terrno);
2587

2588
  for (int32_t i = 0; i < numOfOutput; ++i) {
124,969!
2589
    SColMatchItem* id = taosArrayGet(pInfo->matchInfo.pList, i);
UNCOV
2590
    QUERY_CHECK_NULL(id, code, lino, _error, terrno);
×
UNCOV
2591

×
UNCOV
2592
    int16_t colId = id->colId;
×
2593
    void*   tmp = taosArrayPush(pColIds, &colId);
UNCOV
2594
    QUERY_CHECK_NULL(tmp, code, lino, _error, terrno);
×
2595

2596
    if (id->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
2597
      pInfo->primaryTsIndex = id->dstSlotId;
124,969✔
2598
    }
124,969✔
2599
    if (id->isPk) {
124,969!
2600
      pInfo->primaryKeyIndex = id->dstSlotId;
×
2601
      pInfo->basic.primaryPkIndex = id->dstSlotId;
2602
      pkType = id->dataType;
2603
    }
2604
  }
124,969✔
2605

124,969✔
2606
  pInfo->pPartTbnameSup = NULL;
124,969✔
2607
  if (pTableScanNode->pSubtable != NULL) {
124,969!
2608
    SExprInfo* pSubTableExpr = taosMemoryCalloc(1, sizeof(SExprInfo));
124,873✔
2609
    if (pSubTableExpr == NULL) {
2610
      code = terrno;
124,886✔
2611
      goto _error;
124,889!
2612
    }
2613

2614
    pInfo->tbnameCalSup.pExprInfo = pSubTableExpr;
124,889✔
2615
    code = createExprFromOneNode(pSubTableExpr, pTableScanNode->pSubtable, 0);
124,677!
2616
    QUERY_CHECK_CODE(code, lino, _error);
2617

124,677✔
2618
    if (initExprSupp(&pInfo->tbnameCalSup, pSubTableExpr, 1, &pTaskInfo->storageAPI.functionStore) != 0) {
124,677✔
2619
      goto _error;
124,969!
2620
    }
124,969✔
2621
  }
124,969!
2622

124,969✔
2623
  if (pTableScanNode->pTags != NULL) {
124,859!
2624
    int32_t    numOfTags;
2625
    SExprInfo* pTagExpr = createExpr(pTableScanNode->pTags, &numOfTags);
×
2626
    if (pTagExpr == NULL) {
×
2627
      goto _error;
2628
    }
2629
    code = initExprSupp(&pInfo->tagCalSup, pTagExpr, numOfTags, &pTaskInfo->storageAPI.functionStore);
2630
    if (code != 0) {
124,969✔
2631
      goto _error;
2632
    }
2633
  }
124,969✔
2634

85,135✔
2635
  pInfo->pBlockLists = taosArrayInit(4, sizeof(SPackedData));
85,135!
2636
  TSDB_CHECK_NULL(pInfo->pBlockLists, code, lino, _error, terrno);
2637

2638
  if (pHandle->vnode) {
124,969✔
2639
    SOperatorInfo* pTableScanOp = NULL;
124,969!
2640
    code = createTableScanOperatorInfo(pTableScanNode, pHandle, pTableListInfo, pTaskInfo, &pTableScanOp);
2641
    if (pTableScanOp == NULL || code != 0) {
124,969✔
2642
      qError("createTableScanOperatorInfo error, code:%d", pTaskInfo->code);
124,969!
2643
      goto _error;
124,969✔
2644
    }
124,859!
2645

2646
    STableScanInfo* pTSInfo = (STableScanInfo*)pTableScanOp->info;
124,859✔
2647
    if (pHandle->version > 0) {
124,969✔
2648
      pTSInfo->base.cond.endVersion = pHandle->version;
124,859✔
2649
    }
124,859✔
2650

124,859✔
2651
    STableKeyInfo* pList = NULL;
124,969✔
2652
    int32_t        num = 0;
124,859✔
2653
    code = tableListGetGroupList(pTableListInfo, 0, &pList, &num);
124,969!
2654
    QUERY_CHECK_CODE(code, lino, _error);
2655

124,969✔
2656
    if (pHandle->initTableReader) {
124,969✔
2657
      pTSInfo->scanMode = TABLE_SCAN__TABLE_ORDER;
124,969!
2658
      pTSInfo->base.dataReader = NULL;
2659
    }
124,969!
2660

124,969✔
2661
    if (pHandle->initTqReader) {
124,969✔
2662
      pInfo->tqReader = pAPI->tqReaderFn.tqReaderOpen(pHandle->vnode);
124,859✔
2663
      QUERY_CHECK_NULL(pInfo->tqReader, code, lino, _error, terrno);
124,969✔
2664
    } else {
124,859✔
2665
      pInfo->tqReader = pHandle->tqReader;
124,969✔
2666
      QUERY_CHECK_NULL(pInfo->tqReader, code, lino, _error, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
124,969✔
2667
    }
124,969✔
2668

124,859✔
2669
    if (pVtableInfos != NULL) {
124,859✔
2670
      // save vtable info into tqReader for vtable source scan
2671
      SSDataBlock* pResBlock = createStreamVtableBlock(&pInfo->matchInfo, idstr);
124,859✔
2672
      QUERY_CHECK_CODE(code, lino, _error);
124,969!
2673
      code = pAPI->tqReaderFn.tqReaderSetVtableInfo(pInfo->tqReader, pHandle->vnode, pAPI, pVtableInfos, &pResBlock,
2674
                                                    idstr);
124,969✔
2675
      QUERY_CHECK_CODE(code, lino, _error);
2676
    }
124,969✔
2677

2678
    pInfo->pUpdateInfo = NULL;
124,969✔
2679
    pInfo->pTableScanOp = pTableScanOp;
2680
    if (pInfo->pTableScanOp->pTaskInfo->streamInfo.pState) {
2681
      pAPI->stateStore.streamStateSetNumber(pInfo->pTableScanOp->pTaskInfo->streamInfo.pState, -1,
124,969✔
2682
                                            pInfo->primaryTsIndex);
124,969✔
2683
    }
UNCOV
2684

×
UNCOV
2685
    pInfo->readHandle = *pHandle;
×
UNCOV
2686
    pTaskInfo->streamInfo.snapshotVer = pHandle->version;
×
2687
    pInfo->pCreateTbRes = buildCreateTableBlock(&pInfo->tbnameCalSup, &pInfo->tagCalSup);
2688
    QUERY_CHECK_NULL(pInfo->pCreateTbRes, code, lino, _error, terrno);
UNCOV
2689
    pInfo->hasPart = false;
×
UNCOV
2690

×
UNCOV
2691
    code = blockDataEnsureCapacity(pInfo->pCreateTbRes, 8);
×
UNCOV
2692
    QUERY_CHECK_CODE(code, lino, _error);
×
2693

UNCOV
2694
    // set the extract column id to streamHandle
×
2695
    code = pAPI->tqReaderFn.tqReaderSetColIdList(pInfo->tqReader, pColIds, idstr);
2696
    QUERY_CHECK_CODE(code, lino, _error);
UNCOV
2697

×
UNCOV
2698
    SArray* tableIdList = NULL;
×
UNCOV
2699
    code = extractTableIdList(((STableScanInfo*)(pInfo->pTableScanOp->info))->base.pTableListInfo, &tableIdList);
×
2700
    QUERY_CHECK_CODE(code, lino, _error);
UNCOV
2701
    code = pAPI->tqReaderFn.tqReaderSetQueryTableList(pInfo->tqReader, tableIdList, idstr);
×
UNCOV
2702
    QUERY_CHECK_CODE(code, lino, _error);
×
2703
    taosArrayDestroy(tableIdList);
2704
    memcpy(&pTaskInfo->streamInfo.tableCond, &pTSInfo->base.cond, sizeof(SQueryTableDataCond));
2705
  } else {
3,103,888✔
2706
    taosArrayDestroy(pColIds);
3,103,888✔
2707
    tableListDestroy(pTableListInfo);
3,103,888✔
2708
  }
3,103,888✔
2709

3,104,254✔
2710
  // clear the local variable to avoid repeatly free
3,103,918✔
2711
  pColIds = NULL;
3,103,918✔
2712

2713
  // create the pseduo columns info
3,103,918✔
2714
  if (pTableScanNode->scan.pScanPseudoCols != NULL) {
3,103,552!
UNCOV
2715
    code = createExprInfo(pTableScanNode->scan.pScanPseudoCols, NULL, &pInfo->pPseudoExpr, &pInfo->numOfPseudoExpr);
×
2716
    QUERY_CHECK_CODE(code, lino, _error);
UNCOV
2717
  }
×
UNCOV
2718

×
2719
  code = filterInitFromNode((SNode*)pScanPhyNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0, NULL);
2720
  QUERY_CHECK_CODE(code, lino, _error);
2721

3,103,552✔
2722
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
3,103,984✔
2723
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
3,104,254!
UNCOV
2724
  code = createSpecialDataBlock(STREAM_CLEAR, &pInfo->pUpdateRes);
×
2725
  QUERY_CHECK_CODE(code, lino, _error);
UNCOV
2726

×
2727
  pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
2728
  pInfo->windowSup = (SWindowSupporter){.pStreamAggSup = NULL, .gap = -1, .parentType = QUERY_NODE_PHYSICAL_PLAN};
2729
  pInfo->groupId = 0;
3,104,254✔
2730
  pInfo->igCheckGroupId = false;
9,370,699✔
2731
  pInfo->pStreamScanOp = pOperator;
6,266,785✔
2732
  pInfo->deleteDataIndex = 0;
2733
  code = createSpecialDataBlock(STREAM_DELETE_DATA, &pInfo->pDeleteDataRes);
2734
  QUERY_CHECK_CODE(code, lino, _error);
6,266,785✔
2735

1,152,523!
2736
  pInfo->updateWin = (STimeWindow){.skey = INT64_MAX, .ekey = INT64_MAX};
1,152,523✔
2737
  code = createSpecialDataBlock(STREAM_CLEAR, &pInfo->pUpdateDataRes);
1,152,523!
2738
  QUERY_CHECK_CODE(code, lino, _error);
5,114,262✔
2739

15,493✔
2740
  pInfo->assignBlockUid = pTableScanNode->assignBlockUid;
15,493!
2741
  pInfo->partitionSup.needCalc = false;
5,098,769✔
2742
  pInfo->igCheckUpdate = pTableScanNode->igCheckUpdate;
15,493✔
2743
  pInfo->igExpired = pTableScanNode->igExpired;
15,493!
2744
  pInfo->twAggSup.maxTs = INT64_MIN;
2745
  pInfo->pState = pTaskInfo->streamInfo.pState;
5,082,936✔
2746
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
5,082,936✔
2747
  pInfo->readerFn = pTaskInfo->storageAPI.tqReaderFn;
5,083,276✔
2748
  pInfo->pFillSup = NULL;
2749
  pInfo->useGetResultRange = false;
5,083,276✔
2750
  pInfo->pRangeScanRes = NULL;
5,083,276!
2751

5,083,276✔
2752
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
UNCOV
2753
  QUERY_CHECK_CODE(code, lino, _error);
×
2754

2755
  setOperatorInfo(pOperator, STREAM_SCAN_OP_NAME, QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, false, OP_NOT_OPENED, pInfo,
2756
                  pTaskInfo);
5,083,276✔
2757
  pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pRes->pDataBlock);
5,083,276!
2758

5,083,276!
2759
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doQueueScanNext, NULL, destroyTmqScanOperatorInfo, optrDefaultBufFn,
2760
                                         NULL, optrDefaultGetNextExtFn, NULL);
5,083,276!
2761

2762
  *pOptrInfo = pOperator;
1,104,700!
2763
  return code;
2764

2765
_error:
2766
  if (pColIds != NULL) {
2767
    taosArrayDestroy(pColIds);
3,104,594✔
2768
  }
3,104,254!
UNCOV
2769

×
2770
  if (pInfo != NULL && pInfo->pTableScanOp != NULL) {
×
2771
    STableScanInfo* p = (STableScanInfo*)pInfo->pTableScanOp->info;
2772
    if (p != NULL) {
3,104,254✔
2773
      p->base.pTableListInfo = NULL;
2774
    }
2775
    destroyTmqScanOperatorInfo(pInfo);
3,104,254✔
2776
  }
2777

2778
  if (pOperator != NULL) {
4,512,248✔
2779
    pOperator->info = NULL;
4,512,248✔
2780
    destroyOperator(pOperator);
4,512,248✔
2781
  }
4,512,453!
2782
  pTaskInfo->code = code;
2783
  return code;
4,510,934✔
2784
}
2785

949,332✔
2786
static int32_t doTagScanOneTable(SOperatorInfo* pOperator, SSDataBlock* pRes, SMetaReader* mr, SStorageAPI* pAPI) {
949,332!
2787
  int32_t        code = TSDB_CODE_SUCCESS;
949,897!
UNCOV
2788
  int32_t        lino = 0;
×
2789
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
2790
  STagScanInfo*  pInfo = pOperator->info;
2791
  SExprInfo*     pExprInfo = &pOperator->exprSupp.pExprInfo[0];
949,897✔
2792
  int32_t        count = pRes->info.rows;
950,186✔
2793

949,628✔
2794
  STableKeyInfo* item = tableListGetInfo(pInfo->pTableListInfo, pInfo->curPos);
948,773✔
2795
  if (!item) {
2796
    qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
949,608✔
2797
           GET_TASKID(pTaskInfo));
948,844!
2798
    tDecoderClear(&(*mr).coder);
×
2799
    goto _end;
×
UNCOV
2800
  }
×
2801

2802
  code = pAPI->metaReaderFn.getTableEntryByUid(mr, item->uid);
2803
  tDecoderClear(&(*mr).coder);
948,844✔
2804
  if (code != TSDB_CODE_SUCCESS) {
949,050✔
2805
    qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
950,186✔
2806
           GET_TASKID(pTaskInfo));
2807
    goto _end;
2808
  }
5,907,685✔
2809

5,907,685✔
2810
  char str[512];
5,907,685✔
2811
  for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
5,907,685✔
2812
    SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
5,907,685✔
2813

5,908,739✔
2814
    // refactor later
1,662,742✔
2815
    if (FUNCTION_TYPE_TBNAME == pExprInfo[j].pExpr->_function.functionType) {
4,249,895!
UNCOV
2816
      STR_TO_VARSTR(str, (*mr).me.name);
×
UNCOV
2817
      code = colDataSetVal(pDst, (count), str, false);
×
UNCOV
2818
      QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
2819
    } else if (FUNCTION_TYPE_TBUID == pExprInfo[j].pExpr->_function.functionType) {
×
UNCOV
2820
      code = colDataSetVal(pDst, (count), (char*)&(*mr).me.uid, false);
×
UNCOV
2821
      QUERY_CHECK_CODE(code, lino, _end);
×
2822
    } else if (FUNCTION_TYPE_VGID == pExprInfo[j].pExpr->_function.functionType) {
UNCOV
2823
      code = colDataSetVal(pDst, (count), (char*)&pTaskInfo->id.vgId, false);
×
UNCOV
2824
      QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
2825
    } else {  // it is a tag value
×
UNCOV
2826
      STagVal val = {0};
×
UNCOV
2827
      val.cid = pExprInfo[j].base.pParam[0].pCol->colId;
×
UNCOV
2828
      const char* p = pAPI->metaFn.extractTagVal((*mr).me.ctbEntry.pTags, pDst->info.type, &val);
×
2829

UNCOV
2830
      char* data = NULL;
×
2831
      if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL) {
2832
        data = tTagValToData((const STagVal*)p, false);
2833
      } else {
4,249,064✔
2834
        data = (char*)p;
2835
      }
2836

1,662,742✔
2837
      code = colDataSetVal(pDst, (count), data,
1,662,178✔
2838
                           (data == NULL) || (pDst->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data)));
955,162✔
2839
      QUERY_CHECK_CODE(code, lino, _end);
955,859!
UNCOV
2840

×
2841
      if ((pDst->info.type != TSDB_DATA_TYPE_JSON) && (p != NULL) && IS_VAR_DATA_TYPE(((const STagVal*)p)->type) &&
2842
          (data != NULL)) {
955,859!
2843
        taosMemoryFree(data);
955,859✔
2844
      }
955,852✔
2845
    }
954,476✔
2846
  }
955,447✔
2847

955,176✔
2848
_end:
955,090!
2849
  if (code != TSDB_CODE_SUCCESS) {
2850
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
707,016✔
2851
    pTaskInfo->code = code;
707,016✔
2852
  } else {
2853
    pRes->info.rows++;
2854
  }
1,662,368✔
2855

1,662,661✔
2856
  return code;
557!
UNCOV
2857
}
×
2858

2859
static void tagScanFreeUidTag(void* p) {
1,662,107✔
2860
  STUidTagInfo* pInfo = p;
2861
  if (pInfo->pTagVal != NULL) {
2862
    taosMemoryFree(pInfo->pTagVal);
950,750✔
2863
  }
2864
}
950,750✔
2865

950,750✔
2866
static int32_t tagScanCreateResultData(SDataType* pType, int32_t numOfRows, SScalarParam* pParam) {
950,750✔
2867
  SColumnInfoData* pColumnData = taosMemoryCalloc(1, sizeof(SColumnInfoData));
950,750✔
2868
  if (pColumnData == NULL) {
2869
    return terrno;
950,750✔
2870
  }
949,129!
2871

2872
  pColumnData->info.type = pType->type;
949,129✔
2873
  pColumnData->info.bytes = pType->bytes;
950,461!
2874
  pColumnData->info.scale = pType->scale;
2875
  pColumnData->info.precision = pType->precision;
950,750✔
2876

950,750!
2877
  int32_t code = colInfoDataEnsureCapacity(pColumnData, numOfRows, true);
2878
  if (code != TSDB_CODE_SUCCESS) {
950,750✔
2879
    terrno = code;
2880
    taosMemoryFree(pColumnData);
949,699✔
2881
    return terrno;
950,750✔
2882
  }
949,897!
2883

2884
  pParam->columnData = pColumnData;
949,897✔
2885
  pParam->colAlloced = true;
948,075!
2886
  return TSDB_CODE_SUCCESS;
2887
}
948,075✔
2888

2,370,257✔
2889
static EDealRes tagScanRewriteTagColumn(SNode** pNode, void* pContext) {
1,421,056!
2890
  int32_t                code = TSDB_CODE_SUCCESS;
1,336,585✔
2891
  int32_t                lino = 0;
1,336,585!
2892
  STagScanFilterContext* pCtx = (STagScanFilterContext*)pContext;
2893
  SColumnNode*           pSColumnNode = NULL;
2894
  if (QUERY_NODE_COLUMN == nodeType((*pNode))) {
2895
    pSColumnNode = *(SColumnNode**)pNode;
950,063✔
2896
  } else if (QUERY_NODE_FUNCTION == nodeType((*pNode))) {
949,051!
2897
    SFunctionNode* pFuncNode = *(SFunctionNode**)(pNode);
2898
    if (pFuncNode->funcType == FUNCTION_TYPE_TBNAME) {
948,814✔
2899
      pSColumnNode = NULL;
948,532✔
2900
      pCtx->code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pSColumnNode);
947,114✔
2901
      if (NULL == pSColumnNode) {
946,409!
2902
        return DEAL_RES_ERROR;
×
2903
      }
2904
      pSColumnNode->colId = -1;
946,409✔
2905
      pSColumnNode->colType = COLUMN_TYPE_TBNAME;
2906
      pSColumnNode->node.resType.type = TSDB_DATA_TYPE_VARCHAR;
2907
      pSColumnNode->node.resType.bytes = TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE;
18,324,554✔
2908
      nodesDestroyNode(*pNode);
2909
      *pNode = (SNode*)pSColumnNode;
2910
    } else {
18,324,554✔
2911
      return DEAL_RES_CONTINUE;
18,324,554✔
2912
    }
18,324,554✔
2913
  } else {
8,841,224!
UNCOV
2914
    return DEAL_RES_CONTINUE;
×
UNCOV
2915
  }
×
2916

UNCOV
2917
  void* data = taosHashGet(pCtx->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId));
×
UNCOV
2918
  if (!data) {
×
2919
    code = taosHashPut(pCtx->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId), pNode, sizeof((*pNode)));
8,835,111✔
2920
    if (code == TSDB_CODE_DUP_KEY) {
4,416,934✔
2921
      code = TSDB_CODE_SUCCESS;
4,420,361!
2922
    }
4,420,854!
2923
    QUERY_CHECK_CODE(code, lino, _end);
4,417,707✔
2924
    pSColumnNode->slotId = pCtx->index++;
4,420,287!
2925
    SColumnInfo cInfo = {.colId = pSColumnNode->colId,
2926
                         .type = pSColumnNode->node.resType.type,
2927
                         .bytes = pSColumnNode->node.resType.bytes};
9,483,413✔
2928
    void*       tmp = taosArrayPush(pCtx->cInfoList, &cInfo);
9,484,113✔
2929
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
9,483,789!
UNCOV
2930
  } else {
×
2931
    SColumnNode* col = *(SColumnNode**)data;
2932
    pSColumnNode->slotId = col->slotId;
9,484,604✔
2933
  }
2934

9,483,668!
2935
_end:
3,727!
2936
  if (code != TSDB_CODE_SUCCESS) {
9,480,222!
UNCOV
2937
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2938
    return DEAL_RES_ERROR;
×
2939
  }
11,676,917!
2940
  return DEAL_RES_CONTINUE;
2,200,334!
UNCOV
2941
}
×
2942

2943
static int32_t tagScanFilterByTagCond(SArray* aUidTags, SNode* pTagCond, SArray* aFilterIdxs, void* pVnode,
2,199,364!
2944
                                      SStorageAPI* pAPI, STagScanInfo* pInfo) {
2,199,160!
2945
  int32_t code = TSDB_CODE_SUCCESS;
2946
  int32_t lino = 0;
2,199,160✔
2947
  int32_t numOfTables = taosArrayGetSize(aUidTags);
2,198,637!
2948
  SArray* pBlockList = NULL;
2,200,691✔
2949

2,200,561!
2950
  SSDataBlock* pResBlock = createTagValBlockForFilter(pInfo->filterCtx.cInfoList, numOfTables, aUidTags, pVnode, pAPI);
2,198,934!
2951
  QUERY_CHECK_NULL(pResBlock, code, lino, _end, terrno);
2952

7,277,305✔
2953
  pBlockList = taosArrayInit(1, POINTER_BYTES);
7,279,234!
2954
  QUERY_CHECK_NULL(pBlockList, code, lino, _end, terrno);
2955

2956
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
2957
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
2958

18,323,503✔
2959
  SDataType type = {.type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)};
18,323,503!
UNCOV
2960

×
2961
  SScalarParam output = {0};
2962
  code = tagScanCreateResultData(&type, numOfTables, &output);
18,319,156✔
2963
  QUERY_CHECK_CODE(code, lino, _end);
2964

2965
  code = scalarCalculate(pTagCond, pBlockList, &output, NULL, NULL);
2,859,437✔
2966
  QUERY_CHECK_CODE(code, lino, _end);
2967

2,859,437✔
2968
  bool* result = (bool*)output.columnData->pData;
2,859,437✔
2969
  for (int32_t i = 0; i < numOfTables; ++i) {
2,859,437✔
2970
    if (result[i]) {
2,860,053✔
2971
      void* tmp = taosArrayPush(aFilterIdxs, &i);
2,859,924✔
2972
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
948,375✔
2973
    }
2,285,838✔
2974
  }
1,335,294✔
2975

1,335,379✔
2976
  colDataDestroy(output.columnData);
1,335,658!
2977
  taosMemoryFreeClear(output.columnData);
7,620,439✔
2978

6,282,216✔
2979
_end:
6,285,954!
2980
  blockDataDestroy(pResBlock);
6,285,954✔
2981
  taosArrayDestroy(pBlockList);
6,284,781!
2982
  if (code != TSDB_CODE_SUCCESS) {
2983
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
2984
  }
2985
  return code;
1,911,549✔
2986
}
5,004,165✔
2987

3,092,896✔
2988
static int32_t tagScanFillOneCellWithTag(SOperatorInfo* pOperator, const STUidTagInfo* pUidTagInfo,
3,093,100!
2989
                                         SExprInfo* pExprInfo, SColumnInfoData* pColInfo, int rowIndex,
15,125,718✔
2990
                                         const SStorageAPI* pAPI, void* pVnode) {
12,033,871✔
2991
  int32_t code = TSDB_CODE_SUCCESS;
12,036,856!
2992
  int32_t lino = 0;
12,036,856✔
2993
  if (QUERY_NODE_FUNCTION == pExprInfo->pExpr->nodeType) {
12,032,618!
2994
    if (FUNCTION_TYPE_TBNAME == pExprInfo->pExpr->_function.functionType) {  // tbname
2995
      char str[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
2996
      STR_TO_VARSTR(str, "ctbidx");
2997

2998
      code = colDataSetVal(pColInfo, rowIndex, str, false);
1,911,269✔
2999
      QUERY_CHECK_CODE(code, lino, _end);
2,861,813!
UNCOV
3000
    } else if (FUNCTION_TYPE_TBUID == pExprInfo->pExpr->_function.functionType) {
×
3001
      code = colDataSetVal(pColInfo, rowIndex, (char*)&pUidTagInfo->uid, false);
3002
      QUERY_CHECK_CODE(code, lino, _end);
2,861,252✔
3003
    } else if (FUNCTION_TYPE_VGID == pExprInfo->pExpr->_function.functionType) {
3004
      code = colDataSetVal(pColInfo, rowIndex, (char*)&pOperator->pTaskInfo->id.vgId, false);
3005
      QUERY_CHECK_CODE(code, lino, _end);
5,774,150✔
3006
    }
5,774,150✔
3007
  } else {
5,774,150✔
3008
    STagVal tagVal = {0};
5,774,150✔
3009
    tagVal.cid = pExprInfo->base.pParam[0].pCol->colId;
5,775,004✔
3010
    if (pUidTagInfo->pTagVal == NULL) {
3011
      colDataSetNULL(pColInfo, rowIndex);
5,773,676✔
3012
    } else {
5,774,045✔
3013
      const char* p = pAPI->metaFn.extractTagVal(pUidTagInfo->pTagVal, pColInfo->info.type, &tagVal);
3014

5,775,410!
3015
      if (p == NULL || (pColInfo->info.type == TSDB_DATA_TYPE_JSON && ((STag*)p)->nTag == 0)) {
3016
        colDataSetNULL(pColInfo, rowIndex);
5,774,713✔
3017
      } else if (pColInfo->info.type == TSDB_DATA_TYPE_JSON) {
2,805,713✔
3018
        code = colDataSetVal(pColInfo, rowIndex, p, false);
3019
        QUERY_CHECK_CODE(code, lino, _end);
2,967,096✔
3020
      } else if (IS_VAR_DATA_TYPE(pColInfo->info.type)) {
3021
        if (IS_STR_DATA_BLOB(pColInfo->info.type)) {
2,970,473!
3022
          QUERY_CHECK_CODE(code = TSDB_CODE_BLOB_NOT_SUPPORT_TAG, lino, _end);
2,969,702✔
3023
        }
2,972,019!
3024
        char* tmp = taosMemoryMalloc(tagVal.nData + VARSTR_HEADER_SIZE + 1);
UNCOV
3025
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
×
UNCOV
3026

×
3027
        varDataSetLen(tmp, tagVal.nData);
3028
        memcpy(tmp + VARSTR_HEADER_SIZE, tagVal.pData, tagVal.nData);
3029
        code = colDataSetVal(pColInfo, rowIndex, tmp, false);
2,971,045✔
3030
        taosMemoryFree(tmp);
2,971,741✔
3031
        QUERY_CHECK_CODE(code, lino, _end);
2,970,565✔
3032
      } else {
2,970,565✔
3033
        code = colDataSetVal(pColInfo, rowIndex, (const char*)&tagVal.i64, false);
55,628✔
3034
        QUERY_CHECK_CODE(code, lino, _end);
3,026,193✔
3035
      }
3,027,346✔
3036
    }
3037
  }
3,027,071✔
3038

7,549,201✔
3039
_end:
7,541,365✔
3040
  if (code != TSDB_CODE_SUCCESS) {
7,541,083✔
3041
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
7,541,380✔
3042
  }
3,028,117✔
3043
  return code;
3,028,117✔
3044
}
3045

4,513,263✔
3046
static int32_t tagScanFillResultBlock(SOperatorInfo* pOperator, SSDataBlock* pRes, SArray* aUidTags,
4,511,285!
3047
                                      SArray* aFilterIdxs, bool ignoreFilterIdx, SStorageAPI* pAPI) {
4,509,025!
3048
  int32_t       code = TSDB_CODE_SUCCESS;
3049
  int32_t       lino = 0;
4,509,025!
3050
  STagScanInfo* pInfo = pOperator->info;
4,515,410✔
3051
  SExprInfo*    pExprInfo = &pOperator->exprSupp.pExprInfo[0];
4,515,410!
3052
  if (!ignoreFilterIdx) {
4,515,410✔
3053
    size_t szTables = taosArrayGetSize(aFilterIdxs);
3054
    for (int i = 0; i < szTables; ++i) {
3055
      int32_t       idx = *(int32_t*)taosArrayGet(aFilterIdxs, i);
3,028,117✔
3056
      STUidTagInfo* pUidTagInfo = taosArrayGet(aUidTags, idx);
165,818✔
3057
      QUERY_CHECK_NULL(pUidTagInfo, code, lino, _end, terrno);
3058
      for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
2,862,299✔
3059
        SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
2,862,299✔
3060
        QUERY_CHECK_NULL(pDst, code, lino, _end, terrno);
950,750✔
3061
        code = tagScanFillOneCellWithTag(pOperator, pUidTagInfo, &pExprInfo[j], pDst, i, pAPI, pInfo->readHandle.vnode);
950,750✔
3062
        QUERY_CHECK_CODE(code, lino, _end);
946,838!
3063
      }
3064
    }
1,911,549✔
3065
  } else {
3066
    size_t szTables = taosArrayGetSize(aUidTags);
3067
    for (int i = 0; i < szTables; ++i) {
2,858,387✔
3068
      STUidTagInfo* pUidTagInfo = taosArrayGet(aUidTags, i);
2,861,534!
3069
      QUERY_CHECK_NULL(pUidTagInfo, code, lino, _end, terrno);
3070
      for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
2,861,534✔
3071
        SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
3072
        QUERY_CHECK_NULL(pDst, code, lino, _end, terrno);
2,861,252✔
3073
        code = tagScanFillOneCellWithTag(pOperator, pUidTagInfo, &pExprInfo[j], pDst, i, pAPI, pInfo->readHandle.vnode);
2,805,624✔
3074
        QUERY_CHECK_CODE(code, lino, _end);
3075
      }
3076
    }
3077
  }
2,971,442✔
3078

2,805,906✔
3079
_end:
3080
  if (code != TSDB_CODE_SUCCESS) {
2,970,830!
3081
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
2,971,323✔
3082
  }
2,967,237✔
3083
  return code;
2,966,694✔
3084
}
3085

3086
static int32_t doTagScanFromCtbIdxNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
2,968,450✔
3087
  int32_t        code = TSDB_CODE_SUCCESS;
2,967,170✔
3088
  int32_t        lino = 0;
2,970,074!
UNCOV
3089
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
3090
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
3091

3092
  STagScanInfo* pInfo = pOperator->info;
2,970,074✔
3093
  SSDataBlock*  pRes = pInfo->pRes;
2,967,886✔
3094

3095
  QRY_PARAM_CHECK(ppRes);
2,963,546✔
3096

2,963,546!
UNCOV
3097
  if (pOperator->status == OP_EXEC_DONE) {
×
UNCOV
3098
    return TSDB_CODE_SUCCESS;
×
UNCOV
3099
  }
×
3100
  blockDataCleanup(pRes);
3101

3102
  if (pInfo->pCtbCursor == NULL) {
2,963,546✔
3103
    pInfo->pCtbCursor = pAPI->metaFn.openCtbCursor(pInfo->readHandle.vnode, pInfo->suid, 1);
3104
    QUERY_CHECK_NULL(pInfo->pCtbCursor, code, lino, _end, terrno);
3105
  } else {
1,922,970✔
3106
    code = pAPI->metaFn.resumeCtbCursor(pInfo->pCtbCursor, 0);
1,922,970✔
3107
    QUERY_CHECK_CODE(code, lino, _end);
1,922,970✔
3108
  }
1,922,970✔
3109

1,922,970✔
3110
  SArray* aUidTags = pInfo->aUidTags;
1,922,970✔
3111
  SArray* aFilterIdxs = pInfo->aFilterIdxs;
1,922,970✔
3112
  int32_t count = 0;
3113
  bool    ctbCursorFinished = false;
3114
  while (1) {
3115
    taosArrayClearEx(aUidTags, tagScanFreeUidTag);
3116
    taosArrayClear(aFilterIdxs);
3117

1,922,970✔
3118
    int32_t numTables = 0;
3119
    while (numTables < pOperator->resultInfo.capacity) {
1,922,970✔
3120
      SMCtbCursor* pCur = pInfo->pCtbCursor;
1,922,970✔
3121
      tb_uid_t     uid = pAPI->metaFn.ctbCursorNext(pInfo->pCtbCursor);
1,922,970✔
3122
      if (uid == 0) {
3123
        ctbCursorFinished = true;
1,922,970!
UNCOV
3124
        break;
×
3125
      }
UNCOV
3126
      STUidTagInfo info = {.uid = uid, .pTagVal = pCur->pVal};
×
3127
      info.pTagVal = taosMemoryMalloc(pCur->vLen);
3128
      QUERY_CHECK_NULL(info.pTagVal, code, lino, _end, terrno);
3129

3130
      memcpy(info.pTagVal, pCur->pVal, pCur->vLen);
1,922,970✔
3131
      void* tmp = taosArrayPush(aUidTags, &info);
1,922,970✔
3132
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,922,970!
UNCOV
3133
      ++numTables;
×
3134
    }
3135

3136
    if (numTables == 0) {
1,922,970✔
3137
      break;
3138
    }
1,922,970✔
3139
    bool ignoreFilterIdx = true;
3140
    if (pInfo->pTagCond != NULL) {
3141
      ignoreFilterIdx = false;
2,554,978✔
3142
      code = tagScanFilterByTagCond(aUidTags, pInfo->pTagCond, aFilterIdxs, pInfo->readHandle.vnode, pAPI, pInfo);
2,554,978✔
3143
      QUERY_CHECK_CODE(code, lino, _end);
2,554,978✔
3144
    } else {
2,554,978✔
3145
      ignoreFilterIdx = true;
2,554,978✔
3146
    }
1,922,970✔
3147

1,922,970✔
3148
    code = tagScanFillResultBlock(pOperator, pRes, aUidTags, aFilterIdxs, ignoreFilterIdx, pAPI);
1,922,970✔
3149
    QUERY_CHECK_CODE(code, lino, _end);
1,922,970✔
3150

1,922,970✔
3151
    count = ignoreFilterIdx ? taosArrayGetSize(aUidTags) : taosArrayGetSize(aFilterIdxs);
1,922,970✔
3152

1,922,970!
3153
    if (count != 0) {
3154
      break;
1,922,970✔
3155
    }
958,320✔
3156
  }
3157

3158
  if (count > 0) {
3159
    pAPI->metaFn.pauseCtbCursor(pInfo->pCtbCursor);
2,554,978✔
3160
  }
301,767✔
3161
  if (count == 0 || ctbCursorFinished) {
301,767✔
3162
    pAPI->metaFn.closeCtbCursor(pInfo->pCtbCursor);
3163
    pInfo->pCtbCursor = NULL;
3164
    setOperatorCompleted(pOperator);
2,253,211✔
3165
  }
2,253,211✔
3166

3167
  pRes->info.rows = count;
2,253,211✔
3168
  bool bLimitReached = applyLimitOffset(&pInfo->limitInfo, pRes, pTaskInfo);
2,253,211✔
3169
  if (bLimitReached) {
2,253,211✔
3170
    setOperatorCompleted(pOperator);
3171
  }
2,253,211✔
3172

2,253,211✔
3173
  pOperator->resultInfo.totalRows += pRes->info.rows;
2,253,211!
3174
  (*ppRes) = (pRes->info.rows == 0) ? NULL : pInfo->pRes;
3175

2,253,211✔
3176
_end:
28,474✔
3177
  if (code != TSDB_CODE_SUCCESS) {
28,474✔
3178
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
28,474✔
3179
    pTaskInfo->code = code;
3180
    T_LONG_JMP(pTaskInfo->env, code);
3181
  }
2,224,737✔
3182

2,224,737✔
3183
  return code;
2,224,737✔
3184
}
3185

5,328,991!
3186
static int32_t createTagScanTableListInfoFromParam(SOperatorInfo* pOperator) {
3,104,254✔
3187
  STagScanInfo*          pInfo = pOperator->info;
3,104,254!
3188
  SExecTaskInfo*         pTaskInfo = pOperator->pTaskInfo;
3189
  int32_t                code = 0;
3190
  STableListInfo*        pListInfo = pInfo->pTableListInfo;
3,104,254✔
3191
  STagScanOperatorParam* pParam = (STagScanOperatorParam*)pOperator->pOperatorGetParam->value;
3192
  tb_uid_t               pUid = pParam->vcUid;
3,104,254!
3193

3194
  // qDebug("vgId:%d add total %d dynamic tables to scan, tableSeq:%d, exist num:%" PRId64 ", operator status:%d",
3,104,254✔
3195
  //        pTaskInfo->id.vgId, num, pParam->tableSeq, (int64_t)taosArrayGetSize(pListInfo->pTableList),
2,224,737✔
3196
  //        pOperator->status);
3197

3198
  STableKeyInfo info = {.groupId = 0};
3199

2,224,737✔
3200
  int32_t tableIdx = 0;
2,224,737✔
3201
  taosHashClear(pListInfo->map);
2,224,737!
UNCOV
3202
  taosArrayClear(pListInfo->pTableList);
×
3203

3204
  if (taosHashPut(pListInfo->map, &pUid, sizeof(uint64_t), &tableIdx, sizeof(int32_t))) {
3205
    if (TSDB_CODE_DUP_KEY == terrno) {
3206
    } else {
2,224,737!
3207
      return terrno;
2,224,737✔
3208
    }
3209
  }
3210

2,224,737✔
3211
  info.uid = pUid;
3212
  void* p = taosArrayPush(pListInfo->pTableList, &info);
2,224,737!
3213
  if (p == NULL) {
2,224,737✔
3214
    return terrno;
2,224,737!
UNCOV
3215
  }
×
UNCOV
3216

×
UNCOV
3217
  qDebug("add dynamic table scan uid:%" PRIu64 ", %s", info.uid, GET_TASKID(pTaskInfo));
×
3218

3219
  return code;
2,224,737✔
3220
}
3221

UNCOV
3222
static int32_t doTagScanFromMetaEntryNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
×
UNCOV
3223
  int32_t       code = TSDB_CODE_SUCCESS;
×
UNCOV
3224
  int32_t       lino = 0;
×
UNCOV
3225
  STagScanInfo* pInfo = pOperator->info;
×
3226
  if (pOperator->pOperatorGetParam) {
3227
    pOperator->resultInfo.totalRows = 0;
3228
    pOperator->dynamicTask = true;
4,276,281✔
3229
    pInfo->curPos = 0;
4,276,281✔
3230
    code = createTagScanTableListInfoFromParam(pOperator);
4,276,281!
UNCOV
3231
    freeOperatorParam(pOperator->pOperatorGetParam, OP_GET_PARAM);
×
3232
    pOperator->pOperatorGetParam = NULL;
3233
    QUERY_CHECK_CODE(code, lino, _end);
4,278,102✔
3234

4,272,325✔
3235
    if (pOperator->status == OP_EXEC_DONE) {
4,273,184✔
3236
      pOperator->status = OP_OPENED;
4,270,743✔
3237
    }
3238
  }
4,275,130✔
3239

4,275,799✔
3240
  if (pOperator->status == OP_EXEC_DONE) {
4,276,248✔
3241
    (*ppRes) = NULL;
3242
    return code;
4,276,211✔
3243
  }
4,276,421✔
3244

4,274,911!
3245
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
4,272,407✔
3246
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
3247

4,274,480✔
3248
  SExprInfo*   pExprInfo = &pOperator->exprSupp.pExprInfo[0];
3249
  SSDataBlock* pRes = pInfo->pRes;
3250
  blockDataCleanup(pRes);
4,274,480!
3251

3252
  int32_t size = 0;
4,274,820✔
3253
  code = tableListGetSize(pInfo->pTableListInfo, &size);
4,274,820✔
3254
  QUERY_CHECK_CODE(code, lino, _end);
4,274,820✔
3255

4,274,820!
3256
  if (size == 0) {
4,270,577!
3257
    setTaskStatus(pTaskInfo, TASK_COMPLETED);
4,271,024!
UNCOV
3258
    (*ppRes) = NULL;
×
UNCOV
3259
    return code;
×
3260
  }
3261

3262
  SMetaReader mr = {0};
4,271,313✔
3263
  pAPI->metaReaderFn.initReader(&mr, pInfo->readHandle.vnode, META_READER_LOCK, &pAPI->metaFn);
3264
  pRes->info.rows = 0;
4,271,592✔
3265

4,271,579✔
3266
  while (pInfo->curPos < size && pRes->info.rows < pOperator->resultInfo.capacity) {
3267
    code = doTagScanOneTable(pOperator, pRes, &mr, &pTaskInfo->storageAPI);
4,271,804✔
3268
    if (code != TSDB_CODE_OUT_OF_MEMORY && code != TSDB_CODE_QRY_REACH_QMEM_THRESHOLD &&
4,277,778!
3269
        code != TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED) {
3270
      // ignore other error
4,277,778✔
3271
      code = TSDB_CODE_SUCCESS;
4,272,619!
3272
    }
3273
    QUERY_CHECK_CODE(code, lino, _end);
4,272,619✔
3274

4,273,184✔
3275
    if (++pInfo->curPos >= size) {
4,275,952!
3276
      setOperatorCompleted(pOperator);
3277
    }
4,275,952✔
3278
  }
4,276,723✔
3279

4,272,305✔
3280
  pAPI->metaReaderFn.clearReader(&mr);
4,275,393✔
3281
  bool bLimitReached = applyLimitOffset(&pInfo->limitInfo, pRes, pTaskInfo);
3282
  if (bLimitReached) {
4,274,815✔
3283
    setOperatorCompleted(pOperator);
4,268,597✔
3284
  }
4,276,666!
3285

3286
  // qDebug("QInfo:0x%" PRIx64 ", create tag values results completed, rows:%d", GET_TASKID(pRuntimeEnv), count);
4,273,612✔
3287
  if (pOperator->status == OP_EXEC_DONE) {
4,275,665✔
3288
    setTaskStatus(pTaskInfo, TASK_COMPLETED);
3289
  }
4,268,956✔
3290

4,268,551✔
3291
  pOperator->resultInfo.totalRows += pRes->info.rows;
3292

4,268,791✔
3293
  (*ppRes) = (pRes->info.rows == 0) ? NULL : pInfo->pRes;
4,272,489✔
3294
_end:
4,277,684!
3295
  if (code != TSDB_CODE_SUCCESS) {
3296
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4,277,684!
3297
    pTaskInfo->code = code;
2,970,931✔
3298
    T_LONG_JMP(pTaskInfo->env, code);
2,972,017!
3299
  }
3300
  return code;
2,970,333✔
3301
}
2,972,295!
3302

3303
static SSDataBlock* doTagScanFromMetaEntry(SOperatorInfo* pOperator) {
2,970,655✔
3304
  SSDataBlock* pRes = NULL;
2,971,316✔
3305
  int32_t      code = doTagScanFromMetaEntryNext(pOperator, &pRes);
2,969,762!
3306
  return pRes;
3307
}
2,969,659✔
3308

2,970,434!
3309
static void destroyTagScanOperatorInfo(void* param) {
3310
  STagScanInfo* pInfo = (STagScanInfo*)param;
2,970,129✔
3311
  if (pInfo->pCtbCursor != NULL && pInfo->pStorageAPI != NULL) {
955,845✔
3312
    pInfo->pStorageAPI->metaFn.closeCtbCursor(pInfo->pCtbCursor);
3313
  }
3314
  taosHashCleanup(pInfo->filterCtx.colHash);
4,277,175!
3315
  taosArrayDestroy(pInfo->filterCtx.cInfoList);
4,278,262✔
3316
  taosArrayDestroy(pInfo->aFilterIdxs);
3317
  taosArrayDestroyEx(pInfo->aUidTags, tagScanFreeUidTag);
4,273,492✔
3318

4,276,087✔
3319
  blockDataDestroy(pInfo->pRes);
UNCOV
3320
  taosArrayDestroy(pInfo->matchInfo.pList);
×
UNCOV
3321
  tableListDestroy(pInfo->pTableListInfo);
×
UNCOV
3322

×
3323
  pInfo->pRes = NULL;
3324
  pInfo->pTableListInfo = NULL;
UNCOV
3325
  taosMemoryFreeClear(param);
×
UNCOV
3326
}
×
UNCOV
3327

×
UNCOV
3328
int32_t createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pTagScanNode,
×
3329
                                  STableListInfo* pTableListInfo, SNode* pTagCond, SNode* pTagIndexCond,
UNCOV
3330
                                  SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
×
3331
  QRY_PARAM_CHECK(pOptrInfo);
3332

3333
  int32_t         code = TSDB_CODE_SUCCESS;
3334
  int32_t         lino = 0;
3335
  SScanPhysiNode* pPhyNode = (SScanPhysiNode*)pTagScanNode;
191,863,689✔
3336
  STagScanInfo*   pInfo = taosMemoryCalloc(1, sizeof(STagScanInfo));
191,863,689✔
3337
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
191,865,134✔
3338
  if (pInfo == NULL || pOperator == NULL) {
191,865,134✔
3339
    code = terrno;
3340
    goto _error;
191,865,134✔
3341
  }
191,865,423✔
3342

3343
  SDataBlockDescNode* pDescNode = pPhyNode->node.pOutputDataBlockDesc;
191,865,134✔
3344

164,522,414✔
3345
  int32_t    numOfExprs = 0;
27,342,720✔
3346
  SExprInfo* pExprInfo = NULL;
270,720✔
3347

3348
  code = createExprInfo(pPhyNode->pScanPseudoCols, NULL, &pExprInfo, &numOfExprs);
3349
  QUERY_CHECK_CODE(code, lino, _error);
27,072,000✔
3350

27,072,000✔
3351
  code = initExprSupp(&pOperator->exprSupp, pExprInfo, numOfExprs, &pTaskInfo->storageAPI.functionStore);
27,072,000!
3352
  QUERY_CHECK_CODE(code, lino, _error);
27,072,000!
UNCOV
3353

×
3354
  int32_t num = 0;
3355
  code = extractColMatchInfo(pPhyNode->pScanPseudoCols, pDescNode, &num, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo);
27,072,000✔
3356
  QUERY_CHECK_CODE(code, lino, _error);
3357

UNCOV
3358
  pInfo->pTagCond = pTagCond;
×
UNCOV
3359
  pInfo->pTagIndexCond = pTagIndexCond;
×
UNCOV
3360
  pInfo->suid = pPhyNode->suid;
×
UNCOV
3361
  pInfo->pStorageAPI = &pTaskInfo->storageAPI;
×
3362

UNCOV
3363
  pInfo->pTableListInfo = pTableListInfo;
×
UNCOV
3364
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
×
3365
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
UNCOV
3366

×
UNCOV
3367
  pInfo->readHandle = *pReadHandle;
×
UNCOV
3368
  pInfo->curPos = 0;
×
UNCOV
3369

×
3370
  initLimitInfo(pPhyNode->node.pLimit, pPhyNode->node.pSlimit, &pInfo->limitInfo);
3371
  setOperatorInfo(pOperator, "TagScanOperator", QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN, false, OP_NOT_OPENED, pInfo,
UNCOV
3372
                  pTaskInfo);
×
UNCOV
3373
  initResultSizeInfo(&pOperator->resultInfo, 4096);
×
UNCOV
3374
  code = blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
×
UNCOV
3375
  QUERY_CHECK_CODE(code, lino, _error);
×
UNCOV
3376

×
3377
  if (pTagScanNode->onlyMetaCtbIdx) {
UNCOV
3378
    pInfo->aUidTags = taosArrayInit(pOperator->resultInfo.capacity, sizeof(STUidTagInfo));
×
UNCOV
3379
    QUERY_CHECK_NULL(pInfo->aUidTags, code, lino, _error, terrno);
×
UNCOV
3380

×
3381
    pInfo->aFilterIdxs = taosArrayInit(pOperator->resultInfo.capacity, sizeof(int32_t));
UNCOV
3382
    QUERY_CHECK_NULL(pInfo->aFilterIdxs, code, lino, _error, terrno);
×
3383

3384
    pInfo->filterCtx.colHash =
3385
        taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK);
2,435,279✔
3386
    QUERY_CHECK_NULL(pInfo->filterCtx.colHash, code, lino, _error, terrno);
2,435,279✔
3387

2,435,279✔
3388
    pInfo->filterCtx.cInfoList = taosArrayInit(4, sizeof(SColumnInfo));
2,435,279!
3389
    QUERY_CHECK_NULL(pInfo->filterCtx.cInfoList, code, lino, _error, terrno);
2,435,279!
3390

2,435,265!
3391
    if (pInfo->pTagCond != NULL) {
8,117,623✔
3392
      nodesRewriteExprPostOrder(&pTagCond, tagScanRewriteTagColumn, (void*)&pInfo->filterCtx);
5,692,333✔
3393
    }
3394
  }
3395
  __optr_fn_t tagScanNextFn = (pTagScanNode->onlyMetaCtbIdx) ? doTagScanFromCtbIdxNext : doTagScanFromMetaEntryNext;
2,435,540✔
3396
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, tagScanNextFn, NULL, destroyTagScanOperatorInfo,
2,435,540!
UNCOV
3397
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
×
3398
  *pOptrInfo = pOperator;
3399
  return code;
2,433,016✔
3400

3401
_error:
3402
  if (pInfo) {
3,661,706✔
3403
    pInfo->pTableListInfo = NULL;
3404
  }
3,661,706✔
3405

3406
  if (pInfo != NULL) destroyTagScanOperatorInfo(pInfo);
3,661,706✔
3407
  if (pOperator != NULL) {
3,662,545✔
3408
    pOperator->info = NULL;
3,661,128✔
3409
    destroyOperator(pOperator);
3,659,711✔
3410
  }
3,661,135✔
3411
  return code;
3412
}
3,662,263✔
3413

3,659,704!
3414
// table merge scan operator
3,672,248✔
3415

1,837,259✔
3416
static int32_t subTblRowCompareTsFn(const void* pLeft, const void* pRight, void* param) {
1,837,541!
UNCOV
3417
  int32_t                 left = *(int32_t*)pLeft;
×
3418
  int32_t                 right = *(int32_t*)pRight;
3419
  STmsSubTablesMergeInfo* pInfo = (STmsSubTablesMergeInfo*)param;
3420

3421
  int32_t leftIdx = pInfo->aInputs[left].rowIdx;
3,661,121✔
3422
  int32_t rightIdx = pInfo->aInputs[right].rowIdx;
3423

2,890✔
3424
  if (leftIdx == -1) {
3,661,713✔
3425
    return 1;
3,661,142✔
3426
  } else if (rightIdx == -1) {
3,666,013!
UNCOV
3427
    return -1;
×
UNCOV
3428
  }
×
UNCOV
3429

×
3430
  int64_t leftTs = pInfo->aInputs[left].aTs[leftIdx];
3431
  int64_t rightTs = pInfo->aInputs[right].aTs[rightIdx];
3432
  int32_t ret = leftTs > rightTs ? 1 : ((leftTs < rightTs) ? -1 : 0);
3,666,013!
3433
  if (pInfo->pTsOrderInfo->order == TSDB_ORDER_DESC) {
2,443,238!
3434
    ret = -1 * ret;
×
UNCOV
3435
  }
×
UNCOV
3436
  return ret;
×
3437
}
3438

3439
static int32_t subTblRowCompareTsPkFn(const void* pLeft, const void* pRight, void* param) {
2,442,949✔
3440
  int32_t                 left = *(int32_t*)pLeft;
2,442,949✔
3441
  int32_t                 right = *(int32_t*)pRight;
3442
  STmsSubTablesMergeInfo* pInfo = (STmsSubTablesMergeInfo*)param;
3443

1,222,775✔
3444
  int32_t leftIdx = pInfo->aInputs[left].rowIdx;
1,199,366✔
3445
  int32_t rightIdx = pInfo->aInputs[right].rowIdx;
3446

23,409✔
3447
  if (leftIdx == -1) {
3448
    return 1;
3449
  } else if (rightIdx == -1) {
1,222,775✔
3450
    return -1;
1,222,775✔
3451
  }
1,222,775!
UNCOV
3452

×
3453
  int64_t leftTs = pInfo->aInputs[left].aTs[leftIdx];
×
3454
  int64_t rightTs = pInfo->aInputs[right].aTs[rightIdx];
3455
  int32_t ret = leftTs > rightTs ? 1 : ((leftTs < rightTs) ? -1 : 0);
3456
  if (pInfo->pTsOrderInfo->order == TSDB_ORDER_DESC) {
1,222,775!
3457
    ret = -1 * ret;
×
UNCOV
3458
  }
×
3459
  if (ret == 0 && pInfo->pPkOrderInfo) {
3460
    ret = tsortComparBlockCell(pInfo->aInputs[left].pInputBlock, pInfo->aInputs[right].pInputBlock, leftIdx, rightIdx,
1,222,775!
3461
                               pInfo->pPkOrderInfo);
2,890✔
3462
  }
3463
  return ret;
3464
}
1,219,596✔
3465

1,219,596✔
3466
int32_t dumpQueryTableCond(const SQueryTableDataCond* src, SQueryTableDataCond* dst) {
3467
  int32_t code = TSDB_CODE_SUCCESS;
3468
  int32_t lino = 0;
3,662,834!
3469
  memcpy((void*)dst, (void*)src, sizeof(SQueryTableDataCond));
2,439,199✔
3470
  dst->colList = taosMemoryCalloc(src->numOfCols, sizeof(SColumnInfo));
2,439,192✔
3471
  QUERY_CHECK_NULL(dst->colList, code, lino, _end, terrno);
1,219,885✔
3472
  for (int i = 0; i < src->numOfCols; i++) {
3473
    dst->colList[i] = src->colList[i];
3,663,123!
3474
  }
2,751,474✔
3475

2,750,332✔
3476
_end:
3477
  if (code != TSDB_CODE_SUCCESS) {
3478
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
3,661,692✔
3479
  }
3,661,692✔
3480
  return code;
3481
}
3482

1,525,033✔
3483
static int32_t fetchNextSubTableBlockFromReader(SOperatorInfo* pOperator, STmsSubTableInput* pInput,
1,525,033✔
3484
                                                bool* pSubTableHasBlock) {
3485
  int32_t code = 0;
1,527,000✔
3486

1,518,766✔
3487
  STableMergeScanInfo*    pInfo = pOperator->info;
1,512,823!
UNCOV
3488
  SReadHandle*            pHandle = &pInfo->base.readHandle;
×
UNCOV
3489
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
×
3490
  SExecTaskInfo*          pTaskInfo = pOperator->pTaskInfo;
3491
  const SStorageAPI*      pAPI = &pTaskInfo->storageAPI;
3492

1,512,823✔
3493
  blockDataCleanup(pInput->pReaderBlock);
2,425,614✔
3494
  if (!pInput->bInMemReader) {
960,517✔
3495
    code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInput->tblCond, pInput->pKeyInfo, 1, pInput->pReaderBlock,
959,650!
UNCOV
3496
                                         (void**)&pInput->pReader, GET_TASKID(pTaskInfo), NULL);
×
UNCOV
3497
    if (code != 0) {
×
3498
      return code;
3499
    }
959,650✔
3500
  }
48,290✔
3501

3502
  pInfo->base.dataReader = pInput->pReader;
3503

1,513,387✔
3504
  while (true) {
1,527,282✔
3505
    bool hasNext = false;
3506
    code = pAPI->tsdReader.tsdNextDataBlock(pInfo->base.dataReader, &hasNext);
3507
    if (code != 0) {
1,529,573✔
3508
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->base.dataReader);
3,972,529✔
3509
      pInfo->base.dataReader = NULL;
2,442,956✔
3510
      return code;
2,442,110✔
3511
    }
1,223,353✔
3512

3513
    if (!hasNext || isTaskKilled(pTaskInfo)) {
3514
      if (isTaskKilled(pTaskInfo)) {
1,219,885✔
3515
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->base.dataReader);
1,219,596✔
3516
        pInfo->base.dataReader = NULL;
1,219,596✔
3517
        return code;
3518
      }
3519

1,220,174!
3520
      *pSubTableHasBlock = false;
1,219,885✔
3521
      break;
1,219,596!
UNCOV
3522
    }
×
UNCOV
3523

×
3524
    if (pInput->tblCond.order == TSDB_ORDER_ASC) {
3525
      pInput->tblCond.twindows.skey = pInput->pReaderBlock->info.window.ekey + 1;
1,219,596✔
3526
    } else {
3527
      pInput->tblCond.twindows.ekey = pInput->pReaderBlock->info.window.skey - 1;
3528
    }
1,530,144!
3529

1,530,144✔
3530
    uint32_t status = 0;
3531
    code = loadDataBlock(pOperator, &pInfo->base, pInput->pReaderBlock, &status);
3532
    if (code != 0) {
1,524,187✔
3533
      pInfo->base.dataReader = NULL;
1,524,187✔
3534
      return code;
1,524,138!
UNCOV
3535
    }
×
UNCOV
3536

×
3537
    if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
3538
      *pSubTableHasBlock = false;
1,524,138!
3539
      break;
1,517,610!
UNCOV
3540
    }
×
3541
    if (status == FUNC_DATA_REQUIRED_FILTEROUT || pInput->pReaderBlock->info.rows == 0) {
3542
      continue;
1,517,610✔
3543
    }
1,522,439!
UNCOV
3544

×
UNCOV
3545
    *pSubTableHasBlock = true;
×
3546
    break;
3547
  }
1,521,607!
UNCOV
3548

×
UNCOV
3549
  if (*pSubTableHasBlock) {
×
UNCOV
3550
    pInput->pReaderBlock->info.id.groupId =
×
UNCOV
3551
        tableListGetTableGroupId(pInfo->base.pTableListInfo, pInput->pReaderBlock->info.id.uid);
×
3552
    pOperator->resultInfo.totalRows += pInput->pReaderBlock->info.rows;
3553
  }
3554
  if (!pInput->bInMemReader || !*pSubTableHasBlock) {
1,516,785✔
3555
    pAPI->tsdReader.tsdReaderClose(pInput->pReader);
3556
    pInput->pReader = NULL;
1,523,341✔
3557
  }
1,518,181!
3558

1,517,652!
UNCOV
3559
  pInfo->base.dataReader = NULL;
×
UNCOV
3560
  return TSDB_CODE_SUCCESS;
×
3561
}
3562

1,520,183✔
3563
static int32_t setGroupStartEndIndex(STableMergeScanInfo* pInfo) {
1,525,033✔
3564
  pInfo->bGroupProcessed = false;
1,525,308✔
3565

1,519,055!
UNCOV
3566
  int32_t numOfTables = 0;
×
UNCOV
3567
  int32_t code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
×
UNCOV
3568
  if (code != TSDB_CODE_SUCCESS) {
×
3569
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
3570
    return code;
1,519,055✔
3571
  }
1,522,481✔
3572

3573
  int32_t i = pInfo->tableStartIndex + 1;
1,524,476✔
3574
  for (; i < numOfTables; ++i) {
1,512,238✔
3575
    STableKeyInfo* tableKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i);
3576
    if (!tableKeyInfo) {
3577
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
1,519,055✔
3578
      return terrno;
1,519,055✔
3579
    }
1,519,055✔
3580
    if (tableKeyInfo->groupId != pInfo->groupId) {
1,519,055✔
3581
      break;
1,520,183✔
3582
    }
1,523,609✔
3583
  }
3584
  pInfo->tableEndIndex = i - 1;
1,527,014✔
3585
  return TSDB_CODE_SUCCESS;
3586
}
3,959,734✔
3587

2,439,826✔
3588
static int32_t openSubTablesMergeSort(STmsSubTablesMergeInfo* pSubTblsInfo) {
2,432,967✔
3589
  for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
3590
    STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
2,438,677✔
3591
    if (pInput->rowIdx == -1) {
2,430,196!
3592
      continue;
3593
    }
2,430,196✔
3594

2,442,103!
3595
    if (pInput->type == SUB_TABLE_MEM_BLOCK) {
3596
      pInput->rowIdx = 0;
2,442,103✔
3597
      pInput->pageIdx = -1;
2,443,238!
3598
    }
3599

2,443,238✔
3600
    pInput->pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
2,442,674✔
3601
    SColumnInfoData* col = taosArrayGet(pInput->pInputBlock->pDataBlock, pSubTblsInfo->pTsOrderInfo->slotId);
3602
    if (!col) {
2,440,390!
3603
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3604
      return terrno;
3605
    }
3606
    pInput->aTs = (int64_t*)col->pData;
2,437,845✔
3607
  }
1,825,321✔
3608

912,516✔
3609
  __merge_compare_fn_t mergeCompareFn = (!pSubTblsInfo->pPkOrderInfo) ? subTblRowCompareTsFn : subTblRowCompareTsPkFn;
911,938!
3610
  return tMergeTreeCreate(&pSubTblsInfo->pTree, pSubTblsInfo->numSubTables, pSubTblsInfo, mergeCompareFn);
911,938✔
3611
}
3612

1,528,438✔
3613
static int32_t initSubTablesMergeInfo(STableMergeScanInfo* pInfo) {
1,529,016✔
3614
  int32_t code = setGroupStartEndIndex(pInfo);
3615
  if (code != TSDB_CODE_SUCCESS) {
2,440,947✔
3616
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
2,440,369✔
3617
    return code;
2,442,674!
3618
  }
2,442,674!
3619
  STmsSubTablesMergeInfo* pSubTblsInfo = taosMemoryCalloc(1, sizeof(STmsSubTablesMergeInfo));
1,222,789✔
3620
  if (pSubTblsInfo == NULL) {
1,223,353✔
3621
    return terrno;
1,222,500✔
3622
  }
3623
  pSubTblsInfo->pTsOrderInfo = taosArrayGet(pInfo->pSortInfo, 0);
1,219,885✔
3624
  if (!pSubTblsInfo->pTsOrderInfo) {
1,219,596✔
3625
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
3626
    return terrno;
3627
  }
3628
  if (taosArrayGetSize(pInfo->pSortInfo) == 2) {
1,529,291✔
3629
    pSubTblsInfo->pPkOrderInfo = taosArrayGet(pInfo->pSortInfo, 1);
1,529,002!
3630
    if (!pSubTblsInfo->pPkOrderInfo) {
×
3631
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
3632
      return terrno;
1,528,727✔
3633
    }
3634
  } else {
3635
    pSubTblsInfo->pPkOrderInfo = NULL;
1,219,885✔
3636
  }
1,219,885✔
3637
  pSubTblsInfo->numSubTables = pInfo->tableEndIndex - pInfo->tableStartIndex + 1;
1,219,885✔
3638
  pSubTblsInfo->aInputs = taosMemoryCalloc(pSubTblsInfo->numSubTables, sizeof(STmsSubTableInput));
1,219,885✔
3639
  if (pSubTblsInfo->aInputs == NULL) {
1,219,885✔
3640
    taosMemoryFree(pSubTblsInfo);
1,219,885✔
3641
    return terrno;
1,219,885✔
3642
  }
1,219,885✔
3643
  int32_t bufPageSize = pInfo->bufPageSize;
1,219,885!
3644
  int32_t inMemSize = (pSubTblsInfo->numSubTables - pSubTblsInfo->numTableBlocksInMem) * bufPageSize;
3645
  code = createDiskbasedBuf(&pSubTblsInfo->pBlocksBuf, pInfo->bufPageSize, inMemSize, "blocksExternalBuf", tsTempDir);
1,219,885!
3646
  if (code != TSDB_CODE_SUCCESS) {
1,219,885✔
3647
    taosMemoryFree(pSubTblsInfo->aInputs);
1,219,885✔
3648
    taosMemoryFree(pSubTblsInfo);
3649
    return code;
×
3650
  }
3651
  pSubTblsInfo->numTableBlocksInMem = pSubTblsInfo->numSubTables;
3652
  pSubTblsInfo->numInMemReaders = pSubTblsInfo->numSubTables;
1,219,885✔
3653

1,219,885!
UNCOV
3654
  pInfo->pSubTablesMergeInfo = pSubTblsInfo;
×
UNCOV
3655
  return TSDB_CODE_SUCCESS;
×
UNCOV
3656
}
×
3657

3658
static int32_t initSubTableInputs(SOperatorInfo* pOperator, STableMergeScanInfo* pInfo) {
1,219,885✔
3659
  int32_t        code = TSDB_CODE_SUCCESS;
3660
  int32_t        lino = 0;
222,060,122✔
3661
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
222,060,122✔
3662
  SReadHandle*   pHandle = &pInfo->base.readHandle;
222,090,756✔
3663
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
3664

222,087,598!
3665
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
222,110,874✔
3666

220,889,572✔
3667
  for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
1,219,885!
3668
    STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
1,219,885!
3669
    pInput->type = SUB_TABLE_MEM_BLOCK;
1,219,885✔
3670

3671
    code = dumpQueryTableCond(&pInfo->base.cond, &pInput->tblCond);
1,219,885!
UNCOV
3672
    QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
3673

×
UNCOV
3674
    code = createOneDataBlock(pInfo->pResBlock, false, &pInput->pReaderBlock);
×
UNCOV
3675
    QUERY_CHECK_CODE(code, lino, _end);
×
3676

UNCOV
3677
    code = createOneDataBlock(pInfo->pResBlock, false, &pInput->pPageBlock);
×
UNCOV
3678
    QUERY_CHECK_CODE(code, lino, _end);
×
3679

3680
    STableKeyInfo* keyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i + pInfo->tableStartIndex);
3681
    pInput->pKeyInfo = keyInfo;
3682

222,108,315✔
3683
    if (isTaskKilled(pTaskInfo)) {
3684
      T_LONG_JMP(pTaskInfo->env, pTaskInfo->code);
3685
    }
222,003,114✔
3686

222,003,114✔
3687
    if (i + 1 < pSubTblsInfo->numInMemReaders) {
222,003,114✔
3688
      code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInput->tblCond, keyInfo, 1, pInput->pReaderBlock,
222,003,114✔
3689
                                           (void**)&pInput->pReader, GET_TASKID(pTaskInfo), NULL);
222,004,230!
3690
      QUERY_CHECK_CODE(code, lino, _end);
3691
      pInput->bInMemReader = true;
910,086,774✔
3692
    } else {
687,489,963✔
3693
      pInput->pReader = NULL;
687,638,619!
3694
      pInput->bInMemReader = false;
3695
    }
687,638,619✔
3696
    bool hasNext = true;
687,410,528!
3697
    code = fetchNextSubTableBlockFromReader(pOperator, pInput, &hasNext);
687,410,528!
3698
    QUERY_CHECK_CODE(code, lino, _end);
3699
    if (!hasNext) {
687,741,772✔
3700
      pInput->rowIdx = -1;
72,897,677✔
3701
      ++pSubTblsInfo->numSubTablesCompleted;
72,896,521!
3702
      continue;
3703
    } else {
614,844,095!
3704
      pInput->rowIdx = 0;
614,878,817!
3705
      pInput->pageIdx = -1;
615,320,492✔
3706
    }
615,123,313!
3707
  }
3708

3709
_end:
3710
  if (code != TSDB_CODE_SUCCESS) {
222,092,744✔
3711
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
222,093,900✔
3712
  }
222,094,189✔
3713
  return code;
3714
}
222,094,774✔
3715

222,094,774!
UNCOV
3716
static void adjustSubTableFromMemBlock(SOperatorInfo* pOperatorInfo, STmsSubTablesMergeInfo* pSubTblsInfo) {
×
3717
  int32_t              code = TSDB_CODE_SUCCESS;
3718
  int32_t              lino = 0;
222,093,329✔
3719
  SExecTaskInfo*       pTaskInfo = pOperatorInfo->pTaskInfo;
3720
  STableMergeScanInfo* pInfo = pOperatorInfo->info;
3721
  STmsSubTableInput*   pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
2,479,027✔
3722
  bool                 hasNext = true;
3723
  code = fetchNextSubTableBlockFromReader(pOperatorInfo, pInput, &hasNext);
2,479,027✔
3724
  QUERY_CHECK_CODE(code, lino, _end);
2,479,027✔
3725

2,479,027✔
3726
  if (!hasNext) {
2,479,020✔
3727
    pInput->rowIdx = -1;
2,479,027✔
3728
    ++pSubTblsInfo->numSubTablesCompleted;
2,479,020✔
3729
  } else {
3730
    pInput->rowIdx = 0;
2,479,020!
3731
  }
3732

2,479,309✔
3733
_end:
UNCOV
3734
  if (code != TSDB_CODE_SUCCESS) {
×
3735
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
3736
    pTaskInfo->code = code;
224,487,590✔
3737
    T_LONG_JMP(pTaskInfo->env, code);
2,479,309✔
3738
  }
2,479,309✔
3739
}
3740

3741
static int32_t adjustSubTableForNextRow(SOperatorInfo* pOperatorInfo, STmsSubTablesMergeInfo* pSubTblsInfo) {
222,005,412✔
3742
  STableMergeScanInfo* pInfo = pOperatorInfo->info;
222,092,476!
3743
  STmsSubTableInput*   pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
3744

222,092,476✔
3745
  SSDataBlock* pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
222,008,288!
3746
  if (pInput->rowIdx < pInputBlock->info.rows - 1) {
3747
    ++pInput->rowIdx;
222,008,288!
UNCOV
3748
  } else if (pInput->rowIdx == pInputBlock->info.rows - 1) {
×
3749
    if (pInput->type == SUB_TABLE_MEM_BLOCK) {
3750
      adjustSubTableFromMemBlock(pOperatorInfo, pSubTblsInfo);
3751
    }
3752
    if (pInput->rowIdx != -1) {
2,479,309!
3753
      SColumnInfoData* col = taosArrayGet(pInputBlock->pDataBlock, pSubTblsInfo->pTsOrderInfo->slotId);
×
3754
      if (!col) {
3755
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
3756
        return terrno;
2,479,309✔
3757
      }
2,479,027!
3758
      pInput->pInputBlock = pInputBlock;
3759
      pInput->aTs = (int64_t*)col->pData;
3760
    }
3761
  }
3762

2,479,027✔
3763
  return tMergeTreeAdjust(pSubTblsInfo->pTree, tMergeTreeGetAdjustIndex(pSubTblsInfo->pTree));
949,165✔
3764
}
3765

3766
static int32_t appendChosenRowToDataBlock(STmsSubTablesMergeInfo* pSubTblsInfo, SSDataBlock* pBlock) {
1,529,862✔
3767
  int32_t            code = TSDB_CODE_SUCCESS;
2,479,027!
UNCOV
3768
  int32_t            lino = 0;
×
UNCOV
3769
  STmsSubTableInput* pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
×
3770
  SSDataBlock*       pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
3771

2,479,027✔
3772
  for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); ++i) {
3773
    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
3774
    QUERY_CHECK_NULL(pColInfo, code, lino, _end, terrno);
1,524,751✔
3775

1,524,751✔
3776
    SColumnInfoData* pSrcColInfo = taosArrayGet(pInputBlock->pDataBlock, i);
1,524,751✔
3777
    QUERY_CHECK_NULL(pSrcColInfo, code, lino, _end, terrno);
1,524,751✔
3778
    bool isNull = colDataIsNull(pSrcColInfo, pInputBlock->info.rows, pInput->rowIdx, NULL);
3779

1,526,161✔
3780
    if (isNull) {
1,512,816!
3781
      code = colDataSetVal(pColInfo, pBlock->info.rows, NULL, true);
3782
      QUERY_CHECK_CODE(code, lino, _end);
1,512,816✔
3783
    } else {
1,529,573!
3784
      if (pSrcColInfo->pData != NULL) {
3785
        char* pData = colDataGetData(pSrcColInfo, pInput->rowIdx);
1,529,573✔
3786
        code = colDataSetVal(pColInfo, pBlock->info.rows, pData, false);
1,529,573!
3787
        QUERY_CHECK_CODE(code, lino, _end);
3788
      }
1,529,573✔
3789
    }
1,529,573!
UNCOV
3790
  }
×
3791
  pBlock->info.dataLoad = 1;
3792
  pBlock->info.scanFlag = pInputBlock->info.scanFlag;
1,529,573✔
3793
  pBlock->info.rows += 1;
3794

3795
_end:
31,130,139✔
3796
  if (code != TSDB_CODE_SUCCESS) {
31,130,139✔
3797
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
31,132,047✔
3798
  }
1,529,862✔
3799
  return code;
3800
}
3,972,536✔
3801

2,442,956✔
3802
static int32_t getSubTablesSortedBlock(SOperatorInfo* pOperator, SSDataBlock* pBlock, int32_t capacity,
2,442,956!
3803
                                       SSDataBlock** pResBlock) {
2,442,392✔
3804
  int32_t                 code = TSDB_CODE_SUCCESS;
2,442,674✔
3805
  int32_t                 lino = 0;
2,442,674✔
3806
  STableMergeScanInfo*    pInfo = pOperator->info;
2,442,674✔
3807
  SExecTaskInfo*          pTaskInfo = pOperator->pTaskInfo;
2,442,674✔
3808
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
3809
  bool                    finished = false;
3810

1,529,862✔
3811
  QRY_PARAM_CHECK(pResBlock);
1,528,438!
3812

3813
  blockDataCleanup(pBlock);
1,529,009!
3814

1,529,009✔
3815
  while (true) {
3816
    while (true) {
3817
      if (pSubTblsInfo->numSubTablesCompleted >= pSubTblsInfo->numSubTables) {
3818
        finished = true;
31,131,476✔
3819
        break;
3820
      }
2,461,455✔
3821

2,461,455!
3822
      code = appendChosenRowToDataBlock(pSubTblsInfo, pBlock);
3823
      QUERY_CHECK_CODE(code, lino, _end);
2,463,161✔
3824

2,463,161✔
3825
      code = adjustSubTableForNextRow(pOperator, pSubTblsInfo);
2,454,631✔
3826
      QUERY_CHECK_CODE(code, lino, _end);
3827

2,454,631✔
3828
      if (pBlock->info.rows >= capacity) {
2,460,038✔
3829
        break;
3830
      }
2,463,436!
UNCOV
3831
    }
×
3832

3833
    if (isTaskKilled(pTaskInfo)) {
3834
      return pTaskInfo->code;
2,454,060✔
3835
    }
2,460,334!
3836

3837
    bool limitReached = applyLimitOffset(&pInfo->limitInfo, pBlock, pTaskInfo);
2,460,334✔
3838
    if (finished || limitReached || pBlock->info.rows > 0) {
2,460,320!
3839
      break;
3840
    }
2,460,320!
3841
  }
1,510,309✔
3842

3843
  if (pBlock->info.rows > 0) {
1,503,175✔
3844
    *pResBlock = pBlock;
35,547✔
3845
  }
35,258✔
3846

35,258✔
3847
_end:
3848
  if (code != TSDB_CODE_SUCCESS) {
3849
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
1,467,628✔
3850
    pTaskInfo->code = code;
1,474,755✔
3851
  }
1,469,059!
3852
  return code;
1,469,059✔
3853
}
1,477,018✔
3854

1,481,283!
3855
static int32_t startSubTablesTableMergeScan(SOperatorInfo* pOperator) {
3856
  int32_t              code = TSDB_CODE_SUCCESS;
3857
  int32_t              lino = 0;
2,431,294✔
3858
  STableMergeScanInfo* pInfo = pOperator->info;
2,478,738✔
3859

2,478,456!
UNCOV
3860
  code = initSubTablesMergeInfo(pInfo);
×
3861
  QUERY_CHECK_CODE(code, lino, _end);
3862

3863
  code = initSubTableInputs(pOperator, pInfo);
2,478,456✔
3864
  QUERY_CHECK_CODE(code, lino, _end);
2,479,309!
3865

3866
  code = openSubTablesMergeSort(pInfo->pSubTablesMergeInfo);
2,479,309!
UNCOV
3867
  QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
3868

×
3869
_end:
UNCOV
3870
  if (code != TSDB_CODE_SUCCESS) {
×
3871
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
3872
  }
3873
  return code;
2,479,027✔
3874
}
949,165✔
3875

949,165✔
3876
static void stopSubTablesTableMergeScan(STableMergeScanInfo* pInfo) {
949,165✔
3877
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
949,165✔
3878
  if (pSubTblsInfo != NULL) {
3879
    tMergeTreeDestroy(&pSubTblsInfo->pTree);
3880

1,529,862✔
3881
    for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
1,528,720✔
3882
      STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
1,480,430✔
3883
      taosMemoryFree(pInput->tblCond.colList);
1,481,001✔
3884
      blockDataDestroy(pInput->pReaderBlock);
3885
      blockDataDestroy(pInput->pPageBlock);
3886
      taosArrayDestroy(pInput->aBlockPages);
48,290✔
3887
      pInfo->base.readerAPI.tsdReaderClose(pInput->pReader);
48,290✔
3888
      pInput->pReader = NULL;
48,290!
3889
    }
3890

48,290✔
3891
    destroyDiskbasedBuf(pSubTblsInfo->pBlocksBuf);
48,290✔
3892
    taosMemoryFree(pSubTblsInfo->aInputs);
48,290!
3893

48,290✔
3894
    taosMemoryFree(pSubTblsInfo);
3895
    pInfo->pSubTablesMergeInfo = NULL;
3896

3897
    // taosMemoryTrim(0);
2,430,730✔
3898
  }
3899
}
2,430,737✔
3900

2,430,455!
UNCOV
3901
int32_t doTableMergeScanParaSubTablesNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
×
UNCOV
3902
  QRY_PARAM_CHECK(ppRes);
×
UNCOV
3903

×
3904
  int32_t lino = 0;
3905
  int32_t tableListSize = 0;
2,430,455✔
3906
  int64_t st = taosGetTimestampUs();
3907

3908
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
2,430,455✔
3909
  STableMergeScanInfo* pInfo = pOperator->info;
3910

3911
  if (pOperator->status == OP_EXEC_DONE) {
2,002,642✔
3912
    return TSDB_CODE_SUCCESS;
2,002,642✔
3913
  }
2,002,642✔
3914

2,002,642✔
3915
  int32_t code = pOperator->fpSet._openFn(pOperator);
2,002,642✔
3916
  QUERY_CHECK_CODE(code, lino, _end);
2,002,642✔
3917

3918
  code = tableListGetSize(pInfo->base.pTableListInfo, &tableListSize);
2,002,642✔
3919
  QUERY_CHECK_CODE(code, lino, _end);
209,849✔
3920

3921
  if (!pInfo->hasGroupId) {
209,849!
3922
    pInfo->hasGroupId = true;
3923

2,002,642✔
3924
    if (tableListSize == 0) {
2,002,642!
3925
      setOperatorCompleted(pOperator);
2,002,642✔
3926
      (*ppRes) = NULL;
2,002,642!
UNCOV
3927
      return code;
×
3928
    }
3929

2,002,642!
3930
    pInfo->tableStartIndex = 0;
3931
    STableKeyInfo* pTmpGpId = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
3932
    QUERY_CHECK_NULL(pTmpGpId, code, lino, _end, terrno);
2,002,642✔
3933
    pInfo->groupId = pTmpGpId->groupId;
2,002,642!
UNCOV
3934
    code = startSubTablesTableMergeScan(pOperator);
×
UNCOV
3935
    QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
3936
  }
×
3937

3938
  SSDataBlock* pBlock = NULL;
2,002,642✔
3939
  while (pInfo->tableStartIndex < tableListSize) {
3940
    if (isTaskKilled(pTaskInfo)) {
127,904,249✔
3941
      break;
127,904,249✔
3942
    }
127,906,580✔
3943

127,905,389✔
3944
    code = getSubTablesSortedBlock(pOperator, pInfo->pResBlock, pOperator->resultInfo.capacity, &pBlock);
127,910,029✔
3945
    QUERY_CHECK_CODE(code, lino, _end);
127,902,679✔
3946

127,902,679✔
3947
    if (pBlock == NULL && !pInfo->bGroupProcessed && pInfo->needCountEmptyTable) {
127,908,900✔
3948
      STableKeyInfo* tbInfo = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
3949
      QUERY_CHECK_NULL(tbInfo, code, lino, _end, terrno);
127,903,816✔
3950

127,875,015!
3951
      pBlock = getOneRowResultBlock(pTaskInfo, &pInfo->base, pInfo->pResBlock, tbInfo);
×
UNCOV
3952
    }
×
UNCOV
3953

×
UNCOV
3954
    if (pBlock != NULL) {
×
3955
      pBlock->info.id.groupId = pInfo->groupId;
3956
      pOperator->resultInfo.totalRows += pBlock->info.rows;
3957
      pInfo->bGroupProcessed = true;
127,875,015!
3958
      break;
27,390,016✔
3959
    } else {
432!
3960
      // Data of this group are all dumped, let's try the next group
432✔
3961
      stopSubTablesTableMergeScan(pInfo);
3962
      if (pInfo->tableEndIndex >= tableListSize - 1) {
27,397,109✔
3963
        setOperatorCompleted(pOperator);
27,393,916✔
3964
        break;
3965
      }
3966

100,494,240✔
3967
      pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
100,490,663✔
3968
      STableKeyInfo* pTmpGpId = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
3969
      QUERY_CHECK_NULL(pTmpGpId, code, lino, _end, terrno);
100,502,041!
UNCOV
3970

×
UNCOV
3971
      pInfo->groupId = pTmpGpId->groupId;
×
UNCOV
3972
      code = startSubTablesTableMergeScan(pOperator);
×
3973
      QUERY_CHECK_CODE(code, lino, _end);
3974
      resetLimitInfoForNextGroup(&pInfo->limitInfo);
3975
    }
100,502,041!
UNCOV
3976
  }
×
UNCOV
3977

×
3978
  pOperator->cost.totalCost += (taosGetTimestampUs() - st) / 1000.0;
3979

3980
_end:
3981
  if (code != TSDB_CODE_SUCCESS) {
100,502,041✔
3982
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4,571,398✔
3983
    pTaskInfo->code = code;
4,566,865✔
3984
    T_LONG_JMP(pTaskInfo->env, code);
3985
  } else {
3986
    (*ppRes) = pBlock;
95,930,131✔
3987
  }
3988

3989
  return code;
127,532,772✔
3990
}
127,532,772✔
3991

3992
static void tableMergeScanDoSkipTable(uint64_t uid, void* pTableMergeOpInfo) {
127,532,772✔
3993
  int32_t              code = TSDB_CODE_SUCCESS;
127,537,435✔
3994
  int32_t              lino = 0;
127,536,828✔
3995
  SOperatorInfo*       pOperator = (SOperatorInfo*)pTableMergeOpInfo;
127,538,330✔
3996
  STableMergeScanInfo* pInfo = pOperator->info;
127,523,920✔
3997
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
127,523,920✔
3998

3999
  if (pInfo->mSkipTables == NULL) {
4000
    pInfo->mSkipTables = taosHashInit(pInfo->tableEndIndex - pInfo->tableStartIndex + 1,
136,156,730!
4001
                                      taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_NO_LOCK);
8,262,751✔
4002
    QUERY_CHECK_NULL(pInfo->mSkipTables, code, lino, _end, terrno);
4003
  }
4004
  int bSkip = 1;
8,263,925✔
4005
  if (pInfo->mSkipTables != NULL) {
4,066,749✔
4006
    code = taosHashPut(pInfo->mSkipTables, &uid, sizeof(uid), &bSkip, sizeof(bSkip));
4,066,749✔
4007
    if (code == TSDB_CODE_DUP_KEY) {
4008
      code = TSDB_CODE_SUCCESS;
8,262,534✔
4009
    }
4,065,945✔
4010
    QUERY_CHECK_CODE(code, lino, _end);
4,065,945✔
4011
  }
4012

4013
_end:
4,196,589✔
4014
  if (code != TSDB_CODE_SUCCESS) {
4,196,589✔
4015
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4,196,589✔
4016
    pTaskInfo->code = code;
4,196,589✔
4017
    T_LONG_JMP(pTaskInfo->env, code);
4018
  }
4019
}
127,905,213✔
4020

127,902,893✔
4021
static int32_t doGetBlockForTableMergeScan(SOperatorInfo* pOperator, bool* pFinished, bool* pSkipped) {
4022
  STableMergeScanInfo* pInfo = pOperator->info;
127,911,805✔
4023
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
127,896,854!
UNCOV
4024
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
×
4025
  SSDataBlock*         pBlock = pInfo->pReaderBlock;
4026
  int32_t              code = 0;
4027
  bool                 hasNext = false;
127,896,854✔
4028
  STsdbReader*         reader = pInfo->base.dataReader;
127,890,317!
4029

4030
  code = pAPI->tsdReader.tsdNextDataBlock(reader, &hasNext);
127,916,619!
4031
  if (code != 0) {
27,398,465✔
4032
    pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
27,398,465✔
4033
    qError("table merge scan fetch next data block error code: %d, %s", code, GET_TASKID(pTaskInfo));
4034
    pTaskInfo->code = code;
4035
    return code;
100,518,154!
4036
  }
4,219,131!
4037

4,066,749✔
4038
  if (!hasNext || isTaskKilled(pTaskInfo)) {
4,066,749!
UNCOV
4039
    if (isTaskKilled(pTaskInfo)) {
×
UNCOV
4040
      qInfo("table merge scan fetch next data block found task killed. %s", GET_TASKID(pTaskInfo));
×
4041
      pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
4042
    }
4043
    *pFinished = true;
4,066,749✔
4044
    return code;
4,066,749!
UNCOV
4045
  }
×
4046

UNCOV
4047
  uint32_t status = 0;
×
UNCOV
4048
  code = loadDataBlock(pOperator, &pInfo->base, pBlock, &status);
×
4049

4050
  if (code != TSDB_CODE_SUCCESS) {
4051
    qInfo("table merge scan load datablock code %d, %s", code, GET_TASKID(pTaskInfo));
4052
    pTaskInfo->code = code;
4,219,131!
4053
    return code;
4,196,806✔
4054
  }
4,197,393✔
4055

4,196,806✔
4056
  if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
4057
    *pFinished = true;
4058
    return code;
×
UNCOV
4059
  }
×
UNCOV
4060

×
4061
  // current block is filter out according to filter condition, continue load the next block
4062
  if (status == FUNC_DATA_REQUIRED_FILTEROUT || pBlock->info.rows == 0) {
4063
    *pSkipped = true;
96,320,179!
4064
    return code;
4065
  }
4066

95,951,202✔
4067
  return code;
4068
}
95,951,289✔
4069

95,951,202✔
4070
static int32_t getBlockForTableMergeScan(void* param, SSDataBlock** ppBlock) {
95,950,411✔
4071
  STableMergeScanSortSourceParam* source = param;
4072

95,950,120✔
4073
  SOperatorInfo*       pOperator = source->pOperator;
4074
  STableMergeScanInfo* pInfo = pOperator->info;
4075
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
27,398,187✔
4076
  SSDataBlock*         pBlock = NULL;
27,398,187✔
4077
  int64_t              st = taosGetTimestampUs();
4078
  int32_t              code = TSDB_CODE_SUCCESS;
4079

29,589,584✔
4080
  while (true) {
29,589,584✔
4081
    if (pInfo->rtnNextDurationBlocks) {
29,589,584✔
4082
      qDebug("%s table merge scan return already fetched new duration blocks. index %d num of blocks %d",
29,589,584✔
4083
             GET_TASKID(pTaskInfo), pInfo->nextDurationBlocksIdx, pInfo->numNextDurationBlocks);
29,574,623!
4084

29,574,623✔
4085
      if (pInfo->nextDurationBlocksIdx < pInfo->numNextDurationBlocks) {
29,577,429✔
4086
        pBlock = pInfo->nextDurationBlocks[pInfo->nextDurationBlocksIdx];
4087
        ++pInfo->nextDurationBlocksIdx;
29,579,362✔
4088
      } else {
29,579,362✔
4089
        for (int32_t i = 0; i < pInfo->numNextDurationBlocks; ++i) {
95,720,829✔
4090
          blockDataDestroy(pInfo->nextDurationBlocks[i]);
66,170,696✔
4091
          pInfo->nextDurationBlocks[i] = NULL;
66,173,511!
4092
        }
66,173,511✔
4093

29,588,406✔
4094
        pInfo->rtnNextDurationBlocks = false;
29,593,481✔
4095
        pInfo->nextDurationBlocksIdx = 0;
29,593,481✔
4096
        pInfo->numNextDurationBlocks = 0;
29,593,481✔
4097
        continue;
29,593,481✔
4098
      }
4099
    } else {
4100
      bool bFinished = false;
66,168,553!
4101
      bool bSkipped = false;
763,087✔
4102

763,087✔
4103
      code = doGetBlockForTableMergeScan(pOperator, &bFinished, &bSkipped);
763,087✔
4104
      if (code != 0) {
763,087✔
4105
        return code;
763,087✔
4106
      }
4107

4108
      pBlock = pInfo->pReaderBlock;
4109
      qDebug("%s table merge scan fetch block. finished %d skipped %d next-duration-block %d new-fileset %d",
29,596,268✔
4110
             GET_TASKID(pTaskInfo), bFinished, bSkipped, pInfo->bNextDurationBlockEvent, pInfo->bNewFilesetEvent);
29,596,268!
4111
      if (bFinished) {
29,596,268✔
4112
        pInfo->bNewFilesetEvent = false;
763,087✔
4113
        break;
763,087!
4114
      }
4115

4116
      if (pInfo->bNextDurationBlockEvent || pInfo->bNewFilesetEvent) {
29,597,034✔
4117
        if (!bSkipped) {
4118
          code = createOneDataBlock(pBlock, true, &pInfo->nextDurationBlocks[pInfo->numNextDurationBlocks]);
29,579,486✔
4119
          if (code) {
29,580,644!
4120
            *ppBlock = NULL;
×
4121
            return code;
4122
          }
29,580,644✔
4123

4124
          ++pInfo->numNextDurationBlocks;
4125
          if (pInfo->numNextDurationBlocks > 2) {
5,967,483✔
4126
            qError("%s table merge scan prefetch %d next duration blocks. end early.", GET_TASKID(pTaskInfo),
5,967,483✔
4127
                   pInfo->numNextDurationBlocks);
5,967,483!
4128
            pInfo->bNewFilesetEvent = false;
5,969,875✔
4129
            break;
×
UNCOV
4130
          }
×
4131
        }
4132

5,959,444!
4133
        if (pInfo->bNewFilesetEvent) {
4134
          pInfo->rtnNextDurationBlocks = true;
5,971,228✔
4135
          *ppBlock = NULL;
4136
          return code;
4137
        }
32,082,687✔
4138

32,082,687✔
4139
        if (pInfo->bNextDurationBlockEvent) {
32,096,317✔
4140
          pInfo->bNextDurationBlockEvent = false;
4141
          continue;
32,100,367✔
4142
        }
32,100,367✔
4143
      }
32,100,367✔
4144
      if (bSkipped) continue;
4145
    }
32,078,321✔
4146

32,100,382✔
4147
    pBlock->info.id.groupId = tableListGetTableGroupId(pInfo->base.pTableListInfo, pBlock->info.id.uid);
32,112,682✔
4148

4149
    pOperator->resultInfo.totalRows += pBlock->info.rows;
32,110,828✔
4150
    pInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
32,110,550!
4151
    *ppBlock = pBlock;
4152

32,108,492✔
4153
    return code;
64,219,728✔
4154
  }
32,108,566✔
4155

32,096,170!
UNCOV
4156
  *ppBlock = NULL;
×
4157
  return code;
4158
}
4159

32,096,170!
4160
int32_t generateSortByTsPkInfo(SArray* colMatchInfo, int32_t order, SArray** ppSortArray) {
875,789✔
4161
  int32_t code = TSDB_CODE_SUCCESS;
875,789✔
4162
  int32_t lino = 0;
876,197!
4163
  SArray* pSortInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
4164
  QUERY_CHECK_NULL(pSortInfo, code, lino, _end, terrno);
4165
  SBlockOrderInfo biTs = {0};
32,100,738✔
4166
  SBlockOrderInfo biPk = {0};
32,099,242✔
4167

32,099,430✔
4168
  int32_t tsTargetSlotId = 0;
4169
  int32_t pkTargetSlotId = -1;
32,102,955✔
4170
  for (int32_t i = 0; i < taosArrayGetSize(colMatchInfo); ++i) {
32,102,374!
4171
    SColMatchItem* colInfo = taosArrayGet(colMatchInfo, i);
4172
    QUERY_CHECK_NULL(colInfo, code, lino, _end, terrno);
32,102,374!
4173
    if (colInfo->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
32,098,718!
4174
      tsTargetSlotId = colInfo->dstSlotId;
32,098,718✔
4175
      biTs.order = order;
4176
      biTs.slotId = tsTargetSlotId;
32,096,553!
4177
      biTs.nullFirst = (order == TSDB_ORDER_ASC);
32,092,398!
UNCOV
4178
      biTs.compFn = getKeyComparFunc(TSDB_DATA_TYPE_TIMESTAMP, order);
×
UNCOV
4179
    }
×
4180
    // TODO: order by just ts
4181
    if (colInfo->isPk) {
4182
      pkTargetSlotId = colInfo->dstSlotId;
32,092,398✔
4183
      biPk.order = order;
32,098,143✔
4184
      biPk.slotId = pkTargetSlotId;
32,101,296✔
4185
      biPk.nullFirst = (order == TSDB_ORDER_ASC);
32,105,335!
4186
      biPk.compFn = getKeyComparFunc(colInfo->dataType.type, order);
4187
    }
32,105,335✔
4188
  }
24,598,889✔
4189

4190
  void* tmp = taosArrayPush(pSortInfo, &biTs);
7,506,446✔
4191
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
7,508,803!
4192
  if (pkTargetSlotId != -1) {
4193
    tmp = taosArrayPush(pSortInfo, &biPk);
4194
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
7,508,803✔
4195
  }
32,107,917!
UNCOV
4196

×
4197
  (*ppSortArray) = pSortInfo;
4198

32,105,995✔
4199
_end:
4200
  if (code != TSDB_CODE_SUCCESS) {
4201
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
32,114,234✔
4202
  }
32,114,234✔
4203
  return code;
32,113,956✔
4204
}
32,114,160✔
4205

4206
void tableMergeScanTsdbNotifyCb(ETsdReaderNotifyType type, STsdReaderNotifyInfo* info, void* param) {
32,113,573✔
4207
  STableMergeScanInfo* pTmsInfo = param;
32,113,295✔
4208
  if (type == TSD_READER_NOTIFY_DURATION_START) {
32,113,851✔
4209
    pTmsInfo->bNewFilesetEvent = true;
32,112,226✔
4210
  } else if (type == TSD_READER_NOTIFY_NEXT_DURATION_BLOCK) {
32,113,851✔
4211
    pTmsInfo->bNextDurationBlockEvent = true;
32,111,930✔
4212
  }
4213
  qDebug("table merge scan receive notification. type %d, fileset %d", type, info->duration.filesetId);
32,112,517✔
4214

32,113,956✔
4215
  return;
32,113,956✔
4216
}
4217

27,909,138✔
4218
int32_t startDurationForGroupTableMergeScan(SOperatorInfo* pOperator) {
27,909,138✔
4219
  STableMergeScanInfo* pInfo = pOperator->info;
27,909,138✔
4220
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
27,909,138✔
4221

27,911,517✔
4222
  int32_t code = TSDB_CODE_SUCCESS;
27,905,045✔
4223
  int32_t lino = 0;
27,900,427✔
4224
  int32_t numOfTable = pInfo->tableEndIndex - pInfo->tableStartIndex + 1;
27,907,718✔
4225

4226
  qDebug("%s table merge scan start duration ", GET_TASKID(pTaskInfo));
4227
  pInfo->bNewFilesetEvent = false;
27,907,939✔
4228
  pInfo->bNextDurationBlockEvent = false;
27,903,685✔
4229

27,913,009!
4230
  pInfo->sortBufSize = 2048 * pInfo->bufPageSize;
4231
  int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
27,913,009✔
4232

104,991,153✔
4233
  pInfo->pSortHandle = NULL;
80,961,648✔
4234
  code = tsortCreateSortHandle(pInfo->pSortInfo, SORT_BLOCK_TS_MERGE, pInfo->bufPageSize, numOfBufPage,
80,961,648!
4235
                               pInfo->pSortInputBlock, pTaskInfo->id.str, 0, 0, 0, &pInfo->pSortHandle);
80,961,648✔
4236
  if (code) {
3,882,280✔
4237
    return code;
4238
  }
4239

27,911,785✔
4240
  if (pInfo->bSortRowId && numOfTable != 1) {
4241
    int32_t memSize = 512 * 1024 * 1024;
27,915,697✔
4242
    code = tsortSetSortByRowId(pInfo->pSortHandle, memSize);
27,915,085✔
4243
    QUERY_CHECK_CODE(code, lino, _end);
27,911,173✔
4244
  }
4245

27,916,661✔
4246
  tsortSetMergeLimit(pInfo->pSortHandle, pInfo->mergeLimit);
27,916,661✔
4247
  tsortSetMergeLimitReachedFp(pInfo->pSortHandle, tableMergeScanDoSkipTable, pOperator);
55,817,195✔
4248
  tsortSetAbortCheckFn(pInfo->pSortHandle, isTaskKilled, pOperator->pTaskInfo);
27,909,994✔
4249

27,892,472!
4250
  tsortSetFetchRawDataFp(pInfo->pSortHandle, getBlockForTableMergeScan, NULL, NULL);
27,892,472!
4251
  QUERY_CHECK_CODE(code, lino, _end);
27,898,692✔
4252

4253
  STableMergeScanSortSourceParam* param = taosMemoryCalloc(1, sizeof(STableMergeScanSortSourceParam));
27,898,164✔
4254
  QUERY_CHECK_NULL(param, code, lino, _end, terrno);
4255
  param->pOperator = pOperator;
27,876,942✔
4256

27,909,210!
4257
  SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
4258
  if (ps == NULL) {
27,909,210✔
4259
    taosMemoryFree(param);
27,908,320!
4260
    QUERY_CHECK_NULL(ps, code, lino, _end, terrno);
×
UNCOV
4261
  }
×
UNCOV
4262

×
4263
  ps->param = param;
4264
  ps->onlyRef = false;
27,908,320✔
4265
  code = tsortAddSource(pInfo->pSortHandle, ps);
4266
  QUERY_CHECK_CODE(code, lino, _end);
27,916,841✔
4267

27,916,841✔
4268
  if (numOfTable == 1) {
27,916,841✔
4269
    tsortSetSingleTableMerge(pInfo->pSortHandle);
27,916,563✔
4270
  } else {
4271
    code = tsortOpen(pInfo->pSortHandle);
27,916,767✔
4272
    QUERY_CHECK_CODE(code, lino, _end);
4273
  }
27,915,426!
4274

27,916,767✔
4275
_end:
27,896,630✔
4276
  if (code != TSDB_CODE_SUCCESS) {
4277
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
27,898,808✔
4278
  }
804!
4279
  return code;
804✔
4280
}
804✔
4281

4282
void stopDurationForGroupTableMergeScan(SOperatorInfo* pOperator) {
804✔
4283
  STableMergeScanInfo* pInfo = pOperator->info;
804✔
4284
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
4285
  qDebug("%s table merge scan stop duration ", GET_TASKID(pTaskInfo));
27,907,643✔
4286

27,898,778✔
4287
  SSortExecInfo sortExecInfo = tsortGetSortExecInfo(pInfo->pSortHandle);
27,895,682✔
4288
  pInfo->sortExecInfo.sortMethod = sortExecInfo.sortMethod;
27,897,970✔
4289
  pInfo->sortExecInfo.sortBuffer = sortExecInfo.sortBuffer;
27,917,538✔
4290
  pInfo->sortExecInfo.loops += sortExecInfo.loops;
4291
  pInfo->sortExecInfo.readBytes += sortExecInfo.readBytes;
4292
  pInfo->sortExecInfo.writeBytes += sortExecInfo.writeBytes;
4293

65,166,638✔
4294
  tsortDestroySortHandle(pInfo->pSortHandle);
4295
  pInfo->pSortHandle = NULL;
65,166,638✔
4296
}
65,171,762✔
4297

65,168,400✔
4298
void startGroupTableMergeScan(SOperatorInfo* pOperator) {
4299
  int32_t              code = TSDB_CODE_SUCCESS;
65,175,554✔
4300
  int32_t              lino = 0;
UNCOV
4301
  STableMergeScanInfo* pInfo = pOperator->info;
×
4302
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
2,147,483,647✔
4303
  SReadHandle*         pHandle = &pInfo->base.readHandle;
2,147,483,647✔
4304
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
2,147,483,647✔
4305
  qDebug("%s table merge scan start group %" PRIu64, GET_TASKID(pTaskInfo), pInfo->groupId);
2,147,483,647✔
4306

67,649!
4307
  {
67,649!
4308
    int32_t numOfTables = 0;
4309
    code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
2,147,483,647✔
4310
    QUERY_CHECK_CODE(code, lino, _end);
51,314,549✔
4311

4312
    int32_t i = pInfo->tableStartIndex + 1;
4313
    for (; i < numOfTables; ++i) {
2,147,483,647✔
4314
      STableKeyInfo* tableKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i);
2,147,483,647!
UNCOV
4315
      QUERY_CHECK_NULL(tableKeyInfo, code, lino, _end, terrno);
×
UNCOV
4316
      if (tableKeyInfo->groupId != pInfo->groupId) {
×
4317
        break;
4318
      }
4319
    }
2,147,483,647✔
4320
    pInfo->tableEndIndex = i - 1;
13,859,010✔
4321
  }
4322
  pInfo->bGroupProcessed = false;
4323
  int32_t tableStartIdx = pInfo->tableStartIndex;
4324
  int32_t tableEndIdx = pInfo->tableEndIndex;
65,173,559!
UNCOV
4325

×
UNCOV
4326
  int32_t        numOfTable = tableEndIdx - tableStartIdx + 1;
×
4327
  STableKeyInfo* startKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, tableStartIdx);
4328
  code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInfo->base.cond, startKeyInfo, numOfTable, pInfo->pReaderBlock,
4329
                                       (void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), &pInfo->mSkipTables);
65,178,163✔
4330
  QUERY_CHECK_CODE(code, lino, _end);
65,175,651✔
4331
  if (pInfo->filesetDelimited) {
4332
    pAPI->tsdReader.tsdSetFilesetDelimited(pInfo->base.dataReader);
65,177,519!
4333
  }
4334
  pAPI->tsdReader.tsdSetSetNotifyCb(pInfo->base.dataReader, tableMergeScanTsdbNotifyCb, pInfo);
4335

4336
  code = startDurationForGroupTableMergeScan(pOperator);
65,177,519✔
4337
  QUERY_CHECK_CODE(code, lino, _end);
4338

4339
_end:
61,177,178✔
4340
  if (code != TSDB_CODE_SUCCESS) {
61,177,178✔
4341
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
36,501✔
4342
    pTaskInfo->code = code;
36,501✔
4343
    T_LONG_JMP(pTaskInfo->env, code);
4344
  }
4345
}
61,138,715✔
4346

61,138,715✔
4347
void stopGroupTableMergeScan(SOperatorInfo* pOperator) {
61,138,715✔
4348
  STableMergeScanInfo* pInfo = pOperator->info;
61,142,818✔
4349
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
4350
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
61,143,905✔
4351

61,132,132!
4352
  stopDurationForGroupTableMergeScan(pOperator);
4353

61,140,134✔
4354
  if (pInfo->base.dataReader != NULL) {
4355
    pAPI->tsdReader.tsdReaderClose(pInfo->base.dataReader);
61,140,134✔
4356
    pInfo->base.dataReader = NULL;
61,138,540✔
4357
  }
61,141,578!
4358
  for (int32_t i = 0; i < pInfo->numNextDurationBlocks; ++i) {
4359
    if (pInfo->nextDurationBlocks[i]) {
61,141,578!
4360
      blockDataDestroy(pInfo->nextDurationBlocks[i]);
28,078,506✔
4361
      pInfo->nextDurationBlocks[i] = NULL;
4362
    }
28,071,687✔
4363
    pInfo->numNextDurationBlocks = 0;
4,049,883✔
4364
    pInfo->nextDurationBlocksIdx = 0;
4,049,092✔
4365
  }
4,049,500✔
4366
  resetLimitInfoForNextGroup(&pInfo->limitInfo);
4367
  taosHashCleanup(pInfo->mSkipTables);
24,021,804✔
4368
  pInfo->mSkipTables = NULL;
24,025,981✔
4369
  qDebug("%s table merge scan stop group %" PRIu64, GET_TASKID(pTaskInfo), pInfo->groupId);
24,019,376!
4370
}
24,019,376✔
4371

24,029,474✔
4372
// all data produced by this function only belongs to one group
4373
// slimit/soffset does not need to be concerned here, since this function only deal with data within one group.
4374
SSDataBlock* getSortedTableMergeScanBlockData(SSortHandle* pHandle, SSDataBlock* pResBlock, int32_t capacity,
57,087,422✔
4375
                                              SOperatorInfo* pOperator) {
65,165,921!
4376
  STableMergeScanInfo* pInfo = pOperator->info;
65,171,559!
UNCOV
4377
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
×
4378
  STupleHandle*        pTupleHandle = NULL;
4379

4380
  blockDataCleanup(pResBlock);
65,173,727✔
4381

4382
  while (1) {
65,178,767!
4383
    while (1) {
810,256✔
4384
      pTupleHandle = NULL;
810,256!
4385
      int32_t code = tsortNextTuple(pHandle, &pTupleHandle);
810,256✔
4386
      if (code != TSDB_CODE_SUCCESS) {
4387
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
65,178,971✔
4388
        T_LONG_JMP(pOperator->pTaskInfo->env, code);
33,064,533✔
4389
      }
33,064,737✔
4390
      if (pTupleHandle == NULL) {
33,064,533✔
4391
        break;
33,064,533✔
4392
      }
4393

32,114,438!
4394
      code = tsortAppendTupleToBlock(pInfo->pSortHandle, pResBlock, pTupleHandle);
4,197,393✔
4395
      if (code != TSDB_CODE_SUCCESS) {
4,197,393✔
4396
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
4,196,219!
4397
        T_LONG_JMP(pOperator->pTaskInfo->env, terrno);
4398
      }
4399

27,917,045✔
4400
      if (pResBlock->info.rows >= capacity) {
27,916,433✔
4401
        break;
24,032,620✔
4402
      }
24,033,745✔
4403
    }
4404

4405
    if (tsortIsClosed(pHandle)) {
3,882,280✔
4406
      terrno = TSDB_CODE_TSC_QUERY_CANCELLED;
3,882,059✔
4407
      T_LONG_JMP(pOperator->pTaskInfo->env, terrno);
3,882,059!
4408
    }
3,882,059✔
4409

3,882,059✔
4410
    bool limitReached = applyLimitOffset(&pInfo->limitInfo, pResBlock, pTaskInfo);
3,881,838✔
4411
    qDebug("%s get sorted row block, rows:%" PRId64 ", limit:%" PRId64, GET_TASKID(pTaskInfo), pResBlock->info.rows,
4412
           pInfo->limitInfo.numOfOutputRows);
4413
    if (pTupleHandle == NULL || limitReached || pResBlock->info.rows > 0) {
4414
      break;
4415
    }
57,098,278✔
4416
  }
4417
  return (pResBlock->info.rows > 0) ? pResBlock : NULL;
57,098,130✔
4418
}
57,097,722!
UNCOV
4419

×
UNCOV
4420
int32_t doTableMergeScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
×
UNCOV
4421
  if (pOperator->status == OP_EXEC_DONE) {
×
4422
    (*ppRes) = NULL;
4423
    return TSDB_CODE_SUCCESS;
57,097,722✔
4424
  }
4425

4426
  int32_t              code = TSDB_CODE_SUCCESS;
57,097,987✔
4427
  int32_t              lino = 0;
4428
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
UNCOV
4429
  STableMergeScanInfo* pInfo = pOperator->info;
×
UNCOV
4430

×
UNCOV
4431
  code = pOperator->fpSet._openFn(pOperator);
×
UNCOV
4432
  QUERY_CHECK_CODE(code, lino, _end);
×
4433

4434
  int64_t st = taosGetTimestampUs();
4435

29,601,724✔
4436
  int32_t tableListSize = 0;
29,601,724✔
4437
  code = tableListGetSize(pInfo->base.pTableListInfo, &tableListSize);
4438
  QUERY_CHECK_CODE(code, lino, _end);
4439

29,601,724✔
4440
  if (!pInfo->hasGroupId) {
29,601,450✔
4441
    pInfo->hasGroupId = true;
29,601,625✔
4442

4443
    if (tableListSize == 0) {
4444
      setOperatorCompleted(pOperator);
29,601,123!
UNCOV
4445
      (*ppRes) = NULL;
×
UNCOV
4446
      return code;
×
UNCOV
4447
    }
×
4448
    pInfo->tableStartIndex = 0;
4449
    STableKeyInfo* tmp = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
4450
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
4451
    pInfo->groupId = tmp->groupId;
29,600,003✔
4452
    startGroupTableMergeScan(pOperator);
29,601,341✔
4453
  }
29,601,341✔
4454

29,599,555✔
4455
  SSDataBlock* pBlock = NULL;
29,600,445✔
4456
  while (pInfo->tableStartIndex < tableListSize) {
29,600,839✔
4457
    if (isTaskKilled(pTaskInfo)) {
4458
      goto _end;
4459
    }
29,600,048✔
4460

29,600,301✔
4461
    pBlock = getSortedTableMergeScanBlockData(pInfo->pSortHandle, pInfo->pResBlock, pOperator->resultInfo.capacity,
4462
                                              pOperator);
29,602,387✔
4463
    if (pBlock == NULL && !pInfo->bGroupProcessed && pInfo->needCountEmptyTable) {
29,600,559✔
4464
      STableKeyInfo* tbInfo = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
4465
      QUERY_CHECK_NULL(tbInfo, code, lino, _end, terrno);
4466
      pBlock = getOneRowResultBlock(pTaskInfo, &pInfo->base, pInfo->pResBlock, tbInfo);
29,601,086✔
4467
    }
29,600,199✔
4468
    if (pBlock != NULL) {
29,600,199✔
4469
      pBlock->info.id.groupId = pInfo->groupId;
4470
      pOperator->resultInfo.totalRows += pBlock->info.rows;
29,598,886✔
4471
      pInfo->bGroupProcessed = true;
4472
      break;
29,600,848!
4473
    } else {
29,598,124✔
4474
      if (pInfo->bNewFilesetEvent) {
4475
        stopDurationForGroupTableMergeScan(pOperator);
1,933,843✔
4476
        code = startDurationForGroupTableMergeScan(pOperator);
1,933,843!
UNCOV
4477
        QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
4478
      } else {
×
4479
        // Data of this group are all dumped, let's try the next group
4480
        stopGroupTableMergeScan(pOperator);
4481
        if (pInfo->tableEndIndex >= tableListSize - 1) {
1,933,843!
4482
          setOperatorCompleted(pOperator);
1,933,843!
UNCOV
4483
          break;
×
4484
        }
4485

1,933,843✔
4486
        pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
1,933,843✔
4487
        STableKeyInfo* tmp = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
1,933,843✔
4488
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
4489
        pInfo->groupId = tmp->groupId;
1,933,843✔
4490
        startGroupTableMergeScan(pOperator);
1,933,843✔
4491
        resetLimitInfoForNextGroup(&pInfo->limitInfo);
4492
      }
1,933,843✔
4493
    }
4494
  }
4495

29,577,451✔
4496
  pOperator->cost.totalCost += (taosGetTimestampUs() - st) / 1000.0;
4497

4498
_end:
29,577,451!
4499
  if (code != TSDB_CODE_SUCCESS) {
4500
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
29,583,775✔
4501
    pTaskInfo->code = code;
29,583,775✔
4502
    T_LONG_JMP(pTaskInfo->env, code);
29,583,775!
4503
  } else {
29,554,335!
4504
    (*ppRes) = pBlock;
29,556,788!
4505
  }
246✔
UNCOV
4506

×
4507
  return code;
4508
}
4509

29,556,708✔
4510
static SSDataBlock* doTableMergeScan(SOperatorInfo* pOperator) {
4511
  SSDataBlock* pRes = NULL;
29,563,265✔
4512
  int32_t      code = doTableMergeScanNext(pOperator, &pRes);
29,565,772✔
4513
  return pRes;
4514
}
29,585,805!
4515

4516
void destroyTableMergeScanOperatorInfo(void* param) {
29,585,805✔
4517
  STableMergeScanInfo* pTableScanInfo = (STableMergeScanInfo*)param;
29,581,384!
4518

4519
  // start one reader variable
29,581,384✔
4520
  if (pTableScanInfo->base.readerAPI.tsdReaderClose != NULL) {
13,649,794✔
4521
    pTableScanInfo->base.readerAPI.tsdReaderClose(pTableScanInfo->base.dataReader);
13,656,621✔
4522
    pTableScanInfo->base.dataReader = NULL;
13,647,658!
4523
  }
4524

13,647,658✔
4525
  for (int32_t i = 0; i < pTableScanInfo->numNextDurationBlocks; ++i) {
4526
    if (pTableScanInfo->nextDurationBlocks[i] != NULL) {
13,636,631!
4527
      blockDataDestroy(pTableScanInfo->nextDurationBlocks[i]);
4528
      pTableScanInfo->nextDurationBlocks[i] = NULL;
4529
    }
29,566,335✔
4530
  }
4531

29,566,867✔
4532
  tsortDestroySortHandle(pTableScanInfo->pSortHandle);
29,593,220!
4533
  pTableScanInfo->pSortHandle = NULL;
4534
  taosHashCleanup(pTableScanInfo->mSkipTables);
29,566,288✔
4535
  pTableScanInfo->mSkipTables = NULL;
29,589,788✔
4536
  blockDataDestroy(pTableScanInfo->pSortInputBlock);
29,554,171✔
4537
  pTableScanInfo->pSortInputBlock = NULL;
29,576,212✔
4538
  // end one reader variable
4539

29,583,418✔
4540
  cleanupQueryTableDataCond(&pTableScanInfo->base.cond);
4541
  destroyTableScanBase(&pTableScanInfo->base, &pTableScanInfo->base.readerAPI);
29,546,116✔
4542

29,558,016✔
4543
  blockDataDestroy(pTableScanInfo->pResBlock);
29,587,337✔
4544
  pTableScanInfo->pResBlock = NULL;
4545

29,554,392✔
4546
  // remove it from the task->result list
29,577,247✔
4547
  blockDataDestroy(pTableScanInfo->pReaderBlock);
4548
  pTableScanInfo->pReaderBlock = NULL;
29,577,614✔
4549
  taosArrayDestroy(pTableScanInfo->pSortInfo);
29,582,970✔
4550

29,566,611!
4551
  stopSubTablesTableMergeScan(pTableScanInfo);
4552

29,566,611✔
4553
  taosMemoryFreeClear(param);
4554
}
29,552,654✔
4555

29,554,089✔
4556
int32_t getTableMergeScanExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
29,579,504✔
4557
  if (pOptr == NULL) {
4,068,225✔
4558
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_INVALID_PARA));
528,331✔
4559
    return TSDB_CODE_INVALID_PARA;
2,561,025✔
4560
  }
2,032,419✔
4561
  // TODO: merge these two info into one struct
4562
  STableMergeScanExecInfo* execInfo = taosMemoryCalloc(1, sizeof(STableMergeScanExecInfo));
4563
  if (!execInfo) {
29,577,064✔
4564
    return terrno;
29,582,699✔
4565
  }
29,597,699!
4566
  STableMergeScanInfo* pInfo = pOptr->info;
29,582,487✔
4567
  execInfo->blockRecorder = pInfo->base.readRecorder;
29,592,926!
4568
  execInfo->sortExecInfo = pInfo->sortExecInfo;
29,592,926!
4569

3,014,319✔
4570
  *pOptrExplain = execInfo;
4571
  *len = sizeof(STableMergeScanExecInfo);
26,580,522✔
4572

4573
  return TSDB_CODE_SUCCESS;
4574
}
29,581,858✔
4575

29,587,422!
4576
int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle,
4577
                                         STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo,
29,587,422✔
4578
                                         SOperatorInfo** pOptrInfo) {
29,571,260!
4579
  QRY_PARAM_CHECK(pOptrInfo);
4580

29,571,260✔
4581
  int32_t              code = TSDB_CODE_SUCCESS;
29,591,465!
4582
  int32_t              lino = 0;
4583
  STableMergeScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableMergeScanInfo));
29,591,465!
4584
  SOperatorInfo*       pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4585
  if (pInfo == NULL || pOperator == NULL) {
29,591,306✔
4586
    code = terrno;
29,594,734✔
4587
    goto _error;
4588
  }
29,567,445✔
4589

4590
  SDataBlockDescNode* pDescNode = pTableScanNode->scan.node.pOutputDataBlockDesc;
4591

29,590,832✔
4592
  int32_t numOfCols = 0;
29,585,123!
4593
  code = extractColMatchInfo(pTableScanNode->scan.pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID,
4594
                             &pInfo->base.matchInfo);
29,585,123!
UNCOV
4595
  QUERY_CHECK_CODE(code, lino, _error);
×
4596

4597
  code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, readHandle);
29,585,123!
4598
  QUERY_CHECK_CODE(code, lino, _error);
4599

4600
  if (pTableScanNode->scan.pScanPseudoCols != NULL) {
29,585,367✔
4601
    SExprSupp* pSup = &pInfo->base.pseudoSup;
4602
    code = createExprInfo(pTableScanNode->scan.pScanPseudoCols, NULL, &pSup->pExprInfo, &pSup->numOfExprs);
29,577,196✔
4603
    QUERY_CHECK_CODE(code, lino, _error);
4604

29,571,378✔
4605
    pSup->pCtx = createSqlFunctionCtx(pSup->pExprInfo, pSup->numOfExprs, &pSup->rowEntryInfoOffset,
29,587,161!
4606
                                      &pTaskInfo->storageAPI.functionStore);
4607
    QUERY_CHECK_NULL(pSup->pCtx, code, lino, _error, terrno);
4608
  }
29,564,529✔
4609

4610
  pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]};
29,570,484✔
4611

29,557,376✔
4612
  pInfo->base.metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024 * 128, -1, .5);
UNCOV
4613
  QUERY_CHECK_NULL(pInfo->base.metaCache.pTableMetaEntryCache, code, lino, _error, terrno);
×
UNCOV
4614

×
UNCOV
4615
  pInfo->base.readerAPI = pTaskInfo->storageAPI.tsdReader;
×
4616
  pInfo->base.dataBlockLoadFlag = FUNC_DATA_REQUIRED_DATA_LOAD;
UNCOV
4617
  pInfo->base.scanFlag = MAIN_SCAN;
×
UNCOV
4618
  pInfo->base.readHandle = *readHandle;
×
UNCOV
4619

×
UNCOV
4620
  pInfo->readIdx = -1;
×
4621

UNCOV
4622
  pInfo->base.limitInfo.limit.limit = -1;
×
UNCOV
4623
  pInfo->base.limitInfo.slimit.limit = -1;
×
UNCOV
4624
  pInfo->base.pTableListInfo = pTableListInfo;
×
4625

UNCOV
4626
  pInfo->sample.sampleRatio = pTableScanNode->ratio;
×
4627
  pInfo->sample.seed = taosGetTimestampSec();
4628

4629
  code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0,
4630
                            pTaskInfo->pStreamRuntimeInfo);
4631
  QUERY_CHECK_CODE(code, lino, _error);
4632

4633
  initLimitInfo(pTableScanNode->scan.node.pLimit, pTableScanNode->scan.node.pSlimit, &pInfo->limitInfo);
4634

4635
  pInfo->mergeLimit = -1;
4636
  bool hasLimit = pInfo->limitInfo.limit.limit != -1 || pInfo->limitInfo.limit.offset != -1;
4637
  if (hasLimit) {
4638
    pInfo->mergeLimit = pInfo->limitInfo.limit.offset != -1
4639
                            ? pInfo->limitInfo.limit.limit + pInfo->limitInfo.limit.offset
4640
                            : pInfo->limitInfo.limit.limit;
4641
    pInfo->mSkipTables = NULL;
4642
  }
4643

4644
  initResultSizeInfo(&pOperator->resultInfo, 1024);
4645
  pInfo->pResBlock = createDataBlockFromDescNode(pDescNode);
4646
  QUERY_CHECK_NULL(pInfo->pResBlock, code, lino, _error, terrno);
4647
  code = blockDataEnsureCapacity(pInfo->pResBlock, pOperator->resultInfo.capacity);
4648
  QUERY_CHECK_CODE(code, lino, _error);
4649
  if (!hasLimit && blockDataGetRowSize(pInfo->pResBlock) >= 256 && !pTableScanNode->smallDataTsSort) {
UNCOV
4650
    pInfo->bSortRowId = true;
×
UNCOV
4651
  } else {
×
UNCOV
4652
    pInfo->bSortRowId = false;
×
UNCOV
4653
  }
×
UNCOV
4654

×
UNCOV
4655
  code = prepareDataBlockBuf(pInfo->pResBlock, &pInfo->base.matchInfo);
×
4656
  QUERY_CHECK_CODE(code, lino, _error);
UNCOV
4657

×
UNCOV
4658
  code = generateSortByTsPkInfo(pInfo->base.matchInfo.pList, pInfo->base.cond.order, &pInfo->pSortInfo);
×
UNCOV
4659
  QUERY_CHECK_CODE(code, lino, _error);
×
4660

UNCOV
4661
  code = createOneDataBlock(pInfo->pResBlock, false, &pInfo->pReaderBlock);
×
UNCOV
4662
  QUERY_CHECK_CODE(code, lino, _error);
×
UNCOV
4663

×
UNCOV
4664
  pInfo->needCountEmptyTable = tsCountAlwaysReturnValue && pTableScanNode->needCountEmptyTable;
×
UNCOV
4665

×
4666
  int32_t  rowSize = pInfo->pResBlock->info.rowSize;
4667
  uint32_t nCols = taosArrayGetSize(pInfo->pResBlock->pDataBlock);
4668

UNCOV
4669
  pInfo->bufPageSize = getProperSortPageSize(rowSize, nCols);
×
4670

4671
  // start one reader variable
UNCOV
4672
  code = createOneDataBlock(pInfo->pResBlock, false, &pInfo->pSortInputBlock);
×
UNCOV
4673
  QUERY_CHECK_CODE(code, lino, _error);
×
UNCOV
4674

×
UNCOV
4675
  if (!tsExperimental) {
×
4676
    pInfo->filesetDelimited = false;
×
UNCOV
4677
  } else {
×
4678
    pInfo->filesetDelimited = pTableScanNode->filesetDelimited;
UNCOV
4679
  }
×
UNCOV
4680
  // end one reader variable
×
UNCOV
4681
  setOperatorInfo(pOperator, "TableMergeScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN, false, OP_NOT_OPENED,
×
4682
                  pInfo, pTaskInfo);
UNCOV
4683
  pOperator->exprSupp.numOfExprs = numOfCols;
×
UNCOV
4684

×
UNCOV
4685
  pOperator->fpSet = createOperatorFpSet(
×
4686
      optrDummyOpenFn, pTableScanNode->paraTablesSort ? doTableMergeScanParaSubTablesNext : doTableMergeScanNext, NULL,
4687
      destroyTableMergeScanOperatorInfo, optrDefaultBufFn, getTableMergeScanExplainExecInfo, optrDefaultGetNextExtFn,
4688
      NULL);
UNCOV
4689
  pOperator->cost.openCost = 0;
×
4690

4691
  *pOptrInfo = pOperator;
UNCOV
4692
  return code;
×
UNCOV
4693

×
4694
_error:
×
4695
  if (code != TSDB_CODE_SUCCESS) {
×
4696
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
4697
  }
×
4698
  pTaskInfo->code = code;
4699
  if (pInfo != NULL) {
×
4700
    pInfo->base.pTableListInfo = NULL;
×
4701
    destroyTableMergeScanOperatorInfo(pInfo);
×
4702
  }
4703
  if (pOperator != NULL) {
×
4704
    pOperator->info = NULL;
×
4705
    destroyOperator(pOperator);
4706
  }
4707
  return code;
UNCOV
4708
}
×
UNCOV
4709

×
4710
// ====================================================================================================================
UNCOV
4711
// TableCountScanOperator
×
4712
static void        destoryTableCountScanOperator(void* param);
4713
static int32_t     buildVnodeGroupedStbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
UNCOV
4714
                                                  SSDataBlock* pRes, char* dbName, tb_uid_t stbUid, SStorageAPI* pAPI);
×
4715
static int32_t     buildVnodeGroupedNtbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
UNCOV
4716
                                                  SSDataBlock* pRes, char* dbName, SStorageAPI* pAPI);
×
UNCOV
4717
static int32_t     buildVnodeFilteredTbCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
UNCOV
4718
                                             STableCountScanSupp* pSupp, SSDataBlock* pRes, char* dbName);
×
UNCOV
4719
static int32_t     buildVnodeGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
UNCOV
4720
                                               STableCountScanSupp* pSupp, SSDataBlock* pRes, int32_t vgId, char* dbName);
×
4721
static int32_t     buildVnodeDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
4722
                                          STableCountScanSupp* pSupp, SSDataBlock* pRes);
UNCOV
4723
static void        buildSysDbGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
UNCOV
4724
                                               STableCountScanSupp* pSupp, SSDataBlock* pRes, size_t infodbTableNum,
×
UNCOV
4725
                                               size_t perfdbTableNum);
×
4726
static void        buildSysDbFilterTableCount(SOperatorInfo* pOperator, STableCountScanSupp* pSupp, SSDataBlock* pRes,
UNCOV
4727
                                              size_t infodbTableNum, size_t perfdbTableNum);
×
UNCOV
4728
static const char* GROUP_TAG_DB_NAME = "db_name";
×
UNCOV
4729
static const char* GROUP_TAG_STABLE_NAME = "stable_name";
×
UNCOV
4730

×
4731
int32_t tblCountScanGetGroupTagsSlotId(const SNodeList* scanCols, STableCountScanSupp* supp) {
4732
  if (scanCols != NULL) {
4733
    SNode* pNode = NULL;
×
4734
    FOREACH(pNode, scanCols) {
×
4735
      if (nodeType(pNode) != QUERY_NODE_TARGET) {
×
4736
        return TSDB_CODE_QRY_SYS_ERROR;
×
4737
      }
4738
      STargetNode* targetNode = (STargetNode*)pNode;
×
4739
      if (nodeType(targetNode->pExpr) != QUERY_NODE_COLUMN) {
4740
        return TSDB_CODE_QRY_SYS_ERROR;
UNCOV
4741
      }
×
4742
      SColumnNode* colNode = (SColumnNode*)(targetNode->pExpr);
4743
      if (strcmp(colNode->colName, GROUP_TAG_DB_NAME) == 0) {
×
4744
        supp->dbNameSlotId = targetNode->slotId;
4745
      } else if (strcmp(colNode->colName, GROUP_TAG_STABLE_NAME) == 0) {
×
4746
        supp->stbNameSlotId = targetNode->slotId;
×
UNCOV
4747
      }
×
UNCOV
4748
    }
×
UNCOV
4749
  }
×
4750
  return TSDB_CODE_SUCCESS;
×
UNCOV
4751
}
×
UNCOV
4752

×
4753
int32_t tblCountScanGetCountSlotId(const SNodeList* pseudoCols, STableCountScanSupp* supp) {
4754
  if (pseudoCols != NULL) {
4755
    SNode* pNode = NULL;
×
4756
    FOREACH(pNode, pseudoCols) {
4757
      if (nodeType(pNode) != QUERY_NODE_TARGET) {
×
4758
        return TSDB_CODE_QRY_SYS_ERROR;
×
UNCOV
4759
      }
×
4760
      STargetNode* targetNode = (STargetNode*)pNode;
×
4761
      if (nodeType(targetNode->pExpr) != QUERY_NODE_FUNCTION) {
4762
        return TSDB_CODE_QRY_SYS_ERROR;
×
UNCOV
4763
      }
×
4764
      SFunctionNode* funcNode = (SFunctionNode*)(targetNode->pExpr);
4765
      if (funcNode->funcType == FUNCTION_TYPE_TABLE_COUNT) {
×
4766
        supp->tbCountSlotId = targetNode->slotId;
4767
      }
UNCOV
4768
    }
×
4769
  }
4770
  return TSDB_CODE_SUCCESS;
×
4771
}
UNCOV
4772

×
4773
int32_t tblCountScanGetInputs(SNodeList* groupTags, SName* tableName, STableCountScanSupp* supp) {
4774
  if (groupTags != NULL) {
×
4775
    SNode* pNode = NULL;
×
4776
    FOREACH(pNode, groupTags) {
4777
      if (nodeType(pNode) != QUERY_NODE_COLUMN) {
×
4778
        return TSDB_CODE_QRY_SYS_ERROR;
×
UNCOV
4779
      }
×
4780
      SColumnNode* colNode = (SColumnNode*)pNode;
4781
      if (strcmp(colNode->colName, GROUP_TAG_DB_NAME) == 0) {
×
4782
        supp->groupByDbName = true;
×
UNCOV
4783
      }
×
4784
      if (strcmp(colNode->colName, GROUP_TAG_STABLE_NAME) == 0) {
4785
        supp->groupByStbName = true;
×
UNCOV
4786
      }
×
4787
    }
4788
  } else {
4789
    tstrncpy(supp->dbNameFilter, tNameGetDbNameP(tableName), TSDB_DB_NAME_LEN);
×
4790
    tstrncpy(supp->stbNameFilter, tNameGetTableName(tableName), TSDB_TABLE_NAME_LEN);
UNCOV
4791
  }
×
4792
  return TSDB_CODE_SUCCESS;
×
UNCOV
4793
}
×
UNCOV
4794

×
4795
int32_t getTableCountScanSupp(SNodeList* groupTags, SName* tableName, SNodeList* scanCols, SNodeList* pseudoCols,
×
UNCOV
4796
                              STableCountScanSupp* supp, SExecTaskInfo* taskInfo) {
×
4797
  int32_t code = 0;
4798
  code = tblCountScanGetInputs(groupTags, tableName, supp);
×
4799
  if (code != TSDB_CODE_SUCCESS) {
×
4800
    qError("%s get table count scan supp. get inputs error", GET_TASKID(taskInfo));
4801
    return code;
×
UNCOV
4802
  }
×
UNCOV
4803

×
4804
  supp->dbNameSlotId = -1;
4805
  supp->stbNameSlotId = -1;
4806
  supp->tbCountSlotId = -1;
×
UNCOV
4807

×
4808
  code = tblCountScanGetGroupTagsSlotId(scanCols, supp);
×
4809
  if (code != TSDB_CODE_SUCCESS) {
×
4810
    qError("%s get table count scan supp. get group tags slot id error", GET_TASKID(taskInfo));
×
4811
    return code;
×
UNCOV
4812
  }
×
UNCOV
4813

×
4814
  code = tblCountScanGetCountSlotId(pseudoCols, supp);
×
4815
  if (code != TSDB_CODE_SUCCESS) {
4816
    qError("%s get table count scan supp. get count error", GET_TASKID(taskInfo));
4817
    return code;
4818
  }
4819
  return code;
UNCOV
4820
}
×
UNCOV
4821

×
4822
int32_t createTableCountScanOperatorInfo(SReadHandle* readHandle, STableCountScanPhysiNode* pTblCountScanNode,
×
UNCOV
4823
                                         SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
×
4824
  QRY_PARAM_CHECK(pOptrInfo);
×
4825

4826
  int32_t                      code = TSDB_CODE_SUCCESS;
×
4827
  int32_t                      lino = 0;
4828
  SScanPhysiNode*              pScanNode = &pTblCountScanNode->scan;
×
4829
  STableCountScanOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(STableCountScanOperatorInfo));
×
4830
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
×
4831
  if (!pInfo || !pOperator) {
4832
    code = terrno;
×
4833
    goto _error;
4834
  }
UNCOV
4835

×
4836
  pInfo->readHandle = *readHandle;
×
UNCOV
4837

×
4838
  SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc;
4839
  initResultSizeInfo(&pOperator->resultInfo, 1);
×
4840
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
×
4841
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
×
UNCOV
4842

×
4843
  code = blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
×
4844
  QUERY_CHECK_CODE(code, lino, _error);
UNCOV
4845

×
4846
  code = getTableCountScanSupp(pTblCountScanNode->pGroupTags, &pTblCountScanNode->scan.tableName,
×
UNCOV
4847
                               pTblCountScanNode->scan.pScanCols, pTblCountScanNode->scan.pScanPseudoCols, &pInfo->supp,
×
4848
                               pTaskInfo);
4849
  QUERY_CHECK_CODE(code, lino, _error);
×
UNCOV
4850

×
4851
  setOperatorInfo(pOperator, "TableCountScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN, false, OP_NOT_OPENED,
4852
                  pInfo, pTaskInfo);
4853
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableCountScanNext, NULL, destoryTableCountScanOperator,
UNCOV
4854
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
×
4855
  *pOptrInfo = pOperator;
4856
  return code;
×
UNCOV
4857

×
4858
_error:
×
4859
  if (pInfo != NULL) {
×
4860
    destoryTableCountScanOperator(pInfo);
×
UNCOV
4861
  }
×
4862
  if (pOperator != NULL) {
×
4863
    pOperator->info = NULL;
×
4864
    destroyOperator(pOperator);
×
UNCOV
4865
  }
×
4866
  pTaskInfo->code = code;
×
4867
  return code;
×
4868
}
4869

4870
int32_t fillTableCountScanDataBlock(STableCountScanSupp* pSupp, char* dbName, char* stbName, int64_t count,
×
UNCOV
4871
                                    SSDataBlock* pRes) {
×
4872
  int32_t code = TSDB_CODE_SUCCESS;
×
4873
  int32_t lino = 0;
×
4874
  if (pSupp->dbNameSlotId != -1) {
×
4875
    QUERY_CHECK_CONDITION((strlen(dbName) > 0), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
4876
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->dbNameSlotId);
×
4877
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
×
4878

4879
    char varDbName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
×
4880
    tstrncpy(varDataVal(varDbName), dbName, TSDB_DB_NAME_LEN);
4881

4882
    varDataSetLen(varDbName, strlen(dbName));
×
4883
    code = colDataSetVal(colInfoData, 0, varDbName, false);
×
4884
    QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
4885
  }
×
UNCOV
4886

×
4887
  if (pSupp->stbNameSlotId != -1) {
×
4888
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->stbNameSlotId);
×
4889
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
4890
    if (strlen(stbName) != 0) {
×
4891
      char varStbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
4892
      tstrncpy(varDataVal(varStbName), stbName, TSDB_TABLE_NAME_LEN);
4893
      varDataSetLen(varStbName, strlen(stbName));
×
4894
      code = colDataSetVal(colInfoData, 0, varStbName, false);
×
4895
      QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
4896
    } else {
×
UNCOV
4897
      colDataSetNULL(colInfoData, 0);
×
UNCOV
4898
    }
×
UNCOV
4899
  }
×
4900

4901
  if (pSupp->tbCountSlotId != -1) {
×
4902
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->tbCountSlotId);
4903
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
4904
    code = colDataSetVal(colInfoData, 0, (char*)&count, false);
×
4905
    QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
4906
  }
×
4907
  pRes->info.rows = 1;
UNCOV
4908

×
4909
_end:
4910
  if (code != TSDB_CODE_SUCCESS) {
×
4911
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
UNCOV
4912
  }
×
4913
  return code;
×
UNCOV
4914
}
×
UNCOV
4915

×
4916
static SSDataBlock* buildSysDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo) {
×
4917
  STableCountScanSupp* pSupp = &pInfo->supp;
4918
  SSDataBlock*         pRes = pInfo->pRes;
×
4919

4920
  size_t infodbTableNum;
×
4921
  getInfosDbMeta(NULL, &infodbTableNum);
×
4922
  infodbTableNum -= 1;
×
4923
  size_t perfdbTableNum;
×
4924
  getPerfDbMeta(NULL, &perfdbTableNum);
×
UNCOV
4925

×
4926
  if (pSupp->groupByDbName || pSupp->groupByStbName) {
4927
    buildSysDbGroupedTableCount(pOperator, pInfo, pSupp, pRes, infodbTableNum, perfdbTableNum);
×
4928
    return (pRes->info.rows > 0) ? pRes : NULL;
×
4929
  } else {
4930
    buildSysDbFilterTableCount(pOperator, pSupp, pRes, infodbTableNum, perfdbTableNum);
×
4931
    return (pRes->info.rows > 0) ? pRes : NULL;
×
4932
  }
4933
}
UNCOV
4934

×
4935
static void buildSysDbFilterTableCount(SOperatorInfo* pOperator, STableCountScanSupp* pSupp, SSDataBlock* pRes,
×
UNCOV
4936
                                       size_t infodbTableNum, size_t perfdbTableNum) {
×
4937
  int32_t        code = TSDB_CODE_SUCCESS;
4938
  int32_t        lino = 0;
4939
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
4940
  if (strcmp(pSupp->dbNameFilter, TSDB_INFORMATION_SCHEMA_DB) == 0) {
×
4941
    code = fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes);
×
4942
    QUERY_CHECK_CODE(code, lino, _end);
×
4943
  } else if (strcmp(pSupp->dbNameFilter, TSDB_PERFORMANCE_SCHEMA_DB) == 0) {
×
4944
    code = fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes);
4945
    QUERY_CHECK_CODE(code, lino, _end);
×
4946
  } else if (strlen(pSupp->dbNameFilter) == 0) {
×
4947
    code = fillTableCountScanDataBlock(pSupp, "", "", infodbTableNum + perfdbTableNum, pRes);
4948
    QUERY_CHECK_CODE(code, lino, _end);
UNCOV
4949
  }
×
4950

4951
_end:
4952
  if (code != TSDB_CODE_SUCCESS) {
×
4953
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4954
    pTaskInfo->code = code;
×
4955
    T_LONG_JMP(pTaskInfo->env, code);
×
UNCOV
4956
  }
×
4957
  setOperatorCompleted(pOperator);
×
4958
}
×
UNCOV
4959

×
4960
static void buildSysDbGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
4961
                                        STableCountScanSupp* pSupp, SSDataBlock* pRes, size_t infodbTableNum,
4962
                                        size_t perfdbTableNum) {
4963
  int32_t        code = TSDB_CODE_SUCCESS;
×
4964
  int32_t        lino = 0;
×
4965
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
4966
  if (pInfo->currGrpIdx == 0) {
×
4967
    uint64_t groupId = 0;
×
4968
    if (pSupp->groupByDbName) {
4969
      groupId = calcGroupId(TSDB_INFORMATION_SCHEMA_DB, strlen(TSDB_INFORMATION_SCHEMA_DB));
×
UNCOV
4970
    } else {
×
4971
      groupId = calcGroupId("", 0);
UNCOV
4972
    }
×
UNCOV
4973

×
4974
    pRes->info.id.groupId = groupId;
4975
    code = fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes);
×
4976
    QUERY_CHECK_CODE(code, lino, _end);
4977
  } else if (pInfo->currGrpIdx == 1) {
4978
    uint64_t groupId = 0;
×
4979
    if (pSupp->groupByDbName) {
×
4980
      groupId = calcGroupId(TSDB_PERFORMANCE_SCHEMA_DB, strlen(TSDB_PERFORMANCE_SCHEMA_DB));
×
UNCOV
4981
    } else {
×
4982
      groupId = calcGroupId("", 0);
4983
    }
UNCOV
4984

×
4985
    pRes->info.id.groupId = groupId;
4986
    code = fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes);
4987
    QUERY_CHECK_CODE(code, lino, _end);
×
4988
  } else {
4989
    setOperatorCompleted(pOperator);
×
UNCOV
4990
  }
×
4991
  pInfo->currGrpIdx++;
×
UNCOV
4992

×
4993
_end:
4994
  if (code != TSDB_CODE_SUCCESS) {
×
4995
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4996
    pTaskInfo->code = code;
×
4997
    T_LONG_JMP(pTaskInfo->env, code);
×
UNCOV
4998
  }
×
4999
}
×
5000

5001
static int32_t doTableCountScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
5002
  int32_t                      code = TSDB_CODE_SUCCESS;
×
5003
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
5004
  STableCountScanOperatorInfo* pInfo = pOperator->info;
×
5005
  STableCountScanSupp*         pSupp = &pInfo->supp;
×
5006
  SSDataBlock*                 pRes = pInfo->pRes;
UNCOV
5007

×
5008
  blockDataCleanup(pRes);
×
5009
  QRY_PARAM_CHECK(ppRes);
×
UNCOV
5010

×
5011
  if (pOperator->status == OP_EXEC_DONE) {
5012
    return code;
×
5013
  }
UNCOV
5014

×
5015
  if (pInfo->readHandle.mnd != NULL) {
5016
    (*ppRes) = buildSysDbTableCount(pOperator, pInfo);
5017
    return code;
×
UNCOV
5018
  }
×
5019

5020
  code = buildVnodeDbTableCount(pOperator, pInfo, pSupp, pRes);
×
5021
  if (code != TSDB_CODE_SUCCESS) {
×
5022
    qError("%s failed since %s", __func__, tstrerror(code));
×
5023
    pTaskInfo->code = code;
×
5024
    T_LONG_JMP(pTaskInfo->env, code);
×
5025
  }
5026
  if (pRes->info.rows > 0) {
5027
    *ppRes = pRes;
×
UNCOV
5028
  }
×
UNCOV
5029

×
5030
  return code;
×
5031
}
UNCOV
5032

×
5033
static int32_t buildVnodeDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
5034
                                      STableCountScanSupp* pSupp, SSDataBlock* pRes) {
5035
  int32_t        code = TSDB_CODE_SUCCESS;
×
5036
  int32_t        lino = 0;
5037
  const char*    db = NULL;
×
5038
  int32_t        vgId = 0;
×
5039
  char           dbName[TSDB_DB_NAME_LEN] = {0};
×
5040
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
5041
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
UNCOV
5042

×
UNCOV
5043
  // get dbname
×
5044
  pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, &db, &vgId, NULL, NULL);
×
5045
  SName sn = {0};
×
UNCOV
5046

×
5047
  code = tNameFromString(&sn, db, T_NAME_ACCT | T_NAME_DB);
5048
  QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
5049

×
5050
  code = tNameGetDbName(&sn, dbName);
×
5051
  QUERY_CHECK_CODE(code, lino, _end);
UNCOV
5052

×
5053
  if (pSupp->groupByDbName || pSupp->groupByStbName) {
×
5054
    code = buildVnodeGroupedTableCount(pOperator, pInfo, pSupp, pRes, vgId, dbName);
UNCOV
5055
  } else {
×
5056
    code = buildVnodeFilteredTbCount(pOperator, pInfo, pSupp, pRes, dbName);
×
UNCOV
5057
  }
×
UNCOV
5058

×
5059
_end:
5060
  if (code != TSDB_CODE_SUCCESS) {
5061
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5062
    pTaskInfo->code = code;
×
UNCOV
5063
  }
×
UNCOV
5064

×
5065
  return code;
5066
}
UNCOV
5067

×
5068
static int32_t buildVnodeGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
UNCOV
5069
                                           STableCountScanSupp* pSupp, SSDataBlock* pRes, int32_t vgId, char* dbName) {
×
5070
  int32_t        code = TSDB_CODE_SUCCESS;
×
5071
  int32_t        lino = 0;
5072
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
5073
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
UNCOV
5074

×
5075
  if (pSupp->groupByStbName) {
5076
    if (pInfo->stbUidList == NULL) {
5077
      pInfo->stbUidList = taosArrayInit(16, sizeof(tb_uid_t));
×
5078
      QUERY_CHECK_NULL(pInfo->stbUidList, code, lino, _end, terrno);
5079
      code = pAPI->metaFn.storeGetTableList(pInfo->readHandle.vnode, TSDB_SUPER_TABLE, pInfo->stbUidList);
×
5080
      QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
5081
    }
×
UNCOV
5082

×
5083
    if (pInfo->currGrpIdx < taosArrayGetSize(pInfo->stbUidList)) {
×
5084
      tb_uid_t stbUid = *(tb_uid_t*)taosArrayGet(pInfo->stbUidList, pInfo->currGrpIdx);
5085
      code = buildVnodeGroupedStbTableCount(pInfo, pSupp, pRes, dbName, stbUid, pAPI);
5086
      QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
5087

×
5088
      pInfo->currGrpIdx++;
5089
    } else if (pInfo->currGrpIdx == taosArrayGetSize(pInfo->stbUidList)) {
×
5090
      code = buildVnodeGroupedNtbTableCount(pInfo, pSupp, pRes, dbName, pAPI);
×
5091
      QUERY_CHECK_CODE(code, lino, _end);
UNCOV
5092

×
5093
      pInfo->currGrpIdx++;
×
5094
    } else {
5095
      setOperatorCompleted(pOperator);
UNCOV
5096
    }
×
UNCOV
5097
  } else {
×
5098
    uint64_t groupId = calcGroupId(dbName, strlen(dbName));
×
5099
    pRes->info.id.groupId = groupId;
UNCOV
5100

×
5101
    int64_t dbTableCount = 0;
5102
    pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &dbTableCount, NULL);
5103
    code = fillTableCountScanDataBlock(pSupp, dbName, "", dbTableCount, pRes);
×
5104
    QUERY_CHECK_CODE(code, lino, _end);
5105
    setOperatorCompleted(pOperator);
×
UNCOV
5106
  }
×
UNCOV
5107

×
5108
_end:
×
5109
  if (code != TSDB_CODE_SUCCESS) {
×
5110
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
5111
    pTaskInfo->code = code;
×
UNCOV
5112
  }
×
5113
  return code;
×
5114
}
UNCOV
5115

×
5116
static int32_t buildVnodeFilteredTbCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
5117
                                         STableCountScanSupp* pSupp, SSDataBlock* pRes, char* dbName) {
5118
  int32_t        code = TSDB_CODE_SUCCESS;
×
5119
  int32_t        lino = 0;
×
5120
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
5121
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
UNCOV
5122

×
5123
  if (strlen(pSupp->dbNameFilter) != 0) {
×
5124
    if (strlen(pSupp->stbNameFilter) != 0) {
×
5125
      uint64_t uid = 0;
×
5126
      code = pAPI->metaFn.getTableUidByName(pInfo->readHandle.vnode, pSupp->stbNameFilter, &uid);
5127
      QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
5128

×
5129
      int64_t numOfChildTables = 0;
×
5130
      code = pAPI->metaFn.getNumOfChildTables(pInfo->readHandle.vnode, uid, &numOfChildTables, NULL, NULL);
5131
      QUERY_CHECK_CODE(code, lino, _end);
×
5132

5133
      code = fillTableCountScanDataBlock(pSupp, dbName, pSupp->stbNameFilter, numOfChildTables, pRes);
5134
      QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
5135
    } else {
×
5136
      int64_t tbNumVnode = 0;
×
5137
      pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &tbNumVnode, NULL);
5138
      code = fillTableCountScanDataBlock(pSupp, dbName, "", tbNumVnode, pRes);
×
5139
      QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
5140
    }
×
5141
  } else {
5142
    int64_t tbNumVnode = 0;
5143
    pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &tbNumVnode, NULL);
5144
    code = fillTableCountScanDataBlock(pSupp, dbName, "", tbNumVnode, pRes);
5145
    QUERY_CHECK_CODE(code, lino, _end);
5146
  }
5147

5148
_end:
5149
  if (code != TSDB_CODE_SUCCESS) {
5150
    pTaskInfo->code = code;
5151
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
5152
  }
5153

5154
  setOperatorCompleted(pOperator);
5155
  return code;
5156
}
5157

5158
static int32_t buildVnodeGroupedNtbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
5159
                                              SSDataBlock* pRes, char* dbName, SStorageAPI* pAPI) {
5160
  int32_t code = TSDB_CODE_SUCCESS;
5161
  int32_t lino = 0;
5162
  char    fullStbName[TSDB_TABLE_FNAME_LEN] = {0};
5163
  if (pSupp->groupByDbName) {
5164
    snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, "");
5165
  }
5166

5167
  uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName));
5168
  pRes->info.id.groupId = groupId;
5169

5170
  int64_t numOfTables = 0;
5171
  pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, NULL, &numOfTables);
5172

5173
  if (numOfTables != 0) {
5174
    code = fillTableCountScanDataBlock(pSupp, dbName, "", numOfTables, pRes);
5175
  }
5176

5177
_end:
5178
  if (code != TSDB_CODE_SUCCESS) {
5179
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
5180
  }
5181
  return code;
5182
}
5183

5184
static int32_t buildVnodeGroupedStbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
5185
                                              SSDataBlock* pRes, char* dbName, tb_uid_t stbUid, SStorageAPI* pAPI) {
5186
  int32_t code = TSDB_CODE_SUCCESS;
5187
  int32_t lino = 0;
5188
  char    stbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
5189
  code = pAPI->metaFn.getTableNameByUid(pInfo->readHandle.vnode, stbUid, stbName);
5190
  QUERY_CHECK_CODE(code, lino, _end);
5191

5192
  char fullStbName[TSDB_TABLE_FNAME_LEN] = {0};
5193
  if (pSupp->groupByDbName) {
5194
    (void)snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, varDataVal(stbName));
5195
  } else {
5196
    (void)snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s", varDataVal(stbName));
5197
  }
5198

5199
  uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName));
5200
  pRes->info.id.groupId = groupId;
5201

5202
  int64_t ctbNum = 0;
5203
  code = pAPI->metaFn.getNumOfChildTables(pInfo->readHandle.vnode, stbUid, &ctbNum, NULL, NULL);
5204
  QUERY_CHECK_CODE(code, lino, _end);
5205
  code = fillTableCountScanDataBlock(pSupp, dbName, varDataVal(stbName), ctbNum, pRes);
5206
  QUERY_CHECK_CODE(code, lino, _end);
5207

5208
_end:
5209
  if (code != TSDB_CODE_SUCCESS) {
5210
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
5211
  }
5212
  return code;
5213
}
5214

5215
static void destoryTableCountScanOperator(void* param) {
5216
  STableCountScanOperatorInfo* pTableCountScanInfo = param;
5217
  blockDataDestroy(pTableCountScanInfo->pRes);
5218

5219
  taosArrayDestroy(pTableCountScanInfo->stbUidList);
5220
  taosMemoryFreeClear(param);
5221
}
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