• 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

69.76
/source/dnode/vnode/src/tsdb/tsdbRead2.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 "osDef.h"
17
#include "tsdb.h"
18
#include "tsdbDataFileRW.h"
19
#include "tsdbFS2.h"
20
#include "tsdbMerge.h"
21
#include "tsdbReadUtil.h"
22
#include "tsdbUtil2.h"
23
#include "tsimplehash.h"
24

25
#define ASCENDING_TRAVERSE(o)       (o == TSDB_ORDER_ASC)
26
#define getCurrentKeyInSttBlock(_r) (&((_r)->currentKey))
27
#define tColRowGetKeyDeepCopy(_pBlock, _irow, _slotId, _pKey)             \
28
  do {                                                                    \
29
    (_pKey)->ts = (_pBlock)->aTSKEY[(_irow)];                             \
30
    (_pKey)->numOfPKs = 0;                                                \
31
    if ((_slotId) != -1) {                                                \
32
      code = tColRowGetPriamyKeyDeepCopy(_pBlock, _irow, _slotId, _pKey); \
33
      TSDB_CHECK_CODE(code, lino, _end);                                  \
34
    }                                                                     \
35
  } while (0)
36

37
#define outOfTimeWindow(_ts, _window) (((_ts) > (_window)->ekey) || ((_ts) < (_window)->skey))
38

39
typedef struct {
40
  bool overlapWithNeighborBlock;
41
  bool hasDupTs;
42
  bool overlapWithDelInfo;
43
  bool overlapWithSttBlock;
44
  bool overlapWithKeyInBuf;
45
  bool partiallyRequired;
46
  bool moreThanCapcity;
47
} SDataBlockToLoadInfo;
48

49
static int32_t getCurrentBlockInfo(SDataBlockIter* pBlockIter, SFileDataBlockInfo** pInfo, const char* idStr);
50
static int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t endKey, int32_t capacity,
51
                                         STsdbReader* pReader);
52
static int32_t getValidMemRow(SIterInfo* pIter, const SArray* pDelList, STsdbReader* pReader, TSDBROW** pRes);
53
static int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pScanInfo, SRowKey* pKey,
54
                                       STsdbReader* pReader);
55
static int32_t doMergeRowsInSttBlock(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo,
56
                                     SRowMerger* pMerger, int32_t pkSrcSlot, SVersionRange* pVerRange, const char* id);
57
static int32_t doMergeRowsInBuf(SIterInfo* pIter, uint64_t uid, SRowKey* pCurKey, SArray* pDelList,
58
                                STsdbReader* pReader);
59
static int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, SRow* pTSRow,
60
                                    STableBlockScanInfo* pScanInfo);
61
static int32_t doAppendRowFromFileBlock(SSDataBlock* pResBlock, STsdbReader* pReader, SBlockData* pBlockData,
62
                                        int32_t rowIndex);
63
static void    setComposedBlockFlag(STsdbReader* pReader, bool composed);
64
static int32_t hasBeenDropped(const SArray* pDelList, int32_t* index, int64_t key, int64_t ver, int32_t order,
65
                              SVersionRange* pVerRange, bool hasPk, bool* dropped);
66

67
static int32_t doMergeMemTableMultiRows(TSDBROW* pRow, SRowKey* pKey, uint64_t uid, SIterInfo* pIter, SArray* pDelList,
68
                                        TSDBROW* pResRow, STsdbReader* pReader, bool* freeTSRow);
69
static int32_t doMergeMemIMemRows(TSDBROW* pRow, SRowKey* pRowKey, TSDBROW* piRow, SRowKey* piRowKey,
70
                                  STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, SRow** pTSRow);
71
static int32_t mergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pBlockScanInfo, SRowKey* pKey,
72
                                     STsdbReader* pReader);
73
static int32_t mergeRowsInSttBlocks(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo,
74
                                    STsdbReader* pReader);
75

76
static int32_t initDelSkylineIterator(STableBlockScanInfo* pBlockScanInfo, int32_t order, SReadCostSummary* pCost);
77
static void getTsdbByRetentions(SVnode* pVnode, SQueryTableDataCond* pCond, SRetention* retentions, const char* idstr,
78
                                int8_t* pLevel, STsdb** pTsdb);
79
static SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_t level);
80
static int32_t       doBuildDataBlock(STsdbReader* pReader);
81
static int32_t       getCurrentKeyInBuf(STableBlockScanInfo* pScanInfo, STsdbReader* pReader, TSDBKEY* key);
82
static bool          hasDataInFileBlock(const SBlockData* pBlockData, const SFileBlockDumpInfo* pDumpInfo);
83
static bool          hasDataInSttBlock(STableBlockScanInfo* pInfo);
84
static int32_t       initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter);
85
static int32_t       getInitialDelIndex(const SArray* pDelSkyline, int32_t order);
86
static int32_t       resetTableListIndex(SReaderStatus* pStatus, const char* id);
87
static void          getMemTableTimeRange(STsdbReader* pReader, int64_t* pMaxKey, int64_t* pMinKey);
88
static void          updateComposedBlockInfo(STsdbReader* pReader, double el, STableBlockScanInfo* pBlockScanInfo);
89
static int32_t       buildFromPreFilesetBuffer(STsdbReader* pReader);
90

91
static void resetPreFilesetMemTableListIndex(SReaderStatus* pStatus);
92

93
FORCE_INLINE int32_t pkCompEx(SRowKey* p1, SRowKey* p2) {
×
94
  if (p2 == NULL) {
1,113,472,815!
95
    return 1;
273,889,119✔
96
  }
97

98
  if (p1 == NULL) {
1,210,844,353!
99
    return -1;
×
100
  }
101

102
  if (p1->ts < p2->ts) {
1,210,844,353!
103
    return -1;
722,819,475✔
104
  } else if (p1->ts > p2->ts) {
488,024,878!
105
    return 1;
193,500,568✔
106
  }
107

108
  if (p1->numOfPKs == 0) {
294,524,310!
109
    return 0;
285,972,892✔
110
  } else {
111
    return tRowKeyCompare(p1, p2);
8,551,418✔
112
  }
113
}
114

115
static int32_t tColRowGetPriamyKeyDeepCopy(SBlockData* pBlock, int32_t irow, int32_t slotId, SRowKey* pKey) {
49,297,643✔
116
  int32_t   code = TSDB_CODE_SUCCESS;
49,297,643✔
117
  int32_t   lino = 0;
49,297,643✔
118
  SColData* pColData = NULL;
49,297,643✔
119
  SColVal   cv;
120

121
  TSDB_CHECK_CONDITION((pBlock != NULL) && (pBlock->aColData != NULL), code, lino, _end, TSDB_CODE_INVALID_PARA);
49,297,643!
122
  TSDB_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
49,297,643!
123

124
  pColData = &pBlock->aColData[slotId];
49,297,643✔
125

126
  code = tColDataGetValue(pColData, irow, &cv);
49,297,643✔
127
  TSDB_CHECK_CODE(code, lino, _end);
50,162,351!
128

129
  pKey->numOfPKs = 1;
50,162,351✔
130
  pKey->pks[0].type = cv.value.type;
50,162,351✔
131

132
  if (IS_NUMERIC_TYPE(cv.value.type)) {
50,162,351!
133
    valueCloneDatum(pKey->pks, &cv.value, cv.value.type);
50,162,351✔
134
  } else {
135
    pKey->pks[0].nData = cv.value.nData;
×
136
    TAOS_MEMCPY(pKey->pks[0].pData, cv.value.pData, cv.value.nData);
×
137
  }
138

139
_end:
49,771,466✔
140
  if (code != TSDB_CODE_SUCCESS) {
49,771,466!
141
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
142
  }
143
  return code;
49,712,882✔
144
}
145

146
// for test purpose, todo remove it
147
static int32_t tGetPrimaryKeyIndex(uint8_t* p, SPrimaryKeyIndex* index) {
15,710,620✔
148
  int32_t n = 0;
15,710,620✔
149
  n += tGetI8(p + n, &index->type);
15,710,620!
150
  n += tGetU32v(p + n, &index->offset);
15,710,620!
151
  return n;
15,710,620✔
152
}
153

154
static int32_t tRowGetPrimaryKeyDeepCopy(SRow* pRow, SRowKey* pKey) {
15,710,361✔
155
  int32_t          code = TSDB_CODE_SUCCESS;
15,710,361✔
156
  int32_t          lino = 0;
15,710,361✔
157
  SPrimaryKeyIndex indices[TD_MAX_PK_COLS];
158
  uint8_t*         data = NULL;
15,710,361✔
159
  int32_t          len = 0;
15,710,361✔
160

161
  TSDB_CHECK_NULL(pRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
15,710,361!
162
  if (pRow->numOfPKs > 0) {
15,710,361!
163
    TSDB_CHECK_NULL(pRow->data, code, lino, _end, TSDB_CODE_INVALID_PARA);
15,710,548!
164
    TSDB_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
15,710,548!
165
  }
166

167
  data = pRow->data;
15,710,361✔
168
  for (int32_t i = 0; i < pRow->numOfPKs; i++) {
31,421,819✔
169
    data += tGetPrimaryKeyIndex(data, &indices[i]);
15,710,512✔
170
  }
171

172
  // primary keys
173
  for (int32_t i = 0; i < pRow->numOfPKs; i++) {
31,422,633✔
174
    pKey->pks[i].type = indices[i].type;
15,711,656✔
175

176
    uint8_t* tdata = data + indices[i].offset;
15,711,656✔
177
    if (pRow->flag >> 4) {
15,711,656✔
178
      tdata += tGetI16v(tdata, NULL);
19,055✔
179
    }
180

181
    if (IS_VAR_DATA_TYPE(indices[i].type)) {
15,711,656!
182
      tdata += tGetU32v(tdata, &pKey->pks[i].nData);
217!
183
      TAOS_MEMCPY(pKey->pks[i].pData, tdata, pKey->pks[i].nData);
217✔
184
    } else {
185
      valueSetDatum(pKey->pks + i, indices[i].type, data + indices[i].offset, tDataTypes[pKey->pks[i].type].bytes);
15,711,439✔
186
    }
187
  }
188

189
_end:
15,710,977✔
190
  if (code != TSDB_CODE_SUCCESS) {
15,710,977!
191
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
192
  }
193
  return code;
15,711,349✔
194
}
195

196
static int32_t setColumnIdSlotList(SBlockLoadSuppInfo* pSupInfo, SColumnInfo* pCols, const int32_t* pSlotIdList,
4,668,822✔
197
                                   int32_t numOfCols) {
198
  int32_t code = TSDB_CODE_SUCCESS;
4,668,822✔
199
  int32_t lino = 0;
4,668,822✔
200

201
  TSDB_CHECK_NULL(pSupInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,668,822!
202
  if (numOfCols > 0) {
4,668,822!
203
    TSDB_CHECK_NULL(pSlotIdList, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,678,096!
204
    TSDB_CHECK_NULL(pCols, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,678,096!
205
  }
206

207
  pSupInfo->pk.pk = 0;
4,668,822✔
208
  pSupInfo->numOfPks = 0;
4,668,822✔
209
  pSupInfo->pkSrcSlot = -1;
4,668,822✔
210
  pSupInfo->pkDstSlot = -1;
4,668,822✔
211
  pSupInfo->smaValid = true;
4,668,822✔
212
  pSupInfo->numOfCols = numOfCols;
4,668,822✔
213

214
  pSupInfo->colId = taosMemoryCalloc(numOfCols, sizeof(int16_t) * 2 + POINTER_BYTES);
4,668,822!
215
  TSDB_CHECK_NULL(pSupInfo->colId, code, lino, _end, terrno);
4,683,786!
216

217
  pSupInfo->slotId = (int16_t*)((char*)pSupInfo->colId + (sizeof(int16_t) * numOfCols));
4,683,786✔
218
  pSupInfo->buildBuf = (char**)((char*)pSupInfo->slotId + (sizeof(int16_t) * numOfCols));
4,683,786✔
219
  for (int32_t i = 0; i < numOfCols; ++i) {
26,644,980✔
220
    pSupInfo->colId[i] = pCols[i].colId;
21,967,633✔
221
    pSupInfo->slotId[i] = pSlotIdList[i];
21,967,633✔
222

223
    if (pCols[i].pk) {
21,967,633✔
224
      pSupInfo->pk = pCols[i];
171,239✔
225
      pSupInfo->pkSrcSlot = i - 1;
171,239✔
226
      pSupInfo->pkDstSlot = pSlotIdList[i];
171,239✔
227
      pSupInfo->numOfPks += 1;
171,239✔
228
    }
229

230
    if (IS_VAR_DATA_TYPE(pCols[i].type)) {
21,967,633!
231
      pSupInfo->buildBuf[i] = taosMemoryMalloc(pCols[i].bytes);
3,052,281✔
232
      if (pSupInfo->buildBuf[i] == NULL) {
3,046,083!
233
        tsdbError("failed to prepare memory for set columnId slot list, size:%d, code:%s", pCols[i].bytes,
×
234
                  tstrerror(terrno));
235
      }
236
      TSDB_CHECK_NULL(pSupInfo->buildBuf[i], code, lino, _end, terrno);
3,045,842!
237
    } else {
238
      pSupInfo->buildBuf[i] = NULL;
18,915,352✔
239
    }
240
  }
241

242
_end:
4,677,347✔
243
  if (code != TSDB_CODE_SUCCESS) {
4,677,347!
244
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
245
  }
246
  return code;
4,671,811✔
247
}
248

249
static int32_t updateBlockSMAInfo(STSchema* pSchema, SBlockLoadSuppInfo* pSupInfo) {
4,621,477✔
250
  int32_t   code = TSDB_CODE_SUCCESS;
4,621,477✔
251
  int32_t   lino = 0;
4,621,477✔
252
  int32_t   i = 0, j = 0;
4,621,477✔
253
  STColumn* pTCol = NULL;
4,621,477✔
254

255
  TSDB_CHECK_NULL(pSchema, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,621,477!
256
  TSDB_CHECK_NULL(pSupInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,621,477!
257

258
  while (i < pSchema->numOfCols && j < pSupInfo->numOfCols) {
54,722,683✔
259
    pTCol = &pSchema->columns[i];
50,135,033✔
260
    if (pTCol->colId == pSupInfo->colId[j]) {
50,135,033✔
261
      if (!IS_BSMA_ON(pTCol) && (PRIMARYKEY_TIMESTAMP_COL_ID != pTCol->colId)) {
21,232,986✔
262
        pSupInfo->smaValid = false;
33,811✔
263
        goto _end;
33,811✔
264
      }
265

266
      i += 1;
21,199,175✔
267
      j += 1;
21,199,175✔
268
    } else if (pTCol->colId < pSupInfo->colId[j]) {  // do nothing
28,902,047!
269
      i += 1;
28,905,070✔
270
    } else {
271
      code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
×
272
      TSDB_CHECK_CODE(code, lino, _end);
×
273
    }
274
  }
275

276
_end:
4,587,650✔
277
  if (code != TSDB_CODE_SUCCESS) {
4,621,477✔
278
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
16!
279
  }
280
  return code;
4,623,588✔
281
}
282

283
static bool isEmptyQueryTimeWindow(STimeWindow* pWindow) {
21,933,092✔
284
  return (pWindow == NULL) || (pWindow->skey > pWindow->ekey);
21,933,092!
285
}
286

287
// Update the query time window according to the data time to live(TTL) information, in order to avoid to return
288
// the expired data to client, even it is queried already.
289
static int32_t updateQueryTimeWindow(STsdb* pTsdb, STimeWindow* pWindow, STimeWindow* out) {
4,702,076✔
290
  int32_t code = TSDB_CODE_SUCCESS;
4,702,076✔
291
  int32_t lino = 0;
4,702,076✔
292
  int64_t earlyTs = 0;
4,702,076✔
293

294
  TSDB_CHECK_NULL(pTsdb, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,702,076!
295
  TSDB_CHECK_NULL(pWindow, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,702,076!
296
  TSDB_CHECK_NULL(out, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,702,076!
297

298
  earlyTs = tsdbGetEarliestTs(pTsdb);
4,702,076✔
299
  *out = *pWindow;
4,704,713✔
300
  if (out->skey < earlyTs) {
4,704,713✔
301
    out->skey = earlyTs;
2,510,377✔
302
  }
303

304
_end:
2,194,336✔
305
  if (code != TSDB_CODE_SUCCESS) {
4,704,713!
306
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
307
  }
308
  return code;
4,703,384✔
309
}
310

311
// init file iterator
312
static int32_t initFilesetIterator(SFilesetIter* pIter, TFileSetArray* pFileSetArray, STsdbReader* pReader) {
4,536,429✔
313
  int32_t             code = TSDB_CODE_SUCCESS;
4,536,429✔
314
  int32_t             lino = 0;
4,536,429✔
315
  SBlockLoadSuppInfo* pInfo = NULL;
4,536,429✔
316
  SSttBlockReader*    pSttReader = NULL;
4,536,429✔
317
  size_t              numOfFileset = 0;
4,536,429✔
318
  bool                asc = false;
4,536,429✔
319

320
  TSDB_CHECK_NULL(pIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,536,429!
321
  TSDB_CHECK_NULL(pFileSetArray, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,536,429!
322
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,536,429!
323

324
  pInfo = &pReader->suppInfo;
4,536,429✔
325
  numOfFileset = TARRAY2_SIZE(pFileSetArray);
4,536,429✔
326
  asc = ASCENDING_TRAVERSE(pReader->info.order);
4,536,429✔
327

328
  pIter->index = asc ? -1 : numOfFileset;
4,536,429✔
329
  pIter->order = pReader->info.order;
4,536,429✔
330
  pIter->pFilesetList = pFileSetArray;
4,536,429✔
331
  pIter->numOfFiles = numOfFileset;
4,536,429✔
332

333
  if (pIter->pSttBlockReader == NULL) {
4,536,429✔
334
    pIter->pSttBlockReader = taosMemoryCalloc(1, sizeof(struct SSttBlockReader));
4,514,104!
335
    if (pIter->pSttBlockReader == NULL) {
4,512,426!
336
      tsdbError("failed to prepare the last block iterator, since:%s %s", tstrerror(terrno), pReader->idStr);
×
337
    }
338
    TSDB_CHECK_NULL(pIter->pSttBlockReader, code, lino, _end, terrno);
4,514,043!
339
  }
340

341
  pSttReader = pIter->pSttBlockReader;
4,536,368✔
342
  pSttReader->order = pReader->info.order;
4,536,368✔
343
  pSttReader->window = pReader->info.window;
4,536,368✔
344
  pSttReader->verRange = pReader->info.verRange;
4,536,368✔
345
  pSttReader->numOfPks = pReader->suppInfo.numOfPks;
4,536,368✔
346
  pSttReader->uid = 0;
4,536,368✔
347

348
  tMergeTreeClose(&pSttReader->mergeTree);
4,536,368✔
349
  code = initRowKey(&pSttReader->currentKey, INT64_MIN, pInfo->numOfPks, pInfo->pk.type, pInfo->pk.bytes, asc);
4,535,759✔
350
  if (code != TSDB_CODE_SUCCESS) {
4,535,124!
351
    tsdbError("failed init row key, %s", pReader->idStr);
×
352
  } else {
353
    tsdbDebug("init fileset iterator, total files:%d %s", pIter->numOfFiles, pReader->idStr);
4,535,124✔
354
  }
355
  TSDB_CHECK_CODE(code, lino, _end);
4,534,113!
356

357
_end:
4,534,113✔
358
  if (code != TSDB_CODE_SUCCESS) {
4,534,113!
359
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
360
  }
361
  return code;
4,535,357✔
362
}
363

364
static int32_t filesetIteratorNext(SFilesetIter* pIter, STsdbReader* pReader, bool* hasNext) {
7,180,608✔
365
  int32_t           code = TSDB_CODE_SUCCESS;
7,180,608✔
366
  int32_t           lino = 0;
7,180,608✔
367
  bool              asc = false;
7,180,608✔
368
  int32_t           step = 0;
7,180,608✔
369
  SReadCostSummary* pCost = NULL;
7,180,608✔
370
  STFileObj**       pFileObj = NULL;
7,180,608✔
371

372
  TSDB_CHECK_NULL(pIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,180,608!
373
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,180,608!
374
  TSDB_CHECK_NULL(hasNext, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,180,608!
375

376
  asc = ASCENDING_TRAVERSE(pIter->order);
7,180,608✔
377
  step = asc ? 1 : -1;
7,180,608✔
378
  *hasNext = false;
7,180,608✔
379

380
  pIter->index += step;
7,180,608✔
381
  if ((asc && pIter->index >= pIter->numOfFiles) || ((!asc) && pIter->index < 0)) {
7,180,608✔
382
    *hasNext = false;
1,368,069✔
383
    goto _end;
1,368,069✔
384
  }
385

386
  pCost = &pReader->cost;
5,812,539✔
387

388
  TSDB_CHECK_NULL(pIter->pSttBlockReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,812,539!
389
  pIter->pSttBlockReader->uid = 0;
5,812,539✔
390
  tMergeTreeClose(&pIter->pSttBlockReader->mergeTree);
5,812,539✔
391
  destroySttBlockReader(pReader->status.pLDataIterArray, &pCost->sttCost);
5,811,142✔
392

393
  pReader->status.pLDataIterArray = taosArrayInit(4, POINTER_BYTES);
5,814,209✔
394
  TSDB_CHECK_NULL(pReader->status.pLDataIterArray, code, lino, _end, terrno);
5,816,363!
395

396
  // check file the time range of coverage
397
  STimeWindow win = {0};
5,816,363✔
398

399
  while (1) {
917,112✔
400
    if (pReader->pFileReader != NULL) {
6,733,475✔
401
      tsdbDataFileReaderClose(&pReader->pFileReader);
170,618✔
402
    }
403

404
    TSDB_CHECK_CONDITION(pIter->index < pIter->pFilesetList->size, code, lino, _end, TSDB_CODE_INTERNAL_ERROR);
6,730,317!
405
    pReader->status.pCurrentFileset = pIter->pFilesetList->data[pIter->index];
6,730,317✔
406

407
    pFileObj = pReader->status.pCurrentFileset->farr;
6,730,317✔
408
    if (pFileObj[0] != NULL || pFileObj[3] != NULL) {
6,730,317✔
409
      SDataFileReaderConfig conf = {.tsdb = pReader->pTsdb, .szPage = pReader->pTsdb->pVnode->config.tsdbPageSize};
227,649✔
410

411
      const char* filesName[4] = {0};
227,649✔
412

413
      if (pFileObj[0] != NULL) {
227,649✔
414
        conf.files[0].file = *pFileObj[0]->f;
222,043✔
415
        conf.files[0].exist = true;
222,043✔
416
        filesName[0] = pFileObj[0]->fname;
222,043✔
417

418
        conf.files[1].file = *pFileObj[1]->f;
222,043✔
419
        conf.files[1].exist = true;
222,043✔
420
        filesName[1] = pFileObj[1]->fname;
222,043✔
421

422
        conf.files[2].file = *pFileObj[2]->f;
222,043✔
423
        conf.files[2].exist = true;
222,043✔
424
        filesName[2] = pFileObj[2]->fname;
222,043✔
425
      }
426

427
      if (pFileObj[3] != NULL) {
227,649✔
428
        conf.files[3].exist = true;
48,820✔
429
        conf.files[3].file = *pFileObj[3]->f;
48,820✔
430
        filesName[3] = pFileObj[3]->fname;
48,820✔
431
      }
432

433
      code = tsdbDataFileReaderOpen(filesName, &conf, &pReader->pFileReader);
227,649✔
434
      TSDB_CHECK_CODE(code, lino, _end);
229,274!
435

436
      pReader->cost.headFileLoad += 1;
229,274✔
437
    }
438

439
    int32_t fid = pReader->status.pCurrentFileset->fid;
6,731,942✔
440
    tsdbFidKeyRange(fid, pReader->pTsdb->keepCfg.days, pReader->pTsdb->keepCfg.precision, &win.skey, &win.ekey);
6,731,942✔
441

442
    // current file are no longer overlapped with query time window, ignore remain files
443
    if ((asc && win.skey > pReader->info.window.ekey) || (!asc && win.ekey < pReader->info.window.skey)) {
6,728,003✔
444
      tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pReader,
470,572✔
445
                pReader->info.window.skey, pReader->info.window.ekey, pReader->idStr);
446
      *hasNext = false;
470,703✔
447
      break;
470,703✔
448
    }
449

450
    if ((asc && (win.ekey < pReader->info.window.skey)) || ((!asc) && (win.skey > pReader->info.window.ekey))) {
6,257,431✔
451
      pIter->index += step;
1,157,126✔
452
      if ((asc && pIter->index >= pIter->numOfFiles) || ((!asc) && pIter->index < 0)) {
1,157,126✔
453
        *hasNext = false;
240,014✔
454
        break;
240,014✔
455
      }
456
      continue;
917,112✔
457
    }
458

459
    tsdbDebug("%p file found fid:%d for qrange:%" PRId64 "-%" PRId64 ", %s", pReader, fid, pReader->info.window.skey,
5,100,305✔
460
              pReader->info.window.ekey, pReader->idStr);
461

462
    *hasNext = true;
5,097,169✔
463
    break;
5,097,169✔
464
  }
465

466
_end:
7,175,955✔
467
  if (code != TSDB_CODE_SUCCESS) {
7,175,955!
468
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
469
  }
470
  return code;
7,176,676✔
471
}
472

473
bool shouldFreePkBuf(SBlockLoadSuppInfo* pSupp) {
14,464,023✔
474
  return (pSupp != NULL) && (pSupp->numOfPks > 0) && IS_VAR_DATA_TYPE(pSupp->pk.type);
14,464,023!
475
}
476

477
int32_t resetDataBlockIterator(SDataBlockIter* pIter, int32_t order, bool needFree, const char* id) {
9,616,890✔
478
  int32_t code = TSDB_CODE_SUCCESS;
9,616,890✔
479
  int32_t lino = 0;
9,616,890✔
480

481
  TSDB_CHECK_NULL(pIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
9,616,890!
482

483
  pIter->order = order;
9,616,890✔
484
  pIter->index = -1;
9,616,890✔
485
  pIter->numOfBlocks = 0;
9,616,890✔
486

487
  if (pIter->blockList == NULL) {
9,616,890✔
488
    pIter->blockList = taosArrayInit(4, sizeof(SFileDataBlockInfo));
4,510,365✔
489
    if (pIter->blockList == NULL) {
4,513,594!
490
      tsdbError("%s failed to reset block iter, func:%s at line:%d code:%s", id, __func__, __LINE__, tstrerror(terrno));
×
491
    }
492
    TSDB_CHECK_NULL(pIter->blockList, code, lino, _end, terrno);
4,513,082!
493
  } else {
494
    clearDataBlockIterator(pIter, needFree);
5,106,525✔
495
  }
496

497
_end:
9,626,336✔
498
  if (code != TSDB_CODE_SUCCESS) {
9,626,336!
499
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
500
  }
501
  return code;
9,627,963✔
502
}
503

504
static void initReaderStatus(SReaderStatus* pStatus) {
4,683,454✔
505
  if (pStatus == NULL) {
4,683,454!
506
    return;
×
507
  }
508
  pStatus->pTableIter = NULL;
4,683,454✔
509
  pStatus->loadFromFile = true;
4,683,454✔
510
}
511

512
static int32_t createResBlock(SQueryTableDataCond* pCond, int32_t capacity, SSDataBlock** pResBlock) {
2,532✔
513
  int32_t      code = TSDB_CODE_SUCCESS;
2,532✔
514
  int32_t      lino = 0;
2,532✔
515
  SSDataBlock* pBlock = NULL;
2,532✔
516

517
  TSDB_CHECK_NULL(pCond, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,532!
518
  TSDB_CHECK_CONDITION(capacity >= 0, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,532!
519
  TSDB_CHECK_NULL(pResBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,532!
520

521
  code = createDataBlock(&pBlock);
2,532✔
522
  TSDB_CHECK_CODE(code, lino, _end);
2,539!
523

524
  for (int32_t i = 0; i < pCond->numOfCols; ++i) {
15,836✔
525
    SColumnInfoData colInfo = {0};
13,285✔
526
    colInfo.info = pCond->colList[i];
13,285✔
527
    code = blockDataAppendColInfo(pBlock, &colInfo);
13,285✔
528
    TSDB_CHECK_CODE(code, lino, _end);
13,297!
529
  }
530

531
  code = blockDataEnsureCapacity(pBlock, capacity);
2,551✔
532
  TSDB_CHECK_CODE(code, lino, _end);
2,539!
533

534
  *pResBlock = pBlock;
2,539✔
535
  pBlock = NULL;
2,539✔
536

537
_end:
2,539✔
538
  if (code != TSDB_CODE_SUCCESS) {
2,539!
539
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
540
  }
541
  if (pBlock) {
2,539!
542
    taosArrayDestroy(pBlock->pDataBlock);
×
543
    taosMemoryFreeClear(pBlock);
×
544
  }
545
  return code;
2,539✔
546
}
547

548
static int32_t tsdbInitReaderLock(STsdbReader* pReader) {
4,666,176✔
549
  int32_t code = TSDB_CODE_SUCCESS;
4,666,176✔
550
  int32_t lino = 0;
4,666,176✔
551

552
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,666,176!
553

554
  code = taosThreadMutexInit(&pReader->readerMutex, NULL);
4,666,176✔
555
  tsdbTrace("tsdb/read: %p, post-init read mutex: %p, code: %d", pReader, &pReader->readerMutex, code);
4,673,990✔
556
  TSDB_CHECK_CODE(code, lino, _end);
4,671,783!
557

558
_end:
4,671,783✔
559
  if (code != TSDB_CODE_SUCCESS) {
4,671,783!
560
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
561
  }
562
  return code;
4,669,937✔
563
}
564

565
static int32_t tsdbUninitReaderLock(STsdbReader* pReader) {
4,686,712✔
566
  int32_t code = TSDB_CODE_SUCCESS;
4,686,712✔
567
  int32_t lino = 0;
4,686,712✔
568

569
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,686,712!
570

571
  tsdbTrace("tsdb/read: %p, pre-uninit read mutex: %p, code: %d", pReader, &pReader->readerMutex, code);
4,686,712✔
572
  code = taosThreadMutexDestroy(&pReader->readerMutex);
4,686,712✔
573
  tsdbTrace("tsdb/read: %p, post-uninit read mutex: %p, code: %d", pReader, &pReader->readerMutex, code);
4,685,793✔
574
  TSDB_CHECK_CODE(code, lino, _end);
4,686,078✔
575

576
_end:
4,686,074✔
577
  if (code != TSDB_CODE_SUCCESS) {
4,686,078✔
578
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
579
  }
580
  return code;
4,686,054✔
581
}
582

583
static int32_t tsdbAcquireReader(STsdbReader* pReader) {
21,956,696✔
584
  int32_t code = TSDB_CODE_SUCCESS;
21,956,696✔
585
  int32_t lino = 0;
21,956,696✔
586

587
  TSDB_CHECK_CONDITION((pReader != NULL) && (pReader->idStr != NULL), code, lino, _end, TSDB_CODE_INVALID_PARA);
21,956,696!
588

589
  tsdbTrace("tsdb/read: %s, pre-take read mutex: %p, code: %d", pReader->idStr, &pReader->readerMutex, code);
21,956,696✔
590
  code = taosThreadMutexLock(&pReader->readerMutex);
21,956,709✔
591
  if (code != TSDB_CODE_SUCCESS) {
21,969,640!
592
    tsdbError("tsdb/read:%p, failed to lock reader mutex, code:%s", pReader->idStr, tstrerror(code));
×
593
  } else {
594
    tsdbTrace("tsdb/read: %s, post-take read mutex: %p, code: %d", pReader->idStr, &pReader->readerMutex, code);
21,969,640✔
595
  }
596
  TSDB_CHECK_CODE(code, lino, _end);
21,963,536!
597

598
_end:
21,963,536✔
599
  if (code != TSDB_CODE_SUCCESS) {
21,963,536!
600
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
601
  }
602
  return code;
21,964,085✔
603
}
604

605
static int32_t tsdbTryAcquireReader(STsdbReader* pReader) {
×
606
  int32_t code = TSDB_CODE_SUCCESS;
×
607
  int32_t lino = 0;
×
608

609
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
610

611
  code = taosThreadMutexTryLock(&pReader->readerMutex);
×
612
  if (code != TSDB_CODE_SUCCESS) {
×
613
    // Failing to acquire the lock is reasonable, not an error
614
    tsdbWarn("tsdb/read: %p, post-trytake read mutex: %p, code: %d", pReader, &pReader->readerMutex, code);
×
615
  } else {
616
    tsdbTrace("tsdb/read: %p, post-trytask read mutex: %p", pReader, &pReader->readerMutex);
×
617
  }
618
  return code;
×
619

620
_end:
×
621
  if (code != TSDB_CODE_SUCCESS) {
×
622
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
623
  }
624
  return code;
×
625
}
626

627
static int32_t tsdbReleaseReader(STsdbReader* pReader) {
21,963,088✔
628
  int32_t code = TSDB_CODE_SUCCESS;
21,963,088✔
629
  int32_t lino = 0;
21,963,088✔
630

631
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
21,963,088!
632

633
  code = taosThreadMutexUnlock(&pReader->readerMutex);
21,963,088✔
634
  if (code != TSDB_CODE_SUCCESS) {
21,971,738!
635
    tsdbError("tsdb/read: %p post-untake read mutex:%p failed, code:%d", pReader, &pReader->readerMutex, code);
×
636
  } else {
637
    tsdbTrace("tsdb/read: %p, post-untake read mutex: %p", pReader, &pReader->readerMutex);
21,971,738✔
638
  }
639
  TSDB_CHECK_CODE(code, lino, _end);
21,969,552!
640

641
_end:
21,969,552✔
642
  if (code != TSDB_CODE_SUCCESS) {
21,969,552!
643
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
644
  }
645
  return code;
21,970,168✔
646
}
647

648
void tsdbReleaseDataBlock2(STsdbReader* pReader) {
3,066,291✔
649
  if (pReader == NULL) return;
3,066,291!
650

651
  SReaderStatus* pStatus = &pReader->status;
3,066,291✔
652
  if (!pStatus->composedDataBlock) {
3,066,291✔
653
    (void) tsdbReleaseReader(pReader);
2,864,969✔
654
  }
655
}
656

657
static int32_t initResBlockInfo(SResultBlockInfo* pResBlockInfo, int64_t capacity, SSDataBlock* pResBlock,
4,670,369✔
658
                                SQueryTableDataCond* pCond, SBlockLoadSuppInfo* pSup) {
659
  int32_t      code = TSDB_CODE_SUCCESS;
4,670,369✔
660
  int32_t      lino = 0;
4,670,369✔
661
  SSDataBlock* p = NULL;
4,670,369✔
662

663
  TSDB_CHECK_NULL(pResBlockInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,670,369!
664
  TSDB_CHECK_CONDITION((pResBlockInfo->pResBlock != NULL) || (pSup != NULL), code, lino, _end, TSDB_CODE_INVALID_PARA);
4,670,369!
665

666
  pResBlockInfo->capacity = capacity;
4,670,369✔
667
  pResBlockInfo->pResBlock = pResBlock;
4,670,369✔
668

669
  if (pResBlockInfo->pResBlock == NULL) {
4,670,369✔
670
    pResBlockInfo->freeBlock = true;
2,533✔
671
    pResBlockInfo->pResBlock = NULL;
2,533✔
672

673
    code = createResBlock(pCond, pResBlockInfo->capacity, &pResBlockInfo->pResBlock);
2,533✔
674
    TSDB_CHECK_CODE(code, lino, _end);
2,539!
675

676
    if (pSup->numOfPks > 0) {
2,539!
677
      p = pResBlockInfo->pResBlock;
×
678
      p->info.pks[0].type = pSup->pk.type;
×
679
      p->info.pks[1].type = pSup->pk.type;
×
680

681
      if (IS_VAR_DATA_TYPE(pSup->pk.type)) {
×
682
        p->info.pks[0].pData = taosMemoryCalloc(1, pSup->pk.bytes);
×
683
        TSDB_CHECK_NULL(p->info.pks[0].pData, code, lino, _end, terrno);
×
684

685
        p->info.pks[1].pData = taosMemoryCalloc(1, pSup->pk.bytes);
×
686
        TSDB_CHECK_NULL(p->info.pks[0].pData, code, lino, _end, terrno);
×
687

688
        p->info.pks[0].nData = pSup->pk.bytes;
×
689
        p->info.pks[1].nData = pSup->pk.bytes;
×
690
      }
691
    }
692
  } else {
693
    pResBlockInfo->freeBlock = false;
4,667,836✔
694
  }
695

696
_end:
4,670,375✔
697
  if (code != TSDB_CODE_SUCCESS) {
4,670,375!
698
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
699
  }
700
  return code;
4,672,255✔
701
}
702

703
static int32_t tsdbReaderCreate(SVnode* pVnode, SQueryTableDataCond* pCond, void** ppReader, int32_t capacity,
4,684,551✔
704
                                SSDataBlock* pResBlock, const char* idstr) {
705
  int32_t             code = TSDB_CODE_SUCCESS;
4,684,551✔
706
  int32_t             lino = 0;
4,684,551✔
707
  int8_t              level = 0;
4,684,551✔
708
  STsdbReader*        pReader = NULL;
4,684,551✔
709
  SBlockLoadSuppInfo* pSup = NULL;
4,684,551✔
710

711
  TSDB_CHECK_NULL(pVnode, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,684,551!
712
  TSDB_CHECK_NULL(pCond, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,684,551!
713
  TSDB_CHECK_NULL(ppReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,684,551!
714

715
  *ppReader = NULL;
4,684,551✔
716
  pReader = (STsdbReader*)taosMemoryCalloc(1, sizeof(*pReader));
4,684,551!
717
  TSDB_CHECK_NULL(pReader, code, lino, _end, terrno);
4,681,395!
718

719
  if (VND_IS_TSMA(pVnode)) {
4,681,395!
720
    tsdbDebug("vgId:%d, tsma is selected to query, %s", TD_VID(pVnode), idstr);
×
721
  }
722

723
  initReaderStatus(&pReader->status);
4,681,395✔
724
  getTsdbByRetentions(pVnode, pCond, pVnode->config.tsdbCfg.retentions, idstr, &level, &pReader->pTsdb);
4,683,214✔
725

726
  pReader->info.suid = pCond->suid;
4,678,324✔
727
  pReader->info.order = pCond->order;
4,678,324✔
728
  pReader->info.verRange = getQueryVerRange(pVnode, pCond, level);
4,678,324✔
729
  code = updateQueryTimeWindow(pReader->pTsdb, &pCond->twindows, &pReader->info.window);
4,679,971✔
730
  TSDB_CHECK_CODE(code, lino, _end);
4,681,942!
731

732
  if (idstr == NULL) {
4,681,942✔
733
    idstr = "";
2,503✔
734
  }
735
  pReader->idStr = taosStrdup(idstr);
4,681,942!
736
  TSDB_CHECK_NULL(pReader->idStr, code, lino, _end, terrno);
4,681,883!
737

738
  pReader->type = pCond->type;
4,681,883✔
739
  pReader->bFilesetDelimited = false;
4,681,883✔
740
  pReader->blockInfoBuf.numPerBucket = 1000;  // 1000 tables per bucket
4,681,883✔
741

742
  if (pCond->numOfCols <= 0) {
4,681,883!
743
    tsdbError("vgId:%d, invalid column number %d in query cond, %s", TD_VID(pVnode), pCond->numOfCols, idstr);
×
744
    TSDB_CHECK_CONDITION(pCond->numOfCols > 0, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
745
  }
746

747
  // allocate buffer in order to load data blocks from file
748
  pSup = &pReader->suppInfo;
4,681,883✔
749
  pSup->tsColAgg.colId = PRIMARYKEY_TIMESTAMP_COL_ID;
4,681,883✔
750
  code = setColumnIdSlotList(pSup, pCond->colList, pCond->pSlotList, pCond->numOfCols);
4,681,883✔
751
  TSDB_CHECK_CODE(code, lino, _end);
4,669,653!
752

753
  code = initResBlockInfo(&pReader->resBlockInfo, capacity, pResBlock, pCond, pSup);
4,669,653✔
754
  TSDB_CHECK_CODE(code, lino, _end);
4,668,623!
755

756
  code = tBlockDataCreate(&pReader->status.fileBlockData);
4,668,623✔
757
  TSDB_CHECK_CODE(code, lino, _end);
4,672,282!
758

759
  if (pReader->suppInfo.colId[0] != PRIMARYKEY_TIMESTAMP_COL_ID) {
4,672,282!
760
    tsdbError("the first column isn't primary timestamp, %d, %s", pReader->suppInfo.colId[0], pReader->idStr);
×
761
    TSDB_CHECK_CONDITION(pReader->suppInfo.colId[0] == PRIMARYKEY_TIMESTAMP_COL_ID, code, lino, _end,
×
762
                         TSDB_CODE_INVALID_PARA);
763
  }
764

765
  pReader->status.pPrimaryTsCol = taosArrayGet(pReader->resBlockInfo.pResBlock->pDataBlock, pSup->slotId[0]);
4,672,282✔
766
  TSDB_CHECK_NULL(pReader->status.pPrimaryTsCol, code, lino, _end, terrno);
4,669,688!
767

768
  int32_t type = pReader->status.pPrimaryTsCol->info.type;
4,669,688✔
769
  if (type != TSDB_DATA_TYPE_TIMESTAMP) {
4,669,688!
770
    tsdbError("the first column isn't primary timestamp in result block, actual: %s, %s", tDataTypes[type].name,
×
771
              pReader->idStr);
772
    TSDB_CHECK_CONDITION(type == TSDB_DATA_TYPE_TIMESTAMP, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
773
  }
774

775
  code = tsdbInitReaderLock(pReader);
4,669,688✔
776
  TSDB_CHECK_CODE(code, lino, _end);
4,669,638!
777

778
  code = tsem_init(&pReader->resumeAfterSuspend, 0, 0);
4,669,638✔
779
  TSDB_CHECK_CODE(code, lino, _end);
4,667,653!
780

781
  *ppReader = pReader;
4,667,653✔
782
  pReader = NULL;
4,667,653✔
783

784
_end:
4,667,653✔
785
  if (code != TSDB_CODE_SUCCESS) {
4,667,653!
786
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
787
  }
788
  if (pReader) {
4,669,394!
789
    tsdbReaderClose2(pReader);
×
790
  }
791
  return code;
4,671,204✔
792
}
793

794
static int32_t doLoadBlockIndex(STsdbReader* pReader, SDataFileReader* pFileReader, SArray* pIndexList) {
5,096,637✔
795
  int32_t              code = TSDB_CODE_SUCCESS;
5,096,637✔
796
  int32_t              lino = 0;
5,096,637✔
797
  int32_t              st = 0;
5,096,637✔
798
  int32_t              et1 = 0;
5,096,637✔
799
  int32_t              et2 = 0;
5,096,637✔
800
  int32_t              numOfTables = 0;
5,096,637✔
801
  const TBrinBlkArray* pBlkArray = NULL;
5,096,637✔
802
  STableUidList*       pList = NULL;
5,096,637✔
803
  SBrinBlk*            pBrinBlk = NULL;
5,096,637✔
804

805
  if (pFileReader == NULL) {
5,096,637✔
806
    goto _end;
4,920,486✔
807
  }
808

809
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
176,151!
810
  TSDB_CHECK_NULL(pIndexList, code, lino, _end, TSDB_CODE_INVALID_PARA);
176,151!
811

812
  st = taosGetTimestampUs();
179,172✔
813
  numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
179,172✔
814

815
  code = tsdbDataFileReadBrinBlk(pFileReader, &pBlkArray);
179,171✔
816
  TSDB_CHECK_CODE(code, lino, _end);
179,079!
817

818
#if 0
819
  LRUHandle* handle = NULL;
820

821
  int32_t    code = tsdbCacheGetBlockIdx(pFileReader->pTsdb->biCache, pFileReader, &handle);
822
  if (code != TSDB_CODE_SUCCESS || handle == NULL) {
823
    goto _end;
824
  }
825

826

827
  SArray* aBlockIdx = (SArray*)taosLRUCacheValue(pFileReader->pTsdb->biCache, handle);
828
  size_t  num = taosArrayGetSize(aBlockIdx);
829
  if (num == 0) {
830
    tsdbBICacheRelease(pFileReader->pTsdb->biCache, handle);
831
    return TSDB_CODE_SUCCESS;
832
  }
833
#endif
834

835
  // todo binary search to the start position
836
  et1 = taosGetTimestampUs();
179,070✔
837

838
  pList = &pReader->status.uidList;
179,070✔
839

840
  int32_t i = 0;
179,070✔
841
  int32_t j = 0;
179,070✔
842
  while (i < TARRAY2_SIZE(pBlkArray)) {
464,952✔
843
    pBrinBlk = &pBlkArray->data[i];
320,882✔
844
    if (pBrinBlk->maxTbid.suid < pReader->info.suid) {
320,882✔
845
      i += 1;
3,855✔
846
      continue;
3,855✔
847
    }
848

849
    if (pBrinBlk->minTbid.suid > pReader->info.suid) {  // not include the queried table/super table, quit the loop
317,027✔
850
      break;
614✔
851
    }
852

853
    TSDB_CHECK_CONDITION(
316,413!
854
        (pBrinBlk->minTbid.suid <= pReader->info.suid) && (pBrinBlk->maxTbid.suid >= pReader->info.suid), code, lino,
855
        _end, TSDB_CODE_INTERNAL_ERROR);
856

857
    if (pBrinBlk->maxTbid.suid == pReader->info.suid && pBrinBlk->maxTbid.uid < pList->tableUidList[j]) {
316,413✔
858
      i += 1;
131,174✔
859
      continue;
131,174✔
860
    }
861

862
    if (pBrinBlk->minTbid.suid == pReader->info.suid && pBrinBlk->minTbid.uid > pList->tableUidList[numOfTables - 1]) {
185,239✔
863
      break;
600✔
864
    }
865

866
    const void* p1 = taosArrayPush(pIndexList, pBrinBlk);
184,612✔
867
    TSDB_CHECK_NULL(p1, code, lino, _end, terrno);
184,612!
868

869
    i += 1;
184,612✔
870
    if (pBrinBlk->maxTbid.suid == pReader->info.suid) {
184,612✔
871
      while (j < numOfTables && pList->tableUidList[j] < pBrinBlk->maxTbid.uid) {
438,618✔
872
        j++;
268,882✔
873
      }
874
      if (j >= numOfTables) {
169,736✔
875
        break;
33,759✔
876
      }
877
    }
878
  }
879

880
  et2 = taosGetTimestampUs();
179,172✔
881
  tsdbDebug("load block index for %d/%d tables completed, elapsed time:%.2f ms, set BrinBlk:%.2f ms, size:%.2f Kb %s",
179,172✔
882
            numOfTables, (int32_t)pBlkArray->size, (et1 - st) / 1000.0, (et2 - et1) / 1000.0,
883
            pBlkArray->size * sizeof(SBrinBlk) / 1024.0, pReader->idStr);
884

885
  pReader->cost.headFileLoadTime += (et1 - st) / 1000.0;
179,188✔
886

887
_end:
5,099,674✔
888
  if (code != TSDB_CODE_SUCCESS) {
5,099,674!
889
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
890
  }
891
  return code;
5,094,653✔
892
}
893

894
static int32_t loadFileBlockBrinInfo(STsdbReader* pReader, SArray* pIndexList, SBlockNumber* pBlockNum,
5,092,918✔
895
                                     SArray* pTableScanInfoList) {
896
  int32_t         code = TSDB_CODE_SUCCESS;
5,092,918✔
897
  int32_t         lino = 0;
5,092,918✔
898
  int64_t         st = 0;
5,092,918✔
899
  bool            asc = false;
5,092,918✔
900
  STimeWindow     w = {0};
5,092,918✔
901
  SBrinRecordIter iter = {0};
5,092,918✔
902
  int32_t         numOfTables = 0;
5,092,918✔
903
  SBrinRecord*    pRecord = NULL;
5,092,918✔
904
  int32_t         k = 0;
5,092,918✔
905
  size_t          sizeInDisk = 0;
5,092,918✔
906

907
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,092,918!
908
  TSDB_CHECK_NULL(pBlockNum, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,092,918!
909
  TSDB_CHECK_NULL(pTableScanInfoList, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,092,918!
910

911
  st = taosGetTimestampUs();
5,097,550✔
912
  asc = ASCENDING_TRAVERSE(pReader->info.order);
5,097,550✔
913
  w = pReader->info.window;
5,097,550✔
914
  numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
5,097,550✔
915

916
  // clear info for the new file
917
  cleanupInfoForNextFileset(pReader->status.pTableMap);
5,098,338✔
918
  initBrinRecordIter(&iter, pReader->pFileReader, pIndexList);
5,099,867✔
919

920
  while (1) {
9,523,607✔
921
    code = getNextBrinRecord(&iter, &pRecord);
14,624,435✔
922
    TSDB_CHECK_CODE(code, lino, _end);
14,619,127!
923

924
    if (pRecord == NULL) {
14,619,127✔
925
      break;
5,048,587✔
926
    }
927

928
    if (pRecord->suid > pReader->info.suid) {
9,570,540✔
929
      break;
14,360✔
930
    }
931

932
    uint64_t uid = pReader->status.uidList.tableUidList[k];
9,556,180✔
933
    if (pRecord->suid < pReader->info.suid) {
9,556,180✔
934
      continue;
4,203,332✔
935
    }
936

937
    if (uid < pRecord->uid) {  // forward the table uid index
9,548,617✔
938
      while (k < numOfTables && pReader->status.uidList.tableUidList[k] < pRecord->uid) {
536,185✔
939
        k += 1;
269,449✔
940
      }
941

942
      if (k >= numOfTables) {
266,736✔
943
        break;
34,308✔
944
      }
945

946
      uid = pReader->status.uidList.tableUidList[k];
232,428✔
947
    }
948

949
    if (pRecord->uid < uid) {
9,514,309✔
950
      continue;
4,146,214✔
951
    }
952

953
    TSDB_CHECK_CONDITION((pRecord->suid == pReader->info.suid) && (uid == pRecord->uid), code, lino, _end,
5,368,095!
954
                         TSDB_CODE_INTERNAL_ERROR);
955

956
    STableBlockScanInfo* pScanInfo = NULL;
5,368,095✔
957
    code = getTableBlockScanInfo(pReader->status.pTableMap, uid, &pScanInfo, pReader->idStr);
5,368,095✔
958
    TSDB_CHECK_CODE(code, lino, _end);
5,368,834!
959

960
    // here we should find the first timestamp that is greater than the lastProcKey
961
    // the window is an open interval NOW.
962
    if (asc) {
5,368,834✔
963
      w.skey = pScanInfo->lastProcKey.ts;
5,041,954✔
964
    } else {
965
      w.ekey = pScanInfo->lastProcKey.ts;
326,880✔
966
    }
967

968
    // NOTE: specialized for open interval
969
    if (((w.skey < INT64_MAX) && ((w.skey + 1) > w.ekey)) || (w.skey == INT64_MAX)) {
5,368,834!
970
      k += 1;
×
971
      if (k >= numOfTables) {
×
972
        break;
×
973
      } else {
974
        continue;
×
975
      }
976
    }
977

978
    // 1. time range check
979
    if (pRecord->firstKey.key.ts > w.ekey || pRecord->lastKey.key.ts < w.skey) {
5,368,870✔
980
      continue;
49,573✔
981
    }
982
    // The data block's time range must intersect with the query time range
983
    if (pRecord->firstKey.key.ts > pReader->info.window.ekey || pRecord->lastKey.key.ts < pReader->info.window.skey) {
5,319,297!
984
      continue;
×
985
    }
986

987
    if (asc) {
5,319,305✔
988
      if (pkCompEx(&pRecord->lastKey.key, &pScanInfo->lastProcKey) <= 0) {
10,019,563!
989
        continue;
×
990
      }
991
    } else {
992
      if (pkCompEx(&pRecord->firstKey.key, &pScanInfo->lastProcKey) >= 0) {
619,053!
993
        continue;
×
994
      }
995
    }
996

997
    // 2. version range check, version range is an CLOSED interval
998
    if (pRecord->minVer > pReader->info.verRange.maxVer || pRecord->maxVer < pReader->info.verRange.minVer) {
5,319,311!
999
      continue;
26✔
1000
    }
1001

1002
    if (pScanInfo->pBlockList == NULL) {
5,319,285✔
1003
      pScanInfo->pBlockList = taosArrayInit(4, sizeof(SFileDataBlockInfo));
392,729✔
1004
      TSDB_CHECK_NULL(pScanInfo->pBlockList, code, lino, _end, terrno);
393,027!
1005
    }
1006

1007
    if (pScanInfo->pBlockIdxList == NULL) {
5,319,583✔
1008
      pScanInfo->pBlockIdxList = taosArrayInit(4, sizeof(STableDataBlockIdx));
111,859✔
1009
      TSDB_CHECK_NULL(pScanInfo->pBlockIdxList, code, lino, _end, terrno);
111,886!
1010
    }
1011

1012
    SFileDataBlockInfo blockInfo = {.tbBlockIdx = TARRAY_SIZE(pScanInfo->pBlockList)};
5,319,610✔
1013
    code = recordToBlockInfo(&blockInfo, pRecord);
5,319,610✔
1014
    TSDB_CHECK_CODE(code, lino, _end);
5,320,247!
1015
    sizeInDisk += blockInfo.blockSize;
5,320,247✔
1016

1017
    const void* p1 = taosArrayPush(pScanInfo->pBlockList, &blockInfo);
5,320,247✔
1018
    TSDB_CHECK_NULL(p1, code, lino, _end, terrno);
5,320,247!
1019

1020
    // todo: refactor to record the fileset skey/ekey
1021
    if (pScanInfo->filesetWindow.skey > pRecord->firstKey.key.ts) {
5,320,247✔
1022
      pScanInfo->filesetWindow.skey = pRecord->firstKey.key.ts;
392,936✔
1023
    }
1024

1025
    if (pScanInfo->filesetWindow.ekey < pRecord->lastKey.key.ts) {
5,320,247!
1026
      pScanInfo->filesetWindow.ekey = pRecord->lastKey.key.ts;
5,320,266✔
1027
    }
1028

1029
    pBlockNum->numOfBlocks += 1;
5,320,247✔
1030
    if (taosArrayGetSize(pTableScanInfoList) == 0) {
5,320,247✔
1031
      p1 = taosArrayPush(pTableScanInfoList, &pScanInfo);
160,655✔
1032
      TSDB_CHECK_NULL(p1, code, lino, _end, terrno);
160,655!
1033
    } else {
1034
      STableBlockScanInfo** p = taosArrayGetLast(pTableScanInfoList);
5,159,563✔
1035
      TSDB_CHECK_NULL(p, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,159,638!
1036

1037
      if ((*p)->uid != uid) {
5,159,638✔
1038
        p1 = taosArrayPush(pTableScanInfoList, &pScanInfo);
232,386✔
1039
        TSDB_CHECK_NULL(p1, code, lino, _end, terrno);
232,386!
1040
      }
1041
    }
1042
  }
1043

1044
  pBlockNum->numOfSttFiles = pReader->status.pCurrentFileset->lvlArr->size;
5,097,255✔
1045
  int32_t total = pBlockNum->numOfSttFiles + pBlockNum->numOfBlocks;
5,097,255✔
1046

1047
  double el = (taosGetTimestampUs() - st) / 1000.0;
5,097,382✔
1048
  tsdbDebug(
5,097,382✔
1049
      "load block of %d tables completed, blocks:%d in %d tables, stt-files:%d, block-info-size:%.2f Kb, elapsed "
1050
      "time:%.2f ms %s",
1051
      numOfTables, pBlockNum->numOfBlocks, (int32_t)taosArrayGetSize(pTableScanInfoList), pBlockNum->numOfSttFiles,
1052
      sizeInDisk / 1000.0, el, pReader->idStr);
1053

1054
  pReader->cost.numOfBlocks += total;
5,095,830✔
1055
  pReader->cost.headFileLoadTime += el;
5,095,830✔
1056

1057
_end:
5,095,830✔
1058
  if (code != TSDB_CODE_SUCCESS) {
5,095,830!
1059
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1060
  }
1061
  clearBrinBlockIter(&iter);
5,095,830✔
1062
  return code;
5,093,037✔
1063
}
1064

1065
static void setBlockAllDumped(SFileBlockDumpInfo* pDumpInfo, int64_t maxKey, int32_t order) {
7,574,293✔
1066
  if (pDumpInfo != NULL) {
7,574,293!
1067
    pDumpInfo->allDumped = true;
7,574,322✔
1068
  }
1069
}
7,574,293✔
1070

1071
static int32_t updateLastKeyInfo(SRowKey* pKey, SFileDataBlockInfo* pBlockInfo, SDataBlockInfo* pInfo, int32_t numOfPks,
5,199,654✔
1072
                                 bool asc) {
1073
  int32_t code = TSDB_CODE_SUCCESS;
5,199,654✔
1074
  int32_t lino = 0;
5,199,654✔
1075

1076
  TSDB_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,199,654!
1077
  TSDB_CHECK_NULL(pInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,199,654!
1078

1079
  pKey->ts = asc ? pInfo->window.ekey : pInfo->window.skey;
5,199,654✔
1080
  pKey->numOfPKs = numOfPks;
5,199,654✔
1081
  if (pKey->numOfPKs <= 0) {
5,199,654✔
1082
    goto _end;
5,063,264✔
1083
  }
1084

1085
  TSDB_CHECK_NULL(pBlockInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
136,390!
1086
  if (IS_NUMERIC_TYPE(pKey->pks[0].type)) {
136,390!
1087
    VALUE_SET_TRIVIAL_DATUM(pKey->pks, asc ? pBlockInfo->lastPk.val : pBlockInfo->firstPk.val);
136,390!
1088
  } else {
1089
    uint8_t* p = asc ? pBlockInfo->lastPk.pData : pBlockInfo->firstPk.pData;
×
1090
    pKey->pks[0].nData = asc ? varDataLen(pBlockInfo->lastPk.pData) : varDataLen(pBlockInfo->firstPk.pData);
×
1091
    TAOS_MEMCPY(pKey->pks[0].pData, p, pKey->pks[0].nData);
×
1092
  }
1093

1094
_end:
5,199,654✔
1095
  if (code != TSDB_CODE_SUCCESS) {
5,199,654!
1096
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1097
  }
1098
  return code;
5,199,677✔
1099
}
1100

1101
static int32_t doCopyColVal(SColumnInfoData* pColInfoData, int32_t rowIndex, int32_t colIndex, SColVal* pColVal,
2,147,483,647✔
1102
                            SBlockLoadSuppInfo* pSup) {
1103
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
1104
  int32_t lino = 0;
2,147,483,647✔
1105

1106
  TSDB_CHECK_NULL(pColInfoData, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,147,483,647!
1107
  TSDB_CHECK_NULL(pColVal, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,147,483,647!
1108

1109
  if (IS_VAR_DATA_TYPE(pColVal->value.type)) {
2,147,483,647!
1110
    if (!COL_VAL_IS_VALUE(pColVal)) {
566,770,417✔
1111
      colDataSetNULL(pColInfoData, rowIndex);
102,615,651✔
1112
    } else {
1113
      TSDB_CHECK_NULL(pSup, code, lino, _end, TSDB_CODE_INVALID_PARA);
464,154,766!
1114
      varDataSetLen(pSup->buildBuf[colIndex], pColVal->value.nData);
464,154,766✔
1115
      if ((pColVal->value.nData + VARSTR_HEADER_SIZE) > pColInfoData->info.bytes) {
464,154,766✔
1116
        tsdbWarn("column cid:%d actual data len %d is bigger than schema len %d", pColVal->cid, pColVal->value.nData,
4!
1117
                 pColInfoData->info.bytes);
1118
        code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
4✔
1119
        TSDB_CHECK_CODE(code, lino, _end);
4!
1120
      }
1121

1122
      if (pColVal->value.nData > 0) {  // pData may be null, if nData is 0
464,154,762!
1123
        (void)memcpy(varDataVal(pSup->buildBuf[colIndex]), pColVal->value.pData, pColVal->value.nData);
486,523,591✔
1124
      }
1125

1126
      code = colDataSetVal(pColInfoData, rowIndex, pSup->buildBuf[colIndex], false);
464,154,762✔
1127
      TSDB_CHECK_CODE(code, lino, _end);
485,725,594!
1128
    }
1129
  } else {
1130
    code = colDataSetVal(pColInfoData, rowIndex, VALUE_GET_DATUM(&pColVal->value, pColVal->value.type),
2,147,483,647!
1131
                         !COL_VAL_IS_VALUE(pColVal));
2,147,483,647✔
1132
    TSDB_CHECK_CODE(code, lino, _end);
2,147,483,647!
1133
  }
1134

1135
_end:
2,147,483,647✔
1136
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
1137
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
1138
  }
1139
  return code;
2,147,483,647✔
1140
}
1141

1142
static int32_t getCurrentBlockInfo(SDataBlockIter* pBlockIter, SFileDataBlockInfo** pInfo, const char* id) {
24,318,690✔
1143
  int32_t code = TSDB_CODE_SUCCESS;
24,318,690✔
1144
  int32_t lino = 0;
24,318,690✔
1145

1146
  TSDB_CHECK_NULL(pBlockIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
24,318,690!
1147
  TSDB_CHECK_NULL(pInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
24,318,690!
1148
  TSDB_CHECK_NULL(pBlockIter->blockList, code, lino, _end, TSDB_CODE_INVALID_PARA);
24,318,690!
1149

1150
  *pInfo = NULL;
24,318,690✔
1151

1152
  size_t num = TARRAY_SIZE(pBlockIter->blockList);
24,318,690✔
1153
  if (num == 0) {
24,318,690✔
1154
    // Some callers would attempt to call this function. Filter out certain normal cases and return directly to avoid
1155
    // generating excessive unnecessary error logs.
1156
    TSDB_CHECK_CONDITION(num == pBlockIter->numOfBlocks, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,934,343!
1157
    return TSDB_CODE_INVALID_PARA;
4,934,343✔
1158
  }
1159

1160
  *pInfo = taosArrayGet(pBlockIter->blockList, pBlockIter->index);
19,384,347✔
1161
  TSDB_CHECK_NULL(*pInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
19,385,188!
1162

1163
_end:
19,385,188✔
1164
  if (code != TSDB_CODE_SUCCESS) {
19,385,188!
UNCOV
1165
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1166
  }
1167
  return code;
19,385,508✔
1168
}
1169

1170
static int32_t doBinarySearchKey(const TSKEY* keyList, int num, int pos, TSKEY key, int order) {
1,797✔
1171
  // start end position
1172
  int s, e;
1173
  s = pos;
1,797✔
1174

1175
  // check
1176
  if (!(keyList != NULL && pos >= 0 && pos < num && num > 0)) {
1,797!
UNCOV
1177
    return -1;
×
1178
  }
1179
  if (order == TSDB_ORDER_ASC) {
1,799✔
1180
    // find the first position which is smaller than the key
1181
    e = num - 1;
1,782✔
1182
    if (key < keyList[pos]) return -1;
1,782!
1183
    while (1) {
21,266✔
1184
      // check can return
1185
      if (key >= keyList[e]) return e;
23,048!
1186
      if (key <= keyList[s]) return s;
23,048✔
1187
      if (e - s <= 1) return s;
23,042✔
1188

1189
      // change start or end position
1190
      int mid = s + (e - s + 1) / 2;
21,269✔
1191
      if (keyList[mid] > key)
21,269✔
1192
        e = mid;
13,645✔
1193
      else if (keyList[mid] < key)
7,624✔
1194
        s = mid;
7,621✔
1195
      else
1196
        return mid;
3✔
1197
    }
1198
  } else {  // DESC
1199
    // find the first position which is bigger than the key
1200
    e = 0;
17✔
1201
    if (key > keyList[pos]) return -1;
17!
1202
    while (1) {
204✔
1203
      // check can return
1204
      if (key <= keyList[e]) return e;
221!
1205
      if (key >= keyList[s]) return s;
221✔
1206
      if (s - e <= 1) return s;
220✔
1207

1208
      // change start or end position
1209
      int mid = s - (s - e + 1) / 2;
204✔
1210
      if (keyList[mid] < key)
204✔
1211
        e = mid;
142✔
1212
      else if (keyList[mid] > key)
62!
1213
        s = mid;
62✔
1214
      else
UNCOV
1215
        return mid;
×
1216
    }
1217
  }
1218
}
1219

1220
// handle the repeat ts cases.
1221
static int32_t findFirstPos(const int64_t* pTsList, int32_t num, int32_t startPos, bool asc) {
1,799✔
1222
  int32_t i = startPos;
1,799✔
1223
  int64_t startTs = pTsList[startPos];
1,799✔
1224
  if (asc) {
1,799✔
1225
    while (i < num && (pTsList[i] == startTs)) {
3,566✔
1226
      i++;
1,785✔
1227
    }
1228
    return i - 1;
1,781✔
1229
  } else {
1230
    while (i >= 0 && (pTsList[i] == startTs)) {
37!
1231
      i--;
19✔
1232
    }
1233
    return i + 1;
18✔
1234
  }
1235
}
1236

1237
static int32_t getEndPosInDataBlock(STsdbReader* pReader, SBlockData* pBlockData, SBrinRecord* pRecord, int32_t pos) {
2,336,601✔
1238
  // NOTE: reverse the order to find the end position in data block
1239
  int32_t code = TSDB_CODE_SUCCESS;
2,336,601✔
1240
  int32_t lino = 0;
2,336,601✔
1241
  int32_t endPos = -1;
2,336,601✔
1242
  bool    asc = false;
2,336,601✔
1243

1244
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,336,601!
1245
  TSDB_CHECK_NULL(pRecord, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,336,601!
1246

1247
  asc = ASCENDING_TRAVERSE(pReader->info.order);
2,336,601✔
1248

1249
  if (asc && pReader->info.window.ekey >= pRecord->lastKey.key.ts) {
2,336,601✔
1250
    endPos = pRecord->numRow - 1;
2,038,646✔
1251
  } else if (!asc && pReader->info.window.skey <= pRecord->firstKey.key.ts) {
297,955✔
1252
    endPos = 0;
297,206✔
1253
  } else {
1254
    int64_t key = asc ? pReader->info.window.ekey : pReader->info.window.skey;
749!
1255
    endPos = doBinarySearchKey(pBlockData->aTSKEY, pRecord->numRow, pos, key, pReader->info.order);
749✔
1256
    if (endPos == -1) {
901!
UNCOV
1257
      goto _end;
×
1258
    }
1259

1260
    endPos = findFirstPos(pBlockData->aTSKEY, pRecord->numRow, endPos, asc);
901✔
1261
  }
1262

1263
  if ((pReader->info.verRange.maxVer >= pRecord->minVer && pReader->info.verRange.maxVer < pRecord->maxVer) ||
2,336,798!
1264
      (pReader->info.verRange.minVer <= pRecord->maxVer && pReader->info.verRange.minVer > pRecord->minVer)) {
2,336,801!
UNCOV
1265
    int32_t i = endPos;
×
1266

1267
    if (asc) {
×
1268
      for (; i >= 0; --i) {
×
1269
        if (pBlockData->aVersion[i] <= pReader->info.verRange.maxVer) {
×
UNCOV
1270
          break;
×
1271
        }
1272
      }
1273
    } else {
1274
      for (; i < pRecord->numRow; ++i) {
×
1275
        if (pBlockData->aVersion[i] >= pReader->info.verRange.minVer) {
×
UNCOV
1276
          break;
×
1277
        }
1278
      }
1279
    }
1280

UNCOV
1281
    endPos = i;
×
1282
  }
1283

1284
_end:
2,336,798✔
1285
  if (code != TSDB_CODE_SUCCESS) {
2,336,798!
UNCOV
1286
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1287
  }
1288
  return endPos;
2,336,743✔
1289
}
1290

1291
static int32_t copyPrimaryTsCol(const SBlockData* pBlockData, SFileBlockDumpInfo* pDumpInfo, SColumnInfoData* pColData,
2,336,699✔
1292
                                int32_t dumpedRows, bool asc) {
1293
  int32_t code = TSDB_CODE_SUCCESS;
2,336,699✔
1294
  int32_t lino = 0;
2,336,699✔
1295

1296
  TSDB_CHECK_CONDITION((pBlockData != NULL) && (pBlockData->aTSKEY != NULL), code, lino, _end, TSDB_CODE_INVALID_PARA);
2,336,699!
1297
  TSDB_CHECK_NULL(pDumpInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,336,699!
1298
  TSDB_CHECK_NULL(pColData, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,336,699!
1299
  TSDB_CHECK_CONDITION(dumpedRows >= 0, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,336,699!
1300

1301
  if (asc) {
2,336,699✔
1302
    TAOS_MEMCPY(pColData->pData, &pBlockData->aTSKEY[pDumpInfo->rowIndex], dumpedRows * sizeof(int64_t));
2,039,561✔
1303
  } else {
1304
    int32_t startIndex = pDumpInfo->rowIndex - dumpedRows + 1;
297,138✔
1305
    TAOS_MEMCPY(pColData->pData, &pBlockData->aTSKEY[startIndex], dumpedRows * sizeof(int64_t));
297,138✔
1306

1307
    // todo: opt perf by extract the loop
1308
    // reverse the array list
1309
    int32_t  mid = dumpedRows >> 1u;
297,138✔
1310
    int64_t* pts = (int64_t*)pColData->pData;
297,138✔
1311
    for (int32_t j = 0; j < mid; ++j) {
605,238,791✔
1312
      int64_t t = pts[j];
604,941,653✔
1313
      pts[j] = pts[dumpedRows - j - 1];
604,941,653✔
1314
      pts[dumpedRows - j - 1] = t;
604,941,653✔
1315
    }
1316
  }
1317

1318
_end:
297,138✔
1319
  if (code != TSDB_CODE_SUCCESS) {
2,336,699!
UNCOV
1320
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1321
  }
1322
  return code;
2,336,678✔
1323
}
1324

1325
// a faster version of copy procedure.
1326
static int32_t copyNumericCols(const SColData* pData, SFileBlockDumpInfo* pDumpInfo, SColumnInfoData* pColData,
1,819,529✔
1327
                               int32_t dumpedRows, bool asc) {
1328
  int32_t  code = TSDB_CODE_SUCCESS;
1,819,529✔
1329
  int32_t  lino = 0;
1,819,529✔
1330
  uint8_t* p = NULL;
1,819,529✔
1331
  int32_t  step = asc ? 1 : -1;
1,819,529!
1332

1333
  TSDB_CHECK_NULL(pData, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,819,529!
1334
  TSDB_CHECK_NULL(pDumpInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,819,529!
1335
  TSDB_CHECK_NULL(pColData, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,819,529!
1336
  TSDB_CHECK_CONDITION(dumpedRows >= 0, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,819,529!
1337

1338
  TSDB_CHECK_CONDITION(pData->type < TSDB_DATA_TYPE_MAX, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,819,529!
1339
  if (asc) {
1,819,529✔
1340
    p = pData->pData + tDataTypes[pData->type].bytes * pDumpInfo->rowIndex;
1,819,528✔
1341
  } else {
1342
    int32_t startIndex = pDumpInfo->rowIndex - dumpedRows + 1;
1✔
1343
    p = pData->pData + tDataTypes[pData->type].bytes * startIndex;
1✔
1344
  }
1345

1346
  // make sure it is aligned to 8bit, the allocated memory address is aligned to 256bit
1347

1348
  // 1. copy data in a batch model
1349
  TAOS_MEMCPY(pColData->pData, p, dumpedRows * tDataTypes[pData->type].bytes);
1,819,529✔
1350

1351
  // 2. reverse the array list in case of descending order scan data block
1352
  if (!asc) {
1,819,529✔
1353
    switch (pColData->info.type) {
9!
1354
      case TSDB_DATA_TYPE_TIMESTAMP:
9✔
1355
      case TSDB_DATA_TYPE_DOUBLE:
1356
      case TSDB_DATA_TYPE_BIGINT:
1357
      case TSDB_DATA_TYPE_DECIMAL64:
1358
      case TSDB_DATA_TYPE_UBIGINT: {
1359
        int32_t  mid = dumpedRows >> 1u;
9✔
1360
        int64_t* pts = (int64_t*)pColData->pData;
9✔
1361
        for (int32_t j = 0; j < mid; ++j) {
17✔
1362
          int64_t t = pts[j];
8✔
1363
          pts[j] = pts[dumpedRows - j - 1];
8✔
1364
          pts[dumpedRows - j - 1] = t;
8✔
1365
        }
1366
        break;
9✔
1367
      }
1368

UNCOV
1369
      case TSDB_DATA_TYPE_BOOL:
×
1370
      case TSDB_DATA_TYPE_TINYINT:
1371
      case TSDB_DATA_TYPE_UTINYINT: {
1372
        int32_t mid = dumpedRows >> 1u;
×
1373
        int8_t* pts = (int8_t*)pColData->pData;
×
1374
        for (int32_t j = 0; j < mid; ++j) {
×
1375
          int8_t t = pts[j];
×
UNCOV
1376
          pts[j] = pts[dumpedRows - j - 1];
×
1377
          pts[dumpedRows - j - 1] = t;
×
1378
        }
UNCOV
1379
        break;
×
1380
      }
1381

1382
      case TSDB_DATA_TYPE_SMALLINT:
×
1383
      case TSDB_DATA_TYPE_USMALLINT: {
1384
        int32_t  mid = dumpedRows >> 1u;
×
1385
        int16_t* pts = (int16_t*)pColData->pData;
×
1386
        for (int32_t j = 0; j < mid; ++j) {
×
1387
          int64_t t = pts[j];
×
UNCOV
1388
          pts[j] = pts[dumpedRows - j - 1];
×
1389
          pts[dumpedRows - j - 1] = t;
×
1390
        }
UNCOV
1391
        break;
×
1392
      }
1393

UNCOV
1394
      case TSDB_DATA_TYPE_FLOAT:
×
1395
      case TSDB_DATA_TYPE_INT:
1396
      case TSDB_DATA_TYPE_UINT: {
1397
        int32_t  mid = dumpedRows >> 1u;
×
1398
        int32_t* pts = (int32_t*)pColData->pData;
×
1399
        for (int32_t j = 0; j < mid; ++j) {
×
1400
          int32_t t = pts[j];
×
UNCOV
1401
          pts[j] = pts[dumpedRows - j - 1];
×
1402
          pts[dumpedRows - j - 1] = t;
×
1403
        }
UNCOV
1404
        break;
×
1405
      }
UNCOV
1406
      case TSDB_DATA_TYPE_DECIMAL: {
×
UNCOV
1407
        int32_t  mid = dumpedRows >> 1u;
×
UNCOV
1408
        DecimalWord* pDec = (DecimalWord*)pColData->pData;
×
UNCOV
1409
        DecimalWord tmp[2] = {0};
×
UNCOV
1410
        for (int32_t j = 0; j < mid; ++j) {
×
UNCOV
1411
          tmp[0] = pDec[2 * j];
×
UNCOV
1412
          tmp[1] = pDec[2 * j + 1];
×
UNCOV
1413
          pDec[2 * j] = pDec[2 * (dumpedRows - j - 1)];
×
UNCOV
1414
          pDec[2 * j + 1] = pDec[2 * (dumpedRows - j - 1) + 1];
×
UNCOV
1415
          pDec[2 * (dumpedRows - j - 1)] = tmp[0];
×
UNCOV
1416
          pDec[2 * (dumpedRows - j - 1) + 1] = tmp[1];
×
1417
        }
UNCOV
1418
        break;
×
1419
      }
1420
    }
1421
  }
1422

1423
  // 3. if the  null value exists, check items one-by-one
1424
  if (pData->flag != HAS_VALUE) {
1,819,529✔
1425
    int32_t rowIndex = 0;
12,644✔
1426

1427
    for (int32_t j = pDumpInfo->rowIndex; rowIndex < dumpedRows; j += step, rowIndex++) {
12,206,472✔
1428
      uint8_t v = tColDataGetBitValue(pData, j);
12,193,844✔
1429
      if (v == 0 || v == 1) {
12,193,828✔
1430
        colDataSetNull_f(pColData->nullbitmap, rowIndex);
188,616✔
1431
        pColData->hasNull = true;
188,616✔
1432
      }
1433
    }
1434
  }
1435

1436
_end:
1,819,513✔
1437
  if (code != TSDB_CODE_SUCCESS) {
1,819,513!
UNCOV
1438
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1439
  }
1440
  return code;
1,819,530✔
1441
}
1442

1443
static void blockInfoToRecord(SBrinRecord* record, SFileDataBlockInfo* pBlockInfo, SBlockLoadSuppInfo* pSupp) {
16,557,085✔
1444
  record->uid = pBlockInfo->uid;
16,557,085✔
1445
  record->firstKey = (STsdbRowKey){.key = {.ts = pBlockInfo->firstKey, .numOfPKs = pSupp->numOfPks}};
16,557,085✔
1446
  record->lastKey = (STsdbRowKey){.key = {.ts = pBlockInfo->lastKey, .numOfPKs = pSupp->numOfPks}};
16,557,085✔
1447

1448
  if (pSupp->numOfPks > 0) {
16,557,085✔
1449
    SValue* pFirst = &record->firstKey.key.pks[0];
597,002✔
1450
    SValue* pLast = &record->lastKey.key.pks[0];
597,002✔
1451

1452
    pFirst->type = pSupp->pk.type;
597,002✔
1453
    pLast->type = pSupp->pk.type;
597,002✔
1454

1455
    if (IS_VAR_DATA_TYPE(pFirst->type)) {
597,002!
1456
      pFirst->pData = (uint8_t*)varDataVal(pBlockInfo->firstPk.pData);
5✔
1457
      pFirst->nData = varDataLen(pBlockInfo->firstPk.pData);
5✔
1458

1459
      pLast->pData = (uint8_t*)varDataVal(pBlockInfo->lastPk.pData);
5✔
1460
      pLast->nData = varDataLen(pBlockInfo->lastPk.pData);
5✔
1461
    } else {
1462
      VALUE_SET_TRIVIAL_DATUM(pFirst, pBlockInfo->firstPk.val);
596,997✔
1463
      VALUE_SET_TRIVIAL_DATUM(pLast, pBlockInfo->lastPk.val);
596,997✔
1464
    }
1465
  }
1466

1467
  record->minVer = pBlockInfo->minVer;
16,557,085✔
1468
  record->maxVer = pBlockInfo->maxVer;
16,557,085✔
1469
  record->blockOffset = pBlockInfo->blockOffset;
16,557,085✔
1470
  record->smaOffset = pBlockInfo->smaOffset;
16,557,085✔
1471
  record->blockSize = pBlockInfo->blockSize;
16,557,085✔
1472
  record->blockKeySize = pBlockInfo->blockKeySize;
16,557,085✔
1473
  record->smaSize = pBlockInfo->smaSize;
16,557,085✔
1474
  record->numRow = pBlockInfo->numRow;
16,557,085✔
1475
  record->count = pBlockInfo->count;
16,557,085✔
1476
}
16,557,085✔
1477

1478
static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader, SRowKey* pLastProcKey) {
2,336,659✔
1479
  int32_t             code = TSDB_CODE_SUCCESS;
2,336,659✔
1480
  int32_t             lino = 0;
2,336,659✔
1481
  SReaderStatus*      pStatus = NULL;
2,336,659✔
1482
  SDataBlockIter*     pBlockIter = NULL;
2,336,659✔
1483
  SBlockLoadSuppInfo* pSupInfo = NULL;
2,336,659✔
1484
  SFileBlockDumpInfo* pDumpInfo = NULL;
2,336,659✔
1485
  SBlockData*         pBlockData = NULL;
2,336,659✔
1486
  SFileDataBlockInfo* pBlockInfo = NULL;
2,336,659✔
1487
  SSDataBlock*        pResBlock = NULL;
2,336,659✔
1488
  int32_t             numOfOutputCols = 0;
2,336,659✔
1489
  int64_t             st = 0;
2,336,659✔
1490
  bool                asc = false;
2,336,659✔
1491
  int32_t             step = 0;
2,336,659✔
1492
  SColVal             cv = {0};
2,336,659✔
1493
  SBrinRecord         tmp;
1494
  SBrinRecord*        pRecord = NULL;
2,336,659✔
1495

1496
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,336,659!
1497

1498
  pStatus = &pReader->status;
2,336,659✔
1499
  pBlockIter = &pStatus->blockIter;
2,336,659✔
1500
  pSupInfo = &pReader->suppInfo;
2,336,659✔
1501
  pDumpInfo = &pReader->status.fBlockDumpInfo;
2,336,659✔
1502

1503
  pBlockData = &pStatus->fileBlockData;
2,336,659✔
1504
  pResBlock = pReader->resBlockInfo.pResBlock;
2,336,659✔
1505
  numOfOutputCols = pSupInfo->numOfCols;
2,336,659✔
1506
  st = taosGetTimestampUs();
2,336,849✔
1507
  asc = ASCENDING_TRAVERSE(pReader->info.order);
2,336,849✔
1508
  step = asc ? 1 : -1;
2,336,849✔
1509

1510
  code = getCurrentBlockInfo(pBlockIter, &pBlockInfo, pReader->idStr);
2,336,849✔
1511
  TSDB_CHECK_CODE(code, lino, _end);
2,336,767!
1512

1513
  blockInfoToRecord(&tmp, pBlockInfo, pSupInfo);
2,336,767✔
1514
  pRecord = &tmp;
2,336,789✔
1515

1516
  // no data exists, return directly.
1517
  if (pBlockData->nRow == 0 || pBlockData->aTSKEY == 0) {
2,336,789!
UNCOV
1518
    tsdbWarn("%p no need to copy since no data in blockData, table uid:%" PRIu64 " has been dropped, %s", pReader,
×
1519
             pBlockInfo->uid, pReader->idStr);
UNCOV
1520
    pResBlock->info.rows = 0;
×
UNCOV
1521
    goto _end;
×
1522
  }
1523

1524
  TSDB_CHECK_CONDITION((pDumpInfo->rowIndex >= 0) && (pDumpInfo->rowIndex < pRecord->numRow), code, lino, _end,
2,336,836!
1525
                       TSDB_CODE_INVALID_PARA);
1526

1527
  // row index of dump info remain the initial position, let's find the appropriate start position.
1528
  if (((pDumpInfo->rowIndex == 0) && asc) || ((pDumpInfo->rowIndex == (pRecord->numRow - 1)) && (!asc))) {
2,336,836!
1529
    if (asc && pReader->info.window.skey <= pRecord->firstKey.key.ts &&
2,336,814✔
1530
        pReader->info.verRange.minVer <= pRecord->minVer) {
2,039,591✔
1531
      // pDumpInfo->rowIndex = 0;
1532
    } else if (!asc && pReader->info.window.ekey >= pRecord->lastKey.key.ts &&
297,225✔
1533
               pReader->info.verRange.maxVer >= pRecord->maxVer) {
296,326!
1534
      // pDumpInfo->rowIndex = pRecord->numRow - 1;
1535
    } else {  // find the appropriate the start position in current block, and set it to be the current rowIndex
1536
      int32_t pos = asc ? pRecord->numRow - 1 : 0;
899✔
1537
      int32_t order = asc ? TSDB_ORDER_DESC : TSDB_ORDER_ASC;
899✔
1538
      int64_t key = asc ? pReader->info.window.skey : pReader->info.window.ekey;
899✔
1539
      pDumpInfo->rowIndex = doBinarySearchKey(pBlockData->aTSKEY, pRecord->numRow, pos, key, order);
899✔
1540

1541
      if (pDumpInfo->rowIndex < 0) {
899!
UNCOV
1542
        tsdbError(
×
1543
            "%p failed to locate the start position in current block, global index:%d, table index:%d, brange:%" PRId64
1544
            "-%" PRId64 ", minVer:%" PRId64 ", maxVer:%" PRId64 " %s",
1545
            pReader, pBlockIter->index, pBlockInfo->tbBlockIdx, pRecord->firstKey.key.ts, pRecord->lastKey.key.ts,
1546
            pRecord->minVer, pRecord->maxVer, pReader->idStr);
1547
        code = TSDB_CODE_INVALID_PARA;
×
1548
        TSDB_CHECK_CODE(code, lino, _end);
×
1549
      }
1550

1551
      pDumpInfo->rowIndex = findFirstPos(pBlockData->aTSKEY, pRecord->numRow, pDumpInfo->rowIndex, (!asc));
899✔
1552

1553
      TSDB_CHECK_CONDITION(
898!
1554
          (pReader->info.verRange.minVer <= pRecord->maxVer && pReader->info.verRange.maxVer >= pRecord->minVer), code,
1555
          lino, _end, TSDB_CODE_INVALID_PARA);
1556

1557
      // find the appropriate start position that satisfies the version requirement.
1558
      if ((pReader->info.verRange.maxVer >= pRecord->minVer && pReader->info.verRange.maxVer < pRecord->maxVer) ||
898!
1559
          (pReader->info.verRange.minVer <= pRecord->maxVer && pReader->info.verRange.minVer > pRecord->minVer)) {
898!
UNCOV
1560
        int32_t i = pDumpInfo->rowIndex;
×
UNCOV
1561
        if (asc) {
×
UNCOV
1562
          for (; i < pRecord->numRow; ++i) {
×
UNCOV
1563
            if (pBlockData->aVersion[i] >= pReader->info.verRange.minVer) {
×
UNCOV
1564
              break;
×
1565
            }
1566
          }
1567
        } else {
1568
          for (; i >= 0; --i) {
×
UNCOV
1569
            if (pBlockData->aVersion[i] <= pReader->info.verRange.maxVer) {
×
UNCOV
1570
              break;
×
1571
            }
1572
          }
1573
        }
1574

UNCOV
1575
        pDumpInfo->rowIndex = i;
×
1576
      }
1577
    }
1578
  }
1579

1580
  // time window check
1581
  int32_t endIndex = getEndPosInDataBlock(pReader, pBlockData, pRecord, pDumpInfo->rowIndex);
2,336,835✔
1582
  if (endIndex == -1) {
2,336,647!
UNCOV
1583
    setBlockAllDumped(pDumpInfo, pReader->info.window.ekey, pReader->info.order);
×
UNCOV
1584
    goto _end;
×
1585
  }
1586

1587
  endIndex += step;
2,336,753✔
1588
  int32_t dumpedRows = asc ? (endIndex - pDumpInfo->rowIndex) : (pDumpInfo->rowIndex - endIndex);
2,336,753✔
1589
  if (dumpedRows > pReader->resBlockInfo.capacity) {  // output buffer check
2,336,753!
UNCOV
1590
    dumpedRows = pReader->resBlockInfo.capacity;
×
1591
  } else if (dumpedRows <= 0) {  // no qualified rows in current data block, quit directly.
2,336,753!
UNCOV
1592
    setBlockAllDumped(pDumpInfo, pReader->info.window.ekey, pReader->info.order);
×
UNCOV
1593
    goto _end;
×
1594
  }
1595

1596
  int32_t i = 0;
2,336,753✔
1597
  int32_t rowIndex = 0;
2,336,753✔
1598

1599
  SColumnInfoData* pColData = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]);
2,336,753✔
1600
  TSDB_CHECK_NULL(pColData, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,336,749!
1601

1602
  if (pSupInfo->colId[i] == PRIMARYKEY_TIMESTAMP_COL_ID) {
2,336,749!
1603
    code = copyPrimaryTsCol(pBlockData, pDumpInfo, pColData, dumpedRows, asc);
2,336,779✔
1604
    TSDB_CHECK_CODE(code, lino, _end);
2,336,675!
1605
    i += 1;
2,336,675✔
1606
  }
1607

1608
  int32_t colIndex = 0;
2,336,645✔
1609
  int32_t num = pBlockData->nColData;
2,336,645✔
1610
  while (i < numOfOutputCols && colIndex < num) {
4,441,339!
1611
    rowIndex = 0;
2,108,634✔
1612

1613
    SColData* pData = tBlockDataGetColDataByIdx(pBlockData, colIndex);
2,108,634✔
1614
    if (pData->cid < pSupInfo->colId[i]) {
2,108,634!
UNCOV
1615
      colIndex += 1;
×
1616
    } else if (pData->cid == pSupInfo->colId[i]) {
2,108,634!
1617
      pColData = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]);
2,108,672✔
1618
      TSDB_CHECK_NULL(pColData, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,108,540!
1619

1620
      if (pData->flag == HAS_NONE || pData->flag == HAS_NULL || pData->flag == (HAS_NULL | HAS_NONE)) {
2,108,540!
1621
        colDataSetNNULL(pColData, 0, dumpedRows);
85,026!
1622
      } else {
1623
        if (IS_MATHABLE_TYPE(pColData->info.type)) {
2,023,514✔
1624
          code = copyNumericCols(pData, pDumpInfo, pColData, dumpedRows, asc);
1,819,380✔
1625
          TSDB_CHECK_CODE(code, lino, _end);
1,819,509!
1626
        } else {  // varchar/nchar type
1627
          for (int32_t j = pDumpInfo->rowIndex; rowIndex < dumpedRows; j += step) {
44,122,172✔
1628
            code = tColDataGetValue(pData, j, &cv);
43,922,013✔
1629
            TSDB_CHECK_CODE(code, lino, _end);
44,411,863!
1630
            code = doCopyColVal(pColData, rowIndex++, i, &cv, pSupInfo);
44,411,863✔
1631
            TSDB_CHECK_CODE(code, lino, _end);
43,918,038!
1632
          }
1633
        }
1634
      }
1635

1636
      colIndex += 1;
2,104,694✔
1637
      i += 1;
2,104,694✔
1638
    } else {  // the specified column does not exist in file block, fill with null data
UNCOV
1639
      pColData = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]);
×
UNCOV
1640
      TSDB_CHECK_NULL(pColData, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
1641

UNCOV
1642
      colDataSetNNULL(pColData, 0, dumpedRows);
×
UNCOV
1643
      i += 1;
×
1644
    }
1645
  }
1646

1647
  // fill the mis-matched columns with null value
1648
  while (i < numOfOutputCols) {
2,332,705!
UNCOV
1649
    pColData = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]);
×
UNCOV
1650
    TSDB_CHECK_NULL(pColData, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
1651

UNCOV
1652
    colDataSetNNULL(pColData, 0, dumpedRows);
×
UNCOV
1653
    i += 1;
×
1654
  }
1655

1656
  pResBlock->info.dataLoad = 1;
2,332,705✔
1657
  pResBlock->info.rows = dumpedRows;
2,332,705✔
1658
  pDumpInfo->rowIndex += step * dumpedRows;
2,332,705✔
1659

1660
  tColRowGetKeyDeepCopy(pBlockData, pDumpInfo->rowIndex - step, pSupInfo->pkSrcSlot, pLastProcKey);
2,332,705!
1661

1662
  // check if current block are all handled
1663
  if (pDumpInfo->rowIndex >= 0 && pDumpInfo->rowIndex < pRecord->numRow) {
2,333,607✔
1664
    int64_t ts = pBlockData->aTSKEY[pDumpInfo->rowIndex];
902✔
1665

1666
    // the remain data has out of query time window, ignore current block
1667
    if (outOfTimeWindow(ts, &pReader->info.window)) {
902!
1668
      setBlockAllDumped(pDumpInfo, ts, pReader->info.order);
902✔
1669
    }
1670
  } else {
1671
    int64_t ts = asc ? pRecord->lastKey.key.ts : pRecord->firstKey.key.ts;
2,331,803✔
1672
    setBlockAllDumped(pDumpInfo, ts, pReader->info.order);
2,331,803✔
1673
  }
1674

1675
  double elapsedTime = (taosGetTimestampUs() - st) / 1000.0;
2,336,729✔
1676
  pReader->cost.blockLoadTime += elapsedTime;
2,336,729✔
1677

1678
  int32_t unDumpedRows = asc ? pRecord->numRow - pDumpInfo->rowIndex : pDumpInfo->rowIndex + 1;
2,336,729✔
1679
  tsdbDebug("%p copy file block to sdatablock, global index:%d, table index:%d, brange:%" PRId64 "-%" PRId64
2,336,729✔
1680
            ", rows:%d, remain:%d, minVer:%" PRId64 ", maxVer:%" PRId64 ", uid:%" PRIu64 " elapsed time:%.2f ms, %s",
1681
            pReader, pBlockIter->index, pBlockInfo->tbBlockIdx, pRecord->firstKey.key.ts, pRecord->lastKey.key.ts,
1682
            dumpedRows, unDumpedRows, pRecord->minVer, pRecord->maxVer, pBlockInfo->uid, elapsedTime, pReader->idStr);
1683

1684
_end:
2,325,339✔
1685
  if (code != TSDB_CODE_SUCCESS) {
2,336,729!
UNCOV
1686
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1687
  }
1688
  return code;
2,336,734✔
1689
}
1690

1691
static FORCE_INLINE STSchema* getTableSchemaImpl(STsdbReader* pReader, uint64_t uid) {
1692
  int32_t code = TSDB_CODE_SUCCESS;
81✔
1693
  int32_t lino = 0;
81✔
1694

1695
  TSDB_CHECK_CONDITION((pReader != NULL) && (pReader->info.pSchema == NULL), code, lino, _end, TSDB_CODE_INVALID_PARA);
81!
1696

1697
  code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->info.suid, uid, -1, &pReader->info.pSchema);
81✔
1698
  if (code != TSDB_CODE_SUCCESS || pReader->info.pSchema == NULL) {
81!
UNCOV
1699
    terrno = code;
×
UNCOV
1700
    tsdbError("failed to get table schema, uid:%" PRIu64 ", it may have been dropped, ver:-1, %s", uid, pReader->idStr);
×
1701
  }
1702
  TSDB_CHECK_CODE(code, lino, _end);
81!
1703
  TSDB_CHECK_NULL(pReader->info.pSchema, code, lino, _end, TSDB_CODE_INTERNAL_ERROR);
81!
1704

1705
  code = tsdbRowMergerInit(&pReader->status.merger, pReader->info.pSchema);
81✔
1706
  TSDB_CHECK_CODE(code, lino, _end);
81!
1707

1708
_end:
81✔
1709
  if (code != TSDB_CODE_SUCCESS) {
81!
UNCOV
1710
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
1711
    terrno = code;
×
UNCOV
1712
    return NULL;
×
1713
  }
1714
  return pReader->info.pSchema;
81✔
1715
}
1716

1717
static int32_t doLoadFileBlockData(STsdbReader* pReader, SDataBlockIter* pBlockIter, SBlockData* pBlockData,
2,374,607✔
1718
                                   uint64_t uid) {
1719
  int32_t             code = TSDB_CODE_SUCCESS;
2,374,607✔
1720
  int32_t             lino = 0;
2,374,607✔
1721
  STSchema*           pSchema = NULL;
2,374,607✔
1722
  SFileDataBlockInfo* pBlockInfo = NULL;
2,374,607✔
1723
  SBlockLoadSuppInfo* pSup = NULL;
2,374,607✔
1724
  SFileBlockDumpInfo* pDumpInfo = NULL;
2,374,607✔
1725
  int64_t             st = 0;
2,374,607✔
1726
  SBrinRecord         tmp;
1727
  SBrinRecord*        pRecord = NULL;
2,374,607✔
1728

1729
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,374,607!
1730
  TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,374,607!
1731

1732
  pSchema = pReader->info.pSchema;
2,374,607✔
1733
  st = taosGetTimestampUs();
2,374,730✔
1734
  pSup = &pReader->suppInfo;
2,374,730✔
1735

1736
  tBlockDataReset(pBlockData);
2,374,730✔
1737

1738
  if (pReader->info.pSchema == NULL) {
2,374,792!
UNCOV
1739
    pSchema = getTableSchemaImpl(pReader, uid);
×
UNCOV
1740
    if (pSchema == NULL) {
×
1741
      tsdbError("%p table uid:%" PRIu64 " failed to get tableschema, code:%s, %s", pReader, uid, tstrerror(code),
×
1742
                pReader->idStr);
UNCOV
1743
      TSDB_CHECK_NULL(pSchema, code, lino, _end, terrno);
×
1744
    }
1745
  }
1746

1747
  code = getCurrentBlockInfo(pBlockIter, &pBlockInfo, pReader->idStr);
2,374,792✔
1748
  TSDB_CHECK_CODE(code, lino, _end);
2,374,799!
1749

1750
  pDumpInfo = &pReader->status.fBlockDumpInfo;
2,374,799✔
1751

1752
  blockInfoToRecord(&tmp, pBlockInfo, pSup);
2,374,799✔
1753
  pRecord = &tmp;
2,374,954✔
1754
  code = tsdbDataFileReadBlockDataByColumn(pReader->pFileReader, pRecord, pBlockData, pSchema, &pSup->colId[1],
2,374,954✔
1755
                                           pSup->numOfCols - 1);
2,374,954✔
1756
  if (code != TSDB_CODE_SUCCESS) {
2,374,936!
UNCOV
1757
    tsdbError("%p error occurs in loading file block, global index:%d, table index:%d, brange:%" PRId64 "-%" PRId64
×
1758
              ", rows:%d, code:%s %s",
1759
              pReader, pBlockIter->index, pBlockInfo->tbBlockIdx, pBlockInfo->firstKey, pBlockInfo->lastKey,
1760
              pBlockInfo->numRow, tstrerror(code), pReader->idStr);
UNCOV
1761
    TSDB_CHECK_CODE(code, lino, _end);
×
1762
  }
1763

1764
  double elapsedTime = (taosGetTimestampUs() - st) / 1000.0;
2,374,904✔
1765

1766
  tsdbDebug("%p load file block into buffer, global index:%d, index in table block list:%d, brange:%" PRId64 "-%" PRId64
2,374,904✔
1767
            ", rows:%d, minVer:%" PRId64 ", maxVer:%" PRId64 ", elapsed time:%.2f ms, %s",
1768
            pReader, pBlockIter->index, pBlockInfo->tbBlockIdx, pRecord->firstKey.key.ts, pRecord->lastKey.key.ts,
1769
            pRecord->numRow, pRecord->minVer, pRecord->maxVer, elapsedTime, pReader->idStr);
1770

1771
  pReader->cost.blockLoadTime += elapsedTime;
2,374,969✔
1772
  pDumpInfo->allDumped = false;
2,374,969✔
1773

1774
_end:
2,374,969✔
1775
  if (code != TSDB_CODE_SUCCESS) {
2,374,969!
UNCOV
1776
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1777
  }
1778
  return code;
2,374,941✔
1779
}
1780

1781
/**
1782
 * This is an two rectangles overlap cases.
1783
 */
1784
static int32_t dataBlockPartiallyRequired(STimeWindow* pWindow, SVersionRange* pVerRange, SFileDataBlockInfo* pBlock) {
5,280,632✔
1785
  return (pWindow->ekey < pBlock->lastKey && pWindow->ekey >= pBlock->firstKey) ||
63,850!
1786
         (pWindow->skey > pBlock->firstKey && pWindow->skey <= pBlock->lastKey) ||
5,216,782!
1787
         (pVerRange->minVer > pBlock->minVer && pVerRange->minVer <= pBlock->maxVer) ||
15,776,676!
1788
         (pVerRange->maxVer < pBlock->maxVer && pVerRange->maxVer >= pBlock->minVer);
5,215,412!
1789
}
1790

1791
static int32_t getNeighborBlockOfTable(SDataBlockIter* pBlockIter, SFileDataBlockInfo* pBlockInfo,
5,319,001✔
1792
                                       STableBlockScanInfo* pScanInfo, int32_t* nextIndex, int32_t order,
1793
                                       SBrinRecord* pRecord, SBlockLoadSuppInfo* pSupInfo, bool* res) {
1794
  int32_t             code = TSDB_CODE_SUCCESS;
5,319,001✔
1795
  int32_t             lino = 0;
5,319,001✔
1796
  bool                asc = false;
5,319,001✔
1797
  int32_t             step = 0;
5,319,001✔
1798
  STableDataBlockIdx* pTableDataBlockIdx = NULL;
5,319,001✔
1799
  SFileDataBlockInfo* p = NULL;
5,319,001✔
1800

1801
  TSDB_CHECK_NULL(pBlockInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,319,001!
1802
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,319,001!
1803
  TSDB_CHECK_NULL(res, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,319,001!
1804

1805
  *res = false;
5,319,001✔
1806
  asc = ASCENDING_TRAVERSE(order);
5,319,001✔
1807
  step = asc ? 1 : -1;
5,319,001✔
1808

1809
  if (asc && pBlockInfo->tbBlockIdx >= taosArrayGetSize(pScanInfo->pBlockIdxList) - 1) {
5,319,001✔
1810
    *res = false;
423,074✔
1811
  } else if (!asc && pBlockInfo->tbBlockIdx == 0) {
4,895,926✔
1812
    *res = false;
39,046✔
1813
  } else {
1814
    TSDB_CHECK_NULL(pBlockIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,856,880!
1815
    TSDB_CHECK_NULL(nextIndex, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,856,880!
1816
    TSDB_CHECK_NULL(pRecord, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,856,880!
1817
    TSDB_CHECK_NULL(pSupInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,856,880!
1818

1819
    pTableDataBlockIdx = taosArrayGet(pScanInfo->pBlockIdxList, pBlockInfo->tbBlockIdx + step);
4,856,880✔
1820
    TSDB_CHECK_NULL(pTableDataBlockIdx, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,856,993!
1821

1822
    p = taosArrayGet(pBlockIter->blockList, pTableDataBlockIdx->globalIndex);
4,856,993✔
1823
    TSDB_CHECK_NULL(p, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,856,991!
1824

1825
    blockInfoToRecord(pRecord, p, pSupInfo);
4,856,991✔
1826

1827
    *nextIndex = pBlockInfo->tbBlockIdx + step;
4,856,993✔
1828
    *res = true;
4,856,993✔
1829
  }
1830

1831
_end:
5,319,113✔
1832
  if (code != TSDB_CODE_SUCCESS) {
5,319,113!
UNCOV
1833
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1834
  }
1835
  return code;
5,319,031✔
1836
}
1837

1838
static int32_t setFileBlockActiveInBlockIter(STsdbReader* pReader, SDataBlockIter* pBlockIter, int32_t index,
5✔
1839
                                             int32_t step) {
1840
  int32_t              code = TSDB_CODE_SUCCESS;
5✔
1841
  int32_t              lino = 0;
5✔
1842
  const void*          p = NULL;
5✔
1843
  SFileDataBlockInfo   fblock;
1844
  SFileDataBlockInfo*  pBlockInfo = NULL;
5✔
1845
  STableBlockScanInfo* pBlockScanInfo = NULL;
5✔
1846
  STableDataBlockIdx*  pTableDataBlockIdx = NULL;
5✔
1847

1848
  TSDB_CHECK_NULL(pBlockIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
5!
1849
  TSDB_CHECK_CONDITION((index >= 0) && (index < pBlockIter->numOfBlocks), code, lino, _end, TSDB_CODE_INVALID_PARA);
5!
1850

1851
  p = taosArrayGet(pBlockIter->blockList, index);
5✔
1852
  TSDB_CHECK_NULL(p, code, lino, _end, TSDB_CODE_INVALID_PARA);
5!
1853

1854
  fblock = *(SFileDataBlockInfo*)p;
5✔
1855
  pBlockIter->index += step;
5✔
1856

1857
  if (index != pBlockIter->index) {
5!
1858
    if (index > pBlockIter->index) {
×
1859
      for (int32_t i = index - 1; i >= pBlockIter->index; --i) {
×
1860
        pBlockInfo = taosArrayGet(pBlockIter->blockList, i);
×
UNCOV
1861
        TSDB_CHECK_NULL(pBlockInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
1862

1863
        code = getTableBlockScanInfo(pReader->status.pTableMap, pBlockInfo->uid, &pBlockScanInfo, pReader->idStr);
×
UNCOV
1864
        TSDB_CHECK_CODE(code, lino, _end);
×
1865

1866
        pTableDataBlockIdx = taosArrayGet(pBlockScanInfo->pBlockIdxList, pBlockInfo->tbBlockIdx);
×
UNCOV
1867
        TSDB_CHECK_NULL(pTableDataBlockIdx, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
1868

1869
        pTableDataBlockIdx->globalIndex = i + 1;
×
1870

UNCOV
1871
        taosArraySet(pBlockIter->blockList, i + 1, pBlockInfo);
×
1872
      }
1873
    } else if (index < pBlockIter->index) {
×
1874
      for (int32_t i = index + 1; i <= pBlockIter->index; ++i) {
×
1875
        pBlockInfo = taosArrayGet(pBlockIter->blockList, i);
×
1876
        TSDB_CHECK_NULL(pBlockInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
1877

1878
        code = getTableBlockScanInfo(pReader->status.pTableMap, pBlockInfo->uid, &pBlockScanInfo, pReader->idStr);
×
1879
        TSDB_CHECK_CODE(code, lino, _end);
×
1880

1881
        pTableDataBlockIdx = taosArrayGet(pBlockScanInfo->pBlockIdxList, pBlockInfo->tbBlockIdx);
×
UNCOV
1882
        TSDB_CHECK_NULL(pTableDataBlockIdx, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
1883

UNCOV
1884
        pTableDataBlockIdx->globalIndex = i - 1;
×
UNCOV
1885
        taosArraySet(pBlockIter->blockList, i - 1, pBlockInfo);
×
1886
      }
1887
    }
1888

UNCOV
1889
    taosArraySet(pBlockIter->blockList, pBlockIter->index, &fblock);
×
UNCOV
1890
    pBlockScanInfo = NULL;
×
UNCOV
1891
    code = getTableBlockScanInfo(pReader->status.pTableMap, fblock.uid, &pBlockScanInfo, pReader->idStr);
×
UNCOV
1892
    TSDB_CHECK_CODE(code, lino, _end);
×
1893

UNCOV
1894
    pTableDataBlockIdx = taosArrayGet(pBlockScanInfo->pBlockIdxList, fblock.tbBlockIdx);
×
UNCOV
1895
    TSDB_CHECK_NULL(pTableDataBlockIdx, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
1896

UNCOV
1897
    pTableDataBlockIdx->globalIndex = pBlockIter->index;
×
1898
  }
1899

1900
_end:
5✔
1901
  if (code != TSDB_CODE_SUCCESS) {
5!
UNCOV
1902
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1903
  }
1904
  return code;
5✔
1905
}
1906

1907
// todo: this attribute could be acquired during extractin the global ordered block list.
1908
static bool overlapWithNeighborBlock2(SFileDataBlockInfo* pBlock, SBrinRecord* pRec, int32_t order, int32_t pkType,
4,856,990✔
1909
                                      int32_t numOfPk) {
1910
  // it is the last block in current file, no chance to overlap with neighbor blocks.
1911
  if (ASCENDING_TRAVERSE(order)) {
4,856,990✔
1912
    if (pBlock->lastKey == pRec->firstKey.key.ts) {
4,560,275✔
1913
      if (numOfPk > 0) {
165✔
1914
        SValue v1 = {.type = pkType};
150✔
1915
        if (IS_VAR_DATA_TYPE(pkType)) {
150!
1916
          v1.pData = (uint8_t*)varDataVal(pBlock->lastPk.pData), v1.nData = varDataLen(pBlock->lastPk.pData);
×
1917
        } else {
1918
          VALUE_SET_TRIVIAL_DATUM(&v1, pBlock->lastPk.val);
150✔
1919
        }
1920
        return (tValueCompare(&v1, &pRec->firstKey.key.pks[0]) == 0);
150✔
1921
      } else {  // no pk
1922
        return true;
15✔
1923
      }
1924
    } else {
1925
      return false;
4,560,110✔
1926
    }
1927
  } else {
1928
    if (pBlock->firstKey == pRec->lastKey.key.ts) {
296,715✔
1929
      if (numOfPk > 0) {
75!
1930
        SValue v1 = {.type = pkType};
75✔
1931
        if (IS_VAR_DATA_TYPE(pkType)) {
75!
UNCOV
1932
          v1.pData = (uint8_t*)varDataVal(pBlock->firstPk.pData), v1.nData = varDataLen(pBlock->firstPk.pData);
×
1933
        } else {
1934
          VALUE_SET_TRIVIAL_DATUM(&v1, pBlock->firstPk.val);
75✔
1935
        }
1936
        return (tValueCompare(&v1, &pRec->lastKey.key.pks[0]) == 0);
75✔
1937
      } else {  // no pk
UNCOV
1938
        return true;
×
1939
      }
1940
    } else {
1941
      return false;
296,640✔
1942
    }
1943
  }
1944
}
1945

1946
static int64_t getBoarderKeyInFiles(SFileDataBlockInfo* pBlock, STableBlockScanInfo* pScanInfo, int32_t order) {
5,200,717✔
1947
  bool ascScan = ASCENDING_TRAVERSE(order);
5,200,717✔
1948

1949
  int64_t key = 0;
5,200,717✔
1950
  if (pScanInfo->sttKeyInfo.status == STT_FILE_HAS_DATA) {
5,200,717✔
1951
    int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey.ts;
2,440,801✔
1952
    key = ascScan ? TMIN(pBlock->firstKey, keyInStt) : TMAX(pBlock->lastKey, keyInStt);
2,440,801✔
1953
  } else {
1954
    key = ascScan ? pBlock->firstKey : pBlock->lastKey;
2,759,916✔
1955
  }
1956

1957
  return key;
5,200,717✔
1958
}
1959

1960
static bool bufferDataInFileBlockGap(TSDBKEY keyInBuf, SFileDataBlockInfo* pBlock, STableBlockScanInfo* pScanInfo,
5,200,543✔
1961
                                     int32_t order) {
1962
  bool    ascScan = ASCENDING_TRAVERSE(order);
5,200,543✔
1963
  int64_t key = getBoarderKeyInFiles(pBlock, pScanInfo, order);
5,200,543✔
1964

1965
  return (ascScan && (keyInBuf.ts != TSKEY_INITIAL_VAL && keyInBuf.ts < key)) ||
10,401,198!
1966
         (!ascScan && (keyInBuf.ts != TSKEY_INITIAL_VAL && keyInBuf.ts > key));
5,200,599!
1967
}
1968

1969
static bool keyOverlapFileBlock(TSDBKEY key, SFileDataBlockInfo* pBlock, SVersionRange* pVerRange) {
5,280,617✔
1970
  return (key.ts >= pBlock->firstKey && key.ts <= pBlock->lastKey) && (pBlock->maxVer >= pVerRange->minVer) &&
5,325,213!
1971
         (pBlock->minVer <= pVerRange->maxVer);
44,596!
1972
}
1973

1974
static int32_t getBlockToLoadInfo(SDataBlockToLoadInfo* pInfo, SFileDataBlockInfo* pBlockInfo,
5,280,631✔
1975
                                  STableBlockScanInfo* pScanInfo, TSDBKEY keyInBuf, STsdbReader* pReader) {
1976
  int32_t             code = TSDB_CODE_SUCCESS;
5,280,631✔
1977
  int32_t             lino = 0;
5,280,631✔
1978
  SBrinRecord         rec = {0};
5,280,631✔
1979
  int32_t             neighborIndex = 0;
5,280,631✔
1980
  int32_t             order = 0;
5,280,631✔
1981
  SBlockLoadSuppInfo* pSupInfo = NULL;
5,280,631✔
1982
  SBrinRecord         pRecord;
1983
  bool                hasNeighbor = false;
5,280,631✔
1984

1985
  TSDB_CHECK_NULL(pInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,280,631!
1986
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,280,631!
1987

1988
  order = pReader->info.order;
5,280,631✔
1989
  pSupInfo = &pReader->suppInfo;
5,280,631✔
1990

1991
  code = getNeighborBlockOfTable(&pReader->status.blockIter, pBlockInfo, pScanInfo, &neighborIndex, order, &rec,
5,280,631✔
1992
                                 pSupInfo, &hasNeighbor);
1993
  TSDB_CHECK_CODE(code, lino, _end);
5,280,754!
1994

1995
  // overlap with neighbor
1996
  if (hasNeighbor) {
5,280,754✔
1997
    pInfo->overlapWithNeighborBlock =
4,853,956✔
1998
        overlapWithNeighborBlock2(pBlockInfo, &rec, order, pSupInfo->pk.type, pSupInfo->numOfPks);
4,853,960✔
1999
  }
2000

2001
  blockInfoToRecord(&pRecord, pBlockInfo, pSupInfo);
5,280,750✔
2002

2003
  // has duplicated ts of different version in this block
2004
  pInfo->hasDupTs = (pBlockInfo->numRow > pBlockInfo->count) || (pBlockInfo->count <= 0);
5,280,721!
2005
  pInfo->overlapWithDelInfo = overlapWithDelSkyline(pScanInfo, &pRecord, order);
5,280,721✔
2006

2007
  // todo handle the primary key overlap case
2008
  if (pScanInfo->sttKeyInfo.status == STT_FILE_HAS_DATA) {
5,280,659✔
2009
    int64_t nextProcKeyInStt = pScanInfo->sttKeyInfo.nextProcKey.ts;
2,442,777✔
2010
    pInfo->overlapWithSttBlock = !(pBlockInfo->lastKey < nextProcKeyInStt || pBlockInfo->firstKey > nextProcKeyInStt);
2,442,777!
2011
  }
2012

2013
  pInfo->moreThanCapcity = pBlockInfo->numRow > pReader->resBlockInfo.capacity;
5,280,659✔
2014
  pInfo->partiallyRequired = dataBlockPartiallyRequired(&pReader->info.window, &pReader->info.verRange, pBlockInfo);
5,280,659✔
2015
  pInfo->overlapWithKeyInBuf = keyOverlapFileBlock(keyInBuf, pBlockInfo, &pReader->info.verRange);
5,280,646✔
2016

2017
_end:
5,280,636✔
2018
  if (code != TSDB_CODE_SUCCESS) {
5,280,636!
UNCOV
2019
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2020
  }
2021
  return code;
5,280,650✔
2022
}
2023

2024
// 1. the version of all rows should be less than the endVersion
2025
// 2. current block should not overlap with next neighbor block
2026
// 3. current timestamp should not be overlap with each other
2027
// 4. output buffer should be large enough to hold all rows in current block
2028
// 5. delete info should not overlap with current block data
2029
// 6. current block should not contain the duplicated ts
2030
static int32_t fileBlockShouldLoad(STsdbReader* pReader, SFileDataBlockInfo* pBlockInfo, STableBlockScanInfo* pScanInfo,
5,240,609✔
2031
                                   TSDBKEY keyInBuf, bool* load) {
2032
  int32_t              code = TSDB_CODE_SUCCESS;
5,240,609✔
2033
  int32_t              lino = 0;
5,240,609✔
2034
  SDataBlockToLoadInfo info = {0};
5,240,609✔
2035

2036
  TSDB_CHECK_NULL(load, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,240,609!
2037

2038
  *load = false;
5,240,609✔
2039
  code = getBlockToLoadInfo(&info, pBlockInfo, pScanInfo, keyInBuf, pReader);
5,240,609✔
2040
  TSDB_CHECK_CODE(code, lino, _end);
5,240,644!
2041

2042
  *load = (info.overlapWithNeighborBlock || info.hasDupTs || info.partiallyRequired || info.overlapWithKeyInBuf ||
5,240,569!
2043
           info.moreThanCapcity || info.overlapWithDelInfo || info.overlapWithSttBlock);
10,481,213!
2044

2045
  // log the reason why load the datablock for profile
2046
  if (*load) {
5,240,644✔
2047
    tsdbDebug("%p uid:%" PRIu64
40,024✔
2048
              " need to load the datablock, overlapneighbor:%d, hasDup:%d, partiallyRequired:%d, "
2049
              "overlapWithKey:%d, greaterThanBuf:%d, overlapWithDel:%d, overlapWithSttBlock:%d, %s",
2050
              pReader, pBlockInfo->uid, info.overlapWithNeighborBlock, info.hasDupTs, info.partiallyRequired,
2051
              info.overlapWithKeyInBuf, info.moreThanCapcity, info.overlapWithDelInfo, info.overlapWithSttBlock,
2052
              pReader->idStr);
2053
  }
2054

2055
_end:
5,240,626✔
2056
  if (code != TSDB_CODE_SUCCESS) {
5,240,644!
UNCOV
2057
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2058
  }
2059
  return code;
5,240,670✔
2060
}
2061

2062
static int32_t isCleanFileDataBlock(STsdbReader* pReader, SFileDataBlockInfo* pBlockInfo,
40,028✔
2063
                                    STableBlockScanInfo* pScanInfo, TSDBKEY keyInBuf, bool* res) {
2064
  int32_t              code = TSDB_CODE_SUCCESS;
40,028✔
2065
  int32_t              lino = 0;
40,028✔
2066
  SDataBlockToLoadInfo info = {0};
40,028✔
2067

2068
  TSDB_CHECK_NULL(res, code, lino, _end, TSDB_CODE_INVALID_PARA);
40,028!
2069

2070
  *res = false;
40,028✔
2071
  code = getBlockToLoadInfo(&info, pBlockInfo, pScanInfo, keyInBuf, pReader);
40,028✔
2072
  TSDB_CHECK_CODE(code, lino, _end);
40,028!
2073

2074
  *res = !(info.overlapWithNeighborBlock || info.hasDupTs || info.overlapWithKeyInBuf || info.overlapWithDelInfo ||
42,805!
2075
           info.overlapWithSttBlock);
2,777✔
2076

2077
_end:
40,028✔
2078
  if (code != TSDB_CODE_SUCCESS) {
40,028!
UNCOV
2079
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2080
  }
2081
  return code;
40,030✔
2082
}
2083

2084
static int32_t initRowMergeIfNeeded(STsdbReader* pReader, int64_t uid) {
515,482,833✔
2085
  int32_t     code = TSDB_CODE_SUCCESS;
515,482,833✔
2086
  int32_t     lino = 0;
515,482,833✔
2087
  SRowMerger* pMerger = NULL;
515,482,833✔
2088
  STSchema*   ps = NULL;
515,482,833✔
2089

2090
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
515,482,833!
2091

2092
  pMerger = &pReader->status.merger;
515,482,833✔
2093

2094
  if (pMerger->pArray == NULL) {
515,482,833✔
2095
    ps = getTableSchemaImpl(pReader, uid);
81!
2096
    TSDB_CHECK_NULL(ps, code, lino, _end, terrno);
81!
2097
  }
2098

2099
_end:
515,482,833✔
2100
  if (code != TSDB_CODE_SUCCESS) {
515,482,833!
UNCOV
2101
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2102
  }
2103
  return code;
515,355,078✔
2104
}
2105

2106
static int32_t buildDataBlockFromBuf(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo, int64_t endKey) {
17,880,549✔
2107
  int32_t      code = TSDB_CODE_SUCCESS;
17,880,549✔
2108
  int32_t      lino = 0;
17,880,549✔
2109
  int64_t      st = 0;
17,880,549✔
2110
  SSDataBlock* pBlock = NULL;
17,880,549✔
2111

2112
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
17,880,549!
2113

2114
  if (!(pBlockScanInfo->iiter.hasVal || pBlockScanInfo->iter.hasVal)) {
17,880,549✔
2115
    goto _end;
12,874,012✔
2116
  }
2117

2118
  code = initRowMergeIfNeeded(pReader, pBlockScanInfo->uid);
5,006,537✔
2119
  TSDB_CHECK_CODE(code, lino, _end);
5,009,723!
2120

2121
  st = taosGetTimestampUs();
5,010,044✔
2122
  pBlock = pReader->resBlockInfo.pResBlock;
5,010,044✔
2123
  code = buildDataBlockFromBufImpl(pBlockScanInfo, endKey, pReader->resBlockInfo.capacity, pReader);
5,010,044✔
2124
  TSDB_CHECK_CODE(code, lino, _end);
5,010,139✔
2125

2126
  double el = (taosGetTimestampUs() - st) / 1000.0;
5,010,427✔
2127
  updateComposedBlockInfo(pReader, el, pBlockScanInfo);
5,010,427✔
2128

2129
  tsdbDebug("%p build data block from cache completed, elapsed time:%.2f ms, numOfRows:%" PRId64 ", brange:%" PRId64
5,010,379✔
2130
            " - %" PRId64 ", uid:%" PRIu64 ",  %s",
2131
            pReader, el, pBlock->info.rows, pBlock->info.window.skey, pBlock->info.window.ekey, pBlockScanInfo->uid,
2132
            pReader->idStr);
2133

2134
  pReader->cost.buildmemBlock += el;
5,010,390✔
2135

2136
_end:
17,884,406✔
2137
  if (code != TSDB_CODE_SUCCESS) {
17,884,406✔
2138
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
2139
  }
2140
  return code;
17,882,266✔
2141
}
2142

2143
static int32_t tryCopyDistinctRowFromFileBlock(STsdbReader* pReader, SBlockData* pBlockData, SRowKey* pKey,
2,541,784✔
2144
                                               SFileBlockDumpInfo* pDumpInfo, bool* copied) {
2145
  // opt version
2146
  // 1. it is not a border point
2147
  // 2. the direct next point is not an duplicated timestamp
2148
  int32_t code = TSDB_CODE_SUCCESS;
2,541,784✔
2149
  int32_t lino = 0;
2,541,784✔
2150
  bool    asc = false;
2,541,784✔
2151

2152
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,541,784!
2153
  TSDB_CHECK_NULL(pDumpInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,541,784!
2154
  TSDB_CHECK_NULL(copied, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,541,784!
2155

2156
  *copied = false;
2,541,784✔
2157
  asc = (pReader->info.order == TSDB_ORDER_ASC);
2,541,784✔
2158
  if ((pDumpInfo->rowIndex < pDumpInfo->totalRows - 1 && asc) || (pDumpInfo->rowIndex > 0 && (!asc))) {
2,541,784!
2159
    int32_t step = ASCENDING_TRAVERSE(pReader->info.order) ? 1 : -1;
2,541,012✔
2160

2161
    SRowKey nextRowKey;
2162
    TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,541,012!
2163
    tColRowGetKey(pBlockData, pDumpInfo->rowIndex + step, &nextRowKey);
2,541,012✔
2164

2165
    if (pkCompEx(pKey, &nextRowKey) != 0) {  // merge is not needed
2,542,054✔
2166
      code = doAppendRowFromFileBlock(pReader->resBlockInfo.pResBlock, pReader, pBlockData, pDumpInfo->rowIndex);
2,536,954✔
2167
      TSDB_CHECK_CODE(code, lino, _end);
2,533,666!
2168
      pDumpInfo->rowIndex += step;
2,533,666✔
2169
      *copied = true;
2,533,666✔
2170
    }
2171
  }
2172

2173
_end:
772✔
2174
  if (code != TSDB_CODE_SUCCESS) {
2,539,538!
UNCOV
2175
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2176
  }
2177
  return code;
2,531,841✔
2178
}
2179

2180
static int32_t nextRowFromSttBlocks(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo, int32_t pkSrcSlot,
381,637,825✔
2181
                                    SVersionRange* pVerRange) {
2182
  int32_t  code = TSDB_CODE_SUCCESS;
381,637,825✔
2183
  int32_t  lino = 0;
381,637,825✔
2184
  int32_t  order = 0;
381,637,825✔
2185
  int32_t  step = 0;
381,637,825✔
2186
  SRowKey* pNextProc = NULL;
381,637,825✔
2187

2188
  TSDB_CHECK_NULL(pSttBlockReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
381,637,825!
2189
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
381,637,825!
2190

2191
  order = pSttBlockReader->order;
381,637,825✔
2192
  step = ASCENDING_TRAVERSE(order) ? 1 : -1;
381,637,825✔
2193
  pNextProc = &pScanInfo->sttKeyInfo.nextProcKey;
381,637,825✔
2194

2195
  while (1) {
2,307,563✔
2196
    bool hasVal = false;
383,945,388✔
2197
    code = tMergeTreeNext(&pSttBlockReader->mergeTree, &hasVal);
383,945,388✔
2198
    if (code) {
384,127,552!
UNCOV
2199
      tsdbError("failed to iter the next row in stt-file merge tree, code:%s, %s", tstrerror(code),
×
2200
                pSttBlockReader->mergeTree.idStr);
2201
      TSDB_CHECK_CODE(code, lino, _end);
380,758,558!
2202
    }
2203

2204
    if (!hasVal) {  // the next value will be the accessed key in stt
384,226,698✔
2205
      pScanInfo->sttKeyInfo.status = STT_FILE_NO_DATA;
11,581,415✔
2206

2207
      // next file, the timestamps in the next file must be greater than those in current
2208
      pNextProc->ts += step;
11,581,415✔
2209
      if (pSttBlockReader->numOfPks > 0) {
11,581,415✔
2210
        if (IS_NUMERIC_TYPE(pNextProc->pks[0].type)) {
206,060!
2211
          VALUE_SET_TRIVIAL_DATUM(pNextProc->pks, INT64_MAX);
206,060✔
2212
        } else {
UNCOV
2213
          memset(pNextProc->pks[0].pData, 0, pNextProc->pks[0].nData);
×
2214
        }
2215
      }
2216
      goto _end;
11,581,415✔
2217
    }
2218

2219
    TSDBROW* pRow = tMergeTreeGetRow(&pSttBlockReader->mergeTree);
372,645,283✔
2220
    int64_t  key = pRow->pBlockData->aTSKEY[pRow->iRow];
372,645,283✔
2221
    int64_t  ver = pRow->pBlockData->aVersion[pRow->iRow];
372,645,283✔
2222

2223
    if (pSttBlockReader->numOfPks == 0) {
372,645,283✔
2224
      pSttBlockReader->currentKey.ts = key;
347,215,496✔
2225
    } else {
2226
      tColRowGetKeyDeepCopy(pRow->pBlockData, pRow->iRow, pkSrcSlot, &pSttBlockReader->currentKey);
25,429,787!
2227
    }
2228

2229
    tColRowGetKeyDeepCopy(pRow->pBlockData, pRow->iRow, pkSrcSlot, pNextProc);
372,573,272!
2230

2231
    if (pScanInfo->delSkyline != NULL && TARRAY_SIZE(pScanInfo->delSkyline) > 0) {
374,881,604✔
2232
      bool dropped = false;
22,681,979✔
2233
      code = hasBeenDropped(pScanInfo->delSkyline, &pScanInfo->sttBlockDelIndex, key, ver, order, pVerRange,
22,681,979✔
2234
                            pSttBlockReader->numOfPks > 0, &dropped);
22,681,979✔
2235
      TSDB_CHECK_CODE(code, lino, _end);
40,679,433!
2236
      if (!dropped) {
21,493,498✔
2237
        pScanInfo->sttKeyInfo.status = STT_FILE_HAS_DATA;
19,185,935✔
2238
        goto _end;
19,185,935✔
2239
      }
2240
    } else {
2241
      pScanInfo->sttKeyInfo.status = STT_FILE_HAS_DATA;
349,892,062✔
2242
      goto _end;
349,892,062✔
2243
    }
2244
  }
2245

2246
_end:
380,659,412✔
2247
  if (code != TSDB_CODE_SUCCESS) {
380,659,412!
UNCOV
2248
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2249
  }
2250
  return code;
380,424,517✔
2251
}
2252

2253
static void doPinSttBlock(SSttBlockReader* pSttBlockReader) { tMergeTreePinSttBlock(&pSttBlockReader->mergeTree); }
229,010,165✔
2254

2255
static void doUnpinSttBlock(SSttBlockReader* pSttBlockReader) { tMergeTreeUnpinSttBlock(&pSttBlockReader->mergeTree); }
225,810,142✔
2256

2257
static int32_t tryCopyDistinctRowFromSttBlock(TSDBROW* fRow, SSttBlockReader* pSttBlockReader,
229,027,202✔
2258
                                              STableBlockScanInfo* pScanInfo, SRowKey* pSttKey, STsdbReader* pReader,
2259
                                              bool* copied) {
2260
  int32_t  code = TSDB_CODE_SUCCESS;
229,027,202✔
2261
  int32_t  lino = 0;
229,027,202✔
2262
  SRowKey* pNext = NULL;
229,027,202✔
2263

2264
  TSDB_CHECK_NULL(pSttBlockReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
229,027,202!
2265
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
229,027,202!
2266
  TSDB_CHECK_NULL(copied, code, lino, _end, TSDB_CODE_INVALID_PARA);
229,027,202!
2267

2268
  *copied = false;
229,027,202✔
2269

2270
  // avoid the fetch next row replace the referenced stt block in buffer
2271
  doPinSttBlock(pSttBlockReader);
229,027,202✔
2272
  code = nextRowFromSttBlocks(pSttBlockReader, pScanInfo, pReader->suppInfo.pkSrcSlot, &pReader->info.verRange);
228,248,111✔
2273
  doUnpinSttBlock(pSttBlockReader);
226,656,949✔
2274
  TSDB_CHECK_CODE(code, lino, _end);
224,428,350!
2275

2276
  if (hasDataInSttBlock(pScanInfo)) {
224,428,350✔
2277
    pNext = getCurrentKeyInSttBlock(pSttBlockReader);
223,196,294!
2278
    if (pkCompEx(pSttKey, pNext) != 0) {
223,975,154✔
2279
      code = doAppendRowFromFileBlock(pReader->resBlockInfo.pResBlock, pReader, fRow->pBlockData, fRow->iRow);
222,038,841✔
2280
      *copied = (code == TSDB_CODE_SUCCESS);
225,153,676✔
2281
      TSDB_CHECK_CODE(code, lino, _end);
225,153,676!
2282
    }
2283
  } else {
2284
    code = doAppendRowFromFileBlock(pReader->resBlockInfo.pResBlock, pReader, fRow->pBlockData, fRow->iRow);
1,111,806✔
2285
    *copied = (code == TSDB_CODE_SUCCESS);
1,248,110✔
2286
    TSDB_CHECK_CODE(code, lino, _end);
1,248,110!
2287
  }
2288

2289
_end:
1,248,110✔
2290
  if (code != TSDB_CODE_SUCCESS) {
228,338,099!
2291
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2292
  }
2293
  return code;
227,453,759✔
2294
}
2295

2296
static FORCE_INLINE STSchema* doGetSchemaForTSRow(int32_t sversion, STsdbReader* pReader, uint64_t uid) {
2297
  int32_t   code = TSDB_CODE_SUCCESS;
1,551,004,159✔
2298
  int32_t   lino = 0;
1,551,004,159✔
2299
  STSchema* ps = NULL;
1,551,004,159✔
2300
  void**    p = NULL;
1,551,004,159✔
2301

2302
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
278,099,075!
2303

2304
  // always set the newest schema version in pReader->info.pSchema
2305
  if (pReader->info.pSchema == NULL) {
1,551,004,159!
UNCOV
2306
    ps = getTableSchemaImpl(pReader, uid);
×
UNCOV
2307
    TSDB_CHECK_NULL(ps, code, lino, _end, terrno);
×
2308
  }
2309

2310
  if (pReader->info.pSchema && sversion == pReader->info.pSchema->version) {
1,551,004,159!
2311
    ps = pReader->info.pSchema;
1,539,971,562✔
2312
    goto _end;
1,539,971,562✔
2313
  }
2314

2315
  p = tSimpleHashGet(pReader->pSchemaMap, &sversion, sizeof(sversion));
11,032,597✔
2316
  if (p != NULL) {
24,649,578!
2317
    ps = *(STSchema**)p;
24,570,373✔
2318
    goto _end;
24,570,373✔
2319
  }
2320

2321
  code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->info.suid, uid, sversion, &ps);
79,205✔
2322
  TSDB_CHECK_CODE(code, lino, _end);
85,070!
2323

2324
  code = tSimpleHashPut(pReader->pSchemaMap, &sversion, sizeof(sversion), &ps, POINTER_BYTES);
85,070✔
2325
  TSDB_CHECK_CODE(code, lino, _end);
85,067!
2326

2327
_end:
85,067✔
2328
  if (code != TSDB_CODE_SUCCESS) {
1,564,627,002!
UNCOV
2329
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
2330
    terrno = code;
×
UNCOV
2331
    return NULL;
×
2332
  }
2333
  return ps;
1,564,627,002✔
2334
}
2335

2336
static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo, TSDBROW* pRow,
270,942,111✔
2337
                                     SIterInfo* pIter, SSttBlockReader* pSttBlockReader) {
2338
  int32_t             code = TSDB_CODE_SUCCESS;
270,942,111✔
2339
  int32_t             lino = 0;
270,942,111✔
2340
  SRowMerger*         pMerger = NULL;
270,942,111✔
2341
  SRow*               pTSRow = NULL;
270,942,111✔
2342
  SBlockData*         pBlockData = NULL;
270,942,111✔
2343
  SFileBlockDumpInfo* pDumpInfo = NULL;
270,942,111✔
2344
  SRowKey*            pSttKey = NULL;
270,942,111✔
2345
  int32_t             pkSrcSlot = 0;
270,942,111✔
2346
  SRowKey             k = {0};
270,942,111✔
2347
  STSchema*           pSchema = NULL;
270,942,111✔
2348

2349
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
270,942,111!
2350
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
270,942,111!
2351
  TSDB_CHECK_NULL(pRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
270,942,111!
2352

2353
  pMerger = &pReader->status.merger;
270,942,111✔
2354
  pBlockData = &pReader->status.fileBlockData;
270,942,111✔
2355
  pDumpInfo = &pReader->status.fBlockDumpInfo;
270,942,111✔
2356
  pkSrcSlot = pReader->suppInfo.pkSrcSlot;
270,942,111✔
2357

2358
  if (hasDataInSttBlock(pBlockScanInfo) && (!pBlockScanInfo->cleanSttBlocks)) {
270,942,111!
2359
    pSttKey = getCurrentKeyInSttBlock(pSttBlockReader);
262,748,104✔
2360
  }
2361

2362
  tRowGetKeyEx(pRow, &k);
270,807,210!
2363

2364
  if (pRow->type == TSDBROW_ROW_FMT) {
270,845,893✔
2365
    pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid);
270,818,024!
2366
    TSDB_CHECK_NULL(pSchema, code, lino, _end, terrno);
270,837,916!
2367
  }
2368

2369
  SRowKey* pfKey = &(SRowKey){0};
270,865,785✔
2370
  if (hasDataInFileBlock(pBlockData, pDumpInfo)) {
270,865,785✔
2371
    tColRowGetKey(pBlockData, pDumpInfo->rowIndex, pfKey);
8,043,679✔
2372
  } else {
2373
    pfKey = NULL;
262,755,290✔
2374
  }
2375

2376
  TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
270,797,535✔
2377

2378
  // merge is not initialized yet, due to the fact that the pReader->info.pSchema is not initialized
2379
  code = initRowMergeIfNeeded(pReader, pBlockScanInfo->uid);
270,797,535✔
2380
  TSDB_CHECK_CODE(code, lino, _end);
270,711,565!
2381

2382
  SRowKey minKey = k;
270,711,565✔
2383
  if (pReader->info.order == TSDB_ORDER_ASC) {
270,711,565✔
2384
    if (pfKey != NULL && pkCompEx(pfKey, &minKey) < 0) {
228,165,074✔
2385
      minKey = *pfKey;
6,634,591✔
2386
    }
2387

2388
    if (pSttKey != NULL && pkCompEx(pSttKey, &minKey) < 0) {
434,689,935✔
2389
      minKey = *pSttKey;
115,260,999✔
2390
    }
2391
  } else {
2392
    if (pfKey != NULL && pkCompEx(pfKey, &minKey) > 0) {
50,644,449✔
2393
      minKey = *pfKey;
401,090✔
2394
    }
2395

2396
    if (pSttKey != NULL && pkCompEx(pSttKey, &minKey) > 0) {
98,806,193✔
2397
      minKey = *pSttKey;
16,102,976✔
2398
    }
2399
  }
2400

2401
  // copy the last key before the time of stt reader loading the next stt block, in which the underlying data block may
2402
  // be changed, resulting in the corresponding changing of the value of sttRowKey
2403
  tRowKeyAssign(&pBlockScanInfo->lastProcKey, &minKey);
270,834,058✔
2404

2405
  // file block ---> stt block -----> mem
2406
  if (pkCompEx(&minKey, pfKey) == 0) {
270,652,628✔
2407
    code = tsdbRowMergerAdd(pMerger, &fRow, NULL);
7,765,025✔
2408
    TSDB_CHECK_CODE(code, lino, _end);
7,810,877!
2409

2410
    code = doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pfKey, pReader);
7,810,877✔
2411
    TSDB_CHECK_CODE(code, lino, _end);
7,779,746!
2412
  }
2413

2414
  if (pkCompEx(&minKey, pSttKey) == 0) {
270,833,584✔
2415
    TSDBROW* fRow1 = tMergeTreeGetRow(&pSttBlockReader->mergeTree);
136,798,536✔
2416
    code = tsdbRowMergerAdd(pMerger, fRow1, NULL);
136,798,536✔
2417
    TSDB_CHECK_CODE(code, lino, _end);
136,990,542!
2418
    code = doMergeRowsInSttBlock(pSttBlockReader, pBlockScanInfo, pMerger, pkSrcSlot, &pReader->info.verRange,
136,990,542✔
2419
                                 pReader->idStr);
136,990,542✔
2420
    TSDB_CHECK_CODE(code, lino, _end);
136,654,258!
2421
  }
2422

2423
  if (pkCompEx(&minKey, &k) == 0) {
270,619,190✔
2424
    code = tsdbRowMergerAdd(pMerger, pRow, pSchema);
132,407,740✔
2425
    TSDB_CHECK_CODE(code, lino, _end);
132,438,308!
2426

2427
    code = doMergeRowsInBuf(pIter, pBlockScanInfo->uid, &k, pBlockScanInfo->delSkyline, pReader);
132,438,308✔
2428
    TSDB_CHECK_CODE(code, lino, _end);
132,469,756!
2429
  }
2430

2431
  code = tsdbRowMergerGetRow(pMerger, &pTSRow);
270,681,206✔
2432
  TSDB_CHECK_CODE(code, lino, _end);
271,151,536!
2433

2434
  code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo);
271,151,536✔
2435

2436
  taosMemoryFreeClear(pTSRow);
270,406,814!
2437
  tsdbRowMergerClear(pMerger);
271,303,497✔
2438
  TSDB_CHECK_CODE(code, lino, _end);
269,973,633!
2439

2440
_end:
269,973,633✔
2441
  if (code != TSDB_CODE_SUCCESS) {
269,973,633!
UNCOV
2442
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2443
  }
2444
  return code;
269,961,213✔
2445
}
2446

2447
static int32_t mergeFileBlockAndSttBlock(STsdbReader* pReader, SSttBlockReader* pSttBlockReader, SRowKey* pKey,
231,087,221✔
2448
                                         STableBlockScanInfo* pBlockScanInfo, SBlockData* pBlockData) {
2449
  int32_t             code = TSDB_CODE_SUCCESS;
231,087,221✔
2450
  int32_t             lino = 0;
231,087,221✔
2451
  SFileBlockDumpInfo* pDumpInfo = NULL;
231,087,221✔
2452
  SRowMerger*         pMerger = NULL;
231,087,221✔
2453
  SRow*               pTSRow = NULL;
231,087,221✔
2454
  int32_t             pkSrcSlot = 0;
231,087,221✔
2455

2456
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
231,087,221!
2457
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
231,087,221!
2458
  TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
231,087,221!
2459

2460
  pDumpInfo = &pReader->status.fBlockDumpInfo;
231,087,221✔
2461
  pMerger = &pReader->status.merger;
231,087,221✔
2462
  pkSrcSlot = pReader->suppInfo.pkSrcSlot;
231,087,221✔
2463

2464
  // merge is not initialized yet, due to the fact that the pReader->info.pSchema is not initialized
2465
  code = initRowMergeIfNeeded(pReader, pBlockScanInfo->uid);
231,087,221✔
2466
  TSDB_CHECK_CODE(code, lino, _end);
233,529,925!
2467

2468
  bool dataInDataFile = hasDataInFileBlock(pBlockData, pDumpInfo);
233,529,925✔
2469
  bool dataInSttFile = hasDataInSttBlock(pBlockScanInfo);
232,112,497✔
2470

2471
  if (dataInDataFile && (!dataInSttFile)) {
231,560,380✔
2472
    // no stt file block available, only data block exists
2473
    code = mergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pKey, pReader);
40,121✔
2474
    TSDB_CHECK_CODE(code, lino, _end);
40,070!
2475
  } else if ((!dataInDataFile) && dataInSttFile) {
231,520,259!
2476
    // no data in data file exists
2477
    code = mergeRowsInSttBlocks(pSttBlockReader, pBlockScanInfo, pReader);
228,933,625✔
2478
    TSDB_CHECK_CODE(code, lino, _end);
227,374,962!
2479
  } else if (pBlockScanInfo->cleanSttBlocks && pReader->info.execMode == READER_EXEC_ROWS) {
2,586,634!
2480
    // opt model for count data in stt file, which is not overlap with data blocks in files.
2481
    code = mergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pKey, pReader);
199✔
2482
    TSDB_CHECK_CODE(code, lino, _end);
199!
2483
  } else {
2484
    TSDB_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,069,431!
2485
    // row in both stt file blocks and data file blocks
2486
    TSDBROW  fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
2,586,435✔
2487
    SRowKey* pSttKey = getCurrentKeyInSttBlock(pSttBlockReader);
2,586,435!
2488

2489
    int32_t ret = pkCompEx(pKey, pSttKey);
2,590,468✔
2490

2491
    if (ASCENDING_TRAVERSE(pReader->info.order)) {
2,590,468✔
2492
      if (ret < 0) {  // asc
2,569,659✔
2493
        code = mergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pKey, pReader);
2,486,514✔
2494
        TSDB_CHECK_CODE(code, lino, _end);
2,475,322!
2495
      } else if (ret > 0) {
83,145✔
2496
        code = mergeRowsInSttBlocks(pSttBlockReader, pBlockScanInfo, pReader);
1,777✔
2497
        TSDB_CHECK_CODE(code, lino, _end);
1,777!
2498
      }
2499
    } else {  // desc
2500
      if (ret > 0) {
20,809✔
2501
        code = mergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pKey, pReader);
5,590✔
2502
        TSDB_CHECK_CODE(code, lino, _end);
5,590!
2503
      } else if (ret < 0) {
15,219✔
2504
        code = mergeRowsInSttBlocks(pSttBlockReader, pBlockScanInfo, pReader);
272✔
2505
        TSDB_CHECK_CODE(code, lino, _end);
272!
2506
      }
2507
    }
2508
    if (ret != 0) {
2,579,276✔
2509
      goto _end;
2,482,996✔
2510
    }
2511

2512
    // pKey == pSttKey
2513
    tRowKeyAssign(&pBlockScanInfo->lastProcKey, pKey);
96,280✔
2514

2515
    // the following for key == sttKey->key.ts
2516
    // file block ------> stt  block
2517

2518
    code = tsdbRowMergerAdd(pMerger, &fRow, NULL);
95,422✔
2519
    TSDB_CHECK_CODE(code, lino, _end);
95,478!
2520

2521
    code = doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pKey, pReader);
95,478✔
2522
    TSDB_CHECK_CODE(code, lino, _end);
95,439!
2523

2524
    TSDBROW* pRow1 = tMergeTreeGetRow(&pSttBlockReader->mergeTree);
95,439✔
2525
    code = tsdbRowMergerAdd(pMerger, pRow1, NULL);
95,439✔
2526
    TSDB_CHECK_CODE(code, lino, _end);
95,019!
2527

2528
    // pSttKey will be changed when sttBlockReader iterates to the next row, so use pKey instead.
2529
    code = doMergeRowsInSttBlock(pSttBlockReader, pBlockScanInfo, pMerger, pkSrcSlot, &pReader->info.verRange,
95,019✔
2530
                                 pReader->idStr);
95,019✔
2531
    TSDB_CHECK_CODE(code, lino, _end);
95,363!
2532

2533
    code = tsdbRowMergerGetRow(pMerger, &pTSRow);
95,363✔
2534
    TSDB_CHECK_CODE(code, lino, _end);
95,556!
2535

2536
    code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo);
95,556✔
2537

2538
    taosMemoryFreeClear(pTSRow);
95,475!
2539
    tsdbRowMergerClear(pMerger);
95,553✔
2540
    TSDB_CHECK_CODE(code, lino, _end);
95,055!
2541
  }
2542

2543
_end:
229,993,282✔
2544
  if (code != TSDB_CODE_SUCCESS) {
229,993,282!
UNCOV
2545
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2546
  }
2547
  return code;
229,968,815✔
2548
}
2549

2550
static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo, SBlockData* pBlockData,
3,224,686✔
2551
                                     SSttBlockReader* pSttBlockReader) {
2552
  int32_t             code = TSDB_CODE_SUCCESS;
3,224,686✔
2553
  int32_t             lino = 0;
3,224,686✔
2554
  SRowMerger*         pMerger = NULL;
3,224,686✔
2555
  SRow*               pTSRow = NULL;
3,224,686✔
2556
  SFileBlockDumpInfo* pDumpInfo = NULL;
3,224,686✔
2557
  SArray*             pDelList = NULL;
3,224,686✔
2558
  int32_t             pkSrcSlot = 0;
3,224,686✔
2559
  TSDBROW*            pRow = NULL;
3,224,686✔
2560
  TSDBROW*            piRow = NULL;
3,224,686✔
2561
  SRowKey*            pSttKey = NULL;
3,224,686✔
2562

2563
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
3,224,686!
2564
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
3,224,686!
2565
  TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
3,224,686!
2566

2567
  pMerger = &pReader->status.merger;
3,224,686✔
2568
  pDumpInfo = &pReader->status.fBlockDumpInfo;
3,224,686✔
2569
  pDelList = pBlockScanInfo->delSkyline;
3,224,686✔
2570
  pkSrcSlot = pReader->suppInfo.pkSrcSlot;
3,224,686✔
2571

2572
  code = getValidMemRow(&pBlockScanInfo->iter, pDelList, pReader, &pRow);
6,449,374✔
2573
  TSDB_CHECK_CODE(code, lino, _end);
3,224,688!
2574
  code = getValidMemRow(&pBlockScanInfo->iiter, pDelList, pReader, &piRow);
6,449,376✔
2575
  TSDB_CHECK_CODE(code, lino, _end);
3,224,688!
2576

2577
  if (hasDataInSttBlock(pBlockScanInfo) && (!pBlockScanInfo->cleanSttBlocks)) {
3,224,688!
2578
    pSttKey = getCurrentKeyInSttBlock(pSttBlockReader);
3,224,688✔
2579
  }
2580

2581
  SRowKey* pfKey = &(SRowKey){0};
3,224,688✔
2582
  if (hasDataInFileBlock(pBlockData, pDumpInfo)) {
3,224,688!
UNCOV
2583
    tColRowGetKey(pBlockData, pDumpInfo->rowIndex, pfKey);
×
2584
  } else {
2585
    pfKey = NULL;
3,224,687✔
2586
  }
2587

2588
  SRowKey k = {0}, ik = {0};
3,224,687✔
2589
  tRowGetKeyEx(pRow, &k);
3,224,687!
2590
  tRowGetKeyEx(piRow, &ik);
3,224,687!
2591

2592
  STSchema* pSchema = NULL;
3,224,687✔
2593
  if (pRow->type == TSDBROW_ROW_FMT) {
3,224,687!
2594
    pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid);
3,224,687!
2595
    TSDB_CHECK_NULL(pSchema, code, lino, _end, terrno);
3,224,687!
2596
  }
2597

2598
  STSchema* piSchema = NULL;
3,224,687✔
2599
  if (piRow->type == TSDBROW_ROW_FMT) {
3,224,687!
2600
    piSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(piRow), pReader, pBlockScanInfo->uid);
3,224,687!
2601
    TSDB_CHECK_NULL(pSchema, code, lino, _end, terrno);
3,224,687!
2602
  }
2603

2604
  // merge is not initialized yet, due to the fact that the pReader->info.pSchema is not initialized
2605
  code = initRowMergeIfNeeded(pReader, pBlockScanInfo->uid);
3,224,687✔
2606
  TSDB_CHECK_CODE(code, lino, _end);
3,224,687!
2607

2608
  SRowKey minKey = k;
3,224,687✔
2609
  if (ASCENDING_TRAVERSE(pReader->info.order)) {
3,224,687✔
2610
    if (pkCompEx(&ik, &minKey) < 0) {  // minKey > ik.key.ts) {
3,224,682✔
2611
      minKey = ik;
3,217,324✔
2612
    }
2613

2614
    if ((pfKey != NULL) && (pkCompEx(pfKey, &minKey) < 0)) {
3,224,682!
2615
      minKey = *pfKey;
×
2616
    }
2617

2618
    if ((pSttKey != NULL) && (pkCompEx(pSttKey, &minKey) < 0)) {
6,449,364!
2619
      minKey = *pSttKey;
3,206,064✔
2620
    }
2621
  } else {
2622
    if (pkCompEx(&ik, &minKey) > 0) {
5!
2623
      minKey = ik;
×
2624
    }
2625

2626
    if ((pfKey != NULL) && (pkCompEx(pfKey, &minKey) > 0)) {
5!
2627
      minKey = *pfKey;
×
2628
    }
2629

2630
    if ((pSttKey != NULL) && (pkCompEx(pSttKey, &minKey) > 0)) {
10!
UNCOV
2631
      minKey = *pSttKey;
×
2632
    }
2633
  }
2634

2635
  tRowKeyAssign(&pBlockScanInfo->lastProcKey, &minKey);
3,224,687✔
2636

2637
  // file block -----> stt block -----> imem -----> mem
2638
  if (pkCompEx(&minKey, pfKey) == 0) {
3,224,687!
UNCOV
2639
    TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
×
UNCOV
2640
    code = tsdbRowMergerAdd(pMerger, &fRow, NULL);
×
UNCOV
2641
    TSDB_CHECK_CODE(code, lino, _end);
×
2642

UNCOV
2643
    code = doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pfKey, pReader);
×
UNCOV
2644
    TSDB_CHECK_CODE(code, lino, _end);
×
2645
  }
2646

2647
  if (pkCompEx(&minKey, pSttKey) == 0) {
3,224,687✔
2648
    TSDBROW* pRow1 = tMergeTreeGetRow(&pSttBlockReader->mergeTree);
3,223,843✔
2649
    code = tsdbRowMergerAdd(pMerger, pRow1, NULL);
3,223,843✔
2650
    TSDB_CHECK_CODE(code, lino, _end);
3,223,843!
2651

2652
    code = doMergeRowsInSttBlock(pSttBlockReader, pBlockScanInfo, pMerger, pkSrcSlot, &pReader->info.verRange,
3,223,843✔
2653
                                 pReader->idStr);
3,223,843✔
2654
    TSDB_CHECK_CODE(code, lino, _end);
3,223,834!
2655
  }
2656

2657
  if (pkCompEx(&minKey, &ik) == 0) {
3,224,678✔
2658
    code = tsdbRowMergerAdd(pMerger, piRow, piSchema);
18,621✔
2659
    TSDB_CHECK_CODE(code, lino, _end);
18,621!
2660

2661
    code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, &ik, pBlockScanInfo->delSkyline, pReader);
18,621✔
2662
    TSDB_CHECK_CODE(code, lino, _end);
18,621!
2663
  }
2664

2665
  if (pkCompEx(&minKey, &k) == 0) {
3,224,677✔
2666
    code = tsdbRowMergerAdd(pMerger, pRow, pSchema);
7,363✔
2667
    TSDB_CHECK_CODE(code, lino, _end);
7,363!
2668

2669
    code = doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, &k, pBlockScanInfo->delSkyline, pReader);
7,363✔
2670
    TSDB_CHECK_CODE(code, lino, _end);
7,363!
2671
  }
2672

2673
  code = tsdbRowMergerGetRow(pMerger, &pTSRow);
3,224,677✔
2674
  TSDB_CHECK_CODE(code, lino, _end);
3,224,682!
2675

2676
  code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo);
3,224,682✔
2677

2678
  taosMemoryFreeClear(pTSRow);
3,224,673!
2679
  tsdbRowMergerClear(pMerger);
3,224,687✔
2680
  TSDB_CHECK_CODE(code, lino, _end);
3,224,620!
2681

2682
_end:
3,224,620✔
2683
  if (code != TSDB_CODE_SUCCESS) {
3,224,620!
UNCOV
2684
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2685
  }
2686
  return code;
3,224,621✔
2687
}
2688

2689
int32_t doInitMemDataIter(STsdbReader* pReader, STbData** pData, STableBlockScanInfo* pBlockScanInfo, STsdbRowKey* pKey,
23,412,571✔
2690
                          SMemTable* pMem, SIterInfo* pIter, const char* type) {
2691
  int32_t code = TSDB_CODE_SUCCESS;
23,412,571✔
2692
  int32_t lino = 0;
23,412,571✔
2693
  int32_t backward = false;
23,412,571✔
2694

2695
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
23,412,571!
2696
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
23,412,571!
2697
  TSDB_CHECK_NULL(pIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
23,412,571!
2698
  TSDB_CHECK_NULL(type, code, lino, _end, TSDB_CODE_INVALID_PARA);
23,412,571!
2699

2700
  backward = (!ASCENDING_TRAVERSE(pReader->info.order));
23,412,571✔
2701
  pIter->hasVal = false;
23,412,571✔
2702

2703
  if (pMem != NULL) {
23,412,571✔
2704
    TSDB_CHECK_NULL(pData, code, lino, _end, TSDB_CODE_INVALID_PARA);
10,810,982!
2705
    *pData = tsdbGetTbDataFromMemTable(pMem, pReader->info.suid, pBlockScanInfo->uid);
10,810,982✔
2706

2707
    if ((*pData) != NULL) {
10,818,057✔
2708
      code = tsdbTbDataIterCreate((*pData), pKey, backward, &pIter->iter);
4,123,191✔
2709
      if (code == TSDB_CODE_SUCCESS) {
4,119,823!
2710
        pIter->hasVal = (tsdbTbDataIterGet(pIter->iter) != NULL);
4,119,897!
2711

2712
        tsdbDebug("%p uid:%" PRIu64 ", check data in %s from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64
4,119,897✔
2713
                  "-%" PRId64 " %s",
2714
                  pReader, pBlockScanInfo->uid, type, pKey->key.ts, pReader->info.order, (*pData)->minKey,
2715
                  (*pData)->maxKey, pReader->idStr);
2716
      } else {
UNCOV
2717
        tsdbError("%p uid:%" PRIu64 ", failed to create iterator for %s, code:%s, %s", pReader, pBlockScanInfo->uid,
×
2718
                  type, tstrerror(code), pReader->idStr);
UNCOV
2719
        TSDB_CHECK_CODE(code, lino, _end);
×
2720
      }
2721
    }
2722
  } else {
2723
    tsdbDebug("%p uid:%" PRIu64 ", no data in %s, %s", pReader, pBlockScanInfo->uid, type, pReader->idStr);
12,601,589✔
2724
  }
2725

2726
_end:
12,284,790✔
2727
  if (code != TSDB_CODE_SUCCESS) {
23,416,365!
UNCOV
2728
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2729
  }
2730
  return code;
23,410,318✔
2731
}
2732

2733
static int32_t doForwardDataIter(SRowKey* pKey, SIterInfo* pIter, STableBlockScanInfo* pBlockScanInfo,
1,186,761✔
2734
                                 STsdbReader* pReader) {
2735
  int32_t  code = TSDB_CODE_SUCCESS;
1,186,761✔
2736
  int32_t  lino = 0;
1,186,761✔
2737
  SRowKey  rowKey = {0};
1,186,761✔
2738
  TSDBROW* pRow = NULL;
1,186,761✔
2739

2740
  while (1) {
428✔
2741
    code = getValidMemRow(pIter, pBlockScanInfo->delSkyline, pReader, &pRow);
2,374,226✔
2742
    TSDB_CHECK_CODE(code, lino, _end);
1,187,037!
2743
    if (!pIter->hasVal) {
1,187,037✔
2744
      break;
941,719✔
2745
    }
2746

2747
    tRowGetKeyEx(pRow, &rowKey);
245,318!
2748
    int32_t ret = pkCompEx(pKey, &rowKey);
245,587✔
2749
    if (ret == 0) {
245,587!
UNCOV
2750
      pIter->hasVal = tsdbTbDataIterNext(pIter->iter);
×
2751
    } else {
2752
      break;
245,587✔
2753
    }
2754
  }
2755

2756
_end:
1,187,306✔
2757
  if (code != TSDB_CODE_SUCCESS) {
1,187,306!
UNCOV
2758
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2759
  }
2760
  return code;
1,186,686✔
2761
}
2762

2763
// handle the open interval issue. Find the first row key that is greater than the given one.
2764
static int32_t forwardDataIter(SRowKey* pKey, STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader) {
593,857✔
2765
  int32_t code = TSDB_CODE_SUCCESS;
593,857✔
2766
  int32_t lino = 0;
593,857✔
2767

2768
  TSDB_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
593,857!
2769
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
593,857!
2770

2771
  code = doForwardDataIter(pKey, &pBlockScanInfo->iter, pBlockScanInfo, pReader);
593,857✔
2772
  TSDB_CHECK_CODE(code, lino, _end);
593,303!
2773
  code = doForwardDataIter(pKey, &pBlockScanInfo->iiter, pBlockScanInfo, pReader);
593,303✔
2774
  TSDB_CHECK_CODE(code, lino, _end);
593,603!
2775

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

2783
static int32_t initMemDataIterator(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader) {
29,472,112✔
2784
  int32_t        code = TSDB_CODE_SUCCESS;
29,472,112✔
2785
  int32_t        lino = 0;
29,472,112✔
2786
  STbData*       d = NULL;
29,472,112✔
2787
  STbData*       di = NULL;
29,472,112✔
2788
  bool           asc = false;
29,472,112✔
2789
  bool           forward = true;
29,472,112✔
2790
  STsdbReadSnap* pSnap = NULL;
29,472,112✔
2791
  STimeWindow*   pWindow = NULL;
29,472,112✔
2792
  STsdbRowKey    startKey;
2793

2794
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
29,472,112!
2795
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
29,472,112!
2796

2797
  asc = ASCENDING_TRAVERSE(pReader->info.order);
29,472,112✔
2798
  pSnap = pReader->pReadSnap;
29,472,112✔
2799
  pWindow = &pReader->info.window;
29,472,112✔
2800

2801
  if (pBlockScanInfo->iterInit) {
29,472,112✔
2802
    goto _end;
17,770,969✔
2803
  }
2804

2805
  startKey.key = pBlockScanInfo->lastProcKey;
11,701,143✔
2806
  startKey.version = asc ? pReader->info.verRange.minVer : pReader->info.verRange.maxVer;
11,701,143✔
2807
  if ((asc && (startKey.key.ts < pWindow->skey)) || ((!asc) && startKey.key.ts > pWindow->ekey)) {
11,701,143!
2808
    startKey.key.ts = asc ? pWindow->skey : pWindow->ekey;
11,112,387✔
2809
    forward = false;
11,112,387✔
2810
  }
2811

2812
  code = doInitMemDataIter(pReader, &d, pBlockScanInfo, &startKey, pSnap->pMem, &pBlockScanInfo->iter, "mem");
11,701,143✔
2813
  TSDB_CHECK_CODE(code, lino, _end);
11,709,862!
2814

2815
  code = doInitMemDataIter(pReader, &di, pBlockScanInfo, &startKey, pSnap->pIMem, &pBlockScanInfo->iiter, "imem");
11,709,862✔
2816
  TSDB_CHECK_CODE(code, lino, _end);
11,707,761!
2817

2818
  code = loadMemTombData(&pBlockScanInfo->pMemDelData, d, di, pReader->info.verRange.maxVer);
11,707,761✔
2819
  TSDB_CHECK_CODE(code, lino, _end);
11,712,356!
2820

2821
  if (forward) {
11,712,356✔
2822
    code = forwardDataIter(&startKey.key, pBlockScanInfo, pReader);
593,957✔
2823
    TSDB_CHECK_CODE(code, lino, _end);
593,620!
2824
  }
2825

2826
  pBlockScanInfo->iterInit = true;
11,712,019✔
2827

2828
_end:
29,482,988✔
2829
  if (code != TSDB_CODE_SUCCESS) {
29,482,988!
2830
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2831
  }
2832
  return code;
29,480,240✔
2833
}
2834

2835
static int32_t isValidFileBlockRow(SBlockData* pBlockData, int32_t rowIndex, STableBlockScanInfo* pBlockScanInfo,
110,108,353✔
2836
                                   bool asc, STsdbReaderInfo* pInfo, STsdbReader* pReader, bool* valid) {
2837
  int32_t code = TSDB_CODE_SUCCESS;
110,108,353✔
2838
  int32_t lino = 0;
110,108,353✔
2839

2840
  TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
110,108,353!
2841
  TSDB_CHECK_NULL(valid, code, lino, _end, TSDB_CODE_INVALID_PARA);
110,108,353!
2842

2843
  *valid = false;
110,108,353✔
2844
  // it is an multi-table data block
2845
  if (pBlockData->aUid != NULL) {
110,108,353!
UNCOV
2846
    uint64_t uid = pBlockData->aUid[rowIndex];
×
UNCOV
2847
    if (uid != pBlockScanInfo->uid) {  // move to next row
×
UNCOV
2848
      *valid = false;
×
UNCOV
2849
      goto _end;
×
2850
    }
2851
  }
2852

2853
  TSDB_CHECK_NULL(pInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
110,108,353!
2854
  // check for version and time range
2855
  int64_t ver = pBlockData->aVersion[rowIndex];
110,108,353✔
2856
  if (ver > pInfo->verRange.maxVer || ver < pInfo->verRange.minVer) {
110,108,353!
UNCOV
2857
    *valid = false;
×
UNCOV
2858
    goto _end;
×
2859
  }
2860

2861
  int64_t ts = pBlockData->aTSKEY[rowIndex];
110,165,591✔
2862
  if (ts > pInfo->window.ekey || ts < pInfo->window.skey) {
110,165,591✔
2863
    *valid = false;
98,119,597✔
2864
    goto _end;
98,119,597✔
2865
  }
2866

2867
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
12,045,994!
2868
  if ((asc && (ts < pBlockScanInfo->lastProcKey.ts)) || ((!asc) && (ts > pBlockScanInfo->lastProcKey.ts))) {
12,045,994!
UNCOV
2869
    *valid = false;
×
UNCOV
2870
    goto _end;
×
2871
  }
2872

2873
  if (ts == pBlockScanInfo->lastProcKey.ts) {  // todo opt perf
12,045,994✔
2874
    SRowKey nextRowKey;                        // lazy eval
2875
    tColRowGetKey(pBlockData, rowIndex, &nextRowKey);
616,840✔
2876
    if (pkCompEx(&pBlockScanInfo->lastProcKey, &nextRowKey) == 0) {
1,233,661!
UNCOV
2877
      *valid = false;
×
UNCOV
2878
      goto _end;
×
2879
    }
2880
  }
2881

2882
  if (pBlockScanInfo->delSkyline != NULL && TARRAY_SIZE(pBlockScanInfo->delSkyline) > 0) {
12,045,982!
2883
    bool dropped = false;
3,159,689✔
2884
    code = hasBeenDropped(pBlockScanInfo->delSkyline, &pBlockScanInfo->fileDelIndex, ts, ver, pInfo->order,
3,159,689✔
2885
                          &pInfo->verRange, pReader->suppInfo.numOfPks > 0, &dropped);
3,159,689✔
2886
    TSDB_CHECK_CODE(code, lino, _end);
4,616,892!
2887
    if (dropped) {
3,159,521✔
2888
      *valid = false;
1,457,371✔
2889
      goto _end;
1,457,371✔
2890
    }
2891
  }
2892

2893
  *valid = true;
10,588,443✔
2894

2895
_end:
110,108,173✔
2896
  if (code != TSDB_CODE_SUCCESS) {
110,108,173!
UNCOV
2897
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2898
  }
2899
  return code;
110,141,119✔
2900
}
2901

2902
static void initSttBlockReader(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo, STsdbReader* pReader) {
15,683,744✔
2903
  int32_t              code = TSDB_CODE_SUCCESS;
15,683,744✔
2904
  int32_t              lino = 0;
15,683,744✔
2905
  int32_t              order = 0;
15,683,744✔
2906
  bool                 asc = false;
15,683,744✔
2907
  int64_t              st = 0;
15,683,744✔
2908
  SSttDataInfoForTable info = (SSttDataInfoForTable){0};
15,683,744✔
2909

2910
  TSDB_CHECK_NULL(pSttBlockReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
15,683,744!
2911
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
15,683,744!
2912
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
15,683,744!
2913

2914
  order = pReader->info.order;
15,683,744✔
2915
  asc = ASCENDING_TRAVERSE(order);
15,683,744✔
2916

2917
  // the stt block reader has been initialized for this table.
2918
  if (pSttBlockReader->uid == pScanInfo->uid) {
15,683,744✔
2919
    goto _end;
4,092,026✔
2920
  }
2921

2922
  if (pSttBlockReader->uid != 0) {
11,591,718✔
2923
    tMergeTreeClose(&pSttBlockReader->mergeTree);
6,503,606✔
2924
  }
2925

2926
  pSttBlockReader->uid = pScanInfo->uid;
11,590,280✔
2927

2928
  // second or third time init stt block reader
2929
  if (pScanInfo->cleanSttBlocks && (pReader->info.execMode == READER_EXEC_ROWS)) {
11,590,280!
2930
    // only allowed to retrieve clean stt blocks for count once
UNCOV
2931
    if (pScanInfo->sttBlockReturned) {
×
UNCOV
2932
      pScanInfo->sttKeyInfo.status = STT_FILE_NO_DATA;
×
UNCOV
2933
      tsdbDebug("uid:%" PRIu64 " set no stt-file data after stt-block retrieved, %s", pScanInfo->uid, pReader->idStr);
×
2934
    }
UNCOV
2935
    goto _end;
×
2936
  }
2937

2938
  STimeWindow w = pSttBlockReader->window;
11,590,280✔
2939
  if (asc) {
11,590,280✔
2940
    w.skey = pScanInfo->sttKeyInfo.nextProcKey.ts;
9,695,195✔
2941
  } else {
2942
    w.ekey = pScanInfo->sttKeyInfo.nextProcKey.ts;
1,895,085✔
2943
  }
2944

2945
  st = taosGetTimestampUs();
11,594,911✔
2946
  tsdbDebug("init stt block reader, window:%" PRId64 "-%" PRId64 ", uid:%" PRIu64 ", %s", w.skey, w.ekey,
11,594,911✔
2947
            pScanInfo->uid, pReader->idStr);
2948

2949
  SMergeTreeConf conf = {
11,594,911✔
2950
      .uid = pScanInfo->uid,
11,594,911✔
2951
      .suid = pReader->info.suid,
11,594,911✔
2952
      .pTsdb = pReader->pTsdb,
11,594,911✔
2953
      .timewindow = w,
2954
      .verRange = pSttBlockReader->verRange,
2955
      .strictTimeRange = false,
2956
      .pSchema = pReader->info.pSchema,
11,594,911✔
2957
      .pCurrentFileset = pReader->status.pCurrentFileset,
11,594,911✔
2958
      .backward = (pSttBlockReader->order == TSDB_ORDER_DESC),
11,594,911✔
2959
      .pSttFileBlockIterArray = pReader->status.pLDataIterArray,
11,594,911✔
2960
      .pCols = pReader->suppInfo.colId,
11,594,911✔
2961
      .numOfCols = pReader->suppInfo.numOfCols,
11,594,911✔
2962
      .loadTombFn = loadSttTombDataForAll,
2963
      .pCurRowKey = &pScanInfo->sttKeyInfo.nextProcKey,
11,594,911✔
2964
      .pReader = pReader,
2965
      .idstr = pReader->idStr,
11,594,911✔
2966
      .rspRows = (pReader->info.execMode == READER_EXEC_ROWS),
11,594,911✔
2967
  };
2968

2969
  info.pKeyRangeList = taosArrayInit(4, sizeof(SSttKeyRange));
11,594,911✔
2970
  TSDB_CHECK_NULL(info.pKeyRangeList, code, lino, _end, terrno);
11,595,180!
2971

2972
  code = tMergeTreeOpen2(&pSttBlockReader->mergeTree, &conf, &info);
11,595,180✔
2973
  TSDB_CHECK_CODE(code, lino, _end);
11,596,189!
2974

2975
  code = initMemDataIterator(pScanInfo, pReader);
11,596,189✔
2976
  TSDB_CHECK_CODE(code, lino, _end);
11,597,965!
2977

2978
  code = initDelSkylineIterator(pScanInfo, pReader->info.order, &pReader->cost);
11,597,965✔
2979
  TSDB_CHECK_CODE(code, lino, _end);
11,597,572!
2980

2981
  if (conf.rspRows) {
11,597,572✔
2982
    pScanInfo->cleanSttBlocks = isCleanSttBlock(info.pKeyRangeList, &pReader->info.window, pScanInfo, order);
150,849✔
2983
    if (pScanInfo->cleanSttBlocks) {
150,816✔
2984
      pScanInfo->numOfRowsInStt = info.numOfRows;
15,934✔
2985

2986
      // calculate the time window for data in stt files
2987
      for (int32_t i = 0; i < taosArrayGetSize(info.pKeyRangeList); ++i) {
31,864✔
2988
        SSttKeyRange* pKeyRange = taosArrayGet(info.pKeyRangeList, i);
15,939✔
2989
        if (pKeyRange == NULL) {
15,942!
UNCOV
2990
          continue;
×
2991
        }
2992

2993
        if (pkCompEx(&pScanInfo->sttRange.skey, &pKeyRange->skey) > 0) {
31,889!
2994
          tRowKeyAssign(&pScanInfo->sttRange.skey, &pKeyRange->skey);
15,934✔
2995
        }
2996

2997
        if (pkCompEx(&pScanInfo->sttRange.ekey, &pKeyRange->ekey) < 0) {
31,850!
2998
          tRowKeyAssign(&pScanInfo->sttRange.ekey, &pKeyRange->ekey);
15,931✔
2999
        }
3000
      }
3001

3002
      pScanInfo->sttKeyInfo.status = taosArrayGetSize(info.pKeyRangeList) ? STT_FILE_HAS_DATA : STT_FILE_NO_DATA;
15,858!
3003

3004
      SRowKey* p = asc ? &pScanInfo->sttRange.skey : &pScanInfo->sttRange.ekey;
15,914!
3005
      tRowKeyAssign(&pScanInfo->sttKeyInfo.nextProcKey, p);
15,914✔
3006
    } else {                                // not clean stt blocks
3007
      INIT_KEYRANGE(&pScanInfo->sttRange);  // reset the time window
134,882✔
3008
      code = nextRowFromSttBlocks(pSttBlockReader, pScanInfo, pReader->suppInfo.pkSrcSlot, &pReader->info.verRange);
134,882✔
3009
      if (code != TSDB_CODE_SUCCESS) {
134,814!
UNCOV
3010
        pScanInfo->sttBlockReturned = false;
×
UNCOV
3011
        TSDB_CHECK_CODE(code, lino, _end);
×
3012
      }
3013
    }
3014
  } else {
3015
    pScanInfo->cleanSttBlocks = false;
11,446,723✔
3016
    INIT_KEYRANGE(&pScanInfo->sttRange);  // reset the time window
11,446,723✔
3017
    code = nextRowFromSttBlocks(pSttBlockReader, pScanInfo, pReader->suppInfo.pkSrcSlot, &pReader->info.verRange);
11,446,723✔
3018
    if (code != TSDB_CODE_SUCCESS) {
11,443,048!
UNCOV
3019
      pScanInfo->sttBlockReturned = false;
×
UNCOV
3020
      TSDB_CHECK_CODE(code, lino, _end);
×
3021
    }
3022
  }
3023

3024
  pScanInfo->sttBlockReturned = false;
11,593,766✔
3025
  int64_t el = taosGetTimestampUs() - st;
11,596,359✔
3026
  pReader->cost.initSttBlockReader += (el / 1000.0);
11,596,359✔
3027

3028
  tsdbDebug("init stt block reader completed, elapsed time:%" PRId64 "us %s", el, pReader->idStr);
11,596,359✔
3029

3030
_end:
11,532,776✔
3031
  if (code != TSDB_CODE_SUCCESS) {
15,688,385!
UNCOV
3032
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
3033
    if (pReader) {
×
UNCOV
3034
      pReader->code = code;
×
3035
    }
3036
  }
3037
  taosArrayDestroy(info.pKeyRangeList);
15,688,385✔
3038
}
15,689,303✔
3039

3040
static bool hasDataInSttBlock(STableBlockScanInfo* pInfo) { return pInfo->sttKeyInfo.status == STT_FILE_HAS_DATA; }
1,356,218,631✔
3041

3042
bool hasDataInFileBlock(const SBlockData* pBlockData, const SFileBlockDumpInfo* pDumpInfo) {
991,269,711✔
3043
  if ((pBlockData->nRow > 0) && (pBlockData->nRow != pDumpInfo->totalRows)) {
991,269,711!
UNCOV
3044
    return false;  // this is an invalid result.
×
3045
  }
3046
  return pBlockData->nRow > 0 && (!pDumpInfo->allDumped);
991,269,711!
3047
}
3048

3049
int32_t mergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pBlockScanInfo, SRowKey* pKey,
2,532,411✔
3050
                              STsdbReader* pReader) {
3051
  int32_t             code = TSDB_CODE_SUCCESS;
2,532,411✔
3052
  int32_t             lino = 0;
2,532,411✔
3053
  SRow*               pTSRow = NULL;
2,532,411✔
3054
  SRowMerger*         pMerger = NULL;
2,532,411✔
3055
  SFileBlockDumpInfo* pDumpInfo = NULL;
2,532,411✔
3056
  bool                copied = false;
2,532,411✔
3057

3058
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,532,411!
3059
  TSDB_CHECK_NULL(pKey, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,532,411!
3060
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,532,411!
3061

3062
  pMerger = &pReader->status.merger;
2,532,411✔
3063
  pDumpInfo = &pReader->status.fBlockDumpInfo;
2,532,411✔
3064

3065
  code = tryCopyDistinctRowFromFileBlock(pReader, pBlockData, pKey, pDumpInfo, &copied);
2,532,411✔
3066
  TSDB_CHECK_CODE(code, lino, _end);
2,526,887!
3067

3068
  // merge is not initialized yet, due to the fact that the pReader->info.pSchema is not initialized
3069
  code = initRowMergeIfNeeded(pReader, pBlockScanInfo->uid);
2,526,887✔
3070
  TSDB_CHECK_CODE(code, lino, _end);
2,521,492!
3071

3072
  tRowKeyAssign(&pBlockScanInfo->lastProcKey, pKey);
2,521,492✔
3073

3074
  if (copied) {
2,521,413✔
3075
    goto _end;
2,520,800✔
3076
  }
3077

3078
  TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex);
613✔
3079

3080
  code = tsdbRowMergerAdd(pMerger, &fRow, NULL);
613✔
3081
  TSDB_CHECK_CODE(code, lino, _end);
772!
3082

3083
  code = doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pKey, pReader);
772✔
3084
  TSDB_CHECK_CODE(code, lino, _end);
772!
3085

3086
  code = tsdbRowMergerGetRow(pMerger, &pTSRow);
772✔
3087
  TSDB_CHECK_CODE(code, lino, _end);
772!
3088

3089
  code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo);
772✔
3090

3091
  taosMemoryFreeClear(pTSRow);
772!
3092
  tsdbRowMergerClear(pMerger);
772✔
3093
  TSDB_CHECK_CODE(code, lino, _end);
772!
3094

3095
_end:
772✔
3096
  if (code != TSDB_CODE_SUCCESS) {
2,521,572!
UNCOV
3097
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3098
  }
3099
  return code;
2,521,333✔
3100
}
3101

3102
int32_t mergeRowsInSttBlocks(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo, STsdbReader* pReader) {
228,372,039✔
3103
  int32_t     code = TSDB_CODE_SUCCESS;
228,372,039✔
3104
  int32_t     lino = 0;
228,372,039✔
3105
  SRow*       pTSRow = NULL;
228,372,039✔
3106
  int32_t     pkSrcSlot = 0;
228,372,039✔
3107
  SRowMerger* pMerger = NULL;
228,372,039✔
3108
  bool        copied = false;
228,372,039✔
3109

3110
  TSDB_CHECK_NULL(pSttBlockReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
228,372,039!
3111
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
228,372,039!
3112
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
228,372,039!
3113

3114
  pkSrcSlot = pReader->suppInfo.pkSrcSlot;
228,372,039✔
3115
  pMerger = &pReader->status.merger;
228,372,039✔
3116

3117
  // let's record the last processed key
3118
  tRowKeyAssign(&pScanInfo->lastProcKey, getCurrentKeyInSttBlock(pSttBlockReader));
228,372,039✔
3119

3120
  TSDBROW* pRow = tMergeTreeGetRow(&pSttBlockReader->mergeTree);
228,658,699✔
3121
  TSDBROW  fRow = {.iRow = pRow->iRow, .type = TSDBROW_COL_FMT, .pBlockData = pRow->pBlockData};
228,658,699✔
3122

3123
  if (IS_VAR_DATA_TYPE(pScanInfo->lastProcKey.pks[0].type)) {
228,658,699!
3124
    tsdbTrace("fRow ptr:%p, %d, uid:%" PRIu64 ", ts:%" PRId64 " pk:%s %s", pRow->pBlockData, pRow->iRow,
20,823!
3125
              pSttBlockReader->uid, fRow.pBlockData->aTSKEY[fRow.iRow], pScanInfo->lastProcKey.pks[0].pData,
3126
              pReader->idStr);
3127
  }
3128

3129
  code = tryCopyDistinctRowFromSttBlock(&fRow, pSttBlockReader, pScanInfo, &pScanInfo->lastProcKey, pReader, &copied);
228,658,699✔
3130
  TSDB_CHECK_CODE(code, lino, _end);
227,278,898!
3131

3132
  if (copied) {
227,278,898✔
3133
    goto _end;
226,243,113✔
3134
  }
3135

3136
  code = tsdbRowMergerAdd(pMerger, &fRow, NULL);
1,035,785✔
3137
  TSDB_CHECK_CODE(code, lino, _end);
1,127,118!
3138

3139
  TSDBROW* pRow1 = tMergeTreeGetRow(&pSttBlockReader->mergeTree);
1,127,118✔
3140
  code = tsdbRowMergerAdd(pMerger, pRow1, NULL);
1,127,118✔
3141
  TSDB_CHECK_CODE(code, lino, _end);
1,095,425!
3142

3143
  code = doMergeRowsInSttBlock(pSttBlockReader, pScanInfo, pMerger, pkSrcSlot, &pReader->info.verRange, pReader->idStr);
1,095,425✔
3144
  TSDB_CHECK_CODE(code, lino, _end);
1,111,670!
3145

3146
  code = tsdbRowMergerGetRow(pMerger, &pTSRow);
1,111,670✔
3147
  TSDB_CHECK_CODE(code, lino, _end);
1,135,475!
3148

3149
  code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pScanInfo);
1,135,475✔
3150

3151
  taosMemoryFreeClear(pTSRow);
1,130,058!
3152
  tsdbRowMergerClear(pMerger);
1,135,722✔
3153
  TSDB_CHECK_CODE(code, lino, _end);
1,090,223!
3154

3155
_end:
1,090,223✔
3156
  if (code != TSDB_CODE_SUCCESS) {
227,333,336!
UNCOV
3157
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3158
  }
3159
  return code;
227,497,451✔
3160
}
3161

3162
static int32_t buildComposedDataBlockImpl(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo,
501,729,015✔
3163
                                          SBlockData* pBlockData, SSttBlockReader* pSttBlockReader) {
3164
  int32_t             code = TSDB_CODE_SUCCESS;
501,729,015✔
3165
  int32_t             lino = 0;
501,729,015✔
3166
  SFileBlockDumpInfo* pDumpInfo = NULL;
501,729,015✔
3167
  TSDBROW*            pRow = NULL;
501,729,015✔
3168
  TSDBROW*            piRow = NULL;
501,729,015✔
3169
  SRowKey*            pKey = &(SRowKey){0};
501,729,015✔
3170

3171
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
501,729,015!
3172
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
501,729,015!
3173
  TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
501,729,015!
3174

3175
  pDumpInfo = &pReader->status.fBlockDumpInfo;
501,729,015✔
3176

3177
  if (hasDataInFileBlock(pBlockData, pDumpInfo)) {
501,729,015✔
3178
    tColRowGetKey(pBlockData, pDumpInfo->rowIndex, pKey);
10,397,760✔
3179
  } else {
3180
    pKey = NULL;
492,804,652✔
3181
  }
3182

3183
  if (pBlockScanInfo->iter.hasVal) {
502,622,174✔
3184
    code = getValidMemRow(&pBlockScanInfo->iter, pBlockScanInfo->delSkyline, pReader, &pRow);
509,060,719✔
3185
    TSDB_CHECK_CODE(code, lino, _end);
254,636,635!
3186
  }
3187

3188
  if (pBlockScanInfo->iiter.hasVal) {
502,834,725✔
3189
    code = getValidMemRow(&pBlockScanInfo->iiter, pBlockScanInfo->delSkyline, pReader, &piRow);
45,171,849✔
3190
    TSDB_CHECK_CODE(code, lino, _end);
22,791,461!
3191
  }
3192

3193
  if (pRow != NULL && piRow != NULL) {
503,245,798✔
3194
    // two levels of mem-table does contain the valid rows
3195
    code = doMergeMultiLevelRows(pReader, pBlockScanInfo, pBlockData, pSttBlockReader);
3,224,686✔
3196
    TSDB_CHECK_CODE(code, lino, _end);
3,224,621!
3197
  } else if (pBlockScanInfo->iiter.hasVal) {
500,021,112✔
3198
    // imem + file + stt block
3199
    code = doMergeBufAndFileRows(pReader, pBlockScanInfo, piRow, &pBlockScanInfo->iiter, pSttBlockReader);
19,598,203✔
3200
    TSDB_CHECK_CODE(code, lino, _end);
19,147,579!
3201
  } else if (pBlockScanInfo->iter.hasVal) {
480,422,909✔
3202
    // mem + file + stt block
3203
    code = doMergeBufAndFileRows(pReader, pBlockScanInfo, pRow, &pBlockScanInfo->iter, pSttBlockReader);
251,438,048✔
3204
    TSDB_CHECK_CODE(code, lino, _end);
250,839,909!
3205
  } else {
3206
    // files data blocks + stt block
3207
    code = mergeFileBlockAndSttBlock(pReader, pSttBlockReader, pKey, pBlockScanInfo, pBlockData);
228,984,861✔
3208
    TSDB_CHECK_CODE(code, lino, _end);
229,793,389!
3209
  }
3210

3211
_end:
229,793,389✔
3212
  if (code != TSDB_CODE_SUCCESS) {
503,005,498!
UNCOV
3213
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3214
  }
3215
  return code;
502,517,860✔
3216
}
3217

3218
static int32_t loadNeighborIfOverlap(SFileDataBlockInfo* pBlockInfo, STableBlockScanInfo* pBlockScanInfo,
38,246✔
3219
                                     STsdbReader* pReader, bool* loadNeighbor) {
3220
  int32_t             code = TSDB_CODE_SUCCESS;
38,246✔
3221
  int32_t             lino = 0;
38,246✔
3222
  int32_t             order = 0;
38,246✔
3223
  SDataBlockIter*     pIter = NULL;
38,246✔
3224
  SBlockLoadSuppInfo* pSupInfo = NULL;
38,246✔
3225
  int32_t             step = 0;
38,246✔
3226
  int32_t             nextIndex = -1;
38,246✔
3227
  SBrinRecord         rec = {0};
38,246✔
3228
  bool                hasNeighbor = false;
38,246✔
3229

3230
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
38,246!
3231
  TSDB_CHECK_NULL(loadNeighbor, code, lino, _end, TSDB_CODE_INVALID_PARA);
38,246!
3232

3233
  order = pReader->info.order;
38,246✔
3234
  pIter = &pReader->status.blockIter;
38,246✔
3235
  pSupInfo = &pReader->suppInfo;
38,246✔
3236
  step = ASCENDING_TRAVERSE(order) ? 1 : -1;
38,246✔
3237

3238
  *loadNeighbor = false;
38,246✔
3239
  code = getNeighborBlockOfTable(pIter, pBlockInfo, pBlockScanInfo, &nextIndex, order, &rec, pSupInfo, &hasNeighbor);
38,246✔
3240
  TSDB_CHECK_CODE(code, lino, _end);
38,246!
3241
  if (!hasNeighbor) {  // do nothing
38,246✔
3242
    goto _end;
35,212✔
3243
  }
3244

3245
  // load next block
3246
  if (overlapWithNeighborBlock2(pBlockInfo, &rec, order, pReader->suppInfo.pk.type, pReader->suppInfo.numOfPks)) {
3,034✔
3247
    SReaderStatus*  pStatus = &pReader->status;
5✔
3248
    SDataBlockIter* pBlockIter = &pStatus->blockIter;
5✔
3249

3250
    // 1. find the next neighbor block in the scan block list
3251
    STableDataBlockIdx* tableDataBlockIdx = taosArrayGet(pBlockScanInfo->pBlockIdxList, nextIndex);
5✔
3252
    TSDB_CHECK_NULL(tableDataBlockIdx, code, lino, _end, TSDB_CODE_INVALID_PARA);
5!
3253

3254
    // 2. remove it from the scan block list
3255
    int32_t neighborIndex = tableDataBlockIdx->globalIndex;
5✔
3256
    code = setFileBlockActiveInBlockIter(pReader, pBlockIter, neighborIndex, step);
5✔
3257
    TSDB_CHECK_CODE(code, lino, _end);
5!
3258

3259
    // 3. load the neighbor block, and set it to be the currently accessed file data block
3260
    code = doLoadFileBlockData(pReader, pBlockIter, &pStatus->fileBlockData, pBlockInfo->uid);
5✔
3261
    TSDB_CHECK_CODE(code, lino, _end);
5!
3262

3263
    // 4. check the data values
3264
    code = initBlockDumpInfo(pReader, pBlockIter);
5✔
3265
    TSDB_CHECK_CODE(code, lino, _end);
5!
3266
    *loadNeighbor = true;
5✔
3267
  }
3268

3269
_end:
3,029✔
3270
  if (code != TSDB_CODE_SUCCESS) {
38,246!
UNCOV
3271
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3272
  }
3273
  return code;
38,246✔
3274
}
3275

3276
void updateComposedBlockInfo(STsdbReader* pReader, double el, STableBlockScanInfo* pBlockScanInfo) {
9,040,561✔
3277
  SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock;
9,040,561✔
3278

3279
  pResBlock->info.id.uid = (pBlockScanInfo != NULL) ? pBlockScanInfo->uid : 0;
9,040,561!
3280
  pResBlock->info.dataLoad = 1;
9,040,561✔
3281
  pResBlock->info.version = pReader->info.verRange.maxVer;
9,040,561✔
3282

3283
  int32_t code = blockDataUpdateTsWindow(pResBlock, pReader->suppInfo.slotId[0]);
9,040,561✔
3284
  code = blockDataUpdatePkRange(pResBlock, pReader->suppInfo.pkDstSlot, ASCENDING_TRAVERSE(pReader->info.order));
9,041,597✔
3285
  setComposedBlockFlag(pReader, true);
9,041,330✔
3286

3287
  pReader->cost.composedBlocks += 1;
9,039,819✔
3288
  pReader->cost.buildComposedBlockTime += el;
9,039,819✔
3289
}
9,039,819✔
3290

3291
static int32_t buildComposedDataBlock(STsdbReader* pReader) {
40,031✔
3292
  int32_t              code = TSDB_CODE_SUCCESS;
40,031✔
3293
  int32_t              lino = 0;
40,031✔
3294
  bool                 asc = false;
40,031✔
3295
  int64_t              st = 0;
40,031✔
3296
  double               el = 0;
40,031✔
3297
  int32_t              step = 0;
40,031✔
3298
  SSDataBlock*         pResBlock = NULL;
40,031✔
3299
  SFileDataBlockInfo*  pBlockInfo = NULL;
40,031✔
3300
  SSttBlockReader*     pSttBlockReader = NULL;
40,031✔
3301
  SFileBlockDumpInfo*  pDumpInfo = NULL;
40,031✔
3302
  STableBlockScanInfo* pBlockScanInfo = NULL;
40,031✔
3303
  TSDBKEY              keyInBuf;
3304

3305
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
40,031!
3306

3307
  asc = ASCENDING_TRAVERSE(pReader->info.order);
40,031✔
3308
  st = taosGetTimestampUs();
40,031✔
3309
  step = asc ? 1 : -1;
40,031✔
3310
  pResBlock = pReader->resBlockInfo.pResBlock;
40,031✔
3311
  pSttBlockReader = pReader->status.fileIter.pSttBlockReader;
40,031✔
3312
  pDumpInfo = &pReader->status.fBlockDumpInfo;
40,031✔
3313

3314
  code = getCurrentBlockInfo(&pReader->status.blockIter, &pBlockInfo, pReader->idStr);
40,031✔
3315
  if (code != TSDB_CODE_SUCCESS) {
40,032!
UNCOV
3316
    return 0;
×
3317
  }
3318

3319
  if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &pBlockInfo->uid, sizeof(pBlockInfo->uid))) {
40,032!
UNCOV
3320
    setBlockAllDumped(pDumpInfo, pBlockInfo->lastKey, pReader->info.order);
×
UNCOV
3321
    return code;
×
3322
  }
3323

3324
  code = getTableBlockScanInfo(pReader->status.pTableMap, pBlockInfo->uid, &pBlockScanInfo, pReader->idStr);
40,030✔
3325
  TSDB_CHECK_CODE(code, lino, _end);
40,030!
3326

3327
  code = getCurrentKeyInBuf(pBlockScanInfo, pReader, &keyInBuf);
40,030✔
3328
  TSDB_CHECK_CODE(code, lino, _end);
40,029!
3329

3330
  // it is a clean block, load it directly
3331
  int64_t cap = pReader->resBlockInfo.capacity;
40,029✔
3332
  bool    isClean = false;
40,029✔
3333
  code = isCleanFileDataBlock(pReader, pBlockInfo, pBlockScanInfo, keyInBuf, &isClean);
40,029✔
3334
  TSDB_CHECK_CODE(code, lino, _end);
40,030!
3335
  bool directCopy = isClean && (pBlockInfo->numRow <= cap) && (pBlockScanInfo->sttKeyInfo.status == STT_FILE_NO_DATA) &&
41,820!
3336
                    ((asc && ((pBlockInfo->lastKey < keyInBuf.ts) || (keyInBuf.ts == INT64_MIN))) ||
900!
3337
                     (!asc && (pBlockInfo->lastKey > keyInBuf.ts)));
892✔
3338
  if (directCopy) {
40,030✔
3339
    code = copyBlockDataToSDataBlock(pReader, &pBlockScanInfo->lastProcKey);
1,787✔
3340
    TSDB_CHECK_CODE(code, lino, _end);
1,784!
3341
    goto _end;
1,784✔
3342
  }
3343

3344
  SBlockData* pBlockData = &pReader->status.fileBlockData;
38,243✔
3345
  initSttBlockReader(pSttBlockReader, pBlockScanInfo, pReader);
38,243✔
3346
  code = pReader->code;
38,245✔
3347
  TSDB_CHECK_CODE(code, lino, _end);
38,245!
3348

3349
  while (1) {
10,585,515✔
3350
    bool hasBlockData = false;
10,623,760✔
3351
    {
3352
      while (pBlockData->nRow > 0 && pBlockData->uid == pBlockScanInfo->uid) {
110,139,951✔
3353
        // find the first qualified row in data block
3354
        bool valid = false;
110,135,898✔
3355
        code =
3356
            isValidFileBlockRow(pBlockData, pDumpInfo->rowIndex, pBlockScanInfo, asc, &pReader->info, pReader, &valid);
110,135,898✔
3357
        TSDB_CHECK_CODE(code, lino, _end);
110,130,843!
3358
        if (valid) {
110,130,843✔
3359
          hasBlockData = true;
10,582,873✔
3360
          break;
10,617,903✔
3361
        }
3362

3363
        pDumpInfo->rowIndex += step;
99,547,970✔
3364

3365
        if (pDumpInfo->rowIndex >= pBlockData->nRow || pDumpInfo->rowIndex < 0) {
99,547,970✔
3366
          // NOTE: get the new block info
3367
          code = getCurrentBlockInfo(&pReader->status.blockIter, &pBlockInfo, pReader->idStr);
31,779✔
3368
          TSDB_CHECK_CODE(code, lino, _end);
35,030!
3369

3370
          // continue check for the next file block if the last ts in the current block
3371
          // is overlapped with the next neighbor block
3372
          bool loadNeighbor = false;
35,030✔
3373
          code = loadNeighborIfOverlap(pBlockInfo, pBlockScanInfo, pReader, &loadNeighbor);
35,030✔
3374
          if ((!loadNeighbor) || (code != 0)) {
35,030!
3375
            lino = __LINE__;
35,030✔
3376
            setBlockAllDumped(pDumpInfo, pBlockInfo->lastKey, pReader->info.order);
35,030✔
3377
            break;
35,030✔
3378
          }
3379
        }
3380
      }
3381
    }
3382

3383
    // no data in last block and block, no need to proceed.
3384
    if (hasBlockData == false) {
10,621,956✔
3385
      break;
35,030✔
3386
    }
3387

3388
    code = buildComposedDataBlockImpl(pReader, pBlockScanInfo, pBlockData, pSttBlockReader);
10,586,926✔
3389
    TSDB_CHECK_CODE(code, lino, _end);
10,588,432!
3390

3391
    // currently loaded file data block is consumed
3392
    if ((pBlockData->nRow > 0) && (pDumpInfo->rowIndex >= pBlockData->nRow || pDumpInfo->rowIndex < 0)) {
10,588,432!
3393
      setBlockAllDumped(pDumpInfo, pBlockInfo->lastKey, pReader->info.order);
2,913✔
3394
      break;
3,211✔
3395
    }
3396

3397
    if (pResBlock->info.rows >= pReader->resBlockInfo.capacity) {
10,585,519✔
3398
      break;
4✔
3399
    }
3400
  }
3401

3402
_end:
40,029✔
3403
  if (pReader) {
40,029✔
3404
    el = (taosGetTimestampUs() - st) / 1000.0;
40,029✔
3405
    updateComposedBlockInfo(pReader, el, pBlockScanInfo);
40,029✔
3406
  }
3407

3408
  if (pResBlock && pResBlock->info.rows > 0) {
40,032✔
3409
    tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 " rows:%" PRId64
25,052✔
3410
              ", elapsed time:%.2f ms %s",
3411
              pReader, pResBlock->info.id.uid, pResBlock->info.window.skey, pResBlock->info.window.ekey,
3412
              pResBlock->info.rows, el, pReader->idStr);
3413
  }
3414

3415
  if (code != TSDB_CODE_SUCCESS) {
40,032!
UNCOV
3416
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3417
  }
3418
  return code;
40,028✔
3419
}
3420

3421
void setComposedBlockFlag(STsdbReader* pReader, bool composed) { pReader->status.composedDataBlock = composed; }
14,255,623✔
3422

3423
int32_t getInitialDelIndex(const SArray* pDelSkyline, int32_t order) {
230,443✔
3424
  if (pDelSkyline == NULL) {
230,443!
UNCOV
3425
    return 0;
×
3426
  }
3427

3428
  return ASCENDING_TRAVERSE(order) ? 0 : taosArrayGetSize(pDelSkyline) - 1;
230,443✔
3429
}
3430

3431
int32_t initDelSkylineIterator(STableBlockScanInfo* pBlockScanInfo, int32_t order, SReadCostSummary* pCost) {
29,477,311✔
3432
  int32_t code = TSDB_CODE_SUCCESS;
29,477,311✔
3433
  int32_t lino = 0;
29,477,311✔
3434
  int32_t newDelDataInFile = 0;
29,477,311✔
3435
  int64_t st = 0;
29,477,311✔
3436
  SArray* pSource = NULL;
29,477,311✔
3437

3438
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
29,477,311!
3439

3440
  newDelDataInFile = taosArrayGetSize(pBlockScanInfo->pFileDelData);
29,477,311✔
3441
  if (newDelDataInFile == 0 &&
29,478,042✔
3442
      ((pBlockScanInfo->delSkyline != NULL) || (TARRAY_SIZE(pBlockScanInfo->pMemDelData) == 0))) {
29,393,264✔
3443
    goto _end;
29,249,754✔
3444
  }
3445

3446
  st = taosGetTimestampUs();
230,445✔
3447

3448
  if (pBlockScanInfo->delSkyline != NULL) {
230,445✔
3449
    taosArrayClear(pBlockScanInfo->delSkyline);
40,232✔
3450
  } else {
3451
    pBlockScanInfo->delSkyline = taosArrayInit(4, sizeof(TSDBKEY));
190,213✔
3452
    TSDB_CHECK_NULL(pBlockScanInfo->delSkyline, code, lino, _end, terrno);
190,219!
3453
  }
3454

3455
  pSource = pBlockScanInfo->pFileDelData;
230,451✔
3456
  if (pSource == NULL) {
230,451✔
3457
    pSource = pBlockScanInfo->pMemDelData;
139,393✔
3458
  } else {
3459
    const void* p1 = taosArrayAddAll(pSource, pBlockScanInfo->pMemDelData);
91,058✔
3460
    TSDB_CHECK_NULL(p1, code, lino, _end, terrno);
91,057!
3461
  }
3462

3463
  code = tsdbBuildDeleteSkyline(pSource, 0, taosArrayGetSize(pSource) - 1, pBlockScanInfo->delSkyline);
230,450✔
3464

3465
  taosArrayClear(pBlockScanInfo->pFileDelData);
230,447✔
3466
  int32_t index = getInitialDelIndex(pBlockScanInfo->delSkyline, order);
230,447✔
3467

3468
  pBlockScanInfo->iter.index = index;
230,445✔
3469
  pBlockScanInfo->iiter.index = index;
230,445✔
3470
  pBlockScanInfo->fileDelIndex = index;
230,445✔
3471
  pBlockScanInfo->sttBlockDelIndex = index;
230,445✔
3472
  TSDB_CHECK_CODE(code, lino, _end);
230,445!
3473

3474
  TSDB_CHECK_NULL(pCost, code, lino, _end, TSDB_CODE_INVALID_PARA);
230,445!
3475
  double el = taosGetTimestampUs() - st;
230,447✔
3476
  pCost->createSkylineIterTime = el / 1000.0;
230,447✔
3477

3478
_end:
29,480,201✔
3479
  if (code != TSDB_CODE_SUCCESS) {
29,480,201!
UNCOV
3480
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3481
  }
3482
  return code;
29,477,818✔
3483
}
3484

3485
int32_t getCurrentKeyInBuf(STableBlockScanInfo* pScanInfo, STsdbReader* pReader, TSDBKEY* pkey) {
5,280,718✔
3486
  int32_t  code = TSDB_CODE_SUCCESS;
5,280,718✔
3487
  int32_t  lino = 0;
5,280,718✔
3488
  bool     asc = false;
5,280,718✔
3489
  bool     hasKey = false;
5,280,718✔
3490
  bool     hasIKey = false;
5,280,718✔
3491
  TSDBROW* pRow = NULL;
5,280,718✔
3492
  TSDBROW* pIRow = NULL;
5,280,718✔
3493
  TSDBKEY  key = {.ts = TSKEY_INITIAL_VAL};
5,280,718✔
3494
  TSDBKEY  ikey = {.ts = TSKEY_INITIAL_VAL};
5,280,718✔
3495

3496
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,280,718!
3497
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,280,718!
3498
  TSDB_CHECK_NULL(pkey, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,280,718!
3499

3500
  asc = ASCENDING_TRAVERSE(pReader->info.order);
5,280,718✔
3501

3502
  code = getValidMemRow(&pScanInfo->iter, pScanInfo->delSkyline, pReader, &pRow);
10,561,392✔
3503
  TSDB_CHECK_CODE(code, lino, _end);
5,280,674!
3504
  if (pRow != NULL) {
5,280,674✔
3505
    hasKey = true;
1,893,156✔
3506
    key = TSDBROW_KEY(pRow);
1,893,156!
3507
  }
3508

3509
  code = getValidMemRow(&pScanInfo->iiter, pScanInfo->delSkyline, pReader, &pIRow);
10,561,357✔
3510
  TSDB_CHECK_CODE(code, lino, _end);
5,280,683!
3511
  if (pIRow != NULL) {
5,280,683✔
3512
    hasIKey = true;
151,994✔
3513
    ikey = TSDBROW_KEY(pIRow);
151,994!
3514
  }
3515

3516
  if (hasKey) {
5,280,683✔
3517
    if (hasIKey) {  // has data in mem & imem
1,893,156✔
3518
      if (asc) {
24!
3519
        *pkey = key.ts <= ikey.ts ? key : ikey;
24!
3520
      } else {
UNCOV
3521
        *pkey = key.ts <= ikey.ts ? ikey : key;
×
3522
      }
3523
    } else {  // no data in imem
3524
      *pkey = key;
1,893,132✔
3525
    }
3526
  } else {
3527
    // no data in mem & imem, return the initial value
3528
    // only imem has data, return ikey
3529
    *pkey = ikey;
3,387,527✔
3530
  }
3531

3532
_end:
5,280,683✔
3533
  if (code != TSDB_CODE_SUCCESS) {
5,280,683!
UNCOV
3534
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3535
  }
3536
  return code;
5,280,666✔
3537
}
3538

3539
static void prepareDurationForNextFileSet(STsdbReader* pReader) {
2,076,557✔
3540
  if (pReader->status.bProcMemFirstFileset) {
2,076,557✔
3541
    pReader->status.prevFilesetStartKey = INT64_MIN;
743,696✔
3542
    pReader->status.prevFilesetEndKey = INT64_MAX;
743,696✔
3543
    pReader->status.bProcMemFirstFileset = false;
743,696✔
3544
  }
3545

3546
  int32_t     fid = pReader->status.pCurrentFileset->fid;
2,076,557✔
3547
  STimeWindow winFid = {0};
2,076,557✔
3548
  tsdbFidKeyRange(fid, pReader->pTsdb->keepCfg.days, pReader->pTsdb->keepCfg.precision, &winFid.skey, &winFid.ekey);
2,076,557✔
3549

3550
  if (ASCENDING_TRAVERSE(pReader->info.order)) {
2,075,359✔
3551
    pReader->status.bProcMemPreFileset = !(pReader->status.memTableMaxKey < pReader->status.prevFilesetStartKey ||
3,333,932✔
3552
                                           (winFid.skey - 1) < pReader->status.memTableMinKey);
1,505,321✔
3553
  } else {
3554
    pReader->status.bProcMemPreFileset = !(pReader->status.memTableMaxKey < (winFid.ekey + 1) ||
413,169✔
3555
                                           pReader->status.prevFilesetEndKey < pReader->status.memTableMinKey);
166,421✔
3556
  }
3557

3558
  if (pReader->status.bProcMemPreFileset) {
2,075,359✔
3559
    tsdbDebug("will start pre-fileset %d buffer processing. %s", fid, pReader->idStr);
1,012,452!
3560
    pReader->status.procMemUidList.tableUidList = pReader->status.uidList.tableUidList;
1,012,452✔
3561
    resetPreFilesetMemTableListIndex(&pReader->status);
1,012,452✔
3562
  }
3563

3564
  if (!pReader->status.bProcMemPreFileset) {
2,075,378✔
3565
    if (pReader->notifyFn) {
1,063,062!
3566
      STsdReaderNotifyInfo info = {0};
1,063,078✔
3567
      info.duration.filesetId = fid;
1,063,078✔
3568
      pReader->notifyFn(TSD_READER_NOTIFY_DURATION_START, &info, pReader->notifyParam);
1,063,078✔
3569
      tsdbDebug("new duration %d start notification when no buffer preceeding fileset, %s", fid, pReader->idStr);
1,062,364✔
3570
    }
3571
  }
3572

3573
  pReader->status.prevFilesetStartKey = winFid.skey;
2,075,068✔
3574
  pReader->status.prevFilesetEndKey = winFid.ekey;
2,075,068✔
3575
}
2,075,068✔
3576

3577
static int32_t moveToNextFile(STsdbReader* pReader, SBlockNumber* pBlockNum, SArray* pTableList) {
7,177,293✔
3578
  int32_t        code = TSDB_CODE_SUCCESS;
7,177,293✔
3579
  int32_t        lino = 0;
7,177,293✔
3580
  SReaderStatus* pStatus = NULL;
7,177,293✔
3581
  SArray*        pIndexList = NULL;
7,177,293✔
3582
  size_t         numOfTables = 0;
7,177,293✔
3583

3584
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,177,293!
3585
  TSDB_CHECK_NULL(pBlockNum, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,177,293!
3586

3587
  pStatus = &pReader->status;
7,177,293✔
3588
  pBlockNum->numOfBlocks = 0;
7,177,293✔
3589
  pBlockNum->numOfSttFiles = 0;
7,177,293✔
3590

3591
  numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
7,177,293✔
3592
  pIndexList = taosArrayInit(numOfTables, sizeof(SBrinBlk));
7,178,287✔
3593
  TSDB_CHECK_NULL(pIndexList, code, lino, _end, terrno);
7,177,213!
3594

3595
  while (1) {
3,014✔
3596
    // only check here, since the iterate data in memory is very fast.
3597
    if (pReader->code != TSDB_CODE_SUCCESS) {
7,180,227!
UNCOV
3598
      tsdbWarn("tsdb reader is stopped ASAP, code:%s, %s", tstrerror(pReader->code), pReader->idStr);
×
UNCOV
3599
      code = pReader->code;
×
UNCOV
3600
      TSDB_CHECK_CODE(code, lino, _end);
×
3601
    }
3602

3603
    bool hasNext = false;
7,180,227✔
3604
    code = filesetIteratorNext(&pStatus->fileIter, pReader, &hasNext);
7,180,227✔
3605
    TSDB_CHECK_CODE(code, lino, _end);
7,175,236!
3606

3607
    if (!hasNext) {  // no data files on disk
7,175,236✔
3608
      break;
2,078,822✔
3609
    }
3610

3611
    taosArrayClear(pIndexList);
5,096,414✔
3612
    code = doLoadBlockIndex(pReader, pReader->pFileReader, pIndexList);
5,096,683✔
3613
    TSDB_CHECK_CODE(code, lino, _end);
5,093,324!
3614

3615
    if (taosArrayGetSize(pIndexList) > 0 || pReader->status.pCurrentFileset->lvlArr->size > 0) {
5,093,324✔
3616
      code = loadFileBlockBrinInfo(pReader, pIndexList, pBlockNum, pTableList);
5,092,221✔
3617
      TSDB_CHECK_CODE(code, lino, _end);
5,092,318!
3618

3619
      if (pBlockNum->numOfBlocks + pBlockNum->numOfSttFiles > 0) {
5,092,318✔
3620
        if (pReader->bFilesetDelimited) {
5,092,207✔
3621
          prepareDurationForNextFileSet(pReader);
2,075,192✔
3622
        }
3623
        break;
5,092,817✔
3624
      }
3625
    }
3626

3627
    // no blocks in current file, try next files
3628
  }
3629

3630
  code = loadDataFileTombDataForAll(pReader);
7,171,639✔
3631
  TSDB_CHECK_CODE(code, lino, _end);
7,171,368!
3632

3633
_end:
7,171,368✔
3634
  if (code != TSDB_CODE_SUCCESS) {
7,171,368!
UNCOV
3635
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3636
  }
3637
  if (pIndexList) {
7,171,325!
3638
    taosArrayDestroy(pIndexList);
7,171,325✔
3639
  }
3640
  return code;
7,179,376✔
3641
}
3642

3643
// pTableIter can be NULL, no need to handle the return value
3644
static int32_t resetTableListIndex(SReaderStatus* pStatus, const char* id) {
12,791,944✔
3645
  int32_t        code = TSDB_CODE_SUCCESS;
12,791,944✔
3646
  int32_t        lino = 0;
12,791,944✔
3647
  STableUidList* pList = NULL;
12,791,944✔
3648

3649
  TSDB_CHECK_NULL(pStatus, code, lino, _end, TSDB_CODE_INVALID_PARA);
12,791,944!
3650

3651
  pList = &pStatus->uidList;
12,791,944✔
3652

3653
  pList->currentIndex = 0;
12,791,944✔
3654
  uint64_t uid = pList->tableUidList[0];
12,791,944✔
3655
  pStatus->pTableIter = tSimpleHashGet(pStatus->pTableMap, &uid, sizeof(uid));
12,791,944✔
3656
  if (pStatus->pTableIter == NULL) {
12,797,435!
UNCOV
3657
    tsdbError("%s failed to load tableBlockScanInfo for uid:%" PRId64 ", code: internal error", id, uid);
×
UNCOV
3658
    TSDB_CHECK_NULL(pStatus->pTableIter, code, lino, _end, TSDB_CODE_INTERNAL_ERROR);
×
3659
  }
3660

3661
_end:
12,797,435✔
3662
  if (code != TSDB_CODE_SUCCESS) {
12,797,435!
UNCOV
3663
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3664
  }
3665
  return code;
12,791,540✔
3666
}
3667

3668
static void resetPreFilesetMemTableListIndex(SReaderStatus* pStatus) {
1,012,440✔
3669
  STableUidList* pList = &pStatus->procMemUidList;
1,012,440✔
3670

3671
  pList->currentIndex = 0;
1,012,440✔
3672
  uint64_t uid = pList->tableUidList[0];
1,012,440✔
3673
  pStatus->pProcMemTableIter = tSimpleHashGet(pStatus->pTableMap, &uid, sizeof(uid));
1,012,440✔
3674
}
1,012,470✔
3675

3676
static bool moveToNextTable(STableUidList* pOrderedCheckInfo, SReaderStatus* pStatus) {
22,844,875✔
3677
  pOrderedCheckInfo->currentIndex += 1;
22,844,875✔
3678
  if (pOrderedCheckInfo->currentIndex >= tSimpleHashGetSize(pStatus->pTableMap)) {
22,844,875✔
3679
    pStatus->pTableIter = NULL;
9,450,924✔
3680
    return false;
9,450,924✔
3681
  }
3682

3683
  uint64_t uid = pOrderedCheckInfo->tableUidList[pOrderedCheckInfo->currentIndex];
13,395,098✔
3684
  pStatus->pTableIter = tSimpleHashGet(pStatus->pTableMap, &uid, sizeof(uid));
13,395,098✔
3685
  return (pStatus->pTableIter != NULL);
13,398,400✔
3686
}
3687

3688
static bool moveToNextTableForPreFileSetMem(SReaderStatus* pStatus) {
2,882,189✔
3689
  STableUidList* pUidList = &pStatus->procMemUidList;
2,882,189✔
3690
  pUidList->currentIndex += 1;
2,882,189✔
3691
  if (pUidList->currentIndex >= tSimpleHashGetSize(pStatus->pTableMap)) {
2,882,189✔
3692
    pStatus->pProcMemTableIter = NULL;
1,012,485✔
3693
    return false;
1,012,485✔
3694
  }
3695

3696
  uint64_t uid = pUidList->tableUidList[pUidList->currentIndex];
1,869,709✔
3697
  pStatus->pProcMemTableIter = tSimpleHashGet(pStatus->pTableMap, &uid, sizeof(uid));
1,869,709✔
3698
  return (pStatus->pProcMemTableIter != NULL);
1,869,750✔
3699
}
3700

3701
static int32_t buildCleanBlockFromSttFiles(STsdbReader* pReader, STableBlockScanInfo* pScanInfo) {
15,915✔
3702
  int32_t          code = TSDB_CODE_SUCCESS;
15,915✔
3703
  int32_t          lino = 0;
15,915✔
3704
  SReaderStatus*   pStatus = NULL;
15,915✔
3705
  SSttBlockReader* pSttBlockReader = NULL;
15,915✔
3706
  SSDataBlock*     pResBlock = NULL;
15,915✔
3707
  SDataBlockInfo*  pInfo = NULL;
15,915✔
3708
  bool             asc = false;
15,915✔
3709

3710
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
15,915!
3711
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
15,915!
3712

3713
  pStatus = &pReader->status;
15,915✔
3714
  pSttBlockReader = pStatus->fileIter.pSttBlockReader;
15,915✔
3715
  pResBlock = pReader->resBlockInfo.pResBlock;
15,915✔
3716

3717
  asc = ASCENDING_TRAVERSE(pReader->info.order);
15,915✔
3718
  code = blockDataEnsureCapacity(pResBlock, pScanInfo->numOfRowsInStt);
15,915✔
3719
  TSDB_CHECK_CODE(code, lino, _end);
15,917!
3720

3721
  pInfo = &pResBlock->info;
15,917✔
3722
  pInfo->rows = pScanInfo->numOfRowsInStt;
15,917✔
3723
  pInfo->id.uid = pScanInfo->uid;
15,917✔
3724
  pInfo->dataLoad = 1;
15,917✔
3725
  pInfo->window.skey = pScanInfo->sttRange.skey.ts;
15,917✔
3726
  pInfo->window.ekey = pScanInfo->sttRange.ekey.ts;
15,917✔
3727

3728
  setComposedBlockFlag(pReader, true);
15,917✔
3729

3730
  pScanInfo->sttKeyInfo.nextProcKey.ts = asc ? pScanInfo->sttRange.ekey.ts + 1 : pScanInfo->sttRange.skey.ts - 1;
15,913!
3731
  pScanInfo->sttKeyInfo.status = STT_FILE_NO_DATA;
15,913✔
3732

3733
  if (asc) {
15,913!
3734
    tRowKeyAssign(&pScanInfo->lastProcKey, &pScanInfo->sttRange.ekey);
15,920✔
3735
  } else {
UNCOV
3736
    tRowKeyAssign(&pScanInfo->lastProcKey, &pScanInfo->sttRange.skey);
×
3737
  }
3738

3739
  pScanInfo->sttBlockReturned = true;
15,919✔
3740
  pSttBlockReader->mergeTree.pIter = NULL;
15,919✔
3741

3742
  tsdbDebug("%p uid:%" PRId64 " return clean stt block as one, brange:%" PRId64 "-%" PRId64 " rows:%" PRId64 " %s",
15,919✔
3743
            pReader, pResBlock->info.id.uid, pResBlock->info.window.skey, pResBlock->info.window.ekey,
3744
            pResBlock->info.rows, pReader->idStr);
3745

3746
_end:
15,684✔
3747
  if (code != TSDB_CODE_SUCCESS) {
15,919!
UNCOV
3748
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3749
  }
3750
  return code;
15,918✔
3751
}
3752

3753
static int32_t buildCleanBlockFromDataFiles(STsdbReader* pReader, STableBlockScanInfo* pScanInfo,
5,199,715✔
3754
                                            SFileDataBlockInfo* pBlockInfo, int32_t blockIndex) {
3755
  int32_t         code = TSDB_CODE_SUCCESS;
5,199,715✔
3756
  int32_t         lino = 0;
5,199,715✔
3757
  SReaderStatus*  pStatus = NULL;
5,199,715✔
3758
  SDataBlockInfo* pInfo = NULL;
5,199,715✔
3759
  bool            asc = false;
5,199,715✔
3760

3761
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,199,715!
3762
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,199,715!
3763
  TSDB_CHECK_NULL(pBlockInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,199,715!
3764

3765
  // whole data block is required, return it directly
3766
  pStatus = &pReader->status;
5,199,715✔
3767
  pInfo = &pReader->resBlockInfo.pResBlock->info;
5,199,715✔
3768
  asc = ASCENDING_TRAVERSE(pReader->info.order);
5,199,715✔
3769

3770
  pInfo->rows = pBlockInfo->numRow;
5,199,715✔
3771
  pInfo->id.uid = pScanInfo->uid;
5,199,715✔
3772
  pInfo->dataLoad = 0;
5,199,715✔
3773
  pInfo->version = pReader->info.verRange.maxVer;
5,199,715✔
3774
  pInfo->window = (STimeWindow){.skey = pBlockInfo->firstKey, .ekey = pBlockInfo->lastKey};
5,199,715✔
3775

3776
  if (pReader->suppInfo.numOfPks > 0) {
5,199,715✔
3777
    if (IS_NUMERIC_TYPE(pReader->suppInfo.pk.type)) {
136,427!
3778
      VALUE_SET_TRIVIAL_DATUM(pInfo->pks, pBlockInfo->firstPk.val);
136,427✔
3779
      VALUE_SET_TRIVIAL_DATUM(pInfo->pks + 1, pBlockInfo->lastPk.val);
136,427✔
3780
    } else {
UNCOV
3781
      (void)memcpy(pInfo->pks[0].pData, varDataVal(pBlockInfo->firstPk.pData), varDataLen(pBlockInfo->firstPk.pData));
×
UNCOV
3782
      (void)memcpy(pInfo->pks[1].pData, varDataVal(pBlockInfo->lastPk.pData), varDataLen(pBlockInfo->lastPk.pData));
×
3783

UNCOV
3784
      pInfo->pks[0].nData = varDataLen(pBlockInfo->firstPk.pData);
×
UNCOV
3785
      pInfo->pks[1].nData = varDataLen(pBlockInfo->lastPk.pData);
×
3786
    }
3787
  }
3788

3789
  // update the last key for the corresponding table
3790
  setComposedBlockFlag(pReader, false);
5,199,715✔
3791
  setBlockAllDumped(&pStatus->fBlockDumpInfo, pBlockInfo->lastKey, pReader->info.order);
5,199,637✔
3792
  code = updateLastKeyInfo(&pScanInfo->lastProcKey, pBlockInfo, pInfo, pReader->suppInfo.numOfPks, asc);
5,199,671✔
3793
  TSDB_CHECK_CODE(code, lino, _end);
5,199,675!
3794

3795
  tsdbDebug("%p uid:%" PRIu64
5,199,675✔
3796
            " clean file block retrieved from file, global index:%d, "
3797
            "table index:%d, rows:%d, brange:%" PRId64 "-%" PRId64 ", %s",
3798
            pReader, pScanInfo->uid, blockIndex, pBlockInfo->tbBlockIdx, pBlockInfo->numRow, pBlockInfo->firstKey,
3799
            pBlockInfo->lastKey, pReader->idStr);
3800

3801
_end:
5,188,207✔
3802
  if (code != TSDB_CODE_SUCCESS) {
5,199,675!
UNCOV
3803
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3804
  }
3805
  return code;
5,199,651✔
3806
}
3807

3808
static int32_t doLoadSttBlockSequentially(STsdbReader* pReader) {
9,061,664✔
3809
  int32_t              code = TSDB_CODE_SUCCESS;
9,061,664✔
3810
  int32_t              lino = 0;
9,061,664✔
3811
  SReaderStatus*       pStatus = NULL;
9,061,664✔
3812
  SSttBlockReader*     pSttBlockReader = NULL;
9,061,664✔
3813
  STableUidList*       pUidList = NULL;
9,061,664✔
3814
  SSDataBlock*         pResBlock = NULL;
9,061,664✔
3815
  STableBlockScanInfo* pScanInfo = NULL;
9,061,664✔
3816

3817
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
9,061,664!
3818

3819
  pStatus = &pReader->status;
9,061,664✔
3820
  pSttBlockReader = pStatus->fileIter.pSttBlockReader;
9,061,664✔
3821
  pUidList = &pStatus->uidList;
9,061,664✔
3822

3823
  if (tSimpleHashGetSize(pStatus->pTableMap) == 0) {
9,061,664!
3824
    goto _end;
×
3825
  }
3826

3827
  pResBlock = pReader->resBlockInfo.pResBlock;
9,059,503✔
3828

3829
  while (1) {
6,226,562✔
3830
    if (pReader->code != TSDB_CODE_SUCCESS) {
15,286,065!
UNCOV
3831
      tsdbWarn("tsdb reader is stopped ASAP, code:%s, %s", tstrerror(pReader->code), pReader->idStr);
×
UNCOV
3832
      code = pReader->code;
×
UNCOV
3833
      TSDB_CHECK_CODE(code, lino, _end);
×
3834
    }
3835

3836
    // load the last data block of current table
3837
    if (pStatus->pTableIter == NULL) {
15,282,473!
UNCOV
3838
      tsdbError("table Iter is null, invalid pScanInfo, try next table %s", pReader->idStr);
×
UNCOV
3839
      bool hasNexTable = moveToNextTable(pUidList, pStatus);
×
UNCOV
3840
      if (!hasNexTable) {
×
UNCOV
3841
        break;
×
3842
      }
3843

UNCOV
3844
      continue;
×
3845
    } else {
3846
      pScanInfo = *(STableBlockScanInfo**)pStatus->pTableIter;
15,282,473✔
3847
    }
3848

3849
    if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &pScanInfo->uid, sizeof(pScanInfo->uid))) {
15,282,473✔
3850
      // reset the index in last block when handing a new file
3851
      bool hasNexTable = moveToNextTable(pUidList, pStatus);
31,638✔
3852
      if (!hasNexTable) {
31,634✔
3853
        break;
590✔
3854
      }
3855

3856
      continue;
31,044✔
3857
    }
3858

3859
    initSttBlockReader(pSttBlockReader, pScanInfo, pReader);
15,248,327✔
3860
    code = pReader->code;
15,260,405✔
3861
    TSDB_CHECK_CODE(code, lino, _end);
15,260,405!
3862

3863
    if (!hasDataInSttBlock(pScanInfo)) {
15,260,405✔
3864
      bool hasNexTable = moveToNextTable(pUidList, pStatus);
11,255,905✔
3865
      if (!hasNexTable) {
11,255,940✔
3866
        break;
5,060,422✔
3867
      }
3868

3869
      continue;
6,195,518✔
3870
    }
3871

3872
    // if only require the total rows, no need to load data from stt file if it is clean stt blocks
3873
    if (pReader->info.execMode == READER_EXEC_ROWS && pScanInfo->cleanSttBlocks) {
4,004,902✔
3874
      code = buildCleanBlockFromSttFiles(pReader, pScanInfo);
15,932✔
3875
      TSDB_CHECK_CODE(code, lino, _end);
15,917!
3876
      break;
15,917✔
3877
    }
3878

3879
    int64_t st = taosGetTimestampUs();
3,990,344✔
3880
    while (1) {
3881
      // no data in stt block and block, no need to proceed.
3882
      if (!hasDataInSttBlock(pScanInfo)) {
493,420,490✔
3883
        break;
3,945,909✔
3884
      }
3885

3886
      code = buildComposedDataBlockImpl(pReader, pScanInfo, &pReader->status.fileBlockData, pSttBlockReader);
488,956,686✔
3887
      TSDB_CHECK_CODE(code, lino, _end);
489,474,778!
3888

3889
      if (pResBlock->info.rows >= pReader->resBlockInfo.capacity) {
489,474,778✔
3890
        break;
44,632✔
3891
      }
3892
    }
3893

3894
    double el = (taosGetTimestampUs() - st) / 1000.0;
3,990,922✔
3895
    updateComposedBlockInfo(pReader, el, pScanInfo);
3,990,922✔
3896

3897
    if (pResBlock->info.rows > 0) {
3,989,539!
3898
      tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 " rows:%" PRId64
3,990,005✔
3899
                ", elapsed time:%.2f ms %s",
3900
                pReader, pResBlock->info.id.uid, pResBlock->info.window.skey, pResBlock->info.window.ekey,
3901
                pResBlock->info.rows, el, pReader->idStr);
3902
      break;
3,990,477✔
3903
    }
3904

3905
    // current table is exhausted, let's try next table
UNCOV
3906
    bool hasNexTable = moveToNextTable(pUidList, pStatus);
×
UNCOV
3907
    if (!hasNexTable) {
×
UNCOV
3908
      break;
×
3909
    }
3910
  }
3911

3912
_end:
9,067,406✔
3913
  if (code != TSDB_CODE_SUCCESS) {
9,067,406!
UNCOV
3914
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3915
  }
3916
  return code;
9,065,428✔
3917
}
3918

3919
// current active data block not overlap with the stt-files/stt-blocks
3920
static bool notOverlapWithFiles(SFileDataBlockInfo* pBlockInfo, STableBlockScanInfo* pScanInfo, bool asc) {
5,200,306✔
3921
  if ((!hasDataInSttBlock(pScanInfo)) || (pScanInfo->cleanSttBlocks == true)) {
5,200,306✔
3922
    return true;
3,498,291✔
3923
  } else {
3924
    int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey.ts;
1,702,081✔
3925
    return (asc && pBlockInfo->lastKey < keyInStt) || (!asc && pBlockInfo->firstKey > keyInStt);
1,702,081!
3926
  }
3927
}
3928

3929
static int32_t doBuildDataBlock(STsdbReader* pReader) {
5,240,671✔
3930
  int32_t              code = TSDB_CODE_SUCCESS;
5,240,671✔
3931
  int32_t              lino = 0;
5,240,671✔
3932
  SReaderStatus*       pStatus = NULL;
5,240,671✔
3933
  SDataBlockIter*      pBlockIter = NULL;
5,240,671✔
3934
  STableBlockScanInfo* pScanInfo = NULL;
5,240,671✔
3935
  SFileDataBlockInfo*  pBlockInfo = NULL;
5,240,671✔
3936
  SSttBlockReader*     pSttBlockReader = NULL;
5,240,671✔
3937
  TSDBKEY              keyInBuf;
3938
  bool                 asc = false;
5,240,671✔
3939

3940
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,240,671!
3941

3942
  pStatus = &pReader->status;
5,240,671✔
3943
  pBlockIter = &pStatus->blockIter;
5,240,671✔
3944
  pSttBlockReader = pReader->status.fileIter.pSttBlockReader;
5,240,671✔
3945
  asc = ASCENDING_TRAVERSE(pReader->info.order);
5,240,671✔
3946

3947
  code = getCurrentBlockInfo(pBlockIter, &pBlockInfo, pReader->idStr);
5,240,671✔
3948
  TSDB_CHECK_CODE(code, lino, _end);
5,240,736!
3949

3950
  if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &pBlockInfo->uid, sizeof(pBlockInfo->uid))) {
5,240,736✔
3951
    setBlockAllDumped(&pStatus->fBlockDumpInfo, pBlockInfo->lastKey, pReader->info.order);
8✔
3952
    goto _end;
18✔
3953
  }
3954

3955
  code = pReader->code;
5,240,689✔
3956
  TSDB_CHECK_CODE(code, lino, _end);
5,240,689!
3957

3958
  code = getTableBlockScanInfo(pReader->status.pTableMap, pBlockInfo->uid, &pScanInfo, pReader->idStr);
5,240,689✔
3959
  TSDB_CHECK_CODE(code, lino, _end);
5,240,696!
3960

3961
  if (pScanInfo->sttKeyInfo.status == STT_FILE_READER_UNINIT) {
5,240,696✔
3962
    initSttBlockReader(pSttBlockReader, pScanInfo, pReader);
389,804✔
3963
    code = pReader->code;
389,869✔
3964
    TSDB_CHECK_CODE(code, lino, _end);
389,869!
3965
  }
3966

3967
  code = getCurrentKeyInBuf(pScanInfo, pReader, &keyInBuf);
5,240,761✔
3968
  TSDB_CHECK_CODE(code, lino, _end);
5,240,637!
3969
  bool load = false;
5,240,637✔
3970
  code = fileBlockShouldLoad(pReader, pBlockInfo, pScanInfo, keyInBuf, &load);
5,240,637✔
3971
  TSDB_CHECK_CODE(code, lino, _end);
5,240,642!
3972
  if (load) {
5,240,642✔
3973
    code = doLoadFileBlockData(pReader, pBlockIter, &pStatus->fileBlockData, pScanInfo->uid);
40,021✔
3974
    TSDB_CHECK_CODE(code, lino, _end);
40,027!
3975

3976
    // build composed data block
3977
    code = buildComposedDataBlock(pReader);
40,027✔
3978
    TSDB_CHECK_CODE(code, lino, _end);
40,021!
3979
  } else if (bufferDataInFileBlockGap(keyInBuf, pBlockInfo, pScanInfo, pReader->info.order)) {
5,200,621✔
3980
    // data in memory that are earlier than current file block and stt blocks
3981
    // rows in buffer should be less than the file block in asc, greater than file block in desc
3982
    int64_t endKey = getBoarderKeyInFiles(pBlockInfo, pScanInfo, pReader->info.order);
201✔
3983
    code = buildDataBlockFromBuf(pReader, pScanInfo, endKey);
201✔
3984
    TSDB_CHECK_CODE(code, lino, _end);
201!
3985
  } else {
3986
    if (notOverlapWithFiles(pBlockInfo, pScanInfo, asc)) {
5,200,424✔
3987
      int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey.ts;
5,199,793✔
3988

3989
      if ((!hasDataInSttBlock(pScanInfo)) || (asc && pBlockInfo->lastKey < keyInStt) ||
5,199,793!
UNCOV
3990
          (!asc && pBlockInfo->firstKey > keyInStt)) {
×
3991
        // the stt blocks may located in the gap of different data block, but the whole sttRange may overlap with the
3992
        // data block, so the overlap check is invalid actually.
3993
        code = buildCleanBlockFromDataFiles(pReader, pScanInfo, pBlockInfo, pBlockIter->index);
5,199,810✔
3994
        TSDB_CHECK_CODE(code, lino, _end);
5,199,662!
3995
      } else {  // clean stt block
UNCOV
3996
        TSDB_CHECK_CONDITION((pReader->info.execMode == READER_EXEC_ROWS) && (pSttBlockReader->mergeTree.pIter == NULL),
×
3997
                             code, lino, _end, TSDB_CODE_INTERNAL_ERROR);
UNCOV
3998
        code = buildCleanBlockFromSttFiles(pReader, pScanInfo);
×
UNCOV
3999
        TSDB_CHECK_CODE(code, lino, _end);
×
4000
      }
4001
    } else {
4002
      SBlockData* pBData = &pReader->status.fileBlockData;
578✔
4003
      tBlockDataReset(pBData);
578✔
4004

4005
      SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock;
603✔
4006

4007
      tsdbDebug("load data in stt block firstly %s", pReader->idStr);
603!
4008
      int64_t st = taosGetTimestampUs();
603✔
4009

4010
      // let's load data from stt files, make sure clear the cleanStt block flag before load the data from stt files
4011
      initSttBlockReader(pSttBlockReader, pScanInfo, pReader);
603✔
4012
      code = pReader->code;
603✔
4013
      TSDB_CHECK_CODE(code, lino, _end);
603!
4014

4015
      // no data in stt block, no need to proceed.
4016
      while (hasDataInSttBlock(pScanInfo)) {
2,460,003✔
4017
        TSDB_CHECK_CONDITION(pScanInfo->sttKeyInfo.status == STT_FILE_HAS_DATA, code, lino, _end,
2,460,000!
4018
                             TSDB_CODE_INTERNAL_ERROR);
4019

4020
        code = buildComposedDataBlockImpl(pReader, pScanInfo, &pReader->status.fileBlockData, pSttBlockReader);
2,460,000✔
4021
        TSDB_CHECK_CODE(code, lino, _end);
2,460,000!
4022

4023
        if (pResBlock->info.rows >= pReader->resBlockInfo.capacity) {
2,460,000✔
4024
          break;
600✔
4025
        }
4026

4027
        // data in stt now overlaps with current active file data block, need to composed with file data block.
4028
        SRowKey* pSttKey = getCurrentKeyInSttBlock(pSttBlockReader);
2,459,400✔
4029
        if ((pSttKey->ts >= pBlockInfo->firstKey && asc) || (pSttKey->ts <= pBlockInfo->lastKey && (!asc))) {
2,459,400!
UNCOV
4030
          tsdbDebug("%p lastKeyInStt:%" PRId64 ", overlap with file block, brange:%" PRId64 "-%" PRId64 " %s", pReader,
×
4031
                    pSttKey->ts, pBlockInfo->firstKey, pBlockInfo->lastKey, pReader->idStr);
UNCOV
4032
          break;
×
4033
        }
4034
      }
4035

4036
      double el = (taosGetTimestampUs() - st) / 1000.0;
603✔
4037
      updateComposedBlockInfo(pReader, el, pScanInfo);
603✔
4038

4039
      if (pResBlock->info.rows > 0) {
603!
4040
        tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 " rows:%" PRId64
603!
4041
                  ", elapsed time:%.2f ms %s",
4042
                  pReader, pResBlock->info.id.uid, pResBlock->info.window.skey, pResBlock->info.window.ekey,
4043
                  pResBlock->info.rows, el, pReader->idStr);
4044
      }
4045
    }
4046
  }
4047

4048
  code = pReader->code;
5,240,457✔
4049
  TSDB_CHECK_CODE(code, lino, _end);
5,240,457!
4050

4051
_end:
5,240,457✔
4052
  if (code != TSDB_CODE_SUCCESS) {
5,240,475!
UNCOV
4053
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4054
  }
4055
  return code;
5,240,491✔
4056
}
4057

4058
static int32_t buildBlockFromBufferSeqForPreFileset(STsdbReader* pReader, int64_t endKey) {
1,233,634✔
4059
  int32_t        code = TSDB_CODE_SUCCESS;
1,233,634✔
4060
  int32_t        lino = 0;
1,233,634✔
4061
  SReaderStatus* pStatus = NULL;
1,233,634✔
4062

4063
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,233,634!
4064

4065
  pStatus = &pReader->status;
1,233,634✔
4066

4067
  tsdbDebug("seq load data blocks from cache that preceeds fileset %d, %s", pReader->status.pCurrentFileset->fid,
1,233,634!
4068
            pReader->idStr);
4069

4070
  while (1) {
1,869,724✔
4071
    if (pReader->code != TSDB_CODE_SUCCESS) {
3,103,378!
UNCOV
4072
      tsdbWarn("tsdb reader is stopped ASAP, code:%s, %s", tstrerror(pReader->code), pReader->idStr);
×
UNCOV
4073
      code = pReader->code;
×
UNCOV
4074
      TSDB_CHECK_CODE(code, lino, _end);
×
4075
    }
4076

4077
    STableBlockScanInfo** pBlockScanInfo = pStatus->pProcMemTableIter;
3,103,378✔
4078
    if (pReader->pIgnoreTables &&
6,206,767✔
4079
        taosHashGet(*pReader->pIgnoreTables, &(*pBlockScanInfo)->uid, sizeof((*pBlockScanInfo)->uid))) {
3,103,372✔
4080
      bool hasNexTable = moveToNextTableForPreFileSetMem(pStatus);
2,316✔
4081
      if (!hasNexTable) {
2,316!
UNCOV
4082
        break;
×
4083
      }
4084
      continue;
2,316✔
4085
    }
4086

4087
    code = initMemDataIterator(*pBlockScanInfo, pReader);
3,101,079✔
4088
    TSDB_CHECK_CODE(code, lino, _end);
3,101,078!
4089

4090
    code = initDelSkylineIterator(*pBlockScanInfo, pReader->info.order, &pReader->cost);
3,101,078✔
4091
    TSDB_CHECK_CODE(code, lino, _end);
3,101,045!
4092

4093
    code = buildDataBlockFromBuf(pReader, *pBlockScanInfo, endKey);
3,101,045✔
4094
    TSDB_CHECK_CODE(code, lino, _end);
3,101,073!
4095

4096
    if (pReader->resBlockInfo.pResBlock->info.rows > 0) {
3,101,073✔
4097
      break;
221,195✔
4098
    }
4099

4100
    // current table is exhausted, let's try next table
4101
    bool hasNexTable = moveToNextTableForPreFileSetMem(pStatus);
2,879,878✔
4102
    if (!hasNexTable) {
2,879,893✔
4103
      break;
1,012,485✔
4104
    }
4105
  }
4106

4107
_end:
1,233,680✔
4108
  if (code != TSDB_CODE_SUCCESS) {
1,233,680!
UNCOV
4109
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4110
  }
4111
  return code;
1,233,674✔
4112
}
4113

4114
static int32_t buildBlockFromBufferSequentially(STsdbReader* pReader, int64_t endKey) {
7,659,779✔
4115
  int32_t        code = TSDB_CODE_SUCCESS;
7,659,779✔
4116
  int32_t        lino = 0;
7,659,779✔
4117
  SReaderStatus* pStatus = NULL;
7,659,779✔
4118
  STableUidList* pUidList = NULL;
7,659,779✔
4119

4120
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,659,779!
4121

4122
  pStatus = &pReader->status;
7,659,779✔
4123
  pUidList = &pStatus->uidList;
7,659,779✔
4124

4125
  tsdbDebug("seq load data blocks from cache, %s", pReader->idStr);
7,659,779✔
4126

4127
  while (1) {
7,170,074✔
4128
    if (pReader->code != TSDB_CODE_SUCCESS) {
14,829,424!
UNCOV
4129
      tsdbWarn("tsdb reader is stopped ASAP, code:%s, %s", tstrerror(pReader->code), pReader->idStr);
×
4130
      code = pReader->code;
1,873✔
4131
      TSDB_CHECK_CODE(code, lino, _end);
1,873!
4132
    }
4133

4134
    STableBlockScanInfo** pBlockScanInfo = pStatus->pTableIter;
14,831,297✔
4135
    if (pBlockScanInfo == NULL || *pBlockScanInfo == NULL) {
14,831,297!
4136
      break;
4137
    }
4138

4139
    if (pReader->pIgnoreTables &&
29,600,777✔
4140
        taosHashGet(*pReader->pIgnoreTables, &(*pBlockScanInfo)->uid, sizeof((*pBlockScanInfo)->uid))) {
14,774,472✔
4141
      bool hasNexTable = moveToNextTable(pUidList, pStatus);
54,326✔
4142
      if (!hasNexTable) {
54,342✔
4143
        break;
1,270✔
4144
      }
4145
      continue;
53,072✔
4146
    }
4147

4148
    code = initMemDataIterator(*pBlockScanInfo, pReader);
14,771,979✔
4149
    TSDB_CHECK_CODE(code, lino, _end);
14,781,683!
4150

4151
    code = initDelSkylineIterator(*pBlockScanInfo, pReader->info.order, &pReader->cost);
14,781,683✔
4152
    TSDB_CHECK_CODE(code, lino, _end);
14,780,248!
4153

4154
    code = buildDataBlockFromBuf(pReader, *pBlockScanInfo, endKey);
14,780,248✔
4155
    TSDB_CHECK_CODE(code, lino, _end);
14,780,896✔
4156

4157
    if (pReader->resBlockInfo.pResBlock->info.rows > 0) {
14,780,892✔
4158
      break;
3,277,457✔
4159
    }
4160

4161
    // current table is exhausted, let's try next table
4162
    bool hasNexTable = moveToNextTable(pUidList, pStatus);
11,503,435✔
4163
    if (!hasNexTable) {
11,505,768✔
4164
      break;
4,388,766✔
4165
    }
4166
  }
4167

UNCOV
4168
_end:
×
4169
  if (code != TSDB_CODE_SUCCESS) {
7,666,168✔
4170
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
4171
  }
4172
  return code;
7,667,213✔
4173
}
4174

4175
// set the correct start position in case of the first/last file block, according to the query time window
4176
static int32_t initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter) {
10,170,132✔
4177
  int32_t             code = TSDB_CODE_SUCCESS;
10,170,132✔
4178
  int32_t             lino = 0;
10,170,132✔
4179
  SFileDataBlockInfo* pBlockInfo = NULL;
10,170,132✔
4180
  SReaderStatus*      pStatus = NULL;
10,170,132✔
4181
  SFileBlockDumpInfo* pDumpInfo = NULL;
10,170,132✔
4182

4183
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
10,170,132!
4184

4185
  pStatus = &pReader->status;
10,170,132✔
4186
  pDumpInfo = &pStatus->fBlockDumpInfo;
10,170,132✔
4187

4188
  code = getCurrentBlockInfo(pBlockIter, &pBlockInfo, pReader->idStr);
10,170,132✔
4189
  if (code == TSDB_CODE_SUCCESS) {
10,170,037✔
4190
    pDumpInfo->totalRows = pBlockInfo->numRow;
5,239,932✔
4191
    pDumpInfo->rowIndex = ASCENDING_TRAVERSE(pReader->info.order) ? 0 : pBlockInfo->numRow - 1;
5,239,932✔
4192
  } else {
4193
    pDumpInfo->totalRows = 0;
4,930,105✔
4194
    pDumpInfo->rowIndex = 0;
4,930,105✔
4195
    code = TSDB_CODE_SUCCESS;
4,930,105✔
4196
  }
4197

4198
  pDumpInfo->allDumped = false;
10,170,037✔
4199

4200
_end:
10,170,037✔
4201
  if (code != TSDB_CODE_SUCCESS) {
10,170,037!
UNCOV
4202
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4203
  }
4204
  return code;
10,169,216✔
4205
}
4206

4207
static int32_t initForFirstBlockInFile(STsdbReader* pReader, SDataBlockIter* pBlockIter) {
7,175,902✔
4208
  int32_t      code = TSDB_CODE_SUCCESS;
7,175,902✔
4209
  int32_t      lino = 0;
7,175,902✔
4210
  SBlockNumber num = {0};
7,175,902✔
4211
  SArray*      pTableList = NULL;
7,175,902✔
4212

4213
  pTableList = taosArrayInit(40, POINTER_BYTES);
7,175,902✔
4214
  TSDB_CHECK_NULL(pTableList, code, lino, _end, terrno);
7,177,270!
4215

4216
  code = moveToNextFile(pReader, &num, pTableList);
7,177,270✔
4217
  TSDB_CHECK_CODE(code, lino, _end);
7,176,046!
4218

4219
  // all data files are consumed, try data in buffer
4220
  if (num.numOfBlocks + num.numOfSttFiles == 0) {
7,176,046✔
4221
    pReader->status.loadFromFile = false;
2,079,783✔
4222
    goto _end;
2,079,783✔
4223
  }
4224

4225
  // initialize the block iterator for a new fileset
4226
  if (num.numOfBlocks > 0) {
5,096,263✔
4227
    code = initBlockIterator(pReader, pBlockIter, num.numOfBlocks, pTableList);
160,707✔
4228
    TSDB_CHECK_CODE(code, lino, _end);
160,668!
4229
  } else {  // no block data, only last block exists
4230
    tBlockDataReset(&pReader->status.fileBlockData);
4,935,556✔
4231
    code = resetDataBlockIterator(pBlockIter, pReader->info.order, shouldFreePkBuf(&pReader->suppInfo), pReader->idStr);
4,928,776✔
4232
    TSDB_CHECK_CODE(code, lino, _end);
4,934,622!
4233

4234
    code = resetTableListIndex(&pReader->status, pReader->idStr);
4,934,622✔
4235
    TSDB_CHECK_CODE(code, lino, _end);
4,933,935!
4236
  }
4237

4238
  code = initBlockDumpInfo(pReader, pBlockIter);
5,094,603✔
4239
  TSDB_CHECK_CODE(code, lino, _end);
5,091,116!
4240

4241
_end:
5,091,116✔
4242
  if (code != TSDB_CODE_SUCCESS) {
7,170,899!
UNCOV
4243
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4244
  }
4245
  if (pTableList) {
7,170,363!
4246
    taosArrayDestroy(pTableList);
7,170,363✔
4247
  }
4248
  return code;
7,179,525✔
4249
}
4250

4251
static bool fileBlockPartiallyRead(SFileBlockDumpInfo* pDumpInfo, bool asc) {
5,285,002✔
4252
  return (!pDumpInfo->allDumped) &&
5,331,352✔
4253
         ((pDumpInfo->rowIndex > 0 && asc) || (pDumpInfo->rowIndex < (pDumpInfo->totalRows - 1) && (!asc)));
46,350!
4254
}
4255

4256
typedef enum {
4257
  TSDB_READ_RETURN = 0x1,
4258
  TSDB_READ_CONTINUE = 0x2,
4259
} ERetrieveType;
4260

4261
static int32_t doReadDataFromSttFiles(STsdbReader* pReader, ERetrieveType* pReturnType) {
5,885,853✔
4262
  int32_t         code = TSDB_CODE_SUCCESS;
5,885,853✔
4263
  int32_t         lino = 0;
5,885,853✔
4264
  SSDataBlock*    pResBlock = NULL;
5,885,853✔
4265
  SDataBlockIter* pBlockIter = NULL;
5,885,853✔
4266

4267
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,885,853!
4268
  TSDB_CHECK_NULL(pReturnType, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,885,853!
4269

4270
  pResBlock = pReader->resBlockInfo.pResBlock;
5,885,853✔
4271
  pBlockIter = &pReader->status.blockIter;
5,885,853✔
4272

4273
  *pReturnType = TSDB_READ_RETURN;
5,885,853✔
4274

4275
  tsdbDebug("seq load data blocks from stt files %s", pReader->idStr);
5,885,853✔
4276

4277
  while (1) {
4278
    code = doLoadSttBlockSequentially(pReader);
9,061,319✔
4279
    TSDB_CHECK_CODE(code, lino, _end);
9,065,273!
4280

4281
    if (pResBlock->info.rows > 0) {
9,065,273✔
4282
      goto _end;
4,006,827✔
4283
    }
4284

4285
    // all data blocks are checked in this stt file, now let's try the next file set
4286
    TSDB_CHECK_CONDITION(pReader->status.pTableIter == NULL, code, lino, _end, TSDB_CODE_INTERNAL_ERROR);
5,058,446!
4287

4288
    code = initForFirstBlockInFile(pReader, pBlockIter);
5,058,446✔
4289
    TSDB_CHECK_CODE(code, lino, _end);
5,061,275!
4290

4291
    // all the data files are completely checked
4292
    if (pReader->status.loadFromFile == false) {
5,061,275✔
4293
      goto _end;
1,621,239✔
4294
    }
4295

4296
    if (pReader->status.bProcMemPreFileset) {
3,440,036✔
4297
      code = buildFromPreFilesetBuffer(pReader);
956,904✔
4298
      TSDB_CHECK_CODE(code, lino, _end);
956,914!
4299
      if (pResBlock->info.rows > 0) {
956,914✔
4300
        pReader->status.processingMemPreFileSet = true;
146,393✔
4301
        goto _end;
146,393✔
4302
      }
4303
    }
4304

4305
    if (pBlockIter->numOfBlocks > 0) {  // there are data blocks existed.
3,293,653✔
4306
      *pReturnType = TSDB_READ_CONTINUE;
115,106✔
4307
      goto _end;
115,106✔
4308
    } else {  // all blocks in data file are checked, let's check the data in stt-files
4309
      code = resetTableListIndex(&pReader->status, pReader->idStr);
3,178,547✔
4310
      TSDB_CHECK_CODE(code, lino, _end);
3,178,433!
4311
    }
4312
  }
4313

4314
_end:
5,889,565✔
4315
  if (code != TSDB_CODE_SUCCESS) {
5,889,565!
UNCOV
4316
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4317
  }
4318
  return code;
5,888,519✔
4319
}
4320

4321
static int32_t buildBlockFromFiles(STsdbReader* pReader) {
10,997,171✔
4322
  int32_t             code = TSDB_CODE_SUCCESS;
10,997,171✔
4323
  int32_t             lino = 0;
10,997,171✔
4324
  SDataBlockIter*     pBlockIter = NULL;
10,997,171✔
4325
  SSDataBlock*        pResBlock = NULL;
10,997,171✔
4326
  SFileBlockDumpInfo* pDumpInfo = NULL;
10,997,171✔
4327
  SBlockData*         pBlockData = NULL;
10,997,171✔
4328
  const char*         id = NULL;
10,997,171✔
4329
  bool                asc = false;
10,997,171✔
4330

4331
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
10,997,171!
4332

4333
  asc = ASCENDING_TRAVERSE(pReader->info.order);
10,997,171✔
4334

4335
  pBlockIter = &pReader->status.blockIter;
10,997,171✔
4336
  pResBlock = pReader->resBlockInfo.pResBlock;
10,997,171✔
4337
  pDumpInfo = &pReader->status.fBlockDumpInfo;
10,997,171✔
4338
  pBlockData = &pReader->status.fileBlockData;
10,997,171✔
4339
  id = pReader->idStr;
10,997,171✔
4340

4341
  if (pBlockIter->numOfBlocks == 0) {
10,997,171✔
4342
    // let's try to extract data from stt files.
4343
    ERetrieveType type = 0;
5,724,085✔
4344
    code = doReadDataFromSttFiles(pReader, &type);
5,724,085✔
4345
    TSDB_CHECK_CODE(code, lino, _end);
11,457,364!
4346
    if (type == TSDB_READ_RETURN) {
5,728,380!
4347
      goto _end;
5,728,750✔
4348
    }
4349

UNCOV
4350
    code = doBuildDataBlock(pReader);
×
4351
    TSDB_CHECK_CODE(code, lino, _end);
438!
4352
    if (pResBlock->info.rows > 0) {
438✔
4353
      goto _end;
234✔
4354
    }
4355
  }
4356

4357
  while (1) {
4358
    if (fileBlockPartiallyRead(pDumpInfo, asc)) {  // file data block is partially loaded
5,288,020✔
4359
      code = buildComposedDataBlock(pReader);
4✔
4360
      TSDB_CHECK_CODE(code, lino, _end);
4!
4361
    } else {
4362
      // current block are exhausted, try the next file block
4363
      if (pDumpInfo->allDumped) {
5,285,001✔
4364
        // try next data block in current file
4365
        bool hasNext = blockIteratorNext(&pReader->status.blockIter);
5,238,686✔
4366
        if (hasNext) {  // check for the next block in the block accessed order list
5,238,702✔
4367
          code = initBlockDumpInfo(pReader, pBlockIter);
5,079,350✔
4368
          TSDB_CHECK_CODE(code, lino, _end);
5,079,351!
4369
        } else {
4370
          // all data blocks in files are checked, let's check the data in last files.
4371
          // data blocks in current file are exhausted, let's try the next file now
4372
          if (pBlockData->uid != 0) {
159,352✔
4373
            tBlockDataClear(pBlockData);
159,286✔
4374
          }
4375

4376
          tBlockDataReset(pBlockData);
159,341✔
4377
          code = resetDataBlockIterator(pBlockIter, pReader->info.order, shouldFreePkBuf(&pReader->suppInfo), id);
159,540✔
4378
          TSDB_CHECK_CODE(code, lino, _end);
159,478!
4379

4380
          code = resetTableListIndex(&pReader->status, id);
159,478✔
4381
          TSDB_CHECK_CODE(code, lino, _end);
159,480!
4382

4383
          ERetrieveType type = 0;
159,480✔
4384
          code = doReadDataFromSttFiles(pReader, &type);
159,480✔
4385
          TSDB_CHECK_CODE(code, lino, _end);
159,494!
4386
          if (type == TSDB_READ_RETURN) {
159,494✔
4387
            break;
44,851✔
4388
          }
4389
        }
4390
      }
4391

4392
      code = doBuildDataBlock(pReader);
5,240,309✔
4393
      TSDB_CHECK_CODE(code, lino, _end);
5,240,047!
4394
    }
4395

4396
    if (pResBlock->info.rows > 0) {
5,240,051✔
4397
      break;
5,225,321✔
4398
    }
4399
  }
4400

4401
_end:
10,999,156✔
4402
  if (code != TSDB_CODE_SUCCESS) {
10,999,156!
UNCOV
4403
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4404
  }
4405
  return code;
10,997,352✔
4406
}
4407

4408
static void getTsdbByRetentions(SVnode* pVnode, SQueryTableDataCond* pCond, SRetention* retentions, const char* idStr,
4,682,744✔
4409
                                int8_t* pLevel, STsdb** pTsdb) {
4410
  if (pTsdb == NULL) {
4,682,744!
4411
    return;
×
4412
  }
4413

4414
  *pTsdb = NULL;
4,682,744✔
4415
  if (VND_IS_RSMA(pVnode) && !pCond->skipRollup) {
4,682,744✔
4416
    int8_t  level = 0;
38✔
4417
    int8_t  precision = pVnode->config.tsdbCfg.precision;
38✔
4418
    int64_t now = taosGetTimestamp(precision);
38!
4419
    int64_t offset = tsQueryRsmaTolerance * ((precision == TSDB_TIME_PRECISION_MILLI)   ? 1L
76✔
4420
                                             : (precision == TSDB_TIME_PRECISION_MICRO) ? 1000L
38!
UNCOV
4421
                                                                                        : 1000000L);
×
4422

4423
    for (int32_t i = 0; i < TSDB_RETENTION_MAX; ++i) {
91✔
4424
      SRetention* pRetention = retentions + level;
79✔
4425
      if (pRetention->keep <= 0) {
79!
UNCOV
4426
        if (level > 0) {
×
UNCOV
4427
          --level;
×
4428
        }
UNCOV
4429
        break;
×
4430
      }
4431
      if ((now - pRetention->keep) <= (pCond->twindows.skey + offset)) {
79✔
4432
        break;
26✔
4433
      }
4434
      ++level;
53✔
4435
    }
4436

4437
    const char* str = (idStr != NULL) ? idStr : "";
38!
4438

4439
    if (level == TSDB_RETENTION_L0) {
38✔
4440
      *pLevel = TSDB_RETENTION_L0;
11✔
4441
      tsdbDebug("vgId:%d, rsma level %d is selected to query %s", TD_VID(pVnode), TSDB_RETENTION_L0, str);
11!
4442
      *pTsdb = VND_RSMA0(pVnode);
11✔
4443
      return;
11✔
4444
    } else if (level == TSDB_RETENTION_L1) {
27✔
4445
      *pLevel = TSDB_RETENTION_L1;
13✔
4446
      tsdbDebug("vgId:%d, rsma level %d is selected to query %s", TD_VID(pVnode), TSDB_RETENTION_L1, str);
13!
4447
      *pTsdb = VND_RSMA1(pVnode);
13✔
4448
      return;
13✔
4449
    } else {
4450
      *pLevel = TSDB_RETENTION_L2;
14✔
4451
      tsdbDebug("vgId:%d, rsma level %d is selected to query %s", TD_VID(pVnode), TSDB_RETENTION_L2, str);
14!
4452
      *pTsdb = VND_RSMA2(pVnode);
14✔
4453
      return;
14✔
4454
    }
4455
  }
4456

4457
  *pTsdb = VND_TSDB(pVnode);
4,682,706✔
4458
}
4459

4460
SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_t level) {
4,680,084✔
4461
  int64_t startVer = (pCond->startVersion == -1) ? 0 : pCond->startVersion;
4,680,084✔
4462

4463
  int64_t endVer = 0;
4,680,084✔
4464
  if (pCond->endVersion == -1) {
4,680,084✔
4465
    // user not specified end version, set current maximum version of vnode as the endVersion
4466
    endVer = pVnode->state.applied;
4,672,764✔
4467
  } else {
4468
    endVer = (pCond->endVersion > pVnode->state.applied) ? pVnode->state.applied : pCond->endVersion;
7,320✔
4469
  }
4470

4471
  return (SVersionRange){.minVer = startVer, .maxVer = endVer};
4,680,084✔
4472
}
4473

4474
static int32_t reverseSearchStartPos(const SArray* pDelList, int32_t index, int64_t key, bool asc, int32_t* start) {
43,868,746✔
4475
  int32_t code = TSDB_CODE_SUCCESS;
43,868,746✔
4476
  int32_t lino = 0;
43,868,746✔
4477
  size_t  num = 0;
43,868,746✔
4478

4479
  num = taosArrayGetSize(pDelList);
43,868,746✔
4480
  *start = index;
43,510,110✔
4481

4482
  if (asc) {
43,510,110✔
4483
    if (*start >= num - 1) {
34,867,027✔
4484
      *start = num - 1;
11,108,331✔
4485
    }
4486

4487
    TSDBKEY* p = taosArrayGet(pDelList, *start);
34,867,027✔
4488
    TSDB_CHECK_NULL(p, code, lino, _end, TSDB_CODE_INVALID_PARA);
34,801,921!
4489

4490
    while (p->ts >= key && *start > 0) {
34,867,582✔
4491
      *start -= 1;
65,661✔
4492
    }
4493
  } else {
4494
    if (index <= 0) {
8,643,083!
UNCOV
4495
      *start = 0;
×
4496
    }
4497

4498
    TSDBKEY* p = taosArrayGet(pDelList, *start);
8,643,083✔
4499
    TSDB_CHECK_NULL(p, code, lino, _end, TSDB_CODE_INVALID_PARA);
8,747,732!
4500

4501
    while (p->ts <= key && *start < num - 1) {
8,751,513✔
4502
      *start += 1;
3,781✔
4503
    }
4504
  }
4505

4506
_end:
8,747,732✔
4507
  if (code != TSDB_CODE_SUCCESS) {
43,549,653!
4508
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4509
  }
4510
  return code;
43,570,508✔
4511
}
4512

4513
int32_t hasBeenDropped(const SArray* pDelList, int32_t* index, int64_t key, int64_t ver, int32_t order,
48,647,386✔
4514
                       SVersionRange* pVerRange, bool hasPk, bool* dropped) {
4515
  int32_t code = TSDB_CODE_SUCCESS;
48,647,386✔
4516
  int32_t lino = 0;
48,647,386✔
4517
  size_t  num = 0;
48,647,386✔
4518
  int32_t step = 0;
48,647,386✔
4519
  bool    asc = false;
48,647,386✔
4520

4521
  *dropped = false;
48,647,386✔
4522

4523
  if (pDelList == NULL || (TARRAY_SIZE(pDelList) == 0)) {
48,647,386!
4524
    goto _end;
×
4525
  }
4526

4527
  num = taosArrayGetSize(pDelList);
48,851,135✔
4528
  asc = ASCENDING_TRAVERSE(order);
48,798,765✔
4529
  step = asc ? 1 : -1;
48,798,765✔
4530

4531
  if (hasPk) {  // handle the case where duplicated timestamps existed.
48,798,765✔
4532
    code = reverseSearchStartPos(pDelList, *index, key, asc, index);
43,924,755✔
4533
    TSDB_CHECK_CODE(code, lino, _end);
43,394,988!
4534
  }
4535

4536
  if (asc) {
48,268,998✔
4537
    if (*index >= num - 1) {
38,845,297✔
4538
      TSDBKEY* last = taosArrayGetLast(pDelList);
13,459,712✔
4539
      if (last == NULL) {
13,429,326!
UNCOV
4540
        goto _end;
×
4541
      }
4542

4543
      if (key > last->ts) {
13,429,326✔
4544
        goto _end;
13,426,991✔
4545
      } else if (key == last->ts) {
2,335!
4546
        TSDBKEY* prev = taosArrayGet(pDelList, num - 2);
4,996✔
4547
        if (prev == NULL) {
4,996!
UNCOV
4548
          goto _end;
×
4549
        }
4550

4551
        *dropped = (prev->version >= ver && prev->version <= pVerRange->maxVer && prev->version >= pVerRange->minVer);
4,996!
4552
      }
4553
    } else {
4554
      TSDBKEY* pCurrent = taosArrayGet(pDelList, *index);
25,385,585✔
4555
      TSDBKEY* pNext = taosArrayGet(pDelList, (*index) + 1);
26,193,044✔
4556
      if (pCurrent == NULL || pNext == NULL) {
25,964,266!
UNCOV
4557
        goto _end;
×
4558
      }
4559

4560
      if (key < pCurrent->ts) {
25,964,266✔
4561
        goto _end;
6,188,223✔
4562
      }
4563

4564
      if (pCurrent->ts <= key && pNext->ts >= key && pCurrent->version >= ver &&
19,776,043!
4565
          pVerRange->maxVer >= pCurrent->version) {
8,116,965!
4566
        *dropped = true;
8,117,159✔
4567
        goto _end;
8,117,159✔
4568
      }
4569

4570
      while (pNext->ts <= key && (*index) < num - 1) {
12,510,100✔
4571
        (*index) += 1;
971,746✔
4572

4573
        if ((*index) < num - 1) {
971,746✔
4574
          pCurrent = taosArrayGet(pDelList, *index);
912,182✔
4575
          pNext = taosArrayGet(pDelList, (*index) + 1);
912,178✔
4576
          if (pCurrent == NULL || pNext == NULL) {
1,759,654!
4577
            break;
4578
          }
4579

4580
          // it is not a consecutive deletion range, ignore it
4581
          if (pCurrent->version == 0 && pNext->version > 0) {
912,186!
4582
            continue;
409,558✔
4583
          }
4584

4585
          if (pCurrent->ts <= key && pNext->ts >= key && pCurrent->version >= ver &&
502,628!
4586
              pVerRange->maxVer >= pCurrent->version) {
120,534!
4587
            *dropped = true;
120,534✔
4588
            break;
120,534✔
4589
          }
4590
        }
4591
      }
4592
    }
4593
  } else {
4594
    if (*index <= 0) {
9,423,701!
4595
      TSDBKEY* pFirst = taosArrayGet(pDelList, 0);
×
UNCOV
4596
      if (pFirst == NULL) {
×
UNCOV
4597
        goto _end;
×
4598
      }
4599

UNCOV
4600
      if (key < pFirst->ts) {
×
UNCOV
4601
        goto _end;
×
UNCOV
4602
      } else if (key == pFirst->ts) {
×
UNCOV
4603
        *dropped = pFirst->version >= ver;
×
4604
      } else {
UNCOV
4605
        tsdbError("unexpected error, key:%" PRId64 ", first:%" PRId64, key, pFirst->ts);
×
4606
      }
4607
    } else {
4608
      TSDBKEY* pCurrent = taosArrayGet(pDelList, *index);
9,423,701✔
4609
      TSDBKEY* pPrev = taosArrayGet(pDelList, (*index) - 1);
9,441,207✔
4610
      if (pCurrent == NULL || pPrev == NULL) {
9,440,433!
UNCOV
4611
        goto _end;
×
4612
      }
4613

4614
      if (key > pCurrent->ts) {
9,440,433✔
4615
        goto _end;
4,940,126✔
4616
      }
4617

4618
      if (pPrev->ts <= key && pCurrent->ts >= key && pPrev->version >= ver) {
4,500,307!
4619
        *dropped = true;
576,025✔
4620
        goto _end;
576,025✔
4621
      }
4622

4623
      while (pPrev->ts >= key && (*index) > 1) {
4,007,906✔
4624
        (*index) += step;
91,934✔
4625

4626
        if ((*index) >= 1) {
91,934✔
4627
          pCurrent = taosArrayGet(pDelList, *index);
90,995✔
4628
          pPrev = taosArrayGet(pDelList, (*index) - 1);
90,995✔
4629
          if (pCurrent == NULL || pPrev == NULL) {
90,996!
4630
            break;
4631
          }
4632

4633
          // it is not a consecutive deletion range, ignore it
4634
          if (pCurrent->version > 0 && pPrev->version == 0) {
90,996✔
4635
            continue;
34,449✔
4636
          }
4637

4638
          if (pPrev->ts <= key && pCurrent->ts >= key && pPrev->version >= ver) {
56,547!
4639
            *dropped = true;
8,311✔
4640
            break;
8,311✔
4641
          }
4642
        }
4643
      }
4644
    }
4645
  }
4646

4647
_end:
3,915,972✔
4648
  if (code != TSDB_CODE_SUCCESS) {
49,477,749!
UNCOV
4649
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4650
  }
4651
  return code;
47,553,809✔
4652
}
4653

4654
FORCE_INLINE int32_t getValidMemRow(SIterInfo* pIter, const SArray* pDelList, STsdbReader* pReader, TSDBROW** pRes) {
4655
  int32_t  code = TSDB_CODE_SUCCESS;
2,147,483,647✔
4656
  int32_t  lino = 0;
2,147,483,647✔
4657
  int32_t  order = 0;
2,147,483,647✔
4658
  TSDBROW* pRow = NULL;
2,147,483,647✔
4659
  TSDBKEY  key;
4660

4661
  TSDB_CHECK_NULL(pIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,300,224,792!
4662
  TSDB_CHECK_NULL(pRes, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,147,483,647!
4663

4664
  *pRes = NULL;
2,147,483,647✔
4665

4666
  if (!pIter->hasVal) {
2,147,483,647!
4667
    goto _end;
1,028,197,604✔
4668
  }
4669

4670
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,147,483,647!
4671
  order = pReader->info.order;
2,147,483,647✔
4672
  pRow = tsdbTbDataIterGet(pIter->iter);
2,147,483,647!
4673

4674
  TSDBROW_INIT_KEY(pRow, key);
2,147,483,647!
4675
  if (outOfTimeWindow(key.ts, &pReader->info.window)) {
2,147,483,647!
UNCOV
4676
    pIter->hasVal = false;
×
UNCOV
4677
    goto _end;
×
4678
  }
4679

4680
  // it is a valid data version
4681
  if (key.version <= pReader->info.verRange.maxVer && key.version >= pReader->info.verRange.minVer) {
2,147,483,647!
4682
    if (pDelList == NULL || TARRAY_SIZE(pDelList) == 0) {
2,147,483,647!
4683
      *pRes = pRow;
2,147,483,647✔
4684
      goto _end;
2,147,483,647✔
4685
    } else {
4686
      bool dropped = false;
18,204,072✔
4687
      code = hasBeenDropped(pDelList, &pIter->index, key.ts, key.version, order, &pReader->info.verRange,
18,204,072✔
4688
                            pReader->suppInfo.numOfPks > 0, &dropped);
18,204,072✔
4689
      TSDB_CHECK_CODE(code, lino, _end);
36,197,118!
4690
      if (!dropped) {
18,182,173!
4691
        *pRes = pRow;
18,014,945✔
4692
        goto _end;
18,014,945✔
4693
      }
4694
    }
4695
  }
4696

4697
  while (1) {
4698
    pIter->hasVal = tsdbTbDataIterNext(pIter->iter);
2,464,260✔
4699
    if (!pIter->hasVal) {
5,376,369!
4700
      goto _end;
8,537✔
4701
    }
4702

4703
    pRow = tsdbTbDataIterGet(pIter->iter);
5,367,832!
4704

4705
    TSDBROW_INIT_KEY(pRow, key);
5,367,832!
4706
    if (outOfTimeWindow(key.ts, &pReader->info.window)) {
5,367,832!
4707
      pIter->hasVal = false;
58,329✔
4708
      goto _end;
58,329✔
4709
    }
4710

4711
    if (key.version <= pReader->info.verRange.maxVer && key.version >= pReader->info.verRange.minVer) {
5,309,503!
4712
      if (pDelList == NULL || TARRAY_SIZE(pDelList) == 0) {
4,738,284!
4713
        *pRes = pRow;
1,736✔
4714
        goto _end;
1,736✔
4715
      } else {
4716
        bool dropped = false;
4,736,548✔
4717
        code = hasBeenDropped(pDelList, &pIter->index, key.ts, key.version, order, &pReader->info.verRange,
4,736,548✔
4718
                              pReader->suppInfo.numOfPks > 0, &dropped);
4,736,548✔
4719
        TSDB_CHECK_CODE(code, lino, _end);
4,841,111!
4720
        if (!dropped) {
4,736,653!
4721
          *pRes = pRow;
104,458✔
4722
          goto _end;
104,458✔
4723
        }
4724
      }
4725
    }
4726
  }
4727

4728
_end:
2,147,483,647✔
4729
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647!
UNCOV
4730
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4731
  }
4732
  return code;
2,147,483,647✔
4733
}
4734

4735
int32_t doMergeRowsInBuf(SIterInfo* pIter, uint64_t uid, SRowKey* pCurKey, SArray* pDelList, STsdbReader* pReader) {
134,230,912✔
4736
  int32_t     code = TSDB_CODE_SUCCESS;
134,230,912✔
4737
  int32_t     lino = 0;
134,230,912✔
4738
  SRowMerger* pMerger = NULL;
134,230,912✔
4739

4740
  TSDB_CHECK_NULL(pIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
134,230,912!
4741
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
134,230,912!
4742

4743
  pMerger = &pReader->status.merger;
134,230,912✔
4744

4745
  while (1) {
766,661✔
4746
    pIter->hasVal = tsdbTbDataIterNext(pIter->iter);
134,997,573✔
4747
    if (!pIter->hasVal) {
134,987,185✔
4748
      break;
134,291,887✔
4749
    }
4750

4751
    // data exists but not valid
4752
    TSDBROW* pRow = NULL;
134,733,556!
4753
    code = getValidMemRow(pIter, pDelList, pReader, &pRow);
134,786,205✔
4754
    TSDB_CHECK_CODE(code, lino, _end);
134,786,205!
4755
    if (pRow == NULL) {
134,786,205✔
4756
      break;
40,352✔
4757
    }
4758

4759
    // ts is not identical, quit
4760
    if (TSDBROW_TS(pRow) != pCurKey->ts) {
134,745,853!
4761
      break;
133,997,900✔
4762
    }
4763

4764
    if (pCurKey->numOfPKs > 0) {
747,953✔
4765
      SRowKey nextKey = {0};
6✔
4766
      tRowGetKeyEx(pRow, &nextKey);
6!
4767
      if (pkCompEx(pCurKey, &nextKey) != 0) {
6!
4768
        break;
6✔
4769
      }
4770
    }
4771

4772
    STSchema* pTSchema = NULL;
747,947✔
4773
    if (pRow->type == TSDBROW_ROW_FMT) {
747,947!
4774
      pTSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, uid);
766,883!
4775
      TSDB_CHECK_NULL(pTSchema, code, lino, _end, terrno);
767,020!
4776
    }
4777

4778
    code = tsdbRowMergerAdd(pMerger, pRow, pTSchema);
748,084✔
4779
    TSDB_CHECK_CODE(code, lino, _end);
766,661!
4780
  }
4781

4782
_end:
134,291,887✔
4783
  if (code != TSDB_CODE_SUCCESS) {
134,291,887!
UNCOV
4784
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4785
  }
4786
  return code;
134,254,986✔
4787
}
4788

4789
static int32_t doMergeRowsInFileBlockImpl(SBlockData* pBlockData, int32_t* rowIndex, SRowKey* pKey, SRowMerger* pMerger,
7,874,740✔
4790
                                          SVersionRange* pVerRange, int32_t step) {
4791
  int32_t code = TSDB_CODE_SUCCESS;
7,874,740✔
4792
  int32_t lino = 0;
7,874,740✔
4793

4794
  TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,874,740!
4795
  TSDB_CHECK_NULL(rowIndex, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,874,740!
4796

4797
  while ((*rowIndex) < pBlockData->nRow && (*rowIndex) >= 0) {
7,874,680!
4798
    SRowKey cur;
4799
    tColRowGetKey(pBlockData, (*rowIndex), &cur);
7,874,427✔
4800
    if (pkCompEx(&cur, pKey) != 0) {
7,872,561!
4801
      break;
7,872,621✔
4802
    }
4803

UNCOV
4804
    if (pBlockData->aVersion[(*rowIndex)] > pVerRange->maxVer ||
×
4805
        pBlockData->aVersion[(*rowIndex)] < pVerRange->minVer) {
5!
UNCOV
4806
      (*rowIndex) += step;
×
UNCOV
4807
      continue;
×
4808
    }
4809

4810
    TSDBROW fRow = tsdbRowFromBlockData(pBlockData, (*rowIndex));
5✔
4811
    code = tsdbRowMergerAdd(pMerger, &fRow, NULL);
5✔
4812
    TSDB_CHECK_CODE(code, lino, _end);
5!
4813
    (*rowIndex) += step;
5✔
4814
  }
4815

4816
_end:
253✔
4817
  if (code != TSDB_CODE_SUCCESS) {
7,872,874!
UNCOV
4818
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4819
  }
4820
  return code;
7,874,285✔
4821
}
4822

4823
typedef enum {
4824
  CHECK_FILEBLOCK_CONT = 0x1,
4825
  CHECK_FILEBLOCK_QUIT = 0x2,
4826
} CHECK_FILEBLOCK_STATE;
4827

4828
static int32_t checkForNeighborFileBlock(STsdbReader* pReader, STableBlockScanInfo* pScanInfo,
3,216✔
4829
                                         SFileDataBlockInfo* pFBlock, SRowMerger* pMerger, SRowKey* pKey,
4830
                                         CHECK_FILEBLOCK_STATE* state) {
4831
  int32_t             code = TSDB_CODE_SUCCESS;
3,216✔
4832
  int32_t             lino = 0;
3,216✔
4833
  SFileBlockDumpInfo* pDumpInfo = NULL;
3,216✔
4834
  SBlockData*         pBlockData = NULL;
3,216✔
4835
  bool                asc = false;
3,216✔
4836
  SVersionRange*      pVerRange = NULL;
3,216✔
4837
  bool                loadNeighbor = true;
3,216✔
4838
  int32_t             step = 0;
3,216✔
4839

4840
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
3,216!
4841
  TSDB_CHECK_NULL(state, code, lino, _end, TSDB_CODE_INVALID_PARA);
3,216!
4842

4843
  pDumpInfo = &pReader->status.fBlockDumpInfo;
3,216✔
4844
  pBlockData = &pReader->status.fileBlockData;
3,216✔
4845
  asc = ASCENDING_TRAVERSE(pReader->info.order);
3,216✔
4846
  pVerRange = &pReader->info.verRange;
3,216✔
4847
  step = ASCENDING_TRAVERSE(pReader->info.order) ? 1 : -1;
3,216✔
4848

4849
  *state = CHECK_FILEBLOCK_QUIT;
3,216✔
4850
  code = loadNeighborIfOverlap(pFBlock, pScanInfo, pReader, &loadNeighbor);
3,216✔
4851
  TSDB_CHECK_CODE(code, lino, _end);
3,216!
4852

4853
  if (loadNeighbor) {
3,216✔
4854
    code = doMergeRowsInFileBlockImpl(pBlockData, &pDumpInfo->rowIndex, pKey, pMerger, pVerRange, step);
5✔
4855
    TSDB_CHECK_CODE(code, lino, _end);
5!
4856
    if ((pDumpInfo->rowIndex >= pDumpInfo->totalRows && asc) || (pDumpInfo->rowIndex < 0 && !asc)) {
5!
UNCOV
4857
      *state = CHECK_FILEBLOCK_CONT;
×
4858
    }
4859
  }
4860

4861
_end:
3,216✔
4862
  if (code != TSDB_CODE_SUCCESS) {
3,216!
UNCOV
4863
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4864
  }
4865
  return code;
3,216✔
4866
}
4867

4868
int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pScanInfo, SRowKey* pKey,
7,906,526✔
4869
                                STsdbReader* pReader) {
4870
  int32_t             code = TSDB_CODE_SUCCESS;
7,906,526✔
4871
  int32_t             lino = 0;
7,906,526✔
4872
  SFileBlockDumpInfo* pDumpInfo = NULL;
7,906,526✔
4873
  SRowMerger*         pMerger = NULL;
7,906,526✔
4874
  bool                asc = false;
7,906,526✔
4875
  int32_t             step = 0;
7,906,526✔
4876
  SVersionRange*      pRange = NULL;
7,906,526✔
4877

4878
  TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,906,526!
4879
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
7,906,526!
4880

4881
  pDumpInfo = &pReader->status.fBlockDumpInfo;
7,906,526✔
4882
  pMerger = &pReader->status.merger;
7,906,526✔
4883
  asc = ASCENDING_TRAVERSE(pReader->info.order);
7,906,526✔
4884
  step = asc ? 1 : -1;
7,906,526✔
4885
  pRange = &pReader->info.verRange;
7,906,526✔
4886

4887
  pDumpInfo->rowIndex += step;
7,906,526✔
4888
  if ((pDumpInfo->rowIndex <= pBlockData->nRow - 1 && asc) || (pDumpInfo->rowIndex >= 0 && !asc)) {
7,906,526!
4889
    code = doMergeRowsInFileBlockImpl(pBlockData, &pDumpInfo->rowIndex, pKey, pMerger, pRange, step);
7,902,650✔
4890
    TSDB_CHECK_CODE(code, lino, _end);
7,872,609!
4891
  }
4892

4893
  // all rows are consumed, let's try next file block
4894
  if ((pDumpInfo->rowIndex >= pBlockData->nRow && asc) || (pDumpInfo->rowIndex < 0 && !asc)) {
7,876,485!
UNCOV
4895
    while (1) {
×
4896
      SFileDataBlockInfo* pFileBlockInfo = NULL;
3,216✔
4897
      code = getCurrentBlockInfo(&pReader->status.blockIter, &pFileBlockInfo, pReader->idStr);
3,216✔
4898
      TSDB_CHECK_CODE(code, lino, _end);
3,216!
4899

4900
      if (pFileBlockInfo == NULL) {
3,216!
4901
        break;
3,216✔
4902
      }
4903

4904
      CHECK_FILEBLOCK_STATE st = CHECK_FILEBLOCK_QUIT;
3,216✔
4905
      code = checkForNeighborFileBlock(pReader, pScanInfo, pFileBlockInfo, pMerger, pKey, &st);
3,216✔
4906
      TSDB_CHECK_CODE(code, lino, _end);
3,216!
4907
      if (st == CHECK_FILEBLOCK_QUIT) {
3,216!
4908
        break;
3,216✔
4909
      }
4910
    }
4911
  }
4912

4913
_end:
7,873,269✔
4914
  if (code != TSDB_CODE_SUCCESS) {
7,876,485!
UNCOV
4915
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4916
  }
4917
  return code;
7,875,974✔
4918
}
4919

4920
int32_t doMergeRowsInSttBlock(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo, SRowMerger* pMerger,
141,373,481✔
4921
                              int32_t pkSrcSlot, SVersionRange* pVerRange, const char* idStr) {
4922
  int32_t  code = TSDB_CODE_SUCCESS;
141,373,481✔
4923
  int32_t  lino = 0;
141,373,481✔
4924
  SRowKey* pRowKey = NULL;
141,373,481✔
4925
  SRowKey* pNextKey = NULL;
141,373,481✔
4926

4927
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
141,373,481!
4928

4929
  pRowKey = &pScanInfo->lastProcKey;
141,373,481✔
4930

4931
  while (1) {
1,131,255✔
4932
    code = nextRowFromSttBlocks(pSttBlockReader, pScanInfo, pkSrcSlot, pVerRange);
142,504,736✔
4933
    TSDB_CHECK_CODE(code, lino, _end);
142,230,232!
4934
    if (!hasDataInSttBlock(pScanInfo)) {
142,230,232✔
4935
      break;
2,697,817✔
4936
    }
4937

4938
    pNextKey = getCurrentKeyInSttBlock(pSttBlockReader);
139,509,924!
4939

4940
    int32_t ret = pkCompEx(pRowKey, pNextKey);
139,513,292✔
4941
    if (ret == 0) {
139,513,292✔
4942
      TSDBROW* pRow1 = tMergeTreeGetRow(&pSttBlockReader->mergeTree);
1,134,761✔
4943
      code = tsdbRowMergerAdd(pMerger, pRow1, NULL);
1,134,761✔
4944
      TSDB_CHECK_CODE(code, lino, _end);
1,131,255!
4945
    } else {
4946
      tsdbTrace("uid:%" PRIu64 " last del index:%d, del range:%d, lastKeyInStt:%" PRId64 ", %s", pScanInfo->uid,
138,378,531✔
4947
                pScanInfo->sttBlockDelIndex, (int32_t)taosArrayGetSize(pScanInfo->delSkyline),
4948
                pScanInfo->sttKeyInfo.nextProcKey.ts, idStr);
4949
      break;
138,347,149✔
4950
    }
4951
  }
4952

4953
_end:
141,044,966✔
4954
  if (code != TSDB_CODE_SUCCESS) {
141,044,966!
UNCOV
4955
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4956
  }
4957
  return code;
141,047,021✔
4958
}
4959

4960
int32_t doMergeMemTableMultiRows(TSDBROW* pRow, SRowKey* pKey, uint64_t uid, SIterInfo* pIter, SArray* pDelList,
1,011,884,797✔
4961
                                 TSDBROW* pResRow, STsdbReader* pReader, bool* freeTSRow) {
4962
  int32_t     code = TSDB_CODE_SUCCESS;
1,011,884,797✔
4963
  int32_t     lino = 0;
1,011,884,797✔
4964
  SRowMerger* pMerger = NULL;
1,011,884,797✔
4965
  TSDBROW*    pNextRow = NULL;
1,011,884,797✔
4966
  STSchema*   pTSchema = NULL;
1,011,884,797✔
4967
  STSchema*   pTSchema1 = NULL;
1,011,884,797✔
4968
  TSDBROW     current;
4969

4970
  TSDB_CHECK_NULL(pRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,011,884,797!
4971
  TSDB_CHECK_NULL(pIter, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,011,884,797!
4972
  TSDB_CHECK_NULL(pResRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,011,884,797!
4973
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,011,884,797!
4974
  TSDB_CHECK_NULL(freeTSRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,011,884,797!
4975

4976
  pMerger = &pReader->status.merger;
1,011,884,797✔
4977
  current = *pRow;
1,011,884,797✔
4978

4979
  {  // if the timestamp of the next valid row has a different ts, return current row directly
4980
    pIter->hasVal = tsdbTbDataIterNext(pIter->iter);
1,011,884,797✔
4981

4982
    if (!pIter->hasVal) {
1,007,525,473✔
4983
      *pResRow = *pRow;
2,303,108✔
4984
      *freeTSRow = false;
2,303,108✔
4985
      goto _end;
2,303,108✔
4986
    } else {  // has next point in mem/imem
4987
      code = getValidMemRow(pIter, pDelList, pReader, &pNextRow);
1,005,834,434✔
4988
      TSDB_CHECK_CODE(code, lino, _end);
1,005,834,434!
4989
      if (pNextRow == NULL) {
1,005,834,434✔
4990
        *pResRow = current;
795,593✔
4991
        *freeTSRow = false;
795,593✔
4992
        goto _end;
795,593✔
4993
      }
4994

4995
      if (TSDBROW_TS(&current) != TSDBROW_TS(pNextRow)) {
1,005,038,841!
4996
        *pResRow = current;
1,002,947,559✔
4997
        *freeTSRow = false;
1,002,947,559✔
4998
        goto _end;
1,002,947,559✔
4999
      }
5000

5001
      if (pKey->numOfPKs > 0) {
2,091,282✔
5002
        SRowKey nextRowKey = {0};
719,748✔
5003
        tRowGetKeyEx(pNextRow, &nextRowKey);
719,748!
5004
        if (pkCompEx(pKey, &nextRowKey) != 0) {
719,776✔
5005
          *pResRow = current;
718,313✔
5006
          *freeTSRow = false;
718,313✔
5007
          goto _end;
718,313✔
5008
        }
5009
      }
5010
    }
5011
  }
5012

5013
  // start to merge duplicated rows
5014
  if (current.type == TSDBROW_ROW_FMT) {  // get the correct schema for row-wise data in memory
1,372,997!
5015
    pTSchema = doGetSchemaForTSRow(current.pTSRow->sver, pReader, uid);
1,698,582!
5016
    TSDB_CHECK_NULL(pTSchema, code, lino, _end, terrno);
1,698,464!
5017
  }
5018

5019
  code = tsdbRowMergerAdd(pMerger, &current, pTSchema);
1,372,879✔
5020
  TSDB_CHECK_CODE(code, lino, _end);
1,697,708!
5021

5022
  if (pNextRow->type == TSDBROW_ROW_FMT) {  // get the correct schema for row-wise data in memory
1,697,708!
5023
    pTSchema1 = doGetSchemaForTSRow(pNextRow->pTSRow->sver, pReader, uid);
1,697,999!
5024
    TSDB_CHECK_NULL(pTSchema1, code, lino, _end, terrno);
1,697,774!
5025
  }
5026

5027
  code = tsdbRowMergerAdd(pMerger, pNextRow, pTSchema1);
1,697,483✔
5028
  TSDB_CHECK_CODE(code, lino, _end);
1,697,597!
5029

5030
  code = doMergeRowsInBuf(pIter, uid, pKey, pDelList, pReader);
1,697,597✔
5031
  TSDB_CHECK_CODE(code, lino, _end);
1,696,769!
5032

5033
  code = tsdbRowMergerGetRow(pMerger, &pResRow->pTSRow);
1,696,769✔
5034
  TSDB_CHECK_CODE(code, lino, _end);
1,697,435!
5035

5036
  pResRow->type = TSDBROW_ROW_FMT;
1,697,435✔
5037
  tsdbRowMergerClear(pMerger);
1,697,435✔
5038
  *freeTSRow = true;
1,695,617✔
5039

5040
_end:
1,008,460,190✔
5041
  if (code != TSDB_CODE_SUCCESS) {
1,008,460,190!
UNCOV
5042
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5043
  }
5044
  return code;
1,005,359,738✔
5045
}
5046

5047
int32_t doMergeMemIMemRows(TSDBROW* pRow, SRowKey* pRowKey, TSDBROW* piRow, SRowKey* piRowKey,
32,397✔
5048
                           STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, SRow** pTSRow) {
5049
  int32_t     code = TSDB_CODE_SUCCESS;
32,397✔
5050
  int32_t     lino = 0;
32,397✔
5051
  SRowMerger* pMerger = NULL;
32,397✔
5052
  STSchema*   pSchema = NULL;
32,397✔
5053
  STSchema*   piSchema = NULL;
32,397✔
5054

5055
  TSDB_CHECK_NULL(pRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
32,397!
5056
  TSDB_CHECK_NULL(piRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
32,397!
5057
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
32,397!
5058
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
32,397!
5059

5060
  pMerger = &pReader->status.merger;
32,397✔
5061

5062
  if (pRow->type == TSDBROW_ROW_FMT) {
32,397!
5063
    pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid);
32,397!
5064
    TSDB_CHECK_NULL(pSchema, code, lino, _end, terrno);
32,397!
5065
  }
5066

5067
  if (piRow->type == TSDBROW_ROW_FMT) {
32,397!
5068
    piSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(piRow), pReader, pBlockScanInfo->uid);
32,397!
5069
    TSDB_CHECK_NULL(piSchema, code, lino, _end, terrno);
32,397!
5070
  }
5071

5072
  if (ASCENDING_TRAVERSE(pReader->info.order)) {  // ascending order imem --> mem
32,397!
5073
    code = tsdbRowMergerAdd(pMerger, piRow, piSchema);
32,397✔
5074
    TSDB_CHECK_CODE(code, lino, _end);
32,397!
5075

5076
    code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, piRowKey, pBlockScanInfo->delSkyline, pReader);
32,397✔
5077
    TSDB_CHECK_CODE(code, lino, _end);
32,396!
5078

5079
    code = tsdbRowMergerAdd(pMerger, pRow, pSchema);
32,396✔
5080
    TSDB_CHECK_CODE(code, lino, _end);
32,396!
5081

5082
    code = doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, pRowKey, pBlockScanInfo->delSkyline, pReader);
32,396✔
5083
    TSDB_CHECK_CODE(code, lino, _end);
32,394!
5084
  } else {
UNCOV
5085
    code = tsdbRowMergerAdd(pMerger, pRow, pSchema);
×
UNCOV
5086
    TSDB_CHECK_CODE(code, lino, _end);
×
5087

UNCOV
5088
    code = doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, pRowKey, pBlockScanInfo->delSkyline, pReader);
×
UNCOV
5089
    TSDB_CHECK_CODE(code, lino, _end);
×
5090

UNCOV
5091
    code = tsdbRowMergerAdd(pMerger, piRow, piSchema);
×
UNCOV
5092
    TSDB_CHECK_CODE(code, lino, _end);
×
5093

UNCOV
5094
    code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, piRowKey, pBlockScanInfo->delSkyline, pReader);
×
UNCOV
5095
    TSDB_CHECK_CODE(code, lino, _end);
×
5096
  }
5097

5098
  tRowKeyAssign(&pBlockScanInfo->lastProcKey, pRowKey);
32,394✔
5099

5100
  code = tsdbRowMergerGetRow(pMerger, pTSRow);
32,394✔
5101
  tsdbRowMergerClear(pMerger);
32,397✔
5102
  TSDB_CHECK_CODE(code, lino, _end);
32,395!
5103

5104
_end:
32,395✔
5105
  if (code != TSDB_CODE_SUCCESS) {
32,395!
UNCOV
5106
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5107
  }
5108
  return code;
32,395✔
5109
}
5110

5111
static int32_t tsdbGetNextRowInMem(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, TSDBROW* pResRow,
987,714,975✔
5112
                                   int64_t endKey, bool* freeTSRow) {
5113
  int32_t    code = TSDB_CODE_SUCCESS;
987,714,975✔
5114
  int32_t    lino = 0;
987,714,975✔
5115
  TSDBROW*   pRow = NULL;
987,714,975✔
5116
  TSDBROW*   piRow = NULL;
987,714,975✔
5117
  SArray*    pDelList = NULL;
987,714,975✔
5118
  uint64_t   uid = 0;
987,714,975✔
5119
  SIterInfo* piter = NULL;
987,714,975✔
5120
  SIterInfo* piiter = NULL;
987,714,975✔
5121
  SRowKey    rowKey = {0};
987,714,975✔
5122
  SRowKey    irowKey = {0};
987,714,975✔
5123
  bool       asc = false;
987,714,975✔
5124

5125
  TSDB_CHECK_NULL(pBlockScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
987,714,975!
5126
  TSDB_CHECK_NULL(pResRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
987,714,975!
5127
  TSDB_CHECK_NULL(freeTSRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
987,714,975!
5128

5129
  code = getValidMemRow(&pBlockScanInfo->iter, pBlockScanInfo->delSkyline, pReader, &pRow);
987,714,975!
5130
  TSDB_CHECK_CODE(code, lino, _end);
1,025,703,519!
5131
  code = getValidMemRow(&pBlockScanInfo->iiter, pBlockScanInfo->delSkyline, pReader, &piRow);
1,025,703,519!
5132
  TSDB_CHECK_CODE(code, lino, _end);
1,019,544,856!
5133

5134
  pDelList = pBlockScanInfo->delSkyline;
1,019,544,856✔
5135
  uid = pBlockScanInfo->uid;
1,019,544,856✔
5136
  piter = &pBlockScanInfo->iter;
1,019,544,856✔
5137
  piiter = &pBlockScanInfo->iiter;
1,019,544,856✔
5138

5139
  // todo refactor
5140
  asc = ASCENDING_TRAVERSE(pReader->info.order);
1,019,544,856✔
5141
  if (piter->hasVal) {
1,019,544,856✔
5142
    tRowGetKeyEx(pRow, &rowKey);
988,530,885!
5143
    if ((rowKey.ts >= endKey && asc) || (rowKey.ts <= endKey && !asc)) {
989,386,388✔
5144
      pRow = NULL;
1,304,005✔
5145
    }
5146
  }
5147

5148
  if (piiter->hasVal) {
1,020,400,359✔
5149
    tRowGetKeyEx(piRow, &irowKey);
39,510,017!
5150
    if ((irowKey.ts >= endKey && asc) || (irowKey.ts <= endKey && !asc)) {
38,664,297!
UNCOV
5151
      piRow = NULL;
×
5152
    }
5153
  }
5154

5155
  if (pRow != NULL && piRow != NULL) {
1,019,554,639✔
5156
    if (rowKey.numOfPKs == 0) {
4,463,214✔
5157
      if ((rowKey.ts > irowKey.ts && asc) || (rowKey.ts < irowKey.ts && (!asc))) {  // ik.ts < k.ts
4,430,486!
5158
        code = doMergeMemTableMultiRows(piRow, &irowKey, uid, piiter, pDelList, pResRow, pReader, freeTSRow);
4,397,268✔
5159
        TSDB_CHECK_CODE(code, lino, _end);
4,390,697!
5160
      } else if ((rowKey.ts < irowKey.ts && asc) || (rowKey.ts > irowKey.ts && (!asc))) {
33,218!
5161
        code = doMergeMemTableMultiRows(pRow, &rowKey, uid, piter, pDelList, pResRow, pReader, freeTSRow);
942✔
5162
        TSDB_CHECK_CODE(code, lino, _end);
942!
5163
      } else {  // ik.ts == k.ts
5164
        pResRow->type = TSDBROW_ROW_FMT;
32,276✔
5165
        code = doMergeMemIMemRows(pRow, &rowKey, piRow, &irowKey, pBlockScanInfo, pReader, &pResRow->pTSRow);
32,276✔
5166
        TSDB_CHECK_CODE(code, lino, _end);
32,395!
5167
        *freeTSRow = true;
32,395✔
5168
      }
5169
    } else {
5170
      int32_t ret = pkCompEx(&rowKey, &irowKey);
32,736✔
5171
      if (ret != 0) {
32,736✔
5172
        if ((ret > 0 && asc) || (ret < 0 && (!asc))) {  // ik.ts < k.ts
32,734✔
5173
          code = doMergeMemTableMultiRows(piRow, &irowKey, uid, piiter, pDelList, pResRow, pReader, freeTSRow);
25,414✔
5174
          TSDB_CHECK_CODE(code, lino, _end);
25,414!
5175
        } else if ((ret < 0 && asc) || (ret > 0 && (!asc))) {
7,320!
5176
          code = doMergeMemTableMultiRows(pRow, &rowKey, uid, piter, pDelList, pResRow, pReader, freeTSRow);
7,327✔
5177
          TSDB_CHECK_CODE(code, lino, _end);
7,318!
5178
        }
5179
      } else {  // ik.ts == k.ts
5180
        pResRow->type = TSDBROW_ROW_FMT;
2✔
5181
        code = doMergeMemIMemRows(pRow, &rowKey, piRow, &irowKey, pBlockScanInfo, pReader, &pResRow->pTSRow);
2✔
UNCOV
5182
        TSDB_CHECK_CODE(code, lino, _end);
×
UNCOV
5183
        *freeTSRow = true;
×
5184
      }
5185
    }
5186
  } else if (piter->hasVal && pRow != NULL) {
1,015,091,425!
5187
    code = doMergeMemTableMultiRows(pRow, &rowKey, uid, piter, pDelList, pResRow, pReader, freeTSRow);
978,233,321✔
5188
    TSDB_CHECK_CODE(code, lino, _end);
962,059,940!
5189
  } else if (piiter->hasVal && piRow != NULL) {
36,858,104!
5190
    code = doMergeMemTableMultiRows(piRow, &irowKey, uid, piiter, pDelList, pResRow, pReader, freeTSRow);
35,136,029✔
5191
    TSDB_CHECK_CODE(code, lino, _end);
34,748,154!
5192
  }
5193

5194
_end:
36,470,229✔
5195
  if (code != TSDB_CODE_SUCCESS) {
1,002,986,928!
UNCOV
5196
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5197
  }
5198
  return code;
1,002,023,129✔
5199
}
5200

5201
int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, SRow* pTSRow, STableBlockScanInfo* pScanInfo) {
1,269,508,503✔
5202
  int32_t             code = TSDB_CODE_SUCCESS;
1,269,508,503✔
5203
  int32_t             lino = 0;
1,269,508,503✔
5204
  int32_t             outputRowIndex = 0;
1,269,508,503✔
5205
  int64_t             uid = 0;
1,269,508,503✔
5206
  SBlockLoadSuppInfo* pSupInfo = NULL;
1,269,508,503✔
5207
  STSchema*           pSchema = NULL;
1,269,508,503✔
5208
  SColVal             colVal = {0};
1,269,508,503✔
5209
  int32_t             i = 0, j = 0;
1,269,508,503✔
5210

5211
  TSDB_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,269,508,503!
5212
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,269,508,503!
5213
  TSDB_CHECK_NULL(pTSRow, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,269,508,503!
5214
  TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,269,508,503!
5215

5216
  outputRowIndex = pBlock->info.rows;
1,269,508,503✔
5217
  uid = pScanInfo->uid;
1,269,508,503✔
5218

5219
  pSupInfo = &pReader->suppInfo;
1,269,508,503✔
5220
  pSchema = doGetSchemaForTSRow(pTSRow->sver, pReader, uid);
1,269,508,503!
5221
  TSDB_CHECK_NULL(pSchema, code, lino, _end, terrno);
1,283,111,660!
5222

5223
  if (pSupInfo->colId[i] == PRIMARYKEY_TIMESTAMP_COL_ID) {
1,283,111,660✔
5224
    SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, pSupInfo->slotId[i]);
1,276,186,615✔
5225
    TSDB_CHECK_NULL(pColData, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,269,356,267!
5226

5227
    ((int64_t*)pColData->pData)[outputRowIndex] = pTSRow->ts;
1,269,356,267✔
5228
    i += 1;
1,269,356,267✔
5229
  }
5230

5231
  while (i < pSupInfo->numOfCols && j < pSchema->numOfCols) {
2,147,483,647!
5232
    col_id_t colId = pSupInfo->colId[i];
2,147,483,647✔
5233

5234
    if (colId == pSchema->columns[j].colId) {
2,147,483,647✔
5235
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pSupInfo->slotId[i]);
2,147,483,647✔
5236
      TSDB_CHECK_NULL(pColInfoData, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,147,483,647!
5237

5238
      code = tRowGet(pTSRow, pSchema, j, &colVal);
2,147,483,647✔
5239
      TSDB_CHECK_CODE(code, lino, _end);
2,147,483,647!
5240

5241
      code = doCopyColVal(pColInfoData, outputRowIndex, i, &colVal, pSupInfo);
2,147,483,647✔
5242
      TSDB_CHECK_CODE(code, lino, _end);
2,147,483,647✔
5243
      i += 1;
2,147,483,647✔
5244
      j += 1;
2,147,483,647✔
5245
    } else if (colId < pSchema->columns[j].colId) {
2,147,483,647!
UNCOV
5246
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pSupInfo->slotId[i]);
×
UNCOV
5247
      TSDB_CHECK_NULL(pColInfoData, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
5248

UNCOV
5249
      colDataSetNULL(pColInfoData, outputRowIndex);
×
UNCOV
5250
      i += 1;
×
5251
    } else if (colId > pSchema->columns[j].colId) {
2,147,483,647!
5252
      j += 1;
2,147,483,647✔
5253
    }
5254
  }
5255

5256
  // set null value since current column does not exist in the "pSchema"
5257
  while (i < pSupInfo->numOfCols) {
1,290,145,257✔
5258
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pSupInfo->slotId[i]);
41,285✔
5259
    TSDB_CHECK_NULL(pColInfoData, code, lino, _end, TSDB_CODE_INVALID_PARA);
41,285!
5260

5261
    colDataSetNULL(pColInfoData, outputRowIndex);
41,285✔
5262
    i += 1;
41,285✔
5263
  }
5264

5265
  pBlock->info.dataLoad = 1;
1,290,103,972✔
5266
  pBlock->info.rows += 1;
1,290,103,972✔
5267

5268
_end:
1,290,103,976✔
5269
  if (code != TSDB_CODE_SUCCESS) {
1,290,103,976✔
5270
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
5271
  }
5272
  return code;
1,263,488,531✔
5273
}
5274

5275
int32_t doAppendRowFromFileBlock(SSDataBlock* pResBlock, STsdbReader* pReader, SBlockData* pBlockData,
225,734,719✔
5276
                                 int32_t rowIndex) {
5277
  int32_t             code = TSDB_CODE_SUCCESS;
225,734,719✔
5278
  int32_t             lino = 0;
225,734,719✔
5279
  int32_t             i = 0, j = 0;
225,734,719✔
5280
  int32_t             outputRowIndex = 0;
225,734,719✔
5281
  SBlockLoadSuppInfo* pSupInfo = NULL;
225,734,719✔
5282
  SColVal             cv = {0};
225,734,719✔
5283
  int32_t             numOfInputCols = 0;
225,734,719✔
5284
  int32_t             numOfOutputCols = 0;
225,734,719✔
5285

5286
  TSDB_CHECK_NULL(pResBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
225,734,719!
5287
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
225,734,719!
5288
  TSDB_CHECK_NULL(pBlockData, code, lino, _end, TSDB_CODE_INVALID_PARA);
225,734,719!
5289

5290
  outputRowIndex = pResBlock->info.rows;
225,734,719✔
5291

5292
  pSupInfo = &pReader->suppInfo;
225,734,719✔
5293
  ((int64_t*)pReader->status.pPrimaryTsCol->pData)[outputRowIndex] = pBlockData->aTSKEY[rowIndex];
225,734,719✔
5294
  i += 1;
225,734,719✔
5295

5296
  numOfInputCols = pBlockData->nColData;
225,734,719✔
5297
  numOfOutputCols = pSupInfo->numOfCols;
225,734,719✔
5298

5299
  while (i < numOfOutputCols && j < numOfInputCols) {
453,772,962✔
5300
    SColData* pData = tBlockDataGetColDataByIdx(pBlockData, j);
226,651,194✔
5301
    if (pData->cid < pSupInfo->colId[i]) {
226,651,194✔
5302
      j += 1;
10✔
5303
      continue;
10✔
5304
    }
5305

5306
    SColumnInfoData* pCol = TARRAY_GET_ELEM(pResBlock->pDataBlock, pSupInfo->slotId[i]);
226,651,184✔
5307
    if (pData->cid == pSupInfo->colId[i]) {
226,651,184!
5308
      code = tColDataGetValue(pData, rowIndex, &cv);
226,694,843✔
5309
      TSDB_CHECK_CODE(code, lino, _end);
228,610,983!
5310
      code = doCopyColVal(pCol, outputRowIndex, i, &cv, pSupInfo);
228,610,983✔
5311
      TSDB_CHECK_CODE(code, lino, _end);
228,081,892!
5312
      j += 1;
228,081,892✔
UNCOV
5313
    } else if (pData->cid > pCol->info.colId) {
×
5314
      // the specified column does not exist in file block, fill with null data
5315
      colDataSetNULL(pCol, outputRowIndex);
50,002!
5316
    }
5317

5318
    i += 1;
228,038,233✔
5319
  }
5320

5321
  while (i < numOfOutputCols) {
227,121,798✔
5322
    SColumnInfoData* pCol = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]);
30✔
5323
    TSDB_CHECK_NULL(pCol, code, lino, _end, TSDB_CODE_INVALID_PARA);
30!
5324

5325
    colDataSetNULL(pCol, outputRowIndex);
30!
5326
    i += 1;
30✔
5327
  }
5328

5329
  pResBlock->info.dataLoad = 1;
227,121,768✔
5330
  pResBlock->info.rows += 1;
227,121,768✔
5331

5332
_end:
227,121,768✔
5333
  if (code != TSDB_CODE_SUCCESS) {
227,121,768!
UNCOV
5334
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5335
  }
5336
  return code;
229,232,351✔
5337
}
5338

5339
int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t endKey, int32_t capacity,
5,009,286✔
5340
                                  STsdbReader* pReader) {
5341
  int32_t      code = TSDB_CODE_SUCCESS;
5,009,286✔
5342
  int32_t      lino = 0;
5,009,286✔
5343
  SSDataBlock* pBlock = NULL;
5,009,286✔
5344

5345
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,009,286!
5346

5347
  pBlock = pReader->resBlockInfo.pResBlock;
5,009,286✔
5348

5349
  do {
981,886,344✔
5350
    TSDBROW row = {.type = -1};
986,895,630✔
5351
    bool    freeTSRow = false;
986,895,630✔
5352
    code = tsdbGetNextRowInMem(pBlockScanInfo, pReader, &row, endKey, &freeTSRow);
986,895,630✔
5353
    TSDB_CHECK_CODE(code, lino, _end);
998,923,088!
5354

5355
    if (row.type == -1) {
998,923,084✔
5356
      break;
5,010,196✔
5357
    }
5358

5359
    if (row.type == TSDBROW_ROW_FMT) {
997,191,170✔
5360
      code = doAppendRowFromTSRow(pBlock, pReader, row.pTSRow, pBlockScanInfo);
995,431,949✔
5361
      if (code != TSDB_CODE_SUCCESS) {
985,119,927✔
5362
        if (freeTSRow) {
4!
UNCOV
5363
          taosMemoryFreeClear(row.pTSRow);
×
5364
        }
5365
        TSDB_CHECK_CODE(code, lino, _end);
4!
5366
      }
5367
      pBlockScanInfo->lastProcKey.ts = row.pTSRow->ts;
985,119,923✔
5368
      pBlockScanInfo->lastProcKey.numOfPKs = row.pTSRow->numOfPKs;
985,119,923✔
5369
      if (row.pTSRow->numOfPKs > 0) {
985,119,923✔
5370
        code = tRowGetPrimaryKeyDeepCopy(row.pTSRow, &pBlockScanInfo->lastProcKey);
15,710,420✔
5371
        if (code != TSDB_CODE_SUCCESS) {
15,711,177!
UNCOV
5372
          if (freeTSRow) {
×
UNCOV
5373
            taosMemoryFreeClear(row.pTSRow);
×
5374
          }
UNCOV
5375
          TSDB_CHECK_CODE(code, lino, _end);
×
5376
        }
5377
      }
5378

5379
      if (freeTSRow) {
985,120,680✔
5380
        taosMemoryFreeClear(row.pTSRow);
1,729,327!
5381
      }
5382
    } else {
5383
      code = doAppendRowFromFileBlock(pBlock, pReader, row.pBlockData, row.iRow);
1,759,221✔
5384
      TSDB_CHECK_CODE(code, lino, _end);
41,107!
5385

5386
      tColRowGetKeyDeepCopy(row.pBlockData, row.iRow, pReader->suppInfo.pkSrcSlot, &pBlockScanInfo->lastProcKey);
41,107!
5387
    }
5388

5389
    // no data in buffer, return immediately
5390
    if (!(pBlockScanInfo->iter.hasVal || pBlockScanInfo->iiter.hasVal)) {
985,164,626✔
5391
      break;
3,160,964✔
5392
    }
5393

5394
    if (pBlock->info.rows >= capacity) {
982,003,662✔
5395
      break;
117,318✔
5396
    }
5397
  } while (1);
5398

5399
_end:
5,010,200✔
5400
  if (code != TSDB_CODE_SUCCESS) {
5,010,200✔
5401
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
5402
  }
5403
  return code;
5,010,258✔
5404
}
5405

5406
// TODO refactor: with createDataBlockScanInfo
5407
int32_t tsdbSetTableList2(STsdbReader* pReader, const void* pTableList, int32_t num) {
20,118✔
5408
  int32_t               code = TSDB_CODE_SUCCESS;
20,118✔
5409
  int32_t               lino = 0;
20,118✔
5410
  int32_t               size = 0;
20,118✔
5411
  STableBlockScanInfo** p = NULL;
20,118✔
5412
  STableUidList*        pUidList = NULL;
20,118✔
5413
  int32_t               iter = 0;
20,118✔
5414
  bool                  acquired = false;
20,118✔
5415

5416
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
20,118!
5417

5418
  size = tSimpleHashGetSize(pReader->status.pTableMap);
20,118✔
5419

5420
  code = tsdbAcquireReader(pReader);
20,117✔
5421
  TSDB_CHECK_CODE(code, lino, _end);
20,118!
5422
  acquired = true;
20,118✔
5423

5424
  while ((p = tSimpleHashIterate(pReader->status.pTableMap, p, &iter)) != NULL) {
40,319✔
5425
    clearBlockScanInfo(*p);
20,202✔
5426
  }
5427

5428
  tSimpleHashClear(pReader->status.pTableMap);
20,116✔
5429

5430
  if (size < num) {
20,117✔
5431
    code = ensureBlockScanInfoBuf(&pReader->blockInfoBuf, num);
7✔
5432
    TSDB_CHECK_CODE(code, lino, _end);
6!
5433

5434
    char* p1 = taosMemoryRealloc(pReader->status.uidList.tableUidList, sizeof(uint64_t) * num);
6!
5435
    TSDB_CHECK_NULL(p1, code, lino, _end, terrno);
6!
5436

5437
    pReader->status.uidList.tableUidList = (uint64_t*)p1;
6✔
5438
  }
5439

5440
  pUidList = &pReader->status.uidList;
20,116✔
5441
  pUidList->currentIndex = 0;
20,116✔
5442

5443
  STableKeyInfo* pList = (STableKeyInfo*)pTableList;
20,116✔
5444
  for (int32_t i = 0; i < num; ++i) {
40,239✔
5445
    pUidList->tableUidList[i] = pList[i].uid;
20,123✔
5446

5447
    STableBlockScanInfo* pInfo = NULL;
20,123✔
5448
    code = getPosInBlockInfoBuf(&pReader->blockInfoBuf, i, &pInfo);
20,123✔
5449
    TSDB_CHECK_CODE(code, lino, _end);
20,126!
5450

5451
    code = initTableBlockScanInfo(pInfo, pList[i].uid, pReader->status.pTableMap, pReader);
20,126✔
5452
    TSDB_CHECK_CODE(code, lino, _end);
20,123!
5453
  }
5454

5455
_end:
20,116✔
5456
  if (code != TSDB_CODE_SUCCESS) {
20,116!
UNCOV
5457
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5458
  }
5459
  if (acquired) {
20,114!
5460
    (void)tsdbReleaseReader(pReader);
20,114✔
5461
  }
5462
  return code;
20,116✔
5463
}
5464

UNCOV
5465
uint64_t tsdbGetReaderMaxVersion2(STsdbReader* pReader) { return pReader->info.verRange.maxVer; }
×
5466

5467
static int32_t doOpenReaderImpl(STsdbReader* pReader) {
4,515,928✔
5468
  int32_t         code = TSDB_CODE_SUCCESS;
4,515,928✔
5469
  int32_t         lino = 0;
4,515,928✔
5470
  SReaderStatus*  pStatus = NULL;
4,515,928✔
5471
  SDataBlockIter* pBlockIter = NULL;
4,515,928✔
5472

5473
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,515,928!
5474

5475
  pStatus = &pReader->status;
4,515,928✔
5476
  pBlockIter = &pStatus->blockIter;
4,515,928✔
5477

5478
  if (pReader->bFilesetDelimited) {
4,515,928✔
5479
    getMemTableTimeRange(pReader, &pReader->status.memTableMaxKey, &pReader->status.memTableMinKey);
1,894,132✔
5480
    pReader->status.bProcMemFirstFileset = true;
1,895,489✔
5481
  }
5482

5483
  code = initFilesetIterator(&pStatus->fileIter, pReader->pReadSnap->pfSetArray, pReader);
4,517,285✔
5484
  TSDB_CHECK_CODE(code, lino, _end);
4,513,713!
5485

5486
  code = resetDataBlockIterator(&pStatus->blockIter, pReader->info.order, shouldFreePkBuf(&pReader->suppInfo),
4,511,244✔
5487
                                pReader->idStr);
4,513,713✔
5488
  TSDB_CHECK_CODE(code, lino, _end);
4,513,888!
5489

5490
  if (pStatus->fileIter.numOfFiles == 0) {
4,513,888✔
5491
    pStatus->loadFromFile = false;
2,421,399✔
5492
  } else {
5493
    code = initForFirstBlockInFile(pReader, pBlockIter);
2,092,489✔
5494
  }
5495

5496
  if (!pStatus->loadFromFile) {
4,516,203✔
5497
    code = resetTableListIndex(pStatus, pReader->idStr);
2,877,362✔
5498
    TSDB_CHECK_CODE(code, lino, _end);
2,874,628!
5499
  }
5500

5501
_end:
4,513,469✔
5502
  if (code != TSDB_CODE_SUCCESS) {
4,513,469!
UNCOV
5503
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5504
  }
5505
  return code;
4,511,614✔
5506
}
5507

5508
static void freeSchemaFunc(void* param) {
85,062✔
5509
  void** p = (void**)param;
85,062✔
5510
  taosMemoryFreeClear(*p);
85,062!
5511
}
85,070✔
5512

5513
static void clearSharedPtr(STsdbReader* p) {
21,972✔
5514
  if (p) {
21,972!
5515
    p->status.pTableMap = NULL;
21,972✔
5516
    p->status.uidList.tableUidList = NULL;
21,972✔
5517
    p->info.pSchema = NULL;
21,972✔
5518
    p->pReadSnap = NULL;
21,972✔
5519
    p->pSchemaMap = NULL;
21,972✔
5520
  }
5521
}
21,972✔
5522

5523
static int32_t setSharedPtr(STsdbReader* pDst, const STsdbReader* pSrc) {
15,730✔
5524
  pDst->status.pTableMap = pSrc->status.pTableMap;
15,730✔
5525
  pDst->status.uidList = pSrc->status.uidList;
15,730✔
5526
  pDst->info.pSchema = pSrc->info.pSchema;
15,730✔
5527
  pDst->pSchemaMap = pSrc->pSchemaMap;
15,730✔
5528
  pDst->pReadSnap = pSrc->pReadSnap;
15,730✔
5529
  pDst->pReadSnap->pfSetArray = pSrc->pReadSnap->pfSetArray;
15,730✔
5530

5531
  if (pDst->info.pSchema) {
15,730!
5532
    return tsdbRowMergerInit(&pDst->status.merger, pDst->info.pSchema);
15,730✔
5533
  }
5534

UNCOV
5535
  return TSDB_CODE_SUCCESS;
×
5536
}
5537

5538
// ====================================== EXPOSED APIs ======================================
5539
int32_t tsdbReaderOpen2(void* pVnode, SQueryTableDataCond* pCond, void* pTableList, int32_t numOfTables,
4,649,489✔
5540
                        SSDataBlock* pResBlock, void** ppReader, const char* idstr, SHashObj** pIgnoreTables) {
5541
  int32_t      code = TSDB_CODE_SUCCESS;
4,649,489✔
5542
  int32_t      lino = 0;
4,649,489✔
5543
  STimeWindow  window = {0};
4,649,489✔
5544
  SVnodeCfg*   pConf = NULL;
4,649,489✔
5545
  STsdbReader* pReader = NULL;
4,649,489✔
5546
  int32_t      capacity = 0;
4,649,489✔
5547

5548
  window = pCond->twindows;
4,649,489✔
5549
  pConf = &(((SVnode*)pVnode)->config);
4,649,489✔
5550

5551
  capacity = pConf->tsdbCfg.maxRows;
4,649,489✔
5552
  if (pResBlock != NULL) {
4,649,489!
5553
    code = blockDataEnsureCapacity(pResBlock, capacity);
4,658,180✔
5554
    TSDB_CHECK_CODE(code, lino, _end);
4,662,221!
5555
  }
5556

5557
  code = tsdbReaderCreate(pVnode, pCond, ppReader, capacity, pResBlock, idstr);
4,653,530✔
5558
  TSDB_CHECK_CODE(code, lino, _end);
4,648,740!
5559

5560
  // check for query time window
5561
  pReader = *ppReader;
4,648,740✔
5562
  if (isEmptyQueryTimeWindow(&pReader->info.window) && pCond->type == TIMEWINDOW_RANGE_CONTAINED) {
4,648,740✔
5563
    tsdbDebug("%p query window not overlaps with the data set, no result returned, %s", pReader, pReader->idStr);
35,360✔
5564
    goto _end;
35,357✔
5565
  }
5566

5567
  if (pCond->type == TIMEWINDOW_RANGE_EXTERNAL) {
4,609,676✔
5568
    // update the SQueryTableDataCond to create inner reader
5569
    int32_t order = pCond->order;
10,986✔
5570
    if (order == TSDB_ORDER_ASC) {
10,986!
5571
      pCond->twindows = pCond->extTwindows[0];
10,986✔
5572
      pCond->order = TSDB_ORDER_DESC;
10,986✔
5573
    } else {
UNCOV
5574
      pCond->twindows = pCond->extTwindows[1];
×
UNCOV
5575
      pCond->order = TSDB_ORDER_ASC;
×
5576
    }
5577

5578
    // here we only need one more row, so the capacity is set to be ONE.
5579
    code = tsdbReaderCreate(pVnode, pCond, (void**)&((STsdbReader*)pReader)->innerReader[0], 1, pResBlock, idstr);
10,986✔
5580
    TSDB_CHECK_CODE(code, lino, _end);
10,986!
5581

5582
    if (order == TSDB_ORDER_ASC) {
10,986!
5583
      pCond->twindows = pCond->extTwindows[1];
10,986✔
5584
    } else {
UNCOV
5585
      pCond->twindows = pCond->extTwindows[0];
×
5586
    }
5587
    pCond->order = order;
10,986✔
5588

5589
    code = tsdbReaderCreate(pVnode, pCond, (void**)&((STsdbReader*)pReader)->innerReader[1], 1, pResBlock, idstr);
10,986✔
5590
    TSDB_CHECK_CODE(code, lino, _end);
10,986!
5591
  }
5592

5593
  // NOTE: the endVersion in pCond is the data version not schema version, so pCond->endVersion is not correct here.
5594
  //  no valid error code set in metaGetTbTSchema, so let's set the error code here.
5595
  //  we should proceed in case of tmq processing.
5596
  if (pCond->suid != 0) {
4,609,676✔
5597
    code = metaGetTbTSchemaMaybeNull(pReader->pTsdb->pVnode->pMeta, pReader->info.suid, -1, 1, &pReader->info.pSchema);
4,336,079✔
5598
    TSDB_CHECK_CODE(code, lino, _end);
4,345,981!
5599
    if (pReader->info.pSchema == NULL) {
4,345,981✔
5600
      tsdbWarn("failed to get table schema, suid:%" PRIu64 ", ver:-1, %s", pReader->info.suid, pReader->idStr);
81!
5601
    }
5602
  } else if (numOfTables > 0) {
273,597!
5603
    STableKeyInfo* pKey = pTableList;
280,291✔
5604
    code = metaGetTbTSchemaMaybeNull(pReader->pTsdb->pVnode->pMeta, pKey->uid, -1, 1, &pReader->info.pSchema);
280,291✔
5605
    TSDB_CHECK_CODE(code, lino, _end);
280,398!
5606
    if (pReader->info.pSchema == NULL) {
280,398!
UNCOV
5607
      tsdbWarn("failed to get table schema, uid:%" PRIu64 ", ver:-1, %s", pKey->uid, pReader->idStr);
×
5608
    }
5609
  }
5610

5611
  if (pReader->info.pSchema != NULL) {
4,619,685!
5612
    code = tsdbRowMergerInit(&pReader->status.merger, pReader->info.pSchema);
4,619,848✔
5613
    TSDB_CHECK_CODE(code, lino, _end);
4,623,910!
5614
  }
5615

5616
  pReader->pSchemaMap = tSimpleHashInit(8, taosFastHash);
4,623,747✔
5617
  if (pReader->pSchemaMap == NULL) {
4,627,459!
UNCOV
5618
    tsdbError("failed init schema hash for reader %s", pReader->idStr);
×
UNCOV
5619
    TSDB_CHECK_NULL(pReader->pSchemaMap, code, lino, _end, terrno);
×
5620
  }
5621

5622
  tSimpleHashSetFreeFp(pReader->pSchemaMap, freeSchemaFunc);
4,627,459✔
5623
  if (pReader->info.pSchema != NULL) {
4,623,322✔
5624
    code = updateBlockSMAInfo(pReader->info.pSchema, &pReader->suppInfo);
4,621,574✔
5625
    TSDB_CHECK_CODE(code, lino, _end);
4,619,355✔
5626
  }
5627

5628
  STsdbReader* p = (pReader->innerReader[0] != NULL) ? pReader->innerReader[0] : pReader;
4,621,087✔
5629

5630
  code = createDataBlockScanInfo(p, &pReader->blockInfoBuf, pTableList, &pReader->status.uidList, numOfTables,
4,621,087✔
5631
                                 &pReader->status.pTableMap);
5632
  TSDB_CHECK_CODE(code, lino, _end);
4,625,605!
5633

5634
  pReader->status.pLDataIterArray = taosArrayInit(4, POINTER_BYTES);
4,625,605✔
5635
  TSDB_CHECK_NULL(pReader->status.pLDataIterArray, code, lino, _end, terrno);
4,629,609✔
5636

5637
  pReader->flag = READER_STATUS_SUSPEND;
4,628,697✔
5638
  pReader->info.execMode = pCond->notLoadData ? READER_EXEC_ROWS : READER_EXEC_DATA;
4,628,697✔
5639

5640
  pReader->pIgnoreTables = pIgnoreTables;
4,628,697✔
5641
  tsdbDebug("%p total numOfTable:%d, window:%" PRId64 " - %" PRId64 ", verRange:%" PRId64 " - %" PRId64
4,628,697✔
5642
            " in this query %s",
5643
            pReader, numOfTables, pReader->info.window.skey, pReader->info.window.ekey, pReader->info.verRange.minVer,
5644
            pReader->info.verRange.maxVer, pReader->idStr);
5645

5646
_end:
4,504,590✔
5647
  if (code != TSDB_CODE_SUCCESS) {
4,662,533✔
5648
    tsdbError("%s failed at line %d since %s, %s", __func__, lino, tstrerror(code), idstr);
16!
5649
    tsdbReaderClose2(*ppReader);
16✔
5650
    *ppReader = NULL;  // reset the pointer value.
16✔
5651
  }
5652
  return code;
4,662,533✔
5653
}
5654

5655
void tsdbReaderClose2(STsdbReader* pReader) {
8,721,714✔
5656
  if (pReader == NULL) {
8,721,714✔
5657
    return;
4,035,255✔
5658
  }
5659

5660
  int32_t code = tsdbAcquireReader(pReader);
4,686,459✔
5661
  if (code) {
4,688,369!
UNCOV
5662
    return;
×
5663
  }
5664

5665
  {
5666
    if (pReader->innerReader[0] != NULL || pReader->innerReader[1] != NULL) {
4,688,369!
5667
      STsdbReader* p = pReader->innerReader[0];
11,016✔
5668
      clearSharedPtr(p);
11,016✔
5669

5670
      p = pReader->innerReader[1];
10,986✔
5671
      clearSharedPtr(p);
10,986✔
5672

5673
      tsdbReaderClose2(pReader->innerReader[0]);
10,986✔
5674
      tsdbReaderClose2(pReader->innerReader[1]);
10,986✔
5675
    }
5676
  }
5677

5678
  SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo;
4,686,978✔
5679
  TARRAY2_DESTROY(&pSupInfo->colAggArray, NULL);
4,686,978!
5680

5681
  if (pSupInfo->buildBuf) {
4,686,978✔
5682
    for (int32_t i = 0; i < pSupInfo->numOfCols; ++i) {
26,726,315✔
5683
      if (pSupInfo->buildBuf[i] != NULL) {
22,039,586✔
5684
        taosMemoryFreeClear(pSupInfo->buildBuf[i]);
3,050,265!
5685
      }
5686
    }
5687
  }
5688

5689
  if (pReader->resBlockInfo.freeBlock) {
4,686,750✔
5690
    blockDataDestroy(pReader->resBlockInfo.pResBlock);
2,539✔
5691
    pReader->resBlockInfo.pResBlock = NULL;
2,540✔
5692
  }
5693

5694
  taosMemoryFree(pSupInfo->colId);
4,686,751!
5695
  tBlockDataDestroy(&pReader->status.fileBlockData);
4,687,504✔
5696
  cleanupDataBlockIterator(&pReader->status.blockIter, shouldFreePkBuf(&pReader->suppInfo));
4,684,749✔
5697

5698
  size_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
4,687,560✔
5699
  if (pReader->status.pTableMap != NULL) {
4,687,216✔
5700
    destroyAllBlockScanInfo(&pReader->status.pTableMap);
4,629,990✔
5701
  }
5702
  clearBlockScanInfoBuf(&pReader->blockInfoBuf);
4,687,822✔
5703

5704
  if (pReader->pFileReader != NULL) {
4,687,788✔
5705
    tsdbDataFileReaderClose(&pReader->pFileReader);
58,554✔
5706
  }
5707

5708
  SReadCostSummary* pCost = &pReader->cost;
4,687,789✔
5709
  SFilesetIter*     pFilesetIter = &pReader->status.fileIter;
4,687,789✔
5710
  if (pFilesetIter->pSttBlockReader != NULL) {
4,687,789✔
5711
    SSttBlockReader* pSttBlockReader = pFilesetIter->pSttBlockReader;
4,521,056✔
5712
    tMergeTreeClose(&pSttBlockReader->mergeTree);
4,521,056✔
5713

5714
    clearRowKey(&pSttBlockReader->currentKey);
4,520,566✔
5715
    taosMemoryFree(pSttBlockReader);
4,520,187!
5716
  }
5717

5718
  destroySttBlockReader(pReader->status.pLDataIterArray, &pCost->sttCost);
4,688,092✔
5719
  pReader->status.pLDataIterArray = NULL;
4,687,580✔
5720
  taosMemoryFreeClear(pReader->status.uidList.tableUidList);
4,687,580!
5721

5722
  tsdbTrace("tsdb/reader-close: %p, untake snapshot", pReader);
4,687,833✔
5723
  void* p = pReader->pReadSnap;
4,687,833✔
5724
  if ((p == atomic_val_compare_exchange_ptr((void**)&pReader->pReadSnap, p, NULL)) && (p != NULL)) {
4,687,833✔
5725
    tsdbUntakeReadSnap2(pReader, p, true);
4,505,486✔
5726
    pReader->pReadSnap = NULL;
4,503,852✔
5727
  }
5728

5729
  (void) tsem_destroy(&pReader->resumeAfterSuspend);
4,686,466✔
5730
  (void) tsdbReleaseReader(pReader);
4,686,203✔
5731
  (void) tsdbUninitReaderLock(pReader);
4,688,047✔
5732

5733
  tsdbDebug(
4,685,886✔
5734
      "%p :io-cost summary: head-file:%" PRIu64 ", head-file time:%.2f ms, SMA:%" PRId64
5735
      " SMA-time:%.2f ms, fileBlocks:%" PRId64
5736
      ", fileBlocks-load-time:%.2f ms, "
5737
      "build in-memory-block-time:%.2f ms, sttBlocks:%" PRId64 ", sttBlocks-time:%.2f ms, sttStatisBlock:%" PRId64
5738
      ", stt-statis-Block-time:%.2f ms, composed-blocks:%" PRId64
5739
      ", composed-blocks-time:%.2fms, STableBlockScanInfo size:%.2f Kb, createTime:%.2f ms,createSkylineIterTime:%.2f "
5740
      "ms, initSttBlockReader:%.2fms, %s",
5741
      pReader, pCost->headFileLoad, pCost->headFileLoadTime, pCost->smaDataLoad, pCost->smaLoadTime, pCost->numOfBlocks,
5742
      pCost->blockLoadTime, pCost->buildmemBlock, pCost->sttCost.loadBlocks, pCost->sttCost.blockElapsedTime,
5743
      pCost->sttCost.loadStatisBlocks, pCost->sttCost.statisElapsedTime, pCost->composedBlocks,
5744
      pCost->buildComposedBlockTime, numOfTables * sizeof(STableBlockScanInfo) / 1000.0, pCost->createScanInfoList,
5745
      pCost->createSkylineIterTime, pCost->initSttBlockReader, pReader->idStr);
5746

5747
  taosMemoryFree(pReader->idStr);
4,685,886✔
5748

5749
  tsdbRowMergerCleanup(&pReader->status.merger);
4,685,330✔
5750
  taosMemoryFree(pReader->info.pSchema);
4,687,243!
5751

5752
  tSimpleHashCleanup(pReader->pSchemaMap);
4,688,075✔
5753
  taosMemoryFreeClear(pReader);
4,688,101!
5754
}
5755

5756
static int32_t doSuspendCurrentReader(STsdbReader* pCurrentReader) {
×
UNCOV
5757
  int32_t               code = TSDB_CODE_SUCCESS;
×
UNCOV
5758
  int32_t               lino = 0;
×
UNCOV
5759
  SReaderStatus*        pStatus = NULL;
×
5760
  STableBlockScanInfo** p = NULL;
×
5761

5762
  TSDB_CHECK_NULL(pCurrentReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
5763

5764
  pStatus = &pCurrentReader->status;
×
5765

UNCOV
5766
  if (pStatus->loadFromFile) {
×
UNCOV
5767
    tsdbDataFileReaderClose(&pCurrentReader->pFileReader);
×
5768

5769
    SReadCostSummary* pCost = &pCurrentReader->cost;
×
5770
    destroySttBlockReader(pStatus->pLDataIterArray, &pCost->sttCost);
×
UNCOV
5771
    pStatus->pLDataIterArray = taosArrayInit(4, POINTER_BYTES);
×
5772
    TSDB_CHECK_NULL(pStatus->pLDataIterArray, code, lino, _end, terrno);
×
5773
  }
5774

5775
  // resetDataBlockScanInfo excluding lastKey
5776
  int32_t step = ASCENDING_TRAVERSE(pCurrentReader->info.order) ? 1 : -1;
×
UNCOV
5777
  int32_t iter = 0;
×
UNCOV
5778
  while ((p = tSimpleHashIterate(pStatus->pTableMap, p, &iter)) != NULL) {
×
5779
    STableBlockScanInfo* pInfo = *(STableBlockScanInfo**)p;
×
5780
    clearBlockScanInfo(pInfo);
×
5781
    //    pInfo->sttKeyInfo.nextProcKey = pInfo->lastProcKey.ts + step;
5782
    //    pInfo->sttKeyInfo.nextProcKey = pInfo->lastProcKey + step;
5783
  }
5784

UNCOV
5785
  pStatus->uidList.currentIndex = 0;
×
5786
  initReaderStatus(pStatus);
×
5787

5788
_end:
×
5789
  if (code != TSDB_CODE_SUCCESS) {
×
5790
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5791
  }
5792
  return code;
×
5793
}
5794

UNCOV
5795
int32_t tsdbReaderSuspend2(STsdbReader* pReader) {
×
UNCOV
5796
  int32_t code = TSDB_CODE_SUCCESS;
×
5797
  int32_t lino = 0;
×
5798

UNCOV
5799
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
×
5800

5801
  // save reader's base state & reset top state to be reconstructed from base state
5802
  pReader->status.suspendInvoked = true;  // record the suspend status
×
5803

5804
  if (pReader->type == TIMEWINDOW_RANGE_EXTERNAL) {
×
UNCOV
5805
    if (pReader->step == EXTERNAL_ROWS_PREV) {
×
UNCOV
5806
      code = doSuspendCurrentReader(pReader->innerReader[0]);
×
5807
    } else if (pReader->step == EXTERNAL_ROWS_MAIN) {
×
5808
      code = doSuspendCurrentReader(pReader);
×
5809
    } else {
UNCOV
5810
      code = doSuspendCurrentReader(pReader->innerReader[1]);
×
5811
    }
5812
  } else {
5813
    code = doSuspendCurrentReader(pReader);
×
5814
  }
5815

5816
  // make sure only release once
UNCOV
5817
  void* p = pReader->pReadSnap;
×
UNCOV
5818
  if ((p == atomic_val_compare_exchange_ptr((void**)&pReader->pReadSnap, p, NULL)) && (p != NULL)) {
×
UNCOV
5819
    tsdbUntakeReadSnap2(pReader, p, false);
×
UNCOV
5820
    pReader->pReadSnap = NULL;
×
5821
  }
5822

UNCOV
5823
  if (pReader->bFilesetDelimited) {
×
5824
    pReader->status.memTableMinKey = INT64_MAX;
×
5825
    pReader->status.memTableMaxKey = INT64_MIN;
×
5826
  }
UNCOV
5827
  pReader->flag = READER_STATUS_SUSPEND;
×
5828

UNCOV
5829
  if (pReader->type == TIMEWINDOW_RANGE_EXTERNAL) {
×
UNCOV
5830
    clearSharedPtr(pReader->innerReader[0]);
×
5831
    clearSharedPtr(pReader->innerReader[1]);
×
5832
  }
5833

5834
#if SUSPEND_RESUME_TEST
5835
  tsem_post(&pReader->resumeAfterSuspend);
5836
#endif
5837

5838
  tsdbDebug("reader: %p suspended in this query %s, step:%d", pReader, pReader->idStr, pReader->step);
×
5839

UNCOV
5840
_end:
×
UNCOV
5841
  if (code != TSDB_CODE_SUCCESS) {
×
5842
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5843
  }
5844
  return code;
×
5845
}
5846

UNCOV
5847
static int32_t tsdbSetQueryReseek(void* pQHandle) {
×
5848
  int32_t      code = 0;
×
5849
  STsdbReader* pReader = pQHandle;
×
5850

UNCOV
5851
  code = tsdbTryAcquireReader(pReader);
×
UNCOV
5852
  if (code == 0) {
×
UNCOV
5853
    if (pReader->flag == READER_STATUS_SUSPEND) {
×
UNCOV
5854
      code = tsdbReleaseReader(pReader);
×
UNCOV
5855
      return code;
×
5856
    }
5857

UNCOV
5858
    code = tsdbReaderSuspend2(pReader);
×
UNCOV
5859
    (void)tsdbReleaseReader(pReader);
×
UNCOV
5860
    return code;
×
UNCOV
5861
  } else if (code == EBUSY) {
×
UNCOV
5862
    return TSDB_CODE_VND_QUERY_BUSY;
×
5863
  } else {
UNCOV
5864
    terrno = TAOS_SYSTEM_ERROR(code);
×
UNCOV
5865
    return TSDB_CODE_FAILED;
×
5866
  }
5867
}
5868

5869
int32_t tsdbReaderResume2(STsdbReader* pReader) {
4,620,554✔
5870
  int32_t               code = TSDB_CODE_SUCCESS;
4,620,554✔
5871
  int32_t               lino = 0;
4,620,554✔
5872
  STableBlockScanInfo** pBlockScanInfo = NULL;
4,620,554✔
5873
  int32_t               numOfTables = 0;
4,620,554✔
5874

5875
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
4,620,554!
5876

5877
  pBlockScanInfo = pReader->status.pTableIter;
4,620,554✔
5878

5879
  //  restore reader's state, task snapshot
5880
  numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
4,620,554✔
5881
  if (numOfTables > 0) {
4,615,921✔
5882
    tsdbTrace("tsdb/reader: %p, take snapshot", pReader);
4,494,700✔
5883
    code = tsdbTakeReadSnap2(pReader, tsdbSetQueryReseek, &pReader->pReadSnap, pReader->idStr);
4,494,700✔
5884
    TSDB_CHECK_CODE(code, lino, _end);
4,502,044!
5885

5886
    // open reader failure may cause the flag still to be READER_STATUS_SUSPEND, which may cause suspend reader failure.
5887
    // So we need to set it A.S.A.P
5888
    pReader->flag = READER_STATUS_NORMAL;
4,502,044✔
5889

5890
    if (pReader->type == TIMEWINDOW_RANGE_CONTAINED) {
4,502,044✔
5891
      code = doOpenReaderImpl(pReader);
4,494,751✔
5892
      TSDB_CHECK_CODE(code, lino, _end);
4,488,131!
5893
    } else {
5894
      STsdbReader* pPrevReader = pReader->innerReader[0];
7,293✔
5895
      STsdbReader* pNextReader = pReader->innerReader[1];
7,293✔
5896

5897
      // we need only one row
5898
      pPrevReader->resBlockInfo.capacity = 1;
7,293✔
5899
      code = setSharedPtr(pPrevReader, pReader);
7,293✔
5900
      TSDB_CHECK_CODE(code, lino, _end);
7,865!
5901

5902
      pNextReader->resBlockInfo.capacity = 1;
7,865✔
5903
      code = setSharedPtr(pNextReader, pReader);
7,865✔
5904
      TSDB_CHECK_CODE(code, lino, _end);
7,865!
5905

5906
      if (pReader->step == 0 || pReader->step == EXTERNAL_ROWS_PREV) {
7,865!
5907
        code = doOpenReaderImpl(pPrevReader);
7,865✔
5908
        TSDB_CHECK_CODE(code, lino, _end);
7,865!
UNCOV
5909
      } else if (pReader->step == EXTERNAL_ROWS_MAIN) {
×
UNCOV
5910
        code = doOpenReaderImpl(pReader);
×
UNCOV
5911
        TSDB_CHECK_CODE(code, lino, _end);
×
5912
      } else {
UNCOV
5913
        code = doOpenReaderImpl(pNextReader);
×
UNCOV
5914
        TSDB_CHECK_CODE(code, lino, _end);
×
5915
      }
5916
    }
5917
  }
5918

5919
  tsdbDebug("reader: %p resumed uid %" PRIu64 ", numOfTable:%" PRId32 ", in this query %s", pReader,
4,617,217!
5920
            pBlockScanInfo ? (*pBlockScanInfo)->uid : 0, numOfTables, pReader->idStr);
5921

5922
_end:
4,496,226✔
5923
  if (code != TSDB_CODE_SUCCESS) {
4,617,224!
UNCOV
5924
    tsdbError("%s failed at line %d since %s, %s", __func__, lino, tstrerror(code),
×
5925
              (pReader && pReader->idStr) ? pReader->idStr : "");
5926
  }
5927
  return code;
4,617,402✔
5928
}
5929

5930
static int32_t buildFromPreFilesetBuffer(STsdbReader* pReader) {
1,233,650✔
5931
  int32_t        code = TSDB_CODE_SUCCESS;
1,233,650✔
5932
  int32_t        lino = 0;
1,233,650✔
5933
  SReaderStatus* pStatus = NULL;
1,233,650✔
5934
  SSDataBlock*   pBlock = NULL;
1,233,650✔
5935
  int32_t        fid = 0;
1,233,650✔
5936
  STimeWindow    win = {0};
1,233,650✔
5937

5938
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,233,650!
5939

5940
  pStatus = &pReader->status;
1,233,650✔
5941
  pBlock = pReader->resBlockInfo.pResBlock;
1,233,650✔
5942
  fid = pReader->status.pCurrentFileset->fid;
1,233,650✔
5943
  tsdbFidKeyRange(fid, pReader->pTsdb->keepCfg.days, pReader->pTsdb->keepCfg.precision, &win.skey, &win.ekey);
1,233,650✔
5944

5945
  int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? win.skey : win.ekey;
1,233,658✔
5946
  code = buildBlockFromBufferSeqForPreFileset(pReader, endKey);
1,233,658✔
5947
  TSDB_CHECK_CODE(code, lino, _end);
1,233,675!
5948
  if (pBlock->info.rows <= 0) {
1,233,675✔
5949
    tsdbDebug("finished pre-fileset %d buffer processing. %s", fid, pReader->idStr);
1,012,485!
5950
    pStatus->bProcMemPreFileset = false;
1,012,484✔
5951
    pStatus->processingMemPreFileSet = false;
1,012,484✔
5952
    if (pReader->notifyFn) {
1,012,484✔
5953
      STsdReaderNotifyInfo info = {0};
1,012,472✔
5954
      info.duration.filesetId = fid;
1,012,472✔
5955
      pReader->notifyFn(TSD_READER_NOTIFY_DURATION_START, &info, pReader->notifyParam);
1,012,472✔
5956
      tsdbDebug("new duration %d start notification when buffer pre-fileset, %s", fid, pReader->idStr);
1,012,471!
5957
    }
5958
  }
5959

5960
_end:
221,202✔
5961
  if (code != TSDB_CODE_SUCCESS) {
1,233,673!
UNCOV
5962
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5963
  }
5964
  return code;
1,233,674✔
5965
}
5966

5967
static int32_t doTsdbNextDataBlockFilesetDelimited(STsdbReader* pReader) {
6,112,023✔
5968
  int32_t        code = TSDB_CODE_SUCCESS;
6,112,023✔
5969
  int32_t        lino = 0;
6,112,023✔
5970
  SReaderStatus* pStatus = NULL;
6,112,023✔
5971
  SSDataBlock*   pBlock = NULL;
6,112,023✔
5972

5973
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
6,112,023!
5974

5975
  pStatus = &pReader->status;
6,112,023✔
5976
  pBlock = pReader->resBlockInfo.pResBlock;
6,112,023✔
5977

5978
  if (pStatus->loadFromFile) {
6,112,023✔
5979
    if (pStatus->bProcMemPreFileset) {
3,649,819✔
5980
      code = buildFromPreFilesetBuffer(pReader);
276,756✔
5981
      TSDB_CHECK_CODE(code, lino, _end);
276,764!
5982
      if (pBlock->info.rows > 0) {
276,764✔
5983
        goto _end;
74,802✔
5984
      }
5985
    }
5986

5987
    code = buildBlockFromFiles(pReader);
3,575,025✔
5988
    TSDB_CHECK_CODE(code, lino, _end);
3,576,253!
5989

5990
    tsdbTrace("block from file rows: %" PRId64 ", will process pre-file set buffer: %d. %s", pBlock->info.rows,
3,576,253✔
5991
              pStatus->bProcMemFirstFileset, pReader->idStr);
5992
    if (pStatus->bProcMemPreFileset) {
3,576,253✔
5993
      if (pBlock->info.rows > 0) {
146,393!
5994
        if (pReader->notifyFn && !pReader->status.processingMemPreFileSet) {
146,393!
UNCOV
5995
          int32_t              fid = pReader->status.pCurrentFileset->fid;
×
UNCOV
5996
          STsdReaderNotifyInfo info = {0};
×
UNCOV
5997
          info.duration.filesetId = fid;
×
UNCOV
5998
          pReader->notifyFn(TSD_READER_NOTIFY_NEXT_DURATION_BLOCK, &info, pReader->notifyParam);
×
5999
        }
6000
      } else {
UNCOV
6001
        pStatus->bProcMemPreFileset = false;
×
6002
      }
6003
    }
6004

6005
    if (pBlock->info.rows <= 0) {
3,576,253✔
6006
      code = resetTableListIndex(&pReader->status, pReader->idStr);
743,855✔
6007
      TSDB_CHECK_CODE(code, lino, _end);
743,858!
6008

6009
      int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
743,858✔
6010
      code = buildBlockFromBufferSequentially(pReader, endKey);
743,858✔
6011
      TSDB_CHECK_CODE(code, lino, _end);
743,860!
6012
    }
6013
  } else {  // no data in files, let's try the buffer
6014
    int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
2,462,204✔
6015
    code = buildBlockFromBufferSequentially(pReader, endKey);
2,462,204✔
6016
    TSDB_CHECK_CODE(code, lino, _end);
2,464,000!
6017
  }
6018

6019
_end:
2,464,000✔
6020
  if (code != TSDB_CODE_SUCCESS) {
6,115,060!
UNCOV
6021
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6022
  }
6023
  return code;
6,114,825✔
6024
}
6025

6026
static int32_t doTsdbNextDataBlockFilesFirst(STsdbReader* pReader) {
11,001,881✔
6027
  int32_t        code = TSDB_CODE_SUCCESS;
11,001,881✔
6028
  int32_t        lino = 0;
11,001,881✔
6029
  SReaderStatus* pStatus = NULL;
11,001,881✔
6030
  SSDataBlock*   pBlock = NULL;
11,001,881✔
6031

6032
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
11,001,881!
6033

6034
  pStatus = &pReader->status;
11,001,881✔
6035
  pBlock = pReader->resBlockInfo.pResBlock;
11,001,881✔
6036

6037
  if (pStatus->loadFromFile) {
11,001,881✔
6038
    code = buildBlockFromFiles(pReader);
7,422,779✔
6039
    TSDB_CHECK_CODE(code, lino, _end);
7,422,029!
6040

6041
    if (pBlock->info.rows <= 0) {
7,422,029✔
6042
      code = resetTableListIndex(&pReader->status, pReader->idStr);
877,282✔
6043
      TSDB_CHECK_CODE(code, lino, _end);
877,317!
6044

6045
      int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
877,317✔
6046
      code = buildBlockFromBufferSequentially(pReader, endKey);
877,317✔
6047
      TSDB_CHECK_CODE(code, lino, _end);
877,333!
6048
    }
6049
  } else {  // no data in files, let's try the buffer
6050
    int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
3,579,102✔
6051
    code = buildBlockFromBufferSequentially(pReader, endKey);
3,579,102✔
6052
    TSDB_CHECK_CODE(code, lino, _end);
3,582,001✔
6053
  }
6054

6055
_end:
3,581,997✔
6056
  if (code != TSDB_CODE_SUCCESS) {
11,004,081✔
6057
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
6058
  }
6059
  return code;
11,003,803✔
6060
}
6061

6062
static int32_t doTsdbNextDataBlock2(STsdbReader* pReader, bool* hasNext) {
17,230,853✔
6063
  int32_t      code = TSDB_CODE_SUCCESS;
17,230,853✔
6064
  int32_t      lino = 0;
17,230,853✔
6065
  SSDataBlock* pBlock = NULL;
17,230,853✔
6066

6067
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
17,230,853!
6068

6069
  // cleanup the data that belongs to the previous data block
6070
  pBlock = pReader->resBlockInfo.pResBlock;
17,230,853✔
6071
  blockDataCleanup(pBlock);
17,230,853✔
6072

6073
  *hasNext = false;
17,238,063✔
6074

6075
  SReaderStatus* pStatus = &pReader->status;
17,238,063✔
6076
  if (tSimpleHashGetSize(pStatus->pTableMap) == 0) {
17,238,063✔
6077
    goto _end;
121,583✔
6078
  }
6079

6080
  if (!pReader->bFilesetDelimited) {
17,114,636✔
6081
    code = doTsdbNextDataBlockFilesFirst(pReader);
11,002,239✔
6082
  } else {
6083
    code = doTsdbNextDataBlockFilesetDelimited(pReader);
6,112,397✔
6084
  }
6085

6086
  *hasNext = pBlock->info.rows > 0;
17,119,813✔
6087
  TSDB_CHECK_CODE(code, lino, _end);
17,119,813✔
6088

6089
_end:
17,119,809✔
6090
  if (code != TSDB_CODE_SUCCESS) {
17,241,396✔
6091
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
6092
  }
6093
  return code;
17,241,087✔
6094
}
6095

6096
int32_t tsdbNextDataBlock2(STsdbReader* pReader, bool* hasNext) {
17,271,954✔
6097
  int32_t        code = TSDB_CODE_SUCCESS;
17,271,954✔
6098
  int32_t        lino = 0;
17,271,954✔
6099
  SReaderStatus* pStatus = NULL;
17,271,954✔
6100
  bool           acquired = false;
17,271,954✔
6101

6102
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
17,271,954!
6103
  TSDB_CHECK_NULL(hasNext, code, lino, _end, TSDB_CODE_INVALID_PARA);
17,271,954!
6104

6105
  *hasNext = false;
17,271,954✔
6106

6107
  code = pReader->code;
17,271,954✔
6108
  TSDB_CHECK_CODE(code, lino, _end);
17,271,954!
6109

6110
  if (isEmptyQueryTimeWindow(&pReader->info.window) || pReader->step == EXTERNAL_ROWS_NEXT) {
17,271,954✔
6111
    goto _end;
43,901✔
6112
  }
6113

6114
  pStatus = &pReader->status;
17,229,526✔
6115

6116
  // NOTE: the following codes is used to perform test for suspend/resume for tsdbReader when it blocks the commit
6117
  // the data should be ingested in round-robin and all the child tables should be createted before ingesting data
6118
  // the version range of query will be used to identify the correctness of suspend/resume functions.
6119
  // this function will be blocked before loading the SECOND block from vnode-buffer, and restart itself from sst-files
6120
#if SUSPEND_RESUME_TEST
6121
  if (!pReader->status.suspendInvoked && !pReader->status.loadFromFile) {
6122
    tsem_wait(&pReader->resumeAfterSuspend);
6123
  }
6124
#endif
6125

6126
  code = tsdbAcquireReader(pReader);
17,229,526✔
6127
  TSDB_CHECK_CODE(code, lino, _end);
17,226,207!
6128
  acquired = true;
17,226,207✔
6129

6130
  tsdbTrace("tsdb/read: %p, take read mutex, code: %d", pReader, code);
17,226,207✔
6131

6132
  if (pReader->flag == READER_STATUS_SUSPEND) {
17,226,207✔
6133
    code = tsdbReaderResume2(pReader);
4,613,558✔
6134
    TSDB_CHECK_CODE(code, lino, _end);
4,613,015!
6135
  }
6136

6137
  if (pReader->innerReader[0] != NULL && pReader->step == 0) {
17,225,664✔
6138
    code = doTsdbNextDataBlock2(pReader->innerReader[0], hasNext);
7,865✔
6139
    TSDB_CHECK_CODE(code, lino, _end);
7,865!
6140

6141
    pReader->step = EXTERNAL_ROWS_PREV;
7,865✔
6142
    if (*hasNext) {
7,865✔
6143
      pStatus = &pReader->innerReader[0]->status;
6,678✔
6144
      if (pStatus->composedDataBlock) {
6,678!
6145
        tsdbTrace("tsdb/read: %p, unlock read mutex", pReader);
6,678✔
6146
        code = tsdbReleaseReader(pReader);
6,678✔
6147
        acquired = false;
6,678✔
6148
        TSDB_CHECK_CODE(code, lino, _end);
6,678!
6149
      }
6150

6151
      return code;
6,678✔
6152
    }
6153
  }
6154

6155
  if (pReader->step == EXTERNAL_ROWS_PREV) {
17,218,986✔
6156
    // prepare for the main scan
6157
    if (tSimpleHashGetSize(pReader->status.pTableMap) > 0) {
7,865!
6158
      code = doOpenReaderImpl(pReader);
7,865✔
6159
    }
6160

6161
    int32_t step = 1;
7,865✔
6162
    resetAllDataBlockScanInfo(pReader->status.pTableMap, pReader->innerReader[0]->info.window.ekey, step);
7,865✔
6163
    TSDB_CHECK_CODE(code, lino, _end);
7,865!
6164

6165
    pReader->step = EXTERNAL_ROWS_MAIN;
7,865✔
6166
  }
6167

6168
  code = doTsdbNextDataBlock2(pReader, hasNext);
17,218,986✔
6169
  TSDB_CHECK_CODE(code, lino, _end);
17,224,196✔
6170

6171
  if (*hasNext) {
17,224,192✔
6172
    if (pStatus->composedDataBlock) {
12,714,546✔
6173
      tsdbTrace("tsdb/read: %p, unlock read mutex", pReader);
7,516,837✔
6174
      code = tsdbReleaseReader(pReader);
7,516,837✔
6175
      acquired = false;
7,519,030✔
6176
      TSDB_CHECK_CODE(code, lino, _end);
7,519,030!
6177
    }
6178
    return code;
12,716,739✔
6179
  }
6180

6181
  if (pReader->step == EXTERNAL_ROWS_MAIN && pReader->innerReader[1] != NULL) {
4,509,646!
6182
    // prepare for the next row scan
6183
    if (tSimpleHashGetSize(pReader->status.pTableMap) > 0) {
7,865!
6184
      code = doOpenReaderImpl(pReader->innerReader[1]);
7,865✔
6185
    }
6186

6187
    int32_t step = -1;
7,865✔
6188
    resetAllDataBlockScanInfo(pReader->innerReader[1]->status.pTableMap, pReader->info.window.ekey, step);
7,865✔
6189
    TSDB_CHECK_CODE(code, lino, _end);
7,865!
6190

6191
    code = doTsdbNextDataBlock2(pReader->innerReader[1], hasNext);
7,865✔
6192
    TSDB_CHECK_CODE(code, lino, _end);
7,865!
6193

6194
    pReader->step = EXTERNAL_ROWS_NEXT;
7,865✔
6195
    if (*hasNext) {
7,865✔
6196
      pStatus = &pReader->innerReader[1]->status;
6,635✔
6197
      if (pStatus->composedDataBlock) {
6,635!
6198
        tsdbTrace("tsdb/read: %p, unlock read mutex", pReader);
6,635✔
6199
        code = tsdbReleaseReader(pReader);
6,635✔
6200
        acquired = false;
6,635✔
6201
        TSDB_CHECK_CODE(code, lino, _end);
6,635!
6202
      }
6203

6204
      return code;
6,635✔
6205
    }
6206
  }
6207

6208
  tsdbTrace("tsdb/read: %p, unlock read mutex", pReader);
4,503,011✔
6209
  code = tsdbReleaseReader(pReader);
4,503,011✔
6210
  acquired = false;
4,502,478✔
6211
  TSDB_CHECK_CODE(code, lino, _end);
4,502,478!
6212

6213
_end:
4,502,478✔
6214
  if (code != TSDB_CODE_SUCCESS) {
4,546,383✔
6215
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
4!
6216
  }
6217
  if (acquired) {
4,547,660✔
6218
    tsdbTrace("tsdb/read: %p, unlock read mutex", pReader);
4!
6219
    (void)tsdbReleaseReader(pReader);
4✔
6220
  }
6221
  return code;
4,547,615✔
6222
}
6223

6224
static int32_t doFillNullColSMA(SBlockLoadSuppInfo* pSup, int32_t numOfRows, int32_t numOfCols,
1,708,541✔
6225
                                SColumnDataAgg* pTsAgg) {
6226
  // do fill all null column value SMA info
6227
  int32_t code = TSDB_CODE_SUCCESS;
1,708,541✔
6228
  int32_t lino = 0;
1,708,541✔
6229
  int32_t i = 0, j = 0;
1,708,541✔
6230
  int32_t size = 0;
1,708,541✔
6231

6232
  TSDB_CHECK_NULL(pSup, code, lino, _end, TSDB_CODE_INVALID_PARA);
1,708,541!
6233

6234
  size = (int32_t)TARRAY2_SIZE(&pSup->colAggArray);
1,708,541✔
6235
  code = TARRAY2_INSERT_PTR(&pSup->colAggArray, 0, pTsAgg);
1,708,541!
6236
  TSDB_CHECK_CODE(code, lino, _end);
1,708,541!
6237

6238
  size++;
1,708,541✔
6239

6240
  while (j < numOfCols && i < size) {
5,221,158✔
6241
    SColumnDataAgg* pAgg = &pSup->colAggArray.data[i];
3,512,617✔
6242
    if (pAgg->colId == pSup->colId[j]) {
3,512,617✔
6243
      i += 1;
3,491,663✔
6244
      j += 1;
3,491,663✔
6245
    } else if (pAgg->colId < pSup->colId[j]) {
20,954!
6246
      i += 1;
20,954✔
UNCOV
6247
    } else if (pSup->colId[j] < pAgg->colId) {
×
UNCOV
6248
      if (pSup->colId[j] != PRIMARYKEY_TIMESTAMP_COL_ID) {
×
UNCOV
6249
        SColumnDataAgg nullColAgg = {.colId = pSup->colId[j], .numOfNull = numOfRows};
×
UNCOV
6250
        code = TARRAY2_INSERT_PTR(&pSup->colAggArray, i, &nullColAgg);
×
UNCOV
6251
        TSDB_CHECK_CODE(code, lino, _end);
×
6252

UNCOV
6253
        i += 1;
×
UNCOV
6254
        size++;
×
6255
      }
UNCOV
6256
      j += 1;
×
6257
    }
6258
  }
6259

6260
  while (j < numOfCols) {
1,708,542✔
6261
    if (pSup->colId[j] != PRIMARYKEY_TIMESTAMP_COL_ID) {
1!
6262
      SColumnDataAgg nullColAgg = {.colId = pSup->colId[j], .numOfNull = numOfRows};
1✔
6263
      code = TARRAY2_INSERT_PTR(&pSup->colAggArray, i, &nullColAgg);
1!
6264
      TSDB_CHECK_CODE(code, lino, _end);
1!
6265

6266
      i += 1;
1✔
6267
    }
6268
    j++;
1✔
6269
  }
6270

6271
_end:
1,708,541✔
6272
  if (code != TSDB_CODE_SUCCESS) {
1,708,541!
UNCOV
6273
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6274
  }
6275
  return code;
1,708,541✔
6276
}
6277

6278
int32_t tsdbRetrieveDatablockSMA2(STsdbReader* pReader, SSDataBlock* pDataBlock, bool* allHave, bool* hasNullSMA) {
5,552,433✔
6279
  int32_t             code = TSDB_CODE_SUCCESS;
5,552,433✔
6280
  int32_t             lino = 0;
5,552,433✔
6281
  SColumnDataAgg**    pBlockSMA = NULL;
5,552,433✔
6282
  SFileDataBlockInfo* pBlockInfo = NULL;
5,552,433✔
6283

6284
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,552,433!
6285
  TSDB_CHECK_NULL(pDataBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,552,433!
6286
  TSDB_CHECK_NULL(allHave, code, lino, _end, TSDB_CODE_INVALID_PARA);
5,552,433!
6287

6288
  pBlockSMA = &pDataBlock->pBlockAgg;
5,552,433✔
6289
  *allHave = false;
5,552,433✔
6290
  *pBlockSMA = NULL;
5,552,433✔
6291

6292
  if (pReader->type == TIMEWINDOW_RANGE_EXTERNAL) {
5,552,433✔
6293
    goto _end;
15✔
6294
  }
6295

6296
  // there is no statistics data for composed block
6297
  if (pReader->status.composedDataBlock || (!pReader->suppInfo.smaValid)) {
5,552,418!
6298
    goto _end;
3,843,877✔
6299
  }
6300

6301
  code = getCurrentBlockInfo(&pReader->status.blockIter, &pBlockInfo, pReader->idStr);
1,708,541✔
6302
  TSDB_CHECK_CODE(code, lino, _end);
1,708,541!
6303

6304
  SBlockLoadSuppInfo* pSup = &pReader->suppInfo;
1,708,541✔
6305

6306
  SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock;
1,708,541✔
6307
  if (pResBlock->info.id.uid != pBlockInfo->uid) {
1,708,541!
UNCOV
6308
    goto _end;
×
6309
  }
6310

6311
  //  int64_t st = taosGetTimestampUs();
6312
  TARRAY2_CLEAR(&pSup->colAggArray, 0);
1,708,541✔
6313

6314
  SBrinRecord pRecord;
6315
  blockInfoToRecord(&pRecord, pBlockInfo, pSup);
1,708,541✔
6316
  code = tsdbDataFileReadBlockSma(pReader->pFileReader, &pRecord, &pSup->colAggArray);
1,708,541✔
6317
  if (code != TSDB_CODE_SUCCESS) {
1,708,541!
UNCOV
6318
    tsdbDebug("vgId:%d, failed to load block SMA for uid %" PRIu64 ", code:%s, %s", 0, pBlockInfo->uid, tstrerror(code),
×
6319
              pReader->idStr);
UNCOV
6320
    TSDB_CHECK_CODE(code, lino, _end);
×
6321
  }
6322

6323
  if (pSup->colAggArray.size > 0) {
1,708,541!
6324
    *allHave = true;
1,708,541✔
6325
  } else {
UNCOV
6326
    *pBlockSMA = NULL;
×
UNCOV
6327
    goto _end;
×
6328
  }
6329

6330
  // always load the first primary timestamp column data
6331
  SColumnDataAgg* pTsAgg = &pSup->tsColAgg;
1,708,541✔
6332

6333
  pTsAgg->numOfNull = 0;
1,708,541✔
6334
  pTsAgg->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
1,708,541✔
6335
  pTsAgg->min = pResBlock->info.window.skey;
1,708,541✔
6336
  pTsAgg->max = pResBlock->info.window.ekey;
1,708,541✔
6337

6338
  // update the number of NULL data rows
6339
  size_t numOfCols = pSup->numOfCols;
1,708,541✔
6340

6341
  if (pResBlock->pBlockAgg == NULL) {
1,708,541!
6342
    size_t num = taosArrayGetSize(pResBlock->pDataBlock);
1,708,541✔
6343
    pResBlock->pBlockAgg = taosMemoryCalloc(num, sizeof(SColumnDataAgg));
1,708,541!
6344
    TSDB_CHECK_NULL(pResBlock->pBlockAgg, code, lino, _end, terrno);
1,708,541!
6345
    for (int i = 0; i < num; ++i) {
5,202,653✔
6346
      pResBlock->pBlockAgg[i].colId = -1;
3,494,112✔
6347
    }
6348
  }
6349

6350
  // do fill all null column value SMA info
6351
  code = doFillNullColSMA(pSup, pBlockInfo->numRow, numOfCols, pTsAgg);
1,708,541✔
6352
  TSDB_CHECK_CODE(code, lino, _end);
1,708,541!
6353

6354
  size_t size = pSup->colAggArray.size;
1,708,541✔
6355

6356
  int32_t i = 0, j = 0;
1,708,541✔
6357
  while (j < numOfCols && i < size) {
5,221,159!
6358
    SColumnDataAgg* pAgg = &pSup->colAggArray.data[i];
3,512,618✔
6359
    if (pAgg->colId == pSup->colId[j]) {
3,512,618✔
6360
      pResBlock->pBlockAgg[pSup->slotId[j]] = *pAgg;
3,491,664✔
6361
      i += 1;
3,491,664✔
6362
      j += 1;
3,491,664✔
6363
    } else if (pAgg->colId < pSup->colId[j]) {
20,954!
6364
      i += 1;
20,954✔
UNCOV
6365
    } else if (pSup->colId[j] < pAgg->colId) {
×
6366
      pResBlock->pBlockAgg[pSup->slotId[j]].colId = -1;
×
UNCOV
6367
      *allHave = false;
×
UNCOV
6368
      j += 1;
×
6369
    }
6370
  }
6371

6372
  *pBlockSMA = pResBlock->pBlockAgg;
1,708,541✔
6373
  pReader->cost.smaDataLoad += 1;
1,708,541✔
6374

6375
  //  double elapsedTime = (taosGetTimestampUs() - st) / 1000.0;
6376
  pReader->cost.smaLoadTime += 0;  // elapsedTime;
1,708,541✔
6377

6378
  tsdbDebug("vgId:%d, succeed to load block SMA for uid %" PRIu64 ", %s", 0, pBlockInfo->uid, pReader->idStr);
1,708,541✔
6379

6380
_end:
1,704,365✔
6381
  if (code != TSDB_CODE_SUCCESS) {
5,552,433!
UNCOV
6382
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6383
  }
6384
  return code;
5,552,289✔
6385
}
6386

6387
static int32_t doRetrieveDataBlock(STsdbReader* pReader, SSDataBlock** pBlock) {
2,334,638✔
6388
  int32_t              code = TSDB_CODE_SUCCESS;
2,334,638✔
6389
  int32_t              lino = 0;
2,334,638✔
6390
  SReaderStatus*       pStatus = NULL;
2,334,638✔
6391
  SFileDataBlockInfo*  pBlockInfo = NULL;
2,334,638✔
6392
  STableBlockScanInfo* pBlockScanInfo = NULL;
2,334,638✔
6393
  bool                 reset = false;
2,334,638✔
6394

6395
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,334,638!
6396
  TSDB_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
2,334,638!
6397

6398
  pStatus = &pReader->status;
2,334,638✔
6399
  *pBlock = NULL;
2,334,638✔
6400

6401
  code = getCurrentBlockInfo(&pStatus->blockIter, &pBlockInfo, pReader->idStr);
2,334,638✔
6402
  TSDB_CHECK_CODE(code, lino, _end);
2,334,769!
6403

6404
  code = pReader->code;
2,334,769✔
6405
  TSDB_CHECK_CODE(code, lino, _end);
2,334,769!
6406

6407
  code = getTableBlockScanInfo(pStatus->pTableMap, pBlockInfo->uid, &pBlockScanInfo, pReader->idStr);
2,334,769✔
6408
  TSDB_CHECK_CODE(code, lino, _end);
2,334,764!
6409

6410
  reset = true;
2,334,764✔
6411
  code = doLoadFileBlockData(pReader, &pStatus->blockIter, &pStatus->fileBlockData, pBlockScanInfo->uid);
2,334,764✔
6412
  TSDB_CHECK_CODE(code, lino, _end);
2,334,849!
6413

6414
  code = copyBlockDataToSDataBlock(pReader, &pBlockScanInfo->lastProcKey);
2,334,849✔
6415
  TSDB_CHECK_CODE(code, lino, _end);
2,334,948!
6416

6417
  *pBlock = pReader->resBlockInfo.pResBlock;
2,334,948✔
6418

6419
_end:
2,334,948✔
6420
  if (code != TSDB_CODE_SUCCESS) {
2,334,948!
UNCOV
6421
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
6422
    if (reset) {
×
UNCOV
6423
      tBlockDataReset(&pStatus->fileBlockData);
×
6424
    }
6425
  }
6426
  return code;
2,334,804✔
6427
}
6428

6429
int32_t tsdbRetrieveDataBlock2(STsdbReader* pReader, SSDataBlock** pBlock, SArray* pIdList) {
9,663,589✔
6430
  int32_t      code = TSDB_CODE_SUCCESS;
9,663,589✔
6431
  int32_t      lino = 0;
9,663,589✔
6432
  STsdbReader* pTReader = NULL;
9,663,589✔
6433

6434
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
9,663,589!
6435
  TSDB_CHECK_NULL(pBlock, code, lino, _end, TSDB_CODE_INVALID_PARA);
9,663,589!
6436

6437
  *pBlock = NULL;
9,663,589✔
6438

6439
  pTReader = pReader;
9,663,589✔
6440
  if (pReader->type == TIMEWINDOW_RANGE_EXTERNAL) {
9,663,589✔
6441
    if (pReader->step == EXTERNAL_ROWS_PREV) {
18,503✔
6442
      pTReader = pReader->innerReader[0];
6,678✔
6443
    } else if (pReader->step == EXTERNAL_ROWS_NEXT) {
11,825✔
6444
      pTReader = pReader->innerReader[1];
6,635✔
6445
    }
6446
  }
6447

6448
  SReaderStatus* pStatus = &pTReader->status;
9,663,589✔
6449
  if (pStatus->composedDataBlock || pReader->info.execMode == READER_EXEC_ROWS) {
9,663,589!
6450
    //    tsdbReaderSuspend2(pReader);
6451
    //    tsdbReaderResume2(pReader);
6452
    *pBlock = pTReader->resBlockInfo.pResBlock;
7,328,932✔
6453
    goto _end;
7,328,932✔
6454
  }
6455

6456
  code = doRetrieveDataBlock(pTReader, pBlock);
2,334,657✔
6457

6458
  tsdbTrace("tsdb/read-retrieve: %p, unlock read mutex", pReader);
2,334,797✔
6459
  (void) tsdbReleaseReader(pReader);
2,334,797✔
6460
  TSDB_CHECK_CODE(code, lino, _end);
2,334,975!
6461

6462
  //  tsdbReaderSuspend2(pReader);
6463
  //  tsdbReaderResume2(pReader);
6464
_end:
2,334,975✔
6465
  if (code != TSDB_CODE_SUCCESS) {
9,663,907!
UNCOV
6466
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6467
  }
6468
  return code;
9,662,905✔
6469
}
6470

6471
int32_t tsdbReaderReset2(STsdbReader* pReader, SQueryTableDataCond* pCond) {
20,915✔
6472
  int32_t code = TSDB_CODE_SUCCESS;
20,915✔
6473
  int32_t lino = 0;
20,915✔
6474
  bool    acquired = false;
20,915✔
6475

6476
  tsdbTrace("tsdb/reader-reset: %p, take read mutex", pReader);
20,915!
6477
  code = tsdbAcquireReader(pReader);
20,915✔
6478
  TSDB_CHECK_CODE(code, lino, _end);
20,920!
6479
  acquired = true;
20,920✔
6480

6481
  if (pReader->flag == READER_STATUS_SUSPEND) {
20,920✔
6482
    code = tsdbReaderResume2(pReader);
46✔
6483
    TSDB_CHECK_CODE(code, lino, _end);
46!
6484
  }
6485

6486
  if (isEmptyQueryTimeWindow(&pReader->info.window) || pReader->pReadSnap == NULL) {
20,920✔
6487
    tsdbDebug("tsdb reader reset return %p, %s", pReader->pReadSnap, pReader->idStr);
54✔
6488
    code = tsdbReleaseReader(pReader);
54✔
6489
    acquired = false;
58✔
6490
    TSDB_CHECK_CODE(code, lino, _end);
58!
6491
    goto _end;
58✔
6492
  }
6493

6494
  SReaderStatus*  pStatus = &pReader->status;
20,861✔
6495
  SDataBlockIter* pBlockIter = &pStatus->blockIter;
20,861✔
6496

6497
  TSDB_CHECK_NULL(pCond, code, lino, _end, TSDB_CODE_INVALID_PARA);
20,861!
6498
  pReader->info.order = pCond->order;
20,861✔
6499
  pReader->type = TIMEWINDOW_RANGE_CONTAINED;
20,861✔
6500
  code = updateQueryTimeWindow(pReader->pTsdb, &pCond->twindows, &pReader->info.window);
20,861✔
6501
  TSDB_CHECK_CODE(code, lino, _end);
20,862!
6502
  pStatus->loadFromFile = true;
20,862✔
6503
  pStatus->pTableIter = NULL;
20,862✔
6504

6505
  // allocate buffer in order to load data blocks from file
6506
  memset(&pReader->suppInfo.tsColAgg, 0, sizeof(SColumnDataAgg));
20,862✔
6507

6508
  pReader->suppInfo.tsColAgg.colId = PRIMARYKEY_TIMESTAMP_COL_ID;
20,862✔
6509
  tsdbDataFileReaderClose(&pReader->pFileReader);
20,862✔
6510

6511
  int32_t numOfTables = tSimpleHashGetSize(pStatus->pTableMap);
20,860✔
6512

6513
  code = initFilesetIterator(&pStatus->fileIter, pReader->pReadSnap->pfSetArray, pReader);
20,861✔
6514
  TSDB_CHECK_CODE(code, lino, _end);
20,857!
6515

6516
  code = resetDataBlockIterator(pBlockIter, pReader->info.order, shouldFreePkBuf(&pReader->suppInfo), pReader->idStr);
20,857✔
6517
  TSDB_CHECK_CODE(code, lino, _end);
20,857!
6518

6519
  code = resetTableListIndex(&pReader->status, pReader->idStr);
20,857✔
6520
  TSDB_CHECK_CODE(code, lino, _end);
20,855!
6521

6522
  bool    asc = ASCENDING_TRAVERSE(pReader->info.order);
20,855✔
6523
  int32_t step = asc ? 1 : -1;
20,855✔
6524
  int64_t ts = 0;
20,855✔
6525
  if (asc) {
20,855✔
6526
    ts = (pReader->info.window.skey > INT64_MIN) ? pReader->info.window.skey - 1 : pReader->info.window.skey;
20,223!
6527
  } else {
6528
    ts = (pReader->info.window.ekey < INT64_MAX) ? pReader->info.window.ekey + 1 : pReader->info.window.ekey;
632✔
6529
  }
6530
  resetAllDataBlockScanInfo(pStatus->pTableMap, ts, step);
20,855✔
6531

6532
  // no data in files, let's try buffer in memory
6533
  if (pStatus->fileIter.numOfFiles == 0) {
20,857✔
6534
    pStatus->loadFromFile = false;
3,496✔
6535
    code = resetTableListIndex(pStatus, pReader->idStr);
3,496✔
6536
    TSDB_CHECK_CODE(code, lino, _end);
3,496!
6537
  } else {
6538
    code = initForFirstBlockInFile(pReader, pBlockIter);
17,361✔
6539
    if (code != TSDB_CODE_SUCCESS) {
17,349!
UNCOV
6540
      tsdbError("%p reset reader failed, numOfTables:%d, query range:%" PRId64 " - %" PRId64 " in query %s", pReader,
×
6541
                numOfTables, pReader->info.window.skey, pReader->info.window.ekey, pReader->idStr);
UNCOV
6542
      TSDB_CHECK_CODE(code, lino, _end);
×
6543
    }
6544
  }
6545

6546
  tsdbDebug("%p reset reader, suid:%" PRIu64 ", numOfTables:%d, skey:%" PRId64 ", query range:%" PRId64 " - %" PRId64
20,845✔
6547
            " in query %s",
6548
            pReader, pReader->info.suid, numOfTables, pCond->twindows.skey, pReader->info.window.skey,
6549
            pReader->info.window.ekey, pReader->idStr);
6550

6551
  code = tsdbReleaseReader(pReader);
20,845✔
6552
  acquired = false;
20,851✔
6553
  TSDB_CHECK_CODE(code, lino, _end);
20,851!
6554

6555
_end:
20,851✔
6556
  if (code != TSDB_CODE_SUCCESS) {
20,909!
UNCOV
6557
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6558
  }
6559
  if (acquired) {
20,904!
UNCOV
6560
    (void)tsdbReleaseReader(pReader);
×
6561
  }
6562
  return code;
20,894✔
6563
}
6564

6565
static int32_t getBucketIndex(int32_t startRow, int32_t bucketRange, int32_t numOfRows, int32_t numOfBucket) {
73,874✔
6566
  if (numOfRows < startRow) {
73,874!
UNCOV
6567
    return 0;
×
6568
  }
6569
  int32_t bucketIndex = ((numOfRows - startRow) / bucketRange);
73,874✔
6570
  if (bucketIndex == numOfBucket) {
73,874!
UNCOV
6571
    bucketIndex -= 1;
×
6572
  }
6573
  return bucketIndex;
73,874✔
6574
}
6575

6576
int32_t tsdbGetFileBlocksDistInfo2(STsdbReader* pReader, STableBlockDistInfo* pTableBlockInfo) {
3,274✔
6577
  int32_t       code = TSDB_CODE_SUCCESS;
3,274✔
6578
  int32_t       lino = 0;
3,274✔
6579
  const int32_t numOfBuckets = 20.0;
3,274✔
6580
  bool          acquired = false;
3,274✔
6581

6582
  TSDB_CHECK_NULL(pTableBlockInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
3,274!
6583

6584
  pTableBlockInfo->totalSize = 0;
3,274✔
6585
  pTableBlockInfo->totalRows = 0;
3,274✔
6586
  pTableBlockInfo->numOfVgroups = 1;
3,274✔
6587

6588
  // find the start data block in file
6589
  code = tsdbAcquireReader(pReader);
3,274✔
6590
  TSDB_CHECK_CODE(code, lino, _end);
3,282!
6591
  acquired = true;
3,282✔
6592

6593
  if (pReader->flag == READER_STATUS_SUSPEND) {
3,282✔
6594
    code = tsdbReaderResume2(pReader);
3,278✔
6595
    TSDB_CHECK_CODE(code, lino, _end);
3,283!
6596
  }
6597

6598
  SMergeTreeConf conf = {
3,287✔
6599
      .pReader = pReader,
6600
      .pSchema = pReader->info.pSchema,
3,287✔
6601
      .pCols = pReader->suppInfo.colId,
3,287✔
6602
      .numOfCols = pReader->suppInfo.numOfCols,
3,287✔
6603
      .suid = pReader->info.suid,
3,287✔
6604
  };
6605

6606
  SReaderStatus* pStatus = &pReader->status;
3,287✔
6607
  if (pStatus->pCurrentFileset != NULL) {
3,287✔
6608
    pTableBlockInfo->numOfSttRows += tsdbGetRowsInSttFiles(pStatus->pCurrentFileset, pStatus->pLDataIterArray,
1,645✔
6609
                                                           pReader->pTsdb, &conf, pReader->idStr);
1,643✔
6610
  }
6611

6612
  STsdbCfg* pc = &pReader->pTsdb->pVnode->config.tsdbCfg;
3,289✔
6613
  pTableBlockInfo->defMinRows = pc->minRows;
3,289✔
6614
  pTableBlockInfo->defMaxRows = pc->maxRows;
3,289✔
6615

6616
  int32_t bucketRange = ceil(((double)(pc->maxRows - pc->minRows)) / numOfBuckets);
3,289✔
6617

6618
  pTableBlockInfo->numOfFiles += 1;
3,289✔
6619

6620
  int32_t numOfTables = (int32_t)tSimpleHashGetSize(pStatus->pTableMap);
3,289✔
6621

6622
  SDataBlockIter* pBlockIter = &pStatus->blockIter;
3,281✔
6623
  pTableBlockInfo->numOfFiles += pStatus->fileIter.numOfFiles;
3,281✔
6624

6625
  if (pBlockIter->numOfBlocks > 0) {
3,281✔
6626
    pTableBlockInfo->numOfBlocks += pBlockIter->numOfBlocks;
2✔
6627
  }
6628

6629
  pTableBlockInfo->numOfTables = numOfTables;
3,281✔
6630
  bool hasNext = (pBlockIter->numOfBlocks > 0);
3,281✔
6631

6632
  while (true) {
6633
    if (hasNext) {
80,393✔
6634
      SFileDataBlockInfo* pBlockInfo = NULL;
73,874✔
6635
      code = getCurrentBlockInfo(pBlockIter, &pBlockInfo, pReader->idStr);
73,874✔
6636
      TSDB_CHECK_CODE(code, lino, _end);
73,874!
6637

6638
      int32_t numOfRows = pBlockInfo->numRow;
73,874✔
6639

6640
      pTableBlockInfo->totalRows += numOfRows;
73,874✔
6641

6642
      if (numOfRows > pTableBlockInfo->maxRows) {
73,874✔
6643
        pTableBlockInfo->maxRows = numOfRows;
2✔
6644
      }
6645

6646
      if (numOfRows < pTableBlockInfo->minRows) {
73,874✔
6647
        pTableBlockInfo->minRows = numOfRows;
3✔
6648
      }
6649

6650
      pTableBlockInfo->totalSize += pBlockInfo->blockSize;
73,874✔
6651

6652
      int32_t bucketIndex = getBucketIndex(pTableBlockInfo->defMinRows, bucketRange, numOfRows, numOfBuckets);
73,874✔
6653
      pTableBlockInfo->blockRowsHisto[bucketIndex]++;
73,874✔
6654

6655
      hasNext = blockIteratorNext(&pStatus->blockIter);
73,874✔
6656
    } else {
6657
      code = initForFirstBlockInFile(pReader, pBlockIter);
6,519✔
6658
      TSDB_CHECK_CODE(code, lino, _end);
6,525!
6659
      if (pStatus->loadFromFile == false) {
6,525✔
6660
        break;
3,286✔
6661
      }
6662

6663
      // add the data in stt files of new fileset
6664
      if (pStatus->pCurrentFileset != NULL) {
3,239✔
6665
        pTableBlockInfo->numOfSttRows += tsdbGetRowsInSttFiles(pStatus->pCurrentFileset, pStatus->pLDataIterArray,
3,240✔
6666
                                                               pReader->pTsdb, &conf, pReader->idStr);
3,238✔
6667
      }
6668

6669
      pTableBlockInfo->numOfBlocks += pBlockIter->numOfBlocks;
3,241✔
6670
      hasNext = (pBlockIter->numOfBlocks > 0);
3,241✔
6671
    }
6672
  }
6673

6674
  // record the data in stt files
6675
_end:
3,286✔
6676
  if (code != TSDB_CODE_SUCCESS) {
3,286!
UNCOV
6677
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6678
  }
6679
  if (acquired) {
3,286!
6680
    (void)tsdbReleaseReader(pReader);
3,286✔
6681
  }
6682
  return code;
3,284✔
6683
}
6684

6685
static void getMemTableTimeRange(STsdbReader* pReader, int64_t* pMaxKey, int64_t* pMinKey) {
1,893,148✔
6686
  SReaderStatus* pStatus = &pReader->status;
1,893,148✔
6687

6688
  int32_t iter = 0;
1,893,148✔
6689
  int64_t maxKey = INT64_MIN;
1,893,148✔
6690
  int64_t minKey = INT64_MAX;
1,893,148✔
6691

6692
  void* pHashIter = tSimpleHashIterate(pStatus->pTableMap, NULL, &iter);
1,893,148✔
6693
  while (pHashIter != NULL) {
6,751,544✔
6694
    STableBlockScanInfo* pBlockScanInfo = *(STableBlockScanInfo**)pHashIter;
4,856,098✔
6695

6696
    STbData* d = NULL;
4,856,098✔
6697
    if (pReader->pReadSnap->pMem != NULL) {
4,856,098✔
6698
      d = tsdbGetTbDataFromMemTable(pReader->pReadSnap->pMem, pReader->info.suid, pBlockScanInfo->uid);
4,502,499✔
6699
      if (d != NULL) {
4,506,994✔
6700
        if (d->maxKey > maxKey) {
1,655,740✔
6701
          maxKey = d->maxKey;
1,404,173✔
6702
        }
6703
        if (d->minKey < minKey) {
1,655,740✔
6704
          minKey = d->minKey;
1,387,783✔
6705
        }
6706
      }
6707
    }
6708

6709
    STbData* di = NULL;
4,860,593✔
6710
    if (pReader->pReadSnap->pIMem != NULL) {
4,860,593✔
6711
      di = tsdbGetTbDataFromMemTable(pReader->pReadSnap->pIMem, pReader->info.suid, pBlockScanInfo->uid);
1✔
6712
      if (di != NULL) {
1!
6713
        if (di->maxKey > maxKey) {
1!
6714
          maxKey = di->maxKey;
1✔
6715
        }
6716
        if (di->minKey < minKey) {
1!
6717
          minKey = di->minKey;
1✔
6718
        }
6719
      }
6720
    }
6721

6722
    // current table is exhausted, let's try the next table
6723
    pHashIter = tSimpleHashIterate(pStatus->pTableMap, pHashIter, &iter);
4,860,593✔
6724
  }
6725

6726
  *pMaxKey = maxKey;
1,895,446✔
6727
  *pMinKey = minKey;
1,895,446✔
6728
}
1,895,446✔
6729

6730
int64_t tsdbGetNumOfRowsInMemTable2(STsdbReader* pReader, uint32_t* rows) {
3,281✔
6731
  int32_t        code = TSDB_CODE_SUCCESS;
3,281✔
6732
  int32_t        lino = 0;
3,281✔
6733
  SReaderStatus* pStatus = NULL;
3,281✔
6734
  bool           acquired = false;
3,281✔
6735

6736
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
3,281!
6737
  TSDB_CHECK_NULL(rows, code, lino, _end, TSDB_CODE_INVALID_PARA);
3,281!
6738

6739
  *rows = 0;
3,281✔
6740
  pStatus = &pReader->status;
3,281✔
6741
  code = tsdbAcquireReader(pReader);
3,281✔
6742
  TSDB_CHECK_CODE(code, lino, _end);
3,286!
6743
  acquired = true;
3,286✔
6744

6745
  if (pReader->flag == READER_STATUS_SUSPEND) {
3,286✔
6746
    code = tsdbReaderResume2(pReader);
554✔
6747
    TSDB_CHECK_CODE(code, lino, _end);
554!
6748
  }
6749

6750
  int32_t iter = 0;
3,286✔
6751
  pStatus->pTableIter = tSimpleHashIterate(pStatus->pTableMap, NULL, &iter);
3,286✔
6752

6753
  while (pStatus->pTableIter != NULL) {
10,343✔
6754
    STableBlockScanInfo* pBlockScanInfo = *(STableBlockScanInfo**)pStatus->pTableIter;
7,050✔
6755

6756
    STbData* d = NULL;
7,050✔
6757
    if (pReader->pReadSnap->pMem != NULL) {
7,050✔
6758
      d = tsdbGetTbDataFromMemTable(pReader->pReadSnap->pMem, pReader->info.suid, pBlockScanInfo->uid);
7,019✔
6759
      if (d != NULL) {
7,024✔
6760
        *rows += tsdbGetNRowsInTbData(d);
1,626✔
6761
      }
6762
    }
6763

6764
    STbData* di = NULL;
7,055✔
6765
    if (pReader->pReadSnap->pIMem != NULL) {
7,055✔
6766
      di = tsdbGetTbDataFromMemTable(pReader->pReadSnap->pIMem, pReader->info.suid, pBlockScanInfo->uid);
5✔
6767
      if (di != NULL) {
5!
6768
        *rows += tsdbGetNRowsInTbData(di);
5✔
6769
      }
6770
    }
6771

6772
    // current table is exhausted, let's try the next table
6773
    pStatus->pTableIter = tSimpleHashIterate(pStatus->pTableMap, pStatus->pTableIter, &iter);
7,055✔
6774
  }
6775

6776
_end:
3,293✔
6777
  if (code != TSDB_CODE_SUCCESS) {
3,293!
UNCOV
6778
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6779
  }
6780
  if (acquired) {
3,286!
6781
    (void)tsdbReleaseReader(pReader);
3,286✔
6782
  }
6783
  return code;
3,286✔
6784
}
6785

6786
int32_t tsdbGetTableSchema(SMeta* pMeta, int64_t uid, STSchema** pSchema, int64_t* suid) {
254✔
6787
  SMetaReader mr = {0};
254✔
6788
  metaReaderDoInit(&mr, pMeta, META_READER_LOCK);
254✔
6789
  int32_t code = metaReaderGetTableEntryByUidCache(&mr, uid);
254✔
6790
  if (code != TSDB_CODE_SUCCESS) {
254!
UNCOV
6791
    code = TSDB_CODE_TDB_INVALID_TABLE_ID;
×
UNCOV
6792
    metaReaderClear(&mr);
×
UNCOV
6793
    return code;
×
6794
  }
6795

6796
  *suid = 0;
254✔
6797

6798
  // only child table and ordinary table is allowed, super table is not allowed.
6799
  if (mr.me.type == TSDB_CHILD_TABLE) {
254✔
6800
    tDecoderClear(&mr.coder);
169✔
6801
    *suid = mr.me.ctbEntry.suid;
169✔
6802
    code = metaReaderGetTableEntryByUidCache(&mr, *suid);
169✔
6803
    if (code != TSDB_CODE_SUCCESS) {
169!
UNCOV
6804
      code = TSDB_CODE_TDB_INVALID_TABLE_ID;
×
UNCOV
6805
      metaReaderClear(&mr);
×
UNCOV
6806
      return code;
×
6807
    }
6808
  } else if (mr.me.type == TSDB_NORMAL_TABLE) {  // do nothing
85!
6809
  } else {
UNCOV
6810
    code = TSDB_CODE_INVALID_PARA;
×
UNCOV
6811
    tsdbError("invalid mr.me.type:%d, code:%s", mr.me.type, tstrerror(code));
×
UNCOV
6812
    metaReaderClear(&mr);
×
UNCOV
6813
    return code;
×
6814
  }
6815

6816
  metaReaderClear(&mr);
254✔
6817

6818
  // get the newest table schema version
6819
  code = metaGetTbTSchemaEx(pMeta, *suid, uid, -1, pSchema);
254✔
6820
  return code;
254✔
6821
}
6822

6823
int32_t tsdbTakeReadSnap2(STsdbReader* pReader, _query_reseek_func_t reseek, STsdbReadSnap** ppSnap, const char* id) {
4,502,577✔
6824
  int32_t        code = 0;
4,502,577✔
6825
  STsdb*         pTsdb = pReader->pTsdb;
4,502,577✔
6826
  SVersionRange* pRange = &pReader->info.verRange;
4,502,577✔
6827
  int32_t        lino = 0;
4,502,577✔
6828
  *ppSnap = NULL;
4,502,577✔
6829

6830
  // lock
6831
  code = taosThreadMutexLock(&pTsdb->mutex);
4,502,577✔
6832
  if (code != TSDB_CODE_SUCCESS) {
4,510,197!
6833
    tsdbError("%s failed to lock tsdb, code:%s", id, tstrerror(code));
×
6834
    return code;
×
6835
  }
6836

6837
  // alloc
6838
  STsdbReadSnap* pSnap = (STsdbReadSnap*)taosMemoryCalloc(1, sizeof(STsdbReadSnap));
4,510,197✔
6839
  if (pSnap == NULL) {
4,510,009!
UNCOV
6840
    (void) taosThreadMutexUnlock(&pTsdb->mutex);
×
UNCOV
6841
    TSDB_CHECK_NULL(pSnap, code, lino, _exit, terrno);
×
6842
  }
6843

6844
  // take snapshot
6845
  if (pTsdb->mem && (pRange->minVer <= pTsdb->mem->maxVer && pRange->maxVer >= pTsdb->mem->minVer)) {
4,510,009!
6846
    pSnap->pMem = pTsdb->mem;
4,021,607✔
6847
    pSnap->pNode = taosMemoryMalloc(sizeof(*pSnap->pNode));
4,021,607✔
6848
    if (pSnap->pNode == NULL) {
4,019,449!
UNCOV
6849
      (void) taosThreadMutexUnlock(&pTsdb->mutex);
×
6850
      TSDB_CHECK_NULL(pSnap->pNode, code, lino, _exit, terrno);
×
6851
    }
6852

6853
    pSnap->pNode->pQHandle = pReader;
4,019,449✔
6854
    pSnap->pNode->reseek = reseek;
4,019,449✔
6855

6856
    code = tsdbRefMemTable(pTsdb->mem, pSnap->pNode);
4,019,449✔
6857
    TSDB_CHECK_CODE(code, lino, _exit);
4,020,698!
6858
  }
6859

6860
  if (pTsdb->imem && (pRange->minVer <= pTsdb->imem->maxVer && pRange->maxVer >= pTsdb->imem->minVer)) {
4,509,100!
6861
    pSnap->pIMem = pTsdb->imem;
24,649✔
6862
    pSnap->pINode = taosMemoryMalloc(sizeof(*pSnap->pINode));
24,649!
6863
    if (pSnap->pINode == NULL) {
24,648!
UNCOV
6864
      code = terrno;
×
6865

UNCOV
6866
      if (pTsdb->mem && pSnap->pNode) {
×
UNCOV
6867
        tsdbUnrefMemTable(pTsdb->mem, pSnap->pNode, true);  // unref the previous refed mem
×
6868
      }
6869

UNCOV
6870
      (void) taosThreadMutexUnlock(&pTsdb->mutex);
×
UNCOV
6871
      goto _exit;
×
6872
    }
6873

6874
    pSnap->pINode->pQHandle = pReader;
24,648✔
6875
    pSnap->pINode->reseek = reseek;
24,648✔
6876

6877
    code = tsdbRefMemTable(pTsdb->imem, pSnap->pINode);
24,648✔
6878
    TSDB_CHECK_CODE(code, lino, _exit);
24,649!
6879
  }
6880

6881
  // fs
6882
  code = tsdbFSCreateRefSnapshotWithoutLock(pTsdb->pFS, &pSnap->pfSetArray);
4,509,100✔
6883
  if (code) {
4,508,907!
UNCOV
6884
    if (pSnap->pNode) {
×
UNCOV
6885
      tsdbUnrefMemTable(pTsdb->mem, pSnap->pNode, true);  // unref the previous refed mem
×
6886
    }
6887

6888
    if (pSnap->pINode) {
×
UNCOV
6889
      tsdbUnrefMemTable(pTsdb->imem, pSnap->pINode, true);
×
6890
    }
6891

6892
    (void) taosThreadMutexUnlock(&pTsdb->mutex);
×
6893
    TSDB_CHECK_CODE(code, lino, _exit);
×
6894
  }
6895

6896
  // unlock
6897
  (void) taosThreadMutexUnlock(&pTsdb->mutex);
4,508,907✔
6898
  *ppSnap = pSnap;
4,510,800✔
6899

6900
  tsdbTrace("%s vgId:%d, take read snapshot", id, TD_VID(pTsdb->pVnode));
4,510,800✔
6901
  return code;
4,509,003✔
6902

UNCOV
6903
_exit:
×
UNCOV
6904
  tsdbError("%s vgId:%d take read snapshot failed, line:%d code:%s", id, TD_VID(pTsdb->pVnode), lino, tstrerror(code));
×
6905

UNCOV
6906
  if (pSnap) {
×
UNCOV
6907
    if (pSnap->pNode) taosMemoryFree(pSnap->pNode);
×
UNCOV
6908
    if (pSnap->pINode) taosMemoryFree(pSnap->pINode);
×
UNCOV
6909
    taosMemoryFree(pSnap);
×
6910
  }
UNCOV
6911
  return code;
×
6912
}
6913

6914
void tsdbUntakeReadSnap2(STsdbReader* pReader, STsdbReadSnap* pSnap, bool proactive) {
4,510,822✔
6915
  STsdb* pTsdb = pReader->pTsdb;
4,510,822✔
6916

6917
  if (pSnap) {
4,510,822!
6918
    if (pSnap->pMem) {
4,511,428✔
6919
      tsdbUnrefMemTable(pSnap->pMem, pSnap->pNode, proactive);
4,022,898✔
6920
    }
6921

6922
    if (pSnap->pIMem) {
4,511,528✔
6923
      tsdbUnrefMemTable(pSnap->pIMem, pSnap->pINode, proactive);
24,649✔
6924
    }
6925

6926
    if (pSnap->pNode) taosMemoryFree(pSnap->pNode);
4,511,528✔
6927
    if (pSnap->pINode) taosMemoryFree(pSnap->pINode);
4,511,353!
6928

6929
    tsdbFSDestroyRefSnapshot(&pSnap->pfSetArray);
4,511,353✔
6930

6931
    taosMemoryFree(pSnap);
4,510,343!
6932
  }
6933
  tsdbTrace("vgId:%d, untake read snapshot", TD_VID(pTsdb->pVnode));
4,510,959✔
6934
}
4,510,959✔
6935

6936
// if failed, do nothing
6937
int32_t tsdbReaderSetId(void* p, const char* idstr) {
921✔
6938
  int32_t      code = TSDB_CODE_SUCCESS;
921✔
6939
  int32_t      lino = 0;
921✔
6940
  STsdbReader* pReader = (STsdbReader*)p;
921✔
6941

6942
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
921!
6943

6944
  taosMemoryFreeClear(pReader->idStr);
921!
6945
  pReader->idStr = taosStrdup(idstr);
921!
6946
  TSDB_CHECK_NULL(pReader->idStr, code, lino, _end, terrno);
921!
6947

6948
  pReader->status.fileIter.pSttBlockReader->mergeTree.idStr = pReader->idStr;
921✔
6949

6950
_end:
921✔
6951
  if (code != TSDB_CODE_SUCCESS) {
921!
UNCOV
6952
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
6953
  }
6954
  return code;
922✔
6955
}
6956

6957
void tsdbReaderSetCloseFlag(STsdbReader* pReader) { /*pReader->code = TSDB_CODE_TSC_QUERY_CANCELLED;*/ }
1,037✔
6958

6959
void tsdbSetFilesetDelimited(STsdbReader* pReader) { pReader->bFilesetDelimited = true; }
1,892,585✔
6960

6961
void tsdbReaderSetNotifyCb(STsdbReader* pReader, TsdReaderNotifyCbFn notifyFn, void* param) {
1,892,513✔
6962
  pReader->notifyFn = notifyFn;
1,892,513✔
6963
  pReader->notifyParam = param;
1,892,513✔
6964
}
1,892,513✔
6965

6966
#if 0
6967
static int32_t tsdbEncodeLastProcKeys(const SSHashObj* pTableMap, void** buf) {
6968
  void* p = NULL;
6969
  int32_t iter = 0;
6970
  int32_t len = 0;
6971

6972
  len += taosEncodeFixedI32(buf, tSimpleHashGetSize(pTableMap)); // number of tables
6973

6974
  while ((p = tSimpleHashIterate(pTableMap, p, &iter)) != NULL) {
6975
    uint64_t uid = *(uint64_t*)tSimpleHashGetKey(p, NULL);
6976
    SRowKey* pKey = &(*(STableBlockScanInfo**)p)->lastProcKey;
6977

6978
    len += taosEncodeFixedU64(buf, uid);            // table uid
6979
    len += taosEncodeFixedI64(buf, pKey->ts);       // last read ts
6980
    len += taosEncodeFixedU8(buf, pKey->numOfPKs);  // number of pks
6981

6982
    if (pKey->numOfPKs > 0) {
6983
      int8_t type = pKey->pks[0].type;
6984
      len += taosEncodeFixedI8(buf, type);  // pk data type
6985

6986
      uint8_t* pData = 0;
6987
      uint32_t nData = 0;
6988
      if (IS_VAR_DATA_TYPE(type)) {
6989
        pData = pKey->pks[0].pData;
6990
        nData = pKey->pks[0].nData;
6991
        len += taosEncodeFixedU32(buf, nData);  // data length
6992
      } else {
6993
        pData = (uint8_t*)&pKey->pks[0].val;
6994
        nData = tDataTypes[pKey->pks[0].type].bytes;
6995
      }
6996
      len += taosEncodeBinary(buf, pData, nData); // data value
6997
    }
6998
  }
6999

7000
  return len;
7001
}
7002

7003
static int32_t tsdbDecodeLastProcKeys(const void* buf, int32_t len, SSHashObj* pTableMap) {
7004
  int32_t code = TSDB_CODE_SUCCESS;
7005
  int32_t lino = 0;
7006
  const void *begin = buf;
7007

7008
  TSDB_CHECK_NULL(buf, code, lino, _end, TSDB_CODE_INVALID_PARA);
7009
  TSDB_CHECK_NULL(pTableMap, code, lino, _end, TSDB_CODE_INVALID_PARA);
7010

7011
  int32_t numOfTables = 0;
7012
  buf = taosDecodeFixedI32(buf, &numOfTables);
7013

7014
  TSDB_CHECK_CONDITION(numOfTables == tSimpleHashGetSize(pTableMap), code, lino, _end, TSDB_CODE_INVALID_PARA);
7015

7016
  for (int32_t i = 0; i < numOfTables; ++i) {
7017
    uint64_t uid = 0;
7018
    buf = taosDecodeFixedU64(buf, &uid);
7019

7020
    STableBlockScanInfo** pScanInfo = tSimpleHashGet(pTableMap, &uid, sizeof(uid));
7021
    if (pScanInfo == NULL) {
7022
      tsdbError("failed to find scan info of uid: %" PRIu64 " when decoding last proc keys", uid);
7023
      TSDB_CHECK_NULL(pScanInfo, code, lino, _end, TSDB_CODE_INVALID_PARA);
7024
    }
7025
    SRowKey* pKey = &(*pScanInfo)->lastProcKey;
7026

7027
    buf = taosDecodeFixedI64(buf, &pKey->ts);
7028
    uint8_t numOfPks = 0;
7029
    buf = taosDecodeFixedU8(buf, &numOfPks);
7030
    if (numOfPks != pKey->numOfPKs) {
7031
      tsdbError("numOfPks of uid %" PRIu64 " mismatch: [%u/%u]", uid, numOfPks, pKey->numOfPKs);
7032
      TSDB_CHECK_CONDITION(numOfPks == pKey->numOfPKs, code, lino, _end, TSDB_CODE_INVALID_PARA);
7033
    }
7034

7035
    if (numOfPks > 0) {
7036
      int8_t type = 0;
7037
      buf = taosDecodeFixedI8(buf, &type);
7038
      if (type != pKey->pks[0].type) {
7039
        tsdbError("pk type of uid %" PRIu64 " mismatch: [%d/%d]", uid, type, pKey->pks[0].type);
7040
        TSDB_CHECK_CONDITION(type == pKey->pks[0].type, code, lino, _end, TSDB_CODE_INVALID_PARA);
7041
      }
7042

7043
      uint8_t *pData = 0;
7044
      uint32_t nData = 0;
7045
      if (IS_VAR_DATA_TYPE(type)) {
7046
        pData = pKey->pks[0].pData;
7047
        buf = taosDecodeFixedU32(buf, &nData);
7048
        pKey->pks[0].nData = nData;
7049
      } else {
7050
        pKey->pks[0].val = 0;
7051
        pData = (uint8_t*)&pKey->pks[0].val;
7052
        nData = tDataTypes[type].bytes;
7053
      }
7054
      buf = taosDecodeBinary(buf, (void **)&pData, nData);
7055
    }
7056
  }
7057

7058
  TSDB_CHECK_CONDITION(buf == begin + len , code, lino, _end, TSDB_CODE_INVALID_PARA);
7059

7060
_end:
7061
  if (code != TSDB_CODE_SUCCESS) {
7062
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
7063
  }
7064
  return code;
7065
}
7066
#endif
7067

UNCOV
7068
int32_t tsdbReaderGetProgress(const STsdbReader* pReader, void** pBuf, uint64_t* pLen) {
×
UNCOV
7069
  int32_t              code = TSDB_CODE_SUCCESS;
×
7070
#if 0
7071
  int32_t              lino = 0;
7072
  void*                buf = NULL;
7073
  int32_t len = 0;
7074

7075
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
7076
  TSDB_CHECK_NULL(pBuf, code, lino, _end, TSDB_CODE_INVALID_PARA);
7077
  TSDB_CHECK_NULL(pLen, code, lino, _end, TSDB_CODE_INVALID_PARA);
7078

7079
  *pBuf = NULL;
7080
  *pLen = tsdbEncodeLastProcKeys(pReader->status.pTableMap, NULL);
7081

7082
  buf = taosMemoryMalloc(*pLen);
7083
  TSDB_CHECK_NULL(buf, code, lino, _end, terrno);
7084
  *pBuf = buf;
7085
  len = tsdbEncodeLastProcKeys(pReader->status.pTableMap, &buf);
7086
  TSDB_CHECK_CONDITION(len == *pLen, code, lino, _end, TSDB_CODE_INTERNAL_ERROR);
7087
  buf = NULL;
7088

7089
_end:
7090
  if (code != TSDB_CODE_SUCCESS) {
7091
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
7092
  }
7093
  if (buf != NULL) {
7094
    taosMemoryFreeClear(buf);
7095
  }
7096
#endif
UNCOV
7097
  return code;
×
7098
}
7099

UNCOV
7100
int32_t tsdbReaderSetProgress(STsdbReader* pReader, const void* buf, uint64_t len) {
×
UNCOV
7101
  int32_t code = TSDB_CODE_SUCCESS;
×
7102
#if 0
7103
  int32_t lino = 0;
7104

7105
  if (len == 0) {
7106
    goto _end;
7107
  }
7108

7109
  TSDB_CHECK_NULL(pReader, code, lino, _end, TSDB_CODE_INVALID_PARA);
7110
  TSDB_CHECK_NULL(buf, code, lino, _end, TSDB_CODE_INVALID_PARA);
7111

7112
  code = tsdbDecodeLastProcKeys(buf, len, pReader->status.pTableMap);
7113
  TSDB_CHECK_CODE(code, lino, _end);
7114

7115
_end:
7116
  if (code != TSDB_CODE_SUCCESS) {
7117
    tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
7118
  }
7119
#endif
UNCOV
7120
  return code;
×
7121
}
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