tdataformat.c 24.6 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

H
Hongze Cheng 已提交
22 23 24 25 26
struct SKVIdx {
  int32_t cid;
  int32_t offset;
};

H
Hongze Cheng 已提交
27 28
#define TSROW_IS_KV_ROW(r) ((r)->flags & TSROW_KV_ROW)

H
Hongze Cheng 已提交
29
// STSRow2
H
Hongze Cheng 已提交
30 31
int32_t tEncodeTSRow(SEncoder *pEncoder, const STSRow2 *pRow) {
  if (tEncodeI64(pEncoder, pRow->ts) < 0) return -1;
H
Hongze Cheng 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  if (tEncodeU8(pEncoder, pRow->flags) < 0) return -1;

  ASSERT(pRow->flags & 0xf != 0);

  switch (pRow->flags & 0xf) {
    case TSROW_HAS_NONE:
    case TSROW_HAS_NULL:
      ASSERT(TSROW_IS_KV_ROW(pRow) && pRow->nData == 0 && pRow->pData == NULL);
      return 0;
    case TSROW_HAS_VAL:
      ASSERT(!TSROW_IS_KV_ROW(pRow));
    default:
      ASSERT(pRow->nData && pRow->pData);
      if (TSROW_IS_KV_ROW(pRow)) {
        if (tEncodeI32v(pEncoder, pRow->ncols) < 0) return -1;
      } else {
        if (tEncodeI32v(pEncoder, pRow->sver) < 0) return -1;
      }
      if (tEncodeBinary(pEncoder, pRow->pData, pRow->nData)) return -1;
      break;
H
Hongze Cheng 已提交
52
  }
H
Hongze Cheng 已提交
53

H
Hongze Cheng 已提交
54 55 56 57 58
  return 0;
}

int32_t tDecodeTSRow(SDecoder *pDecoder, STSRow2 *pRow) {
  if (tDecodeI64(pDecoder, &pRow->ts) < 0) return -1;
H
Hongze Cheng 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
  if (tDecodeU8(pDecoder, &pRow->flags) < 0) return -1;

  ASSERT(pRow->flags & 0xf != 0);

  switch (pRow->flags & 0xf) {
    case TSROW_HAS_NONE:
    case TSROW_HAS_NULL:
      ASSERT(TSROW_IS_KV_ROW(pRow));
      pRow->nData = 0;
      pRow->pData = NULL;
      return 0;
    case TSROW_HAS_VAL:
      ASSERT(!TSROW_IS_KV_ROW(pRow));
    default:
      if (TSROW_IS_KV_ROW(pRow)) {
        if (tDecodeI32v(pDecoder, &pRow->ncols) < 0) return -1;
      } else {
        if (tDecodeI32v(pDecoder, &pRow->sver) < 0) return -1;
      }
      if (tDecodeBinary(pDecoder, &pRow->pData, &pRow->nData)) return -1;
      break;
H
Hongze Cheng 已提交
80
  }
H
Hongze Cheng 已提交
81

H
Hongze Cheng 已提交
82 83 84
  return 0;
}

H
Hongze Cheng 已提交
85 86 87 88 89 90 91 92 93 94 95 96
int32_t tTSRowGet(const STSRow2 *pRow, STSchema *pTSchema, int32_t cid, const uint8_t **ppData, uint32_t *nData,
                  int8_t *flags) {
  if (cid == 0) {
    *ppData = (uint8_t *)&pRow->ts;
    *nData = sizeof(TSKEY);
    *flags = 0;
  } else {
    uint32_t tflags = pRow->flags & 0xf;
    *ppData = NULL;
    *nData = 0;

    switch (tflags) {
H
Hongze Cheng 已提交
97
      case TSROW_HAS_NONE:
H
Hongze Cheng 已提交
98 99
        *flags = -1;
        break;
H
Hongze Cheng 已提交
100
      case TSROW_HAS_NULL:
H
Hongze Cheng 已提交
101 102
        *flags = 1;
        break;
H
Hongze Cheng 已提交
103
      case TSROW_HAS_VAL:
H
Hongze Cheng 已提交
104 105 106
        *flags = 0;
        // find the row
        break;
H
Hongze Cheng 已提交
107
      case TSROW_HAS_NULL | TSROW_HAS_NONE:
H
Hongze Cheng 已提交
108 109 110 111 112 113 114
        // read bit map (todo)
        if (0) {
          *flags = 1;
        } else {
          *flags = -1;
        }
        break;
H
Hongze Cheng 已提交
115 116
      case TSROW_HAS_VAL | TSROW_HAS_NONE:
      case TSROW_HAS_VAL | TSROW_HAS_NULL:
H
Hongze Cheng 已提交
117 118
        // read bitmap (todo)
        if (0) {
H
Hongze Cheng 已提交
119
          if (tflags & TSROW_HAS_NONE) {
H
Hongze Cheng 已提交
120 121 122 123 124 125 126 127
            *flags = -1;
          } else {
            *flags = 1;
          }
        } else {
          // get value (todo)
        }
        break;
H
Hongze Cheng 已提交
128
      case TSROW_HAS_VAL | TSROW_HAS_NULL | TSROW_HAS_NONE:
H
Hongze Cheng 已提交
129 130 131 132 133 134 135 136 137
        break;
      default:
        return -1;
    }
  }
  return 0;
}

// STSchema
H
Hongze Cheng 已提交
138 139 140 141 142 143 144
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 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
  (*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 已提交
170 171 172 173 174
  return 0;
}

void tTSchemaDestroy(STSchema *pTSchema) { taosMemoryFree(pTSchema); }

H
Hongze Cheng 已提交
175
// STSRowBuilder
H
Hongze Cheng 已提交
176
int32_t tTSRowBuilderInit(STSRowBuilder *pBuilder, int32_t sver, SSchema *pSchema, int32_t nCols) {
H
Hongze Cheng 已提交
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
  int32_t  kvBufLen;
  int32_t  tpBufLen;
  uint8_t *p;

  if (tTSchemaCreate(sver, pSchema, nCols, &pBuilder->pTSchema) < 0) return -1;

  kvBufLen = sizeof(SKVIdx) * nCols + pBuilder->pTSchema->flen + pBuilder->pTSchema->vlen;
  tpBufLen = pBuilder->pTSchema->flen + pBuilder->pTSchema->vlen;

  if (pBuilder->szKVBuf < kvBufLen) {
    p = taosMemoryRealloc(pBuilder->pKVBuf, kvBufLen);
    if (p == NULL) {
      terrno = TSDB_CODE_OUT_OF_MEMORY;
      return -1;
    }
    pBuilder->pKVBuf = p;
    pBuilder->szKVBuf = kvBufLen;
  }

  if (pBuilder->szTPBuf < tpBufLen) {
    p = taosMemoryRealloc(pBuilder->pTPBuf, tpBufLen);
    if (p == NULL) {
      terrno = TSDB_CODE_OUT_OF_MEMORY;
      return -1;
    }
    pBuilder->pTPBuf = p;
    pBuilder->szTPBuf = tpBufLen;
  }

  tTSRowBuilderReset(pBuilder);

H
Hongze Cheng 已提交
208 209 210
  return 0;
}

H
Hongze Cheng 已提交
211 212 213
void tTSRowBuilderClear(STSRowBuilder *pBuilder) {
  taosMemoryFree(pBuilder->pKVBuf);
  taosMemoryFree(pBuilder->pTPBuf);
H
Hongze Cheng 已提交
214 215
}

H
Hongze Cheng 已提交
216
void tTSRowBuilderReset(STSRowBuilder *pBuilder) {
H
Hongze Cheng 已提交
217 218 219
  for (int32_t iCol = pBuilder->pTSchema->numOfCols - 1; iCol >= 0; iCol--) {
    pBuilder->pTColumn = &pBuilder->pTSchema->columns[iCol];

H
Hongze Cheng 已提交
220
    pBuilder->pTColumn->flags &= 0xf;
H
Hongze Cheng 已提交
221 222
  }

H
Hongze Cheng 已提交
223 224 225 226
  pBuilder->nCols = 0;
  pBuilder->kvVLen = 0;
  pBuilder->tpVLen = 0;
  pBuilder->row.flags = 0;
H
Hongze Cheng 已提交
227 228 229
}

int32_t tTSRowBuilderPut(STSRowBuilder *pBuilder, int32_t cid, const uint8_t *pData, uint32_t nData) {
H
Hongze Cheng 已提交
230
  // search column (TODO: bsearch with interp)
H
Hongze Cheng 已提交
231
  if (pBuilder->pTColumn->colId < cid) {
H
Hongze Cheng 已提交
232
    int32_t iCol = (pBuilder->pTColumn - pBuilder->pTSchema->columns) / sizeof(STColumn) + 1;
H
Hongze Cheng 已提交
233 234 235 236
    for (; iCol < pBuilder->pTSchema->numOfCols; iCol++) {
      pBuilder->pTColumn = &pBuilder->pTSchema->columns[iCol];
      if (pBuilder->pTColumn->colId == cid) break;
    }
H
Hongze Cheng 已提交
237
  } else if (pBuilder->pTColumn->colId > cid) {
H
Hongze Cheng 已提交
238
    int32_t iCol = (pBuilder->pTColumn - pBuilder->pTSchema->columns) / sizeof(STColumn) - 1;
H
Hongze Cheng 已提交
239 240 241 242
    for (; iCol >= 0; iCol--) {
      pBuilder->pTColumn = &pBuilder->pTSchema->columns[iCol];
      if (pBuilder->pTColumn->colId == cid) break;
    }
H
Hongze Cheng 已提交
243 244
  }

H
Hongze Cheng 已提交
245
  // check
H
Hongze Cheng 已提交
246
  if (pBuilder->pTColumn->colId != cid || COL_IS_SET(pBuilder->pTColumn->flags)) {
H
Hongze Cheng 已提交
247 248 249 250
    return -1;
  }

  // set value
H
Hongze Cheng 已提交
251
  uint8_t *p;
H
Hongze Cheng 已提交
252 253 254
  if (cid == 0) {
    ASSERT(pData && nData == sizeof(TSKEY));
    pBuilder->row.ts = *(TSKEY *)pData;
H
Hongze Cheng 已提交
255 256

    pBuilder->pTColumn->flags |= COL_SET_VAL;
H
Hongze Cheng 已提交
257
  } else {
H
Hongze Cheng 已提交
258 259
    if (pData) {  // set val
      pBuilder->row.flags |= TSROW_HAS_VAL;
H
Hongze Cheng 已提交
260
      pBuilder->pTColumn->flags |= COL_SET_VAL;
H
Hongze Cheng 已提交
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

      // set tuple data
      p = pBuilder->pTPBuf + pBuilder->pTColumn->offset;
      if (IS_VAR_DATA_TYPE(pBuilder->pTColumn->type)) {
        *(int32_t *)p = pBuilder->tpVLen;

        // encode the variant-length data
        p = pBuilder->pTPBuf + pBuilder->pTSchema->flen + pBuilder->tpVLen;
        pBuilder->tpVLen += tPutBinary(p, pData, nData);
      } else {
        memcpy(p, pData, nData);
      }

      // set kv data
      p = pBuilder->pKVBuf + sizeof(SKVIdx) * pBuilder->nCols;
      ((SKVIdx *)p)->cid = cid;
      ((SKVIdx *)p)->offset = pBuilder->kvVLen;

H
Hongze Cheng 已提交
279
      p = pBuilder->pKVBuf + sizeof(SKVIdx) * (pBuilder->pTSchema->numOfCols - 1) + pBuilder->kvVLen;
H
Hongze Cheng 已提交
280 281 282 283 284 285
      if (IS_VAR_DATA_TYPE(pBuilder->pTColumn->type)) {
        pBuilder->kvVLen += tPutBinary(p, pData, nData);
      } else {
        memcpy(p, pData, nData);
        pBuilder->kvVLen += nData;
      }
H
Hongze Cheng 已提交
286 287
    } else {  // set NULL
      pBuilder->row.flags |= TSROW_HAS_NULL;
H
Hongze Cheng 已提交
288 289 290 291
      pBuilder->pTColumn->flags |= COL_SET_NULL;

      p = pBuilder->pKVBuf + sizeof(SKVIdx) * pBuilder->nCols;
      ((SKVIdx *)p)->cid = cid;
H
Hongze Cheng 已提交
292
      ((SKVIdx *)p)->offset = -1;  // for TSROW_KV_ROW, offset -1 means NULL
H
Hongze Cheng 已提交
293
    }
H
Hongze Cheng 已提交
294 295

    pBuilder->nCols++;
H
Hongze Cheng 已提交
296 297 298 299 300
  }

  return 0;
}

H
Hongze Cheng 已提交
301 302 303 304 305 306 307 308 309 310
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 已提交
311
int32_t tTSRowBuilderGetRow(STSRowBuilder *pBuilder, const STSRow2 **ppRow) {
H
Hongze Cheng 已提交
312 313 314 315
  int32_t  tpDataLen, kvDataLen;
  uint32_t flags;

  // error not set ts
H
Hongze Cheng 已提交
316
  if (!COL_IS_SET(pBuilder->pTSchema->columns->flags)) {
H
Hongze Cheng 已提交
317 318 319
    return -1;
  }

H
Hongze Cheng 已提交
320
  ASSERT(pBuilder->nCols < pBuilder->pTSchema->numOfCols);
H
Hongze Cheng 已提交
321
  if (pBuilder->nCols < pBuilder->pTSchema->numOfCols - 1) {
H
Hongze Cheng 已提交
322
    pBuilder->row.flags |= TSROW_HAS_NONE;
H
Hongze Cheng 已提交
323
  }
H
Hongze Cheng 已提交
324

H
Hongze Cheng 已提交
325 326 327 328 329 330
  ASSERT(pBuilder->row.flags & 0xf != 0);
  *(ppRow) = &pBuilder->row;
  switch (pBuilder->row.flags & 0xf) {
    case TSROW_HAS_NONE:
    case TSROW_HAS_NULL:
      pBuilder->row.flags |= TSROW_KV_ROW;
H
Hongze Cheng 已提交
331 332
      pBuilder->row.nData = 0;
      pBuilder->row.pData = NULL;
H
Hongze Cheng 已提交
333 334 335
      return 0;
    case TSROW_HAS_NULL | TSROW_HAS_NONE:
      tpDataLen = (pBuilder->pTSchema->numOfCols - 1) / 8;
H
Hongze Cheng 已提交
336
      break;
H
Hongze Cheng 已提交
337 338
    case TSROW_HAS_VAL:
      tpDataLen = pBuilder->pTSchema->flen + pBuilder->tpVLen;
H
Hongze Cheng 已提交
339
      break;
H
Hongze Cheng 已提交
340 341 342
    case TSROW_HAS_VAL | TSROW_HAS_NONE:
    case TSROW_HAS_VAL | TSROW_HAS_NULL:
      tpDataLen = pBuilder->pTSchema->flen + pBuilder->tpVLen + (pBuilder->pTSchema->numOfCols - 1) / 8;
H
Hongze Cheng 已提交
343
      break;
H
Hongze Cheng 已提交
344 345
    case TSROW_HAS_VAL | TSROW_HAS_NULL | TSROW_HAS_NONE:
      tpDataLen = pBuilder->pTSchema->flen + pBuilder->tpVLen + (pBuilder->pTSchema->numOfCols - 1) / 4;
H
Hongze Cheng 已提交
346 347
      break;
    default:
H
Hongze Cheng 已提交
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
      // decide chose tuple or kv
      kvDataLen = sizeof(SKVIdx) * pBuilder->nCols + pBuilder->kvVLen;
      break;
  }

  if (kvDataLen < tpDataLen) {
    pBuilder->row.flags |= TSROW_KV_ROW;
    pBuilder->row.ncols = pBuilder->nCols;

    pBuilder->row.nData = kvDataLen;
    pBuilder->row.pData = pBuilder->pKVBuf;
    qsort(pBuilder->pKVBuf, pBuilder->nCols, sizeof(SKVIdx), tSKVIdxCmprFn);
    if (pBuilder->nCols < pBuilder->pTSchema->numOfCols - 1) {
      memmove(pBuilder->pKVBuf + sizeof(SKVIdx) * pBuilder->nCols,
              pBuilder->pKVBuf + sizeof(SKVIdx) * (pBuilder->pTSchema->numOfCols - 1), pBuilder->kvVLen);
    }
  } else {
    pBuilder->row.sver = pBuilder->pTSchema->version;

    pBuilder->row.nData = tpDataLen;
H
Hongze Cheng 已提交
368 369 370 371 372
  }

  return 0;
}

H
Hongze Cheng 已提交
373
#if 1  // ====================
374
static void dataColSetNEleNull(SDataCol *pCol, int nEle);
H
Hongze Cheng 已提交
375
int         tdAllocMemForCol(SDataCol *pCol, int maxPoints) {
L
Liu Jicong 已提交
376
  int spaceNeeded = pCol->bytes * maxPoints;
S
Shengliang Guan 已提交
377
  if (IS_VAR_DATA_TYPE(pCol->type)) {
L
Liu Jicong 已提交
378
    spaceNeeded += sizeof(VarDataOffsetT) * maxPoints;
L
Liu Jicong 已提交
379
  }
C
Cary Xu 已提交
380
#ifdef TD_SUPPORT_BITMAP
C
Cary Xu 已提交
381 382 383 384
  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.
385 386
  // 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 已提交
387
#endif
C
Cary Xu 已提交
388

S
Shengliang Guan 已提交
389
  if (pCol->spaceSize < spaceNeeded) {
wafwerar's avatar
wafwerar 已提交
390
    void *ptr = taosMemoryRealloc(pCol->pData, spaceNeeded);
S
Shengliang Guan 已提交
391 392
    if (ptr == NULL) {
      uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)spaceNeeded, strerror(errno));
L
Liu Jicong 已提交
393
      return -1;
L
Liu Jicong 已提交
394 395 396
    } else {
      pCol->pData = ptr;
      pCol->spaceSize = spaceNeeded;
397 398
    }
  }
C
Cary Xu 已提交
399
#ifdef TD_SUPPORT_BITMAP
400

C
Cary Xu 已提交
401 402 403 404
  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 已提交
405
    pCol->pBitmap = POINTER_SHIFT(pCol->pData, pCol->bytes * maxPoints);
L
Liu Jicong 已提交
406
  }
C
Cary Xu 已提交
407 408 409 410
#else
  if (IS_VAR_DATA_TYPE(pCol->type)) {
    pCol->dataOff = POINTER_SHIFT(pCol->pData, pCol->bytes * maxPoints);
  }
C
Cary Xu 已提交
411
#endif
L
Liu Jicong 已提交
412
  return 0;
413 414
}

H
hzcheng 已提交
415 416 417
/**
 * Duplicate the schema and return a new object
 */
H
Hongze Cheng 已提交
418
STSchema *tdDupSchema(const STSchema *pSchema) {
S
Shengliang Guan 已提交
419
  int       tlen = sizeof(STSchema) + sizeof(STColumn) * schemaNCols(pSchema);
wafwerar's avatar
wafwerar 已提交
420
  STSchema *tSchema = (STSchema *)taosMemoryMalloc(tlen);
H
hzcheng 已提交
421 422
  if (tSchema == NULL) return NULL;

H
Hongze Cheng 已提交
423
  memcpy((void *)tSchema, (void *)pSchema, tlen);
H
hzcheng 已提交
424 425 426 427

  return tSchema;
}

H
TD-27  
hzcheng 已提交
428 429 430
/**
 * Encode a schema to dst, and return the next pointer
 */
H
TD-353  
Hongze Cheng 已提交
431 432 433 434
int tdEncodeSchema(void **buf, STSchema *pSchema) {
  int tlen = 0;
  tlen += taosEncodeFixedI32(buf, schemaVersion(pSchema));
  tlen += taosEncodeFixedI32(buf, schemaNCols(pSchema));
H
TD-166  
hzcheng 已提交
435

H
TD-27  
hzcheng 已提交
436 437
  for (int i = 0; i < schemaNCols(pSchema); i++) {
    STColumn *pCol = schemaColAt(pSchema, i);
H
TD-353  
Hongze Cheng 已提交
438
    tlen += taosEncodeFixedI8(buf, colType(pCol));
C
Cary Xu 已提交
439
    tlen += taosEncodeFixedI8(buf, colFlags(pCol));
H
TD-353  
Hongze Cheng 已提交
440
    tlen += taosEncodeFixedI16(buf, colColId(pCol));
441
    tlen += taosEncodeFixedI16(buf, colBytes(pCol));
H
TD-27  
hzcheng 已提交
442 443
  }

H
TD-353  
Hongze Cheng 已提交
444
  return tlen;
H
TD-27  
hzcheng 已提交
445 446 447 448 449
}

/**
 * Decode a schema from a binary.
 */
H
TD-353  
Hongze Cheng 已提交
450
void *tdDecodeSchema(void *buf, STSchema **pRSchema) {
S
Shengliang Guan 已提交
451 452
  int             version = 0;
  int             numOfCols = 0;
H
TD-353  
Hongze Cheng 已提交
453
  STSchemaBuilder schemaBuilder;
H
TD-27  
hzcheng 已提交
454

H
TD-353  
Hongze Cheng 已提交
455 456
  buf = taosDecodeFixedI32(buf, &version);
  buf = taosDecodeFixedI32(buf, &numOfCols);
H
TD-27  
hzcheng 已提交
457

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

H
TD-353  
Hongze Cheng 已提交
460
  for (int i = 0; i < numOfCols; i++) {
461
    col_type_t  type = 0;
C
Cary Xu 已提交
462
    int8_t      flags = 0;
463 464
    col_id_t    colId = 0;
    col_bytes_t bytes = 0;
H
TD-353  
Hongze Cheng 已提交
465
    buf = taosDecodeFixedI8(buf, &type);
C
Cary Xu 已提交
466
    buf = taosDecodeFixedI8(buf, &flags);
H
TD-353  
Hongze Cheng 已提交
467
    buf = taosDecodeFixedI16(buf, &colId);
468
    buf = taosDecodeFixedI32(buf, &bytes);
C
Cary Xu 已提交
469
    if (tdAddColToSchema(&schemaBuilder, type, flags, colId, bytes) < 0) {
H
Hongze Cheng 已提交
470 471 472
      tdDestroyTSchemaBuilder(&schemaBuilder);
      return NULL;
    }
H
TD-27  
hzcheng 已提交
473 474
  }

H
TD-353  
Hongze Cheng 已提交
475
  *pRSchema = tdGetSchemaFromBuilder(&schemaBuilder);
H
Hongze Cheng 已提交
476
  tdDestroyTSchemaBuilder(&schemaBuilder);
H
TD-353  
Hongze Cheng 已提交
477
  return buf;
H
Hongze Cheng 已提交
478 479
}

C
Cary Xu 已提交
480
int tdInitTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version) {
H
Hongze Cheng 已提交
481 482 483
  if (pBuilder == NULL) return -1;

  pBuilder->tCols = 256;
wafwerar's avatar
wafwerar 已提交
484
  pBuilder->columns = (STColumn *)taosMemoryMalloc(sizeof(STColumn) * pBuilder->tCols);
H
Hongze Cheng 已提交
485 486 487 488 489 490 491 492
  if (pBuilder->columns == NULL) return -1;

  tdResetTSchemaBuilder(pBuilder, version);
  return 0;
}

void tdDestroyTSchemaBuilder(STSchemaBuilder *pBuilder) {
  if (pBuilder) {
wafwerar's avatar
wafwerar 已提交
493
    taosMemoryFreeClear(pBuilder->columns);
H
Hongze Cheng 已提交
494 495 496
  }
}

C
Cary Xu 已提交
497
void tdResetTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version) {
H
Hongze Cheng 已提交
498 499 500
  pBuilder->nCols = 0;
  pBuilder->tlen = 0;
  pBuilder->flen = 0;
T
Tao Liu 已提交
501
  pBuilder->vlen = 0;
H
Hongze Cheng 已提交
502 503 504
  pBuilder->version = version;
}

C
Cary Xu 已提交
505
int32_t tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int8_t flags, col_id_t colId, col_bytes_t bytes) {
506
  if (!isValidDataType(type)) return -1;
H
Hongze Cheng 已提交
507 508 509

  if (pBuilder->nCols >= pBuilder->tCols) {
    pBuilder->tCols *= 2;
wafwerar's avatar
wafwerar 已提交
510
    STColumn *columns = (STColumn *)taosMemoryRealloc(pBuilder->columns, sizeof(STColumn) * pBuilder->tCols);
T
tickduan 已提交
511 512
    if (columns == NULL) return -1;
    pBuilder->columns = columns;
H
Hongze Cheng 已提交
513 514 515 516 517
  }

  STColumn *pCol = &(pBuilder->columns[pBuilder->nCols]);
  colSetType(pCol, type);
  colSetColId(pCol, colId);
C
Cary Xu 已提交
518
  colSetFlags(pCol, flags);
H
Hongze Cheng 已提交
519 520 521
  if (pBuilder->nCols == 0) {
    colSetOffset(pCol, 0);
  } else {
S
Shengliang Guan 已提交
522
    STColumn *pTCol = &(pBuilder->columns[pBuilder->nCols - 1]);
H
Hongze Cheng 已提交
523 524 525 526 527
    colSetOffset(pCol, pTCol->offset + TYPE_BYTES[pTCol->type]);
  }

  if (IS_VAR_DATA_TYPE(type)) {
    colSetBytes(pCol, bytes);
T
Tao Liu 已提交
528 529
    pBuilder->tlen += (TYPE_BYTES[type] + bytes);
    pBuilder->vlen += bytes - sizeof(VarDataLenT);
H
Hongze Cheng 已提交
530 531 532
  } else {
    colSetBytes(pCol, TYPE_BYTES[type]);
    pBuilder->tlen += TYPE_BYTES[type];
T
Tao Liu 已提交
533
    pBuilder->vlen += TYPE_BYTES[type];
H
Hongze Cheng 已提交
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
  }

  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 已提交
549
  STSchema *pSchema = (STSchema *)taosMemoryMalloc(tlen);
H
Hongze Cheng 已提交
550 551 552 553 554 555
  if (pSchema == NULL) return NULL;

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

C
Cary Xu 已提交
558
#ifdef TD_SUPPORT_BITMAP
C
Cary Xu 已提交
559
  schemaTLen(pSchema) += (int)TD_BITMAP_BYTES(schemaNCols(pSchema));
C
Cary Xu 已提交
560 561
#endif

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

H
TD-27  
hzcheng 已提交
564 565 566
  return pSchema;
}

567
void dataColInit(SDataCol *pDataCol, STColumn *pCol, int maxPoints) {
H
TD-166  
hzcheng 已提交
568 569 570
  pDataCol->type = colType(pCol);
  pDataCol->colId = colColId(pCol);
  pDataCol->bytes = colBytes(pCol);
S
Shengliang Guan 已提交
571
  pDataCol->offset = colOffset(pCol) + 0;  // TD_DATA_ROW_HEAD_SIZE;
H
TD-166  
hzcheng 已提交
572 573 574

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

L
Liu Jicong 已提交
576 577 578 579 580 581
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 已提交
582 583
}

H
TD-166  
hzcheng 已提交
584
bool isNEleNull(SDataCol *pCol, int nEle) {
S
Shengliang Guan 已提交
585
  if (isAllRowsNull(pCol)) return true;
586
  for (int i = 0; i < nEle; ++i) {
L
Liu Jicong 已提交
587
    if (!isNull(tdGetColDataOfRowUnsafe(pCol, i), pCol->type)) return false;
H
TD-166  
hzcheng 已提交
588
  }
H
Hongze Cheng 已提交
589
  return true;
H
TD-166  
hzcheng 已提交
590 591
}

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

H
Hongze Cheng 已提交
595
  void *tptr = pCol->pData;
H
TD-166  
hzcheng 已提交
596
  // char *tptr = (char *)(pCol->pData);
H
TD-166  
hzcheng 已提交
597

H
TD-166  
hzcheng 已提交
598
  VarDataOffsetT offset = 0;
599
  for (int i = 0; i < nEle; ++i) {
H
TD-166  
hzcheng 已提交
600
    pCol->dataOff[i] = offset;
H
TD-166  
hzcheng 已提交
601
    offset += varDataTLen(tptr);
H
hzcheng 已提交
602
    tptr = POINTER_SHIFT(tptr, varDataTLen(tptr));
H
TD-166  
hzcheng 已提交
603
  }
C
Cary Xu 已提交
604
  return POINTER_SHIFT(tptr, varDataTLen(tptr));
H
TD-166  
hzcheng 已提交
605 606
}

L
Liu Jicong 已提交
607
SDataCols *tdNewDataCols(int maxCols, int maxRows) {
wafwerar's avatar
wafwerar 已提交
608
  SDataCols *pCols = (SDataCols *)taosMemoryCalloc(1, sizeof(SDataCols));
H
Haojun Liao 已提交
609
  if (pCols == NULL) {
S
Shengliang Guan 已提交
610
    uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCols), strerror(errno));
H
Haojun Liao 已提交
611 612
    return NULL;
  }
H
TD-34  
hzcheng 已提交
613

H
Hongze Cheng 已提交
614
  pCols->maxPoints = maxRows;
L
Liu Jicong 已提交
615 616 617
  pCols->maxCols = maxCols;
  pCols->numOfRows = 0;
  pCols->numOfCols = 0;
C
Cary Xu 已提交
618
  // pCols->bitmapMode = 0; // calloc already set 0
H
Hongze Cheng 已提交
619 620

  if (maxCols > 0) {
wafwerar's avatar
wafwerar 已提交
621
    pCols->cols = (SDataCol *)taosMemoryCalloc(maxCols, sizeof(SDataCol));
H
Hongze Cheng 已提交
622 623 624 625 626 627
    if (pCols->cols == NULL) {
      uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCol) * maxCols,
             strerror(errno));
      tdFreeDataCols(pCols);
      return NULL;
    }
628
#if 0  // no need as calloc used
L
Liu Jicong 已提交
629
    int i;
S
Shengliang Guan 已提交
630
    for (i = 0; i < maxCols; i++) {
L
Liu Jicong 已提交
631
      pCols->cols[i].spaceSize = 0;
L
Liu Jicong 已提交
632
      pCols->cols[i].len = 0;
L
Liu Jicong 已提交
633 634 635
      pCols->cols[i].pData = NULL;
      pCols->cols[i].dataOff = NULL;
    }
636
#endif
H
Hongze Cheng 已提交
637 638
  }

H
TD-34  
hzcheng 已提交
639 640 641
  return pCols;
}

H
Hongze Cheng 已提交
642
int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) {
643 644
  int i;
  int oldMaxCols = pCols->maxCols;
L
Liu Jicong 已提交
645
  if (schemaNCols(pSchema) > oldMaxCols) {
H
Hongze Cheng 已提交
646
    pCols->maxCols = schemaNCols(pSchema);
wafwerar's avatar
wafwerar 已提交
647
    void *ptr = (SDataCol *)taosMemoryRealloc(pCols->cols, sizeof(SDataCol) * pCols->maxCols);
L
Liu Jicong 已提交
648 649
    if (ptr == NULL) return -1;
    pCols->cols = ptr;
650
    for (i = oldMaxCols; i < pCols->maxCols; ++i) {
651 652
      pCols->cols[i].pData = NULL;
      pCols->cols[i].dataOff = NULL;
653
      pCols->cols[i].pBitmap = NULL;
L
Liu Jicong 已提交
654
      pCols->cols[i].spaceSize = 0;
655
    }
L
Liu Jicong 已提交
656
  }
657 658 659
#if 0
  tdResetDataCols(pCols); // redundant loop to reset len/blen to 0, already reset in following dataColInit(...)
#endif
H
Hongze Cheng 已提交
660

661
  pCols->numOfRows = 0;
C
Cary Xu 已提交
662
  pCols->bitmapMode = 0;
H
TD-34  
hzcheng 已提交
663 664
  pCols->numOfCols = schemaNCols(pSchema);

665
  for (i = 0; i < schemaNCols(pSchema); ++i) {
666
    dataColInit(pCols->cols + i, schemaColAt(pSchema, i), pCols->maxPoints);
H
TD-34  
hzcheng 已提交
667
  }
S
Shengliang Guan 已提交
668

H
Hongze Cheng 已提交
669
  return 0;
H
TD-34  
hzcheng 已提交
670 671
}

H
Hongze Cheng 已提交
672
SDataCols *tdFreeDataCols(SDataCols *pCols) {
673
  int i;
H
TD-34  
hzcheng 已提交
674
  if (pCols) {
S
Shengliang Guan 已提交
675
    if (pCols->cols) {
676
      int maxCols = pCols->maxCols;
677
      for (i = 0; i < maxCols; ++i) {
678
        SDataCol *pCol = &pCols->cols[i];
wafwerar's avatar
wafwerar 已提交
679
        taosMemoryFreeClear(pCol->pData);
680
      }
wafwerar's avatar
wafwerar 已提交
681
      taosMemoryFree(pCols->cols);
682 683
      pCols->cols = NULL;
    }
wafwerar's avatar
wafwerar 已提交
684
    taosMemoryFree(pCols);
H
TD-34  
hzcheng 已提交
685
  }
H
Hongze Cheng 已提交
686
  return NULL;
H
TD-34  
hzcheng 已提交
687 688 689
}

void tdResetDataCols(SDataCols *pCols) {
B
Bomin Zhang 已提交
690 691
  if (pCols != NULL) {
    pCols->numOfRows = 0;
C
Cary Xu 已提交
692
    pCols->bitmapMode = 0;
693
    for (int i = 0; i < pCols->maxCols; ++i) {
B
Bomin Zhang 已提交
694 695
      dataColReset(pCols->cols + i);
    }
H
TD-34  
hzcheng 已提交
696 697
  }
}
H
Hongze Cheng 已提交
698

H
Hongze Cheng 已提交
699
SKVRow tdKVRowDup(SKVRow row) {
wafwerar's avatar
wafwerar 已提交
700
  SKVRow trow = taosMemoryMalloc(kvRowLen(row));
H
Hongze Cheng 已提交
701 702
  if (trow == NULL) return NULL;

H
Hongze Cheng 已提交
703
  kvRowCpy(trow, row);
H
Hongze Cheng 已提交
704 705 706
  return trow;
}

S
Shengliang Guan 已提交
707 708 709
static int compareColIdx(const void *a, const void *b) {
  const SColIdx *x = (const SColIdx *)a;
  const SColIdx *y = (const SColIdx *)b;
B
Bomin Zhang 已提交
710 711 712 713 714 715 716 717 718
  if (x->colId > y->colId) {
    return 1;
  }
  if (x->colId < y->colId) {
    return -1;
  }
  return 0;
}

S
Shengliang Guan 已提交
719
void tdSortKVRowByColIdx(SKVRow row) { qsort(kvRowColIdx(row), kvRowNCols(row), sizeof(SColIdx), compareColIdx); }
B
Bomin Zhang 已提交
720

H
TD-90  
Hongze Cheng 已提交
721 722 723 724
int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value) {
  SColIdx *pColIdx = NULL;
  SKVRow   row = *orow;
  SKVRow   nrow = NULL;
S
Shengliang Guan 已提交
725
  void    *ptr = taosbsearch(&colId, kvRowColIdx(row), kvRowNCols(row), sizeof(SColIdx), comparTagId, TD_GE);
H
TD-90  
Hongze Cheng 已提交
726

727
  if (ptr == NULL || ((SColIdx *)ptr)->colId > colId) {  // need to add a column value to the row
C
Cary Xu 已提交
728
    int diff = IS_VAR_DATA_TYPE(type) ? varDataTLen(value) : TYPE_BYTES[type];
729 730 731 732
    int nRowLen = kvRowLen(row) + sizeof(SColIdx) + diff;
    int oRowCols = kvRowNCols(row);

    ASSERT(diff > 0);
wafwerar's avatar
wafwerar 已提交
733
    nrow = taosMemoryMalloc(nRowLen);
H
TD-90  
Hongze Cheng 已提交
734 735
    if (nrow == NULL) return -1;

736 737
    kvRowSetLen(nrow, nRowLen);
    kvRowSetNCols(nrow, oRowCols + 1);
H
TD-90  
Hongze Cheng 已提交
738

739 740
    memcpy(kvRowColIdx(nrow), kvRowColIdx(row), sizeof(SColIdx) * oRowCols);
    memcpy(kvRowValues(nrow), kvRowValues(row), kvRowValLen(row));
H
TD-90  
Hongze Cheng 已提交
741

742 743 744
    pColIdx = kvRowColIdxAt(nrow, oRowCols);
    pColIdx->colId = colId;
    pColIdx->offset = kvRowValLen(row);
H
TD-90  
Hongze Cheng 已提交
745

746
    memcpy(kvRowColVal(nrow, pColIdx), value, diff);  // copy new value
H
TD-90  
Hongze Cheng 已提交
747

748
    tdSortKVRowByColIdx(nrow);
H
TD-90  
Hongze Cheng 已提交
749 750

    *orow = nrow;
wafwerar's avatar
wafwerar 已提交
751
    taosMemoryFree(row);
H
TD-90  
Hongze Cheng 已提交
752 753 754 755 756
  } else {
    ASSERT(((SColIdx *)ptr)->colId == colId);
    if (IS_VAR_DATA_TYPE(type)) {
      void *pOldVal = kvRowColVal(row, (SColIdx *)ptr);

S
Shengliang Guan 已提交
757
      if (varDataTLen(value) == varDataTLen(pOldVal)) {  // just update the column value in place
H
TD-90  
Hongze Cheng 已提交
758
        memcpy(pOldVal, value, varDataTLen(value));
759 760
      } else {  // need to reallocate the memory
        int16_t nlen = kvRowLen(row) + (varDataTLen(value) - varDataTLen(pOldVal));
H
TD-90  
Hongze Cheng 已提交
761
        ASSERT(nlen > 0);
wafwerar's avatar
wafwerar 已提交
762
        nrow = taosMemoryMalloc(nlen);
H
TD-90  
Hongze Cheng 已提交
763
        if (nrow == NULL) return -1;
H
TD-90  
Hongze Cheng 已提交
764 765 766 767

        kvRowSetLen(nrow, nlen);
        kvRowSetNCols(nrow, kvRowNCols(row));

768 769 770 771 772 773 774 775
        int zsize = sizeof(SColIdx) * kvRowNCols(row) + ((SColIdx *)ptr)->offset;
        memcpy(kvRowColIdx(nrow), kvRowColIdx(row), zsize);
        memcpy(kvRowColVal(nrow, ((SColIdx *)ptr)), value, varDataTLen(value));
        // Copy left value part
        int lsize = kvRowLen(row) - TD_KV_ROW_HEAD_SIZE - zsize - varDataTLen(pOldVal);
        if (lsize > 0) {
          memcpy(POINTER_SHIFT(nrow, TD_KV_ROW_HEAD_SIZE + zsize + varDataTLen(value)),
                 POINTER_SHIFT(row, TD_KV_ROW_HEAD_SIZE + zsize + varDataTLen(pOldVal)), lsize);
H
TD-90  
Hongze Cheng 已提交
776 777
        }

778 779 780 781 782
        for (int i = 0; i < kvRowNCols(nrow); i++) {
          pColIdx = kvRowColIdxAt(nrow, i);

          if (pColIdx->offset > ((SColIdx *)ptr)->offset) {
            pColIdx->offset = pColIdx->offset - varDataTLen(pOldVal) + varDataTLen(value);
H
TD-90  
Hongze Cheng 已提交
783 784 785 786
          }
        }

        *orow = nrow;
wafwerar's avatar
wafwerar 已提交
787
        taosMemoryFree(row);
H
TD-90  
Hongze Cheng 已提交
788 789 790 791 792 793 794
      }
    } else {
      memcpy(kvRowColVal(row, (SColIdx *)ptr), value, TYPE_BYTES[type]);
    }
  }

  return 0;
H
Hongze Cheng 已提交
795 796
}

H
TD-353  
Hongze Cheng 已提交
797
int tdEncodeKVRow(void **buf, SKVRow row) {
H
Hongze Cheng 已提交
798
  // May change the encode purpose
H
TD-353  
Hongze Cheng 已提交
799 800 801 802 803 804
  if (buf != NULL) {
    kvRowCpy(*buf, row);
    *buf = POINTER_SHIFT(*buf, kvRowLen(row));
  }

  return kvRowLen(row);
H
Hongze Cheng 已提交
805 806
}

H
Hongze Cheng 已提交
807 808
void *tdDecodeKVRow(void *buf, SKVRow *row) {
  *row = tdKVRowDup(buf);
H
TD-353  
Hongze Cheng 已提交
809
  if (*row == NULL) return NULL;
H
Hongze Cheng 已提交
810
  return POINTER_SHIFT(buf, kvRowLen(*row));
H
Hongze Cheng 已提交
811 812
}

H
Hongze Cheng 已提交
813
int tdInitKVRowBuilder(SKVRowBuilder *pBuilder) {
H
Hongze Cheng 已提交
814 815
  pBuilder->tCols = 128;
  pBuilder->nCols = 0;
wafwerar's avatar
wafwerar 已提交
816
  pBuilder->pColIdx = (SColIdx *)taosMemoryMalloc(sizeof(SColIdx) * pBuilder->tCols);
H
Hongze Cheng 已提交
817 818 819
  if (pBuilder->pColIdx == NULL) return -1;
  pBuilder->alloc = 1024;
  pBuilder->size = 0;
wafwerar's avatar
wafwerar 已提交
820
  pBuilder->buf = taosMemoryMalloc(pBuilder->alloc);
H
Hongze Cheng 已提交
821
  if (pBuilder->buf == NULL) {
wafwerar's avatar
wafwerar 已提交
822
    taosMemoryFree(pBuilder->pColIdx);
H
Hongze Cheng 已提交
823 824 825 826 827
    return -1;
  }
  return 0;
}

H
Hongze Cheng 已提交
828
void tdDestroyKVRowBuilder(SKVRowBuilder *pBuilder) {
wafwerar's avatar
wafwerar 已提交
829 830
  taosMemoryFreeClear(pBuilder->pColIdx);
  taosMemoryFreeClear(pBuilder->buf);
H
Hongze Cheng 已提交
831 832
}

H
Hongze Cheng 已提交
833
void tdResetKVRowBuilder(SKVRowBuilder *pBuilder) {
H
Hongze Cheng 已提交
834 835 836 837
  pBuilder->nCols = 0;
  pBuilder->size = 0;
}

H
Hongze Cheng 已提交
838
SKVRow tdGetKVRowFromBuilder(SKVRowBuilder *pBuilder) {
C
Cary Xu 已提交
839
  int tlen = sizeof(SColIdx) * pBuilder->nCols + pBuilder->size;
H
Hongze Cheng 已提交
840 841
  if (tlen == 0) return NULL;

H
Hongze Cheng 已提交
842 843
  tlen += TD_KV_ROW_HEAD_SIZE;

wafwerar's avatar
wafwerar 已提交
844
  SKVRow row = taosMemoryMalloc(tlen);
H
Hongze Cheng 已提交
845 846
  if (row == NULL) return NULL;

H
Hongze Cheng 已提交
847
  kvRowSetNCols(row, pBuilder->nCols);
H
Hongze Cheng 已提交
848
  kvRowSetLen(row, tlen);
H
Hongze Cheng 已提交
849

H
Hongze Cheng 已提交
850 851
  memcpy(kvRowColIdx(row), pBuilder->pColIdx, sizeof(SColIdx) * pBuilder->nCols);
  memcpy(kvRowValues(row), pBuilder->buf, pBuilder->size);
H
Hongze Cheng 已提交
852 853

  return row;
854
}
H
Hongze Cheng 已提交
855
#endif