tvariant.c 28.8 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
#include "taos.h"
H
Haojun Liao 已提交
18
#include "thash.h"
H
hjxilinx 已提交
19
#include "taosdef.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

W
wpan 已提交
26 27 28 29 30 31
#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)
32

H
Haojun Liao 已提交
33 34
void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type) {
  int32_t ret = 0;
H
Haojun Liao 已提交
35
  memset(pVar, 0, sizeof(SVariant));
36

H
Haojun Liao 已提交
37
  switch (type) {
38
    case TSDB_DATA_TYPE_BOOL: {
H
Haojun Liao 已提交
39
      if (strncasecmp(z, "true", 4) == 0) {
40
        pVar->i64 = TSDB_TRUE;
H
Haojun Liao 已提交
41
      } else if (strncasecmp(z, "false", 5) == 0) {
42
        pVar->i64 = TSDB_FALSE;
43 44
      } else {
        return;
45
      }
46

47 48
      break;
    }
49

50 51 52
    case TSDB_DATA_TYPE_TINYINT:
    case TSDB_DATA_TYPE_SMALLINT:
    case TSDB_DATA_TYPE_BIGINT:
53
    case TSDB_DATA_TYPE_INT:{
H
Haojun Liao 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
//      ret = tStrToInteger(token->z, token->type, token->n, &pVar->i64, true);
//      if (ret != 0) {
//        SToken t = {0};
//        tGetToken(token->z, &t.type);
//        if (t.type == TK_MINUS) {  // it is a signed number which is greater than INT64_MAX or less than INT64_MIN
//          pVar->nType = -1;   // -1 means error type
//          return;
//        }
//
//        // data overflow, try unsigned parse the input number
//        ret = tStrToInteger(token->z, token->type, token->n, &pVar->i64, false);
//        if (ret != 0) {
//          pVar->nType = -1;   // -1 means error type
//          return;
//        }
//      }
70

71
      break;
72 73
    }

74
    case TSDB_DATA_TYPE_DOUBLE:
75
    case TSDB_DATA_TYPE_FLOAT: {
H
Haojun Liao 已提交
76
      pVar->d = strtod(z, NULL);
77
      break;
78 79
    }

80
    case TSDB_DATA_TYPE_BINARY: {
H
Haojun Liao 已提交
81 82
      pVar->pz = strndup(z, n);
      pVar->nLen = strRmquote(pVar->pz, n);
83 84
      break;
    }
85 86 87 88
    case TSDB_DATA_TYPE_TIMESTAMP: {
      pVar->i64 = taosGetTimestamp(TSDB_TIME_PRECISION_NANO);                           
      break;                             
    }                            
89 90 91 92 93 94 95 96
    
    default: {  // nType == 0 means the null value
      type = TSDB_DATA_TYPE_NULL;
    }
  }
  
  pVar->nType = type;
}
H
Haojun Liao 已提交
97

98 99

/**
H
Haojun Liao 已提交
100
 * create SVariant from binary string, not ascii data
101 102 103 104 105
 * @param pVar
 * @param pz
 * @param len
 * @param type
 */
H
Haojun Liao 已提交
106
void taosVariantCreateFromBinary(SVariant *pVar, const char *pz, size_t len, uint32_t type) {
107 108 109
  switch (type) {
    case TSDB_DATA_TYPE_BOOL:
    case TSDB_DATA_TYPE_TINYINT: {
110
      pVar->nLen = tDataTypes[type].bytes;
111 112 113 114
      pVar->i64 = GET_INT8_VAL(pz);
      break;
    }
    case TSDB_DATA_TYPE_UTINYINT: {
115
      pVar->nLen = tDataTypes[type].bytes;
116
      pVar->u64 = GET_UINT8_VAL(pz);
117 118 119
      break;
    }
    case TSDB_DATA_TYPE_SMALLINT: {
120
      pVar->nLen = tDataTypes[type].bytes;
121 122 123 124
      pVar->i64 = GET_INT16_VAL(pz);
      break;
    }
    case TSDB_DATA_TYPE_USMALLINT: {
125
      pVar->nLen = tDataTypes[type].bytes;
126
      pVar->u64 = GET_UINT16_VAL(pz);
127 128 129
      break;
    }
    case TSDB_DATA_TYPE_INT: {
130
      pVar->nLen = tDataTypes[type].bytes;
131 132 133 134
      pVar->i64 = GET_INT32_VAL(pz);
      break;
    }
    case TSDB_DATA_TYPE_UINT: {
135
      pVar->nLen = tDataTypes[type].bytes;
136
      pVar->u64 = GET_UINT32_VAL(pz);
137 138 139 140
      break;
    }
    case TSDB_DATA_TYPE_BIGINT:
    case TSDB_DATA_TYPE_TIMESTAMP: {
141
      pVar->nLen = tDataTypes[type].bytes;
142 143 144 145
      pVar->i64 = GET_INT64_VAL(pz);
      break;
    }
    case TSDB_DATA_TYPE_UBIGINT: {
146
      pVar->nLen = tDataTypes[type].bytes;
147
      pVar->u64 = GET_UINT64_VAL(pz);
148 149 150
      break;
    }
    case TSDB_DATA_TYPE_DOUBLE: {
151
      pVar->nLen = tDataTypes[type].bytes;
H
Haojun Liao 已提交
152
      pVar->d = GET_DOUBLE_VAL(pz);
153 154 155
      break;
    }
    case TSDB_DATA_TYPE_FLOAT: {
156
      pVar->nLen = tDataTypes[type].bytes;
H
Haojun Liao 已提交
157
      pVar->d = GET_FLOAT_VAL(pz);
158 159 160
      break;
    }
    case TSDB_DATA_TYPE_NCHAR: { // here we get the nchar length from raw binary bits length
161
      size_t lenInwchar = len / TSDB_NCHAR_SIZE;
162

163
      pVar->wpz = calloc(1, (lenInwchar + 1) * TSDB_NCHAR_SIZE);
164
      memcpy(pVar->wpz, pz, lenInwchar * TSDB_NCHAR_SIZE);
165
      pVar->nLen = (int32_t)len;
166 167 168
      
      break;
    }
169
    case TSDB_DATA_TYPE_BINARY: {  // todo refactor, extract a method
H
Haojun Liao 已提交
170
      pVar->pz = calloc(len + 1, sizeof(char));
171
      memcpy(pVar->pz, pz, len);
172
      pVar->nLen = (int32_t)len;
173 174 175 176
      break;
    }
    
    default:
177
      pVar->i64 = GET_INT32_VAL(pz);
178
      pVar->nLen = tDataTypes[TSDB_DATA_TYPE_INT].bytes;
179 180 181 182 183
  }
  
  pVar->nType = type;
}

H
Haojun Liao 已提交
184
void taosVariantDestroy(SVariant *pVar) {
185 186 187
  if (pVar == NULL) return;
  
  if (pVar->nType == TSDB_DATA_TYPE_BINARY || pVar->nType == TSDB_DATA_TYPE_NCHAR) {
S
TD-1848  
Shengliang Guan 已提交
188
    tfree(pVar->pz);
189 190
    pVar->nLen = 0;
  }
weixin_48148422's avatar
weixin_48148422 已提交
191 192

  // NOTE: this is only for string array
W
wpan 已提交
193
  if (pVar->nType == TSDB_DATA_TYPE_POINTER_ARRAY) {
weixin_48148422's avatar
weixin_48148422 已提交
194 195 196 197 198 199 200
    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 已提交
201 202 203
  } else if (pVar->nType == TSDB_DATA_TYPE_VALUE_ARRAY) {
    taosArrayDestroy(pVar->arr);
    pVar->arr = NULL;
weixin_48148422's avatar
weixin_48148422 已提交
204
  }
205 206
}

H
Haojun Liao 已提交
207
bool taosVariantIsValid(SVariant *pVar) {
208 209 210 211
  assert(pVar != NULL);
  return isValidDataType(pVar->nType);
}

H
Haojun Liao 已提交
212
void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) {
213 214
  if (pSrc == NULL || pDst == NULL) return;
  
H
Haojun Liao 已提交
215
  pDst->nType = pSrc->nType;
H
Haojun Liao 已提交
216
  if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_NCHAR) {
H
Haojun Liao 已提交
217 218
    int32_t len = pSrc->nLen + TSDB_NCHAR_SIZE;
    char* p = realloc(pDst->pz, len);
H
Haojun Liao 已提交
219 220
    assert(p);

H
Haojun Liao 已提交
221
    memset(p, 0, len);
H
Haojun Liao 已提交
222 223
    pDst->pz = p;

H
Haojun Liao 已提交
224 225
    memcpy(pDst->pz, pSrc->pz, pSrc->nLen);
    pDst->nLen = pSrc->nLen;
H
Haojun Liao 已提交
226 227 228 229
    return;

  }

230
  if (IS_NUMERIC_TYPE(pSrc->nType) || (pSrc->nType == TSDB_DATA_TYPE_BOOL)) {
231
    pDst->i64 = pSrc->i64;
W
wpan 已提交
232
  } else if (pSrc->nType == TSDB_DATA_TYPE_POINTER_ARRAY) {  // this is only for string array
weixin_48148422's avatar
weixin_48148422 已提交
233 234 235 236 237 238 239
    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 已提交
240 241 242 243 244 245 246 247 248
  } 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);
      }
249
  }
H
Haojun Liao 已提交
250

W
wpan 已提交
251
  if (pDst->nType != TSDB_DATA_TYPE_POINTER_ARRAY && pDst->nType != TSDB_DATA_TYPE_VALUE_ARRAY) {
H
Haojun Liao 已提交
252
    pDst->nLen = tDataTypes[pDst->nType].bytes;
H
Haojun Liao 已提交
253
  }
254 255
}

H
Haojun Liao 已提交
256
int32_t taosVariantCompare(const SVariant* p1, const SVariant* p2) {
H
Haojun Liao 已提交
257 258 259 260 261 262 263 264 265 266 267
  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;
  }
268

269 270 271 272 273 274 275
  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 已提交
276
    if (p1->d == p2->d) {
277 278
      return 0;
    } else {
H
Haojun Liao 已提交
279
      return p1->d > p2->d? 1:-1;
280 281 282 283 284 285 286 287 288 289 290 291 292
    }
  } else if (IS_UNSIGNED_NUMERIC_TYPE(p1->nType)) {
    if (p1->u64 == p2->u64) {
      return 0;
    } else {
      return p1->u64 > p2->u64? 1:-1;
    }
  } else {
    if (p1->i64 == p2->i64) {
      return 0;
    } else {
      return p1->i64 > p2->i64? 1:-1;
    }
293 294 295
  }
}

H
Haojun Liao 已提交
296
int32_t taosVariantToString(SVariant *pVar, char *dst) {
297 298 299 300 301 302 303 304 305 306 307
  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 已提交
308
      taosUcs4ToMbs(pVar->wpz, (twcslen(pVar->wpz) + 1) * TSDB_NCHAR_SIZE, dst + 1);
309
      int32_t len = (int32_t)strlen(dst);
310 311 312 313 314 315 316 317 318
      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:
319 320 321 322
    case TSDB_DATA_TYPE_UTINYINT:
    case TSDB_DATA_TYPE_USMALLINT:
    case TSDB_DATA_TYPE_UINT:
      return sprintf(dst, "%d", (int32_t)pVar->i64);
323 324
    
    case TSDB_DATA_TYPE_BIGINT:
325 326 327
      return sprintf(dst, "%" PRId64, pVar->i64);
    case TSDB_DATA_TYPE_UBIGINT:
      return sprintf(dst, "%" PRIu64, pVar->u64);
328 329
    case TSDB_DATA_TYPE_FLOAT:
    case TSDB_DATA_TYPE_DOUBLE:
H
Haojun Liao 已提交
330
      return sprintf(dst, "%.9lf", pVar->d);
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
    
    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;
354 355
  } else if (memcmp(pstr, L"null", wcslen(L"null")) == 0) {
    return TSDB_DATA_BOOL_NULL;
356 357 358 359 360
  } else {
    return -1;
  }
}

H
Haojun Liao 已提交
361
static int32_t toBinary(SVariant *pVariant, char **pDest, int32_t *pDestSize) {
362
  const int32_t INITIAL_ALLOC_SIZE = 40;
363
  char *        pBuf = NULL;
364

H
Haojun Liao 已提交
365
  // it is a in-place convert type for SVariant, local buffer is needed
366 367 368 369 370 371 372
  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 已提交
373
      if (newSize >= INITIAL_ALLOC_SIZE) {
374 375 376
        pBuf = realloc(pBuf, newSize + 1);
      }
      
377
      taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, pBuf);
378 379 380
      free(pVariant->wpz);
      pBuf[newSize] = 0;
    } else {
381
      taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, *pDest);
382 383 384
    }
    
  } else {
385 386
    if (IS_SIGNED_NUMERIC_TYPE(pVariant->nType)) {
      sprintf(pBuf == NULL ? *pDest : pBuf, "%" PRId64, pVariant->i64);
387
    } else if (pVariant->nType == TSDB_DATA_TYPE_DOUBLE || pVariant->nType == TSDB_DATA_TYPE_FLOAT) {
H
Haojun Liao 已提交
388
      sprintf(pBuf == NULL ? *pDest : pBuf, "%lf", pVariant->d);
389
    } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL) {
390
      sprintf(pBuf == NULL ? *pDest : pBuf, "%s", (pVariant->i64 == TSDB_TRUE) ? "TRUE" : "FALSE");
391 392 393 394 395 396 397 398 399
    } else if (pVariant->nType == 0) {  // null data
      setNull(pBuf == NULL ? *pDest : pBuf, TSDB_DATA_TYPE_BINARY, 0);
    }
  }
  
  if (pBuf != NULL) {
    *pDest = pBuf;
  }
  
400
  *pDestSize = (int32_t)strlen(*pDest);
401 402 403
  return 0;
}

H
Haojun Liao 已提交
404
static int32_t toNchar(SVariant *pVariant, char **pDest, int32_t *pDestSize) {
405 406 407 408
  char tmpBuf[40] = {0};
  
  char *  pDst = tmpBuf;
  int32_t nLen = 0;
409 410 411 412 413 414

  // convert the number to string, than convert it to wchar string.
  if (IS_SIGNED_NUMERIC_TYPE(pVariant->nType)) {
    nLen = sprintf(pDst, "%" PRId64, pVariant->i64);
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
    nLen = sprintf(pDst, "%"PRIu64, pVariant->u64);
415
  } else if (pVariant->nType == TSDB_DATA_TYPE_DOUBLE || pVariant->nType == TSDB_DATA_TYPE_FLOAT) {
H
Haojun Liao 已提交
416
    nLen = sprintf(pDst, "%lf", pVariant->d);
417 418 419 420
  } else if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
    pDst = pVariant->pz;
    nLen = pVariant->nLen;
  } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL) {
421
    nLen = sprintf(pDst, "%s", (pVariant->i64 == TSDB_TRUE) ? "TRUE" : "FALSE");
422 423 424 425
  }
  
  if (*pDest == pVariant->pz) {
    wchar_t *pWStr = calloc(1, (nLen + 1) * TSDB_NCHAR_SIZE);
426 427
    bool ret = taosMbsToUcs4(pDst, nLen, (char *)pWStr, (nLen + 1) * TSDB_NCHAR_SIZE, NULL);
    if (!ret) {
H
Haojun Liao 已提交
428
      tfree(pWStr);
429 430 431
      return -1;
    }

432 433 434 435 436 437
    // 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 已提交
438
    *pDestSize = twcslen(pVariant->wpz);
439 440 441 442 443 444 445
    
    // 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 {
446
    int32_t output = 0;
447

448 449 450 451 452
    bool ret = taosMbsToUcs4(pDst, nLen, *pDest, (nLen + 1) * TSDB_NCHAR_SIZE, &output);
    if (!ret) {
      return -1;
    }

H
hjxilinx 已提交
453
    if (pDestSize != NULL) {
454
      *pDestSize = output;
H
hjxilinx 已提交
455
    }
456 457 458 459 460 461
  }
  
  return 0;
}

static FORCE_INLINE int32_t convertToDouble(char *pStr, int32_t len, double *value) {
H
Haojun Liao 已提交
462 463 464 465 466 467
//  SToken stoken = {.z = pStr, .n = len};
//  if (TK_ILLEGAL == tGetNumericStringType(&stoken)) {
//    return -1;
//  }
//
//  *value = strtod(pStr, NULL);
468 469 470
  return 0;
}

H
Haojun Liao 已提交
471
static FORCE_INLINE int32_t convertToInteger(SVariant *pVariant, int64_t *result, int32_t type, bool issigned, bool releaseVariantPtr, bool *converted) {
472
  if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
H
Haojun Liao 已提交
473
    setNull((char *)result, type, tDataTypes[type].bytes);
474 475
    return 0;
  }
H
Haojun Liao 已提交
476
#if 0
477
  errno = 0;
D
fix bug  
dapan1121 已提交
478
  if (IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || (pVariant->nType == TSDB_DATA_TYPE_BOOL)) {
479 480 481 482
    *result = pVariant->i64;
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
    *result = pVariant->u64;
  } else if (IS_FLOAT_TYPE(pVariant->nType)) {
H
Haojun Liao 已提交
483
    *result = (int64_t) pVariant->d;
484
  } else if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
H
Haojun Liao 已提交
485
    SToken token = {.z = pVariant->pz, .n = pVariant->nLen};
486
    /*int32_t n = */tGetToken(pVariant->pz, &token.type);
487

488 489 490 491 492
    if (token.type == TK_NULL) {
      if (releaseVariantPtr) {
        free(pVariant->pz);
        pVariant->nLen = 0;
      }
493

H
Haojun Liao 已提交
494
      setNull((char *)result, type, tDataTypes[type].bytes);
495 496
      return 0;
    }
497 498 499 500

    // decide if it is a valid number
    token.type = tGetNumericStringType(&token);
    if (token.type == TK_ILLEGAL) {
501 502
      return -1;
    }
503 504

    int64_t res = 0;
505 506
    int32_t t = tStrToInteger(token.z, token.type, token.n, &res, issigned);
    if (t != 0) {
507 508
      return -1;
    }
509 510 511 512 513 514 515

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

    *result = res;
516 517 518 519
  } else if (pVariant->nType == TSDB_DATA_TYPE_NCHAR) {
    errno = 0;
    wchar_t *endPtr = NULL;
    
H
Haojun Liao 已提交
520
    SToken token = {0};
521
    token.n = tGetToken(pVariant->pz, &token.type);
522 523
    
    if (token.type == TK_MINUS || token.type == TK_PLUS) {
524
      token.n = tGetToken(pVariant->pz + token.n, &token.type);
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
    }
    
    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 已提交
544
      setNull((char *)result, type, tDataTypes[type].bytes);
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
      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;
    }
  }
560

W
wpan 已提交
561 562 563 564
  if (converted) {
    *converted = true;
  }

565
  bool code = false;
566 567

  uint64_t ui = 0;
568 569 570 571 572 573 574 575 576 577
  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:
578 579
      ui = *result;
      code = IS_VALID_UTINYINT(ui); break;
580
    case TSDB_DATA_TYPE_USMALLINT:
581 582
      ui = *result;
      code = IS_VALID_USMALLINT(ui); break;
583
    case TSDB_DATA_TYPE_UINT:
584 585
      ui = *result;
      code = IS_VALID_UINT(ui); break;
586
    case TSDB_DATA_TYPE_UBIGINT:
587 588
      ui = *result;
      code = IS_VALID_UBIGINT(ui); break;
589
  }
590

H
Haojun Liao 已提交
591

592
  return code? 0:-1;
H
Haojun Liao 已提交
593 594
#endif
  return 0;
595 596
}

H
Haojun Liao 已提交
597
static int32_t convertToBool(SVariant *pVariant, int64_t *pDest) {
598
  if (pVariant->nType == TSDB_DATA_TYPE_BOOL) {
599 600 601
    *pDest = pVariant->i64;  // in order to be compatible to null of bool
  } else if (IS_NUMERIC_TYPE(pVariant->nType)) {
    *pDest = ((pVariant->i64 != 0) ? TSDB_TRUE : TSDB_FALSE);
602
  } else if (pVariant->nType == TSDB_DATA_TYPE_FLOAT || pVariant->nType == TSDB_DATA_TYPE_DOUBLE) {
H
Haojun Liao 已提交
603
    *pDest = ((pVariant->d != 0) ? TSDB_TRUE : TSDB_FALSE);
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
  } 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 已提交
629
int32_t tVariantDumpEx(SVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix, bool *converted, char *extInfo) {
W
wpan 已提交
630 631 632 633
  if (converted) {
    *converted = false;
  }
  
634
  if (pVariant == NULL || (pVariant->nType != 0 && !isValidDataType(pVariant->nType))) {
635 636
    return -1;
  }
637

638
  errno = 0;  // reset global error code
H
Haojun Liao 已提交
639
  int64_t result = 0;
640

641 642
  switch (type) {
    case TSDB_DATA_TYPE_BOOL: {
643
      if (convertToBool(pVariant, &result) < 0) {
644 645
        return -1;
      }
646 647

      *(int8_t *)payload = (int8_t)result;
648 649 650 651
      break;
    }
    
    case TSDB_DATA_TYPE_TINYINT: {
W
wpan 已提交
652 653
      if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) {
        SET_EXT_INFO(converted, result, INT8_MIN + 1, INT8_MAX, extInfo);
654 655
        return -1;
      }
656 657 658 659 660
      *((int8_t *)payload) = (int8_t) result;
      break;
    }

    case TSDB_DATA_TYPE_UTINYINT: {
W
wpan 已提交
661 662
      if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) {        
        SET_EXT_INFO(converted, result, 0, UINT8_MAX - 1, extInfo);
663 664 665
        return -1;
      }
      *((uint8_t *)payload) = (uint8_t) result;
666 667 668 669
      break;
    }
    
    case TSDB_DATA_TYPE_SMALLINT: {
W
wpan 已提交
670 671
      if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) {
        SET_EXT_INFO(converted, result, INT16_MIN + 1, INT16_MAX, extInfo);
672 673 674 675 676
        return -1;
      }
      *((int16_t *)payload) = (int16_t)result;
      break;
    }
677 678

    case TSDB_DATA_TYPE_USMALLINT: {
W
wpan 已提交
679 680
      if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) {
        SET_EXT_INFO(converted, result, 0, UINT16_MAX - 1, extInfo);
681 682 683 684 685
        return -1;
      }
      *((uint16_t *)payload) = (uint16_t)result;
      break;
    }
686 687
    
    case TSDB_DATA_TYPE_INT: {
W
wpan 已提交
688 689
      if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) {
        SET_EXT_INFO(converted, result, INT32_MIN + 1, INT32_MAX, extInfo);
690 691 692 693 694
        return -1;
      }
      *((int32_t *)payload) = (int32_t)result;
      break;
    }
695 696

    case TSDB_DATA_TYPE_UINT: {
W
wpan 已提交
697 698
      if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) {
        SET_EXT_INFO(converted, result, 0, UINT32_MAX - 1, extInfo);
699 700 701 702 703
        return -1;
      }
      *((uint32_t *)payload) = (uint32_t)result;
      break;
    }
704 705
    
    case TSDB_DATA_TYPE_BIGINT: {
W
wpan 已提交
706 707
      if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) {
        SET_EXT_INFO(converted, (int64_t)result, INT64_MIN + 1, INT64_MAX, extInfo);
708 709 710 711 712
        return -1;
      }
      *((int64_t *)payload) = (int64_t)result;
      break;
    }
713 714

    case TSDB_DATA_TYPE_UBIGINT: {
W
wpan 已提交
715 716
      if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) {
        SET_EXT_INFO(converted, (uint64_t)result, 0, UINT64_MAX - 1, extInfo);
717 718 719 720 721 722
        return -1;
      }
      *((uint64_t *)payload) = (uint64_t)result;
      break;
    }

723 724 725 726 727 728 729
    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 已提交
730
          double  value = -1;
731
          int32_t ret = convertToDouble(pVariant->pz, pVariant->nLen, &value);
732 733 734 735
          if ((errno == ERANGE && (float)value == -1) || (ret != 0)) {
            return -1;
          }

W
wpan 已提交
736 737 738 739 740 741 742 743
          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 已提交
744
          SET_FLOAT_VAL(payload, value);
745
        }
746
      } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
W
wpan 已提交
747 748 749 750 751 752 753 754 755
        if (converted) {
          *converted = true;
        }
        
        if (pVariant->i64 > FLT_MAX || pVariant->i64 < -FLT_MAX) {          
          SET_EXT_INFO(converted, pVariant->i64, -FLT_MAX, FLT_MAX, extInfo);
          return -1;
        }

756
        SET_FLOAT_VAL(payload, pVariant->i64);
757
      } else if (IS_FLOAT_TYPE(pVariant->nType)) {
W
wpan 已提交
758 759 760 761
        if (converted) {
          *converted = true;
        }
        
H
Haojun Liao 已提交
762 763
        if (pVariant->d > FLT_MAX || pVariant->d < -FLT_MAX) {          
          SET_EXT_INFO(converted, pVariant->d, -FLT_MAX, FLT_MAX, extInfo);
W
wpan 已提交
764 765 766
          return -1;
        }
      
H
Haojun Liao 已提交
767
        SET_FLOAT_VAL(payload, pVariant->d);
768
      } else if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
769
        *((uint32_t *)payload) = TSDB_DATA_FLOAT_NULL;
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
        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 已提交
793
          SET_DOUBLE_VAL(payload, value);
794
        }
795
      } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
796
        SET_DOUBLE_VAL(payload, pVariant->i64);
797
      } else if (IS_FLOAT_TYPE(pVariant->nType)) {
H
Haojun Liao 已提交
798
        SET_DOUBLE_VAL(payload, pVariant->d);
799 800 801 802 803 804
      } else if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
        *((int64_t *)payload) = TSDB_DATA_DOUBLE_NULL;
        return 0;
      }

      double dv = GET_DOUBLE_VAL(payload);
805
      if (errno == ERANGE || isinf(dv) || isnan(dv)) {
806 807
        return -1;
      }
808

809 810 811 812
      break;
    }
    
    case TSDB_DATA_TYPE_BINARY: {
813 814 815 816 817 818 819 820 821 822
      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);
          }
        }
823
      } else {
824 825
        if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
          setVardataNull(payload, TSDB_DATA_TYPE_BINARY);
826
        } else {
827 828 829 830 831 832 833 834 835 836
          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));
837 838 839 840 841 842 843 844
        }
      }
      break;
    }
    case TSDB_DATA_TYPE_TIMESTAMP: {
      if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
        *((int64_t *)payload) = TSDB_DATA_BIGINT_NULL;
      } else {
845
        *((int64_t *)payload) = pVariant->i64;
846 847 848 849
      }
      break;
    }
    case TSDB_DATA_TYPE_NCHAR: {
L
liu0x54 已提交
850
      int32_t newlen = 0;
851 852 853 854 855
      if (!includeLengthPrefix) {
        if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
          *(uint32_t *)payload = TSDB_DATA_NCHAR_NULL;
        } else {
          if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) {
856 857 858
            if (toNchar(pVariant, &payload, &newlen) != 0) {
              return -1;
            }
859 860 861 862
          } else {
            wcsncpy((wchar_t *)payload, pVariant->wpz, pVariant->nLen);
          }
        }
863
      } else {
864 865
        if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
          setVardataNull(payload, TSDB_DATA_TYPE_NCHAR);
866
        } else {
867 868 869
          char *p = varDataVal(payload);

          if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) {
870 871 872
            if (toNchar(pVariant, &p, &newlen) != 0) {
              return -1;
            }
873
          } else {
D
fix bug  
dapan1121 已提交
874
            memcpy(p, pVariant->wpz, pVariant->nLen);
L
liu0x54 已提交
875
            newlen = pVariant->nLen;
876 877
          }

L
liu0x54 已提交
878
          varDataSetLen(payload, newlen);  // the length may be changed after toNchar function called
879
          assert(p == varDataVal(payload));
880 881
        }
      }
882
      
883 884 885 886 887 888 889
      break;
    }
  }
  
  return 0;
}

H
Haojun Liao 已提交
890 891 892 893
/*
 * 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 已提交
894
int32_t taosVariantDump(SVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix) {
H
Haojun Liao 已提交
895 896
  return tVariantDumpEx(pVariant, payload, type, includeLengthPrefix, NULL, NULL);
}
W
wpan 已提交
897

898 899 900 901 902 903
/*
 * 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
 */
H
Haojun Liao 已提交
904
int32_t tVariantTypeSetType(SVariant *pVariant, char type) {
905 906 907 908 909 910
  if (pVariant == NULL || pVariant->nType == 0) {  // value is not set
    return 0;
  }
  
  switch (type) {
    case TSDB_DATA_TYPE_BOOL: {  // bool
911
      if (convertToBool(pVariant, &pVariant->i64) < 0) {
912 913 914 915 916 917 918 919 920 921
        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: {
W
wpan 已提交
922
      convertToInteger(pVariant, &(pVariant->i64), type, true, true, NULL);
923 924 925 926 927 928 929 930 931 932 933 934 935 936
      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 已提交
937
        pVariant->d = v;
938 939 940 941 942 943 944 945 946
      } 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 已提交
947
        pVariant->d = v;
948
      } else if (pVariant->nType >= TSDB_DATA_TYPE_BOOL && pVariant->nType <= TSDB_DATA_TYPE_BIGINT) {
H
Haojun Liao 已提交
949
        double tmp = (double) pVariant->i64;
H
Haojun Liao 已提交
950
        pVariant->d = tmp;
951 952 953 954 955 956 957 958 959 960 961 962 963 964
      }
      
      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) {
965
        if (toNchar(pVariant, &pVariant->pz, &pVariant->nLen) != 0) {
966 967
          return -1;
        }
968 969 970 971 972 973 974
      }
      pVariant->nType = type;
      break;
    }
  }
  
  return 0;
H
Haojun Liao 已提交
975
}