tdataformat.c 30.9 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
S
common  
Shengliang Guan 已提交
15 16

#define _DEFAULT_SOURCE
S
slguan 已提交
17
#include "tdataformat.h"
S
Shengliang Guan 已提交
18
#include "tcoding.h"
L
Liu Jicong 已提交
19
#include "tdatablock.h"
S
log  
Shengliang Guan 已提交
20
#include "tlog.h"
H
more  
hzcheng 已提交
21

C
Cary Xu 已提交
22 23
static int32_t tGetTagVal(uint8_t *p, STagVal *pTagVal, int8_t isJson);

H
Hongze Cheng 已提交
24
typedef struct SKVIdx {
H
Hongze Cheng 已提交
25 26
  int32_t cid;
  int32_t offset;
H
Hongze Cheng 已提交
27
} SKVIdx;
H
Hongze Cheng 已提交
28

H
Hongze Cheng 已提交
29 30 31 32 33 34 35
#pragma pack(push, 1)
typedef struct {
  int16_t nCols;
  SKVIdx  idx[];
} STSKVRow;
#pragma pack(pop)

H
Hongze Cheng 已提交
36
#define TSROW_IS_KV_ROW(r) ((r)->flags & TSROW_KV_ROW)
H
Hongze Cheng 已提交
37 38
#define BIT1_SIZE(n)       (((n)-1) / 8 + 1)
#define BIT2_SIZE(n)       (((n)-1) / 4 + 1)
H
Hongze Cheng 已提交
39 40
#define SET_BIT1(p, i, v)  ((p)[(i) / 8] = (p)[(i) / 8] & (~(((uint8_t)1) << ((i) % 8))) | ((v) << ((i) % 8)))
#define SET_BIT2(p, i, v)  ((p)[(i) / 4] = (p)[(i) / 4] & (~(((uint8_t)3) << ((i) % 4))) | ((v) << ((i) % 4)))
H
Hongze Cheng 已提交
41 42
#define GET_BIT1(p, i)     (((p)[(i) / 8] >> ((i) % 8)) & ((uint8_t)1))
#define GET_BIT2(p, i)     (((p)[(i) / 4] >> ((i) % 4)) & ((uint8_t)3))
H
Hongze Cheng 已提交
43

H
Hongze Cheng 已提交
44 45
static FORCE_INLINE int tSKVIdxCmprFn(const void *p1, const void *p2);

H
Hongze Cheng 已提交
46
// STSRow2
H
Hongze Cheng 已提交
47 48
int32_t tPutTSRow(uint8_t *p, STSRow2 *pRow) {
  int32_t n = 0;
H
Hongze Cheng 已提交
49

H
Hongze Cheng 已提交
50 51 52 53 54
  n += tPutI64(p ? p + n : p, pRow->ts);
  n += tPutI8(p ? p + n : p, pRow->flags);
  n += tPutI32v(p ? p + n : p, pRow->sver);

  ASSERT(pRow->flags & 0xf);
H
Hongze Cheng 已提交
55 56 57 58

  switch (pRow->flags & 0xf) {
    case TSROW_HAS_NONE:
    case TSROW_HAS_NULL:
H
Hongze Cheng 已提交
59
      break;
H
Hongze Cheng 已提交
60
    default:
H
Hongze Cheng 已提交
61
      n += tPutBinary(p ? p + n : p, pRow->pData, pRow->nData);
H
Hongze Cheng 已提交
62
      break;
H
Hongze Cheng 已提交
63
  }
H
Hongze Cheng 已提交
64

H
Hongze Cheng 已提交
65
  return n;
H
Hongze Cheng 已提交
66 67
}

H
Hongze Cheng 已提交
68 69 70
int32_t tGetTSRow(uint8_t *p, STSRow2 *pRow) {
  int32_t n = 0;
  uint8_t flags;
H
Hongze Cheng 已提交
71

H
Hongze Cheng 已提交
72 73 74
  n += tGetI64(p + n, pRow ? &pRow->ts : NULL);
  n += tGetI8(p + n, pRow ? &pRow->flags : &flags);
  n += tGetI32v(p + n, pRow ? &pRow->sver : NULL);
H
Hongze Cheng 已提交
75

H
Hongze Cheng 已提交
76 77
  if (pRow) flags = pRow->flags;
  switch (flags & 0xf) {
H
Hongze Cheng 已提交
78 79
    case TSROW_HAS_NONE:
    case TSROW_HAS_NULL:
H
Hongze Cheng 已提交
80
      break;
H
Hongze Cheng 已提交
81
    default:
H
Hongze Cheng 已提交
82
      n += tGetBinary(p + n, pRow ? &pRow->pData : NULL, pRow ? &pRow->nData : NULL);
H
Hongze Cheng 已提交
83
      break;
H
Hongze Cheng 已提交
84
  }
H
Hongze Cheng 已提交
85

H
Hongze Cheng 已提交
86
  return n;
H
Hongze Cheng 已提交
87 88
}

H
Hongze Cheng 已提交
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
int32_t tTSRowDup(const STSRow2 *pRow, STSRow2 **ppRow) {
  (*ppRow) = taosMemoryMalloc(sizeof(*pRow) + pRow->nData);
  if (*ppRow == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }

  (*ppRow)->ts = pRow->ts;
  (*ppRow)->flags = pRow->flags;
  (*ppRow)->sver = pRow->sver;
  (*ppRow)->nData = pRow->nData;
  if (pRow->nData) {
    (*ppRow)->pData = (uint8_t *)(&(*ppRow)[1]);
    memcpy((*ppRow)->pData, pRow->pData, pRow->nData);
  } else {
    (*ppRow)->pData = NULL;
  }

  return 0;
}

void tTSRowFree(STSRow2 *pRow) {
  if (pRow) taosMemoryFree(pRow);
}

H
Hongze Cheng 已提交
114
int32_t tTSRowGet(const STSRow2 *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal) {
H
Hongze Cheng 已提交
115 116 117 118 119 120 121
  uint32_t  n;
  uint8_t  *p;
  uint8_t   v;
  int32_t   bidx = iCol - 1;
  STColumn *pTColumn = &pTSchema->columns[iCol];
  STSKVRow *pTSKVRow;
  SKVIdx   *pKVIdx;
H
Hongze Cheng 已提交
122

H
Hongze Cheng 已提交
123
  ASSERT(iCol != 0);
H
Hongze Cheng 已提交
124 125 126 127 128
  ASSERT(pTColumn->colId != 0);

  ASSERT(pRow->flags & 0xf != 0);
  switch (pRow->flags & 0xf) {
    case TSROW_HAS_NONE:
H
Hongze Cheng 已提交
129
      *pColVal = ColValNONE;
H
Hongze Cheng 已提交
130 131
      return 0;
    case TSROW_HAS_NULL:
H
Hongze Cheng 已提交
132
      *pColVal = ColValNULL;
H
Hongze Cheng 已提交
133 134 135 136 137 138 139
      return 0;
  }

  if (TSROW_IS_KV_ROW(pRow)) {
    ASSERT((pRow->flags & 0xf) != TSROW_HAS_VAL);

    pTSKVRow = (STSKVRow *)pRow->pData;
H
Hongze Cheng 已提交
140 141
    pKVIdx =
        bsearch(&((SKVIdx){.cid = pTColumn->colId}), pTSKVRow->idx, pTSKVRow->nCols, sizeof(SKVIdx), tSKVIdxCmprFn);
H
Hongze Cheng 已提交
142
    if (pKVIdx == NULL) {
H
Hongze Cheng 已提交
143
      *pColVal = ColValNONE;
H
Hongze Cheng 已提交
144
    } else if (pKVIdx->offset < 0) {
H
Hongze Cheng 已提交
145
      *pColVal = ColValNULL;
H
Hongze Cheng 已提交
146 147
    } else {
      p = pRow->pData + sizeof(STSKVRow) + sizeof(SKVIdx) * pTSKVRow->nCols + pKVIdx->offset;
H
Hongze Cheng 已提交
148 149
      pColVal->type = COL_VAL_DATA;
      tGetBinary(p, &pColVal->pData, &pColVal->nData);
H
Hongze Cheng 已提交
150 151 152
    }
  } else {
    // get bitmap
H
Hongze Cheng 已提交
153
    p = pRow->pData;
H
Hongze Cheng 已提交
154
    switch (pRow->flags & 0xf) {
H
Hongze Cheng 已提交
155
      case TSROW_HAS_NULL | TSROW_HAS_NONE:
H
Hongze Cheng 已提交
156 157
        v = GET_BIT1(p, bidx);
        if (v == 0) {
H
Hongze Cheng 已提交
158
          *pColVal = ColValNONE;
H
Hongze Cheng 已提交
159
        } else {
H
Hongze Cheng 已提交
160
          *pColVal = ColValNULL;
H
Hongze Cheng 已提交
161
        }
H
Hongze Cheng 已提交
162
        return 0;
H
Hongze Cheng 已提交
163
      case TSROW_HAS_VAL | TSROW_HAS_NONE:
H
Hongze Cheng 已提交
164 165
        v = GET_BIT1(p, bidx);
        if (v == 1) {
H
Hongze Cheng 已提交
166
          p = p + BIT1_SIZE(pTSchema->numOfCols - 1);
H
Hongze Cheng 已提交
167 168
          break;
        } else {
H
Hongze Cheng 已提交
169
          *pColVal = ColValNONE;
H
Hongze Cheng 已提交
170 171
          return 0;
        }
H
Hongze Cheng 已提交
172
      case TSROW_HAS_VAL | TSROW_HAS_NULL:
H
Hongze Cheng 已提交
173 174
        v = GET_BIT1(p, bidx);
        if (v == 1) {
H
Hongze Cheng 已提交
175
          p = p + BIT1_SIZE(pTSchema->numOfCols - 1);
H
Hongze Cheng 已提交
176
          break;
H
Hongze Cheng 已提交
177
        } else {
H
Hongze Cheng 已提交
178
          *pColVal = ColValNULL;
H
Hongze Cheng 已提交
179
          return 0;
H
Hongze Cheng 已提交
180
        }
H
Hongze Cheng 已提交
181
      case TSROW_HAS_VAL | TSROW_HAS_NULL | TSROW_HAS_NONE:
H
Hongze Cheng 已提交
182 183
        v = GET_BIT2(p, bidx);
        if (v == 0) {
H
Hongze Cheng 已提交
184
          *pColVal = ColValNONE;
H
Hongze Cheng 已提交
185 186
          return 0;
        } else if (v == 1) {
H
Hongze Cheng 已提交
187
          *pColVal = ColValNULL;
H
Hongze Cheng 已提交
188 189
          return 0;
        } else if (v == 2) {
H
Hongze Cheng 已提交
190
          p = p + BIT2_SIZE(pTSchema->numOfCols - 1);
H
Hongze Cheng 已提交
191 192 193 194
          break;
        } else {
          ASSERT(0);
        }
H
Hongze Cheng 已提交
195
      default:
H
Hongze Cheng 已提交
196
        break;
H
Hongze Cheng 已提交
197
    }
H
Hongze Cheng 已提交
198 199 200

    // get real value
    p = p + pTColumn->offset;
H
Hongze Cheng 已提交
201
    pColVal->type = COL_VAL_DATA;
H
Hongze Cheng 已提交
202
    if (IS_VAR_DATA_TYPE(pTColumn->type)) {
H
Hongze Cheng 已提交
203
      tGetBinary(p + pTSchema->flen + *(int32_t *)p, &pColVal->pData, &pColVal->nData);
H
Hongze Cheng 已提交
204
    } else {
H
Hongze Cheng 已提交
205 206
      pColVal->pData = p;
      pColVal->nData = pTColumn->bytes;
H
Hongze Cheng 已提交
207
    }
H
Hongze Cheng 已提交
208
  }
H
Hongze Cheng 已提交
209

H
Hongze Cheng 已提交
210 211 212 213
  return 0;
}

// STSchema
H
Hongze Cheng 已提交
214 215 216 217 218 219 220
int32_t tTSchemaCreate(int32_t sver, SSchema *pSchema, int32_t ncols, STSchema **ppTSchema) {
  *ppTSchema = (STSchema *)taosMemoryMalloc(sizeof(STSchema) + sizeof(STColumn) * ncols);
  if (*ppTSchema == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }

H
Hongze Cheng 已提交
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
  (*ppTSchema)->numOfCols = ncols;
  (*ppTSchema)->version = sver;
  (*ppTSchema)->flen = 0;
  (*ppTSchema)->vlen = 0;
  (*ppTSchema)->tlen = 0;

  for (int32_t iCol = 0; iCol < ncols; iCol++) {
    SSchema  *pColumn = &pSchema[iCol];
    STColumn *pTColumn = &((*ppTSchema)->columns[iCol]);

    pTColumn->colId = pColumn->colId;
    pTColumn->type = pColumn->type;
    pTColumn->flags = pColumn->flags;
    pTColumn->bytes = pColumn->bytes;
    pTColumn->offset = (*ppTSchema)->flen;

    // skip first column
    if (iCol) {
      (*ppTSchema)->flen += TYPE_BYTES[pColumn->type];
      if (IS_VAR_DATA_TYPE(pColumn->type)) {
        (*ppTSchema)->vlen += (pColumn->bytes + 5);
      }
    }
  }

H
Hongze Cheng 已提交
246 247 248
  return 0;
}

H
Hongze Cheng 已提交
249 250 251
void tTSchemaDestroy(STSchema *pTSchema) {
  if (pTSchema) taosMemoryFree(pTSchema);
}
H
Hongze Cheng 已提交
252

H
Hongze Cheng 已提交
253
// STSRowBuilder
H
Hongze Cheng 已提交
254
int32_t tTSRowBuilderInit(STSRowBuilder *pBuilder, int32_t sver, int32_t nCols, SSchema *pSchema) {
H
Hongze Cheng 已提交
255 256
  if (tTSchemaCreate(sver, pSchema, nCols, &pBuilder->pTSchema) < 0) return -1;

H
Hongze Cheng 已提交
257 258
  pBuilder->szBitMap1 = BIT1_SIZE(nCols - 1);
  pBuilder->szBitMap2 = BIT2_SIZE(nCols - 1);
H
Hongze Cheng 已提交
259 260
  pBuilder->szKVBuf =
      sizeof(STSKVRow) + sizeof(SKVIdx) * (nCols - 1) + pBuilder->pTSchema->flen + pBuilder->pTSchema->vlen;
H
Hongze Cheng 已提交
261 262 263
  pBuilder->szTPBuf = pBuilder->szBitMap2 + pBuilder->pTSchema->flen + pBuilder->pTSchema->vlen;
  pBuilder->pKVBuf = taosMemoryMalloc(pBuilder->szKVBuf);
  if (pBuilder->pKVBuf == NULL) {
H
Hongze Cheng 已提交
264 265
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    tTSchemaDestroy(pBuilder->pTSchema);
H
Hongze Cheng 已提交
266
    return -1;
H
Hongze Cheng 已提交
267
  }
H
Hongze Cheng 已提交
268 269 270
  pBuilder->pTPBuf = taosMemoryMalloc(pBuilder->szTPBuf);
  if (pBuilder->pTPBuf == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
H
Hongze Cheng 已提交
271 272
    taosMemoryFree(pBuilder->pKVBuf);
    tTSchemaDestroy(pBuilder->pTSchema);
H
Hongze Cheng 已提交
273
    return -1;
H
Hongze Cheng 已提交
274 275
  }

H
Hongze Cheng 已提交
276 277 278
  return 0;
}

H
Hongze Cheng 已提交
279
void tTSRowBuilderClear(STSRowBuilder *pBuilder) {
H
Hongze Cheng 已提交
280 281 282 283
  if (pBuilder->pTPBuf) {
    taosMemoryFree(pBuilder->pTPBuf);
    pBuilder->pTPBuf = NULL;
  }
H
Hongze Cheng 已提交
284 285 286 287 288 289
  if (pBuilder->pKVBuf) {
    taosMemoryFree(pBuilder->pKVBuf);
    pBuilder->pKVBuf = NULL;
  }
  tTSchemaDestroy(pBuilder->pTSchema);
  pBuilder->pTSchema = NULL;
H
Hongze Cheng 已提交
290 291
}

H
Hongze Cheng 已提交
292
void tTSRowBuilderReset(STSRowBuilder *pBuilder) {
H
Hongze Cheng 已提交
293
  for (int32_t iCol = pBuilder->pTSchema->numOfCols - 1; iCol >= 0; iCol--) {
H
Hongze Cheng 已提交
294 295
    STColumn *pTColumn = &pBuilder->pTSchema->columns[iCol];
    COL_CLR_SET(pTColumn->flags);
H
Hongze Cheng 已提交
296 297
  }

H
Hongze Cheng 已提交
298
  pBuilder->iCol = 0;
H
Hongze Cheng 已提交
299
  ((STSKVRow *)pBuilder->pKVBuf)->nCols = 0;
H
Hongze Cheng 已提交
300 301
  pBuilder->vlenKV = 0;
  pBuilder->vlenTP = 0;
H
Hongze Cheng 已提交
302
  pBuilder->row.flags = 0;
H
Hongze Cheng 已提交
303 304
}

H
Hongze Cheng 已提交
305
int32_t tTSRowBuilderPut(STSRowBuilder *pBuilder, int32_t cid, uint8_t *pData, uint32_t nData) {
H
Hongze Cheng 已提交
306 307 308
  STColumn *pTColumn = &pBuilder->pTSchema->columns[pBuilder->iCol];
  uint8_t  *p;
  int32_t   iCol;
H
Hongze Cheng 已提交
309
  STSKVRow *pTSKVRow = (STSKVRow *)pBuilder->pKVBuf;
H
Hongze Cheng 已提交
310

H
Hongze Cheng 已提交
311 312
  // use interp search
  if (pTColumn->colId < cid) {  // right search
H
Hongze Cheng 已提交
313 314
    for (iCol = pBuilder->iCol + 1; iCol < pBuilder->pTSchema->numOfCols; iCol++) {
      pTColumn = &pBuilder->pTSchema->columns[iCol];
H
Hongze Cheng 已提交
315
      if (pTColumn->colId >= cid) break;
H
Hongze Cheng 已提交
316
    }
H
Hongze Cheng 已提交
317
  } else if (pTColumn->colId > cid) {  // left search
H
Hongze Cheng 已提交
318 319
    for (iCol = pBuilder->iCol - 1; iCol >= 0; iCol--) {
      pTColumn = &pBuilder->pTSchema->columns[iCol];
H
Hongze Cheng 已提交
320
      if (pTColumn->colId <= cid) break;
H
Hongze Cheng 已提交
321
    }
H
Hongze Cheng 已提交
322 323
  }

H
Hongze Cheng 已提交
324
  if (pTColumn->colId != cid || COL_IS_SET(pTColumn->flags)) {
H
Hongze Cheng 已提交
325 326 327
    return -1;
  }

H
Hongze Cheng 已提交
328 329
  pBuilder->iCol = iCol;

H
Hongze Cheng 已提交
330 331
  // set value
  if (cid == 0) {
H
Hongze Cheng 已提交
332
    ASSERT(pData && nData == sizeof(TSKEY) && iCol == 0);
H
Hongze Cheng 已提交
333
    pBuilder->row.ts = *(TSKEY *)pData;
H
Hongze Cheng 已提交
334
    pTColumn->flags |= COL_SET_VAL;
H
Hongze Cheng 已提交
335
  } else {
H
Hongze Cheng 已提交
336 337
    if (pData) {
      // set VAL
H
Hongze Cheng 已提交
338

H
Hongze Cheng 已提交
339 340 341 342 343
      pBuilder->row.flags |= TSROW_HAS_VAL;
      pTColumn->flags |= COL_SET_VAL;

      /* KV */
      if (1) {  // avoid KV at some threshold (todo)
H
Hongze Cheng 已提交
344 345
        pTSKVRow->idx[pTSKVRow->nCols].cid = cid;
        pTSKVRow->idx[pTSKVRow->nCols].offset = pBuilder->vlenKV;
H
Hongze Cheng 已提交
346

H
Hongze Cheng 已提交
347 348
        p = pBuilder->pKVBuf + sizeof(STSKVRow) + sizeof(SKVIdx) * (pBuilder->pTSchema->numOfCols - 1) +
            pBuilder->vlenKV;
H
Hongze Cheng 已提交
349 350 351 352 353 354 355 356
        if (IS_VAR_DATA_TYPE(pTColumn->type)) {
          ASSERT(nData <= pTColumn->bytes);
          pBuilder->vlenKV += tPutBinary(p, pData, nData);
        } else {
          ASSERT(nData == pTColumn->bytes);
          memcpy(p, pData, nData);
          pBuilder->vlenKV += nData;
        }
H
Hongze Cheng 已提交
357 358
      }

H
Hongze Cheng 已提交
359 360 361 362 363
      /* TUPLE */
      p = pBuilder->pTPBuf + pBuilder->szBitMap2 + pTColumn->offset;
      if (IS_VAR_DATA_TYPE(pTColumn->type)) {
        ASSERT(nData <= pTColumn->bytes);
        *(int32_t *)p = pBuilder->vlenTP;
H
Hongze Cheng 已提交
364

H
Hongze Cheng 已提交
365
        p = pBuilder->pTPBuf + pBuilder->szBitMap2 + pBuilder->pTSchema->flen + pBuilder->vlenTP;
H
Hongze Cheng 已提交
366
        pBuilder->vlenTP += tPutBinary(p, pData, nData);
H
Hongze Cheng 已提交
367
      } else {
H
Hongze Cheng 已提交
368
        ASSERT(nData == pTColumn->bytes);
H
Hongze Cheng 已提交
369 370
        memcpy(p, pData, nData);
      }
H
Hongze Cheng 已提交
371 372 373
    } else {
      // set NULL

H
Hongze Cheng 已提交
374
      pBuilder->row.flags |= TSROW_HAS_NULL;
H
Hongze Cheng 已提交
375
      pTColumn->flags |= COL_SET_NULL;
H
Hongze Cheng 已提交
376

H
Hongze Cheng 已提交
377 378
      pTSKVRow->idx[pTSKVRow->nCols].cid = cid;
      pTSKVRow->idx[pTSKVRow->nCols].offset = -1;
H
Hongze Cheng 已提交
379
    }
H
Hongze Cheng 已提交
380

H
Hongze Cheng 已提交
381
    pTSKVRow->nCols++;
H
Hongze Cheng 已提交
382 383 384 385 386
  }

  return 0;
}

H
Hongze Cheng 已提交
387 388 389 390 391 392 393 394 395 396
static FORCE_INLINE int tSKVIdxCmprFn(const void *p1, const void *p2) {
  SKVIdx *pKVIdx1 = (SKVIdx *)p1;
  SKVIdx *pKVIdx2 = (SKVIdx *)p2;
  if (pKVIdx1->cid > pKVIdx2->cid) {
    return 1;
  } else if (pKVIdx1->cid < pKVIdx2->cid) {
    return -1;
  }
  return 0;
}
H
Hongze Cheng 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
static void setBitMap(uint8_t *p, STSchema *pTSchema, uint8_t flags) {
  int32_t   bidx;
  STColumn *pTColumn;

  for (int32_t iCol = 1; iCol < pTSchema->numOfCols; iCol++) {
    pTColumn = &pTSchema->columns[iCol];
    bidx = iCol - 1;

    switch (flags) {
      case TSROW_HAS_NULL | TSROW_HAS_NONE:
        if (pTColumn->flags & COL_SET_NULL) {
          SET_BIT1(p, bidx, (uint8_t)1);
        } else {
          SET_BIT1(p, bidx, (uint8_t)0);
        }
        break;
      case TSROW_HAS_VAL | TSROW_HAS_NULL | TSROW_HAS_NONE:
        if (pTColumn->flags & COL_SET_NULL) {
          SET_BIT2(p, bidx, (uint8_t)1);
H
Hongze Cheng 已提交
416
        } else if (pTColumn->flags & COL_SET_VAL) {
H
Hongze Cheng 已提交
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
          SET_BIT2(p, bidx, (uint8_t)2);
        } else {
          SET_BIT2(p, bidx, (uint8_t)0);
        }
        break;
      default:
        if (pTColumn->flags & COL_SET_VAL) {
          SET_BIT1(p, bidx, (uint8_t)1);
        } else {
          SET_BIT1(p, bidx, (uint8_t)0);
        }

        break;
    }
  }
}
H
Hongze Cheng 已提交
433
int32_t tTSRowBuilderGetRow(STSRowBuilder *pBuilder, const STSRow2 **ppRow) {
H
Hongze Cheng 已提交
434 435 436
  int32_t   nDataTP, nDataKV;
  uint32_t  flags;
  STSKVRow *pTSKVRow = (STSKVRow *)pBuilder->pKVBuf;
H
Hongze Cheng 已提交
437
  int32_t   nCols = pBuilder->pTSchema->numOfCols;
H
Hongze Cheng 已提交
438 439

  // error not set ts
H
Hongze Cheng 已提交
440
  if (!COL_IS_SET(pBuilder->pTSchema->columns->flags)) {
H
Hongze Cheng 已提交
441 442 443
    return -1;
  }

H
Hongze Cheng 已提交
444 445
  ASSERT(pTSKVRow->nCols < nCols);
  if (pTSKVRow->nCols < nCols - 1) {
H
Hongze Cheng 已提交
446
    pBuilder->row.flags |= TSROW_HAS_NONE;
H
Hongze Cheng 已提交
447
  }
H
Hongze Cheng 已提交
448

H
Hongze Cheng 已提交
449 450 451 452 453
  ASSERT(pBuilder->row.flags & 0xf != 0);
  *(ppRow) = &pBuilder->row;
  switch (pBuilder->row.flags & 0xf) {
    case TSROW_HAS_NONE:
    case TSROW_HAS_NULL:
H
Hongze Cheng 已提交
454 455
      pBuilder->row.nData = 0;
      pBuilder->row.pData = NULL;
H
Hongze Cheng 已提交
456 457
      return 0;
    case TSROW_HAS_NULL | TSROW_HAS_NONE:
H
Hongze Cheng 已提交
458
      nDataTP = pBuilder->szBitMap1;
H
Hongze Cheng 已提交
459
      break;
H
Hongze Cheng 已提交
460
    case TSROW_HAS_VAL:
H
Hongze Cheng 已提交
461
      nDataTP = pBuilder->pTSchema->flen + pBuilder->vlenTP;
H
Hongze Cheng 已提交
462
      break;
H
Hongze Cheng 已提交
463 464
    case TSROW_HAS_VAL | TSROW_HAS_NONE:
    case TSROW_HAS_VAL | TSROW_HAS_NULL:
H
Hongze Cheng 已提交
465
      nDataTP = pBuilder->szBitMap1 + pBuilder->pTSchema->flen + pBuilder->vlenTP;
H
Hongze Cheng 已提交
466
      break;
H
Hongze Cheng 已提交
467
    case TSROW_HAS_VAL | TSROW_HAS_NULL | TSROW_HAS_NONE:
H
Hongze Cheng 已提交
468
      nDataTP = pBuilder->szBitMap2 + pBuilder->pTSchema->flen + pBuilder->vlenTP;
H
Hongze Cheng 已提交
469 470
      break;
    default:
H
Hongze Cheng 已提交
471
      ASSERT(0);
H
Hongze Cheng 已提交
472 473
  }

H
Hongze Cheng 已提交
474 475
  nDataKV = sizeof(STSKVRow) + sizeof(SKVIdx) * pTSKVRow->nCols + pBuilder->vlenKV;
  pBuilder->row.sver = pBuilder->pTSchema->version;
H
Hongze Cheng 已提交
476 477 478
  if (nDataKV < nDataTP) {
    // generate KV row

H
Hongze Cheng 已提交
479 480
    ASSERT(pBuilder->row.flags & 0xf != TSROW_HAS_VAL);

H
Hongze Cheng 已提交
481
    pBuilder->row.flags |= TSROW_KV_ROW;
H
Hongze Cheng 已提交
482
    pBuilder->row.nData = nDataKV;
H
Hongze Cheng 已提交
483
    pBuilder->row.pData = pBuilder->pKVBuf;
H
Hongze Cheng 已提交
484

H
Hongze Cheng 已提交
485
    qsort(pTSKVRow->idx, pTSKVRow->nCols, sizeof(SKVIdx), tSKVIdxCmprFn);
H
Hongze Cheng 已提交
486 487
    if (pTSKVRow->nCols < nCols - 1) {
      memmove(&pTSKVRow->idx[pTSKVRow->nCols], &pTSKVRow->idx[nCols - 1], pBuilder->vlenKV);
H
Hongze Cheng 已提交
488 489
    }
  } else {
H
Hongze Cheng 已提交
490 491 492 493
    // generate TUPLE row

    pBuilder->row.nData = nDataTP;

H
Hongze Cheng 已提交
494 495
    uint8_t *p;
    uint8_t  flags = pBuilder->row.flags & 0xf;
H
Hongze Cheng 已提交
496

H
Hongze Cheng 已提交
497 498
    if (flags == TSROW_HAS_VAL) {
      pBuilder->row.pData = pBuilder->pTPBuf + pBuilder->szBitMap2;
H
Hongze Cheng 已提交
499
    } else {
H
Hongze Cheng 已提交
500 501
      if (flags == TSROW_HAS_VAL | TSROW_HAS_NULL | TSROW_HAS_NONE) {
        pBuilder->row.pData = pBuilder->pTPBuf;
H
Hongze Cheng 已提交
502
      } else {
H
Hongze Cheng 已提交
503
        pBuilder->row.pData = pBuilder->pTPBuf + pBuilder->szBitMap2 - pBuilder->szBitMap1;
H
Hongze Cheng 已提交
504 505
      }

H
Hongze Cheng 已提交
506
      setBitMap(pBuilder->row.pData, pBuilder->pTSchema, flags);
H
Hongze Cheng 已提交
507
    }
H
Hongze Cheng 已提交
508 509 510 511 512
  }

  return 0;
}

H
Hongze Cheng 已提交
513 514
static int tTagValCmprFn(const void *p1, const void *p2) {
  if (((STagVal *)p1)->cid < ((STagVal *)p2)->cid) {
H
Hongze Cheng 已提交
515
    return -1;
H
Hongze Cheng 已提交
516
  } else if (((STagVal *)p1)->cid > ((STagVal *)p2)->cid) {
H
Hongze Cheng 已提交
517 518
    return 1;
  }
H
Hongze Cheng 已提交
519 520

  ASSERT(0);
H
Hongze Cheng 已提交
521 522
  return 0;
}
H
Hongze Cheng 已提交
523 524 525
static int tTagValJsonCmprFn(const void *p1, const void *p2) {
  return strcmp(((STagVal *)p1)[0].pKey, ((STagVal *)p2)[0].pKey);
}
C
Cary Xu 已提交
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596

static void debugPrintTagVal(int8_t type, const void *val, int32_t vlen, const char *tag, int32_t ln) {
  switch (type) {
    case TSDB_DATA_TYPE_JSON:
    case TSDB_DATA_TYPE_VARCHAR:
    case TSDB_DATA_TYPE_NCHAR: {
      char tmpVal[32] = {0};
      memcpy(tmpVal, val, 32);
      printf("%s:%d type:%d vlen:%d, val:\"%s\"\n", tag, ln, (int32_t)type, vlen, tmpVal);
    } break;
    case TSDB_DATA_TYPE_FLOAT:
      printf("%s:%d type:%d vlen:%d, val:%f\n", tag, ln, (int32_t)type, vlen, *(float *)val);
      break;
    case TSDB_DATA_TYPE_DOUBLE:
      printf("%s:%d type:%d vlen:%d, val:%lf\n", tag, ln, (int32_t)type, vlen, *(double *)val);
      break;
    case TSDB_DATA_TYPE_BOOL:
      printf("%s:%d type:%d vlen:%d, val:%" PRIu8 "\n", tag, ln, (int32_t)type, vlen, *(uint8_t *)val);
      break;
    case TSDB_DATA_TYPE_TINYINT:
      printf("%s:%d type:%d vlen:%d, val:%" PRIi8 "\n", tag, ln, (int32_t)type, vlen, *(int8_t *)val);
      break;
    case TSDB_DATA_TYPE_SMALLINT:
      printf("%s:%d type:%d vlen:%d, val:%" PRIi16 "\n", tag, ln, (int32_t)type, vlen, *(int16_t *)val);
      break;
    case TSDB_DATA_TYPE_INT:
      printf("%s:%d type:%d vlen:%d, val:%" PRIi32 "\n", tag, ln, (int32_t)type, vlen, *(int32_t *)val);
      break;
    case TSDB_DATA_TYPE_BIGINT:
      printf("%s:%d type:%d vlen:%d, val:%" PRIi64 "\n", tag, ln, (int32_t)type, vlen, *(int64_t *)val);
      break;
    case TSDB_DATA_TYPE_TIMESTAMP:
      printf("%s:%d type:%d vlen:%d, val:%" PRIi64 "\n", tag, ln, (int32_t)type, vlen, *(int64_t *)val);
      break;
    case TSDB_DATA_TYPE_UTINYINT:
      printf("%s:%d type:%d vlen:%d, val:%" PRIu8 "\n", tag, ln, (int32_t)type, vlen, *(uint8_t *)val);
      break;
    case TSDB_DATA_TYPE_USMALLINT:
      printf("%s:%d type:%d vlen:%d, val:%" PRIu16 "\n", tag, ln, (int32_t)type, vlen, *(uint16_t *)val);
      break;
    case TSDB_DATA_TYPE_UINT:
      printf("%s:%d type:%d vlen:%d, val:%" PRIu32 "\n", tag, ln, (int32_t)type, vlen, *(uint32_t *)val);
      break;
    case TSDB_DATA_TYPE_UBIGINT:
      printf("%s:%d type:%d vlen:%d, val:%" PRIu64 "\n", tag, ln, (int32_t)type, vlen, *(uint64_t *)val);
      break;
    default:
      ASSERT(0);
      break;
  }
}

void debugPrintSTag(STag *pTag, const char *tag, int32_t ln) {
  printf("%s:%d >>> STAG === isJson:%s, len: %d, nTag: %d, sver:%d\n", tag, ln, pTag->isJson ? "true" : "false",
         (int32_t)pTag->len, (int32_t)pTag->nTag, pTag->ver);
  char *p = (char *)&pTag->idx[pTag->nTag];
  for (uint16_t n = 0; n < pTag->nTag; ++n) {
    int16_t *pIdx = pTag->idx + n;
    STagVal  tagVal = {0};
    if (pTag->isJson) {
      tagVal.pKey = (char *)POINTER_SHIFT(p, *pIdx);
    } else {
      tagVal.cid = *(int16_t *)POINTER_SHIFT(p, *pIdx);
    }
    printf("%s:%d loop[%d-%d] offset=%d\n", __func__, __LINE__, (int32_t)pTag->nTag, (int32_t)n, *pIdx);
    tGetTagVal(p, &tagVal, pTag->isJson);
    debugPrintTagVal(tagVal.type, tagVal.pData, tagVal.nData, __func__, __LINE__);
  }
  printf("\n");
}

H
Hongze Cheng 已提交
597 598
static int32_t tPutTagVal(uint8_t *p, STagVal *pTagVal, int8_t isJson) {
  int32_t n = 0;
H
Hongze Cheng 已提交
599

H
Hongze Cheng 已提交
600 601 602 603 604 605
  // key
  if (isJson) {
    n += tPutCStr(p ? p + n : p, pTagVal->pKey);
  } else {
    n += tPutI16v(p ? p + n : p, pTagVal->cid);
  }
H
Hongze Cheng 已提交
606

H
Hongze Cheng 已提交
607 608 609
  // type
  n += tPutI8(p ? p + n : p, pTagVal->type);

C
Cary Xu 已提交
610
  debugPrintTagVal(pTagVal->type, pTagVal->pData, pTagVal->nData, __func__, __LINE__);
H
Hongze Cheng 已提交
611 612 613 614 615 616 617
  // value
  if (IS_VAR_DATA_TYPE(pTagVal->type)) {
    n += tPutBinary(p ? p + n : p, pTagVal->pData, pTagVal->nData);
  } else {
    ASSERT(pTagVal->nData == TYPE_BYTES[pTagVal->type]);
    if (p) memcpy(p + n, pTagVal->pData, pTagVal->nData);
    n += pTagVal->nData;
H
Hongze Cheng 已提交
618 619
  }

H
Hongze Cheng 已提交
620 621 622 623 624 625 626 627 628 629
  return n;
}
static int32_t tGetTagVal(uint8_t *p, STagVal *pTagVal, int8_t isJson) {
  int32_t n = 0;

  // key
  if (isJson) {
    n += tGetCStr(p + n, &pTagVal->pKey);
  } else {
    n += tGetI16v(p + n, &pTagVal->cid);
H
Hongze Cheng 已提交
630 631
  }

H
Hongze Cheng 已提交
632 633
  // type
  n += tGetI8(p + n, &pTagVal->type);
H
Hongze Cheng 已提交
634

H
Hongze Cheng 已提交
635 636 637 638 639 640 641 642 643 644 645
  // value
  if (IS_VAR_DATA_TYPE(pTagVal->type)) {
    n += tGetBinary(p + n, &pTagVal->pData, &pTagVal->nData);
  } else {
    pTagVal->pData = p + n;
    pTagVal->nData = TYPE_BYTES[pTagVal->type];
    n += pTagVal->nData;
  }

  return n;
}
H
Hongze Cheng 已提交
646
int32_t tTagNew(SArray *pArray, int32_t version, int8_t isJson, STag **ppTag) {
H
Hongze Cheng 已提交
647 648 649
  int32_t  code = 0;
  uint8_t *p = NULL;
  int16_t  n = 0;
H
Hongze Cheng 已提交
650
  int16_t  nTag = taosArrayGetSize(pArray);
H
Hongze Cheng 已提交
651 652 653 654
  int32_t  szTag = sizeof(STag) + sizeof(int16_t) * nTag;

  // sort
  if (isJson) {
H
Hongze Cheng 已提交
655
    qsort(pArray->pData, nTag, sizeof(STagVal), tTagValJsonCmprFn);
H
Hongze Cheng 已提交
656
  } else {
H
Hongze Cheng 已提交
657
    qsort(pArray->pData, nTag, sizeof(STagVal), tTagValCmprFn);
H
Hongze Cheng 已提交
658 659 660
  }

  // get size
H
Hongze Cheng 已提交
661
  for (int16_t iTag = 0; iTag < nTag; iTag++) {
H
Hongze Cheng 已提交
662
    szTag += tPutTagVal(NULL, (STagVal *)taosArrayGet(pArray, iTag), isJson);
H
Hongze Cheng 已提交
663
  }
H
Hongze Cheng 已提交
664

H
Hongze Cheng 已提交
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
  // TODO
  // if (szTag >= 16 * 1024) {
  //   code = TSDB_CODE_IVLD_TAG;
  //   goto _err;
  // }

  // build tag
  (*ppTag) = (STag *)taosMemoryMalloc(szTag);
  if ((*ppTag) == NULL) {
    code = TSDB_CODE_OUT_OF_MEMORY;
    goto _err;
  }
  (*ppTag)->isJson = isJson ? 1 : 0;
  (*ppTag)->len = szTag;
  (*ppTag)->nTag = nTag;
  (*ppTag)->ver = version;
H
Hongze Cheng 已提交
681

H
Hongze Cheng 已提交
682 683 684 685
  p = (uint8_t *)&(*ppTag)->idx[nTag];
  n = 0;
  for (int16_t iTag = 0; iTag < nTag; iTag++) {
    (*ppTag)->idx[iTag] = n;
H
Hongze Cheng 已提交
686
    n += tPutTagVal(p + n, (STagVal *)taosArrayGet(pArray, iTag), isJson);
H
Hongze Cheng 已提交
687 688
  }

C
Cary Xu 已提交
689 690
  debugPrintSTag(*ppTag, __func__, __LINE__);

H
Hongze Cheng 已提交
691 692 693 694
  return code;

_err:
  return code;
H
Hongze Cheng 已提交
695 696 697 698 699 700
}

void tTagFree(STag *pTag) {
  if (pTag) taosMemoryFree(pTag);
}

C
Cary Xu 已提交
701
bool tTagGet(const STag *pTag, STagVal *pTagVal) {
H
Hongze Cheng 已提交
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
  int16_t  lidx = 0;
  int16_t  ridx = pTag->nTag - 1;
  int16_t  midx;
  uint8_t *p = (uint8_t *)&pTag->idx[pTag->nTag];
  STagVal  tv;
  int      c;

  pTagVal->type = TSDB_DATA_TYPE_NULL;
  pTagVal->pData = NULL;
  pTagVal->nData = 0;
  while (lidx <= ridx) {
    midx = (lidx + ridx) / 2;

    tGetTagVal(p + pTag->idx[midx], &tv, pTag->isJson);
    if (pTag->isJson) {
      c = tTagValJsonCmprFn(pTagVal, &tv);
H
Hongze Cheng 已提交
718
    } else {
H
Hongze Cheng 已提交
719
      c = tTagValCmprFn(pTagVal, &tv);
H
Hongze Cheng 已提交
720 721
    }

H
Hongze Cheng 已提交
722 723 724 725
    if (c < 0) {
      ridx = midx - 1;
    } else if (c > 0) {
      lidx = midx + 1;
H
Hongze Cheng 已提交
726
    } else {
H
Hongze Cheng 已提交
727 728 729
      pTagVal->type = tv.type;
      pTagVal->nData = tv.nData;
      pTagVal->pData = tv.pData;
C
Cary Xu 已提交
730
      return true;
H
Hongze Cheng 已提交
731 732
    }
  }
C
Cary Xu 已提交
733
  return false;
H
Hongze Cheng 已提交
734 735
}

H
more  
Hongze Cheng 已提交
736 737
int32_t tEncodeTag(SEncoder *pEncoder, const STag *pTag) {
  return tEncodeBinary(pEncoder, (const uint8_t *)pTag, pTag->len);
H
Hongze Cheng 已提交
738 739
}

H
Hongze Cheng 已提交
740
int32_t tDecodeTag(SDecoder *pDecoder, STag **ppTag) { return tDecodeBinary(pDecoder, (uint8_t **)ppTag, NULL); }
H
Hongze Cheng 已提交
741

C
Cary Xu 已提交
742
int32_t tTagToValArray(const STag *pTag, SArray **ppArray) {
H
Hongze Cheng 已提交
743 744
  int32_t  code = 0;
  uint8_t *p = (uint8_t *)&pTag->idx[pTag->nTag];
H
Hongze Cheng 已提交
745
  STagVal  tv;
H
Hongze Cheng 已提交
746

H
more  
Hongze Cheng 已提交
747
  (*ppArray) = taosArrayInit(pTag->nTag + 1, sizeof(STagVal));
H
Hongze Cheng 已提交
748
  if (*ppArray == NULL) {
H
Hongze Cheng 已提交
749 750 751 752 753
    code = TSDB_CODE_OUT_OF_MEMORY;
    goto _err;
  }

  for (int16_t iTag = 0; iTag < pTag->nTag; iTag++) {
H
Hongze Cheng 已提交
754 755
    tGetTagVal(p + pTag->idx[iTag], &tv, pTag->isJson);
    taosArrayPush(*ppArray, &tv);
H
Hongze Cheng 已提交
756 757 758 759 760 761 762 763
  }

  return code;

_err:
  return code;
}

H
Hongze Cheng 已提交
764
#if 1  // ===================================================================================================================
765
static void dataColSetNEleNull(SDataCol *pCol, int nEle);
H
Hongze Cheng 已提交
766
int         tdAllocMemForCol(SDataCol *pCol, int maxPoints) {
L
Liu Jicong 已提交
767
  int spaceNeeded = pCol->bytes * maxPoints;
S
Shengliang Guan 已提交
768
  if (IS_VAR_DATA_TYPE(pCol->type)) {
L
Liu Jicong 已提交
769
    spaceNeeded += sizeof(VarDataOffsetT) * maxPoints;
L
Liu Jicong 已提交
770
  }
C
Cary Xu 已提交
771
#ifdef TD_SUPPORT_BITMAP
C
Cary Xu 已提交
772 773 774 775
  int32_t nBitmapBytes = (int32_t)TD_BITMAP_BYTES(maxPoints);
  spaceNeeded += (int)nBitmapBytes;
  // TODO: Currently, the compression of bitmap parts is affiliated to the column data parts, thus allocate 1 more
  // TYPE_BYTES as to comprise complete TYPE_BYTES. Otherwise, invalid read/write would be triggered.
H
Hongze Cheng 已提交
776 777
  // spaceNeeded += TYPE_BYTES[pCol->type]; // the bitmap part is append as a single part since 2022.04.03, thus
  // remove the additional space
C
Cary Xu 已提交
778
#endif
C
Cary Xu 已提交
779

S
Shengliang Guan 已提交
780
  if (pCol->spaceSize < spaceNeeded) {
wafwerar's avatar
wafwerar 已提交
781
    void *ptr = taosMemoryRealloc(pCol->pData, spaceNeeded);
S
Shengliang Guan 已提交
782 783
    if (ptr == NULL) {
      uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)spaceNeeded, strerror(errno));
L
Liu Jicong 已提交
784
      return -1;
L
Liu Jicong 已提交
785 786 787
    } else {
      pCol->pData = ptr;
      pCol->spaceSize = spaceNeeded;
788 789
    }
  }
C
Cary Xu 已提交
790
#ifdef TD_SUPPORT_BITMAP
791

C
Cary Xu 已提交
792 793 794 795
  if (IS_VAR_DATA_TYPE(pCol->type)) {
    pCol->pBitmap = POINTER_SHIFT(pCol->pData, pCol->bytes * maxPoints);
    pCol->dataOff = POINTER_SHIFT(pCol->pBitmap, nBitmapBytes);
  } else {
C
Cary Xu 已提交
796
    pCol->pBitmap = POINTER_SHIFT(pCol->pData, pCol->bytes * maxPoints);
L
Liu Jicong 已提交
797
  }
C
Cary Xu 已提交
798 799 800 801
#else
  if (IS_VAR_DATA_TYPE(pCol->type)) {
    pCol->dataOff = POINTER_SHIFT(pCol->pData, pCol->bytes * maxPoints);
  }
C
Cary Xu 已提交
802
#endif
L
Liu Jicong 已提交
803
  return 0;
804 805
}

H
hzcheng 已提交
806 807 808
/**
 * Duplicate the schema and return a new object
 */
H
Hongze Cheng 已提交
809
STSchema *tdDupSchema(const STSchema *pSchema) {
S
Shengliang Guan 已提交
810
  int       tlen = sizeof(STSchema) + sizeof(STColumn) * schemaNCols(pSchema);
wafwerar's avatar
wafwerar 已提交
811
  STSchema *tSchema = (STSchema *)taosMemoryMalloc(tlen);
H
hzcheng 已提交
812 813
  if (tSchema == NULL) return NULL;

H
Hongze Cheng 已提交
814
  memcpy((void *)tSchema, (void *)pSchema, tlen);
H
hzcheng 已提交
815 816 817 818

  return tSchema;
}

H
TD-27  
hzcheng 已提交
819 820 821
/**
 * Encode a schema to dst, and return the next pointer
 */
H
TD-353  
Hongze Cheng 已提交
822 823 824 825
int tdEncodeSchema(void **buf, STSchema *pSchema) {
  int tlen = 0;
  tlen += taosEncodeFixedI32(buf, schemaVersion(pSchema));
  tlen += taosEncodeFixedI32(buf, schemaNCols(pSchema));
H
TD-166  
hzcheng 已提交
826

H
TD-27  
hzcheng 已提交
827 828
  for (int i = 0; i < schemaNCols(pSchema); i++) {
    STColumn *pCol = schemaColAt(pSchema, i);
H
TD-353  
Hongze Cheng 已提交
829
    tlen += taosEncodeFixedI8(buf, colType(pCol));
C
Cary Xu 已提交
830
    tlen += taosEncodeFixedI8(buf, colFlags(pCol));
H
TD-353  
Hongze Cheng 已提交
831
    tlen += taosEncodeFixedI16(buf, colColId(pCol));
832
    tlen += taosEncodeFixedI16(buf, colBytes(pCol));
H
TD-27  
hzcheng 已提交
833 834
  }

H
TD-353  
Hongze Cheng 已提交
835
  return tlen;
H
TD-27  
hzcheng 已提交
836 837 838 839 840
}

/**
 * Decode a schema from a binary.
 */
H
TD-353  
Hongze Cheng 已提交
841
void *tdDecodeSchema(void *buf, STSchema **pRSchema) {
S
Shengliang Guan 已提交
842 843
  int             version = 0;
  int             numOfCols = 0;
H
TD-353  
Hongze Cheng 已提交
844
  STSchemaBuilder schemaBuilder;
H
TD-27  
hzcheng 已提交
845

H
TD-353  
Hongze Cheng 已提交
846 847
  buf = taosDecodeFixedI32(buf, &version);
  buf = taosDecodeFixedI32(buf, &numOfCols);
H
TD-27  
hzcheng 已提交
848

H
Hongze Cheng 已提交
849 850
  if (tdInitTSchemaBuilder(&schemaBuilder, version) < 0) return NULL;

H
TD-353  
Hongze Cheng 已提交
851
  for (int i = 0; i < numOfCols; i++) {
852
    col_type_t  type = 0;
C
Cary Xu 已提交
853
    int8_t      flags = 0;
854 855
    col_id_t    colId = 0;
    col_bytes_t bytes = 0;
H
TD-353  
Hongze Cheng 已提交
856
    buf = taosDecodeFixedI8(buf, &type);
C
Cary Xu 已提交
857
    buf = taosDecodeFixedI8(buf, &flags);
H
TD-353  
Hongze Cheng 已提交
858
    buf = taosDecodeFixedI16(buf, &colId);
859
    buf = taosDecodeFixedI32(buf, &bytes);
C
Cary Xu 已提交
860
    if (tdAddColToSchema(&schemaBuilder, type, flags, colId, bytes) < 0) {
H
Hongze Cheng 已提交
861 862 863
      tdDestroyTSchemaBuilder(&schemaBuilder);
      return NULL;
    }
H
TD-27  
hzcheng 已提交
864 865
  }

H
TD-353  
Hongze Cheng 已提交
866
  *pRSchema = tdGetSchemaFromBuilder(&schemaBuilder);
H
Hongze Cheng 已提交
867
  tdDestroyTSchemaBuilder(&schemaBuilder);
H
TD-353  
Hongze Cheng 已提交
868
  return buf;
H
Hongze Cheng 已提交
869 870
}

C
Cary Xu 已提交
871
int tdInitTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version) {
H
Hongze Cheng 已提交
872 873 874
  if (pBuilder == NULL) return -1;

  pBuilder->tCols = 256;
wafwerar's avatar
wafwerar 已提交
875
  pBuilder->columns = (STColumn *)taosMemoryMalloc(sizeof(STColumn) * pBuilder->tCols);
H
Hongze Cheng 已提交
876 877 878 879 880 881 882 883
  if (pBuilder->columns == NULL) return -1;

  tdResetTSchemaBuilder(pBuilder, version);
  return 0;
}

void tdDestroyTSchemaBuilder(STSchemaBuilder *pBuilder) {
  if (pBuilder) {
wafwerar's avatar
wafwerar 已提交
884
    taosMemoryFreeClear(pBuilder->columns);
H
Hongze Cheng 已提交
885 886 887
  }
}

C
Cary Xu 已提交
888
void tdResetTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version) {
H
Hongze Cheng 已提交
889 890 891
  pBuilder->nCols = 0;
  pBuilder->tlen = 0;
  pBuilder->flen = 0;
T
Tao Liu 已提交
892
  pBuilder->vlen = 0;
H
Hongze Cheng 已提交
893 894 895
  pBuilder->version = version;
}

C
Cary Xu 已提交
896
int32_t tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int8_t flags, col_id_t colId, col_bytes_t bytes) {
897
  if (!isValidDataType(type)) return -1;
H
Hongze Cheng 已提交
898 899 900

  if (pBuilder->nCols >= pBuilder->tCols) {
    pBuilder->tCols *= 2;
wafwerar's avatar
wafwerar 已提交
901
    STColumn *columns = (STColumn *)taosMemoryRealloc(pBuilder->columns, sizeof(STColumn) * pBuilder->tCols);
T
tickduan 已提交
902 903
    if (columns == NULL) return -1;
    pBuilder->columns = columns;
H
Hongze Cheng 已提交
904 905 906 907 908
  }

  STColumn *pCol = &(pBuilder->columns[pBuilder->nCols]);
  colSetType(pCol, type);
  colSetColId(pCol, colId);
C
Cary Xu 已提交
909
  colSetFlags(pCol, flags);
H
Hongze Cheng 已提交
910 911 912
  if (pBuilder->nCols == 0) {
    colSetOffset(pCol, 0);
  } else {
S
Shengliang Guan 已提交
913
    STColumn *pTCol = &(pBuilder->columns[pBuilder->nCols - 1]);
H
Hongze Cheng 已提交
914 915 916 917 918
    colSetOffset(pCol, pTCol->offset + TYPE_BYTES[pTCol->type]);
  }

  if (IS_VAR_DATA_TYPE(type)) {
    colSetBytes(pCol, bytes);
T
Tao Liu 已提交
919 920
    pBuilder->tlen += (TYPE_BYTES[type] + bytes);
    pBuilder->vlen += bytes - sizeof(VarDataLenT);
H
Hongze Cheng 已提交
921 922 923
  } else {
    colSetBytes(pCol, TYPE_BYTES[type]);
    pBuilder->tlen += TYPE_BYTES[type];
T
Tao Liu 已提交
924
    pBuilder->vlen += TYPE_BYTES[type];
H
Hongze Cheng 已提交
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
  }

  pBuilder->nCols++;
  pBuilder->flen += TYPE_BYTES[type];

  ASSERT(pCol->offset < pBuilder->flen);

  return 0;
}

STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder) {
  if (pBuilder->nCols <= 0) return NULL;

  int tlen = sizeof(STSchema) + sizeof(STColumn) * pBuilder->nCols;

wafwerar's avatar
wafwerar 已提交
940
  STSchema *pSchema = (STSchema *)taosMemoryMalloc(tlen);
H
Hongze Cheng 已提交
941 942 943 944 945 946
  if (pSchema == NULL) return NULL;

  schemaVersion(pSchema) = pBuilder->version;
  schemaNCols(pSchema) = pBuilder->nCols;
  schemaTLen(pSchema) = pBuilder->tlen;
  schemaFLen(pSchema) = pBuilder->flen;
T
Tao Liu 已提交
947
  schemaVLen(pSchema) = pBuilder->vlen;
H
Hongze Cheng 已提交
948

C
Cary Xu 已提交
949
#ifdef TD_SUPPORT_BITMAP
C
Cary Xu 已提交
950
  schemaTLen(pSchema) += (int)TD_BITMAP_BYTES(schemaNCols(pSchema));
C
Cary Xu 已提交
951 952
#endif

H
Hongze Cheng 已提交
953 954
  memcpy(schemaColAt(pSchema, 0), pBuilder->columns, sizeof(STColumn) * pBuilder->nCols);

H
TD-27  
hzcheng 已提交
955 956 957
  return pSchema;
}

958
void dataColInit(SDataCol *pDataCol, STColumn *pCol, int maxPoints) {
H
TD-166  
hzcheng 已提交
959 960 961
  pDataCol->type = colType(pCol);
  pDataCol->colId = colColId(pCol);
  pDataCol->bytes = colBytes(pCol);
S
Shengliang Guan 已提交
962
  pDataCol->offset = colOffset(pCol) + 0;  // TD_DATA_ROW_HEAD_SIZE;
H
TD-166  
hzcheng 已提交
963 964 965

  pDataCol->len = 0;
}
C
Cary Xu 已提交
966

L
Liu Jicong 已提交
967 968 969 970 971 972
static FORCE_INLINE const void *tdGetColDataOfRowUnsafe(SDataCol *pCol, int row) {
  if (IS_VAR_DATA_TYPE(pCol->type)) {
    return POINTER_SHIFT(pCol->pData, pCol->dataOff[row]);
  } else {
    return POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * row);
  }
H
TD-166  
hzcheng 已提交
973 974
}

H
TD-166  
hzcheng 已提交
975
bool isNEleNull(SDataCol *pCol, int nEle) {
S
Shengliang Guan 已提交
976
  if (isAllRowsNull(pCol)) return true;
977
  for (int i = 0; i < nEle; ++i) {
L
Liu Jicong 已提交
978
    if (!isNull(tdGetColDataOfRowUnsafe(pCol, i), pCol->type)) return false;
H
TD-166  
hzcheng 已提交
979
  }
H
Hongze Cheng 已提交
980
  return true;
H
TD-166  
hzcheng 已提交
981 982
}

C
Cary Xu 已提交
983
void *dataColSetOffset(SDataCol *pCol, int nEle) {
H
TD-166  
hzcheng 已提交
984 985
  ASSERT(((pCol->type == TSDB_DATA_TYPE_BINARY) || (pCol->type == TSDB_DATA_TYPE_NCHAR)));

H
Hongze Cheng 已提交
986
  void *tptr = pCol->pData;
H
TD-166  
hzcheng 已提交
987
  // char *tptr = (char *)(pCol->pData);
H
TD-166  
hzcheng 已提交
988

H
TD-166  
hzcheng 已提交
989
  VarDataOffsetT offset = 0;
990
  for (int i = 0; i < nEle; ++i) {
H
TD-166  
hzcheng 已提交
991
    pCol->dataOff[i] = offset;
H
TD-166  
hzcheng 已提交
992
    offset += varDataTLen(tptr);
H
hzcheng 已提交
993
    tptr = POINTER_SHIFT(tptr, varDataTLen(tptr));
H
TD-166  
hzcheng 已提交
994
  }
C
Cary Xu 已提交
995
  return POINTER_SHIFT(tptr, varDataTLen(tptr));
H
TD-166  
hzcheng 已提交
996 997
}

L
Liu Jicong 已提交
998
SDataCols *tdNewDataCols(int maxCols, int maxRows) {
wafwerar's avatar
wafwerar 已提交
999
  SDataCols *pCols = (SDataCols *)taosMemoryCalloc(1, sizeof(SDataCols));
H
Haojun Liao 已提交
1000
  if (pCols == NULL) {
S
Shengliang Guan 已提交
1001
    uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCols), strerror(errno));
H
Haojun Liao 已提交
1002 1003
    return NULL;
  }
H
TD-34  
hzcheng 已提交
1004

H
Hongze Cheng 已提交
1005
  pCols->maxPoints = maxRows;
L
Liu Jicong 已提交
1006 1007 1008
  pCols->maxCols = maxCols;
  pCols->numOfRows = 0;
  pCols->numOfCols = 0;
1009
  pCols->bitmapMode = TSDB_BITMODE_DEFAULT;
H
Hongze Cheng 已提交
1010 1011

  if (maxCols > 0) {
wafwerar's avatar
wafwerar 已提交
1012
    pCols->cols = (SDataCol *)taosMemoryCalloc(maxCols, sizeof(SDataCol));
H
Hongze Cheng 已提交
1013 1014 1015 1016 1017 1018
    if (pCols->cols == NULL) {
      uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCol) * maxCols,
             strerror(errno));
      tdFreeDataCols(pCols);
      return NULL;
    }
1019
#if 0  // no need as calloc used
L
Liu Jicong 已提交
1020
    int i;
S
Shengliang Guan 已提交
1021
    for (i = 0; i < maxCols; i++) {
L
Liu Jicong 已提交
1022
      pCols->cols[i].spaceSize = 0;
L
Liu Jicong 已提交
1023
      pCols->cols[i].len = 0;
L
Liu Jicong 已提交
1024 1025 1026
      pCols->cols[i].pData = NULL;
      pCols->cols[i].dataOff = NULL;
    }
1027
#endif
H
Hongze Cheng 已提交
1028 1029
  }

H
TD-34  
hzcheng 已提交
1030 1031 1032
  return pCols;
}

H
Hongze Cheng 已提交
1033
int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) {
1034 1035
  int i;
  int oldMaxCols = pCols->maxCols;
L
Liu Jicong 已提交
1036
  if (schemaNCols(pSchema) > oldMaxCols) {
H
Hongze Cheng 已提交
1037
    pCols->maxCols = schemaNCols(pSchema);
wafwerar's avatar
wafwerar 已提交
1038
    void *ptr = (SDataCol *)taosMemoryRealloc(pCols->cols, sizeof(SDataCol) * pCols->maxCols);
L
Liu Jicong 已提交
1039 1040
    if (ptr == NULL) return -1;
    pCols->cols = ptr;
1041
    for (i = oldMaxCols; i < pCols->maxCols; ++i) {
1042 1043
      pCols->cols[i].pData = NULL;
      pCols->cols[i].dataOff = NULL;
1044
      pCols->cols[i].pBitmap = NULL;
L
Liu Jicong 已提交
1045
      pCols->cols[i].spaceSize = 0;
1046
    }
L
Liu Jicong 已提交
1047
  }
1048 1049 1050
#if 0
  tdResetDataCols(pCols); // redundant loop to reset len/blen to 0, already reset in following dataColInit(...)
#endif
H
Hongze Cheng 已提交
1051

1052
  pCols->numOfRows = 0;
1053
  pCols->bitmapMode = TSDB_BITMODE_DEFAULT;
H
TD-34  
hzcheng 已提交
1054 1055
  pCols->numOfCols = schemaNCols(pSchema);

1056
  for (i = 0; i < schemaNCols(pSchema); ++i) {
1057
    dataColInit(pCols->cols + i, schemaColAt(pSchema, i), pCols->maxPoints);
H
TD-34  
hzcheng 已提交
1058
  }
S
Shengliang Guan 已提交
1059

H
Hongze Cheng 已提交
1060
  return 0;
H
TD-34  
hzcheng 已提交
1061 1062
}

H
Hongze Cheng 已提交
1063
SDataCols *tdFreeDataCols(SDataCols *pCols) {
1064
  int i;
H
TD-34  
hzcheng 已提交
1065
  if (pCols) {
S
Shengliang Guan 已提交
1066
    if (pCols->cols) {
1067
      int maxCols = pCols->maxCols;
1068
      for (i = 0; i < maxCols; ++i) {
1069
        SDataCol *pCol = &pCols->cols[i];
wafwerar's avatar
wafwerar 已提交
1070
        taosMemoryFreeClear(pCol->pData);
1071
      }
wafwerar's avatar
wafwerar 已提交
1072
      taosMemoryFree(pCols->cols);
1073 1074
      pCols->cols = NULL;
    }
wafwerar's avatar
wafwerar 已提交
1075
    taosMemoryFree(pCols);
H
TD-34  
hzcheng 已提交
1076
  }
H
Hongze Cheng 已提交
1077
  return NULL;
H
TD-34  
hzcheng 已提交
1078 1079 1080
}

void tdResetDataCols(SDataCols *pCols) {
B
Bomin Zhang 已提交
1081 1082
  if (pCols != NULL) {
    pCols->numOfRows = 0;
C
Cary Xu 已提交
1083
    pCols->bitmapMode = 0;
1084
    for (int i = 0; i < pCols->maxCols; ++i) {
B
Bomin Zhang 已提交
1085 1086
      dataColReset(pCols->cols + i);
    }
H
TD-34  
hzcheng 已提交
1087 1088
  }
}
H
Hongze Cheng 已提交
1089

H
Hongze Cheng 已提交
1090
#endif