clientSmlLine.c 22.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * 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/>.
 */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "clientSml.h"

// comma ,
X
Xiaoyu Wang 已提交
24
#define IS_COMMA(sql) (*(sql) == COMMA && *((sql)-1) != SLASH)
25
// space
X
Xiaoyu Wang 已提交
26
#define IS_SPACE(sql) (*(sql) == SPACE && *((sql)-1) != SLASH)
27
// equal =
X
Xiaoyu Wang 已提交
28
#define IS_EQUAL(sql) (*(sql) == EQUAL && *((sql)-1) != SLASH)
29
// quote "
30
// #define IS_QUOTE(sql) (*(sql) == QUOTE && *((sql)-1) != SLASH)
31 32
// SLASH

33
#define IS_SLASH_LETTER_IN_FIELD_VALUE(sql) (*((sql)-1) == SLASH && (*(sql) == QUOTE || *(sql) == SLASH))
34

35
#define IS_SLASH_LETTER_IN_TAG_FIELD_KEY(sql) \
wmmhello's avatar
wmmhello 已提交
36
  (*((sql)-1) == SLASH && (*(sql) == COMMA || *(sql) == SPACE || *(sql) == EQUAL))
37

38 39 40 41 42 43
#define PROCESS_SLASH_IN_FIELD_VALUE(key, keyLen)  \
  for (int i = 1; i < keyLen; ++i) {               \
    if (IS_SLASH_LETTER_IN_FIELD_VALUE(key + i)) { \
      MOVE_FORWARD_ONE(key + i, keyLen - i);       \
      keyLen--;                                    \
    }                                              \
wmmhello's avatar
wmmhello 已提交
44 45
  }

46 47 48 49 50 51
#define PROCESS_SLASH_IN_TAG_FIELD_KEY(key, keyLen)  \
  for (int i = 1; i < keyLen; ++i) {                 \
    if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(key + i)) { \
      MOVE_FORWARD_ONE(key + i, keyLen - i);         \
      keyLen--;                                      \
    }                                                \
52 53 54 55 56
  }

#define BINARY_ADD_LEN 2  // "binary"   2 means " "
#define NCHAR_ADD_LEN  3  // L"nchar"   3 means L" "

X
Xiaoyu Wang 已提交
57
uint8_t smlPrecisionConvert[7] = {TSDB_TIME_PRECISION_NANO,    TSDB_TIME_PRECISION_HOURS, TSDB_TIME_PRECISION_MINUTES,
58 59 60 61 62 63
                                  TSDB_TIME_PRECISION_SECONDS, TSDB_TIME_PRECISION_MILLI, TSDB_TIME_PRECISION_MICRO,
                                  TSDB_TIME_PRECISION_NANO};

static int64_t smlParseInfluxTime(SSmlHandle *info, const char *data, int32_t len) {
  uint8_t toPrecision = info->currSTableMeta ? info->currSTableMeta->tableInfo.precision : TSDB_TIME_PRECISION_NANO;

X
Xiaoyu Wang 已提交
64 65
  if (unlikely(len == 0 || (len == 1 && data[0] == '0'))) {
    return taosGetTimestampNs() / smlFactorNS[toPrecision];
66 67 68 69 70 71 72 73 74 75 76 77
  }

  uint8_t fromPrecision = smlPrecisionConvert[info->precision];

  int64_t ts = smlGetTimeValue(data, len, fromPrecision, toPrecision);
  if (unlikely(ts == -1)) {
    smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", data);
    return -1;
  }
  return ts;
}

wmmhello's avatar
wmmhello 已提交
78
int32_t smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg) {
X
Xiaoyu Wang 已提交
79
  if (pVal->value[0] == '"') {  // binary
wmmhello's avatar
wmmhello 已提交
80 81 82 83 84 85 86 87
    if (pVal->length >= 2 && pVal->value[pVal->length - 1] == '"') {
      pVal->type = TSDB_DATA_TYPE_BINARY;
      pVal->length -= BINARY_ADD_LEN;
      if (pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) {
        return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
      }
      pVal->value += (BINARY_ADD_LEN - 1);
      return TSDB_CODE_SUCCESS;
88
    }
wmmhello's avatar
wmmhello 已提交
89
    return TSDB_CODE_TSC_INVALID_VALUE;
90
  }
wmmhello's avatar
wmmhello 已提交
91

X
Xiaoyu Wang 已提交
92 93
  if (pVal->value[0] == 'l' || pVal->value[0] == 'L') {  // nchar
    if (pVal->value[1] == '"' && pVal->value[pVal->length - 1] == '"' && pVal->length >= 3) {
wmmhello's avatar
wmmhello 已提交
94 95 96 97 98 99 100
      pVal->type = TSDB_DATA_TYPE_NCHAR;
      pVal->length -= NCHAR_ADD_LEN;
      if (pVal->length > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
        return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
      }
      pVal->value += (NCHAR_ADD_LEN - 1);
      return TSDB_CODE_SUCCESS;
101
    }
wmmhello's avatar
wmmhello 已提交
102
    return TSDB_CODE_TSC_INVALID_VALUE;
103 104
  }

105 106 107 108 109 110 111
  if (pVal->value[0] == 'g' || pVal->value[0] == 'G') {  // geometry
    if (pVal->value[1] == '"' && pVal->value[pVal->length - 1] == '"' && pVal->length >= sizeof("POINT")+3) {
      int32_t code = initCtxGeomFromText();
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }
      char* tmp = taosMemoryCalloc(pVal->length, 1);
112
      memcpy(tmp, pVal->value + 2, pVal->length - 3);
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
      code = doGeomFromText(tmp, (unsigned char **)&pVal->value, &pVal->length);
      taosMemoryFree(tmp);
      if (code != TSDB_CODE_SUCCESS) {
        return code;
      }

      pVal->type = TSDB_DATA_TYPE_GEOMETRY;
      if (pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) {
        geosFreeBuffer((void*)(pVal->value));
        return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
      }
      return TSDB_CODE_SUCCESS;
    }
    return TSDB_CODE_TSC_INVALID_VALUE;
  }

X
Xiaoyu Wang 已提交
129 130 131 132
  if (pVal->value[0] == 't' || pVal->value[0] == 'T') {
    if (pVal->length == 1 ||
        (pVal->length == 4 && (pVal->value[1] == 'r' || pVal->value[1] == 'R') &&
         (pVal->value[2] == 'u' || pVal->value[2] == 'U') && (pVal->value[3] == 'e' || pVal->value[3] == 'E'))) {
wmmhello's avatar
wmmhello 已提交
133 134 135 136 137 138
      pVal->i = TSDB_TRUE;
      pVal->type = TSDB_DATA_TYPE_BOOL;
      pVal->length = (int16_t)tDataTypes[pVal->type].bytes;
      return TSDB_CODE_SUCCESS;
    }
    return TSDB_CODE_TSC_INVALID_VALUE;
139
  }
wmmhello's avatar
wmmhello 已提交
140

X
Xiaoyu Wang 已提交
141 142 143 144 145
  if (pVal->value[0] == 'f' || pVal->value[0] == 'F') {
    if (pVal->length == 1 ||
        (pVal->length == 5 && (pVal->value[1] == 'a' || pVal->value[1] == 'A') &&
         (pVal->value[2] == 'l' || pVal->value[2] == 'L') && (pVal->value[3] == 's' || pVal->value[3] == 'S') &&
         (pVal->value[4] == 'e' || pVal->value[4] == 'E'))) {
wmmhello's avatar
wmmhello 已提交
146 147 148 149 150 151 152 153
      pVal->i = TSDB_FALSE;
      pVal->type = TSDB_DATA_TYPE_BOOL;
      pVal->length = (int16_t)tDataTypes[pVal->type].bytes;
      return TSDB_CODE_SUCCESS;
    }
    return TSDB_CODE_TSC_INVALID_VALUE;
  }

154 155 156 157 158 159 160 161 162
  // number
  if (smlParseNumber(pVal, msg)) {
    pVal->length = (int16_t)tDataTypes[pVal->type].bytes;
    return TSDB_CODE_SUCCESS;
  }

  return TSDB_CODE_TSC_INVALID_VALUE;
}

X
Xiaoyu Wang 已提交
163 164 165
static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLineInfo *currElement, bool isSameMeasure,
                             bool isSameCTable) {
  if (isSameCTable) {
166 167 168 169 170
    return TSDB_CODE_SUCCESS;
  }

  int     cnt = 0;
  SArray *preLineKV = info->preLineTagKV;
X
Xiaoyu Wang 已提交
171 172 173 174
  if (info->dataFormat) {
    if (unlikely(!isSameMeasure)) {
      SSmlSTableMeta **tmp =
          (SSmlSTableMeta **)taosHashGet(info->superTables, currElement->measure, currElement->measureLen);
175

176
      SSmlSTableMeta *sMeta = NULL;
X
Xiaoyu Wang 已提交
177
      if (unlikely(tmp == NULL)) {
178
        char *measure = currElement->measure;
wmmhello's avatar
wmmhello 已提交
179
        int   measureLen = currElement->measureLen;
180 181
        if (currElement->measureEscaped) {
          measure = (char *)taosMemoryMalloc(currElement->measureLen);
wmmhello's avatar
wmmhello 已提交
182 183
          memcpy(measure, currElement->measure, currElement->measureLen);
          PROCESS_SLASH_IN_MEASUREMENT(measure, measureLen);
184
          smlStrReplace(measure, measureLen);
wmmhello's avatar
wmmhello 已提交
185 186
        }
        STableMeta *pTableMeta = smlGetMeta(info, measure, measureLen);
187
        if (currElement->measureEscaped) {
wmmhello's avatar
wmmhello 已提交
188 189
          taosMemoryFree(measure);
        }
X
Xiaoyu Wang 已提交
190
        if (pTableMeta == NULL) {
191
          info->dataFormat = false;
X
Xiaoyu Wang 已提交
192
          info->reRun = true;
193 194
          return TSDB_CODE_SUCCESS;
        }
195
        sMeta = smlBuildSTableMeta(info->dataFormat);
wmmhello's avatar
wmmhello 已提交
196
        if(sMeta == NULL){
wmmhello's avatar
wmmhello 已提交
197
          taosMemoryFreeClear(pTableMeta);
wmmhello's avatar
wmmhello 已提交
198 199
          return TSDB_CODE_OUT_OF_MEMORY;
        }
wmmhello's avatar
wmmhello 已提交
200
        sMeta->tableMeta = pTableMeta;
201
        taosHashPut(info->superTables, currElement->measure, currElement->measureLen, &sMeta, POINTER_BYTES);
202 203
        for (int i = pTableMeta->tableInfo.numOfColumns;
             i < pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; i++) {
204
          SSchema *tag = pTableMeta->schema + i;
205 206 207 208
          SSmlKv   kv = {.key = tag->name,
                         .keyLen = strlen(tag->name),
                         .type = tag->type,
                         .length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE};
209 210
          taosArrayPush(sMeta->tags, &kv);
        }
211
        tmp = &sMeta;
212
      }
213 214
      info->currSTableMeta = (*tmp)->tableMeta;
      info->maxTagKVs = (*tmp)->tags;
215 216
    }
  }
wmmhello's avatar
wmmhello 已提交
217
  taosArrayClearEx(preLineKV, freeSSmlKv);
218 219 220 221 222 223 224 225

  while (*sql < sqlEnd) {
    if (unlikely(IS_SPACE(*sql))) {
      break;
    }

    // parse key
    const char *key = *sql;
X
Xiaoyu Wang 已提交
226
    size_t      keyLen = 0;
wmmhello's avatar
wmmhello 已提交
227 228
    bool        keyEscaped = false;
    size_t      keyLenEscaped = 0;
229
    while (*sql < sqlEnd) {
230
      if (unlikely(IS_SPACE(*sql) || IS_COMMA(*sql))) {
231 232 233 234 235 236 237 238
        smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", *sql);
        return TSDB_CODE_SML_INVALID_DATA;
      }
      if (unlikely(IS_EQUAL(*sql))) {
        keyLen = *sql - key;
        (*sql)++;
        break;
      }
wmmhello's avatar
wmmhello 已提交
239 240 241
      if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(*sql)) {
        keyLenEscaped++;
        keyEscaped = true;
242 243 244 245
      }
      (*sql)++;
    }

wmmhello's avatar
wmmhello 已提交
246
    if (unlikely(IS_INVALID_COL_LEN(keyLen - keyLenEscaped))) {
247 248 249 250 251 252
      smlBuildInvalidDataMsg(&info->msgBuf, "invalid key or key is too long than 64", key);
      return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH;
    }

    // parse value
    const char *value = *sql;
X
Xiaoyu Wang 已提交
253
    size_t      valueLen = 0;
wmmhello's avatar
wmmhello 已提交
254 255
    bool        valueEscaped = false;
    size_t      valueLenEscaped = 0;
256 257 258 259
    while (*sql < sqlEnd) {
      // parse value
      if (unlikely(IS_SPACE(*sql) || IS_COMMA(*sql))) {
        break;
X
Xiaoyu Wang 已提交
260
      } else if (unlikely(IS_EQUAL(*sql))) {
261 262 263 264
        smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", *sql);
        return TSDB_CODE_SML_INVALID_DATA;
      }

265
      if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(*sql)) {
wmmhello's avatar
wmmhello 已提交
266 267
        valueLenEscaped++;
        valueEscaped = true;
268 269 270 271 272 273 274 275 276 277 278
      }

      (*sql)++;
    }
    valueLen = *sql - value;

    if (unlikely(valueLen == 0)) {
      smlBuildInvalidDataMsg(&info->msgBuf, "invalid value", value);
      return TSDB_CODE_SML_INVALID_DATA;
    }

wmmhello's avatar
wmmhello 已提交
279
    if (unlikely(valueLen - valueLenEscaped > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)) {
280 281 282
      return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN;
    }

283 284
    if (keyEscaped) {
      char *tmp = (char *)taosMemoryMalloc(keyLen);
wmmhello's avatar
wmmhello 已提交
285 286 287 288
      memcpy(tmp, key, keyLen);
      PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, keyLen);
      key = tmp;
    }
289 290
    if (valueEscaped) {
      char *tmp = (char *)taosMemoryMalloc(valueLen);
wmmhello's avatar
wmmhello 已提交
291 292 293 294
      memcpy(tmp, value, valueLen);
      PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, valueLen);
      value = tmp;
    }
295 296 297 298 299 300 301
    SSmlKv kv = {.key = key,
                 .keyLen = keyLen,
                 .type = TSDB_DATA_TYPE_NCHAR,
                 .value = value,
                 .length = valueLen,
                 .keyEscaped = keyEscaped,
                 .valueEscaped = valueEscaped};
wmmhello's avatar
wmmhello 已提交
302
    taosArrayPush(preLineKV, &kv);
X
Xiaoyu Wang 已提交
303 304
    if (info->dataFormat) {
      if (unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)) {
305
        info->dataFormat = false;
X
Xiaoyu Wang 已提交
306
        info->reRun = true;
307 308 309
        return TSDB_CODE_SUCCESS;
      }

310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
      if (unlikely(cnt >= taosArrayGetSize(info->maxTagKVs))) {
        info->dataFormat = false;
        info->reRun = true;
        return TSDB_CODE_SUCCESS;
      }
      SSmlKv *maxKV = (SSmlKv *)taosArrayGet(info->maxTagKVs, cnt);

      if (unlikely(!IS_SAME_KEY)) {
        info->dataFormat = false;
        info->reRun = true;
        return TSDB_CODE_SUCCESS;
      }

      if (unlikely(kv.length > maxKV->length)) {
        maxKV->length = kv.length;
        info->needModifySchema = true;
326 327 328 329
      }
    }

    cnt++;
X
Xiaoyu Wang 已提交
330
    if (IS_SPACE(*sql)) {
331 332 333 334 335
      break;
    }
    (*sql)++;
  }

X
Xiaoyu Wang 已提交
336
  void *oneTable = taosHashGet(info->childTables, currElement->measure, currElement->measureTagsLen);
337 338 339 340 341 342 343 344 345
  if ((oneTable != NULL)) {
    return TSDB_CODE_SUCCESS;
  }

  SSmlTableInfo *tinfo = smlBuildTableInfo(1, currElement->measure, currElement->measureLen);
  if (unlikely(!tinfo)) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  tinfo->tags = taosArrayDup(preLineKV, NULL);
346
  for (size_t i = 0; i < taosArrayGetSize(preLineKV); i++) {
wmmhello's avatar
wmmhello 已提交
347
    SSmlKv *kv = (SSmlKv *)taosArrayGet(preLineKV, i);
348 349
    if (kv->keyEscaped) kv->key = NULL;
    if (kv->valueEscaped) kv->value = NULL;
wmmhello's avatar
wmmhello 已提交
350
  }
351 352

  smlSetCTableName(tinfo);
353
  getTableUid(info, currElement, tinfo);
X
Xiaoyu Wang 已提交
354
  if (info->dataFormat) {
355 356
    info->currSTableMeta->uid = tinfo->uid;
    tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta);
X
Xiaoyu Wang 已提交
357
    if (tinfo->tableDataCtx == NULL) {
wmmhello's avatar
wmmhello 已提交
358
      smlDestroyTableInfo(&tinfo);
359 360 361 362 363
      smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL);
      return TSDB_CODE_SML_INVALID_DATA;
    }
  }

364
  taosHashPut(info->childTables, currElement->measure, currElement->measureTagsLen, &tinfo, POINTER_BYTES);
365 366 367 368

  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
369 370
static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLineInfo *currElement, bool isSameMeasure,
                             bool isSameCTable) {
371
  int cnt = 0;
X
Xiaoyu Wang 已提交
372 373 374 375
  if (info->dataFormat) {
    if (unlikely(!isSameCTable)) {
      SSmlTableInfo **oneTable =
          (SSmlTableInfo **)taosHashGet(info->childTables, currElement->measure, currElement->measureTagsLen);
376 377 378 379
      if (unlikely(oneTable == NULL)) {
        smlBuildInvalidDataMsg(&info->msgBuf, "child table should inside", currElement->measure);
        return TSDB_CODE_SML_INVALID_DATA;
      }
380
      info->currTableDataCtx = (*oneTable)->tableDataCtx;
381 382
    }

X
Xiaoyu Wang 已提交
383 384 385 386
    if (unlikely(!isSameMeasure)) {
      SSmlSTableMeta **tmp =
          (SSmlSTableMeta **)taosHashGet(info->superTables, currElement->measure, currElement->measureLen);
      if (unlikely(tmp == NULL)) {
387
        char *measure = currElement->measure;
wmmhello's avatar
wmmhello 已提交
388
        int   measureLen = currElement->measureLen;
389 390
        if (currElement->measureEscaped) {
          measure = (char *)taosMemoryMalloc(currElement->measureLen);
wmmhello's avatar
wmmhello 已提交
391 392
          memcpy(measure, currElement->measure, currElement->measureLen);
          PROCESS_SLASH_IN_MEASUREMENT(measure, measureLen);
393
          smlStrReplace(measure, measureLen);
wmmhello's avatar
wmmhello 已提交
394 395
        }
        STableMeta *pTableMeta = smlGetMeta(info, measure, measureLen);
396
        if (currElement->measureEscaped) {
wmmhello's avatar
wmmhello 已提交
397 398
          taosMemoryFree(measure);
        }
X
Xiaoyu Wang 已提交
399
        if (pTableMeta == NULL) {
400
          info->dataFormat = false;
X
Xiaoyu Wang 已提交
401
          info->reRun = true;
402 403
          return TSDB_CODE_SUCCESS;
        }
404
        *tmp = smlBuildSTableMeta(info->dataFormat);
wmmhello's avatar
wmmhello 已提交
405
        if(*tmp == NULL){
wmmhello's avatar
wmmhello 已提交
406
          taosMemoryFreeClear(pTableMeta);
wmmhello's avatar
wmmhello 已提交
407 408
          return TSDB_CODE_OUT_OF_MEMORY;
        }
409 410 411
        (*tmp)->tableMeta = pTableMeta;
        taosHashPut(info->superTables, currElement->measure, currElement->measureLen, tmp, POINTER_BYTES);

412
        for (int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) {
413
          SSchema *tag = pTableMeta->schema + i;
414 415
          SSmlKv   kv = {.key = tag->name, .keyLen = strlen(tag->name), .type = tag->type};
          if (tag->type == TSDB_DATA_TYPE_NCHAR) {
416
            kv.length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
417
          } else if (tag->type == TSDB_DATA_TYPE_BINARY || tag->type == TSDB_DATA_TYPE_GEOMETRY) {
418 419 420 421
            kv.length = tag->bytes - VARSTR_HEADER_SIZE;
          }
          taosArrayPush((*tmp)->cols, &kv);
        }
422
      }
423
      info->currSTableMeta = (*tmp)->tableMeta;
424
      info->maxColKVs = (*tmp)->cols;
425 426 427 428 429 430 431 432 433 434
    }
  }

  while (*sql < sqlEnd) {
    if (unlikely(IS_SPACE(*sql))) {
      break;
    }

    // parse key
    const char *key = *sql;
X
Xiaoyu Wang 已提交
435
    size_t      keyLen = 0;
wmmhello's avatar
wmmhello 已提交
436 437
    bool        keyEscaped = false;
    size_t      keyLenEscaped = 0;
438
    while (*sql < sqlEnd) {
439
      if (unlikely(IS_SPACE(*sql) || IS_COMMA(*sql))) {
440 441 442 443 444 445 446 447
        smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", *sql);
        return TSDB_CODE_SML_INVALID_DATA;
      }
      if (unlikely(IS_EQUAL(*sql))) {
        keyLen = *sql - key;
        (*sql)++;
        break;
      }
wmmhello's avatar
wmmhello 已提交
448 449 450
      if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(*sql)) {
        keyLenEscaped++;
        keyEscaped = true;
451 452 453 454
      }
      (*sql)++;
    }

wmmhello's avatar
wmmhello 已提交
455
    if (unlikely(IS_INVALID_COL_LEN(keyLen - keyLenEscaped))) {
456 457 458 459 460 461
      smlBuildInvalidDataMsg(&info->msgBuf, "invalid key or key is too long than 64", key);
      return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH;
    }

    // parse value
    const char *value = *sql;
X
Xiaoyu Wang 已提交
462
    size_t      valueLen = 0;
wmmhello's avatar
wmmhello 已提交
463 464
    bool        valueEscaped = false;
    size_t      valueLenEscaped = 0;
wmmhello's avatar
wmmhello 已提交
465
    int         quoteNum = 0;
wmmhello's avatar
wmmhello 已提交
466
    const char *escapeChar = NULL;
467 468
    while (*sql < sqlEnd) {
      // parse value
wmmhello's avatar
wmmhello 已提交
469
      if (unlikely(*(*sql) == QUOTE && (*(*sql - 1) != SLASH || (*sql - 1) == escapeChar))) {
wmmhello's avatar
wmmhello 已提交
470
        quoteNum++;
471
        (*sql)++;
wmmhello's avatar
wmmhello 已提交
472 473
        if(quoteNum > 2){
          break;
474
        }
475 476
        continue;
      }
wmmhello's avatar
wmmhello 已提交
477 478
      if (quoteNum % 2 == 0 && (unlikely(IS_SPACE(*sql) || IS_COMMA(*sql)))) {
        break;
479
      }
wmmhello's avatar
wmmhello 已提交
480 481 482 483
      if (IS_SLASH_LETTER_IN_FIELD_VALUE(*sql) && (*sql - 1) != escapeChar) {
        escapeChar = *sql;
        valueEscaped = true;
        valueLenEscaped++;
484 485 486 487 488 489
      }

      (*sql)++;
    }
    valueLen = *sql - value;

wmmhello's avatar
wmmhello 已提交
490 491
    if (unlikely(quoteNum != 0 && quoteNum != 2)) {
      smlBuildInvalidDataMsg(&info->msgBuf, "unbalanced quotes", value);
492 493 494 495 496 497
      return TSDB_CODE_SML_INVALID_DATA;
    }
    if (unlikely(valueLen == 0)) {
      smlBuildInvalidDataMsg(&info->msgBuf, "invalid value", value);
      return TSDB_CODE_SML_INVALID_DATA;
    }
wmmhello's avatar
wmmhello 已提交
498

499 500 501 502 503 504 505
    SSmlKv  kv = {.key = key, .keyLen = keyLen, .value = value, .length = valueLen};
    int32_t ret = smlParseValue(&kv, &info->msgBuf);
    if (ret != TSDB_CODE_SUCCESS) {
      smlBuildInvalidDataMsg(&info->msgBuf, "smlParseValue error", value);
      return ret;
    }

506 507
    if (keyEscaped) {
      char *tmp = (char *)taosMemoryMalloc(kv.keyLen);
508 509
      memcpy(tmp, key, kv.keyLen);
      PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, kv.keyLen);
510 511
      kv.key = tmp;
      kv.keyEscaped = keyEscaped;
512 513
    }

514 515
    if (valueEscaped) {
      char *tmp = (char *)taosMemoryMalloc(kv.length);
516 517 518 519
      memcpy(tmp, kv.value, kv.length);
      PROCESS_SLASH_IN_FIELD_VALUE(tmp, kv.length);
      kv.value = tmp;
      kv.valueEscaped = valueEscaped;
520 521
    }

X
Xiaoyu Wang 已提交
522 523 524
    if (info->dataFormat) {
      // cnt begin 0, add ts so + 2
      if (unlikely(cnt + 2 > info->currSTableMeta->tableInfo.numOfColumns)) {
525
        info->dataFormat = false;
X
Xiaoyu Wang 已提交
526
        info->reRun = true;
wmmhello's avatar
wmmhello 已提交
527
        freeSSmlKv(&kv);
528 529 530 531 532
        return TSDB_CODE_SUCCESS;
      }
      // bind data
      ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, cnt + 1);
      if (unlikely(ret != TSDB_CODE_SUCCESS)) {
wmmhello's avatar
wmmhello 已提交
533
        uDebug("smlBuildCol error, retry");
534
        info->dataFormat = false;
X
Xiaoyu Wang 已提交
535
        info->reRun = true;
wmmhello's avatar
wmmhello 已提交
536
        freeSSmlKv(&kv);
537 538
        return TSDB_CODE_SUCCESS;
      }
539
      if (cnt >= taosArrayGetSize(info->maxColKVs)) {
540 541
        info->dataFormat = false;
        info->reRun = true;
wmmhello's avatar
wmmhello 已提交
542
        freeSSmlKv(&kv);
543 544
        return TSDB_CODE_SUCCESS;
      }
545
      SSmlKv *maxKV = (SSmlKv *)taosArrayGet(info->maxColKVs, cnt);
546 547 548
      if (kv.type != maxKV->type) {
        info->dataFormat = false;
        info->reRun = true;
wmmhello's avatar
wmmhello 已提交
549
        freeSSmlKv(&kv);
550 551 552 553 554
        return TSDB_CODE_SUCCESS;
      }
      if (unlikely(!IS_SAME_KEY)) {
        info->dataFormat = false;
        info->reRun = true;
wmmhello's avatar
wmmhello 已提交
555
        freeSSmlKv(&kv);
556 557
        return TSDB_CODE_SUCCESS;
      }
558

559 560 561
      if (unlikely(IS_VAR_DATA_TYPE(kv.type) && kv.length > maxKV->length)) {
        maxKV->length = kv.length;
        info->needModifySchema = true;
562
      }
wmmhello's avatar
wmmhello 已提交
563
      freeSSmlKv(&kv);
X
Xiaoyu Wang 已提交
564 565
    } else {
      if (currElement->colArray == NULL) {
X
Xiaoyu Wang 已提交
566
        currElement->colArray = taosArrayInit_s(sizeof(SSmlKv), 1);
567
      }
X
Xiaoyu Wang 已提交
568
      taosArrayPush(currElement->colArray, &kv);  // reserve for timestamp
569 570 571
    }

    cnt++;
X
Xiaoyu Wang 已提交
572
    if (IS_SPACE(*sql)) {
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
      break;
    }
    (*sql)++;
  }

  return TSDB_CODE_SUCCESS;
}

int32_t smlParseInfluxString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLineInfo *elements) {
  if (!sql) return TSDB_CODE_SML_INVALID_DATA;
  JUMP_SPACE(sql, sqlEnd)
  if (unlikely(*sql == COMMA)) return TSDB_CODE_SML_INVALID_DATA;
  elements->measure = sql;

  // parse measure
wmmhello's avatar
wmmhello 已提交
588
  size_t measureLenEscaped = 0;
589
  while (sql < sqlEnd) {
wmmhello's avatar
wmmhello 已提交
590 591 592 593
    if (unlikely((sql != elements->measure) && IS_SLASH_LETTER_IN_MEASUREMENT(sql))) {
      elements->measureEscaped = true;
      measureLenEscaped++;
      sql++;
594 595 596 597 598 599 600 601 602 603 604 605
      continue;
    }
    if (unlikely(IS_COMMA(sql))) {
      break;
    }

    if (unlikely(IS_SPACE(sql))) {
      break;
    }
    sql++;
  }
  elements->measureLen = sql - elements->measure;
wmmhello's avatar
wmmhello 已提交
606
  if (unlikely(IS_INVALID_TABLE_LEN(elements->measureLen - measureLenEscaped))) {
607 608 609 610 611
    smlBuildInvalidDataMsg(&info->msgBuf, "measure is empty or too large than 192", NULL);
    return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
  }

  // to get measureTagsLen before
X
Xiaoyu Wang 已提交
612 613
  const char *tmp = sql;
  while (tmp < sqlEnd) {
614 615 616 617 618 619 620 621 622
    if (unlikely(IS_SPACE(tmp))) {
      break;
    }
    tmp++;
  }
  elements->measureTagsLen = tmp - elements->measure;

  bool isSameCTable = false;
  bool isSameMeasure = false;
X
Xiaoyu Wang 已提交
623
  if (IS_SAME_CHILD_TABLE) {
624 625
    isSameCTable = true;
    isSameMeasure = true;
X
Xiaoyu Wang 已提交
626
  } else if (info->dataFormat) {
627 628 629 630 631 632 633
    isSameMeasure = IS_SAME_SUPER_TABLE;
  }
  // parse tag
  if (*sql == COMMA) sql++;
  elements->tags = sql;

  int ret = smlParseTagKv(info, &sql, sqlEnd, elements, isSameMeasure, isSameCTable);
X
Xiaoyu Wang 已提交
634
  if (unlikely(ret != TSDB_CODE_SUCCESS)) {
635 636
    return ret;
  }
X
Xiaoyu Wang 已提交
637
  if (unlikely(info->reRun)) {
638 639 640 641 642 643 644 645 646 647 648
    return TSDB_CODE_SUCCESS;
  }

  sql = elements->measure + elements->measureTagsLen;
  elements->tagsLen = sql - elements->tags;

  // parse cols
  JUMP_SPACE(sql, sqlEnd)
  elements->cols = sql;

  ret = smlParseColKv(info, &sql, sqlEnd, elements, isSameMeasure, isSameCTable);
X
Xiaoyu Wang 已提交
649
  if (unlikely(ret != TSDB_CODE_SUCCESS)) {
650 651 652
    return ret;
  }

X
Xiaoyu Wang 已提交
653
  if (unlikely(info->reRun)) {
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
    return TSDB_CODE_SUCCESS;
  }

  elements->colsLen = sql - elements->cols;
  if (unlikely(elements->colsLen == 0)) {
    smlBuildInvalidDataMsg(&info->msgBuf, "cols is empty", NULL);
    return TSDB_CODE_SML_INVALID_DATA;
  }

  // parse timestamp
  JUMP_SPACE(sql, sqlEnd)
  elements->timestamp = sql;
  while (sql < sqlEnd) {
    if (unlikely(isspace(*sql))) {
      break;
    }
    sql++;
  }
  elements->timestampLen = sql - elements->timestamp;

  int64_t ts = smlParseInfluxTime(info, elements->timestamp, elements->timestampLen);
  if (unlikely(ts <= 0)) {
    uError("SML:0x%" PRIx64 " smlParseTS error:%" PRId64, info->id, ts);
    return TSDB_CODE_INVALID_TIMESTAMP;
  }
  // add ts to
680 681
  SSmlKv kv = {.key = tsSmlTsDefaultName,
               .keyLen = strlen(tsSmlTsDefaultName),
X
Xiaoyu Wang 已提交
682 683
               .type = TSDB_DATA_TYPE_TIMESTAMP,
               .i = ts,
wmmhello's avatar
wmmhello 已提交
684 685 686
               .length = (size_t)tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes,
               .keyEscaped = false,
               .valueEscaped = false};
X
Xiaoyu Wang 已提交
687
  if (info->dataFormat) {
wmmhello's avatar
wmmhello 已提交
688
    uDebug("SML:0x%" PRIx64 " smlParseInfluxString format true, ts:%" PRId64, info->id, ts);
wmmhello's avatar
wmmhello 已提交
689
    ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, 0);
690 691
    if (ret == TSDB_CODE_SUCCESS) {
      ret = smlBuildRow(info->currTableDataCtx);
692
    }
693 694 695 696

    clearColValArray(info->currTableDataCtx->pValues);
    if (unlikely(ret != TSDB_CODE_SUCCESS)) {
      smlBuildInvalidDataMsg(&info->msgBuf, "smlBuildCol error", NULL);
697 698
      return ret;
    }
X
Xiaoyu Wang 已提交
699
  } else {
wmmhello's avatar
wmmhello 已提交
700
    uDebug("SML:0x%" PRIx64 " smlParseInfluxString format false, ts:%" PRId64, info->id, ts);
701 702 703 704 705 706
    taosArraySet(elements->colArray, 0, &kv);
  }
  info->preLine = *elements;

  return ret;
}