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

taosdata / TDengine / #3660

15 Mar 2025 09:06AM UTC coverage: 62.039% (-1.3%) from 63.314%
#3660

push

travis-ci

web-flow
feat(stream): support stream processing for virtual tables (#30144)

* enh: add client processing

* enh: add mnode vtables processing

* enh: add mnode vtable processing

* enh: add normal child vtable support

* fix: compile issues

* fix: compile issues

* fix: create stream issues

* fix: multi stream scan issue

* fix: remove debug info

* fix: agg task and task level issues

* fix: correct task output type

* fix: split vtablescan from agg

* fix: memory leak issues

* fix: add limitations

* Update 09-error-code.md

* Update 09-error-code.md

* fix: remove usless case

* feat(stream): extract original table data in source scan task

Implemented functionality in the source task to extract data
corresponding to the virtual table from the original table using WAL.
The extracted data is then sent to the downstream merge task for further
processing.

* feat(stream): multi-way merge using loser tree in virtual merge task

Implemented multi-way merge in the merge task using a loser tree to
combine data from multiple original table into a single virtual table.
The merged virtual table data is then pushed downstream for further
processing.  Introduced memory limit handling during the merge process
with configurable behavior when the memory limit is reached.

* fix(test): remove useless cases

---------

Co-authored-by: dapan1121 <wpan@taosdata.com>
Co-authored-by: Pan Wei <72057773+dapan1121@users.noreply.github.com>

154078 of 317582 branches covered (48.52%)

Branch coverage included in aggregate %.

313 of 2391 new or added lines in 34 files covered. (13.09%)

26134 existing lines in 205 files now uncovered.

240261 of 318051 relevant lines covered (75.54%)

16655189.27 hits per line

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

63.73
/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 "storageapi.h"
38
#include "wal.h"
39

40
int32_t scanDebug = 0;
41

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

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

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

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

65
  STableCountScanSupp supp;
66

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

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

74
bool processBlockWithProbability(const SSampleExecInfo* pInfo) {
8,502,107✔
75
#if 0
76
  if (pInfo->sampleRatio == 1) {
77
    return true;
78
  }
79

80
  uint32_t val = taosRandR((uint32_t*) &pInfo->seed);
81
  return (val % ((uint32_t)(1/pInfo->sampleRatio))) == 0;
82
#else
83
  return true;
8,502,107✔
84
#endif
85
}
86

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

93
static int32_t overlapWithTimeWindow(SInterval* pInterval, SDataBlockInfo* pBlockInfo, int32_t order, bool* overlap) {
8,952,444✔
94
  int32_t     code = TSDB_CODE_SUCCESS;
8,952,444✔
95
  STimeWindow w = {0};
8,952,444✔
96

97
  // 0 by default, which means it is not a interval operator of the upstream operator.
98
  if (pInterval->interval == 0) {
8,952,444✔
99
    *overlap = false;
8,207,754✔
100
    return code;
8,207,754✔
101
  }
102

103
  if (order == TSDB_ORDER_ASC) {
744,690✔
104
    w = getAlignQueryTimeWindow(pInterval, pBlockInfo->window.skey);
498,217✔
105
    if (w.ekey < pBlockInfo->window.skey) {
498,096!
106
      qError("w.ekey:%" PRId64 " < pBlockInfo->window.skey:%" PRId64, w.ekey, pBlockInfo->window.skey);
×
107
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
108
    }
109

110
    if (w.ekey < pBlockInfo->window.ekey) {
498,096✔
111
      *overlap = true;
402,943✔
112
      return code;
402,943✔
113
    }
114

115
    while (1) {
116
      getNextTimeWindow(pInterval, &w, order);
95,167✔
117
      if (w.skey > pBlockInfo->window.ekey) {
95,091✔
118
        break;
76,486✔
119
      }
120

121
      if (w.ekey <= pBlockInfo->window.ekey) {
18,605!
122
        qError("w.ekey:%" PRId64 " <= pBlockInfo->window.ekey:%" PRId64, w.ekey, pBlockInfo->window.ekey);
×
123
        return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
124
      }
125
      if (TMAX(w.skey, pBlockInfo->window.skey) <= pBlockInfo->window.ekey) {
18,605✔
126
        *overlap = true;
18,591✔
127
        return code;
18,591✔
128
      }
129
    }
130
  } else {
131
    w = getAlignQueryTimeWindow(pInterval, pBlockInfo->window.ekey);
246,473✔
132
    if (w.skey > pBlockInfo->window.ekey) {
246,633!
133
      qError("w.skey:%" PRId64 " > pBlockInfo->window.skey:%" PRId64, w.skey, pBlockInfo->window.ekey);
×
134
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
135
    }
136

137
    if (w.skey > pBlockInfo->window.skey) {
246,633✔
138
      *overlap = true;
174,896✔
139
      return code;
174,896✔
140
    }
141

142
    while (1) {
143
      getNextTimeWindow(pInterval, &w, order);
71,737✔
144
      if (w.ekey < pBlockInfo->window.skey) {
71,740✔
145
        break;
54,256✔
146
      }
147

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

159
  *overlap = false;
130,742✔
160
  return code;
130,742✔
161
}
162

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

169
  int64_t buf[2] = {0};
1,578,007✔
170
  SET_RES_WINDOW_KEY((char*)buf, &groupId, sizeof(groupId), groupId);
1,578,007✔
171

172
  STableScanInfo* pTableScanInfo = pOperator->info;
1,578,007✔
173

174
  SResultRowPosition* p1 = (SResultRowPosition*)tSimpleHashGet(pTableScanInfo->base.pdInfo.pAggSup->pResultRowHashTable,
1,578,007✔
175
                                                               buf, GET_RES_WINDOW_KEY_LEN(sizeof(groupId)));
176

177
  if (p1 == NULL) {
1,578,166✔
178
    return NULL;
305,192✔
179
  }
180

181
  *pPage = getBufPage(pTableScanInfo->base.pdInfo.pAggSup->pResultBuf, p1->pageId);
1,272,974✔
182
  if (NULL == *pPage) {
1,272,924!
183
    return NULL;
×
184
  }
185

186
  return (SResultRow*)((char*)(*pPage) + p1->offset);
1,272,924✔
187
}
188

189
static int32_t insertTableToScanIgnoreList(STableScanInfo* pTableScanInfo, uint64_t uid) {
9,827✔
190
  if (NULL == pTableScanInfo->pIgnoreTables) {
9,827✔
191
    int32_t tableNum = taosArrayGetSize(pTableScanInfo->base.pTableListInfo->pTableList);
7,807✔
192
    pTableScanInfo->pIgnoreTables =
7,807✔
193
        taosHashInit(tableNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
7,807✔
194
    if (NULL == pTableScanInfo->pIgnoreTables) {
7,807!
195
      return terrno;
×
196
    }
197
  }
198

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

208
static int32_t doDynamicPruneDataBlock(SOperatorInfo* pOperator, SDataBlockInfo* pBlockInfo, uint32_t* status) {
9,669,996✔
209
  STableScanInfo* pTableScanInfo = pOperator->info;
9,669,996✔
210
  int32_t         code = TSDB_CODE_SUCCESS;
9,669,996✔
211

212
  if (pTableScanInfo->base.pdInfo.pExprSup == NULL) {
9,669,996✔
213
    return TSDB_CODE_SUCCESS;
8,093,695✔
214
  }
215

216
  SExprSupp* pSup1 = pTableScanInfo->base.pdInfo.pExprSup;
1,576,301✔
217

218
  SFilePage*  pPage = NULL;
1,576,301✔
219
  SResultRow* pRow = getTableGroupOutputBuf(pOperator, pBlockInfo->id.groupId, &pPage);
1,576,301✔
220

221
  if (pRow == NULL) {
1,578,119✔
222
    return TSDB_CODE_SUCCESS;
305,194✔
223
  }
224

225
  bool notLoadBlock = true;
1,272,925✔
226
  for (int32_t i = 0; i < pSup1->numOfExprs; ++i) {
1,400,430✔
227
    int32_t functionId = pSup1->pCtx[i].functionId;
1,390,582✔
228

229
    SResultRowEntryInfo* pEntry = getResultEntryInfo(pRow, i, pTableScanInfo->base.pdInfo.pExprSup->rowEntryInfoOffset);
1,390,582✔
230

231
    EFuncDataRequired reqStatus = fmFuncDynDataRequired(functionId, pEntry, pBlockInfo);
1,390,581✔
232
    if (reqStatus != FUNC_DATA_REQUIRED_NOT_LOAD) {
1,390,604✔
233
      notLoadBlock = false;
1,263,099✔
234
      break;
1,263,099✔
235
    }
236
  }
237

238
  // release buffer pages
239
  releaseBufPage(pTableScanInfo->base.pdInfo.pAggSup->pResultBuf, pPage);
1,272,947✔
240

241
  if (notLoadBlock) {
1,272,908✔
242
    *status = FUNC_DATA_REQUIRED_NOT_LOAD;
9,827✔
243
    code = insertTableToScanIgnoreList(pTableScanInfo, pBlockInfo->id.uid);
9,827✔
244
  }
245

246
  return code;
1,272,912✔
247
}
248

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

256
  return filterRangeExecute(pFilterInfo, pColsAgg, numOfCols, numOfRows, keep);
77,897✔
257
}
258

259
static int32_t doLoadBlockSMA(STableScanBase* pTableScanInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo,
5,552,353✔
260
                              bool* pLoad) {
261
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
5,552,353✔
262
  bool         allColumnsHaveAgg = true;
5,552,353✔
263
  bool         hasNullSMA = false;
5,552,353✔
264
  if (pLoad != NULL) {
5,552,353!
265
    *pLoad = false;
5,552,671✔
266
  }
267

268
  int32_t code = pAPI->tsdReader.tsdReaderRetrieveBlockSMAInfo(pTableScanInfo->dataReader, pBlock, &allColumnsHaveAgg,
5,552,353✔
269
                                                               &hasNullSMA);
270
  if (code != TSDB_CODE_SUCCESS) {
5,552,433!
271
    return code;
×
272
  }
273

274
  if (!allColumnsHaveAgg || hasNullSMA) {
5,552,433!
275
    *pLoad = false;
3,843,892✔
276
  } else {
277
    *pLoad = true;
1,708,541✔
278
  }
279

280
  return code;
5,552,433✔
281
}
282

283
static int32_t doSetTagColumnData(STableScanBase* pTableScanInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo,
13,137,158✔
284
                                  int32_t rows) {
285
  int32_t    code = 0;
13,137,158✔
286
  SExprSupp* pSup = &pTableScanInfo->pseudoSup;
13,137,158✔
287
  if (pSup->numOfExprs > 0) {
13,137,158✔
288
    code = addTagPseudoColumnData(&pTableScanInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pBlock, rows,
3,697,922✔
289
                                  pTaskInfo, &pTableScanInfo->metaCache);
290
    // ignore the table not exists error, since this table may have been dropped during the scan procedure.
291
    if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) {
3,698,015!
292
      if (pTaskInfo->streamInfo.pState) blockDataCleanup(pBlock);
×
293
      code = 0;
×
294
    }
295
  }
296

297
  return code;
13,138,172✔
298
}
299

300
bool applyLimitOffset(SLimitInfo* pLimitInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo) {
33,617,578✔
301
  SLimit*     pLimit = &pLimitInfo->limit;
33,617,578✔
302
  const char* id = GET_TASKID(pTaskInfo);
33,617,578✔
303

304
  if (pLimitInfo->remainOffset > 0) {
33,617,578✔
305
    if (pLimitInfo->remainOffset >= pBlock->info.rows) {
72,051✔
306
      pLimitInfo->remainOffset -= pBlock->info.rows;
21,286✔
307
      blockDataEmpty(pBlock);
21,286✔
308
      qDebug("current block ignore due to offset, current:%" PRId64 ", %s", pLimitInfo->remainOffset, id);
21,286✔
309
      return false;
21,286✔
310
    } else {
311
      int32_t code = blockDataTrimFirstRows(pBlock, pLimitInfo->remainOffset);
50,765✔
312
      if (code != TSDB_CODE_SUCCESS) {
50,765!
313
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
314
        pTaskInfo->code = code;
×
315
        T_LONG_JMP(pTaskInfo->env, code);
×
316
      }
317
      pLimitInfo->remainOffset = 0;
50,765✔
318
    }
319
  }
320

321
  if (pLimit->limit != -1 && pLimit->limit <= (pLimitInfo->numOfOutputRows + pBlock->info.rows)) {
33,596,292✔
322
    // limit the output rows
323
    int32_t keep = (int32_t)(pLimit->limit - pLimitInfo->numOfOutputRows);
384,682✔
324
    blockDataKeepFirstNRows(pBlock, keep);
384,682✔
325

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

331
  pLimitInfo->numOfOutputRows += pBlock->info.rows;
33,211,610✔
332
  return false;
33,211,610✔
333
}
334

335
static bool isDynVtbScan(SOperatorInfo* pOperator) {
1,023✔
336
  return pOperator->dynamicTask && ((STableScanInfo*)(pOperator->info))->virtualStableScan;
1,023!
337
}
338

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

347
  SFileBlockLoadRecorder* pCost = &pTableScanInfo->readRecorder;
12,727,438✔
348

349
  pCost->totalBlocks += 1;
12,727,438✔
350
  pCost->totalRows += pBlock->info.rows;
12,727,438✔
351
  *status = pTableScanInfo->dataBlockLoadFlag;
12,727,438✔
352

353
  if (pOperator->exprSupp.pFilterInfo != NULL) {
12,727,438✔
354
    (*status) = FUNC_DATA_REQUIRED_DATA_LOAD;
3,775,232✔
355
  } else {
356
    bool overlap = false;
8,952,206✔
357
    int  ret =
358
        overlapWithTimeWindow(&pTableScanInfo->pdInfo.interval, &pBlock->info, pTableScanInfo->cond.order, &overlap);
8,952,206✔
359
    if (ret != TSDB_CODE_SUCCESS) {
8,951,497!
UNCOV
360
      return ret;
×
361
    }
362
    if (overlap) {
8,951,497✔
363
      (*status) = FUNC_DATA_REQUIRED_DATA_LOAD;
613,850✔
364
    }
365
  }
366

367
  SDataBlockInfo* pBlockInfo = &pBlock->info;
12,726,729✔
368
  taosMemoryFreeClear(pBlock->pBlockAgg);
12,726,729!
369

370
  if (*status == FUNC_DATA_REQUIRED_FILTEROUT) {
12,726,729!
371
    qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, GET_TASKID(pTaskInfo),
×
372
           pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
UNCOV
373
    pCost->filterOutBlocks += 1;
×
UNCOV
374
    pCost->totalRows += pBlock->info.rows;
×
UNCOV
375
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
UNCOV
376
    return TSDB_CODE_SUCCESS;
×
377
  } else if (*status == FUNC_DATA_REQUIRED_NOT_LOAD) {
12,726,729✔
378
    qDebug("%s data block skipped, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64 ", uid:%" PRIu64,
1,423,864✔
379
           GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows,
380
           pBlockInfo->id.uid);
381
    code = doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows);
1,423,864✔
382
    pCost->skipBlocks += 1;
1,423,863✔
383
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
1,423,863✔
384
    return code;
1,423,850✔
385
  } else if (*status == FUNC_DATA_REQUIRED_SMA_LOAD) {
11,302,865✔
386
    pCost->loadBlockStatis += 1;
1,777,671✔
387
    loadSMA = true;  // mark the operation of load sma;
1,777,671✔
388
    bool success = true;
1,777,671✔
389
    code = doLoadBlockSMA(pTableScanInfo, pBlock, pTaskInfo, &success);
1,777,671✔
390
    if (code) {
1,777,670!
UNCOV
391
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
UNCOV
392
      qError("%s failed to retrieve sma info", GET_TASKID(pTaskInfo));
×
UNCOV
393
      QUERY_CHECK_CODE(code, lino, _end);
×
394
    }
395

396
    if (success) {  // failed to load the block sma data, data block statistics does not exist, load data block instead
1,777,604✔
397
      qDebug("%s data block SMA loaded, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, GET_TASKID(pTaskInfo),
1,630,644✔
398
             pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
399
      code = doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows);
1,630,644✔
400
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
1,630,643✔
401
      return code;
1,631,588✔
402
    } else {
403
      qDebug("%s failed to load SMA, since not all columns have SMA", GET_TASKID(pTaskInfo));
146,960✔
404
      *status = FUNC_DATA_REQUIRED_DATA_LOAD;
146,965✔
405
    }
406
  }
407

408
  if (*status != FUNC_DATA_REQUIRED_DATA_LOAD) {
9,672,159!
UNCOV
409
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
UNCOV
410
    qError("%s loadDataBlock invalid status:%d", GET_TASKID(pTaskInfo), *status);
×
UNCOV
411
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
412
  }
413

414
  // try to filter data block according to sma info
415
  if (pOperator->exprSupp.pFilterInfo != NULL && (!loadSMA)) {
9,672,159!
416
    bool success = true;
3,774,854✔
417
    code = doLoadBlockSMA(pTableScanInfo, pBlock, pTaskInfo, &success);
3,774,854✔
418
    if (code) {
3,774,888!
UNCOV
419
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
×
UNCOV
420
      qError("%s failed to retrieve sma info", GET_TASKID(pTaskInfo));
×
UNCOV
421
      QUERY_CHECK_CODE(code, lino, _end);
×
422
    }
423

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

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

441
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
3✔
442
        return TSDB_CODE_SUCCESS;
3✔
443
      }
444
    }
445
  }
446

447
  // free the sma info, since it should not be involved in *later computing process.
448
  taosMemoryFreeClear(pBlock->pBlockAgg);
9,671,895!
449

450
  // try to filter data block according to current results
451
  code = doDynamicPruneDataBlock(pOperator, pBlockInfo, status);
9,671,895✔
452
  if (code) {
9,670,646✔
453
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
854✔
UNCOV
454
    QUERY_CHECK_CODE(code, lino, _end);
×
455
  }
456

457
  if (*status == FUNC_DATA_REQUIRED_NOT_LOAD) {
9,669,792✔
458
    qDebug("%s data block skipped due to dynamic prune, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64,
9,827✔
459
           GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
460
    pCost->skipBlocks += 1;
9,827✔
461
    pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->dataReader);
9,827✔
462

463
    STableScanInfo* p1 = pOperator->info;
9,827✔
464
    if (taosHashGetSize(p1->pIgnoreTables) == taosArrayGetSize(p1->base.pTableListInfo->pTableList)) {
9,827✔
465
      *status = FUNC_DATA_REQUIRED_ALL_FILTEROUT;
2,482✔
466
    } else {
467
      *status = FUNC_DATA_REQUIRED_FILTEROUT;
7,345✔
468
    }
469
    return TSDB_CODE_SUCCESS;
9,827✔
470
  }
471

472
  pCost->totalCheckedRows += pBlock->info.rows;
9,659,965✔
473
  pCost->loadBlocks += 1;
9,659,965✔
474

475
  SSDataBlock* p = NULL;
9,659,965✔
476
  code = pAPI->tsdReader.tsdReaderRetrieveDataBlock(pTableScanInfo->dataReader, &p, NULL);
9,659,965✔
477
  if (p == NULL || code != TSDB_CODE_SUCCESS || p != pBlock) {
9,659,772!
UNCOV
478
    return code;
×
479
  }
480

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

491
  // restore the previous value
492
  pCost->totalRows -= pBlock->info.rows;
9,660,441✔
493

494
  if (pOperator->exprSupp.pFilterInfo != NULL) {
9,660,441✔
495
    code = doFilter(pBlock, pOperator->exprSupp.pFilterInfo, &pTableScanInfo->matchInfo);
3,767,822✔
496
    QUERY_CHECK_CODE(code, lino, _end);
3,768,160!
497

498
    int64_t st = taosGetTimestampUs();
3,768,076✔
499
    double  el = (taosGetTimestampUs() - st) / 1000.0;
3,768,232✔
500
    pTableScanInfo->readRecorder.filterTime += el;
3,768,232✔
501

502
    if (pBlock->info.rows == 0) {
3,768,232✔
503
      pCost->filterOutBlocks += 1;
59,217✔
504
      qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64 ", elapsed time:%.2f ms",
59,217✔
505
             GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, el);
506
    } else {
507
      qDebug("%s data block filter applied, elapsed time:%.2f ms", GET_TASKID(pTaskInfo), el);
3,709,015✔
508
    }
509
  }
510

511
  bool limitReached = applyLimitOffset(&pTableScanInfo->limitInfo, pBlock, pTaskInfo);
9,660,856✔
512
  if (limitReached) {  // set operator flag is done
9,659,961✔
513
    setOperatorCompleted(pOperator);
102,744✔
514
  }
515

516
  pCost->totalRows += pBlock->info.rows;
9,662,330✔
517

518
_end:
9,662,330✔
519
  if (code != TSDB_CODE_SUCCESS) {
9,662,330!
UNCOV
520
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
521
  }
522
  return code;
9,661,711✔
523
}
524

525
static void prepareForDescendingScan(STableScanBase* pTableScanInfo, SqlFunctionCtx* pCtx, int32_t numOfOutput) {
179✔
526
  SET_REVERSE_SCAN_FLAG(pTableScanInfo);
179✔
527

528
  switchCtxOrder(pCtx, numOfOutput);
179✔
529
  pTableScanInfo->cond.order = TSDB_ORDER_DESC;
179✔
530
  STimeWindow* pTWindow = &pTableScanInfo->cond.twindows;
179✔
531
  TSWAP(pTWindow->skey, pTWindow->ekey);
179✔
532
}
179✔
533

534
typedef struct STableCachedVal {
535
  const char* pName;
536
  STag*       pTags;
537
} STableCachedVal;
538

539
static void freeTableCachedVal(void* param) {
1,830,147✔
540
  if (param == NULL) {
1,830,147!
UNCOV
541
    return;
×
542
  }
543

544
  STableCachedVal* pVal = param;
1,830,147✔
545
  taosMemoryFree((void*)pVal->pName);
1,830,147!
546
  taosMemoryFree(pVal->pTags);
1,831,330!
547
  taosMemoryFree(pVal);
1,831,363✔
548
}
549

550
static int32_t createTableCacheVal(const SMetaReader* pMetaReader, STableCachedVal** ppResVal) {
1,830,743✔
551
  int32_t          code = TSDB_CODE_SUCCESS;
1,830,743✔
552
  int32_t          lino = 0;
1,830,743✔
553
  STableCachedVal* pVal = taosMemoryMalloc(sizeof(STableCachedVal));
1,830,743!
554
  QUERY_CHECK_NULL(pVal, code, lino, _end, terrno);
1,830,997!
555

556
  pVal->pTags = NULL;
1,830,997✔
557
  pVal->pName = taosStrdup(pMetaReader->me.name);
1,830,997!
558
  QUERY_CHECK_NULL(pVal->pName, code, lino, _end, terrno);
1,830,635!
559

560
  // only child table has tag value
561
  if (pMetaReader->me.type == TSDB_CHILD_TABLE || pMetaReader->me.type == TSDB_VIRTUAL_CHILD_TABLE) {
1,830,635✔
562
    STag* pTag = (STag*)pMetaReader->me.ctbEntry.pTags;
1,830,099✔
563
    pVal->pTags = taosMemoryMalloc(pTag->len);
1,830,099✔
564
    QUERY_CHECK_NULL(pVal->pTags, code, lino, _end, terrno);
1,829,489!
565
    memcpy(pVal->pTags, pTag, pTag->len);
1,829,489✔
566
  }
567

568
  (*ppResVal) = pVal;
1,830,025✔
569

570
_end:
1,830,025✔
571
  if (code != TSDB_CODE_SUCCESS) {
1,830,025!
UNCOV
572
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
573
    freeTableCachedVal(pVal);
×
574
  }
575
  return code;
1,830,000✔
576
}
577

578
// const void *key, size_t keyLen, void *value
579
static void freeCachedMetaItem(const void* key, size_t keyLen, void* value, void* ud) {
1,830,139✔
580
  (void)key;
581
  (void)keyLen;
582
  (void)ud;
583
  freeTableCachedVal(value);
1,830,139✔
584
}
1,831,362✔
585

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

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

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

600
int32_t addTagPseudoColumnData(SReadHandle* pHandle, const SExprInfo* pExpr, int32_t numOfExpr, SSDataBlock* pBlock,
4,055,302✔
601
                               int32_t rows, SExecTaskInfo* pTask, STableMetaCacheInfo* pCache) {
602
  int32_t          code = TSDB_CODE_SUCCESS;
4,055,302✔
603
  int32_t          lino = 0;
4,055,302✔
604
  bool             freeReader = false;
4,055,302✔
605
  LRUHandle*       h = NULL;
4,055,302✔
606
  STableCachedVal  val = {0};
4,055,302✔
607
  SMetaReader      mr = {0};
4,055,302✔
608
  const char*      idStr = pTask->id.str;
4,055,302✔
609
  int32_t          insertRet = TAOS_LRU_STATUS_OK;
4,055,302✔
610
  STableCachedVal* pVal = NULL;
4,055,302✔
611

612
  // currently only the tbname pseudo column
613
  if (numOfExpr <= 0) {
4,055,302✔
614
    return TSDB_CODE_SUCCESS;
1,837✔
615
  }
616

617
  // todo: opt if only require the vgId and the vgVer;
618

619
  // backup the rows
620
  int32_t backupRows = pBlock->info.rows;
4,053,465✔
621
  pBlock->info.rows = rows;
4,053,465✔
622

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

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

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

645
    pHandle->api.metaReaderFn.readerReleaseLock(&mr);
880✔
646

647
    val.pName = mr.me.name;
880✔
648
    val.pTags = (STag*)mr.me.ctbEntry.pTags;
880✔
649

650
    freeReader = true;
880✔
651
  } else {
652
    pCache->metaFetch += 1;
4,052,583✔
653

654
    h = taosLRUCacheLookup(pCache->pTableMetaEntryCache, &pBlock->info.id.uid, sizeof(pBlock->info.id.uid));
4,052,583✔
655
    if (h == NULL) {
4,053,542✔
656
      pHandle->api.metaReaderFn.initReader(&mr, pHandle->vnode, META_READER_LOCK, &pHandle->api.metaFn);
1,831,251✔
657
      freeReader = true;
1,831,216✔
658
      code = pHandle->api.metaReaderFn.getEntryGetUidCache(&mr, pBlock->info.id.uid);
1,831,216✔
659
      if (code != TSDB_CODE_SUCCESS) {
1,829,997!
660
        if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) {
×
661
          qWarn("failed to get table meta, table may have been dropped, uid:0x%" PRIx64 ", code:%s, %s",
×
662
                pBlock->info.id.uid, tstrerror(code), idStr);
663
          // append null value before return to caller, since the caller will ignore this error code and proceed
UNCOV
664
          doSetNullValue(pBlock, pExpr, numOfExpr);
×
665
        } else {
UNCOV
666
          qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", pBlock->info.id.uid, tstrerror(code),
×
667
                 idStr);
668
        }
UNCOV
669
        pHandle->api.metaReaderFn.clearReader(&mr);
×
UNCOV
670
        return code;
×
671
      }
672

673
      pHandle->api.metaReaderFn.readerReleaseLock(&mr);
1,829,997✔
674

675
      code = createTableCacheVal(&mr, &pVal);
1,830,986✔
676
      QUERY_CHECK_CODE(code, lino, _end);
1,830,031!
677

678
      val = *pVal;
1,830,031✔
679
    } else {
680
      pCache->cacheHit += 1;
2,222,291✔
681
      STableCachedVal* pValTmp = taosLRUCacheValue(pCache->pTableMetaEntryCache, h);
2,222,291✔
682
      val = *pValTmp;
2,222,267✔
683

684
      bool bRes = taosLRUCacheRelease(pCache->pTableMetaEntryCache, h, false);
2,222,267✔
685
      qTrace("release LRU cache, res %d", bRes);
2,222,429✔
686
    }
687

688
    qDebug("retrieve table meta from cache:%" PRIu64 ", hit:%" PRIu64 " miss:%" PRIu64 ", %s", pCache->metaFetch,
4,052,460✔
689
           pCache->cacheHit, (pCache->metaFetch - pCache->cacheHit), idStr);
690
  }
691

692
  for (int32_t j = 0; j < numOfExpr; ++j) {
16,324,375✔
693
    const SExprInfo* pExpr1 = &pExpr[j];
12,270,317✔
694
    int32_t          dstSlotId = pExpr1->base.resSchema.slotId;
12,270,317✔
695

696
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, dstSlotId);
12,270,317✔
697
    colInfoDataCleanup(pColInfoData, pBlock->info.rows);
12,269,755✔
698

699
    int32_t functionId = pExpr1->pExpr->_function.functionId;
12,269,029✔
700

701
    // this is to handle the tbname
702
    if (fmIsScanPseudoColumnFunc(functionId)) {
12,269,029✔
703
      int32_t fType = pExpr1->pExpr->_function.functionType;
1,755,076✔
704
      if (fType == FUNCTION_TYPE_TBNAME) {
1,755,076✔
705
        code = setTbNameColData(pBlock, pColInfoData, functionId, val.pName);
1,679,971✔
706
        QUERY_CHECK_CODE(code, lino, _end);
1,680,298!
707
      } else if (fType == FUNCTION_TYPE_VGID) {
75,105✔
708
        code = setVgIdColData(pBlock, pColInfoData, functionId, pTask->id.vgId);
37,553✔
709
        QUERY_CHECK_CODE(code, lino, _end);
37,549!
710
      } else if (fType == FUNCTION_TYPE_VGVER) {
37,552!
711
        code = setVgVerColData(pBlock, pColInfoData, functionId, pBlock->info.version);
37,552✔
712
        QUERY_CHECK_CODE(code, lino, _end);
37,552!
713
      }
714
    } else {  // these are tags
715
      STagVal tagVal = {0};
10,514,537✔
716
      tagVal.cid = pExpr1->base.pParam[0].pCol->colId;
10,514,537✔
717
      const char* p = pHandle->api.metaFn.extractTagVal(val.pTags, pColInfoData->info.type, &tagVal);
10,514,537✔
718

719
      char* data = NULL;
10,516,769✔
720
      if (pColInfoData->info.type != TSDB_DATA_TYPE_JSON && p != NULL) {
10,516,769✔
721
        data = tTagValToData((const STagVal*)p, false);
10,385,371✔
722
      } else {
723
        data = (char*)p;
131,398✔
724
      }
725

726
      bool isNullVal = (data == NULL) || (pColInfoData->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data));
10,516,324✔
727
      if (isNullVal) {
10,516,325✔
728
        colDataSetNNULL(pColInfoData, 0, pBlock->info.rows);
128,716✔
729
      } else if (pColInfoData->info.type != TSDB_DATA_TYPE_JSON) {
10,387,609✔
730
        code = colDataSetNItems(pColInfoData, 0, data, pBlock->info.rows, false);
10,384,298✔
731
        if (IS_VAR_DATA_TYPE(((const STagVal*)p)->type)) {
10,384,597!
732
          taosMemoryFree(data);
2,851,768!
733
        }
734
        QUERY_CHECK_CODE(code, lino, _end);
10,383,962!
735
      } else {  // todo opt for json tag
736
        for (int32_t i = 0; i < pBlock->info.rows; ++i) {
6,661✔
737
          code = colDataSetVal(pColInfoData, i, data, false);
3,350✔
738
          QUERY_CHECK_CODE(code, lino, _end);
3,350!
739
        }
740
      }
741
    }
742
  }
743

744
  // restore the rows
745
  pBlock->info.rows = backupRows;
4,054,058✔
746

747
_end:
4,054,058✔
748

749
  if (NULL != pVal) {
4,054,058✔
750
    insertRet = taosLRUCacheInsert(pCache->pTableMetaEntryCache, &pBlock->info.id.uid, sizeof(uint64_t), pVal,
1,830,763✔
751
                                   sizeof(STableCachedVal), freeCachedMetaItem, NULL, NULL, TAOS_LRU_PRIORITY_LOW, NULL);
752
    if (insertRet != TAOS_LRU_STATUS_OK) {
1,830,898!
UNCOV
753
      qWarn("failed to put meta into lru cache, code:%d, %s", insertRet, idStr);
×
754
    }
755
  }
756

757
  if (freeReader) {
4,054,193✔
758
    pHandle->api.metaReaderFn.clearReader(&mr);
1,831,769✔
759
  }
760
  if (code != TSDB_CODE_SUCCESS) {
4,054,265!
UNCOV
761
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
762
  }
763
  return code;
4,053,779✔
764
}
765

766
int32_t setTbNameColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId,
1,679,891✔
767
                         const char* name) {
768
  int32_t                     code = TSDB_CODE_SUCCESS;
1,679,891✔
769
  int32_t                     lino = 0;
1,679,891✔
770
  struct SScalarFuncExecFuncs fpSet = {0};
1,679,891✔
771
  code = fmGetScalarFuncExecFuncs(functionId, &fpSet);
1,679,891✔
772
  QUERY_CHECK_CODE(code, lino, _end);
1,679,937!
773

774
  size_t len = TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE;
1,679,937✔
775
  char   buf[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
1,679,937✔
776
  STR_TO_VARSTR(buf, name)
1,679,937✔
777

778
  SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, len, 1);
1,679,937✔
779

780
  code = colInfoDataEnsureCapacity(&infoData, 1, false);
1,680,711✔
781
  QUERY_CHECK_CODE(code, lino, _end);
1,680,441!
782

783
  code = colDataSetVal(&infoData, 0, buf, false);
1,680,441✔
784
  QUERY_CHECK_CODE(code, lino, _end);
1,680,456!
785

786
  SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .columnData = &infoData};
1,680,456✔
787
  SScalarParam param = {.columnData = pColInfoData};
1,680,456✔
788

789
  if (fpSet.process != NULL) {
1,680,456!
790
    code = fpSet.process(&srcParam, 1, &param);
1,680,548✔
791
    QUERY_CHECK_CODE(code, lino, _end);
1,680,618!
792
  } else {
UNCOV
793
    qError("failed to get the corresponding callback function, functionId:%d", functionId);
×
794
  }
795

796
  colDataDestroy(&infoData);
1,680,526✔
797

798
_end:
1,680,322✔
799
  if (code != TSDB_CODE_SUCCESS) {
1,680,322!
UNCOV
800
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
801
  }
802
  return code;
1,680,345✔
803
}
804

805
int32_t setVgIdColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId, int32_t vgId) {
37,553✔
806
  int32_t                     code = TSDB_CODE_SUCCESS;
37,553✔
807
  int32_t                     lino = 0;
37,553✔
808
  struct SScalarFuncExecFuncs fpSet = {0};
37,553✔
809
  code = fmGetScalarFuncExecFuncs(functionId, &fpSet);
37,553✔
810
  QUERY_CHECK_CODE(code, lino, _end);
37,553!
811

812
  SColumnInfoData infoData = createColumnInfoData(pColInfoData->info.type, pColInfoData->info.bytes, 1);
37,553✔
813

814
  code = colInfoDataEnsureCapacity(&infoData, 1, false);
37,553✔
815
  QUERY_CHECK_CODE(code, lino, _end);
37,553!
816

817
  code = colDataSetVal(&infoData, 0, (const char*)&vgId, false);
37,553✔
818
  QUERY_CHECK_CODE(code, lino, _end);
37,553!
819

820
  SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .columnData = &infoData};
37,553✔
821
  SScalarParam param = {.columnData = pColInfoData};
37,553✔
822

823
  if (fpSet.process != NULL) {
37,553!
824
    code = fpSet.process(&srcParam, 1, &param);
37,553✔
825
    QUERY_CHECK_CODE(code, lino, _end);
37,553!
826
  } else {
UNCOV
827
    qError("failed to get the corresponding callback function, functionId:%d", functionId);
×
828
  }
829

UNCOV
830
_end:
×
831
  colDataDestroy(&infoData);
37,553✔
832
  if (code != TSDB_CODE_SUCCESS) {
37,550!
UNCOV
833
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
834
  }
835
  return code;
37,549✔
836
}
837

838
int32_t setVgVerColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId, int64_t vgVer) {
37,552✔
839
  int32_t                     code = TSDB_CODE_SUCCESS;
37,552✔
840
  int32_t                     lino = 0;
37,552✔
841
  struct SScalarFuncExecFuncs fpSet = {0};
37,552✔
842
  code = fmGetScalarFuncExecFuncs(functionId, &fpSet);
37,552✔
843
  QUERY_CHECK_CODE(code, lino, _end);
37,551!
844

845
  SColumnInfoData infoData = createColumnInfoData(pColInfoData->info.type, pColInfoData->info.bytes, 1);
37,551✔
846

847
  code = colInfoDataEnsureCapacity(&infoData, 1, false);
37,552✔
848
  QUERY_CHECK_CODE(code, lino, _end);
37,552!
849

850
  code = colDataSetVal(&infoData, 0, (const char*)&vgVer, false);
37,552✔
851
  QUERY_CHECK_CODE(code, lino, _end);
37,553!
852

853
  SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .columnData = &infoData};
37,553✔
854
  SScalarParam param = {.columnData = pColInfoData};
37,553✔
855

856
  if (fpSet.process != NULL) {
37,553✔
857
    code = fpSet.process(&srcParam, 1, &param);
37,550✔
858
    QUERY_CHECK_CODE(code, lino, _end);
37,553!
859
  } else {
860
    qError("failed to get the corresponding callback function, functionId:%d", functionId);
3!
861
  }
862

863
_end:
3✔
864
  colDataDestroy(&infoData);
37,556✔
865
  if (code != TSDB_CODE_SUCCESS) {
37,552!
UNCOV
866
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
867
  }
868
  return code;
37,552✔
869
}
870

871
static int32_t initNextGroupScan(STableScanInfo* pInfo, STableKeyInfo** pKeyInfo, int32_t* size) {
2,745,056✔
872
  int32_t code = TSDB_CODE_SUCCESS;
2,745,056✔
873
  int32_t lino = 0;
2,745,056✔
874
  code = tableListGetGroupList(pInfo->base.pTableListInfo, pInfo->currentGroupId, pKeyInfo, size);
2,745,056✔
875
  QUERY_CHECK_CODE(code, lino, _end);
2,742,284!
876

877
  pInfo->tableStartIndex = TARRAY_ELEM_IDX(pInfo->base.pTableListInfo->pTableList, *pKeyInfo);
2,742,284✔
878
  pInfo->tableEndIndex = (pInfo->tableStartIndex + (*size) - 1);
2,742,284✔
879
  pInfo->pResBlock->info.blankFill = false;
2,742,284✔
880
  taosMemoryFreeClear(pInfo->pResBlock->pBlockAgg);
2,742,284!
881

882
  if (!pInfo->needCountEmptyTable) {
2,742,284✔
883
    pInfo->countState = TABLE_COUNT_STATE_END;
2,534,893✔
884
  } else {
885
    pInfo->countState = TABLE_COUNT_STATE_SCAN;
207,391✔
886
  }
887

888
_end:
2,742,284✔
889
  if (code != TSDB_CODE_SUCCESS) {
2,742,284!
UNCOV
890
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
891
  }
892
  return code;
2,739,759✔
893
}
894

895
void markGroupProcessed(STableScanInfo* pInfo, uint64_t groupId) {
8,838,228✔
896
  if (pInfo->countState == TABLE_COUNT_STATE_END) {
8,838,228✔
897
    return;
7,670,966✔
898
  }
899
  if (pInfo->base.pTableListInfo->groupOffset) {
1,167,262✔
900
    pInfo->countState = TABLE_COUNT_STATE_PROCESSED;
406✔
901
  } else {
902
    int32_t code = taosHashRemove(pInfo->base.pTableListInfo->remainGroups, &groupId, sizeof(groupId));
1,166,856✔
903
    if (code != TSDB_CODE_SUCCESS) {
1,168,228✔
904
      qDebug("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
617,169✔
905
    }
906
  }
907
}
908

909
static SSDataBlock* getOneRowResultBlock(SExecTaskInfo* pTaskInfo, STableScanBase* pBase, SSDataBlock* pBlock,
421,951✔
910
                                         const STableKeyInfo* tbInfo) {
911
  blockDataEmpty(pBlock);
421,951✔
912
  pBlock->info.rows = 1;
421,981✔
913
  pBlock->info.id.uid = tbInfo->uid;
421,981✔
914
  pBlock->info.id.groupId = tbInfo->groupId;
421,981✔
915
  pBlock->info.blankFill = true;
421,981✔
916

917
  // only one row: set all col data to null & hasNull
918
  int32_t col_num = blockDataGetNumOfCols(pBlock);
421,981✔
919
  for (int32_t i = 0; i < col_num; ++i) {
1,652,611✔
920
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
1,231,094✔
921
    colDataSetNULL(pColInfoData, 0);
922
  }
923

924
  // set tag/tbname
925
  terrno = doSetTagColumnData(pBase, pBlock, pTaskInfo, 1);
421,517✔
926

927
  return pBlock;
421,736✔
928
}
929

930
static SSDataBlock* getBlockForEmptyTable(SOperatorInfo* pOperator, const STableKeyInfo* tbInfo) {
407,734✔
931
  STableScanInfo* pTableScanInfo = pOperator->info;
407,734✔
932
  SSDataBlock*    pBlock =
933
      getOneRowResultBlock(pOperator->pTaskInfo, &pTableScanInfo->base, pTableScanInfo->pResBlock, tbInfo);
407,734✔
934

935
  pOperator->resultInfo.totalRows++;
407,468✔
936
  return pBlock;
407,468✔
937
}
938

939
static int32_t doTableScanImplNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
11,072,429✔
940
  int32_t         code = TSDB_CODE_SUCCESS;
11,072,429✔
941
  int32_t         lino = 0;
11,072,429✔
942
  STableScanInfo* pTableScanInfo = pOperator->info;
11,072,429✔
943
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
11,072,429✔
944
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
11,072,429✔
945
  SSDataBlock*    pBlock = pTableScanInfo->pResBlock;
11,072,429✔
946
  bool            hasNext = false;
11,072,429✔
947
  int64_t         st = taosGetTimestampUs();
11,074,536✔
948

949
  QRY_PARAM_CHECK(ppRes);
11,074,536!
950
  pBlock->info.dataLoad = false;
11,074,536✔
951

952
  while (true) {
67,110✔
953
    code = pAPI->tsdReader.tsdNextDataBlock(pTableScanInfo->base.dataReader, &hasNext);
11,141,646✔
954
    if (code != TSDB_CODE_SUCCESS) {
11,143,763✔
955
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
304✔
956
      QUERY_CHECK_CODE(code, lino, _end);
954!
957
    }
958

959
    if (!hasNext) {
11,143,459✔
960
      break;
2,643,889✔
961
    }
962

963
    if (isTaskKilled(pTaskInfo)) {
8,503,060✔
964
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
631✔
965
      code = pTaskInfo->code;
950✔
966
      goto _end;
950✔
967
    }
968

969
    if (pOperator->status == OP_EXEC_DONE) {
8,503,826✔
970
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pTableScanInfo->base.dataReader);
1,008✔
971
      break;
1,008✔
972
    }
973

974
    // process this data block based on the probabilities
975
    bool processThisBlock = processBlockWithProbability(&pTableScanInfo->sample);
8,502,818✔
976
    if (!processThisBlock) {
8,502,248!
977
      continue;
67,110✔
978
    }
979

980
    if (pBlock->info.id.uid) {
8,502,248!
981
      pBlock->info.id.groupId = tableListGetTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid);
8,503,168✔
982
    }
983

984
    uint32_t status = 0;
8,503,327✔
985
    code = loadDataBlock(pOperator, &pTableScanInfo->base, pBlock, &status);
8,503,327✔
986
    QUERY_CHECK_CODE(code, lino, _end);
8,501,892!
987

988
    if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
8,501,892✔
989
      break;
2,482✔
990
    }
991

992
    // current block is filter out according to filter condition, continue load the next block
993
    if (status == FUNC_DATA_REQUIRED_FILTEROUT || pBlock->info.rows == 0) {
8,499,410✔
994
      continue;
67,110✔
995
    }
996

997
    pOperator->resultInfo.totalRows = pTableScanInfo->base.readRecorder.totalRows;
8,432,300✔
998
    pTableScanInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
8,432,627✔
999

1000
    pOperator->cost.totalCost = pTableScanInfo->base.readRecorder.elapsedTime;
8,432,627✔
1001
    pBlock->info.scanFlag = pTableScanInfo->base.scanFlag;
8,432,627✔
1002

1003
    (*ppRes) = pBlock;
8,432,627✔
1004
    return code;
8,432,627✔
1005
  }
1006

1007
_end:
2,644,843✔
1008
  if (code != TSDB_CODE_SUCCESS) {
2,644,843✔
1009
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
954!
1010
    pTaskInfo->code = code;
954✔
1011
    T_LONG_JMP(pTaskInfo->env, code);
954!
1012
  }
1013
  return code;
2,643,889✔
1014
}
1015

1016
static int32_t doGroupedTableScan(SOperatorInfo* pOperator, SSDataBlock** pBlock) {
11,579,659✔
1017
  int32_t         code = TSDB_CODE_SUCCESS;
11,579,659✔
1018
  int32_t         lino = 0;
11,579,659✔
1019
  STableScanInfo* pTableScanInfo = pOperator->info;
11,579,659✔
1020
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
11,579,659✔
1021
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
11,579,659✔
1022

1023
  QRY_PARAM_CHECK(pBlock);
11,579,659!
1024

1025
  // The read handle is not initialized yet, since no qualified tables exists
1026
  if (pTableScanInfo->base.dataReader == NULL || pOperator->status == OP_EXEC_DONE) {
11,579,659!
1027
    return code;
95,676✔
1028
  }
1029

1030
  // do the ascending order traverse in the first place.
1031
  while (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) {
13,430,152✔
1032
    SSDataBlock* p = NULL;
9,670,219✔
1033
    code = doTableScanImplNext(pOperator, &p);
9,670,219✔
1034
    QUERY_CHECK_CODE(code, lino, _end);
9,669,480!
1035

1036
    if (p != NULL) {
9,669,480✔
1037
      markGroupProcessed(pTableScanInfo, p->info.id.groupId);
7,724,371✔
1038
      *pBlock = p;
7,724,195✔
1039
      return code;
7,724,195✔
1040
    }
1041

1042
    pTableScanInfo->scanTimes += 1;
1,945,109✔
1043
    taosHashClear(pTableScanInfo->pIgnoreTables);
1,945,109✔
1044

1045
    if (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) {
1,946,168✔
1046
      setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED);
620✔
1047
      pTableScanInfo->base.scanFlag = MAIN_SCAN;
621✔
1048
      pTableScanInfo->base.dataBlockLoadFlag = FUNC_DATA_REQUIRED_DATA_LOAD;
621✔
1049
      qDebug("start to repeat ascending order scan data blocks due to query func required, %s", GET_TASKID(pTaskInfo));
621✔
1050

1051
      // do prepare for the next round table scan operation
1052
      code = pAPI->tsdReader.tsdReaderResetStatus(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond);
621✔
1053
      QUERY_CHECK_CODE(code, lino, _end);
621!
1054
    }
1055
  }
1056

1057
  int32_t total = pTableScanInfo->scanInfo.numOfAsc + pTableScanInfo->scanInfo.numOfDesc;
3,759,933✔
1058
  if (pTableScanInfo->scanTimes < total) {
3,759,933✔
1059
    if (pTableScanInfo->base.cond.order == TSDB_ORDER_ASC) {
1,403,967✔
1060
      prepareForDescendingScan(&pTableScanInfo->base, pOperator->exprSupp.pCtx, 0);
179✔
1061
      code = pAPI->tsdReader.tsdReaderResetStatus(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond);
179✔
1062
      QUERY_CHECK_CODE(code, lino, _end);
178!
1063
      qDebug("%s start to descending order scan data blocks due to query func required", GET_TASKID(pTaskInfo));
178✔
1064
    }
1065

1066
    while (pTableScanInfo->scanTimes < total) {
2,101,309✔
1067
      SSDataBlock* p = NULL;
1,403,420✔
1068
      code = doTableScanImplNext(pOperator, &p);
1,403,420✔
1069
      QUERY_CHECK_CODE(code, lino, _end);
1,404,714!
1070

1071
      if (p != NULL) {
1,404,714✔
1072
        markGroupProcessed(pTableScanInfo, p->info.id.groupId);
707,215✔
1073
        *pBlock = p;
707,192✔
1074
        return code;
707,192✔
1075
      }
1076

1077
      pTableScanInfo->scanTimes += 1;
697,499✔
1078
      taosHashClear(pTableScanInfo->pIgnoreTables);
697,499✔
1079

1080
      if (pTableScanInfo->scanTimes < total) {
697,502✔
1081
        setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED);
4✔
UNCOV
1082
        pTableScanInfo->base.scanFlag = MAIN_SCAN;
×
1083

UNCOV
1084
        qDebug("%s start to repeat descending order scan data blocks", GET_TASKID(pTaskInfo));
×
UNCOV
1085
        code = pAPI->tsdReader.tsdReaderResetStatus(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond);
×
1086
        QUERY_CHECK_CODE(code, lino, _end);
×
1087
      }
1088
    }
1089
  }
1090

1091
  if (pTableScanInfo->countState < TABLE_COUNT_STATE_END) {
3,053,855✔
1092
    STableListInfo* pTableListInfo = pTableScanInfo->base.pTableListInfo;
611,869✔
1093
    if (pTableListInfo->groupOffset) {  // group by tbname, group by tag + sort
611,869✔
1094
      if (pTableScanInfo->countState < TABLE_COUNT_STATE_PROCESSED) {
198!
1095
        pTableScanInfo->countState = TABLE_COUNT_STATE_PROCESSED;
×
1096
        STableKeyInfo* pStart =
UNCOV
1097
            (STableKeyInfo*)tableListGetInfo(pTableScanInfo->base.pTableListInfo, pTableScanInfo->tableStartIndex);
×
1098

UNCOV
1099
        if (NULL == pStart) {
×
UNCOV
1100
          return code;
×
1101
        }
1102

UNCOV
1103
        *pBlock = getBlockForEmptyTable(pOperator, pStart);
×
UNCOV
1104
        return code;
×
1105
      }
1106
    } else {  // group by tag + no sort
1107
      int32_t numOfTables = 0;
611,671✔
1108
      code = tableListGetSize(pTableListInfo, &numOfTables);
611,671✔
1109
      QUERY_CHECK_CODE(code, lino, _end);
611,669!
1110

1111
      if (pTableScanInfo->tableEndIndex + 1 >= numOfTables) {
611,669✔
1112
        // get empty group, mark processed & rm from hash
1113
        void* pIte = taosHashIterate(pTableListInfo->remainGroups, NULL);
611,340✔
1114
        if (pIte != NULL) {
611,817✔
1115
          size_t        keySize = 0;
407,706✔
1116
          uint64_t*     pGroupId = taosHashGetKey(pIte, &keySize);
407,706✔
1117
          STableKeyInfo info = {.uid = *(uint64_t*)pIte, .groupId = *pGroupId};
407,726✔
1118
          taosHashCancelIterate(pTableListInfo->remainGroups, pIte);
407,726✔
1119
          markGroupProcessed(pTableScanInfo, *pGroupId);
407,703✔
1120
          *pBlock = getBlockForEmptyTable(pOperator, &info);
407,778✔
1121

1122
          return code;
407,454✔
1123
        }
1124
      }
1125
    }
1126
    pTableScanInfo->countState = TABLE_COUNT_STATE_END;
204,638✔
1127
  }
1128

1129
_end:
2,441,986✔
1130
  if (code != TSDB_CODE_SUCCESS) {
2,646,624!
UNCOV
1131
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
1132
    pTaskInfo->code = code;
×
1133
  }
1134

1135
  return code;
2,646,624✔
1136
}
1137

1138
static int32_t createTableListInfoFromParam(SOperatorInfo* pOperator) {
1,022✔
1139
  STableScanInfo*          pInfo = pOperator->info;
1,022✔
1140
  SExecTaskInfo*           pTaskInfo = pOperator->pTaskInfo;
1,022✔
1141
  int32_t                  code = 0;
1,022✔
1142
  STableListInfo*          pListInfo = pInfo->base.pTableListInfo;
1,022✔
1143
  STableScanOperatorParam* pParam = (STableScanOperatorParam*)pOperator->pOperatorGetParam->value;
1,022✔
1144
  int32_t                  num = taosArrayGetSize(pParam->pUidList);
1,022✔
1145
  if (num <= 0) {
1,023!
UNCOV
1146
    qError("empty table scan uid list");
×
UNCOV
1147
    return TSDB_CODE_INVALID_PARA;
×
1148
  }
1149

1150
  qDebug("vgId:%d add total %d dynamic tables to scan, tableSeq:%d, exist num:%" PRId64 ", operator status:%d",
1,023✔
1151
         pTaskInfo->id.vgId, num, pParam->tableSeq, (int64_t)taosArrayGetSize(pListInfo->pTableList),
1152
         pOperator->status);
1153

1154
  if (pParam->tableSeq) {
1,023✔
1155
    pListInfo->oneTableForEachGroup = true;
48✔
1156
    if (taosArrayGetSize(pListInfo->pTableList) > 0) {
48!
UNCOV
1157
      taosHashClear(pListInfo->map);
×
UNCOV
1158
      taosArrayClear(pListInfo->pTableList);
×
UNCOV
1159
      pOperator->status = OP_EXEC_DONE;
×
1160
    }
1161
  } else {
1162
    pListInfo->oneTableForEachGroup = false;
975✔
1163
    pListInfo->numOfOuputGroups = 1;
975✔
1164
  }
1165

1166
  STableKeyInfo info = {.groupId = 0};
1,023✔
1167
  int32_t       tableIdx = 0;
1,023✔
1168
  for (int32_t i = 0; i < num; ++i) {
42,929✔
1169
    uint64_t* pUid = taosArrayGet(pParam->pUidList, i);
41,902✔
1170
    if (!pUid) {
41,903!
UNCOV
1171
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
1172
      return terrno;
×
1173
    }
1174

1175
    if (taosHashPut(pListInfo->map, pUid, sizeof(uint64_t), &tableIdx, sizeof(int32_t))) {
41,903✔
1176
      if (TSDB_CODE_DUP_KEY == terrno) {
39,059!
1177
        continue;
39,059✔
1178
      }
UNCOV
1179
      return terrno;
×
1180
    }
1181

1182
    info.uid = *pUid;
2,865✔
1183
    void* p = taosArrayPush(pListInfo->pTableList, &info);
2,865✔
1184
    if (p == NULL) {
2,872!
UNCOV
1185
      return terrno;
×
1186
    }
1187

1188
    tableIdx++;
2,872✔
1189
    qDebug("add dynamic table scan uid:%" PRIu64 ", %s", info.uid, GET_TASKID(pTaskInfo));
2,872✔
1190
  }
1191

1192
  return code;
1,027✔
1193
}
1194

1195
static int32_t doInitReader(STableScanInfo* pInfo, SExecTaskInfo* pTaskInfo, SStorageAPI* pAPI, int32_t* pNum,
2,745,250✔
1196
                            STableKeyInfo** pList) {
1197
  const char* idStr = GET_TASKID(pTaskInfo);
2,745,250✔
1198
  int32_t     code = initNextGroupScan(pInfo, pList, pNum);
2,745,250✔
1199
  if (code) {
2,738,262✔
1200
    qError("%s failed to init groupScan Info, code:%s at line:%d", idStr, tstrerror(code), __LINE__);
2,548!
UNCOV
1201
    return code;
×
1202
  }
1203

1204
  if (pInfo->base.dataReader != NULL) {
2,735,714!
UNCOV
1205
    qError("%s tsdb reader should be null", idStr);
×
UNCOV
1206
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1207
  }
1208

1209
  code = pAPI->tsdReader.tsdReaderOpen(pInfo->base.readHandle.vnode, &pInfo->base.cond, *pList, *pNum, pInfo->pResBlock,
2,735,714✔
1210
                                       (void**)&pInfo->base.dataReader, idStr, &pInfo->pIgnoreTables);
2,735,714✔
1211
  if (code) {
2,750,244✔
1212
    qError("%s failed to open tsdbReader, code:%s at line:%d", idStr, tstrerror(code), __LINE__);
16!
1213
  }
1214

1215
  return code;
2,749,730✔
1216
}
1217

UNCOV
1218
static int32_t createVTableScanInfoFromParam(SOperatorInfo* pOperator) {
×
UNCOV
1219
  int32_t                  code = 0;
×
UNCOV
1220
  int32_t                  lino = 0;
×
UNCOV
1221
  STableScanInfo*          pInfo = pOperator->info;
×
UNCOV
1222
  SExecTaskInfo*           pTaskInfo = pOperator->pTaskInfo;
×
UNCOV
1223
  SStorageAPI*             pAPI = &pTaskInfo->storageAPI;
×
UNCOV
1224
  STableListInfo*          pListInfo = pInfo->base.pTableListInfo;
×
UNCOV
1225
  STableScanOperatorParam* pParam = (STableScanOperatorParam*)pOperator->pOperatorGetParam->value;
×
UNCOV
1226
  SMetaReader              orgTable = {0};
×
UNCOV
1227
  SMetaReader              superTable = {0};
×
UNCOV
1228
  SSchemaWrapper*          schema = NULL;
×
UNCOV
1229
  SArray*                  pColArray = NULL;
×
UNCOV
1230
  SArray*                  pBlockColArray = NULL;
×
UNCOV
1231
  int32_t                  num = 0;
×
UNCOV
1232
  STableKeyInfo*           pList = NULL;
×
1233

UNCOV
1234
  cleanupQueryTableDataCond(&pInfo->base.cond);
×
UNCOV
1235
  if (pAPI->tsdReader.tsdReaderClose) {
×
1236
    pAPI->tsdReader.tsdReaderClose(pInfo->base.dataReader);
×
1237
  }
1238

UNCOV
1239
  pAPI->metaReaderFn.initReader(&orgTable, pInfo->base.readHandle.vnode, META_READER_LOCK, &pAPI->metaFn);
×
UNCOV
1240
  QUERY_CHECK_CODE(pAPI->metaReaderFn.getTableEntryByName(&orgTable, strstr(pParam->pOrgTbInfo->tbName, ".") + 1), lino, _return);
×
UNCOV
1241
  switch (orgTable.me.type) {
×
UNCOV
1242
    case TSDB_CHILD_TABLE:
×
UNCOV
1243
      pAPI->metaReaderFn.initReader(&superTable, pInfo->base.readHandle.vnode, META_READER_LOCK, &pAPI->metaFn);
×
UNCOV
1244
      QUERY_CHECK_CODE(pAPI->metaReaderFn.getTableEntryByUid(&superTable, orgTable.me.ctbEntry.suid), lino, _return);
×
UNCOV
1245
      schema = &superTable.me.stbEntry.schemaRow;
×
UNCOV
1246
      break;
×
UNCOV
1247
    case TSDB_NORMAL_TABLE:
×
1248
      schema = &orgTable.me.ntbEntry.schemaRow;
×
UNCOV
1249
      break;
×
UNCOV
1250
    default:
×
UNCOV
1251
      qError("invalid table type:%d", orgTable.me.type);
×
1252
      return TSDB_CODE_INVALID_PARA;
×
1253
      break;
1254
  }
1255

UNCOV
1256
  pColArray = taosArrayInit(schema->nCols, sizeof(SColIdPair));
×
UNCOV
1257
  QUERY_CHECK_NULL(pColArray, code, lino, _return, terrno);
×
UNCOV
1258
  pBlockColArray = taosArrayInit(schema->nCols, sizeof(int32_t));
×
UNCOV
1259
  QUERY_CHECK_NULL(pBlockColArray, code, lino, _return, terrno);
×
1260

1261
  // virtual table's origin table scan do not has ts column.
UNCOV
1262
  SColIdPair tsPair = {.vtbColId = PRIMARYKEY_TIMESTAMP_COL_ID, .orgColId = PRIMARYKEY_TIMESTAMP_COL_ID};
×
UNCOV
1263
  QUERY_CHECK_NULL(taosArrayPush(pColArray, &tsPair), code, lino, _return, terrno);
×
1264

UNCOV
1265
  for (int32_t i = 0; i < taosArrayGetSize(pParam->pOrgTbInfo->colMap); ++i) {
×
UNCOV
1266
    SColIdNameKV *kv = taosArrayGet(pParam->pOrgTbInfo->colMap, i);
×
UNCOV
1267
    for (int32_t j = 0; j < schema->nCols; j++) {
×
UNCOV
1268
      if (strncmp(kv->colName, schema->pSchema[j].name, strlen(schema->pSchema[j].name)) == 0) {
×
UNCOV
1269
        SColIdPair pPair = {.vtbColId = kv->colId, .orgColId = (col_id_t)(j + 1)};
×
UNCOV
1270
        QUERY_CHECK_NULL(taosArrayPush(pColArray, &pPair), code, lino, _return, terrno);
×
UNCOV
1271
        break;
×
1272
      }
1273
    }
1274
  }
1275

UNCOV
1276
  for (int32_t i = 0; i < taosArrayGetSize(pColArray); i++) {
×
UNCOV
1277
    SColIdPair *pPair = (SColIdPair*)taosArrayGet(pColArray, i);
×
UNCOV
1278
    for (int32_t j = 0; j < taosArrayGetSize(pInfo->base.matchInfo.pList); j++) {
×
UNCOV
1279
      SColMatchItem *pItem = taosArrayGet(pInfo->base.matchInfo.pList, j);
×
1280
      if (pItem->colId == pPair->vtbColId) {
×
1281
        SColIdPair tmpPair = {.orgColId = pPair->orgColId, .vtbColId = pItem->dstSlotId};
×
UNCOV
1282
        QUERY_CHECK_NULL(taosArrayPush(pBlockColArray, &tmpPair), code, lino, _return, terrno);
×
UNCOV
1283
        break;
×
1284
      }
1285
    }
1286
  }
1287

UNCOV
1288
  if (pInfo->pResBlock) {
×
UNCOV
1289
    blockDataDestroy(pInfo->pResBlock);
×
UNCOV
1290
    pInfo->pResBlock = NULL;
×
1291
  }
UNCOV
1292
  QUERY_CHECK_CODE(createOneDataBlockWithColArray(pInfo->pOrgBlock, pBlockColArray, &pInfo->pResBlock), lino, _return);
×
UNCOV
1293
  QUERY_CHECK_CODE(initQueryTableDataCondWithColArray(&pInfo->base.cond, &pInfo->base.orgCond, &pInfo->base.readHandle, pColArray), lino, _return);
×
1294
  pInfo->base.cond.twindows.skey = pParam->window.ekey + 1;
×
UNCOV
1295
  pInfo->base.cond.suid = orgTable.me.type == TSDB_CHILD_TABLE ? superTable.me.uid : 0;
×
UNCOV
1296
  pInfo->currentGroupId = 0;
×
UNCOV
1297
  pInfo->base.dataReader = NULL;
×
UNCOV
1298
  pInfo->ignoreTag = true;
×
1299

UNCOV
1300
  pListInfo->oneTableForEachGroup = true;
×
UNCOV
1301
  taosHashClear(pListInfo->map);
×
UNCOV
1302
  taosArrayClear(pListInfo->pTableList);
×
1303

UNCOV
1304
  uint64_t      pUid = orgTable.me.uid;
×
UNCOV
1305
  STableKeyInfo info = {.groupId = 0, .uid = pUid};
×
UNCOV
1306
  int32_t       tableIdx = 0;
×
UNCOV
1307
  QUERY_CHECK_CODE(taosHashPut(pListInfo->map, &pUid, sizeof(uint64_t), &tableIdx, sizeof(int32_t)), lino, _return);
×
UNCOV
1308
  QUERY_CHECK_NULL(taosArrayPush(pListInfo->pTableList, &info), code, lino, _return, terrno);
×
UNCOV
1309
  qDebug("add dynamic table scan uid:%" PRIu64 ", %s", info.uid, GET_TASKID(pTaskInfo));
×
1310

UNCOV
1311
  pOperator->status = OP_OPENED;
×
1312

UNCOV
1313
  taosRLockLatch(&pTaskInfo->lock);
×
UNCOV
1314
  code = doInitReader(pInfo, pTaskInfo, pAPI, &num, &pList);
×
UNCOV
1315
  taosRUnLockLatch(&pTaskInfo->lock);
×
UNCOV
1316
  QUERY_CHECK_CODE(code, lino, _return);
×
1317

UNCOV
1318
  if (pInfo->pResBlock->info.capacity > pOperator->resultInfo.capacity) {
×
UNCOV
1319
    pOperator->resultInfo.capacity = pInfo->pResBlock->info.capacity;
×
1320
  }
1321

UNCOV
1322
  pInfo->currentGroupId = -1;
×
UNCOV
1323
_return:
×
UNCOV
1324
  if (code) {
×
UNCOV
1325
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1326
  }
UNCOV
1327
  taosArrayDestroy(pColArray);
×
UNCOV
1328
  taosArrayDestroy(pBlockColArray);
×
UNCOV
1329
  pAPI->metaReaderFn.clearReader(&superTable);
×
UNCOV
1330
  pAPI->metaReaderFn.clearReader(&orgTable);
×
UNCOV
1331
  return code;
×
1332
}
1333

1334
static int32_t startNextGroupScan(SOperatorInfo* pOperator, SSDataBlock** pResult) {
2,723,282✔
1335
  int32_t         code = TSDB_CODE_SUCCESS;
2,723,282✔
1336
  int32_t         lino = 0;
2,723,282✔
1337
  STableScanInfo* pInfo = pOperator->info;
2,723,282✔
1338
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
2,723,282✔
1339
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
2,723,282✔
1340
  int32_t         numOfTables = 0;
2,723,282✔
1341

1342
  QRY_PARAM_CHECK(pResult);
2,723,282!
1343

1344
  code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
2,723,282✔
1345
  QUERY_CHECK_CODE(code, lino, _end);
2,723,732!
1346

1347
  if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) {
2,723,732✔
1348
    setOperatorCompleted(pOperator);
2,722,627✔
1349
    if (pOperator->dynamicTask) {
2,722,918✔
1350
      taosArrayClear(pInfo->base.pTableListInfo->pTableList);
1,017✔
1351
      taosHashClear(pInfo->base.pTableListInfo->map);
1,017✔
1352
    }
1353
    return code;
2,722,882✔
1354
  }
1355

1356
  // reset value for the next group data output
1357
  pOperator->status = OP_OPENED;
845✔
1358
  resetLimitInfoForNextGroup(&pInfo->base.limitInfo);
845✔
1359

1360
  int32_t        num = 0;
958✔
1361
  STableKeyInfo* pList = NULL;
958✔
1362
  code = initNextGroupScan(pInfo, &pList, &num);
958✔
1363
  QUERY_CHECK_CODE(code, lino, _end);
958!
1364

1365
  code = pAPI->tsdReader.tsdSetQueryTableList(pInfo->base.dataReader, pList, num);
958✔
1366
  QUERY_CHECK_CODE(code, lino, _end);
958!
1367

1368
  code = pAPI->tsdReader.tsdReaderResetStatus(pInfo->base.dataReader, &pInfo->base.cond);
958✔
1369
  QUERY_CHECK_CODE(code, lino, _end);
958!
1370
  pInfo->scanTimes = 0;
958✔
1371

1372
  code = doGroupedTableScan(pOperator, pResult);
958✔
1373
  QUERY_CHECK_CODE(code, lino, _end);
959!
1374

1375
  if (*pResult != NULL) {
959✔
1376
    if (pOperator->dynamicTask) {
835✔
1377
      (*pResult)->info.id.groupId = (*pResult)->info.id.uid;
24✔
1378
    }
1379
    return code;
835✔
1380
  }
1381

1382
_end:
124✔
1383
  if (code != TSDB_CODE_SUCCESS) {
124!
1384
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1385
    pTaskInfo->code = code;
×
1386
  }
1387
  return code;
124✔
1388
}
1389

1390
static int32_t groupSeqTableScan(SOperatorInfo* pOperator, SSDataBlock** pResBlock) {
11,533,713✔
1391
  int32_t         code = TSDB_CODE_SUCCESS;
11,533,713✔
1392
  int32_t         lino = 0;
11,533,713✔
1393
  STableScanInfo* pInfo = pOperator->info;
11,533,713✔
1394
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
11,533,713✔
1395
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
11,533,713✔
1396
  int32_t         num = 0;
11,533,713✔
1397
  STableKeyInfo*  pList = NULL;
11,533,713✔
1398
  SSDataBlock*    pResult = NULL;
11,533,713✔
1399
  const char*     idStr = GET_TASKID(pTaskInfo);
11,533,713✔
1400

1401
  QRY_PARAM_CHECK(pResBlock);
11,533,713!
1402

1403
  if (pInfo->currentGroupId == -1) {
11,533,713✔
1404
    if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) {
2,744,195!
UNCOV
1405
      setOperatorCompleted(pOperator);
×
UNCOV
1406
      return code;
×
1407
    }
1408

1409
    taosRLockLatch(&pTaskInfo->lock);
2,742,880✔
1410
    code = doInitReader(pInfo, pTaskInfo, pAPI, &num, &pList);
2,751,400✔
1411
    taosRUnLockLatch(&pTaskInfo->lock);
2,749,709✔
1412
    QUERY_CHECK_CODE(code, lino, _end);
2,751,847✔
1413

1414
    if (pInfo->filesetDelimited) {
2,751,831✔
1415
      pAPI->tsdReader.tsdSetFilesetDelimited(pInfo->base.dataReader);
997✔
1416
    }
1417

1418
    if (pInfo->pResBlock->info.capacity > pOperator->resultInfo.capacity) {
2,751,830!
UNCOV
1419
      pOperator->resultInfo.capacity = pInfo->pResBlock->info.capacity;
×
1420
    }
1421
  }
1422

1423
  code = doGroupedTableScan(pOperator, &pResult);
11,541,348✔
1424
  QUERY_CHECK_CODE(code, lino, _end);
11,539,074!
1425

1426
  if (pResult != NULL) {
11,539,074✔
1427
    if (pOperator->dynamicTask) {
8,817,794✔
1428
      pResult->info.id.groupId = pResult->info.id.uid;
2,595✔
1429
    }
1430

1431
    *pResBlock = pResult;
8,817,794✔
1432
    return code;
8,817,794✔
1433
  }
1434

1435
  while (true) {
1436
    code = startNextGroupScan(pOperator, &pResult);
2,721,404✔
1437
    QUERY_CHECK_CODE(code, lino, _end);
2,723,877!
1438

1439
    if (pResult || pOperator->status == OP_EXEC_DONE) {
2,723,877✔
1440
      *pResBlock = pResult;
2,723,753✔
1441
      return code;
2,723,753✔
1442
    }
1443
  }
1444

1445
_end:
16✔
1446
  if (code != TSDB_CODE_SUCCESS) {
16!
1447
    qError("%s %s failed at line %d since %s", idStr, __func__, lino, tstrerror(code));
16!
1448
    pTaskInfo->code = code;
16✔
1449
  }
1450

1451
  return code;
16✔
1452
}
1453

1454
int32_t doTableScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
11,554,410✔
1455
  int32_t         code = TSDB_CODE_SUCCESS;
11,554,410✔
1456
  int32_t         lino = 0;
11,554,410✔
1457
  STableScanInfo* pInfo = pOperator->info;
11,554,410✔
1458
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
11,554,410✔
1459
  SStorageAPI*    pAPI = &pTaskInfo->storageAPI;
11,554,410✔
1460
  QRY_PARAM_CHECK(ppRes);
11,554,410!
1461

1462
  if (pOperator->pOperatorGetParam) {
11,554,410✔
1463
    pOperator->dynamicTask = true;
1,023✔
1464
    if (isDynVtbScan(pOperator)) {
1,023!
UNCOV
1465
      code = createVTableScanInfoFromParam(pOperator);
×
1466

UNCOV
1467
      freeOperatorParam(pOperator->pOperatorGetParam, OP_GET_PARAM);
×
UNCOV
1468
      pOperator->pOperatorGetParam = NULL;
×
UNCOV
1469
      QUERY_CHECK_CODE(code, lino, _end);
×
1470

UNCOV
1471
      SSDataBlock* result = NULL;
×
1472
      while (true) {
UNCOV
1473
        QUERY_CHECK_CODE(startNextGroupScan(pOperator, &result), lino, _end);
×
1474

UNCOV
1475
        if (result || pOperator->status == OP_EXEC_DONE) {
×
UNCOV
1476
          SSDataBlock* res = NULL;
×
UNCOV
1477
          if (result) {
×
UNCOV
1478
            QUERY_CHECK_CODE(createOneDataBlockWithTwoBlock(result, pInfo->pOrgBlock, &res), lino, _end);
×
UNCOV
1479
            pInfo->pResBlock = res;
×
UNCOV
1480
            blockDataDestroy(result);
×
1481
          }
UNCOV
1482
          (*ppRes) = res;
×
UNCOV
1483
          return code;
×
1484
        }
1485
      }
1486
    } else {
1487
      code = createTableListInfoFromParam(pOperator);
1,023✔
1488
      freeOperatorParam(pOperator->pOperatorGetParam, OP_GET_PARAM);
1,023✔
1489
      pOperator->pOperatorGetParam = NULL;
×
UNCOV
1490
      QUERY_CHECK_CODE(code, lino, _end);
×
1491

UNCOV
1492
      if (pOperator->status == OP_EXEC_DONE) {
×
1493
        pInfo->currentGroupId = -1;
24✔
1494
        pOperator->status = OP_OPENED;
24✔
1495
        SSDataBlock* result = NULL;
24✔
1496

1497
        while (true) {
1498
          code = startNextGroupScan(pOperator, &result);
24✔
1499
          QUERY_CHECK_CODE(code, lino, _end);
24!
1500

1501
          if (result || pOperator->status == OP_EXEC_DONE) {
24!
1502
            (*ppRes) = result;
24✔
1503
            return code;
24✔
1504
          }
1505
        }
1506
      }
1507
    }
1508
  }
1509

1510
  // scan table one by one sequentially
1511
  if (pInfo->scanMode == TABLE_SCAN__TABLE_ORDER) {
11,551,404✔
1512
    int32_t       numOfTables = 0;
20,536✔
1513
    STableKeyInfo tInfo = {0};
20,536✔
1514
    pInfo->countState = TABLE_COUNT_STATE_END;
20,536✔
1515

1516
    while (1) {
19,121✔
1517
      SSDataBlock* result = NULL;
39,657✔
1518
      code = doGroupedTableScan(pOperator, &result);
39,657✔
1519
      QUERY_CHECK_CODE(code, lino, _end);
39,628!
1520

1521
      if (result || (pOperator->status == OP_EXEC_DONE) || isTaskKilled(pTaskInfo)) {
39,628!
1522
        (*ppRes) = result;
20,293✔
1523
        return code;
20,494✔
1524
      }
1525

1526
      // if no data, switch to next table and continue scan
1527
      pInfo->currentTable++;
19,334✔
1528

1529
      taosRLockLatch(&pTaskInfo->lock);
19,334✔
1530
      numOfTables = 0;
19,343✔
1531
      code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
19,343✔
1532
      if (code != TSDB_CODE_SUCCESS) {
19,343!
UNCOV
1533
        taosRUnLockLatch(&pTaskInfo->lock);
×
UNCOV
1534
        TSDB_CHECK_CODE(code, lino, _end);
×
1535
      }
1536

1537
      if (pInfo->currentTable >= numOfTables) {
19,343✔
1538
        qDebug("all table checked in table list, total:%d, return NULL, %s", numOfTables, GET_TASKID(pTaskInfo));
201✔
1539
        taosRUnLockLatch(&pTaskInfo->lock);
201✔
1540
        (*ppRes) = NULL;
201✔
1541
        return code;
201✔
1542
      }
1543

1544
      STableKeyInfo* tmp = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->currentTable);
19,142✔
1545
      if (!tmp) {
19,140!
UNCOV
1546
        taosRUnLockLatch(&pTaskInfo->lock);
×
UNCOV
1547
        (*ppRes) = NULL;
×
UNCOV
1548
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
×
1549
      }
1550

1551
      tInfo = *tmp;
19,140✔
1552
      taosRUnLockLatch(&pTaskInfo->lock);
19,140✔
1553

1554
      code = pAPI->tsdReader.tsdSetQueryTableList(pInfo->base.dataReader, &tInfo, 1);
19,142✔
1555
      QUERY_CHECK_CODE(code, lino, _end);
19,140!
1556
      qDebug("set uid:%" PRIu64 " into scanner, total tables:%d, index:%d/%d %s", tInfo.uid, numOfTables,
19,140✔
1557
             pInfo->currentTable, numOfTables, GET_TASKID(pTaskInfo));
1558

1559
      code = pAPI->tsdReader.tsdReaderResetStatus(pInfo->base.dataReader, &pInfo->base.cond);
19,140✔
1560
      QUERY_CHECK_CODE(code, lino, _end);
19,121!
1561
      pInfo->scanTimes = 0;
19,121✔
1562
    }
1563
  } else {  // scan table group by group sequentially
1564
    code = groupSeqTableScan(pOperator, ppRes);
11,530,868✔
1565
    QUERY_CHECK_CODE(code, lino, _end);
11,540,139✔
1566
  }
1567

1568
_end:
11,540,123✔
1569
  if (code != TSDB_CODE_SUCCESS) {
11,540,139✔
1570
    qError("%s %s failed at line %d since %s", GET_TASKID(pTaskInfo), __func__, lino, tstrerror(code));
16!
1571
    pTaskInfo->code = code;
16✔
1572
    T_LONG_JMP(pTaskInfo->env, code);
16!
1573
  }
1574

1575
  return code;
11,540,123✔
1576
}
1577

1578
static int32_t getTableScannerExecInfo(struct SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
144,037✔
1579
  SFileBlockLoadRecorder* pRecorder = taosMemoryCalloc(1, sizeof(SFileBlockLoadRecorder));
144,037!
1580
  if (!pRecorder) {
144,075!
1581
    return terrno;
×
1582
  }
1583
  STableScanInfo* pTableScanInfo = pOptr->info;
144,075✔
1584
  *pRecorder = pTableScanInfo->base.readRecorder;
144,075✔
1585
  *pOptrExplain = pRecorder;
144,075✔
1586
  *len = sizeof(SFileBlockLoadRecorder);
144,075✔
1587
  return 0;
144,075✔
1588
}
1589

1590
static void destroyTableScanBase(STableScanBase* pBase, TsdReader* pAPI) {
4,771,561✔
1591
  cleanupQueryTableDataCond(&pBase->cond);
4,771,561✔
1592
  cleanupQueryTableDataCond(&pBase->orgCond);
4,772,335✔
1593

1594
  if (pAPI->tsdReaderClose) {
4,772,518!
1595
    pAPI->tsdReaderClose(pBase->dataReader);
4,772,582✔
1596
  }
1597
  pBase->dataReader = NULL;
4,772,816✔
1598

1599
  if (pBase->matchInfo.pList != NULL) {
4,772,816!
1600
    taosArrayDestroy(pBase->matchInfo.pList);
4,772,838✔
1601
  }
1602

1603
  tableListDestroy(pBase->pTableListInfo);
4,772,931✔
1604
  taosLRUCacheCleanup(pBase->metaCache.pTableMetaEntryCache);
4,773,200✔
1605
  cleanupExprSupp(&pBase->pseudoSup);
4,773,260✔
1606
}
4,773,258✔
1607

1608
static void destroyTableScanOperatorInfo(void* param) {
2,793,556✔
1609
  STableScanInfo* pTableScanInfo = (STableScanInfo*)param;
2,793,556✔
1610
  blockDataDestroy(pTableScanInfo->pResBlock);
2,793,556✔
1611
  blockDataDestroy(pTableScanInfo->pOrgBlock);
2,794,771✔
1612
  taosHashCleanup(pTableScanInfo->pIgnoreTables);
2,794,755✔
1613
  destroyTableScanBase(&pTableScanInfo->base, &pTableScanInfo->base.readerAPI);
2,794,282✔
1614
  taosMemoryFreeClear(param);
2,794,708!
1615
}
2,794,844✔
1616

1617
static void resetClolumnReserve(SSDataBlock* pBlock, int32_t dataRequireFlag) {
2,789,473✔
1618
  if (pBlock && dataRequireFlag == FUNC_DATA_REQUIRED_NOT_LOAD) {
2,789,473!
1619
    int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
184,172✔
1620
    for (int32_t i = 0; i < numOfCols; ++i) {
512,349✔
1621
      SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
328,194✔
1622
      if (pCol) {
328,183!
1623
        pCol->info.noData = true;
328,202✔
1624
      }
1625
    }
1626
  }
1627
}
2,789,456✔
1628

1629
int32_t createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle,
2,791,374✔
1630
                                    STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo,
1631
                                    SOperatorInfo** pOptrInfo) {
1632
  QRY_PARAM_CHECK(pOptrInfo);
2,791,374!
1633

1634
  int32_t         code = TSDB_CODE_SUCCESS;
2,791,374✔
1635
  int32_t         lino = 0;
2,791,374✔
1636
  STableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableScanInfo));
2,791,374!
1637
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
2,791,670!
1638
  if (pInfo == NULL || pOperator == NULL) {
2,792,101!
UNCOV
1639
    code = terrno;
×
UNCOV
1640
    goto _error;
×
1641
  }
1642

1643
  SScanPhysiNode*     pScanNode = &pTableScanNode->scan;
2,792,336✔
1644
  SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc;
2,792,336✔
1645

1646
  int32_t numOfCols = 0;
2,792,336✔
1647
  code =
1648
      extractColMatchInfo(pScanNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID, &pInfo->base.matchInfo);
2,792,336✔
1649
  QUERY_CHECK_CODE(code, lino, _error);
2,792,460!
1650

1651
  initLimitInfo(pScanNode->node.pLimit, pScanNode->node.pSlimit, &pInfo->base.limitInfo);
2,792,460✔
1652
  code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, readHandle);
2,792,869✔
1653
  QUERY_CHECK_CODE(code, lino, _error);
2,791,319!
1654

1655
  if (pScanNode->pScanPseudoCols != NULL) {
2,791,319✔
1656
    SExprSupp* pSup = &pInfo->base.pseudoSup;
658,998✔
1657
    pSup->pExprInfo = NULL;
658,998✔
1658
    code = createExprInfo(pScanNode->pScanPseudoCols, NULL, &pSup->pExprInfo, &pSup->numOfExprs);
658,998✔
1659
    QUERY_CHECK_CODE(code, lino, _error);
658,949!
1660

1661
    pSup->pCtx = createSqlFunctionCtx(pSup->pExprInfo, pSup->numOfExprs, &pSup->rowEntryInfoOffset,
658,949✔
1662
                                      &pTaskInfo->storageAPI.functionStore);
1663
    QUERY_CHECK_NULL(pSup->pCtx, code, lino, _error, terrno);
658,118✔
1664
  }
1665

1666
  pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]};
2,788,638✔
1667
  pInfo->base.scanFlag = (pInfo->scanInfo.numOfAsc > 1) ? PRE_SCAN : MAIN_SCAN;
2,788,638✔
1668

1669
  pInfo->base.pdInfo.interval = extractIntervalInfo(pTableScanNode);
2,788,638✔
1670
  pInfo->base.readHandle = *readHandle;
2,786,860✔
1671
  pInfo->base.dataBlockLoadFlag = pTableScanNode->dataRequired;
2,786,860✔
1672

1673
  pInfo->sample.sampleRatio = pTableScanNode->ratio;
2,786,860✔
1674
  pInfo->sample.seed = taosGetTimestampSec();
2,786,860✔
1675

1676
  pInfo->base.readerAPI = pTaskInfo->storageAPI.tsdReader;
2,787,718✔
1677
  initResultSizeInfo(&pOperator->resultInfo, 4096);
2,787,718✔
1678
  pInfo->pResBlock = createDataBlockFromDescNode(pDescNode);
2,786,600✔
1679
  resetClolumnReserve(pInfo->pResBlock, pInfo->base.dataBlockLoadFlag);
2,792,911✔
1680
  QUERY_CHECK_NULL(pInfo->pResBlock, code, lino, _error, terrno);
2,789,225!
1681

1682
  code = prepareDataBlockBuf(pInfo->pResBlock, &pInfo->base.matchInfo);
2,789,225✔
1683
  QUERY_CHECK_CODE(code, lino, _error);
2,785,881!
1684

1685
  pInfo->virtualStableScan = pScanNode->virtualStableScan;
2,785,881✔
1686
  if (pScanNode->node.dynamicOp && pScanNode->virtualStableScan) {
2,785,881!
UNCOV
1687
    TSWAP(pInfo->pOrgBlock, pInfo->pResBlock);
×
UNCOV
1688
    pInfo->pResBlock = NULL;
×
UNCOV
1689
    memcpy(&pInfo->base.orgCond, &pInfo->base.cond, sizeof(SQueryTableDataCond));
×
UNCOV
1690
    memset(&pInfo->base.cond, 0, sizeof(SQueryTableDataCond));
×
1691
  }
1692

1693
  code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
2,785,881✔
1694
  QUERY_CHECK_CODE(code, lino, _error);
2,787,453✔
1695

1696
  pInfo->currentGroupId = -1;
2,787,277✔
1697

1698
  pInfo->tableEndIndex = -1;
2,787,277✔
1699
  pInfo->assignBlockUid = pTableScanNode->assignBlockUid;
2,787,277✔
1700
  pInfo->hasGroupByTag = pTableScanNode->pGroupTags ? true : false;
2,787,277✔
1701

1702
  setOperatorInfo(pOperator, "TableScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, false, OP_NOT_OPENED, pInfo,
2,787,277✔
1703
                  pTaskInfo);
1704
  pOperator->exprSupp.numOfExprs = numOfCols;
2,785,560✔
1705

1706
  pInfo->needCountEmptyTable = tsCountAlwaysReturnValue && pTableScanNode->needCountEmptyTable;
2,785,560✔
1707
  pInfo->ignoreTag = false;
2,785,560✔
1708

1709
  pInfo->base.pTableListInfo = pTableListInfo;
2,785,560✔
1710
  pInfo->base.metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024 * 128, -1, .5);
2,785,560✔
1711
  if (pInfo->base.metaCache.pTableMetaEntryCache == NULL) {
2,793,725!
UNCOV
1712
    code = terrno;
×
UNCOV
1713
    QUERY_CHECK_CODE(code, lino, _error);
×
1714
  }
1715

1716
  pInfo->filesetDelimited = pTableScanNode->filesetDelimited;
2,793,725✔
1717

1718
  taosLRUCacheSetStrictCapacity(pInfo->base.metaCache.pTableMetaEntryCache, false);
2,793,725✔
1719
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableScanNext, NULL, destroyTableScanOperatorInfo,
2,794,347✔
1720
                                         optrDefaultBufFn, getTableScannerExecInfo, optrDefaultGetNextExtFn, NULL);
1721

1722
  // for non-blocking operator, the open cost is always 0
1723
  pOperator->cost.openCost = 0;
2,791,054✔
1724
  *pOptrInfo = pOperator;
2,791,054✔
1725
  return TSDB_CODE_SUCCESS;
2,791,054✔
1726

1727
_error:
176✔
1728
  if (pInfo != NULL) {
176!
1729
    pInfo->base.pTableListInfo = NULL;  // this attribute will be destroy outside of this function
176✔
1730
    destroyTableScanOperatorInfo(pInfo);
176✔
1731
  }
1732

1733
  if (pOperator != NULL) {
176!
1734
    pOperator->info = NULL;
176✔
1735
    destroyOperator(pOperator);
176✔
1736
  }
1737
  pTaskInfo->code = code;
176✔
1738
  return code;
176✔
1739
}
1740

1741
int32_t createTableSeqScanOperatorInfo(void* pReadHandle, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
×
1742
  QRY_PARAM_CHECK(pOptrInfo);
×
1743

UNCOV
1744
  int32_t         code = 0;
×
UNCOV
1745
  STableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableScanInfo));
×
1746
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
×
1747
  if (pInfo == NULL || pOperator == NULL) {
×
UNCOV
1748
    code = terrno;
×
UNCOV
1749
    goto _end;
×
1750
  }
1751

UNCOV
1752
  pInfo->base.dataReader = pReadHandle;
×
1753
  //  pInfo->prevGroupId       = -1;
1754

UNCOV
1755
  setOperatorInfo(pOperator, "TableSeqScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN, false, OP_NOT_OPENED,
×
1756
                  pInfo, pTaskInfo);
UNCOV
1757
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableScanImplNext, NULL, NULL, optrDefaultBufFn, NULL,
×
1758
                                         optrDefaultGetNextExtFn, NULL);
UNCOV
1759
  *pOptrInfo = pOperator;
×
UNCOV
1760
  return code;
×
1761

UNCOV
1762
_end:
×
1763
  if (pInfo != NULL) {
×
UNCOV
1764
    taosMemoryFree(pInfo);
×
1765
  }
1766

UNCOV
1767
  if (pOperator != NULL) {
×
UNCOV
1768
    taosMemoryFree(pOperator);
×
1769
  }
1770

UNCOV
1771
  pTaskInfo->code = code;
×
UNCOV
1772
  return code;
×
1773
}
1774

1775
FORCE_INLINE void doClearBufferedBlocks(SStreamScanInfo* pInfo) {
63✔
1776
  qDebug("clear buff blocks:%d", (int32_t)taosArrayGetSize(pInfo->pBlockLists));
45,874!
1777
  taosArrayClear(pInfo->pBlockLists);
45,874✔
1778
  pInfo->validBlockIndex = 0;
45,874✔
1779
}
45,811✔
1780

1781
static bool isSessionWindow(SStreamScanInfo* pInfo) {
1,898✔
1782
  return pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION ||
3,282✔
1783
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION ||
3,195✔
1784
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION;
1,297!
1785
}
1786

1787
static bool isStateWindow(SStreamScanInfo* pInfo) {
1,361✔
1788
  return pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE ||
1,734✔
1789
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT;
373✔
1790
}
1791

1792
static bool isIntervalWindow(SStreamScanInfo* pInfo) {
11,047✔
1793
  return pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL ||
18,691✔
1794
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL ||
7,644✔
1795
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL ||
6,375!
1796
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL ||
6,375!
1797
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_CONTINUE_INTERVAL ||
6,375✔
1798
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_CONTINUE_SEMI_INTERVAL ||
23,456!
1799
         pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_CONTINUE_FINAL_INTERVAL;
4,765!
1800
}
1801

1802
static bool isSignleIntervalWindow(SStreamScanInfo* pInfo) {
30,862,269✔
1803
  return pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL;
30,862,269✔
1804
}
1805

1806
static bool isSlidingWindow(SStreamScanInfo* pInfo) {
6,937✔
1807
  return isIntervalWindow(pInfo) && pInfo->interval.interval != pInfo->interval.sliding;
6,937✔
1808
}
1809

1810
static bool isCountSlidingWindow(SStreamScanInfo* pInfo) {
6,898✔
1811
  return pInfo->windowSup.pStreamAggSup &&
11,329✔
1812
         (pInfo->windowSup.pStreamAggSup->windowCount != pInfo->windowSup.pStreamAggSup->windowSliding);
4,431✔
1813
}
1814

1815
static bool isCountWindow(SStreamScanInfo* pInfo) {
282✔
1816
  return pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT;
282✔
1817
}
1818

1819
static bool isTimeSlice(SStreamScanInfo* pInfo) {
153✔
1820
  return pInfo->windowSup.parentType == QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERP_FUNC;
153✔
1821
}
1822

1823
static void setGroupId(SStreamScanInfo* pInfo, SSDataBlock* pBlock, int32_t groupColIndex, int32_t rowIndex) {
6,937✔
1824
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, groupColIndex);
6,937✔
1825
  uint64_t*        groupCol = (uint64_t*)pColInfo->pData;
6,937✔
1826
  if (colDataIsNull_s(pColInfo, rowIndex)) {
13,874✔
1827
    pInfo->igCheckGroupId = true;
3,264✔
1828
  } else {
1829
    pInfo->groupId = groupCol[rowIndex];
3,673✔
1830
  }
1831
}
6,937✔
1832

1833
void resetTableScanInfo(STableScanInfo* pTableScanInfo, STimeWindow* pWin, int64_t ver) {
6,936✔
1834
  pTableScanInfo->base.cond.twindows = *pWin;
6,936✔
1835
  pTableScanInfo->base.cond.startVersion = 0;
6,936✔
1836
  pTableScanInfo->base.cond.endVersion = ver;
6,936✔
1837
  pTableScanInfo->scanTimes = 0;
6,936✔
1838
  pTableScanInfo->currentGroupId = -1;
6,936✔
1839
  pTableScanInfo->tableEndIndex = -1;
6,936✔
1840
  pTableScanInfo->base.readerAPI.tsdReaderClose(pTableScanInfo->base.dataReader);
6,936✔
1841
  pTableScanInfo->base.dataReader = NULL;
6,933✔
1842
  pTableScanInfo->scanMode = TABLE_SCAN__BLOCK_ORDER;
6,933✔
1843
}
6,933✔
1844

1845
SSDataBlock* readPreVersionData(SOperatorInfo* pTableScanOp, uint64_t tbUid, TSKEY startTs, TSKEY endTs,
714✔
1846
                                int64_t maxVersion) {
1847
  int32_t       code = TSDB_CODE_SUCCESS;
714✔
1848
  int32_t       lino = 0;
714✔
1849
  STableKeyInfo tblInfo = {.uid = tbUid, .groupId = 0};
714✔
1850

1851
  STableScanInfo*     pTableScanInfo = pTableScanOp->info;
714✔
1852
  SQueryTableDataCond cond = pTableScanInfo->base.cond;
714✔
1853

1854
  cond.startVersion = -1;
714✔
1855
  cond.endVersion = maxVersion;
714✔
1856
  cond.twindows = (STimeWindow){.skey = startTs, .ekey = endTs};
714✔
1857

1858
  SExecTaskInfo* pTaskInfo = pTableScanOp->pTaskInfo;
714✔
1859
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
714✔
1860

1861
  SSDataBlock* pBlock = pTableScanInfo->pResBlock;
714✔
1862
  STsdbReader* pReader = NULL;
714✔
1863
  code = pAPI->tsdReader.tsdReaderOpen(pTableScanInfo->base.readHandle.vnode, &cond, &tblInfo, 1, pBlock,
714✔
1864
                                       (void**)&pReader, GET_TASKID(pTaskInfo), NULL);
714✔
1865
  QUERY_CHECK_CODE(code, lino, _end);
713!
1866

1867
  bool hasNext = false;
713✔
1868
  code = pAPI->tsdReader.tsdNextDataBlock(pReader, &hasNext);
713✔
1869
  QUERY_CHECK_CODE(code, lino, _end);
711!
1870

1871
  if (hasNext) {
711✔
1872
    SSDataBlock* p = NULL;
678✔
1873
    code = pAPI->tsdReader.tsdReaderRetrieveDataBlock(pReader, &p, NULL);
678✔
1874
    QUERY_CHECK_CODE(code, lino, _end);
677!
1875

1876
    code = doSetTagColumnData(&pTableScanInfo->base, pBlock, pTaskInfo, pBlock->info.rows);
677✔
1877
    QUERY_CHECK_CODE(code, lino, _end);
680!
1878

1879
    pBlock->info.id.groupId = tableListGetTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid);
680✔
1880
  }
1881

1882
_end:
33✔
1883
  pAPI->tsdReader.tsdReaderClose(pReader);
713✔
1884
  qDebug("retrieve prev rows:%" PRId64 ", skey:%" PRId64 ", ekey:%" PRId64 " uid:%" PRIu64 ", max ver:%" PRId64
713✔
1885
         ", suid:%" PRIu64,
1886
         pBlock->info.rows, startTs, endTs, tbUid, maxVersion, cond.suid);
1887
  if (code != TSDB_CODE_SUCCESS) {
713!
UNCOV
1888
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
1889
    terrno = code;
×
UNCOV
1890
    return NULL;
×
1891
  }
1892

1893
  return pBlock->info.rows > 0 ? pBlock : NULL;
713✔
1894
}
1895

1896
bool comparePrimaryKey(SColumnInfoData* pCol, int32_t rowId, void* pVal) {
2✔
1897
  // coverity scan
1898
  if (!pVal || !pCol) {
2!
UNCOV
1899
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_INVALID_PARA));
×
UNCOV
1900
    return false;
×
1901
  }
1902
  void* pData = colDataGetData(pCol, rowId);
2!
1903
  if (IS_VAR_DATA_TYPE(pCol->info.type)) {
2!
UNCOV
1904
    int32_t colLen = varDataLen(pData);
×
UNCOV
1905
    int32_t keyLen = varDataLen(pVal);
×
UNCOV
1906
    if (pCol->info.type == TSDB_DATA_TYPE_JSON) {
×
UNCOV
1907
      colLen = getJsonValueLen(pData);
×
UNCOV
1908
      keyLen = getJsonValueLen(pVal);
×
1909
    }
1910

UNCOV
1911
    if (colLen == keyLen && memcmp(pData, pVal, colLen) == 0) {
×
UNCOV
1912
      return true;
×
1913
    }
1914
  } else {
1915
    if (memcmp(pData, pVal, pCol->info.bytes) == 0) {
2!
1916
      return true;
2✔
1917
    }
1918
  }
UNCOV
1919
  return false;
×
1920
}
1921

1922
static bool hasPrimaryKeyCol(SStreamScanInfo* pInfo) { return pInfo->primaryKeyIndex != -1; }
51,802,431✔
1923

1924
static uint64_t getGroupIdByCol(SStreamScanInfo* pInfo, uint64_t uid, TSKEY ts, int64_t maxVersion, void* pVal) {
659✔
1925
  SSDataBlock* pPreRes = readPreVersionData(pInfo->pTableScanOp, uid, ts, ts, maxVersion);
659✔
1926
  if (!pPreRes || pPreRes->info.rows == 0) {
660✔
1927
    if (terrno != TSDB_CODE_SUCCESS) {
35!
UNCOV
1928
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1929
    }
1930
    return 0;
34✔
1931
  }
1932

1933
  int32_t rowId = 0;
625✔
1934
  if (hasPrimaryKeyCol(pInfo)) {
625✔
1935
    SColumnInfoData* pPkCol = taosArrayGet(pPreRes->pDataBlock, pInfo->primaryKeyIndex);
1✔
1936
    for (; rowId < pPreRes->info.rows; rowId++) {
2!
1937
      if (comparePrimaryKey(pPkCol, rowId, pVal)) {
2!
1938
        break;
2✔
1939
      }
1940
    }
1941
  }
1942
  if (rowId >= pPreRes->info.rows) {
626!
UNCOV
1943
    qInfo("===stream===read preversion data of primary key failed. ts:%" PRId64 ",version:%" PRId64, ts, maxVersion);
×
UNCOV
1944
    return 0;
×
1945
  }
1946
  return calGroupIdByData(&pInfo->partitionSup, pInfo->pPartScalarSup, pPreRes, rowId);
626✔
1947
}
1948

1949
static uint64_t getGroupIdByUid(SStreamScanInfo* pInfo, uint64_t uid) {
2,518✔
1950
  STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info;
2,518✔
1951
  return tableListGetTableGroupId(pTableScanInfo->base.pTableListInfo, uid);
2,518✔
1952
}
1953

1954
static uint64_t getGroupIdByData(SStreamScanInfo* pInfo, uint64_t uid, TSKEY ts, int64_t maxVersion, void* pVal) {
2,329✔
1955
  if (pInfo->partitionSup.needCalc) {
2,329✔
1956
    return getGroupIdByCol(pInfo, uid, ts, maxVersion, pVal);
659✔
1957
  }
1958

1959
  return getGroupIdByUid(pInfo, uid);
1,670✔
1960
}
1961

1962
void prepareRangeScan(SStreamScanInfo* pInfo, SSDataBlock* pBlock, int32_t* pRowIndex, bool* pRes) {
13,556✔
1963
  int32_t code = TSDB_CODE_SUCCESS;
13,556✔
1964
  int32_t lino = 0;
13,556✔
1965
  if (pBlock->info.rows == 0) {
13,556✔
1966
    if (pRes) {
1!
UNCOV
1967
      (*pRes) = false;
×
1968
    }
1969
    goto _end;
1✔
1970
  }
1971
  if ((*pRowIndex) == pBlock->info.rows) {
13,555✔
1972
    if (pRes) {
6,617✔
1973
      (*pRes) = false;
6,616✔
1974
    }
1975
    goto _end;
6,617✔
1976
  }
1977

1978
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
6,938✔
1979
  TSKEY*           startData = (TSKEY*)pStartTsCol->pData;
6,937✔
1980
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
6,937✔
1981
  TSKEY*           endData = (TSKEY*)pEndTsCol->pData;
6,937✔
1982
  STimeWindow      win = {.skey = startData[*pRowIndex], .ekey = endData[*pRowIndex]};
6,937✔
1983
  SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
6,937✔
1984
  uint64_t*        gpData = (uint64_t*)pGpCol->pData;
6,934✔
1985
  uint64_t         groupId = gpData[*pRowIndex];
6,934✔
1986

1987
  SColumnInfoData* pCalStartTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
6,934✔
1988
  TSKEY*           calStartData = (TSKEY*)pCalStartTsCol->pData;
6,933✔
1989
  SColumnInfoData* pCalEndTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
6,933✔
1990
  TSKEY*           calEndData = (TSKEY*)pCalEndTsCol->pData;
6,933✔
1991

1992
  setGroupId(pInfo, pBlock, GROUPID_COLUMN_INDEX, *pRowIndex);
6,933✔
1993
  if (isSlidingWindow(pInfo) || isCountSlidingWindow(pInfo)) {
6,937✔
1994
    pInfo->updateWin.skey = calStartData[*pRowIndex];
56✔
1995
    pInfo->updateWin.ekey = calEndData[*pRowIndex];
56✔
1996
  }
1997
  (*pRowIndex)++;
6,938✔
1998

1999
  for (; *pRowIndex < pBlock->info.rows; (*pRowIndex)++) {
6,945✔
2000
    if (win.skey == startData[*pRowIndex] && groupId == gpData[*pRowIndex]) {
329✔
2001
      win.ekey = TMAX(win.ekey, endData[*pRowIndex]);
7✔
2002
      continue;
7✔
2003
    }
2004

2005
    if (win.skey == endData[*pRowIndex] && groupId == gpData[*pRowIndex]) {
322!
UNCOV
2006
      win.skey = TMIN(win.skey, startData[*pRowIndex]);
×
UNCOV
2007
      continue;
×
2008
    }
2009
    break;
322✔
2010
  }
2011

2012
  STableScanInfo* pTScanInfo = pInfo->pTableScanOp->info;
6,938✔
2013

2014
  int64_t maxVer = -1;
6,938✔
2015
  if (!isRecalculateOperator(&pInfo->basic)) {
6,938!
2016
    // coverity scan
2017
    QUERY_CHECK_NULL(pInfo->pUpdateInfo, code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
6,938!
2018

2019
    qDebug("prepare range scan start:%" PRId64 ",end:%" PRId64 ",maxVer:%" PRId64, win.skey, win.ekey,
6,938✔
2020
          pInfo->pUpdateInfo->maxDataVersion);
2021
    maxVer = pInfo->pUpdateInfo->maxDataVersion;
6,937✔
2022
  }
2023
  resetTableScanInfo(pInfo->pTableScanOp->info, &win, maxVer);
6,937✔
2024
  pInfo->pTableScanOp->status = OP_OPENED;
6,933✔
2025
  if (pRes) {
6,933✔
2026
    (*pRes) = true;
322✔
2027
  }
2028

2029
_end:
6,611✔
2030
  if (code != TSDB_CODE_SUCCESS) {
13,551!
UNCOV
2031
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2032
  }
2033
}
13,551✔
2034

2035
STimeWindow getSlidingWindow(TSKEY* startTsCol, TSKEY* endTsCol, uint64_t* gpIdCol, SInterval* pInterval,
1,717✔
2036
                             SDataBlockInfo* pDataBlockInfo, int32_t* pRowIndex, bool hasGroup) {
2037
  SResultRowInfo dumyInfo = {0};
1,717✔
2038
  dumyInfo.cur.pageId = -1;
1,717✔
2039
  STimeWindow win = getActiveTimeWindow(NULL, &dumyInfo, startTsCol[*pRowIndex], pInterval, TSDB_ORDER_ASC);
1,717✔
2040
  STimeWindow endWin = win;
1,716✔
2041
  STimeWindow preWin = win;
1,716✔
2042
  uint64_t    groupId = gpIdCol[*pRowIndex];
1,716✔
2043

2044
  while (1) {
2045
    if (hasGroup) {
1,716✔
2046
      (*pRowIndex) += 1;
147✔
2047
    } else {
2048
      while ((groupId == gpIdCol[(*pRowIndex)] && startTsCol[*pRowIndex] <= endWin.ekey)) {
2,599!
2049
        (*pRowIndex) += 1;
2,555✔
2050
        if ((*pRowIndex) == pDataBlockInfo->rows) {
2,555✔
2051
          break;
1,525✔
2052
        }
2053
      }
2054
    }
2055

2056
    do {
2057
      preWin = endWin;
2,554✔
2058
      getNextTimeWindow(pInterval, &endWin, TSDB_ORDER_ASC);
2,554✔
2059
    } while (endTsCol[(*pRowIndex) - 1] >= endWin.skey);
2,554✔
2060
    endWin = preWin;
1,716✔
2061
    if (win.ekey == endWin.ekey || (*pRowIndex) == pDataBlockInfo->rows || groupId != gpIdCol[*pRowIndex]) {
1,716!
2062
      win.ekey = endWin.ekey;
1,716✔
2063
      return win;
1,716✔
2064
    }
UNCOV
2065
    win.ekey = endWin.ekey;
×
2066
  }
2067
}
2068

2069
int32_t doRangeScan(SStreamScanInfo* pInfo, SSDataBlock* pSDB, int32_t tsColIndex, int32_t* pRowIndex,
9,656✔
2070
                    SSDataBlock** ppRes) {
2071
  qDebug("do stream range scan. windows index:%d", *pRowIndex);
9,656✔
2072

2073
  int32_t code = TSDB_CODE_SUCCESS;
9,657✔
2074
  int32_t lino = 0;
9,657✔
2075
  bool    prepareRes = true;
9,657✔
2076

2077
  while (1) {
3,096✔
2078
    SSDataBlock* pResult = NULL;
12,753✔
2079
    code = doTableScanNext(pInfo->pTableScanOp, &pResult);
12,753✔
2080
    QUERY_CHECK_CODE(code, lino, _end);
22,406!
2081

2082
    if (!pResult) {
12,750✔
2083
      prepareRangeScan(pInfo, pSDB, pRowIndex, &prepareRes);
6,937✔
2084
      // scan next window data
2085
      code = doTableScanNext(pInfo->pTableScanOp, &pResult);
6,936✔
2086
      QUERY_CHECK_CODE(code, lino, _end);
6,938!
2087
    }
2088

2089
    if (!pResult) {
12,751✔
2090
      if (prepareRes) {
6,721✔
2091
        continue;
104✔
2092
      }
2093
      blockDataCleanup(pSDB);
6,617✔
2094
      *pRowIndex = 0;
6,612✔
2095
      pInfo->updateWin = (STimeWindow){.skey = INT64_MIN, .ekey = INT64_MAX};
6,612✔
2096
      STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info;
6,612✔
2097
      pTableScanInfo->base.readerAPI.tsdReaderClose(pTableScanInfo->base.dataReader);
6,612✔
2098
      pTableScanInfo->base.dataReader = NULL;
6,617✔
2099
      (*ppRes) = NULL;
6,617✔
2100
      goto _end;
6,617✔
2101
    }
2102

2103
    code = doFilter(pResult, pInfo->pTableScanOp->exprSupp.pFilterInfo, NULL);
6,030✔
2104
    QUERY_CHECK_CODE(code, lino, _end);
6,031!
2105
    if (pResult->info.rows == 0) {
6,031!
UNCOV
2106
      continue;
×
2107
    }
2108

2109
    if (pInfo->igCheckGroupId == true) {
6,031✔
2110
      pResult->info.calWin = pInfo->updateWin;
499✔
2111
      (*ppRes) = pResult;
499✔
2112
      goto _end;
499✔
2113
    }
2114

2115
    if (pInfo->partitionSup.needCalc) {
5,532✔
2116
      SSDataBlock* tmpBlock = NULL;
653✔
2117
      code = createOneDataBlock(pResult, true, &tmpBlock);
653✔
2118
      QUERY_CHECK_CODE(code, lino, _end);
1,105!
2119

2120
      blockDataCleanup(pResult);
653✔
2121
      for (int32_t i = 0; i < tmpBlock->info.rows; i++) {
2,095✔
2122
        if (calGroupIdByData(&pInfo->partitionSup, pInfo->pPartScalarSup, tmpBlock, i) == pInfo->groupId) {
1,442✔
2123
          for (int32_t j = 0; j < pInfo->pTableScanOp->exprSupp.numOfExprs; j++) {
10,343✔
2124
            SColumnInfoData* pSrcCol = taosArrayGet(tmpBlock->pDataBlock, j);
9,580✔
2125
            SColumnInfoData* pDestCol = taosArrayGet(pResult->pDataBlock, j);
9,580✔
2126
            bool             isNull = colDataIsNull(pSrcCol, tmpBlock->info.rows, i, NULL);
9,580✔
2127
            char*            pSrcData = NULL;
9,580✔
2128
            if (!isNull) pSrcData = colDataGetData(pSrcCol, i);
9,580!
2129
            code = colDataSetVal(pDestCol, pResult->info.rows, pSrcData, isNull);
9,580✔
2130
            QUERY_CHECK_CODE(code, lino, _end);
9,580!
2131
          }
2132
          pResult->info.rows++;
763✔
2133
        }
2134
      }
2135

2136
      blockDataDestroy(tmpBlock);
653✔
2137

2138
      if (pResult->info.rows > 0) {
653✔
2139
        pResult->info.calWin = pInfo->updateWin;
452✔
2140
        (*ppRes) = pResult;
452✔
2141
        goto _end;
452✔
2142
      }
2143
    } else if (pResult->info.id.groupId == pInfo->groupId) {
4,879✔
2144
      pResult->info.calWin = pInfo->updateWin;
2,088✔
2145
      (*ppRes) = pResult;
2,088✔
2146
      goto _end;
2,088✔
2147
    }
2148
  }
2149

2150
_end:
9,656✔
2151
  if (code != TSDB_CODE_SUCCESS) {
9,656!
UNCOV
2152
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2153
  }
2154
  return code;
9,657✔
2155
}
2156

2157
static void getPreSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
2✔
2158
                                SSessionKey* pKey) {
2159
  pKey->win.skey = startTs;
2✔
2160
  pKey->win.ekey = endTs;
2✔
2161
  pKey->groupId = groupId;
2✔
2162

2163
  void*   pCur = pAggSup->stateStore.streamStateSessionSeekKeyCurrentPrev(pAggSup->pState, pKey);
2✔
2164
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, pKey, NULL, 0);
2✔
2165
  if (code != TSDB_CODE_SUCCESS) {
2!
UNCOV
2166
    SET_SESSION_WIN_KEY_INVALID(pKey);
×
2167
  }
2168

2169
  taosMemoryFree(pCur);
2!
2170
}
2✔
2171

2172
int32_t appendOneRowToSpecialBlockImpl(SSDataBlock* pBlock, TSKEY* pStartTs, TSKEY* pEndTs, TSKEY* pCalStartTs,
7,757✔
2173
                                       TSKEY* pCalEndTs, uint64_t* pUid, uint64_t* pGp, void* pTbName, void* pPkData) {
2174
  int32_t          code = TSDB_CODE_SUCCESS;
7,757✔
2175
  int32_t          lino = 0;
7,757✔
2176
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
7,757✔
2177
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
7,756✔
2178
  SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
7,753✔
2179
  SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
7,754✔
2180
  SColumnInfoData* pCalStartCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
7,755✔
2181
  SColumnInfoData* pCalEndCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
7,753✔
2182
  SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
7,753✔
2183
  code = colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)pStartTs, false);
7,753✔
2184
  QUERY_CHECK_CODE(code, lino, _end);
7,756!
2185

2186
  code = colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)pEndTs, false);
7,756✔
2187
  QUERY_CHECK_CODE(code, lino, _end);
7,759!
2188

2189
  code = colDataSetVal(pUidCol, pBlock->info.rows, (const char*)pUid, pUid == NULL);
7,759✔
2190
  QUERY_CHECK_CODE(code, lino, _end);
7,759!
2191

2192
  code = colDataSetVal(pGpCol, pBlock->info.rows, (const char*)pGp, pGp == NULL);
7,759✔
2193
  QUERY_CHECK_CODE(code, lino, _end);
7,757!
2194

2195
  code = colDataSetVal(pCalStartCol, pBlock->info.rows, (const char*)pCalStartTs, false);
7,757✔
2196
  QUERY_CHECK_CODE(code, lino, _end);
7,758!
2197

2198
  code = colDataSetVal(pCalEndCol, pBlock->info.rows, (const char*)pCalEndTs, false);
7,758✔
2199
  QUERY_CHECK_CODE(code, lino, _end);
7,757!
2200

2201
  code = colDataSetVal(pTableCol, pBlock->info.rows, (const char*)pTbName, pTbName == NULL);
7,757✔
2202
  QUERY_CHECK_CODE(code, lino, _end);
7,760!
2203

2204
  if (taosArrayGetSize(pBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
7,760✔
2205
    SColumnInfoData* pPkCol = taosArrayGet(pBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
1,003✔
2206
    code = colDataSetVal(pPkCol, pBlock->info.rows, (const char*)pPkData, pPkData == NULL);
1,003✔
2207
    QUERY_CHECK_CODE(code, lino, _end);
1,004!
2208
  }
2209
  pBlock->info.rows++;
7,760✔
2210

2211
_end:
7,760✔
2212
  if (code != TSDB_CODE_SUCCESS) {
7,760!
UNCOV
2213
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2214
  }
2215
  return code;
7,760✔
2216
}
2217

2218
int32_t appendPkToSpecialBlock(SSDataBlock* pBlock, TSKEY* pTsArray, SColumnInfoData* pPkCol, int32_t rowId,
2,704✔
2219
                               uint64_t* pUid, uint64_t* pGp, void* pTbName) {
2220
  void* pVal = NULL;
2,704✔
2221
  if (pPkCol) {
2,704✔
2222
    pVal = colDataGetData(pPkCol, rowId);
1,009!
2223
  }
2224
  return appendOneRowToSpecialBlockImpl(pBlock, pTsArray + rowId, pTsArray + rowId, pTsArray + rowId, pTsArray + rowId,
2,704✔
2225
                                        pUid, pGp, pTbName, pVal);
2226
}
2227

2228
static int32_t getPreVersionDataBlock(uint64_t uid, TSKEY startTs, TSKEY endTs, int64_t version, char* taskIdStr,
7✔
2229
                                      SStreamScanInfo* pInfo, SSDataBlock* pBlock) {
2230
  int32_t      code = TSDB_CODE_SUCCESS;
7✔
2231
  int32_t      lino = 0;
7✔
2232
  SSDataBlock* pPreRes = readPreVersionData(pInfo->pTableScanOp, uid, startTs, endTs, version);
7✔
2233
  printDataBlock(pPreRes, "pre res", taskIdStr);
7✔
2234
  blockDataCleanup(pBlock);
7✔
2235
  if (!pPreRes) {
7!
UNCOV
2236
    if (terrno != TSDB_CODE_SUCCESS) {
×
UNCOV
2237
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
2238
    }
UNCOV
2239
    goto _end;
×
2240
  }
2241
  code = blockDataEnsureCapacity(pBlock, pPreRes->info.rows);
7✔
2242
  QUERY_CHECK_CODE(code, lino, _end);
7!
2243

2244
  SColumnInfoData* pTsCol = (SColumnInfoData*)taosArrayGet(pPreRes->pDataBlock, pInfo->primaryTsIndex);
7✔
2245
  SColumnInfoData* pPkCol = NULL;
7✔
2246
  if (hasPrimaryKeyCol(pInfo)) {
7✔
2247
    pPkCol = (SColumnInfoData*)taosArrayGet(pPreRes->pDataBlock, pInfo->primaryKeyIndex);
2✔
2248
  }
2249
  for (int32_t i = 0; i < pPreRes->info.rows; i++) {
28✔
2250
    uint64_t groupId = calGroupIdByData(&pInfo->partitionSup, pInfo->pPartScalarSup, pPreRes, i);
21✔
2251
    code = appendPkToSpecialBlock(pBlock, (TSKEY*)pTsCol->pData, pPkCol, i, &uid, &groupId, NULL);
21✔
2252
    QUERY_CHECK_CODE(code, lino, _end);
21!
2253
  }
2254
  printDataBlock(pBlock, "new delete", taskIdStr);
7✔
2255

2256
_end:
7✔
2257
  if (code != TSDB_CODE_SUCCESS) {
7!
UNCOV
2258
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2259
  }
2260
  return code;
7✔
2261
}
2262

2263
static int32_t generateSessionScanRange(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, SSDataBlock* pDestBlock,
1,038✔
2264
                                        EStreamType mode) {
2265
  int32_t code = TSDB_CODE_SUCCESS;
1,038✔
2266
  int32_t lino = 0;
1,038✔
2267
  if (pSrcBlock->info.rows == 0) {
1,038!
UNCOV
2268
    return TSDB_CODE_SUCCESS;
×
2269
  }
2270
  SSHashObj*       pScanRange = tSimpleHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT));
1,038✔
2271
  SExecTaskInfo*   pTaskInfo = pInfo->pStreamScanOp->pTaskInfo;
1,039✔
2272
  SColumnInfoData* pStartTsCol = taosArrayGet(pSrcBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,039✔
2273
  TSKEY*           startData = (TSKEY*)pStartTsCol->pData;
1,039✔
2274
  SColumnInfoData* pEndTsCol = taosArrayGet(pSrcBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,039✔
2275
  TSKEY*           endData = (TSKEY*)pEndTsCol->pData;
1,039✔
2276
  SColumnInfoData* pUidCol = taosArrayGet(pSrcBlock->pDataBlock, UID_COLUMN_INDEX);
1,039✔
2277
  uint64_t*        uidCol = (uint64_t*)pUidCol->pData;
1,039✔
2278
  SColumnInfoData* pGpCol = taosArrayGet(pSrcBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,039✔
2279
  SColumnInfoData* pSrcPkCol = NULL;
1,039✔
2280
  uint64_t*        pSrcGp = (uint64_t*)pGpCol->pData;
1,039✔
2281
  if (taosArrayGetSize(pSrcBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
1,039✔
2282
    pSrcPkCol = taosArrayGet(pSrcBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
1✔
2283
  }
2284
  int64_t ver = pSrcBlock->info.version - 1;
1,039✔
2285

2286
  if (pInfo->partitionSup.needCalc &&
1,039✔
2287
      (startData[0] != endData[0] || (hasPrimaryKeyCol(pInfo) && mode == STREAM_DELETE_DATA))) {
498✔
2288
    code = getPreVersionDataBlock(uidCol[0], startData[0], endData[0], ver, GET_TASKID(pTaskInfo), pInfo, pSrcBlock);
4✔
2289
    QUERY_CHECK_CODE(code, lino, _end);
4!
2290
    startData = (TSKEY*)pStartTsCol->pData;
4✔
2291
    endData = (TSKEY*)pEndTsCol->pData;
4✔
2292
    uidCol = (uint64_t*)pUidCol->pData;
4✔
2293
    pSrcGp = (uint64_t*)pGpCol->pData;
4✔
2294
  }
2295
  blockDataCleanup(pDestBlock);
1,039✔
2296
  code = blockDataEnsureCapacity(pDestBlock, pSrcBlock->info.rows);
1,039✔
2297
  QUERY_CHECK_CODE(code, lino, _end);
1,039!
2298

2299
  SColumnInfoData* pDestStartCol = taosArrayGet(pDestBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,039✔
2300
  SColumnInfoData* pDestEndCol = taosArrayGet(pDestBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,039✔
2301
  SColumnInfoData* pDestUidCol = taosArrayGet(pDestBlock->pDataBlock, UID_COLUMN_INDEX);
1,039✔
2302
  SColumnInfoData* pDestGpCol = taosArrayGet(pDestBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,037✔
2303
  SColumnInfoData* pDestCalStartTsCol = taosArrayGet(pDestBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
1,038✔
2304
  SColumnInfoData* pDestCalEndTsCol = taosArrayGet(pDestBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
1,039✔
2305
  SColumnInfoData* pDestTableNameInxCol = taosArrayGet(pDestBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
1,038✔
2306
  for (int32_t i = 0; i < pSrcBlock->info.rows; i++) {
2,122✔
2307
    uint64_t groupId = pSrcGp[i];
1,083✔
2308
    if (groupId == 0) {
1,083✔
2309
      void* pVal = NULL;
907✔
2310
      if (hasPrimaryKeyCol(pInfo) && pSrcPkCol) {
907!
2311
        pVal = colDataGetData(pSrcPkCol, i);
1!
2312
      }
2313
      groupId = getGroupIdByData(pInfo, uidCol[i], startData[i], ver, pVal);
908✔
2314
    }
2315
    // gap must be 0.
2316
    SSessionKey startWin = {0};
1,086✔
2317
    getCurSessionWindow(pInfo->windowSup.pStreamAggSup, startData[i], startData[i], groupId, &startWin);
1,086✔
2318
    if (IS_INVALID_SESSION_WIN_KEY(startWin)) {
1,086✔
2319
      // window has been closed.
2320
      continue;
82✔
2321
    }
2322
    SSessionKey endWin = {0};
1,009✔
2323
    getCurSessionWindow(pInfo->windowSup.pStreamAggSup, endData[i], endData[i], groupId, &endWin);
1,009✔
2324
    if (IS_INVALID_SESSION_WIN_KEY(endWin)) {
1,009✔
2325
      getPreSessionWindow(pInfo->windowSup.pStreamAggSup, endData[i], endData[i], groupId, &endWin);
2✔
2326
    }
2327
    if (IS_INVALID_SESSION_WIN_KEY(startWin)) {
1,009!
2328
      // window has been closed.
UNCOV
2329
      qError("generate session scan range failed. rang start:%" PRIx64 ", end:%" PRIx64, startData[i], endData[i]);
×
UNCOV
2330
      continue;
×
2331
    }
2332

2333
    SSessionKey checkKey = {.groupId = groupId, .win.skey = startWin.win.skey, .win.ekey = endWin.win.ekey};
1,009✔
2334
    if (tSimpleHashGet(pScanRange, &checkKey, sizeof(SSessionKey)) != NULL) {
1,009✔
2335
      continue;
5✔
2336
    }
2337
    code = tSimpleHashPut(pScanRange, &checkKey, sizeof(SSessionKey), NULL, 0);
1,004✔
2338
    QUERY_CHECK_CODE(code, lino, _end);
1,004!
2339

2340
    code = colDataSetVal(pDestStartCol, i, (const char*)&startWin.win.skey, false);
1,004✔
2341
    QUERY_CHECK_CODE(code, lino, _end);
1,004!
2342

2343
    code = colDataSetVal(pDestEndCol, i, (const char*)&endWin.win.ekey, false);
1,004✔
2344
    QUERY_CHECK_CODE(code, lino, _end);
1,004!
2345

2346
    colDataSetNULL(pDestUidCol, i);
1,004!
2347
    code = colDataSetVal(pDestGpCol, i, (const char*)&groupId, false);
1,004✔
2348
    QUERY_CHECK_CODE(code, lino, _end);
1,003!
2349

2350
    colDataSetNULL(pDestCalStartTsCol, i);
1,003!
2351
    colDataSetNULL(pDestTableNameInxCol, i);
1,003!
2352
    pDestBlock->info.rows++;
1,003✔
2353
  }
2354

2355
_end:
1,039✔
2356
  tSimpleHashCleanup(pScanRange);
1,039✔
2357
  if (code != TSDB_CODE_SUCCESS) {
1,039!
UNCOV
2358
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2359
  }
2360
  return code;
1,039✔
2361
}
2362

2363
static int32_t generateCountScanRange(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, SSDataBlock* pDestBlock,
69✔
2364
                                      EStreamType mode) {
2365
  int32_t code = TSDB_CODE_SUCCESS;
69✔
2366
  int32_t lino = 0;
69✔
2367
  blockDataCleanup(pDestBlock);
69✔
2368
  if (pSrcBlock->info.rows == 0) {
69!
UNCOV
2369
    return TSDB_CODE_SUCCESS;
×
2370
  }
2371
  SExecTaskInfo*   pTaskInfo = pInfo->pStreamScanOp->pTaskInfo;
69✔
2372
  SColumnInfoData* pStartTsCol = taosArrayGet(pSrcBlock->pDataBlock, START_TS_COLUMN_INDEX);
69✔
2373
  TSKEY*           startData = (TSKEY*)pStartTsCol->pData;
69✔
2374
  SColumnInfoData* pEndTsCol = taosArrayGet(pSrcBlock->pDataBlock, END_TS_COLUMN_INDEX);
69✔
2375
  TSKEY*           endData = (TSKEY*)pEndTsCol->pData;
69✔
2376
  SColumnInfoData* pUidCol = taosArrayGet(pSrcBlock->pDataBlock, UID_COLUMN_INDEX);
69✔
2377
  uint64_t*        uidCol = (uint64_t*)pUidCol->pData;
69✔
2378
  SColumnInfoData* pGpCol = taosArrayGet(pSrcBlock->pDataBlock, GROUPID_COLUMN_INDEX);
69✔
2379
  uint64_t*        pSrcGp = (uint64_t*)pGpCol->pData;
69✔
2380
  SColumnInfoData* pSrcPkCol = NULL;
69✔
2381
  if (taosArrayGetSize(pSrcBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
69!
2382
    pSrcPkCol = taosArrayGet(pSrcBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
×
2383
  }
2384
  int64_t ver = pSrcBlock->info.version - 1;
69✔
2385

2386
  if (pInfo->partitionSup.needCalc &&
69✔
2387
      (startData[0] != endData[0] || (hasPrimaryKeyCol(pInfo) && mode == STREAM_DELETE_DATA))) {
16!
2388
    code = getPreVersionDataBlock(uidCol[0], startData[0], endData[0], ver, GET_TASKID(pTaskInfo), pInfo, pSrcBlock);
1✔
2389
    QUERY_CHECK_CODE(code, lino, _end);
1!
2390
    startData = (TSKEY*)pStartTsCol->pData;
1✔
2391
    endData = (TSKEY*)pEndTsCol->pData;
1✔
2392
    uidCol = (uint64_t*)pUidCol->pData;
1✔
2393
    pSrcGp = (uint64_t*)pGpCol->pData;
1✔
2394
  }
2395

2396
  code = blockDataEnsureCapacity(pDestBlock, pSrcBlock->info.rows);
69✔
2397
  QUERY_CHECK_CODE(code, lino, _end);
69!
2398

2399
  SColumnInfoData* pDestStartCol = taosArrayGet(pDestBlock->pDataBlock, START_TS_COLUMN_INDEX);
69✔
2400
  SColumnInfoData* pDestEndCol = taosArrayGet(pDestBlock->pDataBlock, END_TS_COLUMN_INDEX);
69✔
2401
  SColumnInfoData* pDestUidCol = taosArrayGet(pDestBlock->pDataBlock, UID_COLUMN_INDEX);
69✔
2402
  SColumnInfoData* pDestGpCol = taosArrayGet(pDestBlock->pDataBlock, GROUPID_COLUMN_INDEX);
69✔
2403
  SColumnInfoData* pDestCalStartTsCol = taosArrayGet(pDestBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
69✔
2404
  SColumnInfoData* pDestCalEndTsCol = taosArrayGet(pDestBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
69✔
2405
  SColumnInfoData* pDestTableNameInxCol = taosArrayGet(pDestBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
69✔
2406
  for (int32_t i = 0; i < pSrcBlock->info.rows; i++) {
140✔
2407
    uint64_t groupId = pSrcGp[i];
71✔
2408
    if (groupId == 0) {
71✔
2409
      void* pVal = NULL;
56✔
2410
      if (hasPrimaryKeyCol(pInfo) && pSrcPkCol) {
56!
UNCOV
2411
        pVal = colDataGetData(pSrcPkCol, i);
×
2412
      }
2413
      groupId = getGroupIdByData(pInfo, uidCol[i], startData[i], ver, pVal);
56✔
2414
    }
2415
    SSessionKey startWin = {.win.skey = startData[i], .win.ekey = endData[i], .groupId = groupId};
71✔
2416
    SSessionKey range = {0};
71✔
2417
    getCountWinRange(pInfo->windowSup.pStreamAggSup, &startWin, mode, &range);
71✔
2418
    code = colDataSetVal(pDestStartCol, i, (const char*)&range.win.skey, false);
71✔
2419
    QUERY_CHECK_CODE(code, lino, _end);
71!
2420

2421
    code = colDataSetVal(pDestEndCol, i, (const char*)&range.win.ekey, false);
71✔
2422
    QUERY_CHECK_CODE(code, lino, _end);
71!
2423

2424
    colDataSetNULL(pDestUidCol, i);
71!
2425
    code = colDataSetVal(pDestGpCol, i, (const char*)&groupId, false);
71✔
2426
    QUERY_CHECK_CODE(code, lino, _end);
71!
2427

2428
    code = colDataSetVal(pDestCalStartTsCol, i, (const char*)&range.win.skey, false);
71✔
2429
    QUERY_CHECK_CODE(code, lino, _end);
71!
2430

2431
    code = colDataSetVal(pDestCalEndTsCol, i, (const char*)&range.win.ekey, false);
71✔
2432
    QUERY_CHECK_CODE(code, lino, _end);
71!
2433

2434
    colDataSetNULL(pDestTableNameInxCol, i);
71!
2435

2436
    pDestBlock->info.rows++;
71✔
2437
  }
2438

2439
_end:
69✔
2440
  if (code != TSDB_CODE_SUCCESS) {
69!
UNCOV
2441
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2442
  }
2443
  return code;
69✔
2444
}
2445

2446
static int32_t setDelRangeEndKey(SStreamAggSupporter* pAggSup, SStreamFillSupporter* pFillSup, SWinKey* pEndKey, STimeWindow* pScanRange, bool* pRes) {
24✔
2447
  int32_t     code = TSDB_CODE_SUCCESS;
24✔
2448
  int32_t     lino = 0;
24✔
2449
  SSlicePoint nextPoint = {.key.groupId = pEndKey->groupId};
24✔
2450
  int32_t     vLen = 0;
24✔
2451
  int32_t     winCode = TSDB_CODE_SUCCESS;
24✔
2452
  code = pAggSup->stateStore.streamStateFillGetNext(pAggSup->pState, pEndKey, &nextPoint.key, (void**)&nextPoint.pResPos, &vLen, &winCode);
24✔
2453
  QUERY_CHECK_CODE(code, lino, _end);
24!
2454
  if (winCode == TSDB_CODE_SUCCESS) {
24✔
2455
    setPointBuff(&nextPoint, pFillSup);
16✔
2456
    if (HAS_ROW_DATA(nextPoint.pLeftRow) && pEndKey->ts < nextPoint.pLeftRow->key) {
16!
2457
      pScanRange->ekey = nextPoint.pLeftRow->key;
8✔
2458
      *pRes = true;
8✔
2459
    } else if (pEndKey->ts < nextPoint.pRightRow->key) {
8✔
2460
      pScanRange->ekey = nextPoint.pRightRow->key;
2✔
2461
      *pRes = true;
2✔
2462
    } else {
2463
      *pEndKey = nextPoint.key;
6✔
2464
      pScanRange->ekey = TMAX(nextPoint.pRightRow->key, nextPoint.key.ts);
6✔
2465
      *pRes = false;
6✔
2466
    }
2467
  }
2468

2469
_end:
8✔
2470
  if (code != TSDB_CODE_SUCCESS) {
24!
UNCOV
2471
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2472
  }
2473
  return code;
24✔
2474
}
2475

2476
int32_t getTimeSliceWinRange(SStreamAggSupporter* pAggSup, SStreamFillSupporter* pFillSup, SInterval* pInterval, TSKEY start, TSKEY end,
15✔
2477
                             int64_t groupId, STimeWindow* pScanRange) {
2478
  int32_t        code = TSDB_CODE_SUCCESS;
15✔
2479
  int32_t        lino = 0;
15✔
2480
  int32_t        winCode = TSDB_CODE_SUCCESS;
15✔
2481
  SResultRowInfo dumyInfo = {0};
15✔
2482
  dumyInfo.cur.pageId = -1;
15✔
2483
  STimeWindow sWin = getActiveTimeWindow(NULL, &dumyInfo, start, pInterval, TSDB_ORDER_ASC);
15✔
2484
  SWinKey     startKey = {.groupId = groupId, .ts = sWin.skey};
15✔
2485

2486
  sWin = getActiveTimeWindow(NULL, &dumyInfo, end, pInterval, TSDB_ORDER_ASC);
15✔
2487
  SWinKey endKey = {.groupId = groupId, .ts = sWin.ekey};
15✔
2488

2489
  SSlicePoint prevPoint = {.key.groupId = groupId};
15✔
2490
  SSlicePoint nextPoint = {.key.groupId = groupId};
15✔
2491
  int32_t     vLen = 0;
15✔
2492
  code = pAggSup->stateStore.streamStateFillGetPrev(pAggSup->pState, &startKey, &prevPoint.key, (void**)&prevPoint.pResPos, &vLen, &winCode);
15✔
2493
  QUERY_CHECK_CODE(code, lino, _end);
15!
2494
  if (winCode == TSDB_CODE_SUCCESS) {
15✔
2495
    setPointBuff(&prevPoint, pFillSup);
10✔
2496
    if (HAS_ROW_DATA(prevPoint.pRightRow)) {
10!
2497
      pScanRange->skey = prevPoint.pRightRow->key;
9✔
2498
    } else {
2499
      pScanRange->skey = prevPoint.pLeftRow->key;
1✔
2500
    }
2501
  } else {
2502
    pScanRange->skey = startKey.ts;
5✔
2503
  }
2504

2505
  bool res = false;
15✔
2506
  SWinKey curKey = endKey;
15✔
2507
  code = setDelRangeEndKey(pAggSup, pFillSup, &curKey, pScanRange, &res);
15✔
2508
  QUERY_CHECK_CODE(code, lino, _end);
15!
2509
  if (res == false) {
15✔
2510
    code = setDelRangeEndKey(pAggSup, pFillSup, &curKey, pScanRange, &res);
9✔
2511
    QUERY_CHECK_CODE(code, lino, _end);
9!
2512
  }
2513
  if (res == false) {
15✔
2514
    pScanRange->ekey = TMAX(endKey.ts, pScanRange->ekey);
5✔
2515
  }
2516

2517
_end:
10✔
2518
  if (code != TSDB_CODE_SUCCESS) {
15!
UNCOV
2519
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2520
  }
2521
  return code;
15✔
2522
}
2523

2524
static int32_t generateTimeSliceScanRange(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, SSDataBlock* pDestBlock,
15✔
2525
                                          EStreamType mode) {
2526
  int32_t code = TSDB_CODE_SUCCESS;
15✔
2527
  int32_t lino = 0;
15✔
2528
  blockDataCleanup(pDestBlock);
15✔
2529
  if (pSrcBlock->info.rows == 0) {
15!
2530
    return TSDB_CODE_SUCCESS;
×
2531
  }
2532
  SExecTaskInfo*   pTaskInfo = pInfo->pStreamScanOp->pTaskInfo;
15✔
2533
  SColumnInfoData* pStartTsCol = taosArrayGet(pSrcBlock->pDataBlock, START_TS_COLUMN_INDEX);
15✔
2534
  TSKEY*           startData = (TSKEY*)pStartTsCol->pData;
15✔
2535
  SColumnInfoData* pEndTsCol = taosArrayGet(pSrcBlock->pDataBlock, END_TS_COLUMN_INDEX);
15✔
2536
  TSKEY*           endData = (TSKEY*)pEndTsCol->pData;
15✔
2537
  SColumnInfoData* pUidCol = taosArrayGet(pSrcBlock->pDataBlock, UID_COLUMN_INDEX);
15✔
2538
  uint64_t*        uidCol = (uint64_t*)pUidCol->pData;
15✔
2539
  SColumnInfoData* pGpCol = taosArrayGet(pSrcBlock->pDataBlock, GROUPID_COLUMN_INDEX);
15✔
2540
  uint64_t*        pSrcGp = (uint64_t*)pGpCol->pData;
15✔
2541
  SColumnInfoData* pSrcPkCol = NULL;
15✔
2542
  if (taosArrayGetSize(pSrcBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
15!
UNCOV
2543
    pSrcPkCol = taosArrayGet(pSrcBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
×
2544
  }
2545
  int64_t ver = pSrcBlock->info.version - 1;
15✔
2546

2547
  if (pInfo->partitionSup.needCalc &&
15!
UNCOV
2548
      (startData[0] != endData[0] || (hasPrimaryKeyCol(pInfo) && mode == STREAM_DELETE_DATA))) {
×
UNCOV
2549
    code = getPreVersionDataBlock(uidCol[0], startData[0], endData[0], ver, GET_TASKID(pTaskInfo), pInfo, pSrcBlock);
×
2550
    QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
2551
    startData = (TSKEY*)pStartTsCol->pData;
×
UNCOV
2552
    endData = (TSKEY*)pEndTsCol->pData;
×
UNCOV
2553
    uidCol = (uint64_t*)pUidCol->pData;
×
UNCOV
2554
    pSrcGp = (uint64_t*)pGpCol->pData;
×
2555
  }
2556

2557
  code = blockDataEnsureCapacity(pDestBlock, pSrcBlock->info.rows);
15✔
2558
  QUERY_CHECK_CODE(code, lino, _end);
15!
2559

2560
  SColumnInfoData* pDestStartCol = taosArrayGet(pDestBlock->pDataBlock, START_TS_COLUMN_INDEX);
15✔
2561
  SColumnInfoData* pDestEndCol = taosArrayGet(pDestBlock->pDataBlock, END_TS_COLUMN_INDEX);
15✔
2562
  SColumnInfoData* pDestUidCol = taosArrayGet(pDestBlock->pDataBlock, UID_COLUMN_INDEX);
15✔
2563
  SColumnInfoData* pDestGpCol = taosArrayGet(pDestBlock->pDataBlock, GROUPID_COLUMN_INDEX);
15✔
2564
  SColumnInfoData* pDestCalStartTsCol = taosArrayGet(pDestBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
15✔
2565
  SColumnInfoData* pDestCalEndTsCol = taosArrayGet(pDestBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
15✔
2566
  for (int32_t i = 0; i < pSrcBlock->info.rows; i++) {
30✔
2567
    uint64_t groupId = pSrcGp[i];
15✔
2568
    if (groupId == 0) {
15!
2569
      void* pVal = NULL;
15✔
2570
      if (hasPrimaryKeyCol(pInfo) && pSrcPkCol) {
15!
UNCOV
2571
        pVal = colDataGetData(pSrcPkCol, i);
×
2572
      }
2573
      groupId = getGroupIdByData(pInfo, uidCol[i], startData[i], ver, pVal);
15✔
2574
    }
2575

2576
    STimeWindow scanRange = {0};
15✔
2577
    code = getTimeSliceWinRange(pInfo->windowSup.pStreamAggSup, pInfo->pFillSup, &pInfo->interval, startData[i], endData[i], groupId,
15✔
2578
                                &scanRange);
2579
    QUERY_CHECK_CODE(code, lino, _end);
15!
2580

2581
    code = colDataSetVal(pDestStartCol, i, (const char*)&scanRange.skey, false);
15✔
2582
    QUERY_CHECK_CODE(code, lino, _end);
15!
2583

2584
    code = colDataSetVal(pDestEndCol, i, (const char*)&scanRange.ekey, false);
15✔
2585
    QUERY_CHECK_CODE(code, lino, _end);
15!
2586

2587
    colDataSetNULL(pDestUidCol, i);
15!
2588
    code = colDataSetVal(pDestGpCol, i, (const char*)&groupId, false);
15✔
2589
    QUERY_CHECK_CODE(code, lino, _end);
15!
2590

2591
    code = colDataSetVal(pDestCalStartTsCol, i, (const char*)&scanRange.skey, false);
15✔
2592
    QUERY_CHECK_CODE(code, lino, _end);
15!
2593

2594
    code = colDataSetVal(pDestCalEndTsCol, i, (const char*)&scanRange.ekey, false);
15✔
2595
    QUERY_CHECK_CODE(code, lino, _end);
15!
2596

2597
    pDestBlock->info.rows++;
15✔
2598
  }
2599

2600
_end:
15✔
2601
  if (code != TSDB_CODE_SUCCESS) {
15!
UNCOV
2602
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2603
  }
2604
  return code;
15✔
2605
}
2606

2607
static int32_t generateIntervalScanRange(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, SSDataBlock* pDestBlock,
1,652✔
2608
                                         EStreamType mode) {
2609
  int32_t code = TSDB_CODE_SUCCESS;
1,652✔
2610
  int32_t lino = 0;
1,652✔
2611
  blockDataCleanup(pDestBlock);
1,652✔
2612
  if (pSrcBlock->info.rows == 0) {
1,653!
UNCOV
2613
    return TSDB_CODE_SUCCESS;
×
2614
  }
2615
  SSHashObj*       pScanRange = tSimpleHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT));
1,653✔
2616
  SExecTaskInfo*   pTaskInfo = pInfo->pStreamScanOp->pTaskInfo;
1,656✔
2617
  SColumnInfoData* pSrcStartTsCol = (SColumnInfoData*)taosArrayGet(pSrcBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,656✔
2618
  SColumnInfoData* pSrcEndTsCol = (SColumnInfoData*)taosArrayGet(pSrcBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,656✔
2619
  SColumnInfoData* pSrcUidCol = taosArrayGet(pSrcBlock->pDataBlock, UID_COLUMN_INDEX);
1,656✔
2620
  SColumnInfoData* pSrcGpCol = taosArrayGet(pSrcBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,656✔
2621
  SColumnInfoData* pSrcPkCol = NULL;
1,655✔
2622
  if (taosArrayGetSize(pSrcBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
1,655✔
2623
    pSrcPkCol = taosArrayGet(pSrcBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
11✔
2624
  }
2625

2626
  uint64_t* srcUidData = (uint64_t*)pSrcUidCol->pData;
1,656✔
2627
  TSKEY*    srcStartTsCol = (TSKEY*)pSrcStartTsCol->pData;
1,656✔
2628
  TSKEY*    srcEndTsCol = (TSKEY*)pSrcEndTsCol->pData;
1,656✔
2629
  int64_t   ver = pSrcBlock->info.version - 1;
1,656✔
2630

2631
  if (pInfo->partitionSup.needCalc &&
1,656✔
2632
      (srcStartTsCol[0] != srcEndTsCol[0] || (hasPrimaryKeyCol(pInfo) && mode == STREAM_DELETE_DATA))) {
129✔
2633
    code = getPreVersionDataBlock(srcUidData[0], srcStartTsCol[0], srcEndTsCol[0], ver, GET_TASKID(pTaskInfo), pInfo,
2✔
2634
                                  pSrcBlock);
2635
    QUERY_CHECK_CODE(code, lino, _end);
2!
2636

2637
    srcStartTsCol = (TSKEY*)pSrcStartTsCol->pData;
2✔
2638
    srcEndTsCol = (TSKEY*)pSrcEndTsCol->pData;
2✔
2639
    srcUidData = (uint64_t*)pSrcUidCol->pData;
2✔
2640
  }
2641

2642
  uint64_t* srcGp = (uint64_t*)pSrcGpCol->pData;
1,656✔
2643
  code = blockDataEnsureCapacity(pDestBlock, pSrcBlock->info.rows);
1,656✔
2644
  QUERY_CHECK_CODE(code, lino, _end);
1,654!
2645

2646
  SColumnInfoData* pStartTsCol = taosArrayGet(pDestBlock->pDataBlock, START_TS_COLUMN_INDEX);
1,654✔
2647
  SColumnInfoData* pEndTsCol = taosArrayGet(pDestBlock->pDataBlock, END_TS_COLUMN_INDEX);
1,653✔
2648
  SColumnInfoData* pDeUidCol = taosArrayGet(pDestBlock->pDataBlock, UID_COLUMN_INDEX);
1,652✔
2649
  SColumnInfoData* pGpCol = taosArrayGet(pDestBlock->pDataBlock, GROUPID_COLUMN_INDEX);
1,652✔
2650
  SColumnInfoData* pCalStartTsCol = taosArrayGet(pDestBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
1,652✔
2651
  SColumnInfoData* pCalEndTsCol = taosArrayGet(pDestBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
1,652✔
2652
  SColumnInfoData* pDestTableNameInxCol = taosArrayGet(pDestBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
1,651✔
2653
  for (int32_t i = 0; i < pSrcBlock->info.rows;) {
3,368✔
2654
    uint64_t srcUid = srcUidData[i];
1,714✔
2655
    uint64_t groupId = srcGp[i];
1,714✔
2656
    if (groupId == 0) {
1,714✔
2657
      void* pVal = NULL;
1,299✔
2658
      if (hasPrimaryKeyCol(pInfo) && pSrcPkCol) {
1,299!
2659
        pVal = colDataGetData(pSrcPkCol, i);
21!
2660
      }
2661
      groupId = getGroupIdByData(pInfo, srcUid, srcStartTsCol[i], ver, pVal);
1,299✔
2662
    }
2663
    TSKEY calStartTs = srcStartTsCol[i];
1,718✔
2664
    code = colDataSetVal(pCalStartTsCol, pDestBlock->info.rows, (const char*)(&calStartTs), false);
1,718✔
2665
    QUERY_CHECK_CODE(code, lino, _end);
1,717!
2666

2667
    STimeWindow win = getSlidingWindow(srcStartTsCol, srcEndTsCol, srcGp, &pInfo->interval, &pSrcBlock->info, &i,
1,717✔
2668
                                       pInfo->partitionSup.needCalc);
1,717✔
2669
    TSKEY       calEndTs = srcStartTsCol[i - 1];
1,716✔
2670
    code = colDataSetVal(pCalEndTsCol, pDestBlock->info.rows, (const char*)(&calEndTs), false);
1,716✔
2671
    QUERY_CHECK_CODE(code, lino, _end);
1,715!
2672

2673
    code = colDataSetVal(pDeUidCol, pDestBlock->info.rows, (const char*)(&srcUid), false);
1,715✔
2674
    QUERY_CHECK_CODE(code, lino, _end);
1,717!
2675

2676
    SSessionKey checkKey = {.groupId = groupId, .win = win};
1,717✔
2677
    if (tSimpleHashGet(pScanRange, &checkKey, sizeof(SSessionKey)) != NULL) {
1,717!
2678
      continue;
×
2679
    }
2680
    code = tSimpleHashPut(pScanRange, &checkKey, sizeof(SSessionKey), NULL, 0);
1,717✔
2681
    QUERY_CHECK_CODE(code, lino, _end);
1,718!
2682

2683
    code = colDataSetVal(pStartTsCol, pDestBlock->info.rows, (const char*)(&win.skey), false);
1,718✔
2684
    QUERY_CHECK_CODE(code, lino, _end);
1,718!
2685

2686
    code = colDataSetVal(pEndTsCol, pDestBlock->info.rows, (const char*)(&win.ekey), false);
1,718✔
2687
    QUERY_CHECK_CODE(code, lino, _end);
1,716!
2688

2689
    code = colDataSetVal(pGpCol, pDestBlock->info.rows, (const char*)(&groupId), false);
1,716✔
2690
    QUERY_CHECK_CODE(code, lino, _end);
1,717!
2691

2692
    colDataSetNULL(pDestTableNameInxCol,  pDestBlock->info.rows);
1,717!
2693

2694
    pDestBlock->info.rows++;
1,717✔
2695
  }
2696

2697
_end:
1,654✔
2698
  tSimpleHashCleanup(pScanRange);
1,654✔
2699
  if (code != TSDB_CODE_SUCCESS) {
1,653!
UNCOV
2700
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2701
  }
2702
  return code;
1,652✔
2703
}
2704

2705
int32_t calBlockTbName(SStreamScanInfo* pInfo, SSDataBlock* pBlock, int32_t rowId) {
918,177✔
2706
  int32_t code = TSDB_CODE_SUCCESS;
918,177✔
2707
  int32_t lino = 0;
918,177✔
2708
  blockDataCleanup(pInfo->pCreateTbRes);
918,177✔
2709
  if (pInfo->tbnameCalSup.numOfExprs == 0 && pInfo->tagCalSup.numOfExprs == 0) {
918,134✔
2710
    pBlock->info.parTbName[0] = 0;
898,054✔
2711
    if (pInfo->hasPart == false) {
898,054✔
2712
      pInfo->stateStore.streamStateSetParNameInvalid(pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState);
892,558✔
2713
    }
2714
  } else {
2715
    code = appendCreateTableRow(pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState, &pInfo->tbnameCalSup,
20,080✔
2716
                                &pInfo->tagCalSup, pBlock->info.id.groupId, pBlock, rowId, pInfo->pCreateTbRes,
2717
                                &pInfo->stateStore);
2718
    QUERY_CHECK_CODE(code, lino, _end);
20,104!
2719
  }
2720

2721
_end:
20,104✔
2722
  if (code != TSDB_CODE_SUCCESS) {
918,159!
UNCOV
2723
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2724
  }
2725
  return code;
918,162✔
2726
}
2727

2728
static int32_t generatePartitionDelResBlock(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, SSDataBlock* pDestBlock) {
47✔
2729
  int32_t          code = TSDB_CODE_SUCCESS;
47✔
2730
  int32_t          lino = 0;
47✔
2731
  SColumnInfoData* pSrcStartTsCol = (SColumnInfoData*)taosArrayGet(pSrcBlock->pDataBlock, START_TS_COLUMN_INDEX);
47✔
2732
  SColumnInfoData* pSrcEndTsCol = (SColumnInfoData*)taosArrayGet(pSrcBlock->pDataBlock, END_TS_COLUMN_INDEX);
47✔
2733
  SColumnInfoData* pSrcUidCol = taosArrayGet(pSrcBlock->pDataBlock, UID_COLUMN_INDEX);
47✔
2734
  uint64_t*        srcUidData = (uint64_t*)pSrcUidCol->pData;
47✔
2735
  SColumnInfoData* pSrcGpCol = taosArrayGet(pSrcBlock->pDataBlock, GROUPID_COLUMN_INDEX);
47✔
2736
  uint64_t*        srcGp = (uint64_t*)pSrcGpCol->pData;
47✔
2737

2738
  TSKEY*  srcStartTsCol = (TSKEY*)pSrcStartTsCol->pData;
47✔
2739
  TSKEY*  srcEndTsCol = (TSKEY*)pSrcEndTsCol->pData;
47✔
2740
  int64_t ver = pSrcBlock->info.version - 1;
47✔
2741
  for (int32_t delI = 0; delI < pSrcBlock->info.rows; delI++) {
94✔
2742
    uint64_t     groupId = 0;
47✔
2743
    uint64_t     srcUid = srcUidData[delI];
47✔
2744
    char         tbname[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN] = {0};
47✔
2745
    SSDataBlock* pPreRes = readPreVersionData(pInfo->pTableScanOp, srcUid, srcStartTsCol[delI], srcEndTsCol[delI], ver);
47✔
2746
    if (!pPreRes) {
47!
UNCOV
2747
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
2748
      continue;
×
2749
    }
2750
    code = blockDataEnsureCapacity(pDestBlock, pDestBlock->info.rows + pPreRes->info.rows);
47✔
2751
    QUERY_CHECK_CODE(code, lino, _end);
47!
2752
    for (int32_t preJ = 0; preJ < pPreRes->info.rows; preJ++) {
99✔
2753
      groupId = calGroupIdByData(&pInfo->partitionSup, pInfo->pPartScalarSup, pPreRes, preJ);
52✔
2754
      if (pInfo->pPartTbnameSup) {
52!
2755
        void*   parTbname = NULL;
52✔
2756
        int32_t winCode = TSDB_CODE_SUCCESS;
52✔
2757
        code = pInfo->stateStore.streamStateGetParName(pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState, groupId,
52✔
2758
                                                       &parTbname, false, &winCode);
2759
        QUERY_CHECK_CODE(code, lino, _end);
52!
2760

2761
        if (winCode != TSDB_CODE_SUCCESS) {
52✔
2762
          code = calBlockTbName(pInfo, pPreRes, preJ);
49✔
2763
          QUERY_CHECK_CODE(code, lino, _end);
49!
2764
          memcpy(varDataVal(tbname), pPreRes->info.parTbName, strlen(pPreRes->info.parTbName));
49✔
2765
        } else {
2766
          memcpy(varDataVal(tbname), parTbname, TSDB_TABLE_NAME_LEN);
3✔
2767
        }
2768
        varDataSetLen(tbname, strlen(varDataVal(tbname)));
52✔
2769
        pInfo->stateStore.streamStateFreeVal(parTbname);
52✔
2770
      }
2771
      code = appendDataToSpecialBlock(pDestBlock, srcStartTsCol + delI, srcEndTsCol + delI, srcUidData + delI, &groupId,
52✔
2772
                                      tbname[0] == 0 ? NULL : tbname);
52✔
2773
      QUERY_CHECK_CODE(code, lino, _end);
52!
2774
    }
2775
  }
2776

2777
_end:
47✔
2778
  if (code != TSDB_CODE_SUCCESS) {
47!
UNCOV
2779
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2780
  }
2781
  return code;
47✔
2782
}
2783

2784
static int32_t generateDeleteResultBlockImpl(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, SSDataBlock* pDestBlock) {
76✔
2785
  int32_t          code = TSDB_CODE_SUCCESS;
76✔
2786
  int32_t          lino = 0;
76✔
2787
  SColumnInfoData* pSrcStartTsCol = (SColumnInfoData*)taosArrayGet(pSrcBlock->pDataBlock, START_TS_COLUMN_INDEX);
76✔
2788
  SColumnInfoData* pSrcEndTsCol = (SColumnInfoData*)taosArrayGet(pSrcBlock->pDataBlock, END_TS_COLUMN_INDEX);
76✔
2789
  SColumnInfoData* pSrcUidCol = taosArrayGet(pSrcBlock->pDataBlock, UID_COLUMN_INDEX);
76✔
2790
  uint64_t*        srcUidData = (uint64_t*)pSrcUidCol->pData;
76✔
2791
  SColumnInfoData* pSrcGpCol = taosArrayGet(pSrcBlock->pDataBlock, GROUPID_COLUMN_INDEX);
76✔
2792
  uint64_t*        srcGp = (uint64_t*)pSrcGpCol->pData;
76✔
2793
  SColumnInfoData* pSrcPkCol = NULL;
76✔
2794
  if (taosArrayGetSize(pSrcBlock->pDataBlock) > PRIMARY_KEY_COLUMN_INDEX) {
76!
UNCOV
2795
    pSrcPkCol = taosArrayGet(pSrcBlock->pDataBlock, PRIMARY_KEY_COLUMN_INDEX);
×
2796
  }
2797

2798
  TSKEY*  srcStartTsCol = (TSKEY*)pSrcStartTsCol->pData;
76✔
2799
  TSKEY*  srcEndTsCol = (TSKEY*)pSrcEndTsCol->pData;
76✔
2800
  int64_t ver = pSrcBlock->info.version - 1;
76✔
2801
  for (int32_t i = 0; i < pSrcBlock->info.rows; i++) {
152✔
2802
    uint64_t srcUid = srcUidData[i];
76✔
2803
    uint64_t groupId = srcGp[i];
76✔
2804
    char     tbname[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN] = {0};
76✔
2805
    if (groupId == 0) {
76✔
2806
      void* pVal = NULL;
51✔
2807
      if (hasPrimaryKeyCol(pInfo) && pSrcPkCol) {
51!
UNCOV
2808
        pVal = colDataGetData(pSrcPkCol, i);
×
2809
      }
2810
      groupId = getGroupIdByData(pInfo, srcUid, srcStartTsCol[i], ver, pVal);
51✔
2811
    }
2812
    if (pInfo->tbnameCalSup.pExprInfo) {
76✔
2813
      void*   parTbname = NULL;
26✔
2814
      int32_t winCode = TSDB_CODE_SUCCESS;
26✔
2815
      code = pInfo->stateStore.streamStateGetParName(pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState, groupId,
26✔
2816
                                                     &parTbname, false, &winCode);
2817
      QUERY_CHECK_CODE(code, lino, _end);
26!
2818

2819
      if (winCode != TSDB_CODE_SUCCESS) {
26!
UNCOV
2820
        SSDataBlock* pPreRes = readPreVersionData(pInfo->pTableScanOp, srcUid, srcStartTsCol[i], srcStartTsCol[i], ver);
×
UNCOV
2821
        if (!pPreRes) {
×
UNCOV
2822
          qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
2823
          continue;
×
2824
        }
UNCOV
2825
        printDataBlock(pPreRes, "pre res", GET_TASKID(pInfo->pStreamScanOp->pTaskInfo));
×
UNCOV
2826
        code = calBlockTbName(pInfo, pPreRes, 0);
×
UNCOV
2827
        QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
2828
        memcpy(varDataVal(tbname), pPreRes->info.parTbName, strlen(pPreRes->info.parTbName));
×
2829
      } else {
2830
        memcpy(varDataVal(tbname), parTbname, TSDB_TABLE_NAME_LEN);
26✔
2831
      }
2832
      varDataSetLen(tbname, strlen(varDataVal(tbname)));
26✔
2833
      pInfo->stateStore.streamStateFreeVal(parTbname);
26✔
2834
    }
2835
    code = appendDataToSpecialBlock(pDestBlock, srcStartTsCol + i, srcEndTsCol + i, srcUidData + i, &groupId,
76✔
2836
                                    tbname[0] == 0 ? NULL : tbname);
76✔
2837
    QUERY_CHECK_CODE(code, lino, _end);
76!
2838
  }
2839

2840
_end:
76✔
2841
  if (code != TSDB_CODE_SUCCESS) {
76!
UNCOV
2842
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2843
  }
2844
  return code;
76✔
2845
}
2846

2847
int32_t generateDeleteResultBlock(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, SSDataBlock* pDestBlock) {
123✔
2848
  blockDataCleanup(pDestBlock);
123✔
2849
  int32_t rows = pSrcBlock->info.rows;
123✔
2850
  if (rows == 0) {
123!
UNCOV
2851
    return TSDB_CODE_SUCCESS;
×
2852
  }
2853
  int32_t code = blockDataEnsureCapacity(pDestBlock, rows);
123✔
2854
  if (code != TSDB_CODE_SUCCESS) {
123!
UNCOV
2855
    return code;
×
2856
  }
2857
  if (pInfo->partitionSup.needCalc) {
123✔
2858
    return generatePartitionDelResBlock(pInfo, pSrcBlock, pDestBlock);
47✔
2859
  }
2860
  return generateDeleteResultBlockImpl(pInfo, pSrcBlock, pDestBlock);
76✔
2861
}
2862

2863
int32_t generateScanRange(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, SSDataBlock* pDestBlock, EStreamType type) {
2,822✔
2864
  int32_t code = TSDB_CODE_SUCCESS;
2,822✔
2865
  int32_t lino = 0;
2,822✔
2866
  if (isIntervalWindow(pInfo)) {
2,822✔
2867
    code = generateIntervalScanRange(pInfo, pSrcBlock, pDestBlock, type);
1,651✔
2868
    QUERY_CHECK_CODE(code, lino, _end);
1,653!
2869
  } else if (isSessionWindow(pInfo) || isStateWindow(pInfo)) {
1,166✔
2870
    code = generateSessionScanRange(pInfo, pSrcBlock, pDestBlock, type);
1,037✔
2871
    QUERY_CHECK_CODE(code, lino, _end);
1,039!
2872
  } else if (isCountWindow(pInfo)) {
129✔
2873
    code = generateCountScanRange(pInfo, pSrcBlock, pDestBlock, type);
69✔
2874
    QUERY_CHECK_CODE(code, lino, _end);
69!
2875
  } else if (isTimeSlice(pInfo)) {
60✔
2876
    code = generateTimeSliceScanRange(pInfo, pSrcBlock, pDestBlock, type);
15✔
2877
    QUERY_CHECK_CODE(code, lino, _end);
15!
2878
  } else {
2879
    code = generateDeleteResultBlock(pInfo, pSrcBlock, pDestBlock);
45✔
2880
    QUERY_CHECK_CODE(code, lino, _end);
45!
2881
  }
2882
  pDestBlock->info.type = STREAM_CLEAR;
2,821✔
2883
  pDestBlock->info.version = pSrcBlock->info.version;
2,821✔
2884
  pDestBlock->info.dataLoad = 1;
2,821✔
2885
  code = blockDataUpdateTsWindow(pDestBlock, 0);
2,821✔
2886
  QUERY_CHECK_CODE(code, lino, _end);
2,822!
2887

2888
_end:
2,822✔
2889
  if (code != TSDB_CODE_SUCCESS) {
2,822!
2890
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2891
  }
2892
  return code;
2,822✔
2893
}
2894

2895
int32_t appendDataToSpecialBlock(SSDataBlock* pBlock, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t* pUid, uint64_t* pGp,
5,054✔
2896
                                 void* pTbName) {
2897
  return appendOneRowToSpecialBlockImpl(pBlock, pStartTs, pEndTs, pStartTs, pEndTs, pUid, pGp, pTbName, NULL);
5,054✔
2898
}
2899

2900
bool checkExpiredData(SStateStore* pAPI, SUpdateInfo* pUpdateInfo, STimeWindowAggSupp* pTwSup, uint64_t tableId,
6,501✔
2901
                      TSKEY ts, void* pPkVal, int32_t len) {
2902
  bool isExpired = false;
6,501✔
2903
  bool isInc = pAPI->isIncrementalTimeStamp(pUpdateInfo, tableId, ts, pPkVal, len);
6,501✔
2904
  if (!isInc) {
6,501✔
2905
    isExpired = isOverdue(ts, pTwSup);
371✔
2906
  }
2907
  return isExpired;
6,501✔
2908
}
2909

2910
int32_t checkUpdateData(SStreamScanInfo* pInfo, bool invertible, SSDataBlock* pBlock, bool out) {
341,709✔
2911
  int32_t code = TSDB_CODE_SUCCESS;
341,709✔
2912
  int32_t lino = 0;
341,709✔
2913
  if (out) {
341,709✔
2914
    blockDataCleanup(pInfo->pUpdateDataRes);
339,196✔
2915
    code = blockDataEnsureCapacity(pInfo->pUpdateDataRes, pBlock->info.rows * 2);
339,170✔
2916
    QUERY_CHECK_CODE(code, lino, _end);
339,172!
2917
  }
2918
  SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryTsIndex);
341,685✔
2919
  TSKEY*           tsCol = (TSKEY*)pColDataInfo->pData;
341,692✔
2920
  SColumnInfoData* pPkColDataInfo = NULL;
341,692✔
2921
  if (hasPrimaryKeyCol(pInfo)) {
341,692✔
2922
    pPkColDataInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryKeyIndex);
315,202✔
2923
  }
2924

2925
  bool tableInserted = pInfo->stateStore.updateInfoIsTableInserted(pInfo->pUpdateInfo, pBlock->info.id.uid);
341,688✔
2926
  for (int32_t rowId = 0; rowId < pBlock->info.rows; rowId++) {
51,838,086✔
2927
    SResultRowInfo dumyInfo;
2928
    dumyInfo.cur.pageId = -1;
51,485,033✔
2929
    bool        isClosed = false;
51,485,033✔
2930
    STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX};
51,485,033✔
2931
    bool        overDue = isOverdue(tsCol[rowId], &pInfo->twAggSup);
51,485,033✔
2932
    if (pInfo->igExpired && overDue) {
51,474,235✔
2933
      continue;
307✔
2934
    }
2935

2936
    if (tableInserted && overDue) {
51,473,928✔
2937
      win = getActiveTimeWindow(NULL, &dumyInfo, tsCol[rowId], &pInfo->interval, TSDB_ORDER_ASC);
31,330,462✔
2938
      isClosed = isCloseWindow(&win, &pInfo->twAggSup);
31,316,171✔
2939
    }
2940
    // must check update info first.
2941
    void*   pPkVal = NULL;
51,458,410✔
2942
    int32_t pkLen = 0;
51,458,410✔
2943
    if (hasPrimaryKeyCol(pInfo)) {
51,458,410✔
2944
      pPkVal = colDataGetData(pPkColDataInfo, rowId);
31,491,708!
2945
      pkLen = colDataGetRowLength(pPkColDataInfo, rowId);
31,491,708✔
2946
    }
2947
    bool update =
2948
        pInfo->stateStore.updateInfoIsUpdated(pInfo->pUpdateInfo, pBlock->info.id.uid, tsCol[rowId], pPkVal, pkLen);
51,470,070✔
2949
    bool isDeleted =
51,496,059✔
2950
        isClosed && isSignleIntervalWindow(pInfo) &&
82,335,705!
2951
        isDeletedStreamWindow(&win, pBlock->info.id.groupId, pInfo->pState, &pInfo->twAggSup, &pInfo->stateStore);
30,837,324✔
2952
    if ((update || isDeleted) && out) {
51,496,059!
2953
      qDebug("stream update check not pass, update %d, deleted Win %d", update, isDeleted);
2,683✔
2954
      uint64_t gpId = 0;
2,683✔
2955
      code = appendPkToSpecialBlock(pInfo->pUpdateDataRes, tsCol, pPkColDataInfo, rowId, &pBlock->info.id.uid, &gpId,
2,683✔
2956
                                    NULL);
2957
      QUERY_CHECK_CODE(code, lino, _end);
2,684!
2958
      if (isDeleted && pInfo->partitionSup.needCalc) {
2,684!
UNCOV
2959
        gpId = calGroupIdByData(&pInfo->partitionSup, pInfo->pPartScalarSup, pBlock, rowId);
×
UNCOV
2960
        code = appendPkToSpecialBlock(pInfo->pUpdateDataRes, tsCol, pPkColDataInfo, rowId, &pBlock->info.id.uid, &gpId,
×
2961
                                      NULL);
UNCOV
2962
        QUERY_CHECK_CODE(code, lino, _end);
×
2963
      }
2964
    }
2965
  }
2966
  if (out && pInfo->pUpdateDataRes->info.rows > 0) {
353,053✔
2967
    pInfo->pUpdateDataRes->info.version = pBlock->info.version;
1,608✔
2968
    pInfo->pUpdateDataRes->info.dataLoad = 1;
1,608✔
2969
    code = blockDataUpdateTsWindow(pInfo->pUpdateDataRes, 0);
1,608✔
2970
    QUERY_CHECK_CODE(code, lino, _end);
1,610!
2971
    pInfo->pUpdateDataRes->info.type = pInfo->partitionSup.needCalc ? STREAM_DELETE_DATA : STREAM_CLEAR;
1,610✔
2972
  }
2973

2974
_end:
351,445✔
2975
  if (code != TSDB_CODE_SUCCESS) {
353,055!
UNCOV
2976
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2977
  }
2978
  return code;
341,716✔
2979
}
2980

2981
int32_t doBlockDataWindowFilter(SSDataBlock* pBlock, int32_t tsIndex, STimeWindow* pWindow, const char* id) {
878,081✔
2982
  int32_t code = TSDB_CODE_SUCCESS;
878,081✔
2983
  int32_t lino = 0;
878,081✔
2984
  bool*   p = NULL;
878,081✔
2985
  if (pWindow->skey != INT64_MIN || pWindow->ekey != INT64_MAX) {
878,081✔
2986
    p = taosMemoryCalloc(pBlock->info.rows, sizeof(bool));
86,259!
2987
    QUERY_CHECK_NULL(p, code, lino, _end, terrno);
86,331!
2988
    bool hasUnqualified = false;
86,331✔
2989

2990
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, tsIndex);
86,331✔
2991

2992
    if (pWindow->skey != INT64_MIN) {
86,332✔
2993
      qDebug("%s filter for additional history window, skey:%" PRId64, id, pWindow->skey);
45,049✔
2994

2995
      QUERY_CHECK_NULL(pCol->pData, code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
45,048!
2996
      for (int32_t i = 0; i < pBlock->info.rows; ++i) {
4,437,099✔
2997
        int64_t* ts = (int64_t*)colDataGetData(pCol, i);
4,392,051!
2998
        p[i] = (*ts >= pWindow->skey);
4,392,051✔
2999

3000
        if (!p[i]) {
4,392,051✔
3001
          hasUnqualified = true;
1,112✔
3002
        }
3003
      }
3004
    } else if (pWindow->ekey != INT64_MAX) {
41,283!
3005
      qDebug("%s filter for additional history window, ekey:%" PRId64, id, pWindow->ekey);
41,284✔
3006
      for (int32_t i = 0; i < pBlock->info.rows; ++i) {
4,128,726✔
3007
        int64_t* ts = (int64_t*)colDataGetData(pCol, i);
4,087,442!
3008
        p[i] = (*ts <= pWindow->ekey);
4,087,442✔
3009

3010
        if (!p[i]) {
4,087,442✔
3011
          hasUnqualified = true;
4,087,067✔
3012
        }
3013
      }
3014
    }
3015

3016
    if (hasUnqualified) {
86,331✔
3017
      code = trimDataBlock(pBlock, pBlock->info.rows, p);
42,023✔
3018
      QUERY_CHECK_CODE(code, lino, _end);
42,024!
3019
    }
3020
  }
3021

3022
_end:
878,154✔
3023
  taosMemoryFree(p);
878,154!
3024
  if (code != TSDB_CODE_SUCCESS) {
878,112!
UNCOV
3025
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3026
  }
3027
  return code;
878,123✔
3028
}
3029

UNCOV
3030
static int32_t doBlockDataPrimaryKeyFilter(SSDataBlock* pBlock, STqOffsetVal* offset) {
×
UNCOV
3031
  int32_t code = TSDB_CODE_SUCCESS;
×
UNCOV
3032
  int32_t lino = 0;
×
UNCOV
3033
  if (pBlock->info.window.skey != offset->ts || offset->primaryKey.type == 0) {
×
UNCOV
3034
    return code;
×
3035
  }
UNCOV
3036
  bool* p = taosMemoryCalloc(pBlock->info.rows, sizeof(bool));
×
UNCOV
3037
  QUERY_CHECK_NULL(p, code, lino, _end, terrno);
×
UNCOV
3038
  bool hasUnqualified = false;
×
3039

UNCOV
3040
  SColumnInfoData* pColTs = taosArrayGet(pBlock->pDataBlock, 0);
×
UNCOV
3041
  SColumnInfoData* pColPk = taosArrayGet(pBlock->pDataBlock, 1);
×
3042

UNCOV
3043
  qDebug("doBlockDataWindowFilter primary key, ts:%" PRId64 " %" PRId64, offset->ts,
×
3044
         VALUE_GET_TRIVIAL_DATUM(&offset->primaryKey));
UNCOV
3045
  QUERY_CHECK_CONDITION((pColPk->info.type == offset->primaryKey.type), code, lino, _end,
×
3046
                        TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
3047

UNCOV
3048
  __compar_fn_t func = getComparFunc(pColPk->info.type, 0);
×
UNCOV
3049
  QUERY_CHECK_NULL(func, code, lino, _end, terrno);
×
UNCOV
3050
  for (int32_t i = 0; i < pBlock->info.rows; ++i) {
×
UNCOV
3051
    int64_t* ts = (int64_t*)colDataGetData(pColTs, i);
×
UNCOV
3052
    void*    data = colDataGetData(pColPk, i);
×
UNCOV
3053
    if (IS_VAR_DATA_TYPE(pColPk->info.type)) {
×
UNCOV
3054
      void* tmq = taosMemoryMalloc(offset->primaryKey.nData + VARSTR_HEADER_SIZE);
×
UNCOV
3055
      QUERY_CHECK_NULL(tmq, code, lino, _end, terrno);
×
UNCOV
3056
      memcpy(varDataVal(tmq), offset->primaryKey.pData, offset->primaryKey.nData);
×
UNCOV
3057
      varDataLen(tmq) = offset->primaryKey.nData;
×
UNCOV
3058
      p[i] = (*ts > offset->ts) || (func(data, tmq) > 0);
×
UNCOV
3059
      taosMemoryFree(tmq);
×
3060
    } else {
3061
      p[i] = (*ts > offset->ts) || (func(data, VALUE_GET_DATUM(&offset->primaryKey, pColPk->info.type)) > 0);
×
3062
    }
3063

UNCOV
3064
    if (!p[i]) {
×
UNCOV
3065
      hasUnqualified = true;
×
3066
    }
3067
  }
3068

UNCOV
3069
  if (hasUnqualified) {
×
UNCOV
3070
    code = trimDataBlock(pBlock, pBlock->info.rows, p);
×
UNCOV
3071
    QUERY_CHECK_CODE(code, lino, _end);
×
3072
  }
3073

UNCOV
3074
_end:
×
UNCOV
3075
  taosMemoryFree(p);
×
UNCOV
3076
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3077
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3078
  }
UNCOV
3079
  return code;
×
3080
}
3081

3082
// re-build the delete block, ONLY according to the split timestamp
3083
int32_t rebuildDeleteBlockData(SSDataBlock* pBlock, STimeWindow* pWindow, const char* id) {
2,426✔
3084
  int32_t code = TSDB_CODE_SUCCESS;
2,426✔
3085
  int32_t lino = 0;
2,426✔
3086
  int32_t numOfRows = pBlock->info.rows;
2,426✔
3087
  bool*   p = taosMemoryCalloc(numOfRows, sizeof(bool));
2,426!
3088
  QUERY_CHECK_NULL(p, code, lino, _end, terrno);
2,425!
3089

3090
  bool    hasUnqualified = false;
2,425✔
3091
  int64_t skey = pWindow->skey;
2,425✔
3092
  int64_t ekey = pWindow->ekey;
2,425✔
3093

3094
  SColumnInfoData* pSrcStartCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
2,425✔
3095
  uint64_t*        tsStartCol = (uint64_t*)pSrcStartCol->pData;
2,425✔
3096
  SColumnInfoData* pSrcEndCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
2,425✔
3097
  uint64_t*        tsEndCol = (uint64_t*)pSrcEndCol->pData;
2,425✔
3098

3099
  if (pWindow->skey != INT64_MIN) {
2,425!
UNCOV
3100
    for (int32_t i = 0; i < numOfRows; i++) {
×
UNCOV
3101
      if (tsStartCol[i] < skey) {
×
UNCOV
3102
        tsStartCol[i] = skey;
×
3103
      }
3104

UNCOV
3105
      if (tsEndCol[i] >= skey) {
×
UNCOV
3106
        p[i] = true;
×
3107
      } else {  // this row should be removed, since it is not in this query time window, which is [skey, INT64_MAX]
3108
        hasUnqualified = true;
×
3109
      }
3110
    }
3111
  } else if (pWindow->ekey != INT64_MAX) {
2,425!
UNCOV
3112
    for (int32_t i = 0; i < numOfRows; ++i) {
×
3113
      if (tsEndCol[i] > ekey) {
×
UNCOV
3114
        tsEndCol[i] = ekey;
×
3115
      }
3116

UNCOV
3117
      if (tsStartCol[i] <= ekey) {
×
3118
        p[i] = true;
×
3119
      } else {
3120
        hasUnqualified = true;
×
3121
      }
3122
    }
3123
  }
3124

3125
  if (hasUnqualified) {
2,425!
3126
    code = trimDataBlock(pBlock, pBlock->info.rows, p);
×
UNCOV
3127
    qDebug("%s re-build delete datablock, start key revised to:%" PRId64 ", rows:%" PRId64, id, skey,
×
3128
           pBlock->info.rows);
UNCOV
3129
    QUERY_CHECK_CODE(code, lino, _end);
×
3130
  } else {
3131
    qDebug("%s not update the delete block", id);
2,425✔
3132
  }
3133

3134
_end:
1,186✔
3135
  taosMemoryFree(p);
2,425!
3136
  if (code != TSDB_CODE_SUCCESS) {
2,425!
UNCOV
3137
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3138
  }
3139
  return code;
2,424✔
3140
}
3141

3142
int32_t colIdComparFn(const void* param1, const void* param2) {
5,219,457✔
3143
  int32_t p1 = *(int32_t*)param1;
5,219,457✔
3144
  int32_t p2 = *(int32_t*)param2;
5,219,457✔
3145

3146
  if (p1 == p2) {
5,219,457!
UNCOV
3147
    return 0;
×
3148
  } else {
3149
    return (p1 < p2) ? -1 : 1;
5,219,457✔
3150
  }
3151
}
3152

3153
int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock, STimeWindow* pTimeWindow, bool filter) {
878,132✔
3154
  int32_t         code = TSDB_CODE_SUCCESS;
878,132✔
3155
  int32_t         lino = 0;
878,132✔
3156
  SDataBlockInfo* pBlockInfo = &pInfo->pRes->info;
878,132✔
3157
  SOperatorInfo*  pOperator = pInfo->pStreamScanOp;
878,132✔
3158
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
878,132✔
3159
  const char*     id = GET_TASKID(pTaskInfo);
878,132✔
3160
  SSHashObj*      pVtableInfos = pTaskInfo->pSubplan->pVTables;
878,132✔
3161

3162
  code = blockDataEnsureCapacity(pInfo->pRes, pBlock->info.rows);
878,132✔
3163
  QUERY_CHECK_CODE(code, lino, _end);
878,156!
3164

3165
  pBlockInfo->rows = pBlock->info.rows;
878,156✔
3166
  pBlockInfo->id.uid = pBlock->info.id.uid;
878,156✔
3167
  pBlockInfo->type = STREAM_NORMAL;
878,156✔
3168
  pBlockInfo->version = pBlock->info.version;
878,156✔
3169

3170
  STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info;
878,156✔
3171
  if (pVtableInfos == NULL) {
878,156✔
3172
    pBlockInfo->id.groupId = tableListGetTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid);
878,150✔
3173
  } else {
3174
    // use original table uid as groupId for vtable
3175
    pBlockInfo->id.groupId = pBlock->info.id.groupId;
6✔
3176
  }
3177

3178
  SArray* pColList = taosArrayInit(4, sizeof(int32_t));
878,190✔
3179
  QUERY_CHECK_NULL(pColList, code, lino, _end, terrno);
878,174!
3180

3181
  // todo extract method
3182
  for (int32_t i = 0; i < taosArrayGetSize(pInfo->matchInfo.pList); ++i) {
4,143,495✔
3183
    SColMatchItem* pColMatchInfo = taosArrayGet(pInfo->matchInfo.pList, i);
3,265,384✔
3184
    if (!pColMatchInfo->needOutput) {
3,265,283✔
3185
      continue;
2✔
3186
    }
3187

3188
    bool colExists = false;
3,265,281✔
3189
    for (int32_t j = 0; j < blockDataGetNumOfCols(pBlock); ++j) {
8,696,722!
3190
      SColumnInfoData* pResCol = NULL;
8,695,533✔
3191
      code = bdGetColumnInfoData(pBlock, j, &pResCol);
8,695,533✔
3192
      QUERY_CHECK_CODE(code, lino, _end);
8,696,466!
3193

3194
      if (pResCol->info.colId == pColMatchInfo->colId) {
8,696,466✔
3195
        SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->dstSlotId);
3,265,025✔
3196
        code = colDataAssign(pDst, pResCol, pBlock->info.rows, &pInfo->pRes->info);
3,264,855✔
3197
        QUERY_CHECK_CODE(code, lino, _end);
3,265,043!
3198

3199
        colExists = true;
3,265,043✔
3200
        void* tmp = taosArrayPush(pColList, &pColMatchInfo->dstSlotId);
3,265,043✔
3201
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
3,265,328!
3202
        break;
3,265,328✔
3203
      }
3204
    }
3205

3206
    // the required column does not exists in submit block, let's set it to be all null value
3207
    if (!colExists) {
3,265,317✔
3208
      SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->dstSlotId);
4✔
3209
      colDataSetNNULL(pDst, 0, pBlockInfo->rows);
4!
3210
      void* tmp = taosArrayPush(pColList, &pColMatchInfo->dstSlotId);
4✔
3211
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
4!
3212
    }
3213
  }
3214

3215
  // currently only the tbname pseudo column
3216
  if (pInfo->numOfPseudoExpr > 0) {
877,869✔
3217
    code = addTagPseudoColumnData(&pInfo->readHandle, pInfo->pPseudoExpr, pInfo->numOfPseudoExpr, pInfo->pRes,
354,818✔
3218
                                  pBlockInfo->rows, pTaskInfo, &pTableScanInfo->base.metaCache);
354,818✔
3219
    // ignore the table not exists error, since this table may have been dropped during the scan procedure.
3220
    if (code) {
354,823!
UNCOV
3221
      QUERY_CHECK_CODE(code, lino, _end);
×
3222
    }
3223

3224
    // reset the error code.
3225
    terrno = 0;
354,823✔
3226

3227
    for (int32_t i = 0; i < pInfo->numOfPseudoExpr; ++i) {
1,338,079✔
3228
      void* tmp = taosArrayPush(pColList, &pInfo->pPseudoExpr[i].base.resSchema.slotId);
983,265✔
3229
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
983,261!
3230
    }
3231
  }
3232

3233
  taosArraySort(pColList, colIdComparFn);
877,865✔
3234

3235
  int32_t i = 0, j = 0;
878,143✔
3236
  while (i < taosArrayGetSize(pColList)) {
5,127,025✔
3237
    int32_t slot1 = *(int32_t*)taosArrayGet(pColList, i);
4,248,817✔
3238
    if (slot1 > j) {
4,248,951✔
3239
      SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, j);
69✔
UNCOV
3240
      colDataSetNNULL(pDst, 0, pBlockInfo->rows);
×
UNCOV
3241
      j += 1;
×
3242
    } else {
3243
      i += 1;
4,248,882✔
3244
      j += 1;
4,248,882✔
3245
    }
3246
  }
3247

3248
  while (j < taosArrayGetSize(pInfo->pRes->pDataBlock)) {
879,855✔
3249
    SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, j);
1,747✔
3250
    colDataSetNNULL(pDst, 0, pBlockInfo->rows);
1,747✔
3251
    j += 1;
1,747✔
3252
  }
3253

3254
  taosArrayDestroy(pColList);
878,101✔
3255

3256
  if (filter) {
878,169✔
3257
    code = doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL);
480,557✔
3258
    QUERY_CHECK_CODE(code, lino, _end);
480,513!
3259
  }
3260

3261
  // filter the block extracted from WAL files, according to the time window apply additional time window filter
3262
  code = doBlockDataWindowFilter(pInfo->pRes, pInfo->primaryTsIndex, pTimeWindow, id);
878,125✔
3263
  QUERY_CHECK_CODE(code, lino, _end);
878,117!
3264
  pInfo->pRes->info.dataLoad = 1;
878,117✔
3265

3266
  code = blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex);
878,117✔
3267
  QUERY_CHECK_CODE(code, lino, _end);
878,140!
3268
  if (pInfo->pRes->info.rows == 0) {
878,140✔
3269
    return 0;
44,354✔
3270
  }
3271

3272
  code = calBlockTbName(pInfo, pInfo->pRes, 0);
833,786✔
3273
  QUERY_CHECK_CODE(code, lino, _end);
833,704!
3274

3275
_end:
833,704✔
3276
  if (code != TSDB_CODE_SUCCESS) {
833,704!
UNCOV
3277
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3278
  }
3279
  return code;
833,713✔
3280
}
3281

3282
static int32_t processPrimaryKey(SSDataBlock* pBlock, bool hasPrimaryKey, STqOffsetVal* offset) {
22,828✔
3283
  int32_t code = TSDB_CODE_SUCCESS;
22,828✔
3284
  int32_t lino = 0;
22,828✔
3285
  SValue  val = {0};
22,828✔
3286
  if (hasPrimaryKey) {
22,828!
UNCOV
3287
    code = doBlockDataPrimaryKeyFilter(pBlock, offset);
×
UNCOV
3288
    if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3289
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
UNCOV
3290
      return code;
×
3291
    }
UNCOV
3292
    SColumnInfoData* pColPk = taosArrayGet(pBlock->pDataBlock, 1);
×
3293

3294
    if (pBlock->info.rows < 1) {
×
UNCOV
3295
      return code;
×
3296
    }
UNCOV
3297
    void* tmp = colDataGetData(pColPk, pBlock->info.rows - 1);
×
UNCOV
3298
    val.type = pColPk->info.type;
×
UNCOV
3299
    if (IS_VAR_DATA_TYPE(pColPk->info.type)) {
×
UNCOV
3300
      val.pData = taosMemoryMalloc(varDataLen(tmp));
×
UNCOV
3301
      QUERY_CHECK_NULL(val.pData, code, lino, _end, terrno);
×
UNCOV
3302
      val.nData = varDataLen(tmp);
×
UNCOV
3303
      memcpy(val.pData, varDataVal(tmp), varDataLen(tmp));
×
3304
    } else {
UNCOV
3305
      valueSetDatum(&val, pColPk->info.type, tmp, pColPk->info.bytes);
×
3306
    }
3307
  }
3308
  tqOffsetResetToData(offset, pBlock->info.id.uid, pBlock->info.window.ekey, val);
45,679!
3309

3310
_end:
22,851✔
3311
  if (code != TSDB_CODE_SUCCESS) {
22,851!
UNCOV
3312
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3313
  }
3314
  return code;
22,840✔
3315
}
3316

3317
static int32_t doQueueScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
594,069✔
3318
  int32_t        code = TSDB_CODE_SUCCESS;
594,069✔
3319
  int32_t        lino = 0;
594,069✔
3320
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
594,069✔
3321
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
594,069✔
3322

3323
  SStreamScanInfo* pInfo = pOperator->info;
594,069✔
3324
  const char*      id = GET_TASKID(pTaskInfo);
594,069✔
3325

3326
  qDebug("start to exec queue scan, %s", id);
594,069✔
3327

3328
  if (isTaskKilled(pTaskInfo)) {
594,069!
UNCOV
3329
    (*ppRes) = NULL;
×
UNCOV
3330
    return pTaskInfo->code;
×
3331
  }
3332

3333
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) {
594,074✔
UNCOV
3334
    while (1) {
×
3335
      SSDataBlock* pResult = NULL;
20,536✔
3336
      code = doTableScanNext(pInfo->pTableScanOp, &pResult);
20,536✔
3337
      QUERY_CHECK_CODE(code, lino, _end);
20,489!
3338

3339
      if (pResult && pResult->info.rows > 0) {
20,489!
3340
        bool hasPrimaryKey = pAPI->tqReaderFn.tqGetTablePrimaryKey(pInfo->tqReader);
20,322✔
3341
        code = processPrimaryKey(pResult, hasPrimaryKey, &pTaskInfo->streamInfo.currentOffset);
20,321✔
3342
        QUERY_CHECK_CODE(code, lino, _end);
20,320!
3343
        qDebug("tmqsnap doQueueScan get data utid:%" PRId64 "", pResult->info.id.uid);
20,320✔
3344
        if (pResult->info.rows > 0) {
20,327!
3345
          (*ppRes) = pResult;
20,327✔
3346
          return code;
20,327✔
3347
        }
3348
      } else {
3349
        break;
3350
      }
3351
    }
3352

3353
    STableScanInfo* pTSInfo = pInfo->pTableScanOp->info;
167✔
3354
    pAPI->tsdReader.tsdReaderClose(pTSInfo->base.dataReader);
167✔
3355

3356
    pTSInfo->base.dataReader = NULL;
201✔
3357
    int64_t validVer = pTaskInfo->streamInfo.snapshotVer + 1;
201✔
3358
    qDebug("queue scan tsdb over, switch to wal ver %" PRId64 "", validVer);
201✔
3359
    if (pAPI->tqReaderFn.tqReaderSeek(pInfo->tqReader, validVer, pTaskInfo->id.str) < 0) {
201✔
3360
      (*ppRes) = NULL;
105✔
3361
      return code;
105✔
3362
    }
3363

3364
    tqOffsetResetToLog(&pTaskInfo->streamInfo.currentOffset, validVer);
96✔
3365
  }
3366

3367
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__LOG) {
573,634!
3368
    while (1) {
2,330✔
3369
      bool hasResult =
3370
          pAPI->tqReaderFn.tqReaderNextBlockInWal(pInfo->tqReader, id, pTaskInfo->streamInfo.sourceExcluded);
575,964✔
3371

3372
      SSDataBlock*       pRes = pAPI->tqReaderFn.tqGetResultBlock(pInfo->tqReader);
575,955✔
3373
      struct SWalReader* pWalReader = pAPI->tqReaderFn.tqReaderGetWalReader(pInfo->tqReader);
575,948✔
3374

3375
      // curVersion move to next
3376
      tqOffsetResetToLog(&pTaskInfo->streamInfo.currentOffset, pWalReader->curVersion);
575,943✔
3377

3378
      // use ts to pass time when replay, because ts not used if type is log
3379
      pTaskInfo->streamInfo.currentOffset.ts = pAPI->tqReaderFn.tqGetResultBlockTime(pInfo->tqReader);
575,943✔
3380

3381
      if (hasResult) {
575,945✔
3382
        qDebug("doQueueScan get data from log %" PRId64 " rows, version:%" PRId64, pRes->info.rows,
480,584✔
3383
               pTaskInfo->streamInfo.currentOffset.version);
3384
        blockDataCleanup(pInfo->pRes);
480,597✔
3385
        STimeWindow defaultWindow = {.skey = INT64_MIN, .ekey = INT64_MAX};
480,545✔
3386
        code = setBlockIntoRes(pInfo, pRes, &defaultWindow, true);
480,545✔
3387
        QUERY_CHECK_CODE(code, lino, _end);
480,473!
3388
        qDebug("doQueueScan after filter get data from log %" PRId64 " rows, version:%" PRId64, pInfo->pRes->info.rows,
480,473✔
3389
               pTaskInfo->streamInfo.currentOffset.version);
3390
        if (pInfo->pRes->info.rows > 0) {
480,519✔
3391
          (*ppRes) = pInfo->pRes;
478,189✔
3392
          return code;
478,189✔
3393
        }
3394
      } else {
3395
        qDebug("doQueueScan get none from log, return, version:%" PRId64, pTaskInfo->streamInfo.currentOffset.version);
95,361✔
3396
        (*ppRes) = NULL;
95,365✔
3397
        return code;
95,365✔
3398
      }
3399
    }
3400
  } else {
UNCOV
3401
    qError("unexpected streamInfo prepare type: %d", pTaskInfo->streamInfo.currentOffset.type);
×
UNCOV
3402
    (*ppRes) = NULL;
×
UNCOV
3403
    return code;
×
3404
  }
3405

3406
_end:
×
3407
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3408
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
3409
    pTaskInfo->code = code;
×
3410
    T_LONG_JMP(pTaskInfo->env, code);
×
3411
  }
UNCOV
3412
  (*ppRes) = NULL;
×
UNCOV
3413
  return code;
×
3414
}
3415

UNCOV
3416
static SSDataBlock* doQueueScan(SOperatorInfo* pOperator) {
×
UNCOV
3417
  SSDataBlock* pRes = NULL;
×
UNCOV
3418
  int32_t      code = doQueueScanNext(pOperator, &pRes);
×
UNCOV
3419
  return pRes;
×
3420
}
3421

3422
int32_t filterDelBlockByUid(SSDataBlock* pDst, const SSDataBlock* pSrc, STqReader* pReader, SStoreTqReader* pReaderFn) {
2,425✔
3423
  int32_t    code = TSDB_CODE_SUCCESS;
2,425✔
3424
  int32_t    lino = 0;
2,425✔
3425
  int32_t    rows = pSrc->info.rows;
2,425✔
3426
  code = blockDataEnsureCapacity(pDst, rows);
2,425✔
3427
  QUERY_CHECK_CODE(code, lino, _end);
2,426!
3428

3429
  SColumnInfoData* pSrcStartCol = taosArrayGet(pSrc->pDataBlock, START_TS_COLUMN_INDEX);
2,426✔
3430
  uint64_t*        startCol = (uint64_t*)pSrcStartCol->pData;
2,426✔
3431
  SColumnInfoData* pSrcEndCol = taosArrayGet(pSrc->pDataBlock, END_TS_COLUMN_INDEX);
2,426✔
3432
  uint64_t*        endCol = (uint64_t*)pSrcEndCol->pData;
2,425✔
3433
  SColumnInfoData* pSrcUidCol = taosArrayGet(pSrc->pDataBlock, UID_COLUMN_INDEX);
2,425✔
3434
  uint64_t*        uidCol = (uint64_t*)pSrcUidCol->pData;
2,425✔
3435

3436
  SColumnInfoData* pDstStartCol = taosArrayGet(pDst->pDataBlock, START_TS_COLUMN_INDEX);
2,425✔
3437
  SColumnInfoData* pDstEndCol = taosArrayGet(pDst->pDataBlock, END_TS_COLUMN_INDEX);
2,425✔
3438
  SColumnInfoData* pDstUidCol = taosArrayGet(pDst->pDataBlock, UID_COLUMN_INDEX);
2,425✔
3439

3440
  int32_t j = 0;
2,424✔
3441
  for (int32_t i = 0; i < rows; i++) {
4,857✔
3442
    if (pReaderFn->tqReaderIsQueriedTable(pReader, uidCol[i])) {
2,431✔
3443
      code = colDataSetVal(pDstStartCol, j, (const char*)&startCol[i], false);
1,296✔
3444
      QUERY_CHECK_CODE(code, lino, _end);
1,297!
3445

3446
      code = colDataSetVal(pDstEndCol, j, (const char*)&endCol[i], false);
1,297✔
3447
      QUERY_CHECK_CODE(code, lino, _end);
1,297!
3448

3449
      code = colDataSetVal(pDstUidCol, j, (const char*)&uidCol[i], false);
1,297✔
3450
      QUERY_CHECK_CODE(code, lino, _end);
1,296!
3451

3452
      colDataSetNULL(taosArrayGet(pDst->pDataBlock, GROUPID_COLUMN_INDEX), j);
1,296✔
3453
      colDataSetNULL(taosArrayGet(pDst->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX), j);
1,296✔
3454
      colDataSetNULL(taosArrayGet(pDst->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX), j);
1,296✔
3455
      colDataSetNULL(taosArrayGet(pDst->pDataBlock, TABLE_NAME_COLUMN_INDEX), j);
1,297✔
3456
      j++;
1,296✔
3457
    }
3458
  }
3459

3460
  uint32_t cap = pDst->info.capacity;
2,426✔
3461
  pDst->info = pSrc->info;
2,426✔
3462
  pDst->info.rows = j;
2,426✔
3463
  pDst->info.capacity = cap;
2,426✔
3464

3465
_end:
2,426✔
3466
  if (code != TSDB_CODE_SUCCESS) {
2,426!
UNCOV
3467
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3468
  }
3469
  return code;
2,426✔
3470
}
3471

3472
// for partition by tag
3473
int32_t setBlockGroupIdByUid(SStreamScanInfo* pInfo, SSDataBlock* pBlock) {
2,425✔
3474
  int32_t          code = TSDB_CODE_SUCCESS;
2,425✔
3475
  int32_t          lino = 0;
2,425✔
3476
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
2,425✔
3477
  TSKEY*           startTsCol = (TSKEY*)pStartTsCol->pData;
2,425✔
3478
  SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
2,425✔
3479
  uint64_t*        gpCol = (uint64_t*)pGpCol->pData;
2,425✔
3480
  SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
2,425✔
3481
  uint64_t*        uidCol = (uint64_t*)pUidCol->pData;
2,425✔
3482
  int32_t          rows = pBlock->info.rows;
2,425✔
3483
  if (!pInfo->partitionSup.needCalc) {
2,425✔
3484
    for (int32_t i = 0; i < rows; i++) {
2,436✔
3485
      uint64_t groupId = getGroupIdByUid(pInfo, uidCol[i]);
849✔
3486
      code = colDataSetVal(pGpCol, i, (const char*)&groupId, false);
850✔
3487
      QUERY_CHECK_CODE(code, lino, _end);
850!
3488
    }
3489
  }
3490

3491
_end:
2,426✔
3492
  if (code != TSDB_CODE_SUCCESS) {
2,426!
UNCOV
3493
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3494
  }
3495
  return code;
2,426✔
3496
}
3497

3498
int32_t doCheckUpdate(SStreamScanInfo* pInfo, TSKEY endKey, SSDataBlock* pBlock) {
355,500✔
3499
  int32_t code = TSDB_CODE_SUCCESS;
355,500✔
3500
  int32_t lino = 0;
355,500✔
3501
  if (pInfo->pUpdateInfo) {
355,500✔
3502
    pInfo->pUpdateInfo->maxDataVersion = TMAX(pInfo->pUpdateInfo->maxDataVersion, pBlock->info.version);
354,375✔
3503
  }
3504
  if (!pInfo->igCheckUpdate && pInfo->pUpdateInfo) {
355,500✔
3505
    code = checkUpdateData(pInfo, true, pBlock, true);
339,199✔
3506
    QUERY_CHECK_CODE(code, lino, _end);
339,197!
3507
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, endKey);
339,197✔
3508
    if (pInfo->pUpdateDataRes->info.rows > 0) {
339,197✔
3509
      pInfo->updateResIndex = 0;
1,612✔
3510
      if (pInfo->pUpdateDataRes->info.type == STREAM_CLEAR) {
1,612✔
3511
        pInfo->scanMode = STREAM_SCAN_FROM_UPDATERES;
1,365✔
3512
      } else if (pInfo->pUpdateDataRes->info.type == STREAM_INVERT) {
247!
UNCOV
3513
        pInfo->scanMode = STREAM_SCAN_FROM_RES;
×
3514
        // return pInfo->pUpdateDataRes;
3515
      } else if (pInfo->pUpdateDataRes->info.type == STREAM_DELETE_DATA) {
247✔
3516
        pInfo->scanMode = STREAM_SCAN_FROM_DELETE_DATA;
245✔
3517
      }
3518
    }
3519
  }
3520

3521
_end:
353,888✔
3522
  if (code != TSDB_CODE_SUCCESS) {
355,498!
UNCOV
3523
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3524
  }
3525
  return code;
355,503✔
3526
}
3527

3528
int32_t streamScanOperatorEncode(SStreamScanInfo* pInfo, void** pBuff, int32_t* pLen) {
46✔
3529
  int32_t   code = TSDB_CODE_SUCCESS;
46✔
3530
  int32_t   lino = 0;
46✔
3531
  int32_t   len = 0;
46✔
3532
  SEncoder* pEnCoder = NULL;
46✔
3533
  SEncoder* pScanEnCoder = NULL;
46✔
3534

3535
  len += encodeSTimeWindowAggSupp(NULL, &pInfo->twAggSup);
46✔
3536
  SEncoder encoder = {0};
46✔
3537
  pEnCoder = &encoder;
46✔
3538
  tEncoderInit(pEnCoder, NULL, 0);
46✔
3539
  if (tStartEncode(pEnCoder) != 0) {
46!
UNCOV
3540
    code = TSDB_CODE_STREAM_INTERNAL_ERROR;
×
UNCOV
3541
    QUERY_CHECK_CODE(code, lino, _end);
×
3542
  }
3543
  code = pInfo->stateStore.updateInfoSerialize(pEnCoder, pInfo->pUpdateInfo);
46✔
3544
  QUERY_CHECK_CODE(code, lino, _end);
46!
3545

3546
  if (tEncodeI64(pEnCoder, pInfo->lastScanRange.skey) < 0) {
92!
UNCOV
3547
    code = TSDB_CODE_STREAM_INTERNAL_ERROR;
×
UNCOV
3548
    QUERY_CHECK_CODE(code, lino, _end);
×
3549
  }
3550
  if (tEncodeI64(pEnCoder, pInfo->lastScanRange.ekey) < 0) {
92!
UNCOV
3551
    code = TSDB_CODE_STREAM_INTERNAL_ERROR;
×
UNCOV
3552
    QUERY_CHECK_CODE(code, lino, _end);
×
3553
  }
3554

3555
  tEndEncode(pEnCoder);
46✔
3556
  len += encoder.pos;
46✔
3557
  tEncoderClear(pEnCoder);
46✔
3558
  pEnCoder = NULL;
46✔
3559

3560
  *pBuff = taosMemoryCalloc(1, len);
46!
3561
  if (!(*pBuff)) {
46!
UNCOV
3562
    code = terrno;
×
UNCOV
3563
    QUERY_CHECK_CODE(code, lino, _end);
×
3564
  }
3565
  void* buf = *pBuff;
46✔
3566
  int32_t stwLen = encodeSTimeWindowAggSupp(&buf, &pInfo->twAggSup);
46✔
3567

3568
  SEncoder scanEncoder = {0};
46✔
3569
  pScanEnCoder = &scanEncoder;
46✔
3570
  tEncoderInit(pScanEnCoder, buf, len - stwLen);
46✔
3571
  if (tStartEncode(pScanEnCoder) != 0) {
46!
UNCOV
3572
    code = TSDB_CODE_FAILED;
×
UNCOV
3573
    QUERY_CHECK_CODE(code, lino, _end);
×
3574
  }
3575
  code = pInfo->stateStore.updateInfoSerialize(pScanEnCoder, pInfo->pUpdateInfo);
46✔
3576
  QUERY_CHECK_CODE(code, lino, _end);
46!
3577

3578
  if (tEncodeI64(pScanEnCoder, pInfo->lastScanRange.skey) < 0) {
92!
UNCOV
3579
    code = TSDB_CODE_STREAM_INTERNAL_ERROR;
×
UNCOV
3580
    QUERY_CHECK_CODE(code, lino, _end);
×
3581
  }
3582
  if (tEncodeI64(pScanEnCoder, pInfo->lastScanRange.ekey) < 0) {
92!
UNCOV
3583
    code = TSDB_CODE_STREAM_INTERNAL_ERROR;
×
UNCOV
3584
    QUERY_CHECK_CODE(code, lino, _end);
×
3585
  }
3586

3587
  qDebug("%s last scan range %d. %" PRId64 ",%" PRId64, __func__, __LINE__, pInfo->lastScanRange.skey, pInfo->lastScanRange.ekey);
46✔
3588

3589
  *pLen = len;
46✔
3590

3591
_end:
46✔
3592
  if (code != TSDB_CODE_SUCCESS) {
46!
UNCOV
3593
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3594
  }
3595
  if (pEnCoder != NULL) {
46!
UNCOV
3596
    tEndEncode(pEnCoder);
×
UNCOV
3597
    tEncoderClear(pEnCoder);
×
3598
  }
3599
  if (pScanEnCoder != NULL) {
46!
3600
    tEndEncode(pScanEnCoder);
46✔
3601
    tEncoderClear(pScanEnCoder);
46✔
3602
  }
3603
  return code;
46✔
3604
}
3605

3606
void streamScanOperatorSaveCheckpoint(SStreamScanInfo* pInfo) {
3,601✔
3607
  int32_t code = TSDB_CODE_SUCCESS;
3,601✔
3608
  int32_t lino = 0;
3,601✔
3609
  if (!pInfo->pState) {
3,601!
UNCOV
3610
    return;
×
3611
  }
3612
  if (needSaveStreamOperatorInfo(&pInfo->basic)) {
3,601✔
3613
    void*   pBuf = NULL;
46✔
3614
    int32_t len = 0;
46✔
3615
    code = streamScanOperatorEncode(pInfo, &pBuf, &len);
46✔
3616
    QUERY_CHECK_CODE(code, lino, _end);
46!
3617
    pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_SCAN_OP_CHECKPOINT_NAME,
46✔
3618
                                          strlen(STREAM_SCAN_OP_CHECKPOINT_NAME), pBuf, len);
3619
    taosMemoryFree(pBuf);
46!
3620
    saveStreamOperatorStateComplete(&pInfo->basic);
46✔
3621
  }
3622

3623
_end:
3,555✔
3624
  if (code != TSDB_CODE_SUCCESS) {
3,601!
UNCOV
3625
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3626
  }
3627
}
3628

3629
// other properties are recovered from the execution plan
3630
void streamScanOperatorDecode(void* pBuff, int32_t len, SStreamScanInfo* pInfo) {
35✔
3631
  int32_t   code = TSDB_CODE_SUCCESS;
35✔
3632
  int32_t   lino = 0;
35✔
3633
  SDecoder* pDeCoder = NULL;
35✔
3634
  if (!pBuff || len == 0) {
35!
UNCOV
3635
    lino = __LINE__;
×
UNCOV
3636
    goto _end;
×
3637
  }
3638
  void* buf = pBuff;
35✔
3639
  buf = decodeSTimeWindowAggSupp(buf, &pInfo->twAggSup);
35✔
3640
  int32_t tlen = len - encodeSTimeWindowAggSupp(NULL, &pInfo->twAggSup);
35✔
3641
  if (tlen == 0) {
35!
UNCOV
3642
    lino = __LINE__;
×
UNCOV
3643
    goto _end;
×
3644
  }
3645

3646
  SDecoder decoder = {0};
35✔
3647
  pDeCoder = &decoder;
35✔
3648
  tDecoderInit(pDeCoder, buf, tlen);
35✔
3649
  if (tStartDecode(pDeCoder) < 0) {
35!
UNCOV
3650
    lino = __LINE__;
×
UNCOV
3651
    goto _end;
×
3652
  }
3653

3654
  void* pUpInfo = taosMemoryCalloc(1, sizeof(SUpdateInfo));
35!
3655
  if (!pUpInfo) {
35!
UNCOV
3656
    lino = __LINE__;
×
UNCOV
3657
    goto _end;
×
3658
  }
3659
  code = pInfo->stateStore.updateInfoDeserialize(pDeCoder, pUpInfo);
35✔
3660
  if (code == TSDB_CODE_SUCCESS) {
35✔
3661
    pInfo->stateStore.updateInfoDestroy(pInfo->pUpdateInfo);
32✔
3662
    pInfo->pUpdateInfo = pUpInfo;
32✔
3663
    qDebug("%s line:%d. stream scan updateinfo deserialize success", __func__, __LINE__);
32✔
3664
  } else {
3665
    taosMemoryFree(pUpInfo);
3!
3666
    code = TSDB_CODE_SUCCESS;
3✔
3667
    qDebug("%s line:%d. stream scan did not have updateinfo", __func__, __LINE__);
3!
3668
  }
3669

3670
  if (tDecodeIsEnd(pDeCoder)) {
35!
UNCOV
3671
    lino = __LINE__;
×
UNCOV
3672
    goto _end;
×
3673
  }
3674

3675
  SET_WIN_KEY_INVALID(pInfo->lastScanRange.skey);
35✔
3676
  SET_WIN_KEY_INVALID(pInfo->lastScanRange.ekey);
35✔
3677

3678
  if (tDecodeI64(pDeCoder, &pInfo->lastScanRange.skey) < 0) {
70!
UNCOV
3679
    lino = __LINE__;
×
UNCOV
3680
    goto _end;
×
3681
  }
3682

3683
  if (tDecodeI64(pDeCoder, &pInfo->lastScanRange.ekey) < 0) {
70!
UNCOV
3684
    lino = __LINE__;
×
UNCOV
3685
    goto _end;
×
3686
  }
3687
  qDebug("%s last scan range %d. %" PRId64 ",%" PRId64, __func__, __LINE__, pInfo->lastScanRange.skey, pInfo->lastScanRange.ekey);
35✔
3688

3689
_end:
29✔
3690
  if (pDeCoder != NULL) {
35!
3691
    tEndDecode(pDeCoder);
35✔
3692
    tDecoderClear(pDeCoder);
35✔
3693
  }
3694
  qInfo("%s end at line %d", __func__, lino);
35!
3695
}
35✔
3696

3697
bool hasScanRange(SStreamScanInfo* pInfo) {
393,200✔
3698
  SStreamAggSupporter* pSup = pInfo->windowSup.pStreamAggSup;
393,200✔
3699
  return pSup && pSup->pScanBlock->info.rows > 0 && (isStateWindow(pInfo) || isCountWindow(pInfo));
393,200✔
3700
}
3701

3702
bool isStreamWindow(SStreamScanInfo* pInfo) {
1,290✔
3703
  return isIntervalWindow(pInfo) || isSessionWindow(pInfo) || isStateWindow(pInfo) || isCountWindow(pInfo) ||
1,383✔
3704
         isTimeSlice(pInfo);
93✔
3705
}
3706

3707
int32_t copyGetResultBlock(SSDataBlock* dest, TSKEY start, TSKEY end) {
3,264✔
3708
  int32_t code = blockDataEnsureCapacity(dest, 1);
3,264✔
3709
  if (code != TSDB_CODE_SUCCESS) {
3,264!
UNCOV
3710
    return code;
×
3711
  }
3712
  return appendDataToSpecialBlock(dest, &start, &end, NULL, NULL, NULL);
3,264✔
3713
}
3714

3715
int32_t deletePartName(SStateStore* pStore, SStreamState* pState, SSDataBlock* pBlock, int32_t *deleteNum) {
185✔
3716
  int32_t code = TSDB_CODE_SUCCESS;
185✔
3717
  int32_t lino = 0;
185✔
3718
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
375✔
3719
    // uid is the same as gid
3720
    SColumnInfoData* pGpIdCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
190✔
3721
    SColumnInfoData* pTbnameCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
190✔
3722
    int64_t*         gpIdCol = (int64_t*)pGpIdCol->pData;
190✔
3723
    void*            pParName = NULL;
190✔
3724
    int32_t          winCode = 0;
190✔
3725
    code = pStore->streamStateGetParName(pState, gpIdCol[i],
190✔
3726
                                                   &pParName, false, &winCode);
3727
    if (TSDB_CODE_SUCCESS == code && winCode != 0) {
190!
3728
      qDebug("delete stream part Name for:%"PRId64 " not found", gpIdCol[i]);
135!
3729
      colDataSetNULL(pTbnameCol, i);
135!
3730
      continue;
135✔
3731
    }
3732
    (*deleteNum)++;
55✔
3733
    QUERY_CHECK_CODE(code, lino, _end);
55!
3734
    char varTbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE + 1] = {0};
55✔
3735
    varDataSetLen(varTbName, strlen(pParName));
55✔
3736
    int64_t len = tsnprintf(varTbName + VARSTR_HEADER_SIZE, TSDB_TABLE_NAME_LEN + 1, "%s", pParName);
55✔
3737
    code = colDataSetVal(pTbnameCol, i, varTbName, false);
55✔
3738
    qDebug("delete stream part for:%"PRId64 " res tb: %s", gpIdCol[i], (char*)pParName);
55!
3739
    pStore->streamStateFreeVal(pParName);
55✔
3740
    QUERY_CHECK_CODE(code, lino, _end);
55!
3741
    code = pStore->streamStateDeleteParName(pState, gpIdCol[i]);
55✔
3742
    QUERY_CHECK_CODE(code, lino, _end);
55!
3743
    pBlock->info.id.groupId = gpIdCol[i];
55✔
3744
    // currently, only one valid row in pBlock
3745
    memcpy(pBlock->info.parTbName, varTbName + VARSTR_HEADER_SIZE, TSDB_TABLE_NAME_LEN + 1);
55✔
3746
  }
3747

3748
_end:
185✔
3749
  if (code != TSDB_CODE_SUCCESS) {
185!
UNCOV
3750
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3751
  }
3752
  return code;
185✔
3753
}
3754

3755
static int32_t doStreamScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
509,408✔
3756
  // NOTE: this operator does never check if current status is done or not
3757
  int32_t        code = TSDB_CODE_SUCCESS;
509,408✔
3758
  int32_t        lino = 0;
509,408✔
3759
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
509,408✔
3760
  const char*    id = GET_TASKID(pTaskInfo);
509,408✔
3761

3762
  SStorageAPI*     pAPI = &pTaskInfo->storageAPI;
509,408✔
3763
  SStreamScanInfo* pInfo = pOperator->info;
509,408✔
3764
  SStreamTaskInfo* pStreamInfo = &pTaskInfo->streamInfo;
509,408✔
3765

3766
  qDebug("stream scan started, %s", id);
509,408✔
3767

3768
  if (pStreamInfo->recoverStep == STREAM_RECOVER_STEP__PREPARE1 ||
509,395✔
3769
      pStreamInfo->recoverStep == STREAM_RECOVER_STEP__PREPARE2) {
507,079✔
3770
    STableScanInfo* pTSInfo = pInfo->pTableScanOp->info;
5,127✔
3771
    memcpy(&pTSInfo->base.cond, &pStreamInfo->tableCond, sizeof(SQueryTableDataCond));
5,127✔
3772

3773
    if (pStreamInfo->recoverStep == STREAM_RECOVER_STEP__PREPARE1) {
5,127✔
3774
      pTSInfo->base.cond.startVersion = pStreamInfo->fillHistoryVer.minVer;
2,345✔
3775
      pTSInfo->base.cond.endVersion = pStreamInfo->fillHistoryVer.maxVer;
2,345✔
3776

3777
      pTSInfo->base.cond.twindows = pStreamInfo->fillHistoryWindow;
2,345✔
3778
      qDebug("stream scan step1, verRange:%" PRId64 "-%" PRId64 " window:%" PRId64 "-%" PRId64 ", %s",
2,345✔
3779
             pTSInfo->base.cond.startVersion, pTSInfo->base.cond.endVersion, pTSInfo->base.cond.twindows.skey,
3780
             pTSInfo->base.cond.twindows.ekey, id);
3781
      pStreamInfo->recoverStep = STREAM_RECOVER_STEP__SCAN1;
2,344✔
3782
      pStreamInfo->recoverScanFinished = false;
2,344✔
3783
    } else {
3784
      pTSInfo->base.cond.startVersion = pStreamInfo->fillHistoryVer.minVer;
2,782✔
3785
      pTSInfo->base.cond.endVersion = pStreamInfo->fillHistoryVer.maxVer;
2,782✔
3786
      pTSInfo->base.cond.twindows = pStreamInfo->fillHistoryWindow;
2,782✔
3787
      qDebug("stream scan step2 (scan wal), verRange:%" PRId64 " - %" PRId64 ", window:%" PRId64 "-%" PRId64 ", %s",
2,782✔
3788
             pTSInfo->base.cond.startVersion, pTSInfo->base.cond.endVersion, pTSInfo->base.cond.twindows.skey,
3789
             pTSInfo->base.cond.twindows.ekey, id);
3790
      pStreamInfo->recoverStep = STREAM_RECOVER_STEP__NONE;
2,782✔
3791
    }
3792

3793
    pAPI->tsdReader.tsdReaderClose(pTSInfo->base.dataReader);
5,126✔
3794

3795
    pTSInfo->base.dataReader = NULL;
5,127✔
3796
    pInfo->pTableScanOp->status = OP_OPENED;
5,127✔
3797

3798
    pTSInfo->scanTimes = 0;
5,127✔
3799
    pTSInfo->currentGroupId = -1;
5,127✔
3800
  }
3801

3802
  if (pStreamInfo->recoverStep == STREAM_RECOVER_STEP__SCAN1) {
509,395✔
3803
    if (isTaskKilled(pTaskInfo)) {
85,953✔
3804
      qInfo("===stream===stream scan is killed. task id:%s, code %s", id, tstrerror(pTaskInfo->code));
2!
3805
      (*ppRes) = NULL;
2✔
3806
      return code;
2✔
3807
    }
3808

3809
    switch (pInfo->scanMode) {
85,951✔
3810
      case STREAM_SCAN_FROM_RES: {
2,247✔
3811
        pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
2,247✔
3812
        printSpecDataBlock(pInfo->pRecoverRes, getStreamOpName(pOperator->operatorType), "recover",
2,247✔
3813
                           GET_TASKID(pTaskInfo));
2,247✔
3814
        (*ppRes) = pInfo->pRecoverRes;
2,247✔
3815
        return code;
2,247✔
3816
      } break;
3817
      default:
83,704✔
3818
        break;
83,704✔
3819
    }
3820

3821
    code = doTableScanNext(pInfo->pTableScanOp, &pInfo->pRecoverRes);
83,704✔
3822
    QUERY_CHECK_CODE(code, lino, _end);
83,706!
3823

3824
    if (pInfo->pRecoverRes != NULL) {
83,706✔
3825
      code = calBlockTbName(pInfo, pInfo->pRecoverRes, 0);
81,363✔
3826
      QUERY_CHECK_CODE(code, lino, _end);
81,363!
3827
      if (!pInfo->igCheckUpdate && pInfo->pUpdateInfo) {
81,363✔
3828
        TSKEY maxTs = INT64_MIN;
80,390✔
3829
        code = pAPI->stateStore.updateInfoFillBlockData(pInfo->pUpdateInfo, pInfo->pRecoverRes, pInfo->primaryTsIndex,
80,390✔
3830
                                                        pInfo->primaryKeyIndex, &maxTs);
3831
        QUERY_CHECK_CODE(code, lino, _end);
80,390!
3832
        pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
80,390✔
3833
      }
3834
      if (pInfo->pCreateTbRes->info.rows > 0) {
81,363✔
3835
        pInfo->scanMode = STREAM_SCAN_FROM_RES;
2,247✔
3836
        printSpecDataBlock(pInfo->pCreateTbRes, getStreamOpName(pOperator->operatorType), "recover",
2,247✔
3837
                           GET_TASKID(pTaskInfo));
2,247✔
3838
        (*ppRes) = pInfo->pCreateTbRes;
2,247✔
3839
        return code;
2,247✔
3840
      }
3841

3842
      qDebug("stream recover scan get block, rows %" PRId64, pInfo->pRecoverRes->info.rows);
79,116✔
3843
      printSpecDataBlock(pInfo->pRecoverRes, getStreamOpName(pOperator->operatorType), "recover",
79,116✔
3844
                         GET_TASKID(pTaskInfo));
79,116✔
3845
      (*ppRes) = pInfo->pRecoverRes;
79,116✔
3846
      return code;
79,116✔
3847
    }
3848
    pStreamInfo->recoverStep = STREAM_RECOVER_STEP__NONE;
2,343✔
3849
    STableScanInfo* pTSInfo = pInfo->pTableScanOp->info;
2,343✔
3850
    pAPI->tsdReader.tsdReaderClose(pTSInfo->base.dataReader);
2,343✔
3851

3852
    pTSInfo->base.dataReader = NULL;
2,343✔
3853

3854
    pTSInfo->base.cond.startVersion = -1;
2,343✔
3855
    pTSInfo->base.cond.endVersion = -1;
2,343✔
3856

3857
    pStreamInfo->recoverScanFinished = true;
2,343✔
3858
    (*ppRes) = NULL;
2,343✔
3859
    return code;
2,343✔
3860
  }
3861

3862
  size_t total = taosArrayGetSize(pInfo->pBlockLists);
423,442✔
3863
// TODO: refactor
3864
FETCH_NEXT_BLOCK:
424,676✔
3865
  if (pInfo->blockType == STREAM_INPUT__DATA_BLOCK) {
424,676✔
3866
    if (pInfo->validBlockIndex >= total) {
18,175✔
3867
      doClearBufferedBlocks(pInfo);
3868
      (*ppRes) = NULL;
4,537✔
3869
      return code;
4,537✔
3870
    }
3871

3872
    int32_t current = pInfo->validBlockIndex++;
13,638✔
3873
    qDebug("process %d/%d input data blocks, %s", current, (int32_t)total, id);
13,638✔
3874

3875
    SPackedData* pPacked = taosArrayGet(pInfo->pBlockLists, current);
13,638✔
3876
    QUERY_CHECK_NULL(pPacked, code, lino, _end, terrno);
13,639!
3877

3878
    SSDataBlock* pBlock = pPacked->pDataBlock;
13,639✔
3879
    if (pBlock->info.parTbName[0]) {
13,639✔
3880
      code =
3881
          pAPI->stateStore.streamStatePutParName(pStreamInfo->pState, pBlock->info.id.groupId, pBlock->info.parTbName);
1,415✔
3882
      QUERY_CHECK_CODE(code, lino, _end);
1,415!
3883
    }
3884

3885
    // TODO move into scan
3886
    pBlock->info.calWin.skey = INT64_MIN;
13,639✔
3887
    pBlock->info.calWin.ekey = INT64_MAX;
13,639✔
3888
    pBlock->info.dataLoad = 1;
13,639✔
3889
    if (pInfo->pUpdateInfo) {
13,639✔
3890
      pInfo->pUpdateInfo->maxDataVersion = TMAX(pInfo->pUpdateInfo->maxDataVersion, pBlock->info.version);
8,095✔
3891
    }
3892

3893
    code = blockDataUpdateTsWindow(pBlock, 0);
13,639✔
3894
    QUERY_CHECK_CODE(code, lino, _end);
13,638!
3895
    switch (pBlock->info.type) {
13,638!
3896
      case STREAM_NORMAL:
3,698✔
3897
      case STREAM_GET_ALL:
3898
        printDataBlock(pBlock, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
3,698✔
3899
        setStreamOperatorState(&pInfo->basic, pBlock->info.type);
3,699✔
3900
        (*ppRes) = pBlock;
3,699✔
3901
        return code;
3,699✔
3902
      case STREAM_RETRIEVE: {
528✔
3903
        pInfo->blockType = STREAM_INPUT__DATA_SUBMIT;
528✔
3904
        pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RETRIEVE;
528✔
3905
        code = copyDataBlock(pInfo->pUpdateRes, pBlock);
528✔
3906
        QUERY_CHECK_CODE(code, lino, _end);
528!
3907
        pInfo->updateResIndex = 0;
528✔
3908
        prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex, NULL);
528✔
3909
        pAPI->stateStore.updateInfoAddCloseWindowSBF(pInfo->pUpdateInfo);
527✔
3910
      } break;
528✔
3911
      case STREAM_DELETE_DATA: {
2,425✔
3912
        printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "delete recv", GET_TASKID(pTaskInfo));
2,425✔
3913
        SSDataBlock* pDelBlock = NULL;
2,426✔
3914
        if (pInfo->tqReader) {
2,426!
3915
          code = createSpecialDataBlock(STREAM_DELETE_DATA, &pDelBlock);
2,426✔
3916
          QUERY_CHECK_CODE(code, lino, _end);
2,426!
3917

3918
          code = filterDelBlockByUid(pDelBlock, pBlock, pInfo->tqReader, &pInfo->readerFn);
2,426✔
3919
          QUERY_CHECK_CODE(code, lino, _end);
2,426!
3920
        } else {
UNCOV
3921
          pDelBlock = pBlock;
×
3922
        }
3923

3924
        code = setBlockGroupIdByUid(pInfo, pDelBlock);
2,426✔
3925
        QUERY_CHECK_CODE(code, lino, _end);
2,426!
3926
        code = rebuildDeleteBlockData(pDelBlock, &pStreamInfo->fillHistoryWindow, id);
2,426✔
3927
        QUERY_CHECK_CODE(code, lino, _end);
2,424!
3928
        printSpecDataBlock(pDelBlock, getStreamOpName(pOperator->operatorType), "delete recv filtered",
2,426✔
3929
                           GET_TASKID(pTaskInfo));
2,424✔
3930
        if (pDelBlock->info.rows == 0) {
2,426✔
3931
          if (pInfo->tqReader) {
1,136!
3932
            blockDataDestroy(pDelBlock);
1,136✔
3933
          }
3934
          goto FETCH_NEXT_BLOCK;
1,137✔
3935
        }
3936

3937
        if (!isStreamWindow(pInfo)) {
1,290✔
3938
          code = generateDeleteResultBlock(pInfo, pDelBlock, pInfo->pDeleteDataRes);
78✔
3939
          QUERY_CHECK_CODE(code, lino, _end);
78!
3940
          if (pInfo->partitionSup.needCalc) {
78✔
3941
            pInfo->pDeleteDataRes->info.type = STREAM_DELETE_DATA;
2✔
3942
          } else {
3943
            pInfo->pDeleteDataRes->info.type = STREAM_DELETE_RESULT;
76✔
3944
          }
3945
          blockDataDestroy(pDelBlock);
78✔
3946

3947
          if (pInfo->pDeleteDataRes->info.rows > 0) {
78!
3948
            printSpecDataBlock(pInfo->pDeleteDataRes, getStreamOpName(pOperator->operatorType), "delete result",
78✔
3949
                               GET_TASKID(pTaskInfo));
78✔
3950
            setStreamOperatorState(&pInfo->basic, pInfo->pDeleteDataRes->info.type);
78✔
3951
            (*ppRes) = pInfo->pDeleteDataRes;
78✔
3952
            return code;
1,289✔
3953
          } else {
UNCOV
3954
            goto FETCH_NEXT_BLOCK;
×
3955
          }
3956
        } else {
3957
          pInfo->blockType = STREAM_INPUT__DATA_SUBMIT;
1,212✔
3958
          pInfo->updateResIndex = 0;
1,212✔
3959
          code = generateScanRange(pInfo, pDelBlock, pInfo->pUpdateRes, STREAM_DELETE_DATA);
1,212✔
3960
          QUERY_CHECK_CODE(code, lino, _end);
1,212!
3961
          prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex, NULL);
1,212✔
3962
          code = copyDataBlock(pInfo->pDeleteDataRes, pInfo->pUpdateRes);
1,210✔
3963
          QUERY_CHECK_CODE(code, lino, _end);
1,212!
3964
          pInfo->pDeleteDataRes->info.type = STREAM_DELETE_DATA;
1,212✔
3965
          if (pInfo->tqReader) {
1,212!
3966
            blockDataDestroy(pDelBlock);
1,212✔
3967
          }
3968
          if (pInfo->pDeleteDataRes->info.rows > 0) {
1,212✔
3969
            pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RANGE;
1,211✔
3970
            printSpecDataBlock(pInfo->pDeleteDataRes, getStreamOpName(pOperator->operatorType), "delete result",
1,211✔
3971
                               GET_TASKID(pTaskInfo));
1,211✔
3972
            setStreamOperatorState(&pInfo->basic, pInfo->pDeleteDataRes->info.type);
1,211✔
3973
            (*ppRes) = pInfo->pDeleteDataRes;
1,211✔
3974
            return code;
1,211✔
3975
          } else {
3976
            goto FETCH_NEXT_BLOCK;
1✔
3977
          }
3978
        }
3979
      } break;
3980
      case STREAM_GET_RESULT: {
3,264✔
3981
        pInfo->blockType = STREAM_INPUT__DATA_SUBMIT;
3,264✔
3982
        pInfo->updateResIndex = 0;
3,264✔
3983
        pInfo->lastScanRange = pBlock->info.window;
3,264✔
3984
        TSKEY endKey = taosTimeGetIntervalEnd(pBlock->info.window.skey, &pInfo->interval);
3,264✔
3985
        if (pInfo->useGetResultRange == true) {
3,264✔
3986
          endKey = pBlock->info.window.ekey;
881✔
3987
        }
3988
        code = copyGetResultBlock(pInfo->pUpdateRes, pBlock->info.window.skey, endKey);
3,264✔
3989
        QUERY_CHECK_CODE(code, lino, _end);
3,264!
3990
        pInfo->pUpdateInfo->maxDataVersion = -1;
3,264✔
3991
        prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex, NULL);
3,264✔
3992
        pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RANGE;
3,264✔
3993
      } break;
3,264✔
3994
      case STREAM_DROP_CHILD_TABLE: {
185✔
3995
        int32_t deleteNum = 0;
185✔
3996
        code = deletePartName(&pInfo->stateStore, pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState, pBlock, &deleteNum);
185✔
3997
        QUERY_CHECK_CODE(code, lino, _end);
185!
3998
        if (deleteNum == 0) {
185✔
3999
          printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "block recv", GET_TASKID(pTaskInfo));
130✔
4000
          qDebug("===stream=== ignore block type 18, delete num is 0");
130!
4001
          goto FETCH_NEXT_BLOCK;
130✔
4002
        }
4003
      } break;
55✔
UNCOV
4004
      case STREAM_CHECKPOINT: {
×
UNCOV
4005
        qError("stream check point error. msg type: STREAM_INPUT__DATA_BLOCK");
×
UNCOV
4006
      } break;
×
4007
      default:
3,538✔
4008
        break;
3,538✔
4009
    }
4010
    printSpecDataBlock(pBlock, getStreamOpName(pOperator->operatorType), "block recv", GET_TASKID(pTaskInfo));
7,385✔
4011
    setStreamOperatorState(&pInfo->basic, pBlock->info.type);
7,385✔
4012
    (*ppRes) = pBlock;
7,385✔
4013
    return code;
7,385✔
4014
  } else if (pInfo->blockType == STREAM_INPUT__DATA_SUBMIT) {
406,501✔
4015
    qDebug("stream scan mode:%d, %s", pInfo->scanMode, id);
399,342✔
4016
    switch (pInfo->scanMode) {
399,325✔
4017
      case STREAM_SCAN_FROM_RES: {
1,523✔
4018
        pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
1,523✔
4019
        code = doCheckUpdate(pInfo, pInfo->pRes->info.window.ekey, pInfo->pRes);
1,523✔
4020
        QUERY_CHECK_CODE(code, lino, _end);
1,523!
4021
        setStreamOperatorState(&pInfo->basic, pInfo->pRes->info.type);
1,523✔
4022
        code = doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL);
1,522✔
4023
        QUERY_CHECK_CODE(code, lino, _end);
1,521!
4024
        pInfo->pRes->info.dataLoad = 1;
1,521✔
4025
        code = blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex);
1,521✔
4026
        QUERY_CHECK_CODE(code, lino, _end);
1,523!
4027
        if (pInfo->pRes->info.rows > 0) {
1,523!
4028
          printDataBlock(pInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
1,523✔
4029
          (*ppRes) = pInfo->pRes;
1,523✔
4030
          return code;
1,523✔
4031
        }
UNCOV
4032
      } break;
×
4033
      case STREAM_SCAN_FROM_DELETE_DATA: {
245✔
4034
        code = generateScanRange(pInfo, pInfo->pUpdateDataRes, pInfo->pUpdateRes, STREAM_PARTITION_DELETE_DATA);
245✔
4035
        QUERY_CHECK_CODE(code, lino, _end);
246!
4036
        if (pInfo->pUpdateRes->info.rows > 0) {
246✔
4037
          prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex, NULL);
212✔
4038
          pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RANGE;
212✔
4039
          code = copyDataBlock(pInfo->pDeleteDataRes, pInfo->pUpdateRes);
212✔
4040
          QUERY_CHECK_CODE(code, lino, _end);
212!
4041
          pInfo->pDeleteDataRes->info.type = STREAM_DELETE_DATA;
212✔
4042
          (*ppRes) = pInfo->pDeleteDataRes;
212✔
4043
          return code;
212✔
4044
        }
4045
        qError("%s===stream=== %s failed at line %d since pInfo->pUpdateRes is empty", GET_TASKID(pTaskInfo), __func__,
34!
4046
               __LINE__);
4047
        blockDataCleanup(pInfo->pUpdateDataRes);
34✔
4048
        pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
34✔
4049
      } break;
34✔
4050
      case STREAM_SCAN_FROM_UPDATERES: {
1,367✔
4051
        code = generateScanRange(pInfo, pInfo->pUpdateDataRes, pInfo->pUpdateRes, STREAM_CLEAR);
1,367✔
4052
        QUERY_CHECK_CODE(code, lino, _end);
1,364!
4053
        if (pInfo->pUpdateRes->info.rows > 0) {
1,364✔
4054
          prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex, NULL);
1,337✔
4055
          pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RANGE;
1,332✔
4056
          (*ppRes) = pInfo->pUpdateRes;
1,332✔
4057
          return code;
1,332✔
4058
        }
4059
        qError("%s===stream=== %s failed at line %d since pInfo->pUpdateRes is empty", GET_TASKID(pTaskInfo), __func__,
27!
4060
               __LINE__);
4061
        blockDataCleanup(pInfo->pUpdateDataRes);
27✔
4062
        pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
27✔
4063
      } break;
27✔
4064
      case STREAM_SCAN_FROM_DATAREADER_RANGE:
9,677✔
4065
      case STREAM_SCAN_FROM_DATAREADER_RETRIEVE: {
4066
        if (pInfo->pRangeScanRes != NULL) {
9,677✔
4067
          (*ppRes) = pInfo->pRangeScanRes;
21✔
4068
          pInfo->pRangeScanRes = NULL;
21✔
4069
          return code;
3,060✔
4070
        } 
4071
        SSDataBlock* pSDB = NULL;
9,656✔
4072
        code = doRangeScan(pInfo, pInfo->pUpdateRes, pInfo->primaryTsIndex, &pInfo->updateResIndex, &pSDB);
9,656✔
4073
        QUERY_CHECK_CODE(code, lino, _end);
9,658!
4074
        if (pSDB) {
9,658✔
4075
          STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info;
3,041✔
4076
          pSDB->info.type = pInfo->scanMode == STREAM_SCAN_FROM_DATAREADER_RANGE ? STREAM_NORMAL : STREAM_PULL_DATA;
3,041✔
4077
          if (!pInfo->igCheckUpdate && pInfo->pUpdateInfo) {
3,041!
4078
            code = checkUpdateData(pInfo, true, pSDB, false);
2,520✔
4079
            QUERY_CHECK_CODE(code, lino, _end);
2,520!
4080
          }
4081
          printSpecDataBlock(pSDB, getStreamOpName(pOperator->operatorType), "update", GET_TASKID(pTaskInfo));
3,041✔
4082
          code = calBlockTbName(pInfo, pSDB, 0);
3,040✔
4083
          QUERY_CHECK_CODE(code, lino, _end);
3,040!
4084

4085
          if (pInfo->pCreateTbRes->info.rows > 0) {
3,040✔
4086
            printSpecDataBlock(pInfo->pCreateTbRes, getStreamOpName(pOperator->operatorType), "update",
21✔
4087
                               GET_TASKID(pTaskInfo));
21✔
4088
            (*ppRes) = pInfo->pCreateTbRes;
20✔
4089
            pInfo->pRangeScanRes = pSDB;
20✔
4090
            return code;
20✔
4091
          }
4092

4093
          (*ppRes) = pSDB;
3,019✔
4094
          return code;
3,019✔
4095
        }
4096
        blockDataCleanup(pInfo->pUpdateDataRes);
6,617✔
4097
        pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
6,617✔
4098
      } break;
6,617✔
4099
      default:
386,513✔
4100
        break;
386,513✔
4101
    }
4102

4103
    if (hasScanRange(pInfo)) {
393,191✔
4104
      pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RANGE;
64✔
4105
      pInfo->updateResIndex = 0;
64✔
4106
      SStreamAggSupporter* pSup = pInfo->windowSup.pStreamAggSup;
64✔
4107
      code = copyDataBlock(pInfo->pUpdateRes, pSup->pScanBlock);
64✔
4108
      QUERY_CHECK_CODE(code, lino, _end);
64!
4109
      blockDataCleanup(pSup->pScanBlock);
64✔
4110
      prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex, NULL);
64✔
4111
      pInfo->pUpdateRes->info.type = STREAM_DELETE_DATA;
64✔
4112
      printSpecDataBlock(pInfo->pUpdateRes, getStreamOpName(pOperator->operatorType), "rebuild", GET_TASKID(pTaskInfo));
64✔
4113
      (*ppRes) = pInfo->pUpdateRes;
64✔
4114
      return code;
64✔
4115
    }
4116

4117
    SDataBlockInfo* pBlockInfo = &pInfo->pRes->info;
393,156✔
4118
    int32_t         totalBlocks = taosArrayGetSize(pInfo->pBlockLists);
393,156✔
4119

4120
  NEXT_SUBMIT_BLK:
393,144✔
4121
    while (1) {
4122
      if (pInfo->readerFn.tqReaderCurrentBlockConsumed(pInfo->tqReader)) {
863,544✔
4123
        if (pInfo->validBlockIndex >= totalBlocks) {
508,050✔
4124
          pAPI->stateStore.updateInfoDestoryColseWinSBF(pInfo->pUpdateInfo);
37,682✔
4125
          doClearBufferedBlocks(pInfo);
4126

4127
          qDebug("stream scan return empty, all %d submit blocks consumed, %s", totalBlocks, id);
37,673✔
4128
          (*ppRes) = NULL;
37,673✔
4129
          return code;
37,673✔
4130
        }
4131

4132
        int32_t      current = pInfo->validBlockIndex++;
470,368✔
4133
        SPackedData* pSubmit = taosArrayGet(pInfo->pBlockLists, current);
470,368✔
4134
        QUERY_CHECK_NULL(pSubmit, code, lino, _end, terrno);
470,340!
4135

4136
        qDebug("set %d/%d as the input submit block, %s", current + 1, totalBlocks, id);
470,340✔
4137
        if (pAPI->tqReaderFn.tqReaderSetSubmitMsg(pInfo->tqReader, pSubmit->msgStr, pSubmit->msgLen, pSubmit->ver, NULL) <
470,340!
4138
            0) {
UNCOV
4139
          qError("submit msg messed up when initializing stream submit block %p, current %d/%d, %s", pSubmit, current,
×
4140
                 totalBlocks, id);
UNCOV
4141
          continue;
×
4142
        }
4143
      }
4144

4145
      blockDataCleanup(pInfo->pRes);
825,828✔
4146

4147
      while (pAPI->tqReaderFn.tqNextBlockImpl(pInfo->tqReader, id)) {
867,836✔
4148
        SSDataBlock* pRes = NULL;
397,570✔
4149

4150
        code = pAPI->tqReaderFn.tqRetrieveBlock(pInfo->tqReader, &pRes, id);
397,570✔
4151
        qDebug("retrieve data from submit completed code:%s rows:%" PRId64 " %s", tstrerror(code), pRes->info.rows, id);
397,560✔
4152

4153
        if (code != TSDB_CODE_SUCCESS || pRes->info.rows == 0) {
397,565✔
4154
          qDebug("retrieve data failed, try next block in submit block, %s", id);
28✔
4155
          continue;
42,049✔
4156
        }
4157

4158
        code = setBlockIntoRes(pInfo, pRes, &pStreamInfo->fillHistoryWindow, false);
397,537✔
4159
        if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) {
397,530!
UNCOV
4160
          pInfo->pRes->info.rows = 0;
×
UNCOV
4161
          code = TSDB_CODE_SUCCESS;
×
4162
        } else {
4163
          QUERY_CHECK_CODE(code, lino, _end);
397,530!
4164
        }
4165

4166
        if (pInfo->pRes->info.rows == 0) {
397,530✔
4167
          continue;
42,024✔
4168
        }
4169

4170
        if (pInfo->pCreateTbRes->info.rows > 0) {
355,506✔
4171
          pInfo->scanMode = STREAM_SCAN_FROM_RES;
1,523✔
4172
          qDebug("create table res exists, rows:%" PRId64 " return from stream scan, %s",
1,523✔
4173
                 pInfo->pCreateTbRes->info.rows, id);
4174
          (*ppRes) = pInfo->pCreateTbRes;
1,523✔
4175
          return code;
1,523✔
4176
        }
4177

4178
        code = doCheckUpdate(pInfo, pBlockInfo->window.ekey, pInfo->pRes);
353,983✔
4179
        QUERY_CHECK_CODE(code, lino, _end);
353,979!
4180
        setStreamOperatorState(&pInfo->basic, pInfo->pRes->info.type);
353,979✔
4181
        code = doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL);
353,976✔
4182
        QUERY_CHECK_CODE(code, lino, _end);
353,956!
4183

4184
        code = blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex);
353,956✔
4185
        QUERY_CHECK_CODE(code, lino, _end);
353,971!
4186

4187
        int64_t numOfUpdateRes = pInfo->pUpdateDataRes->info.rows;
353,971✔
4188
        qDebug("%s %" PRId64 " rows in datablock, update res:%" PRId64, id, pBlockInfo->rows, numOfUpdateRes);
353,971✔
4189
        if (pBlockInfo->rows > 0 || numOfUpdateRes > 0) {
353,969✔
4190
          break;
4191
        }
4192
      }
4193

4194
      if (pBlockInfo->rows > 0 || pInfo->pUpdateDataRes->info.rows > 0) {
824,331✔
4195
        break;
4196
      } else {
4197
        continue;
470,400✔
4198
      }
4199
    }
4200

4201
    // record the scan action.
4202
    pInfo->numOfExec++;
353,931✔
4203
    pOperator->resultInfo.totalRows += pBlockInfo->rows;
353,931✔
4204

4205
    qDebug("stream scan completed, and return source rows:%" PRId64 ", %s", pBlockInfo->rows, id);
353,931✔
4206
    if (pBlockInfo->rows > 0) {
353,973✔
4207
      printDataBlock(pInfo->pRes, getStreamOpName(pOperator->operatorType), GET_TASKID(pTaskInfo));
353,969✔
4208
      (*ppRes) = pInfo->pRes;
353,946✔
4209
      return code;
353,946✔
4210
    }
4211

4212
    if (pInfo->pUpdateDataRes->info.rows > 0) {
4!
UNCOV
4213
      goto FETCH_NEXT_BLOCK;
×
4214
    }
4215

4216
    goto NEXT_SUBMIT_BLK;
7✔
4217
  } else if (pInfo->blockType == STREAM_INPUT__CHECKPOINT) {
7,159!
4218
    if (pInfo->validBlockIndex >= total) {
7,202✔
4219
      doClearBufferedBlocks(pInfo);
4220
      (*ppRes) = NULL;
3,601✔
4221
      return code;
3,601✔
4222
    }
4223

4224
    int32_t current = pInfo->validBlockIndex++;
3,601✔
4225
    qDebug("process %d/%d input data blocks, %s", current, (int32_t)total, id);
3,601✔
4226

4227
    SPackedData* pData = taosArrayGet(pInfo->pBlockLists, current);
3,601✔
4228
    QUERY_CHECK_NULL(pData, code, lino, _end, terrno);
3,601!
4229
    SSDataBlock* pBlock = taosArrayGet(pData->pDataBlock, 0);
3,601✔
4230
    QUERY_CHECK_NULL(pBlock, code, lino, _end, terrno);
3,601!
4231

4232
    if (pBlock->info.type == STREAM_CHECKPOINT) {
3,601!
4233
      streamScanOperatorSaveCheckpoint(pInfo);
3,601✔
4234
    }
4235
    // printDataBlock(pInfo->pCheckpointRes, "stream scan ck", GET_TASKID(pTaskInfo));
4236
    (*ppRes) = pInfo->pCheckpointRes;
3,601✔
4237
    return code;
3,601✔
4238
  } else {
UNCOV
4239
    qError("stream scan error, invalid block type %d, %s", pInfo->blockType, id);
×
UNCOV
4240
    code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4241
  }
4242

4243
_end:
×
4244
  if (code != TSDB_CODE_SUCCESS) {
×
4245
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4246
    pTaskInfo->code = code;
×
4247
    T_LONG_JMP(pTaskInfo->env, code);
×
4248
  }
UNCOV
4249
  (*ppRes) = NULL;
×
4250
  return code;
×
4251
}
4252

UNCOV
4253
static SSDataBlock* doStreamScan(SOperatorInfo* pOperator) {
×
UNCOV
4254
  SSDataBlock* pRes = NULL;
×
UNCOV
4255
  int32_t      code = doStreamScanNext(pOperator, &pRes);
×
UNCOV
4256
  return pRes;
×
4257
}
4258
int32_t extractTableIdList(const STableListInfo* pTableListInfo, SArray** ppArrayRes) {
8,472✔
4259
  int32_t code = TSDB_CODE_SUCCESS;
8,472✔
4260
  int32_t lino = 0;
8,472✔
4261
  SArray* tableIdList = taosArrayInit(4, sizeof(uint64_t));
8,472✔
4262
  QUERY_CHECK_NULL(tableIdList, code, lino, _end, terrno);
8,479!
4263

4264
  // Transfer the Array of STableKeyInfo into uid list.
4265
  int32_t size = 0;
8,479✔
4266
  code = tableListGetSize(pTableListInfo, &size);
8,479✔
4267
  QUERY_CHECK_CODE(code, lino, _end);
8,479!
4268
  for (int32_t i = 0; i < size; ++i) {
189,292✔
4269
    STableKeyInfo* pkeyInfo = tableListGetInfo(pTableListInfo, i);
180,813✔
4270
    QUERY_CHECK_NULL(pkeyInfo, code, lino, _end, terrno);
180,737!
4271
    void* tmp = taosArrayPush(tableIdList, &pkeyInfo->uid);
180,737✔
4272
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
180,813!
4273
  }
4274

4275
  (*ppArrayRes) = tableIdList;
8,479✔
4276

4277
_end:
8,479✔
4278
  if (code != TSDB_CODE_SUCCESS) {
8,479!
4279
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4280
  }
4281
  return code;
8,477✔
4282
}
4283

4284
static int32_t doRawScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
5,046✔
4285
  int32_t        code = TSDB_CODE_SUCCESS;
5,046✔
4286
  int32_t        lino = 0;
5,046✔
4287
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
5,046✔
4288
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
5,046✔
4289

4290
  SStreamRawScanInfo* pInfo = pOperator->info;
5,046✔
4291
  pTaskInfo->streamInfo.btMetaRsp.batchMetaReq = NULL;  // use batchMetaReq != NULL to judge if data is meta
5,046✔
4292
  pTaskInfo->streamInfo.btMetaRsp.batchMetaLen = NULL;
5,046✔
4293

4294
  qDebug("tmqsnap doRawScan called");
5,046✔
4295
  if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) {
5,046✔
4296
    bool hasNext = false;
5,030✔
4297
    if (pInfo->dataReader && pInfo->sContext->withMeta != ONLY_META) {
5,030!
4298
      code = pAPI->tsdReader.tsdNextDataBlock(pInfo->dataReader, &hasNext);
5,025✔
4299
      if (code != TSDB_CODE_SUCCESS) {
5,022!
UNCOV
4300
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->dataReader);
×
4301
        QUERY_CHECK_CODE(code, lino, _end);
×
4302
      }
4303
    }
4304

4305
    if (pInfo->dataReader && hasNext) {
5,027✔
4306
      if (isTaskKilled(pTaskInfo)) {
2,525!
UNCOV
4307
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->dataReader);
×
4308
        return code;
2,524✔
4309
      }
4310

4311
      SSDataBlock* pBlock = NULL;
2,525✔
4312
      code = pAPI->tsdReader.tsdReaderRetrieveDataBlock(pInfo->dataReader, &pBlock, NULL);
2,525✔
4313
      QUERY_CHECK_CODE(code, lino, _end);
2,525!
4314

4315
      if (pBlock && pBlock->info.rows > 0) {
2,525!
4316
        bool hasPrimaryKey = pAPI->snapshotFn.taosXGetTablePrimaryKey(pInfo->sContext);
2,525✔
4317
        code = processPrimaryKey(pBlock, hasPrimaryKey, &pTaskInfo->streamInfo.currentOffset);
2,525✔
4318
        QUERY_CHECK_CODE(code, lino, _end);
2,524!
4319
        qDebug("tmqsnap doRawScan get data uid:%" PRId64 "", pBlock->info.id.uid);
2,524✔
4320
        (*ppRes) = pBlock;
2,524✔
4321
        return code;
2,524✔
4322
      }
4323
    }
4324

4325
    SMetaTableInfo mtInfo = {0};
2,502✔
4326
    code = pAPI->snapshotFn.getMetaTableInfoFromSnapshot(pInfo->sContext, &mtInfo);
2,502✔
4327
    QUERY_CHECK_CODE(code, lino, _end);
2,506!
4328
    if (code != 0) {
2,506!
4329
      destroyMetaTableInfo(&mtInfo);
UNCOV
4330
      QUERY_CHECK_CODE(code, lino, _end);
×
4331
    }
4332
    STqOffsetVal offset = {0};
2,506✔
4333
    if (mtInfo.uid == 0 || pInfo->sContext->withMeta == ONLY_META) {  // read snapshot done, change to get data from wal
2,506!
4334
      qDebug("tmqsnap read snapshot done, change to get data from wal");
29✔
4335
      tqOffsetResetToLog(&offset, pInfo->sContext->snapVersion + 1);
29✔
4336
    } else {
4337
      SValue val = {0};
2,477✔
4338
      tqOffsetResetToData(&offset, mtInfo.uid, INT64_MIN, val);
2,477!
4339
      qDebug("tmqsnap change get data uid:%" PRId64 "", mtInfo.uid);
2,477✔
4340
    }
4341
    destroyMetaTableInfo(&mtInfo);
4342
    code = qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType);
2,506✔
4343
    QUERY_CHECK_CODE(code, lino, _end);
2,505!
4344
    (*ppRes) = NULL;
2,505✔
4345
    return code;
2,505✔
4346
  } else if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_META) {
16!
4347
    SSnapContext* sContext = pInfo->sContext;
16✔
4348
    for (int32_t i = 0; i < tmqRowSize; i++) {
143!
4349
      void*   data = NULL;
143✔
4350
      int32_t dataLen = 0;
143✔
4351
      int16_t type = 0;
143✔
4352
      int64_t uid = 0;
143✔
4353
      if (pAPI->snapshotFn.getTableInfoFromSnapshot(sContext, &data, &dataLen, &type, &uid) < 0) {
143!
UNCOV
4354
        qError("tmqsnap getTableInfoFromSnapshot error");
×
UNCOV
4355
        taosMemoryFreeClear(data);
×
4356
        break;
16✔
4357
      }
4358

4359
      if (!sContext->queryMeta) {  // change to get data next poll request
143✔
4360
        STqOffsetVal offset = {0};
16✔
4361
        SValue       val = {0};
16!
4362
        tqOffsetResetToData(&offset, 0, INT64_MIN, val);
16✔
4363
        code = qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType);
16✔
4364
        QUERY_CHECK_CODE(code, lino, _end);
16!
4365
        break;
16✔
4366
      } else {
4367
        tqOffsetResetToMeta(&pTaskInfo->streamInfo.currentOffset, uid);
127✔
4368
        SMqMetaRsp tmpMetaRsp = {0};
127✔
4369
        tmpMetaRsp.resMsgType = type;
127✔
4370
        tmpMetaRsp.metaRspLen = dataLen;
127✔
4371
        tmpMetaRsp.metaRsp = data;
127✔
4372
        if (!pTaskInfo->streamInfo.btMetaRsp.batchMetaReq) {
127✔
4373
          pTaskInfo->streamInfo.btMetaRsp.batchMetaReq = taosArrayInit(4, POINTER_BYTES);
14✔
4374
          QUERY_CHECK_NULL(pTaskInfo->streamInfo.btMetaRsp.batchMetaReq, code, lino, _end, terrno);
14!
4375

4376
          pTaskInfo->streamInfo.btMetaRsp.batchMetaLen = taosArrayInit(4, sizeof(int32_t));
14✔
4377
          QUERY_CHECK_NULL(pTaskInfo->streamInfo.btMetaRsp.batchMetaLen, code, lino, _end, terrno);
14!
4378
        }
4379
        int32_t  tempRes = TSDB_CODE_SUCCESS;
127✔
4380
        uint32_t len = 0;
127✔
4381
        tEncodeSize(tEncodeMqMetaRsp, &tmpMetaRsp, len, tempRes);
127!
4382
        if (TSDB_CODE_SUCCESS != tempRes) {
127!
UNCOV
4383
          qError("tmqsnap tEncodeMqMetaRsp error");
×
UNCOV
4384
          taosMemoryFreeClear(data);
×
UNCOV
4385
          break;
×
4386
        }
4387

4388
        int32_t tLen = sizeof(SMqRspHead) + len;
127✔
4389
        void*   tBuf = taosMemoryCalloc(1, tLen);
127!
4390
        QUERY_CHECK_NULL(tBuf, code, lino, _end, terrno);
127!
4391

4392
        void*    metaBuff = POINTER_SHIFT(tBuf, sizeof(SMqRspHead));
127✔
4393
        SEncoder encoder = {0};
127✔
4394
        tEncoderInit(&encoder, metaBuff, len);
127✔
4395
        int32_t tempLen = tEncodeMqMetaRsp(&encoder, &tmpMetaRsp);
127✔
4396
        if (tempLen < 0) {
127!
UNCOV
4397
          qError("tmqsnap tEncodeMqMetaRsp error");
×
UNCOV
4398
          tEncoderClear(&encoder);
×
UNCOV
4399
          taosMemoryFreeClear(tBuf);
×
4400
          taosMemoryFreeClear(data);
×
UNCOV
4401
          break;
×
4402
        }
4403
        taosMemoryFreeClear(data);
127!
4404
        void* tmp = taosArrayPush(pTaskInfo->streamInfo.btMetaRsp.batchMetaReq, &tBuf);
127✔
4405
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
127!
4406

4407
        tmp = taosArrayPush(pTaskInfo->streamInfo.btMetaRsp.batchMetaLen, &tLen);
127✔
4408
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
127!
4409
      }
4410
    }
4411

4412
    (*ppRes) = NULL;
16✔
4413
    return code;
16✔
4414
  }
4415

UNCOV
4416
_end:
×
UNCOV
4417
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
4418
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
4419
    pTaskInfo->code = code;
×
UNCOV
4420
    T_LONG_JMP(pTaskInfo->env, code);
×
4421
  }
4422

UNCOV
4423
  (*ppRes) = NULL;
×
UNCOV
4424
  return code;
×
4425
}
4426

4427
static void destroyRawScanOperatorInfo(void* param) {
308✔
4428
  SStreamRawScanInfo* pRawScan = (SStreamRawScanInfo*)param;
308✔
4429
  pRawScan->pAPI->tsdReader.tsdReaderClose(pRawScan->dataReader);
308✔
4430
  pRawScan->pAPI->snapshotFn.destroySnapshot(pRawScan->sContext);
308✔
4431
  tableListDestroy(pRawScan->pTableListInfo);
308✔
4432
  taosMemoryFree(pRawScan);
308!
4433
}
308✔
4434

4435
// for subscribing db or stb (not including column),
4436
// if this scan is used, meta data can be return
4437
// and schemas are decided when scanning
4438
int32_t createRawScanOperatorInfo(SReadHandle* pHandle, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
307✔
4439
  // create operator
4440
  // create tb reader
4441
  // create meta reader
4442
  // create tq reader
4443

4444
  QRY_PARAM_CHECK(pOptrInfo);
307!
4445
  int32_t code = TSDB_CODE_SUCCESS;
307✔
4446
  int32_t lino = 0;
307✔
4447

4448
  SStreamRawScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamRawScanInfo));
307!
4449
  SOperatorInfo*      pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
308!
4450
  if (pInfo == NULL || pOperator == NULL) {
308!
UNCOV
4451
    code = terrno;
×
UNCOV
4452
    lino = __LINE__;
×
UNCOV
4453
    goto _end;
×
4454
  }
4455

4456
  pInfo->pTableListInfo = tableListCreate();
308✔
4457
  QUERY_CHECK_NULL(pInfo->pTableListInfo, code, lino, _end, terrno);
308!
4458
  pInfo->vnode = pHandle->vnode;
308✔
4459
  pInfo->pAPI = &pTaskInfo->storageAPI;
308✔
4460

4461
  pInfo->sContext = pHandle->sContext;
308✔
4462
  setOperatorInfo(pOperator, "RawScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, false, OP_NOT_OPENED, pInfo,
308✔
4463
                  pTaskInfo);
4464

4465
  pOperator->fpSet = createOperatorFpSet(NULL, doRawScanNext, NULL, destroyRawScanOperatorInfo, optrDefaultBufFn, NULL,
308✔
4466
                                         optrDefaultGetNextExtFn, NULL);
4467
  *pOptrInfo = pOperator;
308✔
4468
  return code;
308✔
4469

UNCOV
4470
_end:
×
UNCOV
4471
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
4472
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4473
  }
UNCOV
4474
  taosMemoryFree(pInfo);
×
UNCOV
4475
  taosMemoryFree(pOperator);
×
UNCOV
4476
  pTaskInfo->code = code;
×
4477
  return code;
×
4478
}
4479

4480
void destroyStreamScanOperatorInfo(void* param) {
8,710✔
4481
  if (param == NULL) {
8,710!
UNCOV
4482
    return;
×
4483
  }
4484

4485
  SStreamScanInfo* pStreamScan = (SStreamScanInfo*)param;
8,710✔
4486
  if (pStreamScan->pTableScanOp && pStreamScan->pTableScanOp->info) {
8,710✔
4487
    destroyOperator(pStreamScan->pTableScanOp);
8,431✔
4488
  }
4489

4490
  if (pStreamScan->tqReader != NULL && pStreamScan->readerFn.tqReaderClose != NULL) {
8,713!
4491
    pStreamScan->readerFn.tqReaderClose(pStreamScan->tqReader);
8,434✔
4492
  }
4493
  if (pStreamScan->pVtableMergeHandles) {
8,714!
NEW
4494
    taosHashCleanup(pStreamScan->pVtableMergeHandles);
×
NEW
4495
    pStreamScan->pVtableMergeHandles = NULL;
×
4496
  }
4497
  if (pStreamScan->matchInfo.pList) {
8,714!
4498
    taosArrayDestroy(pStreamScan->matchInfo.pList);
8,717✔
4499
  }
4500
  if (pStreamScan->pPseudoExpr) {
8,714✔
4501
    destroyExprInfo(pStreamScan->pPseudoExpr, pStreamScan->numOfPseudoExpr);
5,174✔
4502
    taosMemoryFree(pStreamScan->pPseudoExpr);
5,174!
4503
  }
4504

4505
  cleanupExprSupp(&pStreamScan->tbnameCalSup);
8,714✔
4506
  cleanupExprSupp(&pStreamScan->tagCalSup);
8,717✔
4507

4508
  if (pStreamScan->stateStore.updateInfoDestroy) {
8,717!
4509
    pStreamScan->stateStore.updateInfoDestroy(pStreamScan->pUpdateInfo);
8,717✔
4510
  }
4511

4512
  blockDataDestroy(pStreamScan->pRes);
8,716✔
4513
  blockDataDestroy(pStreamScan->pUpdateRes);
8,717✔
4514
  blockDataDestroy(pStreamScan->pDeleteDataRes);
8,716✔
4515
  blockDataDestroy(pStreamScan->pUpdateDataRes);
8,717✔
4516
  blockDataDestroy(pStreamScan->pCreateTbRes);
8,717✔
4517
  taosArrayDestroy(pStreamScan->pBlockLists);
8,717✔
4518
  blockDataDestroy(pStreamScan->pCheckpointRes);
8,717✔
4519

4520
  taosMemoryFree(pStreamScan);
8,716!
4521
}
4522

4523
void streamScanReleaseState(SOperatorInfo* pOperator) {
2,221✔
4524
  int32_t          code = TSDB_CODE_SUCCESS;
2,221✔
4525
  int32_t          lino = 0;
2,221✔
4526
  SStreamScanInfo* pInfo = pOperator->info;
2,221✔
4527
  void*            pBuff = NULL;
2,221✔
4528
  SEncoder*        pEnCoder = NULL;
2,221✔
4529
  SEncoder*        pScanEnCoder = NULL;
2,221✔
4530
  if (!pInfo->pState) {
2,221!
4531
    return;
461✔
4532
  }
4533
  if (!pInfo->pUpdateInfo) {
2,221✔
4534
    qDebug("stask:%s streamScanReleaseState cancel", GET_TASKID(pOperator->pTaskInfo));
461✔
4535
    return;
461✔
4536
  }
4537
  int32_t  len = 0;
1,760✔
4538
  SEncoder encoder = {0};
1,760✔
4539
  pEnCoder = &encoder;
1,760✔
4540
  tEncoderInit(pEnCoder, NULL, 0);
1,760✔
4541
  if (tStartEncode(pEnCoder) != 0) {
1,760!
UNCOV
4542
    code = TSDB_CODE_FAILED;
×
UNCOV
4543
    QUERY_CHECK_CODE(code, lino, _end);
×
4544
  }
4545
  code = pInfo->stateStore.updateInfoSerialize(pEnCoder, pInfo->pUpdateInfo);
1,760✔
4546
  QUERY_CHECK_CODE(code, lino, _end);
1,760!
4547

4548
  tEndEncode(pEnCoder);
1,760✔
4549
  len += encoder.pos;
1,760✔
4550
  tEncoderClear(pEnCoder);
1,760✔
4551
  pEnCoder = NULL;
1,760✔
4552

4553
  pBuff = taosMemoryCalloc(1, len);
1,760!
4554
  if (!pBuff) {
1,760!
UNCOV
4555
    code = terrno;
×
UNCOV
4556
    QUERY_CHECK_CODE(code, lino, _end);
×
4557
  }
4558

4559
  SEncoder scanEncoder = {0};
1,760✔
4560
  pScanEnCoder = &scanEncoder;
1,760✔
4561
  tEncoderInit(pScanEnCoder, pBuff, len);
1,760✔
4562
  if (tStartEncode(pScanEnCoder) != 0) {
1,760!
UNCOV
4563
    code = TSDB_CODE_FAILED;
×
UNCOV
4564
    QUERY_CHECK_CODE(code, lino, _end);
×
4565
  }
4566
  code = pInfo->stateStore.updateInfoSerialize(pScanEnCoder, pInfo->pUpdateInfo);
1,760✔
4567
  QUERY_CHECK_CODE(code, lino, _end);
1,760!
4568

4569
  tEndEncode(pScanEnCoder);
1,760✔
4570
  tEncoderClear(pScanEnCoder);
1,760✔
4571
  pScanEnCoder = NULL;
1,760✔
4572

4573
  pInfo->stateStore.streamStateSaveInfo(pInfo->pState, STREAM_SCAN_OP_STATE_NAME, strlen(STREAM_SCAN_OP_STATE_NAME),
1,760✔
4574
                                        pBuff, len);
4575
_end:
1,760✔
4576
  if (code != TSDB_CODE_SUCCESS) {
1,760!
UNCOV
4577
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4578
  }
4579
  if (pEnCoder != NULL) {
1,760!
UNCOV
4580
    tEndEncode(pEnCoder);
×
UNCOV
4581
    tEncoderClear(pEnCoder);
×
4582
  }
4583
  if (pScanEnCoder != NULL) {
1,760!
UNCOV
4584
    tEndEncode(pScanEnCoder);
×
UNCOV
4585
    tEncoderClear(pScanEnCoder);
×
4586
  }
4587
  taosMemoryFree(pBuff);
1,760!
4588
}
4589

4590
void streamScanReloadState(SOperatorInfo* pOperator) {
2,221✔
4591
  int32_t          code = TSDB_CODE_SUCCESS;
2,221✔
4592
  int32_t          lino = 0;
2,221✔
4593
  SDecoder*        pDeCoder = NULL;
2,221✔
4594
  SStreamScanInfo* pInfo = pOperator->info;
2,221✔
4595
  if (!pInfo->pState) {
2,221!
4596
    return;
461✔
4597
  }
4598
  if (!pInfo->pUpdateInfo) {
2,221✔
4599
    qDebug("stask:%s streamScanReloadState cancel", GET_TASKID(pOperator->pTaskInfo));
461✔
4600
    return;
461✔
4601
  }
4602
  void*   pBuff = NULL;
1,760✔
4603
  int32_t len = 0;
1,760✔
4604
  code = pInfo->stateStore.streamStateGetInfo(pInfo->pState, STREAM_SCAN_OP_STATE_NAME,
1,760✔
4605
                                              strlen(STREAM_SCAN_OP_STATE_NAME), &pBuff, &len);
4606
  QUERY_CHECK_CODE(code, lino, _end);
1,760!
4607

4608
  SUpdateInfo* pUpInfo = taosMemoryCalloc(1, sizeof(SUpdateInfo));
1,760!
4609
  if (!pUpInfo) {
1,760!
UNCOV
4610
    code = terrno;
×
UNCOV
4611
    QUERY_CHECK_CODE(code, lino, _end);
×
4612
  }
4613

4614
  SDecoder decoder = {0};
1,760✔
4615
  pDeCoder = &decoder;
1,760✔
4616
  tDecoderInit(pDeCoder, pBuff, len);
1,760✔
4617
  if (tStartDecode(pDeCoder) < 0) {
1,760!
UNCOV
4618
    lino = __LINE__;
×
UNCOV
4619
    goto _end;
×
4620
  }
4621
  int32_t winCode = pInfo->stateStore.updateInfoDeserialize(pDeCoder, pUpInfo);
1,760✔
4622
  taosMemoryFree(pBuff);
1,760!
4623
  if (winCode == TSDB_CODE_SUCCESS && pInfo->pUpdateInfo) {
1,760!
4624
    if (pInfo->pUpdateInfo->minTS < 0) {
1,760✔
4625
      pInfo->stateStore.updateInfoDestroy(pInfo->pUpdateInfo);
1,757✔
4626
      pInfo->pUpdateInfo = pUpInfo;
1,757✔
4627
    } else {
4628
      pInfo->stateStore.windowSBfDelete(pInfo->pUpdateInfo, 1);
3✔
4629
      code = pInfo->stateStore.windowSBfAdd(pInfo->pUpdateInfo, 1);
3✔
4630
      QUERY_CHECK_CODE(code, lino, _end);
3!
4631

4632
      QUERY_CHECK_CONDITION((pInfo->pUpdateInfo->minTS > pUpInfo->minTS), code, lino, _end,
3!
4633
                            TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
4634
      pInfo->pUpdateInfo->maxDataVersion = TMAX(pInfo->pUpdateInfo->maxDataVersion, pUpInfo->maxDataVersion);
3✔
4635
      SHashObj* curMap = pInfo->pUpdateInfo->pMap;
3✔
4636
      void*     pIte = taosHashIterate(curMap, NULL);
3✔
4637
      while (pIte != NULL) {
863✔
4638
        size_t   keySize = 0;
860✔
4639
        int64_t* pUid = taosHashGetKey(pIte, &keySize);
860✔
4640
        code = taosHashPut(pUpInfo->pMap, pUid, sizeof(int64_t), pIte, sizeof(TSKEY));
860✔
4641
        if (code == TSDB_CODE_DUP_KEY) {
860!
UNCOV
4642
          code = TSDB_CODE_SUCCESS;
×
4643
        }
4644
        QUERY_CHECK_CODE(code, lino, _end);
860!
4645

4646
        pIte = taosHashIterate(curMap, pIte);
860✔
4647
      }
4648
      taosHashCleanup(curMap);
3✔
4649
      pInfo->pUpdateInfo->pMap = pUpInfo->pMap;
3✔
4650
      pUpInfo->pMap = NULL;
3✔
4651
      pInfo->stateStore.updateInfoDestroy(pUpInfo);
3✔
4652
    }
4653
  } else {
UNCOV
4654
    pInfo->stateStore.updateInfoDestroy(pUpInfo);
×
4655
  }
4656

4657
_end:
1,760✔
4658
  if (pDeCoder != NULL) {
1,760!
4659
    tEndDecode(pDeCoder);
1,760✔
4660
    tDecoderClear(pDeCoder);
1,760✔
4661
  }
4662
  if (code != TSDB_CODE_SUCCESS) {
1,760!
UNCOV
4663
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4664
  }
4665
}
4666

4667
int32_t addPrimaryKeyCol(SSDataBlock* pBlock, uint8_t type, int32_t bytes) {
85✔
4668
  int32_t code = TSDB_CODE_SUCCESS;
85✔
4669
  int32_t lino = 0;
85✔
4670
  pBlock->info.rowSize += bytes;
85✔
4671
  SColumnInfoData infoData = {0};
85✔
4672
  infoData.info.type = type;
85✔
4673
  infoData.info.bytes = bytes;
85✔
4674
  void* tmp = taosArrayPush(pBlock->pDataBlock, &infoData);
85✔
4675
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
85!
4676

4677
_end:
85✔
4678
  if (code != TSDB_CODE_SUCCESS) {
85!
UNCOV
4679
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4680
  }
4681
  return code;
85✔
4682
}
4683

NEW
4684
static int32_t createStreamVtableBlock(SColMatchInfo *pMatchInfo, SSDataBlock **ppRes, const char *idstr) {
×
NEW
4685
  int32_t code = TSDB_CODE_SUCCESS;
×
NEW
4686
  int32_t lino = 0;
×
NEW
4687
  SSDataBlock *pRes = NULL;
×
4688

NEW
4689
  QUERY_CHECK_NULL(pMatchInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
4690

NEW
4691
  *ppRes = NULL;
×
4692

NEW
4693
  code = createDataBlock(&pRes);
×
NEW
4694
  QUERY_CHECK_CODE(code, lino, _end);
×
NEW
4695
  int32_t numOfOutput = taosArrayGetSize(pMatchInfo->pList);
×
NEW
4696
  for (int32_t i = 0; i < numOfOutput; ++i) {
×
NEW
4697
    SColMatchItem*  pItem = taosArrayGet(pMatchInfo->pList, i);
×
NEW
4698
    if (!pItem->needOutput) {
×
NEW
4699
      continue;
×
4700
    }
NEW
4701
    SColumnInfoData colInfo = createColumnInfoData(pItem->dataType.type, pItem->dataType.bytes, pItem->colId);
×
NEW
4702
    code = blockDataAppendColInfo(pRes, &colInfo);
×
NEW
4703
    QUERY_CHECK_CODE(code, lino, _end);
×
4704
  }
4705

NEW
4706
  *ppRes = pRes;
×
NEW
4707
  pRes = NULL;
×
4708

4709

NEW
4710
_end:
×
NEW
4711
  if (code != TSDB_CODE_SUCCESS) {
×
NEW
4712
    qError("%s failed at line %d since %s, id: %s", __func__, lino, tstrerror(code), idstr);
×
4713
  }
NEW
4714
  if (pRes != NULL) {
×
NEW
4715
    blockDataDestroy(pRes);
×
4716
  }
NEW
4717
  return code;
×
4718
}
4719

4720
static int32_t createStreamNormalScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode,
8,715✔
4721
                                                  SNode* pTagCond, STableListInfo* pTableListInfo,
4722
                                                  SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
4723
  QRY_PARAM_CHECK(pOptrInfo);
8,715!
4724

4725
  int32_t          code = TSDB_CODE_SUCCESS;
8,715✔
4726
  int32_t          lino = 0;
8,715✔
4727
  SArray*          pColIds = NULL;
8,715✔
4728
  SStreamScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamScanInfo));
8,715!
4729
  SOperatorInfo*   pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
8,717!
4730
  SStorageAPI*     pAPI = &pTaskInfo->storageAPI;
8,717✔
4731
  const char*      idstr = pTaskInfo->id.str;
8,717✔
4732
  SSHashObj*       pVtableInfos = pTaskInfo->pSubplan->pVTables;
8,717✔
4733

4734
  if (pInfo == NULL || pOperator == NULL) {
8,717!
UNCOV
4735
    code = terrno;
×
UNCOV
4736
    goto _error;
×
4737
  }
4738

4739
  SScanPhysiNode*     pScanPhyNode = &pTableScanNode->scan;
8,717✔
4740
  SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc;
8,717✔
4741

4742
  pInfo->pTagCond = pTagCond;
8,717✔
4743
  pInfo->pGroupTags = pTableScanNode->pGroupTags;
8,717✔
4744

4745
  int32_t numOfCols = 0;
8,717✔
4746
  code = extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo);
8,717✔
4747
  if (code != TSDB_CODE_SUCCESS) {
8,714!
UNCOV
4748
    goto _error;
×
4749
  }
4750

4751
  SDataType pkType = {0};
8,714✔
4752
  pInfo->primaryKeyIndex = -1;
8,714✔
4753
  pInfo->basic.primaryPkIndex = -1;
8,714✔
4754
  int32_t numOfOutput = taosArrayGetSize(pInfo->matchInfo.pList);
8,714✔
4755
  pColIds = taosArrayInit(numOfOutput, sizeof(int16_t));
8,714✔
4756
  QUERY_CHECK_NULL(pColIds, code, lino, _error, terrno);
8,716!
4757

4758
  for (int32_t i = 0; i < numOfOutput; ++i) {
220,779✔
4759
    SColMatchItem* id = taosArrayGet(pInfo->matchInfo.pList, i);
212,065✔
4760
    QUERY_CHECK_NULL(id, code, lino, _error, terrno);
212,064!
4761

4762
    int16_t colId = id->colId;
212,064✔
4763
    void*   tmp = taosArrayPush(pColIds, &colId);
212,063✔
4764
    QUERY_CHECK_NULL(tmp, code, lino, _error, terrno);
212,063!
4765

4766
    if (id->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
212,063✔
4767
      pInfo->primaryTsIndex = id->dstSlotId;
8,433✔
4768
    }
4769
    if (id->isPk) {
212,063✔
4770
      pInfo->primaryKeyIndex = id->dstSlotId;
85✔
4771
      pInfo->basic.primaryPkIndex = id->dstSlotId;
85✔
4772
      pkType = id->dataType;
85✔
4773
    }
4774
  }
4775

4776
  pInfo->pPartTbnameSup = NULL;
8,714✔
4777
  if (pTableScanNode->pSubtable != NULL) {
8,714✔
4778
    SExprInfo* pSubTableExpr = taosMemoryCalloc(1, sizeof(SExprInfo));
3,184!
4779
    if (pSubTableExpr == NULL) {
3,184!
4780
      code = terrno;
×
4781
      goto _error;
×
4782
    }
4783

4784
    pInfo->tbnameCalSup.pExprInfo = pSubTableExpr;
3,184✔
4785
    code = createExprFromOneNode(pSubTableExpr, pTableScanNode->pSubtable, 0);
3,184✔
4786
    QUERY_CHECK_CODE(code, lino, _error);
3,184!
4787

4788
    if (initExprSupp(&pInfo->tbnameCalSup, pSubTableExpr, 1, &pTaskInfo->storageAPI.functionStore) != 0) {
3,184!
4789
      goto _error;
×
4790
    }
4791
  }
4792

4793
  if (pTableScanNode->pTags != NULL) {
8,713✔
4794
    int32_t    numOfTags;
4795
    SExprInfo* pTagExpr = createExpr(pTableScanNode->pTags, &numOfTags);
2,291✔
4796
    if (pTagExpr == NULL) {
2,291!
UNCOV
4797
      goto _error;
×
4798
    }
4799
    code = initExprSupp(&pInfo->tagCalSup, pTagExpr, numOfTags, &pTaskInfo->storageAPI.functionStore);
2,291✔
4800
    if (code != 0) {
2,291!
UNCOV
4801
      goto _error;
×
4802
    }
4803
  }
4804

4805
  pInfo->pBlockLists = taosArrayInit(4, sizeof(SPackedData));
8,713✔
4806
  TSDB_CHECK_NULL(pInfo->pBlockLists, code, lino, _error, terrno);
8,716!
4807

4808
  if (pHandle->vnode) {
8,717✔
4809
    SOperatorInfo* pTableScanOp = NULL;
8,435✔
4810
    code = createTableScanOperatorInfo(pTableScanNode, pHandle, pTableListInfo, pTaskInfo, &pTableScanOp);
8,435✔
4811
    if (pTableScanOp == NULL || code != 0) {
8,433!
UNCOV
4812
      qError("createTableScanOperatorInfo error, code:%d", pTaskInfo->code);
×
UNCOV
4813
      goto _error;
×
4814
    }
4815

4816
    STableScanInfo* pTSInfo = (STableScanInfo*)pTableScanOp->info;
8,434✔
4817
    if (pHandle->version > 0) {
8,434✔
4818
      pTSInfo->base.cond.endVersion = pHandle->version;
1,243✔
4819
    }
4820

4821
    STableKeyInfo* pList = NULL;
8,434✔
4822
    int32_t        num = 0;
8,434✔
4823
    code = tableListGetGroupList(pTableListInfo, 0, &pList, &num);
8,434✔
4824
    QUERY_CHECK_CODE(code, lino, _error);
8,431!
4825

4826
    if (pHandle->initTableReader) {
8,431✔
4827
      pTSInfo->scanMode = TABLE_SCAN__TABLE_ORDER;
1,244✔
4828
      pTSInfo->base.dataReader = NULL;
1,244✔
4829
    }
4830

4831
    if (pHandle->initTqReader) {
8,431!
4832
      pInfo->tqReader = pAPI->tqReaderFn.tqReaderOpen(pHandle->vnode);
8,432✔
4833
      QUERY_CHECK_NULL(pInfo->tqReader, code, lino, _error, terrno);
8,434!
4834
    } else {
UNCOV
4835
      pInfo->tqReader = pHandle->tqReader;
×
UNCOV
4836
      QUERY_CHECK_NULL(pInfo->tqReader, code, lino, _error, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
4837
    }
4838

4839
    if (pVtableInfos != NULL) {
8,433!
4840
      // save vtable info into tqReader for vtable source scan
NEW
4841
      SSDataBlock* pResBlock = NULL;
×
NEW
4842
      code = createStreamVtableBlock(&pInfo->matchInfo, &pResBlock, idstr);
×
NEW
4843
      QUERY_CHECK_CODE(code, lino, _error);
×
NEW
4844
      code = pAPI->tqReaderFn.tqReaderSetVtableInfo(pInfo->tqReader, pHandle->vnode, pAPI, pVtableInfos, &pResBlock,
×
4845
                                                    idstr);
NEW
4846
      QUERY_CHECK_CODE(code, lino, _error);
×
4847
    }
4848

4849
    pInfo->pUpdateInfo = NULL;
8,433✔
4850
    pInfo->pTableScanOp = pTableScanOp;
8,433✔
4851
    if (pInfo->pTableScanOp->pTaskInfo->streamInfo.pState) {
8,433✔
4852
      pAPI->stateStore.streamStateSetNumber(pInfo->pTableScanOp->pTaskInfo->streamInfo.pState, -1,
7,189✔
4853
                                            pInfo->primaryTsIndex);
4854
    }
4855

4856
    pInfo->readHandle = *pHandle;
8,430✔
4857
    pTaskInfo->streamInfo.snapshotVer = pHandle->version;
8,430✔
4858
    pInfo->pCreateTbRes = buildCreateTableBlock(&pInfo->tbnameCalSup, &pInfo->tagCalSup);
8,430✔
4859
    QUERY_CHECK_NULL(pInfo->pCreateTbRes, code, lino, _error, terrno);
8,433!
4860
    pInfo->hasPart = false;
8,433✔
4861

4862
    code = blockDataEnsureCapacity(pInfo->pCreateTbRes, 8);
8,433✔
4863
    QUERY_CHECK_CODE(code, lino, _error);
8,431!
4864

4865
    // set the extract column id to streamHandle
4866
    code = pAPI->tqReaderFn.tqReaderSetColIdList(pInfo->tqReader, pColIds, idstr);
8,431✔
4867
    QUERY_CHECK_CODE(code, lino, _error);
8,432!
4868

4869
    SArray* tableIdList = NULL;
8,432✔
4870
    code = extractTableIdList(((STableScanInfo*)(pInfo->pTableScanOp->info))->base.pTableListInfo, &tableIdList);
8,432✔
4871
    QUERY_CHECK_CODE(code, lino, _error);
8,433!
4872
    code = pAPI->tqReaderFn.tqReaderSetQueryTableList(pInfo->tqReader, tableIdList, idstr);
8,433✔
4873
    QUERY_CHECK_CODE(code, lino, _error);
8,435!
4874
    taosArrayDestroy(tableIdList);
8,435✔
4875
    memcpy(&pTaskInfo->streamInfo.tableCond, &pTSInfo->base.cond, sizeof(SQueryTableDataCond));
8,435✔
4876
  } else {
4877
    taosArrayDestroy(pColIds);
282✔
4878
    tableListDestroy(pTableListInfo);
282✔
4879
  }
4880

4881
  // clear the local variable to avoid repeatly free
4882
  pColIds = NULL;
8,717✔
4883

4884
  // create the pseduo columns info
4885
  if (pTableScanNode->scan.pScanPseudoCols != NULL) {
8,717✔
4886
    code = createExprInfo(pTableScanNode->scan.pScanPseudoCols, NULL, &pInfo->pPseudoExpr, &pInfo->numOfPseudoExpr);
5,174✔
4887
    QUERY_CHECK_CODE(code, lino, _error);
5,174!
4888
  }
4889

4890
  code = filterInitFromNode((SNode*)pScanPhyNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
8,717✔
4891
  QUERY_CHECK_CODE(code, lino, _error);
8,717!
4892

4893
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
8,717✔
4894
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
8,717!
4895
  code = createSpecialDataBlock(STREAM_CLEAR, &pInfo->pUpdateRes);
8,717✔
4896
  QUERY_CHECK_CODE(code, lino, _error);
8,715!
4897

4898
  pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE;
8,715✔
4899
  pInfo->windowSup = (SWindowSupporter){.pStreamAggSup = NULL, .gap = -1, .parentType = QUERY_NODE_PHYSICAL_PLAN};
8,715✔
4900
  pInfo->groupId = 0;
8,715✔
4901
  pInfo->igCheckGroupId = false;
8,715✔
4902
  pInfo->pStreamScanOp = pOperator;
8,715✔
4903
  pInfo->deleteDataIndex = 0;
8,715✔
4904
  code = createSpecialDataBlock(STREAM_DELETE_DATA, &pInfo->pDeleteDataRes);
8,715✔
4905
  QUERY_CHECK_CODE(code, lino, _error);
8,717!
4906

4907
  pInfo->updateWin = (STimeWindow){.skey = INT64_MAX, .ekey = INT64_MAX};
8,717✔
4908
  code = createSpecialDataBlock(STREAM_CLEAR, &pInfo->pUpdateDataRes);
8,717✔
4909
  QUERY_CHECK_CODE(code, lino, _error);
8,717!
4910

4911
  if (hasPrimaryKeyCol(pInfo)) {
8,717✔
4912
    code = addPrimaryKeyCol(pInfo->pUpdateDataRes, pkType.type, pkType.bytes);
85✔
4913
    QUERY_CHECK_CODE(code, lino, _error);
85!
4914

4915
    pInfo->pkColType = pkType.type;
85✔
4916
    pInfo->pkColLen = pkType.bytes;
85✔
4917
  }
4918

4919
  pInfo->assignBlockUid = pTableScanNode->assignBlockUid;
8,716✔
4920
  pInfo->partitionSup.needCalc = false;
8,716✔
4921
  pInfo->igCheckUpdate = pTableScanNode->igCheckUpdate;
8,716✔
4922
  pInfo->igExpired = pTableScanNode->igExpired;
8,716✔
4923
  pInfo->twAggSup.maxTs = INT64_MIN;
8,716✔
4924
  pInfo->pState = pTaskInfo->streamInfo.pState;
8,716✔
4925
  pInfo->stateStore = pTaskInfo->storageAPI.stateStore;
8,716✔
4926
  pInfo->readerFn = pTaskInfo->storageAPI.tqReaderFn;
8,716✔
4927
  pInfo->pFillSup = NULL;
8,716✔
4928
  pInfo->useGetResultRange = false;
8,716✔
4929
  pInfo->pRangeScanRes = NULL;
8,716✔
4930

4931
  code = createSpecialDataBlock(STREAM_CHECKPOINT, &pInfo->pCheckpointRes);
8,716✔
4932
  QUERY_CHECK_CODE(code, lino, _error);
8,717!
4933

4934
  SET_WIN_KEY_INVALID(pInfo->lastScanRange.skey);
8,717✔
4935
  SET_WIN_KEY_INVALID(pInfo->lastScanRange.ekey);
8,717✔
4936
  // for stream
4937
  if (pTaskInfo->streamInfo.pState) {
8,717✔
4938
    void*   buff = NULL;
7,473✔
4939
    int32_t len = 0;
7,473✔
4940
    int32_t res = pAPI->stateStore.streamStateGetInfo(pTaskInfo->streamInfo.pState, STREAM_SCAN_OP_CHECKPOINT_NAME,
7,473✔
4941
                                                      strlen(STREAM_SCAN_OP_CHECKPOINT_NAME), &buff, &len);
4942
    if (res == TSDB_CODE_SUCCESS) {
7,470✔
4943
      streamScanOperatorDecode(buff, len, pInfo);
35✔
4944
      taosMemoryFree(buff);
35!
4945
    }
4946
  }
4947

4948
  setOperatorInfo(pOperator, STREAM_SCAN_OP_NAME, QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, false, OP_NOT_OPENED, pInfo,
8,714✔
4949
                  pTaskInfo);
4950
  pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pRes->pDataBlock);
8,715✔
4951

4952
  __optr_fn_t nextFn = (pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM) ? doStreamScanNext : doQueueScanNext;
8,712✔
4953
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, nextFn, NULL, destroyStreamScanOperatorInfo, optrDefaultBufFn,
8,712✔
4954
                                         NULL, optrDefaultGetNextExtFn, NULL);
4955
  setOperatorStreamStateFn(pOperator, streamScanReleaseState, streamScanReloadState);
8,714✔
4956

4957
  *pOptrInfo = pOperator;
8,712✔
4958
  return code;
8,712✔
4959

UNCOV
4960
_error:
×
UNCOV
4961
  if (pColIds != NULL) {
×
UNCOV
4962
    taosArrayDestroy(pColIds);
×
4963
  }
4964

UNCOV
4965
  if (pInfo != NULL) {
×
UNCOV
4966
    STableScanInfo* p = (STableScanInfo*) pInfo->pTableScanOp->info;
×
UNCOV
4967
    if (p != NULL) {
×
UNCOV
4968
      p->base.pTableListInfo = NULL;
×
4969
    }
UNCOV
4970
    destroyStreamScanOperatorInfo(pInfo);
×
4971
  }
4972

UNCOV
4973
  if (pOperator != NULL) {
×
UNCOV
4974
    pOperator->info = NULL;
×
UNCOV
4975
    destroyOperator(pOperator);
×
4976
  }
UNCOV
4977
  pTaskInfo->code = code;
×
UNCOV
4978
  return code;
×
4979
}
4980

4981
int32_t createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode, SNode* pTagCond,
8,756✔
4982
                                     STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo,
4983
                                     SOperatorInfo** pOptrInfo) {
4984
  if (pTableScanNode->triggerType == STREAM_TRIGGER_CONTINUOUS_WINDOW_CLOSE) {
8,756✔
4985
    return createStreamDataScanOperatorInfo(pHandle, pTableScanNode, pTagCond, pTableListInfo, pTaskInfo, pOptrInfo);
57✔
4986
  } else {
4987
    return createStreamNormalScanOperatorInfo(pHandle, pTableScanNode, pTagCond, pTableListInfo, pTaskInfo, pOptrInfo);
8,699✔
4988
  }
4989
}
4990

4991
static int32_t doTagScanOneTable(SOperatorInfo* pOperator, SSDataBlock* pRes, SMetaReader* mr, SStorageAPI* pAPI) {
18,830✔
4992
  int32_t        code = TSDB_CODE_SUCCESS;
18,830✔
4993
  int32_t        lino = 0;
18,830✔
4994
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
18,830✔
4995
  STagScanInfo*  pInfo = pOperator->info;
18,830✔
4996
  SExprInfo*     pExprInfo = &pOperator->exprSupp.pExprInfo[0];
18,830✔
4997
  int32_t        count = pRes->info.rows;
18,830✔
4998

4999
  STableKeyInfo* item = tableListGetInfo(pInfo->pTableListInfo, pInfo->curPos);
18,830✔
5000
  if (!item) {
18,827!
UNCOV
5001
    qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
×
5002
           GET_TASKID(pTaskInfo));
UNCOV
5003
    tDecoderClear(&(*mr).coder);
×
5004
    goto _end;
×
5005
  }
5006

5007
  code = pAPI->metaReaderFn.getTableEntryByUid(mr, item->uid);
18,827✔
5008
  tDecoderClear(&(*mr).coder);
18,795✔
5009
  if (code != TSDB_CODE_SUCCESS) {
18,865!
UNCOV
5010
    qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
×
5011
           GET_TASKID(pTaskInfo));
UNCOV
5012
    goto _end;
×
5013
  }
5014

5015
  char str[512];
5016
  for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
51,540✔
5017
    SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
32,693✔
5018

5019
    // refactor later
5020
    if (FUNCTION_TYPE_TBNAME == pExprInfo[j].pExpr->_function.functionType) {
32,676✔
5021
      STR_TO_VARSTR(str, (*mr).me.name);
18,847✔
5022
      code = colDataSetVal(pDst, (count), str, false);
18,847✔
5023
      QUERY_CHECK_CODE(code, lino, _end);
18,844!
5024
    } else if (FUNCTION_TYPE_TBUID == pExprInfo[j].pExpr->_function.functionType) {
13,829✔
5025
      code = colDataSetVal(pDst, (count), (char*)&(*mr).me.uid, false);
94✔
5026
      QUERY_CHECK_CODE(code, lino, _end);
94!
5027
    } else if (FUNCTION_TYPE_VGID == pExprInfo[j].pExpr->_function.functionType) {
13,735✔
5028
      code = colDataSetVal(pDst, (count), (char*)&pTaskInfo->id.vgId, false);
94✔
5029
      QUERY_CHECK_CODE(code, lino, _end);
94!
5030
    } else {  // it is a tag value
5031
      STagVal val = {0};
13,641✔
5032
      val.cid = pExprInfo[j].base.pParam[0].pCol->colId;
13,641✔
5033
      const char* p = pAPI->metaFn.extractTagVal((*mr).me.ctbEntry.pTags, pDst->info.type, &val);
13,641✔
5034

5035
      char* data = NULL;
13,646✔
5036
      if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL) {
13,646!
5037
        data = tTagValToData((const STagVal*)p, false);
13,646✔
5038
      } else {
5039
        data = (char*)p;
×
5040
      }
5041

5042
      code = colDataSetVal(pDst, (count), data,
13,646✔
5043
                           (data == NULL) || (pDst->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data)));
13,646!
5044
      QUERY_CHECK_CODE(code, lino, _end);
13,642!
5045

5046
      if ((pDst->info.type != TSDB_DATA_TYPE_JSON) && (p != NULL) && IS_VAR_DATA_TYPE(((const STagVal*)p)->type) &&
13,642!
5047
          (data != NULL)) {
5048
        taosMemoryFree(data);
2,872!
5049
      }
5050
    }
5051
  }
5052

5053
_end:
18,847✔
5054
  if (code != TSDB_CODE_SUCCESS) {
18,847!
UNCOV
5055
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
5056
    pTaskInfo->code = code;
×
5057
  } else {
5058
    pRes->info.rows++;
18,847✔
5059
  }
5060

5061
  return code;
18,847✔
5062
}
5063

5064
static void tagScanFreeUidTag(void* p) {
67,555✔
5065
  STUidTagInfo* pInfo = p;
67,555✔
5066
  if (pInfo->pTagVal != NULL) {
67,555!
5067
    taosMemoryFree(pInfo->pTagVal);
67,581!
5068
  }
5069
}
67,605✔
5070

5071
static int32_t tagScanCreateResultData(SDataType* pType, int32_t numOfRows, SScalarParam* pParam) {
14,810✔
5072
  SColumnInfoData* pColumnData = taosMemoryCalloc(1, sizeof(SColumnInfoData));
14,810!
5073
  if (pColumnData == NULL) {
14,817!
UNCOV
5074
    return terrno;
×
5075
  }
5076

5077
  pColumnData->info.type = pType->type;
14,817✔
5078
  pColumnData->info.bytes = pType->bytes;
14,817✔
5079
  pColumnData->info.scale = pType->scale;
14,817✔
5080
  pColumnData->info.precision = pType->precision;
14,817✔
5081

5082
  int32_t code = colInfoDataEnsureCapacity(pColumnData, numOfRows, true);
14,817✔
5083
  if (code != TSDB_CODE_SUCCESS) {
14,818✔
5084
    terrno = code;
3✔
UNCOV
5085
    taosMemoryFree(pColumnData);
×
UNCOV
5086
    return terrno;
×
5087
  }
5088

5089
  pParam->columnData = pColumnData;
14,815✔
5090
  pParam->colAlloced = true;
14,815✔
5091
  return TSDB_CODE_SUCCESS;
14,815✔
5092
}
5093

5094
static EDealRes tagScanRewriteTagColumn(SNode** pNode, void* pContext) {
92,875✔
5095
  int32_t                code = TSDB_CODE_SUCCESS;
92,875✔
5096
  int32_t                lino = 0;
92,875✔
5097
  STagScanFilterContext* pCtx = (STagScanFilterContext*)pContext;
92,875✔
5098
  SColumnNode*           pSColumnNode = NULL;
92,875✔
5099
  if (QUERY_NODE_COLUMN == nodeType((*pNode))) {
92,875✔
5100
    pSColumnNode = *(SColumnNode**)pNode;
25,949✔
5101
  } else if (QUERY_NODE_FUNCTION == nodeType((*pNode))) {
66,926!
UNCOV
5102
    SFunctionNode* pFuncNode = *(SFunctionNode**)(pNode);
×
UNCOV
5103
    if (pFuncNode->funcType == FUNCTION_TYPE_TBNAME) {
×
UNCOV
5104
      pSColumnNode = NULL;
×
UNCOV
5105
      pCtx->code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pSColumnNode);
×
UNCOV
5106
      if (NULL == pSColumnNode) {
×
UNCOV
5107
        return DEAL_RES_ERROR;
×
5108
      }
UNCOV
5109
      pSColumnNode->colId = -1;
×
UNCOV
5110
      pSColumnNode->colType = COLUMN_TYPE_TBNAME;
×
UNCOV
5111
      pSColumnNode->node.resType.type = TSDB_DATA_TYPE_VARCHAR;
×
UNCOV
5112
      pSColumnNode->node.resType.bytes = TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE;
×
UNCOV
5113
      nodesDestroyNode(*pNode);
×
UNCOV
5114
      *pNode = (SNode*)pSColumnNode;
×
5115
    } else {
UNCOV
5116
      return DEAL_RES_CONTINUE;
×
5117
    }
5118
  } else {
5119
    return DEAL_RES_CONTINUE;
66,926✔
5120
  }
5121

5122
  void* data = taosHashGet(pCtx->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId));
25,949✔
5123
  if (!data) {
25,948✔
5124
    code = taosHashPut(pCtx->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId), pNode, sizeof((*pNode)));
14,806✔
5125
    if (code == TSDB_CODE_DUP_KEY) {
14,827!
UNCOV
5126
      code = TSDB_CODE_SUCCESS;
×
5127
    }
5128
    QUERY_CHECK_CODE(code, lino, _end);
14,827!
5129
    pSColumnNode->slotId = pCtx->index++;
14,827✔
5130
    SColumnInfo cInfo = {.colId = pSColumnNode->colId,
14,827✔
5131
                         .type = pSColumnNode->node.resType.type,
14,827✔
5132
                         .bytes = pSColumnNode->node.resType.bytes};
14,827✔
5133
    void*       tmp = taosArrayPush(pCtx->cInfoList, &cInfo);
14,827✔
5134
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
14,829!
5135
  } else {
5136
    SColumnNode* col = *(SColumnNode**)data;
11,142✔
5137
    pSColumnNode->slotId = col->slotId;
11,142✔
5138
  }
5139

5140
_end:
25,971✔
5141
  if (code != TSDB_CODE_SUCCESS) {
25,971!
UNCOV
5142
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
5143
    return DEAL_RES_ERROR;
×
5144
  }
5145
  return DEAL_RES_CONTINUE;
25,971✔
5146
}
5147

5148
static int32_t tagScanFilterByTagCond(SArray* aUidTags, SNode* pTagCond, SArray* aFilterIdxs, void* pVnode,
14,812✔
5149
                                      SStorageAPI* pAPI, STagScanInfo* pInfo) {
5150
  int32_t code = TSDB_CODE_SUCCESS;
14,812✔
5151
  int32_t lino = 0;
14,812✔
5152
  int32_t numOfTables = taosArrayGetSize(aUidTags);
14,812✔
5153
  SArray* pBlockList = NULL;
14,812✔
5154

5155
  SSDataBlock* pResBlock = createTagValBlockForFilter(pInfo->filterCtx.cInfoList, numOfTables, aUidTags, pVnode, pAPI);
14,812✔
5156
  QUERY_CHECK_NULL(pResBlock, code, lino, _end, terrno);
14,801!
5157

5158
  pBlockList = taosArrayInit(1, POINTER_BYTES);
14,801✔
5159
  QUERY_CHECK_NULL(pBlockList, code, lino, _end, terrno);
14,817!
5160

5161
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
14,813✔
5162
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
14,813!
5163

5164
  SDataType type = {.type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)};
14,813✔
5165

5166
  SScalarParam output = {0};
14,813✔
5167
  code = tagScanCreateResultData(&type, numOfTables, &output);
14,813✔
5168
  QUERY_CHECK_CODE(code, lino, _end);
14,816!
5169

5170
  code = scalarCalculate(pTagCond, pBlockList, &output);
14,816✔
5171
  QUERY_CHECK_CODE(code, lino, _end);
14,790!
5172

5173
  bool* result = (bool*)output.columnData->pData;
14,790✔
5174
  for (int32_t i = 0; i < numOfTables; ++i) {
37,029✔
5175
    if (result[i]) {
22,251✔
5176
      void* tmp = taosArrayPush(aFilterIdxs, &i);
21,229✔
5177
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
21,229!
5178
    }
5179
  }
5180

5181
  colDataDestroy(output.columnData);
14,778✔
5182
  taosMemoryFreeClear(output.columnData);
14,812!
5183

UNCOV
5184
_end:
×
5185
  blockDataDestroy(pResBlock);
14,812✔
5186
  taosArrayDestroy(pBlockList);
14,811✔
5187
  if (code != TSDB_CODE_SUCCESS) {
14,819!
5188
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5189
  }
5190
  return code;
14,812✔
5191
}
5192

5193
static int32_t tagScanFillOneCellWithTag(SOperatorInfo* pOperator, const STUidTagInfo* pUidTagInfo,
278,702✔
5194
                                         SExprInfo* pExprInfo, SColumnInfoData* pColInfo, int rowIndex,
5195
                                         const SStorageAPI* pAPI, void* pVnode) {
5196
  int32_t code = TSDB_CODE_SUCCESS;
278,702✔
5197
  int32_t lino = 0;
278,702✔
5198
  if (QUERY_NODE_FUNCTION == pExprInfo->pExpr->nodeType) {
278,702✔
5199
    if (FUNCTION_TYPE_TBNAME == pExprInfo->pExpr->_function.functionType) {  // tbname
133,123!
UNCOV
5200
      char str[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
×
UNCOV
5201
      STR_TO_VARSTR(str, "ctbidx");
×
5202

UNCOV
5203
      code = colDataSetVal(pColInfo, rowIndex, str, false);
×
UNCOV
5204
      QUERY_CHECK_CODE(code, lino, _end);
×
5205
    } else if (FUNCTION_TYPE_TBUID == pExprInfo->pExpr->_function.functionType) {
133,123✔
5206
      code = colDataSetVal(pColInfo, rowIndex, (char*)&pUidTagInfo->uid, false);
66,591✔
5207
      QUERY_CHECK_CODE(code, lino, _end);
66,589!
5208
    } else if (FUNCTION_TYPE_VGID == pExprInfo->pExpr->_function.functionType) {
66,532!
5209
      code = colDataSetVal(pColInfo, rowIndex, (char*)&pOperator->pTaskInfo->id.vgId, false);
66,596✔
5210
      QUERY_CHECK_CODE(code, lino, _end);
66,601!
5211
    }
5212
  } else {
5213
    STagVal tagVal = {0};
145,579✔
5214
    tagVal.cid = pExprInfo->base.pParam[0].pCol->colId;
145,579✔
5215
    if (pUidTagInfo->pTagVal == NULL) {
145,579!
UNCOV
5216
      colDataSetNULL(pColInfo, rowIndex);
×
5217
    } else {
5218
      const char* p = pAPI->metaFn.extractTagVal(pUidTagInfo->pTagVal, pColInfo->info.type, &tagVal);
145,579✔
5219

5220
      if (p == NULL || (pColInfo->info.type == TSDB_DATA_TYPE_JSON && ((STag*)p)->nTag == 0)) {
145,920!
5221
        colDataSetNULL(pColInfo, rowIndex);
25!
5222
      } else if (pColInfo->info.type == TSDB_DATA_TYPE_JSON) {
145,895!
UNCOV
5223
        code = colDataSetVal(pColInfo, rowIndex, p, false);
×
UNCOV
5224
        QUERY_CHECK_CODE(code, lino, _end);
×
5225
      } else if (IS_VAR_DATA_TYPE(pColInfo->info.type)) {
182,339!
5226
        char* tmp = taosMemoryMalloc(tagVal.nData + VARSTR_HEADER_SIZE + 1);
36,456!
5227
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
36,439!
5228

5229
        varDataSetLen(tmp, tagVal.nData);
36,439✔
5230
        memcpy(tmp + VARSTR_HEADER_SIZE, tagVal.pData, tagVal.nData);
36,439✔
5231
        code = colDataSetVal(pColInfo, rowIndex, tmp, false);
36,439✔
5232
        taosMemoryFree(tmp);
36,439!
5233
        QUERY_CHECK_CODE(code, lino, _end);
36,444!
5234
      } else {
5235
        code = colDataSetVal(pColInfo, rowIndex, (const char*)&tagVal.i64, false);
109,439✔
5236
        QUERY_CHECK_CODE(code, lino, _end);
109,426!
5237
      }
5238
    }
5239
  }
5240

5241
_end:
279,021✔
5242
  if (code != TSDB_CODE_SUCCESS) {
279,021!
UNCOV
5243
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5244
  }
5245
  return code;
278,735✔
5246
}
5247

5248
static int32_t tagScanFillResultBlock(SOperatorInfo* pOperator, SSDataBlock* pRes, SArray* aUidTags,
43,929✔
5249
                                      SArray* aFilterIdxs, bool ignoreFilterIdx, SStorageAPI* pAPI) {
5250
  int32_t       code = TSDB_CODE_SUCCESS;
43,929✔
5251
  int32_t       lino = 0;
43,929✔
5252
  STagScanInfo* pInfo = pOperator->info;
43,929✔
5253
  SExprInfo*    pExprInfo = &pOperator->exprSupp.pExprInfo[0];
43,929✔
5254
  if (!ignoreFilterIdx) {
43,929✔
5255
    size_t szTables = taosArrayGetSize(aFilterIdxs);
14,811✔
5256
    for (int i = 0; i < szTables; ++i) {
36,042✔
5257
      int32_t       idx = *(int32_t*)taosArrayGet(aFilterIdxs, i);
21,260✔
5258
      STUidTagInfo* pUidTagInfo = taosArrayGet(aUidTags, idx);
21,255✔
5259
      QUERY_CHECK_NULL(pUidTagInfo, code, lino, _end, terrno);
21,256!
5260
      for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
120,926✔
5261
        SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
99,695✔
5262
        QUERY_CHECK_NULL(pDst, code, lino, _end, terrno);
99,666!
5263
        code = tagScanFillOneCellWithTag(pOperator, pUidTagInfo, &pExprInfo[j], pDst, i, pAPI, pInfo->readHandle.vnode);
99,666✔
5264
        QUERY_CHECK_CODE(code, lino, _end);
99,670!
5265
      }
5266
    }
5267
  } else {
5268
    size_t szTables = taosArrayGetSize(aUidTags);
29,118✔
5269
    for (int i = 0; i < szTables; ++i) {
74,499✔
5270
      STUidTagInfo* pUidTagInfo = taosArrayGet(aUidTags, i);
45,372✔
5271
      QUERY_CHECK_NULL(pUidTagInfo, code, lino, _end, terrno);
45,370✔
5272
      for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
224,442✔
5273
        SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
179,083✔
5274
        QUERY_CHECK_NULL(pDst, code, lino, _end, terrno);
179,051!
5275
        code = tagScanFillOneCellWithTag(pOperator, pUidTagInfo, &pExprInfo[j], pDst, i, pAPI, pInfo->readHandle.vnode);
179,051✔
5276
        QUERY_CHECK_CODE(code, lino, _end);
179,076!
5277
      }
5278
    }
5279
  }
5280

5281
_end:
29,127✔
5282
  if (code != TSDB_CODE_SUCCESS) {
43,909!
UNCOV
5283
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5284
  }
5285
  return code;
43,944✔
5286
}
5287

5288
static int32_t doTagScanFromCtbIdxNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
87,365✔
5289
  int32_t        code = TSDB_CODE_SUCCESS;
87,365✔
5290
  int32_t        lino = 0;
87,365✔
5291
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
87,365✔
5292
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
87,365✔
5293

5294
  STagScanInfo* pInfo = pOperator->info;
87,365✔
5295
  SSDataBlock*  pRes = pInfo->pRes;
87,365✔
5296

5297
  QRY_PARAM_CHECK(ppRes);
87,365!
5298

5299
  if (pOperator->status == OP_EXEC_DONE) {
87,365✔
5300
    return TSDB_CODE_SUCCESS;
43,277✔
5301
  }
5302
  blockDataCleanup(pRes);
44,088✔
5303

5304
  if (pInfo->pCtbCursor == NULL) {
44,127!
5305
    pInfo->pCtbCursor = pAPI->metaFn.openCtbCursor(pInfo->readHandle.vnode, pInfo->suid, 1);
44,128✔
5306
    QUERY_CHECK_NULL(pInfo->pCtbCursor, code, lino, _end, terrno);
44,126!
5307
  } else {
5308
    code = pAPI->metaFn.resumeCtbCursor(pInfo->pCtbCursor, 0);
×
UNCOV
5309
    QUERY_CHECK_CODE(code, lino, _end);
×
5310
  }
5311

5312
  SArray* aUidTags = pInfo->aUidTags;
44,126✔
5313
  SArray* aFilterIdxs = pInfo->aFilterIdxs;
44,126✔
5314
  int32_t count = 0;
44,126✔
5315
  bool    ctbCursorFinished = false;
44,126✔
5316
  while (1) {
650✔
5317
    taosArrayClearEx(aUidTags, tagScanFreeUidTag);
44,776✔
5318
    taosArrayClear(aFilterIdxs);
44,774✔
5319

5320
    int32_t numTables = 0;
44,728✔
5321
    while (numTables < pOperator->resultInfo.capacity) {
112,311!
5322
      SMCtbCursor* pCur = pInfo->pCtbCursor;
112,314✔
5323
      tb_uid_t     uid = pAPI->metaFn.ctbCursorNext(pInfo->pCtbCursor);
112,314✔
5324
      if (uid == 0) {
112,319✔
5325
        ctbCursorFinished = true;
44,790✔
5326
        break;
44,790✔
5327
      }
5328
      STUidTagInfo info = {.uid = uid, .pTagVal = pCur->pVal};
67,529✔
5329
      info.pTagVal = taosMemoryMalloc(pCur->vLen);
67,529!
5330
      QUERY_CHECK_NULL(info.pTagVal, code, lino, _end, terrno);
67,601!
5331

5332
      memcpy(info.pTagVal, pCur->pVal, pCur->vLen);
67,601✔
5333
      void* tmp = taosArrayPush(aUidTags, &info);
67,583✔
5334
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
67,583!
5335
      ++numTables;
67,583✔
5336
    }
5337

5338
    if (numTables == 0) {
44,787✔
5339
      break;
834✔
5340
    }
5341
    bool ignoreFilterIdx = true;
43,953✔
5342
    if (pInfo->pTagCond != NULL) {
43,953✔
5343
      ignoreFilterIdx = false;
14,813✔
5344
      code = tagScanFilterByTagCond(aUidTags, pInfo->pTagCond, aFilterIdxs, pInfo->readHandle.vnode, pAPI, pInfo);
14,813✔
5345
      QUERY_CHECK_CODE(code, lino, _end);
14,808!
5346
    } else {
5347
      ignoreFilterIdx = true;
29,140✔
5348
    }
5349

5350
    code = tagScanFillResultBlock(pOperator, pRes, aUidTags, aFilterIdxs, ignoreFilterIdx, pAPI);
43,948✔
5351
    QUERY_CHECK_CODE(code, lino, _end);
43,946!
5352

5353
    count = ignoreFilterIdx ? taosArrayGetSize(aUidTags) : taosArrayGetSize(aFilterIdxs);
43,946✔
5354

5355
    if (count != 0) {
43,934✔
5356
      break;
43,284✔
5357
    }
5358
  }
5359

5360
  if (count > 0) {
44,118✔
5361
    pAPI->metaFn.pauseCtbCursor(pInfo->pCtbCursor);
43,292✔
5362
  }
5363
  if (count == 0 || ctbCursorFinished) {
44,131!
5364
    pAPI->metaFn.closeCtbCursor(pInfo->pCtbCursor);
44,131✔
5365
    pInfo->pCtbCursor = NULL;
44,151✔
5366
    setOperatorCompleted(pOperator);
44,151✔
5367
  }
5368

5369
  pRes->info.rows = count;
44,136✔
5370
  bool bLimitReached = applyLimitOffset(&pInfo->limitInfo, pRes, pTaskInfo);
44,136✔
5371
  if (bLimitReached) {
44,111!
5372
    setOperatorCompleted(pOperator);
×
5373
  }
5374

5375
  pOperator->resultInfo.totalRows += pRes->info.rows;
44,136✔
5376
  (*ppRes) = (pRes->info.rows == 0) ? NULL : pInfo->pRes;
44,136✔
5377

5378
_end:
44,136✔
5379
  if (code != TSDB_CODE_SUCCESS) {
44,136!
5380
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
5381
    pTaskInfo->code = code;
×
UNCOV
5382
    T_LONG_JMP(pTaskInfo->env, code);
×
5383
  }
5384

5385
  return code;
44,136✔
5386
}
5387

5388
static int32_t doTagScanFromMetaEntryNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
7,353✔
5389
  int32_t code = TSDB_CODE_SUCCESS;
7,353✔
5390
  int32_t lino = 0;
7,353✔
5391
  if (pOperator->status == OP_EXEC_DONE) {
7,353✔
5392
    (*ppRes) = NULL;
3,656✔
5393
    return code;
3,656✔
5394
  }
5395

5396
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3,697✔
5397
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
3,697✔
5398

5399
  STagScanInfo* pInfo = pOperator->info;
3,697✔
5400
  SExprInfo*    pExprInfo = &pOperator->exprSupp.pExprInfo[0];
3,697✔
5401
  SSDataBlock*  pRes = pInfo->pRes;
3,697✔
5402
  blockDataCleanup(pRes);
3,697✔
5403

5404
  int32_t size = 0;
3,704✔
5405
  code = tableListGetSize(pInfo->pTableListInfo, &size);
3,704✔
5406
  QUERY_CHECK_CODE(code, lino, _end);
3,704!
5407

5408
  if (size == 0) {
3,704✔
5409
    setTaskStatus(pTaskInfo, TASK_COMPLETED);
53✔
5410
    (*ppRes) = NULL;
53✔
5411
    return code;
53✔
5412
  }
5413

5414
  SMetaReader mr = {0};
3,651✔
5415
  pAPI->metaReaderFn.initReader(&mr, pInfo->readHandle.vnode, META_READER_LOCK, &pAPI->metaFn);
3,651✔
5416
  pRes->info.rows = 0;
3,656✔
5417

5418
  while (pInfo->curPos < size && pRes->info.rows < pOperator->resultInfo.capacity) {
22,499!
5419
    code = doTagScanOneTable(pOperator, pRes, &mr, &pTaskInfo->storageAPI);
18,838✔
5420
    if (code != TSDB_CODE_OUT_OF_MEMORY && code != TSDB_CODE_QRY_REACH_QMEM_THRESHOLD && code != TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED) {
18,842!
5421
      // ignore other error
5422
      code = TSDB_CODE_SUCCESS;
18,847✔
5423
    }
5424
    QUERY_CHECK_CODE(code, lino, _end);
18,842!
5425

5426
    if (++pInfo->curPos >= size) {
18,842✔
5427
      setOperatorCompleted(pOperator);
3,656✔
5428
    }
5429
  }
5430

5431
  pAPI->metaReaderFn.clearReader(&mr);
3,661✔
5432
  bool bLimitReached = applyLimitOffset(&pInfo->limitInfo, pRes, pTaskInfo);
3,657✔
5433
  if (bLimitReached) {
3,651!
UNCOV
5434
    setOperatorCompleted(pOperator);
×
5435
  }
5436

5437
  // qDebug("QInfo:0x%" PRIx64 ", create tag values results completed, rows:%d", GET_TASKID(pRuntimeEnv), count);
5438
  if (pOperator->status == OP_EXEC_DONE) {
3,651!
5439
    setTaskStatus(pTaskInfo, TASK_COMPLETED);
3,652✔
5440
  }
5441

5442
  pOperator->resultInfo.totalRows += pRes->info.rows;
3,655✔
5443

5444
  (*ppRes) = (pRes->info.rows == 0) ? NULL : pInfo->pRes;
3,655!
5445

5446
_end:
3,655✔
5447
  if (code != TSDB_CODE_SUCCESS) {
3,655!
UNCOV
5448
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
5449
    pTaskInfo->code = code;
×
UNCOV
5450
    T_LONG_JMP(pTaskInfo->env, code);
×
5451
  }
5452
  return code;
3,655✔
5453
}
5454

UNCOV
5455
static SSDataBlock* doTagScanFromMetaEntry(SOperatorInfo* pOperator) {
×
UNCOV
5456
  SSDataBlock* pRes = NULL;
×
UNCOV
5457
  int32_t      code = doTagScanFromMetaEntryNext(pOperator, &pRes);
×
UNCOV
5458
  return pRes;
×
5459
}
5460

5461
static void destroyTagScanOperatorInfo(void* param) {
47,734✔
5462
  STagScanInfo* pInfo = (STagScanInfo*)param;
47,734✔
5463
  if (pInfo->pCtbCursor != NULL && pInfo->pStorageAPI != NULL) {
47,734!
UNCOV
5464
    pInfo->pStorageAPI->metaFn.closeCtbCursor(pInfo->pCtbCursor);
×
5465
  }
5466
  taosHashCleanup(pInfo->filterCtx.colHash);
47,734✔
5467
  taosArrayDestroy(pInfo->filterCtx.cInfoList);
47,832✔
5468
  taosArrayDestroy(pInfo->aFilterIdxs);
47,830✔
5469
  taosArrayDestroyEx(pInfo->aUidTags, tagScanFreeUidTag);
47,842✔
5470

5471
  blockDataDestroy(pInfo->pRes);
47,842✔
5472
  taosArrayDestroy(pInfo->matchInfo.pList);
47,849✔
5473
  tableListDestroy(pInfo->pTableListInfo);
47,848✔
5474

5475
  pInfo->pRes = NULL;
47,860✔
5476
  pInfo->pTableListInfo = NULL;
47,860✔
5477
  taosMemoryFreeClear(param);
47,860!
5478
}
47,859✔
5479

5480
int32_t createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pTagScanNode,
47,788✔
5481
                                  STableListInfo* pTableListInfo, SNode* pTagCond, SNode* pTagIndexCond,
5482
                                  SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
5483
  QRY_PARAM_CHECK(pOptrInfo);
47,788!
5484

5485
  int32_t         code = TSDB_CODE_SUCCESS;
47,788✔
5486
  int32_t         lino = 0;
47,788✔
5487
  SScanPhysiNode* pPhyNode = (SScanPhysiNode*)pTagScanNode;
47,788✔
5488
  STagScanInfo*   pInfo = taosMemoryCalloc(1, sizeof(STagScanInfo));
47,788!
5489
  SOperatorInfo*  pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
47,802!
5490
  if (pInfo == NULL || pOperator == NULL) {
47,815!
UNCOV
5491
    code = terrno;
×
UNCOV
5492
    goto _error;
×
5493
  }
5494

5495
  SDataBlockDescNode* pDescNode = pPhyNode->node.pOutputDataBlockDesc;
47,817✔
5496

5497
  int32_t    numOfExprs = 0;
47,817✔
5498
  SExprInfo* pExprInfo = NULL;
47,817✔
5499

5500
  code = createExprInfo(pPhyNode->pScanPseudoCols, NULL, &pExprInfo, &numOfExprs);
47,817✔
5501
  QUERY_CHECK_CODE(code, lino, _error);
47,822!
5502

5503
  code = initExprSupp(&pOperator->exprSupp, pExprInfo, numOfExprs, &pTaskInfo->storageAPI.functionStore);
47,822✔
5504
  QUERY_CHECK_CODE(code, lino, _error);
47,777!
5505

5506
  int32_t num = 0;
47,777✔
5507
  code = extractColMatchInfo(pPhyNode->pScanPseudoCols, pDescNode, &num, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo);
47,777✔
5508
  QUERY_CHECK_CODE(code, lino, _error);
47,799!
5509

5510
  pInfo->pTagCond = pTagCond;
47,799✔
5511
  pInfo->pTagIndexCond = pTagIndexCond;
47,799✔
5512
  pInfo->suid = pPhyNode->suid;
47,799✔
5513
  pInfo->pStorageAPI = &pTaskInfo->storageAPI;
47,799✔
5514

5515
  pInfo->pTableListInfo = pTableListInfo;
47,799✔
5516
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
47,799✔
5517
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
47,814!
5518

5519
  pInfo->readHandle = *pReadHandle;
47,814✔
5520
  pInfo->curPos = 0;
47,814✔
5521

5522
  initLimitInfo(pPhyNode->node.pLimit, pPhyNode->node.pSlimit, &pInfo->limitInfo);
47,814✔
5523
  setOperatorInfo(pOperator, "TagScanOperator", QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN, false, OP_NOT_OPENED, pInfo,
47,847✔
5524
                  pTaskInfo);
5525
  initResultSizeInfo(&pOperator->resultInfo, 4096);
47,750✔
5526
  code = blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
47,762✔
5527
  QUERY_CHECK_CODE(code, lino, _error);
47,852!
5528

5529
  if (pTagScanNode->onlyMetaCtbIdx) {
47,852✔
5530
    pInfo->aUidTags = taosArrayInit(pOperator->resultInfo.capacity, sizeof(STUidTagInfo));
44,147✔
5531
    QUERY_CHECK_NULL(pInfo->aUidTags, code, lino, _error, terrno);
44,134!
5532

5533
    pInfo->aFilterIdxs = taosArrayInit(pOperator->resultInfo.capacity, sizeof(int32_t));
44,134✔
5534
    QUERY_CHECK_NULL(pInfo->aFilterIdxs, code, lino, _error, terrno);
44,127!
5535

5536
    pInfo->filterCtx.colHash =
44,119✔
5537
        taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK);
44,127✔
5538
    QUERY_CHECK_NULL(pInfo->filterCtx.colHash, code, lino, _error, terrno);
44,119!
5539

5540
    pInfo->filterCtx.cInfoList = taosArrayInit(4, sizeof(SColumnInfo));
44,119✔
5541
    QUERY_CHECK_NULL(pInfo->filterCtx.cInfoList, code, lino, _error, terrno);
44,147!
5542

5543
    if (pInfo->pTagCond != NULL) {
44,147✔
5544
      nodesRewriteExprPostOrder(&pTagCond, tagScanRewriteTagColumn, (void*)&pInfo->filterCtx);
14,829✔
5545
    }
5546
  }
5547
  __optr_fn_t tagScanNextFn = (pTagScanNode->onlyMetaCtbIdx) ? doTagScanFromCtbIdxNext : doTagScanFromMetaEntryNext;
47,832✔
5548
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, tagScanNextFn, NULL, destroyTagScanOperatorInfo,
47,832✔
5549
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
5550
  *pOptrInfo = pOperator;
47,836✔
5551
  return code;
47,836✔
5552

UNCOV
5553
_error:
×
UNCOV
5554
  if (pInfo) {
×
UNCOV
5555
    pInfo->pTableListInfo = NULL;
×
5556
  }
5557

UNCOV
5558
  if (pInfo != NULL) destroyTagScanOperatorInfo(pInfo);
×
UNCOV
5559
  if (pOperator != NULL) {
×
UNCOV
5560
    pOperator->info = NULL;
×
UNCOV
5561
    destroyOperator(pOperator);
×
5562
  }
UNCOV
5563
  return code;
×
5564
}
5565

5566
// table merge scan operator
5567

5568
static int32_t subTblRowCompareTsFn(const void* pLeft, const void* pRight, void* param) {
913,247✔
5569
  int32_t                 left = *(int32_t*)pLeft;
913,247✔
5570
  int32_t                 right = *(int32_t*)pRight;
913,247✔
5571
  STmsSubTablesMergeInfo* pInfo = (STmsSubTablesMergeInfo*)param;
913,247✔
5572

5573
  int32_t leftIdx = pInfo->aInputs[left].rowIdx;
913,247✔
5574
  int32_t rightIdx = pInfo->aInputs[right].rowIdx;
913,247✔
5575

5576
  if (leftIdx == -1) {
913,247✔
5577
    return 1;
767,959✔
5578
  } else if (rightIdx == -1) {
145,288✔
5579
    return -1;
1,440✔
5580
  }
5581

5582
  int64_t leftTs = pInfo->aInputs[left].aTs[leftIdx];
143,848✔
5583
  int64_t rightTs = pInfo->aInputs[right].aTs[rightIdx];
143,848✔
5584
  int32_t ret = leftTs > rightTs ? 1 : ((leftTs < rightTs) ? -1 : 0);
143,848!
5585
  if (pInfo->pTsOrderInfo->order == TSDB_ORDER_DESC) {
143,848!
5586
    ret = -1 * ret;
×
5587
  }
5588
  return ret;
143,848✔
5589
}
5590

UNCOV
5591
static int32_t subTblRowCompareTsPkFn(const void* pLeft, const void* pRight, void* param) {
×
UNCOV
5592
  int32_t                 left = *(int32_t*)pLeft;
×
UNCOV
5593
  int32_t                 right = *(int32_t*)pRight;
×
5594
  STmsSubTablesMergeInfo* pInfo = (STmsSubTablesMergeInfo*)param;
×
5595

UNCOV
5596
  int32_t leftIdx = pInfo->aInputs[left].rowIdx;
×
UNCOV
5597
  int32_t rightIdx = pInfo->aInputs[right].rowIdx;
×
5598

5599
  if (leftIdx == -1) {
×
5600
    return 1;
×
5601
  } else if (rightIdx == -1) {
×
UNCOV
5602
    return -1;
×
5603
  }
5604

UNCOV
5605
  int64_t leftTs = pInfo->aInputs[left].aTs[leftIdx];
×
UNCOV
5606
  int64_t rightTs = pInfo->aInputs[right].aTs[rightIdx];
×
UNCOV
5607
  int32_t ret = leftTs > rightTs ? 1 : ((leftTs < rightTs) ? -1 : 0);
×
UNCOV
5608
  if (pInfo->pTsOrderInfo->order == TSDB_ORDER_DESC) {
×
5609
    ret = -1 * ret;
×
5610
  }
UNCOV
5611
  if (ret == 0 && pInfo->pPkOrderInfo) {
×
UNCOV
5612
    ret = tsortComparBlockCell(pInfo->aInputs[left].pInputBlock, pInfo->aInputs[right].pInputBlock, leftIdx, rightIdx,
×
UNCOV
5613
                               pInfo->pPkOrderInfo);
×
5614
  }
UNCOV
5615
  return ret;
×
5616
}
5617

5618
int32_t dumpQueryTableCond(const SQueryTableDataCond* src, SQueryTableDataCond* dst) {
11,187✔
5619
  int32_t code = TSDB_CODE_SUCCESS;
11,187✔
5620
  int32_t lino = 0;
11,187✔
5621
  memcpy((void*)dst, (void*)src, sizeof(SQueryTableDataCond));
11,187✔
5622
  dst->colList = taosMemoryCalloc(src->numOfCols, sizeof(SColumnInfo));
11,187!
5623
  QUERY_CHECK_NULL(dst->colList, code, lino, _end, terrno);
11,226!
5624
  for (int i = 0; i < src->numOfCols; i++) {
37,234✔
5625
    dst->colList[i] = src->colList[i];
26,008✔
5626
  }
5627

5628
_end:
11,226✔
5629
  if (code != TSDB_CODE_SUCCESS) {
11,226!
UNCOV
5630
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5631
  }
5632
  return code;
11,226✔
5633
}
5634

5635
static int32_t fetchNextSubTableBlockFromReader(SOperatorInfo* pOperator, STmsSubTableInput* pInput,
16,806✔
5636
                                                bool* pSubTableHasBlock) {
5637
  int32_t code = 0;
16,806✔
5638

5639
  STableMergeScanInfo*    pInfo = pOperator->info;
16,806✔
5640
  SReadHandle*            pHandle = &pInfo->base.readHandle;
16,806✔
5641
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
16,806✔
5642
  SExecTaskInfo*          pTaskInfo = pOperator->pTaskInfo;
16,806✔
5643
  const SStorageAPI*      pAPI = &pTaskInfo->storageAPI;
16,806✔
5644

5645
  blockDataCleanup(pInput->pReaderBlock);
16,806✔
5646
  if (!pInput->bInMemReader) {
16,813✔
5647
    code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInput->tblCond, pInput->pKeyInfo, 1, pInput->pReaderBlock,
8,490✔
5648
                                         (void**)&pInput->pReader, GET_TASKID(pTaskInfo), NULL);
8,490✔
5649
    if (code != 0) {
8,482!
UNCOV
5650
      return code;
×
5651
    }
5652
  }
5653

5654
  pInfo->base.dataReader = pInput->pReader;
16,805✔
5655

5656
  while (true) {
27✔
5657
    bool hasNext = false;
16,832✔
5658
    code = pAPI->tsdReader.tsdNextDataBlock(pInfo->base.dataReader, &hasNext);
16,832✔
5659
    if (code != 0) {
16,844!
UNCOV
5660
      pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->base.dataReader);
×
UNCOV
5661
      pInfo->base.dataReader = NULL;
×
UNCOV
5662
      return code;
×
5663
    }
5664

5665
    if (!hasNext || isTaskKilled(pTaskInfo)) {
16,844!
5666
      if (isTaskKilled(pTaskInfo)) {
11,227!
UNCOV
5667
        pAPI->tsdReader.tsdReaderReleaseDataBlock(pInfo->base.dataReader);
×
UNCOV
5668
        pInfo->base.dataReader = NULL;
×
UNCOV
5669
        return code;
×
5670
      }
5671

5672
      *pSubTableHasBlock = false;
11,229✔
5673
      break;
11,229✔
5674
    }
5675

5676
    if (pInput->tblCond.order == TSDB_ORDER_ASC) {
5,617✔
5677
      pInput->tblCond.twindows.skey = pInput->pReaderBlock->info.window.ekey + 1;
5,537✔
5678
    } else {
5679
      pInput->tblCond.twindows.ekey = pInput->pReaderBlock->info.window.skey - 1;
80✔
5680
    }
5681

5682
    uint32_t status = 0;
5,617✔
5683
    code = loadDataBlock(pOperator, &pInfo->base, pInput->pReaderBlock, &status);
5,617✔
5684
    if (code != 0) {
5,617!
UNCOV
5685
      pInfo->base.dataReader = NULL;
×
UNCOV
5686
      return code;
×
5687
    }
5688

5689
    if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
5,617!
UNCOV
5690
      *pSubTableHasBlock = false;
×
UNCOV
5691
      break;
×
5692
    }
5693
    if (status == FUNC_DATA_REQUIRED_FILTEROUT || pInput->pReaderBlock->info.rows == 0) {
5,617!
5694
      continue;
27✔
5695
    }
5696

5697
    *pSubTableHasBlock = true;
5,590✔
5698
    break;
5,590✔
5699
  }
5700

5701
  if (*pSubTableHasBlock) {
16,819✔
5702
    pInput->pReaderBlock->info.id.groupId =
11,180✔
5703
        tableListGetTableGroupId(pInfo->base.pTableListInfo, pInput->pReaderBlock->info.id.uid);
5,590✔
5704
    pOperator->resultInfo.totalRows += pInput->pReaderBlock->info.rows;
5,590✔
5705
  }
5706
  if (!pInput->bInMemReader || !*pSubTableHasBlock) {
16,819✔
5707
    pAPI->tsdReader.tsdReaderClose(pInput->pReader);
12,667✔
5708
    pInput->pReader = NULL;
12,669✔
5709
  }
5710

5711
  pInfo->base.dataReader = NULL;
16,821✔
5712
  return TSDB_CODE_SUCCESS;
16,821✔
5713
}
5714

5715
static int32_t setGroupStartEndIndex(STableMergeScanInfo* pInfo) {
6,989✔
5716
  pInfo->bGroupProcessed = false;
6,989✔
5717

5718
  int32_t numOfTables = 0;
6,989✔
5719
  int32_t code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
6,989✔
5720
  if (code != TSDB_CODE_SUCCESS) {
7,030!
UNCOV
5721
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
5722
    return code;
×
5723
  }
5724

5725
  int32_t i = pInfo->tableStartIndex + 1;
7,037✔
5726
  for (; i < numOfTables; ++i) {
11,208✔
5727
    STableKeyInfo* tableKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i);
4,396✔
5728
    if (!tableKeyInfo) {
4,401✔
5729
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
1!
5730
      return terrno;
1✔
5731
    }
5732
    if (tableKeyInfo->groupId != pInfo->groupId) {
4,400✔
5733
      break;
229✔
5734
    }
5735
  }
5736
  pInfo->tableEndIndex = i - 1;
7,041✔
5737
  return TSDB_CODE_SUCCESS;
7,041✔
5738
}
5739

5740
static int32_t openSubTablesMergeSort(STmsSubTablesMergeInfo* pSubTblsInfo) {
7,053✔
5741
  for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
18,283✔
5742
    STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
11,230✔
5743
    if (pInput->rowIdx == -1) {
11,230✔
5744
      continue;
5,640✔
5745
    }
5746

5747
    if (pInput->type == SUB_TABLE_MEM_BLOCK) {
5,590!
5748
      pInput->rowIdx = 0;
5,590✔
5749
      pInput->pageIdx = -1;
5,590✔
5750
    }
5751

5752
    pInput->pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
5,590!
5753
    SColumnInfoData* col = taosArrayGet(pInput->pInputBlock->pDataBlock, pSubTblsInfo->pTsOrderInfo->slotId);
5,590✔
5754
    if (!col) {
5,590!
UNCOV
5755
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
5756
      return terrno;
×
5757
    }
5758
    pInput->aTs = (int64_t*)col->pData;
5,590✔
5759
  }
5760

5761
  __merge_compare_fn_t mergeCompareFn = (!pSubTblsInfo->pPkOrderInfo) ? subTblRowCompareTsFn : subTblRowCompareTsPkFn;
7,053!
5762
  return tMergeTreeCreate(&pSubTblsInfo->pTree, pSubTblsInfo->numSubTables, pSubTblsInfo, mergeCompareFn);
7,053✔
5763
}
5764

5765
static int32_t initSubTablesMergeInfo(STableMergeScanInfo* pInfo) {
6,991✔
5766
  int32_t code = setGroupStartEndIndex(pInfo);
6,991✔
5767
  if (code != TSDB_CODE_SUCCESS) {
7,036!
UNCOV
5768
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
UNCOV
5769
    return code;
×
5770
  }
5771
  STmsSubTablesMergeInfo* pSubTblsInfo = taosMemoryCalloc(1, sizeof(STmsSubTablesMergeInfo));
7,036!
5772
  if (pSubTblsInfo == NULL) {
7,048!
UNCOV
5773
    return terrno;
×
5774
  }
5775
  pSubTblsInfo->pTsOrderInfo = taosArrayGet(pInfo->pSortInfo, 0);
7,048✔
5776
  if (!pSubTblsInfo->pTsOrderInfo) {
7,041!
UNCOV
5777
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
5778
    return terrno;
×
5779
  }
5780
  if (taosArrayGetSize(pInfo->pSortInfo) == 2) {
7,041✔
5781
    pSubTblsInfo->pPkOrderInfo = taosArrayGet(pInfo->pSortInfo, 1);
5✔
UNCOV
5782
    if (!pSubTblsInfo->pPkOrderInfo) {
×
UNCOV
5783
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
5784
      return terrno;
×
5785
    }
5786
  } else {
5787
    pSubTblsInfo->pPkOrderInfo = NULL;
7,026✔
5788
  }
5789
  pSubTblsInfo->numSubTables = pInfo->tableEndIndex - pInfo->tableStartIndex + 1;
7,026✔
5790
  pSubTblsInfo->aInputs = taosMemoryCalloc(pSubTblsInfo->numSubTables, sizeof(STmsSubTableInput));
7,026!
5791
  if (pSubTblsInfo->aInputs == NULL) {
7,030!
UNCOV
5792
    taosMemoryFree(pSubTblsInfo);
×
UNCOV
5793
    return terrno;
×
5794
  }
5795
  int32_t bufPageSize = pInfo->bufPageSize;
7,030✔
5796
  int32_t inMemSize = (pSubTblsInfo->numSubTables - pSubTblsInfo->numTableBlocksInMem) * bufPageSize;
7,030✔
5797
  code = createDiskbasedBuf(&pSubTblsInfo->pBlocksBuf, pInfo->bufPageSize, inMemSize, "blocksExternalBuf", tsTempDir);
7,030✔
5798
  if (code != TSDB_CODE_SUCCESS) {
7,038✔
5799
    taosMemoryFree(pSubTblsInfo->aInputs);
1!
UNCOV
5800
    taosMemoryFree(pSubTblsInfo);
×
UNCOV
5801
    return code;
×
5802
  }
5803
  pSubTblsInfo->numTableBlocksInMem = pSubTblsInfo->numSubTables;
7,037✔
5804
  pSubTblsInfo->numInMemReaders = pSubTblsInfo->numSubTables;
7,037✔
5805

5806
  pInfo->pSubTablesMergeInfo = pSubTblsInfo;
7,037✔
5807
  return TSDB_CODE_SUCCESS;
7,037✔
5808
}
5809

5810
static int32_t initSubTableInputs(SOperatorInfo* pOperator, STableMergeScanInfo* pInfo) {
7,023✔
5811
  int32_t        code = TSDB_CODE_SUCCESS;
7,023✔
5812
  int32_t        lino = 0;
7,023✔
5813
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
7,023✔
5814
  SReadHandle*   pHandle = &pInfo->base.readHandle;
7,023✔
5815
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
7,023✔
5816

5817
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
7,023✔
5818

5819
  for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
18,251✔
5820
    STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
11,190✔
5821
    pInput->type = SUB_TABLE_MEM_BLOCK;
11,190✔
5822

5823
    code = dumpQueryTableCond(&pInfo->base.cond, &pInput->tblCond);
11,190✔
5824
    QUERY_CHECK_CODE(code, lino, _end);
11,226!
5825

5826
    code = createOneDataBlock(pInfo->pResBlock, false, &pInput->pReaderBlock);
11,226✔
5827
    QUERY_CHECK_CODE(code, lino, _end);
11,222!
5828

5829
    code = createOneDataBlock(pInfo->pResBlock, false, &pInput->pPageBlock);
11,222✔
5830
    QUERY_CHECK_CODE(code, lino, _end);
11,227!
5831

5832
    STableKeyInfo* keyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i + pInfo->tableStartIndex);
11,227✔
5833
    pInput->pKeyInfo = keyInfo;
11,225✔
5834

5835
    if (isTaskKilled(pTaskInfo)) {
11,225!
UNCOV
5836
      T_LONG_JMP(pTaskInfo->env, pTaskInfo->code);
×
5837
    }
5838

5839
    if (i + 1 < pSubTblsInfo->numInMemReaders) {
11,225✔
5840
      code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInput->tblCond, keyInfo, 1, pInput->pReaderBlock,
4,173✔
5841
                                           (void**)&pInput->pReader, GET_TASKID(pTaskInfo), NULL);
4,173✔
5842
      QUERY_CHECK_CODE(code, lino, _end);
4,173!
5843
      pInput->bInMemReader = true;
4,173✔
5844
    } else {
5845
      pInput->pReader = NULL;
7,052✔
5846
      pInput->bInMemReader = false;
7,052✔
5847
    }
5848
    bool hasNext = true;
11,225✔
5849
    code = fetchNextSubTableBlockFromReader(pOperator, pInput, &hasNext);
11,225✔
5850
    QUERY_CHECK_CODE(code, lino, _end);
11,228!
5851
    if (!hasNext) {
11,228✔
5852
      pInput->rowIdx = -1;
5,639✔
5853
      ++pSubTblsInfo->numSubTablesCompleted;
5,639✔
5854
      continue;
5,639✔
5855
    } else {
5856
      pInput->rowIdx = 0;
5,589✔
5857
      pInput->pageIdx = -1;
5,589✔
5858
    }
5859
  }
5860

5861
_end:
7,061✔
5862
  if (code != TSDB_CODE_SUCCESS) {
7,061!
UNCOV
5863
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5864
  }
5865
  return code;
7,056✔
5866
}
5867

5868
static void adjustSubTableFromMemBlock(SOperatorInfo* pOperatorInfo, STmsSubTablesMergeInfo* pSubTblsInfo) {
5,590✔
5869
  int32_t              code = TSDB_CODE_SUCCESS;
5,590✔
5870
  int32_t              lino = 0;
5,590✔
5871
  SExecTaskInfo*       pTaskInfo = pOperatorInfo->pTaskInfo;
5,590✔
5872
  STableMergeScanInfo* pInfo = pOperatorInfo->info;
5,590✔
5873
  STmsSubTableInput*   pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
5,590✔
5874
  bool                 hasNext = true;
5,590✔
5875
  code = fetchNextSubTableBlockFromReader(pOperatorInfo, pInput, &hasNext);
5,590✔
5876
  QUERY_CHECK_CODE(code, lino, _end);
5,590!
5877

5878
  if (!hasNext) {
5,590!
5879
    pInput->rowIdx = -1;
5,590✔
5880
    ++pSubTblsInfo->numSubTablesCompleted;
5,590✔
5881
  } else {
UNCOV
5882
    pInput->rowIdx = 0;
×
5883
  }
5884

5885
_end:
5,590✔
5886
  if (code != TSDB_CODE_SUCCESS) {
5,590!
UNCOV
5887
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
5888
    pTaskInfo->code = code;
×
UNCOV
5889
    T_LONG_JMP(pTaskInfo->env, code);
×
5890
  }
5891
}
5,590✔
5892

5893
static int32_t adjustSubTableForNextRow(SOperatorInfo* pOperatorInfo, STmsSubTablesMergeInfo* pSubTblsInfo) {
1,006,701✔
5894
  STableMergeScanInfo* pInfo = pOperatorInfo->info;
1,006,701✔
5895
  STmsSubTableInput*   pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
1,006,701✔
5896

5897
  SSDataBlock* pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
1,006,701✔
5898
  if (pInput->rowIdx < pInputBlock->info.rows - 1) {
1,006,701✔
5899
    ++pInput->rowIdx;
1,001,154✔
5900
  } else if (pInput->rowIdx == pInputBlock->info.rows - 1) {
5,547!
5901
    if (pInput->type == SUB_TABLE_MEM_BLOCK) {
5,590!
5902
      adjustSubTableFromMemBlock(pOperatorInfo, pSubTblsInfo);
5,590✔
5903
    }
5904
    if (pInput->rowIdx != -1) {
5,590!
UNCOV
5905
      SColumnInfoData* col = taosArrayGet(pInputBlock->pDataBlock, pSubTblsInfo->pTsOrderInfo->slotId);
×
UNCOV
5906
      if (!col) {
×
UNCOV
5907
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
5908
        return terrno;
×
5909
      }
5910
      pInput->pInputBlock = pInputBlock;
×
UNCOV
5911
      pInput->aTs = (int64_t*)col->pData;
×
5912
    }
5913
  }
5914

5915
  return tMergeTreeAdjust(pSubTblsInfo->pTree, tMergeTreeGetAdjustIndex(pSubTblsInfo->pTree));
1,006,701✔
5916
}
5917

5918
static int32_t appendChosenRowToDataBlock(STmsSubTablesMergeInfo* pSubTblsInfo, SSDataBlock* pBlock) {
1,006,673✔
5919
  int32_t            code = TSDB_CODE_SUCCESS;
1,006,673✔
5920
  int32_t            lino = 0;
1,006,673✔
5921
  STmsSubTableInput* pInput = pSubTblsInfo->aInputs + tMergeTreeGetChosenIndex(pSubTblsInfo->pTree);
1,006,673✔
5922
  SSDataBlock*       pInputBlock = (pInput->type == SUB_TABLE_MEM_BLOCK) ? pInput->pReaderBlock : pInput->pPageBlock;
1,006,673!
5923

5924
  for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); ++i) {
4,084,764✔
5925
    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
3,009,607✔
5926
    QUERY_CHECK_NULL(pColInfo, code, lino, _end, terrno);
3,057,218!
5927

5928
    SColumnInfoData* pSrcColInfo = taosArrayGet(pInputBlock->pDataBlock, i);
3,057,218✔
5929
    QUERY_CHECK_NULL(pSrcColInfo, code, lino, _end, terrno);
3,041,106!
5930
    bool isNull = colDataIsNull(pSrcColInfo, pInputBlock->info.rows, pInput->rowIdx, NULL);
3,059,601✔
5931

5932
    if (isNull) {
3,059,601✔
5933
      code = colDataSetVal(pColInfo, pBlock->info.rows, NULL, true);
440,768✔
5934
      QUERY_CHECK_CODE(code, lino, _end);
441,505!
5935
    } else {
5936
      if (pSrcColInfo->pData != NULL) {
2,618,833✔
5937
        char* pData = colDataGetData(pSrcColInfo, pInput->rowIdx);
2,616,398!
5938
        code = colDataSetVal(pColInfo, pBlock->info.rows, pData, false);
2,616,398✔
5939
        QUERY_CHECK_CODE(code, lino, _end);
2,634,151!
5940
      }
5941
    }
5942
  }
5943
  pBlock->info.dataLoad = 1;
1,007,392✔
5944
  pBlock->info.scanFlag = pInputBlock->info.scanFlag;
1,007,392✔
5945
  pBlock->info.rows += 1;
1,007,392✔
5946

5947
_end:
1,007,392✔
5948
  if (code != TSDB_CODE_SUCCESS) {
1,007,392!
UNCOV
5949
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5950
  }
5951
  return code;
1,006,892✔
5952
}
5953

5954
static int32_t getSubTablesSortedBlock(SOperatorInfo* pOperator, SSDataBlock* pBlock, int32_t capacity,
11,201✔
5955
                                       SSDataBlock** pResBlock) {
5956
  int32_t                 code = TSDB_CODE_SUCCESS;
11,201✔
5957
  int32_t                 lino = 0;
11,201✔
5958
  STableMergeScanInfo*    pInfo = pOperator->info;
11,201✔
5959
  SExecTaskInfo*          pTaskInfo = pOperator->pTaskInfo;
11,201✔
5960
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
11,201✔
5961
  bool                    finished = false;
11,201✔
5962

5963
  QRY_PARAM_CHECK(pResBlock);
11,201!
5964

5965
  blockDataCleanup(pBlock);
11,201✔
5966

UNCOV
5967
  while (true) {
×
5968
    while (true) {
5969
      if (pSubTblsInfo->numSubTablesCompleted >= pSubTblsInfo->numSubTables) {
1,018,161✔
5970
        finished = true;
11,207✔
5971
        break;
11,207✔
5972
      }
5973

5974
      code = appendChosenRowToDataBlock(pSubTblsInfo, pBlock);
1,006,954✔
5975
      QUERY_CHECK_CODE(code, lino, _end);
1,006,733!
5976

5977
      code = adjustSubTableForNextRow(pOperator, pSubTblsInfo);
1,006,733✔
5978
      QUERY_CHECK_CODE(code, lino, _end);
1,006,853!
5979

5980
      if (pBlock->info.rows >= capacity) {
1,006,853!
UNCOV
5981
        break;
×
5982
      }
5983
    }
5984

5985
    if (isTaskKilled(pTaskInfo)) {
11,207!
5986
      return pTaskInfo->code;
×
5987
    }
5988

5989
    bool limitReached = applyLimitOffset(&pInfo->limitInfo, pBlock, pTaskInfo);
11,206✔
5990
    if (finished || limitReached || pBlock->info.rows > 0) {
11,205!
5991
      break;
5992
    }
5993
  }
5994

5995
  if (pBlock->info.rows > 0) {
11,205✔
5996
    *pResBlock = pBlock;
4,150✔
5997
  }
5998

5999
_end:
7,055✔
6000
  if (code != TSDB_CODE_SUCCESS) {
11,205!
6001
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6002
    pTaskInfo->code = code;
×
6003
  }
6004
  return code;
11,205✔
6005
}
6006

6007
static int32_t startSubTablesTableMergeScan(SOperatorInfo* pOperator) {
6,997✔
6008
  int32_t              code = TSDB_CODE_SUCCESS;
6,997✔
6009
  int32_t              lino = 0;
6,997✔
6010
  STableMergeScanInfo* pInfo = pOperator->info;
6,997✔
6011

6012
  code = initSubTablesMergeInfo(pInfo);
6,997✔
6013
  QUERY_CHECK_CODE(code, lino, _end);
7,037!
6014

6015
  code = initSubTableInputs(pOperator, pInfo);
7,037✔
6016
  QUERY_CHECK_CODE(code, lino, _end);
7,054!
6017

6018
  code = openSubTablesMergeSort(pInfo->pSubTablesMergeInfo);
7,054✔
6019
  QUERY_CHECK_CODE(code, lino, _end);
7,055!
6020

6021
_end:
7,055✔
6022
  if (code != TSDB_CODE_SUCCESS) {
7,055!
UNCOV
6023
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6024
  }
6025
  return code;
7,055✔
6026
}
6027

6028
static void stopSubTablesTableMergeScan(STableMergeScanInfo* pInfo) {
1,985,440✔
6029
  STmsSubTablesMergeInfo* pSubTblsInfo = pInfo->pSubTablesMergeInfo;
1,985,440✔
6030
  if (pSubTblsInfo != NULL) {
1,985,440✔
6031
    tMergeTreeDestroy(&pSubTblsInfo->pTree);
7,056✔
6032

6033
    for (int32_t i = 0; i < pSubTblsInfo->numSubTables; ++i) {
18,287✔
6034
      STmsSubTableInput* pInput = pSubTblsInfo->aInputs + i;
11,230✔
6035
      taosMemoryFree(pInput->tblCond.colList);
11,230!
6036
      blockDataDestroy(pInput->pReaderBlock);
11,230✔
6037
      blockDataDestroy(pInput->pPageBlock);
11,230✔
6038
      taosArrayDestroy(pInput->aBlockPages);
11,231✔
6039
      pInfo->base.readerAPI.tsdReaderClose(pInput->pReader);
11,231✔
6040
      pInput->pReader = NULL;
11,230✔
6041
    }
6042

6043
    destroyDiskbasedBuf(pSubTblsInfo->pBlocksBuf);
7,057✔
6044
    taosMemoryFree(pSubTblsInfo->aInputs);
7,056!
6045

6046
    taosMemoryFree(pSubTblsInfo);
7,056!
6047
    pInfo->pSubTablesMergeInfo = NULL;
7,057✔
6048

6049
    // taosMemoryTrim(0);
6050
  }
6051
}
1,985,441✔
6052

6053
int32_t doTableMergeScanParaSubTablesNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
11,030✔
6054
  QRY_PARAM_CHECK(ppRes);
11,030!
6055

6056
  int32_t lino = 0;
11,030✔
6057
  int32_t tableListSize = 0;
11,030✔
6058
  int64_t st = taosGetTimestampUs();
11,072✔
6059

6060
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
11,072✔
6061
  STableMergeScanInfo* pInfo = pOperator->info;
11,072✔
6062

6063
  if (pOperator->status == OP_EXEC_DONE) {
11,072!
UNCOV
6064
    return TSDB_CODE_SUCCESS;
×
6065
  }
6066

6067
  int32_t code = pOperator->fpSet._openFn(pOperator);
11,072✔
6068
  QUERY_CHECK_CODE(code, lino, _end);
11,036!
6069

6070
  code = tableListGetSize(pInfo->base.pTableListInfo, &tableListSize);
11,036✔
6071
  QUERY_CHECK_CODE(code, lino, _end);
11,085!
6072

6073
  if (!pInfo->hasGroupId) {
11,085✔
6074
    pInfo->hasGroupId = true;
6,939✔
6075

6076
    if (tableListSize == 0) {
6,939✔
6077
      setOperatorCompleted(pOperator);
122✔
6078
      (*ppRes) = NULL;
123✔
6079
      return code;
123✔
6080
    }
6081

6082
    pInfo->tableStartIndex = 0;
6,817✔
6083
    STableKeyInfo* pTmpGpId = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
6,817✔
6084
    QUERY_CHECK_NULL(pTmpGpId, code, lino, _end, terrno);
6,808!
6085
    pInfo->groupId = pTmpGpId->groupId;
6,808✔
6086
    code = startSubTablesTableMergeScan(pOperator);
6,808✔
6087
    QUERY_CHECK_CODE(code, lino, _end);
6,822!
6088
  }
6089

6090
  SSDataBlock* pBlock = NULL;
10,968✔
6091
  while (pInfo->tableStartIndex < tableListSize) {
11,198!
6092
    if (isTaskKilled(pTaskInfo)) {
11,200!
UNCOV
6093
      break;
×
6094
    }
6095

6096
    code = getSubTablesSortedBlock(pOperator, pInfo->pResBlock, pOperator->resultInfo.capacity, &pBlock);
11,201✔
6097
    QUERY_CHECK_CODE(code, lino, _end);
11,206!
6098

6099
    if (pBlock == NULL && !pInfo->bGroupProcessed && pInfo->needCountEmptyTable) {
11,206!
UNCOV
6100
      STableKeyInfo* tbInfo = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
×
UNCOV
6101
      QUERY_CHECK_NULL(tbInfo, code, lino, _end, terrno);
×
6102

UNCOV
6103
      pBlock = getOneRowResultBlock(pTaskInfo, &pInfo->base, pInfo->pResBlock, tbInfo);
×
6104
    }
6105

6106
    if (pBlock != NULL) {
11,206✔
6107
      pBlock->info.id.groupId = pInfo->groupId;
4,150✔
6108
      pOperator->resultInfo.totalRows += pBlock->info.rows;
4,150✔
6109
      pInfo->bGroupProcessed = true;
4,150✔
6110
      break;
4,150✔
6111
    } else {
6112
      // Data of this group are all dumped, let's try the next group
6113
      stopSubTablesTableMergeScan(pInfo);
7,056✔
6114
      if (pInfo->tableEndIndex >= tableListSize - 1) {
7,057✔
6115
        setOperatorCompleted(pOperator);
6,827✔
6116
        break;
6,827✔
6117
      }
6118

6119
      pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
230✔
6120
      STableKeyInfo* pTmpGpId = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
230✔
6121
      QUERY_CHECK_NULL(pTmpGpId, code, lino, _end, terrno);
230!
6122

6123
      pInfo->groupId = pTmpGpId->groupId;
230✔
6124
      code = startSubTablesTableMergeScan(pOperator);
230✔
6125
      QUERY_CHECK_CODE(code, lino, _end);
230!
6126
      resetLimitInfoForNextGroup(&pInfo->limitInfo);
230✔
6127
    }
6128
  }
6129

6130
  pOperator->cost.totalCost += (taosGetTimestampUs() - st) / 1000.0;
10,977✔
6131

6132
_end:
10,977✔
6133
  if (code != TSDB_CODE_SUCCESS) {
10,977!
UNCOV
6134
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
6135
    pTaskInfo->code = code;
×
UNCOV
6136
    T_LONG_JMP(pTaskInfo->env, code);
×
6137
  } else {
6138
    (*ppRes) = pBlock;
10,977✔
6139
  }
6140

6141
  return code;
10,977✔
6142
}
6143

6144
static void tableMergeScanDoSkipTable(uint64_t uid, void* pTableMergeOpInfo) {
47,113✔
6145
  int32_t              code = TSDB_CODE_SUCCESS;
47,113✔
6146
  int32_t              lino = 0;
47,113✔
6147
  SOperatorInfo*       pOperator = (SOperatorInfo*)pTableMergeOpInfo;
47,113✔
6148
  STableMergeScanInfo* pInfo = pOperator->info;
47,113✔
6149
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
47,113✔
6150

6151
  if (pInfo->mSkipTables == NULL) {
47,113✔
6152
    pInfo->mSkipTables = taosHashInit(pInfo->tableEndIndex - pInfo->tableStartIndex + 1,
18,546✔
6153
                                      taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_NO_LOCK);
6154
    QUERY_CHECK_NULL(pInfo->mSkipTables, code, lino, _end, terrno);
18,548!
6155
  }
6156
  int bSkip = 1;
47,115✔
6157
  if (pInfo->mSkipTables != NULL) {
47,115!
6158
    code = taosHashPut(pInfo->mSkipTables, &uid, sizeof(uid), &bSkip, sizeof(bSkip));
47,115✔
6159
    if (code == TSDB_CODE_DUP_KEY) {
47,125!
UNCOV
6160
      code = TSDB_CODE_SUCCESS;
×
6161
    }
6162
    QUERY_CHECK_CODE(code, lino, _end);
47,125!
6163
  }
6164

6165
_end:
47,125✔
6166
  if (code != TSDB_CODE_SUCCESS) {
47,125!
UNCOV
6167
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
6168
    pTaskInfo->code = code;
×
UNCOV
6169
    T_LONG_JMP(pTaskInfo->env, code);
×
6170
  }
6171
}
47,125✔
6172

6173
static int32_t doGetBlockForTableMergeScan(SOperatorInfo* pOperator, bool* pFinished, bool* pSkipped) {
6,108,682✔
6174
  STableMergeScanInfo* pInfo = pOperator->info;
6,108,682✔
6175
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
6,108,682✔
6176
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
6,108,682✔
6177
  SSDataBlock*         pBlock = pInfo->pReaderBlock;
6,108,682✔
6178
  int32_t              code = 0;
6,108,682✔
6179
  bool                 hasNext = false;
6,108,682✔
6180
  STsdbReader*         reader = pInfo->base.dataReader;
6,108,682✔
6181

6182
  code = pAPI->tsdReader.tsdNextDataBlock(reader, &hasNext);
6,108,682✔
6183
  if (code != 0) {
6,111,785!
UNCOV
6184
    pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
×
UNCOV
6185
    qError("table merge scan fetch next data block error code: %d, %s", code, GET_TASKID(pTaskInfo));
×
UNCOV
6186
    pTaskInfo->code = code;
×
UNCOV
6187
    return code;
×
6188
  }
6189

6190
  if (!hasNext || isTaskKilled(pTaskInfo)) {
6,111,785!
6191
    if (isTaskKilled(pTaskInfo)) {
1,893,144!
UNCOV
6192
      qInfo("table merge scan fetch next data block found task killed. %s", GET_TASKID(pTaskInfo));
×
UNCOV
6193
      pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
×
6194
    }
6195
    *pFinished = true;
1,893,375✔
6196
    return code;
1,893,375✔
6197
  }
6198

6199
  uint32_t status = 0;
4,218,596✔
6200
  code = loadDataBlock(pOperator, &pInfo->base, pBlock, &status);
4,218,596✔
6201

6202
  if (code != TSDB_CODE_SUCCESS) {
4,218,083!
UNCOV
6203
    qInfo("table merge scan load datablock code %d, %s", code, GET_TASKID(pTaskInfo));
×
UNCOV
6204
    pTaskInfo->code = code;
×
UNCOV
6205
    return code;
×
6206
  }
6207

6208
  if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) {
4,218,159!
UNCOV
6209
    *pFinished = true;
×
UNCOV
6210
    return code;
×
6211
  }
6212

6213
  // current block is filter out according to filter condition, continue load the next block
6214
  if (status == FUNC_DATA_REQUIRED_FILTEROUT || pBlock->info.rows == 0) {
4,218,159!
6215
    *pSkipped = true;
5,371✔
6216
    return code;
5,371✔
6217
  }
6218

6219
  return code;
4,212,788✔
6220
}
6221

6222
static int32_t getBlockForTableMergeScan(void* param, SSDataBlock** ppBlock) {
7,699,574✔
6223
  STableMergeScanSortSourceParam* source = param;
7,699,574✔
6224

6225
  SOperatorInfo*       pOperator = source->pOperator;
7,699,574✔
6226
  STableMergeScanInfo* pInfo = pOperator->info;
7,699,574✔
6227
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
7,699,574✔
6228
  SSDataBlock*         pBlock = NULL;
7,699,574✔
6229
  int64_t              st = taosGetTimestampUs();
7,700,881✔
6230
  int32_t              code = TSDB_CODE_SUCCESS;
7,700,881✔
6231

6232
  while (true) {
6233
    if (pInfo->rtnNextDurationBlocks) {
9,297,745✔
6234
      qDebug("%s table merge scan return already fetched new duration blocks. index %d num of blocks %d",
3,189,064✔
6235
             GET_TASKID(pTaskInfo), pInfo->nextDurationBlocksIdx, pInfo->numNextDurationBlocks);
6236

6237
      if (pInfo->nextDurationBlocksIdx < pInfo->numNextDurationBlocks) {
3,189,064✔
6238
        pBlock = pInfo->nextDurationBlocks[pInfo->nextDurationBlocksIdx];
1,593,262✔
6239
        ++pInfo->nextDurationBlocksIdx;
1,593,262✔
6240
      } else {
6241
        for (int32_t i = 0; i < pInfo->numNextDurationBlocks; ++i) {
3,189,085✔
6242
          blockDataDestroy(pInfo->nextDurationBlocks[i]);
1,593,280✔
6243
          pInfo->nextDurationBlocks[i] = NULL;
1,593,283✔
6244
        }
6245

6246
        pInfo->rtnNextDurationBlocks = false;
1,595,805✔
6247
        pInfo->nextDurationBlocksIdx = 0;
1,595,805✔
6248
        pInfo->numNextDurationBlocks = 0;
1,595,805✔
6249
        continue;
1,595,805✔
6250
      }
6251
    } else {
6252
      bool bFinished = false;
6,108,681✔
6253
      bool bSkipped = false;
6,108,681✔
6254

6255
      code = doGetBlockForTableMergeScan(pOperator, &bFinished, &bSkipped);
6,108,681✔
6256
      if (code != 0) {
6,111,245!
6257
        return code;
1,597,200✔
6258
      }
6259

6260
      pBlock = pInfo->pReaderBlock;
6,111,245✔
6261
      qDebug("%s table merge scan fetch block. finished %d skipped %d next-duration-block %d new-fileset %d",
6,111,245✔
6262
             GET_TASKID(pTaskInfo), bFinished, bSkipped, pInfo->bNextDurationBlockEvent, pInfo->bNewFilesetEvent);
6263
      if (bFinished) {
6,111,354✔
6264
        pInfo->bNewFilesetEvent = false;
1,893,310✔
6265
        break;
1,893,310✔
6266
      }
6267

6268
      if (pInfo->bNextDurationBlockEvent || pInfo->bNewFilesetEvent) {
4,218,044!
6269
        if (!bSkipped) {
1,597,217✔
6270
          code = createOneDataBlock(pBlock, true, &pInfo->nextDurationBlocks[pInfo->numNextDurationBlocks]);
1,594,700✔
6271
          if (code) {
1,594,683!
UNCOV
6272
            *ppBlock = NULL;
×
UNCOV
6273
            return code;
×
6274
          }
6275

6276
          ++pInfo->numNextDurationBlocks;
1,594,683✔
6277
          if (pInfo->numNextDurationBlocks > 2) {
1,594,683!
UNCOV
6278
            qError("%s table merge scan prefetch %d next duration blocks. end early.", GET_TASKID(pTaskInfo),
×
6279
                   pInfo->numNextDurationBlocks);
UNCOV
6280
            pInfo->bNewFilesetEvent = false;
×
UNCOV
6281
            break;
×
6282
          }
6283
        }
6284

6285
        if (pInfo->bNewFilesetEvent) {
1,597,200!
6286
          pInfo->rtnNextDurationBlocks = true;
1,597,200✔
6287
          *ppBlock = NULL;
1,597,200✔
6288
          return code;
1,597,200✔
6289
        }
6290

UNCOV
6291
        if (pInfo->bNextDurationBlockEvent) {
×
UNCOV
6292
          pInfo->bNextDurationBlockEvent = false;
×
6293
          continue;
1,059✔
6294
        }
6295
      }
6296
      if (bSkipped) continue;
2,620,827✔
6297
    }
6298

6299
    pBlock->info.id.groupId = tableListGetTableGroupId(pInfo->base.pTableListInfo, pBlock->info.id.uid);
4,213,030✔
6300

6301
    pOperator->resultInfo.totalRows += pBlock->info.rows;
4,211,548✔
6302
    pInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
4,211,583✔
6303
    *ppBlock = pBlock;
4,211,583✔
6304

6305
    return code;
4,211,583✔
6306
  }
6307

6308
  *ppBlock = NULL;
1,893,310✔
6309
  return code;
1,893,310✔
6310
}
6311

6312
int32_t generateSortByTsPkInfo(SArray* colMatchInfo, int32_t order, SArray** ppSortArray) {
1,973,003✔
6313
  int32_t code = TSDB_CODE_SUCCESS;
1,973,003✔
6314
  int32_t lino = 0;
1,973,003✔
6315
  SArray* pSortInfo = taosArrayInit(1, sizeof(SBlockOrderInfo));
1,973,003✔
6316
  QUERY_CHECK_NULL(pSortInfo, code, lino, _end, terrno);
1,976,110!
6317
  SBlockOrderInfo biTs = {0};
1,976,812✔
6318
  SBlockOrderInfo biPk = {0};
1,976,812✔
6319

6320
  int32_t tsTargetSlotId = 0;
1,976,812✔
6321
  int32_t pkTargetSlotId = -1;
1,976,812✔
6322
  for (int32_t i = 0; i < taosArrayGetSize(colMatchInfo); ++i) {
11,784,976✔
6323
    SColMatchItem* colInfo = taosArrayGet(colMatchInfo, i);
9,815,892✔
6324
    QUERY_CHECK_NULL(colInfo, code, lino, _end, terrno);
9,813,961✔
6325
    if (colInfo->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
9,809,026✔
6326
      tsTargetSlotId = colInfo->dstSlotId;
1,974,517✔
6327
      biTs.order = order;
1,974,517✔
6328
      biTs.slotId = tsTargetSlotId;
1,974,517✔
6329
      biTs.nullFirst = (order == TSDB_ORDER_ASC);
1,974,517✔
6330
      biTs.compFn = getKeyComparFunc(TSDB_DATA_TYPE_TIMESTAMP, order);
1,974,517✔
6331
    }
6332
    // TODO: order by just ts
6333
    if (colInfo->isPk) {
9,808,164✔
6334
      pkTargetSlotId = colInfo->dstSlotId;
52✔
6335
      biPk.order = order;
52✔
6336
      biPk.slotId = pkTargetSlotId;
52✔
6337
      biPk.nullFirst = (order == TSDB_ORDER_ASC);
52✔
6338
      biPk.compFn = getKeyComparFunc(colInfo->dataType.type, order);
52✔
6339
    }
6340
  }
6341

6342
  void* tmp = taosArrayPush(pSortInfo, &biTs);
1,975,617✔
6343
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,975,617!
6344
  if (pkTargetSlotId != -1) {
1,975,617✔
6345
    tmp = taosArrayPush(pSortInfo, &biPk);
52✔
6346
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
52!
6347
  }
6348

6349
  (*ppSortArray) = pSortInfo;
1,975,617✔
6350

6351
_end:
1,975,617✔
6352
  if (code != TSDB_CODE_SUCCESS) {
1,975,617!
UNCOV
6353
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6354
  }
6355
  return code;
1,971,716✔
6356
}
6357

6358
void tableMergeScanTsdbNotifyCb(ETsdReaderNotifyType type, STsdReaderNotifyInfo* info, void* param) {
2,075,219✔
6359
  STableMergeScanInfo* pTmsInfo = param;
2,075,219✔
6360
  if (type == TSD_READER_NOTIFY_DURATION_START) {
2,075,219!
6361
    pTmsInfo->bNewFilesetEvent = true;
2,075,650✔
UNCOV
6362
  } else if (type == TSD_READER_NOTIFY_NEXT_DURATION_BLOCK) {
×
UNCOV
6363
    pTmsInfo->bNextDurationBlockEvent = true;
×
6364
  }
6365
  qDebug("table merge scan receive notification. type %d, fileset %d", type, info->duration.filesetId);
2,075,219✔
6366

6367
  return;
2,075,159✔
6368
}
6369

6370
int32_t startDurationForGroupTableMergeScan(SOperatorInfo* pOperator) {
3,488,094✔
6371
  STableMergeScanInfo* pInfo = pOperator->info;
3,488,094✔
6372
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
3,488,094✔
6373

6374
  int32_t code = TSDB_CODE_SUCCESS;
3,488,094✔
6375
  int32_t lino = 0;
3,488,094✔
6376
  int32_t numOfTable = pInfo->tableEndIndex - pInfo->tableStartIndex + 1;
3,488,094✔
6377

6378
  qDebug("%s table merge scan start duration ", GET_TASKID(pTaskInfo));
3,488,094✔
6379
  pInfo->bNewFilesetEvent = false;
3,488,095✔
6380
  pInfo->bNextDurationBlockEvent = false;
3,488,095✔
6381

6382
  pInfo->sortBufSize = 2048 * pInfo->bufPageSize;
3,488,095✔
6383
  int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
3,488,095✔
6384

6385
  pInfo->pSortHandle = NULL;
3,488,095✔
6386
  code = tsortCreateSortHandle(pInfo->pSortInfo, SORT_BLOCK_TS_MERGE, pInfo->bufPageSize, numOfBufPage,
3,488,095✔
6387
                               pInfo->pSortInputBlock, pTaskInfo->id.str, 0, 0, 0, &pInfo->pSortHandle);
3,488,095✔
6388
  if (code) {
3,486,359!
UNCOV
6389
    return code;
×
6390
  }
6391

6392
  if (pInfo->bSortRowId && numOfTable != 1) {
3,486,359✔
6393
    int32_t memSize = 512 * 1024 * 1024;
671,526✔
6394
    code = tsortSetSortByRowId(pInfo->pSortHandle, memSize);
671,526✔
6395
    QUERY_CHECK_CODE(code, lino, _end);
672,222!
6396
  }
6397

6398
  tsortSetMergeLimit(pInfo->pSortHandle, pInfo->mergeLimit);
3,487,055✔
6399
  tsortSetMergeLimitReachedFp(pInfo->pSortHandle, tableMergeScanDoSkipTable, pOperator);
3,485,952✔
6400
  tsortSetAbortCheckFn(pInfo->pSortHandle, isTaskKilled, pOperator->pTaskInfo);
3,486,593✔
6401

6402
  tsortSetFetchRawDataFp(pInfo->pSortHandle, getBlockForTableMergeScan, NULL, NULL);
3,485,895✔
6403
  QUERY_CHECK_CODE(code, lino, _end);
3,485,942!
6404

6405
  STableMergeScanSortSourceParam* param = taosMemoryCalloc(1, sizeof(STableMergeScanSortSourceParam));
3,485,942!
6406
  QUERY_CHECK_NULL(param, code, lino, _end, terrno);
3,489,769!
6407
  param->pOperator = pOperator;
3,489,769✔
6408

6409
  SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
3,489,769!
6410
  if (ps == NULL) {
3,489,895!
UNCOV
6411
    taosMemoryFree(param);
×
UNCOV
6412
    QUERY_CHECK_NULL(ps, code, lino, _end, terrno);
×
6413
  }
6414

6415
  ps->param = param;
3,489,895✔
6416
  ps->onlyRef = false;
3,489,895✔
6417
  code = tsortAddSource(pInfo->pSortHandle, ps);
3,489,895✔
6418
  QUERY_CHECK_CODE(code, lino, _end);
3,486,527!
6419

6420
  if (numOfTable == 1) {
3,486,527✔
6421
    tsortSetSingleTableMerge(pInfo->pSortHandle);
1,200,519✔
6422
  } else {
6423
    code = tsortOpen(pInfo->pSortHandle);
2,286,008✔
6424
    QUERY_CHECK_CODE(code, lino, _end);
2,289,524!
6425
  }
6426

6427
_end:
2,289,524✔
6428
  if (code != TSDB_CODE_SUCCESS) {
3,490,113!
UNCOV
6429
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6430
  }
6431
  return code;
3,490,020✔
6432
}
6433

6434
void stopDurationForGroupTableMergeScan(SOperatorInfo* pOperator) {
3,487,241✔
6435
  STableMergeScanInfo* pInfo = pOperator->info;
3,487,241✔
6436
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
3,487,241✔
6437
  qDebug("%s table merge scan stop duration ", GET_TASKID(pTaskInfo));
3,487,241✔
6438

6439
  SSortExecInfo sortExecInfo = tsortGetSortExecInfo(pInfo->pSortHandle);
3,487,240✔
6440
  pInfo->sortExecInfo.sortMethod = sortExecInfo.sortMethod;
3,487,625✔
6441
  pInfo->sortExecInfo.sortBuffer = sortExecInfo.sortBuffer;
3,487,625✔
6442
  pInfo->sortExecInfo.loops += sortExecInfo.loops;
3,487,625✔
6443
  pInfo->sortExecInfo.readBytes += sortExecInfo.readBytes;
3,487,625✔
6444
  pInfo->sortExecInfo.writeBytes += sortExecInfo.writeBytes;
3,487,625✔
6445

6446
  tsortDestroySortHandle(pInfo->pSortHandle);
3,487,625✔
6447
  pInfo->pSortHandle = NULL;
3,487,865✔
6448
}
3,487,865✔
6449

6450
void startGroupTableMergeScan(SOperatorInfo* pOperator) {
1,885,855✔
6451
  int32_t              code = TSDB_CODE_SUCCESS;
1,885,855✔
6452
  int32_t              lino = 0;
1,885,855✔
6453
  STableMergeScanInfo* pInfo = pOperator->info;
1,885,855✔
6454
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
1,885,855✔
6455
  SReadHandle*         pHandle = &pInfo->base.readHandle;
1,885,855✔
6456
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
1,885,855✔
6457
  qDebug("%s table merge scan start group %" PRIu64, GET_TASKID(pTaskInfo), pInfo->groupId);
1,885,855✔
6458

6459
  {
6460
    int32_t numOfTables = 0;
1,885,855✔
6461
    code = tableListGetSize(pInfo->base.pTableListInfo, &numOfTables);
1,885,855✔
6462
    QUERY_CHECK_CODE(code, lino, _end);
1,885,588!
6463

6464
    int32_t i = pInfo->tableStartIndex + 1;
1,885,588✔
6465
    for (; i < numOfTables; ++i) {
4,831,113✔
6466
      STableKeyInfo* tableKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i);
3,004,831✔
6467
      QUERY_CHECK_NULL(tableKeyInfo, code, lino, _end, terrno);
3,005,900!
6468
      if (tableKeyInfo->groupId != pInfo->groupId) {
3,006,033✔
6469
        break;
60,508✔
6470
      }
6471
    }
6472
    pInfo->tableEndIndex = i - 1;
1,886,790✔
6473
  }
6474
  pInfo->bGroupProcessed = false;
1,886,790✔
6475
  int32_t tableStartIdx = pInfo->tableStartIndex;
1,886,790✔
6476
  int32_t tableEndIdx = pInfo->tableEndIndex;
1,886,790✔
6477

6478
  int32_t        numOfTable = tableEndIdx - tableStartIdx + 1;
1,886,790✔
6479
  STableKeyInfo* startKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, tableStartIdx);
1,886,790✔
6480
  code = pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInfo->base.cond, startKeyInfo, numOfTable, pInfo->pReaderBlock,
1,888,311✔
6481
                                       (void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), &pInfo->mSkipTables);
1,888,311✔
6482
  QUERY_CHECK_CODE(code, lino, _end);
1,893,387!
6483
  if (pInfo->filesetDelimited) {
1,893,387!
6484
    pAPI->tsdReader.tsdSetFilesetDelimited(pInfo->base.dataReader);
1,893,736✔
6485
  }
6486
  pAPI->tsdReader.tsdSetSetNotifyCb(pInfo->base.dataReader, tableMergeScanTsdbNotifyCb, pInfo);
1,890,520✔
6487

6488
  code = startDurationForGroupTableMergeScan(pOperator);
1,892,573✔
6489
  QUERY_CHECK_CODE(code, lino, _end);
1,893,961!
6490

6491
_end:
1,893,961✔
6492
  if (code != TSDB_CODE_SUCCESS) {
1,893,961!
UNCOV
6493
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
6494
    pTaskInfo->code = code;
×
UNCOV
6495
    T_LONG_JMP(pTaskInfo->env, code);
×
6496
  }
6497
}
1,893,961✔
6498

6499
void stopGroupTableMergeScan(SOperatorInfo* pOperator) {
1,891,516✔
6500
  STableMergeScanInfo* pInfo = pOperator->info;
1,891,516✔
6501
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
1,891,516✔
6502
  SStorageAPI*         pAPI = &pTaskInfo->storageAPI;
1,891,516✔
6503

6504
  stopDurationForGroupTableMergeScan(pOperator);
1,891,516✔
6505

6506
  if (pInfo->base.dataReader != NULL) {
1,892,095✔
6507
    pAPI->tsdReader.tsdReaderClose(pInfo->base.dataReader);
1,892,090✔
6508
    pInfo->base.dataReader = NULL;
1,892,058✔
6509
  }
6510
  for (int32_t i = 0; i < pInfo->numNextDurationBlocks; ++i) {
1,892,063!
UNCOV
6511
    if (pInfo->nextDurationBlocks[i]) {
×
UNCOV
6512
      blockDataDestroy(pInfo->nextDurationBlocks[i]);
×
UNCOV
6513
      pInfo->nextDurationBlocks[i] = NULL;
×
6514
    }
UNCOV
6515
    pInfo->numNextDurationBlocks = 0;
×
UNCOV
6516
    pInfo->nextDurationBlocksIdx = 0;
×
6517
  }
6518
  resetLimitInfoForNextGroup(&pInfo->limitInfo);
1,892,063✔
6519
  taosHashCleanup(pInfo->mSkipTables);
1,891,794✔
6520
  pInfo->mSkipTables = NULL;
1,891,678✔
6521
  qDebug("%s table merge scan stop group %" PRIu64, GET_TASKID(pTaskInfo), pInfo->groupId);
1,891,678✔
6522
}
1,891,678✔
6523

6524
// all data produced by this function only belongs to one group
6525
// slimit/soffset does not need to be concerned here, since this function only deal with data within one group.
6526
SSDataBlock* getSortedTableMergeScanBlockData(SSortHandle* pHandle, SSDataBlock* pResBlock, int32_t capacity,
9,286,342✔
6527
                                              SOperatorInfo* pOperator) {
6528
  STableMergeScanInfo* pInfo = pOperator->info;
9,286,342✔
6529
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
9,286,342✔
6530
  STupleHandle*        pTupleHandle = NULL;
9,286,342✔
6531

6532
  blockDataCleanup(pResBlock);
9,286,342✔
6533

UNCOV
6534
  while (1) {
×
6535
    while (1) {
2,147,483,647✔
6536
      pTupleHandle = NULL;
2,147,483,647✔
6537
      int32_t code = tsortNextTuple(pHandle, &pTupleHandle);
2,147,483,647✔
6538
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
6539
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
180,274!
6540
        T_LONG_JMP(pOperator->pTaskInfo->env, code);
180,274!
6541
      }
6542
      if (pTupleHandle == NULL) {
2,147,483,647✔
6543
        break;
5,627,674✔
6544
      }
6545

6546
      code = tsortAppendTupleToBlock(pInfo->pSortHandle, pResBlock, pTupleHandle);
2,147,483,647✔
6547
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647!
UNCOV
6548
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
UNCOV
6549
        T_LONG_JMP(pOperator->pTaskInfo->env, terrno);
×
6550
      }
6551

6552
      if (pResBlock->info.rows >= capacity) {
2,147,483,647✔
6553
        break;
3,659,619✔
6554
      }
6555
    }
6556

6557
    if (tsortIsClosed(pHandle)) {
9,287,293!
UNCOV
6558
      terrno = TSDB_CODE_TSC_QUERY_CANCELLED;
×
UNCOV
6559
      T_LONG_JMP(pOperator->pTaskInfo->env, terrno);
×
6560
    }
6561

6562
    bool limitReached = applyLimitOffset(&pInfo->limitInfo, pResBlock, pTaskInfo);
9,287,431✔
6563
    qDebug("%s get sorted row block, rows:%" PRId64 ", limit:%" PRId64, GET_TASKID(pTaskInfo), pResBlock->info.rows,
9,287,155✔
6564
           pInfo->limitInfo.numOfOutputRows);
6565
    if (pTupleHandle == NULL || limitReached || pResBlock->info.rows > 0) {
9,287,346!
6566
      break;
6567
    }
6568
  }
6569
  return (pResBlock->info.rows > 0) ? pResBlock : NULL;
9,287,346✔
6570
}
6571

6572
int32_t doTableMergeScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
7,794,149✔
6573
  if (pOperator->status == OP_EXEC_DONE) {
7,794,149✔
6574
    (*ppRes) = NULL;
33,005✔
6575
    return TSDB_CODE_SUCCESS;
33,005✔
6576
  }
6577

6578
  int32_t              code = TSDB_CODE_SUCCESS;
7,761,144✔
6579
  int32_t              lino = 0;
7,761,144✔
6580
  SExecTaskInfo*       pTaskInfo = pOperator->pTaskInfo;
7,761,144✔
6581
  STableMergeScanInfo* pInfo = pOperator->info;
7,761,144✔
6582

6583
  code = pOperator->fpSet._openFn(pOperator);
7,761,144✔
6584
  QUERY_CHECK_CODE(code, lino, _end);
7,758,203!
6585

6586
  int64_t st = taosGetTimestampUs();
7,761,849✔
6587

6588
  int32_t tableListSize = 0;
7,761,849✔
6589
  code = tableListGetSize(pInfo->base.pTableListInfo, &tableListSize);
7,761,849✔
6590
  QUERY_CHECK_CODE(code, lino, _end);
7,761,098!
6591

6592
  if (!pInfo->hasGroupId) {
7,761,098✔
6593
    pInfo->hasGroupId = true;
1,964,897✔
6594

6595
    if (tableListSize == 0) {
1,964,897✔
6596
      setOperatorCompleted(pOperator);
137,114✔
6597
      (*ppRes) = NULL;
137,159✔
6598
      return code;
137,159✔
6599
    }
6600
    pInfo->tableStartIndex = 0;
1,827,783✔
6601
    STableKeyInfo* tmp = (STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
1,827,783✔
6602
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,826,510!
6603
    pInfo->groupId = tmp->groupId;
1,826,510✔
6604
    startGroupTableMergeScan(pOperator);
1,826,510✔
6605
  }
6606

6607
  SSDataBlock* pBlock = NULL;
7,630,521✔
6608
  while (pInfo->tableStartIndex < tableListSize) {
9,286,650!
6609
    if (isTaskKilled(pTaskInfo)) {
9,286,650✔
6610
      goto _end;
123✔
6611
    }
6612

6613
    pBlock = getSortedTableMergeScanBlockData(pInfo->pSortHandle, pInfo->pResBlock, pOperator->resultInfo.capacity,
9,286,523✔
6614
                                              pOperator);
6615
    if (pBlock == NULL && !pInfo->bGroupProcessed && pInfo->needCountEmptyTable) {
9,287,165✔
6616
      STableKeyInfo* tbInfo = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
14,245✔
6617
      QUERY_CHECK_NULL(tbInfo, code, lino, _end, terrno);
14,244!
6618
      pBlock = getOneRowResultBlock(pTaskInfo, &pInfo->base, pInfo->pResBlock, tbInfo);
14,244✔
6619
    }
6620
    if (pBlock != NULL) {
9,287,276✔
6621
      pBlock->info.id.groupId = pInfo->groupId;
5,799,812✔
6622
      pOperator->resultInfo.totalRows += pBlock->info.rows;
5,799,812✔
6623
      pInfo->bGroupProcessed = true;
5,799,812✔
6624
      break;
5,799,812✔
6625
    } else {
6626
      if (pInfo->bNewFilesetEvent) {
3,487,464✔
6627
        stopDurationForGroupTableMergeScan(pOperator);
1,595,787✔
6628
        code = startDurationForGroupTableMergeScan(pOperator);
1,595,803✔
6629
        QUERY_CHECK_CODE(code, lino, _end);
1,595,774!
6630
      } else {
6631
        // Data of this group are all dumped, let's try the next group
6632
        stopGroupTableMergeScan(pOperator);
1,891,677✔
6633
        if (pInfo->tableEndIndex >= tableListSize - 1) {
1,891,695✔
6634
          setOperatorCompleted(pOperator);
1,831,243✔
6635
          break;
1,831,260✔
6636
        }
6637

6638
        pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
60,452✔
6639
        STableKeyInfo* tmp = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex);
60,452✔
6640
        QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
60,611!
6641
        pInfo->groupId = tmp->groupId;
60,611✔
6642
        startGroupTableMergeScan(pOperator);
60,611✔
6643
        resetLimitInfoForNextGroup(&pInfo->limitInfo);
60,520✔
6644
      }
6645
    }
6646
  }
6647

6648
  pOperator->cost.totalCost += (taosGetTimestampUs() - st) / 1000.0;
7,631,101✔
6649

6650
_end:
7,631,224✔
6651
  if (code != TSDB_CODE_SUCCESS) {
7,631,224!
UNCOV
6652
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
6653
    pTaskInfo->code = code;
×
UNCOV
6654
    T_LONG_JMP(pTaskInfo->env, code);
×
6655
  } else {
6656
    (*ppRes) = pBlock;
7,631,224✔
6657
  }
6658

6659
  return code;
7,631,224✔
6660
}
6661

6662
static SSDataBlock* doTableMergeScan(SOperatorInfo* pOperator) {
×
UNCOV
6663
  SSDataBlock* pRes = NULL;
×
6664
  int32_t      code = doTableMergeScanNext(pOperator, &pRes);
×
6665
  return pRes;
×
6666
}
6667

6668
void destroyTableMergeScanOperatorInfo(void* param) {
1,977,853✔
6669
  STableMergeScanInfo* pTableScanInfo = (STableMergeScanInfo*)param;
1,977,853✔
6670

6671
  // start one reader variable
6672
  if (pTableScanInfo->base.readerAPI.tsdReaderClose != NULL) {
1,977,853!
6673
    pTableScanInfo->base.readerAPI.tsdReaderClose(pTableScanInfo->base.dataReader);
1,978,007✔
6674
    pTableScanInfo->base.dataReader = NULL;
1,977,911✔
6675
  }
6676

6677
  for (int32_t i = 0; i < pTableScanInfo->numNextDurationBlocks; ++i) {
1,979,195✔
6678
    if (pTableScanInfo->nextDurationBlocks[i] != NULL) {
1,438!
6679
      blockDataDestroy(pTableScanInfo->nextDurationBlocks[i]);
1,438✔
6680
      pTableScanInfo->nextDurationBlocks[i] = NULL;
1,438✔
6681
    }
6682
  }
6683

6684
  tsortDestroySortHandle(pTableScanInfo->pSortHandle);
1,977,757✔
6685
  pTableScanInfo->pSortHandle = NULL;
1,977,767✔
6686
  taosHashCleanup(pTableScanInfo->mSkipTables);
1,977,767✔
6687
  pTableScanInfo->mSkipTables = NULL;
1,977,751✔
6688
  blockDataDestroy(pTableScanInfo->pSortInputBlock);
1,977,751✔
6689
  pTableScanInfo->pSortInputBlock = NULL;
1,978,377✔
6690
  // end one reader variable
6691

6692
  cleanupQueryTableDataCond(&pTableScanInfo->base.cond);
1,978,377✔
6693
  destroyTableScanBase(&pTableScanInfo->base, &pTableScanInfo->base.readerAPI);
1,978,264✔
6694

6695
  blockDataDestroy(pTableScanInfo->pResBlock);
1,978,377✔
6696
  pTableScanInfo->pResBlock = NULL;
1,978,455✔
6697

6698
  // remove it from the task->result list
6699
  blockDataDestroy(pTableScanInfo->pReaderBlock);
1,978,455✔
6700
  pTableScanInfo->pReaderBlock = NULL;
1,978,460✔
6701
  taosArrayDestroy(pTableScanInfo->pSortInfo);
1,978,460✔
6702

6703
  stopSubTablesTableMergeScan(pTableScanInfo);
1,978,461✔
6704

6705
  taosMemoryFreeClear(param);
1,978,372!
6706
}
1,978,431✔
6707

6708
int32_t getTableMergeScanExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
249,153✔
6709
  if (pOptr == NULL) {
249,153!
6710
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_INVALID_PARA));
×
6711
    return TSDB_CODE_INVALID_PARA;
×
6712
  }
6713
  // TODO: merge these two info into one struct
6714
  STableMergeScanExecInfo* execInfo = taosMemoryCalloc(1, sizeof(STableMergeScanExecInfo));
249,153!
6715
  if (!execInfo) {
249,191!
6716
    return terrno;
×
6717
  }
6718
  STableMergeScanInfo* pInfo = pOptr->info;
249,191✔
6719
  execInfo->blockRecorder = pInfo->base.readRecorder;
249,191✔
6720
  execInfo->sortExecInfo = pInfo->sortExecInfo;
249,191✔
6721

6722
  *pOptrExplain = execInfo;
249,191✔
6723
  *len = sizeof(STableMergeScanExecInfo);
249,191✔
6724

6725
  return TSDB_CODE_SUCCESS;
249,191✔
6726
}
6727

6728
int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle,
1,972,108✔
6729
                                         STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo,
6730
                                         SOperatorInfo** pOptrInfo) {
6731
  QRY_PARAM_CHECK(pOptrInfo);
1,972,108!
6732

6733
  int32_t              code = TSDB_CODE_SUCCESS;
1,972,108✔
6734
  int32_t              lino = 0;
1,972,108✔
6735
  STableMergeScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableMergeScanInfo));
1,972,108!
6736
  SOperatorInfo*       pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
1,972,817!
6737
  if (pInfo == NULL || pOperator == NULL) {
1,974,140!
UNCOV
6738
    code = terrno;
×
6739
    goto _error;
×
6740
  }
6741

6742
  SDataBlockDescNode* pDescNode = pTableScanNode->scan.node.pOutputDataBlockDesc;
1,974,538✔
6743

6744
  int32_t numOfCols = 0;
1,974,538✔
6745
  code = extractColMatchInfo(pTableScanNode->scan.pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID,
1,974,538✔
6746
                             &pInfo->base.matchInfo);
6747
  QUERY_CHECK_CODE(code, lino, _error);
1,975,977!
6748

6749
  code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, readHandle);
1,975,977✔
6750
  QUERY_CHECK_CODE(code, lino, _error);
1,976,687!
6751

6752
  if (pTableScanNode->scan.pScanPseudoCols != NULL) {
1,976,687✔
6753
    SExprSupp* pSup = &pInfo->base.pseudoSup;
1,191,211✔
6754
    code = createExprInfo(pTableScanNode->scan.pScanPseudoCols, NULL, &pSup->pExprInfo, &pSup->numOfExprs);
1,191,211✔
6755
    QUERY_CHECK_CODE(code, lino, _error);
1,191,826!
6756

6757
    pSup->pCtx = createSqlFunctionCtx(pSup->pExprInfo, pSup->numOfExprs, &pSup->rowEntryInfoOffset,
1,191,826✔
6758
                                      &pTaskInfo->storageAPI.functionStore);
6759
    QUERY_CHECK_NULL(pSup->pCtx, code, lino, _error, terrno);
1,189,131!
6760
  }
6761

6762
  pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]};
1,974,607✔
6763

6764
  pInfo->base.metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024 * 128, -1, .5);
1,974,607✔
6765
  QUERY_CHECK_NULL(pInfo->base.metaCache.pTableMetaEntryCache, code, lino, _error, terrno);
1,977,556!
6766

6767
  pInfo->base.readerAPI = pTaskInfo->storageAPI.tsdReader;
1,977,556✔
6768
  pInfo->base.dataBlockLoadFlag = FUNC_DATA_REQUIRED_DATA_LOAD;
1,977,556✔
6769
  pInfo->base.scanFlag = MAIN_SCAN;
1,977,556✔
6770
  pInfo->base.readHandle = *readHandle;
1,977,556✔
6771

6772
  pInfo->readIdx = -1;
1,977,556✔
6773

6774
  pInfo->base.limitInfo.limit.limit = -1;
1,977,556✔
6775
  pInfo->base.limitInfo.slimit.limit = -1;
1,977,556✔
6776
  pInfo->base.pTableListInfo = pTableListInfo;
1,977,556✔
6777

6778
  pInfo->sample.sampleRatio = pTableScanNode->ratio;
1,977,556✔
6779
  pInfo->sample.seed = taosGetTimestampSec();
1,977,556✔
6780

6781
  code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
1,976,834✔
6782
  QUERY_CHECK_CODE(code, lino, _error);
1,974,052!
6783

6784
  initLimitInfo(pTableScanNode->scan.node.pLimit, pTableScanNode->scan.node.pSlimit, &pInfo->limitInfo);
1,974,052✔
6785

6786
  pInfo->mergeLimit = -1;
1,973,814✔
6787
  bool hasLimit = pInfo->limitInfo.limit.limit != -1 || pInfo->limitInfo.limit.offset != -1;
1,973,814!
6788
  if (hasLimit) {
1,973,814✔
6789
    pInfo->mergeLimit = pInfo->limitInfo.limit.limit + pInfo->limitInfo.limit.offset;
114,972✔
6790
    pInfo->mSkipTables = NULL;
114,972✔
6791
  }
6792

6793
  initResultSizeInfo(&pOperator->resultInfo, 1024);
1,973,814✔
6794
  pInfo->pResBlock = createDataBlockFromDescNode(pDescNode);
1,972,073✔
6795
  QUERY_CHECK_NULL(pInfo->pResBlock, code, lino, _error, terrno);
1,976,402!
6796
  code = blockDataEnsureCapacity(pInfo->pResBlock, pOperator->resultInfo.capacity);
1,976,402✔
6797
  QUERY_CHECK_CODE(code, lino, _error);
1,977,485!
6798
  if (!hasLimit && blockDataGetRowSize(pInfo->pResBlock) >= 256 && !pTableScanNode->smallDataTsSort) {
1,977,485!
6799
    pInfo->bSortRowId = true;
858,222✔
6800
  } else {
6801
    pInfo->bSortRowId = false;
1,117,755✔
6802
  }
6803

6804
  code = prepareDataBlockBuf(pInfo->pResBlock, &pInfo->base.matchInfo);
1,975,977✔
6805
  QUERY_CHECK_CODE(code, lino, _error);
1,974,527!
6806

6807
  code = generateSortByTsPkInfo(pInfo->base.matchInfo.pList, pInfo->base.cond.order, &pInfo->pSortInfo);
1,974,527✔
6808
  QUERY_CHECK_CODE(code, lino, _error);
1,972,548!
6809

6810
  code = createOneDataBlock(pInfo->pResBlock, false, &pInfo->pReaderBlock);
1,972,548✔
6811
  QUERY_CHECK_CODE(code, lino, _error);
1,974,514!
6812

6813
  pInfo->needCountEmptyTable = tsCountAlwaysReturnValue && pTableScanNode->needCountEmptyTable;
1,974,514✔
6814

6815
  int32_t  rowSize = pInfo->pResBlock->info.rowSize;
1,974,514✔
6816
  uint32_t nCols = taosArrayGetSize(pInfo->pResBlock->pDataBlock);
1,974,514✔
6817

6818
  pInfo->bufPageSize = getProperSortPageSize(rowSize, nCols);
1,975,044✔
6819

6820
  // start one reader variable
6821
  code = createOneDataBlock(pInfo->pResBlock, false, &pInfo->pSortInputBlock);
1,976,051✔
6822
  QUERY_CHECK_CODE(code, lino, _error);
1,976,551!
6823

6824
  if (!tsExperimental) {
1,976,551!
6825
    pInfo->filesetDelimited = false;
×
6826
  } else {
6827
    pInfo->filesetDelimited = pTableScanNode->filesetDelimited;
1,976,551✔
6828
  }
6829
  // end one reader variable
6830
  setOperatorInfo(pOperator, "TableMergeScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN, false, OP_NOT_OPENED,
1,976,551✔
6831
                  pInfo, pTaskInfo);
6832
  pOperator->exprSupp.numOfExprs = numOfCols;
1,975,575✔
6833

6834
  pOperator->fpSet = createOperatorFpSet(
1,975,575✔
6835
      optrDummyOpenFn, pTableScanNode->paraTablesSort ? doTableMergeScanParaSubTablesNext : doTableMergeScanNext, NULL,
1,975,575✔
6836
      destroyTableMergeScanOperatorInfo, optrDefaultBufFn, getTableMergeScanExplainExecInfo, optrDefaultGetNextExtFn,
6837
      NULL);
6838
  pOperator->cost.openCost = 0;
1,973,366✔
6839

6840
  *pOptrInfo = pOperator;
1,973,366✔
6841
  return code;
1,973,366✔
6842

6843
_error:
×
UNCOV
6844
  if (code != TSDB_CODE_SUCCESS) {
×
6845
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6846
  }
UNCOV
6847
  pTaskInfo->code = code;
×
6848
  if (pInfo != NULL) {
×
6849
    pInfo->base.pTableListInfo = NULL;
×
6850
    destroyTableMergeScanOperatorInfo(pInfo);
×
6851
  }
UNCOV
6852
  if (pOperator != NULL) {
×
6853
    pOperator->info = NULL;
×
6854
    destroyOperator(pOperator);
×
6855
  }
6856
  return code;
×
6857
}
6858

6859
// ====================================================================================================================
6860
// TableCountScanOperator
6861
static void        destoryTableCountScanOperator(void* param);
6862
static int32_t     buildVnodeGroupedStbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
6863
                                                  SSDataBlock* pRes, char* dbName, tb_uid_t stbUid, SStorageAPI* pAPI);
6864
static int32_t     buildVnodeGroupedNtbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
6865
                                                  SSDataBlock* pRes, char* dbName, SStorageAPI* pAPI);
6866
static int32_t     buildVnodeFilteredTbCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
6867
                                             STableCountScanSupp* pSupp, SSDataBlock* pRes, char* dbName);
6868
static int32_t     buildVnodeGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
6869
                                               STableCountScanSupp* pSupp, SSDataBlock* pRes, int32_t vgId, char* dbName);
6870
static int32_t     buildVnodeDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
6871
                                          STableCountScanSupp* pSupp, SSDataBlock* pRes);
6872
static void        buildSysDbGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
6873
                                               STableCountScanSupp* pSupp, SSDataBlock* pRes, size_t infodbTableNum,
6874
                                               size_t perfdbTableNum);
6875
static void        buildSysDbFilterTableCount(SOperatorInfo* pOperator, STableCountScanSupp* pSupp, SSDataBlock* pRes,
6876
                                              size_t infodbTableNum, size_t perfdbTableNum);
6877
static const char* GROUP_TAG_DB_NAME = "db_name";
6878
static const char* GROUP_TAG_STABLE_NAME = "stable_name";
6879

UNCOV
6880
int32_t tblCountScanGetGroupTagsSlotId(const SNodeList* scanCols, STableCountScanSupp* supp) {
×
UNCOV
6881
  if (scanCols != NULL) {
×
6882
    SNode* pNode = NULL;
×
6883
    FOREACH(pNode, scanCols) {
×
6884
      if (nodeType(pNode) != QUERY_NODE_TARGET) {
×
UNCOV
6885
        return TSDB_CODE_QRY_SYS_ERROR;
×
6886
      }
6887
      STargetNode* targetNode = (STargetNode*)pNode;
×
6888
      if (nodeType(targetNode->pExpr) != QUERY_NODE_COLUMN) {
×
UNCOV
6889
        return TSDB_CODE_QRY_SYS_ERROR;
×
6890
      }
UNCOV
6891
      SColumnNode* colNode = (SColumnNode*)(targetNode->pExpr);
×
6892
      if (strcmp(colNode->colName, GROUP_TAG_DB_NAME) == 0) {
×
6893
        supp->dbNameSlotId = targetNode->slotId;
×
6894
      } else if (strcmp(colNode->colName, GROUP_TAG_STABLE_NAME) == 0) {
×
UNCOV
6895
        supp->stbNameSlotId = targetNode->slotId;
×
6896
      }
6897
    }
6898
  }
UNCOV
6899
  return TSDB_CODE_SUCCESS;
×
6900
}
6901

UNCOV
6902
int32_t tblCountScanGetCountSlotId(const SNodeList* pseudoCols, STableCountScanSupp* supp) {
×
6903
  if (pseudoCols != NULL) {
×
6904
    SNode* pNode = NULL;
×
6905
    FOREACH(pNode, pseudoCols) {
×
6906
      if (nodeType(pNode) != QUERY_NODE_TARGET) {
×
6907
        return TSDB_CODE_QRY_SYS_ERROR;
×
6908
      }
6909
      STargetNode* targetNode = (STargetNode*)pNode;
×
6910
      if (nodeType(targetNode->pExpr) != QUERY_NODE_FUNCTION) {
×
6911
        return TSDB_CODE_QRY_SYS_ERROR;
×
6912
      }
6913
      SFunctionNode* funcNode = (SFunctionNode*)(targetNode->pExpr);
×
6914
      if (funcNode->funcType == FUNCTION_TYPE_TABLE_COUNT) {
×
UNCOV
6915
        supp->tbCountSlotId = targetNode->slotId;
×
6916
      }
6917
    }
6918
  }
6919
  return TSDB_CODE_SUCCESS;
×
6920
}
6921

UNCOV
6922
int32_t tblCountScanGetInputs(SNodeList* groupTags, SName* tableName, STableCountScanSupp* supp) {
×
6923
  if (groupTags != NULL) {
×
6924
    SNode* pNode = NULL;
×
UNCOV
6925
    FOREACH(pNode, groupTags) {
×
6926
      if (nodeType(pNode) != QUERY_NODE_COLUMN) {
×
UNCOV
6927
        return TSDB_CODE_QRY_SYS_ERROR;
×
6928
      }
6929
      SColumnNode* colNode = (SColumnNode*)pNode;
×
6930
      if (strcmp(colNode->colName, GROUP_TAG_DB_NAME) == 0) {
×
6931
        supp->groupByDbName = true;
×
6932
      }
6933
      if (strcmp(colNode->colName, GROUP_TAG_STABLE_NAME) == 0) {
×
6934
        supp->groupByStbName = true;
×
6935
      }
6936
    }
6937
  } else {
UNCOV
6938
    tstrncpy(supp->dbNameFilter, tNameGetDbNameP(tableName), TSDB_DB_NAME_LEN);
×
UNCOV
6939
    tstrncpy(supp->stbNameFilter, tNameGetTableName(tableName), TSDB_TABLE_NAME_LEN);
×
6940
  }
6941
  return TSDB_CODE_SUCCESS;
×
6942
}
6943

6944
int32_t getTableCountScanSupp(SNodeList* groupTags, SName* tableName, SNodeList* scanCols, SNodeList* pseudoCols,
×
6945
                              STableCountScanSupp* supp, SExecTaskInfo* taskInfo) {
6946
  int32_t code = 0;
×
UNCOV
6947
  code = tblCountScanGetInputs(groupTags, tableName, supp);
×
6948
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
6949
    qError("%s get table count scan supp. get inputs error", GET_TASKID(taskInfo));
×
UNCOV
6950
    return code;
×
6951
  }
6952

6953
  supp->dbNameSlotId = -1;
×
UNCOV
6954
  supp->stbNameSlotId = -1;
×
6955
  supp->tbCountSlotId = -1;
×
6956

6957
  code = tblCountScanGetGroupTagsSlotId(scanCols, supp);
×
UNCOV
6958
  if (code != TSDB_CODE_SUCCESS) {
×
6959
    qError("%s get table count scan supp. get group tags slot id error", GET_TASKID(taskInfo));
×
6960
    return code;
×
6961
  }
6962

6963
  code = tblCountScanGetCountSlotId(pseudoCols, supp);
×
UNCOV
6964
  if (code != TSDB_CODE_SUCCESS) {
×
6965
    qError("%s get table count scan supp. get count error", GET_TASKID(taskInfo));
×
UNCOV
6966
    return code;
×
6967
  }
6968
  return code;
×
6969
}
6970

6971
int32_t createTableCountScanOperatorInfo(SReadHandle* readHandle, STableCountScanPhysiNode* pTblCountScanNode,
×
6972
                                         SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
UNCOV
6973
  QRY_PARAM_CHECK(pOptrInfo);
×
6974

6975
  int32_t                      code = TSDB_CODE_SUCCESS;
×
UNCOV
6976
  int32_t                      lino = 0;
×
6977
  SScanPhysiNode*              pScanNode = &pTblCountScanNode->scan;
×
6978
  STableCountScanOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(STableCountScanOperatorInfo));
×
UNCOV
6979
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
×
UNCOV
6980
  if (!pInfo || !pOperator) {
×
6981
    code = terrno;
×
6982
    goto _error;
×
6983
  }
6984

UNCOV
6985
  pInfo->readHandle = *readHandle;
×
6986

6987
  SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc;
×
6988
  initResultSizeInfo(&pOperator->resultInfo, 1);
×
6989
  pInfo->pRes = createDataBlockFromDescNode(pDescNode);
×
6990
  QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
×
6991

6992
  code = blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
×
6993
  QUERY_CHECK_CODE(code, lino, _error);
×
6994

UNCOV
6995
  code = getTableCountScanSupp(pTblCountScanNode->pGroupTags, &pTblCountScanNode->scan.tableName,
×
6996
                               pTblCountScanNode->scan.pScanCols, pTblCountScanNode->scan.pScanPseudoCols, &pInfo->supp,
6997
                               pTaskInfo);
UNCOV
6998
  QUERY_CHECK_CODE(code, lino, _error);
×
6999

UNCOV
7000
  setOperatorInfo(pOperator, "TableCountScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN, false, OP_NOT_OPENED,
×
7001
                  pInfo, pTaskInfo);
7002
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableCountScanNext, NULL, destoryTableCountScanOperator,
×
7003
                                         optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
7004
  *pOptrInfo = pOperator;
×
7005
  return code;
×
7006

7007
_error:
×
UNCOV
7008
  if (pInfo != NULL) {
×
UNCOV
7009
    destoryTableCountScanOperator(pInfo);
×
7010
  }
7011
  if (pOperator != NULL) {
×
UNCOV
7012
    pOperator->info = NULL;
×
7013
    destroyOperator(pOperator);
×
7014
  }
UNCOV
7015
  pTaskInfo->code = code;
×
7016
  return code;
×
7017
}
7018

7019
int32_t fillTableCountScanDataBlock(STableCountScanSupp* pSupp, char* dbName, char* stbName, int64_t count,
×
7020
                                    SSDataBlock* pRes) {
UNCOV
7021
  int32_t code = TSDB_CODE_SUCCESS;
×
7022
  int32_t lino = 0;
×
UNCOV
7023
  if (pSupp->dbNameSlotId != -1) {
×
UNCOV
7024
    QUERY_CHECK_CONDITION((strlen(dbName) > 0), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
7025
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->dbNameSlotId);
×
7026
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
×
7027

7028
    char varDbName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
×
UNCOV
7029
    tstrncpy(varDataVal(varDbName), dbName, TSDB_DB_NAME_LEN);
×
7030

7031
    varDataSetLen(varDbName, strlen(dbName));
×
UNCOV
7032
    code = colDataSetVal(colInfoData, 0, varDbName, false);
×
UNCOV
7033
    QUERY_CHECK_CODE(code, lino, _end);
×
7034
  }
7035

7036
  if (pSupp->stbNameSlotId != -1) {
×
7037
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->stbNameSlotId);
×
7038
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
×
7039
    if (strlen(stbName) != 0) {
×
UNCOV
7040
      char varStbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
×
7041
      tstrncpy(varDataVal(varStbName), stbName, TSDB_TABLE_NAME_LEN);
×
7042
      varDataSetLen(varStbName, strlen(stbName));
×
7043
      code = colDataSetVal(colInfoData, 0, varStbName, false);
×
7044
      QUERY_CHECK_CODE(code, lino, _end);
×
7045
    } else {
7046
      colDataSetNULL(colInfoData, 0);
7047
    }
7048
  }
7049

7050
  if (pSupp->tbCountSlotId != -1) {
×
7051
    SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->tbCountSlotId);
×
7052
    QUERY_CHECK_NULL(colInfoData, code, lino, _end, terrno);
×
UNCOV
7053
    code = colDataSetVal(colInfoData, 0, (char*)&count, false);
×
7054
    QUERY_CHECK_CODE(code, lino, _end);
×
7055
  }
7056
  pRes->info.rows = 1;
×
7057

UNCOV
7058
_end:
×
7059
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
7060
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
7061
  }
UNCOV
7062
  return code;
×
7063
}
7064

7065
static SSDataBlock* buildSysDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo) {
×
UNCOV
7066
  STableCountScanSupp* pSupp = &pInfo->supp;
×
7067
  SSDataBlock*         pRes = pInfo->pRes;
×
7068

7069
  size_t infodbTableNum;
7070
  getInfosDbMeta(NULL, &infodbTableNum);
×
7071
  infodbTableNum -= 1;
×
7072
  size_t perfdbTableNum;
UNCOV
7073
  getPerfDbMeta(NULL, &perfdbTableNum);
×
7074

7075
  if (pSupp->groupByDbName || pSupp->groupByStbName) {
×
7076
    buildSysDbGroupedTableCount(pOperator, pInfo, pSupp, pRes, infodbTableNum, perfdbTableNum);
×
7077
    return (pRes->info.rows > 0) ? pRes : NULL;
×
7078
  } else {
7079
    buildSysDbFilterTableCount(pOperator, pSupp, pRes, infodbTableNum, perfdbTableNum);
×
UNCOV
7080
    return (pRes->info.rows > 0) ? pRes : NULL;
×
7081
  }
7082
}
7083

7084
static void buildSysDbFilterTableCount(SOperatorInfo* pOperator, STableCountScanSupp* pSupp, SSDataBlock* pRes,
×
7085
                                       size_t infodbTableNum, size_t perfdbTableNum) {
7086
  int32_t        code = TSDB_CODE_SUCCESS;
×
7087
  int32_t        lino = 0;
×
UNCOV
7088
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
7089
  if (strcmp(pSupp->dbNameFilter, TSDB_INFORMATION_SCHEMA_DB) == 0) {
×
7090
    code = fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes);
×
7091
    QUERY_CHECK_CODE(code, lino, _end);
×
7092
  } else if (strcmp(pSupp->dbNameFilter, TSDB_PERFORMANCE_SCHEMA_DB) == 0) {
×
7093
    code = fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes);
×
UNCOV
7094
    QUERY_CHECK_CODE(code, lino, _end);
×
7095
  } else if (strlen(pSupp->dbNameFilter) == 0) {
×
7096
    code = fillTableCountScanDataBlock(pSupp, "", "", infodbTableNum + perfdbTableNum, pRes);
×
7097
    QUERY_CHECK_CODE(code, lino, _end);
×
7098
  }
7099

7100
_end:
×
UNCOV
7101
  if (code != TSDB_CODE_SUCCESS) {
×
7102
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
7103
    pTaskInfo->code = code;
×
7104
    T_LONG_JMP(pTaskInfo->env, code);
×
7105
  }
UNCOV
7106
  setOperatorCompleted(pOperator);
×
UNCOV
7107
}
×
7108

7109
static void buildSysDbGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
7110
                                        STableCountScanSupp* pSupp, SSDataBlock* pRes, size_t infodbTableNum,
7111
                                        size_t perfdbTableNum) {
UNCOV
7112
  int32_t        code = TSDB_CODE_SUCCESS;
×
UNCOV
7113
  int32_t        lino = 0;
×
7114
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
7115
  if (pInfo->currGrpIdx == 0) {
×
7116
    uint64_t groupId = 0;
×
7117
    if (pSupp->groupByDbName) {
×
UNCOV
7118
      groupId = calcGroupId(TSDB_INFORMATION_SCHEMA_DB, strlen(TSDB_INFORMATION_SCHEMA_DB));
×
7119
    } else {
7120
      groupId = calcGroupId("", 0);
×
7121
    }
7122

UNCOV
7123
    pRes->info.id.groupId = groupId;
×
7124
    code = fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes);
×
UNCOV
7125
    QUERY_CHECK_CODE(code, lino, _end);
×
7126
  } else if (pInfo->currGrpIdx == 1) {
×
7127
    uint64_t groupId = 0;
×
7128
    if (pSupp->groupByDbName) {
×
7129
      groupId = calcGroupId(TSDB_PERFORMANCE_SCHEMA_DB, strlen(TSDB_PERFORMANCE_SCHEMA_DB));
×
7130
    } else {
UNCOV
7131
      groupId = calcGroupId("", 0);
×
7132
    }
7133

7134
    pRes->info.id.groupId = groupId;
×
UNCOV
7135
    code = fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes);
×
7136
    QUERY_CHECK_CODE(code, lino, _end);
×
7137
  } else {
UNCOV
7138
    setOperatorCompleted(pOperator);
×
7139
  }
7140
  pInfo->currGrpIdx++;
×
7141

UNCOV
7142
_end:
×
7143
  if (code != TSDB_CODE_SUCCESS) {
×
7144
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
7145
    pTaskInfo->code = code;
×
UNCOV
7146
    T_LONG_JMP(pTaskInfo->env, code);
×
7147
  }
UNCOV
7148
}
×
7149

7150
static int32_t doTableCountScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
×
UNCOV
7151
  int32_t                      code = TSDB_CODE_SUCCESS;
×
7152
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
×
7153
  STableCountScanOperatorInfo* pInfo = pOperator->info;
×
7154
  STableCountScanSupp*         pSupp = &pInfo->supp;
×
7155
  SSDataBlock*                 pRes = pInfo->pRes;
×
7156

UNCOV
7157
  blockDataCleanup(pRes);
×
7158
  QRY_PARAM_CHECK(ppRes);
×
7159

7160
  if (pOperator->status == OP_EXEC_DONE) {
×
UNCOV
7161
    return code;
×
7162
  }
7163

UNCOV
7164
  if (pInfo->readHandle.mnd != NULL) {
×
7165
    (*ppRes) = buildSysDbTableCount(pOperator, pInfo);
×
7166
    return code;
×
7167
  }
7168

7169
  code = buildVnodeDbTableCount(pOperator, pInfo, pSupp, pRes);
×
7170
  if (code != TSDB_CODE_SUCCESS) {
×
7171
    qError("%s failed since %s", __func__, tstrerror(code));
×
7172
    pTaskInfo->code = code;
×
UNCOV
7173
    T_LONG_JMP(pTaskInfo->env, code);
×
7174
  }
7175
  if (pRes->info.rows > 0) {
×
7176
    *ppRes = pRes;
×
7177
  }
7178

UNCOV
7179
  return code;
×
7180
}
7181

7182
static int32_t buildVnodeDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
7183
                                      STableCountScanSupp* pSupp, SSDataBlock* pRes) {
UNCOV
7184
  int32_t        code = TSDB_CODE_SUCCESS;
×
7185
  int32_t        lino = 0;
×
7186
  const char*    db = NULL;
×
7187
  int32_t        vgId = 0;
×
UNCOV
7188
  char           dbName[TSDB_DB_NAME_LEN] = {0};
×
UNCOV
7189
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
UNCOV
7190
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
7191

7192
  // get dbname
UNCOV
7193
  pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, &db, &vgId, NULL, NULL);
×
UNCOV
7194
  SName sn = {0};
×
7195

UNCOV
7196
  code = tNameFromString(&sn, db, T_NAME_ACCT | T_NAME_DB);
×
UNCOV
7197
  QUERY_CHECK_CODE(code, lino, _end);
×
7198

UNCOV
7199
  code = tNameGetDbName(&sn, dbName);
×
UNCOV
7200
  QUERY_CHECK_CODE(code, lino, _end);
×
7201

UNCOV
7202
  if (pSupp->groupByDbName || pSupp->groupByStbName) {
×
UNCOV
7203
    code = buildVnodeGroupedTableCount(pOperator, pInfo, pSupp, pRes, vgId, dbName);
×
7204
  } else {
UNCOV
7205
    code = buildVnodeFilteredTbCount(pOperator, pInfo, pSupp, pRes, dbName);
×
7206
  }
7207

UNCOV
7208
_end:
×
UNCOV
7209
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
7210
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
7211
    pTaskInfo->code = code;
×
7212
  }
7213

UNCOV
7214
  return code;
×
7215
}
7216

UNCOV
7217
static int32_t buildVnodeGroupedTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
7218
                                           STableCountScanSupp* pSupp, SSDataBlock* pRes, int32_t vgId, char* dbName) {
UNCOV
7219
  int32_t        code = TSDB_CODE_SUCCESS;
×
UNCOV
7220
  int32_t        lino = 0;
×
UNCOV
7221
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
UNCOV
7222
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
7223

UNCOV
7224
  if (pSupp->groupByStbName) {
×
UNCOV
7225
    if (pInfo->stbUidList == NULL) {
×
UNCOV
7226
      pInfo->stbUidList = taosArrayInit(16, sizeof(tb_uid_t));
×
UNCOV
7227
      QUERY_CHECK_NULL(pInfo->stbUidList, code, lino, _end, terrno);
×
UNCOV
7228
      code = pAPI->metaFn.storeGetTableList(pInfo->readHandle.vnode, TSDB_SUPER_TABLE, pInfo->stbUidList);
×
UNCOV
7229
      QUERY_CHECK_CODE(code, lino, _end);
×
7230
    }
7231

UNCOV
7232
    if (pInfo->currGrpIdx < taosArrayGetSize(pInfo->stbUidList)) {
×
UNCOV
7233
      tb_uid_t stbUid = *(tb_uid_t*)taosArrayGet(pInfo->stbUidList, pInfo->currGrpIdx);
×
UNCOV
7234
      code = buildVnodeGroupedStbTableCount(pInfo, pSupp, pRes, dbName, stbUid, pAPI);
×
UNCOV
7235
      QUERY_CHECK_CODE(code, lino, _end);
×
7236

UNCOV
7237
      pInfo->currGrpIdx++;
×
UNCOV
7238
    } else if (pInfo->currGrpIdx == taosArrayGetSize(pInfo->stbUidList)) {
×
UNCOV
7239
      code = buildVnodeGroupedNtbTableCount(pInfo, pSupp, pRes, dbName, pAPI);
×
UNCOV
7240
      QUERY_CHECK_CODE(code, lino, _end);
×
7241

UNCOV
7242
      pInfo->currGrpIdx++;
×
7243
    } else {
UNCOV
7244
      setOperatorCompleted(pOperator);
×
7245
    }
7246
  } else {
UNCOV
7247
    uint64_t groupId = calcGroupId(dbName, strlen(dbName));
×
UNCOV
7248
    pRes->info.id.groupId = groupId;
×
7249

UNCOV
7250
    int64_t dbTableCount = 0;
×
UNCOV
7251
    pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &dbTableCount, NULL);
×
UNCOV
7252
    code = fillTableCountScanDataBlock(pSupp, dbName, "", dbTableCount, pRes);
×
UNCOV
7253
    QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
7254
    setOperatorCompleted(pOperator);
×
7255
  }
7256

UNCOV
7257
_end:
×
UNCOV
7258
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
7259
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
7260
    pTaskInfo->code = code;
×
7261
  }
UNCOV
7262
  return code;
×
7263
}
7264

UNCOV
7265
static int32_t buildVnodeFilteredTbCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo,
×
7266
                                         STableCountScanSupp* pSupp, SSDataBlock* pRes, char* dbName) {
UNCOV
7267
  int32_t        code = TSDB_CODE_SUCCESS;
×
UNCOV
7268
  int32_t        lino = 0;
×
UNCOV
7269
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
×
UNCOV
7270
  SStorageAPI*   pAPI = &pTaskInfo->storageAPI;
×
7271

UNCOV
7272
  if (strlen(pSupp->dbNameFilter) != 0) {
×
UNCOV
7273
    if (strlen(pSupp->stbNameFilter) != 0) {
×
UNCOV
7274
      uint64_t uid = 0;
×
UNCOV
7275
      code = pAPI->metaFn.getTableUidByName(pInfo->readHandle.vnode, pSupp->stbNameFilter, &uid);
×
UNCOV
7276
      QUERY_CHECK_CODE(code, lino, _end);
×
7277

UNCOV
7278
      int64_t numOfChildTables = 0;
×
UNCOV
7279
      code = pAPI->metaFn.getNumOfChildTables(pInfo->readHandle.vnode, uid, &numOfChildTables, NULL);
×
UNCOV
7280
      QUERY_CHECK_CODE(code, lino, _end);
×
7281

UNCOV
7282
      code = fillTableCountScanDataBlock(pSupp, dbName, pSupp->stbNameFilter, numOfChildTables, pRes);
×
UNCOV
7283
      QUERY_CHECK_CODE(code, lino, _end);
×
7284
    } else {
UNCOV
7285
      int64_t tbNumVnode = 0;
×
UNCOV
7286
      pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &tbNumVnode, NULL);
×
UNCOV
7287
      code = fillTableCountScanDataBlock(pSupp, dbName, "", tbNumVnode, pRes);
×
UNCOV
7288
      QUERY_CHECK_CODE(code, lino, _end);
×
7289
    }
7290
  } else {
UNCOV
7291
    int64_t tbNumVnode = 0;
×
UNCOV
7292
    pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, &tbNumVnode, NULL);
×
UNCOV
7293
    code = fillTableCountScanDataBlock(pSupp, dbName, "", tbNumVnode, pRes);
×
UNCOV
7294
    QUERY_CHECK_CODE(code, lino, _end);
×
7295
  }
7296

UNCOV
7297
_end:
×
UNCOV
7298
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
7299
    pTaskInfo->code = code;
×
UNCOV
7300
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
7301
  }
7302

UNCOV
7303
  setOperatorCompleted(pOperator);
×
UNCOV
7304
  return code;
×
7305
}
7306

UNCOV
7307
static int32_t buildVnodeGroupedNtbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
×
7308
                                              SSDataBlock* pRes, char* dbName, SStorageAPI* pAPI) {
UNCOV
7309
  int32_t code = TSDB_CODE_SUCCESS;
×
UNCOV
7310
  int32_t lino = 0;
×
UNCOV
7311
  char    fullStbName[TSDB_TABLE_FNAME_LEN] = {0};
×
UNCOV
7312
  if (pSupp->groupByDbName) {
×
UNCOV
7313
    snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, "");
×
7314
  }
7315

UNCOV
7316
  uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName));
×
UNCOV
7317
  pRes->info.id.groupId = groupId;
×
7318

UNCOV
7319
  int64_t numOfTables = 0;
×
UNCOV
7320
  pAPI->metaFn.getBasicInfo(pInfo->readHandle.vnode, NULL, NULL, NULL, &numOfTables);
×
7321

UNCOV
7322
  if (numOfTables != 0) {
×
UNCOV
7323
    code = fillTableCountScanDataBlock(pSupp, dbName, "", numOfTables, pRes);
×
7324
  }
7325

UNCOV
7326
_end:
×
UNCOV
7327
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
7328
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
7329
  }
UNCOV
7330
  return code;
×
7331
}
7332

UNCOV
7333
static int32_t buildVnodeGroupedStbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp,
×
7334
                                              SSDataBlock* pRes, char* dbName, tb_uid_t stbUid, SStorageAPI* pAPI) {
UNCOV
7335
  int32_t code = TSDB_CODE_SUCCESS;
×
UNCOV
7336
  int32_t lino = 0;
×
UNCOV
7337
  char    stbName[TSDB_TABLE_NAME_LEN] = {0};
×
UNCOV
7338
  code = pAPI->metaFn.getTableNameByUid(pInfo->readHandle.vnode, stbUid, stbName);
×
UNCOV
7339
  QUERY_CHECK_CODE(code, lino, _end);
×
7340

UNCOV
7341
  char fullStbName[TSDB_TABLE_FNAME_LEN] = {0};
×
UNCOV
7342
  if (pSupp->groupByDbName) {
×
UNCOV
7343
    (void)snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, varDataVal(stbName));
×
7344
  } else {
UNCOV
7345
    (void)snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s", varDataVal(stbName));
×
7346
  }
7347

UNCOV
7348
  uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName));
×
UNCOV
7349
  pRes->info.id.groupId = groupId;
×
7350

UNCOV
7351
  int64_t ctbNum = 0;
×
UNCOV
7352
  code = pAPI->metaFn.getNumOfChildTables(pInfo->readHandle.vnode, stbUid, &ctbNum, NULL);
×
UNCOV
7353
  QUERY_CHECK_CODE(code, lino, _end);
×
UNCOV
7354
  code = fillTableCountScanDataBlock(pSupp, dbName, varDataVal(stbName), ctbNum, pRes);
×
UNCOV
7355
  QUERY_CHECK_CODE(code, lino, _end);
×
7356

UNCOV
7357
_end:
×
UNCOV
7358
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
7359
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
7360
  }
UNCOV
7361
  return code;
×
7362
}
7363

UNCOV
7364
static void destoryTableCountScanOperator(void* param) {
×
UNCOV
7365
  STableCountScanOperatorInfo* pTableCountScanInfo = param;
×
UNCOV
7366
  blockDataDestroy(pTableCountScanInfo->pRes);
×
7367

UNCOV
7368
  taosArrayDestroy(pTableCountScanInfo->stbUidList);
×
UNCOV
7369
  taosMemoryFreeClear(param);
×
UNCOV
7370
}
×
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