tvariant.c 29.5 KB
Newer Older
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/>.
 */
15
#include "os.h"
16

H
hjxilinx 已提交
17 18
#include "taos.h"
#include "taosdef.h"
19
#include "thash.h"
20
#include "ttime.h"
21
#include "ttokendef.h"
H
Haojun Liao 已提交
22
#include "ttypes.h"
23 24
#include "tutil.h"
#include "tvariant.h"
25

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#define SET_EXT_INFO(converted, res, minv, maxv, exti)              \
  do {                                                              \
    if (converted == NULL || exti == NULL || *converted == false) { \
      break;                                                        \
    }                                                               \
    if ((res) < (minv)) {                                           \
      *exti = -1;                                                   \
      break;                                                        \
    }                                                               \
    if ((res) > (maxv)) {                                           \
      *exti = 1;                                                    \
      break;                                                        \
    }                                                               \
    assert(0);                                                      \
  } while (0)
41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
int32_t toInteger(const char* z, int32_t n, int32_t base, int64_t* value, bool* isSigned) {
  errno = 0;
  char* endPtr = NULL;

  int32_t index = 0;

  bool specifiedSign = (z[0] == '+' || z[0] == '-');
  if (specifiedSign) {
    *isSigned = true;
    index = 1;
  }

  uint64_t val = strtoull(&z[index], &endPtr, base);
  if (errno == ERANGE || errno == EINVAL) {
    errno = 0;
    return -1;
  }

  if (specifiedSign && val > INT64_MAX) {
    return -1;
  }

  if (endPtr - &z[index] != n - index) {
    return -1;
  }

  *isSigned = specifiedSign || (val <= INT64_MAX);
  if (*isSigned) {
    *value = (z[0] == '-')? -val:val;
  } else {
    *(uint64_t*) value = val;
  }

  return 0;
}

H
Haojun Liao 已提交
78 79
void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type) {
  int32_t ret = 0;
H
Haojun Liao 已提交
80
  memset(pVar, 0, sizeof(SVariant));
81

H
Haojun Liao 已提交
82
  switch (type) {
83
    case TSDB_DATA_TYPE_BOOL: {
H
Haojun Liao 已提交
84
      if (strncasecmp(z, "true", 4) == 0) {
85
        pVar->i = TSDB_TRUE;
H
Haojun Liao 已提交
86
      } else if (strncasecmp(z, "false", 5) == 0) {
87
        pVar->i = TSDB_FALSE;
88 89
      } else {
        return;
90 91 92
      }
      break;
    }
93

94 95 96
    case TSDB_DATA_TYPE_TINYINT:
    case TSDB_DATA_TYPE_SMALLINT:
    case TSDB_DATA_TYPE_BIGINT:
97
    case TSDB_DATA_TYPE_INT:{
98 99 100 101 102 103 104 105 106 107 108
      bool sign = true;

      int32_t base = 10;
      if (type == TK_HEX) {
        base = 16;
      } else if (type == TK_OCT) {
        base = 8;
      } else if (type == TK_BIN) {
        base = 2;
      }

109
      ret = toInteger(z, n, base, &pVar->i, &sign);
110 111 112 113
      if (ret != 0) {
        pVar->nType = -1;   // -1 means error type
        return;
      }
114

115
      pVar->nType = (sign)? TSDB_DATA_TYPE_BIGINT:TSDB_DATA_TYPE_UBIGINT;
116
      break;
117
    }
118
    case TSDB_DATA_TYPE_DOUBLE:
119
    case TSDB_DATA_TYPE_FLOAT: {
H
Haojun Liao 已提交
120
      pVar->d = strtod(z, NULL);
121
      break;
122
    }
123
    case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
124 125
      pVar->pz = strndup(z, n);
      pVar->nLen = strRmquote(pVar->pz, n);
126 127
      break;
    }
128
    case TSDB_DATA_TYPE_TIMESTAMP: {
129
      assert(0);
130
      pVar->i = taosGetTimestamp(TSDB_TIME_PRECISION_NANO);                           
131 132
      break;                             
    }                            
133 134 135 136 137 138 139 140
    
    default: {  // nType == 0 means the null value
      type = TSDB_DATA_TYPE_NULL;
    }
  }
  
  pVar->nType = type;
}
H
Haojun Liao 已提交
141

142
/**
H
Haojun Liao 已提交
143
 * create SVariant from binary string, not ascii data
144 145 146 147 148
 * @param pVar
 * @param pz
 * @param len
 * @param type
 */
H
Haojun Liao 已提交
149
void taosVariantCreateFromBinary(SVariant *pVar, const char *pz, size_t len, uint32_t type) {
150 151 152
  switch (type) {
    case TSDB_DATA_TYPE_BOOL:
    case TSDB_DATA_TYPE_TINYINT: {
153
      pVar->nLen = tDataTypes[type].bytes;
154
      pVar->i = GET_INT8_VAL(pz);
155 156 157
      break;
    }
    case TSDB_DATA_TYPE_UTINYINT: {
158
      pVar->nLen = tDataTypes[type].bytes;
159
      pVar->u = GET_UINT8_VAL(pz);
160 161 162
      break;
    }
    case TSDB_DATA_TYPE_SMALLINT: {
163
      pVar->nLen = tDataTypes[type].bytes;
164
      pVar->i = GET_INT16_VAL(pz);
165 166 167
      break;
    }
    case TSDB_DATA_TYPE_USMALLINT: {
168
      pVar->nLen = tDataTypes[type].bytes;
169
      pVar->u = GET_UINT16_VAL(pz);
170 171 172
      break;
    }
    case TSDB_DATA_TYPE_INT: {
173
      pVar->nLen = tDataTypes[type].bytes;
174
      pVar->i = GET_INT32_VAL(pz);
175 176 177
      break;
    }
    case TSDB_DATA_TYPE_UINT: {
178
      pVar->nLen = tDataTypes[type].bytes;
179
      pVar->u = GET_UINT32_VAL(pz);
180 181 182 183
      break;
    }
    case TSDB_DATA_TYPE_BIGINT:
    case TSDB_DATA_TYPE_TIMESTAMP: {
184
      pVar->nLen = tDataTypes[type].bytes;
185
      pVar->i = GET_INT64_VAL(pz);
186 187 188
      break;
    }
    case TSDB_DATA_TYPE_UBIGINT: {
189
      pVar->nLen = tDataTypes[type].bytes;
190
      pVar->u = GET_UINT64_VAL(pz);
191 192 193
      break;
    }
    case TSDB_DATA_TYPE_DOUBLE: {
194
      pVar->nLen = tDataTypes[type].bytes;
H
Haojun Liao 已提交
195
      pVar->d = GET_DOUBLE_VAL(pz);
196 197 198
      break;
    }
    case TSDB_DATA_TYPE_FLOAT: {
199
      pVar->nLen = tDataTypes[type].bytes;
H
Haojun Liao 已提交
200
      pVar->d = GET_FLOAT_VAL(pz);
201 202 203
      break;
    }
    case TSDB_DATA_TYPE_NCHAR: { // here we get the nchar length from raw binary bits length
204
      size_t lenInwchar = len / TSDB_NCHAR_SIZE;
205

206
      pVar->wpz = calloc(1, (lenInwchar + 1) * TSDB_NCHAR_SIZE);
207
      memcpy(pVar->wpz, pz, lenInwchar * TSDB_NCHAR_SIZE);
208
      pVar->nLen = (int32_t)len;
209 210 211
      
      break;
    }
212
    case TSDB_DATA_TYPE_BINARY: {  // todo refactor, extract a method
H
Haojun Liao 已提交
213
      pVar->pz = calloc(len + 1, sizeof(char));
214
      memcpy(pVar->pz, pz, len);
215
      pVar->nLen = (int32_t)len;
216 217 218 219
      break;
    }
    
    default:
220
      pVar->i = GET_INT32_VAL(pz);
221
      pVar->nLen = tDataTypes[TSDB_DATA_TYPE_INT].bytes;
222 223 224 225 226
  }
  
  pVar->nType = type;
}

H
Haojun Liao 已提交
227
void taosVariantDestroy(SVariant *pVar) {
228 229 230
  if (pVar == NULL) return;
  
  if (pVar->nType == TSDB_DATA_TYPE_BINARY || pVar->nType == TSDB_DATA_TYPE_NCHAR) {
S
TD-1848  
Shengliang Guan 已提交
231
    tfree(pVar->pz);
232 233
    pVar->nLen = 0;
  }
weixin_48148422's avatar
weixin_48148422 已提交
234 235

  // NOTE: this is only for string array
W
wpan 已提交
236
  if (pVar->nType == TSDB_DATA_TYPE_POINTER_ARRAY) {
weixin_48148422's avatar
weixin_48148422 已提交
237 238 239 240 241 242 243
    size_t num = taosArrayGetSize(pVar->arr);
    for(size_t i = 0; i < num; i++) {
      void* p = taosArrayGetP(pVar->arr, i);
      free(p);
    }
    taosArrayDestroy(pVar->arr);
    pVar->arr = NULL;
W
wpan 已提交
244 245 246
  } else if (pVar->nType == TSDB_DATA_TYPE_VALUE_ARRAY) {
    taosArrayDestroy(pVar->arr);
    pVar->arr = NULL;
weixin_48148422's avatar
weixin_48148422 已提交
247
  }
248 249
}

H
Haojun Liao 已提交
250
bool taosVariantIsValid(SVariant *pVar) {
251 252 253 254
  assert(pVar != NULL);
  return isValidDataType(pVar->nType);
}

H
Haojun Liao 已提交
255
void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) {
256 257
  if (pSrc == NULL || pDst == NULL) return;
  
H
Haojun Liao 已提交
258
  pDst->nType = pSrc->nType;
H
Haojun Liao 已提交
259
  if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
260 261
    int32_t len = pSrc->nLen + TSDB_NCHAR_SIZE;
    char* p = realloc(pDst->pz, len);
H
Haojun Liao 已提交
262 263
    assert(p);

H
Haojun Liao 已提交
264
    memset(p, 0, len);
H
Haojun Liao 已提交
265 266
    pDst->pz = p;

H
Haojun Liao 已提交
267 268
    memcpy(pDst->pz, pSrc->pz, pSrc->nLen);
    pDst->nLen = pSrc->nLen;
H
Haojun Liao 已提交
269 270 271 272
    return;

  }

273
  if (IS_NUMERIC_TYPE(pSrc->nType) || (pSrc->nType == TSDB_DATA_TYPE_BOOL)) {
274
    pDst->i = pSrc->i;
W
wpan 已提交
275
  } else if (pSrc->nType == TSDB_DATA_TYPE_POINTER_ARRAY) {  // this is only for string array
weixin_48148422's avatar
weixin_48148422 已提交
276 277 278 279 280 281 282
    size_t num = taosArrayGetSize(pSrc->arr);
    pDst->arr = taosArrayInit(num, sizeof(char*));
    for(size_t i = 0; i < num; i++) {
      char* p = (char*)taosArrayGetP(pSrc->arr, i);
      char* n = strdup(p);
      taosArrayPush(pDst->arr, &n);
    }
W
wpan 已提交
283 284 285 286 287 288 289 290 291
  } else if (pSrc->nType == TSDB_DATA_TYPE_VALUE_ARRAY) {
      size_t num = taosArrayGetSize(pSrc->arr);
      pDst->arr = taosArrayInit(num, sizeof(int64_t));
      pDst->nLen = pSrc->nLen;
      assert(pSrc->nLen == num);
      for(size_t i = 0; i < num; i++) {
        int64_t *p = taosArrayGet(pSrc->arr, i);
        taosArrayPush(pDst->arr, p);
      }
292
  }
H
Haojun Liao 已提交
293

W
wpan 已提交
294
  if (pDst->nType != TSDB_DATA_TYPE_POINTER_ARRAY && pDst->nType != TSDB_DATA_TYPE_VALUE_ARRAY) {
H
Haojun Liao 已提交
295
    pDst->nLen = tDataTypes[pDst->nType].bytes;
H
Haojun Liao 已提交
296
  }
297 298
}

H
Haojun Liao 已提交
299
int32_t taosVariantCompare(const SVariant* p1, const SVariant* p2) {
H
Haojun Liao 已提交
300 301 302 303 304 305 306 307 308 309 310
  if (p1->nType == TSDB_DATA_TYPE_NULL && p2->nType == TSDB_DATA_TYPE_NULL) {
    return 0;
  }

  if (p1->nType == TSDB_DATA_TYPE_NULL) {
    return -1;
  }

  if (p2->nType == TSDB_DATA_TYPE_NULL) {
    return 1;
  }
311

312 313 314 315 316 317 318
  if (p1->nType == TSDB_DATA_TYPE_BINARY || p1->nType == TSDB_DATA_TYPE_NCHAR) {
    if (p1->nLen == p2->nLen) {
      return memcmp(p1->pz, p2->pz, p1->nLen);
    } else {
      return p1->nLen > p2->nLen? 1:-1;
    }
  } else if (p1->nType == TSDB_DATA_TYPE_FLOAT || p1->nType == TSDB_DATA_TYPE_DOUBLE) {
H
Haojun Liao 已提交
319
    if (p1->d == p2->d) {
320 321
      return 0;
    } else {
H
Haojun Liao 已提交
322
      return p1->d > p2->d? 1:-1;
323 324
    }
  } else if (IS_UNSIGNED_NUMERIC_TYPE(p1->nType)) {
325
    if (p1->u == p2->u) {
326 327
      return 0;
    } else {
328
      return p1->u > p2->u? 1:-1;
329 330
    }
  } else {
331
    if (p1->i == p2->i) {
332 333
      return 0;
    } else {
334
      return p1->i > p2->i? 1:-1;
335
    }
336 337 338
  }
}

H
Haojun Liao 已提交
339
int32_t taosVariantToString(SVariant *pVar, char *dst) {
340 341 342 343 344 345 346 347 348 349 350
  if (pVar == NULL || dst == NULL) return 0;
  
  switch (pVar->nType) {
    case TSDB_DATA_TYPE_BINARY: {
      int32_t len = sprintf(dst, "\'%s\'", pVar->pz);
      assert(len <= pVar->nLen + sizeof("\'") * 2);  // two more chars
      return len;
    }
    
    case TSDB_DATA_TYPE_NCHAR: {
      dst[0] = '\'';
H
[TD-92]  
Hui Li 已提交
351
      taosUcs4ToMbs(pVar->wpz, (twcslen(pVar->wpz) + 1) * TSDB_NCHAR_SIZE, dst + 1);
352
      int32_t len = (int32_t)strlen(dst);
353 354 355 356 357 358 359 360 361
      dst[len] = '\'';
      dst[len + 1] = 0;
      return len + 1;
    }
    
    case TSDB_DATA_TYPE_BOOL:
    case TSDB_DATA_TYPE_TINYINT:
    case TSDB_DATA_TYPE_SMALLINT:
    case TSDB_DATA_TYPE_INT:
362 363 364
    case TSDB_DATA_TYPE_UTINYINT:
    case TSDB_DATA_TYPE_USMALLINT:
    case TSDB_DATA_TYPE_UINT:
365
      return sprintf(dst, "%d", (int32_t)pVar->i);
366 367
    
    case TSDB_DATA_TYPE_BIGINT:
368
      return sprintf(dst, "%" PRId64, pVar->i);
369
    case TSDB_DATA_TYPE_UBIGINT:
370
      return sprintf(dst, "%" PRIu64, pVar->u);
371 372
    case TSDB_DATA_TYPE_FLOAT:
    case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
373
      return sprintf(dst, "%.9lf", pVar->d);
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
    
    default:
      return 0;
  }
}

static FORCE_INLINE int32_t convertToBoolImpl(char *pStr, int32_t len) {
  if ((strncasecmp(pStr, "true", len) == 0) && (len == 4)) {
    return TSDB_TRUE;
  } else if ((strncasecmp(pStr, "false", len) == 0) && (len == 5)) {
    return TSDB_FALSE;
  } else if (strcasecmp(pStr, TSDB_DATA_NULL_STR_L) == 0) {
    return TSDB_DATA_BOOL_NULL;
  } else {
    return -1;
  }
}

static FORCE_INLINE int32_t wcsconvertToBoolImpl(wchar_t *pstr, int32_t len) {
  if ((wcsncasecmp(pstr, L"true", len) == 0) && (len == 4)) {
    return TSDB_TRUE;
  } else if (wcsncasecmp(pstr, L"false", len) == 0 && (len == 5)) {
    return TSDB_FALSE;
397 398
  } else if (memcmp(pstr, L"null", wcslen(L"null")) == 0) {
    return TSDB_DATA_BOOL_NULL;
399 400 401 402 403
  } else {
    return -1;
  }
}

H
Haojun Liao 已提交
404
static int32_t toBinary(SVariant *pVariant, char **pDest, int32_t *pDestSize) {
405
  const int32_t INITIAL_ALLOC_SIZE = 40;
406
  char *        pBuf = NULL;
407

H
Haojun Liao 已提交
408
  // it is a in-place convert type for SVariant, local buffer is needed
409 410 411 412 413 414 415
  if (*pDest == pVariant->pz) {
    pBuf = calloc(1, INITIAL_ALLOC_SIZE);
  }
  
  if (pVariant->nType == TSDB_DATA_TYPE_NCHAR) {
    size_t newSize = pVariant->nLen * TSDB_NCHAR_SIZE;
    if (pBuf != NULL) {
dengyihao's avatar
dengyihao 已提交
416
      if (newSize >= INITIAL_ALLOC_SIZE) {
417 418 419
        pBuf = realloc(pBuf, newSize + 1);
      }
      
420
      taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, pBuf);
421 422 423
      free(pVariant->wpz);
      pBuf[newSize] = 0;
    } else {
424
      taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, *pDest);
425 426 427
    }
    
  } else {
428
    if (IS_SIGNED_NUMERIC_TYPE(pVariant->nType)) {
429
      sprintf(pBuf == NULL ? *pDest : pBuf, "%" PRId64, pVariant->i);
430
    } else if (pVariant->nType == TSDB_DATA_TYPE_DOUBLE || pVariant->nType == TSDB_DATA_TYPE_FLOAT) {
H
Haojun Liao 已提交
431
      sprintf(pBuf == NULL ? *pDest : pBuf, "%lf", pVariant->d);
432
    } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL) {
433
      sprintf(pBuf == NULL ? *pDest : pBuf, "%s", (pVariant->i == TSDB_TRUE) ? "TRUE" : "FALSE");
434 435 436 437 438 439 440 441 442
    } else if (pVariant->nType == 0) {  // null data
      setNull(pBuf == NULL ? *pDest : pBuf, TSDB_DATA_TYPE_BINARY, 0);
    }
  }
  
  if (pBuf != NULL) {
    *pDest = pBuf;
  }
  
443
  *pDestSize = (int32_t)strlen(*pDest);
444 445 446
  return 0;
}

H
Haojun Liao 已提交
447
static int32_t toNchar(SVariant *pVariant, char **pDest, int32_t *pDestSize) {
448 449 450 451
  char tmpBuf[40] = {0};
  
  char *  pDst = tmpBuf;
  int32_t nLen = 0;
452 453 454

  // convert the number to string, than convert it to wchar string.
  if (IS_SIGNED_NUMERIC_TYPE(pVariant->nType)) {
455
    nLen = sprintf(pDst, "%" PRId64, pVariant->i);
456
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
457
    nLen = sprintf(pDst, "%"PRIu64, pVariant->u);
458
  } else if (pVariant->nType == TSDB_DATA_TYPE_DOUBLE || pVariant->nType == TSDB_DATA_TYPE_FLOAT) {
H
Haojun Liao 已提交
459
    nLen = sprintf(pDst, "%lf", pVariant->d);
460 461 462 463
  } else if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
    pDst = pVariant->pz;
    nLen = pVariant->nLen;
  } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL) {
464
    nLen = sprintf(pDst, "%s", (pVariant->i == TSDB_TRUE) ? "TRUE" : "FALSE");
465 466 467 468
  }
  
  if (*pDest == pVariant->pz) {
    wchar_t *pWStr = calloc(1, (nLen + 1) * TSDB_NCHAR_SIZE);
469 470
    bool ret = taosMbsToUcs4(pDst, nLen, (char *)pWStr, (nLen + 1) * TSDB_NCHAR_SIZE, NULL);
    if (!ret) {
H
Haojun Liao 已提交
471
      tfree(pWStr);
472 473 474
      return -1;
    }

475 476 477 478 479 480
    // free the binary buffer in the first place
    if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
      free(pVariant->wpz);
    }
    
    pVariant->wpz = pWStr;
H
[TD-92]  
Hui Li 已提交
481
    *pDestSize = twcslen(pVariant->wpz);
482 483 484 485 486 487 488
    
    // shrink the allocate memory, no need to check here.
    char* tmp = realloc(pVariant->wpz, (*pDestSize + 1)*TSDB_NCHAR_SIZE);
    assert(tmp != NULL);
    
    pVariant->wpz = (wchar_t *)tmp;
  } else {
489
    int32_t output = 0;
490

491 492 493 494 495
    bool ret = taosMbsToUcs4(pDst, nLen, *pDest, (nLen + 1) * TSDB_NCHAR_SIZE, &output);
    if (!ret) {
      return -1;
    }

H
hjxilinx 已提交
496
    if (pDestSize != NULL) {
497
      *pDestSize = output;
H
hjxilinx 已提交
498
    }
499 500 501 502 503 504
  }
  
  return 0;
}

static FORCE_INLINE int32_t convertToDouble(char *pStr, int32_t len, double *value) {
H
Haojun Liao 已提交
505 506 507 508 509 510
//  SToken stoken = {.z = pStr, .n = len};
//  if (TK_ILLEGAL == tGetNumericStringType(&stoken)) {
//    return -1;
//  }
//
//  *value = strtod(pStr, NULL);
511 512 513
  return 0;
}

H
Haojun Liao 已提交
514
static FORCE_INLINE int32_t convertToInteger(SVariant *pVariant, int64_t *result, int32_t type, bool issigned, bool releaseVariantPtr, bool *converted) {
515
  if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
H
Haojun Liao 已提交
516
    setNull((char *)result, type, tDataTypes[type].bytes);
517 518
    return 0;
  }
H
Haojun Liao 已提交
519
#if 0
520
  errno = 0;
D
fix bug  
dapan1121 已提交
521
  if (IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || (pVariant->nType == TSDB_DATA_TYPE_BOOL)) {
522
    *result = pVariant->i;
523
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
524
    *result = pVariant->u;
525
  } else if (IS_FLOAT_TYPE(pVariant->nType)) {
H
Haojun Liao 已提交
526
    *result = (int64_t) pVariant->d;
527
  } else if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
H
Haojun Liao 已提交
528
    SToken token = {.z = pVariant->pz, .n = pVariant->nLen};
529
    /*int32_t n = */tGetToken(pVariant->pz, &token.type);
530

531 532 533 534 535
    if (token.type == TK_NULL) {
      if (releaseVariantPtr) {
        free(pVariant->pz);
        pVariant->nLen = 0;
      }
536

H
Haojun Liao 已提交
537
      setNull((char *)result, type, tDataTypes[type].bytes);
538 539
      return 0;
    }
540 541 542 543

    // decide if it is a valid number
    token.type = tGetNumericStringType(&token);
    if (token.type == TK_ILLEGAL) {
544 545
      return -1;
    }
546 547

    int64_t res = 0;
548 549
    int32_t t = tStrToInteger(token.z, token.type, token.n, &res, issigned);
    if (t != 0) {
550 551
      return -1;
    }
552 553 554 555 556 557 558

    if (releaseVariantPtr) {
      free(pVariant->pz);
      pVariant->nLen = 0;
    }

    *result = res;
559 560 561 562
  } else if (pVariant->nType == TSDB_DATA_TYPE_NCHAR) {
    errno = 0;
    wchar_t *endPtr = NULL;
    
H
Haojun Liao 已提交
563
    SToken token = {0};
564
    token.n = tGetToken(pVariant->pz, &token.type);
565 566
    
    if (token.type == TK_MINUS || token.type == TK_PLUS) {
567
      token.n = tGetToken(pVariant->pz + token.n, &token.type);
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
    }
    
    if (token.type == TK_FLOAT) {
      double v = wcstod(pVariant->wpz, &endPtr);
      if (releaseVariantPtr) {
        free(pVariant->pz);
        pVariant->nLen = 0;
      }
      
      if ((errno == ERANGE && v == -1) || (isinf(v) || isnan(v))) {
        return -1;
      }
      
      *result = (int64_t)v;
    } else if (token.type == TK_NULL) {
      if (releaseVariantPtr) {
        free(pVariant->pz);
        pVariant->nLen = 0;
      }
H
Haojun Liao 已提交
587
      setNull((char *)result, type, tDataTypes[type].bytes);
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
      return 0;
    } else {
      int64_t val = wcstoll(pVariant->wpz, &endPtr, 10);
      if (releaseVariantPtr) {
        free(pVariant->pz);
        pVariant->nLen = 0;
      }
      
      if (errno == ERANGE) {
        return -1;  // data overflow
      }
      
      *result = val;
    }
  }
603

W
wpan 已提交
604 605 606 607
  if (converted) {
    *converted = true;
  }

608
  bool code = false;
609 610

  uint64_t ui = 0;
611 612 613 614 615 616 617 618 619 620
  switch(type) {
    case TSDB_DATA_TYPE_TINYINT:
      code = IS_VALID_TINYINT(*result); break;
    case TSDB_DATA_TYPE_SMALLINT:
      code = IS_VALID_SMALLINT(*result); break;
    case TSDB_DATA_TYPE_INT:
      code = IS_VALID_INT(*result); break;
    case TSDB_DATA_TYPE_BIGINT:
      code = IS_VALID_BIGINT(*result); break;
    case TSDB_DATA_TYPE_UTINYINT:
621 622
      ui = *result;
      code = IS_VALID_UTINYINT(ui); break;
623
    case TSDB_DATA_TYPE_USMALLINT:
624 625
      ui = *result;
      code = IS_VALID_USMALLINT(ui); break;
626
    case TSDB_DATA_TYPE_UINT:
627 628
      ui = *result;
      code = IS_VALID_UINT(ui); break;
629
    case TSDB_DATA_TYPE_UBIGINT:
630 631
      ui = *result;
      code = IS_VALID_UBIGINT(ui); break;
632
  }
633

H
Haojun Liao 已提交
634

635
  return code? 0:-1;
H
Haojun Liao 已提交
636 637
#endif
  return 0;
638 639
}

H
Haojun Liao 已提交
640
static int32_t convertToBool(SVariant *pVariant, int64_t *pDest) {
641
  if (pVariant->nType == TSDB_DATA_TYPE_BOOL) {
642
    *pDest = pVariant->i;  // in order to be compatible to null of bool
643
  } else if (IS_NUMERIC_TYPE(pVariant->nType)) {
644
    *pDest = ((pVariant->i != 0) ? TSDB_TRUE : TSDB_FALSE);
645
  } else if (pVariant->nType == TSDB_DATA_TYPE_FLOAT || pVariant->nType == TSDB_DATA_TYPE_DOUBLE) {
H
Haojun Liao 已提交
646
    *pDest = ((pVariant->d != 0) ? TSDB_TRUE : TSDB_FALSE);
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
  } else if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
    int32_t ret = 0;
    if ((ret = convertToBoolImpl(pVariant->pz, pVariant->nLen)) < 0) {
      return ret;
    }
    
    *pDest = ret;
  } else if (pVariant->nType == TSDB_DATA_TYPE_NCHAR) {
    int32_t ret = 0;
    if ((ret = wcsconvertToBoolImpl(pVariant->wpz, pVariant->nLen)) < 0) {
      return ret;
    }
    *pDest = ret;
  } else if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
    *pDest = TSDB_DATA_BOOL_NULL;
  }
  
  assert(*pDest == TSDB_TRUE || *pDest == TSDB_FALSE || *pDest == TSDB_DATA_BOOL_NULL);
  return 0;
}

/*
 * transfer data from variant serve as the implicit data conversion: from input sql string pVariant->nType
 * to column type defined in schema
 */
H
Haojun Liao 已提交
672
int32_t tVariantDumpEx(SVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix, bool *converted, char *extInfo) {
W
wpan 已提交
673 674 675 676
  if (converted) {
    *converted = false;
  }
  
677
  if (pVariant == NULL || (pVariant->nType != 0 && !isValidDataType(pVariant->nType))) {
678 679
    return -1;
  }
680

681
  errno = 0;  // reset global error code
H
Haojun Liao 已提交
682
  int64_t result = 0;
683

684 685
  switch (type) {
    case TSDB_DATA_TYPE_BOOL: {
686
      if (convertToBool(pVariant, &result) < 0) {
687 688
        return -1;
      }
689 690

      *(int8_t *)payload = (int8_t)result;
691 692 693 694
      break;
    }
    
    case TSDB_DATA_TYPE_TINYINT: {
W
wpan 已提交
695 696
      if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) {
        SET_EXT_INFO(converted, result, INT8_MIN + 1, INT8_MAX, extInfo);
697 698
        return -1;
      }
699 700 701 702 703
      *((int8_t *)payload) = (int8_t) result;
      break;
    }

    case TSDB_DATA_TYPE_UTINYINT: {
W
wpan 已提交
704 705
      if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) {        
        SET_EXT_INFO(converted, result, 0, UINT8_MAX - 1, extInfo);
706 707 708
        return -1;
      }
      *((uint8_t *)payload) = (uint8_t) result;
709 710 711 712
      break;
    }
    
    case TSDB_DATA_TYPE_SMALLINT: {
W
wpan 已提交
713 714
      if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) {
        SET_EXT_INFO(converted, result, INT16_MIN + 1, INT16_MAX, extInfo);
715 716 717 718 719
        return -1;
      }
      *((int16_t *)payload) = (int16_t)result;
      break;
    }
720 721

    case TSDB_DATA_TYPE_USMALLINT: {
W
wpan 已提交
722 723
      if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) {
        SET_EXT_INFO(converted, result, 0, UINT16_MAX - 1, extInfo);
724 725 726 727 728
        return -1;
      }
      *((uint16_t *)payload) = (uint16_t)result;
      break;
    }
729 730
    
    case TSDB_DATA_TYPE_INT: {
W
wpan 已提交
731 732
      if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) {
        SET_EXT_INFO(converted, result, INT32_MIN + 1, INT32_MAX, extInfo);
733 734 735 736 737
        return -1;
      }
      *((int32_t *)payload) = (int32_t)result;
      break;
    }
738 739

    case TSDB_DATA_TYPE_UINT: {
W
wpan 已提交
740 741
      if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) {
        SET_EXT_INFO(converted, result, 0, UINT32_MAX - 1, extInfo);
742 743 744 745 746
        return -1;
      }
      *((uint32_t *)payload) = (uint32_t)result;
      break;
    }
747 748
    
    case TSDB_DATA_TYPE_BIGINT: {
W
wpan 已提交
749 750
      if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) {
        SET_EXT_INFO(converted, (int64_t)result, INT64_MIN + 1, INT64_MAX, extInfo);
751 752 753 754 755
        return -1;
      }
      *((int64_t *)payload) = (int64_t)result;
      break;
    }
756 757

    case TSDB_DATA_TYPE_UBIGINT: {
W
wpan 已提交
758 759
      if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) {
        SET_EXT_INFO(converted, (uint64_t)result, 0, UINT64_MAX - 1, extInfo);
760 761 762 763 764 765
        return -1;
      }
      *((uint64_t *)payload) = (uint64_t)result;
      break;
    }

766 767 768 769 770 771 772
    case TSDB_DATA_TYPE_FLOAT: {
      if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
        if (strncasecmp(TSDB_DATA_NULL_STR_L, pVariant->pz, pVariant->nLen) == 0 &&
            strlen(TSDB_DATA_NULL_STR_L) == pVariant->nLen) {
          *((int32_t *)payload) = TSDB_DATA_FLOAT_NULL;
          return 0;
        } else {
S
Shengliang Guan 已提交
773
          double  value = -1;
774
          int32_t ret = convertToDouble(pVariant->pz, pVariant->nLen, &value);
775 776 777 778
          if ((errno == ERANGE && (float)value == -1) || (ret != 0)) {
            return -1;
          }

W
wpan 已提交
779 780 781 782 783 784 785 786
          if (converted) {
            *converted = true;
          }
          
          if (value > FLT_MAX || value < -FLT_MAX) {
            SET_EXT_INFO(converted, value, -FLT_MAX, FLT_MAX, extInfo);
            return -1;
          }
S
TD-1530  
Shengliang Guan 已提交
787
          SET_FLOAT_VAL(payload, value);
788
        }
789
      } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
W
wpan 已提交
790 791 792 793
        if (converted) {
          *converted = true;
        }
        
794 795
        if (pVariant->i > FLT_MAX || pVariant->i < -FLT_MAX) {          
          SET_EXT_INFO(converted, pVariant->i, -FLT_MAX, FLT_MAX, extInfo);
W
wpan 已提交
796 797 798
          return -1;
        }

799
        SET_FLOAT_VAL(payload, pVariant->i);
800
      } else if (IS_FLOAT_TYPE(pVariant->nType)) {
W
wpan 已提交
801 802 803 804
        if (converted) {
          *converted = true;
        }
        
H
Haojun Liao 已提交
805 806
        if (pVariant->d > FLT_MAX || pVariant->d < -FLT_MAX) {          
          SET_EXT_INFO(converted, pVariant->d, -FLT_MAX, FLT_MAX, extInfo);
W
wpan 已提交
807 808 809
          return -1;
        }
      
H
Haojun Liao 已提交
810
        SET_FLOAT_VAL(payload, pVariant->d);
811
      } else if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
812
        *((uint32_t *)payload) = TSDB_DATA_FLOAT_NULL;
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
        return 0;
      }

      float fv = GET_FLOAT_VAL(payload);
      if (isinf(fv) || isnan(fv) || fv > FLT_MAX || fv < -FLT_MAX) {
        return -1;
      }
      break;
    }
    case TSDB_DATA_TYPE_DOUBLE: {
      if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
        if (strncasecmp(TSDB_DATA_NULL_STR_L, pVariant->pz, pVariant->nLen) == 0 &&
            strlen(TSDB_DATA_NULL_STR_L) == pVariant->nLen) {
          *((int64_t *)payload) = TSDB_DATA_DOUBLE_NULL;
          return 0;
        } else {
          double  value = 0;
          int32_t ret;
          ret = convertToDouble(pVariant->pz, pVariant->nLen, &value);
          if ((errno == ERANGE && value == -1) || (ret != 0)) {
            return -1;
          }

S
TD-1530  
Shengliang Guan 已提交
836
          SET_DOUBLE_VAL(payload, value);
837
        }
838
      } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
839
        SET_DOUBLE_VAL(payload, pVariant->i);
840
      } else if (IS_FLOAT_TYPE(pVariant->nType)) {
H
Haojun Liao 已提交
841
        SET_DOUBLE_VAL(payload, pVariant->d);
842 843 844 845 846 847
      } else if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
        *((int64_t *)payload) = TSDB_DATA_DOUBLE_NULL;
        return 0;
      }

      double dv = GET_DOUBLE_VAL(payload);
848
      if (errno == ERANGE || isinf(dv) || isnan(dv)) {
849 850
        return -1;
      }
851

852 853 854 855
      break;
    }
    
    case TSDB_DATA_TYPE_BINARY: {
856 857 858 859 860 861 862 863 864 865
      if (!includeLengthPrefix) {
        if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
          *(uint8_t*) payload = TSDB_DATA_BINARY_NULL;
        } else {
          if (pVariant->nType != TSDB_DATA_TYPE_BINARY) {
            toBinary(pVariant, &payload, &pVariant->nLen);
          } else {
            strncpy(payload, pVariant->pz, pVariant->nLen);
          }
        }
866
      } else {
867 868
        if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
          setVardataNull(payload, TSDB_DATA_TYPE_BINARY);
869
        } else {
870 871 872 873 874 875 876 877 878 879
          char *p = varDataVal(payload);

          if (pVariant->nType != TSDB_DATA_TYPE_BINARY) {
            toBinary(pVariant, &p, &pVariant->nLen);
          } else {
            strncpy(p, pVariant->pz, pVariant->nLen);
          }

          varDataSetLen(payload, pVariant->nLen);
          assert(p == varDataVal(payload));
880 881 882 883 884 885 886 887
        }
      }
      break;
    }
    case TSDB_DATA_TYPE_TIMESTAMP: {
      if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
        *((int64_t *)payload) = TSDB_DATA_BIGINT_NULL;
      } else {
888
        *((int64_t *)payload) = pVariant->i;
889 890 891 892
      }
      break;
    }
    case TSDB_DATA_TYPE_NCHAR: {
L
liu0x54 已提交
893
      int32_t newlen = 0;
894 895 896 897 898
      if (!includeLengthPrefix) {
        if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
          *(uint32_t *)payload = TSDB_DATA_NCHAR_NULL;
        } else {
          if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) {
899 900 901
            if (toNchar(pVariant, &payload, &newlen) != 0) {
              return -1;
            }
902 903 904 905
          } else {
            wcsncpy((wchar_t *)payload, pVariant->wpz, pVariant->nLen);
          }
        }
906
      } else {
907 908
        if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
          setVardataNull(payload, TSDB_DATA_TYPE_NCHAR);
909
        } else {
910 911 912
          char *p = varDataVal(payload);

          if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) {
913 914 915
            if (toNchar(pVariant, &p, &newlen) != 0) {
              return -1;
            }
916
          } else {
D
fix bug  
dapan1121 已提交
917
            memcpy(p, pVariant->wpz, pVariant->nLen);
L
liu0x54 已提交
918
            newlen = pVariant->nLen;
919 920
          }

L
liu0x54 已提交
921
          varDataSetLen(payload, newlen);  // the length may be changed after toNchar function called
922
          assert(p == varDataVal(payload));
923 924
        }
      }
925
      
926 927 928 929 930 931 932
      break;
    }
  }
  
  return 0;
}

H
Haojun Liao 已提交
933 934 935 936
/*
 * transfer data from variant serve as the implicit data conversion: from input sql string pVariant->nType
 * to column type defined in schema
 */
H
Haojun Liao 已提交
937
int32_t taosVariantDump(SVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix) {
H
Haojun Liao 已提交
938 939
  return tVariantDumpEx(pVariant, payload, type, includeLengthPrefix, NULL, NULL);
}
W
wpan 已提交
940

941 942 943 944 945 946
/*
 * In variant, bool/smallint/tinyint/int/bigint share the same attribution of
 * structure, also ignore the convert the type required
 *
 * It is actually the bigint/binary/bool/nchar type transfer
 */
947
int32_t taosVariantTypeSetType(SVariant *pVariant, char type) {
948 949 950 951 952 953
  if (pVariant == NULL || pVariant->nType == 0) {  // value is not set
    return 0;
  }
  
  switch (type) {
    case TSDB_DATA_TYPE_BOOL: {  // bool
954
      if (convertToBool(pVariant, &pVariant->i) < 0) {
955 956 957 958 959 960 961 962 963 964
        return -1;
      }
      
      pVariant->nType = type;
      break;
    }
    case TSDB_DATA_TYPE_INT:
    case TSDB_DATA_TYPE_BIGINT:
    case TSDB_DATA_TYPE_TINYINT:
    case TSDB_DATA_TYPE_SMALLINT: {
965
      convertToInteger(pVariant, &(pVariant->i), type, true, true, NULL);
966 967 968 969 970 971 972 973 974 975 976 977 978 979
      pVariant->nType = TSDB_DATA_TYPE_BIGINT;
      break;
    }
    case TSDB_DATA_TYPE_FLOAT:
    case TSDB_DATA_TYPE_DOUBLE: {
      if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
        errno = 0;
        double v = strtod(pVariant->pz, NULL);
        if ((errno == ERANGE && v == -1) || (isinf(v) || isnan(v))) {
          free(pVariant->pz);
          return -1;
        }
        
        free(pVariant->pz);
H
Haojun Liao 已提交
980
        pVariant->d = v;
981 982 983 984 985 986 987 988 989
      } else if (pVariant->nType == TSDB_DATA_TYPE_NCHAR) {
        errno = 0;
        double v = wcstod(pVariant->wpz, NULL);
        if ((errno == ERANGE && v == -1) || (isinf(v) || isnan(v))) {
          free(pVariant->pz);
          return -1;
        }
        
        free(pVariant->pz);
H
Haojun Liao 已提交
990
        pVariant->d = v;
991
      } else if (pVariant->nType >= TSDB_DATA_TYPE_BOOL && pVariant->nType <= TSDB_DATA_TYPE_BIGINT) {
992
        double tmp = (double) pVariant->i;
H
Haojun Liao 已提交
993
        pVariant->d = tmp;
994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
      }
      
      pVariant->nType = TSDB_DATA_TYPE_DOUBLE;
      break;
    }
    case TSDB_DATA_TYPE_BINARY: {
      if (pVariant->nType != TSDB_DATA_TYPE_BINARY) {
        toBinary(pVariant, &pVariant->pz, &pVariant->nLen);
      }
      pVariant->nType = type;
      break;
    }
    case TSDB_DATA_TYPE_NCHAR: {
      if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) {
1008
        if (toNchar(pVariant, &pVariant->pz, &pVariant->nLen) != 0) {
1009 1010
          return -1;
        }
1011 1012 1013 1014 1015 1016 1017
      }
      pVariant->nType = type;
      break;
    }
  }
  
  return 0;
H
Haojun Liao 已提交
1018
}