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

taosdata / TDengine / #3524

08 Nov 2024 04:27AM UTC coverage: 60.898% (+5.0%) from 55.861%
#3524

push

travis-ci

web-flow
Merge pull request #28647 from taosdata/fix/3.0/TD-32519_drop_ctb

fix TD-32519 drop child table with tsma caused crash

118687 of 248552 branches covered (47.75%)

Branch coverage included in aggregate %.

286 of 337 new or added lines in 18 files covered. (84.87%)

9647 existing lines in 190 files now uncovered.

199106 of 273291 relevant lines covered (72.85%)

15236719.35 hits per line

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

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

24
static bool overlapWithDelSkylineWithoutVer(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord,
25
                                            int32_t order);
26

27
static int32_t initBlockScanInfoBuf(SBlockInfoBuf* pBuf, int32_t numOfTables) {
4,977,977✔
28
  int32_t num = numOfTables / pBuf->numPerBucket;
4,977,977✔
29
  int32_t remainder = numOfTables % pBuf->numPerBucket;
4,977,977✔
30

31
  if (pBuf->pData == NULL) {
4,977,977!
32
    pBuf->pData = taosArrayInit(num + 1, POINTER_BYTES);
4,983,884✔
33
    if (pBuf->pData == NULL) {
4,993,249!
34
      return terrno;
×
35
    }
36
  }
37

38
  for (int32_t i = 0; i < num; ++i) {
4,991,744✔
39
    char* p = taosMemoryCalloc(pBuf->numPerBucket, sizeof(STableBlockScanInfo));
118✔
40
    if (p == NULL) {
118!
41
      return terrno;
×
42
    }
43

44
    void* px = taosArrayPush(pBuf->pData, &p);
118✔
45
    if (px == NULL) {
118!
46
      return terrno;
×
47
    }
48
  }
49

50
  if (remainder > 0) {
4,991,626✔
51
    char* p = taosMemoryCalloc(remainder, sizeof(STableBlockScanInfo));
4,847,816✔
52
    if (p == NULL) {
4,852,902!
UNCOV
53
      return terrno;
×
54
    }
55
    void* px = taosArrayPush(pBuf->pData, &p);
4,852,902✔
56
    if (px == NULL) {
4,855,160!
57
      return terrno;
×
58
    }
59
  }
60

61
  pBuf->numOfTables = numOfTables;
4,998,970✔
62

63
  return TSDB_CODE_SUCCESS;
4,998,970✔
64
}
65

66
int32_t uidComparFunc(const void* p1, const void* p2) {
11,158,668✔
67
  uint64_t pu1 = *(uint64_t*)p1;
11,158,668✔
68
  uint64_t pu2 = *(uint64_t*)p2;
11,158,668✔
69
  if (pu1 == pu2) {
11,158,668!
UNCOV
70
    return 0;
×
71
  } else {
72
    return (pu1 < pu2) ? -1 : 1;
11,158,668✔
73
  }
74
}
75

76
int32_t ensureBlockScanInfoBuf(SBlockInfoBuf* pBuf, int32_t numOfTables) {
6✔
77
  if (numOfTables <= pBuf->numOfTables) {
6!
78
    return TSDB_CODE_SUCCESS;
×
79
  }
80

81
  if (pBuf->numOfTables > 0) {
6!
82
    STableBlockScanInfo** p = (STableBlockScanInfo**)taosArrayPop(pBuf->pData);
6✔
83
    taosMemoryFree(*p);
6✔
84
    pBuf->numOfTables /= pBuf->numPerBucket;
6✔
85
  }
86

87
  int32_t num = (numOfTables - pBuf->numOfTables) / pBuf->numPerBucket;
6✔
88
  int32_t remainder = (numOfTables - pBuf->numOfTables) % pBuf->numPerBucket;
6✔
89
  if (pBuf->pData == NULL) {
6!
90
    pBuf->pData = taosArrayInit(num + 1, POINTER_BYTES);
×
91
    if (pBuf->pData == NULL) {
×
92
      return terrno;
×
93
    }
94
  }
95

96
  for (int32_t i = 0; i < num; ++i) {
6!
97
    char* p = taosMemoryCalloc(pBuf->numPerBucket, sizeof(STableBlockScanInfo));
×
98
    if (p == NULL) {
×
99
      return terrno;
×
100
    }
101

102
    void* px = taosArrayPush(pBuf->pData, &p);
×
103
    if (px == NULL) {
×
104
      return terrno;
×
105
    }
106
  }
107

108
  if (remainder > 0) {
6!
109
    char* p = taosMemoryCalloc(remainder, sizeof(STableBlockScanInfo));
6✔
110
    if (p == NULL) {
6!
111
      return terrno;
×
112
    }
113
    void* px = taosArrayPush(pBuf->pData, &p);
6✔
114
    if (px == NULL) {
6!
115
      return terrno;
×
116
    }
117
  }
118

119
  pBuf->numOfTables = numOfTables;
6✔
120

121
  return TSDB_CODE_SUCCESS;
6✔
122
}
123

124
void clearBlockScanInfoBuf(SBlockInfoBuf* pBuf) {
5,050,892✔
125
  size_t num = taosArrayGetSize(pBuf->pData);
5,050,892✔
126
  for (int32_t i = 0; i < num; ++i) {
9,909,408✔
127
    char** p = taosArrayGet(pBuf->pData, i);
4,858,147✔
128
    if (p != NULL) {
4,857,837!
129
      taosMemoryFree(*p);
4,857,871✔
130
    }
131
  }
132

133
  taosArrayDestroy(pBuf->pData);
5,051,261✔
134
}
5,051,117✔
135

136
int32_t getPosInBlockInfoBuf(SBlockInfoBuf* pBuf, int32_t index, STableBlockScanInfo** pInfo) {
12,863,651✔
137
  *pInfo = NULL;
12,863,651✔
138

139
  int32_t bucketIndex = index / pBuf->numPerBucket;
12,863,651✔
140
  char**  pBucket = taosArrayGet(pBuf->pData, bucketIndex);
12,863,651✔
141
  if (pBucket == NULL) {
12,858,511!
142
    return TSDB_CODE_NOT_FOUND;
×
143
  }
144

145
  *pInfo = (STableBlockScanInfo*)((*pBucket) + (index % pBuf->numPerBucket) * sizeof(STableBlockScanInfo));
12,858,511✔
146
  return TSDB_CODE_SUCCESS;
12,858,511✔
147
}
148

149
int32_t getTableBlockScanInfo(SSHashObj* pTableMap, uint64_t uid, STableBlockScanInfo** pInfo, const char* id) {
2,052,005✔
150
  *pInfo = *(STableBlockScanInfo**)tSimpleHashGet(pTableMap, &uid, sizeof(uid));
2,052,005✔
151
  if (pInfo == NULL) {
2,052,307✔
152
    int32_t size = tSimpleHashGetSize(pTableMap);
309✔
153
    tsdbError("failed to locate the uid:%" PRIu64 " in query table uid list, total tables:%d, %s", uid, size, id);
×
154
    return TSDB_CODE_INVALID_PARA;
×
155
  }
156

157
  return TSDB_CODE_SUCCESS;
2,051,998✔
158
}
159

160
int32_t initRowKey(SRowKey* pKey, int64_t ts, int32_t numOfPks, int32_t type, int32_t len, bool asc) {
56,216,036✔
161
  pKey->numOfPKs = numOfPks;
56,216,036✔
162
  pKey->ts = ts;
56,216,036✔
163

164
  if (numOfPks > 0) {
56,216,036✔
165
    pKey->pks[0].type = type;
2,051,230✔
166

167
    if (IS_NUMERIC_TYPE(type)) {
2,051,230!
168
      if (asc) {
1,801,177✔
169
        switch (type) {
1,291,135!
170
          case TSDB_DATA_TYPE_BIGINT: {
1,017,190✔
171
            pKey->pks[0].val = INT64_MIN;
1,017,190✔
172
            break;
1,017,190✔
173
          }
174
          case TSDB_DATA_TYPE_INT: {
94,200✔
175
            int32_t min = INT32_MIN;
94,200✔
176
            (void)memcpy(&pKey->pks[0].val, &min, tDataTypes[type].bytes);
94,200✔
177
            break;
94,200✔
178
          }
179
          case TSDB_DATA_TYPE_SMALLINT: {
×
180
            int16_t min = INT16_MIN;
×
181
            (void)memcpy(&pKey->pks[0].val, &min, tDataTypes[type].bytes);
×
182
            break;
×
183
          }
184
          case TSDB_DATA_TYPE_TINYINT: {
×
185
            int8_t min = INT8_MIN;
×
186
            (void)memcpy(&pKey->pks[0].val, &min, tDataTypes[type].bytes);
×
187
            break;
×
188
          }
189
          case TSDB_DATA_TYPE_UTINYINT:
179,744✔
190
          case TSDB_DATA_TYPE_USMALLINT:
191
          case TSDB_DATA_TYPE_UINT:
192
          case TSDB_DATA_TYPE_UBIGINT: {
193
            pKey->pks[0].val = 0;
179,744✔
194
            break;
179,744✔
195
          }
196
          default:
1✔
197
            return TSDB_CODE_INVALID_PARA;
1✔
198
        }
199
      } else {
200
        switch (type) {
510,042!
201
          case TSDB_DATA_TYPE_BIGINT:
339,466✔
202
            pKey->pks[0].val = INT64_MAX;
339,466✔
203
            break;
339,466✔
204
          case TSDB_DATA_TYPE_INT:
57,348✔
205
            pKey->pks[0].val = INT32_MAX;
57,348✔
206
            break;
57,348✔
207
          case TSDB_DATA_TYPE_SMALLINT:
×
208
            pKey->pks[0].val = INT16_MAX;
×
209
            break;
×
210
          case TSDB_DATA_TYPE_TINYINT:
×
211
            pKey->pks[0].val = INT8_MAX;
×
212
            break;
×
213
          case TSDB_DATA_TYPE_UBIGINT:
56,118✔
214
            pKey->pks[0].val = UINT64_MAX;
56,118✔
215
            break;
56,118✔
216
          case TSDB_DATA_TYPE_UINT:
57,161✔
217
            pKey->pks[0].val = UINT32_MAX;
57,161✔
218
            break;
57,161✔
219
          case TSDB_DATA_TYPE_USMALLINT:
×
220
            pKey->pks[0].val = UINT16_MAX;
×
221
            break;
×
222
          case TSDB_DATA_TYPE_UTINYINT:
×
223
            pKey->pks[0].val = UINT8_MAX;
×
224
            break;
×
225
          default:
×
226
            return TSDB_CODE_INVALID_PARA;
×
227
        }
228
      }
229
    } else {
230
      pKey->pks[0].pData = taosMemoryCalloc(1, len);
250,053✔
231
      pKey->pks[0].nData = 0;
250,166✔
232

233
      if (pKey->pks[0].pData == NULL) {
250,166!
234
        return terrno;
×
235
      }
236

237
      if (!asc) {
265,792✔
238
        pKey->numOfPKs = 2;
109,014✔
239
      }
240
    }
241
  }
242

243
  return TSDB_CODE_SUCCESS;
56,231,825✔
244
}
245

246
void clearRowKey(SRowKey* pKey) {
56,335,699✔
247
  if (pKey == NULL || pKey->numOfPKs == 0 || (!IS_VAR_DATA_TYPE(pKey->pks[0].type))) {
56,335,699!
248
    return;
56,087,984✔
249
  }
250
  taosMemoryFreeClear(pKey->pks[0].pData);
247,715!
251
}
252

253
static int32_t initLastProcKey(STableBlockScanInfo* pScanInfo, STsdbReader* pReader) {
12,853,800✔
254
  int32_t code = 0;
12,853,800✔
255
  int32_t numOfPks = pReader->suppInfo.numOfPks;
12,853,800✔
256
  bool    asc = ASCENDING_TRAVERSE(pReader->info.order);
12,853,800✔
257
  int8_t  type = pReader->suppInfo.pk.type;
12,853,800✔
258
  int32_t bytes = pReader->suppInfo.pk.bytes;
12,853,800✔
259

260
  SRowKey* pRowKey = &pScanInfo->lastProcKey;
12,853,800✔
261
  if (asc) {
12,853,800✔
262
    int64_t skey = pReader->info.window.skey;
10,478,180✔
263
    int64_t ts = (skey > INT64_MIN) ? (skey - 1) : skey;
10,478,180!
264

265
    code = initRowKey(pRowKey, ts, numOfPks, type, bytes, asc);
10,478,180✔
266
    if (code != TSDB_CODE_SUCCESS) {
10,474,756!
267
      return code;
×
268
    }
269

270
    code = initRowKey(&pScanInfo->sttKeyInfo.nextProcKey, skey, numOfPks, type, bytes, asc);
10,474,756✔
271
    if (code != TSDB_CODE_SUCCESS) {
10,471,893!
272
      return code;
×
273
    }
274
  } else {
275
    int64_t ekey = pReader->info.window.ekey;
2,375,620✔
276
    int64_t ts = (ekey < INT64_MAX) ? (ekey + 1) : ekey;
2,375,620✔
277

278
    code = initRowKey(pRowKey, ts, numOfPks, type, bytes, asc);
2,375,620✔
279
    if (code != TSDB_CODE_SUCCESS) {
2,386,275!
280
      return code;
×
281
    }
282

283
    code = initRowKey(&pScanInfo->sttKeyInfo.nextProcKey, ekey, numOfPks, type, bytes, asc);
2,386,275✔
284
    if (code != TSDB_CODE_SUCCESS) {
2,386,781!
285
      return code;
×
286
    }
287
  }
288

289
  code = initRowKey(&pScanInfo->sttRange.skey, INT64_MAX, numOfPks, type, bytes, asc);
12,858,674✔
290
  if (code != TSDB_CODE_SUCCESS) {
12,846,463!
291
    return code;
×
292
  }
293

294
  code = initRowKey(&pScanInfo->sttRange.ekey, INT64_MIN, numOfPks, type, bytes, asc);
12,846,463✔
295
  return code;
12,850,147✔
296
}
297

298
int32_t initTableBlockScanInfo(STableBlockScanInfo* pScanInfo, uint64_t uid, SSHashObj* pTableMap,
12,854,438✔
299
                               STsdbReader* pReader) {
300
  pScanInfo->uid = uid;
12,854,438✔
301
  INIT_KEYRANGE(&pScanInfo->sttRange);
12,854,438✔
302
  INIT_TIMEWINDOW(&pScanInfo->filesetWindow);
12,854,438✔
303

304
  pScanInfo->cleanSttBlocks = false;
12,854,438✔
305
  pScanInfo->sttBlockReturned = false;
12,854,438✔
306

307
  int32_t code = initLastProcKey(pScanInfo, pReader);
12,854,438✔
308
  if (code != TSDB_CODE_SUCCESS) {
12,851,244!
309
    return code;
×
310
  }
311

312
  pScanInfo->sttKeyInfo.status = STT_FILE_READER_UNINIT;
12,851,244✔
313
  code = tSimpleHashPut(pTableMap, &pScanInfo->uid, sizeof(uint64_t), &pScanInfo, POINTER_BYTES);
12,851,244✔
314
  if (code != TSDB_CODE_SUCCESS) {
12,865,055!
UNCOV
315
    return code;
×
316
  }
317

318
  tsdbTrace("%p check table uid:%" PRId64 " from lastKey:%" PRId64 " %s", pReader, pScanInfo->uid,
12,865,055✔
319
            pScanInfo->lastProcKey.ts, pReader->idStr);
320
  return code;
12,865,345✔
321
}
322

323
// NOTE: speedup the whole processing by preparing the buffer for STableBlockScanInfo in batch model
324
int32_t createDataBlockScanInfo(STsdbReader* pTsdbReader, SBlockInfoBuf* pBuf, const STableKeyInfo* idList,
4,978,390✔
325
                                STableUidList* pUidList, int32_t numOfTables, SSHashObj** pHashObj) {
326
  int32_t code = 0;
4,978,390✔
327
  *pHashObj = NULL;
4,978,390✔
328

329
  // allocate buffer in order to load data blocks from file
330
  // todo use simple hash instead, optimize the memory consumption
331
  SSHashObj* pTableMap = tSimpleHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT));
4,978,390✔
332
  if (pTableMap == NULL) {
4,992,829!
UNCOV
333
    return terrno;
×
334
  }
335

336
  int64_t st = taosGetTimestampUs();
4,986,492✔
337
  code = initBlockScanInfoBuf(pBuf, numOfTables);
4,986,492✔
338
  if (code != TSDB_CODE_SUCCESS) {
4,991,354!
UNCOV
339
    tSimpleHashCleanup(pTableMap);
×
UNCOV
340
    return code;
×
341
  }
342

343
  pUidList->tableUidList = taosMemoryMalloc(numOfTables * sizeof(uint64_t));
4,991,354✔
344
  if (pUidList->tableUidList == NULL) {
4,992,870✔
345
    tSimpleHashCleanup(pTableMap);
4,333✔
UNCOV
346
    return terrno;
×
347
  }
348

349
  pUidList->currentIndex = 0;
4,988,537✔
350

351
  for (int32_t j = 0; j < numOfTables; ++j) {
17,834,486✔
352
    pUidList->tableUidList[j] = idList[j].uid;
12,847,986✔
353

354
    STableBlockScanInfo* pScanInfo = NULL;
12,847,986✔
355
    code = getPosInBlockInfoBuf(pBuf, j, &pScanInfo);
12,847,986✔
356
    if (code != TSDB_CODE_SUCCESS) {
12,841,000!
UNCOV
357
      break;
×
358
    }
359

360
    code = initTableBlockScanInfo(pScanInfo, idList[j].uid, pTableMap, pTsdbReader);
12,841,000✔
361
    if (code != TSDB_CODE_SUCCESS) {
12,845,949!
UNCOV
362
      break;
×
363
    }
364
  }
365

366
  taosSort(pUidList->tableUidList, numOfTables, sizeof(uint64_t), uidComparFunc);
4,986,500✔
367

368
  pTsdbReader->cost.createScanInfoList = (taosGetTimestampUs() - st) / 1000.0;
4,991,131✔
369
  tsdbDebug("%p create %d tables scan-info, size:%.2f Kb, elapsed time:%.2f ms, %s", pTsdbReader, numOfTables,
4,991,131✔
370
            (sizeof(STableBlockScanInfo) * numOfTables) / 1024.0, pTsdbReader->cost.createScanInfoList,
371
            pTsdbReader->idStr);
372

373
  *pHashObj = pTableMap;
4,993,137✔
374
  return code;
4,993,137✔
375
}
376

377
void resetAllDataBlockScanInfo(SSHashObj* pTableMap, int64_t ts, int32_t step) {
24,715✔
378
  void*   p = NULL;
24,715✔
379
  int32_t iter = 0;
24,715✔
380

381
  while ((p = tSimpleHashIterate(pTableMap, p, &iter)) != NULL) {
49,465✔
382
    STableBlockScanInfo* pInfo = *(STableBlockScanInfo**)p;
24,751✔
383

384
    pInfo->iterInit = false;
24,751✔
385
    pInfo->iter.hasVal = false;
24,751✔
386
    pInfo->iiter.hasVal = false;
24,751✔
387

388
    if (pInfo->iter.iter != NULL) {
24,751✔
389
      pInfo->iter.iter = tsdbTbDataIterDestroy(pInfo->iter.iter);
3,980✔
390
    }
391

392
    if (pInfo->iiter.iter != NULL) {
24,751✔
393
      pInfo->iiter.iter = tsdbTbDataIterDestroy(pInfo->iiter.iter);
20✔
394
    }
395

396
    taosArrayDestroy(pInfo->delSkyline);
24,751✔
397
    pInfo->delSkyline = NULL;
24,750✔
398
    pInfo->lastProcKey.ts = ts;
24,750✔
399
    // todo check the nextProcKey info
400
    pInfo->sttKeyInfo.nextProcKey.ts = ts + step;
24,750✔
401
  }
402
}
24,708✔
403

404
void clearBlockScanInfo(STableBlockScanInfo* p) {
12,876,981✔
405
  p->iterInit = false;
12,876,981✔
406
  p->iter.hasVal = false;
12,876,981✔
407
  p->iiter.hasVal = false;
12,876,981✔
408
  p->sttKeyInfo.status = STT_FILE_READER_UNINIT;
12,876,981✔
409

410
  if (p->iter.iter != NULL) {
12,876,981✔
411
    p->iter.iter = tsdbTbDataIterDestroy(p->iter.iter);
4,604,641✔
412
  }
413

414
  if (p->iiter.iter != NULL) {
12,878,680✔
415
    p->iiter.iter = tsdbTbDataIterDestroy(p->iiter.iter);
25,169✔
416
  }
417

418
  taosArrayDestroy(p->delSkyline);
12,879,784✔
419
  p->delSkyline = NULL;
12,876,635✔
420
  taosArrayDestroy(p->pBlockList);
12,876,635✔
421
  p->pBlockList = NULL;
12,876,110✔
422
  taosArrayDestroy(p->pBlockIdxList);
12,876,110✔
423
  p->pBlockIdxList = NULL;
12,875,422✔
424
  taosArrayDestroy(p->pMemDelData);
12,875,422✔
425
  p->pMemDelData = NULL;
12,881,917✔
426
  taosArrayDestroy(p->pFileDelData);
12,881,917✔
427
  p->pFileDelData = NULL;
12,881,272✔
428

429
  clearRowKey(&p->lastProcKey);
12,881,272✔
430
  clearRowKey(&p->sttRange.skey);
12,880,142✔
431
  clearRowKey(&p->sttRange.ekey);
12,878,825✔
432
  clearRowKey(&p->sttKeyInfo.nextProcKey);
12,877,856✔
433
}
12,876,600✔
434

435
void destroyAllBlockScanInfo(SSHashObj* pTableMap) {
4,993,237✔
436
  void*   p = NULL;
4,993,237✔
437
  int32_t iter = 0;
4,993,237✔
438

439
  while ((p = tSimpleHashIterate(pTableMap, p, &iter)) != NULL) {
17,850,012✔
440
    clearBlockScanInfo(*(STableBlockScanInfo**)p);
12,857,931✔
441
  }
442

443
  tSimpleHashCleanup(pTableMap);
4,989,979✔
444
}
4,994,261✔
445

446
static void doCleanupInfoForNextFileset(STableBlockScanInfo* pScanInfo) {
14,653,675✔
447
  // reset the index in last block when handing a new file
448
  taosArrayClear(pScanInfo->pBlockList);
14,653,675✔
449
  taosArrayClear(pScanInfo->pBlockIdxList);
14,655,209✔
450
  taosArrayClear(pScanInfo->pFileDelData);  // del data from each file set
14,655,466✔
451
  pScanInfo->cleanSttBlocks = false;
14,655,757✔
452
  pScanInfo->numOfRowsInStt = 0;
14,655,757✔
453
  pScanInfo->sttBlockReturned = false;
14,655,757✔
454
  INIT_KEYRANGE(&pScanInfo->sttRange);
14,655,757✔
455
  INIT_TIMEWINDOW(&pScanInfo->filesetWindow);
14,655,757✔
456
  pScanInfo->sttKeyInfo.status = STT_FILE_READER_UNINIT;
14,655,757✔
457
}
14,655,757✔
458

459
void cleanupInfoForNextFileset(SSHashObj* pTableMap) {
6,795,927✔
460
  STableBlockScanInfo** p = NULL;
6,795,927✔
461

462
  int32_t iter = 0;
6,795,927✔
463
  while ((p = tSimpleHashIterate(pTableMap, p, &iter)) != NULL) {
21,450,143✔
464
    doCleanupInfoForNextFileset(*p);
14,657,081✔
465
  }
466
}
6,792,344✔
467

468
// brin records iterator
469
void initBrinRecordIter(SBrinRecordIter* pIter, SDataFileReader* pReader, SArray* pList) {
6,798,394✔
470
  (void)memset(&pIter->block, 0, sizeof(SBrinBlock));
6,798,394✔
471
  (void)memset(&pIter->record, 0, sizeof(SBrinRecord));
6,798,394✔
472
  pIter->blockIndex = -1;
6,798,394✔
473
  pIter->recordIndex = -1;
6,798,394✔
474

475
  pIter->pReader = pReader;
6,798,394✔
476
  pIter->pBrinBlockList = pList;
6,798,394✔
477
}
6,798,394✔
478

479
int32_t getNextBrinRecord(SBrinRecordIter* pIter, SBrinRecord** pRecord) {
9,025,115✔
480
  *pRecord = NULL;
9,025,115✔
481

482
  if (pIter->blockIndex == -1 || (pIter->recordIndex + 1) >= pIter->block.numOfRecords) {
9,025,115✔
483
    pIter->blockIndex += 1;
6,914,042✔
484
    if (pIter->blockIndex >= taosArrayGetSize(pIter->pBrinBlockList)) {
6,914,042✔
485
      return TSDB_CODE_SUCCESS;
6,787,800✔
486
    }
487

488
    pIter->pCurrentBlk = taosArrayGet(pIter->pBrinBlockList, pIter->blockIndex);
127,111✔
489
    if (pIter->pCurrentBlk == NULL) {
127,318!
490
      return TSDB_CODE_INVALID_PARA;
×
491
    }
492

493
    tBrinBlockClear(&pIter->block);
127,318✔
494
    int32_t code = tsdbDataFileReadBrinBlock(pIter->pReader, pIter->pCurrentBlk, &pIter->block);
127,500✔
495
    if (code != TSDB_CODE_SUCCESS) {
127,452!
UNCOV
496
      tsdbError("failed to read brinBlock from file, code:%s", tstrerror(code));
×
UNCOV
497
      return code;
×
498
    }
499

500
    pIter->recordIndex = -1;
127,452✔
501
  }
502

503
  pIter->recordIndex += 1;
2,238,525✔
504
  int32_t code = tBrinBlockGet(&pIter->block, pIter->recordIndex, &pIter->record);
2,238,525✔
505
  *pRecord = &pIter->record;
2,235,658✔
506

507
  return code;
2,235,658✔
508
}
509

510
void clearBrinBlockIter(SBrinRecordIter* pIter) { tBrinBlockDestroy(&pIter->block); }
6,797,218✔
511

512
// initialize the file block access order
513
//  sort the file blocks according to the offset of each data block in the files
514
static void cleanupBlockOrderSupporter(SBlockOrderSupporter* pSup) {
119,720✔
515
  taosMemoryFreeClear(pSup->numOfBlocksPerTable);
119,720!
516
  taosMemoryFreeClear(pSup->indexPerTable);
119,760!
517

518
  for (int32_t i = 0; i < pSup->numOfTables; ++i) {
558,450✔
519
    SBlockOrderWrapper* pBlockInfo = pSup->pDataBlockInfo[i];
438,733✔
520
    taosMemoryFreeClear(pBlockInfo);
438,733✔
521
  }
522

523
  taosMemoryFreeClear(pSup->pDataBlockInfo);
119,717!
524
}
119,738✔
525

526
static int32_t initBlockOrderSupporter(SBlockOrderSupporter* pSup, int32_t numOfTables) {
119,537✔
527
  pSup->pDataBlockInfo = taosMemoryCalloc(1, POINTER_BYTES * numOfTables);
119,537✔
528
  pSup->indexPerTable = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
119,799✔
529
  pSup->numOfBlocksPerTable = taosMemoryCalloc(1, sizeof(int32_t) * numOfTables);
119,793✔
530
  pSup->numOfTables = 0;
119,794✔
531
  if (pSup->pDataBlockInfo == NULL || pSup->indexPerTable == NULL || pSup->numOfBlocksPerTable == NULL) {
119,794!
532
    cleanupBlockOrderSupporter(pSup);
15✔
533
    return terrno;
×
534
  }
535

536
  return TSDB_CODE_SUCCESS;
119,779✔
537
}
538

539
static int32_t fileDataBlockOrderCompar(const void* pLeft, const void* pRight, void* param) {
4,788,111✔
540
  int32_t leftIndex = *(int32_t*)pLeft;
4,788,111✔
541
  int32_t rightIndex = *(int32_t*)pRight;
4,788,111✔
542

543
  SBlockOrderSupporter* pSupporter = (SBlockOrderSupporter*)param;
4,788,111✔
544

545
  int32_t leftTableBlockIndex = pSupporter->indexPerTable[leftIndex];
4,788,111✔
546
  int32_t rightTableBlockIndex = pSupporter->indexPerTable[rightIndex];
4,788,111✔
547

548
  if (leftTableBlockIndex > pSupporter->numOfBlocksPerTable[leftIndex]) {
4,788,111✔
549
    /* left block is empty */
550
    return 1;
1,113,881✔
551
  } else if (rightTableBlockIndex > pSupporter->numOfBlocksPerTable[rightIndex]) {
3,674,230✔
552
    /* right block is empty */
553
    return -1;
318,303✔
554
  }
555

556
  SBlockOrderWrapper* pLeftBlock = &pSupporter->pDataBlockInfo[leftIndex][leftTableBlockIndex];
3,355,927✔
557
  SBlockOrderWrapper* pRightBlock = &pSupporter->pDataBlockInfo[rightIndex][rightTableBlockIndex];
3,355,927✔
558

559
  return pLeftBlock->offset > pRightBlock->offset ? 1 : -1;
3,355,927✔
560
}
561

562
int32_t recordToBlockInfo(SFileDataBlockInfo* pBlockInfo, SBrinRecord* record) {
702,844✔
563
  pBlockInfo->uid = record->uid;
702,844✔
564
  pBlockInfo->firstKey = record->firstKey.key.ts;
702,844✔
565
  pBlockInfo->lastKey = record->lastKey.key.ts;
702,844✔
566
  pBlockInfo->minVer = record->minVer;
702,844✔
567
  pBlockInfo->maxVer = record->maxVer;
702,844✔
568
  pBlockInfo->blockOffset = record->blockOffset;
702,844✔
569
  pBlockInfo->smaOffset = record->smaOffset;
702,844✔
570
  pBlockInfo->blockSize = record->blockSize;
702,844✔
571
  pBlockInfo->blockKeySize = record->blockKeySize;
702,844✔
572
  pBlockInfo->smaSize = record->smaSize;
702,844✔
573
  pBlockInfo->numRow = record->numRow;
702,844✔
574
  pBlockInfo->count = record->count;
702,844✔
575

576
  SRowKey* pFirstKey = &record->firstKey.key;
702,844✔
577
  if (pFirstKey->numOfPKs > 0) {
702,844✔
578
    if (IS_NUMERIC_TYPE(pFirstKey->pks[0].type)) {
326,527!
579
      pBlockInfo->firstPk.val = pFirstKey->pks[0].val;
326,527✔
580
      pBlockInfo->lastPk.val = record->lastKey.key.pks[0].val;
326,527✔
581
    } else {
582
      char* p = taosMemoryCalloc(1, pFirstKey->pks[0].nData + VARSTR_HEADER_SIZE);
×
583
      if (p == NULL) {
×
584
        return terrno;
×
585
      }
586
      memcpy(varDataVal(p), pFirstKey->pks[0].pData, pFirstKey->pks[0].nData);
×
587
      varDataSetLen(p, pFirstKey->pks[0].nData);
×
588
      pBlockInfo->firstPk.pData = (uint8_t*)p;
×
589

590
      int32_t keyLen = record->lastKey.key.pks[0].nData;
×
591
      p = taosMemoryCalloc(1, keyLen + VARSTR_HEADER_SIZE);
×
592
      if (p == NULL) {
×
593
        return terrno;
×
594
      }
595
      memcpy(varDataVal(p), record->lastKey.key.pks[0].pData, keyLen);
×
596
      varDataSetLen(p, keyLen);
×
597
      pBlockInfo->lastPk.pData = (uint8_t*)p;
×
598
    }
599
  }
600
  return TSDB_CODE_SUCCESS;
702,844✔
601
}
602

603
static void freePkItem(void* pItem) {
×
604
  SFileDataBlockInfo* p = pItem;
×
605
  taosMemoryFreeClear(p->firstPk.pData);
×
606
  taosMemoryFreeClear(p->lastPk.pData);
×
607
}
×
608

609
void clearDataBlockIterator(SDataBlockIter* pIter, bool needFree) {
6,929,713✔
610
  pIter->index = -1;
6,929,713✔
611
  pIter->numOfBlocks = 0;
6,929,713✔
612

613
  if (needFree) {
6,929,713✔
614
    taosArrayClearEx(pIter->blockList, freePkItem);
249,774✔
615
  } else {
616
    taosArrayClear(pIter->blockList);
6,679,939✔
617
  }
618
}
6,932,226✔
619

620
void cleanupDataBlockIterator(SDataBlockIter* pIter, bool needFree) {
5,049,573✔
621
  pIter->index = -1;
5,049,573✔
622
  pIter->numOfBlocks = 0;
5,049,573✔
623
  if (needFree) {
5,049,573✔
624
    taosArrayDestroyEx(pIter->blockList, freePkItem);
31,127✔
625
  } else {
626
    taosArrayDestroy(pIter->blockList);
5,018,446✔
627
  }
628
}
5,051,002✔
629

630
int32_t initBlockIterator(STsdbReader* pReader, SDataBlockIter* pBlockIter, int32_t numOfBlocks, SArray* pTableList) {
119,528✔
631
  bool asc = ASCENDING_TRAVERSE(pReader->info.order);
119,528✔
632

633
  SBlockOrderSupporter sup = {0};
119,528✔
634
  clearDataBlockIterator(pBlockIter, shouldFreePkBuf(&pReader->suppInfo));
119,528✔
635

636
  pBlockIter->numOfBlocks = numOfBlocks;
119,630✔
637

638
  // access data blocks according to the offset of each block in asc/desc order.
639
  int32_t numOfTables = taosArrayGetSize(pTableList);
119,630✔
640

641
  int64_t st = taosGetTimestampUs();
119,663✔
642
  int32_t code = initBlockOrderSupporter(&sup, numOfTables);
119,663✔
643
  if (code != TSDB_CODE_SUCCESS) {
119,776!
644
    return code;
×
645
  }
646

647
  int32_t cnt = 0;
119,776✔
648

649
  for (int32_t i = 0; i < numOfTables; ++i) {
558,281✔
650
    STableBlockScanInfo* pTableScanInfo = taosArrayGetP(pTableList, i);
437,461✔
651

652
    size_t num = taosArrayGetSize(pTableScanInfo->pBlockList);
437,031✔
653
    sup.numOfBlocksPerTable[sup.numOfTables] = num;
437,066✔
654

655
    char* buf = taosMemoryMalloc(sizeof(SBlockOrderWrapper) * num);
437,066✔
656
    if (buf == NULL) {
438,338!
657
      cleanupBlockOrderSupporter(&sup);
×
658
      return terrno;
×
659
    }
660

661
    sup.pDataBlockInfo[sup.numOfTables] = (SBlockOrderWrapper*)buf;
438,338✔
662

663
    for (int32_t k = 0; k < num; ++k) {
1,142,852✔
664
      SFileDataBlockInfo* pBlockInfo = taosArrayGet(pTableScanInfo->pBlockList, k);
704,347✔
665
      if (pBlockInfo == NULL) {
704,514!
666
        return TSDB_CODE_INVALID_PARA;
×
667
      }
668

669
      sup.pDataBlockInfo[sup.numOfTables][k] =
704,514✔
670
          (SBlockOrderWrapper){.uid = pTableScanInfo->uid, .offset = pBlockInfo->blockOffset, .pInfo = pTableScanInfo};
704,514✔
671
      cnt++;
704,514✔
672
    }
673

674
    sup.numOfTables += 1;
438,505✔
675
  }
676

677
  if (numOfBlocks != cnt && sup.numOfTables != numOfTables) {
120,820!
678
    cleanupBlockOrderSupporter(&sup);
×
679
    return TSDB_CODE_INVALID_PARA;
×
680
  }
681

682
  // since there is only one table qualified, blocks are not sorted
683
  if (sup.numOfTables == 1) {
120,820✔
684
    STableBlockScanInfo* pTableScanInfo = taosArrayGetP(pTableList, 0);
62,165✔
685
    for (int32_t i = 0; i < numOfBlocks; ++i) {
130,160✔
686
      STableDataBlockIdx tableDataBlockIdx = {.globalIndex = i};
67,970✔
687
      void*              px = taosArrayPush(pTableScanInfo->pBlockIdxList, &tableDataBlockIdx);
67,970✔
688
      if (px == NULL) {
68,047!
689
        return terrno;
×
690
      }
691
    }
692

693
    void* p = taosArrayAddAll(pBlockIter->blockList, pTableScanInfo->pBlockList);
62,190✔
694
    if (p == NULL) {
62,147!
695
      return TSDB_CODE_OUT_OF_MEMORY;
×
696
    }
697

698
    taosArrayDestroy(pTableScanInfo->pBlockList);
62,147✔
699
    pTableScanInfo->pBlockList = NULL;
62,221✔
700

701
    int64_t et = taosGetTimestampUs();
62,180✔
702
    tsdbDebug("%p create blocks info struct completed for one table, %d blocks not sorted, elapsed time:%.2f ms %s",
62,180✔
703
              pReader, numOfBlocks, (et - st) / 1000.0, pReader->idStr);
704

705
    pBlockIter->index = asc ? 0 : (numOfBlocks - 1);
62,194✔
706
    cleanupBlockOrderSupporter(&sup);
62,194✔
707
    return TSDB_CODE_SUCCESS;
62,247✔
708
  }
709

710
  tsdbDebug("%p create data blocks info struct completed, %d blocks in %d tables %s", pReader, cnt, sup.numOfTables,
58,655✔
711
            pReader->idStr);
712

713
  SMultiwayMergeTreeInfo* pTree = NULL;
58,655✔
714

715
  uint8_t ret = tMergeTreeCreate(&pTree, sup.numOfTables, &sup, fileDataBlockOrderCompar);
58,655✔
716
  if (ret != TSDB_CODE_SUCCESS) {
57,563!
717
    cleanupBlockOrderSupporter(&sup);
×
718
    return TSDB_CODE_OUT_OF_MEMORY;
×
719
  }
720

721
  int32_t numOfTotal = 0;
57,563✔
722
  while (numOfTotal < cnt) {
691,280✔
723
    int32_t pos = tMergeTreeGetChosenIndex(pTree);
633,743✔
724
    int32_t index = sup.indexPerTable[pos]++;
633,743✔
725

726
    SFileDataBlockInfo* pBlockInfo = taosArrayGet(sup.pDataBlockInfo[pos][index].pInfo->pBlockList, index);
633,743✔
727
    if (pBlockInfo == NULL) {
633,925!
728
      return TSDB_CODE_INVALID_PARA;
×
729
    }
730

731
    void* px = taosArrayPush(pBlockIter->blockList, pBlockInfo);
633,925✔
732
    if (px == NULL) {
633,421!
733
      return terrno;
×
734
    }
735

736
    STableBlockScanInfo* pTableScanInfo = sup.pDataBlockInfo[pos][index].pInfo;
633,421✔
737
    STableDataBlockIdx   tableDataBlockIdx = {.globalIndex = numOfTotal};
633,421✔
738

739
    px = taosArrayPush(pTableScanInfo->pBlockIdxList, &tableDataBlockIdx);
633,421✔
740
    if (px == NULL) {
629,696!
741
      return terrno;
×
742
    }
743

744
    // set data block index overflow, in order to disable the offset comparator
745
    if (sup.indexPerTable[pos] >= sup.numOfBlocksPerTable[pos]) {
629,696✔
746
      sup.indexPerTable[pos] = sup.numOfBlocksPerTable[pos] + 1;
375,639✔
747
    }
748

749
    numOfTotal += 1;
629,696✔
750
    code = tMergeTreeAdjust(pTree, tMergeTreeGetAdjustIndex(pTree));
629,696✔
751
    if (TSDB_CODE_SUCCESS != code) {
633,717!
752
      return code;
×
753
    }
754
  }
755

756
  for (int32_t i = 0; i < numOfTables; ++i) {
433,822✔
757
    STableBlockScanInfo* pTableScanInfo = taosArrayGetP(pTableList, i);
376,259✔
758
    taosArrayDestroy(pTableScanInfo->pBlockList);
376,029✔
759
    pTableScanInfo->pBlockList = NULL;
376,285✔
760
  }
761

762
  int64_t et = taosGetTimestampUs();
57,563✔
763
  tsdbDebug("%p %d data blocks access order completed, elapsed time:%.2f ms %s", pReader, numOfBlocks,
57,563✔
764
            (et - st) / 1000.0, pReader->idStr);
765
  cleanupBlockOrderSupporter(&sup);
57,563✔
766
  taosMemoryFree(pTree);
57,562✔
767

768
  pBlockIter->index = asc ? 0 : (numOfBlocks - 1);
57,564✔
769
  return TSDB_CODE_SUCCESS;
57,564✔
770
}
771

772
bool blockIteratorNext(SDataBlockIter* pBlockIter, const char* idStr) {
658,915✔
773
  bool asc = ASCENDING_TRAVERSE(pBlockIter->order);
658,915✔
774

775
  int32_t step = asc ? 1 : -1;
658,915✔
776
  if ((pBlockIter->index >= pBlockIter->numOfBlocks - 1 && asc) || (pBlockIter->index <= 0 && (!asc))) {
658,915✔
777
    return false;
119,595✔
778
  }
779

780
  pBlockIter->index += step;
539,320✔
781
  return true;
539,320✔
782
}
783

784
typedef enum {
785
  BLK_CHECK_CONTINUE = 0x1,
786
  BLK_CHECK_QUIT = 0x2,
787
} ETombBlkCheckEnum;
788

789
static int32_t loadNextStatisticsBlock(SSttFileReader* pSttFileReader, STbStatisBlock* pStatisBlock,
790
                                       const TStatisBlkArray* pStatisBlkArray, int32_t numOfRows, int32_t* i,
791
                                       int32_t* j);
792
static int32_t doCheckTombBlock(STombBlock* pBlock, STsdbReader* pReader, int32_t numOfTables, int32_t* j,
56,911✔
793
                                ETombBlkCheckEnum* pRet) {
794
  int32_t     code = 0;
56,911✔
795
  STombRecord record = {0};
56,911✔
796

797
  uint64_t             uid = pReader->status.uidList.tableUidList[*j];
56,911✔
798
  STableBlockScanInfo* pScanInfo = NULL;
56,911✔
799

800
  code = getTableBlockScanInfo(pReader->status.pTableMap, uid, &pScanInfo, pReader->idStr);
56,911✔
801
  if (code != TSDB_CODE_SUCCESS) {
56,911!
802
    return code;
×
803
  }
804

805
  if (pScanInfo->pFileDelData == NULL) {
56,911✔
806
    pScanInfo->pFileDelData = taosArrayInit(4, sizeof(SDelData));
29,034✔
807
    if (pScanInfo->pFileDelData == NULL) {
29,034!
808
      return terrno;
×
809
    }
810
  }
811

812
  for (int32_t k = 0; k < pBlock->numOfRecords; ++k) {
5,132,349✔
813
    code = tTombBlockGet(pBlock, k, &record);
5,106,997✔
814
    if (code != TSDB_CODE_SUCCESS) {
5,106,821!
815
      *pRet = BLK_CHECK_QUIT;
×
816
      return code;
×
817
    }
818

819
    if (record.suid < pReader->info.suid) {
5,106,821✔
820
      continue;
921,214✔
821
    }
822

823
    if (record.suid > pReader->info.suid) {
4,185,607✔
824
      *pRet = BLK_CHECK_QUIT;
3,419✔
825
      return TSDB_CODE_SUCCESS;
3,419✔
826
    }
827

828
    if (uid < record.uid) {
4,182,188✔
829
      while ((*j) < numOfTables && pReader->status.uidList.tableUidList[*j] < record.uid) {
125,984✔
830
        (*j) += 1;
65,373✔
831
      }
832

833
      if ((*j) >= numOfTables) {
60,611✔
834
        *pRet = BLK_CHECK_QUIT;
28,149✔
835
        return TSDB_CODE_SUCCESS;
28,149✔
836
      }
837

838
      uid = pReader->status.uidList.tableUidList[*j];
32,462✔
839
      code = getTableBlockScanInfo(pReader->status.pTableMap, uid, &pScanInfo, pReader->idStr);
32,462✔
840
      if (code != TSDB_CODE_SUCCESS) {
32,475!
841
        return code;
×
842
      }
843

844
      if (pScanInfo->pFileDelData == NULL) {
32,475✔
845
        pScanInfo->pFileDelData = taosArrayInit(4, sizeof(SDelData));
12,150✔
846
        if (pScanInfo->pFileDelData == NULL) {
12,162!
UNCOV
847
          return terrno;
×
848
        }
849
      }
850
    }
851

852
    if (record.uid < uid) {
4,154,140✔
853
      continue;
3,731,168✔
854
    }
855

856
    if (!(record.suid == pReader->info.suid && uid == record.uid)) {
422,972!
857
      tsdbError("tsdb reader failed at: %s:%d", __func__, __LINE__);
×
858
      return TSDB_CODE_INTERNAL_ERROR;
×
859
    }
860

861
    if (record.version <= pReader->info.verRange.maxVer) {
422,976✔
862
      SDelData delData = {.version = record.version, .sKey = record.skey, .eKey = record.ekey};
422,974✔
863
      void*    px = taosArrayPush(pScanInfo->pFileDelData, &delData);
422,974✔
864
      if (px == NULL) {
423,054!
865
        return terrno;
×
866
      }
867
    }
868
  }
869

870
  *pRet = BLK_CHECK_CONTINUE;
25,352✔
871
  return TSDB_CODE_SUCCESS;
25,352✔
872
}
873

874
// load tomb data API
875
static int32_t doLoadTombDataFromTombBlk(const TTombBlkArray* pTombBlkArray, STsdbReader* pReader, void* pFileReader,
6,758,443✔
876
                                         bool isFile) {
877
  int32_t        code = 0;
6,758,443✔
878
  STableUidList* pList = &pReader->status.uidList;
6,758,443✔
879
  int32_t        numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
6,758,443✔
880

881
  int32_t i = 0, j = 0;
6,759,476✔
882
  while (i < pTombBlkArray->size && j < numOfTables) {
6,810,141!
883
    STombBlk* pTombBlk = &pTombBlkArray->data[i];
91,640✔
884
    if (pTombBlk->maxTbid.suid < pReader->info.suid) {
91,640✔
885
      i += 1;
15,158✔
886
      continue;
25,322✔
887
    }
888

889
    if (pTombBlk->minTbid.suid > pReader->info.suid) {
76,482✔
890
      break;
9,407✔
891
    }
892

893
    if (!(pTombBlk->minTbid.suid <= pReader->info.suid && pTombBlk->maxTbid.suid >= pReader->info.suid)) {
68,900!
894
      tsdbError("tsdb reader failed at: %s:%d", __func__, __LINE__);
×
895
      return TSDB_CODE_INTERNAL_ERROR;
31,568✔
896
    }
897
    if (pTombBlk->maxTbid.suid == pReader->info.suid && pTombBlk->maxTbid.uid < pList->tableUidList[0]) {
68,900✔
898
      i += 1;
10,164✔
899
      continue;
10,164✔
900
    }
901

902
    if (pTombBlk->minTbid.suid == pReader->info.suid && pTombBlk->minTbid.uid > pList->tableUidList[numOfTables - 1]) {
58,736✔
903
      break;
1,825✔
904
    }
905

906
    STombBlock block = {0};
56,911✔
907
    code = isFile ? tsdbDataFileReadTombBlock(pFileReader, &pTombBlkArray->data[i], &block)
23,252✔
908
                  : tsdbSttFileReadTombBlock(pFileReader, &pTombBlkArray->data[i], &block);
56,911✔
909
    if (code != TSDB_CODE_SUCCESS) {
56,911!
UNCOV
910
      return code;
×
911
    }
912

913
    //    uint64_t uid = pReader->status.uidList.tableUidList[j];
914

915
    //    STableBlockScanInfo* pScanInfo = getTableBlockScanInfo(pReader->status.pTableMap, uid, pReader->idStr);
916
    //    if (pScanInfo->pFileDelData == NULL) {
917
    //      pScanInfo->pFileDelData = taosArrayInit(4, sizeof(SDelData));
918
    //    }
919

920
    ETombBlkCheckEnum ret = 0;
56,911✔
921
    code = doCheckTombBlock(&block, pReader, numOfTables, &j, &ret);
56,911✔
922

923
    tTombBlockDestroy(&block);
56,910✔
924
    if (code != TSDB_CODE_SUCCESS || ret == BLK_CHECK_QUIT) {
56,911✔
925
      return code;
31,568✔
926
    }
927

928
    i += 1;
25,343✔
929
  }
930

931
  return TSDB_CODE_SUCCESS;
6,727,908✔
932
}
933

934
int32_t loadDataFileTombDataForAll(STsdbReader* pReader) {
8,797,993✔
935
  if (pReader->status.pCurrentFileset == NULL || pReader->status.pCurrentFileset->farr[3] == NULL) {
8,797,993!
936
    return TSDB_CODE_SUCCESS;
8,765,300✔
937
  }
938

939
  const TTombBlkArray* pBlkArray = NULL;
32,693✔
940

941
  int32_t code = tsdbDataFileReadTombBlk(pReader->pFileReader, &pBlkArray);
32,693✔
942
  if (code != TSDB_CODE_SUCCESS) {
32,693!
943
    return code;
×
944
  }
945

946
  return doLoadTombDataFromTombBlk(pBlkArray, pReader, pReader->pFileReader, true);
32,693✔
947
}
948

949
int32_t loadSttTombDataForAll(STsdbReader* pReader, SSttFileReader* pSttFileReader, SSttBlockLoadInfo* pLoadInfo) {
6,727,366✔
950
  const TTombBlkArray* pBlkArray = NULL;
6,727,366✔
951
  int32_t              code = tsdbSttFileReadTombBlk(pSttFileReader, &pBlkArray);
6,727,366✔
952
  if (code != TSDB_CODE_SUCCESS) {
6,726,939!
953
    return code;
×
954
  }
955

956
  return doLoadTombDataFromTombBlk(pBlkArray, pReader, pSttFileReader, false);
6,726,939✔
957
}
958

959
int32_t loadMemTombData(SArray** ppMemDelData, STbData* pMemTbData, STbData* piMemTbData, int64_t ver) {
12,776,563✔
960
  if (*ppMemDelData == NULL) {
12,776,563✔
961
    *ppMemDelData = taosArrayInit(4, sizeof(SDelData));
12,772,768✔
962
    if (*ppMemDelData == NULL) {
12,775,553!
UNCOV
963
      return terrno;
×
964
    }
965
  }
966

967
  SArray* pMemDelData = *ppMemDelData;
12,779,348✔
968

969
  SDelData* p = NULL;
12,779,348✔
970
  if (pMemTbData != NULL) {
12,779,348✔
971
    taosRLockLatch(&pMemTbData->lock);
4,609,549✔
972
    p = pMemTbData->pHead;
4,610,697✔
973
    while (p) {
5,398,423✔
974
      if (p->version <= ver) {
787,756✔
975
        void* px = taosArrayPush(pMemDelData, p);
783,520✔
976
        if (px == NULL) {
783,520!
977
          taosRUnLockLatch(&pMemTbData->lock);
×
978
          return terrno;
×
979
        }
980
      }
981

982
      p = p->pNext;
787,726✔
983
    }
984
    taosRUnLockLatch(&pMemTbData->lock);
4,610,667✔
985
  }
986

987
  if (piMemTbData != NULL) {
12,780,751✔
988
    p = piMemTbData->pHead;
26,679✔
989
    while (p) {
80,190✔
990
      if (p->version <= ver) {
53,511!
991
        void* px = taosArrayPush(pMemDelData, p);
53,511✔
992
        if (px == NULL) {
53,511!
993
          return terrno;
×
994
        }
995
      }
996
      p = p->pNext;
53,511✔
997
    }
998
  }
999

1000
  return TSDB_CODE_SUCCESS;
12,780,751✔
1001
}
1002

1003
int32_t getNumOfRowsInSttBlock(SSttFileReader* pSttFileReader, SSttBlockLoadInfo* pBlockLoadInfo,
4,854✔
1004
                               TStatisBlkArray* pStatisBlkArray, uint64_t suid, const uint64_t* pUidList,
1005
                               int32_t numOfTables, int32_t* pNumOfRows) {
1006
  int32_t num = 0;
4,854✔
1007
  int32_t code = 0;
4,854✔
1008
  int32_t lino = 0;
4,854✔
1009

1010
  if (pNumOfRows != 0) {
4,854!
1011
    *pNumOfRows = 0;
4,856✔
1012
  }
1013

1014
  if (TARRAY2_SIZE(pStatisBlkArray) <= 0) {
4,854!
1015
    return code;
×
1016
  }
1017

1018
  int32_t i = 0;
4,854✔
1019
  while ((i < TARRAY2_SIZE(pStatisBlkArray)) && (pStatisBlkArray->data[i].maxTbid.suid < suid)) {
6,798✔
1020
    ++i;
1,944✔
1021
  }
1022

1023
  if (i >= TARRAY2_SIZE(pStatisBlkArray)) {
4,854✔
1024
    return code;
1,944✔
1025
  }
1026

1027
  SStatisBlk*     p = &pStatisBlkArray->data[i];
2,910✔
1028
  STbStatisBlock* pStatisBlock = taosMemoryCalloc(1, sizeof(STbStatisBlock));
2,910✔
1029
  TSDB_CHECK_NULL(pStatisBlock, code, lino, _err, terrno);
2,913!
1030

1031
  code = tStatisBlockInit(pStatisBlock);
2,913✔
1032
  TSDB_CHECK_CODE(code, lino, _err);
2,919!
1033

1034
  int64_t st = taosGetTimestampMs();
2,914✔
1035
  code = tsdbSttFileReadStatisBlock(pSttFileReader, p, pStatisBlock);
2,914✔
1036
  TSDB_CHECK_CODE(code, lino, _err);
2,920!
1037

1038
  double el = (taosGetTimestampMs() - st) / 1000.0;
2,920✔
1039
  pBlockLoadInfo->cost.loadStatisBlocks += 1;
2,920✔
1040
  pBlockLoadInfo->cost.statisElapsedTime += el;
2,920✔
1041

1042
  int32_t index = 0;
2,920✔
1043
  while (index < pStatisBlock->numOfRecords && ((int64_t*)pStatisBlock->suids.data)[index] < suid) {
5,836!
1044
    ++index;
2,916✔
1045
  }
1046

1047
  if (index >= pStatisBlock->numOfRecords) {
2,920!
1048
    tStatisBlockDestroy(pStatisBlock);
×
1049
    taosMemoryFreeClear(pStatisBlock);
×
1050
    *pNumOfRows = num;
×
1051
    return code;
×
1052
  }
1053

1054
  int32_t j = index;
2,920✔
1055
  int32_t uidIndex = 0;
2,920✔
1056
  while (i < TARRAY2_SIZE(pStatisBlkArray) && uidIndex < numOfTables) {
7,782✔
1057
    p = &pStatisBlkArray->data[i];
4,862✔
1058
    if (p->minTbid.suid > suid) {
4,862✔
1059
      tStatisBlockDestroy(pStatisBlock);
1✔
1060
      taosMemoryFreeClear(pStatisBlock);
1!
1061
      *pNumOfRows = num;
1✔
1062
      return code;
1✔
1063
    }
1064

1065
    uint64_t uid = pUidList[uidIndex];
4,861✔
1066

1067
    if (((int64_t*)pStatisBlock->uids.data)[j] == uid) {
4,861✔
1068
      num += ((int64_t*)pStatisBlock->counts.data)[j];
2,917✔
1069
      uidIndex += 1;
2,917✔
1070
      j += 1;
2,917✔
1071
      code = loadNextStatisticsBlock(pSttFileReader, pStatisBlock, pStatisBlkArray, pStatisBlock->numOfRecords, &i, &j);
2,917✔
1072
      TSDB_CHECK_CODE(code, lino, _err);
2,918!
1073
    } else if (((int64_t*)pStatisBlock->uids.data)[j] < uid) {
1,944!
1074
      j += 1;
×
1075
      code = loadNextStatisticsBlock(pSttFileReader, pStatisBlock, pStatisBlkArray, pStatisBlock->numOfRecords, &i, &j);
×
1076
      TSDB_CHECK_CODE(code, lino, _err);
×
1077
    } else {
1078
      uidIndex += 1;
1,944✔
1079
    }
1080
  }
1081

1082
  tStatisBlockDestroy(pStatisBlock);
2,920✔
1083
  taosMemoryFreeClear(pStatisBlock);
2,915!
1084
  *pNumOfRows = num;
2,919✔
1085
  return code;
2,919✔
1086

1087
_err:
×
1088
  tsdbError("%p failed to get number of rows in stt block, %s at line:%d code:%s", pSttFileReader, __func__, lino,
×
1089
            tstrerror(code));
1090
  return code;
×
1091
}
1092

1093
// load next stt statistics block
1094
static int32_t loadNextStatisticsBlock(SSttFileReader* pSttFileReader, STbStatisBlock* pStatisBlock,
2,917✔
1095
                                       const TStatisBlkArray* pStatisBlkArray, int32_t numOfRows, int32_t* i,
1096
                                       int32_t* j) {
1097
  if ((*j) >= numOfRows) {
2,917✔
1098
    (*i) += 1;
1,947✔
1099
    (*j) = 0;
1,947✔
1100
    if ((*i) < TARRAY2_SIZE(pStatisBlkArray)) {
1,947!
1101
      int32_t code = tsdbSttFileReadStatisBlock(pSttFileReader, &pStatisBlkArray->data[(*i)], pStatisBlock);
×
1102
      if (code != 0) {
×
1103
        tsdbError("%p failed to read statisBlock, code:%s", pSttFileReader, tstrerror(code));
×
1104
        return code;
×
1105
      }
1106
    }
1107
  }
1108

1109
  return 0;
2,917✔
1110
}
1111

1112
int32_t doAdjustValidDataIters(SArray* pLDIterList, int32_t numOfFileObj) {
14,474,422✔
1113
  int32_t size = taosArrayGetSize(pLDIterList);
14,474,422✔
1114

1115
  if (size < numOfFileObj) {
14,473,708✔
1116
    int32_t inc = numOfFileObj - size;
6,731,622✔
1117
    for (int32_t k = 0; k < inc; ++k) {
13,471,231✔
1118
      SLDataIter* pIter = taosMemoryCalloc(1, sizeof(SLDataIter));
6,731,887✔
1119
      if (!pIter) {
6,738,085!
UNCOV
1120
        return terrno;
×
1121
      }
1122
      void* px = taosArrayPush(pLDIterList, &pIter);
6,739,609✔
1123
      if (px == NULL) {
6,739,609!
1124
        taosMemoryFree(pIter);
×
1125
        return terrno;
×
1126
      }
1127
    }
1128
  } else if (size > numOfFileObj) {  // remove unused LDataIter
7,742,086!
1129
    int32_t inc = size - numOfFileObj;
×
1130

1131
    for (int i = 0; i < inc; ++i) {
×
1132
      SLDataIter* pIter = taosArrayPop(pLDIterList);
×
1133
      destroyLDataIter(pIter);
×
1134
    }
1135
  }
1136

1137
  return TSDB_CODE_SUCCESS;
14,477,855✔
1138
}
1139

1140
int32_t adjustSttDataIters(SArray* pSttFileBlockIterArray, STFileSet* pFileSet) {
14,266,632✔
1141
  int32_t numOfLevels = pFileSet->lvlArr->size;
14,266,632✔
1142
  int32_t code = 0;
14,266,632✔
1143

1144
  // add the list/iter placeholder
1145
  while (taosArrayGetSize(pSttFileBlockIterArray) < numOfLevels) {
20,999,986✔
1146
    SArray* pList = taosArrayInit(4, POINTER_BYTES);
6,723,290✔
1147
    if (pList == NULL) {
6,736,811!
UNCOV
1148
      return terrno;
×
1149
    }
1150
    void* px = taosArrayPush(pSttFileBlockIterArray, &pList);
6,733,354✔
1151
    if (px == NULL) {
6,733,354!
1152
      return terrno;
×
1153
    }
1154
  }
1155

1156
  for (int32_t j = 0; j < numOfLevels; ++j) {
28,747,861✔
1157
    SSttLvl* pSttLevel = pFileSet->lvlArr->data[j];
14,478,542✔
1158
    SArray*  pList = taosArrayGetP(pSttFileBlockIterArray, j);
14,478,542✔
1159
    code = doAdjustValidDataIters(pList, TARRAY2_SIZE(pSttLevel->fobjArr));
14,475,278✔
1160
    if (code != TSDB_CODE_SUCCESS) {
14,479,055!
UNCOV
1161
      return code;
×
1162
    }
1163
  }
1164

1165
  return TSDB_CODE_SUCCESS;
14,269,319✔
1166
}
1167

1168
int32_t tsdbGetRowsInSttFiles(STFileSet* pFileSet, SArray* pSttFileBlockIterArray, STsdb* pTsdb, SMergeTreeConf* pConf,
4,850✔
1169
                              const char* pstr) {
1170
  int32_t numOfRows = 0;
4,850✔
1171
  int32_t code = 0;
4,850✔
1172

1173
  // no data exists, go to end
1174
  int32_t numOfLevels = pFileSet->lvlArr->size;
4,850✔
1175
  if (numOfLevels == 0) {
4,850!
1176
    return numOfRows;
×
1177
  }
1178

1179
  // add the list/iter placeholder
1180
  code = adjustSttDataIters(pSttFileBlockIterArray, pFileSet);
4,850✔
1181
  if (code != TSDB_CODE_SUCCESS) {
4,857!
UNCOV
1182
    return numOfRows;
×
1183
  }
1184

1185
  for (int32_t j = 0; j < numOfLevels; ++j) {
9,718✔
1186
    SSttLvl* pSttLevel = pFileSet->lvlArr->data[j];
4,856✔
1187
    SArray*  pList = taosArrayGetP(pSttFileBlockIterArray, j);
4,856✔
1188

1189
    for (int32_t i = 0; i < taosArrayGetSize(pList); ++i) {  // open all last file
9,712✔
1190
      SLDataIter* pIter = taosArrayGetP(pList, i);
4,840✔
1191

1192
      // open stt file reader if not opened yet
1193
      // if failed to open this stt file, ignore the error and try next one
1194
      if (pIter->pReader == NULL) {
4,847!
1195
        SSttFileReaderConfig conf = {.tsdb = pTsdb, .szPage = pTsdb->pVnode->config.tsdbPageSize};
4,847✔
1196
        conf.file[0] = *pSttLevel->fobjArr->data[i]->f;
4,847✔
1197

1198
        const char* pName = pSttLevel->fobjArr->data[i]->fname;
4,847✔
1199
        code = tsdbSttFileReaderOpen(pName, &conf, &pIter->pReader);
4,847✔
1200
        if (code != TSDB_CODE_SUCCESS) {
4,853!
1201
          tsdbError("open stt file reader error. file:%s, code %s, %s", pName, tstrerror(code), pstr);
×
1202
          continue;
×
1203
        }
1204
      }
1205

1206
      if (pIter->pBlockLoadInfo == NULL) {
4,853!
1207
        code = tCreateSttBlockLoadInfo(pConf->pSchema, pConf->pCols, pConf->numOfCols, &pIter->pBlockLoadInfo);
4,853✔
1208
        if (code != TSDB_CODE_SUCCESS) {
4,860!
1209
          tsdbError("failed to create block load info, code: out of memory, %s", pstr);
×
1210
          continue;
×
1211
        }
1212
      }
1213

1214
      // load stt blocks statis for all stt-blocks, to decide if the data of queried table exists in current stt file
1215
      TStatisBlkArray* pStatisBlkArray = NULL;
4,860✔
1216
      code = tsdbSttFileReadStatisBlk(pIter->pReader, (const TStatisBlkArray**)&pStatisBlkArray);
4,860✔
1217
      if (code != TSDB_CODE_SUCCESS) {
4,862!
1218
        tsdbError("failed to load stt block statistics, code:%s, %s", tstrerror(code), pstr);
×
1219
        continue;
×
1220
      }
1221

1222
      // extract rows from each stt file one-by-one
1223
      STsdbReader* pReader = pConf->pReader;
4,862✔
1224
      int32_t      numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
4,862✔
1225
      uint64_t*    pUidList = pReader->status.uidList.tableUidList;
4,857✔
1226
      int32_t      n = 0;
4,857✔
1227
      code = getNumOfRowsInSttBlock(pIter->pReader, pIter->pBlockLoadInfo, pStatisBlkArray, pConf->suid, pUidList,
4,857✔
1228
                                    numOfTables, &n);
1229
      numOfRows += n;
4,864✔
1230
      if (code) {
4,864!
1231
        tsdbError("%s failed to get rows in stt blocks, code:%s", pstr, tstrerror(code));
×
1232
      }
1233
    }
1234
  }
1235

1236
  return numOfRows;
4,862✔
1237
}
1238

1239
static bool overlapHelper(const STimeWindow* pLeft, TSKEY minKey, TSKEY maxKey) {
35,517✔
1240
  return (pLeft->ekey >= minKey) && (pLeft->skey <= maxKey);
35,517✔
1241
}
1242

1243
static bool overlapWithTimeWindow(STimeWindow* p1, STimeWindow* pQueryWindow, STableBlockScanInfo* pBlockScanInfo,
96,067✔
1244
                                  int32_t order) {
1245
  // overlap with query window
1246
  if (!(p1->skey >= pQueryWindow->skey && p1->ekey <= pQueryWindow->ekey)) {
96,067✔
1247
    return true;
553✔
1248
  }
1249

1250
  SIterInfo* pMemIter = &pBlockScanInfo->iter;
95,514✔
1251
  SIterInfo* pIMemIter = &pBlockScanInfo->iiter;
95,514✔
1252

1253
  // overlap with mem data
1254
  if (pMemIter->hasVal) {
95,514✔
1255
    STbData* pTbData = pMemIter->iter->pTbData;
32,998✔
1256
    if (overlapHelper(p1, pTbData->minKey, pTbData->maxKey)) {
32,998✔
1257
      return true;
32,716✔
1258
    }
1259
  }
1260

1261
  // overlap with imem data
1262
  if (pIMemIter->hasVal) {
62,806✔
1263
    STbData* pITbData = pIMemIter->iter->pTbData;
917✔
1264
    if (overlapHelper(p1, pITbData->minKey, pITbData->maxKey)) {
917!
1265
      return true;
917✔
1266
    }
1267
  }
1268

1269
  // overlap with data file block
1270
  STimeWindow* pFileWin = &pBlockScanInfo->filesetWindow;
61,889✔
1271
  if ((taosArrayGetSize(pBlockScanInfo->pBlockIdxList) > 0) && overlapHelper(p1, pFileWin->skey, pFileWin->ekey)) {
61,889✔
1272
    return true;
1,581✔
1273
  }
1274

1275
  // overlap with deletion skyline
1276
  SBrinRecord record = {.firstKey = p1->skey, .lastKey = p1->ekey};
60,309✔
1277
  if (overlapWithDelSkylineWithoutVer(pBlockScanInfo, &record, order)) {
60,309✔
1278
    return true;
8,117✔
1279
  }
1280

1281
  return false;
52,246✔
1282
}
1283

1284
static int32_t sortUidComparFn(const void* p1, const void* p2) {
65,985✔
1285
  const SSttKeyRange* px1 = p1;
65,985✔
1286
  const SSttKeyRange* px2 = p2;
65,985✔
1287

1288
  int32_t ret = tRowKeyCompare(&px1->skey, &px2->skey);
65,985✔
1289
  return ret;
66,020✔
1290
}
1291

1292
bool isCleanSttBlock(SArray* pKeyRangeList, STimeWindow* pQueryWindow, STableBlockScanInfo* pScanInfo, int32_t order) {
244,288✔
1293
  // check if it overlap with del skyline
1294
  taosArraySort(pKeyRangeList, sortUidComparFn);
244,288✔
1295

1296
  int32_t num = taosArrayGetSize(pKeyRangeList);
244,329✔
1297
  if (num == 0) {
244,401✔
1298
    return false;
148,292✔
1299
  }
1300

1301
  SSttKeyRange* pRange = taosArrayGet(pKeyRangeList, 0);
96,109✔
1302
  if (pRange == NULL) {
96,088!
1303
    return false;
×
1304
  }
1305

1306
  STimeWindow w = {.skey = pRange->skey.ts, .ekey = pRange->ekey.ts};
96,088✔
1307
  if (overlapWithTimeWindow(&w, pQueryWindow, pScanInfo, order)) {
96,088✔
1308
    return false;
43,925✔
1309
  }
1310

1311
  for (int32_t i = 0; i < num - 1; ++i) {
52,233✔
1312
    SSttKeyRange* p1 = taosArrayGet(pKeyRangeList, i);
24,481✔
1313
    SSttKeyRange* p2 = taosArrayGet(pKeyRangeList, i + 1);
24,483✔
1314
    if (p1 == NULL || p2 == NULL) {
24,471!
1315
      return false;
24,462✔
1316
    }
1317

1318
    if (p1->ekey.ts >= p2->skey.ts) {
24,471✔
1319
      return false;
24,462✔
1320
    }
1321

1322
    STimeWindow w2 = {.skey = p2->skey.ts, .ekey = p2->ekey.ts};
9✔
1323
    bool        overlap = overlapWithTimeWindow(&w2, pQueryWindow, pScanInfo, order);
9✔
1324
    if (overlap) {
7!
1325
      return false;
×
1326
    }
1327
  }
1328

1329
  return true;
27,752✔
1330
}
1331

1332
static bool doCheckDatablockOverlap(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord,
37,043✔
1333
                                    int32_t startIndex) {
1334
  size_t num = taosArrayGetSize(pBlockScanInfo->delSkyline);
37,043✔
1335

1336
  for (int32_t i = startIndex; i < num; i += 1) {
101,701✔
1337
    TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, i);
101,677✔
1338
    if (p == NULL) {
101,677!
1339
      return false;
×
1340
    }
1341

1342
    if (p->ts >= pRecord->firstKey.key.ts && p->ts <= pRecord->lastKey.key.ts) {
101,677✔
1343
      if (p->version >= pRecord->minVer) {
25,895✔
1344
        return true;
23,892✔
1345
      }
1346
    } else if (p->ts < pRecord->firstKey.key.ts) {  // p->ts < pBlock->minKey.ts
75,782✔
1347
      if (p->version >= pRecord->minVer) {
70,627✔
1348
        if (i < num - 1) {
21,636!
1349
          TSDBKEY* pnext = taosArrayGet(pBlockScanInfo->delSkyline, i + 1);
21,636✔
1350
          if (pnext == NULL) {
21,636!
1351
            return false;
×
1352
          }
1353

1354
          if (pnext->ts >= pRecord->firstKey.key.ts) {
21,636✔
1355
            return true;
7,972✔
1356
          }
1357
        } else {  // it must be the last point
1358
          if (!(p->version == 0)) {
×
1359
            tsdbError("unexpected version:%" PRId64, p->version);
×
1360
          }
1361
        }
1362
      }
1363
    } else {  // (p->ts > pBlock->maxKey.ts) {
1364
      return false;
5,155✔
1365
    }
1366
  }
1367

1368
  return false;
24✔
1369
}
1370

1371
static bool doCheckDatablockOverlapWithoutVersion(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord,
8,118✔
1372
                                                  int32_t startIndex) {
1373
  size_t num = taosArrayGetSize(pBlockScanInfo->delSkyline);
8,118✔
1374

1375
  for (int32_t i = startIndex; i < num; i += 1) {
8,117!
1376
    TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, i);
8,117✔
1377
    if (p == NULL) {
8,117!
1378
      return false;
×
1379
    }
1380

1381
    if (p->ts >= pRecord->firstKey.key.ts && p->ts <= pRecord->lastKey.key.ts) {
8,117!
1382
      return true;
8,117✔
1383
    } else if (p->ts < pRecord->firstKey.key.ts) {  // p->ts < pBlock->minKey.ts
×
1384
      if (i < num - 1) {
×
1385
        TSDBKEY* pnext = taosArrayGet(pBlockScanInfo->delSkyline, i + 1);
×
1386
        if (pnext == NULL) {
×
1387
          return false;
×
1388
        }
1389

1390
        if (pnext->ts >= pRecord->firstKey.key.ts) {
×
1391
          return true;
×
1392
        }
1393
      }
1394
    } else {  // (p->ts > pBlock->maxKey.ts) {
1395
      return false;
×
1396
    }
1397
  }
1398

1399
  return false;
×
1400
}
1401

1402
bool overlapWithDelSkyline(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord, int32_t order) {
689,987✔
1403
  if (pBlockScanInfo->delSkyline == NULL || (taosArrayGetSize(pBlockScanInfo->delSkyline) == 0)) {
689,987✔
1404
    return false;
642,769✔
1405
  }
1406

1407
  // ts is not overlap
1408
  TSDBKEY* pFirst = taosArrayGet(pBlockScanInfo->delSkyline, 0);
47,218✔
1409
  TSDBKEY* pLast = taosArrayGetLast(pBlockScanInfo->delSkyline);
47,393✔
1410
  if (pFirst == NULL || pLast == NULL) {
47,393!
1411
    return false;
×
1412
  }
1413

1414
  if (pRecord->firstKey.key.ts > pLast->ts || pRecord->lastKey.key.ts < pFirst->ts) {
47,393✔
1415
    return false;
10,350✔
1416
  }
1417

1418
  // version is not overlap
1419
  if (ASCENDING_TRAVERSE(order)) {
37,043✔
1420
    return doCheckDatablockOverlap(pBlockScanInfo, pRecord, pBlockScanInfo->fileDelIndex);
27,971✔
1421
  } else {
1422
    int32_t index = pBlockScanInfo->fileDelIndex;
9,072✔
1423
    while (1) {
30,278✔
1424
      TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, index);
39,350✔
1425
      if (p == NULL) {
39,350!
1426
        return false;
×
1427
      }
1428

1429
      if (p->ts > pRecord->firstKey.key.ts && index > 0) {
39,350✔
1430
        index -= 1;
30,278✔
1431
      } else {  // find the first point that is smaller than the minKey.ts of dataBlock.
1432
        if (p->ts == pRecord->firstKey.key.ts && p->version < pRecord->maxVer && index > 0) {
9,072!
1433
          index -= 1;
24✔
1434
        }
1435
        break;
9,072✔
1436
      }
1437
    }
1438

1439
    return doCheckDatablockOverlap(pBlockScanInfo, pRecord, index);
9,072✔
1440
  }
1441
}
1442

1443
bool overlapWithDelSkylineWithoutVer(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord, int32_t order) {
60,356✔
1444
  if (pBlockScanInfo->delSkyline == NULL || (taosArrayGetSize(pBlockScanInfo->delSkyline) == 0)) {
60,356✔
1445
    return false;
51,646✔
1446
  }
1447

1448
  // ts is not overlap
1449
  TSDBKEY* pFirst = taosArrayGet(pBlockScanInfo->delSkyline, 0);
8,710✔
1450
  TSDBKEY* pLast = taosArrayGetLast(pBlockScanInfo->delSkyline);
8,719✔
1451
  if (pFirst == NULL || pLast == NULL) {
8,719!
1452
    return false;
×
1453
  }
1454

1455
  if (pRecord->firstKey.key.ts > pLast->ts || pRecord->lastKey.key.ts < pFirst->ts) {
8,719✔
1456
    return false;
601✔
1457
  }
1458

1459
  // version is not overlap
1460
  if (ASCENDING_TRAVERSE(order)) {
8,118!
1461
    return doCheckDatablockOverlapWithoutVersion(pBlockScanInfo, pRecord, pBlockScanInfo->fileDelIndex);
8,118✔
1462
  } else {
1463
    int32_t index = pBlockScanInfo->fileDelIndex;
×
1464
    while (1) {
×
1465
      TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, index);
×
1466
      if (p == NULL) {
×
1467
        return false;
×
1468
      }
1469

1470
      if (p->ts > pRecord->firstKey.key.ts && index > 0) {
×
1471
        index -= 1;
×
1472
      } else {  // find the first point that is smaller than the minKey.ts of dataBlock.
1473
        if (p->ts == pRecord->firstKey.key.ts && index > 0) {
×
1474
          index -= 1;
×
1475
        }
1476
        break;
×
1477
      }
1478
    }
1479

1480
    return doCheckDatablockOverlapWithoutVersion(pBlockScanInfo, pRecord, index);
×
1481
  }
1482
}
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