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

taosdata / TDengine / #4917

07 Jan 2026 03:52PM UTC coverage: 65.42% (+0.02%) from 65.402%
#4917

push

travis-ci

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

31 of 34 new or added lines in 2 files covered. (91.18%)

819 existing lines in 129 files now uncovered.

202679 of 309814 relevant lines covered (65.42%)

116724351.99 hits per line

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

69.63
/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) {
980,836,583✔
28
      int32_t totalSize = 0;
25,585✔
29
      for (int32_t row = 0; row < numOfRows; ++row) {
564,332✔
30
        char*   pColData = pColumnInfoData->pData + pColumnInfoData->varmeta.offset[row];
538,747✔
31
        int32_t colSize = calcStrBytesByType(pColumnInfoData->info.type, pColData);
538,747✔
32
        totalSize += colSize;
538,747✔
33
      }
34
      return totalSize;
25,585✔
35
    }
36
    return pColumnInfoData->varmeta.length;
982,756,044✔
37
  } else {
38
    if (pColumnInfoData->info.type == TSDB_DATA_TYPE_NULL) {
2,147,483,647✔
39
      return 0;
4,114,821✔
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) {
662,830,482✔
47
  if (colDataIsNull_s(pColumnInfoData, rowIdx)) {
1,325,662,315✔
48
    return 0;
×
49
  }
50

51
  if (!IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
662,831,833✔
52
    return pColumnInfoData->info.bytes;
534,513,249✔
53
  } else {
54
    return calcStrBytesByType(pColumnInfoData->info.type, colDataGetData(pColumnInfoData, rowIdx));
128,342,023✔
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,484,558,864✔
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) {
7,062,400✔
75
  int32_t dataLen = 0;
7,062,400✔
76
  if (*data == TSDB_DATA_TYPE_NULL) {
7,062,400✔
77
    dataLen = CHAR_BYTES;
161,748✔
78
  } else if (*data == TSDB_DATA_TYPE_NCHAR) {
6,900,652✔
79
    dataLen = varDataTLen(data + CHAR_BYTES) + CHAR_BYTES;
3,014,394✔
80
  } else if (*data == TSDB_DATA_TYPE_DOUBLE) {
3,886,258✔
81
    dataLen = DOUBLE_BYTES + CHAR_BYTES;
334,506✔
82
  } else if (*data == TSDB_DATA_TYPE_BOOL) {
3,551,302✔
83
    dataLen = CHAR_BYTES + CHAR_BYTES;
98,550✔
84
  } else if (tTagIsJson(data)) {  // json string
3,453,202✔
85
    dataLen = ((STag*)(data))->len;
3,453,202✔
86
  } else {
87
    uError("Invalid data type:%d in Json", *data);
×
88
  }
89
  return dataLen;
7,062,400✔
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);
6,603,196✔
96
  } else if (IS_STR_DATA_BLOB(type)) {
2,147,483,647✔
97
    dataLen = blobDataTLen(pData);
568✔
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
static int32_t checkAllocLen(SColumnInfoData* pColumnInfoData, char** pData, int32_t dataLen){
2,147,483,647✔
107
  SVarColAttr* pAttr = &pColumnInfoData->varmeta;
2,147,483,647✔
108
  char* buf = NULL;
2,147,483,647✔
109
  if (pAttr->allocLen < pAttr->length + dataLen) {
2,147,483,647✔
110
    uint32_t newSize = pAttr->allocLen;
2,147,483,647✔
111
    if (newSize <= 1) {
2,147,483,647✔
112
      newSize = 8;
1,005,318,676✔
113
    }
114

115
    while (newSize < pAttr->length + dataLen) {
2,147,483,647✔
116
      newSize = newSize * 1.5;
2,147,483,647✔
117
      if (newSize > UINT32_MAX) {
118
        return TSDB_CODE_OUT_OF_MEMORY;
119
      }
120
    }
121

122
    buf = taosMemoryRealloc(*pData, newSize);
2,147,483,647✔
123
    if (buf == NULL) {
2,147,483,647✔
124
      return terrno;
×
125
    }
126

127
    *pData = buf;
2,147,483,647✔
128
    pAttr->allocLen = newSize;
2,147,483,647✔
129
  }
130
  return 0;
2,147,483,647✔
131
}
132

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

142
    pColumnInfoData->hasNull = true;
2,147,483,647✔
143
    return 0;
2,147,483,647✔
144
  }
145

146
  int32_t type = pColumnInfoData->info.type;
2,147,483,647✔
147
  if (IS_VAR_DATA_TYPE(type)) {
2,147,483,647✔
148
    int32_t dataLen = getDataLen(type, pData);
2,147,483,647✔
149
    if (pColumnInfoData->varmeta.offset[rowIndex] > 0) {
2,147,483,647✔
150
      pColumnInfoData->varmeta.length = pColumnInfoData->varmeta.offset[rowIndex];
21,792✔
151
    }
152

153
    bool overlap = false;
2,147,483,647✔
154
    uint64_t offset = 0;
2,147,483,647✔
155
    if ((uint64_t)pData >= (uint64_t)pColumnInfoData->pData && ((uint64_t)pData + dataLen) <= ((uint64_t)pColumnInfoData->pData + pColumnInfoData->varmeta.allocLen)) {
2,147,483,647✔
156
      overlap = true;
6,336✔
157
      offset = (uint64_t)pData - (uint64_t)pColumnInfoData->pData;
6,336✔
158
    }
159

160
    int32_t code = checkAllocLen(pColumnInfoData, &pColumnInfoData->pData, dataLen);
2,147,483,647✔
161
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
162
      return code;
×
163
    }
164

165
    uint32_t len = pColumnInfoData->varmeta.length;
2,147,483,647✔
166
    pColumnInfoData->varmeta.offset[rowIndex] = len;
2,147,483,647✔
167

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

175
  return 0;
2,147,483,647✔
176
}
177

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

183
  return colDataSetValHelp(pColumnInfoData, rowIndex, pData, isNull);
2,147,483,647✔
184
}
185

186
int32_t colDataSetValOrCover(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull) {
2,147,483,647✔
187
  return colDataSetValHelp(pColumnInfoData, rowIndex, pData, isNull);
2,147,483,647✔
188
}
189

190
int32_t varColSetVarData(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pVarData, int32_t varDataLen,
928,089✔
191
                         bool isNull) {
192
  if (!IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
928,089✔
193
    return TSDB_CODE_INVALID_PARA;
×
194
  }
195

196
  if (isNull || pVarData == NULL) {
928,089✔
197
    pColumnInfoData->varmeta.offset[rowIndex] = -1;  // it is a null value of VAR type.
×
198
    pColumnInfoData->hasNull = true;
×
199
    return TSDB_CODE_SUCCESS;
×
200
  }
201

202
  int32_t dataLen = VARSTR_HEADER_SIZE + varDataLen;
928,089✔
203
  if (pColumnInfoData->varmeta.offset[rowIndex] > 0) {
928,089✔
204
    pColumnInfoData->varmeta.length = pColumnInfoData->varmeta.offset[rowIndex];
×
205
  }
206

207
  int32_t code = checkAllocLen(pColumnInfoData, &pColumnInfoData->pData, dataLen);
928,089✔
208
  if (code != TSDB_CODE_SUCCESS) {
928,089✔
209
    return code;
×
210
  }
211

212
  uint32_t len = pColumnInfoData->varmeta.length;
928,089✔
213
  pColumnInfoData->varmeta.offset[rowIndex] = len;
928,089✔
214

215
  if (IS_STR_DATA_BLOB(pColumnInfoData->info.type)) {
928,089✔
216
    (void)memmove(blobDataVal(pColumnInfoData->pData + len), pVarData, varDataLen);
×
217
    blobDataSetLen(pColumnInfoData->pData + len, varDataLen);
×
218

219
  } else {
220
    (void)memmove(varDataVal(pColumnInfoData->pData + len), pVarData, varDataLen);
928,089✔
221
    varDataSetLen(pColumnInfoData->pData + len, varDataLen);
928,089✔
222
  }
223
  pColumnInfoData->varmeta.length += dataLen;
928,089✔
224
  return TSDB_CODE_SUCCESS;
928,089✔
225
}
226

227
int32_t colDataReassignVal(SColumnInfoData* pColumnInfoData, uint32_t dstRowIdx, uint32_t srcRowIdx,
×
228
                           const char* pData) {
229
  int32_t type = pColumnInfoData->info.type;
×
230
  if (IS_VAR_DATA_TYPE(type)) {
×
231
    pColumnInfoData->varmeta.offset[dstRowIdx] = pColumnInfoData->varmeta.offset[srcRowIdx];
×
232
    pColumnInfoData->reassigned = true;
×
233
  } else {
234
    memcpy(pColumnInfoData->pData + pColumnInfoData->info.bytes * dstRowIdx, pData, pColumnInfoData->info.bytes);
×
235
    colDataClearNull_f(pColumnInfoData->nullbitmap, dstRowIdx);
×
236
  }
237

238
  return 0;
×
239
}
240

241
static int32_t colDataReserve(SColumnInfoData* pColumnInfoData, size_t newSize) {
425,683,414✔
242
  if (!IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
425,683,414✔
243
    return TSDB_CODE_SUCCESS;
×
244
  }
245

246
  if (pColumnInfoData->varmeta.allocLen >= newSize) {
425,686,014✔
247
    return TSDB_CODE_SUCCESS;
×
248
  }
249

250
  uint32_t sizeTmp = pColumnInfoData->varmeta.allocLen;
425,684,314✔
251
  if (sizeTmp <= 1) {
425,684,265✔
252
    sizeTmp = 8;
40,084,858✔
253
  }
254
  while (sizeTmp < newSize) {
1,186,249,160✔
255
    sizeTmp = sizeTmp * 1.5;
760,564,895✔
256
    if (sizeTmp > UINT32_MAX) {
257
      return TSDB_CODE_OUT_OF_MEMORY;
258
    }
259
  }
260
  if (pColumnInfoData->varmeta.allocLen < newSize) {
425,684,265✔
261
    char* buf = taosMemoryRealloc(pColumnInfoData->pData, newSize);
425,684,367✔
262
    if (buf == NULL) {
425,680,049✔
263
      return terrno;
×
264
    }
265

266
    pColumnInfoData->pData = buf;
425,680,049✔
267
    pColumnInfoData->varmeta.allocLen = newSize;
425,681,267✔
268
  }
269

270
  return TSDB_CODE_SUCCESS;
425,681,468✔
271
}
272

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

285
  size_t   start = 1;
2,147,483,647✔
286
  int32_t  t = 0;
2,147,483,647✔
287
  int32_t  count = log(numOfRows) / log(2);
2,147,483,647✔
288
  uint32_t startOffset =
2,147,483,647✔
289
      (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) ? pColumnInfoData->varmeta.length : (currentRow * itemLen);
2,147,483,647✔
290

291
  // the first item
292
  memcpy(pColumnInfoData->pData + startOffset, pData, itemLen);
2,147,483,647✔
293

294
  while (t < count) {
2,147,483,647✔
295
    int32_t xlen = 1 << t;
2,147,483,647✔
296
    memcpy(pColumnInfoData->pData + start * itemLen + startOffset, pColumnInfoData->pData + startOffset,
2,147,483,647✔
297
           xlen * itemLen);
2,147,483,647✔
298
    t += 1;
2,147,483,647✔
299
    start += xlen;
2,147,483,647✔
300
  }
301

302
  // the tail part
303
  if (numOfRows > start) {
2,147,483,647✔
304
    memcpy(pColumnInfoData->pData + start * itemLen + startOffset, pColumnInfoData->pData + startOffset,
914,274,847✔
305
           (numOfRows - start) * itemLen);
914,255,020✔
306
  }
307

308
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
309
    for (int32_t i = 0; i < numOfRows; ++i) {
2,147,483,647✔
310
      pColumnInfoData->varmeta.offset[i + currentRow] = pColumnInfoData->varmeta.length + i * itemLen;
2,147,483,647✔
311
    }
312

313
    pColumnInfoData->varmeta.length += numOfRows * itemLen;
2,035,285,233✔
314
  }
315

316
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
317
}
318

319
int32_t colDataSetNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t numOfRows, uint32_t capacity,
2,147,483,647✔
320
                         bool trimValue) {
321
  int32_t len = pColumnInfoData->info.bytes;
2,147,483,647✔
322
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
323
    len = calcStrBytesByType(pColumnInfoData->info.type, (char*)pData);
2,035,235,754✔
324
    // if (pColumnInfoData->info.type == TSDB_DATA_TYPE_JSON) {
325
    //   len = getJsonValueLen(pData);
326
    // } else if (IS_STR_DATA_BLOB(pColumnInfoData->info.type)) {
327
    //   len = blobDataTLen(pData);
328
    // } else {
329
    //   len = varDataTLen(pData);
330
    // }
331
    if (pColumnInfoData->varmeta.allocLen < (capacity * numOfRows * len + pColumnInfoData->varmeta.length)) {
2,035,274,375✔
332
      int32_t code = colDataReserve(pColumnInfoData, (capacity * numOfRows * len + pColumnInfoData->varmeta.length));
425,683,932✔
333
      if (code != TSDB_CODE_SUCCESS) {
425,681,595✔
334
        return code;
×
335
      }
336
    }
337
  }
338

339
  return doCopyNItems(pColumnInfoData, currentRow, pData, len, numOfRows, trimValue);
2,147,483,647✔
340
}
341

342
void colDataSetNItemsNull(SColumnInfoData* pColumnInfoData, uint32_t currentRow, uint32_t numOfRows) {
97,358,558✔
343
  pColumnInfoData->hasNull = true;
97,358,558✔
344

345
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
97,358,558✔
346
    memset(&pColumnInfoData->varmeta.offset[currentRow], -1, sizeof(int32_t) * numOfRows);
18,645,258✔
347
  } else {
348
    if (numOfRows < 16) {
78,713,300✔
349
      for (int32_t i = 0; i < numOfRows; ++i) {
84,162,006✔
350
        colDataSetNull_f(pColumnInfoData->nullbitmap, currentRow + i);
43,247,526✔
351
      }
352
    } else {
353
      int32_t i = 0;
37,798,820✔
354
      for (; i < numOfRows; ++i) {
37,798,820✔
355
        if (BitPos(currentRow + i)) {
37,798,820✔
356
          colDataSetNull_f(pColumnInfoData->nullbitmap, currentRow + i);
×
357
        } else {
358
          break;
37,798,820✔
359
        }
360
      }
361

362
      int32_t bytes = (numOfRows - i) / 8;
37,798,820✔
363
      memset(&BMCharPos(pColumnInfoData->nullbitmap, currentRow + i), 0xFF, bytes);
37,798,820✔
364
      i += bytes * 8;
37,798,820✔
365

366
      for (; i < numOfRows; ++i) {
37,798,820✔
367
        colDataSetNull_f(pColumnInfoData->nullbitmap, currentRow + i);
×
368
      }
369
    }
370
  }
371
}
97,358,558✔
372

373
int32_t colDataCopyAndReassign(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData,
1,245,972✔
374
                               uint32_t numOfRows) {
375
  int32_t code = colDataSetVal(pColumnInfoData, currentRow, pData, false);
1,245,972✔
376
  if (code) {
1,245,972✔
377
    return code;
×
378
  }
379

380
  if (numOfRows > 1) {
1,245,972✔
381
    int32_t* pOffset = pColumnInfoData->varmeta.offset;
629,097✔
382
    memset(&pOffset[currentRow + 1], pOffset[currentRow], sizeof(pOffset[0]) * (numOfRows - 1));
629,097✔
383
    pColumnInfoData->reassigned = true;
629,097✔
384
  }
385

386
  return code;
1,245,972✔
387
}
388

389
int32_t colDataCopyNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, uint32_t numOfRows,
1,763,765✔
390
                          bool isNull) {
391
  int32_t len = pColumnInfoData->info.bytes;
1,763,765✔
392
  if (isNull) {
1,763,765✔
393
    colDataSetNItemsNull(pColumnInfoData, currentRow, numOfRows);
4,392✔
394
    pColumnInfoData->hasNull = true;
4,392✔
395
    return 0;
4,392✔
396
  }
397

398
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
1,759,373✔
399
    return colDataCopyAndReassign(pColumnInfoData, currentRow, pData, numOfRows);
1,245,972✔
400
  } else {
401
    int32_t  colBytes = pColumnInfoData->info.bytes;
513,401✔
402
    int32_t  colOffset = currentRow * colBytes;
513,401✔
403
    uint32_t num = 1;
513,401✔
404

405
    void* pStart = pColumnInfoData->pData + colOffset;
513,401✔
406
    memcpy(pStart, pData, colBytes);
513,401✔
407
    colOffset += num * colBytes;
513,401✔
408

409
    while (num < numOfRows) {
1,455,454✔
410
      int32_t maxNum = num << 1;
942,053✔
411
      int32_t tnum = maxNum > numOfRows ? (numOfRows - num) : num;
942,053✔
412

413
      memcpy(pColumnInfoData->pData + colOffset, pStart, tnum * colBytes);
942,053✔
414
      colOffset += tnum * colBytes;
942,053✔
415
      num += tnum;
942,053✔
416
    }
417
  }
418

419
  return TSDB_CODE_SUCCESS;
513,401✔
420
}
421

422
static void doBitmapMerge(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, const SColumnInfoData* pSource,
775,294,672✔
423
                          int32_t numOfRow2) {
424
  if (numOfRow2 <= 0) return;
775,294,672✔
425

426
  uint32_t total = numOfRow1 + numOfRow2;
775,294,672✔
427

428
  uint32_t remindBits = BitPos(numOfRow1);
775,294,672✔
429
  uint32_t shiftBits = 8 - remindBits;
775,294,672✔
430

431
  if (remindBits == 0) {  // no need to shift bits of bitmap
775,294,672✔
432
    memcpy(pColumnInfoData->nullbitmap + BitmapLen(numOfRow1), pSource->nullbitmap, BitmapLen(numOfRow2));
391,520,835✔
433
    return;
391,405,657✔
434
  }
435

436
  uint8_t* p = (uint8_t*)pSource->nullbitmap;
383,773,837✔
437
  pColumnInfoData->nullbitmap[BitmapLen(numOfRow1) - 1] &= (0B11111111 << shiftBits);  // clear remind bits
383,832,531✔
438
  pColumnInfoData->nullbitmap[BitmapLen(numOfRow1) - 1] |= (p[0] >> remindBits);       // copy remind bits
383,841,068✔
439

440
  if (BitmapLen(numOfRow1) == BitmapLen(total)) {
383,844,857✔
441
    return;
251,927,406✔
442
  }
443

444
  int32_t len = BitmapLen(numOfRow2);
131,917,451✔
445
  int32_t i = 0;
131,917,451✔
446

447
  uint8_t* start = (uint8_t*)&pColumnInfoData->nullbitmap[BitmapLen(numOfRow1)];
131,917,451✔
448
  int32_t  overCount = BitmapLen(total) - BitmapLen(numOfRow1);
131,915,242✔
449
  memset(start, 0, overCount);
131,915,242✔
450
  while (i < len) {  // size limit of pSource->nullbitmap
2,147,483,647✔
451
    if (i >= 1) {
2,147,483,647✔
452
      start[i - 1] |= (p[i] >> remindBits);  // copy remind bits
2,147,483,647✔
453
    }
454

455
    if (i >= overCount) {  // size limit of pColumnInfoData->nullbitmap
2,147,483,647✔
456
      return;
38,108,822✔
457
    }
458

459
    start[i] |= (p[i] << shiftBits);  // copy shift bits
2,147,483,647✔
460
    i += 1;
2,147,483,647✔
461
  }
462
}
463

464
int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int32_t* capacity,
1,038,225,500✔
465
                        const SColumnInfoData* pSource, int32_t numOfRow2) {
466
  if (pColumnInfoData->info.type != pSource->info.type) {
1,038,225,500✔
467
    return TSDB_CODE_INVALID_PARA;
×
468
  }
469

470
  if (numOfRow2 == 0) {
1,038,252,853✔
471
    return TSDB_CODE_SUCCESS;
1,990✔
472
  }
473

474
  if (pSource->hasNull) {
1,038,250,863✔
475
    pColumnInfoData->hasNull = pSource->hasNull;
320,291,466✔
476
  }
477

478
  uint32_t finalNumOfRows = numOfRow1 + numOfRow2;
1,038,307,939✔
479
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
1,038,307,939✔
480
    // Handle the bitmap
481
    if (finalNumOfRows > (*capacity)) {
262,966,773✔
482
      char* p = taosMemoryRealloc(pColumnInfoData->varmeta.offset, sizeof(int32_t) * (numOfRow1 + numOfRow2));
220,755,236✔
483
      if (p == NULL) {
220,746,291✔
484
        return terrno;
×
485
      }
486

487
      *capacity = finalNumOfRows;
220,746,291✔
488
      pColumnInfoData->varmeta.offset = (int32_t*)p;
220,756,576✔
489
    }
490

491
    for (int32_t i = 0; i < numOfRow2; ++i) {
2,147,483,647✔
492
      if (pSource->varmeta.offset[i] == -1) {
2,147,483,647✔
493
        pColumnInfoData->varmeta.offset[i + numOfRow1] = -1;
2,147,483,647✔
494
      } else {
495
        pColumnInfoData->varmeta.offset[i + numOfRow1] = pSource->varmeta.offset[i] + pColumnInfoData->varmeta.length;
2,147,483,647✔
496
      }
497
    }
498

499
    // copy data
500
    uint32_t len = pSource->varmeta.length;
262,612,207✔
501
    uint32_t oldLen = pColumnInfoData->varmeta.length;
263,020,439✔
502
    if (pColumnInfoData->varmeta.allocLen < len + oldLen) {
263,026,855✔
503
      char* tmp = taosMemoryRealloc(pColumnInfoData->pData, len + oldLen);
206,648,406✔
504
      if (tmp == NULL) {
206,632,193✔
505
        return terrno;
×
506
      }
507

508
      pColumnInfoData->pData = tmp;
206,632,193✔
509
      pColumnInfoData->varmeta.allocLen = len + oldLen;
206,637,544✔
510
    }
511

512
    if (pColumnInfoData->pData && pSource->pData) {  // TD-20382
263,022,582✔
513
      memcpy(pColumnInfoData->pData + oldLen, pSource->pData, len);
248,981,366✔
514
    }
515
    pColumnInfoData->varmeta.length = len + oldLen;
263,017,064✔
516
  } else {
517
    if (finalNumOfRows > (*capacity)) {
775,053,984✔
518
      // all data may be null, when the pColumnInfoData->info.type == 0, bytes == 0;
519
      char* tmp = taosMemoryRealloc(pColumnInfoData->pData, finalNumOfRows * pColumnInfoData->info.bytes);
645,253,473✔
520
      if (tmp == NULL) {
645,165,410✔
521
        return terrno;
×
522
      }
523

524
      pColumnInfoData->pData = tmp;
645,165,410✔
525
      if (BitmapLen(numOfRow1) < BitmapLen(finalNumOfRows)) {
645,145,877✔
526
        char* btmp = taosMemoryRealloc(pColumnInfoData->nullbitmap, BitmapLen(finalNumOfRows));
410,662,434✔
527
        if (btmp == NULL) {
410,600,732✔
528
          return terrno;
×
529
        }
530
        uint32_t extend = BitmapLen(finalNumOfRows) - BitmapLen(numOfRow1);
410,600,732✔
531
        memset(btmp + BitmapLen(numOfRow1), 0, extend);
410,600,732✔
532
        pColumnInfoData->nullbitmap = btmp;
410,725,447✔
533
      }
534

535
      *capacity = finalNumOfRows;
645,261,565✔
536
    }
537

538
    doBitmapMerge(pColumnInfoData, numOfRow1, pSource, numOfRow2);
775,243,599✔
539

540
    if (pSource->pData) {
775,152,156✔
541
      int32_t offset = pColumnInfoData->info.bytes * numOfRow1;
775,185,709✔
542
      memcpy(pColumnInfoData->pData + offset, pSource->pData, pSource->info.bytes * numOfRow2);
775,322,534✔
543
    }
544
  }
545

546
  return TSDB_CODE_SUCCESS;
1,038,275,553✔
547
}
548

549
int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* pSource, int32_t numOfRows,
2,147,483,647✔
550
                      const SDataBlockInfo* pBlockInfo) {
551
  if (pColumnInfoData->info.type != pSource->info.type || (pBlockInfo != NULL && pBlockInfo->capacity < numOfRows)) {
2,147,483,647✔
552
    return TSDB_CODE_INVALID_PARA;
×
553
  }
554

555
  if (numOfRows <= 0) {
2,147,483,647✔
556
    return numOfRows;
14,864,470✔
557
  }
558

559
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
2,147,483,647✔
560
    int32_t newLen = pSource->varmeta.length;
1,373,974,903✔
561
    memcpy(pColumnInfoData->varmeta.offset, pSource->varmeta.offset, sizeof(int32_t) * numOfRows);
1,375,034,867✔
562
    if (pColumnInfoData->varmeta.allocLen < newLen) {
1,375,061,251✔
563
      char* tmp = taosMemoryRealloc(pColumnInfoData->pData, newLen);
696,349,609✔
564
      if (tmp == NULL) {
696,288,519✔
565
        return terrno;
×
566
      }
567

568
      pColumnInfoData->pData = tmp;
696,288,519✔
569
      pColumnInfoData->varmeta.allocLen = newLen;
696,306,255✔
570
    }
571

572
    pColumnInfoData->varmeta.length = newLen;
1,374,989,896✔
573
    if (pColumnInfoData->pData != NULL && pSource->pData != NULL) {
1,374,923,691✔
574
      memcpy(pColumnInfoData->pData, pSource->pData, newLen);
1,255,700,807✔
575
    }
576
  } else {
577
    memcpy(pColumnInfoData->nullbitmap, pSource->nullbitmap, BitmapLen(numOfRows));
2,147,483,647✔
578
    if (pSource->pData != NULL) {
2,147,483,647✔
579
      memcpy(pColumnInfoData->pData, pSource->pData, pSource->info.bytes * numOfRows);
2,147,483,647✔
580
    }
581
  }
582

583
  pColumnInfoData->hasNull = pSource->hasNull;
2,147,483,647✔
584
  pColumnInfoData->info = pSource->info;
2,147,483,647✔
585
  return 0;
2,147,483,647✔
586
}
587

588
int32_t colDataAssignNRows(SColumnInfoData* pDst, int32_t dstIdx, const SColumnInfoData* pSrc, int32_t srcIdx,
1,132,960,134✔
589
                           int32_t numOfRows) {
590
  if (pDst->info.type != pSrc->info.type || pDst->info.bytes != pSrc->info.bytes || pSrc->reassigned) {
1,132,960,134✔
591
    return TSDB_CODE_INVALID_PARA;
×
592
  }
593

594
  if (numOfRows <= 0) {
1,133,010,054✔
595
    return numOfRows;
×
596
  }
597

598
  if (IS_VAR_DATA_TYPE(pDst->info.type)) {
1,306,792,316✔
599
    int32_t allLen = 0;
173,780,750✔
600
    void*   srcAddr = NULL;
173,780,750✔
601
    if (pSrc->hasNull) {
173,780,750✔
602
      for (int32_t i = 0; i < numOfRows; ++i) {
229,396,612✔
603
        if (colDataIsNull_var(pSrc, srcIdx + i)) {
117,346,222✔
604
          pDst->varmeta.offset[dstIdx + i] = -1;
12,608,727✔
605
          pDst->hasNull = true;
12,608,727✔
606
          continue;
12,608,727✔
607
        }
608

609
        char* pData = colDataGetVarData(pSrc, srcIdx + i);
104,737,967✔
610
        if (NULL == srcAddr) {
104,737,495✔
611
          srcAddr = pData;
99,455,898✔
612
        }
613
        int32_t dataLen = calcStrBytesByType(pSrc->info.type, pData);
104,737,495✔
614
        // if (pSrc->info.type == TSDB_DATA_TYPE_JSON) {
615
        //   dataLen = getJsonValueLen(pData);
616
        // } else if (IS_STR_DATA_BLOB(pSrc->info.type)) {
617
        //   dataLen = blobDataTLen(pData);
618
        // } else {
619
        //   dataLen = varDataTLen(pData);
620
        // }
621
        pDst->varmeta.offset[dstIdx + i] = pDst->varmeta.length + allLen;
104,737,967✔
622
        allLen += dataLen;
104,737,495✔
623
      }
624
    } else {
625
      for (int32_t i = 0; i < numOfRows; ++i) {
316,473,490✔
626
        char*   pData = colDataGetVarData(pSrc, srcIdx + i);
254,742,090✔
627
        int32_t dataLen = 0;
254,742,090✔
628
        if (pSrc->info.type == TSDB_DATA_TYPE_JSON) {
254,742,090✔
629
          dataLen = getJsonValueLen(pData);
5,082✔
630
        } else if (IS_STR_DATA_BLOB(pSrc->info.type)) {
254,737,008✔
631
          dataLen = blobDataTLen(pData);
×
632
        } else {
633
          dataLen = varDataTLen(pData);
254,737,008✔
634
        }
635
        pDst->varmeta.offset[dstIdx + i] = pDst->varmeta.length + allLen;
254,742,090✔
636
        allLen += dataLen;
254,742,090✔
637
      }
638
    }
639

640
    if (allLen > 0) {
173,781,790✔
641
      // copy data
642
      if (pDst->varmeta.allocLen < pDst->varmeta.length + allLen) {
161,187,298✔
643
        char* tmp = taosMemoryRealloc(pDst->pData, pDst->varmeta.length + allLen);
160,519,446✔
644
        if (tmp == NULL) {
160,519,446✔
645
          return terrno;
×
646
        }
647

648
        pDst->pData = tmp;
160,519,446✔
649
        pDst->varmeta.allocLen = pDst->varmeta.length + allLen;
160,519,446✔
650
      }
651
      if (pSrc->hasNull) {
161,187,770✔
652
        memcpy(pDst->pData + pDst->varmeta.length, srcAddr, allLen);
99,455,426✔
653
      } else {
654
        memcpy(pDst->pData + pDst->varmeta.length, colDataGetVarData(pSrc, srcIdx), allLen);
61,731,872✔
655
      }
656
      pDst->varmeta.length = pDst->varmeta.length + allLen;
161,187,298✔
657
    }
658
  } else {
659
    if (pSrc->hasNull) {
959,232,424✔
660
      if (BitPos(dstIdx) == BitPos(srcIdx)) {
530,285,790✔
661
        for (int32_t i = 0; i < numOfRows; ++i) {
552,722,899✔
662
          if (0 == BitPos(dstIdx) && (i + (1 << NBIT) <= numOfRows)) {
423,730,460✔
663
            BMCharPos(pDst->nullbitmap, dstIdx + i) = BMCharPos(pSrc->nullbitmap, srcIdx + i);
76,600,456✔
664
            if (BMCharPos(pDst->nullbitmap, dstIdx + i)) {
76,600,456✔
665
              pDst->hasNull = true;
274,579✔
666
            }
667
            i += (1 << NBIT) - 1;
76,600,456✔
668
          } else {
669
            if (colDataIsNull_f(pSrc, srcIdx + i)) {
347,130,004✔
670
              colDataSetNull_f(pDst->nullbitmap, dstIdx + i);
9,295,668✔
671
              pDst->hasNull = true;
9,295,668✔
672
            } else {
673
              colDataClearNull_f(pDst->nullbitmap, dstIdx + i);
337,837,456✔
674
            }
675
          }
676
        }
677
      } else {
678
        for (int32_t i = 0; i < numOfRows; ++i) {
1,321,334,919✔
679
          if (colDataIsNull_f(pSrc, srcIdx + i)) {
920,043,128✔
680
            colDataSetNull_f(pDst->nullbitmap, dstIdx + i);
58,145,050✔
681
            pDst->hasNull = true;
58,145,050✔
682
          } else {
683
            colDataClearNull_f(pDst->nullbitmap, dstIdx + i);
861,898,078✔
684
          }
685
        }
686
      }
687
    }
688

689
    if (pSrc->pData != NULL) {
959,229,824✔
690
      memcpy(pDst->pData + pDst->info.bytes * dstIdx, pSrc->pData + pSrc->info.bytes * srcIdx,
959,225,664✔
691
             pDst->info.bytes * numOfRows);
959,221,976✔
692
    }
693
  }
694

695
  return 0;
1,132,958,054✔
696
}
697

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

700
size_t blockDataGetNumOfRows(const SSDataBlock* pBlock) { return pBlock->info.rows; }
627,285,674✔
701

702
int32_t blockDataUpdateTsWindow(SSDataBlock* pDataBlock, int32_t tsColumnIndex) {
2,147,483,647✔
703
  if (pDataBlock == NULL || pDataBlock->info.rows <= 0 || pDataBlock->info.dataLoad == 0) {
2,147,483,647✔
704
    return 0;
115,676,521✔
705
  }
706

707
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
2,147,483,647✔
708
  if (numOfCols <= 0) {
2,147,483,647✔
709
    return 0;
1,067,011✔
710
  }
711

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

714
  SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, index);
2,147,483,647✔
715
  if (pColInfoData == NULL) {
2,147,483,647✔
716
    return 0;
×
717
  }
718

719
  if (pColInfoData->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
2,147,483,647✔
720
    return 0;
1,969,803,779✔
721
  }
722

723
  TSKEY skey = *(TSKEY*)colDataGetData(pColInfoData, 0);
913,313,956✔
724
  TSKEY ekey = *(TSKEY*)colDataGetData(pColInfoData, (pDataBlock->info.rows - 1));
913,322,462✔
725

726
  pDataBlock->info.window.skey = TMIN(skey, ekey);
913,304,539✔
727
  pDataBlock->info.window.ekey = TMAX(skey, ekey);
913,338,947✔
728

729
  return 0;
913,186,223✔
730
}
731

732
int32_t blockDataUpdatePkRange(SSDataBlock* pDataBlock, int32_t pkColumnIndex, bool asc) {
635,090,228✔
733
  if (pDataBlock == NULL || pDataBlock->info.rows <= 0 || pDataBlock->info.dataLoad == 0 || pkColumnIndex == -1) {
635,090,228✔
734
    return 0;
559,509,978✔
735
  }
736

737
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
75,718,302✔
738
  if (numOfCols <= 0) {
75,709,976✔
739
    return -1;
×
740
  }
741

742
  SDataBlockInfo*  pInfo = &pDataBlock->info;
75,709,976✔
743
  SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, pkColumnIndex);
75,710,509✔
744
  if (pColInfoData == NULL) {
75,714,331✔
745
    return terrno;
×
746
  }
747

748
  if (!IS_NUMERIC_TYPE(pColInfoData->info.type) && (pColInfoData->info.type != TSDB_DATA_TYPE_VARCHAR)) {
75,714,331✔
749
    return 0;
×
750
  }
751

752
  void* skey = colDataGetData(pColInfoData, 0);
75,716,105✔
753
  void* ekey = colDataGetData(pColInfoData, (pInfo->rows - 1));
75,708,504✔
754

755
  int64_t val = 0;
75,684,219✔
756
  if (asc) {
75,684,219✔
757
    if (IS_NUMERIC_TYPE(pColInfoData->info.type)) {
29,509,459✔
758
      GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, skey, typeGetTypeModFromColInfo(&pColInfoData->info));
20,187,472✔
759
      VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[0], val);
20,184,224✔
760
      GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, ekey, typeGetTypeModFromColInfo(&pColInfoData->info));
20,184,853✔
761
      VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[1], val);
20,184,224✔
762
    } else {  // todo refactor
763
      memcpy(pInfo->pks[0].pData, varDataVal(skey), varDataLen(skey));
9,321,318✔
764
      pInfo->pks[0].nData = varDataLen(skey);
9,329,724✔
765

766
      memcpy(pInfo->pks[1].pData, varDataVal(ekey), varDataLen(ekey));
9,330,902✔
767
      pInfo->pks[1].nData = varDataLen(ekey);
9,329,095✔
768
    }
769
  } else {
770
    if (IS_NUMERIC_TYPE(pColInfoData->info.type)) {
46,174,760✔
771
      GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, ekey, typeGetTypeModFromColInfo(&pColInfoData->info));
26,357,929✔
772
      VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[0], val);
26,347,948✔
773
      GET_TYPED_DATA(val, int64_t, pColInfoData->info.type, skey, typeGetTypeModFromColInfo(&pColInfoData->info));
26,351,482✔
774
      VALUE_SET_TRIVIAL_DATUM(&pInfo->pks[1], val);
26,349,715✔
775
    } else {  // todo refactor
776
      memcpy(pInfo->pks[0].pData, varDataVal(ekey), varDataLen(ekey));
19,827,990✔
777
      pInfo->pks[0].nData = varDataLen(ekey);
19,838,067✔
778

779
      memcpy(pInfo->pks[1].pData, varDataVal(skey), varDataLen(skey));
19,839,834✔
780
      pInfo->pks[1].nData = varDataLen(skey);
19,839,213✔
781
    }
782
  }
783

784
  return 0;
75,700,583✔
785
}
786

787
int32_t blockDataMerge(SSDataBlock* pDest, const SSDataBlock* pSrc) {
276,549,111✔
788
  int32_t code = 0;
276,549,111✔
789
  int32_t capacity = pDest->info.capacity;
276,549,111✔
790
  size_t  numOfCols = taosArrayGetSize(pDest->pDataBlock);
276,582,220✔
791
  for (int32_t i = 0; i < numOfCols; ++i) {
1,314,894,511✔
792
    SColumnInfoData* pCol2 = taosArrayGet(pDest->pDataBlock, i);
1,038,218,383✔
793
    SColumnInfoData* pCol1 = taosArrayGet(pSrc->pDataBlock, i);
1,038,234,903✔
794
    if (pCol1 == NULL || pCol2 == NULL) {
1,038,133,263✔
795
      return terrno;
46,043✔
796
    }
797

798
    capacity = pDest->info.capacity;
1,038,087,220✔
799
    int32_t ret = colDataMergeCol(pCol2, pDest->info.rows, &capacity, pCol1, pSrc->info.rows);
1,038,149,529✔
800
    if (ret < 0) {  // error occurs
1,038,256,102✔
801
      code = ret;
×
802
      return code;
×
803
    }
804
  }
805

806
  pDest->info.capacity = capacity;
276,676,128✔
807
  pDest->info.rows += pSrc->info.rows;
276,682,093✔
808
  return code;
276,526,749✔
809
}
810

811
void blockDataTransform(SSDataBlock* pDest, const SSDataBlock* pSrc) {
6,303,166✔
812
  size_t  numOfCols = taosArrayGetSize(pDest->pDataBlock);
6,303,166✔
813
  size_t  numOfColsSrc = taosArrayGetSize(pSrc->pDataBlock);
6,306,617✔
814
  for (int32_t i = 0; i < numOfCols; ++i) {
19,308,823✔
815
    SColumnInfoData* pCol1 = taosArrayGet(pDest->pDataBlock, i);
13,001,597✔
816
    for (int32_t j = 0; j < numOfColsSrc; ++j) {
20,586,734✔
817
      SColumnInfoData* pCol2 = taosArrayGet(pSrc->pDataBlock, j);
20,585,922✔
818
      if (pCol1->info.colId == pCol2->info.colId) {
20,586,937✔
819
        TSWAP(*pCol1, *pCol2);
13,002,612✔
820
        break;
13,002,612✔
821
      }
822
    }
823
  }
824

825
  pDest->info.rows = pSrc->info.rows;
6,307,226✔
826
  pDest->info.capacity = pSrc->info.rows;
6,306,008✔
827
}
6,306,617✔
828

829
int32_t blockDataMergeNRows(SSDataBlock* pDest, const SSDataBlock* pSrc, int32_t srcIdx, int32_t numOfRows) {
656,893✔
830
  int32_t code = 0, lino = 0;
656,893✔
831
  if (pDest->info.rows + numOfRows > pDest->info.capacity) {
656,893✔
832
    uError("block capacity %d not enough to merge %d rows, currRows:%" PRId64, pDest->info.capacity, numOfRows, pDest->info.rows);
×
833
    TAOS_CHECK_EXIT(TSDB_CODE_INVALID_PARA);
×
834
  }
835

836
  size_t numOfCols = taosArrayGetSize(pDest->pDataBlock);
656,893✔
837
  for (int32_t i = 0; i < numOfCols; ++i) {
2,095,223✔
838
    SColumnInfoData* pCol2 = taosArrayGet(pDest->pDataBlock, i);
1,438,330✔
839
    TSDB_CHECK_NULL(pCol2, code, lino, _exit, terrno);
1,438,330✔
840
    SColumnInfoData* pCol1 = taosArrayGet(pSrc->pDataBlock, i);
1,438,330✔
841
    TSDB_CHECK_NULL(pCol1, code, lino, _exit, terrno);
1,438,330✔
842

843
    TAOS_CHECK_EXIT(colDataAssignNRows(pCol2, pDest->info.rows, pCol1, srcIdx, numOfRows));
1,438,330✔
844
  }
845

846
  pDest->info.rows += numOfRows;
656,893✔
847

848
_exit:
656,893✔
849

850
  if (code) {
656,893✔
851
    uError("%s failed at line %d since %s", __FUNCTION__, lino, tstrerror(code));
×
852
  }
853
  
854
  return code;
656,893✔
855
}
856

857
void blockDataShrinkNRows(SSDataBlock* pBlock, int32_t numOfRows) {
×
858
  if (numOfRows == 0) {
×
859
    return;
×
860
  }
861

862
  if (numOfRows >= pBlock->info.rows) {
×
863
    blockDataCleanup(pBlock);
×
864
    return;
×
865
  }
866

867
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
×
868
  for (int32_t i = 0; i < numOfCols; ++i) {
×
869
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
×
870
    if (pCol == NULL) {
×
871
      continue;
×
872
    }
873

874
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
×
875
      pCol->varmeta.length = pCol->varmeta.offset[pBlock->info.rows - numOfRows];
×
876
      memset(pCol->varmeta.offset + pBlock->info.rows - numOfRows, 0, sizeof(*pCol->varmeta.offset) * numOfRows);
×
877
    } else {
878
      int32_t i = pBlock->info.rows - numOfRows;
×
879
      for (; i < pBlock->info.rows; ++i) {
×
880
        if (BitPos(i)) {
×
881
          colDataClearNull_f(pCol->nullbitmap, i);
×
882
        } else {
883
          break;
×
884
        }
885
      }
886

887
      int32_t bytes = (pBlock->info.rows - i) / 8;
×
888
      memset(&BMCharPos(pCol->nullbitmap, i), 0, bytes);
×
889
      i += bytes * 8;
×
890

891
      for (; i < pBlock->info.rows; ++i) {
×
892
        colDataClearNull_f(pCol->nullbitmap, i);
×
893
      }
894
    }
895
  }
896

897
  pBlock->info.rows -= numOfRows;
×
898
}
899

900
size_t blockDataGetSize(const SSDataBlock* pBlock) {
2,147,483,647✔
901
  size_t total = 0;
2,147,483,647✔
902
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
2,147,483,647✔
903
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
904
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
905
    if (pColInfoData == NULL) {
2,147,483,647✔
906
      continue;
×
907
    }
908

909
    total += colDataGetFullLength(pColInfoData, pBlock->info.rows);
2,147,483,647✔
910
  }
911

912
  return total;
2,147,483,647✔
913
}
914

915
// the number of tuples can be fit in one page.
916
// Actual data rows pluses the corresponding meta data must fit in one memory buffer of the given page size.
917
int32_t blockDataSplitRows(SSDataBlock* pBlock, bool hasVarCol, int32_t startIndex, int32_t* stopIndex,
32,882,765✔
918
                           int32_t pageSize) {
919
  size_t  numOfCols = taosArrayGetSize(pBlock->pDataBlock);
32,882,765✔
920
  int32_t numOfRows = pBlock->info.rows;
32,882,765✔
921

922
  int32_t bitmapChar = 1;
32,882,765✔
923

924
  size_t headerSize = sizeof(int32_t);
32,882,765✔
925
  size_t colHeaderSize = sizeof(int32_t) * numOfCols;
32,882,765✔
926

927
  // TODO speedup by checking if the whole page can fit in firstly.
928
  if (!hasVarCol) {
32,882,765✔
929
    size_t  rowSize = blockDataGetRowSize(pBlock);
2,033,370✔
930
    int32_t capacity = blockDataGetCapacityInRow(pBlock, pageSize, headerSize + colHeaderSize);
2,033,370✔
931
    if (capacity <= 0) {
2,033,370✔
932
      return terrno;
×
933
    }
934

935
    *stopIndex = startIndex + capacity - 1;
2,033,370✔
936
    if (*stopIndex >= numOfRows) {
2,033,370✔
937
      *stopIndex = numOfRows - 1;
2,040✔
938
    }
939

940
    return TSDB_CODE_SUCCESS;
2,033,370✔
941
  }
942
  // iterate the rows that can be fit in this buffer page
943
  int32_t size = (headerSize + colHeaderSize);
30,849,395✔
944
  for (int32_t j = startIndex; j < numOfRows; ++j) {
1,383,245,685✔
945
    for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
946
      SColumnInfoData* pColInfoData = TARRAY_GET_ELEM(pBlock->pDataBlock, i);
2,147,483,647✔
947
      if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
948
        if (pColInfoData->varmeta.offset[j] != -1) {
2,147,483,647✔
949
          char* p = colDataGetData(pColInfoData, j);
2,147,483,647✔
950
          if (IS_STR_DATA_BLOB(pColInfoData->info.type)) {
2,147,483,647✔
951
            size += blobDataTLen(p);
×
952
          } else {
953
            size += varDataTLen(p);
2,147,483,647✔
954
          }
955
        }
956

957
        size += sizeof(pColInfoData->varmeta.offset[0]);
2,147,483,647✔
958
      } else {
959
        size += pColInfoData->info.bytes;
2,147,483,647✔
960

961
        if (((j - startIndex) & 0x07) == 0) {
2,147,483,647✔
962
          size += 1;  // the space for null bitmap
1,911,311,220✔
963
        }
964
      }
965
    }
966

967
    if (size > pageSize) {  // pageSize must be able to hold one row
1,383,213,718✔
968
      *stopIndex = j - 1;
30,817,428✔
969
      if (*stopIndex < startIndex) {
30,817,428✔
970
        return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
971
      }
972

973
      return TSDB_CODE_SUCCESS;
30,817,428✔
974
    }
975
  }
976

977
  // all fit in
978
  *stopIndex = numOfRows - 1;
31,967✔
979
  return TSDB_CODE_SUCCESS;
31,967✔
980
}
981

982
int32_t blockDataExtractBlock(SSDataBlock* pBlock, int32_t startIndex, int32_t rowCount, SSDataBlock** pResBlock) {
40,687,470✔
983
  int32_t code = 0;
40,687,470✔
984
  QRY_PARAM_CHECK(pResBlock);
40,687,470✔
985

986
  if (pBlock == NULL || startIndex < 0 || rowCount > pBlock->info.rows || rowCount + startIndex > pBlock->info.rows) {
40,687,470✔
987
    return TSDB_CODE_INVALID_PARA;
×
988
  }
989

990
  SSDataBlock* pDst = NULL;
40,687,470✔
991
  code = createOneDataBlock(pBlock, false, &pDst);
40,687,470✔
992
  if (code) {
40,687,470✔
993
    return code;
×
994
  }
995

996
  code = blockDataEnsureCapacity(pDst, rowCount);
40,687,470✔
997
  if (code) {
40,686,430✔
998
    blockDataDestroy(pDst);
×
999
    return code;
×
1000
  }
1001

1002
  /* may have disorder varchar data, TODO
1003
    for (int32_t i = 0; i < numOfCols; ++i) {
1004
      SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, i);
1005
      SColumnInfoData* pDstCol = taosArrayGet(pDst->pDataBlock, i);
1006

1007
      colDataAssignNRows(pDstCol, 0, pColData, startIndex, rowCount);
1008
    }
1009
  */
1010

1011
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
40,686,430✔
1012
  for (int32_t i = 0; i < numOfCols; ++i) {
488,598,837✔
1013
    SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, i);
447,911,367✔
1014
    SColumnInfoData* pDstCol = taosArrayGet(pDst->pDataBlock, i);
447,911,367✔
1015
    if (pColData == NULL || pDstCol == NULL) {
447,911,367✔
1016
      continue;
×
1017
    }
1018

1019
    for (int32_t j = startIndex; j < (startIndex + rowCount); ++j) {
2,147,483,647✔
1020
      bool isNull = false;
2,147,483,647✔
1021
      if (pBlock->pBlockAgg == NULL) {
2,147,483,647✔
1022
        isNull = colDataIsNull_s(pColData, j);
2,147,483,647✔
1023
      } else {
1024
        isNull = colDataIsNull(pColData, pBlock->info.rows, j, &pBlock->pBlockAgg[i]);
5,720✔
1025
      }
1026

1027
      if (isNull) {
2,147,483,647✔
1028
        colDataSetNULL(pDstCol, j - startIndex);
1,669,422,328✔
1029
      } else {
1030
        char* p = colDataGetData(pColData, j);
2,147,483,647✔
1031
        code = colDataSetVal(pDstCol, j - startIndex, p, false);
2,147,483,647✔
1032
        if (code) {
2,147,483,647✔
1033
          break;
×
1034
        }
1035
      }
1036
    }
1037
  }
1038

1039
  pDst->info.rows = rowCount;
40,687,470✔
1040
  *pResBlock = pDst;
40,687,470✔
1041
  return code;
40,687,470✔
1042
}
1043

1044
/**
1045
 *
1046
 * +------------------+---------------------------------------------+
1047
 * |the number of rows|                    column #1                |
1048
 * |    (4 bytes)     |------------+-----------------------+--------+
1049
 * |                  | null bitmap| column length(4bytes) | values |
1050
 * +------------------+------------+-----------------------+--------+
1051
 * @param buf
1052
 * @param pBlock
1053
 * @return
1054
 */
1055
int32_t blockDataToBuf(char* buf, const SSDataBlock* pBlock) {
66,153,519✔
1056
  // write the number of rows
1057
  *(uint32_t*)buf = pBlock->info.rows;
66,153,519✔
1058

1059
  size_t  numOfCols = taosArrayGetSize(pBlock->pDataBlock);
66,155,821✔
1060
  int32_t numOfRows = pBlock->info.rows;
66,149,547✔
1061

1062
  char* pStart = buf + sizeof(uint32_t);
66,152,971✔
1063

1064
  for (int32_t i = 0; i < numOfCols; ++i) {
588,929,585✔
1065
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
522,777,833✔
1066
    if (pCol == NULL) {
522,778,270✔
1067
      continue;
×
1068
    }
1069

1070
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
522,778,270✔
1071
      memcpy(pStart, pCol->varmeta.offset, numOfRows * sizeof(int32_t));
97,221,490✔
1072
      pStart += numOfRows * sizeof(int32_t);
97,223,375✔
1073
    } else {
1074
      memcpy(pStart, pCol->nullbitmap, BitmapLen(numOfRows));
425,553,658✔
1075
      pStart += BitmapLen(pBlock->info.rows);
425,557,093✔
1076
    }
1077

1078
    uint32_t dataSize = colDataGetLength(pCol, numOfRows);
522,777,255✔
1079

1080
    *(int32_t*)pStart = dataSize;
522,780,554✔
1081
    pStart += sizeof(int32_t);
522,780,846✔
1082

1083
    if (pCol->reassigned && IS_VAR_DATA_TYPE(pCol->info.type)) {
522,782,671✔
1084
      for (int32_t row = 0; row < numOfRows; ++row) {
×
1085
        char*   pColData = pCol->pData + pCol->varmeta.offset[row];
×
1086
        int32_t colSize = calcStrBytesByType(pCol->info.type, pColData);
×
1087
        // if (pCol->info.type == TSDB_DATA_TYPE_JSON) {
1088
        //   colSize = getJsonValueLen(pColData);
1089
        // } else if (IS_STR_DATA_BLOB(pCol->info.type)) {
1090
        //   colSize = blobDataTLen(pColData);
1091
        // } else {
1092
        //   colSize = varDataTLen(pColData);
1093
        // }
1094
        memcpy(pStart, pColData, colSize);
×
1095
        pStart += colSize;
×
1096
      }
1097
    } else {
1098
      if (dataSize != 0) {
522,781,800✔
1099
        // ubsan reports error if pCol->pData==NULL && dataSize==0
1100
        memcpy(pStart, pCol->pData, dataSize);
518,769,807✔
1101
      }
1102
      pStart += dataSize;
522,781,795✔
1103
    }
1104
  }
1105

1106
  return 0;
66,151,752✔
1107
}
1108

1109
int32_t blockDataFromBuf(SSDataBlock* pBlock, const char* buf) {
68,933,976✔
1110
  int32_t numOfRows = *(int32_t*)buf;
68,933,976✔
1111
  if (numOfRows == 0) {
68,934,560✔
1112
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
1113
  }
1114
  int32_t code = blockDataEnsureCapacity(pBlock, numOfRows);
68,934,560✔
1115
  if (code) {
68,930,700✔
1116
    return code;
×
1117
  }
1118

1119
  pBlock->info.rows = numOfRows;
68,930,700✔
1120
  size_t      numOfCols = taosArrayGetSize(pBlock->pDataBlock);
68,930,992✔
1121
  const char* pStart = buf + sizeof(uint32_t);
68,931,576✔
1122

1123
  for (int32_t i = 0; i < numOfCols; ++i) {
548,858,450✔
1124
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
479,929,057✔
1125
    if (pCol == NULL) {
479,929,784✔
1126
      continue;
×
1127
    }
1128

1129
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
479,929,784✔
1130
      size_t metaSize = pBlock->info.rows * sizeof(int32_t);
82,056,012✔
1131
      memcpy(pCol->varmeta.offset, pStart, metaSize);
82,005,439✔
1132
      pStart += metaSize;
82,005,439✔
1133
    } else {
1134
      memcpy(pCol->nullbitmap, pStart, BitmapLen(pBlock->info.rows));
397,922,458✔
1135
      pStart += BitmapLen(pBlock->info.rows);
397,929,110✔
1136
    }
1137

1138
    int32_t colLength = *(int32_t*)pStart;
479,931,024✔
1139
    pStart += sizeof(int32_t);
479,928,481✔
1140

1141
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
479,932,989✔
1142
      if (pCol->varmeta.allocLen < colLength) {
82,007,547✔
1143
        char* tmp = taosMemoryRealloc(pCol->pData, colLength);
2,934,029✔
1144
        if (tmp == NULL) {
2,934,029✔
1145
          return terrno;
×
1146
        }
1147

1148
        pCol->pData = tmp;
2,934,029✔
1149
        pCol->varmeta.allocLen = colLength;
2,934,029✔
1150
      }
1151

1152
      pCol->varmeta.length = colLength;
82,005,439✔
1153
      if (pCol->varmeta.length > pCol->varmeta.allocLen) {
82,005,439✔
1154
        return TSDB_CODE_FAILED;
×
1155
      }
1156
    }
1157
    if (colLength != 0) {
479,934,549✔
1158
      // ubsan reports error if colLength==0 && pCol->pData == 0
1159
      memcpy(pCol->pData, pStart, colLength);
475,922,713✔
1160
    }
1161
    pStart += colLength;
479,935,133✔
1162
  }
1163

1164
  return TSDB_CODE_SUCCESS;
68,929,393✔
1165
}
1166

1167
static bool colDataIsNNull(const SColumnInfoData* pColumnInfoData, int32_t startIndex, uint32_t nRows) {
716,096,264✔
1168
  if (!pColumnInfoData->hasNull) {
716,096,264✔
1169
    return false;
×
1170
  }
1171

1172
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
716,103,818✔
1173
    for (int32_t i = startIndex; i < nRows; ++i) {
543,363,568✔
1174
      if (!colDataIsNull_var(pColumnInfoData, i)) {
538,840,678✔
1175
        return false;
223,758,310✔
1176
      }
1177
    }
1178
  } else {
1179
    if (pColumnInfoData->nullbitmap == NULL) {
487,899,045✔
1180
      return false;
×
1181
    }
1182

1183
    for (int32_t i = startIndex; i < nRows; ++i) {
1,070,819,371✔
1184
      if (!colDataIsNull_f(pColumnInfoData, i)) {
1,048,667,414✔
1185
        return false;
465,922,231✔
1186
      }
1187
    }
1188
  }
1189

1190
  return true;
26,674,847✔
1191
}
1192

1193
// todo remove this
1194
int32_t blockDataFromBuf1(SSDataBlock* pBlock, const char* buf, size_t capacity) {
130,887,136✔
1195
  pBlock->info.rows = *(int32_t*)buf;
130,887,136✔
1196
  pBlock->info.id.groupId = *(uint64_t*)(buf + sizeof(int32_t));
130,886,805✔
1197

1198
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
130,888,336✔
1199

1200
  const char* pStart = buf + sizeof(uint32_t) + sizeof(uint64_t);
130,883,632✔
1201

1202
  for (int32_t i = 0; i < numOfCols; ++i) {
846,975,338✔
1203
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
716,087,392✔
1204
    if (pCol == NULL) {
716,053,809✔
1205
      continue;
×
1206
    }
1207

1208
    pCol->hasNull = true;
716,053,809✔
1209

1210
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
716,055,787✔
1211
      size_t metaSize = capacity * sizeof(int32_t);
228,205,534✔
1212
      memcpy(pCol->varmeta.offset, pStart, metaSize);
228,205,534✔
1213
      pStart += metaSize;
228,279,751✔
1214
    } else {
1215
      memcpy(pCol->nullbitmap, pStart, BitmapLen(capacity));
487,858,987✔
1216
      pStart += BitmapLen(capacity);
487,864,727✔
1217
    }
1218

1219
    int32_t colLength = *(int32_t*)pStart;
716,140,204✔
1220
    pStart += sizeof(int32_t);
716,084,135✔
1221

1222
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
716,090,217✔
1223
      if (pCol->varmeta.allocLen < colLength) {
228,215,299✔
1224
        char* tmp = taosMemoryRealloc(pCol->pData, colLength);
347,588✔
1225
        if (tmp == NULL) {
347,588✔
1226
          return terrno;
×
1227
        }
1228

1229
        pCol->pData = tmp;
347,588✔
1230
        pCol->varmeta.allocLen = colLength;
347,588✔
1231
      }
1232

1233
      pCol->varmeta.length = colLength;
228,281,198✔
1234
      if (pCol->varmeta.length > pCol->varmeta.allocLen) {
228,279,836✔
1235
        return TSDB_CODE_FAILED;
×
1236
      }
1237
    }
1238

1239
    if (!colDataIsNNull(pCol, 0, pBlock->info.rows)) {
716,165,491✔
1240
      memcpy(pCol->pData, pStart, colLength);
689,611,824✔
1241
    }
1242

1243
    pStart += pCol->info.bytes * capacity;
716,073,616✔
1244
  }
1245

1246
  return TSDB_CODE_SUCCESS;
130,887,946✔
1247
}
1248

1249
size_t blockDataGetRowSize(SSDataBlock* pBlock) {
2,147,483,647✔
1250
  if (pBlock->info.rowSize == 0) {
2,147,483,647✔
1251
    size_t rowSize = 0;
×
1252

1253
    size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
×
1254
    for (int32_t i = 0; i < numOfCols; ++i) {
×
1255
      SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
×
1256
      if (pColInfo == NULL) {
×
1257
        continue;
×
1258
      }
1259

1260
      rowSize += pColInfo->info.bytes;
×
1261
    }
1262

1263
    pBlock->info.rowSize = rowSize;
×
1264
  }
1265

1266
  return pBlock->info.rowSize;
2,147,483,647✔
1267
}
1268

1269
size_t blockDataGetSerialMetaSizeImpl(uint32_t numOfCols, bool internal) {
1,554,960,703✔
1270
  // | version | total length | total rows | blankFull | total columns | flag seg| block group id | column schema
1271
  // | each column length
1272
  // internal: |scanFlag |
1273
  return sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(bool) + sizeof(int32_t) + sizeof(int32_t) +
1274
         sizeof(uint64_t) + numOfCols * (sizeof(int8_t) + sizeof(int32_t)) + numOfCols * sizeof(int32_t) + 
1,554,960,703✔
1275
         (internal ? (sizeof(uint8_t)) : 0);
1,554,960,703✔
1276
}
1277

1278
size_t blockDataGetSerialMetaSizeInternal(uint32_t numOfCols) {
15,149,883✔
1279
  return blockDataGetSerialMetaSizeImpl(numOfCols, true);
15,149,883✔
1280
}
1281

1282
/**
1283
 * @refitem blockDataToBuf for the meta size
1284
 * @param pBlock
1285
 * @return
1286
 */
1287
size_t blockDataGetSerialMetaSize(uint32_t numOfCols) {
1,539,789,367✔
1288
  return blockDataGetSerialMetaSizeImpl(numOfCols, false);
1,539,789,367✔
1289
}
1290

1291
double blockDataGetSerialRowSize(const SSDataBlock* pBlock) {
13,144,576✔
1292
  double rowSize = 0;
13,144,576✔
1293

1294
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
13,144,576✔
1295
  for (int32_t i = 0; i < numOfCols; ++i) {
47,892,474✔
1296
    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
34,750,888✔
1297
    if (pColInfo == NULL) {
34,750,595✔
1298
      continue;
×
1299
    }
1300

1301
    rowSize += pColInfo->info.bytes;
34,750,595✔
1302
    if (IS_VAR_DATA_TYPE(pColInfo->info.type)) {
34,749,427✔
1303
      rowSize += sizeof(int32_t);
2,639,547✔
1304
    } else {
1305
      rowSize += 1 / 8.0;  // one bit for each record
32,107,185✔
1306
    }
1307
  }
1308

1309
  return rowSize;
13,141,586✔
1310
}
1311

1312
typedef struct SSDataBlockSortHelper {
1313
  SArray*      orderInfo;  // SArray<SBlockOrderInfo>
1314
  SSDataBlock* pDataBlock;
1315
} SSDataBlockSortHelper;
1316

1317
int32_t dataBlockCompar(const void* p1, const void* p2, const void* param) {
2,147,483,647✔
1318
  const SSDataBlockSortHelper* pHelper = (const SSDataBlockSortHelper*)param;
2,147,483,647✔
1319

1320
  SSDataBlock* pDataBlock = pHelper->pDataBlock;
2,147,483,647✔
1321

1322
  int32_t left = *(int32_t*)p1;
2,147,483,647✔
1323
  int32_t right = *(int32_t*)p2;
2,147,483,647✔
1324

1325
  SArray* pInfo = pHelper->orderInfo;
2,147,483,647✔
1326

1327
  for (int32_t i = 0; i < pInfo->size; ++i) {
2,147,483,647✔
1328
    SBlockOrderInfo* pOrder = TARRAY_GET_ELEM(pInfo, i);
2,147,483,647✔
1329
    SColumnInfoData* pColInfoData = pOrder->pColData;  // TARRAY_GET_ELEM(pDataBlock->pDataBlock, pOrder->colIndex);
2,147,483,647✔
1330

1331
    if (pColInfoData->hasNull) {
2,147,483,647✔
1332
      bool leftNull = colDataIsNull(pColInfoData, pDataBlock->info.rows, left, NULL);
2,147,483,647✔
1333
      bool rightNull = colDataIsNull(pColInfoData, pDataBlock->info.rows, right, NULL);
2,147,483,647✔
1334
      if (leftNull && rightNull) {
2,147,483,647✔
1335
        continue;  // continue to next slot
2,147,483,647✔
1336
      }
1337

1338
      if (rightNull) {
2,147,483,647✔
1339
        return pOrder->nullFirst ? 1 : -1;
327,056,282✔
1340
      }
1341

1342
      if (leftNull) {
2,147,483,647✔
1343
        return pOrder->nullFirst ? -1 : 1;
960,284,801✔
1344
      }
1345
    }
1346

1347
    void* left1 = colDataGetData(pColInfoData, left);
2,147,483,647✔
1348
    void* right1 = colDataGetData(pColInfoData, right);
2,147,483,647✔
1349
    if (pColInfoData->info.type == TSDB_DATA_TYPE_JSON) {
2,147,483,647✔
1350
      if (tTagIsJson(left1) || tTagIsJson(right1)) {
126,450✔
1351
        terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR;
7,650✔
1352
        return 0;
7,650✔
1353
      }
1354
    }
1355

1356
    __compar_fn_t fn;
1357
    if (pOrder->compFn) {
2,147,483,647✔
1358
      fn = pOrder->compFn;
2,147,483,647✔
1359
    } else {
1360
      fn = getKeyComparFunc(pColInfoData->info.type, pOrder->order);
×
1361
    }
1362

1363
    int ret = fn(left1, right1);
2,147,483,647✔
1364
    if (ret == 0) {
2,147,483,647✔
1365
      continue;
2,147,483,647✔
1366
    } else {
1367
      return ret;
2,147,483,647✔
1368
    }
1369
  }
1370

1371
  return 0;
2,147,483,647✔
1372
}
1373

1374
static void blockDataAssign(SColumnInfoData* pCols, const SSDataBlock* pDataBlock, const int32_t* index) {
21,545,790✔
1375
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
21,545,790✔
1376
  for (int32_t i = 0; i < numOfCols; ++i) {
83,666,775✔
1377
    SColumnInfoData* pDst = &pCols[i];
62,119,257✔
1378
    SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i);
62,120,287✔
1379
    if (pSrc == NULL) {
62,119,673✔
1380
      continue;
×
1381
    }
1382

1383
    if (IS_VAR_DATA_TYPE(pSrc->info.type)) {
62,119,673✔
1384
      if (pSrc->varmeta.length != 0) {
19,890,816✔
1385
        memcpy(pDst->pData, pSrc->pData, pSrc->varmeta.length);
19,030,913✔
1386
      }
1387
      pDst->varmeta.length = pSrc->varmeta.length;
19,892,031✔
1388

1389
      for (int32_t j = 0; j < pDataBlock->info.rows; ++j) {
2,147,483,647✔
1390
        pDst->varmeta.offset[j] = pSrc->varmeta.offset[index[j]];
2,147,483,647✔
1391
      }
1392
    } else {
1393
      for (int32_t j = 0; j < pDataBlock->info.rows; ++j) {
2,147,483,647✔
1394
        if (colDataIsNull_f(pSrc, index[j])) {
2,147,483,647✔
1395
          colDataSetNull_f_s(pDst, j);
2,147,483,647✔
1396
          continue;
2,147,483,647✔
1397
        }
1398
        memcpy(pDst->pData + j * pDst->info.bytes, pSrc->pData + index[j] * pDst->info.bytes, pDst->info.bytes);
2,147,483,647✔
1399
      }
1400
    }
1401
  }
1402
}
21,547,518✔
1403

1404
static int32_t createHelpColInfoData(const SSDataBlock* pDataBlock, SColumnInfoData** ppCols) {
21,546,082✔
1405
  int32_t code = 0;
21,546,082✔
1406
  int32_t rows = pDataBlock->info.capacity;
21,546,082✔
1407
  size_t  numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
21,547,518✔
1408
  int32_t i = 0;
21,544,345✔
1409

1410
  *ppCols = NULL;
21,544,345✔
1411

1412
  SColumnInfoData* pCols = taosMemoryCalloc(numOfCols, sizeof(SColumnInfoData));
21,544,801✔
1413
  if (pCols == NULL) {
21,545,532✔
1414
    return terrno;
×
1415
  }
1416

1417
  for (i = 0; i < numOfCols; ++i) {
83,656,566✔
1418
    SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, i);
62,114,203✔
1419
    if (pColInfoData == NULL) {
62,117,347✔
1420
      continue;
×
1421
    }
1422

1423
    pCols[i].info = pColInfoData->info;
62,117,347✔
1424
    if (IS_VAR_DATA_TYPE(pCols[i].info.type)) {
62,115,160✔
1425
      pCols[i].varmeta.offset = taosMemoryCalloc(rows, sizeof(int32_t));
19,905,366✔
1426
      pCols[i].pData = taosMemoryCalloc(1, pColInfoData->varmeta.length);
19,892,147✔
1427
      if (pCols[i].varmeta.offset == NULL || pCols[i].pData == NULL) {
19,891,712✔
1428
        code = terrno;
394✔
1429
        taosMemoryFree(pCols[i].varmeta.offset);
×
1430
        taosMemoryFree(pCols[i].pData);
×
1431
        goto _error;
×
1432
      }
1433

1434
      pCols[i].varmeta.length = pColInfoData->varmeta.length;
19,890,323✔
1435
      pCols[i].varmeta.allocLen = pCols[i].varmeta.length;
19,890,733✔
1436
    } else {
1437
      pCols[i].nullbitmap = taosMemoryCalloc(1, BitmapLen(rows));
42,218,844✔
1438
      pCols[i].pData = taosMemoryCalloc(rows, pCols[i].info.bytes);
42,221,892✔
1439
      if (pCols[i].nullbitmap == NULL || pCols[i].pData == NULL) {
42,219,510✔
1440
        code = terrno;
8,361✔
1441
        taosMemoryFree(pCols[i].nullbitmap);
×
1442
        taosMemoryFree(pCols[i].pData);
×
1443
        goto _error;
×
1444
      }
1445
    }
1446
  }
1447

1448
  *ppCols = pCols;
21,542,363✔
1449
  return code;
21,544,607✔
1450

1451
_error:
×
1452
  for (int32_t j = 0; j < i; ++j) {
×
1453
    colDataDestroy(&pCols[j]);
×
1454
  }
1455

1456
  taosMemoryFree(pCols);
×
1457
  return code;
×
1458
}
1459

1460
static void copyBackToBlock(SSDataBlock* pDataBlock, SColumnInfoData* pCols) {
21,546,047✔
1461
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
21,546,047✔
1462

1463
  for (int32_t i = 0; i < numOfCols; ++i) {
83,658,143✔
1464
    SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, i);
62,112,977✔
1465
    if (pColInfoData == NULL) {
62,114,963✔
1466
      continue;
×
1467
    }
1468

1469
    pColInfoData->info = pCols[i].info;
62,114,963✔
1470
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
62,116,335✔
1471
      taosMemoryFreeClear(pColInfoData->varmeta.offset);
19,891,760✔
1472
      pColInfoData->varmeta = pCols[i].varmeta;
19,890,101✔
1473
    } else {
1474
      taosMemoryFreeClear(pColInfoData->nullbitmap);
42,221,625✔
1475
      pColInfoData->nullbitmap = pCols[i].nullbitmap;
42,221,117✔
1476
    }
1477

1478
    taosMemoryFreeClear(pColInfoData->pData);
62,109,716✔
1479
    pColInfoData->pData = pCols[i].pData;
62,107,517✔
1480
  }
1481

1482
  taosMemoryFreeClear(pCols);
21,545,166✔
1483
}
21,543,030✔
1484

1485
static int32_t* createTupleIndex(size_t rows) {
21,547,483✔
1486
  int32_t* index = taosMemoryCalloc(rows, sizeof(int32_t));
21,547,483✔
1487
  if (index == NULL) {
21,547,669✔
1488
    return NULL;
×
1489
  }
1490

1491
  for (int32_t i = 0; i < rows; ++i) {
2,147,483,647✔
1492
    index[i] = i;
2,147,483,647✔
1493
  }
1494

1495
  return index;
21,547,189✔
1496
}
1497

1498
static void destroyTupleIndex(int32_t* index) { taosMemoryFreeClear(index); }
21,544,740✔
1499

1500
int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
24,894,214✔
1501
  if (pDataBlock->info.rows <= 1) {
24,894,214✔
1502
    return TSDB_CODE_SUCCESS;
3,346,275✔
1503
  }
1504

1505
  // Allocate the additional buffer.
1506
  uint32_t rows = pDataBlock->info.rows;
21,547,459✔
1507

1508
  bool sortColumnHasNull = false;
21,548,457✔
1509
  bool varTypeSort = false;
21,548,457✔
1510

1511
  for (int32_t i = 0; i < taosArrayGetSize(pOrderInfo); ++i) {
51,246,756✔
1512
    SBlockOrderInfo* pInfo = taosArrayGet(pOrderInfo, i);
29,699,235✔
1513
    if (pInfo == NULL) {
29,699,753✔
1514
      continue;
×
1515
    }
1516

1517
    SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, pInfo->slotId);
29,699,753✔
1518
    if (pColInfoData == NULL) {
29,697,998✔
1519
      continue;
×
1520
    }
1521

1522
    if (pColInfoData->hasNull) {
29,697,998✔
1523
      sortColumnHasNull = true;
29,678,670✔
1524
    }
1525

1526
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
29,697,998✔
1527
      varTypeSort = true;
16,325,471✔
1528
    }
1529
  }
1530

1531
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
21,546,209✔
1532

1533
  if (taosArrayGetSize(pOrderInfo) == 1 && (!sortColumnHasNull)) {
21,547,291✔
1534
    if (numOfCols == 1) {
17,060✔
1535
      if (!varTypeSort) {
×
1536
        SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, 0);
×
1537
        SBlockOrderInfo* pOrder = taosArrayGet(pOrderInfo, 0);
×
1538
        if (pColInfoData == NULL || pOrder == NULL) {
×
1539
          return terrno;
×
1540
        }
1541

1542
        int64_t p0 = taosGetTimestampUs();
×
1543

1544
        __compar_fn_t fn = getKeyComparFunc(pColInfoData->info.type, pOrder->order);
×
1545
        taosSort(pColInfoData->pData, pDataBlock->info.rows, pColInfoData->info.bytes, fn);
×
1546

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

1550
        return TSDB_CODE_SUCCESS;
×
1551
      } else {  // var data type
1552
      }
1553
    } else if (numOfCols == 2) {
1554
    }
1555
  }
1556

1557
  int32_t* index = createTupleIndex(rows);
21,547,291✔
1558
  if (index == NULL) {
21,546,215✔
1559
    return terrno;
×
1560
  }
1561

1562
  int64_t p0 = taosGetTimestampUs();
21,547,003✔
1563

1564
  SSDataBlockSortHelper helper = {.pDataBlock = pDataBlock, .orderInfo = pOrderInfo};
21,547,003✔
1565
  for (int32_t i = 0; i < taosArrayGetSize(helper.orderInfo); ++i) {
51,246,262✔
1566
    struct SBlockOrderInfo* pInfo = taosArrayGet(helper.orderInfo, i);
29,698,778✔
1567
    if (pInfo == NULL) {
29,699,461✔
1568
      continue;
×
1569
    }
1570

1571
    pInfo->pColData = taosArrayGet(pDataBlock->pDataBlock, pInfo->slotId);
29,699,461✔
1572
    if (pInfo->pColData == NULL) {
29,697,478✔
1573
      continue;
×
1574
    }
1575
    pInfo->compFn = getKeyComparFunc(pInfo->pColData->info.type, pInfo->order);
29,697,022✔
1576
  }
1577

1578
  terrno = 0;
21,546,961✔
1579
  taosqsort_r(index, rows, sizeof(int32_t), &helper, dataBlockCompar);
21,547,065✔
1580
  if (terrno) {
21,546,986✔
1581
    destroyTupleIndex(index);
450✔
1582
    return terrno;
450✔
1583
  }
1584

1585
  int64_t p1 = taosGetTimestampUs();
21,547,027✔
1586

1587
  SColumnInfoData* pCols = NULL;
21,547,027✔
1588
  int32_t          code = createHelpColInfoData(pDataBlock, &pCols);
21,544,217✔
1589
  if (code != 0) {
21,542,651✔
1590
    destroyTupleIndex(index);
×
1591
    return code;
×
1592
  }
1593

1594
  int64_t p2 = taosGetTimestampUs();
21,545,022✔
1595
  blockDataAssign(pCols, pDataBlock, index);
21,545,022✔
1596

1597
  int64_t p3 = taosGetTimestampUs();
21,547,027✔
1598
  copyBackToBlock(pDataBlock, pCols);
21,547,027✔
1599

1600
  int64_t p4 = taosGetTimestampUs();
21,542,556✔
1601
  uDebug("blockDataSort complex sort:%" PRId64 ", create:%" PRId64 ", assign:%" PRId64 ", copyback:%" PRId64
21,542,556✔
1602
         ", rows:%d\n",
1603
         p1 - p0, p2 - p1, p3 - p2, p4 - p3, rows);
1604

1605
  destroyTupleIndex(index);
21,542,556✔
1606
  return TSDB_CODE_SUCCESS;
21,542,817✔
1607
}
1608

1609
void blockDataCleanup(SSDataBlock* pDataBlock) {
2,147,483,647✔
1610
  if(pDataBlock == NULL) {
2,147,483,647✔
1611
    return;
48,996✔
1612
  }
1613
  blockDataEmpty(pDataBlock);
2,147,483,647✔
1614
  SDataBlockInfo* pInfo = &pDataBlock->info;
2,147,483,647✔
1615
  pInfo->id.uid = 0;
2,147,483,647✔
1616
  pInfo->id.groupId = 0;
2,147,483,647✔
1617
}
1618

1619
void blockDataEmpty(SSDataBlock* pDataBlock) {
2,147,483,647✔
1620
  if (pDataBlock == NULL) {
2,147,483,647✔
1621
    return;
157,079✔
1622
  }
1623
  SDataBlockInfo* pInfo = &pDataBlock->info;
2,147,483,647✔
1624
  if (pInfo->capacity == 0) {
2,147,483,647✔
1625
    return;
739,112,132✔
1626
  }
1627

1628
  taosMemoryFreeClear(pDataBlock->pBlockAgg);
2,147,483,647✔
1629

1630
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
2,147,483,647✔
1631
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
1632
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
1633
    if (p == NULL) {
2,147,483,647✔
1634
      continue;
×
1635
    }
1636

1637
    colInfoDataCleanup(p, pInfo->capacity);
2,147,483,647✔
1638
  }
1639

1640
  pInfo->rows = 0;
2,147,483,647✔
1641
  pInfo->dataLoad = 0;
2,147,483,647✔
1642
  pInfo->window.ekey = 0;
2,147,483,647✔
1643
  pInfo->window.skey = 0;
2,147,483,647✔
1644
}
1645

1646
void blockDataReset(SSDataBlock* pDataBlock) {
2,092,349✔
1647
  SDataBlockInfo* pInfo = &pDataBlock->info;
2,092,349✔
1648
  if (pInfo->capacity == 0) {
2,092,349✔
1649
    return;
×
1650
  }
1651

1652
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
2,092,349✔
1653
  for (int32_t i = 0; i < numOfCols; ++i) {
9,044,314✔
1654
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
6,951,965✔
1655
    if (p == NULL) {
6,951,965✔
1656
      continue;
×
1657
    }
1658

1659
    p->hasNull = false;
6,951,965✔
1660
    p->reassigned = false;
6,951,965✔
1661
    if (IS_VAR_DATA_TYPE(p->info.type)) {
6,951,965✔
1662
      p->varmeta.length = 0;
921,698✔
1663
    }
1664
  }
1665

1666
  pInfo->rows = 0;
2,092,349✔
1667
  pInfo->dataLoad = 0;
2,092,349✔
1668
  pInfo->window.ekey = 0;
2,092,349✔
1669
  pInfo->window.skey = 0;
2,092,143✔
1670
  pInfo->id.uid = 0;
2,092,143✔
1671
  pInfo->id.groupId = 0;
2,092,143✔
1672
}
1673

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

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

1687
  if (IS_VAR_DATA_TYPE(pColumn->info.type)) {
2,147,483,647✔
1688
    char* tmp = taosMemoryRealloc(pColumn->varmeta.offset, sizeof(int32_t) * numOfRows);
2,147,483,647✔
1689
    if (tmp == NULL) {
2,147,483,647✔
1690
      return terrno;
×
1691
    }
1692

1693
    pColumn->varmeta.offset = (int32_t*)tmp;
2,147,483,647✔
1694
    memset(&pColumn->varmeta.offset[existedRows], 0, sizeof(int32_t) * (numOfRows - existedRows));
2,147,483,647✔
1695
  } else {
1696
    // prepare for the null bitmap
1697
    char* tmp = taosMemoryRealloc(pColumn->nullbitmap, BitmapLen(numOfRows));
2,147,483,647✔
1698
    if (tmp == NULL) {
2,147,483,647✔
1699
      return terrno;
×
1700
    }
1701

1702
    int32_t oldLen = BitmapLen(existedRows);
2,147,483,647✔
1703
    pColumn->nullbitmap = tmp;
2,147,483,647✔
1704
    memset(&pColumn->nullbitmap[oldLen], 0, BitmapLen(numOfRows) - oldLen);
2,147,483,647✔
1705
    if (pColumn->info.bytes == 0) {
2,147,483,647✔
1706
      return TSDB_CODE_INVALID_PARA;
×
1707
    }
1708

1709
    // here we employ the aligned malloc function, to make sure that the address of allocated memory is aligned
1710
    // to MALLOC_ALIGN_BYTES
1711
    tmp = taosMemoryMallocAlign(MALLOC_ALIGN_BYTES, numOfRows * pColumn->info.bytes);
2,147,483,647✔
1712
    if (tmp == NULL) {
2,147,483,647✔
1713
      return terrno;
×
1714
    }
1715
    // memset(tmp, 0, numOfRows * pColumn->info.bytes);
1716

1717
    // copy back the existed data
1718
    if (pColumn->pData != NULL) {
2,147,483,647✔
1719
      memcpy(tmp, pColumn->pData, existedRows * pColumn->info.bytes);
254,013,671✔
1720
      taosMemoryFreeClear(pColumn->pData);
254,020,653✔
1721
    }
1722

1723
    pColumn->pData = tmp;
2,147,483,647✔
1724

1725
    // check if the allocated memory is aligned to the requried bytes.
1726
#if defined LINUX
1727
    if ((((uint64_t)pColumn->pData) & (MALLOC_ALIGN_BYTES - 1)) != 0x0) {
2,147,483,647✔
1728
      return TSDB_CODE_FAILED;
×
1729
    }
1730
#endif
1731

1732
    if (clearPayload) {
2,147,483,647✔
1733
      memset(tmp + pColumn->info.bytes * existedRows, 0, pColumn->info.bytes * (numOfRows - existedRows));
2,147,483,647✔
1734
    }
1735
  }
1736

1737
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
1738
}
1739

1740
void colInfoDataCleanup(SColumnInfoData* pColumn, uint32_t numOfRows) {
2,147,483,647✔
1741
  pColumn->hasNull = false;
2,147,483,647✔
1742

1743
  if (IS_VAR_DATA_TYPE(pColumn->info.type)) {
2,147,483,647✔
1744
    pColumn->varmeta.length = 0;
2,147,483,647✔
1745
    if (pColumn->varmeta.offset != NULL) {
2,147,483,647✔
1746
      memset(pColumn->varmeta.offset, 0, sizeof(int32_t) * numOfRows);
2,147,483,647✔
1747
    }
1748
  } else {
1749
    if (pColumn->nullbitmap != NULL) {
2,147,483,647✔
1750
      memset(pColumn->nullbitmap, 0, BitmapLen(numOfRows));
2,147,483,647✔
1751
    }
1752
  }
1753
}
2,147,483,647✔
1754

1755
int32_t colInfoDataEnsureCapacity(SColumnInfoData* pColumn, uint32_t numOfRows, bool clearPayload) {
2,147,483,647✔
1756
  SDataBlockInfo info = {0};
2,147,483,647✔
1757
  return doEnsureCapacity(pColumn, &info, numOfRows, clearPayload);
2,147,483,647✔
1758
}
1759

1760
int32_t blockDataEnsureCapacity(SSDataBlock* pDataBlock, uint32_t numOfRows) {
2,147,483,647✔
1761
  int32_t code = 0;
2,147,483,647✔
1762
  if (numOfRows == 0 || numOfRows <= pDataBlock->info.capacity) {
2,147,483,647✔
1763
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
1764
  }
1765

1766
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
1,828,964,604✔
1767
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
1768
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
1769
    if (p == NULL) {
2,147,483,647✔
1770
      return terrno;
×
1771
    }
1772

1773
    code = doEnsureCapacity(p, &pDataBlock->info, numOfRows, false);
2,147,483,647✔
1774
    if (code) {
2,147,483,647✔
1775
      return code;
×
1776
    }
1777
  }
1778

1779
  pDataBlock->info.capacity = numOfRows;
1,829,033,334✔
1780
  return TSDB_CODE_SUCCESS;
1,829,045,271✔
1781
}
1782

1783
void blockDataFreeRes(SSDataBlock* pBlock) {
2,147,483,647✔
1784
  if (pBlock == NULL) {
2,147,483,647✔
1785
    return;
41,604,284✔
1786
  }
1787

1788
  int32_t numOfOutput = taosArrayGetSize(pBlock->pDataBlock);
2,147,483,647✔
1789
  for (int32_t i = 0; i < numOfOutput; ++i) {
2,147,483,647✔
1790
    SColumnInfoData* pColInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
1791
    if (pColInfoData == NULL) {
2,147,483,647✔
1792
      continue;
×
1793
    }
1794

1795
    colDataDestroy(pColInfoData);
2,147,483,647✔
1796
  }
1797

1798
  taosArrayDestroy(pBlock->pDataBlock);
2,147,483,647✔
1799
  pBlock->pDataBlock = NULL;
2,147,483,647✔
1800

1801
  taosMemoryFreeClear(pBlock->pBlockAgg);
2,147,483,647✔
1802
  memset(&pBlock->info, 0, sizeof(SDataBlockInfo));
2,147,483,647✔
1803
}
1804

1805
void blockDataFreeCols(SSDataBlock* pBlock) {
×
1806
  if (pBlock == NULL) {
×
1807
    return;
×
1808
  }
1809

1810
  int32_t numOfOutput = taosArrayGetSize(pBlock->pDataBlock);
×
1811
  for (int32_t i = 0; i < numOfOutput; ++i) {
×
1812
    SColumnInfoData* pColInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
×
1813
    if (pColInfoData == NULL) {
×
1814
      continue;
×
1815
    }
1816

1817
    colDataDestroy(pColInfoData);
×
1818
  }
1819

1820
  taosMemoryFreeClear(pBlock->pBlockAgg);
×
1821
  memset(&pBlock->info, 0, sizeof(SDataBlockInfo));
×
1822
}
1823

1824
void blockDataDestroy(SSDataBlock* pBlock) {
2,147,483,647✔
1825
  if (pBlock == NULL) {
2,147,483,647✔
1826
    return;
349,370,836✔
1827
  }
1828

1829
  if (IS_VAR_DATA_TYPE(pBlock->info.pks[0].type)) {
2,147,483,647✔
1830
    taosMemoryFreeClear(pBlock->info.pks[0].pData);
12,657,603✔
1831
    taosMemoryFreeClear(pBlock->info.pks[1].pData);
12,660,851✔
1832
  }
1833

1834
  blockDataFreeRes(pBlock);
2,147,483,647✔
1835
  taosMemoryFreeClear(pBlock);
2,147,483,647✔
1836
}
1837

1838
// todo remove it
1839
int32_t assignOneDataBlock(SSDataBlock* dst, const SSDataBlock* src) {
×
1840
  int32_t code = 0;
×
1841

1842
  dst->info = src->info;
×
1843
  dst->info.pks[0].pData = NULL;
×
1844
  dst->info.pks[1].pData = NULL;
×
1845
  dst->info.rows = 0;
×
1846
  dst->info.capacity = 0;
×
1847

1848
  size_t numOfCols = taosArrayGetSize(src->pDataBlock);
×
1849
  for (int32_t i = 0; i < numOfCols; ++i) {
×
1850
    SColumnInfoData* p = taosArrayGet(src->pDataBlock, i);
×
1851
    if (p == NULL) {
×
1852
      return terrno;
×
1853
    }
1854

1855
    SColumnInfoData colInfo = {.hasNull = true, .info = p->info};
×
1856
    code = blockDataAppendColInfo(dst, &colInfo);
×
1857
    if (code) {
×
1858
      return code;
×
1859
    }
1860
  }
1861

1862
  code = blockDataEnsureCapacity(dst, src->info.rows);
×
1863
  if (code != TSDB_CODE_SUCCESS) {
×
1864
    return code;
×
1865
  }
1866

1867
  for (int32_t i = 0; i < numOfCols; ++i) {
×
1868
    SColumnInfoData* pDst = taosArrayGet(dst->pDataBlock, i);
×
1869
    SColumnInfoData* pSrc = taosArrayGet(src->pDataBlock, i);
×
1870
    if (pSrc == NULL || pDst == NULL || (pSrc->pData == NULL && (!IS_VAR_DATA_TYPE(pSrc->info.type)))) {
×
1871
      continue;
×
1872
    }
1873

1874
    int32_t ret = colDataAssign(pDst, pSrc, src->info.rows, &src->info);
×
1875
    if (ret < 0) {
×
1876
      return ret;
×
1877
    }
1878
  }
1879

1880
  uint32_t cap = dst->info.capacity;
×
1881
  dst->info = src->info;
×
1882
  dst->info.pks[0].pData = NULL;
×
1883
  dst->info.pks[1].pData = NULL;
×
1884
  dst->info.capacity = cap;
×
1885
  uTrace("%s,parName:%s, groupId:%"PRIu64, __FUNCTION__, dst->info.parTbName, dst->info.id.groupId)
×
1886
  return code;
×
1887
}
1888

1889
int32_t copyDataBlock(SSDataBlock* pDst, const SSDataBlock* pSrc) {
95,117,312✔
1890
  blockDataCleanup(pDst);
95,117,312✔
1891

1892
  int32_t code = blockDataEnsureCapacity(pDst, pSrc->info.rows);
95,121,182✔
1893
  if (code != TSDB_CODE_SUCCESS) {
95,120,886✔
1894
    return code;
×
1895
  }
1896

1897
  size_t numOfCols = taosArrayGetSize(pSrc->pDataBlock);
95,120,886✔
1898
  for (int32_t i = 0; i < numOfCols; ++i) {
686,393,538✔
1899
    SColumnInfoData* pDstCol = taosArrayGet(pDst->pDataBlock, i);
591,269,006✔
1900
    SColumnInfoData* pSrcCol = taosArrayGet(pSrc->pDataBlock, i);
591,410,940✔
1901
    if (pDstCol == NULL || pSrcCol == NULL) {
591,350,922✔
1902
      continue;
×
1903
    }
1904

1905
    int32_t ret = colDataAssign(pDstCol, pSrcCol, pSrc->info.rows, &pSrc->info);
591,350,922✔
1906
    if (ret < 0) {
591,299,204✔
1907
      code = ret;
×
1908
      return code;
×
1909
    }
1910
  }
1911

1912
  uint32_t cap = pDst->info.capacity;
95,124,532✔
1913

1914
  if (IS_VAR_DATA_TYPE(pDst->info.pks[0].type)) {
95,124,532✔
1915
    taosMemoryFreeClear(pDst->info.pks[0].pData);
676✔
1916
  }
1917

1918
  if (IS_VAR_DATA_TYPE(pDst->info.pks[1].type)) {
95,125,440✔
1919
    taosMemoryFreeClear(pDst->info.pks[1].pData);
913✔
1920
  }
1921

1922
  pDst->info = pSrc->info;
95,125,234✔
1923
  code = copyPkVal(&pDst->info, &pSrc->info);
95,124,997✔
1924
  if (code != TSDB_CODE_SUCCESS) {
95,122,995✔
1925
    uError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1926
    return code;
×
1927
  }
1928

1929
  pDst->info.capacity = cap;
95,122,995✔
1930
  return code;
95,123,798✔
1931
}
1932

1933
int32_t createSpecialDataBlock(EStreamType type, SSDataBlock** pBlock) {
1,264,984✔
1934
  QRY_PARAM_CHECK(pBlock);
1,264,984✔
1935

1936
  int32_t      code = 0;
1,264,984✔
1937
  SSDataBlock* p = taosMemoryCalloc(1, sizeof(SSDataBlock));
1,264,984✔
1938
  if (p == NULL) {
1,264,984✔
1939
    return terrno;
×
1940
  }
1941

1942
  p->info.hasVarCol = false;
1,264,984✔
1943
  p->info.id.groupId = 0;
1,264,984✔
1944
  p->info.rows = 0;
1,264,984✔
1945
  p->info.type = type;
1,264,984✔
1946
  p->info.rowSize = sizeof(TSKEY) + sizeof(TSKEY) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(TSKEY) +
1,264,984✔
1947
                    sizeof(TSKEY) + VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN;
1948
  p->info.watermark = INT64_MIN;
1,264,984✔
1949

1950
  p->pDataBlock = taosArrayInit(6, sizeof(SColumnInfoData));
1,264,984✔
1951
  if (p->pDataBlock == NULL) {
1,264,984✔
1952
    taosMemoryFree(p);
×
1953
    return terrno;
×
1954
  }
1955

1956
  SColumnInfoData infoData = {0};
1,264,984✔
1957
  infoData.info.type = TSDB_DATA_TYPE_TIMESTAMP;
1,264,984✔
1958
  infoData.info.bytes = sizeof(TSKEY);
1,264,984✔
1959

1960
  // window start ts
1961
  void* px = taosArrayPush(p->pDataBlock, &infoData);
1,264,984✔
1962
  if (px == NULL) {
1,264,984✔
1963
    code = terrno;
×
1964
    goto _err;
×
1965
  }
1966

1967
  // window end ts
1968
  px = taosArrayPush(p->pDataBlock, &infoData);
1,264,984✔
1969
  if (px == NULL) {
1,264,984✔
1970
    code = terrno;
×
1971
    goto _err;
×
1972
  }
1973

1974
  infoData.info.type = TSDB_DATA_TYPE_UBIGINT;
1,264,984✔
1975
  infoData.info.bytes = sizeof(uint64_t);
1,264,984✔
1976

1977
  // uid
1978
  px = taosArrayPush(p->pDataBlock, &infoData);
1,264,984✔
1979
  if (px == NULL) {
1,264,984✔
1980
    code = terrno;
×
1981
    goto _err;
×
1982
  }
1983

1984
  // group id
1985
  px = taosArrayPush(p->pDataBlock, &infoData);
1,264,984✔
1986
  if (px == NULL) {
1,264,984✔
1987
    code = terrno;
×
1988
    goto _err;
×
1989
  }
1990

1991
  infoData.info.type = TSDB_DATA_TYPE_TIMESTAMP;
1,264,984✔
1992
  infoData.info.bytes = sizeof(TSKEY);
1,264,984✔
1993

1994
  // calculate start ts
1995
  px = taosArrayPush(p->pDataBlock, &infoData);
1,264,984✔
1996
  if (px == NULL) {
1,264,984✔
1997
    code = terrno;
×
1998
    goto _err;
×
1999
  }
2000

2001
  // calculate end ts
2002
  px = taosArrayPush(p->pDataBlock, &infoData);
1,264,984✔
2003
  if (px == NULL) {
1,264,984✔
2004
    code = terrno;
×
2005
    goto _err;
×
2006
  }
2007

2008
  // table name
2009
  infoData.info.type = TSDB_DATA_TYPE_VARCHAR;
1,264,984✔
2010
  infoData.info.bytes = VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN;
1,264,984✔
2011
  px = taosArrayPush(p->pDataBlock, &infoData);
1,264,984✔
2012
  if (px == NULL) {
1,264,984✔
2013
    code = terrno;
×
2014
    goto _err;
×
2015
  }
2016

2017
  *pBlock = p;
1,264,984✔
2018
  return code;
1,264,984✔
2019

2020
_err:
×
2021
  taosArrayDestroy(p->pDataBlock);
×
2022
  taosMemoryFree(p);
×
2023
  return code;
×
2024
}
2025

2026
int32_t blockCopyOneRow(const SSDataBlock* pDataBlock, int32_t rowIdx, SSDataBlock** pResBlock) {
×
2027
  QRY_PARAM_CHECK(pResBlock);
×
2028

2029
  if (pDataBlock == NULL) {
×
2030
    return TSDB_CODE_INVALID_PARA;
×
2031
  }
2032

2033
  SSDataBlock* pBlock = NULL;
×
2034
  int32_t      code = createDataBlock(&pBlock);
×
2035
  if (code) {
×
2036
    return code;
×
2037
  }
2038

2039
  pBlock->info = pDataBlock->info;
×
2040
  pBlock->info.pks[0].pData = NULL;
×
2041
  pBlock->info.pks[1].pData = NULL;
×
2042
  pBlock->info.rows = 0;
×
2043
  pBlock->info.capacity = 0;
×
2044

2045
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
×
2046
  for (int32_t i = 0; i < numOfCols; ++i) {
×
2047
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
×
2048
    if (p == NULL) {
×
2049
      blockDataDestroy(pBlock);
×
2050
      return terrno;
×
2051
    }
2052

2053
    SColumnInfoData colInfo = {.hasNull = true, .info = p->info};
×
2054
    code = blockDataAppendColInfo(pBlock, &colInfo);
×
2055
    if (code) {
×
2056
      blockDataDestroy(pBlock);
×
2057
      return code;
×
2058
    }
2059
  }
2060

2061
  code = blockDataEnsureCapacity(pBlock, 1);
×
2062
  if (code != TSDB_CODE_SUCCESS) {
×
2063
    blockDataDestroy(pBlock);
×
2064
    return code;
×
2065
  }
2066

2067
  for (int32_t i = 0; i < numOfCols; ++i) {
×
2068
    SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
×
2069
    SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i);
×
2070
    if (pDst == NULL || pSrc == NULL) {
×
2071
      blockDataDestroy(pBlock);
×
2072
      return terrno;
×
2073
    }
2074

2075
    bool  isNull = colDataIsNull(pSrc, pDataBlock->info.rows, rowIdx, NULL);
×
2076
    void* pData = NULL;
×
2077
    if (!isNull) {
×
2078
      pData = colDataGetData(pSrc, rowIdx);
×
2079
    }
2080

2081
    code = colDataSetVal(pDst, 0, pData, isNull);
×
2082
    if (code) {
×
2083
      blockDataDestroy(pBlock);
×
2084
      return code;
×
2085
    }
2086
  }
2087

2088
  pBlock->info.rows = 1;
×
2089

2090
  *pResBlock = pBlock;
×
2091
  return code;
×
2092
}
2093

2094
int32_t copyPkVal(SDataBlockInfo* pDst, const SDataBlockInfo* pSrc) {
1,358,001,272✔
2095
  int32_t code = TSDB_CODE_SUCCESS;
1,358,001,272✔
2096
  int32_t lino = 0;
1,358,001,272✔
2097
  if (!IS_VAR_DATA_TYPE(pSrc->pks[0].type)) {
1,358,001,272✔
2098
    return code;
1,349,771,803✔
2099
  }
2100

2101
  // prepare the pk buffer if needed
2102
  SValue* p = &pDst->pks[0];
8,256,816✔
2103

2104
  p->type = pSrc->pks[0].type;
8,354,454✔
2105
  p->pData = taosMemoryCalloc(1, pSrc->pks[0].nData);
8,355,075✔
2106
  QUERY_CHECK_NULL(p->pData, code, lino, _end, terrno);
8,352,058✔
2107

2108
  p->nData = pSrc->pks[0].nData;
8,353,276✔
2109
  memcpy(p->pData, pSrc->pks[0].pData, p->nData);
8,353,897✔
2110

2111
  p = &pDst->pks[1];
8,353,276✔
2112
  p->type = pSrc->pks[1].type;
8,355,075✔
2113
  p->pData = taosMemoryCalloc(1, pSrc->pks[1].nData);
8,355,075✔
2114
  QUERY_CHECK_NULL(p->pData, code, lino, _end, terrno);
8,352,655✔
2115

2116
  p->nData = pSrc->pks[1].nData;
8,353,244✔
2117
  memcpy(p->pData, pSrc->pks[1].pData, p->nData);
8,353,833✔
2118

2119
_end:
8,355,075✔
2120
  if (code != TSDB_CODE_SUCCESS) {
8,355,075✔
2121
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2122
  }
2123
  return code;
8,355,075✔
2124
}
2125

2126
int32_t createOneDataBlock(const SSDataBlock* pDataBlock, bool copyData, SSDataBlock** pResBlock) {
1,262,696,784✔
2127
  int32_t code = 0, lino = 0;
1,262,696,784✔
2128
  QRY_PARAM_CHECK(pResBlock);
1,262,696,784✔
2129
  TSDB_CHECK_NULL(pDataBlock, code, lino, _exit, TSDB_CODE_INVALID_PARA);
1,262,945,242✔
2130

2131
  SSDataBlock* pDstBlock = NULL;
1,262,945,242✔
2132
  TAOS_CHECK_EXIT(createDataBlock(&pDstBlock));
1,262,845,795✔
2133

2134
  pDstBlock->info = pDataBlock->info;
1,262,527,897✔
2135
  pDstBlock->info.pks[0].pData = NULL;
1,262,572,367✔
2136
  pDstBlock->info.pks[1].pData = NULL;
1,263,007,617✔
2137

2138
  pDstBlock->info.rows = 0;
1,263,141,872✔
2139
  pDstBlock->info.capacity = 0;
1,263,079,330✔
2140
  pDstBlock->info.rowSize = 0;
1,263,084,725✔
2141
  pDstBlock->info.id = pDataBlock->info.id;
1,262,962,593✔
2142
  pDstBlock->info.blankFill = pDataBlock->info.blankFill;
1,263,091,694✔
2143

2144
  size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
1,262,916,489✔
2145
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
2146
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
2147
    if (p == NULL) {
2,147,483,647✔
2148
      blockDataDestroy(pDstBlock);
×
2149
      TSDB_CHECK_NULL(p, code, lino, _exit, terrno);
×
2150
    }
2151

2152
    SColumnInfoData colInfo = {.hasNull = true, .info = p->info};
2,147,483,647✔
2153
    code = blockDataAppendColInfo(pDstBlock, &colInfo);
2,147,483,647✔
2154
    if (code) {
2,147,483,647✔
2155
      blockDataDestroy(pDstBlock);
×
2156
      TAOS_CHECK_EXIT(code);
×
2157
    }
2158
  }
2159

2160
  code = copyPkVal(&pDstBlock->info, &pDataBlock->info);
1,263,146,639✔
2161
  if (code != TSDB_CODE_SUCCESS) {
1,262,987,331✔
2162
    blockDataDestroy(pDstBlock);
×
2163
    uError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
2164
    TAOS_CHECK_EXIT(code);
×
2165
  }
2166

2167
  if (copyData) {
1,262,987,331✔
2168
    code = blockDataEnsureCapacity(pDstBlock, pDataBlock->info.rows);
585,730,617✔
2169
    if (code != TSDB_CODE_SUCCESS) {
585,726,449✔
2170
      blockDataDestroy(pDstBlock);
×
2171
      TAOS_CHECK_EXIT(code);
×
2172
    }
2173

2174
    for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
2175
      SColumnInfoData* pDst = taosArrayGet(pDstBlock->pDataBlock, i);
2,147,483,647✔
2176
      SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
2177
      if (pDst == NULL) {
2,147,483,647✔
2178
        blockDataDestroy(pDstBlock);
×
2179
        uError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
2180
        TSDB_CHECK_NULL(pDst, code, lino, _exit, terrno);
×
2181
      }
2182

2183
      if (pSrc == NULL) {
2,147,483,647✔
2184
        blockDataDestroy(pDstBlock);
×
2185
        uError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
2186
        TSDB_CHECK_NULL(pSrc, code, lino, _exit, terrno);
×
2187
      }
2188

2189
      int32_t ret = colDataAssign(pDst, pSrc, pDataBlock->info.rows, &pDataBlock->info);
2,147,483,647✔
2190
      if (ret < 0) {
2,147,483,647✔
2191
        code = ret;
×
2192
        blockDataDestroy(pDstBlock);
×
2193
        TAOS_CHECK_EXIT(code);
×
2194
      }
2195
    }
2196

2197
    pDstBlock->info.rows = pDataBlock->info.rows;
585,681,778✔
2198
    pDstBlock->info.capacity = pDataBlock->info.rows;
585,696,580✔
2199
  }
2200

2201
  *pResBlock = pDstBlock;
1,263,009,415✔
2202

2203
_exit:
1,262,828,656✔
2204
  
2205
  return code;
1,262,949,845✔
2206
}
2207

2208
int32_t createOneDataBlockWithColArray(const SSDataBlock* pDataBlock, SArray* pColArray, SSDataBlock** pResBlock) {
1,514,831✔
2209
  int32_t      code = TSDB_CODE_SUCCESS;
1,514,831✔
2210
  int32_t      lino = 0;
1,514,831✔
2211
  SSDataBlock* pDstBlock = NULL;
1,514,831✔
2212

2213
  QRY_PARAM_CHECK(pResBlock);
1,514,831✔
2214
  QUERY_CHECK_NULL(pDataBlock, code, lino, _return, TSDB_CODE_INVALID_PARA);
1,514,831✔
2215

2216
  QUERY_CHECK_CODE(createDataBlock(&pDstBlock), lino, _return);
1,514,831✔
2217

2218
  pDstBlock->info = pDataBlock->info;
1,514,831✔
2219
  pDstBlock->info.pks[0].pData = NULL;
1,514,831✔
2220
  pDstBlock->info.pks[1].pData = NULL;
1,514,831✔
2221

2222
  pDstBlock->info.rows = 0;
1,514,831✔
2223
  pDstBlock->info.capacity = 0;
1,514,831✔
2224
  pDstBlock->info.rowSize = 0;
1,514,831✔
2225
  pDstBlock->info.id = pDataBlock->info.id;
1,514,831✔
2226
  pDstBlock->info.blankFill = pDataBlock->info.blankFill;
1,514,831✔
2227

2228
  for (int32_t i = 0; i < taosArrayGetSize(pColArray); ++i) {
6,734,334✔
2229
    SColIdSlotIdPair* pColPair = taosArrayGet(pColArray, i);
5,219,503✔
2230
    QUERY_CHECK_NULL(pColPair, code, lino, _return, terrno);
5,219,503✔
2231

2232
    SColumnInfoData* p = taosArrayGet(pDataBlock->pDataBlock, pColPair->vtbSlotId);
5,219,503✔
2233
    QUERY_CHECK_NULL(p, code, lino, _return, terrno);
5,219,503✔
2234

2235
    SColumnInfoData pColInfo = {.hasNull = true, .info = p->info};
5,219,503✔
2236
    pColInfo.info.colId = pColPair->orgColId;
5,219,503✔
2237
    QUERY_CHECK_CODE(blockDataAppendColInfo(pDstBlock, &pColInfo), lino, _return);
5,219,503✔
2238
  }
2239

2240
  *pResBlock = pDstBlock;
1,514,831✔
2241
  return code;
1,514,831✔
2242
_return:
×
2243
  uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2244
  blockDataDestroy(pDstBlock);
×
2245
  return code;
×
2246
}
2247

2248
// create a new data block based on the template block, and fill data from the source block according to the column mapping
2249
int32_t createOneDataBlockWithTwoBlock(const SSDataBlock* pSrcBlock, const SSDataBlock* pTemplateBlock, SArray* pColMap,
1,052,515✔
2250
                                       SSDataBlock** pResBlock) {
2251
  int32_t      code = TSDB_CODE_SUCCESS;
1,052,515✔
2252
  int32_t      lino = 0;
1,052,515✔
2253
  SSDataBlock* pDstBlock = NULL;
1,052,515✔
2254

2255
  QRY_PARAM_CHECK(pResBlock);
1,052,515✔
2256
  QUERY_CHECK_NULL(pSrcBlock, code, lino, _return, TSDB_CODE_INVALID_PARA);
1,052,515✔
2257
  QUERY_CHECK_NULL(pTemplateBlock, code, lino, _return, TSDB_CODE_INVALID_PARA);
1,052,515✔
2258
  QUERY_CHECK_NULL(pColMap, code, lino, _return, TSDB_CODE_INVALID_PARA);
1,052,515✔
2259

2260
  code = createOneDataBlock(pTemplateBlock, false, &pDstBlock);
1,052,515✔
2261
  QUERY_CHECK_CODE(code, lino, _return);
1,052,515✔
2262
  code = blockDataEnsureCapacity(pDstBlock, pSrcBlock->info.rows);
1,052,515✔
2263
  QUERY_CHECK_CODE(code, lino, _return);
1,052,515✔
2264

2265
  if (pSrcBlock->pBlockAgg) {
1,052,515✔
2266
    size_t num = taosArrayGetSize(pDstBlock->pDataBlock);
×
2267
    pDstBlock->pBlockAgg = taosMemoryCalloc(num, sizeof(SColumnDataAgg));
×
2268
    QUERY_CHECK_NULL(pDstBlock->pBlockAgg, code, lino, _return, terrno);
×
2269
    for (int i = 0; i < num; ++i) {
×
2270
      pDstBlock->pBlockAgg[i].colId = i;
×
2271
      pDstBlock->pBlockAgg[i].numOfNull = pSrcBlock->info.rows;
×
2272
    }
2273
  } else {
2274
    for (int32_t i = 0; i < taosArrayGetSize(pDstBlock->pDataBlock); ++i) {
11,373,993✔
2275
      SColumnInfoData* pDst = taosArrayGet(pDstBlock->pDataBlock, i);
10,321,274✔
2276
      QUERY_CHECK_NULL(pDst, code, lino, _return, terrno);
10,321,478✔
2277
      colDataSetNNULL(pDst, 0, pSrcBlock->info.rows);
10,321,478✔
2278
    }
2279
  }
2280

2281
  for (int32_t i = 0; i < taosArrayGetSize(pColMap); i++) {
4,742,125✔
2282
    SColIdSlotIdPair* pColPair = taosArrayGet(pColMap, i);
3,689,610✔
2283
    QUERY_CHECK_NULL(pColPair, code, lino, _return, terrno);
3,689,610✔
2284
    for (int32_t j = 0; j < taosArrayGetSize(pSrcBlock->pDataBlock); j++) {
19,663,208✔
2285
      SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, j);
15,973,598✔
2286
      QUERY_CHECK_NULL(pSrcCol, code, lino, _return, terrno);
15,973,394✔
2287
      if (pSrcCol->info.colId == pColPair->orgColId) {
15,973,394✔
2288
        SColumnInfoData* pDstCol = taosArrayGet(pDstBlock->pDataBlock, pColPair->vtbSlotId);
3,689,406✔
2289
        QUERY_CHECK_NULL(pDstCol, code, lino, _return, terrno);
3,689,406✔
2290
        if (pSrcBlock->pBlockAgg) {
3,689,406✔
2291
          (void)memcpy(&pDstBlock->pBlockAgg[pColPair->vtbSlotId], &pSrcBlock->pBlockAgg[j], sizeof(SColumnDataAgg));
×
2292
          pDstBlock->pBlockAgg[pColPair->vtbSlotId].numOfNull = 0;
×
2293
        } else {
2294
          QUERY_CHECK_CODE(colDataAssign(pDstCol, pSrcCol, (int32_t)pSrcBlock->info.rows, &pSrcBlock->info), lino, _return);
3,689,610✔
2295
        }
2296
      }
2297
    }
2298
  }
2299

2300
  pDstBlock->info.rows = pSrcBlock->info.rows;
1,052,515✔
2301
  pDstBlock->info.capacity = pSrcBlock->info.rows;
1,052,515✔
2302
  pDstBlock->info.window = pSrcBlock->info.window;
1,052,515✔
2303

2304
  *pResBlock = pDstBlock;
1,052,515✔
2305
  return code;
1,052,515✔
2306
_return:
×
2307
  uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2308
  blockDataDestroy(pDstBlock);
×
2309
  return code;
×
2310
}
2311

2312
int32_t createDataBlock(SSDataBlock** pResBlock) {
2,107,121,003✔
2313
  QRY_PARAM_CHECK(pResBlock);
2,107,121,003✔
2314
  SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
2,107,176,942✔
2315
  if (pBlock == NULL) {
2,105,075,061✔
2316
    return terrno;
×
2317
  }
2318

2319
  pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
2,105,075,061✔
2320
  if (pBlock->pDataBlock == NULL) {
2,106,054,789✔
2321
    int32_t code = terrno;
×
2322
    taosMemoryFree(pBlock);
×
2323
    return code;
×
2324
  }
2325

2326
  *pResBlock = pBlock;
2,106,522,114✔
2327
  return 0;
2,106,641,716✔
2328
}
2329

2330
int32_t blockDataAppendColInfo(SSDataBlock* pBlock, SColumnInfoData* pColInfoData) {
2,147,483,647✔
2331
  if (pBlock->pDataBlock == NULL) {
2,147,483,647✔
2332
    pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData));
43,794,224✔
2333
    if (pBlock->pDataBlock == NULL) {
43,781,444✔
2334
      return terrno;
×
2335
    }
2336
  }
2337

2338
  void* p = taosArrayPush(pBlock->pDataBlock, pColInfoData);
2,147,483,647✔
2339
  if (p == NULL) {
2,147,483,647✔
2340
    return terrno;
×
2341
  }
2342

2343
  // todo disable it temporarily
2344
  //  A S S E R T(pColInfoData->info.type != 0);
2345
  if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
2346
    pBlock->info.hasVarCol = true;
1,831,957,593✔
2347
  }
2348
  pBlock->info.rowSize += pColInfoData->info.bytes;
2,147,483,647✔
2349

2350
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2351
}
2352

2353
SColumnInfoData createColumnInfoData(int16_t type, int32_t bytes, int16_t colId) {
2,147,483,647✔
2354
  SColumnInfoData col = {.hasNull = true};
2,147,483,647✔
2355
  col.info.colId = colId;
2,147,483,647✔
2356
  col.info.type = type;
2,147,483,647✔
2357
  col.info.bytes = bytes;
2,147,483,647✔
2358
  // if (type == TSDB_DATA_TYPE_BLOB || type == TSDB_DATA_TYPE_MEDIUMBLOB) {
2359
  //   col.info.bytes = TSDB_MAX_BLOB_LEN;
2360
  // }
2361
  return col;
2,147,483,647✔
2362
}
2363

2364
int32_t bdGetColumnInfoData(const SSDataBlock* pBlock, int32_t index, SColumnInfoData** pColInfoData) {
1,689,608,603✔
2365
  int32_t code = 0;
1,689,608,603✔
2366
  QRY_PARAM_CHECK(pColInfoData);
1,689,608,603✔
2367

2368
  if (index >= taosArrayGetSize(pBlock->pDataBlock)) {
1,689,708,074✔
2369
    return TSDB_CODE_INVALID_PARA;
×
2370
  }
2371

2372
  *pColInfoData = taosArrayGet(pBlock->pDataBlock, index);
1,689,525,435✔
2373
  if (*pColInfoData == NULL) {
1,689,948,966✔
UNCOV
2374
    code = terrno;
×
2375
  }
2376

2377
  return code;
1,689,890,065✔
2378
}
2379

2380
size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize, int32_t extraSize) {
52,650,199✔
2381
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
52,650,199✔
2382

2383
  int32_t payloadSize = pageSize - extraSize;
52,640,505✔
2384
  int32_t rowSize = pBlock->info.rowSize;
52,640,505✔
2385
  int32_t nRows = payloadSize / rowSize;
52,615,827✔
2386
  if (nRows < 1) {
52,615,827✔
2387
    uError("rows %d in page is too small, payloadSize:%d, rowSize:%d", nRows, payloadSize, rowSize);
×
2388
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2389
    return -1;
×
2390
  }
2391

2392
  int32_t numVarCols = 0;
52,615,827✔
2393
  int32_t numFixCols = 0;
52,615,827✔
2394
  for (int32_t i = 0; i < numOfCols; ++i) {
199,144,323✔
2395
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
146,531,724✔
2396
    if (pCol == NULL) {
146,518,342✔
2397
      return -1;
×
2398
    }
2399

2400
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
146,518,342✔
2401
      ++numVarCols;
14,790,018✔
2402
    } else {
2403
      ++numFixCols;
131,738,478✔
2404
    }
2405
  }
2406

2407
  // find the data payload whose size is greater than payloadSize
2408
  int result = -1;
52,612,599✔
2409
  int start = 1;
52,612,599✔
2410
  int end = nRows;
52,612,599✔
2411
  while (start <= end) {
503,297,269✔
2412
    int mid = start + (end - start) / 2;
450,684,670✔
2413
    // data size + var data type columns offset + fixed data type columns bitmap len
2414
    int midSize = rowSize * mid + numVarCols * sizeof(int32_t) * mid + numFixCols * BitmapLen(mid);
450,684,670✔
2415
    if (midSize > payloadSize) {
450,684,670✔
2416
      result = mid;
106,296,019✔
2417
      end = mid - 1;
106,296,019✔
2418
    } else {
2419
      start = mid + 1;
344,388,651✔
2420
    }
2421
  }
2422

2423
  int32_t newRows = (result != -1) ? result - 1 : nRows;
52,612,599✔
2424
  // the true value must be less than the value of nRows
2425
  if (newRows > nRows || newRows < 1) {
52,612,599✔
2426
    uError("invalid newRows:%d, nRows:%d", newRows, nRows);
505✔
2427
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
505✔
2428
    return -1;
×
2429
  }
2430

2431
  return newRows;
52,652,430✔
2432
}
2433

2434
void colDataDestroy(SColumnInfoData* pColData) {
2,147,483,647✔
2435
  if (!pColData) {
2,147,483,647✔
2436
    return;
160,315,628✔
2437
  }
2438

2439
  if (IS_VAR_DATA_TYPE(pColData->info.type)) {
2,147,483,647✔
2440
    taosMemoryFreeClear(pColData->varmeta.offset);
2,147,483,647✔
2441
    pColData->varmeta.allocLen = 0;
2,147,483,647✔
2442
    pColData->varmeta.length = 0;
2,147,483,647✔
2443
  } else {
2444
    taosMemoryFreeClear(pColData->nullbitmap);
2,147,483,647✔
2445
  }
2446

2447
  taosMemoryFreeClear(pColData->pData);
2,147,483,647✔
2448
}
2449

2450
static void doShiftBitmap(char* nullBitmap, size_t n, size_t total) {
44,722,555✔
2451
  int32_t len = BitmapLen(total);
44,722,555✔
2452

2453
  int32_t newLen = BitmapLen(total - n);
44,722,555✔
2454
  if (n % 8 == 0) {
44,722,555✔
2455
    (void)memmove(nullBitmap, nullBitmap + n / 8, newLen);
775,350✔
2456
  } else {
2457
    int32_t  tail = n % 8;
43,947,205✔
2458
    int32_t  i = 0;
43,947,205✔
2459
    uint8_t* p = (uint8_t*)nullBitmap;
43,947,205✔
2460

2461
    if (n < 8) {
43,947,205✔
2462
      while (i < len) {
93,488,247✔
2463
        uint8_t v = p[i];  // source bitmap value
87,691,667✔
2464
        p[i] = (v << tail);
87,691,667✔
2465

2466
        if (i < len - 1) {
87,691,667✔
2467
          uint8_t next = p[i + 1];
81,895,087✔
2468
          p[i] |= (next >> (8 - tail));
81,895,087✔
2469
        }
2470

2471
        i += 1;
87,691,667✔
2472
      }
2473
    } else if (n > 8) {
38,150,625✔
2474
      int32_t remain = (total % 8 != 0 && total % 8 <= tail) ? 1 : 0;
38,150,625✔
2475
      int32_t gap = len - newLen - remain;
38,150,625✔
2476
      while (i < newLen) {
732,899,726✔
2477
        uint8_t v = p[i + gap];
694,746,831✔
2478
        p[i] = (v << tail);
694,748,193✔
2479

2480
        if (i < newLen - 1 + remain) {
694,748,647✔
2481
          uint8_t next = p[i + gap + 1];
682,210,685✔
2482
          p[i] |= (next >> (8 - tail));
682,211,593✔
2483
        }
2484

2485
        i += 1;
694,749,101✔
2486
      }
2487
    }
2488
  }
2489
}
44,724,825✔
2490

2491
static int32_t colDataMoveVarData(SColumnInfoData* pColInfoData, size_t start, size_t end) {
×
2492
  int32_t dataOffset = -1;
×
2493
  int32_t dataLen = 0;
×
2494
  int32_t beigin = start;
×
2495
  while (beigin < end) {
×
2496
    int32_t offset = pColInfoData->varmeta.offset[beigin];
×
2497
    if (offset == -1) {
×
2498
      beigin++;
×
2499
      continue;
×
2500
    }
2501
    if (start != 0) {
×
2502
      pColInfoData->varmeta.offset[beigin] = dataLen;
×
2503
    }
2504
    char* data = pColInfoData->pData + offset;
×
2505
    if (dataOffset == -1) dataOffset = offset;  // mark the begin of data
×
2506
    int32_t type = pColInfoData->info.type;
×
2507
    if (type == TSDB_DATA_TYPE_JSON) {
×
2508
      dataLen += getJsonValueLen(data);
×
2509
    } else {
2510
      dataLen += varDataTLen(data);
×
2511
    }
2512
    beigin++;
×
2513
  }
2514

2515
  if (dataOffset > 0) {
×
2516
    (void)memmove(pColInfoData->pData, pColInfoData->pData + dataOffset, dataLen);
×
2517
  }
2518

2519
  (void)memmove(pColInfoData->varmeta.offset, &pColInfoData->varmeta.offset[start], (end - start) * sizeof(int32_t));
×
2520
  return dataLen;
×
2521
}
2522

2523
static void colDataTrimFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_t total) {
55,070,646✔
2524
  if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
55,070,646✔
2525
    // pColInfoData->varmeta.length = colDataMoveVarData(pColInfoData, n, total);
2526
    (void)memmove(pColInfoData->varmeta.offset, &pColInfoData->varmeta.offset[n], (total - n) * sizeof(int32_t));
10,347,637✔
2527

2528
    // clear the offset value of the unused entries.
2529
    memset(&pColInfoData->varmeta.offset[total - n], 0, n);
10,347,637✔
2530
  } else {
2531
    int32_t bytes = pColInfoData->info.bytes;
44,723,009✔
2532
    (void)memmove(pColInfoData->pData, ((char*)pColInfoData->pData + n * bytes), (total - n) * bytes);
44,723,009✔
2533
    doShiftBitmap(pColInfoData->nullbitmap, n, total);
44,723,009✔
2534
  }
2535
}
55,070,646✔
2536

2537
int32_t blockDataTrimFirstRows(SSDataBlock* pBlock, size_t n) {
71,711,328✔
2538
  if (n == 0) {
71,711,328✔
2539
    return TSDB_CODE_SUCCESS;
46,576,636✔
2540
  }
2541

2542
  if (pBlock->info.rows <= n) {
25,134,692✔
2543
    blockDataEmpty(pBlock);
462,810✔
2544
  } else {
2545
    size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
24,678,076✔
2546
    for (int32_t i = 0; i < numOfCols; ++i) {
79,748,722✔
2547
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
55,070,646✔
2548
      if (pColInfoData == NULL) {
55,070,646✔
2549
        return terrno;
×
2550
      }
2551

2552
      colDataTrimFirstNRows(pColInfoData, n, pBlock->info.rows);
55,070,646✔
2553
    }
2554

2555
    pBlock->info.rows -= n;
24,678,076✔
2556
  }
2557
  return TSDB_CODE_SUCCESS;
25,140,886✔
2558
}
2559

2560
static void colDataKeepFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_t total) {
16,722,689✔
2561
  if (n >= total || n == 0) return;
16,722,689✔
2562
  if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
16,723,042✔
2563
    if (pColInfoData->varmeta.length != 0) {
3,312,814✔
2564
      int32_t newLen = pColInfoData->varmeta.offset[n];
2,946,051✔
2565
      if (-1 == newLen) {
2,946,051✔
2566
        for (int i = n - 1; i >= 0; --i) {
357,523✔
2567
          newLen = pColInfoData->varmeta.offset[i];
356,549✔
2568
          if (newLen != -1) {
356,549✔
2569
            newLen += calcStrBytesByType(pColInfoData->info.type, pColInfoData->pData + newLen);
13,099✔
2570
            // if (pColInfoData->info.type == TSDB_DATA_TYPE_JSON) {
2571
            //   newLen += getJsonValueLen(pColInfoData->pData + newLen);
2572
            // } else if (IS_STR_DATA_BLOB(pColInfoData->info.type)) {
2573
            //   newLen += blobDataTLen(pColInfoData->pData + newLen);
2574
            // } else {
2575
            //   newLen += varDataTLen(pColInfoData->pData + newLen);
2576
            // }
2577
            break;
13,099✔
2578
          }
2579
        }
2580
      }
2581
      if (newLen <= -1) {
2,946,051✔
2582
        uFatal("colDataKeepFirstNRows: newLen:%d  old:%d", newLen, pColInfoData->varmeta.length);
974✔
2583
      } else {
2584
        pColInfoData->varmeta.length = newLen;
2,945,077✔
2585
      }
2586
    }
2587
    // pColInfoData->varmeta.length = colDataMoveVarData(pColInfoData, 0, n);
2588
    memset(&pColInfoData->varmeta.offset[n], 0, total - n);
3,313,644✔
2589
  }
2590
}
2591

2592
void blockDataKeepFirstNRows(SSDataBlock* pBlock, size_t n) {
49,723,883✔
2593
  if (n == 0) {
49,723,883✔
2594
    blockDataEmpty(pBlock);
3,650,995✔
2595
    return;
3,650,995✔
2596
  }
2597

2598
  if (pBlock->info.rows <= n) {
46,072,888✔
2599
    return;
39,424,640✔
2600
  } else {
2601
    size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
6,649,965✔
2602
    for (int32_t i = 0; i < numOfCols; ++i) {
23,372,177✔
2603
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
16,722,689✔
2604
      if (pColInfoData == NULL) {
16,723,042✔
2605
        continue;
×
2606
      }
2607

2608
      colDataKeepFirstNRows(pColInfoData, n, pBlock->info.rows);
16,723,042✔
2609
    }
2610

2611
    pBlock->info.rows = n;
6,649,488✔
2612
  }
2613
}
2614

2615
int32_t tEncodeDataBlock(void** buf, const SSDataBlock* pBlock) {
6,051,689✔
2616
  int64_t tbUid = pBlock->info.id.uid;
6,051,689✔
2617
  int16_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
6,051,689✔
2618
  int16_t hasVarCol = pBlock->info.hasVarCol;
6,052,373✔
2619
  int64_t rows = pBlock->info.rows;
6,052,373✔
2620
  int32_t sz = taosArrayGetSize(pBlock->pDataBlock);
6,052,373✔
2621

2622
  int32_t tlen = 0;
6,050,606✔
2623
  tlen += taosEncodeFixedI64(buf, tbUid);
6,050,606✔
2624
  tlen += taosEncodeFixedI16(buf, numOfCols);
6,050,606✔
2625
  tlen += taosEncodeFixedI16(buf, hasVarCol);
12,101,212✔
2626
  tlen += taosEncodeFixedI64(buf, rows);
6,050,606✔
2627
  tlen += taosEncodeFixedI32(buf, sz);
6,050,606✔
2628
  for (int32_t i = 0; i < sz; i++) {
12,263,783✔
2629
    SColumnInfoData* pColData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
6,211,695✔
2630
    if (pColData == NULL) {
6,211,980✔
2631
      return terrno;
×
2632
    }
2633

2634
    tlen += taosEncodeFixedI16(buf, pColData->info.colId);
6,212,379✔
2635
    tlen += taosEncodeFixedI8(buf, pColData->info.type);
6,212,379✔
2636
    tlen += taosEncodeFixedI32(buf, pColData->info.bytes);
6,212,379✔
2637
    tlen += taosEncodeFixedBool(buf, pColData->hasNull);
6,212,379✔
2638

2639
    if (IS_VAR_DATA_TYPE(pColData->info.type)) {
6,212,379✔
2640
      tlen += taosEncodeBinary(buf, pColData->varmeta.offset, sizeof(int32_t) * rows);
63,132✔
2641
    } else {
2642
      tlen += taosEncodeBinary(buf, pColData->nullbitmap, BitmapLen(rows));
12,361,626✔
2643
    }
2644

2645
    int32_t len = colDataGetLength(pColData, rows);
6,212,379✔
2646
    tlen += taosEncodeFixedI32(buf, len);
6,213,177✔
2647

2648
    if (pColData->reassigned && IS_VAR_DATA_TYPE(pColData->info.type)) {
6,213,177✔
2649
      for (int32_t row = 0; row < rows; ++row) {
×
2650
        char*   pData = pColData->pData + pColData->varmeta.offset[row];
×
2651
        int32_t colSize = calcStrBytesByType(pColData->info.type, pData);
×
2652
        // if (pColData->info.type == TSDB_DATA_TYPE_JSON) {
2653
        //   colSize = getJsonValueLen(pData);
2654
        // } else if (IS_STR_DATA_BLOB(pColData->info.type)) {
2655
        //   colSize = blobDataTLen(pData);
2656
        // } else {
2657
        //   colSize = varDataTLen(pData);
2658
        // }
2659
        tlen += taosEncodeBinary(buf, pData, colSize);
×
2660
      }
2661
    } else {
2662
      tlen += taosEncodeBinary(buf, pColData->pData, len);
12,426,354✔
2663
    }
2664
  }
2665
  return tlen;
6,052,088✔
2666
}
2667

2668
void* tDecodeDataBlock(const void* buf, SSDataBlock* pBlock) {
2,809,591✔
2669
  int32_t sz = 0;
2,809,591✔
2670
  int16_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
2,809,591✔
2671

2672
  buf = taosDecodeFixedU64(buf, &pBlock->info.id.uid);
5,618,954✔
2673
  buf = taosDecodeFixedI16(buf, &numOfCols);
2,809,477✔
2674
  buf = taosDecodeFixedI16(buf, &pBlock->info.hasVarCol);
2,809,477✔
2675
  buf = taosDecodeFixedI64(buf, &pBlock->info.rows);
5,618,954✔
2676
  buf = taosDecodeFixedI32(buf, &sz);
2,809,477✔
2677

2678
  pBlock->pDataBlock = taosArrayInit(sz, sizeof(SColumnInfoData));
2,809,477✔
2679
  if (pBlock->pDataBlock == NULL) {
2,809,420✔
2680
    return NULL;
×
2681
  }
2682

2683
  for (int32_t i = 0; i < sz; i++) {
5,705,063✔
2684
    SColumnInfoData data = {0};
2,895,472✔
2685
    buf = taosDecodeFixedI16(buf, &data.info.colId);
2,895,472✔
2686
    buf = taosDecodeFixedI8(buf, &data.info.type);
2,895,472✔
2687
    buf = taosDecodeFixedI32(buf, &data.info.bytes);
2,895,472✔
2688
    buf = taosDecodeFixedBool(buf, &data.hasNull);
2,895,472✔
2689

2690
    if (IS_VAR_DATA_TYPE(data.info.type)) {
2,895,472✔
2691
      buf = taosDecodeBinary(buf, (void**)&data.varmeta.offset, pBlock->info.rows * sizeof(int32_t));
23,325✔
2692
    } else {
2693
      buf = taosDecodeBinary(buf, (void**)&data.nullbitmap, BitmapLen(pBlock->info.rows));
5,767,607✔
2694
    }
2695
    if (buf == NULL) {
2,895,460✔
2696
      uError("failed to decode null bitmap/offset, type:%d", data.info.type);
×
2697
      goto _error;
×
2698
    }
2699

2700
    int32_t len = 0;
2,895,460✔
2701
    buf = taosDecodeFixedI32(buf, &len);
2,895,460✔
2702
    buf = taosDecodeBinary(buf, (void**)&data.pData, len);
2,895,460✔
2703
    if (buf == NULL) {
2,895,700✔
2704
      uError("failed to decode data, type:%d", data.info.type);
×
2705
      goto _error;
×
2706
    }
2707
    if (IS_VAR_DATA_TYPE(data.info.type)) {
2,895,700✔
2708
      data.varmeta.length = len;
11,805✔
2709
      data.varmeta.allocLen = len;
11,805✔
2710
    }
2711

2712
    void* px = taosArrayPush(pBlock->pDataBlock, &data);
2,895,700✔
2713
    if (px == NULL) {
2,895,643✔
2714
      return NULL;
×
2715
    }
2716
  }
2717

2718
  return (void*)buf;
2,809,591✔
2719
_error:
×
2720
  for (int32_t i = 0; i < sz; ++i) {
×
2721
    SColumnInfoData* pColInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i);
×
2722
    if (pColInfoData == NULL) {
×
2723
      break;
×
2724
    }
2725
    colDataDestroy(pColInfoData);
×
2726
  }
2727
  return NULL;
×
2728
}
2729

2730
static int32_t formatTimestamp(char* buf, size_t cap, int64_t val, int precision) {
49,028✔
2731
  time_t  tt;
49,028✔
2732
  int32_t ms = 0;
49,028✔
2733
  int32_t code = TSDB_CODE_SUCCESS;
49,028✔
2734
  int32_t lino = 0;
49,028✔
2735
  if (precision == TSDB_TIME_PRECISION_NANO) {
49,028✔
2736
    tt = (time_t)(val / 1000000000);
×
2737
    ms = val % 1000000000;
×
2738
  } else if (precision == TSDB_TIME_PRECISION_MICRO) {
49,028✔
2739
    tt = (time_t)(val / 1000000);
×
2740
    ms = val % 1000000;
×
2741
  } else {
2742
    tt = (time_t)(val / 1000);
49,028✔
2743
    ms = val % 1000;
49,028✔
2744
  }
2745

2746
  if (tt <= 0 && ms < 0) {
49,028✔
2747
    tt--;
×
2748
    if (precision == TSDB_TIME_PRECISION_NANO) {
×
2749
      ms += 1000000000;
×
2750
    } else if (precision == TSDB_TIME_PRECISION_MICRO) {
×
2751
      ms += 1000000;
×
2752
    } else {
2753
      ms += 1000;
×
2754
    }
2755
  }
2756
  struct tm ptm = {0};
49,028✔
2757
  if (taosLocalTime(&tt, &ptm, buf, cap, NULL) == NULL) {
49,028✔
2758
    code = TSDB_CODE_INTERNAL_ERROR;
×
2759
    TSDB_CHECK_CODE(code, lino, _end);
×
2760
  }
2761

2762
  size_t pos = taosStrfTime(buf, cap, "%Y-%m-%d %H:%M:%S", &ptm);
49,028✔
2763
  if (pos == 0) {
49,028✔
2764
    code = TSDB_CODE_OUT_OF_BUFFER;
×
2765
    TSDB_CHECK_CODE(code, lino, _end);
×
2766
  }
2767
  int32_t nwritten = 0;
49,028✔
2768
  if (precision == TSDB_TIME_PRECISION_NANO) {
49,028✔
2769
    nwritten = snprintf(buf + pos, cap - pos, ".%09d", ms);
×
2770
  } else if (precision == TSDB_TIME_PRECISION_MICRO) {
49,028✔
2771
    nwritten = snprintf(buf + pos, cap - pos, ".%06d", ms);
×
2772
  } else {
2773
    nwritten = snprintf(buf + pos, cap - pos, ".%03d", ms);
49,028✔
2774
  }
2775

2776
  if (nwritten >= cap - pos) {
49,028✔
2777
    code = TSDB_CODE_OUT_OF_BUFFER;
×
2778
    TSDB_CHECK_CODE(code, lino, _end);
×
2779
  }
2780

2781
_end:
49,028✔
2782
  if (code != TSDB_CODE_SUCCESS) {
49,028✔
2783
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2784
  }
2785
  return code;
49,028✔
2786
}
2787

2788
// for debug
2789
int32_t dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf, const char* taskIdStr, int64_t qId) {
15,862✔
2790
  int32_t lino = 0;
15,862✔
2791
  int32_t size = 2048 * 1024;
15,862✔
2792
  int32_t code = 0;
15,862✔
2793
  char*   dumpBuf = NULL;
15,862✔
2794
  char    pBuf[TD_TIME_STR_LEN] = {0};
15,862✔
2795
  int32_t rows = pDataBlock->info.rows;
15,862✔
2796
  int32_t len = 0;
15,862✔
2797

2798
  dumpBuf = taosMemoryCalloc(size, 1);
15,862✔
2799
  if (dumpBuf == NULL) {
15,862✔
2800
    return terrno;
×
2801
  }
2802

2803
  int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
15,862✔
2804
  len += tsnprintf(dumpBuf + len, size - len,
31,724✔
2805
                  "%" PRIx64 " %s %s|block type %d|child id %d|group id:%" PRIx64 "|uid:%" PRId64 "|rows:%" PRId64
2806
                  "|version:%" PRIu64 "|cal start:%" PRIu64 "|cal end:%" PRIu64 "|tbl:%s\n",
2807
                  qId, taskIdStr, flag, (int32_t)pDataBlock->info.type, pDataBlock->info.childId,
15,862✔
2808
                  pDataBlock->info.id.groupId, pDataBlock->info.id.uid, pDataBlock->info.rows, pDataBlock->info.version,
2809
                  pDataBlock->info.calWin.skey, pDataBlock->info.calWin.ekey, pDataBlock->info.parTbName);
15,862✔
2810
  if (len >= size - 1) {
15,862✔
2811
    goto _exit;
×
2812
  }
2813

2814
  for (int32_t j = 0; j < rows; j++) {
57,680✔
2815
    len += tsnprintf(dumpBuf + len, size - len, "%" PRIx64 " %s|", qId, flag);
41,818✔
2816
    if (len >= size - 1) {
41,818✔
2817
      goto _exit;
×
2818
    }
2819

2820
    for (int32_t k = 0; k < colNum; k++) {
148,732✔
2821
      SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k);
106,914✔
2822
      if (pColInfoData == NULL) {
106,914✔
2823
        code = terrno;
×
2824
        lino = __LINE__;
×
2825
        goto _exit;
×
2826
      }
2827

2828
      if (colDataIsNull(pColInfoData, rows, j, NULL) || !pColInfoData->pData) {
213,828✔
2829
        len += tsnprintf(dumpBuf + len, size - len, " %15s |", "NULL");
×
2830
        if (len >= size - 1) goto _exit;
×
2831
        continue;
×
2832
      }
2833

2834
      void* var = colDataGetData(pColInfoData, j);
106,914✔
2835
      switch (pColInfoData->info.type) {
106,914✔
2836
        case TSDB_DATA_TYPE_TIMESTAMP:
49,028✔
2837
          memset(pBuf, 0, sizeof(pBuf));
49,028✔
2838
          code = formatTimestamp(pBuf, sizeof(pBuf), *(uint64_t*)var, pColInfoData->info.precision);
49,028✔
2839
          if (code != TSDB_CODE_SUCCESS) {
49,028✔
2840
            TAOS_UNUSED(tsnprintf(pBuf, sizeof(pBuf), "NaN"));
×
2841
          }
2842
          len += tsnprintf(dumpBuf + len, size - len, " %25s |", pBuf);
49,028✔
2843
          if (len >= size - 1) goto _exit;
49,028✔
2844
          break;
49,028✔
2845
        case TSDB_DATA_TYPE_TINYINT:
×
2846
          len += tsnprintf(dumpBuf + len, size - len, " %15d |", *(int8_t*)var);
×
2847
          if (len >= size - 1) goto _exit;
×
2848
          break;
×
2849
        case TSDB_DATA_TYPE_UTINYINT:
×
2850
          len += tsnprintf(dumpBuf + len, size - len, " %15d |", *(uint8_t*)var);
×
2851
          if (len >= size - 1) goto _exit;
×
2852
          break;
×
2853
        case TSDB_DATA_TYPE_SMALLINT:
×
2854
          len += tsnprintf(dumpBuf + len, size - len, " %15d |", *(int16_t*)var);
×
2855
          if (len >= size - 1) goto _exit;
×
2856
          break;
×
2857
        case TSDB_DATA_TYPE_USMALLINT:
×
2858
          len += tsnprintf(dumpBuf + len, size - len, " %15d |", *(uint16_t*)var);
×
2859
          if (len >= size - 1) goto _exit;
×
2860
          break;
×
2861
        case TSDB_DATA_TYPE_INT:
34,402✔
2862
          len += tsnprintf(dumpBuf + len, size - len, " %15d |", *(int32_t*)var);
34,402✔
2863
          if (len >= size - 1) goto _exit;
34,402✔
2864
          break;
34,402✔
2865
        case TSDB_DATA_TYPE_UINT:
×
2866
          len += tsnprintf(dumpBuf + len, size - len, " %15u |", *(uint32_t*)var);
×
2867
          if (len >= size - 1) goto _exit;
×
2868
          break;
×
2869
        case TSDB_DATA_TYPE_BIGINT:
15,862✔
2870
          len += tsnprintf(dumpBuf + len, size - len, " %15" PRId64 " |", *(int64_t*)var);
15,862✔
2871
          if (len >= size - 1) goto _exit;
15,862✔
2872
          break;
15,862✔
2873
        case TSDB_DATA_TYPE_UBIGINT:
×
2874
          len += tsnprintf(dumpBuf + len, size - len, " %15" PRIu64 " |", *(uint64_t*)var);
×
2875
          if (len >= size - 1) goto _exit;
×
2876
          break;
×
2877
        case TSDB_DATA_TYPE_FLOAT:
×
2878
          len += tsnprintf(dumpBuf + len, size - len, " %15f |", *(float*)var);
×
2879
          if (len >= size - 1) goto _exit;
×
2880
          break;
×
2881
        case TSDB_DATA_TYPE_DOUBLE:
7,416✔
2882
          len += tsnprintf(dumpBuf + len, size - len, " %15f |", *(double*)var);
7,416✔
2883
          if (len >= size - 1) goto _exit;
7,416✔
2884
          break;
7,416✔
2885
        case TSDB_DATA_TYPE_BOOL:
×
2886
          len += tsnprintf(dumpBuf + len, size - len, " %15d |", *(bool*)var);
×
2887
          if (len >= size - 1) goto _exit;
×
2888
          break;
×
2889
        case TSDB_DATA_TYPE_VARCHAR:
206✔
2890
        case TSDB_DATA_TYPE_VARBINARY:
2891
        case TSDB_DATA_TYPE_GEOMETRY: {
2892
          memset(pBuf, 0, sizeof(pBuf));
206✔
2893
          char*   pData = colDataGetVarData(pColInfoData, j);
206✔
2894
          int32_t dataSize = TMIN(sizeof(pBuf), varDataLen(pData));
206✔
2895
          dataSize = TMIN(dataSize, 50);
206✔
2896
          memcpy(pBuf, varDataVal(pData), dataSize);
206✔
2897
          len += tsnprintf(dumpBuf + len, size - len, " %15s |", pBuf);
206✔
2898
          if (len >= size - 1) goto _exit;
206✔
2899
        } break;
206✔
2900
        case TSDB_DATA_TYPE_NCHAR: {
×
2901
          char*   pData = colDataGetVarData(pColInfoData, j);
×
2902
          int32_t dataSize = TMIN(sizeof(pBuf), varDataLen(pData));
×
2903
          memset(pBuf, 0, sizeof(pBuf));
×
2904
          code = taosUcs4ToMbs((TdUcs4*)varDataVal(pData), dataSize, pBuf, NULL);
×
2905
          if (code < 0) {
×
2906
            uError("func %s failed to convert to ucs charset since %s", __func__, tstrerror(code));
×
2907
            lino = __LINE__;
×
2908
            goto _exit;
×
2909
          } else {  // reset the length value
2910
            code = TSDB_CODE_SUCCESS;
×
2911
          }
2912
          len += tsnprintf(dumpBuf + len, size - len, " %15s |", pBuf);
×
2913
          if (len >= size - 1) goto _exit;
×
2914
        } break;
×
2915
        case TSDB_DATA_TYPE_MEDIUMBLOB:
×
2916
        case TSDB_DATA_TYPE_BLOB: {
2917
          memset(pBuf, 0, sizeof(pBuf));
×
2918
          char*   pData = colDataGetVarData(pColInfoData, j);
×
2919
          int32_t dataSize = TMIN(sizeof(pBuf), blobDataLen(pData));
×
2920
          dataSize = TMIN(dataSize, 50);
×
2921
          memcpy(pBuf, blobDataVal(pData), dataSize);
×
2922
          len += tsnprintf(dumpBuf + len, size - len, " %15s |", pBuf);
×
2923
          if (len >= size - 1) goto _exit;
×
2924
          break;
×
2925
        }
2926
      }
2927
    }
2928
    len += tsnprintf(dumpBuf + len, size - len, "%d\n", j);
41,818✔
2929
    if (len >= size - 1) goto _exit;
41,818✔
2930
  }
2931
  len += tsnprintf(dumpBuf + len, size - len, "%s |end\n", flag);
15,862✔
2932

2933
_exit:
15,862✔
2934
  if (code == TSDB_CODE_SUCCESS) {
15,862✔
2935
    *pDataBuf = dumpBuf;
15,862✔
2936
    dumpBuf = NULL;
15,862✔
2937
  } else {
2938
    uError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2939
    if (dumpBuf) {
×
2940
      taosMemoryFree(dumpBuf);
×
2941
    }
2942
  }
2943
  return code;
15,862✔
2944
}
2945

2946
int32_t buildSubmitReqFromDataBlock(SSubmitReq2** ppReq, const SSDataBlock* pDataBlock, const STSchema* pTSchema,
×
2947
                                    int64_t uid, int32_t vgId, tb_uid_t suid) {
2948
  SSubmitReq2* pReq = *ppReq;
×
2949
  SArray*      pVals = NULL;
×
2950
  int32_t      sz = 1;
×
2951
  int32_t      code = 0;
×
2952
  *ppReq = NULL;
×
2953
  terrno = 0;
×
2954

2955
  if (NULL == pReq) {
×
2956
    if (!(pReq = taosMemoryCalloc(1, sizeof(SSubmitReq2)))) {
×
2957
      code = terrno;
×
2958
      goto _end;
×
2959
    }
2960

2961
    if (!(pReq->aSubmitTbData = taosArrayInit(1, sizeof(SSubmitTbData)))) {
×
2962
      code = terrno;
×
2963
      goto _end;
×
2964
    }
2965
  }
2966

2967
  for (int32_t i = 0; i < sz; ++i) {
×
2968
    int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
×
2969
    int32_t rows = pDataBlock->info.rows;
×
2970

2971
    if (colNum <= 1) {  // invalid if only with TS col
×
2972
      continue;
×
2973
    }
2974

2975
    // the rsma result should has the same column number with schema.
2976
    if (colNum != pTSchema->numOfCols) {
×
2977
      uError("colNum %d is not equal to numOfCols %d", colNum, pTSchema->numOfCols);
×
2978
      code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2979
      goto _end;
×
2980
    }
2981

2982
    SSubmitTbData tbData = {0};
×
2983

2984
    if (!(tbData.aRowP = taosArrayInit(rows, sizeof(SRow*)))) {
×
2985
      code = terrno;
×
2986
      goto _end;
×
2987
    }
2988

2989
    tbData.suid = suid;
×
2990
    tbData.uid = uid;
×
2991
    tbData.sver = pTSchema->version;
×
2992

2993
    if (!pVals && !(pVals = taosArrayInit(colNum, sizeof(SColVal)))) {
×
2994
      code = terrno;
×
2995
      taosArrayDestroy(tbData.aRowP);
×
2996
      goto _end;
×
2997
    }
2998

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

3001
      taosArrayClear(pVals);
×
3002

3003
      bool    isStartKey = false;
×
3004
      int32_t offset = 0;
×
3005
      for (int32_t k = 0; k < colNum; ++k) {  // iterate by column
×
3006
        SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k);
×
3007
        if (pColInfoData == NULL) {
×
3008
          return terrno;
×
3009
        }
3010

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

3014
        switch (pColInfoData->info.type) {
×
3015
          case TSDB_DATA_TYPE_TIMESTAMP:
×
3016
            if (pColInfoData->info.type != pCol->type) {
×
3017
              uError("colType:%d mismatch with sechma colType:%d", pColInfoData->info.type, pCol->type);
×
3018
              terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3019
              return terrno;
×
3020
            }
3021
            if (!isStartKey) {
×
3022
              isStartKey = true;
×
3023
              if (PRIMARYKEY_TIMESTAMP_COL_ID != pCol->colId) {
×
3024
                uError("the first timestamp colId %d is not primary colId", pCol->colId);
×
3025
                terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3026
                return terrno;
×
3027
              }
3028
              SValue val = {.type = pCol->type};
×
3029
              VALUE_SET_TRIVIAL_DATUM(&val, *(TSKEY*)var);
×
3030
              SColVal cv = COL_VAL_VALUE(pCol->colId, val);
×
3031
              void*   px = taosArrayPush(pVals, &cv);
×
3032
              if (px == NULL) {
×
3033
                return terrno;
×
3034
              }
3035

3036
            } else if (colDataIsNull_s(pColInfoData, j)) {
×
3037
              SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type);
×
3038
              void*   px = taosArrayPush(pVals, &cv);
×
3039
              if (px == NULL) {
×
3040
                return terrno;
×
3041
              }
3042
            } else {
3043
              SValue val = {.type = pCol->type};
×
3044
              VALUE_SET_TRIVIAL_DATUM(&val, *(int64_t*)var);
×
3045
              SColVal cv = COL_VAL_VALUE(pCol->colId, val);
×
3046
              void*   px = taosArrayPush(pVals, &cv);
×
3047
              if (px == NULL) {
×
3048
                return terrno;
×
3049
              }
3050
            }
3051
            break;
×
3052
          case TSDB_DATA_TYPE_NCHAR:
×
3053
          case TSDB_DATA_TYPE_VARBINARY:
3054
          case TSDB_DATA_TYPE_VARCHAR: {  // TSDB_DATA_TYPE_BINARY
3055
            if (pColInfoData->info.type != pCol->type) {
×
3056
              uError("colType:%d mismatch with sechma colType:%d", pColInfoData->info.type, pCol->type);
×
3057
              terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3058
              return terrno;
×
3059
            }
3060
            if (colDataIsNull_s(pColInfoData, j)) {
×
3061
              SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type);
×
3062
              void*   px = taosArrayPush(pVals, &cv);
×
3063
              if (px == NULL) {
×
3064
                goto _end;
×
3065
              }
3066
            } else {
3067
              void*   data = colDataGetVarData(pColInfoData, j);
×
3068
              SValue  sv = (SValue){.type = pCol->type,
×
3069
                                    .nData = varDataLen(data),
×
3070
                                    .pData = (uint8_t*)varDataVal(data)};  // address copy, no value
×
3071
              SColVal cv = COL_VAL_VALUE(pCol->colId, sv);
×
3072
              void*   px = taosArrayPush(pVals, &cv);
×
3073
              if (px == NULL) {
×
3074
                code = terrno;
×
3075
                goto _end;
×
3076
              }
3077
            }
3078
            break;
×
3079
          }
3080
          case TSDB_DATA_TYPE_DECIMAL:
×
3081
          case TSDB_DATA_TYPE_MEDIUMBLOB:
3082
          case TSDB_DATA_TYPE_BLOB:
3083
            uError("the column type %" PRIi16 " is defined but not implemented yet", pColInfoData->info.type);
×
3084
            terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3085
            return terrno;
×
3086
            break;
3087
          case TSDB_DATA_TYPE_JSON:
×
3088
            uError("the column type %" PRIi16 " is defined but not implemented yet", pColInfoData->info.type);
×
3089
            terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3090
            return terrno;
×
3091
            break;
3092
          default:
×
3093
            if (pColInfoData->info.type < TSDB_DATA_TYPE_MAX && pColInfoData->info.type > TSDB_DATA_TYPE_NULL) {
×
3094
              if (colDataIsNull_s(pColInfoData, j)) {
×
3095
                SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type);  // should use pCol->type
×
3096
                void*   px = taosArrayPush(pVals, &cv);
×
3097
                if (px == NULL) {
×
3098
                  goto _end;
×
3099
                }
3100
              } else {
3101
                SValue sv = {.type = pCol->type};
×
3102
                if (pCol->type == pColInfoData->info.type) {
×
3103
                  valueSetDatum(&sv, sv.type, var, tDataTypes[pCol->type].bytes);
×
3104
                } else {
3105
                  /**
3106
                   *  1. sum/avg would convert to int64_t/uint64_t/double during aggregation
3107
                   *  2. below conversion may lead to overflow or loss, the app should select the right data type.
3108
                   */
3109
                  char tv[DATUM_MAX_SIZE] = {0};
×
3110
                  if (pColInfoData->info.type == TSDB_DATA_TYPE_FLOAT) {
×
3111
                    float v = 0;
×
3112
                    GET_TYPED_DATA(v, float, pColInfoData->info.type, var,
×
3113
                                   typeGetTypeModFromColInfo(&pColInfoData->info));
3114
                    SET_TYPED_DATA(&tv, pCol->type, v);
×
3115
                  } else if (pColInfoData->info.type == TSDB_DATA_TYPE_DOUBLE) {
×
3116
                    double v = 0;
×
3117
                    GET_TYPED_DATA(v, double, pColInfoData->info.type, var,
×
3118
                                   typeGetTypeModFromColInfo(&pColInfoData->info));
3119
                    SET_TYPED_DATA(&tv, pCol->type, v);
×
3120
                  } else if (IS_SIGNED_NUMERIC_TYPE(pColInfoData->info.type)) {
×
3121
                    int64_t v = 0;
×
3122
                    GET_TYPED_DATA(v, int64_t, pColInfoData->info.type, var,
×
3123
                                   typeGetTypeModFromColInfo(&pColInfoData->info));
3124
                    SET_TYPED_DATA(&tv, pCol->type, v);
×
3125
                  } else {
3126
                    uint64_t v = 0;
×
3127
                    GET_TYPED_DATA(v, uint64_t, pColInfoData->info.type, var,
×
3128
                                   typeGetTypeModFromColInfo(&pColInfoData->info));
3129
                    SET_TYPED_DATA(&tv, pCol->type, v);
×
3130
                  }
3131
                  valueSetDatum(&sv, sv.type, tv, tDataTypes[pCol->type].bytes);
×
3132
                }
3133
                SColVal cv = COL_VAL_VALUE(pCol->colId, sv);
×
3134
                void*   px = taosArrayPush(pVals, &cv);
×
3135
                if (px == NULL) {
×
3136
                  code = terrno;
×
3137
                  goto _end;
×
3138
                }
3139
              }
3140
            } else {
3141
              uError("the column type %" PRIi16 " is undefined\n", pColInfoData->info.type);
×
3142
              terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3143
              return terrno;
×
3144
            }
3145
            break;
×
3146
        }
3147
      }
3148
      SRow*             pRow = NULL;
×
3149
      SRowBuildScanInfo sinfo = {0};
×
3150
      if ((code = tRowBuild(pVals, pTSchema, &pRow, &sinfo)) < 0) {
×
3151
        tDestroySubmitTbData(&tbData, TSDB_MSG_FLG_ENCODE);
×
3152
        goto _end;
×
3153
      }
3154

3155
      void* px = taosArrayPush(tbData.aRowP, &pRow);
×
3156
      if (px == NULL) {
×
3157
        code = terrno;
×
3158
        goto _end;
×
3159
      }
3160
    }
3161

3162
    void* px = taosArrayPush(pReq->aSubmitTbData, &tbData);
×
3163
    if (px == NULL) {
×
3164
      code = terrno;
×
3165
      goto _end;
×
3166
    }
3167
  }
3168

3169
_end:
×
3170
  taosArrayDestroy(pVals);
×
3171
  if (code != 0) {
×
3172
    if (pReq) {
×
3173
      tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE);
×
3174
      taosMemoryFreeClear(pReq);
×
3175
    }
3176
  } else {
3177
    *ppReq = pReq;
×
3178
  }
3179

3180
  return code;
×
3181
}
3182

3183
// Construct the child table name in the form of <ctbName>_<stbName>_<groupId> and store it in `ctbName`.
3184
int32_t buildCtbNameAddGroupId(const char* stbName, char* ctbName, uint64_t groupId, size_t cap) {
×
3185
  int32_t code = TSDB_CODE_SUCCESS;
×
3186
  int32_t lino = 0;
×
3187
  char    tmp[TSDB_TABLE_NAME_LEN] = {0};
×
3188

3189
  if (ctbName == NULL || cap < TSDB_TABLE_NAME_LEN) {
×
3190
    code = TSDB_CODE_INTERNAL_ERROR;
×
3191
    TSDB_CHECK_CODE(code, lino, _end);
×
3192
  }
3193

3194
  if (stbName == NULL) {
×
3195
    snprintf(tmp, TSDB_TABLE_NAME_LEN, "_%" PRIu64, groupId);
×
3196
  } else {
3197
    int32_t i = strlen(stbName) - 1;
×
3198
    for (; i >= 0; i--) {
×
3199
      if (stbName[i] == '.') {
×
3200
        break;
×
3201
      }
3202
    }
3203
    snprintf(tmp, TSDB_TABLE_NAME_LEN, "_%s_%" PRIu64, stbName + i + 1, groupId);
×
3204
  }
3205

3206
  ctbName[cap - strlen(tmp) - 1] = 0;  // put stbname + groupId to the end
×
3207
  size_t prefixLen = strlen(ctbName);
×
3208
  ctbName = strncat(ctbName, tmp, cap - prefixLen - 1);
×
3209

3210
  for (char* p = ctbName; *p; ++p) {
×
3211
    if (*p == '.') *p = '_';
×
3212
  }
3213

3214
_end:
×
3215
  if (code != TSDB_CODE_SUCCESS) {
×
3216
    uError("%s failed at line %d since %s, ctbName:%s", __func__, lino, tstrerror(code), ctbName);
×
3217
  }
3218
  return code;
×
3219
}
3220

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

3225
bool alreadyAddGroupId(char* ctbName, int64_t groupId) {
×
3226
  char tmp[64] = {0};
×
3227
  snprintf(tmp, sizeof(tmp), "%" PRIu64, groupId);
×
3228
  size_t len1 = strlen(ctbName);
×
3229
  size_t len2 = strlen(tmp);
×
3230
  if (len1 < len2) return false;
×
3231
  return memcmp(ctbName + len1 - len2, tmp, len2) == 0;
×
3232
}
3233

3234
int32_t buildCtbNameByGroupId(const char* stbFullName, uint64_t groupId, char** pName) {
×
3235
  QRY_PARAM_CHECK(pName);
×
3236

3237
  char* pBuf = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN + 1);
×
3238
  if (!pBuf) {
×
3239
    return terrno;
×
3240
  }
3241

3242
  int32_t code = buildCtbNameByGroupIdImpl(stbFullName, groupId, pBuf);
×
3243
  if (code != TSDB_CODE_SUCCESS) {
×
3244
    taosMemoryFree(pBuf);
×
3245
  } else {
3246
    *pName = pBuf;
×
3247
  }
3248

3249
  return code;
×
3250
}
3251

3252
int32_t buildCtbNameByGroupIdImpl(const char* stbFullName, uint64_t groupId, char* cname) {
×
3253
  if (stbFullName[0] == 0) {
×
3254
    return TSDB_CODE_INVALID_PARA;
×
3255
  }
3256

3257
  SArray* tags = taosArrayInit(0, sizeof(SSmlKv));
×
3258
  if (tags == NULL) {
×
3259
    return terrno;
×
3260
  }
3261

3262
  if (cname == NULL) {
×
3263
    taosArrayDestroy(tags);
×
3264
    return TSDB_CODE_INVALID_PARA;
×
3265
  }
3266

3267
  int8_t      type = TSDB_DATA_TYPE_UBIGINT;
×
3268
  const char* name = "group_id";
×
3269
  int32_t     len = strlen(name);
×
3270

3271
  SSmlKv pTag = {.key = name, .keyLen = len, .type = type, .u = groupId, .length = sizeof(uint64_t)};
×
3272
  void*  px = taosArrayPush(tags, &pTag);
×
3273
  if (px == NULL) {
×
3274
    return terrno;
×
3275
  }
3276

3277
  RandTableName rname = {
×
3278
      .tags = tags, .stbFullName = stbFullName, .stbFullNameLen = strlen(stbFullName), .ctbShortName = cname};
×
3279

3280
  int32_t code = buildChildTableName(&rname);
×
3281
  if (code != TSDB_CODE_SUCCESS) {
×
3282
    return code;
×
3283
  }
3284

3285
  taosArrayDestroy(tags);
×
3286
  if ((rname.ctbShortName && rname.ctbShortName[0]) == 0) {
×
3287
    return TSDB_CODE_INVALID_PARA;
×
3288
  }
3289

3290
  return code;
×
3291
}
3292

3293
int32_t buildSinkDestTableName(char* parTbName, const char* stbFullName, uint64_t gid, bool newSubTableRule,
×
3294
                               char** dstTableName) {
3295
  int32_t code = TSDB_CODE_SUCCESS;
×
3296
  int32_t lino = 0;
×
3297

3298
  if (parTbName[0]) {
×
3299
    if (newSubTableRule && !isAutoTableName(parTbName) && !alreadyAddGroupId(parTbName, gid) && gid != 0 &&
×
3300
        stbFullName) {
3301
      *dstTableName = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN);
×
3302
      TSDB_CHECK_NULL(*dstTableName, code, lino, _end, terrno);
×
3303

3304
      tstrncpy(*dstTableName, parTbName, TSDB_TABLE_NAME_LEN);
×
3305
      code = buildCtbNameAddGroupId(stbFullName, *dstTableName, gid, TSDB_TABLE_NAME_LEN);
×
3306
      TSDB_CHECK_CODE(code, lino, _end);
×
3307
    } else {
3308
      *dstTableName = taosStrdup(parTbName);
×
3309
      TSDB_CHECK_NULL(*dstTableName, code, lino, _end, terrno);
×
3310
    }
3311
  } else {
3312
    code = buildCtbNameByGroupId(stbFullName, gid, dstTableName);
×
3313
    TSDB_CHECK_CODE(code, lino, _end);
×
3314
  }
3315

3316
_end:
×
3317
  return code;
×
3318
}
3319

3320
static int32_t blockCheckSize(int64_t blockSize) {
2,147,483,647✔
3321
  int32_t code = 0;
2,147,483,647✔
3322
  if (blockSize <= 0 || blockSize >= INT32_MAX) {
2,147,483,647✔
3323
    code = TSDB_CODE_OUT_OF_BUFFER;
2✔
3324
    uError("block size:%" PRId64 ", limit %d since %s", blockSize, INT32_MAX, tstrerror(code));
2✔
3325
  }
3326
  return code;
2,147,483,647✔
3327
}
3328
// return length of encoded data, return -1 if failed
3329
int32_t blockEncodeImpl(const SSDataBlock* pBlock, char* data, size_t dataBuflen, int32_t numOfCols, bool internal) {
715,192,073✔
3330
  int32_t code = blockDataCheck(pBlock);
715,192,073✔
3331
  if (code != TSDB_CODE_SUCCESS) {
715,300,854✔
UNCOV
3332
    terrno = code;
×
3333
    return -1;
×
3334
  }
3335
  int64_t blockSize = 0;
715,300,854✔
3336

3337
  int32_t dataLen = 0;
715,300,854✔
3338

3339
  // todo extract method
3340
  int32_t* version = (int32_t*)data;
715,300,854✔
3341
  *version = BLOCK_VERSION_1;
715,300,854✔
3342
  data += sizeof(int32_t);
715,259,711✔
3343

3344
  int32_t* actualLen = (int32_t*)data;
715,230,554✔
3345
  data += sizeof(int32_t);
715,230,554✔
3346

3347
  int32_t* rows = (int32_t*)data;
715,225,548✔
3348
  *rows = pBlock->info.rows;
715,225,548✔
3349
  data += sizeof(int32_t);
715,243,940✔
3350
  if (*rows <= 0) {
715,213,574✔
3351
    uError("Invalid rows %d in block", *rows);
×
3352
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3353
    return -1;
×
3354
  }
3355

3356
  int32_t* cols = (int32_t*)data;
715,139,318✔
3357
  *cols = numOfCols;
715,139,318✔
3358
  data += sizeof(int32_t);
715,155,751✔
3359

3360
  // flag segment.
3361
  // the inital bit is for column info
3362
  int32_t* flagSegment = (int32_t*)data;
715,204,816✔
3363
  *flagSegment = (1 << 31);
715,204,816✔
3364

3365
  data += sizeof(int32_t);
715,232,124✔
3366

3367
  uint64_t* groupId = (uint64_t*)data;
715,185,411✔
3368
  data += sizeof(uint64_t);
715,185,411✔
3369

3370
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
3371
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
3372
    if (pColInfoData == NULL) {
2,147,483,647✔
3373
      return -1;
×
3374
    }
3375

3376
    *((int8_t*)data) = pColInfoData->info.type;
2,147,483,647✔
3377
    data += sizeof(int8_t);
2,147,483,647✔
3378

3379
    int32_t bytes = pColInfoData->info.bytes;
2,147,483,647✔
3380
    *((int32_t*)data) = bytes;
2,147,483,647✔
3381
    if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
3382
      fillBytesForDecimalType((int32_t*)data, pColInfoData->info.type, pColInfoData->info.precision,
51,981,652✔
3383
                              pColInfoData->info.scale);
51,985,538✔
3384
    }
3385
    data += sizeof(int32_t);
2,147,483,647✔
3386
  }
3387

3388
  int32_t* colSizes = (int32_t*)data;
715,128,634✔
3389
  data += numOfCols * sizeof(int32_t);
715,128,634✔
3390

3391
  dataLen = internal ? blockDataGetSerialMetaSizeInternal(numOfCols) : blockDataGetSerialMetaSize(numOfCols);
715,153,981✔
3392
  blockSize = dataLen;
715,205,599✔
3393

3394
  int32_t numOfRows = pBlock->info.rows;
715,205,599✔
3395
  for (int32_t col = 0; col < numOfCols; ++col) {
2,147,483,647✔
3396
    SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, col);
2,147,483,647✔
3397
    if (pColRes == NULL) {
2,147,483,647✔
3398
      return -1;
×
3399
    }
3400

3401
    // copy the null bitmap
3402
    size_t metaSize = 0;
2,147,483,647✔
3403
    if (IS_VAR_DATA_TYPE(pColRes->info.type)) {
2,147,483,647✔
3404
      if (IS_STR_DATA_BLOB(pColRes->info.type)) {
838,065,683✔
3405
        metaSize = numOfRows * sizeof(int32_t);
29,241✔
3406
        if (dataLen + metaSize > dataBuflen) goto _exit;
29,241✔
3407
        memcpy(data, pColRes->varmeta.offset, metaSize);
29,241✔
3408
      } else {
3409
        metaSize = numOfRows * sizeof(int32_t);
838,457,675✔
3410
        if (dataLen + metaSize > dataBuflen) goto _exit;
838,457,675✔
3411
        memcpy(data, pColRes->varmeta.offset, metaSize);
838,457,675✔
3412
      }
3413
    } else {
3414
      metaSize = BitmapLen(numOfRows);
2,147,483,647✔
3415
      if (dataLen + metaSize > dataBuflen) goto _exit;
2,147,483,647✔
3416
      memcpy(data, pColRes->nullbitmap, metaSize);
2,147,483,647✔
3417
    }
3418

3419
    data += metaSize;
2,147,483,647✔
3420
    dataLen += metaSize;
2,147,483,647✔
3421
    blockSize += metaSize;
2,147,483,647✔
3422
    TAOS_CHECK_GOTO(blockCheckSize(blockSize), NULL, _exit);
2,147,483,647✔
3423

3424
    if (pColRes->reassigned && IS_VAR_DATA_TYPE(pColRes->info.type)) {
2,147,483,647✔
3425
      colSizes[col] = 0;
×
3426
      for (int32_t row = 0; row < numOfRows; ++row) {
×
3427
        char*   pColData = pColRes->pData + pColRes->varmeta.offset[row];
×
3428
        int32_t colSize = calcStrBytesByType(pColRes->info.type, pColData);
×
3429

3430
        colSizes[col] += colSize;
×
3431
        dataLen += colSize;
×
3432
        if (dataLen > dataBuflen) goto _exit;
×
3433

3434
        blockSize += colSize;
×
3435
        TAOS_CHECK_GOTO(blockCheckSize(blockSize), NULL, _exit);
×
3436

3437
        (void)memmove(data, pColData, colSize);
×
3438
        data += colSize;
×
3439
      }
3440
    } else {
3441
      colSizes[col] = colDataGetLength(pColRes, numOfRows);
2,147,483,647✔
3442
      dataLen += colSizes[col];
2,147,483,647✔
3443
      if (dataLen > dataBuflen) goto _exit;
2,147,483,647✔
3444

3445
      blockSize += colSizes[col];
2,147,483,647✔
3446
      TAOS_CHECK_GOTO(blockCheckSize(blockSize), NULL, _exit);
2,147,483,647✔
3447

3448
      if (pColRes->pData != NULL) {
2,147,483,647✔
3449
        (void)memmove(data, pColRes->pData, colSizes[col]);
2,147,483,647✔
3450
      }
3451
      data += colSizes[col];
2,147,483,647✔
3452
    }
3453

3454
    if (colSizes[col] <= 0 && !colDataIsNull_s(pColRes, 0) && pColRes->info.type != TSDB_DATA_TYPE_NULL) {
2,147,483,647✔
3455
      uWarn("Invalid colSize:%d colIdx:%d colType:%d while encoding block", colSizes[col], col, pColRes->info.type);
736✔
3456
      //terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
3457
      //return -1;
3458
    }
3459

3460
    colSizes[col] = htonl(colSizes[col]);
2,147,483,647✔
3461
    //    uError("blockEncode col bytes:%d, type:%d, size:%d, htonl size:%d", pColRes->info.bytes, pColRes->info.type,
3462
    //    htonl(colSizes[col]), colSizes[col]);
3463
  }
3464

3465
  bool* blankFill = (bool*)data;
715,153,958✔
3466
  *blankFill = pBlock->info.blankFill;
715,153,958✔
3467
  data += sizeof(bool);
715,246,490✔
3468

3469
  if (internal) {
715,300,486✔
3470
    uint8_t* scanFlag = (uint8_t*)data;
5,655,751✔
3471
    *scanFlag = pBlock->info.scanFlag;
5,655,751✔
3472
    data += sizeof(uint8_t);
5,655,751✔
3473
  }
3474

3475
  *actualLen = dataLen;
715,300,486✔
3476
#ifndef NO_UNALIGNED_ACCESS
3477
  *groupId = pBlock->info.id.groupId;
715,241,873✔
3478
#else
3479
  taosSetPUInt64Aligned(groupId, &pBlock->info.id.groupId);
3480
#endif
3481
  if (dataLen > dataBuflen) goto _exit;
715,167,466✔
3482

3483
  return dataLen;
715,167,466✔
3484

3485
_exit:
×
3486
  uError("blockEncode dataLen:%d, dataBuflen:%zu", dataLen, dataBuflen);
×
3487
  terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3488
  return -1;
×
3489
}
3490

3491
// return length of encoded data, return -1 if failed
3492
int32_t blockEncodeInternal(const SSDataBlock* pBlock, char* data, size_t dataBuflen, int32_t numOfCols) {
5,654,730✔
3493
  return blockEncodeImpl(pBlock, data, dataBuflen, numOfCols, true);
5,654,730✔
3494
}
3495

3496

3497
// return length of encoded data, return -1 if failed
3498
int32_t blockEncode(const SSDataBlock* pBlock, char* data, size_t dataBuflen, int32_t numOfCols) {
709,554,784✔
3499
  return blockEncodeImpl(pBlock, data, dataBuflen, numOfCols, false);
709,554,784✔
3500
}
3501

3502
int32_t blockDecodeImpl(SSDataBlock* pBlock, const char* pData, const char** pEndPos, bool internal) {
430,471,481✔
3503
  const char* pStart = pData;
430,471,481✔
3504

3505
  int32_t version = *(int32_t*)pStart;
430,471,481✔
3506
  pStart += sizeof(int32_t);
430,472,649✔
3507

3508
  // total length sizeof(int32_t)
3509
  int32_t dataLen = *(int32_t*)pStart;
430,472,269✔
3510
  pStart += sizeof(int32_t);
430,468,922✔
3511

3512
  // total rows sizeof(int32_t)
3513
  int32_t numOfRows = *(int32_t*)pStart;
430,470,982✔
3514
  pStart += sizeof(int32_t);
430,465,175✔
3515
  if (numOfRows <= 0) {
430,457,815✔
3516
    uError("block decode numOfRows:%d error", numOfRows);
×
3517
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3518
    return terrno;
×
3519
  }
3520

3521
  // total columns sizeof(int32_t)
3522
  int32_t numOfCols = *(int32_t*)pStart;
430,457,815✔
3523
  pStart += sizeof(int32_t);
430,468,948✔
3524

3525
  // has column info segment
3526
  int32_t flagSeg = *(int32_t*)pStart;
430,471,945✔
3527
  int32_t hasColumnInfo = (flagSeg >> 31);
430,467,806✔
3528
  pStart += sizeof(int32_t);
430,467,806✔
3529

3530
  // group id sizeof(uint64_t)
3531
#ifndef NO_UNALIGNED_ACCESS
3532
  pBlock->info.id.groupId = *(uint64_t*)pStart;
430,468,999✔
3533
#else
3534
  taosSetPUInt64Aligned(&pBlock->info.id.groupId, (uint64_t*)pStart);
3535
#endif
3536
  pStart += sizeof(uint64_t);
430,471,589✔
3537

3538
  if (pBlock->pDataBlock == NULL) {
430,468,082✔
3539
    pBlock->pDataBlock = taosArrayInit_s(sizeof(SColumnInfoData), numOfCols);
1,977,263✔
3540
    if (pBlock->pDataBlock == NULL) {
1,977,263✔
3541
      return terrno;
×
3542
    }
3543
  }
3544

3545
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
3546
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
3547
    if (pColInfoData == NULL) {
2,147,483,647✔
3548
      return terrno;
×
3549
    }
3550

3551
    pColInfoData->info.type = *(int8_t*)pStart;
2,147,483,647✔
3552
    pStart += sizeof(int8_t);
2,147,483,647✔
3553

3554
    pColInfoData->info.bytes = *(int32_t*)pStart;
2,147,483,647✔
3555
    if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
3556
      extractDecimalTypeInfoFromBytes(&pColInfoData->info.bytes, &pColInfoData->info.precision,
50,580,889✔
3557
                                      &pColInfoData->info.scale);
3558
    }
3559
    pStart += sizeof(int32_t);
2,147,483,647✔
3560

3561
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
3562
      pBlock->info.hasVarCol = true;
488,756,475✔
3563
    }
3564
  }
3565

3566
  int32_t code = blockDataEnsureCapacity(pBlock, numOfRows);
430,469,399✔
3567
  if (code) {
430,467,565✔
3568
    return code;
×
3569
  }
3570

3571
  int32_t* colLen = (int32_t*)pStart;
430,467,565✔
3572
  pStart += sizeof(int32_t) * numOfCols;
430,467,565✔
3573

3574
  for (int32_t i = 0; i < numOfCols; ++i) {
2,147,483,647✔
3575
    int oneColsLen = htonl(colLen[i]);
2,147,483,647✔
3576
    if (oneColsLen < 0) {
2,147,483,647✔
3577
      uError("block decode colLen:%d error, colIdx:%d", oneColsLen, i);
×
3578
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3579
      return terrno;
×
3580
    }
3581

3582
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2,147,483,647✔
3583
    if (pColInfoData == NULL) {
2,147,483,647✔
3584
      return terrno;
×
3585
    }
3586

3587
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
2,147,483,647✔
3588
      memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * numOfRows);
488,742,512✔
3589
      pStart += sizeof(int32_t) * numOfRows;
488,751,385✔
3590

3591
      if (oneColsLen > 0 && pColInfoData->varmeta.allocLen < oneColsLen) {
488,751,389✔
3592
        char* tmp = taosMemoryRealloc(pColInfoData->pData, oneColsLen);
237,362,243✔
3593
        if (tmp == NULL) {
237,361,890✔
3594
          return terrno;
×
3595
        }
3596

3597
        pColInfoData->pData = tmp;
237,361,890✔
3598
        pColInfoData->varmeta.allocLen = oneColsLen;
237,361,890✔
3599
      }
3600

3601
      pColInfoData->varmeta.length = oneColsLen;
488,751,036✔
3602
    } else {
3603
      memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(numOfRows));
1,802,209,484✔
3604
      pStart += BitmapLen(numOfRows);
1,802,221,652✔
3605
    }
3606

3607
    // TODO
3608
    // setting this flag to true temporarily so aggregate function on stable will
3609
    // examine NULL value for non-primary key column
3610
    pColInfoData->hasNull = true;
2,147,483,647✔
3611

3612
    if (oneColsLen > 0) {
2,147,483,647✔
3613
      memcpy(pColInfoData->pData, pStart, oneColsLen);
2,147,483,647✔
3614
    } else if (!colDataIsNull_s(pColInfoData, 0) && pColInfoData->info.type != TSDB_DATA_TYPE_NULL) {
87,774,554✔
3615
      uError("block decode colLen:%d error, colIdx:%d, type:%d", oneColsLen, i, pColInfoData->info.type);
×
3616
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3617
      return terrno;
×
3618
    }
3619

3620
    pStart += oneColsLen;
2,147,483,647✔
3621
  }
3622

3623
  bool blankFill = *(bool*)pStart;
430,455,913✔
3624
  pStart += sizeof(bool);
430,460,642✔
3625

3626
  if (internal && (pStart - pData) < dataLen) {
430,455,541✔
3627
    pBlock->info.scanFlag = *(uint8_t*)pStart;
5,655,748✔
3628
    pStart += sizeof(uint8_t);
5,655,953✔
3629
  }
3630

3631
  pBlock->info.dataLoad = 1;
430,455,746✔
3632
  pBlock->info.rows = numOfRows;
430,473,124✔
3633
  pBlock->info.blankFill = blankFill;
430,473,365✔
3634
  if (internal && (pStart - pData != dataLen)) {
430,474,304✔
3635
    uError("block decode msg len error, pStart:%p, pData:%p, dataLen:%d", pStart, pData, dataLen);
×
3636
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3637
    return terrno;
×
3638
  }
3639

3640
  if (pEndPos != NULL) {
430,474,304✔
3641
    *pEndPos = pStart;
426,126,427✔
3642
  }
3643

3644
  code = blockDataCheck(pBlock);
430,475,593✔
3645
  if (code != TSDB_CODE_SUCCESS) {
430,467,659✔
3646
    terrno = code;
1,080✔
3647
    return code;
×
3648
  }
3649

3650
  return TSDB_CODE_SUCCESS;
430,466,579✔
3651
}
3652

3653
int32_t blockDecodeInternal(SSDataBlock* pBlock, const char* pData, const char** pEndPos) {
427,294,947✔
3654
  return blockDecodeImpl(pBlock, pData, pEndPos, true);
427,294,947✔
3655
}
3656
int32_t blockDecode(SSDataBlock* pBlock, const char* pData, const char** pEndPos) {
3,177,116✔
3657
  return blockDecodeImpl(pBlock, pData, pEndPos, false);
3,177,116✔
3658
}
3659

3660
int32_t trimDataBlock(SSDataBlock* pBlock, int32_t totalRows, const bool* pBoolList) {
85,504,304✔
3661
  //  int32_t totalRows = pBlock->info.rows;
3662
  int32_t code = 0;
85,504,304✔
3663
  int32_t bmLen = BitmapLen(totalRows);
85,504,304✔
3664
  char*   pBitmap = NULL;
85,504,304✔
3665
  int32_t maxRows = 0;
85,504,304✔
3666

3667
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
85,504,304✔
3668
  if (!pBoolList) {
85,502,222✔
3669
    for (int32_t i = 0; i < numOfCols; ++i) {
229,570,622✔
3670
      SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
200,222,446✔
3671
      // it is a reserved column for scalar function, and no data in this column yet.
3672
      if (pDst->pData == NULL) {
200,193,900✔
3673
        continue;
8,383,942✔
3674
      }
3675

3676
      int32_t numOfRows = 0;
191,824,601✔
3677
      if (IS_VAR_DATA_TYPE(pDst->info.type)) {
191,824,601✔
3678
        pDst->varmeta.length = 0;
26,604,975✔
3679
      } else {
3680
        memset(pDst->nullbitmap, 0, bmLen);
165,227,304✔
3681
      }
3682
    }
3683
    return code;
29,348,176✔
3684
  }
3685

3686
  for (int32_t i = 0; i < numOfCols; ++i) {
281,483,481✔
3687
    SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
225,322,798✔
3688
    // it is a reserved column for scalar function, and no data in this column yet.
3689
    if (pDst->pData == NULL || (IS_VAR_DATA_TYPE(pDst->info.type) && pDst->varmeta.length == 0)) {
225,325,984✔
3690
      continue;
5,796,009✔
3691
    }
3692

3693
    int32_t numOfRows = 0;
219,545,941✔
3694
    if (IS_VAR_DATA_TYPE(pDst->info.type)) {
266,580,519✔
3695
      int32_t j = 0;
47,054,967✔
3696
      int32_t oriLen = colDataGetLength(pDst, totalRows);
47,054,967✔
3697
      char * tmp = (char*)taosMemoryMalloc(oriLen);
47,029,723✔
3698
      if (tmp == NULL) {
47,029,917✔
3699
        return terrno;
×
3700
      }
3701
      pDst->varmeta.length = 0;
47,029,917✔
3702
      while (j < totalRows) {
2,147,483,647✔
3703
        if (pBoolList[j] == 0) {
2,147,483,647✔
3704
          j += 1;
2,147,483,647✔
3705
          continue;
2,147,483,647✔
3706
        }
3707

3708
        if (colDataIsNull_var(pDst, j)) {
1,766,909,496✔
3709
          colDataSetNull_var(pDst, numOfRows);
3,997,835✔
3710
        } else {
3711
          char*   p1 = colDataGetVarData(pDst, j);
1,764,183,823✔
3712
          int32_t len = calcStrBytesByType(pDst->info.type, p1);
1,764,215,008✔
3713
          memcpy(tmp + pDst->varmeta.length, p1, len);
1,764,216,912✔
3714
          pDst->varmeta.offset[numOfRows] = pDst->varmeta.length;
1,764,235,022✔
3715
          pDst->varmeta.length += len;
1,764,261,590✔
3716
        }
3717
        numOfRows += 1;
1,768,288,344✔
3718
        j += 1;
1,768,288,344✔
3719
      }
3720
      taosMemoryFree(pDst->pData);
47,036,522✔
3721
      pDst->pData = tmp;
47,034,578✔
3722
      pDst->varmeta.allocLen = oriLen;
47,034,952✔
3723
      if (maxRows < numOfRows) {
47,034,578✔
3724
        maxRows = numOfRows;
4,528,710✔
3725
      }
3726
    } else {
3727
      if (pBitmap == NULL) {
172,500,073✔
3728
        pBitmap = taosMemoryCalloc(1, bmLen);
55,006,699✔
3729
        if (pBitmap == NULL) {
55,013,449✔
3730
          return terrno;
×
3731
        }
3732
      }
3733

3734
      memcpy(pBitmap, pDst->nullbitmap, bmLen);
172,506,823✔
3735
      memset(pDst->nullbitmap, 0, bmLen);
172,510,053✔
3736

3737
      int32_t j = 0;
172,518,095✔
3738

3739
      switch (pDst->info.type) {
172,518,095✔
3740
        case TSDB_DATA_TYPE_BIGINT:
93,077,063✔
3741
        case TSDB_DATA_TYPE_UBIGINT:
3742
        case TSDB_DATA_TYPE_DOUBLE:
3743
        case TSDB_DATA_TYPE_TIMESTAMP:
3744
          while (j < totalRows) {
2,147,483,647✔
3745
            if (pBoolList[j] == 0) {
2,147,483,647✔
3746
              j += 1;
2,147,483,647✔
3747
              continue;
2,147,483,647✔
3748
            }
3749

3750
            if (BMIsNull(pBitmap, j)) {
2,147,483,647✔
3751
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
262,746,987✔
3752
            } else {
3753
              ((int64_t*)pDst->pData)[numOfRows] = ((int64_t*)pDst->pData)[j];
2,147,483,647✔
3754
            }
3755
            numOfRows += 1;
2,147,483,647✔
3756
            j += 1;
2,147,483,647✔
3757
          }
3758
          break;
163,245,843✔
3759
        case TSDB_DATA_TYPE_FLOAT:
64,658,305✔
3760
        case TSDB_DATA_TYPE_INT:
3761
        case TSDB_DATA_TYPE_UINT:
3762
          while (j < totalRows) {
2,147,483,647✔
3763
            if (pBoolList[j] == 0) {
2,147,483,647✔
3764
              j += 1;
2,147,483,647✔
3765
              continue;
2,147,483,647✔
3766
            }
3767
            if (BMIsNull(pBitmap, j)) {
2,147,483,647✔
3768
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
169,213,790✔
3769
            } else {
3770
              ((int32_t*)pDst->pData)[numOfRows] = ((int32_t*)pDst->pData)[j];
2,147,483,647✔
3771
            }
3772
            numOfRows += 1;
2,147,483,647✔
3773
            j += 1;
2,147,483,647✔
3774
          }
3775
          break;
67,641,676✔
3776
        case TSDB_DATA_TYPE_SMALLINT:
5,656,539✔
3777
        case TSDB_DATA_TYPE_USMALLINT:
3778
          while (j < totalRows) {
1,038,349,939✔
3779
            if (pBoolList[j] == 0) {
1,032,675,985✔
3780
              j += 1;
822,671,647✔
3781
              continue;
822,671,647✔
3782
            }
3783
            if (BMIsNull(pBitmap, j)) {
210,014,045✔
3784
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
6,373,869✔
3785
            } else {
3786
              ((int16_t*)pDst->pData)[numOfRows] = ((int16_t*)pDst->pData)[j];
203,651,184✔
3787
            }
3788
            numOfRows += 1;
210,021,753✔
3789
            j += 1;
210,021,753✔
3790
          }
3791
          break;
5,673,954✔
3792
        case TSDB_DATA_TYPE_BOOL:
7,971,212✔
3793
        case TSDB_DATA_TYPE_TINYINT:
3794
        case TSDB_DATA_TYPE_UTINYINT:
3795
          while (j < totalRows) {
1,198,687,681✔
3796
            if (pBoolList[j] == 0) {
1,190,667,893✔
3797
              j += 1;
927,965,758✔
3798
              continue;
927,965,758✔
3799
            }
3800
            if (BMIsNull(pBitmap, j)) {
262,744,611✔
3801
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
10,743,998✔
3802
            } else {
3803
              ((int8_t*)pDst->pData)[numOfRows] = ((int8_t*)pDst->pData)[j];
252,017,340✔
3804
            }
3805
            numOfRows += 1;
262,750,711✔
3806
            j += 1;
262,750,711✔
3807
          }
3808
          break;
8,019,788✔
3809
        case TSDB_DATA_TYPE_DECIMAL64:
1,148,439✔
3810
        case TSDB_DATA_TYPE_DECIMAL:
3811
          while (j < totalRows) {
1,149,105,181✔
3812
            if (pBoolList[j] == 0) {
1,147,960,257✔
3813
              j += 1;
390,030,299✔
3814
              continue;
390,030,299✔
3815
            }
3816
            if (BMIsNull(pBitmap, j)) {
757,944,721✔
3817
              colDataSetNull_f(pDst->nullbitmap, numOfRows);
×
3818
            } else {
3819
              memcpy(pDst->pData + numOfRows * pDst->info.bytes, pDst->pData + j * pDst->info.bytes, pDst->info.bytes);
757,946,830✔
3820
            }
3821
            numOfRows += 1;
757,926,443✔
3822
            j += 1;
757,926,443✔
3823
          }
3824
          break;
1,144,924✔
3825
        case TSDB_DATA_TYPE_BLOB:
×
3826
        case TSDB_DATA_TYPE_MEDIUMBLOB: {
3827
          // impl later
3828
          break;
×
3829
        }
3830
      }
3831
    }
3832

3833
    if (maxRows < numOfRows) {
219,534,301✔
3834
      maxRows = numOfRows;
51,619,961✔
3835
    }
3836
  }
3837

3838
  pBlock->info.rows = maxRows;
56,160,683✔
3839
  if (pBitmap != NULL) {
56,158,739✔
3840
    taosMemoryFree(pBitmap);
55,014,695✔
3841
  }
3842

3843
  return code;
56,159,319✔
3844
}
3845

3846
int32_t blockGetEncodeSize(const SSDataBlock* pBlock) {
709,848,550✔
3847
  return blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSize(pBlock);
709,848,550✔
3848
}
3849

3850
int32_t blockGetInternalEncodeSize(const SSDataBlock* pBlock) {
9,498,437✔
3851
  return blockDataGetSerialMetaSizeInternal(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSize(pBlock);
9,498,437✔
3852
}
3853

3854

3855
int32_t blockDataGetSortedRows(SSDataBlock* pDataBlock, SArray* pOrderInfo) {
69,036,427✔
3856
  if (!pDataBlock || !pOrderInfo) return 0;
69,036,427✔
3857
  for (int32_t i = 0; i < taosArrayGetSize(pOrderInfo); ++i) {
138,098,862✔
3858
    SBlockOrderInfo* pOrder = taosArrayGet(pOrderInfo, i);
69,051,863✔
3859
    if (pOrder == NULL) {
69,052,025✔
3860
      continue;
×
3861
    }
3862

3863
    pOrder->pColData = taosArrayGet(pDataBlock->pDataBlock, pOrder->slotId);
69,052,025✔
3864
    if (pOrder->pColData == NULL) {
69,050,079✔
3865
      continue;
×
3866
    }
3867

3868
    pOrder->compFn = getKeyComparFunc(pOrder->pColData->info.type, pOrder->order);
69,051,409✔
3869
  }
3870

3871
  SSDataBlockSortHelper sortHelper = {.orderInfo = pOrderInfo, .pDataBlock = pDataBlock};
69,050,440✔
3872

3873
  int32_t rowIdx = 0, nextRowIdx = 1;
69,053,063✔
3874
  for (; rowIdx < pDataBlock->info.rows && nextRowIdx < pDataBlock->info.rows; ++rowIdx, ++nextRowIdx) {
1,701,782,699✔
3875
    if (dataBlockCompar(&nextRowIdx, &rowIdx, &sortHelper) < 0) {
1,655,200,966✔
3876
      break;
22,475,175✔
3877
    }
3878
  }
3879

3880
  return nextRowIdx;
69,052,771✔
3881
}
3882

3883
#define BLOCK_DATA_CHECK_TRESSA(o)                      \
3884
  if (!(o)) {                                           \
3885
    uError("blockDataCheck failed! line:%d", __LINE__); \
3886
    return TSDB_CODE_INTERNAL_ERROR;                    \
3887
  }
3888
int32_t blockDataCheck(const SSDataBlock* pDataBlock) {
2,147,483,647✔
3889
  if (tsSafetyCheckLevel == TSDB_SAFETY_CHECK_LEVELL_NEVER || NULL == pDataBlock || pDataBlock->info.rows == 0) {
2,147,483,647✔
3890
    return TSDB_CODE_SUCCESS;
804,092,202✔
3891
  }
3892

3893
  BLOCK_DATA_CHECK_TRESSA(pDataBlock->info.rows > 0);
2,147,483,647✔
3894
  if (!pDataBlock->info.dataLoad) {
2,147,483,647✔
3895
    return TSDB_CODE_SUCCESS;
293,667,370✔
3896
  }
3897

3898
  bool    isVarType = false;
2,147,483,647✔
3899
  int32_t colLen = 0;
2,147,483,647✔
3900
  int32_t nextPos = 0;
2,147,483,647✔
3901
  int64_t checkRows = 0;
2,147,483,647✔
3902
  int64_t typeValue = 0;
2,147,483,647✔
3903
  int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
2,147,483,647✔
3904
  for (int32_t i = 0; i < colNum; ++i) {
2,147,483,647✔
3905
    SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pDataBlock->pDataBlock, i);
2,147,483,647✔
3906
    BLOCK_DATA_CHECK_TRESSA(pCol != NULL);
2,147,483,647✔
3907
    isVarType = IS_VAR_DATA_TYPE(pCol->info.type);
2,147,483,647✔
3908
    checkRows = pDataBlock->info.rows;
2,147,483,647✔
3909
    if (pCol->info.noData == true) continue;
2,147,483,647✔
3910

3911
    if (isVarType) {
2,147,483,647✔
3912
      BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.offset);
2,147,483,647✔
3913
    } else {
3914
      BLOCK_DATA_CHECK_TRESSA(pCol->nullbitmap);
2,147,483,647✔
3915
    }
3916

3917
    nextPos = -1;
2,147,483,647✔
3918
    for (int64_t r = 0; r < checkRows; ++r) {
2,147,483,647✔
3919
      if (tsSafetyCheckLevel <= TSDB_SAFETY_CHECK_LEVELL_NORMAL) break;
2,147,483,647✔
3920
      if (!colDataIsNull_s(pCol, r)) {
115,128,000✔
3921
        BLOCK_DATA_CHECK_TRESSA(pCol->pData);
57,564,000✔
3922
        BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.length <= pCol->varmeta.allocLen);
57,564,000✔
3923

3924
        if (isVarType) {
57,564,000✔
3925
          BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.allocLen > 0);
47,970,000✔
3926
          BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.offset[r] <= pCol->varmeta.length);
47,970,000✔
3927
          if (pCol->reassigned) {
47,970,000✔
3928
            BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.offset[r] >= 0);
×
3929
          } else if (0 == r || nextPos == -1) {
47,970,000✔
3930
            nextPos = pCol->varmeta.offset[r];
184,500✔
3931
          } else {
3932
            BLOCK_DATA_CHECK_TRESSA(pCol->varmeta.offset[r] == nextPos);
47,785,500✔
3933
          }
3934

3935
          char*   pColData = pCol->pData + pCol->varmeta.offset[r];
47,970,000✔
3936
          int32_t colSize = 0;
47,970,000✔
3937
          if (pCol->info.type == TSDB_DATA_TYPE_JSON) {
47,970,000✔
3938
            colLen = getJsonValueLen(pColData);
×
3939
          } else if (IS_STR_DATA_BLOB(pCol->info.type)) {
47,970,000✔
3940
            colLen = blobDataTLen(pColData);
×
3941
          } else {
3942
            colLen = varDataTLen(pColData);
47,970,000✔
3943
          }
3944

3945
          if (pCol->info.type == TSDB_DATA_TYPE_JSON) {
47,970,000✔
3946
            BLOCK_DATA_CHECK_TRESSA(colLen >= CHAR_BYTES);
×
3947
          } else if (IS_STR_DATA_BLOB(pCol->info.type)) {
47,970,000✔
3948
            // check or not
3949
          } else {
3950
            BLOCK_DATA_CHECK_TRESSA(colLen >= VARSTR_HEADER_SIZE);
47,970,000✔
3951
          }
3952
          if (pCol->reassigned) {
47,970,000✔
3953
            BLOCK_DATA_CHECK_TRESSA((pCol->varmeta.offset[r] + colLen) <= pCol->varmeta.length);
×
3954
          } else {
3955
            nextPos += colLen;
47,970,000✔
3956
            BLOCK_DATA_CHECK_TRESSA(nextPos <= pCol->varmeta.length);
47,970,000✔
3957
          }
3958
          typeValue = *(char*)(pCol->pData + pCol->varmeta.offset[r] + colLen - 1);
47,970,000✔
3959
        } else {
3960
          if (TSDB_DATA_TYPE_FLOAT == pCol->info.type) {
9,594,000✔
3961
            float v = 0;
×
3962
            GET_TYPED_DATA(v, float, pCol->info.type, colDataGetNumData(pCol, r),
×
3963
                           typeGetTypeModFromColInfo(&pCol->info));
3964
          } else if (TSDB_DATA_TYPE_DOUBLE == pCol->info.type) {
9,594,000✔
3965
            double v = 0;
×
3966
            GET_TYPED_DATA(v, double, pCol->info.type, colDataGetNumData(pCol, r),
×
3967
                           typeGetTypeModFromColInfo(&pCol->info));
3968
          } else if (IS_DECIMAL_TYPE(pCol->info.type)) {
9,594,000✔
3969
            // SKIP for decimal types
3970
          } else {
3971
            GET_TYPED_DATA(typeValue, int64_t, pCol->info.type, colDataGetNumData(pCol, r),
9,594,000✔
3972
                           typeGetTypeModFromColInfo(&pCol->info));
3973
          }
3974
        }
3975
      }
3976
    }
3977
  }
3978
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3979
}
3980

3981
int32_t getFirstNotSmallerThanTSRowNum(const char* pts, int32_t startRow, int32_t numOfRows, TSKEY ts) {
1,798,560✔
3982
  int32_t rowNum = -1;
1,798,560✔
3983
  if (numOfRows < 7) {
1,798,560✔
3984
    for (int32_t i = startRow; i < numOfRows; ++i) {
1,434,058✔
3985
      if (ts <= *(TSKEY*)(pts + i * sizeof(TSKEY))) {
1,434,058✔
3986
        rowNum = i;
1,423,876✔
3987
        break;
1,423,876✔
3988
      }
3989
    }
3990
    return rowNum;
1,423,876✔
3991
  }
3992

3993
  int32_t left = startRow;
374,479✔
3994
  int32_t right = numOfRows - 1;
374,479✔
3995
  rowNum = -1;
374,479✔
3996

3997
  while (left <= right) {
1,664,536✔
3998
    int32_t mid = left + (right - left) / 2;
1,290,057✔
3999
    TSKEY midValue = *(TSKEY*)(pts + mid * sizeof(TSKEY));
1,290,057✔
4000

4001
    if (midValue >= ts) {
1,290,057✔
4002
      rowNum = mid;
1,290,057✔
4003
      right = mid - 1;
1,290,057✔
4004
    } else {
4005
      left = mid + 1;
×
4006
    }
4007
  }
4008

4009
  return rowNum;
374,479✔
4010
}
4011

4012
int32_t getFirstBiggerThanTSRowNum(const char* pts, int32_t startRow, int32_t numOfRows, TSKEY ts) {
1,798,560✔
4013
  if (ts == INT64_MAX) return -1;
1,798,560✔
4014
  int32_t rowNum = -1;
29,216✔
4015
  if (numOfRows < 7) {
29,216✔
4016
    for (int32_t i = 0; i < numOfRows; ++i) {
128,869✔
4017
      if (ts < *(TSKEY*)(pts + i * sizeof(TSKEY))) {
99,653✔
4018
        rowNum = i;
×
4019
        break;
×
4020
      }
4021
    }
4022
    return rowNum;
29,216✔
4023
  }
4024
  int32_t left = startRow;
×
4025
  int32_t right = numOfRows - 1;
×
4026
  rowNum = -1;
×
4027
  while (left <= right) {
×
4028
    int32_t mid = left + (right - left) / 2;
×
4029
    TSKEY midValue = *(TSKEY*)(pts + mid * sizeof(TSKEY));
×
4030

4031
    if (midValue > ts) {
×
4032
      rowNum = mid;
×
4033
      right = mid - 1;
×
4034
    } else {
4035
      left = mid + 1;
×
4036
    }
4037
  }
4038
  return rowNum;
×
4039
}
4040

4041
int32_t getFirstNotBiggerThanTSRowNum(const char* pts, int32_t numOfRows, TSKEY ts) {
×
4042
  int32_t rowNum = -1;
×
4043
  for (int32_t i = numOfRows - 1; i >= 0; --i) {
×
4044
    if (ts >= *(TSKEY*)(pts + i * sizeof(TSKEY))) {
×
4045
      rowNum = i;
×
4046
      break;
×
4047
    }
4048
  }
4049
  return rowNum;
×
4050
}
4051

4052
static int32_t resetVarDataOffset(int32_t* pOffset, int32_t numOfRows) {
27,778✔
4053
  int32_t offset = 0;
27,778✔
4054
  for (int32_t i = 0; i < numOfRows; ++i) {
27,778✔
4055
    if (pOffset[i] < 0) {
27,778✔
4056
      continue;
×
4057
    } else {
4058
      offset = pOffset[i];
27,778✔
4059
      break;
27,778✔
4060
    }
4061
  }
4062
  if (offset > 0) {
27,778✔
4063
    for (int32_t i = 0; i < numOfRows; ++i) {
×
4064
      if (pOffset[i] < 0) {
×
4065
        continue;
×
4066
      }
4067
      pOffset[i] -= offset;
×
4068
    }
4069
  }
4070
  return offset;
27,778✔
4071
}
4072

4073
void colDataGetOffsetAndLen(const SColumnInfoData* pColumnInfoData, int32_t numOfRows, int32_t startIndex,  int32_t endIndex, int32_t* pOffset, int32_t* pLen) {
11,048,531✔
4074
  *pOffset = 0;
11,048,531✔
4075
  *pLen = 0;
11,048,325✔
4076
  if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
11,048,325✔
4077
    for (int32_t row = startIndex; row <= endIndex; ++row) {
27,778✔
4078
      if (pColumnInfoData->varmeta.offset[row] >= 0) {
27,778✔
4079
        *pOffset = pColumnInfoData->varmeta.offset[row];
27,778✔
4080
        break;
27,778✔
4081
      }
4082
    }
4083
    if (endIndex + 1 < numOfRows) {
27,778✔
4084
      for (int32_t row = endIndex + 1; row < numOfRows; ++row) {
×
4085
        if (pColumnInfoData->varmeta.offset[row] >= 0) {
×
4086
          *pLen = pColumnInfoData->varmeta.offset[row] - *pOffset;
×
4087
          return;
×
4088
        }
4089
      }
4090
    }
4091
    *pLen = pColumnInfoData->varmeta.length - *pOffset;
27,778✔
4092
  } else {
4093
    if (pColumnInfoData->info.type == TSDB_DATA_TYPE_NULL) {
11,020,753✔
4094
      return;
×
4095
    } else {
4096
      *pOffset = pColumnInfoData->info.bytes * startIndex;
11,020,753✔
4097
      *pLen = pColumnInfoData->info.bytes * (endIndex - startIndex + 1);
11,020,753✔
4098
    }
4099
  }
4100
}
4101

4102
size_t blockDataGetSizeOfRows(const SSDataBlock* pBlock, int32_t startIndex, int32_t endIndex) {
2,104,614✔
4103
  size_t total = 0;
2,104,614✔
4104
  size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
2,104,614✔
4105
  for (int32_t i = 0; i < numOfCols; ++i) {
7,628,777✔
4106
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
5,524,368✔
4107
    if (pColInfoData == NULL) {
5,523,720✔
4108
      continue;
×
4109
    }
4110

4111
    int32_t colSize = 0;
5,523,720✔
4112
    int32_t offset = 0;
5,523,926✔
4113
    int32_t numOfRows = endIndex - startIndex + 1;
5,523,926✔
4114

4115
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
5,523,926✔
4116
      total += sizeof(int32_t) * numOfRows;
13,889✔
4117
    } else {
4118
      if (pColInfoData->info.type != TSDB_DATA_TYPE_NULL) {
5,510,274✔
4119
        total += (pColInfoData->info.bytes * numOfRows) + BitmapLen(numOfRows);
5,510,068✔
4120
      }
4121
    }
4122

4123
    colDataGetOffsetAndLen(pColInfoData, pBlock->info.rows, startIndex, endIndex, &offset, &colSize);
5,524,369✔
4124
    total += colSize;
5,523,926✔
4125
  }
4126

4127
  return total;
2,104,409✔
4128
}
4129

4130
int32_t blockGetEncodeSizeOfRows(const SSDataBlock* pBlock, int32_t startIndex, int32_t endIndex){
2,104,614✔
4131
  return blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSizeOfRows(pBlock, startIndex, endIndex);
2,104,614✔
4132
}
4133

4134
// return error code if failed
4135
// pLen: return length of encoded data
4136
int32_t blockEncodeAsRows(const SSDataBlock* pBlock, char* data, size_t dataBuflen, int32_t numOfCols, int32_t startIndex, 
2,104,614✔
4137
                          int32_t endIndex, int32_t* pLen) {
4138
  *pLen = 0;
2,104,614✔
4139
  int32_t code = blockDataCheck(pBlock);
2,104,614✔
4140
  if (code != TSDB_CODE_SUCCESS) {
2,104,614✔
4141
    return code;
×
4142
  }
4143

4144
  int32_t dataLen = 0;
2,104,614✔
4145

4146
  // todo extract method
4147
  int32_t* version = (int32_t*)data;
2,104,614✔
4148
  *version = BLOCK_VERSION_1;
2,104,614✔
4149
  data += sizeof(int32_t);
2,104,614✔
4150

4151
  int32_t* actualLen = (int32_t*)data;
2,104,614✔
4152
  data += sizeof(int32_t);
2,104,614✔
4153

4154
  int32_t* rows = (int32_t*)data;
2,104,614✔
4155
  *rows = pBlock->info.rows;
2,104,614✔
4156
  data += sizeof(int32_t);
2,104,614✔
4157
  if (*rows <= 0) {
2,104,614✔
4158
    uError("Invalid rows %d in block", *rows);
×
4159
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4160
  }
4161
  if(*rows <= endIndex) {
2,104,614✔
4162
    uError("Invalid endIdex %d, there is %d rows in block", endIndex, *rows);
×
4163
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4164
  }
4165
  int32_t realRows = endIndex - startIndex + 1;
2,104,614✔
4166
  *rows = realRows;
2,104,614✔
4167

4168
  int32_t* cols = (int32_t*)data;
2,104,614✔
4169
  *cols = numOfCols;
2,104,614✔
4170
  data += sizeof(int32_t);
2,104,614✔
4171

4172
  // flag segment.
4173
  // the inital bit is for column info
4174
  int32_t* flagSegment = (int32_t*)data;
2,104,614✔
4175
  *flagSegment = (1 << 31);
2,104,614✔
4176

4177
  data += sizeof(int32_t);
2,104,614✔
4178

4179
  uint64_t* groupId = (uint64_t*)data;
2,104,614✔
4180
  data += sizeof(uint64_t);
2,104,614✔
4181

4182
  for (int32_t i = 0; i < numOfCols; ++i) {
7,628,745✔
4183
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
5,524,131✔
4184
    if (pColInfoData == NULL) {
5,524,131✔
4185
      return terrno;
×
4186
    }
4187

4188
    *((int8_t*)data) = pColInfoData->info.type;
5,524,131✔
4189
    data += sizeof(int8_t);
5,524,131✔
4190

4191
    int32_t bytes = pColInfoData->info.bytes;
5,524,368✔
4192
    *((int32_t*)data) = bytes;
5,524,131✔
4193
    if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
5,524,131✔
4194
      fillBytesForDecimalType((int32_t*)data, pColInfoData->info.type, pColInfoData->info.precision,
×
4195
                              pColInfoData->info.scale);
×
4196
    }
4197
    data += sizeof(int32_t);
5,524,131✔
4198
  }
4199

4200
  int32_t* colSizes = (int32_t*)data;
2,104,614✔
4201
  data += numOfCols * sizeof(int32_t);
2,104,614✔
4202

4203
  dataLen = blockDataGetSerialMetaSize(numOfCols);
2,104,614✔
4204

4205
  int32_t numOfRows = pBlock->info.rows;
2,104,614✔
4206
  for (int32_t col = 0; col < numOfCols; ++col) {
7,628,982✔
4207
    SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, col);
5,524,368✔
4208
    if (pColRes == NULL) {
5,524,368✔
4209
      return terrno;
×
4210
    }
4211

4212
    // copy the null bitmap
4213
    size_t metaSize = 0;
5,524,368✔
4214
    if (IS_VAR_DATA_TYPE(pColRes->info.type)) {
5,524,368✔
4215
      metaSize = realRows * sizeof(int32_t);
13,889✔
4216
      if(dataLen + metaSize > dataBuflen) goto _exit;
13,889✔
4217
      TAOS_UNUSED(memcpy(data, (char*)pColRes->varmeta.offset + (startIndex * sizeof(int32_t)), metaSize));
13,889✔
4218
      TAOS_UNUSED(resetVarDataOffset((int32_t*)data, realRows));
13,889✔
4219
    } else {
4220
      metaSize = BitmapLen(realRows);
5,510,479✔
4221
      if(dataLen + metaSize > dataBuflen) goto _exit;
5,510,479✔
4222
      for (int32_t j = 0; j < realRows; ++j) {
26,917,516✔
4223
        if (colDataIsNull_f(pColRes, j + startIndex)) {
21,407,274✔
4224
          colDataSetNull_f(data, j);
892,695✔
4225
        }
4226
      }
4227
    }
4228

4229
    data += metaSize;
5,524,131✔
4230
    dataLen += metaSize;
5,524,368✔
4231

4232
    int32_t skipOffset;
5,523,344✔
4233
    colDataGetOffsetAndLen(pColRes, numOfRows, startIndex, endIndex, &skipOffset, &colSizes[col]);
5,524,368✔
4234
    dataLen += colSizes[col];
5,524,368✔
4235
    if (dataLen > dataBuflen) goto _exit;
5,524,368✔
4236
    if (pColRes->pData != NULL) {
5,524,368✔
4237
      (void)memmove(data, pColRes->pData + skipOffset, colSizes[col]);
5,524,368✔
4238
    }
4239
    data += colSizes[col];
5,524,368✔
4240

4241
    if (colSizes[col] <= 0 && !colDataIsNull_s(pColRes, 0) && pColRes->info.type != TSDB_DATA_TYPE_NULL) {
5,524,368✔
4242
      uError("Invalid colSize:%d colIdx:%d colType:%d while encoding block", colSizes[col], col, pColRes->info.type);
×
4243
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4244
    }
4245
    
4246
    colSizes[col] = htonl(colSizes[col]);
5,524,368✔
4247
    //    uError("blockEncode col bytes:%d, type:%d, size:%d, htonl size:%d", pColRes->info.bytes, pColRes->info.type,
4248
    //    htonl(colSizes[col]), colSizes[col]);
4249
  }
4250

4251
  bool* blankFill = (bool*)data;
2,104,614✔
4252
  *blankFill = pBlock->info.blankFill;
2,104,614✔
4253
  data += sizeof(bool);
2,104,614✔
4254

4255
  *actualLen = dataLen;
2,104,614✔
4256
#ifndef NO_UNALIGNED_ACCESS
4257
  *groupId = pBlock->info.id.groupId;
2,104,614✔
4258
#else
4259
  taosSetPUInt64Aligned(groupId, &pBlock->info.id.groupId);
4260
#endif
4261
  if (dataLen > dataBuflen) goto _exit;
2,104,614✔
4262

4263
  *pLen = dataLen;
2,104,614✔
4264
  return TSDB_CODE_SUCCESS;
2,104,614✔
4265
_exit:
×
4266
  uError("blockEncode dataLen:%d, dataBuflen:%zu", dataLen, dataBuflen);
×
4267
  return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4268
}
4269

4270
int32_t getTsColDataOffset(SSDataBlock* pBlock, int32_t* colLen, int32_t numOfRows, int32_t tsColSlotId, int32_t* pOffset) {
1,798,560✔
4271
  *pOffset = 0;
1,798,560✔
4272
  for (int32_t i = 0; i <= tsColSlotId; ++i) {
3,747,673✔
4273
    int oneColsLen = htonl(colLen[i]);
1,949,113✔
4274
    if (oneColsLen < 0) {
1,949,113✔
4275
      uError("block decode colLen:%d error, colIdx:%d", oneColsLen, i);
×
4276
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4277
      return terrno;
×
4278
    }
4279

4280
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
1,949,113✔
4281
    if (pColInfoData == NULL) {
1,948,908✔
4282
      return terrno;
×
4283
    }
4284

4285
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
1,948,908✔
4286
      *pOffset += sizeof(int32_t) * numOfRows;
410✔
4287
    } else {
4288
      *pOffset += BitmapLen(numOfRows);
1,948,908✔
4289
    }
4290
    if (i != tsColSlotId) {
1,948,908✔
4291
      *pOffset += oneColsLen;
150,553✔
4292
    }
4293
  }
4294
  return TSDB_CODE_SUCCESS;
1,798,560✔
4295
}
4296

4297
int32_t blockSpecialDecodeLaterPart(SSDataBlock* pBlock, const char* pData, int32_t tsColSlotId, TSKEY start, TSKEY end) {
1,798,560✔
4298
  int32_t code = TSDB_CODE_SUCCESS;
1,798,560✔
4299

4300
  const char* pStart = pData;
1,798,560✔
4301

4302
  int32_t version = *(int32_t*)pStart;
1,798,560✔
4303
  pStart += sizeof(int32_t);
1,798,560✔
4304

4305
  // total length sizeof(int32_t)
4306
  int32_t dataLen = *(int32_t*)pStart;
1,798,560✔
4307
  pStart += sizeof(int32_t);
1,798,560✔
4308

4309
  // total rows sizeof(int32_t)
4310
  int32_t numOfRows = *(int32_t*)pStart;
1,798,560✔
4311
  pStart += sizeof(int32_t);
1,798,560✔
4312
  if (numOfRows <= 0) {
1,798,355✔
4313
    uError("block decode numOfRows:%d error", numOfRows);
×
4314
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4315
    return terrno;
×
4316
  }
4317

4318
  // total columns sizeof(int32_t)
4319
  int32_t numOfCols = *(int32_t*)pStart;
1,798,355✔
4320
  pStart += sizeof(int32_t);
1,798,560✔
4321

4322
  // has column info segment
4323
  int32_t flagSeg = *(int32_t*)pStart;
1,798,560✔
4324
  int32_t hasColumnInfo = (flagSeg >> 31);
1,798,355✔
4325
  pStart += sizeof(int32_t);
1,798,355✔
4326

4327
  // group id sizeof(uint64_t)
4328
#ifndef NO_UNALIGNED_ACCESS
4329
  pBlock->info.id.groupId = *(uint64_t*)pStart;
1,798,560✔
4330
#else
4331
  taosSetPUInt64Aligned(&pBlock->info.id.groupId, (uint64_t*)pStart);
4332
#endif
4333
  pStart += sizeof(uint64_t);
1,798,560✔
4334

4335
  if (pBlock->pDataBlock == NULL) {
1,798,355✔
4336
    pBlock->pDataBlock = taosArrayInit_s(sizeof(SColumnInfoData), numOfCols);
1,798,560✔
4337
    if (pBlock->pDataBlock == NULL) {
1,798,560✔
4338
      return terrno;
×
4339
    }
4340
  }
4341

4342
  for (int32_t i = 0; i < numOfCols; ++i) {
6,401,607✔
4343
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
4,603,047✔
4344
    if (pColInfoData == NULL) {
4,602,842✔
4345
      return terrno;
×
4346
    }
4347

4348
    pColInfoData->info.type = *(int8_t*)pStart;
4,602,842✔
4349
    pStart += sizeof(int8_t);
4,602,842✔
4350

4351
    pColInfoData->info.bytes = *(int32_t*)pStart;
4,602,842✔
4352
    if (IS_DECIMAL_TYPE(pColInfoData->info.type)) {
4,603,047✔
4353
      extractDecimalTypeInfoFromBytes(&pColInfoData->info.bytes, &pColInfoData->info.precision,
×
4354
                                      &pColInfoData->info.scale);
4355
    }
4356
    pStart += sizeof(int32_t);
4,603,047✔
4357

4358
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
4,603,047✔
4359
      pBlock->info.hasVarCol = true;
13,889✔
4360
    }
4361
  }
4362

4363
  int32_t* colLen = (int32_t*)pStart;
1,798,560✔
4364
  pStart += sizeof(int32_t) * numOfCols;
1,798,560✔
4365

4366
  int32_t tsLen = htonl(colLen[tsColSlotId]);
1,798,560✔
4367
  int32_t tsColOffset;
1,798,048✔
4368
  code = getTsColDataOffset(pBlock, colLen, numOfRows, tsColSlotId, &tsColOffset);
1,798,560✔
4369
  if (code) {
1,798,560✔
4370
    return code;
×
4371
  }
4372
  const char* pts = pStart + tsColOffset;
1,798,560✔
4373
  int32_t     firstRowNum = getFirstNotSmallerThanTSRowNum(pts, 0, numOfRows, start);
1,798,355✔
4374
  if (firstRowNum < 0) {
1,798,560✔
4375
    pBlock->info.rows = 0;
×
4376
    return TSDB_CODE_SUCCESS;
×
4377
  }
4378
  int32_t lastRowNumNext = getFirstBiggerThanTSRowNum(pts, firstRowNum, numOfRows, end);
1,798,560✔
4379
  if (lastRowNumNext < 0) {
1,798,560✔
4380
    lastRowNumNext = numOfRows;
1,798,560✔
4381
  } else if (lastRowNumNext == 0) {
×
4382
    pBlock->info.rows = 0;
×
4383
    return TSDB_CODE_SUCCESS;
×
4384
  }
4385

4386
  int32_t realRows = lastRowNumNext - firstRowNum;
1,798,560✔
4387
  int32_t leftRows = numOfRows - lastRowNumNext;
1,798,560✔
4388

4389
  code = blockDataEnsureCapacity(pBlock, realRows);
1,798,560✔
4390
  if (code) {
1,798,560✔
4391
    return code;
×
4392
  }
4393

4394
  for (int32_t i = 0; i < numOfCols; ++i) {
6,401,607✔
4395
    int32_t oneColsLen = htonl(colLen[i]);
4,603,047✔
4396
    int32_t offset = 0;
4,603,047✔
4397
    int32_t leftlen = 0;
4,603,047✔
4398
    if (oneColsLen < 0) {
4,603,047✔
4399
      uError("block decode colLen:%d error, colIdx:%d", oneColsLen, i);
×
4400
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4401
      return terrno;
×
4402
    }
4403

4404
    SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
4,603,047✔
4405
    if (pColInfoData == NULL) {
4,603,047✔
4406
      return terrno;
×
4407
    }
4408

4409
    if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
4,603,047✔
4410
      pStart += sizeof(int32_t) * firstRowNum;
13,683✔
4411
      memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * realRows);
13,889✔
4412
      pStart += sizeof(int32_t) * realRows;
13,889✔
4413

4414
      offset = resetVarDataOffset(pColInfoData->varmeta.offset, realRows);
13,889✔
4415
      if (leftRows > 0) {
13,889✔
4416
        for (int32_t j = 0; j < leftRows; ++j) {
×
4417
          if (*((int32_t*)pStart + j) != -1) {
×
4418
            leftlen = oneColsLen - *((int32_t*)pStart + j);
×
4419
          }
4420
        }
4421
      }
4422
      oneColsLen -= (offset + leftlen);
13,889✔
4423
      pStart += sizeof(int32_t) * leftRows;
13,889✔
4424

4425
      if (oneColsLen > 0 && pColInfoData->varmeta.allocLen < oneColsLen) {
13,889✔
4426
        char* tmp = taosMemoryRealloc(pColInfoData->pData, oneColsLen);
13,889✔
4427
        if (tmp == NULL) {
13,889✔
4428
          return terrno;
×
4429
        }
4430

4431
        pColInfoData->pData = tmp;
13,889✔
4432
        pColInfoData->varmeta.allocLen = oneColsLen;
13,889✔
4433
      }
4434

4435
      pColInfoData->varmeta.length = oneColsLen;
13,889✔
4436
    } else {
4437
      offset = oneColsLen / numOfRows * firstRowNum;
4,589,158✔
4438
      if (leftRows > 0) {
4,589,158✔
4439
        leftlen = oneColsLen / numOfRows * leftRows;
×
4440
      }
4441
      oneColsLen -= (offset + leftlen);
4,589,158✔
4442

4443
      memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(realRows));
4,589,158✔
4444
      for (int32_t j = 0; j < realRows; ++j) {
25,163,690✔
4445
        if (BMIsNull(pStart, j + firstRowNum)) {
20,574,737✔
4446
          colDataSetNull_f(pColInfoData->nullbitmap, j);
892,695✔
4447
        }
4448
      }
4449
      pStart += BitmapLen(numOfRows);
4,588,953✔
4450
    }
4451

4452
    pColInfoData->hasNull = true;
4,602,842✔
4453

4454
    if (oneColsLen > 0) {
4,602,842✔
4455
      pStart += offset;
4,602,842✔
4456
      memcpy(pColInfoData->pData, pStart, oneColsLen);
4,602,842✔
4457
    } else if (!colDataIsNull_s(pColInfoData, 0) && pColInfoData->info.type != TSDB_DATA_TYPE_NULL) {
×
4458
      uError("block decode colLen:%d error, colIdx:%d, type:%d", oneColsLen, i, pColInfoData->info.type);
×
4459
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4460
      return terrno;
×
4461
    }
4462

4463
    pStart += oneColsLen;
4,603,047✔
4464
    pStart += leftlen;
4,602,842✔
4465
  }
4466

4467
  bool blankFill = *(bool*)pStart;
1,798,560✔
4468
  pStart += sizeof(bool);
1,798,560✔
4469

4470
  pBlock->info.dataLoad = 1;
1,798,560✔
4471
  pBlock->info.rows = realRows;
1,798,560✔
4472
  pBlock->info.blankFill = blankFill;
1,798,560✔
4473
  if (pStart - pData != dataLen) {
1,798,560✔
4474
    uError("block decode msg len error, pStart:%p, pData:%p, dataLen:%d", pStart, pData, dataLen);
×
4475
    terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4476
    return terrno;
×
4477
  }
4478

4479
  code = blockDataCheck(pBlock);
1,798,560✔
4480
  if (code != TSDB_CODE_SUCCESS) {
1,797,829✔
4481
    terrno = code;
×
4482
    return code;
×
4483
  }
4484

4485
  return TSDB_CODE_SUCCESS;
1,797,829✔
4486
}
4487

4488
int32_t getStreamBlockTS(SSDataBlock* pBlock, int32_t tsColSlotId, int32_t row, TSKEY* ts) {
22,874✔
4489
  if (pBlock == NULL || ts == NULL) {
22,874✔
4490
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4491
  }
4492

4493
  if (pBlock->info.rows <= 0) {
22,874✔
4494
    return TSDB_CODE_SUCCESS;
×
4495
  }
4496
  int32_t cols = taosArrayGetSize(pBlock->pDataBlock);
22,874✔
4497
  if (tsColSlotId < 0 || tsColSlotId >= cols) {
22,874✔
4498
    uError("Invalid tsColSlotId %d, block has %d columns", tsColSlotId, cols);
×
4499
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4500
  }
4501

4502
  SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, tsColSlotId);
22,874✔
4503
  if (pColInfoData == NULL) {
22,874✔
4504
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4505
  }
4506

4507
  *ts = *(TSKEY*)(pColInfoData->pData + row * sizeof(TSKEY));
22,874✔
4508
  return TSDB_CODE_SUCCESS;
22,874✔
4509
}
4510

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