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

taosdata / TDengine / #5034

24 Apr 2026 11:25AM UTC coverage: 73.058%. Remained the same
#5034

push

travis-ci

web-flow
merge: from main to 3.0 branch #35224

merge: from main to 3.0 branch[manual-only]

1336 of 1975 new or added lines in 48 files covered. (67.65%)

14149 existing lines in 164 files now uncovered.

275896 of 377640 relevant lines covered (73.06%)

132944440.29 hits per line

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

72.68
/source/common/src/tdatablock.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
#define _DEFAULT_SOURCE
17
#include "tdatablock.h"
18
#include "tcompare.h"
19
#include "tglobal.h"
20
#include "tlog.h"
21
#include "tname.h"
22

23
#define MALLOC_ALIGN_BYTES 32
24

25
int32_t colDataGetLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRows) {
2,147,483,647✔
26
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
27
    if (pColumnInfoData->reassigned) {
1,374,316,429✔
28
      int32_t totalSize = 0;
54,792✔
29
      for (int32_t row = 0; row < numOfRows; ++row) {
627,064✔
30
        char*   pColData = pColumnInfoData->pData + pColumnInfoData->varmeta.offset[row];
572,272✔
31
        int32_t colSize = calcStrBytesByType(pColumnInfoData->info.type, pColData);
572,272✔
32
        totalSize += colSize;
572,272✔
33
      }
34
      return totalSize;
54,792✔
35
    }
36
    return pColumnInfoData->varmeta.length;
1,374,842,400✔
37
  } else {
38
    if (pColumnInfoData->info.type == TSDB_DATA_TYPE_NULL) {
2,147,483,647✔
39
      return 0;
461,952✔
40
    } else {
41
      return pColumnInfoData->info.bytes * numOfRows;
2,147,483,647✔
42
    }
43
  }
44
}
45

46
int32_t colDataGetRowLength(const SColumnInfoData* pColumnInfoData, int32_t rowIdx) {
2,147,483,647✔
47
  if (colDataIsNull_s(pColumnInfoData, rowIdx)) {
2,147,483,647✔
48
    return 0;
×
49
  }
50

51
  if (!IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
52
    return pColumnInfoData->info.bytes;
2,147,483,647✔
53
  } else {
54
    return calcStrBytesByType(pColumnInfoData->info.type, colDataGetData(pColumnInfoData, rowIdx));
1,913,063,774✔
55
  }
56
  // if (pColumnInfoData->info.type == TSDB_DATA_TYPE_JSON) {
57
  //   return getJsonValueLen(colDataGetData(pColumnInfoData, rowIdx));
58
  // } else if (IS_STR_DATA_BLOB(pColumnInfoData->info.type)) {
59
  //   return blobDataTLen(colDataGetData(pColumnInfoData, rowIdx));
60
  // } else {
61
  //   return varDataTLen(colDataGetData(pColumnInfoData, rowIdx));
62
  // }
63
}
64

65
int32_t colDataGetFullLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRows) {
2,147,483,647✔
66
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
67
    return pColumnInfoData->varmeta.length + sizeof(int32_t) * numOfRows;
1,929,533,856✔
68
  } else {
69
    return ((pColumnInfoData->info.type == TSDB_DATA_TYPE_NULL) ? 0 : pColumnInfoData->info.bytes * numOfRows) +
2,147,483,647✔
70
           BitmapLen(numOfRows);
2,147,483,647✔
71
  }
72
}
73

74
int32_t getJsonValueLen(const char* data) {
8,643,741✔
75
  int32_t dataLen = 0;
8,643,741✔
76
  if (*data == TSDB_DATA_TYPE_NULL) {
8,643,741✔
77
    dataLen = CHAR_BYTES;
191,574✔
78
  } else if (*data == TSDB_DATA_TYPE_NCHAR) {
8,452,591✔
79
    dataLen = varDataTLen(data + CHAR_BYTES) + CHAR_BYTES;
3,589,634✔
80
  } else if (*data == TSDB_DATA_TYPE_DOUBLE) {
4,862,539✔
81
    dataLen = DOUBLE_BYTES + CHAR_BYTES;
458,456✔
82
  } else if (*data == TSDB_DATA_TYPE_BOOL) {
4,403,659✔
83
    dataLen = CHAR_BYTES + CHAR_BYTES;
126,780✔
84
  } else if (tTagIsJson(data)) {  // json string
4,277,303✔
85
    dataLen = ((STag*)(data))->len;
4,277,721✔
86
  } else {
87
    uError("Invalid data type:%d in Json", *data);
×
88
  }
89
  return dataLen;
8,643,747✔
90
}
91

92
static int32_t getDataLen(int32_t type, const char* pData) {
2,147,483,647✔
93
  int32_t dataLen = 0;
2,147,483,647✔
94
  if (type == TSDB_DATA_TYPE_JSON) {
2,147,483,647✔
95
    dataLen = getJsonValueLen(pData);
8,054,793✔
96
  } else if (IS_STR_DATA_BLOB(type)) {
2,147,483,647✔
97
    dataLen = blobDataTLen(pData);
1,796✔
98
  } else {
99
    dataLen = varDataTLen(pData);
2,147,483,647✔
100
  }
101
  return dataLen;
2,147,483,647✔
102
}
103

104
int32_t calcStrBytesByType(int8_t type, char* data) { return getDataLen(type, data); }
2,147,483,647✔
105

106
int32_t blockDataGetPagedColumnReservedBytes(const SColumnInfoData* pColumnInfoData) {
2,147,483,647✔
107
  return pColumnInfoData->info.bytes;
2,147,483,647✔
108
}
109

110
static int32_t checkAllocLen(SColumnInfoData* pColumnInfoData, char** pData, int32_t dataLen){
2,147,483,647✔
111
  SVarColAttr* pAttr = &pColumnInfoData->varmeta;
2,147,483,647✔
112
  char* buf = NULL;
2,147,483,647✔
113
  if (pAttr->allocLen < pAttr->length + dataLen) {
2,147,483,647✔
114
    uint32_t newSize = pAttr->allocLen;
2,147,483,647✔
115
    if (newSize <= 1) {
2,147,483,647✔
116
      newSize = 8;
1,321,674,573✔
117
    }
118

119
    while (newSize < pAttr->length + dataLen) {
2,147,483,647✔
120
      newSize = newSize * 1.5;
2,147,483,647✔
121
      if (newSize > UINT32_MAX) {
122
        return TSDB_CODE_OUT_OF_MEMORY;
123
      }
124
    }
125

126
    buf = taosMemoryRealloc(*pData, newSize);
2,147,483,647✔
127
    if (buf == NULL) {
2,147,483,647✔
128
      return terrno;
×
129
    }
130

131
    *pData = buf;
2,147,483,647✔
132
    pAttr->allocLen = newSize;
2,147,483,647✔
133
  }
134
  return 0;
2,147,483,647✔
135
}
136

137
static int32_t colDataSetValHelp(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull) {
2,147,483,647✔
138
  if (isNull || pData == NULL) {
2,147,483,647✔
139
    // There is a placehold for each NULL value of binary or nchar type.
140
    if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
141
      pColumnInfoData->varmeta.offset[rowIndex] = -1;  // it is a null value of VAR type.
803,677,879✔
142
    } else {
143
      colDataSetNull_f_s(pColumnInfoData, rowIndex);
2,147,483,647✔
144
    }
145

146
    pColumnInfoData->hasNull = true;
2,147,483,647✔
147
    return 0;
2,147,483,647✔
148
  }
149

150
  int32_t type = pColumnInfoData->info.type;
2,147,483,647✔
151
  if (IS_VAR_DATA_TYPE(type)) {
2,147,483,647✔
152
    int32_t dataLen = getDataLen(type, pData);
2,147,483,647✔
153
    if (pColumnInfoData->varmeta.offset[rowIndex] > 0) {
2,147,483,647✔
154
      pColumnInfoData->varmeta.length = pColumnInfoData->varmeta.offset[rowIndex];
24,672✔
155
    }
156

157
    bool overlap = false;
2,147,483,647✔
158
    uint64_t offset = 0;
2,147,483,647✔
159
    if ((uint64_t)pData >= (uint64_t)pColumnInfoData->pData && ((uint64_t)pData + dataLen) <= ((uint64_t)pColumnInfoData->pData + pColumnInfoData->varmeta.allocLen)) {
2,147,483,647✔
160
      overlap = true;
105,600,000✔
161
      offset = (uint64_t)pData - (uint64_t)pColumnInfoData->pData;
105,600,000✔
162
    }
163

164
    int32_t code = checkAllocLen(pColumnInfoData, &pColumnInfoData->pData, dataLen);
2,147,483,647✔
165
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
166
      return code;
×
167
    }
168

169
    uint32_t len = pColumnInfoData->varmeta.length;
2,147,483,647✔
170
    pColumnInfoData->varmeta.offset[rowIndex] = len;
2,147,483,647✔
171

172
    (void)memmove(pColumnInfoData->pData + len, overlap ? (pColumnInfoData->pData + offset) : pData, dataLen);
2,147,483,647✔
173
    pColumnInfoData->varmeta.length += dataLen;
2,147,483,647✔
174
  } else {
175
    memcpy(pColumnInfoData->pData + pColumnInfoData->info.bytes * rowIndex, pData, pColumnInfoData->info.bytes);
2,147,483,647✔
176
    colDataClearNull_f(pColumnInfoData->nullbitmap, rowIndex);
2,147,483,647✔
177
  }
178

179
  return 0;
2,147,483,647✔
180
}
181

182
int32_t colDataSetVal(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull) {
2,147,483,647✔
183
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
184
    pColumnInfoData->varmeta.offset[rowIndex] = -1;
2,147,483,647✔
185
  }
186

187
  return colDataSetValHelp(pColumnInfoData, rowIndex, pData, isNull);
2,147,483,647✔
188
}
189

190
int32_t colDataSetValOrCover(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull) {
2,147,483,647✔
191
  return colDataSetValHelp(pColumnInfoData, rowIndex, pData, isNull);
2,147,483,647✔
192
}
193

194
int32_t varColSetVarData(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pVarData, int32_t varDataLen,
1,405,443✔
195
                         bool isNull) {
196
  if (!IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
1,405,443✔
197
    return TSDB_CODE_INVALID_PARA;
×
198
  }
199

200
  if (isNull || pVarData == NULL) {
1,406,233✔
201
    pColumnInfoData->varmeta.offset[rowIndex] = -1;  // it is a null value of VAR type.
790✔
202
    pColumnInfoData->hasNull = true;
×
203
    return TSDB_CODE_SUCCESS;
×
204
  }
205

206
  int32_t headerSize = IS_STR_DATA_BLOB(pColumnInfoData->info.type) ?
1,405,443✔
207
                         BLOBSTR_HEADER_SIZE : VARSTR_HEADER_SIZE;
208
  int32_t dataLen = headerSize + varDataLen;
1,406,233✔
209
  if (pColumnInfoData->varmeta.offset[rowIndex] > 0) {
1,406,233✔
210
    pColumnInfoData->varmeta.length = pColumnInfoData->varmeta.offset[rowIndex];
×
211
  }
212

213
  int32_t code = checkAllocLen(pColumnInfoData, &pColumnInfoData->pData, dataLen);
1,405,443✔
214
  if (code != TSDB_CODE_SUCCESS) {
1,405,443✔
215
    return code;
×
216
  }
217

218
  uint32_t len = pColumnInfoData->varmeta.length;
1,405,443✔
219
  pColumnInfoData->varmeta.offset[rowIndex] = len;
1,406,233✔
220

221
  if (IS_STR_DATA_BLOB(pColumnInfoData->info.type)) {
1,405,443✔
222
    (void)memmove(blobDataVal(pColumnInfoData->pData + len), pVarData, varDataLen);
3,215✔
223
    blobDataSetLen(pColumnInfoData->pData + len, varDataLen);
2,425✔
224

225
  } else {
226
    (void)memmove(varDataVal(pColumnInfoData->pData + len), pVarData, varDataLen);
1,403,018✔
227
    varDataSetLen(pColumnInfoData->pData + len, varDataLen);
1,403,808✔
228
  }
229
  pColumnInfoData->varmeta.length += dataLen;
1,405,443✔
230
  return TSDB_CODE_SUCCESS;
1,405,443✔
231
}
232

233
int32_t colDataReassignVal(SColumnInfoData* pColumnInfoData, uint32_t dstRowIdx, uint32_t srcRowIdx,
×
234
                           const char* pData) {
235
  int32_t type = pColumnInfoData->info.type;
×
236
  if (IS_VAR_DATA_TYPE(type)) {
×
237
    pColumnInfoData->varmeta.offset[dstRowIdx] = pColumnInfoData->varmeta.offset[srcRowIdx];
×
238
    pColumnInfoData->reassigned = true;
×
239
  } else {
240
    memcpy(pColumnInfoData->pData + pColumnInfoData->info.bytes * dstRowIdx, pData, pColumnInfoData->info.bytes);
×
241
    colDataClearNull_f(pColumnInfoData->nullbitmap, dstRowIdx);
×
242
  }
243

244
  return 0;
×
245
}
246

247
static int32_t colDataReserve(SColumnInfoData* pColumnInfoData, size_t newSize) {
479,083,684✔
248
  if (!IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
479,083,684✔
249
    return TSDB_CODE_SUCCESS;
×
250
  }
251

252
  if (pColumnInfoData->varmeta.allocLen >= newSize) {
479,086,656✔
253
    return TSDB_CODE_SUCCESS;
×
254
  }
255

256
  uint32_t sizeTmp = pColumnInfoData->varmeta.allocLen;
479,083,552✔
257
  if (sizeTmp <= 1) {
479,072,607✔
258
    sizeTmp = 8;
50,529,592✔
259
  }
260
  while (sizeTmp < newSize) {
1,429,990,272✔
261
    sizeTmp = sizeTmp * 1.5;
950,917,665✔
262
    if (sizeTmp > UINT32_MAX) {
263
      return TSDB_CODE_OUT_OF_MEMORY;
264
    }
265
  }
266
  if (pColumnInfoData->varmeta.allocLen < newSize) {
479,072,607✔
267
    char* buf = taosMemoryRealloc(pColumnInfoData->pData, newSize);
479,080,928✔
268
    if (buf == NULL) {
479,070,599✔
269
      return terrno;
×
270
    }
271

272
    pColumnInfoData->pData = buf;
479,070,599✔
273
    pColumnInfoData->varmeta.allocLen = newSize;
479,075,961✔
274
  }
275

276
  return TSDB_CODE_SUCCESS;
479,082,277✔
277
}
278

279
int32_t doCopyNItems(struct SColumnInfoData* pColumnInfoData, int32_t currentRow, const char* pData,
2,147,483,647✔
280
                            int32_t itemLen, int32_t numOfRows, bool trimValue) {
281
  if (pColumnInfoData->info.bytes < itemLen) {
2,147,483,647✔
282
    uWarn("column/tag actual data len %d is bigger than schema len %d, trim it:%d", itemLen,
339✔
283
          pColumnInfoData->info.bytes, trimValue);
284
    if (trimValue) {
339✔
285
      itemLen = pColumnInfoData->info.bytes;
×
286
    } else {
287
      return TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
339✔
288
    }
289
  }
290

291
  size_t   start = 1;
2,147,483,647✔
292
  int32_t  t = 0;
2,147,483,647✔
293
  int32_t  count = log(numOfRows) / log(2);
2,147,483,647✔
294
  uint32_t startOffset =
2,147,483,647✔
295
      (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) ? pColumnInfoData->varmeta.length : (currentRow * itemLen);
2,147,483,647✔
296

297
  // the first item
298
  memcpy(pColumnInfoData->pData + startOffset, pData, itemLen);
2,147,483,647✔
299

300
  while (t < count) {
2,147,483,647✔
301
    int32_t xlen = 1 << t;
2,147,483,647✔
302
    memcpy(pColumnInfoData->pData + start * itemLen + startOffset, pColumnInfoData->pData + startOffset,
2,147,483,647✔
303
           xlen * itemLen);
2,147,483,647✔
304
    t += 1;
2,147,483,647✔
305
    start += xlen;
2,147,483,647✔
306
  }
307

308
  // the tail part
309
  if (numOfRows > start) {
2,147,483,647✔
310
    memcpy(pColumnInfoData->pData + start * itemLen + startOffset, pColumnInfoData->pData + startOffset,
936,835,725✔
311
           (numOfRows - start) * itemLen);
936,803,846✔
312
  }
313

314
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
315
    for (int32_t i = 0; i < numOfRows; ++i) {
2,147,483,647✔
316
      pColumnInfoData->varmeta.offset[i + currentRow] = pColumnInfoData->varmeta.length + i * itemLen;
2,147,483,647✔
317
    }
318

319
    pColumnInfoData->varmeta.length += numOfRows * itemLen;
2,147,483,647✔
320
  }
321

322
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
323
}
324

325
int32_t colDataSetNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t numOfRows, uint32_t capacity,
2,147,483,647✔
326
                         bool trimValue) {
327
  int32_t len = pColumnInfoData->info.bytes;
2,147,483,647✔
328
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
329
    len = calcStrBytesByType(pColumnInfoData->info.type, (char*)pData);
2,147,483,647✔
330
    // if (pColumnInfoData->info.type == TSDB_DATA_TYPE_JSON) {
331
    //   len = getJsonValueLen(pData);
332
    // } else if (IS_STR_DATA_BLOB(pColumnInfoData->info.type)) {
333
    //   len = blobDataTLen(pData);
334
    // } else {
335
    //   len = varDataTLen(pData);
336
    // }
337
    if (pColumnInfoData->varmeta.allocLen < (capacity * numOfRows * len + pColumnInfoData->varmeta.length)) {
2,147,483,647✔
338
      int32_t code = colDataReserve(pColumnInfoData, (capacity * numOfRows * len + pColumnInfoData->varmeta.length));
479,082,441✔
339
      if (code != TSDB_CODE_SUCCESS) {
479,082,277✔
340
        return code;
×
341
      }
342
    }
343
  }
344

345
  return doCopyNItems(pColumnInfoData, currentRow, pData, len, numOfRows, trimValue);
2,147,483,647✔
346
}
347

348
void colDataSetNItemsNull(SColumnInfoData* pColumnInfoData, uint32_t currentRow, uint32_t numOfRows) {
327,350,359✔
349
  pColumnInfoData->hasNull = true;
327,350,359✔
350

351
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
327,350,359✔
352
    memset(&pColumnInfoData->varmeta.offset[currentRow], -1, sizeof(int32_t) * numOfRows);
51,607,126✔
353
  } else {
354
    if (numOfRows < 16) {
275,743,233✔
355
      for (int32_t i = 0; i < numOfRows; ++i) {
141,436,100✔
356
        colDataSetNull_f(pColumnInfoData->nullbitmap, currentRow + i);
72,083,385✔
357
      }
358
    } else {
359
      int32_t i = 0;
206,390,518✔
360
      for (; i < numOfRows; ++i) {
206,390,518✔
361
        if (BitPos(currentRow + i)) {
206,390,518✔
362
          colDataSetNull_f(pColumnInfoData->nullbitmap, currentRow + i);
×
363
        } else {
364
          break;
206,390,518✔
365
        }
366
      }
367

368
      int32_t bytes = (numOfRows - i) / 8;
206,390,518✔
369
      memset(&BMCharPos(pColumnInfoData->nullbitmap, currentRow + i), 0xFF, bytes);
206,390,518✔
370
      i += bytes * 8;
206,390,518✔
371

372
      for (; i < numOfRows; ++i) {
206,390,518✔
373
        colDataSetNull_f(pColumnInfoData->nullbitmap, currentRow + i);
×
374
      }
375
    }
376
  }
377
}
327,350,359✔
378

379
int32_t colDataCopyAndReassign(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData,
1,460,687✔
380
                               uint32_t numOfRows) {
381
  int32_t code = colDataSetVal(pColumnInfoData, currentRow, pData, false);
1,460,687✔
382
  if (code) {
1,460,687✔
383
    return code;
×
384
  }
385

386
  if (numOfRows > 1) {
1,460,687✔
387
    int32_t* pOffset = pColumnInfoData->varmeta.offset;
729,175✔
388
    memset(&pOffset[currentRow + 1], pOffset[currentRow], sizeof(pOffset[0]) * (numOfRows - 1));
729,175✔
389
    pColumnInfoData->reassigned = true;
729,175✔
390
  }
391

392
  return code;
1,460,687✔
393
}
394

395
int32_t colDataCopyNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t numOfRows,
2,150,087✔
396
                          bool isNull) {
397
  int32_t len = pColumnInfoData->info.bytes;
2,150,087✔
398
  if (isNull) {
2,150,087✔
399
    colDataSetNItemsNull(pColumnInfoData, currentRow, numOfRows);
5,040✔
400
    pColumnInfoData->hasNull = true;
5,040✔
401
    return 0;
5,040✔
402
  }
403

404
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,145,047✔
405
    return colDataCopyAndReassign(pColumnInfoData, currentRow, pData, numOfRows);
1,460,687✔
406
  } else {
407
    int32_t  colBytes = pColumnInfoData->info.bytes;
684,360✔
408
    int32_t  colOffset = currentRow * colBytes;
684,360✔
409
    uint32_t num = 1;
684,360✔
410

411
    void* pStart = pColumnInfoData->pData + colOffset;
684,360✔
412
    memcpy(pStart, pData, colBytes);
684,360✔
413
    colOffset += num * colBytes;
684,360✔
414

415
    while (num < numOfRows) {
1,733,966✔
416
      int32_t maxNum = num << 1;
1,049,606✔
417
      int32_t tnum = maxNum > numOfRows ? (numOfRows - num) : num;
1,049,606✔
418

419
      memcpy(pColumnInfoData->pData + colOffset, pStart, tnum * colBytes);
1,049,606✔
420
      colOffset += tnum * colBytes;
1,049,606✔
421
      num += tnum;
1,049,606✔
422
    }
423
  }
424

425
  return TSDB_CODE_SUCCESS;
684,360✔
426
}
427

428
static void doBitmapMerge(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, const SColumnInfoData* pSource,
713,341,974✔
429
                          int32_t numOfRow2) {
430
  if (numOfRow2 <= 0) return;
713,341,974✔
431

432
  uint32_t total = numOfRow1 + numOfRow2;
713,341,974✔
433

434
  uint32_t remindBits = BitPos(numOfRow1);
713,341,974✔
435
  uint32_t shiftBits = 8 - remindBits;
713,341,974✔
436

437
  if (remindBits == 0) {  // no need to shift bits of bitmap
713,341,974✔
438
    memcpy(pColumnInfoData->nullbitmap + BitmapLen(numOfRow1), pSource->nullbitmap, BitmapLen(numOfRow2));
403,621,433✔
439
    return;
403,615,300✔
440
  }
441

442
  uint8_t* p = (uint8_t*)pSource->nullbitmap;
309,720,541✔
443
  pColumnInfoData->nullbitmap[BitmapLen(numOfRow1) - 1] &= (0B11111111 << shiftBits);  // clear remind bits
309,778,787✔
444
  pColumnInfoData->nullbitmap[BitmapLen(numOfRow1) - 1] |= (p[0] >> remindBits);       // copy remind bits
309,825,009✔
445

446
  if (BitmapLen(numOfRow1) == BitmapLen(total)) {
309,824,817✔
447
    return;
102,895,205✔
448
  }
449

450
  int32_t len = BitmapLen(numOfRow2);
206,929,612✔
451
  int32_t i = 0;
206,929,612✔
452

453
  uint8_t* start = (uint8_t*)&pColumnInfoData->nullbitmap[BitmapLen(numOfRow1)];
206,929,612✔
454
  int32_t  overCount = BitmapLen(total) - BitmapLen(numOfRow1);
206,929,134✔
455
  memset(start, 0, overCount);
206,929,134✔
456
  while (i < len) {  // size limit of pSource->nullbitmap
2,147,483,647✔
457
    if (i >= 1) {
2,147,483,647✔
458
      start[i - 1] |= (p[i] >> remindBits);  // copy remind bits
2,147,483,647✔
459
    }
460

461
    if (i >= overCount) {  // size limit of pColumnInfoData->nullbitmap
2,147,483,647✔
462
      return;
98,248,631✔
463
    }
464

465
    start[i] |= (p[i] << shiftBits);  // copy shift bits
2,147,483,647✔
466
    i += 1;
2,147,483,647✔
467
  }
468
}
469

470
int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int32_t* capacity,
956,878,762✔
471
                        const SColumnInfoData* pSource, int32_t numOfRow2) {
472
  if (pColumnInfoData->info.type != pSource->info.type) {
956,878,762✔
473
    return TSDB_CODE_INVALID_PARA;
×
474
  }
475

476
  if (numOfRow2 == 0) {
956,936,447✔
477
    return TSDB_CODE_SUCCESS;
2,260✔
478
  }
479

480
  if (pSource->hasNull) {
956,934,187✔
481
    pColumnInfoData->hasNull = pSource->hasNull;
507,147,963✔
482
  }
483

484
  uint32_t finalNumOfRows = numOfRow1 + numOfRow2;
956,950,557✔
485
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
956,950,557✔
486
    // Handle the bitmap
487
    if (finalNumOfRows > (*capacity)) {
243,530,794✔
488
      char* p = taosMemoryRealloc(pColumnInfoData->varmeta.offset, sizeof(int32_t) * (numOfRow1 + numOfRow2));
183,403,980✔
489
      if (p == NULL) {
183,409,264✔
490
        return terrno;
×
491
      }
492

493
      *capacity = finalNumOfRows;
183,409,264✔
494
      pColumnInfoData->varmeta.offset = (int32_t*)p;
183,408,625✔
495
    }
496

497
    for (int32_t i = 0; i < numOfRow2; ++i) {
2,147,483,647✔
498
      if (pSource->varmeta.offset[i] == -1) {
2,147,483,647✔
499
        pColumnInfoData->varmeta.offset[i + numOfRow1] = -1;
2,147,483,647✔
500
      } else {
501
        pColumnInfoData->varmeta.offset[i + numOfRow1] = pSource->varmeta.offset[i] + pColumnInfoData->varmeta.length;
2,147,483,647✔
502
      }
503
    }
504

505
    // copy data
506
    uint32_t len = pSource->varmeta.length;
244,780,959✔
507
    uint32_t oldLen = pColumnInfoData->varmeta.length;
243,521,990✔
508
    if (pColumnInfoData->varmeta.allocLen < len + oldLen) {
243,519,680✔
509
      char* tmp = taosMemoryRealloc(pColumnInfoData->pData, len + oldLen);
181,491,807✔
510
      if (tmp == NULL) {
181,486,897✔
511
        return terrno;
×
512
      }
513

514
      pColumnInfoData->pData = tmp;
181,486,897✔
515
      pColumnInfoData->varmeta.allocLen = len + oldLen;
181,488,853✔
516
    }
517

518
    if (pColumnInfoData->pData && pSource->pData) {  // TD-20382
243,520,003✔
519
      memcpy(pColumnInfoData->pData + oldLen, pSource->pData, len);
229,273,937✔
520
    }
521
    pColumnInfoData->varmeta.length = len + oldLen;
243,510,206✔
522
  } else {
523
    if (finalNumOfRows > (*capacity)) {
713,419,190✔
524
      // all data may be null, when the pColumnInfoData->info.type == 0, bytes == 0;
525
      char* tmp = taosMemoryRealloc(pColumnInfoData->pData, finalNumOfRows * pColumnInfoData->info.bytes);
526,318,853✔
526
      if (tmp == NULL) {
526,303,590✔
527
        return terrno;
×
528
      }
529

530
      pColumnInfoData->pData = tmp;
526,303,590✔
531
      if (BitmapLen(numOfRow1) < BitmapLen(finalNumOfRows)) {
526,305,787✔
532
        char* btmp = taosMemoryRealloc(pColumnInfoData->nullbitmap, BitmapLen(finalNumOfRows));
466,702,559✔
533
        if (btmp == NULL) {
466,706,566✔
534
          return terrno;
×
535
        }
536
        uint32_t extend = BitmapLen(finalNumOfRows) - BitmapLen(numOfRow1);
466,706,566✔
537
        memset(btmp + BitmapLen(numOfRow1), 0, extend);
466,706,566✔
538
        pColumnInfoData->nullbitmap = btmp;
466,704,292✔
539
      }
540

541
      *capacity = finalNumOfRows;
526,311,783✔
542
    }
543

544
    doBitmapMerge(pColumnInfoData, numOfRow1, pSource, numOfRow2);
713,372,455✔
545

546
    if (pSource->pData) {
713,405,391✔
547
      int32_t offset = pColumnInfoData->info.bytes * numOfRow1;
713,426,079✔
548
      memcpy(pColumnInfoData->pData + offset, pSource->pData, pSource->info.bytes * numOfRow2);
713,427,567✔
549
    }
550
  }
551

552
  return TSDB_CODE_SUCCESS;
956,861,490✔
553
}
554

555
int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* pSource, int32_t numOfRows,
2,147,483,647✔
556
                      const SDataBlockInfo* pBlockInfo) {
557
  if (pColumnInfoData->info.type != pSource->info.type || (pBlockInfo != NULL && pBlockInfo->capacity < numOfRows)) {
2,147,483,647✔
558
    return TSDB_CODE_INVALID_PARA;
×
559
  }
560

561
  if (numOfRows <= 0) {
2,147,483,647✔
562
    return numOfRows;
73,292,481✔
563
  }
564

565
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
566
    int32_t newLen = pSource->varmeta.length;
1,791,474,472✔
567
    memcpy(pColumnInfoData->varmeta.offset, pSource->varmeta.offset, sizeof(int32_t) * numOfRows);
1,791,253,704✔
568
    if (pColumnInfoData->varmeta.allocLen < newLen) {
1,791,264,005✔
569
      char* tmp = taosMemoryRealloc(pColumnInfoData->pData, newLen);
1,153,705,580✔
570
      if (tmp == NULL) {
1,153,632,339✔
571
        return terrno;
×
572
      }
573

574
      pColumnInfoData->pData = tmp;
1,153,632,339✔
575
      pColumnInfoData->varmeta.allocLen = newLen;
1,153,632,343✔
576
    }
577

578
    pColumnInfoData->varmeta.length = newLen;
1,791,236,012✔
579
    if (pColumnInfoData->pData != NULL && pSource->pData != NULL) {
1,791,220,609✔
580
      memcpy(pColumnInfoData->pData, pSource->pData, newLen);
1,626,734,224✔
581
    }
582
  } else {
583
    memcpy(pColumnInfoData->nullbitmap, pSource->nullbitmap, BitmapLen(numOfRows));
2,147,483,647✔
584
    if (pSource->pData != NULL) {
2,147,483,647✔
585
      memcpy(pColumnInfoData->pData, pSource->pData, pSource->info.bytes * numOfRows);
2,147,483,647✔
586
    }
587
  }
588

589
  pColumnInfoData->hasNull = pSource->hasNull;
2,147,483,647✔
590
  int16_t slotId = pColumnInfoData->info.slotId;
2,147,483,647✔
591
  pColumnInfoData->info = pSource->info;
2,147,483,647✔
592
  pColumnInfoData->info.slotId = slotId;
2,147,483,647✔
593
  return 0;
2,147,483,647✔
594
}
595

596
int32_t colDataAssignNRows(SColumnInfoData* pDst, int32_t dstIdx, const SColumnInfoData* pSrc, int32_t srcIdx,
1,386,887,076✔
597
                           int32_t numOfRows) {
598
  if (pDst->info.type != pSrc->info.type || pDst->info.bytes != pSrc->info.bytes || pSrc->reassigned) {
1,386,887,076✔
599
    return TSDB_CODE_INVALID_PARA;
×
600
  }
601

602
  if (numOfRows <= 0) {
1,386,913,869✔
603
    return numOfRows;
×
604
  }
605

606
  if (IS_VAR_DATA_TYPE(pDst->info.type)) {
1,611,919,690✔
607
    int32_t allLen = 0;
225,003,314✔
608
    void*   srcAddr = NULL;
225,003,314✔
609
    if (pSrc->hasNull) {
225,003,314✔
610
      for (int32_t i = 0; i < numOfRows; ++i) {
307,693,750✔
611
        if (colDataIsNull_var(pSrc, srcIdx + i)) {
157,114,429✔
612
          pDst->varmeta.offset[dstIdx + i] = -1;
21,399,375✔
613
          pDst->hasNull = true;
21,399,375✔
614
          continue;
21,399,375✔
615
        }
616

617
        char* pData = colDataGetVarData(pSrc, srcIdx + i);
135,715,054✔
618
        if (NULL == srcAddr) {
135,715,054✔
619
          srcAddr = pData;
129,196,326✔
620
        }
621
        int32_t dataLen = calcStrBytesByType(pSrc->info.type, pData);
135,715,054✔
622
        // if (pSrc->info.type == TSDB_DATA_TYPE_JSON) {
623
        //   dataLen = getJsonValueLen(pData);
624
        // } else if (IS_STR_DATA_BLOB(pSrc->info.type)) {
625
        //   dataLen = blobDataTLen(pData);
626
        // } else {
627
        //   dataLen = varDataTLen(pData);
628
        // }
629
        pDst->varmeta.offset[dstIdx + i] = pDst->varmeta.length + allLen;
135,715,054✔
630
        allLen += dataLen;
135,715,054✔
631
      }
632
    } else {
633
      for (int32_t i = 0; i < numOfRows; ++i) {
406,802,209✔
634
        char*   pData = colDataGetVarData(pSrc, srcIdx + i);
332,375,286✔
635
        int32_t dataLen = 0;
332,375,286✔
636
        if (pSrc->info.type == TSDB_DATA_TYPE_JSON) {
332,375,286✔
637
          dataLen = getJsonValueLen(pData);
11,788✔
638
        } else if (IS_STR_DATA_BLOB(pSrc->info.type)) {
332,363,498✔
639
          dataLen = blobDataTLen(pData);
×
640
        } else {
641
          dataLen = varDataTLen(pData);
332,363,498✔
642
        }
643
        pDst->varmeta.offset[dstIdx + i] = pDst->varmeta.length + allLen;
332,375,286✔
644
        allLen += dataLen;
332,375,286✔
645
      }
646
    }
647

648
    if (allLen > 0) {
225,006,244✔
649
      // copy data
650
      if (pDst->varmeta.allocLen < pDst->varmeta.length + allLen) {
203,623,249✔
651
        char* tmp = taosMemoryRealloc(pDst->pData, pDst->varmeta.length + allLen);
198,339,568✔
652
        if (tmp == NULL) {
198,339,568✔
653
          return terrno;
×
654
        }
655

656
        pDst->pData = tmp;
198,339,568✔
657
        pDst->varmeta.allocLen = pDst->varmeta.length + allLen;
198,339,568✔
658
      }
659
      if (pSrc->hasNull) {
203,623,249✔
660
        memcpy(pDst->pData + pDst->varmeta.length, srcAddr, allLen);
129,196,326✔
661
      } else {
662
        memcpy(pDst->pData + pDst->varmeta.length, colDataGetVarData(pSrc, srcIdx), allLen);
74,426,923✔
663
      }
664
      pDst->varmeta.length = pDst->varmeta.length + allLen;
203,622,403✔
665
    }
666
  } else {
667
    if (pSrc->hasNull) {
1,161,910,555✔
668
      if (BitPos(dstIdx) == BitPos(srcIdx)) {
628,359,021✔
669
        for (int32_t i = 0; i < numOfRows; ++i) {
635,255,339✔
670
          if (0 == BitPos(dstIdx) && (i + (1 << NBIT) <= numOfRows)) {
484,098,763✔
671
            BMCharPos(pDst->nullbitmap, dstIdx + i) = BMCharPos(pSrc->nullbitmap, srcIdx + i);
87,478,578✔
672
            if (BMCharPos(pDst->nullbitmap, dstIdx + i)) {
87,481,508✔
673
              pDst->hasNull = true;
255,082✔
674
            }
675
            i += (1 << NBIT) - 1;
87,482,094✔
676
          } else {
677
            if (colDataIsNull_f(pSrc, srcIdx + i)) {
396,620,185✔
678
              colDataSetNull_f(pDst->nullbitmap, dstIdx + i);
7,363,850✔
679
              pDst->hasNull = true;
7,363,850✔
680
            } else {
681
              colDataClearNull_f(pDst->nullbitmap, dstIdx + i);
389,836,475✔
682
            }
683
          }
684
        }
685
      } else {
686
        for (int32_t i = 0; i < numOfRows; ++i) {
1,540,757,607✔
687
          if (colDataIsNull_f(pSrc, srcIdx + i)) {
1,063,476,052✔
688
            colDataSetNull_f(pDst->nullbitmap, dstIdx + i);
44,749,659✔
689
            pDst->hasNull = true;
44,749,659✔
690
          } else {
691
            colDataClearNull_f(pDst->nullbitmap, dstIdx + i);
1,018,693,577✔
692
          }
693
        }
694
      }
695
    }
696

697
    if (pSrc->pData != NULL) {
1,161,990,251✔
698
      memcpy(pDst->pData + pDst->info.bytes * dstIdx, pSrc->pData + pSrc->info.bytes * srcIdx,
1,161,890,045✔
699
             pDst->info.bytes * numOfRows);
1,161,881,841✔
700
    }
701
  }
702

703
  return 0;
1,386,874,770✔
704
}
705

706
size_t blockDataGetNumOfCols(const SSDataBlock* pBlock) { return taosArrayGetSize(pBlock->pDataBlock); }
2,147,483,647✔
707

708
size_t blockDataGetNumOfRows(const SSDataBlock* pBlock) { return pBlock->info.rows; }
809,509,089✔
709

710
int32_t blockDataUpdateTsWindow(SSDataBlock* pDataBlock, int32_t tsColumnIndex) {
2,147,483,647✔
711
  if (pDataBlock == NULL || pDataBlock->info.rows <= 0 || pDataBlock->info.dataLoad == 0) {
2,147,483,647✔
712
    return 0;
210,299,118✔
713
  }
714

715
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
2,147,483,647✔
716
  if (numOfCols <= 0) {
2,147,483,647✔
717
    return 0;
84,617✔
718
  }
719

720
  int32_t index = (tsColumnIndex == -1) ? 0 : tsColumnIndex;
2,147,483,647✔
721

722
  SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, index);
2,147,483,647✔
723
  if (pColInfoData == NULL) {
2,147,483,647✔
724
    return 0;
×
725
  }
726

727
  if (pColInfoData->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
2,147,483,647✔
728
    return 0;
2,147,483,647✔
729
  }
730

731
  TSKEY skey = *(TSKEY*)colDataGetData(pColInfoData, 0);
1,279,221,656✔
732
  TSKEY ekey = *(TSKEY*)colDataGetData(pColInfoData, (pDataBlock->info.rows - 1));
1,279,178,867✔
733

734
  pDataBlock->info.window.skey = TMIN(skey, ekey);
1,279,121,990✔
735
  pDataBlock->info.window.ekey = TMAX(skey, ekey);
1,279,210,045✔
736

737
  return 0;
1,279,221,841✔
738
}
739

740
int32_t blockDataUpdatePkRange(SSDataBlock* pDataBlock, int32_t pkColumnIndex, bool asc) {
779,381,274✔
741
  if (pDataBlock == NULL || pDataBlock->info.rows <= 0 || pDataBlock->info.dataLoad == 0 || pkColumnIndex == -1) {
779,381,274✔
742
    return 0;
693,958,544✔
743
  }
744

745
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
85,456,459✔
746
  if (numOfCols <= 0) {
85,457,825✔
747
    return -1;
×
748
  }
749

750
  SDataBlockInfo*  pInfo = &pDataBlock->info;
85,457,825✔
751
  SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, pkColumnIndex);
85,458,509✔
752
  if (pColInfoData == NULL) {
85,456,451✔
753
    return terrno;
×
754
  }
755

756
  if (!IS_NUMERIC_TYPE(pColInfoData->info.type) && (pColInfoData->info.type != TSDB_DATA_TYPE_VARCHAR)) {
85,456,451✔
757
    return 0;
×
758
  }
759

760
  void* skey = colDataGetData(pColInfoData, 0);
85,436,510✔
761
  void* ekey = colDataGetData(pColInfoData, (pInfo->rows - 1));
85,443,412✔
762

763
  int64_t val = 0;
85,435,829✔
764
  if (asc) {
85,435,829✔
765
    if (IS_NUMERIC_TYPE(pColInfoData->info.type)) {
71,926,829✔
766
      GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, skey, typeGetTypeModFromColInfo(&pColInfoData->info));
45,028,583✔
767
      VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[0], val);
44,994,868✔
768
      GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, ekey, typeGetTypeModFromColInfo(&pColInfoData->info));
45,005,173✔
769
      VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[1], val);
45,000,364✔
770
    } else {  // todo refactor
771
      memcpy(pInfo->pks[0].pData, varDataVal(skey), varDataLen(skey));
26,919,569✔
772
      pInfo->pks[0].nData = varDataLen(skey);
26,916,832✔
773

774
      memcpy(pInfo->pks[1].pData, varDataVal(ekey), varDataLen(ekey));
26,926,461✔
775
      pInfo->pks[1].nData = varDataLen(ekey);
26,927,824✔
776
    }
777
  } else {
778
    if (IS_NUMERIC_TYPE(pColInfoData->info.type)) {
13,509,000✔
779
      GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, ekey, typeGetTypeModFromColInfo(&pColInfoData->info));
8,771,608✔
780
      VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[0], val);
8,764,723✔
781
      GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, skey, typeGetTypeModFromColInfo(&pColInfoData->info));
8,767,475✔
782
      VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[1], val);
8,763,349✔
783
    } else {  // todo refactor
784
      memcpy(pInfo->pks[0].pData, varDataVal(ekey), varDataLen(ekey));
4,745,666✔
785
      pInfo->pks[0].nData = varDataLen(ekey);
4,747,051✔
786

787
      memcpy(pInfo->pks[1].pData, varDataVal(skey), varDataLen(skey));
4,747,742✔
788
      pInfo->pks[1].nData = varDataLen(skey);
4,747,738✔
789
    }
790
  }
791

792
  return 0;
85,436,509✔
793
}
794

795
int32_t blockDataMerge(SSDataBlock* pDest, const SSDataBlock* pSrc) {
227,919,064✔
796
  int32_t code = 0;
227,919,064✔
797
  int32_t capacity = pDest->info.capacity;
227,919,064✔
798
  size_t  numOfCols = taosArrayGetSize(pDest->pDataBlock);
227,936,556✔
799
  for (int32_t i = 0; i < numOfCols; ++i) {
1,155,148,963✔
800
    SColumnInfoData* pCol2 = taosArrayGet(pDest->pDataBlock, i);
927,208,714✔
801
    SColumnInfoData* pCol1 = taosArrayGet(pSrc->pDataBlock, i);
927,212,301✔
802
    if (pCol1 == NULL || pCol2 == NULL) {
927,243,981✔
803
      return terrno;
221✔
804
    }
805

806
    capacity = pDest->info.capacity;
927,243,760✔
807
    int32_t ret = colDataMergeCol(pCol2, pDest->info.rows, &capacity, pCol1, pSrc->info.rows);
927,245,818✔
808
    if (ret < 0) {  // error occurs
927,197,524✔
809
      code = ret;
×
810
      return code;
×
811
    }
812
  }
813

814
  pDest->info.capacity = capacity;
227,940,249✔
815
  pDest->info.rows += pSrc->info.rows;
227,941,116✔
816
  return code;
227,941,217✔
817
}
818

819
void blockDataTransform(SSDataBlock* pDest, const SSDataBlock* pSrc) {
7,203,152✔
820
  size_t  numOfCols = taosArrayGetSize(pDest->pDataBlock);
7,203,152✔
821
  size_t  numOfColsSrc = taosArrayGetSize(pSrc->pDataBlock);
7,207,256✔
822
  for (int32_t i = 0; i < numOfCols; ++i) {
21,954,316✔
823
    SColumnInfoData* pCol1 = taosArrayGet(pDest->pDataBlock, i);
14,746,604✔
824
    for (int32_t j = 0; j < numOfColsSrc; ++j) {
23,384,951✔
825
      SColumnInfoData* pCol2 = taosArrayGet(pSrc->pDataBlock, j);
23,383,783✔
826
      if (pCol1->info.colId == pCol2->info.colId) {
23,388,371✔
827
        TSWAP(*pCol1, *pCol2);
14,750,224✔
828
        break;
14,750,224✔
829
      }
830
    }
831
  }
832

833
  pDest->info.rows = pSrc->info.rows;
7,207,712✔
834
  pDest->info.capacity = pSrc->info.rows;
7,207,940✔
835
}
7,206,344✔
836

837
int32_t blockDataMergeNRows(SSDataBlock* pDest, const SSDataBlock* pSrc, int32_t srcIdx, int32_t numOfRows) {
22,564,960✔
838
  int32_t code = 0, lino = 0;
22,564,960✔
839
  if (pDest->info.rows + numOfRows > pDest->info.capacity) {
22,564,960✔
840
    uError("block capacity %d not enough to merge %d rows, currRows:%" PRId64, pDest->info.capacity, numOfRows, pDest->info.rows);
×
841
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_PARA);
×
842
  }
843

844
  size_t numOfCols = taosArrayGetSize(pDest->pDataBlock);
22,564,960✔
845
  for (int32_t i = 0; i < numOfCols; ++i) {
77,300,136✔
846
    SColumnInfoData* pCol2 = taosArrayGet(pDest->pDataBlock, i);
54,735,599✔
847
    TSDB_CHECK_NULL(pCol2, code, lino, _exit, terrno);
54,735,599✔
848
    SColumnInfoData* pCol1 = taosArrayGet(pSrc->pDataBlock, i);
54,735,599✔
849
    TSDB_CHECK_NULL(pCol1, code, lino, _exit, terrno);
54,736,022✔
850

851
    TAOS_CHECK_EXIT(colDataAssignNRows(pCol2, pDest->info.rows, pCol1, srcIdx, numOfRows));
54,736,022✔
852
  }
853

854
  pDest->info.rows += numOfRows;
22,564,537✔
855

856
_exit:
22,564,537✔
857

858
  if (code) {
22,564,537✔
859
    uError("%s failed at line %d since %s", __FUNCTION__, lino, tstrerror(code));
×
860
  }
861
  
862
  return code;
22,564,537✔
863
}
864

865
void blockDataShrinkNRows(SSDataBlock* pBlock, int32_t numOfRows) {
×
866
  if (numOfRows == 0) {
×
867
    return;
×
868
  }
869

870
  if (numOfRows >= pBlock->info.rows) {
×
871
    blockDataCleanup(pBlock);
×
872
    return;
×
873
  }
874

875
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
×
876
  for (int32_t i = 0; i < numOfCols; ++i) {
×
877
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
×
878
    if (pCol == NULL) {
×
879
      continue;
×
880
    }
881

882
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
×
883
      pCol->varmeta.length = pCol->varmeta.offset[pBlock->info.rows - numOfRows];
×
884
      memset(pCol->varmeta.offset + pBlock->info.rows - numOfRows, 0, sizeof(*pCol->varmeta.offset) * numOfRows);
×
885
    } else {
886
      int32_t i = pBlock->info.rows - numOfRows;
×
887
      for (; i < pBlock->info.rows; ++i) {
×
888
        if (BitPos(i)) {
×
889
          colDataClearNull_f(pCol->nullbitmap, i);
×
890
        } else {
891
          break;
×
892
        }
893
      }
894

895
      int32_t bytes = (pBlock->info.rows - i) / 8;
×
896
      memset(&BMCharPos(pCol->nullbitmap, i), 0, bytes);
×
897
      i += bytes * 8;
×
898

899
      for (; i < pBlock->info.rows; ++i) {
×
900
        colDataClearNull_f(pCol->nullbitmap, i);
×
901
      }
902
    }
903
  }
904

905
  pBlock->info.rows -= numOfRows;
×
906
}
907

908
size_t blockDataGetSize(const SSDataBlock* pBlock) {
2,147,483,647✔
909
  size_t total = 0;
2,147,483,647✔
910
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
2,147,483,647✔
911
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
912
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
913
    if (pColInfoData == NULL) {
2,147,483,647✔
914
      continue;
×
915
    }
916

917
    total += colDataGetFullLength(pColInfoData, pBlock->info.rows);
2,147,483,647✔
918
  }
919

920
  return total;
2,147,483,647✔
921
}
922

923
// the number of tuples can be fit in one page.
924
// Actual data rows pluses the corresponding meta data must fit in one memory buffer of the given page size.
925
int32_t blockDataSplitRows(SSDataBlock* pBlock, bool hasVarCol, int32_t startIndex, int32_t* stopIndex,
52,549,189✔
926
                           int32_t pageSize) {
927
  size_t  numOfCols = taosArrayGetSize(pBlock->pDataBlock);
52,549,189✔
928
  int32_t numOfRows = pBlock->info.rows;
52,549,189✔
929

930
  int32_t bitmapChar = 1;
52,549,189✔
931

932
  size_t headerSize = sizeof(int32_t);
52,549,189✔
933
  size_t colHeaderSize = sizeof(int32_t) * numOfCols;
52,549,189✔
934

935
  // TODO speedup by checking if the whole page can fit in firstly.
936
  if (!hasVarCol) {
52,549,189✔
937
    size_t  rowSize = blockDataGetRowSize(pBlock);
×
938
    int32_t capacity = blockDataGetCapacityInRow(pBlock, pageSize, headerSize + colHeaderSize);
×
939
    if (capacity <= 0) {
×
940
      return terrno;
×
941
    }
942

943
    *stopIndex = startIndex + capacity - 1;
×
944
    if (*stopIndex >= numOfRows) {
×
945
      *stopIndex = numOfRows - 1;
×
946
    }
947

948
    return TSDB_CODE_SUCCESS;
×
949
  }
950
  // iterate the rows that can be fit in this buffer page
951
  int32_t size = (headerSize + colHeaderSize);
52,549,189✔
952
  for (int32_t j = startIndex; j < numOfRows; ++j) {
2,147,483,647✔
953
    for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
954
      SColumnInfoData* pColInfoData = TARRAY_GET_ELEM(pBlock->pDataBlock, i);
2,147,483,647✔
955
      if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
956
        if (pColInfoData->varmeta.offset[j] != -1) {
2,147,483,647✔
957
          char* p = colDataGetData(pColInfoData, j);
2,147,483,647✔
958
          if (IS_STR_DATA_BLOB(pColInfoData->info.type)) {
2,147,483,647✔
959
            size += blobDataTLen(p);
×
960
          } else {
961
            size += varDataTLen(p);
2,147,483,647✔
962
          }
963
        }
964

965
        size += sizeof(pColInfoData->varmeta.offset[0]);
2,147,483,647✔
966
      } else {
967
        size += pColInfoData->info.bytes;
2,147,483,647✔
968

969
        if (((j - startIndex) & 0x07) == 0) {
2,147,483,647✔
970
          size += 1;  // the space for null bitmap
2,147,483,647✔
971
        }
972
      }
973
    }
974

975
    if (size > pageSize) {  // pageSize must be able to hold one row
2,147,483,647✔
976
      *stopIndex = j - 1;
52,495,157✔
977
      if (*stopIndex < startIndex) {
52,495,157✔
978
        return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
979
      }
980

981
      return TSDB_CODE_SUCCESS;
52,495,157✔
982
    }
983
  }
984

985
  // all fit in
986
  *stopIndex = numOfRows - 1;
54,032✔
987
  return TSDB_CODE_SUCCESS;
54,032✔
988
}
989

990
int32_t blockDataExtractBlock(SSDataBlock* pBlock, int32_t startIndex, int32_t rowCount, SSDataBlock** pResBlock) {
60,066,886✔
991
  int32_t code = 0;
60,066,886✔
992
  QRY_PARAM_CHECK(pResBlock);
60,066,886✔
993

994
  if (pBlock == NULL || startIndex < 0 || rowCount > pBlock->info.rows || rowCount + startIndex > pBlock->info.rows) {
60,066,886✔
995
    return TSDB_CODE_INVALID_PARA;
×
996
  }
997

998
  SSDataBlock* pDst = NULL;
60,067,304✔
999
  code = createOneDataBlock(pBlock, false, &pDst);
60,067,304✔
1000
  if (code) {
60,067,304✔
1001
    return code;
×
1002
  }
1003

1004
  code = blockDataEnsureCapacity(pDst, rowCount);
60,067,304✔
1005
  if (code) {
60,067,304✔
1006
    blockDataDestroy(pDst);
×
1007
    return code;
×
1008
  }
1009

1010
  /* may have disorder varchar data, TODO
1011
    for (int32_t i = 0; i < numOfCols; ++i) {
1012
      SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, i);
1013
      SColumnInfoData* pDstCol = taosArrayGet(pDst->pDataBlock, i);
1014

1015
      colDataAssignNRows(pDstCol, 0, pColData, startIndex, rowCount);
1016
    }
1017
  */
1018

1019
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
60,067,304✔
1020
  for (int32_t i = 0; i < numOfCols; ++i) {
814,354,903✔
1021
    SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, i);
754,287,599✔
1022
    SColumnInfoData* pDstCol = taosArrayGet(pDst->pDataBlock, i);
754,287,599✔
1023
    if (pColData == NULL || pDstCol == NULL) {
754,287,599✔
1024
      continue;
×
1025
    }
1026

1027
    for (int32_t j = startIndex; j < (startIndex + rowCount); ++j) {
2,147,483,647✔
1028
      bool isNull = false;
2,147,483,647✔
1029
      if (pBlock->pBlockAgg == NULL) {
2,147,483,647✔
1030
        isNull = colDataIsNull_s(pColData, j);
2,147,483,647✔
1031
      } else {
UNCOV
1032
        isNull = colDataIsNull(pColData, pBlock->info.rows, j, &pBlock->pBlockAgg[i]);
×
1033
      }
1034

1035
      if (isNull) {
2,147,483,647✔
1036
        colDataSetNULL(pDstCol, j - startIndex);
2,147,483,647✔
1037
      } else {
1038
        char* p = colDataGetData(pColData, j);
2,147,483,647✔
1039
        code = colDataSetVal(pDstCol, j - startIndex, p, false);
2,147,483,647✔
1040
        if (code) {
2,147,483,647✔
1041
          break;
×
1042
        }
1043
      }
1044
    }
1045
  }
1046

1047
  pDst->info.rows = rowCount;
60,067,304✔
1048
  *pResBlock = pDst;
60,067,304✔
1049
  return code;
60,067,304✔
1050
}
1051

1052
/**
1053
 *
1054
 * +------------------+---------------------------------------------+
1055
 * |the number of rows|                    column #1                |
1056
 * |    (4 bytes)     |------------+-----------------------+--------+
1057
 * |                  | null bitmap| column length(4bytes) | values |
1058
 * +------------------+------------+-----------------------+--------+
1059
 * @param buf
1060
 * @param pBlock
1061
 * @return
1062
 */
1063
int32_t blockDataToBuf(char* buf, const SSDataBlock* pBlock) {
95,359,553✔
1064
  // write the number of rows
1065
  *(uint32_t*)buf = pBlock->info.rows;
95,359,553✔
1066

1067
  size_t  numOfCols = taosArrayGetSize(pBlock->pDataBlock);
95,361,540✔
1068
  int32_t numOfRows = pBlock->info.rows;
95,359,691✔
1069

1070
  char* pStart = buf + sizeof(uint32_t);
95,360,378✔
1071

1072
  for (int32_t i = 0; i < numOfCols; ++i) {
948,683,406✔
1073
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
853,325,456✔
1074
    if (pCol == NULL) {
853,325,906✔
1075
      continue;
×
1076
    }
1077

1078
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
853,325,906✔
1079
      memcpy(pStart, pCol->varmeta.offset, numOfRows * sizeof(int32_t));
170,737,486✔
1080
      pStart += numOfRows * sizeof(int32_t);
170,737,481✔
1081
    } else {
1082
      memcpy(pStart, pCol->nullbitmap, BitmapLen(numOfRows));
682,592,636✔
1083
      pStart += BitmapLen(pBlock->info.rows);
682,596,237✔
1084
    }
1085

1086
    uint32_t dataSize = colDataGetLength(pCol, numOfRows);
853,329,794✔
1087

1088
    *(int32_t*)pStart = dataSize;
853,329,235✔
1089
    pStart += sizeof(int32_t);
853,327,488✔
1090

1091
    if (pCol->reassigned && IS_VAR_DATA_TYPE(pCol->info.type)) {
853,327,513✔
1092
      for (int32_t row = 0; row < numOfRows; ++row) {
×
1093
        char*   pColData = pCol->pData + pCol->varmeta.offset[row];
×
1094
        int32_t colSize = calcStrBytesByType(pCol->info.type, pColData);
×
1095
        // if (pCol->info.type == TSDB_DATA_TYPE_JSON) {
1096
        //   colSize = getJsonValueLen(pColData);
1097
        // } else if (IS_STR_DATA_BLOB(pCol->info.type)) {
1098
        //   colSize = blobDataTLen(pColData);
1099
        // } else {
1100
        //   colSize = varDataTLen(pColData);
1101
        // }
1102
        memcpy(pStart, pColData, colSize);
×
1103
        pStart += colSize;
×
1104
      }
1105
    } else {
1106
      if (dataSize != 0) {
853,328,786✔
1107
        // ubsan reports error if pCol->pData==NULL && dataSize==0
1108
        memcpy(pStart, pCol->pData, dataSize);
835,546,953✔
1109
      }
1110
      pStart += dataSize;
853,328,094✔
1111
    }
1112
  }
1113

1114
  return 0;
95,357,950✔
1115
}
1116

1117
int32_t blockDataFromBuf(SSDataBlock* pBlock, const char* buf) {
93,343,099✔
1118
  int32_t numOfRows = *(int32_t*)buf;
93,343,099✔
1119
  if (numOfRows == 0) {
93,343,099✔
1120
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1121
  }
1122
  int32_t code = blockDataEnsureCapacity(pBlock, numOfRows);
93,343,099✔
1123
  if (code) {
93,342,246✔
1124
    return code;
×
1125
  }
1126

1127
  pBlock->info.rows = numOfRows;
93,342,246✔
1128
  size_t      numOfCols = taosArrayGetSize(pBlock->pDataBlock);
93,342,246✔
1129
  const char* pStart = buf + sizeof(uint32_t);
93,343,658✔
1130

1131
  for (int32_t i = 0; i < numOfCols; ++i) {
818,743,299✔
1132
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
725,399,810✔
1133
    if (pCol == NULL) {
725,399,671✔
1134
      continue;
×
1135
    }
1136

1137
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
725,399,671✔
1138
      size_t metaSize = pBlock->info.rows * sizeof(int32_t);
133,825,508✔
1139
      memcpy(pCol->varmeta.offset, pStart, metaSize);
133,824,217✔
1140
      pStart += metaSize;
133,824,217✔
1141
    } else {
1142
      memcpy(pCol->nullbitmap, pStart, BitmapLen(pBlock->info.rows));
591,576,834✔
1143
      pStart += BitmapLen(pBlock->info.rows);
591,576,992✔
1144
    }
1145

1146
    int32_t colLength = *(int32_t*)pStart;
725,402,173✔
1147
    pStart += sizeof(int32_t);
725,402,871✔
1148

1149
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
725,402,457✔
1150
      if (pCol->varmeta.allocLen < colLength) {
133,826,422✔
1151
        char* tmp = taosMemoryRealloc(pCol->pData, colLength);
3,067,224✔
1152
        if (tmp == NULL) {
3,067,224✔
1153
          return terrno;
×
1154
        }
1155

1156
        pCol->pData = tmp;
3,067,224✔
1157
        pCol->varmeta.allocLen = colLength;
3,067,224✔
1158
      }
1159

1160
      pCol->varmeta.length = colLength;
133,824,217✔
1161
      if (pCol->varmeta.length > pCol->varmeta.allocLen) {
133,824,217✔
1162
        return TSDB_CODE_FAILED;
×
1163
      }
1164
    }
1165
    if (colLength != 0) {
725,401,413✔
1166
      // ubsan reports error if colLength==0 && pCol->pData == 0
1167
      memcpy(pCol->pData, pStart, colLength);
712,660,094✔
1168
    }
1169
    pStart += colLength;
725,401,413✔
1170
  }
1171

1172
  return TSDB_CODE_SUCCESS;
93,343,489✔
1173
}
1174

1175
static bool colDataIsNNull(const SColumnInfoData* pColumnInfoData, int32_t startIndex, uint32_t nRows) {
2,147,483,647✔
1176
  if (!pColumnInfoData->hasNull) {
2,147,483,647✔
1177
    return false;
×
1178
  }
1179

1180
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
1181
    for (int32_t i = startIndex; i < nRows; ++i) {
900,718,753✔
1182
      if (!colDataIsNull_var(pColumnInfoData, i)) {
900,719,267✔
1183
        return false;
697,301,842✔
1184
      }
1185
    }
1186
  } else {
1187
    if (pColumnInfoData->nullbitmap == NULL) {
2,126,031,368✔
1188
      return false;
×
1189
    }
1190

1191
    for (int32_t i = startIndex; i < nRows; ++i) {
2,147,483,647✔
1192
      if (!colDataIsNull_f(pColumnInfoData, i)) {
2,147,483,647✔
1193
        return false;
1,708,904,386✔
1194
      }
1195
    }
1196
  }
1197

1198
  return true;
417,184,686✔
1199
}
1200

1201
// todo remove this
1202
int32_t blockDataFromBuf1(SSDataBlock* pBlock, const char* buf, size_t capacity) {
285,424,659✔
1203
  pBlock->info.rows = *(int32_t*)buf;
285,424,659✔
1204
  pBlock->info.id.groupId = *(uint64_t*)(buf + sizeof(int32_t));
285,426,201✔
1205

1206
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
285,428,019✔
1207

1208
  const char* pStart = buf + sizeof(uint32_t) + sizeof(uint64_t);
285,428,291✔
1209

1210
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
1211
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
1212
    if (pCol == NULL) {
2,147,483,647✔
1213
      continue;
×
1214
    }
1215

1216
    pCol->hasNull = true;
2,147,483,647✔
1217

1218
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
2,147,483,647✔
1219
      size_t metaSize = capacity * sizeof(int32_t);
812,203,014✔
1220
      memcpy(pCol->varmeta.offset, pStart, metaSize);
812,203,014✔
1221
      pStart += metaSize;
812,296,458✔
1222
    } else {
1223
      memcpy(pCol->nullbitmap, pStart, BitmapLen(capacity));
2,126,380,745✔
1224
      pStart += BitmapLen(capacity);
2,126,408,169✔
1225
    }
1226

1227
    int32_t colLength = *(int32_t*)pStart;
2,147,483,647✔
1228
    pStart += sizeof(int32_t);
2,147,483,647✔
1229

1230
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
2,147,483,647✔
1231
      if (pCol->varmeta.allocLen < colLength) {
812,305,591✔
1232
        char* tmp = taosMemoryRealloc(pCol->pData, colLength);
1,546,473✔
1233
        if (tmp == NULL) {
1,546,473✔
1234
          return terrno;
×
1235
        }
1236

1237
        pCol->pData = tmp;
1,546,473✔
1238
        pCol->varmeta.allocLen = colLength;
1,546,473✔
1239
      }
1240

1241
      pCol->varmeta.length = colLength;
812,306,324✔
1242
      if (pCol->varmeta.length > pCol->varmeta.allocLen) {
812,304,782✔
1243
        return TSDB_CODE_FAILED;
×
1244
      }
1245
    }
1246

1247
    if (colLength != 0 && !colDataIsNNull(pCol, 0, pBlock->info.rows)) {
2,147,483,647✔
1248
      memcpy(pCol->pData, pStart, colLength);
2,147,483,647✔
1249
    }
1250

1251
    pStart += blockDataGetPagedColumnReservedBytes(pCol) * capacity;
2,147,483,647✔
1252
  }
1253

1254
  return TSDB_CODE_SUCCESS;
285,430,694✔
1255
}
1256

1257
size_t blockDataGetRowSize(SSDataBlock* pBlock) {
2,147,483,647✔
1258
  if (pBlock->info.rowSize == 0) {
2,147,483,647✔
1259
    size_t rowSize = 0;
×
1260

1261
    size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
×
1262
    for (int32_t i = 0; i < numOfCols; ++i) {
×
1263
      SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
×
1264
      if (pColInfo == NULL) {
×
1265
        continue;
×
1266
      }
1267

1268
      rowSize += pColInfo->info.bytes;
×
1269
    }
1270

1271
    pBlock->info.rowSize = rowSize;
×
1272
  }
1273

1274
  return pBlock->info.rowSize;
2,147,483,647✔
1275
}
1276

1277
size_t blockDataGetSerialMetaSizeImpl(uint32_t numOfCols, bool internal) {
2,147,483,647✔
1278
  // | version | total length | total rows | blankFull | total columns | flag seg| block group id | column schema
1279
  // | each column length
1280
  // internal: | scanFlag baseGid |
1281
  return sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(bool) + sizeof(int32_t) + sizeof(int32_t) +
1282
         sizeof(uint64_t) + numOfCols * (sizeof(int8_t) + sizeof(int32_t)) + numOfCols * sizeof(int32_t) + 
2,147,483,647✔
1283
         (internal ? (sizeof(uint8_t) + sizeof(uint64_t) + numOfCols * sizeof(int16_t)) : 0);
2,147,483,647✔
1284
}
1285

1286
size_t blockDataGetSerialMetaSizeInternal(uint32_t numOfCols) {
96,066,360✔
1287
  return blockDataGetSerialMetaSizeImpl(numOfCols, true);
96,066,360✔
1288
}
1289

1290
/**
1291
 * @refitem blockDataToBuf for the meta size
1292
 * @param pBlock
1293
 * @return
1294
 */
1295
size_t blockDataGetSerialMetaSize(uint32_t numOfCols) {
2,147,483,647✔
1296
  return blockDataGetSerialMetaSizeImpl(numOfCols, false);
2,147,483,647✔
1297
}
1298

1299
double blockDataGetSerialRowSize(const SSDataBlock* pBlock) {
10,137,617✔
1300
  double rowSize = 0;
10,137,617✔
1301

1302
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
10,137,617✔
1303
  for (int32_t i = 0; i < numOfCols; ++i) {
40,876,739✔
1304
    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
30,737,748✔
1305
    if (pColInfo == NULL) {
30,733,958✔
1306
      continue;
×
1307
    }
1308

1309
    rowSize += pColInfo->info.bytes;
30,733,958✔
1310
    if (IS_VAR_DATA_TYPE(pColInfo->info.type)) {
30,734,645✔
1311
      rowSize += sizeof(int32_t);
2,314,080✔
1312
    } else {
1313
      rowSize += 1 / 8.0;  // one bit for each record
28,425,479✔
1314
    }
1315
  }
1316

1317
  return rowSize;
10,138,991✔
1318
}
1319

1320
typedef struct SSDataBlockSortHelper {
1321
  SArray*      orderInfo;  // SArray<SBlockOrderInfo>
1322
  SSDataBlock* pDataBlock;
1323
} SSDataBlockSortHelper;
1324

1325
int32_t dataBlockCompar(const void* p1, const void* p2, const void* param) {
2,147,483,647✔
1326
  const SSDataBlockSortHelper* pHelper = (const SSDataBlockSortHelper*)param;
2,147,483,647✔
1327

1328
  SSDataBlock* pDataBlock = pHelper->pDataBlock;
2,147,483,647✔
1329

1330
  int32_t left = *(int32_t*)p1;
2,147,483,647✔
1331
  int32_t right = *(int32_t*)p2;
2,147,483,647✔
1332

1333
  SArray* pInfo = pHelper->orderInfo;
2,147,483,647✔
1334

1335
  for (int32_t i = 0; i < pInfo->size; ++i) {
2,147,483,647✔
1336
    SBlockOrderInfo* pOrder = TARRAY_GET_ELEM(pInfo, i);
2,147,483,647✔
1337
    SColumnInfoData* pColInfoData = pOrder->pColData;  // TARRAY_GET_ELEM(pDataBlock->pDataBlock, pOrder->colIndex);
2,147,483,647✔
1338

1339
    if (pColInfoData->hasNull) {
2,147,483,647✔
1340
      bool leftNull = colDataIsNull(pColInfoData, pDataBlock->info.rows, left, NULL);
2,147,483,647✔
1341
      bool rightNull = colDataIsNull(pColInfoData, pDataBlock->info.rows, right, NULL);
2,147,483,647✔
1342
      if (leftNull && rightNull) {
2,147,483,647✔
1343
        continue;  // continue to next slot
2,147,483,647✔
1344
      }
1345

1346
      if (rightNull) {
2,147,483,647✔
1347
        return pOrder->nullFirst ? 1 : -1;
418,862,312✔
1348
      }
1349

1350
      if (leftNull) {
2,147,483,647✔
1351
        return pOrder->nullFirst ? -1 : 1;
742,285,709✔
1352
      }
1353
    }
1354

1355
    void* left1 = colDataGetData(pColInfoData, left);
2,147,483,647✔
1356
    void* right1 = colDataGetData(pColInfoData, right);
2,147,483,647✔
1357
    if (pColInfoData->info.type == TSDB_DATA_TYPE_JSON) {
2,147,483,647✔
1358
      if (tTagIsJson(left1) || tTagIsJson(right1)) {
143,872✔
1359
        terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
8,704✔
1360
        return 0;
8,704✔
1361
      }
1362
    }
1363

1364
    __compar_fn_t fn;
1365
    if (pOrder->compFn) {
2,147,483,647✔
1366
      fn = pOrder->compFn;
2,147,483,647✔
1367
    } else {
1368
      fn = getKeyComparFunc(pColInfoData->info.type, pOrder->order);
×
1369
    }
1370

1371
    int ret = fn(left1, right1);
2,147,483,647✔
1372
    if (ret == 0) {
2,147,483,647✔
1373
      continue;
2,147,483,647✔
1374
    } else {
1375
      return ret;
2,147,483,647✔
1376
    }
1377
  }
1378

1379
  return 0;
2,147,483,647✔
1380
}
1381

1382
static void blockDataAssign(SColumnInfoData* pCols, const SSDataBlock* pDataBlock, const int32_t* index) {
23,243,167✔
1383
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
23,243,167✔
1384
  for (int32_t i = 0; i < numOfCols; ++i) {
101,161,070✔
1385
    SColumnInfoData* pDst = &pCols[i];
77,915,963✔
1386
    SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i);
77,915,212✔
1387
    if (pSrc == NULL) {
77,915,437✔
1388
      continue;
×
1389
    }
1390

1391
    if (IS_VAR_DATA_TYPE(pSrc->info.type)) {
77,915,437✔
1392
      if (pSrc->varmeta.length != 0) {
25,130,778✔
1393
        memcpy(pDst->pData, pSrc->pData, pSrc->varmeta.length);
24,458,805✔
1394
      }
1395
      pDst->varmeta.length = pSrc->varmeta.length;
25,132,459✔
1396

1397
      for (int32_t j = 0; j < pDataBlock->info.rows; ++j) {
2,147,483,647✔
1398
        pDst->varmeta.offset[j] = pSrc->varmeta.offset[index[j]];
2,147,483,647✔
1399
      }
1400
    } else {
1401
      for (int32_t j = 0; j < pDataBlock->info.rows; ++j) {
2,147,483,647✔
1402
        if (colDataIsNull_f(pSrc, index[j])) {
2,147,483,647✔
1403
          colDataSetNull_f_s(pDst, j);
2,147,483,647✔
1404
          continue;
2,147,483,647✔
1405
        }
1406
        memcpy(pDst->pData + j * pDst->info.bytes, pSrc->pData + index[j] * pDst->info.bytes, pDst->info.bytes);
2,147,483,647✔
1407
      }
1408
    }
1409
  }
1410
}
23,245,107✔
1411

1412
static int32_t createHelpColInfoData(const SSDataBlock* pDataBlock, SColumnInfoData** ppCols) {
23,244,683✔
1413
  int32_t code = 0;
23,244,683✔
1414
  int32_t rows = pDataBlock->info.capacity;
23,244,683✔
1415
  size_t  numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
23,244,259✔
1416
  int32_t i = 0;
23,244,683✔
1417

1418
  *ppCols = NULL;
23,244,683✔
1419

1420
  SColumnInfoData* pCols = taosMemoryCalloc(numOfCols, sizeof(SColumnInfoData));
23,244,683✔
1421
  if (pCols == NULL) {
23,244,265✔
1422
    return terrno;
×
1423
  }
1424

1425
  for (i = 0; i < numOfCols; ++i) {
101,159,227✔
1426
    SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, i);
77,915,756✔
1427
    if (pColInfoData == NULL) {
77,916,029✔
1428
      continue;
×
1429
    }
1430

1431
    pCols[i].info = pColInfoData->info;
77,916,029✔
1432
    if (IS_VAR_DATA_TYPE(pCols[i].info.type)) {
77,916,597✔
1433
      pCols[i].varmeta.offset = taosMemoryCalloc(rows, sizeof(int32_t));
25,134,099✔
1434
      pCols[i].pData = taosMemoryCalloc(1, pColInfoData->varmeta.length);
25,131,934✔
1435
      if (pCols[i].varmeta.offset == NULL || pCols[i].pData == NULL) {
25,132,459✔
1436
        code = terrno;
×
1437
        taosMemoryFree(pCols[i].varmeta.offset);
×
1438
        taosMemoryFree(pCols[i].pData);
×
1439
        goto _error;
×
1440
      }
1441

1442
      pCols[i].varmeta.length = pColInfoData->varmeta.length;
25,132,459✔
1443
      pCols[i].varmeta.allocLen = pCols[i].varmeta.length;
25,132,459✔
1444
    } else {
1445
      pCols[i].nullbitmap = taosMemoryCalloc(1, BitmapLen(rows));
52,783,916✔
1446
      pCols[i].pData = taosMemoryCalloc(rows, pCols[i].info.bytes);
52,784,706✔
1447
      if (pCols[i].nullbitmap == NULL || pCols[i].pData == NULL) {
52,781,987✔
1448
        code = terrno;
482✔
1449
        taosMemoryFree(pCols[i].nullbitmap);
×
1450
        taosMemoryFree(pCols[i].pData);
×
1451
        goto _error;
×
1452
      }
1453
    }
1454
  }
1455

1456
  *ppCols = pCols;
23,243,471✔
1457
  return code;
23,243,053✔
1458

1459
_error:
×
1460
  for (int32_t j = 0; j < i; ++j) {
×
1461
    colDataDestroy(&pCols[j]);
×
1462
  }
1463

1464
  taosMemoryFree(pCols);
×
1465
  return code;
×
1466
}
1467

1468
static void copyBackToBlock(SSDataBlock* pDataBlock, SColumnInfoData* pCols) {
23,244,683✔
1469
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
23,244,683✔
1470

1471
  for (int32_t i = 0; i < numOfCols; ++i) {
101,161,137✔
1472
    SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, i);
77,916,030✔
1473
    if (pColInfoData == NULL) {
77,916,179✔
1474
      continue;
×
1475
    }
1476

1477
    pColInfoData->info = pCols[i].info;
77,916,179✔
1478
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
77,915,279✔
1479
      taosMemoryFreeClear(pColInfoData->varmeta.offset);
25,135,233✔
1480
      pColInfoData->varmeta = pCols[i].varmeta;
25,132,459✔
1481
    } else {
1482
      taosMemoryFreeClear(pColInfoData->nullbitmap);
52,782,030✔
1483
      pColInfoData->nullbitmap = pCols[i].nullbitmap;
52,782,300✔
1484
    }
1485

1486
    taosMemoryFreeClear(pColInfoData->pData);
77,915,030✔
1487
    pColInfoData->pData = pCols[i].pData;
77,916,597✔
1488
  }
1489

1490
  taosMemoryFreeClear(pCols);
23,245,107✔
1491
}
23,243,538✔
1492

1493
static int32_t* createTupleIndex(size_t rows) {
23,244,777✔
1494
  int32_t* index = taosMemoryCalloc(rows, sizeof(int32_t));
23,244,777✔
1495
  if (index == NULL) {
23,245,195✔
1496
    return NULL;
×
1497
  }
1498

1499
  for (int32_t i = 0; i < rows; ++i) {
2,147,483,647✔
1500
    index[i] = i;
2,147,483,647✔
1501
  }
1502

1503
  return index;
23,244,359✔
1504
}
1505

1506
static void destroyTupleIndex(int32_t* index) { taosMemoryFreeClear(index); }
23,244,628✔
1507

1508
int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
24,721,274✔
1509
  if (pDataBlock->info.rows <= 1) {
24,721,274✔
1510
    return TSDB_CODE_SUCCESS;
1,476,079✔
1511
  }
1512

1513
  // Allocate the additional buffer.
1514
  uint32_t rows = pDataBlock->info.rows;
23,245,201✔
1515

1516
  bool sortColumnHasNull = false;
23,244,359✔
1517
  bool varTypeSort = false;
23,244,359✔
1518

1519
  for (int32_t i = 0; i < taosArrayGetSize(pOrderInfo); ++i) {
56,586,308✔
1520
    SBlockOrderInfo* pInfo = taosArrayGet(pOrderInfo, i);
33,343,209✔
1521
    if (pInfo == NULL) {
33,343,209✔
1522
      continue;
×
1523
    }
1524

1525
    SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, pInfo->slotId);
33,343,209✔
1526
    if (pColInfoData == NULL) {
33,343,209✔
1527
      continue;
×
1528
    }
1529

1530
    if (pColInfoData->hasNull) {
33,343,209✔
1531
      sortColumnHasNull = true;
33,322,197✔
1532
    }
1533

1534
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
33,343,209✔
1535
      varTypeSort = true;
18,955,472✔
1536
    }
1537
  }
1538

1539
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
23,244,359✔
1540

1541
  if (taosArrayGetSize(pOrderInfo) == 1 && (!sortColumnHasNull)) {
23,244,359✔
1542
    if (numOfCols == 1) {
17,504✔
1543
      if (!varTypeSort) {
×
1544
        SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, 0);
×
1545
        SBlockOrderInfo* pOrder = taosArrayGet(pOrderInfo, 0);
×
1546
        if (pColInfoData == NULL || pOrder == NULL) {
×
1547
          return terrno;
×
1548
        }
1549

1550
        int64_t p0 = taosGetTimestampUs();
×
1551

1552
        __compar_fn_t fn = getKeyComparFunc(pColInfoData->info.type, pOrder->order);
×
1553
        taosSort(pColInfoData->pData, pDataBlock->info.rows, pColInfoData->info.bytes, fn);
×
1554

1555
        int64_t p1 = taosGetTimestampUs();
×
1556
        uDebug("blockDataSort easy cost:%" PRId64 ", rows:%" PRId64 "\n", p1 - p0, pDataBlock->info.rows);
×
1557

1558
        return TSDB_CODE_SUCCESS;
×
1559
      } else {  // var data type
1560
      }
1561
    } else if (numOfCols == 2) {
1562
    }
1563
  }
1564

1565
  int32_t* index = createTupleIndex(rows);
23,244,359✔
1566
  if (index == NULL) {
23,244,777✔
1567
    return terrno;
×
1568
  }
1569

1570
  int64_t p0 = taosGetTimestampUs();
23,244,359✔
1571

1572
  SSDataBlockSortHelper helper = {.pDataBlock = pDataBlock, .orderInfo = pOrderInfo};
23,244,359✔
1573
  for (int32_t i = 0; i < taosArrayGetSize(helper.orderInfo); ++i) {
56,586,994✔
1574
    struct SBlockOrderInfo* pInfo = taosArrayGet(helper.orderInfo, i);
33,342,785✔
1575
    if (pInfo == NULL) {
33,342,785✔
1576
      continue;
×
1577
    }
1578

1579
    pInfo->pColData = taosArrayGet(pDataBlock->pDataBlock, pInfo->slotId);
33,342,785✔
1580
    if (pInfo->pColData == NULL) {
33,341,805✔
1581
      continue;
×
1582
    }
1583
    pInfo->compFn = getKeyComparFunc(pInfo->pColData->info.type, pInfo->order);
33,342,367✔
1584
  }
1585

1586
  terrno = 0;
23,244,777✔
1587
  taosqsort_r(index, rows, sizeof(int32_t), &helper, dataBlockCompar);
23,244,359✔
1588
  if (terrno) {
23,245,619✔
1589
    destroyTupleIndex(index);
512✔
1590
    return terrno;
512✔
1591
  }
1592

1593
  int64_t p1 = taosGetTimestampUs();
23,244,683✔
1594

1595
  SColumnInfoData* pCols = NULL;
23,244,683✔
1596
  int32_t          code = createHelpColInfoData(pDataBlock, &pCols);
23,244,683✔
1597
  if (code != 0) {
23,243,154✔
1598
    destroyTupleIndex(index);
×
1599
    return code;
×
1600
  }
1601

1602
  int64_t p2 = taosGetTimestampUs();
23,243,578✔
1603
  blockDataAssign(pCols, pDataBlock, index);
23,243,578✔
1604

1605
  int64_t p3 = taosGetTimestampUs();
23,244,683✔
1606
  copyBackToBlock(pDataBlock, pCols);
23,244,683✔
1607

1608
  int64_t p4 = taosGetTimestampUs();
23,244,106✔
1609
  uDebug("blockDataSort complex sort:%" PRId64 ", create:%" PRId64 ", assign:%" PRId64 ", copyback:%" PRId64
23,244,106✔
1610
         ", rows:%d\n",
1611
         p1 - p0, p2 - p1, p3 - p2, p4 - p3, rows);
1612

1613
  destroyTupleIndex(index);
23,244,106✔
1614
  return TSDB_CODE_SUCCESS;
23,242,236✔
1615
}
1616

1617
void blockDataCleanup(SSDataBlock* pDataBlock) {
2,147,483,647✔
1618
  if(pDataBlock == NULL) {
2,147,483,647✔
1619
    return;
115,517✔
1620
  }
1621
  blockDataEmpty(pDataBlock);
2,147,483,647✔
1622
  SDataBlockInfo* pInfo = &pDataBlock->info;
2,147,483,647✔
1623
  pInfo->id.uid = 0;
2,147,483,647✔
1624
  pInfo->id.groupId = 0;
2,147,483,647✔
1625
}
1626

1627
void blockDataEmpty(SSDataBlock* pDataBlock) {
2,147,483,647✔
1628
  if (pDataBlock == NULL) {
2,147,483,647✔
1629
    return;
454,957✔
1630
  }
1631
  SDataBlockInfo* pInfo = &pDataBlock->info;
2,147,483,647✔
1632
  if (pInfo->capacity == 0) {
2,147,483,647✔
1633
    return;
1,158,336,521✔
1634
  }
1635

1636
  taosMemoryFreeClear(pDataBlock->pBlockAgg);
2,147,483,647✔
1637

1638
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
2,147,483,647✔
1639
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
1640
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
1641
    if (p == NULL) {
2,147,483,647✔
1642
      continue;
×
1643
    }
1644

1645
    colInfoDataCleanup(p, pInfo->capacity);
2,147,483,647✔
1646
  }
1647

1648
  pInfo->rows = 0;
2,147,483,647✔
1649
  pInfo->dataLoad = 0;
2,147,483,647✔
1650
  pInfo->window.ekey = 0;
2,147,483,647✔
1651
  pInfo->window.skey = 0;
2,147,483,647✔
1652
}
1653

1654
void blockDataReset(SSDataBlock* pDataBlock) {
2,154,856✔
1655
  SDataBlockInfo* pInfo = &pDataBlock->info;
2,154,856✔
1656
  if (pInfo->capacity == 0) {
2,154,856✔
1657
    return;
×
1658
  }
1659

1660
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
2,155,112✔
1661
  for (int32_t i = 0; i < numOfCols; ++i) {
9,575,221✔
1662
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
7,420,365✔
1663
    if (p == NULL) {
7,420,621✔
1664
      continue;
×
1665
    }
1666

1667
    p->hasNull = false;
7,420,621✔
1668
    p->reassigned = false;
7,420,877✔
1669
    if (IS_VAR_DATA_TYPE(p->info.type)) {
7,420,621✔
1670
      p->varmeta.length = 0;
1,089,302✔
1671
    }
1672
  }
1673

1674
  pInfo->rows = 0;
2,154,856✔
1675
  pInfo->dataLoad = 0;
2,155,112✔
1676
  pInfo->window.ekey = 0;
2,155,112✔
1677
  pInfo->window.skey = 0;
2,155,112✔
1678
  pInfo->id.uid = 0;
2,155,112✔
1679
  pInfo->id.groupId = 0;
2,154,856✔
1680
}
1681

1682
/*
1683
 * NOTE: the type of the input column may be TSDB_DATA_TYPE_NULL, which is used to denote
1684
 * the all NULL value in this column. It is an internal representation of all NULL value column, and no visible to
1685
 * any users. The length of TSDB_DATA_TYPE_NULL is 0, and it is an special case.
1686
 */
1687
int32_t doEnsureCapacity(SColumnInfoData* pColumn, const SDataBlockInfo* pBlockInfo, uint32_t numOfRows,
2,147,483,647✔
1688
                         bool clearPayload) {
1689
  if ((numOfRows <= 0) || (pBlockInfo && numOfRows <= pBlockInfo->capacity)) {
2,147,483,647✔
1690
    return TSDB_CODE_SUCCESS;
×
1691
  }
1692

1693
  int32_t existedRows = pBlockInfo ? pBlockInfo->rows : 0;
2,147,483,647✔
1694

1695
  if (IS_VAR_DATA_TYPE(pColumn->info.type)) {
2,147,483,647✔
1696
    char* tmp = taosMemoryRealloc(pColumn->varmeta.offset, sizeof(int32_t) * numOfRows);
2,147,483,647✔
1697
    if (tmp == NULL) {
2,147,483,647✔
1698
      return terrno;
×
1699
    }
1700

1701
    pColumn->varmeta.offset = (int32_t*)tmp;
2,147,483,647✔
1702
    memset(&pColumn->varmeta.offset[existedRows], 0, sizeof(int32_t) * (numOfRows - existedRows));
2,147,483,647✔
1703
  } else {
1704
    // prepare for the null bitmap
1705
    char* tmp = taosMemoryRealloc(pColumn->nullbitmap, BitmapLen(numOfRows));
2,147,483,647✔
1706
    if (tmp == NULL) {
2,147,483,647✔
1707
      return terrno;
×
1708
    }
1709

1710
    int32_t oldLen = BitmapLen(existedRows);
2,147,483,647✔
1711
    pColumn->nullbitmap = tmp;
2,147,483,647✔
1712
    memset(&pColumn->nullbitmap[oldLen], 0, BitmapLen(numOfRows) - oldLen);
2,147,483,647✔
1713
    if (pColumn->info.bytes == 0) {
2,147,483,647✔
1714
      return TSDB_CODE_INVALID_PARA;
×
1715
    }
1716

1717
    // here we employ the aligned malloc function, to make sure that the address of allocated memory is aligned
1718
    // to MALLOC_ALIGN_BYTES
1719
    tmp = taosMemoryMallocAlign(MALLOC_ALIGN_BYTES, numOfRows * pColumn->info.bytes);
2,147,483,647✔
1720
    if (tmp == NULL) {
2,147,483,647✔
1721
      return terrno;
×
1722
    }
1723
    // memset(tmp, 0, numOfRows * pColumn->info.bytes);
1724

1725
    // copy back the existed data
1726
    if (pColumn->pData != NULL) {
2,147,483,647✔
1727
      memcpy(tmp, pColumn->pData, existedRows * pColumn->info.bytes);
622,372,510✔
1728
      taosMemoryFreeClear(pColumn->pData);
622,384,670✔
1729
    }
1730

1731
    pColumn->pData = tmp;
2,147,483,647✔
1732

1733
    // check if the allocated memory is aligned to the requried bytes.
1734
#if defined LINUX
1735
    if ((((uint64_t)pColumn->pData) & (MALLOC_ALIGN_BYTES - 1)) != 0x0) {
2,147,483,647✔
1736
      return TSDB_CODE_FAILED;
×
1737
    }
1738
#endif
1739

1740
    if (clearPayload) {
2,147,483,647✔
1741
      memset(tmp + pColumn->info.bytes * existedRows, 0, pColumn->info.bytes * (numOfRows - existedRows));
2,147,483,647✔
1742
    }
1743
  }
1744

1745
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
1746
}
1747

1748
void colInfoDataCleanup(SColumnInfoData* pColumn, uint32_t numOfRows) {
2,147,483,647✔
1749
  pColumn->hasNull = false;
2,147,483,647✔
1750

1751
  if (IS_VAR_DATA_TYPE(pColumn->info.type)) {
2,147,483,647✔
1752
    pColumn->varmeta.length = 0;
2,147,483,647✔
1753
    if (pColumn->varmeta.offset != NULL) {
2,147,483,647✔
1754
      memset(pColumn->varmeta.offset, 0, sizeof(int32_t) * numOfRows);
2,147,483,647✔
1755
    }
1756
  } else {
1757
    if (pColumn->nullbitmap != NULL) {
2,147,483,647✔
1758
      memset(pColumn->nullbitmap, 0, BitmapLen(numOfRows));
2,147,483,647✔
1759
    }
1760
  }
1761
}
2,147,483,647✔
1762

1763
int32_t colInfoDataEnsureCapacity(SColumnInfoData* pColumn, uint32_t numOfRows, bool clearPayload) {
2,147,483,647✔
1764
  SDataBlockInfo info = {0};
2,147,483,647✔
1765
  return doEnsureCapacity(pColumn, &info, numOfRows, clearPayload);
2,147,483,647✔
1766
}
1767

1768
int32_t blockDataEnsureCapacity(SSDataBlock* pDataBlock, uint32_t numOfRows) {
2,147,483,647✔
1769
  int32_t code = 0;
2,147,483,647✔
1770
  if (numOfRows == 0 || numOfRows <= pDataBlock->info.capacity) {
2,147,483,647✔
1771
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
1772
  }
1773

1774
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
2,147,483,647✔
1775
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
1776
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
1777
    if (p == NULL) {
2,147,483,647✔
1778
      return terrno;
×
1779
    }
1780

1781
    code = doEnsureCapacity(p, &pDataBlock->info, numOfRows, false);
2,147,483,647✔
1782
    if (code) {
2,147,483,647✔
1783
      return code;
×
1784
    }
1785
  }
1786

1787
  pDataBlock->info.capacity = numOfRows;
2,147,483,647✔
1788
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
1789
}
1790

1791
void blockDataFreeRes(SSDataBlock* pBlock) {
2,147,483,647✔
1792
  if (pBlock == NULL) {
2,147,483,647✔
1793
    return;
50,371,621✔
1794
  }
1795

1796
  int32_t numOfOutput = taosArrayGetSize(pBlock->pDataBlock);
2,147,483,647✔
1797
  for (int32_t i = 0; i < numOfOutput; ++i) {
2,147,483,647✔
1798
    SColumnInfoData* pColInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
1799
    if (pColInfoData == NULL) {
2,147,483,647✔
1800
      continue;
×
1801
    }
1802

1803
    colDataDestroy(pColInfoData);
2,147,483,647✔
1804
  }
1805

1806
  taosArrayDestroy(pBlock->pDataBlock);
2,147,483,647✔
1807
  pBlock->pDataBlock = NULL;
2,147,483,647✔
1808

1809
  taosMemoryFreeClear(pBlock->pBlockAgg);
2,147,483,647✔
1810
  memset(&pBlock->info, 0, sizeof(SDataBlockInfo));
2,147,483,647✔
1811
}
1812

1813
void blockDataFreeCols(SSDataBlock* pBlock) {
×
1814
  if (pBlock == NULL) {
×
1815
    return;
×
1816
  }
1817

1818
  int32_t numOfOutput = taosArrayGetSize(pBlock->pDataBlock);
×
1819
  for (int32_t i = 0; i < numOfOutput; ++i) {
×
1820
    SColumnInfoData* pColInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
×
1821
    if (pColInfoData == NULL) {
×
1822
      continue;
×
1823
    }
1824

1825
    colDataDestroy(pColInfoData);
×
1826
  }
1827

1828
  taosMemoryFreeClear(pBlock->pBlockAgg);
×
1829
  memset(&pBlock->info, 0, sizeof(SDataBlockInfo));
×
1830
}
1831

1832
void blockDataDestroy(SSDataBlock* pBlock) {
2,147,483,647✔
1833
  if (pBlock == NULL) {
2,147,483,647✔
1834
    return;
386,766,360✔
1835
  }
1836

1837
  if (IS_VAR_DATA_TYPE(pBlock->info.pks[0].type)) {
2,147,483,647✔
1838
    taosMemoryFreeClear(pBlock->info.pks[0].pData);
14,623,351✔
1839
    taosMemoryFreeClear(pBlock->info.pks[1].pData);
14,686,926✔
1840
  }
1841

1842
  blockDataFreeRes(pBlock);
2,147,483,647✔
1843
  taosMemoryFreeClear(pBlock);
2,147,483,647✔
1844
}
1845

1846
// todo remove it
1847
int32_t assignOneDataBlock(SSDataBlock* dst, const SSDataBlock* src) {
×
1848
  int32_t code = 0;
×
1849

1850
  dst->info = src->info;
×
1851
  dst->info.pks[0].pData = NULL;
×
1852
  dst->info.pks[1].pData = NULL;
×
1853
  dst->info.rows = 0;
×
1854
  dst->info.capacity = 0;
×
1855

1856
  size_t numOfCols = taosArrayGetSize(src->pDataBlock);
×
1857
  for (int32_t i = 0; i < numOfCols; ++i) {
×
1858
    SColumnInfoData* p = taosArrayGet(src->pDataBlock, i);
×
1859
    if (p == NULL) {
×
1860
      return terrno;
×
1861
    }
1862

1863
    SColumnInfoData colInfo = {.hasNull = true, .info = p->info};
×
1864
    code = blockDataAppendColInfo(dst, &colInfo);
×
1865
    if (code) {
×
1866
      return code;
×
1867
    }
1868
  }
1869

1870
  code = blockDataEnsureCapacity(dst, src->info.rows);
×
1871
  if (code != TSDB_CODE_SUCCESS) {
×
1872
    return code;
×
1873
  }
1874

1875
  for (int32_t i = 0; i < numOfCols; ++i) {
×
1876
    SColumnInfoData* pDst = taosArrayGet(dst->pDataBlock, i);
×
1877
    SColumnInfoData* pSrc = taosArrayGet(src->pDataBlock, i);
×
1878
    if (pSrc == NULL || pDst == NULL || (pSrc->pData == NULL && (!IS_VAR_DATA_TYPE(pSrc->info.type)))) {
×
1879
      continue;
×
1880
    }
1881

1882
    int32_t ret = colDataAssign(pDst, pSrc, src->info.rows, &src->info);
×
1883
    if (ret < 0) {
×
1884
      return ret;
×
1885
    }
1886
  }
1887

1888
  uint32_t cap = dst->info.capacity;
×
1889
  dst->info = src->info;
×
1890
  dst->info.pks[0].pData = NULL;
×
1891
  dst->info.pks[1].pData = NULL;
×
1892
  dst->info.capacity = cap;
×
1893
  uTrace("%s,parName:%s, groupId:%"PRIu64, __FUNCTION__, dst->info.parTbName, dst->info.id.groupId)
×
1894
  return code;
×
1895
}
1896

1897
int32_t copyDataBlock(SSDataBlock* pDst, const SSDataBlock* pSrc) {
170,650,026✔
1898
  blockDataCleanup(pDst);
170,650,026✔
1899

1900
  int32_t code = blockDataEnsureCapacity(pDst, pSrc->info.rows);
170,647,816✔
1901
  if (code != TSDB_CODE_SUCCESS) {
170,649,576✔
1902
    return code;
×
1903
  }
1904

1905
  size_t numOfCols = taosArrayGetSize(pSrc->pDataBlock);
170,649,576✔
1906
  for (int32_t i = 0; i < numOfCols; ++i) {
1,298,328,315✔
1907
    SColumnInfoData* pDstCol = taosArrayGet(pDst->pDataBlock, i);
1,127,678,552✔
1908
    SColumnInfoData* pSrcCol = taosArrayGet(pSrc->pDataBlock, i);
1,127,864,416✔
1909
    if (pDstCol == NULL || pSrcCol == NULL) {
1,127,822,413✔
1910
      continue;
×
1911
    }
1912

1913
    int32_t ret = colDataAssign(pDstCol, pSrcCol, pSrc->info.rows, &pSrc->info);
1,127,822,413✔
1914
    if (ret < 0) {
1,127,637,051✔
1915
      code = ret;
×
1916
      return code;
×
1917
    }
1918
  }
1919

1920
  uint32_t cap = pDst->info.capacity;
170,649,763✔
1921

1922
  if (IS_VAR_DATA_TYPE(pDst->info.pks[0].type)) {
170,649,506✔
1923
    taosMemoryFreeClear(pDst->info.pks[0].pData);
2,120✔
1924
  }
1925

1926
  if (IS_VAR_DATA_TYPE(pDst->info.pks[1].type)) {
170,652,334✔
1927
    taosMemoryFreeClear(pDst->info.pks[1].pData);
113✔
1928
  }
1929

1930
  pDst->info = pSrc->info;
170,651,306✔
1931
  code = copyPkVal(&pDst->info, &pSrc->info);
170,652,446✔
1932
  if (code != TSDB_CODE_SUCCESS) {
170,649,861✔
1933
    uError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1934
    return code;
×
1935
  }
1936

1937
  pDst->info.capacity = cap;
170,649,861✔
1938
  return code;
170,650,400✔
1939
}
1940

1941
int32_t blockCopyOneRow(const SSDataBlock* pDataBlock, int32_t rowIdx, SSDataBlock** pResBlock) {
×
1942
  QRY_PARAM_CHECK(pResBlock);
×
1943

1944
  if (pDataBlock == NULL) {
×
1945
    return TSDB_CODE_INVALID_PARA;
×
1946
  }
1947

1948
  SSDataBlock* pBlock = NULL;
×
1949
  int32_t      code = createDataBlock(&pBlock);
×
1950
  if (code) {
×
1951
    return code;
×
1952
  }
1953

1954
  pBlock->info = pDataBlock->info;
×
1955
  pBlock->info.pks[0].pData = NULL;
×
1956
  pBlock->info.pks[1].pData = NULL;
×
1957
  pBlock->info.rows = 0;
×
1958
  pBlock->info.capacity = 0;
×
1959

1960
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
×
1961
  for (int32_t i = 0; i < numOfCols; ++i) {
×
1962
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
×
1963
    if (p == NULL) {
×
1964
      blockDataDestroy(pBlock);
×
1965
      return terrno;
×
1966
    }
1967

1968
    SColumnInfoData colInfo = {.hasNull = true, .info = p->info};
×
1969
    code = blockDataAppendColInfo(pBlock, &colInfo);
×
1970
    if (code) {
×
1971
      blockDataDestroy(pBlock);
×
1972
      return code;
×
1973
    }
1974
  }
1975

1976
  code = blockDataEnsureCapacity(pBlock, 1);
×
1977
  if (code != TSDB_CODE_SUCCESS) {
×
1978
    blockDataDestroy(pBlock);
×
1979
    return code;
×
1980
  }
1981

1982
  for (int32_t i = 0; i < numOfCols; ++i) {
×
1983
    SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
×
1984
    SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i);
×
1985
    if (pDst == NULL || pSrc == NULL) {
×
1986
      blockDataDestroy(pBlock);
×
1987
      return terrno;
×
1988
    }
1989

1990
    bool  isNull = colDataIsNull(pSrc, pDataBlock->info.rows, rowIdx, NULL);
×
1991
    void* pData = NULL;
×
1992
    if (!isNull) {
×
1993
      pData = colDataGetData(pSrc, rowIdx);
×
1994
    }
1995

1996
    code = colDataSetVal(pDst, 0, pData, isNull);
×
1997
    if (code) {
×
1998
      blockDataDestroy(pBlock);
×
1999
      return code;
×
2000
    }
2001
  }
2002

2003
  pBlock->info.rows = 1;
×
2004

2005
  *pResBlock = pBlock;
×
2006
  return code;
×
2007
}
2008

2009
int32_t copyPkVal(SDataBlockInfo* pDst, const SDataBlockInfo* pSrc) {
2,041,999,121✔
2010
  int32_t code = TSDB_CODE_SUCCESS;
2,041,999,121✔
2011
  int32_t lino = 0;
2,041,999,121✔
2012
  if (!IS_VAR_DATA_TYPE(pSrc->pks[0].type)) {
2,041,999,121✔
2013
    return code;
2,034,584,313✔
2014
  }
2015

2016
  // prepare the pk buffer if needed
2017
  SValue* p = &pDst->pks[0];
7,463,124✔
2018

2019
  p->type = pSrc->pks[0].type;
7,496,140✔
2020
  p->pData = taosMemoryCalloc(1, pSrc->pks[0].nData);
7,496,140✔
2021
  QUERY_CHECK_NULL(p->pData, code, lino, _end, terrno);
7,494,766✔
2022

2023
  p->nData = pSrc->pks[0].nData;
7,495,453✔
2024
  memcpy(p->pData, pSrc->pks[0].pData, p->nData);
7,496,827✔
2025

2026
  p = &pDst->pks[1];
7,495,442✔
2027
  p->type = pSrc->pks[1].type;
7,497,525✔
2028
  p->pData = taosMemoryCalloc(1, pSrc->pks[1].nData);
7,496,827✔
2029
  QUERY_CHECK_NULL(p->pData, code, lino, _end, terrno);
7,494,755✔
2030

2031
  p->nData = pSrc->pks[1].nData;
7,494,068✔
2032
  memcpy(p->pData, pSrc->pks[1].pData, p->nData);
7,496,140✔
2033

2034
_end:
7,495,431✔
2035
  if (code != TSDB_CODE_SUCCESS) {
7,495,431✔
2036
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2037
  }
2038
  return code;
7,496,827✔
2039
}
2040

2041
int32_t createOneDataBlock(const SSDataBlock* pDataBlock, bool copyData, SSDataBlock** pResBlock) {
1,871,184,316✔
2042
  int32_t code = 0, lino = 0;
1,871,184,316✔
2043
  QRY_PARAM_CHECK(pResBlock);
1,871,184,316✔
2044
  TSDB_CHECK_NULL(pDataBlock, code, lino, _exit, TSDB_CODE_INVALID_PARA);
1,871,369,289✔
2045

2046
  SSDataBlock* pDstBlock = NULL;
1,871,369,289✔
2047
  TAOS_CHECK_EXIT(createDataBlock(&pDstBlock));
1,871,274,628✔
2048

2049
  pDstBlock->info = pDataBlock->info;
1,871,190,793✔
2050
  pDstBlock->info.pks[0].pData = NULL;
1,871,219,555✔
2051
  pDstBlock->info.pks[1].pData = NULL;
1,871,407,991✔
2052

2053
  pDstBlock->info.rows = 0;
1,871,495,095✔
2054
  pDstBlock->info.capacity = 0;
1,871,493,215✔
2055
  pDstBlock->info.rowSize = 0;
1,871,483,367✔
2056
  pDstBlock->info.id = pDataBlock->info.id;
1,871,415,687✔
2057
  pDstBlock->info.blankFill = pDataBlock->info.blankFill;
1,871,474,198✔
2058

2059
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
1,871,319,603✔
2060
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
2061
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
2062
    if (p == NULL) {
2,147,483,647✔
2063
      blockDataDestroy(pDstBlock);
×
2064
      TSDB_CHECK_NULL(p, code, lino, _exit, terrno);
×
2065
    }
2066

2067
    SColumnInfoData colInfo = {.hasNull = true, .info = p->info};
2,147,483,647✔
2068
    code = blockDataAppendColInfo(pDstBlock, &colInfo);
2,147,483,647✔
2069
    if (code) {
2,147,483,647✔
2070
      blockDataDestroy(pDstBlock);
×
2071
      TAOS_CHECK_EXIT(code);
×
2072
    }
2073
  }
2074

2075
  code = copyPkVal(&pDstBlock->info, &pDataBlock->info);
1,871,513,665✔
2076
  if (code != TSDB_CODE_SUCCESS) {
1,871,437,621✔
2077
    blockDataDestroy(pDstBlock);
×
2078
    uError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
2079
    TAOS_CHECK_EXIT(code);
×
2080
  }
2081

2082
  if (copyData) {
1,871,437,621✔
2083
    code = blockDataEnsureCapacity(pDstBlock, pDataBlock->info.rows);
927,065,097✔
2084
    if (code != TSDB_CODE_SUCCESS) {
927,154,962✔
2085
      blockDataDestroy(pDstBlock);
×
2086
      TAOS_CHECK_EXIT(code);
×
2087
    }
2088

2089
    for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
2090
      SColumnInfoData* pDst = taosArrayGet(pDstBlock->pDataBlock, i);
2,147,483,647✔
2091
      SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
2092
      if (pDst == NULL) {
2,147,483,647✔
2093
        blockDataDestroy(pDstBlock);
×
2094
        uError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
2095
        TSDB_CHECK_NULL(pDst, code, lino, _exit, terrno);
×
2096
      }
2097

2098
      if (pSrc == NULL) {
2,147,483,647✔
2099
        blockDataDestroy(pDstBlock);
×
2100
        uError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
2101
        TSDB_CHECK_NULL(pSrc, code, lino, _exit, terrno);
×
2102
      }
2103

2104
      int32_t ret = colDataAssign(pDst, pSrc, pDataBlock->info.rows, &pDataBlock->info);
2,147,483,647✔
2105
      if (ret < 0) {
2,147,483,647✔
2106
        code = ret;
×
2107
        blockDataDestroy(pDstBlock);
×
2108
        TAOS_CHECK_EXIT(code);
×
2109
      }
2110
    }
2111

2112
    pDstBlock->info.rows = pDataBlock->info.rows;
927,190,534✔
2113
    pDstBlock->info.capacity = pDataBlock->info.rows;
927,153,427✔
2114
  }
2115

2116
  *pResBlock = pDstBlock;
1,871,551,998✔
2117

2118
_exit:
1,871,402,071✔
2119
  
2120
  return code;
1,871,436,908✔
2121
}
2122

2123
int32_t createOneDataBlockWithColArray(const SSDataBlock* pDataBlock, SArray* pColArray, SSDataBlock** pResBlock) {
115,536,396✔
2124
  int32_t      code = TSDB_CODE_SUCCESS;
115,536,396✔
2125
  int32_t      lino = 0;
115,536,396✔
2126
  SSDataBlock* pDstBlock = NULL;
115,536,396✔
2127

2128
  QRY_PARAM_CHECK(pResBlock);
115,555,303✔
2129
  QUERY_CHECK_NULL(pDataBlock, code, lino, _return, TSDB_CODE_INVALID_PARA);
115,561,785✔
2130

2131
  QUERY_CHECK_CODE(createDataBlock(&pDstBlock), lino, _return);
115,561,785✔
2132

2133
  pDstBlock->info = pDataBlock->info;
115,570,332✔
2134
  pDstBlock->info.pks[0].pData = NULL;
115,582,011✔
2135
  pDstBlock->info.pks[1].pData = NULL;
115,589,815✔
2136

2137
  pDstBlock->info.rows = 0;
115,595,012✔
2138
  pDstBlock->info.capacity = 0;
115,592,421✔
2139
  pDstBlock->info.rowSize = 0;
115,591,804✔
2140
  pDstBlock->info.id = pDataBlock->info.id;
115,584,066✔
2141
  pDstBlock->info.blankFill = pDataBlock->info.blankFill;
115,587,326✔
2142

2143
  for (int32_t i = 0; i < taosArrayGetSize(pColArray); ++i) {
475,931,816✔
2144
    SColIdSlotIdPair* pColPair = taosArrayGet(pColArray, i);
360,339,413✔
2145
    QUERY_CHECK_NULL(pColPair, code, lino, _return, terrno);
360,339,451✔
2146

2147
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, pColPair->vtbSlotId);
360,339,451✔
2148
    QUERY_CHECK_NULL(p, code, lino, _return, terrno);
360,328,900✔
2149

2150
    SColumnInfoData pColInfo = {.hasNull = true, .info = p->info};
360,328,900✔
2151
    pColInfo.info.colId = pColPair->orgColId;
360,323,782✔
2152
    QUERY_CHECK_CODE(blockDataAppendColInfo(pDstBlock, &pColInfo), lino, _return);
360,340,077✔
2153
  }
2154

2155
  *pResBlock = pDstBlock;
115,580,168✔
2156
  return code;
115,594,368✔
2157
_return:
×
2158
  uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2159
  blockDataDestroy(pDstBlock);
×
2160
  return code;
×
2161
}
2162

2163
// create a new data block based on the template block, and fill data from the source block according to the column mapping
2164
int32_t createOneDataBlockWithTwoBlock(const SSDataBlock* pSrcBlock, const SSDataBlock* pTemplateBlock, SArray* pColMap,
72,937,958✔
2165
                                       SSDataBlock** pResBlock) {
2166
  int32_t      code = TSDB_CODE_SUCCESS;
72,937,958✔
2167
  int32_t      lino = 0;
72,937,958✔
2168
  SSDataBlock* pDstBlock = NULL;
72,937,958✔
2169

2170
  QRY_PARAM_CHECK(pResBlock);
72,951,041✔
2171
  QUERY_CHECK_NULL(pSrcBlock, code, lino, _return, TSDB_CODE_INVALID_PARA);
72,957,579✔
2172
  QUERY_CHECK_NULL(pTemplateBlock, code, lino, _return, TSDB_CODE_INVALID_PARA);
72,957,579✔
2173
  QUERY_CHECK_NULL(pColMap, code, lino, _return, TSDB_CODE_INVALID_PARA);
72,957,579✔
2174

2175
  code = createOneDataBlock(pTemplateBlock, false, &pDstBlock);
72,957,579✔
2176
  QUERY_CHECK_CODE(code, lino, _return);
72,965,454✔
2177
  code = blockDataEnsureCapacity(pDstBlock, pSrcBlock->info.rows);
72,965,454✔
2178
  QUERY_CHECK_CODE(code, lino, _return);
72,978,509✔
2179

2180
  if (pSrcBlock->pBlockAgg) {
72,978,509✔
2181
    size_t num = taosArrayGetSize(pDstBlock->pDataBlock);
18,610,641✔
2182
    pDstBlock->pBlockAgg = taosMemoryCalloc(num, sizeof(SColumnDataAgg));
18,612,594✔
2183
    QUERY_CHECK_NULL(pDstBlock->pBlockAgg, code, lino, _return, terrno);
18,603,431✔
2184
    for (int i = 0; i < num; ++i) {
151,840,017✔
2185
      pDstBlock->pBlockAgg[i].colId = i;
133,186,340✔
2186
      pDstBlock->pBlockAgg[i].numOfNull = pSrcBlock->info.rows;
133,203,280✔
2187
    }
2188
  } else {
2189
    for (int32_t i = 0; i < taosArrayGetSize(pDstBlock->pDataBlock); ++i) {
704,578,951✔
2190
      SColumnInfoData* pDst = taosArrayGet(pDstBlock->pDataBlock, i);
650,201,318✔
2191
      QUERY_CHECK_NULL(pDst, code, lino, _return, terrno);
650,193,520✔
2192
      colDataSetNNULL(pDst, 0, pSrcBlock->info.rows);
650,193,520✔
2193
    }
2194
  }
2195

2196
  for (int32_t i = 0; i < taosArrayGetSize(pColMap); i++) {
317,138,742✔
2197
    SColIdSlotIdPair* pColPair = taosArrayGet(pColMap, i);
244,168,752✔
2198
    QUERY_CHECK_NULL(pColPair, code, lino, _return, terrno);
244,175,269✔
2199
    for (int32_t j = 0; j < taosArrayGetSize(pSrcBlock->pDataBlock); j++) {
1,188,005,448✔
2200
      SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, j);
943,831,570✔
2201
      QUERY_CHECK_NULL(pSrcCol, code, lino, _return, terrno);
943,844,583✔
2202
      if (pSrcCol->info.colId == pColPair->orgColId) {
943,844,583✔
2203
        SColumnInfoData* pDstCol = taosArrayGet(pDstBlock->pDataBlock, pColPair->vtbSlotId);
244,169,410✔
2204
        QUERY_CHECK_NULL(pDstCol, code, lino, _return, terrno);
244,172,007✔
2205
        if (pSrcBlock->pBlockAgg) {
244,172,007✔
2206
          (void)memcpy(&pDstBlock->pBlockAgg[pColPair->vtbSlotId], &pSrcBlock->pBlockAgg[j], sizeof(SColumnDataAgg));
51,238,873✔
2207
          pDstBlock->pBlockAgg[pColPair->vtbSlotId].numOfNull = 0;
51,238,229✔
2208
        } else {
2209
          QUERY_CHECK_CODE(colDataAssign(pDstCol, pSrcCol, (int32_t)pSrcBlock->info.rows, &pSrcBlock->info), lino, _return);
192,837,409✔
2210
        }
2211
      }
2212
    }
2213
  }
2214

2215
  pDstBlock->info.rows = pSrcBlock->info.rows;
72,956,413✔
2216
  pDstBlock->info.capacity = pSrcBlock->info.rows;
72,983,717✔
2217
  pDstBlock->info.window = pSrcBlock->info.window;
72,985,026✔
2218
  pDstBlock->info.dataLoad = pSrcBlock->info.dataLoad;
72,985,026✔
2219
  pDstBlock->info.scanFlag = pSrcBlock->info.scanFlag;
72,985,026✔
2220

2221
  *pResBlock = pDstBlock;
72,982,415✔
2222
  return code;
72,983,717✔
2223
_return:
×
2224
  uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2225
  blockDataDestroy(pDstBlock);
×
2226
  return code;
×
2227
}
2228

2229
int32_t createDataBlock(SSDataBlock** pResBlock) {
2,147,483,647✔
2230
  QRY_PARAM_CHECK(pResBlock);
2,147,483,647✔
2231
  SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
2,147,483,647✔
2232
  if (pBlock == NULL) {
2,147,483,647✔
2233
    return terrno;
×
2234
  }
2235

2236
  pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
2,147,483,647✔
2237
  if (pBlock->pDataBlock == NULL) {
2,147,483,647✔
2238
    int32_t code = terrno;
×
2239
    taosMemoryFree(pBlock);
×
2240
    return code;
×
2241
  }
2242

2243
  *pResBlock = pBlock;
2,147,483,647✔
2244
  return 0;
2,147,483,647✔
2245
}
2246

2247
int32_t blockDataAppendColInfo(SSDataBlock* pBlock, SColumnInfoData* pColInfoData) {
2,147,483,647✔
2248
  if (pBlock->pDataBlock == NULL) {
2,147,483,647✔
2249
    pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
51,008,350✔
2250
    if (pBlock->pDataBlock == NULL) {
50,989,862✔
2251
      return terrno;
×
2252
    }
2253
  }
2254

2255
  void* p = taosArrayPush(pBlock->pDataBlock, pColInfoData);
2,147,483,647✔
2256
  if (p == NULL) {
2,147,483,647✔
2257
    return terrno;
×
2258
  }
2259

2260
  // todo disable it temporarily
2261
  //  A S S E R T(pColInfoData->info.type != 0);
2262
  if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
2263
    pBlock->info.hasVarCol = true;
2,147,483,647✔
2264
  }
2265
  pBlock->info.rowSize += pColInfoData->info.bytes;
2,147,483,647✔
2266

2267
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2268
}
2269

2270
SColumnInfoData createColumnInfoData(int16_t type, int32_t bytes, int16_t colId) {
2,147,483,647✔
2271
  SColumnInfoData col = {.hasNull = true};
2,147,483,647✔
2272
  col.info.colId = colId;
2,147,483,647✔
2273
  col.info.type = type;
2,147,483,647✔
2274
  col.info.bytes = bytes;
2,147,483,647✔
2275
  // if (type == TSDB_DATA_TYPE_BLOB || type == TSDB_DATA_TYPE_MEDIUMBLOB) {
2276
  //   col.info.bytes = TSDB_MAX_BLOB_LEN;
2277
  // }
2278
  return col;
2,147,483,647✔
2279
}
2280

2281
int32_t bdGetColumnInfoData(const SSDataBlock* pBlock, int32_t index, SColumnInfoData** pColInfoData) {
842,874,306✔
2282
  int32_t code = 0;
842,874,306✔
2283
  QRY_PARAM_CHECK(pColInfoData);
842,874,306✔
2284

2285
  if (index >= taosArrayGetSize(pBlock->pDataBlock)) {
842,874,983✔
2286
    return TSDB_CODE_INVALID_PARA;
×
2287
  }
2288

2289
  *pColInfoData = taosArrayGet(pBlock->pDataBlock, index);
842,874,274✔
2290
  if (*pColInfoData == NULL) {
842,874,305✔
2291
    code = terrno;
×
2292
  }
2293

2294
  return code;
842,874,335✔
2295
}
2296

2297
size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize, int32_t extraSize) {
40,592,911✔
2298
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
40,592,911✔
2299

2300
  int32_t payloadSize = pageSize - extraSize;
40,593,598✔
2301
  int32_t rowSize = pBlock->info.rowSize;
40,593,598✔
2302
  int32_t nRows = payloadSize / rowSize;
40,592,911✔
2303
  if (nRows < 1) {
40,592,911✔
2304
    uError("rows %d in page is too small, payloadSize:%d, rowSize:%d", nRows, payloadSize, rowSize);
×
2305
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2306
    return -1;
×
2307
  }
2308

2309
  int32_t numVarCols = 0;
40,592,911✔
2310
  int32_t numFixCols = 0;
40,592,911✔
2311
  for (int32_t i = 0; i < numOfCols; ++i) {
215,972,992✔
2312
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
175,378,965✔
2313
    if (pCol == NULL) {
175,379,662✔
2314
      return -1;
×
2315
    }
2316

2317
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
175,379,662✔
2318
      ++numVarCols;
22,413,591✔
2319
    } else {
2320
      ++numFixCols;
152,966,490✔
2321
    }
2322
  }
2323

2324
  // find the data payload whose size is greater than payloadSize
2325
  int result = -1;
40,594,027✔
2326
  int start = 1;
40,594,027✔
2327
  int end = nRows;
40,594,027✔
2328
  while (start <= end) {
372,010,618✔
2329
    int mid = start + (end - start) / 2;
331,416,591✔
2330
    // data size + var data type columns offset + fixed data type columns bitmap len
2331
    int midSize = rowSize * mid + numVarCols * sizeof(int32_t) * mid + numFixCols * BitmapLen(mid);
331,416,591✔
2332
    if (midSize > payloadSize) {
331,416,591✔
2333
      result = mid;
70,828,943✔
2334
      end = mid - 1;
70,828,943✔
2335
    } else {
2336
      start = mid + 1;
260,587,648✔
2337
    }
2338
  }
2339

2340
  int32_t newRows = (result != -1) ? result - 1 : nRows;
40,594,027✔
2341
  // the true value must be less than the value of nRows
2342
  if (newRows > nRows || newRows < 1) {
40,594,027✔
2343
    uError("invalid newRows:%d, nRows:%d", newRows, nRows);
540✔
2344
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
540✔
2345
    return -1;
×
2346
  }
2347

2348
  return newRows;
40,593,487✔
2349
}
2350

2351
void colDataDestroy(SColumnInfoData* pColData) {
2,147,483,647✔
2352
  if (!pColData) {
2,147,483,647✔
2353
    return;
158,884,142✔
2354
  }
2355

2356
  if (IS_VAR_DATA_TYPE(pColData->info.type)) {
2,147,483,647✔
2357
    taosMemoryFreeClear(pColData->varmeta.offset);
2,147,483,647✔
2358
    pColData->varmeta.allocLen = 0;
2,147,483,647✔
2359
    pColData->varmeta.length = 0;
2,147,483,647✔
2360
  } else {
2361
    taosMemoryFreeClear(pColData->nullbitmap);
2,147,483,647✔
2362
  }
2363

2364
  taosMemoryFreeClear(pColData->pData);
2,147,483,647✔
2365
}
2366

2367
static void doShiftBitmap(char* nullBitmap, size_t n, size_t total) {
122,382,062✔
2368
  int32_t len = BitmapLen(total);
122,382,062✔
2369

2370
  int32_t newLen = BitmapLen(total - n);
122,382,062✔
2371
  if (n % 8 == 0) {
122,382,062✔
2372
    (void)memmove(nullBitmap, nullBitmap + n / 8, newLen);
1,750,067✔
2373
  } else {
2374
    int32_t  tail = n % 8;
120,631,995✔
2375
    int32_t  i = 0;
120,631,995✔
2376
    uint8_t* p = (uint8_t*)nullBitmap;
120,631,995✔
2377

2378
    if (n < 8) {
120,631,995✔
2379
      while (i < len) {
102,786,123✔
2380
        uint8_t v = p[i];  // source bitmap value
96,099,678✔
2381
        p[i] = (v << tail);
96,099,678✔
2382

2383
        if (i < len - 1) {
96,099,678✔
2384
          uint8_t next = p[i + 1];
89,413,233✔
2385
          p[i] |= (next >> (8 - tail));
89,413,233✔
2386
        }
2387

2388
        i += 1;
96,099,678✔
2389
      }
2390
    } else if (n > 8) {
113,945,550✔
2391
      int32_t remain = (total % 8 != 0 && total % 8 <= tail) ? 1 : 0;
113,945,550✔
2392
      int32_t gap = len - newLen - remain;
113,945,550✔
2393
      while (i < newLen) {
1,051,175,616✔
2394
        uint8_t v = p[i + gap];
937,231,094✔
2395
        p[i] = (v << tail);
937,222,356✔
2396

2397
        if (i < newLen - 1 + remain) {
937,227,496✔
2398
          uint8_t next = p[i + gap + 1];
855,217,760✔
2399
          p[i] |= (next >> (8 - tail));
855,220,330✔
2400
        }
2401

2402
        i += 1;
937,230,066✔
2403
      }
2404
    }
2405
  }
2406
}
122,381,034✔
2407

2408
static int32_t colDataMoveVarData(SColumnInfoData* pColInfoData, size_t start, size_t end) {
×
2409
  int32_t dataOffset = -1;
×
2410
  int32_t dataLen = 0;
×
2411
  int32_t beigin = start;
×
2412
  while (beigin < end) {
×
2413
    int32_t offset = pColInfoData->varmeta.offset[beigin];
×
2414
    if (offset == -1) {
×
2415
      beigin++;
×
2416
      continue;
×
2417
    }
2418
    if (start != 0) {
×
2419
      pColInfoData->varmeta.offset[beigin] = dataLen;
×
2420
    }
2421
    char* data = pColInfoData->pData + offset;
×
2422
    if (dataOffset == -1) dataOffset = offset;  // mark the begin of data
×
2423
    int32_t type = pColInfoData->info.type;
×
2424
    if (type == TSDB_DATA_TYPE_JSON) {
×
2425
      dataLen += getJsonValueLen(data);
×
2426
    } else {
2427
      dataLen += varDataTLen(data);
×
2428
    }
2429
    beigin++;
×
2430
  }
2431

2432
  if (dataOffset > 0) {
×
2433
    (void)memmove(pColInfoData->pData, pColInfoData->pData + dataOffset, dataLen);
×
2434
  }
2435

2436
  (void)memmove(pColInfoData->varmeta.offset, &pColInfoData->varmeta.offset[start], (end - start) * sizeof(int32_t));
×
2437
  return dataLen;
×
2438
}
2439

2440
static void colDataTrimFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_t total) {
155,150,151✔
2441
  if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
155,150,151✔
2442
    // pColInfoData->varmeta.length = colDataMoveVarData(pColInfoData, n, total);
2443
    (void)memmove(pColInfoData->varmeta.offset, &pColInfoData->varmeta.offset[n], (total - n) * sizeof(int32_t));
32,768,089✔
2444

2445
    // clear the offset value of the unused entries.
2446
    memset(&pColInfoData->varmeta.offset[total - n], 0, n);
32,768,089✔
2447
  } else {
2448
    int32_t bytes = pColInfoData->info.bytes;
122,382,062✔
2449
    (void)memmove(pColInfoData->pData, ((char*)pColInfoData->pData + n * bytes), (total - n) * bytes);
122,382,062✔
2450
    doShiftBitmap(pColInfoData->nullbitmap, n, total);
122,382,062✔
2451
  }
2452
}
155,150,151✔
2453

2454
int32_t blockDataTrimFirstRows(SSDataBlock* pBlock, size_t n) {
94,164,096✔
2455
  if (n == 0) {
94,164,096✔
2456
    return TSDB_CODE_SUCCESS;
56,667,910✔
2457
  }
2458

2459
  if (pBlock->info.rows <= n) {
37,496,186✔
2460
    blockDataEmpty(pBlock);
689,540✔
2461
  } else {
2462
    size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
36,809,216✔
2463
    for (int32_t i = 0; i < numOfCols; ++i) {
191,959,367✔
2464
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
155,150,151✔
2465
      if (pColInfoData == NULL) {
155,150,151✔
2466
        return terrno;
×
2467
      }
2468

2469
      colDataTrimFirstNRows(pColInfoData, n, pBlock->info.rows);
155,150,151✔
2470
    }
2471

2472
    pBlock->info.rows -= n;
36,809,216✔
2473
  }
2474
  return TSDB_CODE_SUCCESS;
37,498,756✔
2475
}
2476

2477
static void colDataKeepFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_t total) {
31,573,252✔
2478
  if (n >= total || n == 0) return;
31,573,252✔
2479
  if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
31,572,545✔
2480
    if (pColInfoData->varmeta.length != 0) {
5,851,040✔
2481
      int32_t newLen = pColInfoData->varmeta.offset[n];
5,235,481✔
2482
      if (-1 == newLen) {
5,234,774✔
2483
        for (int i = n - 1; i >= 0; --i) {
3,188,023✔
2484
          newLen = pColInfoData->varmeta.offset[i];
3,184,740✔
2485
          if (newLen != -1) {
3,184,740✔
2486
            newLen += calcStrBytesByType(pColInfoData->info.type, pColInfoData->pData + newLen);
344,191✔
2487
            // if (pColInfoData->info.type == TSDB_DATA_TYPE_JSON) {
2488
            //   newLen += getJsonValueLen(pColInfoData->pData + newLen);
2489
            // } else if (IS_STR_DATA_BLOB(pColInfoData->info.type)) {
2490
            //   newLen += blobDataTLen(pColInfoData->pData + newLen);
2491
            // } else {
2492
            //   newLen += varDataTLen(pColInfoData->pData + newLen);
2493
            // }
2494
            break;
344,898✔
2495
          }
2496
        }
2497
      }
2498
      if (newLen < 0) {
5,235,481✔
2499
        // All kept rows are NULL — no valid var data belongs to them.
2500
        uDebug("colDataKeepFirstNRows: all kept rows are NULL, newLen:%d old:%u, reset length to 0",
3,283✔
2501
               newLen, pColInfoData->varmeta.length);
2502
        pColInfoData->varmeta.length = 0;
3,283✔
2503
      } else {
2504
        pColInfoData->varmeta.length = newLen;
5,232,198✔
2505
      }
2506
    }
2507
    // pColInfoData->varmeta.length = colDataMoveVarData(pColInfoData, 0, n);
2508
    memset(&pColInfoData->varmeta.offset[n], 0, total - n);
5,851,777✔
2509
  }
2510
}
2511

2512
void blockDataKeepFirstNRows(SSDataBlock* pBlock, size_t n) {
52,707,022✔
2513
  if (n == 0) {
52,707,022✔
2514
    blockDataEmpty(pBlock);
6,918,789✔
2515
    return;
6,918,789✔
2516
  }
2517

2518
  if (pBlock->info.rows <= n) {
45,788,233✔
2519
    return;
36,549,392✔
2520
  } else {
2521
    size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
9,239,231✔
2522
    for (int32_t i = 0; i < numOfCols; ++i) {
40,812,892✔
2523
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
31,573,252✔
2524
      if (pColInfoData == NULL) {
31,573,088✔
2525
        continue;
×
2526
      }
2527

2528
      colDataKeepFirstNRows(pColInfoData, n, pBlock->info.rows);
31,573,088✔
2529
    }
2530

2531
    pBlock->info.rows = n;
9,239,640✔
2532
  }
2533
}
2534

2535
int32_t tEncodeDataBlock(void** buf, const SSDataBlock* pBlock) {
1,619,185✔
2536
  int64_t tbUid = pBlock->info.id.uid;
1,619,185✔
2537
  int16_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
1,619,636✔
2538
  int16_t hasVarCol = pBlock->info.hasVarCol;
1,619,421✔
2539
  int64_t rows = pBlock->info.rows;
1,619,872✔
2540
  int32_t sz = taosArrayGetSize(pBlock->pDataBlock);
1,619,421✔
2541

2542
  int32_t tlen = 0;
1,619,126✔
2543
  tlen += taosEncodeFixedI64(buf, tbUid);
1,619,126✔
2544
  tlen += taosEncodeFixedI16(buf, numOfCols);
1,619,126✔
2545
  tlen += taosEncodeFixedI16(buf, hasVarCol);
3,238,252✔
2546
  tlen += taosEncodeFixedI64(buf, rows);
1,619,126✔
2547
  tlen += taosEncodeFixedI32(buf, sz);
1,619,126✔
2548
  for (int32_t i = 0; i < sz; i++) {
3,281,256✔
2549
    SColumnInfoData* pColData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
1,662,307✔
2550
    if (pColData == NULL) {
1,662,130✔
2551
      return terrno;
×
2552
    }
2553

2554
    tlen += taosEncodeFixedI16(buf, pColData->info.colId);
1,662,307✔
2555
    tlen += taosEncodeFixedI8(buf, pColData->info.type);
1,662,307✔
2556
    tlen += taosEncodeFixedI32(buf, pColData->info.bytes);
1,662,307✔
2557
    tlen += taosEncodeFixedBool(buf, pColData->hasNull);
1,662,307✔
2558

2559
    if (IS_VAR_DATA_TYPE(pColData->info.type)) {
1,662,307✔
2560
      tlen += taosEncodeBinary(buf, pColData->varmeta.offset, sizeof(int32_t) * rows);
27,804✔
2561
    } else {
2562
      tlen += taosEncodeBinary(buf, pColData->nullbitmap, BitmapLen(rows));
3,296,810✔
2563
    }
2564

2565
    int32_t len = colDataGetLength(pColData, rows);
1,662,307✔
2566
    tlen += taosEncodeFixedI32(buf, len);
1,662,130✔
2567

2568
    if (pColData->reassigned && IS_VAR_DATA_TYPE(pColData->info.type)) {
1,662,130✔
2569
      for (int32_t row = 0; row < rows; ++row) {
×
2570
        char*   pData = pColData->pData + pColData->varmeta.offset[row];
×
2571
        int32_t colSize = calcStrBytesByType(pColData->info.type, pData);
×
2572
        // if (pColData->info.type == TSDB_DATA_TYPE_JSON) {
2573
        //   colSize = getJsonValueLen(pData);
2574
        // } else if (IS_STR_DATA_BLOB(pColData->info.type)) {
2575
        //   colSize = blobDataTLen(pData);
2576
        // } else {
2577
        //   colSize = varDataTLen(pData);
2578
        // }
2579
        tlen += taosEncodeBinary(buf, pData, colSize);
×
2580
      }
2581
    } else {
2582
      tlen += taosEncodeBinary(buf, pColData->pData, len);
3,324,711✔
2583
    }
2584
  }
2585
  return tlen;
1,618,949✔
2586
}
2587

2588
void* tDecodeDataBlock(const void* buf, SSDataBlock* pBlock) {
934,411✔
2589
  int32_t sz = 0;
934,411✔
2590
  int16_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
934,411✔
2591

2592
  buf = taosDecodeFixedU64(buf, &pBlock->info.id.uid);
1,868,468✔
2593
  buf = taosDecodeFixedI16(buf, &numOfCols);
934,234✔
2594
  buf = taosDecodeFixedI16(buf, &pBlock->info.hasVarCol);
934,234✔
2595
  buf = taosDecodeFixedI64(buf, &pBlock->info.rows);
1,868,468✔
2596
  buf = taosDecodeFixedI32(buf, &sz);
934,234✔
2597

2598
  pBlock->pDataBlock = taosArrayInit(sz, sizeof(SColumnInfoData));
934,234✔
2599
  if (pBlock->pDataBlock == NULL) {
934,234✔
2600
    return NULL;
×
2601
  }
2602

2603
  for (int32_t i = 0; i < sz; i++) {
1,932,332✔
2604
    SColumnInfoData data = {0};
997,980✔
2605
    buf = taosDecodeFixedI16(buf, &data.info.colId);
997,980✔
2606
    buf = taosDecodeFixedI8(buf, &data.info.type);
997,980✔
2607
    buf = taosDecodeFixedI32(buf, &data.info.bytes);
997,980✔
2608
    buf = taosDecodeFixedBool(buf, &data.hasNull);
997,980✔
2609

2610
    if (IS_VAR_DATA_TYPE(data.info.type)) {
997,980✔
2611
      buf = taosDecodeBinary(buf, (void**)&data.varmeta.offset, pBlock->info.rows * sizeof(int32_t));
21,850✔
2612
    } else {
2613
      buf = taosDecodeBinary(buf, (void**)&data.nullbitmap, BitmapLen(pBlock->info.rows));
1,974,358✔
2614
    }
2615
    if (buf == NULL) {
998,228✔
2616
      uError("failed to decode null bitmap/offset, type:%d", data.info.type);
×
2617
      goto _error;
×
2618
    }
2619

2620
    int32_t len = 0;
998,228✔
2621
    buf = taosDecodeFixedI32(buf, &len);
998,228✔
2622
    buf = taosDecodeBinary(buf, (void**)&data.pData, len);
998,228✔
2623
    if (buf == NULL) {
998,411✔
2624
      uError("failed to decode data, type:%d", data.info.type);
×
2625
      goto _error;
×
2626
    }
2627
    if (IS_VAR_DATA_TYPE(data.info.type)) {
998,411✔
2628
      data.varmeta.length = len;
11,111✔
2629
      data.varmeta.allocLen = len;
11,111✔
2630
    }
2631

2632
    void* px = taosArrayPush(pBlock->pDataBlock, &data);
998,411✔
2633
    if (px == NULL) {
998,098✔
2634
      return NULL;
×
2635
    }
2636
  }
2637

2638
  return (void*)buf;
934,352✔
2639
_error:
×
2640
  for (int32_t i = 0; i < sz; ++i) {
×
2641
    SColumnInfoData* pColInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
×
2642
    if (pColInfoData == NULL) {
×
2643
      break;
×
2644
    }
2645
    colDataDestroy(pColInfoData);
×
2646
  }
2647
  return NULL;
×
2648
}
2649

2650
static int32_t formatTimestamp(char* buf, size_t cap, int64_t val, int precision) {
20,051,356✔
2651
  time_t  tt;
20,030,736✔
2652
  int32_t ms = 0;
20,051,356✔
2653
  int32_t code = TSDB_CODE_SUCCESS;
20,051,356✔
2654
  int32_t lino = 0;
20,051,356✔
2655
  if (precision == TSDB_TIME_PRECISION_NANO) {
20,051,356✔
2656
    tt = (time_t)(val / 1000000000);
×
2657
    ms = val % 1000000000;
×
2658
  } else if (precision == TSDB_TIME_PRECISION_MICRO) {
20,051,356✔
2659
    tt = (time_t)(val / 1000000);
×
2660
    ms = val % 1000000;
×
2661
  } else {
2662
    tt = (time_t)(val / 1000);
20,051,356✔
2663
    ms = val % 1000;
20,051,356✔
2664
  }
2665

2666
  if (tt <= 0 && ms < 0) {
20,051,356✔
2667
    tt--;
×
2668
    if (precision == TSDB_TIME_PRECISION_NANO) {
×
2669
      ms += 1000000000;
×
2670
    } else if (precision == TSDB_TIME_PRECISION_MICRO) {
×
2671
      ms += 1000000;
×
2672
    } else {
2673
      ms += 1000;
×
2674
    }
2675
  }
2676
  struct tm ptm = {0};
20,051,356✔
2677
  if (taosLocalTime(&tt, &ptm, buf, cap, NULL) == NULL) {
20,051,356✔
2678
    code = TSDB_CODE_INTERNAL_ERROR;
×
2679
    TSDB_CHECK_CODE(code, lino, _end);
×
2680
  }
2681

2682
  size_t pos = taosStrfTime(buf, cap, "%Y-%m-%d %H:%M:%S", &ptm);
20,051,356✔
2683
  if (pos == 0) {
20,051,356✔
2684
    code = TSDB_CODE_OUT_OF_BUFFER;
×
2685
    TSDB_CHECK_CODE(code, lino, _end);
×
2686
  }
2687
  int32_t nwritten = 0;
20,051,356✔
2688
  if (precision == TSDB_TIME_PRECISION_NANO) {
20,051,356✔
2689
    nwritten = snprintf(buf + pos, cap - pos, ".%09d", ms);
×
2690
  } else if (precision == TSDB_TIME_PRECISION_MICRO) {
20,051,356✔
2691
    nwritten = snprintf(buf + pos, cap - pos, ".%06d", ms);
×
2692
  } else {
2693
    nwritten = snprintf(buf + pos, cap - pos, ".%03d", ms);
20,051,356✔
2694
  }
2695

2696
  if (nwritten >= cap - pos) {
20,051,356✔
2697
    code = TSDB_CODE_OUT_OF_BUFFER;
×
2698
    TSDB_CHECK_CODE(code, lino, _end);
×
2699
  }
2700

2701
_end:
20,051,356✔
2702
  if (code != TSDB_CODE_SUCCESS) {
20,051,356✔
2703
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2704
  }
2705
  return code;
20,051,356✔
2706
}
2707

2708
// for debug
2709
int32_t dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf, const char* taskIdStr, int64_t qId) {
1,523,536✔
2710
  int32_t lino = 0;
1,523,536✔
2711
  int32_t size = 2048 * 1024;
1,523,536✔
2712
  int32_t code = 0;
1,523,536✔
2713
  char*   dumpBuf = NULL;
1,523,536✔
2714
  char    pBuf[TD_TIME_STR_LEN] = {0};
1,523,536✔
2715
  int32_t rows = pDataBlock->info.rows;
1,523,536✔
2716
  int32_t len = 0;
1,523,536✔
2717

2718
  dumpBuf = taosMemoryCalloc(size, 1);
1,523,536✔
2719
  if (dumpBuf == NULL) {
1,523,536✔
2720
    return terrno;
×
2721
  }
2722

2723
  int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
1,523,536✔
2724
  len += tsnprintf(dumpBuf + len, size - len,
1,537,984✔
2725
                  "%" PRIx64 " %s %s|child id %d|group id:%" PRIx64 "|uid:%" PRId64 "|rows:%" PRId64
2726
                  "|version:%" PRIu64 "|cal start:%" PRIu64 "|cal end:%" PRIu64 "|tbl:%s\n",
2727
                  qId, taskIdStr, flag, pDataBlock->info.childId,
2728
                  pDataBlock->info.id.groupId, pDataBlock->info.id.uid, pDataBlock->info.rows, pDataBlock->info.version,
2729
                  pDataBlock->info.calWin.skey, pDataBlock->info.calWin.ekey, pDataBlock->info.parTbName);
1,523,536✔
2730
  if (len >= size - 1) {
1,523,536✔
2731
    goto _exit;
×
2732
  }
2733

2734
  for (int32_t j = 0; j < rows; j++) {
22,777,576✔
2735
    len += snprintf(dumpBuf + len, size - len, "%" PRIx64 " %s|", qId, flag);
21,254,006✔
2736
    if (len >= size - 1) {
21,254,006✔
2737
      goto _exit;
×
2738
    }
2739

2740
    for (int32_t k = 0; k < colNum; k++) {
65,376,608✔
2741
      SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k);
44,122,568✔
2742
      if (pColInfoData == NULL) {
44,122,568✔
2743
        code = terrno;
×
2744
        lino = __LINE__;
×
2745
        goto _exit;
×
2746
      }
2747

2748
      if (colDataIsNull(pColInfoData, rows, j, NULL) || !pColInfoData->pData) {
88,245,460✔
2749
        len += snprintf(dumpBuf + len, size - len, " %15s |", "NULL");
573,344✔
2750
        if (len >= size - 1) goto _exit;
573,344✔
2751
        continue;
573,344✔
2752
      }
2753

2754
      void* var = colDataGetData(pColInfoData, j);
43,549,514✔
2755
      switch (pColInfoData->info.type) {
43,549,514✔
2756
        case TSDB_DATA_TYPE_TIMESTAMP:
20,051,356✔
2757
          memset(pBuf, 0, sizeof(pBuf));
20,051,356✔
2758
          code = formatTimestamp(pBuf, sizeof(pBuf), *(uint64_t*)var, pColInfoData->info.precision);
20,051,356✔
2759
          if (code != TSDB_CODE_SUCCESS) {
20,051,356✔
2760
            TAOS_UNUSED(snprintf(pBuf, sizeof(pBuf), "NaN"));
×
2761
          }
2762
          len += snprintf(dumpBuf + len, size - len, " %25s |", pBuf);
20,051,356✔
2763
          if (len >= size - 1) goto _exit;
20,051,356✔
2764
          break;
20,051,356✔
2765
        case TSDB_DATA_TYPE_TINYINT:
1,024✔
2766
          len += snprintf(dumpBuf + len, size - len, " %15d |", *(int8_t*)var);
1,024✔
2767
          if (len >= size - 1) goto _exit;
1,024✔
2768
          break;
1,024✔
2769
        case TSDB_DATA_TYPE_UTINYINT:
×
2770
          len += snprintf(dumpBuf + len, size - len, " %15d |", *(uint8_t*)var);
×
2771
          if (len >= size - 1) goto _exit;
×
2772
          break;
×
2773
        case TSDB_DATA_TYPE_SMALLINT:
×
2774
          len += snprintf(dumpBuf + len, size - len, " %15d |", *(int16_t*)var);
×
2775
          if (len >= size - 1) goto _exit;
×
2776
          break;
×
2777
        case TSDB_DATA_TYPE_USMALLINT:
×
2778
          len += snprintf(dumpBuf + len, size - len, " %15d |", *(uint16_t*)var);
×
2779
          if (len >= size - 1) goto _exit;
×
2780
          break;
×
2781
        case TSDB_DATA_TYPE_INT:
21,318,065✔
2782
          len += snprintf(dumpBuf + len, size - len, " %15d |", *(int32_t*)var);
21,318,065✔
2783
          if (len >= size - 1) goto _exit;
21,318,065✔
2784
          break;
21,318,065✔
2785
        case TSDB_DATA_TYPE_UINT:
×
2786
          len += snprintf(dumpBuf + len, size - len, " %15u |", *(uint32_t*)var);
×
2787
          if (len >= size - 1) goto _exit;
×
2788
          break;
×
2789
        case TSDB_DATA_TYPE_BIGINT:
1,522,525✔
2790
          len += snprintf(dumpBuf + len, size - len, " %15" PRId64 " |", *(int64_t*)var);
1,522,525✔
2791
          if (len >= size - 1) goto _exit;
1,522,525✔
2792
          break;
1,522,525✔
2793
        case TSDB_DATA_TYPE_UBIGINT:
×
2794
          len += snprintf(dumpBuf + len, size - len, " %15" PRIu64 " |", *(uint64_t*)var);
×
2795
          if (len >= size - 1) goto _exit;
×
2796
          break;
×
2797
        case TSDB_DATA_TYPE_FLOAT:
×
2798
          len += snprintf(dumpBuf + len, size - len, " %15f |", *(float*)var);
×
2799
          if (len >= size - 1) goto _exit;
×
2800
          break;
×
2801
        case TSDB_DATA_TYPE_DOUBLE:
55,476✔
2802
          len += snprintf(dumpBuf + len, size - len, " %15f |", *(double*)var);
55,476✔
2803
          if (len >= size - 1) goto _exit;
55,476✔
2804
          break;
55,476✔
2805
        case TSDB_DATA_TYPE_BOOL:
1,656✔
2806
          len += snprintf(dumpBuf + len, size - len, " %15d |", *(bool*)var);
1,656✔
2807
          if (len >= size - 1) goto _exit;
1,656✔
2808
          break;
1,656✔
2809
        case TSDB_DATA_TYPE_VARCHAR:
599,446✔
2810
        case TSDB_DATA_TYPE_VARBINARY:
2811
        case TSDB_DATA_TYPE_GEOMETRY: {
2812
          memset(pBuf, 0, sizeof(pBuf));
599,446✔
2813
          char*   pData = colDataGetVarData(pColInfoData, j);
599,446✔
2814
          int32_t dataSize = TMIN(sizeof(pBuf), varDataLen(pData));
599,446✔
2815
          dataSize = TMIN(dataSize, 50);
599,446✔
2816
          memcpy(pBuf, varDataVal(pData), dataSize);
599,446✔
2817
          len += snprintf(dumpBuf + len, size - len, " %15s |", pBuf);
599,446✔
2818
          if (len >= size - 1) goto _exit;
599,446✔
2819
        } break;
599,446✔
2820
        case TSDB_DATA_TYPE_NCHAR: {
×
2821
          char*   pData = colDataGetVarData(pColInfoData, j);
×
2822
          int32_t dataSize = TMIN(sizeof(pBuf), varDataLen(pData));
×
2823
          memset(pBuf, 0, sizeof(pBuf));
×
2824
          code = taosUcs4ToMbs((TdUcs4*)varDataVal(pData), dataSize, pBuf, NULL);
×
2825
          if (code < 0) {
×
2826
            uError("func %s failed to convert to ucs charset since %s", __func__, tstrerror(code));
×
2827
            lino = __LINE__;
×
2828
            goto _exit;
×
2829
          } else {  // reset the length value
2830
            code = TSDB_CODE_SUCCESS;
×
2831
          }
2832
          len += snprintf(dumpBuf + len, size - len, " %15s |", pBuf);
×
2833
          if (len >= size - 1) goto _exit;
×
2834
        } break;
×
2835
        case TSDB_DATA_TYPE_MEDIUMBLOB:
×
2836
        case TSDB_DATA_TYPE_BLOB: {
2837
          memset(pBuf, 0, sizeof(pBuf));
×
2838
          char*   pData = colDataGetVarData(pColInfoData, j);
×
2839
          int32_t dataSize = TMIN(sizeof(pBuf), blobDataLen(pData));
×
2840
          dataSize = TMIN(dataSize, 50);
×
2841
          memcpy(pBuf, blobDataVal(pData), dataSize);
×
2842
          len += snprintf(dumpBuf + len, size - len, " %15s |", pBuf);
×
2843
          if (len >= size - 1) goto _exit;
×
2844
          break;
×
2845
        }
2846
      }
2847
    }
2848
    len += snprintf(dumpBuf + len, size - len, "%d\n", j);
21,254,040✔
2849
    if (len >= size - 1) goto _exit;
21,254,040✔
2850
  }
2851
  len += snprintf(dumpBuf + len, size - len, "%s |end\n", flag);
1,523,570✔
2852

2853
_exit:
1,523,570✔
2854
  if (code == TSDB_CODE_SUCCESS) {
1,523,570✔
2855
    *pDataBuf = dumpBuf;
1,523,536✔
2856
    dumpBuf = NULL;
1,523,536✔
2857
  } else {
2858
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
34✔
2859
    if (dumpBuf) {
34✔
2860
      taosMemoryFree(dumpBuf);
×
2861
    }
2862
  }
2863
  return code;
1,523,536✔
2864
}
2865

2866
int32_t buildSubmitReqFromDataBlock(SSubmitReq2** ppReq, const SSDataBlock* pDataBlock, const STSchema* pTSchema,
×
2867
                                    int64_t uid, int32_t vgId, tb_uid_t suid) {
2868
  SSubmitReq2* pReq = *ppReq;
×
2869
  SArray*      pVals = NULL;
×
2870
  int32_t      sz = 1;
×
2871
  int32_t      code = 0;
×
2872
  *ppReq = NULL;
×
2873
  terrno = 0;
×
2874

2875
  if (NULL == pReq) {
×
2876
    if (!(pReq = taosMemoryCalloc(1, sizeof(SSubmitReq2)))) {
×
2877
      code = terrno;
×
2878
      goto _end;
×
2879
    }
2880

2881
    if (!(pReq->aSubmitTbData = taosArrayInit(1, sizeof(SSubmitTbData)))) {
×
2882
      code = terrno;
×
2883
      goto _end;
×
2884
    }
2885
  }
2886

2887
  for (int32_t i = 0; i < sz; ++i) {
×
2888
    int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
×
2889
    int32_t rows = pDataBlock->info.rows;
×
2890

2891
    if (colNum <= 1) {  // invalid if only with TS col
×
2892
      continue;
×
2893
    }
2894

2895
    // the rsma result should has the same column number with schema.
2896
    if (colNum != pTSchema->numOfCols) {
×
2897
      uError("colNum %d is not equal to numOfCols %d", colNum, pTSchema->numOfCols);
×
2898
      code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2899
      goto _end;
×
2900
    }
2901

2902
    SSubmitTbData tbData = {0};
×
2903

2904
    if (!(tbData.aRowP = taosArrayInit(rows, sizeof(SRow*)))) {
×
2905
      code = terrno;
×
2906
      goto _end;
×
2907
    }
2908

2909
    tbData.suid = suid;
×
2910
    tbData.uid = uid;
×
2911
    tbData.sver = pTSchema->version;
×
2912

2913
    if (!pVals && !(pVals = taosArrayInit(colNum, sizeof(SColVal)))) {
×
2914
      code = terrno;
×
2915
      taosArrayDestroy(tbData.aRowP);
×
2916
      goto _end;
×
2917
    }
2918

2919
    for (int32_t j = 0; j < rows; ++j) {  // iterate by row
×
2920

2921
      taosArrayClear(pVals);
×
2922

2923
      bool    isStartKey = false;
×
2924
      int32_t offset = 0;
×
2925
      for (int32_t k = 0; k < colNum; ++k) {  // iterate by column
×
2926
        SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k);
×
2927
        if (pColInfoData == NULL) {
×
2928
          return terrno;
×
2929
        }
2930

2931
        const STColumn* pCol = &pTSchema->columns[k];
×
2932
        void*           var = POINTER_SHIFT(pColInfoData->pData, j * pColInfoData->info.bytes);
×
2933

2934
        switch (pColInfoData->info.type) {
×
2935
          case TSDB_DATA_TYPE_TIMESTAMP:
×
2936
            if (pColInfoData->info.type != pCol->type) {
×
2937
              uError("colType:%d mismatch with sechma colType:%d", pColInfoData->info.type, pCol->type);
×
2938
              terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2939
              return terrno;
×
2940
            }
2941
            if (!isStartKey) {
×
2942
              isStartKey = true;
×
2943
              if (PRIMARYKEY_TIMESTAMP_COL_ID != pCol->colId) {
×
2944
                uError("the first timestamp colId %d is not primary colId", pCol->colId);
×
2945
                terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2946
                return terrno;
×
2947
              }
2948
              SValue val = {.type = pCol->type};
×
2949
              VALUE_SET_TRIVIAL_DATUM(&val, *(TSKEY*)var);
×
2950
              SColVal cv = COL_VAL_VALUE(pCol->colId, val);
×
2951
              void*   px = taosArrayPush(pVals, &cv);
×
2952
              if (px == NULL) {
×
2953
                return terrno;
×
2954
              }
2955

2956
            } else if (colDataIsNull_s(pColInfoData, j)) {
×
2957
              SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type);
×
2958
              void*   px = taosArrayPush(pVals, &cv);
×
2959
              if (px == NULL) {
×
2960
                return terrno;
×
2961
              }
2962
            } else {
2963
              SValue val = {.type = pCol->type};
×
2964
              VALUE_SET_TRIVIAL_DATUM(&val, *(int64_t*)var);
×
2965
              SColVal cv = COL_VAL_VALUE(pCol->colId, val);
×
2966
              void*   px = taosArrayPush(pVals, &cv);
×
2967
              if (px == NULL) {
×
2968
                return terrno;
×
2969
              }
2970
            }
2971
            break;
×
2972
          case TSDB_DATA_TYPE_NCHAR:
×
2973
          case TSDB_DATA_TYPE_VARBINARY:
2974
          case TSDB_DATA_TYPE_VARCHAR: {  // TSDB_DATA_TYPE_BINARY
2975
            if (pColInfoData->info.type != pCol->type) {
×
2976
              uError("colType:%d mismatch with sechma colType:%d", pColInfoData->info.type, pCol->type);
×
2977
              terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2978
              return terrno;
×
2979
            }
2980
            if (colDataIsNull_s(pColInfoData, j)) {
×
2981
              SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type);
×
2982
              void*   px = taosArrayPush(pVals, &cv);
×
2983
              if (px == NULL) {
×
2984
                goto _end;
×
2985
              }
2986
            } else {
2987
              void*   data = colDataGetVarData(pColInfoData, j);
×
2988
              SValue  sv = (SValue){.type = pCol->type,
×
2989
                                    .nData = varDataLen(data),
×
2990
                                    .pData = (uint8_t*)varDataVal(data)};  // address copy, no value
×
2991
              SColVal cv = COL_VAL_VALUE(pCol->colId, sv);
×
2992
              void*   px = taosArrayPush(pVals, &cv);
×
2993
              if (px == NULL) {
×
2994
                code = terrno;
×
2995
                goto _end;
×
2996
              }
2997
            }
2998
            break;
×
2999
          }
3000
          case TSDB_DATA_TYPE_DECIMAL:
×
3001
          case TSDB_DATA_TYPE_MEDIUMBLOB:
3002
          case TSDB_DATA_TYPE_BLOB:
3003
            uError("the column type %" PRIi16 " is defined but not implemented yet", pColInfoData->info.type);
×
3004
            terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3005
            return terrno;
×
3006
            break;
3007
          case TSDB_DATA_TYPE_JSON:
×
3008
            uError("the column type %" PRIi16 " is defined but not implemented yet", pColInfoData->info.type);
×
3009
            terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3010
            return terrno;
×
3011
            break;
3012
          default:
×
3013
            if (pColInfoData->info.type < TSDB_DATA_TYPE_MAX && pColInfoData->info.type > TSDB_DATA_TYPE_NULL) {
×
3014
              if (colDataIsNull_s(pColInfoData, j)) {
×
3015
                SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type);  // should use pCol->type
×
3016
                void*   px = taosArrayPush(pVals, &cv);
×
3017
                if (px == NULL) {
×
3018
                  goto _end;
×
3019
                }
3020
              } else {
3021
                SValue sv = {.type = pCol->type};
×
3022
                if (pCol->type == pColInfoData->info.type) {
×
3023
                  valueSetDatum(&sv, sv.type, var, tDataTypes[pCol->type].bytes);
×
3024
                } else {
3025
                  /**
3026
                   *  1. sum/avg would convert to int64_t/uint64_t/double during aggregation
3027
                   *  2. below conversion may lead to overflow or loss, the app should select the right data type.
3028
                   */
3029
                  char tv[DATUM_MAX_SIZE] = {0};
×
3030
                  if (pColInfoData->info.type == TSDB_DATA_TYPE_FLOAT) {
×
3031
                    float v = 0;
×
3032
                    GET_TYPED_DATA(v, float, pColInfoData->info.type, var,
×
3033
                                   typeGetTypeModFromColInfo(&pColInfoData->info));
3034
                    SET_TYPED_DATA(&tv, pCol->type, v);
×
3035
                  } else if (pColInfoData->info.type == TSDB_DATA_TYPE_DOUBLE) {
×
3036
                    double v = 0;
×
3037
                    GET_TYPED_DATA(v, double, pColInfoData->info.type, var,
×
3038
                                   typeGetTypeModFromColInfo(&pColInfoData->info));
3039
                    SET_TYPED_DATA(&tv, pCol->type, v);
×
3040
                  } else if (IS_SIGNED_NUMERIC_TYPE(pColInfoData->info.type)) {
×
3041
                    int64_t v = 0;
×
3042
                    GET_TYPED_DATA(v, int64_t, pColInfoData->info.type, var,
×
3043
                                   typeGetTypeModFromColInfo(&pColInfoData->info));
3044
                    SET_TYPED_DATA(&tv, pCol->type, v);
×
3045
                  } else {
3046
                    uint64_t v = 0;
×
3047
                    GET_TYPED_DATA(v, uint64_t, pColInfoData->info.type, var,
×
3048
                                   typeGetTypeModFromColInfo(&pColInfoData->info));
3049
                    SET_TYPED_DATA(&tv, pCol->type, v);
×
3050
                  }
3051
                  valueSetDatum(&sv, sv.type, tv, tDataTypes[pCol->type].bytes);
×
3052
                }
3053
                SColVal cv = COL_VAL_VALUE(pCol->colId, sv);
×
3054
                void*   px = taosArrayPush(pVals, &cv);
×
3055
                if (px == NULL) {
×
3056
                  code = terrno;
×
3057
                  goto _end;
×
3058
                }
3059
              }
3060
            } else {
3061
              uError("the column type %" PRIi16 " is undefined\n", pColInfoData->info.type);
×
3062
              terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3063
              return terrno;
×
3064
            }
3065
            break;
×
3066
        }
3067
      }
3068
      SRow*             pRow = NULL;
×
3069
      SRowBuildScanInfo sinfo = {0};
×
3070
      if ((code = tRowBuild(pVals, pTSchema, &pRow, &sinfo)) < 0) {
×
3071
        tDestroySubmitTbData(&tbData, TSDB_MSG_FLG_ENCODE);
×
3072
        goto _end;
×
3073
      }
3074

3075
      void* px = taosArrayPush(tbData.aRowP, &pRow);
×
3076
      if (px == NULL) {
×
3077
        code = terrno;
×
3078
        goto _end;
×
3079
      }
3080
    }
3081

3082
    void* px = taosArrayPush(pReq->aSubmitTbData, &tbData);
×
3083
    if (px == NULL) {
×
3084
      code = terrno;
×
3085
      goto _end;
×
3086
    }
3087
  }
3088

3089
_end:
×
3090
  taosArrayDestroy(pVals);
×
3091
  if (code != 0) {
×
3092
    if (pReq) {
×
3093
      tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE);
×
3094
      taosMemoryFreeClear(pReq);
×
3095
    }
3096
  } else {
3097
    *ppReq = pReq;
×
3098
  }
3099

3100
  return code;
×
3101
}
3102

3103
// Construct the child table name in the form of <ctbName>_<stbName>_<groupId> and store it in `ctbName`.
3104
int32_t buildCtbNameAddGroupId(const char* stbName, char* ctbName, uint64_t groupId, size_t cap) {
1,818✔
3105
  int32_t code = TSDB_CODE_SUCCESS;
1,818✔
3106
  int32_t lino = 0;
1,818✔
3107
  char    tmp[TSDB_TABLE_NAME_LEN] = {0};
1,818✔
3108

3109
  if (ctbName == NULL || cap < TSDB_TABLE_NAME_LEN) {
1,818✔
3110
    code = TSDB_CODE_INTERNAL_ERROR;
404✔
3111
    TSDB_CHECK_CODE(code, lino, _end);
404✔
3112
  }
3113

3114
  if (stbName == NULL) {
1,414✔
3115
    snprintf(tmp, TSDB_TABLE_NAME_LEN, "_%" PRIu64, groupId);
404✔
3116
  } else {
3117
    int32_t i = strlen(stbName) - 1;
1,010✔
3118
    for (; i >= 0; i--) {
37,976✔
3119
      if (stbName[i] == '.') {
37,168✔
3120
        break;
202✔
3121
      }
3122
    }
3123
    snprintf(tmp, TSDB_TABLE_NAME_LEN, "_%s_%" PRIu64, stbName + i + 1, groupId);
1,010✔
3124
  }
3125

3126
  ctbName[cap - strlen(tmp) - 1] = 0;  // put stbname + groupId to the end
1,414✔
3127
  size_t prefixLen = strlen(ctbName);
1,414✔
3128
  ctbName = strncat(ctbName, tmp, cap - prefixLen - 1);
1,414✔
3129

3130
  for (char* p = ctbName; *p; ++p) {
66,054✔
3131
    if (*p == '.') *p = '_';
64,640✔
3132
  }
3133

3134
_end:
1,414✔
3135
  if (code != TSDB_CODE_SUCCESS) {
1,818✔
3136
    uError("%s failed at line %d since %s, ctbName:%s", __func__, lino, tstrerror(code), ctbName);
404✔
3137
  }
3138
  return code;
1,818✔
3139
}
3140

3141
// auto stream subtable name starts with 't_', followed by the first segment of MD5 digest for group vals.
3142
// the total length is fixed to be 34 bytes.
3143
bool isAutoTableName(char* ctbName) { return (strlen(ctbName) == 34 && ctbName[0] == 't' && ctbName[1] == '_'); }
×
3144

3145
bool alreadyAddGroupId(char* ctbName, int64_t groupId) {
808✔
3146
  char tmp[64] = {0};
808✔
3147
  snprintf(tmp, sizeof(tmp), "%" PRIu64, groupId);
808✔
3148
  size_t len1 = strlen(ctbName);
808✔
3149
  size_t len2 = strlen(tmp);
808✔
3150
  if (len1 < len2) return false;
808✔
3151
  return memcmp(ctbName + len1 - len2, tmp, len2) == 0;
606✔
3152
}
3153

3154
int32_t buildCtbNameByGroupId(const char* stbFullName, uint64_t groupId, char** pName) {
×
3155
  QRY_PARAM_CHECK(pName);
×
3156

3157
  char* pBuf = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN + 1);
×
3158
  if (!pBuf) {
×
3159
    return terrno;
×
3160
  }
3161

3162
  int32_t code = buildCtbNameByGroupIdImpl(stbFullName, groupId, pBuf);
×
3163
  if (code != TSDB_CODE_SUCCESS) {
×
3164
    taosMemoryFree(pBuf);
×
3165
  } else {
3166
    *pName = pBuf;
×
3167
  }
3168

3169
  return code;
×
3170
}
3171

3172
int32_t buildCtbNameByGroupIdImpl(const char* stbFullName, uint64_t groupId, char* cname) {
×
3173
  if (stbFullName[0] == 0) {
×
3174
    return TSDB_CODE_INVALID_PARA;
×
3175
  }
3176

3177
  SArray* tags = taosArrayInit(0, sizeof(SSmlKv));
×
3178
  if (tags == NULL) {
×
3179
    return terrno;
×
3180
  }
3181

3182
  if (cname == NULL) {
×
3183
    taosArrayDestroy(tags);
×
3184
    return TSDB_CODE_INVALID_PARA;
×
3185
  }
3186

3187
  int8_t      type = TSDB_DATA_TYPE_UBIGINT;
×
3188
  const char* name = "group_id";
×
3189
  int32_t     len = strlen(name);
×
3190

3191
  SSmlKv pTag = {.key = name, .keyLen = len, .type = type, .u = groupId, .length = sizeof(uint64_t)};
×
3192
  void*  px = taosArrayPush(tags, &pTag);
×
3193
  if (px == NULL) {
×
3194
    return terrno;
×
3195
  }
3196

3197
  RandTableName rname = {
×
3198
      .tags = tags, .stbFullName = stbFullName, .stbFullNameLen = strlen(stbFullName), .ctbShortName = cname};
×
3199

3200
  int32_t code = buildChildTableName(&rname);
×
3201
  if (code != TSDB_CODE_SUCCESS) {
×
3202
    return code;
×
3203
  }
3204

3205
  taosArrayDestroy(tags);
×
3206
  if ((rname.ctbShortName && rname.ctbShortName[0]) == 0) {
×
3207
    return TSDB_CODE_INVALID_PARA;
×
3208
  }
3209

3210
  return code;
×
3211
}
3212

3213
int32_t buildSinkDestTableName(char* parTbName, const char* stbFullName, uint64_t gid, bool newSubTableRule,
×
3214
                               char** dstTableName) {
3215
  int32_t code = TSDB_CODE_SUCCESS;
×
3216
  int32_t lino = 0;
×
3217

3218
  if (parTbName[0]) {
×
3219
    if (newSubTableRule && !isAutoTableName(parTbName) && !alreadyAddGroupId(parTbName, gid) && gid != 0 &&
×
3220
        stbFullName) {
3221
      *dstTableName = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN);
×
3222
      TSDB_CHECK_NULL(*dstTableName, code, lino, _end, terrno);
×
3223

3224
      tstrncpy(*dstTableName, parTbName, TSDB_TABLE_NAME_LEN);
×
3225
      code = buildCtbNameAddGroupId(stbFullName, *dstTableName, gid, TSDB_TABLE_NAME_LEN);
×
3226
      TSDB_CHECK_CODE(code, lino, _end);
×
3227
    } else {
3228
      *dstTableName = taosStrdup(parTbName);
×
3229
      TSDB_CHECK_NULL(*dstTableName, code, lino, _end, terrno);
×
3230
    }
3231
  } else {
3232
    code = buildCtbNameByGroupId(stbFullName, gid, dstTableName);
×
3233
    TSDB_CHECK_CODE(code, lino, _end);
×
3234
  }
3235

3236
_end:
×
3237
  return code;
×
3238
}
3239

3240
static int32_t blockCheckSize(int64_t blockSize) {
2,147,483,647✔
3241
  int32_t code = 0;
2,147,483,647✔
3242
  if (blockSize <= 0 || blockSize >= INT32_MAX) {
2,147,483,647✔
3243
    code = TSDB_CODE_OUT_OF_BUFFER;
×
3244
    uError("block size:%" PRId64 ", limit %d since %s", blockSize, INT32_MAX, tstrerror(code));
×
3245
  }
3246
  return code;
2,147,483,647✔
3247
}
3248
// return length of encoded data, return -1 if failed
3249
int32_t blockEncodeImpl(const SSDataBlock* pBlock, char* data, size_t dataBuflen, int32_t numOfCols, bool internal) {
1,039,170,782✔
3250
  int32_t code = blockDataCheck(pBlock);
1,039,170,782✔
3251
  if (code != TSDB_CODE_SUCCESS) {
1,039,253,785✔
3252
    terrno = code;
193✔
3253
    return -1;
×
3254
  }
3255
  int64_t blockSize = 0;
1,039,253,592✔
3256

3257
  int32_t dataLen = 0;
1,039,253,592✔
3258

3259
  // todo extract method
3260
  int32_t* version = (int32_t*)data;
1,039,253,592✔
3261
  *version = BLOCK_VERSION_1;
1,039,253,592✔
3262
  data += sizeof(int32_t);
1,039,224,448✔
3263

3264
  int32_t* actualLen = (int32_t*)data;
1,039,223,462✔
3265
  data += sizeof(int32_t);
1,039,223,462✔
3266

3267
  int32_t* rows = (int32_t*)data;
1,039,215,239✔
3268
  *rows = pBlock->info.rows;
1,039,215,239✔
3269
  data += sizeof(int32_t);
1,039,291,058✔
3270
  if (*rows <= 0) {
1,039,274,031✔
3271
    uError("Invalid rows %d in block", *rows);
×
3272
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3273
    return -1;
×
3274
  }
3275

3276
  int32_t* cols = (int32_t*)data;
1,039,187,068✔
3277
  *cols = numOfCols;
1,039,187,068✔
3278
  data += sizeof(int32_t);
1,039,178,256✔
3279

3280
  // flag segment.
3281
  // the inital bit is for column info
3282
  int32_t* flagSegment = (int32_t*)data;
1,039,310,834✔
3283
  *flagSegment = (1 << 31);
1,039,310,834✔
3284

3285
  data += sizeof(int32_t);
1,039,332,439✔
3286

3287
  uint64_t* groupId = (uint64_t*)data;
1,039,234,806✔
3288
  data += sizeof(uint64_t);
1,039,234,806✔
3289

3290
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
3291
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
3292
    if (pColInfoData == NULL) {
2,147,483,647✔
3293
      return -1;
×
3294
    }
3295

3296
    *((int8_t*)data) = pColInfoData->info.type;
2,147,483,647✔
3297
    data += sizeof(int8_t);
2,147,483,647✔
3298

3299
    int32_t bytes = pColInfoData->info.bytes;
2,147,483,647✔
3300
    *((int32_t*)data) = bytes;
2,147,483,647✔
3301
    if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
3302
      fillBytesForDecimalType((int32_t*)data, pColInfoData->info.type, pColInfoData->info.precision,
60,199,021✔
3303
                              pColInfoData->info.scale);
60,184,222✔
3304
    }
3305
    data += sizeof(int32_t);
2,147,483,647✔
3306
  }
3307

3308
  int32_t* colSizes = (int32_t*)data;
1,039,306,397✔
3309
  data += numOfCols * sizeof(int32_t);
1,039,306,397✔
3310

3311
  dataLen = internal ? blockDataGetSerialMetaSizeInternal(numOfCols) : blockDataGetSerialMetaSize(numOfCols);
1,039,315,596✔
3312
  blockSize = dataLen;
1,039,326,578✔
3313

3314
  int32_t numOfRows = pBlock->info.rows;
1,039,326,578✔
3315
  for (int32_t col = 0; col < numOfCols; ++col) {
2,147,483,647✔
3316
    SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, col);
2,147,483,647✔
3317
    if (pColRes == NULL) {
2,147,483,647✔
3318
      return -1;
×
3319
    }
3320

3321
    // copy the null bitmap
3322
    size_t metaSize = 0;
2,147,483,647✔
3323
    if (IS_VAR_DATA_TYPE(pColRes->info.type)) {
2,147,483,647✔
3324
      if (IS_STR_DATA_BLOB(pColRes->info.type)) {
1,146,737,820✔
3325
        metaSize = numOfRows * sizeof(int32_t);
49,892✔
3326
        if (dataLen + metaSize > dataBuflen) goto _exit;
49,892✔
3327
        memcpy(data, pColRes->varmeta.offset, metaSize);
49,892✔
3328
      } else {
3329
        metaSize = numOfRows * sizeof(int32_t);
1,146,987,579✔
3330
        if (dataLen + metaSize > dataBuflen) goto _exit;
1,146,987,579✔
3331
        memcpy(data, pColRes->varmeta.offset, metaSize);
1,146,987,579✔
3332
      }
3333
    } else {
3334
      metaSize = BitmapLen(numOfRows);
2,147,483,647✔
3335
      if (dataLen + metaSize > dataBuflen) goto _exit;
2,147,483,647✔
3336
      memcpy(data, pColRes->nullbitmap, metaSize);
2,147,483,647✔
3337
    }
3338

3339
    data += metaSize;
2,147,483,647✔
3340
    dataLen += metaSize;
2,147,483,647✔
3341
    blockSize += metaSize;
2,147,483,647✔
3342
    TAOS_CHECK_GOTO(blockCheckSize(blockSize), NULL, _exit);
2,147,483,647✔
3343

3344
    if (pColRes->reassigned && IS_VAR_DATA_TYPE(pColRes->info.type)) {
2,147,483,647✔
3345
      colSizes[col] = 0;
×
3346
      for (int32_t row = 0; row < numOfRows; ++row) {
×
3347
        char*   pColData = pColRes->pData + pColRes->varmeta.offset[row];
×
3348
        int32_t colSize = calcStrBytesByType(pColRes->info.type, pColData);
×
3349

3350
        colSizes[col] += colSize;
×
3351
        dataLen += colSize;
×
3352
        if (dataLen > dataBuflen) goto _exit;
×
3353

3354
        blockSize += colSize;
×
3355
        TAOS_CHECK_GOTO(blockCheckSize(blockSize), NULL, _exit);
×
3356

3357
        (void)memmove(data, pColData, colSize);
×
3358
        data += colSize;
×
3359
      }
3360
    } else {
3361
      colSizes[col] = colDataGetLength(pColRes, numOfRows);
2,147,483,647✔
3362
      dataLen += colSizes[col];
2,147,483,647✔
3363
      if (dataLen > dataBuflen) goto _exit;
2,147,483,647✔
3364

3365
      blockSize += colSizes[col];
2,147,483,647✔
3366
      TAOS_CHECK_GOTO(blockCheckSize(blockSize), NULL, _exit);
2,147,483,647✔
3367

3368
      if (pColRes->pData != NULL) {
2,147,483,647✔
3369
        (void)memmove(data, pColRes->pData, colSizes[col]);
2,147,483,647✔
3370
      }
3371
      data += colSizes[col];
2,147,483,647✔
3372
    }
3373

3374
    if (colSizes[col] <= 0 && !colDataIsNull_s(pColRes, 0) && pColRes->info.type != TSDB_DATA_TYPE_NULL) {
2,147,483,647✔
3375
      uWarn("Invalid colSize:%d colIdx:%d colType:%d while encoding block", colSizes[col], col, pColRes->info.type);
848✔
3376
      //terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
3377
      //return -1;
3378
    }
3379

3380
    colSizes[col] = htonl(colSizes[col]);
2,147,483,647✔
3381
    //    uError("blockEncode col bytes:%d, type:%d, size:%d, htonl size:%d", pColRes->info.bytes, pColRes->info.type,
3382
    //    htonl(colSizes[col]), colSizes[col]);
3383
  }
3384

3385
  bool* blankFill = (bool*)data;
1,039,334,456✔
3386
  *blankFill = pBlock->info.blankFill;
1,039,334,456✔
3387
  data += sizeof(bool);
1,039,328,591✔
3388

3389
  if (internal) {
1,039,368,219✔
3390
    uint8_t* scanFlag = (uint8_t*)data;
43,047,738✔
3391
    *scanFlag = pBlock->info.scanFlag;
43,047,738✔
3392
    data += sizeof(uint8_t);
43,047,738✔
3393

3394
    uint64_t* baseGid = (uint64_t*)data;
43,047,738✔
3395
    *baseGid = pBlock->info.id.baseGId;
43,047,738✔
3396
    data += sizeof(uint64_t);
43,047,738✔
3397

3398
    // Slot ids used only for virtual super table scan: each column's slotId here
3399
    // refers to the slot position in virtual super table's datablock.
3400
    for (int32_t i = 0; i < numOfCols; ++i) {
152,406,433✔
3401
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
109,359,191✔
3402
      if (pColInfoData == NULL) {
109,359,191✔
3403
        return -1;
×
3404
      }
3405

3406
      *((int16_t *)data) = pColInfoData->info.slotId;
109,359,191✔
3407
      data += sizeof(int16_t);
109,358,695✔
3408
    }
3409
  }
3410

3411
  *actualLen = dataLen;
1,039,367,723✔
3412
#ifndef NO_UNALIGNED_ACCESS
3413
  *groupId = pBlock->info.id.groupId;
1,039,297,269✔
3414
#else
3415
  taosSetPUInt64Aligned(groupId, &pBlock->info.id.groupId);
3416
#endif
3417
  if (dataLen > dataBuflen) goto _exit;
1,039,278,369✔
3418

3419
  return dataLen;
1,039,278,369✔
3420

3421
_exit:
×
3422
  uError("blockEncode dataLen:%d, dataBuflen:%zu", dataLen, dataBuflen);
×
3423
  terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3424
  return -1;
×
3425
}
3426

3427
// return length of encoded data, return -1 if failed
3428
int32_t blockEncodeInternal(const SSDataBlock* pBlock, char* data, size_t dataBuflen, int32_t numOfCols) {
43,047,462✔
3429
  return blockEncodeImpl(pBlock, data, dataBuflen, numOfCols, true);
43,047,462✔
3430
}
3431

3432

3433
// return length of encoded data, return -1 if failed
3434
int32_t blockEncode(const SSDataBlock* pBlock, char* data, size_t dataBuflen, int32_t numOfCols) {
996,173,311✔
3435
  return blockEncodeImpl(pBlock, data, dataBuflen, numOfCols, false);
996,173,311✔
3436
}
3437

3438
int32_t blockDecodeImpl(SSDataBlock* pBlock, const char* pData, const char** pEndPos, bool internal) {
676,960,140✔
3439
  const char* pStart = pData;
676,960,140✔
3440

3441
  int32_t version = *(int32_t*)pStart;
676,960,140✔
3442
  pStart += sizeof(int32_t);
676,960,539✔
3443

3444
  // total length sizeof(int32_t)
3445
  int32_t dataLen = *(int32_t*)pStart;
676,961,354✔
3446
  pStart += sizeof(int32_t);
676,961,406✔
3447

3448
  // total rows sizeof(int32_t)
3449
  int32_t numOfRows = *(int32_t*)pStart;
676,961,840✔
3450
  pStart += sizeof(int32_t);
676,962,683✔
3451
  if (numOfRows <= 0) {
676,958,318✔
3452
    uError("block decode numOfRows:%d error", numOfRows);
×
3453
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3454
    return terrno;
×
3455
  }
3456

3457
  // total columns sizeof(int32_t)
3458
  int32_t numOfCols = *(int32_t*)pStart;
676,958,318✔
3459
  pStart += sizeof(int32_t);
676,961,272✔
3460

3461
  // has column info segment
3462
  int32_t flagSeg = *(int32_t*)pStart;
676,963,047✔
3463
  int32_t hasColumnInfo = (flagSeg >> 31);
676,963,047✔
3464
  pStart += sizeof(int32_t);
676,963,047✔
3465

3466
  // group id sizeof(uint64_t)
3467
#ifndef NO_UNALIGNED_ACCESS
3468
  pBlock->info.id.groupId = *(uint64_t*)pStart;
676,960,252✔
3469
#else
3470
  taosSetPUInt64Aligned(&pBlock->info.id.groupId, (uint64_t*)pStart);
3471
#endif
3472
  pStart += sizeof(uint64_t);
676,962,490✔
3473

3474
  if (pBlock->pDataBlock == NULL) {
676,961,108✔
3475
    pBlock->pDataBlock = taosArrayInit_s(sizeof(SColumnInfoData), numOfCols);
29,058,317✔
3476
    if (pBlock->pDataBlock == NULL) {
29,058,317✔
3477
      return terrno;
×
3478
    }
3479
  }
3480

3481
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
3482
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
3483
    if (pColInfoData == NULL) {
2,147,483,647✔
3484
      return terrno;
×
3485
    }
3486

3487
    pColInfoData->info.type = *(int8_t*)pStart;
2,147,483,647✔
3488
    pStart += sizeof(int8_t);
2,147,483,647✔
3489

3490
    pColInfoData->info.bytes = *(int32_t*)pStart;
2,147,483,647✔
3491
    if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
3492
      extractDecimalTypeInfoFromBytes(&pColInfoData->info.bytes, &pColInfoData->info.precision,
58,393,733✔
3493
                                      &pColInfoData->info.scale);
3494
    }
3495
    pStart += sizeof(int32_t);
2,147,483,647✔
3496

3497
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
3498
      pBlock->info.hasVarCol = true;
766,034,197✔
3499
    }
3500
  }
3501

3502
  int32_t code = blockDataEnsureCapacity(pBlock, numOfRows);
676,959,876✔
3503
  if (code) {
676,957,667✔
3504
    return code;
×
3505
  }
3506

3507
  int32_t* colLen = (int32_t*)pStart;
676,957,667✔
3508
  pStart += sizeof(int32_t) * numOfCols;
676,957,667✔
3509

3510
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
3511
    int oneColsLen = htonl(colLen[i]);
2,147,483,647✔
3512
    if (oneColsLen < 0) {
2,147,483,647✔
3513
      uError("block decode colLen:%d error, colIdx:%d", oneColsLen, i);
×
3514
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3515
      return terrno;
×
3516
    }
3517

3518
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
3519
    if (pColInfoData == NULL) {
2,147,483,647✔
3520
      return terrno;
×
3521
    }
3522

3523
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
3524
      memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * numOfRows);
766,027,794✔
3525
      pStart += sizeof(int32_t) * numOfRows;
766,034,704✔
3526

3527
      if (oneColsLen > 0 && pColInfoData->varmeta.allocLen < oneColsLen) {
766,034,704✔
3528
        char* tmp = taosMemoryRealloc(pColInfoData->pData, oneColsLen);
387,643,604✔
3529
        if (tmp == NULL) {
387,643,593✔
3530
          return terrno;
×
3531
        }
3532

3533
        pColInfoData->pData = tmp;
387,643,593✔
3534
        pColInfoData->varmeta.allocLen = oneColsLen;
387,643,593✔
3535
      }
3536

3537
      pColInfoData->varmeta.length = oneColsLen;
766,035,256✔
3538
    } else {
3539
      memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(numOfRows));
2,147,483,647✔
3540
      pStart += BitmapLen(numOfRows);
2,147,483,647✔
3541
    }
3542

3543
    // TODO
3544
    // setting this flag to true temporarily so aggregate function on stable will
3545
    // examine NULL value for non-primary key column
3546
    pColInfoData->hasNull = true;
2,147,483,647✔
3547

3548
    if (oneColsLen > 0) {
2,147,483,647✔
3549
      memcpy(pColInfoData->pData, pStart, oneColsLen);
2,147,483,647✔
3550
    } else if (!colDataIsNull_s(pColInfoData, 0) && pColInfoData->info.type != TSDB_DATA_TYPE_NULL) {
111,993,654✔
3551
      uError("block decode colLen:%d error, colIdx:%d, type:%d", oneColsLen, i, pColInfoData->info.type);
×
3552
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3553
      return terrno;
×
3554
    }
3555

3556
    pStart += oneColsLen;
2,147,483,647✔
3557
  }
3558

3559
  bool blankFill = *(bool*)pStart;
676,958,544✔
3560
  pStart += sizeof(bool);
676,957,613✔
3561

3562
  if (internal && (pStart - pData) < dataLen) {
676,959,584✔
3563
    pBlock->info.scanFlag = *(uint8_t*)pStart;
69,597,358✔
3564
    pStart += sizeof(uint8_t);
69,597,634✔
3565

3566
    pBlock->info.id.baseGId = *(uint64_t*)pStart;
69,597,634✔
3567
    pStart += sizeof(uint64_t);
69,597,347✔
3568
  }
3569

3570
  if (internal && (pStart - pData) < dataLen) {
676,959,573✔
3571
    for (int32_t i = 0; i < numOfCols; ++i) {
250,018,449✔
3572
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
180,420,826✔
3573
      if (pColInfoData == NULL) {
180,421,378✔
3574
        return terrno;
×
3575
      }
3576

3577
      pColInfoData->info.slotId = *(int16_t*)pStart;
180,421,378✔
3578
      pStart += sizeof(int16_t);
180,421,102✔
3579
    }
3580
  }
3581

3582
  pBlock->info.dataLoad = 1;
676,959,573✔
3583
  pBlock->info.rows = numOfRows;
676,959,872✔
3584
  pBlock->info.blankFill = blankFill;
676,961,552✔
3585
  if (internal && (pStart - pData != dataLen)) {
676,959,052✔
3586
    uError("block decode msg len error, pStart:%p, pData:%p, dataLen:%d", pStart, pData, dataLen);
×
3587
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3588
    return terrno;
×
3589
  }
3590

3591
  if (pEndPos != NULL) {
676,959,052✔
3592
    *pEndPos = pStart;
671,467,398✔
3593
  }
3594

3595
  code = blockDataCheck(pBlock);
676,961,033✔
3596
  if (code != TSDB_CODE_SUCCESS) {
676,961,571✔
3597
    terrno = code;
×
3598
    return code;
×
3599
  }
3600

3601
  return TSDB_CODE_SUCCESS;
676,961,847✔
3602
}
3603

3604
int32_t blockDecodeInternal(SSDataBlock* pBlock, const char* pData, const char** pEndPos) {
673,411,326✔
3605
  return blockDecodeImpl(pBlock, pData, pEndPos, true);
673,411,326✔
3606
}
3607
int32_t blockDecode(SSDataBlock* pBlock, const char* pData, const char** pEndPos) {
3,549,966✔
3608
  return blockDecodeImpl(pBlock, pData, pEndPos, false);
3,549,966✔
3609
}
3610

3611
int32_t trimDataBlock(SSDataBlock* pBlock, int32_t totalRows, const bool* pBoolList) {
122,417,698✔
3612
  //  int32_t totalRows = pBlock->info.rows;
3613
  int32_t code = 0;
122,417,698✔
3614
  int32_t bmLen = BitmapLen(totalRows);
122,417,698✔
3615
  char*   pBitmap = NULL;
122,417,698✔
3616
  int32_t maxRows = 0;
122,417,698✔
3617

3618
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
122,417,698✔
3619
  if (!pBoolList) {
122,415,642✔
3620
    for (int32_t i = 0; i < numOfCols; ++i) {
286,279,487✔
3621
      SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
237,196,799✔
3622
      // it is a reserved column for scalar function, and no data in this column yet.
3623
      if (pDst->pData == NULL) {
237,179,124✔
3624
        continue;
7,478,525✔
3625
      }
3626

3627
      int32_t numOfRows = 0;
229,705,003✔
3628
      if (IS_VAR_DATA_TYPE(pDst->info.type)) {
229,705,003✔
3629
        pDst->varmeta.length = 0;
35,959,037✔
3630
      } else {
3631
        memset(pDst->nullbitmap, 0, bmLen);
193,764,045✔
3632
      }
3633
    }
3634
    return code;
49,082,688✔
3635
  }
3636

3637
  for (int32_t i = 0; i < numOfCols; ++i) {
350,022,556✔
3638
    SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
276,696,671✔
3639
    // it is a reserved column for scalar function, and no data in this column yet.
3640
    if (pDst->pData == NULL || (IS_VAR_DATA_TYPE(pDst->info.type) && pDst->varmeta.length == 0)) {
276,699,471✔
3641
      continue;
6,786,217✔
3642
    }
3643

3644
    int32_t numOfRows = 0;
269,923,089✔
3645
    if (IS_VAR_DATA_TYPE(pDst->info.type)) {
327,020,417✔
3646
      int32_t j = 0;
57,106,911✔
3647
      int32_t oriLen = colDataGetLength(pDst, totalRows);
57,106,911✔
3648
      char * tmp = (char*)taosMemoryMalloc(oriLen);
57,098,732✔
3649
      if (tmp == NULL) {
57,095,920✔
3650
        return terrno;
×
3651
      }
3652
      pDst->varmeta.length = 0;
57,095,920✔
3653
      while (j < totalRows) {
2,147,483,647✔
3654
        if (pBoolList[j] == 0) {
2,147,483,647✔
3655
          j += 1;
2,147,483,647✔
3656
          continue;
2,147,483,647✔
3657
        }
3658

3659
        if (colDataIsNull_var(pDst, j)) {
2,147,483,647✔
3660
          colDataSetNull_var(pDst, numOfRows);
1,917,436,697✔
3661
        } else {
3662
          char*   p1 = colDataGetVarData(pDst, j);
2,147,483,647✔
3663
          int32_t len = calcStrBytesByType(pDst->info.type, p1);
2,147,483,647✔
3664
          memcpy(tmp + pDst->varmeta.length, p1, len);
2,147,483,647✔
3665
          pDst->varmeta.offset[numOfRows] = pDst->varmeta.length;
2,147,483,647✔
3666
          pDst->varmeta.length += len;
2,147,483,647✔
3667
        }
3668
        numOfRows += 1;
2,147,483,647✔
3669
        j += 1;
2,147,483,647✔
3670
      }
3671
      taosMemoryFree(pDst->pData);
57,097,013✔
3672
      pDst->pData = tmp;
57,097,328✔
3673
      pDst->varmeta.allocLen = oriLen;
57,097,328✔
3674
      if (maxRows < numOfRows) {
57,097,328✔
3675
        maxRows = numOfRows;
10,148,714✔
3676
      }
3677
    } else {
3678
      if (pBitmap == NULL) {
212,820,470✔
3679
        pBitmap = taosMemoryCalloc(1, bmLen);
71,988,514✔
3680
        if (pBitmap == NULL) {
71,992,068✔
3681
          return terrno;
×
3682
        }
3683
      }
3684

3685
      memcpy(pBitmap, pDst->nullbitmap, bmLen);
212,824,024✔
3686
      memset(pDst->nullbitmap, 0, bmLen);
212,824,644✔
3687

3688
      int32_t j = 0;
212,831,257✔
3689

3690
      switch (pDst->info.type) {
212,831,257✔
3691
        case TSDB_DATA_TYPE_BIGINT:
119,565,307✔
3692
        case TSDB_DATA_TYPE_UBIGINT:
3693
        case TSDB_DATA_TYPE_DOUBLE:
3694
        case TSDB_DATA_TYPE_TIMESTAMP:
3695
          while (j < totalRows) {
2,147,483,647✔
3696
            if (pBoolList[j] == 0) {
2,147,483,647✔
3697
              j += 1;
2,147,483,647✔
3698
              continue;
2,147,483,647✔
3699
            }
3700

3701
            if (BMIsNull(pBitmap, j)) {
2,147,483,647✔
3702
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
2,064,173,236✔
3703
            } else {
3704
              ((int64_t*)pDst->pData)[numOfRows] = ((int64_t*)pDst->pData)[j];
2,147,483,647✔
3705
            }
3706
            numOfRows += 1;
2,147,483,647✔
3707
            j += 1;
2,147,483,647✔
3708
          }
3709
          break;
121,088,084✔
3710
        case TSDB_DATA_TYPE_FLOAT:
61,160,406✔
3711
        case TSDB_DATA_TYPE_INT:
3712
        case TSDB_DATA_TYPE_UINT:
3713
          while (j < totalRows) {
2,147,483,647✔
3714
            if (pBoolList[j] == 0) {
2,147,483,647✔
3715
              j += 1;
2,147,483,647✔
3716
              continue;
2,147,483,647✔
3717
            }
3718
            if (BMIsNull(pBitmap, j)) {
2,147,483,647✔
3719
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
2,068,650,794✔
3720
            } else {
3721
              ((int32_t*)pDst->pData)[numOfRows] = ((int32_t*)pDst->pData)[j];
2,147,483,647✔
3722
            }
3723
            numOfRows += 1;
2,147,483,647✔
3724
            j += 1;
2,147,483,647✔
3725
          }
3726
          break;
61,963,279✔
3727
        case TSDB_DATA_TYPE_SMALLINT:
11,811,196✔
3728
        case TSDB_DATA_TYPE_USMALLINT:
3729
          while (j < totalRows) {
2,147,483,647✔
3730
            if (pBoolList[j] == 0) {
2,147,483,647✔
3731
              j += 1;
2,147,483,647✔
3732
              continue;
2,147,483,647✔
3733
            }
3734
            if (BMIsNull(pBitmap, j)) {
2,147,483,647✔
3735
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
1,364,246,779✔
3736
            } else {
3737
              ((int16_t*)pDst->pData)[numOfRows] = ((int16_t*)pDst->pData)[j];
1,345,665,249✔
3738
            }
3739
            numOfRows += 1;
2,147,483,647✔
3740
            j += 1;
2,147,483,647✔
3741
          }
3742
          break;
11,840,901✔
3743
        case TSDB_DATA_TYPE_BOOL:
17,757,353✔
3744
        case TSDB_DATA_TYPE_TINYINT:
3745
        case TSDB_DATA_TYPE_UTINYINT:
3746
          while (j < totalRows) {
2,147,483,647✔
3747
            if (pBoolList[j] == 0) {
2,147,483,647✔
3748
              j += 1;
2,147,483,647✔
3749
              continue;
2,147,483,647✔
3750
            }
3751
            if (BMIsNull(pBitmap, j)) {
2,147,483,647✔
3752
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
1,838,606,344✔
3753
            } else {
3754
              ((int8_t*)pDst->pData)[numOfRows] = ((int8_t*)pDst->pData)[j];
2,147,483,647✔
3755
            }
3756
            numOfRows += 1;
2,147,483,647✔
3757
            j += 1;
2,147,483,647✔
3758
          }
3759
          break;
17,826,377✔
3760
        case TSDB_DATA_TYPE_DECIMAL64:
2,536,785✔
3761
        case TSDB_DATA_TYPE_DECIMAL:
3762
          while (j < totalRows) {
1,307,437,937✔
3763
            if (pBoolList[j] == 0) {
1,304,888,528✔
3764
              j += 1;
458,208,310✔
3765
              continue;
458,208,310✔
3766
            }
3767
            if (BMIsNull(pBitmap, j)) {
846,701,521✔
3768
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
510,120✔
3769
            } else {
3770
              memcpy(pDst->pData + numOfRows * pDst->info.bytes, pDst->pData + j * pDst->info.bytes, pDst->info.bytes);
846,192,979✔
3771
            }
3772
            numOfRows += 1;
846,692,842✔
3773
            j += 1;
846,692,842✔
3774
          }
3775
          break;
2,549,409✔
3776
        case TSDB_DATA_TYPE_BLOB:
×
3777
        case TSDB_DATA_TYPE_MEDIUMBLOB: {
3778
          // impl later
3779
          break;
×
3780
        }
3781
      }
3782
    }
3783

3784
    if (maxRows < numOfRows) {
269,911,643✔
3785
      maxRows = numOfRows;
63,164,475✔
3786
    }
3787
  }
3788

3789
  pBlock->info.rows = maxRows;
73,325,885✔
3790
  if (pBitmap != NULL) {
73,327,345✔
3791
    taosMemoryFree(pBitmap);
71,993,743✔
3792
  }
3793

3794
  return code;
73,324,161✔
3795
}
3796

3797
int32_t blockGetEncodeSize(const SSDataBlock* pBlock) {
996,547,486✔
3798
  return blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSize(pBlock);
996,547,486✔
3799
}
3800

3801
int32_t blockGetInternalEncodeSize(const SSDataBlock* pBlock) {
53,015,798✔
3802
  return blockDataGetSerialMetaSizeInternal(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSize(pBlock);
53,015,798✔
3803
}
3804

3805

3806
int32_t blockDataGetSortedRows(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
82,561,214✔
3807
  if (!pDataBlock || !pOrderInfo) return 0;
82,561,214✔
3808
  for (int32_t i = 0; i < taosArrayGetSize(pOrderInfo); ++i) {
165,135,278✔
3809
    SBlockOrderInfo* pOrder = taosArrayGet(pOrderInfo, i);
82,566,868✔
3810
    if (pOrder == NULL) {
82,568,924✔
3811
      continue;
×
3812
    }
3813

3814
    pOrder->pColData = taosArrayGet(pDataBlock->pDataBlock, pOrder->slotId);
82,568,924✔
3815
    if (pOrder->pColData == NULL) {
82,570,466✔
3816
      continue;
×
3817
    }
3818

3819
    pOrder->compFn = getKeyComparFunc(pOrder->pColData->info.type, pOrder->order);
82,570,466✔
3820
  }
3821

3822
  SSDataBlockSortHelper sortHelper = {.orderInfo = pOrderInfo, .pDataBlock = pDataBlock};
82,564,812✔
3823

3824
  int32_t rowIdx = 0, nextRowIdx = 1;
82,568,410✔
3825
  for (; rowIdx < pDataBlock->info.rows && nextRowIdx < pDataBlock->info.rows; ++rowIdx, ++nextRowIdx) {
2,147,483,647✔
3826
    if (dataBlockCompar(&nextRowIdx, &rowIdx, &sortHelper) < 0) {
2,147,483,647✔
3827
      break;
27,598,992✔
3828
    }
3829
  }
3830

3831
  return nextRowIdx;
82,570,466✔
3832
}
3833

3834
#define BLOCK_DATA_CHECK_TRESSA(o)                      \
3835
  if (!(o)) {                                           \
3836
    uError("blockDataCheck failed! line:%d", __LINE__); \
3837
    return TSDB_CODE_INTERNAL_ERROR;                    \
3838
  }
3839
int32_t blockDataCheck(const SSDataBlock* pDataBlock) {
2,147,483,647✔
3840
  if (tsSafetyCheckLevel == TSDB_SAFETY_CHECK_LEVELL_NEVER || NULL == pDataBlock || pDataBlock->info.rows == 0) {
2,147,483,647✔
3841
    return TSDB_CODE_SUCCESS;
1,133,989,681✔
3842
  }
3843

3844
  BLOCK_DATA_CHECK_TRESSA(pDataBlock->info.rows > 0);
2,147,483,647✔
3845
  if (!pDataBlock->info.dataLoad) {
2,147,483,647✔
3846
    return TSDB_CODE_SUCCESS;
314,329,791✔
3847
  }
3848

3849
  bool    isVarType = false;
2,147,483,647✔
3850
  int32_t colLen = 0;
2,147,483,647✔
3851
  int32_t nextPos = 0;
2,147,483,647✔
3852
  int64_t checkRows = 0;
2,147,483,647✔
3853
  int64_t typeValue = 0;
2,147,483,647✔
3854
  int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
2,147,483,647✔
3855
  for (int32_t i = 0; i < colNum; ++i) {
2,147,483,647✔
3856
    SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
3857
    BLOCK_DATA_CHECK_TRESSA(pCol != NULL);
2,147,483,647✔
3858
    isVarType = IS_VAR_DATA_TYPE(pCol->info.type);
2,147,483,647✔
3859
    checkRows = pDataBlock->info.rows;
2,147,483,647✔
3860
    if (pCol->info.noData == true) continue;
2,147,483,647✔
3861

3862
    if (isVarType) {
2,147,483,647✔
3863
      BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.offset);
2,147,483,647✔
3864
    } else {
3865
      BLOCK_DATA_CHECK_TRESSA(pCol->nullbitmap);
2,147,483,647✔
3866
    }
3867

3868
    nextPos = -1;
2,147,483,647✔
3869
    for (int64_t r = 0; r < checkRows; ++r) {
2,147,483,647✔
3870
      if (tsSafetyCheckLevel <= TSDB_SAFETY_CHECK_LEVELL_NORMAL) break;
2,147,483,647✔
3871
      if (!colDataIsNull_s(pCol, r)) {
123,852,384✔
3872
        BLOCK_DATA_CHECK_TRESSA(pCol->pData);
61,926,192✔
3873
        BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.length <= pCol->varmeta.allocLen);
61,926,192✔
3874

3875
        if (isVarType) {
61,926,192✔
3876
          BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.allocLen > 0);
51,605,160✔
3877
          BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.offset[r] <= pCol->varmeta.length);
51,605,160✔
3878
          if (pCol->reassigned) {
51,605,160✔
3879
            BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.offset[r] >= 0);
×
3880
          } else if (0 == r || nextPos == -1) {
51,605,160✔
3881
            nextPos = pCol->varmeta.offset[r];
188,340✔
3882
          } else {
3883
            BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.offset[r] == nextPos);
51,416,820✔
3884
          }
3885

3886
          char*   pColData = pCol->pData + pCol->varmeta.offset[r];
51,605,160✔
3887
          int32_t colSize = 0;
51,605,160✔
3888
          if (pCol->info.type == TSDB_DATA_TYPE_JSON) {
51,605,160✔
3889
            colLen = getJsonValueLen(pColData);
×
3890
          } else if (IS_STR_DATA_BLOB(pCol->info.type)) {
51,605,160✔
3891
            colLen = blobDataTLen(pColData);
×
3892
          } else {
3893
            colLen = varDataTLen(pColData);
51,605,160✔
3894
          }
3895

3896
          if (pCol->info.type == TSDB_DATA_TYPE_JSON) {
51,605,160✔
3897
            BLOCK_DATA_CHECK_TRESSA(colLen >= CHAR_BYTES);
×
3898
          } else if (IS_STR_DATA_BLOB(pCol->info.type)) {
51,605,160✔
3899
            // check or not
3900
          } else {
3901
            BLOCK_DATA_CHECK_TRESSA(colLen >= VARSTR_HEADER_SIZE);
51,605,160✔
3902
          }
3903
          if (pCol->reassigned) {
51,605,160✔
3904
            BLOCK_DATA_CHECK_TRESSA((pCol->varmeta.offset[r] + colLen) <= pCol->varmeta.length);
×
3905
          } else {
3906
            nextPos += colLen;
51,605,160✔
3907
            BLOCK_DATA_CHECK_TRESSA(nextPos <= pCol->varmeta.length);
51,605,160✔
3908
          }
3909
          typeValue = *(char*)(pCol->pData + pCol->varmeta.offset[r] + colLen - 1);
51,605,160✔
3910
        } else {
3911
          if (TSDB_DATA_TYPE_FLOAT == pCol->info.type) {
10,321,032✔
3912
            float v = 0;
×
3913
            GET_TYPED_DATA(v, float, pCol->info.type, colDataGetNumData(pCol, r),
×
3914
                           typeGetTypeModFromColInfo(&pCol->info));
3915
          } else if (TSDB_DATA_TYPE_DOUBLE == pCol->info.type) {
10,321,032✔
3916
            double v = 0;
×
3917
            GET_TYPED_DATA(v, double, pCol->info.type, colDataGetNumData(pCol, r),
×
3918
                           typeGetTypeModFromColInfo(&pCol->info));
3919
          } else if (IS_DECIMAL_TYPE(pCol->info.type)) {
10,321,032✔
3920
            // SKIP for decimal types
3921
          } else {
3922
            GET_TYPED_DATA(typeValue, int64_t, pCol->info.type, colDataGetNumData(pCol, r),
10,321,032✔
3923
                           typeGetTypeModFromColInfo(&pCol->info));
3924
          }
3925
        }
3926
      }
3927
    }
3928
  }
3929
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3930
}
3931

3932
int32_t getFirstNotSmallerThanTSRowNum(const char* pts, int32_t startRow, int32_t numOfRows, TSKEY ts) {
26,367,300✔
3933
  int32_t rowNum = -1;
26,367,300✔
3934
  if (numOfRows < 7) {
26,367,300✔
3935
    for (int32_t i = startRow; i < numOfRows; ++i) {
1,704,517✔
3936
      if (ts <= *(TSKEY*)(pts + i * sizeof(TSKEY))) {
1,704,517✔
3937
        rowNum = i;
1,694,064✔
3938
        break;
1,694,064✔
3939
      }
3940
    }
3941
    return rowNum;
1,694,064✔
3942
  }
3943

3944
  int32_t left = startRow;
24,673,236✔
3945
  int32_t right = numOfRows - 1;
24,673,236✔
3946
  rowNum = -1;
24,673,236✔
3947

3948
  while (left <= right) {
171,610,894✔
3949
    int32_t mid = left + (right - left) / 2;
146,937,658✔
3950
    TSKEY midValue = *(TSKEY*)(pts + mid * sizeof(TSKEY));
146,937,658✔
3951

3952
    if (midValue >= ts) {
146,937,658✔
3953
      rowNum = mid;
146,932,748✔
3954
      right = mid - 1;
146,932,748✔
3955
    } else {
3956
      left = mid + 1;
4,910✔
3957
    }
3958
  }
3959

3960
  return rowNum;
24,673,236✔
3961
}
3962

3963
int32_t getFirstBiggerThanTSRowNum(const char* pts, int32_t startRow, int32_t numOfRows, TSKEY ts) {
26,367,607✔
3964
  if (ts == INT64_MAX) return -1;
26,367,607✔
3965
  int32_t rowNum = -1;
24,274,787✔
3966
  if (numOfRows < 7) {
24,274,787✔
3967
    for (int32_t i = 0; i < numOfRows; ++i) {
132,368✔
3968
      if (ts < *(TSKEY*)(pts + i * sizeof(TSKEY))) {
102,157✔
3969
        rowNum = i;
×
3970
        break;
×
3971
      }
3972
    }
3973
    return rowNum;
30,211✔
3974
  }
3975
  int32_t left = startRow;
24,244,576✔
3976
  int32_t right = numOfRows - 1;
24,244,576✔
3977
  rowNum = -1;
24,244,576✔
3978
  while (left <= right) {
193,946,293✔
3979
    int32_t mid = left + (right - left) / 2;
169,701,717✔
3980
    TSKEY midValue = *(TSKEY*)(pts + mid * sizeof(TSKEY));
169,701,717✔
3981

3982
    if (midValue > ts) {
169,701,717✔
3983
      rowNum = mid;
4,040✔
3984
      right = mid - 1;
4,040✔
3985
    } else {
3986
      left = mid + 1;
169,697,677✔
3987
    }
3988
  }
3989
  return rowNum;
24,244,576✔
3990
}
3991

3992
int32_t getFirstNotBiggerThanTSRowNum(const char* pts, int32_t numOfRows, TSKEY ts) {
×
3993
  int32_t rowNum = -1;
×
3994
  for (int32_t i = numOfRows - 1; i >= 0; --i) {
×
3995
    if (ts >= *(TSKEY*)(pts + i * sizeof(TSKEY))) {
×
3996
      rowNum = i;
×
3997
      break;
×
3998
    }
3999
  }
4000
  return rowNum;
×
4001
}
4002

4003
static int32_t resetVarDataOffset(int32_t* pOffset, int32_t numOfRows) {
48,518,598✔
4004
  int32_t offset = 0;
48,518,598✔
4005
  for (int32_t i = 0; i < numOfRows; ++i) {
97,008,286✔
4006
    if (pOffset[i] < 0) {
97,008,092✔
4007
      continue;
48,489,688✔
4008
    } else {
4009
      offset = pOffset[i];
48,518,404✔
4010
      break;
48,518,404✔
4011
    }
4012
  }
4013
  if (offset > 0) {
48,518,598✔
4014
    for (int32_t i = 0; i < numOfRows; ++i) {
155,540✔
4015
      if (pOffset[i] < 0) {
151,500✔
4016
        continue;
75,750✔
4017
      }
4018
      pOffset[i] -= offset;
75,750✔
4019
    }
4020
  }
4021
  return offset;
48,518,598✔
4022
}
4023

4024
void colDataGetOffsetAndLen(const SColumnInfoData* pColumnInfoData, int32_t numOfRows, int32_t startIndex,  int32_t endIndex, int32_t* pOffset, int32_t* pLen) {
109,269,191✔
4025
  *pOffset = 0;
109,269,191✔
4026
  *pLen = 0;
109,269,191✔
4027
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
109,269,191✔
4028
    for (int32_t row = startIndex; row <= endIndex; ++row) {
97,012,350✔
4029
      if (pColumnInfoData->varmeta.offset[row] >= 0) {
97,012,350✔
4030
        *pOffset = pColumnInfoData->varmeta.offset[row];
48,520,634✔
4031
        break;
48,520,634✔
4032
      }
4033
    }
4034
    if (endIndex + 1 < numOfRows) {
48,520,634✔
4035
      for (int32_t row = endIndex + 1; row < numOfRows; ++row) {
10,504✔
4036
        if (pColumnInfoData->varmeta.offset[row] >= 0) {
10,504✔
4037
          *pLen = pColumnInfoData->varmeta.offset[row] - *pOffset;
5,252✔
4038
          return;
5,252✔
4039
        }
4040
      }
4041
    }
4042
    *pLen = pColumnInfoData->varmeta.length - *pOffset;
48,515,382✔
4043
  } else {
4044
    if (pColumnInfoData->info.type == TSDB_DATA_TYPE_NULL) {
60,748,301✔
4045
      return;
×
4046
    } else {
4047
      *pOffset = pColumnInfoData->info.bytes * startIndex;
60,748,557✔
4048
      *pLen = pColumnInfoData->info.bytes * (endIndex - startIndex + 1);
60,748,557✔
4049
    }
4050
  }
4051
}
4052

4053
size_t blockDataGetSizeOfRows(const SSDataBlock* pBlock, int32_t startIndex, int32_t endIndex) {
26,651,715✔
4054
  size_t total = 0;
26,651,715✔
4055
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
26,651,715✔
4056
  for (int32_t i = 0; i < numOfCols; ++i) {
81,286,691✔
4057
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
54,634,976✔
4058
    if (pColInfoData == NULL) {
54,634,976✔
4059
      continue;
×
4060
    }
4061

4062
    int32_t colSize = 0;
54,634,976✔
4063
    int32_t offset = 0;
54,634,976✔
4064
    int32_t numOfRows = endIndex - startIndex + 1;
54,634,976✔
4065

4066
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
54,634,976✔
4067
      total += sizeof(int32_t) * numOfRows;
24,260,317✔
4068
    } else {
4069
      if (pColInfoData->info.type != TSDB_DATA_TYPE_NULL) {
30,374,659✔
4070
        total += (pColInfoData->info.bytes * numOfRows) + BitmapLen(numOfRows);
30,374,659✔
4071
      }
4072
    }
4073

4074
    colDataGetOffsetAndLen(pColInfoData, pBlock->info.rows, startIndex, endIndex, &offset, &colSize);
54,634,976✔
4075
    total += colSize;
54,634,720✔
4076
  }
4077

4078
  return total;
26,651,715✔
4079
}
4080

4081
int32_t blockGetEncodeSizeOfRows(const SSDataBlock* pBlock, int32_t startIndex, int32_t endIndex){
26,651,715✔
4082
  return blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSizeOfRows(pBlock, startIndex, endIndex);
26,651,715✔
4083
}
4084

4085
// return error code if failed
4086
// pLen: return length of encoded data
4087
int32_t blockEncodeAsRows(const SSDataBlock* pBlock, char* data, size_t dataBuflen, int32_t numOfCols, int32_t startIndex, 
26,651,715✔
4088
                          int32_t endIndex, int32_t* pLen) {
4089
  *pLen = 0;
26,651,715✔
4090
  int32_t code = blockDataCheck(pBlock);
26,651,715✔
4091
  if (code != TSDB_CODE_SUCCESS) {
26,651,715✔
4092
    return code;
×
4093
  }
4094

4095
  int32_t dataLen = 0;
26,651,715✔
4096

4097
  // todo extract method
4098
  int32_t* version = (int32_t*)data;
26,651,715✔
4099
  *version = BLOCK_VERSION_1;
26,651,715✔
4100
  data += sizeof(int32_t);
26,651,715✔
4101

4102
  int32_t* actualLen = (int32_t*)data;
26,651,715✔
4103
  data += sizeof(int32_t);
26,651,715✔
4104

4105
  int32_t* rows = (int32_t*)data;
26,651,715✔
4106
  *rows = pBlock->info.rows;
26,651,715✔
4107
  data += sizeof(int32_t);
26,651,715✔
4108
  if (*rows <= 0) {
26,651,715✔
4109
    uError("Invalid rows %d in block", *rows);
×
4110
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4111
  }
4112
  if(*rows <= endIndex) {
26,651,715✔
4113
    uError("Invalid endIdex %d, there is %d rows in block", endIndex, *rows);
×
4114
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4115
  }
4116
  int32_t realRows = endIndex - startIndex + 1;
26,651,715✔
4117
  *rows = realRows;
26,651,715✔
4118

4119
  int32_t* cols = (int32_t*)data;
26,651,715✔
4120
  *cols = numOfCols;
26,651,715✔
4121
  data += sizeof(int32_t);
26,651,715✔
4122

4123
  // flag segment.
4124
  // the inital bit is for column info
4125
  int32_t* flagSegment = (int32_t*)data;
26,651,715✔
4126
  *flagSegment = (1 << 31);
26,651,715✔
4127

4128
  data += sizeof(int32_t);
26,651,715✔
4129

4130
  uint64_t* groupId = (uint64_t*)data;
26,651,715✔
4131
  data += sizeof(uint64_t);
26,651,715✔
4132

4133
  for (int32_t i = 0; i < numOfCols; ++i) {
81,286,691✔
4134
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
54,634,976✔
4135
    if (pColInfoData == NULL) {
54,634,976✔
4136
      return terrno;
×
4137
    }
4138

4139
    *((int8_t*)data) = pColInfoData->info.type;
54,634,976✔
4140
    data += sizeof(int8_t);
54,634,976✔
4141

4142
    int32_t bytes = pColInfoData->info.bytes;
54,634,976✔
4143
    *((int32_t*)data) = bytes;
54,634,976✔
4144
    if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
54,634,976✔
4145
      fillBytesForDecimalType((int32_t*)data, pColInfoData->info.type, pColInfoData->info.precision,
×
4146
                              pColInfoData->info.scale);
×
4147
    }
4148
    data += sizeof(int32_t);
54,634,976✔
4149
  }
4150

4151
  int32_t* colSizes = (int32_t*)data;
26,651,715✔
4152
  data += numOfCols * sizeof(int32_t);
26,651,715✔
4153

4154
  dataLen = blockDataGetSerialMetaSize(numOfCols);
26,651,715✔
4155

4156
  int32_t numOfRows = pBlock->info.rows;
26,651,459✔
4157
  for (int32_t col = 0; col < numOfCols; ++col) {
81,286,691✔
4158
    SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, col);
54,634,976✔
4159
    if (pColRes == NULL) {
54,633,959✔
4160
      return terrno;
×
4161
    }
4162

4163
    // copy the null bitmap
4164
    size_t metaSize = 0;
54,633,959✔
4165
    if (IS_VAR_DATA_TYPE(pColRes->info.type)) {
54,633,959✔
4166
      metaSize = realRows * sizeof(int32_t);
24,260,317✔
4167
      if(dataLen + metaSize > dataBuflen) goto _exit;
24,260,317✔
4168
      TAOS_UNUSED(memcpy(data, (char*)pColRes->varmeta.offset + (startIndex * sizeof(int32_t)), metaSize));
24,260,317✔
4169
      TAOS_UNUSED(resetVarDataOffset((int32_t*)data, realRows));
24,260,317✔
4170
    } else {
4171
      metaSize = BitmapLen(realRows);
30,374,659✔
4172
      if(dataLen + metaSize > dataBuflen) goto _exit;
30,374,659✔
4173
      for (int32_t j = 0; j < realRows; ++j) {
2,147,483,647✔
4174
        if (colDataIsNull_f(pColRes, j + startIndex)) {
2,147,483,647✔
4175
          colDataSetNull_f(data, j);
830,443✔
4176
        }
4177
      }
4178
    }
4179

4180
    data += metaSize;
54,634,720✔
4181
    dataLen += metaSize;
54,634,720✔
4182

4183
    int32_t skipOffset;
6,141,788✔
4184
    colDataGetOffsetAndLen(pColRes, numOfRows, startIndex, endIndex, &skipOffset, &colSizes[col]);
54,634,720✔
4185
    dataLen += colSizes[col];
54,634,976✔
4186
    if (dataLen > dataBuflen) goto _exit;
54,634,976✔
4187
    if (pColRes->pData != NULL) {
54,634,976✔
4188
      (void)memmove(data, pColRes->pData + skipOffset, colSizes[col]);
54,634,976✔
4189
    }
4190
    data += colSizes[col];
54,634,976✔
4191

4192
    if (colSizes[col] <= 0 && !colDataIsNull_s(pColRes, 0) && pColRes->info.type != TSDB_DATA_TYPE_NULL) {
54,634,976✔
4193
      uError("Invalid colSize:%d colIdx:%d colType:%d while encoding block", colSizes[col], col, pColRes->info.type);
×
4194
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4195
    }
4196
    
4197
    colSizes[col] = htonl(colSizes[col]);
54,634,976✔
4198
    //    uError("blockEncode col bytes:%d, type:%d, size:%d, htonl size:%d", pColRes->info.bytes, pColRes->info.type,
4199
    //    htonl(colSizes[col]), colSizes[col]);
4200
  }
4201

4202
  bool* blankFill = (bool*)data;
26,651,715✔
4203
  *blankFill = pBlock->info.blankFill;
26,651,715✔
4204
  data += sizeof(bool);
26,651,715✔
4205

4206
  *actualLen = dataLen;
26,651,715✔
4207
#ifndef NO_UNALIGNED_ACCESS
4208
  *groupId = pBlock->info.id.groupId;
26,651,715✔
4209
#else
4210
  taosSetPUInt64Aligned(groupId, &pBlock->info.id.groupId);
4211
#endif
4212
  if (dataLen > dataBuflen) goto _exit;
26,651,715✔
4213

4214
  *pLen = dataLen;
26,651,715✔
4215
  return TSDB_CODE_SUCCESS;
26,651,715✔
4216
_exit:
×
4217
  uError("blockEncode dataLen:%d, dataBuflen:%zu", dataLen, dataBuflen);
×
4218
  return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4219
}
4220

4221
int32_t getTsColDataOffset(SSDataBlock* pBlock, int32_t* colLen, int32_t numOfRows, int32_t tsColSlotId, int32_t* pOffset) {
26,367,203✔
4222
  *pOffset = 0;
26,367,203✔
4223
  for (int32_t i = 0; i <= tsColSlotId; ++i) {
52,907,243✔
4224
    int oneColsLen = htonl(colLen[i]);
26,540,439✔
4225
    if (oneColsLen < 0) {
26,540,439✔
4226
      uError("block decode colLen:%d error, colIdx:%d", oneColsLen, i);
×
4227
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4228
      return terrno;
×
4229
    }
4230

4231
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
26,540,439✔
4232
    if (pColInfoData == NULL) {
26,540,393✔
4233
      return terrno;
97✔
4234
    }
4235

4236
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
26,540,296✔
UNCOV
4237
      *pOffset += sizeof(int32_t) * numOfRows;
×
4238
    } else {
4239
      *pOffset += BitmapLen(numOfRows);
26,540,296✔
4240
    }
4241
    if (i != tsColSlotId) {
26,540,296✔
4242
      *pOffset += oneColsLen;
173,139✔
4243
    }
4244
  }
4245
  return TSDB_CODE_SUCCESS;
26,366,804✔
4246
}
4247

4248
int32_t blockSpecialDecodeLaterPart(SSDataBlock* pBlock, const char* pData, int32_t tsColSlotId, TSKEY start, TSKEY end) {
26,367,599✔
4249
  int32_t code = TSDB_CODE_SUCCESS;
26,367,599✔
4250

4251
  const char* pStart = pData;
26,367,599✔
4252

4253
  int32_t version = *(int32_t*)pStart;
26,367,599✔
4254
  pStart += sizeof(int32_t);
26,367,599✔
4255

4256
  // total length sizeof(int32_t)
4257
  int32_t dataLen = *(int32_t*)pStart;
26,367,599✔
4258
  pStart += sizeof(int32_t);
26,367,599✔
4259

4260
  // total rows sizeof(int32_t)
4261
  int32_t numOfRows = *(int32_t*)pStart;
26,367,599✔
4262
  pStart += sizeof(int32_t);
26,367,599✔
4263
  if (numOfRows <= 0) {
26,367,087✔
4264
    uError("block decode numOfRows:%d error", numOfRows);
×
4265
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4266
    return terrno;
×
4267
  }
4268

4269
  // total columns sizeof(int32_t)
4270
  int32_t numOfCols = *(int32_t*)pStart;
26,367,087✔
4271
  pStart += sizeof(int32_t);
26,367,599✔
4272

4273
  // has column info segment
4274
  int32_t flagSeg = *(int32_t*)pStart;
26,367,599✔
4275
  int32_t hasColumnInfo = (flagSeg >> 31);
26,367,599✔
4276
  pStart += sizeof(int32_t);
26,367,599✔
4277

4278
  // group id sizeof(uint64_t)
4279
#ifndef NO_UNALIGNED_ACCESS
4280
  pBlock->info.id.groupId = *(uint64_t*)pStart;
26,367,343✔
4281
#else
4282
  taosSetPUInt64Aligned(&pBlock->info.id.groupId, (uint64_t*)pStart);
4283
#endif
4284
  pStart += sizeof(uint64_t);
26,367,343✔
4285

4286
  if (pBlock->pDataBlock == NULL) {
26,367,599✔
4287
    pBlock->pDataBlock = taosArrayInit_s(sizeof(SColumnInfoData), numOfCols);
26,367,502✔
4288
    if (pBlock->pDataBlock == NULL) {
26,367,502✔
4289
      return terrno;
97✔
4290
    }
4291
  }
4292

4293
  for (int32_t i = 0; i < numOfCols; ++i) {
80,147,092✔
4294
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
53,779,905✔
4295
    if (pColInfoData == NULL) {
53,779,086✔
4296
      return terrno;
×
4297
    }
4298

4299
    pColInfoData->info.type = *(int8_t*)pStart;
53,779,086✔
4300
    pStart += sizeof(int8_t);
53,779,342✔
4301

4302
    pColInfoData->info.bytes = *(int32_t*)pStart;
53,779,342✔
4303
    if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
53,779,086✔
UNCOV
4304
      extractDecimalTypeInfoFromBytes(&pColInfoData->info.bytes, &pColInfoData->info.precision,
×
4305
                                      &pColInfoData->info.scale);
4306
    }
4307
    pStart += sizeof(int32_t);
53,779,590✔
4308

4309
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
53,779,590✔
4310
      pBlock->info.hasVarCol = true;
24,258,243✔
4311
    }
4312
  }
4313

4314
  int32_t* colLen = (int32_t*)pStart;
26,367,187✔
4315
  pStart += sizeof(int32_t) * numOfCols;
26,367,187✔
4316

4317
  int32_t tsLen = htonl(colLen[tsColSlotId]);
26,367,187✔
4318
  int32_t tsColOffset;
2,122,749✔
4319
  code = getTsColDataOffset(pBlock, colLen, numOfRows, tsColSlotId, &tsColOffset);
26,367,187✔
4320
  if (code) {
26,367,192✔
4321
    return code;
×
4322
  }
4323
  const char* pts = pStart + tsColOffset;
26,367,192✔
4324
  int32_t     firstRowNum = getFirstNotSmallerThanTSRowNum(pts, 0, numOfRows, start);
26,367,192✔
4325
  if (firstRowNum < 0) {
26,367,801✔
4326
    pBlock->info.rows = 0;
×
4327
    return TSDB_CODE_SUCCESS;
×
4328
  }
4329
  int32_t lastRowNumNext = getFirstBiggerThanTSRowNum(pts, firstRowNum, numOfRows, end);
26,367,801✔
4330
  if (lastRowNumNext < 0) {
26,367,696✔
4331
    lastRowNumNext = numOfRows;
26,366,888✔
4332
  } else if (lastRowNumNext == 0) {
808✔
4333
    pBlock->info.rows = 0;
×
4334
    return TSDB_CODE_SUCCESS;
×
4335
  }
4336

4337
  int32_t realRows = lastRowNumNext - firstRowNum;
26,367,696✔
4338
  int32_t leftRows = numOfRows - lastRowNumNext;
26,367,696✔
4339

4340
  code = blockDataEnsureCapacity(pBlock, realRows);
26,367,696✔
4341
  if (code) {
26,366,395✔
4342
    return code;
×
4343
  }
4344

4345
  for (int32_t i = 0; i < numOfCols; ++i) {
80,146,133✔
4346
    int32_t oneColsLen = htonl(colLen[i]);
53,776,199✔
4347
    int32_t offset = 0;
53,775,943✔
4348
    int32_t leftlen = 0;
53,775,943✔
4349
    if (oneColsLen < 0) {
53,775,943✔
4350
      uError("block decode colLen:%d error, colIdx:%d", oneColsLen, i);
×
4351
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4352
      return terrno;
×
4353
    }
4354

4355
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
53,775,943✔
4356
    if (pColInfoData == NULL) {
53,776,759✔
4357
      return terrno;
×
4358
    }
4359

4360
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
53,776,759✔
4361
      pStart += sizeof(int32_t) * firstRowNum;
24,257,690✔
4362
      memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * realRows);
24,255,663✔
4363
      pStart += sizeof(int32_t) * realRows;
24,255,663✔
4364

4365
      offset = resetVarDataOffset(pColInfoData->varmeta.offset, realRows);
24,255,663✔
4366
      if (leftRows > 0) {
24,258,693✔
4367
        for (int32_t j = 0; j < leftRows; ++j) {
40,602✔
4368
          if (*((int32_t*)pStart + j) != -1) {
39,794✔
4369
            leftlen = oneColsLen - *((int32_t*)pStart + j);
20,200✔
4370
          }
4371
        }
4372
      }
4373
      oneColsLen -= (offset + leftlen);
24,258,693✔
4374
      pStart += sizeof(int32_t) * leftRows;
24,258,693✔
4375

4376
      if (oneColsLen > 0 && pColInfoData->varmeta.allocLen < oneColsLen) {
24,258,693✔
4377
        char* tmp = taosMemoryRealloc(pColInfoData->pData, oneColsLen);
24,258,903✔
4378
        if (tmp == NULL) {
24,258,596✔
4379
          return terrno;
×
4380
        }
4381

4382
        pColInfoData->pData = tmp;
24,258,596✔
4383
        pColInfoData->varmeta.allocLen = oneColsLen;
24,258,596✔
4384
      }
4385

4386
      pColInfoData->varmeta.length = oneColsLen;
24,258,386✔
4387
    } else {
4388
      offset = oneColsLen / numOfRows * firstRowNum;
29,521,096✔
4389
      if (leftRows > 0) {
29,521,096✔
4390
        leftlen = oneColsLen / numOfRows * leftRows;
808✔
4391
      }
4392
      oneColsLen -= (offset + leftlen);
29,521,096✔
4393

4394
      memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(realRows));
29,521,096✔
4395
      for (int32_t j = 0; j < realRows; ++j) {
2,147,483,647✔
4396
        if (BMIsNull(pStart, j + firstRowNum)) {
2,147,483,647✔
4397
          colDataSetNull_f(pColInfoData->nullbitmap, j);
830,443✔
4398
        }
4399
      }
4400
      pStart += BitmapLen(numOfRows);
29,521,608✔
4401
    }
4402

4403
    pColInfoData->hasNull = true;
53,779,994✔
4404

4405
    if (oneColsLen > 0) {
53,779,994✔
4406
      pStart += offset;
53,780,511✔
4407
      memcpy(pColInfoData->pData, pStart, oneColsLen);
53,780,255✔
4408
    } else if (!colDataIsNull_s(pColInfoData, 0) && pColInfoData->info.type != TSDB_DATA_TYPE_NULL) {
×
4409
      uError("block decode colLen:%d error, colIdx:%d, type:%d", oneColsLen, i, pColInfoData->info.type);
×
4410
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4411
      return terrno;
×
4412
    }
4413

4414
    pStart += oneColsLen;
53,779,994✔
4415
    pStart += leftlen;
53,779,994✔
4416
  }
4417

4418
  bool blankFill = *(bool*)pStart;
26,369,934✔
4419
  pStart += sizeof(bool);
26,369,934✔
4420

4421
  pBlock->info.dataLoad = 1;
26,369,934✔
4422
  pBlock->info.rows = realRows;
26,369,934✔
4423
  pBlock->info.blankFill = blankFill;
26,369,934✔
4424
  if (pStart - pData != dataLen) {
26,369,934✔
4425
    uError("block decode msg len error, pStart:%p, pData:%p, dataLen:%d", pStart, pData, dataLen);
×
4426
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4427
    return terrno;
×
4428
  }
4429

4430
  code = blockDataCheck(pBlock);
26,369,934✔
4431
  if (code != TSDB_CODE_SUCCESS) {
26,366,616✔
4432
    terrno = code;
×
4433
    return code;
×
4434
  }
4435

4436
  return TSDB_CODE_SUCCESS;
26,366,721✔
4437
}
4438

4439
int32_t getStreamBlockTS(SSDataBlock* pBlock, int32_t tsColSlotId, int32_t row, TSKEY* ts) {
48,515,078✔
4440
  if (pBlock == NULL || ts == NULL) {
48,515,078✔
4441
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4442
  }
4443

4444
  if (pBlock->info.rows <= 0) {
48,515,078✔
4445
    return TSDB_CODE_SUCCESS;
×
4446
  }
4447
  int32_t cols = taosArrayGetSize(pBlock->pDataBlock);
48,515,078✔
4448
  if (tsColSlotId < 0 || tsColSlotId >= cols) {
48,515,078✔
4449
    uError("Invalid tsColSlotId %d, block has %d columns", tsColSlotId, cols);
×
4450
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4451
  }
4452

4453
  SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, tsColSlotId);
48,515,078✔
4454
  if (pColInfoData == NULL) {
48,515,078✔
4455
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4456
  }
4457

4458
  *ts = *(TSKEY*)(pColInfoData->pData + row * sizeof(TSKEY));
48,515,078✔
4459
  return TSDB_CODE_SUCCESS;
48,515,078✔
4460
}
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