parInsertSql.c 67.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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/>.
 */

X
Xiaoyu Wang 已提交
16
#include "parInsertUtil.h"
X
Xiaoyu Wang 已提交
17
#include "parToken.h"
18 19 20
#include "tglobal.h"
#include "ttime.h"

X
Xiaoyu Wang 已提交
21 22 23 24 25
#define NEXT_TOKEN_WITH_PREV(pSql, token)           \
  do {                                              \
    int32_t index = 0;                              \
    token = tStrGetToken(pSql, &index, true, NULL); \
    pSql += index;                                  \
X
Xiaoyu Wang 已提交
26 27
  } while (0)

X
Xiaoyu Wang 已提交
28 29 30 31 32 33 34 35 36 37
#define NEXT_TOKEN_WITH_PREV_EXT(pSql, token, pIgnoreComma) \
  do {                                                      \
    int32_t index = 0;                                      \
    token = tStrGetToken(pSql, &index, true, pIgnoreComma); \
    pSql += index;                                          \
  } while (0)

#define NEXT_TOKEN_KEEP_SQL(pSql, token, index)      \
  do {                                               \
    token = tStrGetToken(pSql, &index, false, NULL); \
38 39
  } while (0)

X
Xiaoyu Wang 已提交
40 41 42 43 44 45 46 47
#define NEXT_VALID_TOKEN(pSql, token)           \
  do {                                          \
    (token).n = tGetToken(pSql, &(token).type); \
    (token).z = (char*)pSql;                    \
    pSql += (token).n;                          \
  } while (TK_NK_SPACE == (token).type)

typedef struct SInsertParseContext {
X
Xiaoyu Wang 已提交
48 49 50 51 52 53 54
  SParseContext* pComCxt;
  SMsgBuf        msg;
  char           tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW];
  SBoundColInfo  tags;  // for stmt
  bool           missCache;
  bool           usingDuplicateTable;
  bool           forceUpdate;
X
Xiaoyu Wang 已提交
55
} SInsertParseContext;
56

H
refact  
Hongze Cheng 已提交
57
typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param);
X
Xiaoyu Wang 已提交
58 59 60 61

static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;

X
Xiaoyu Wang 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
static bool isNullStr(SToken* pToken) {
  return ((pToken->type == TK_NK_STRING) && (strlen(TSDB_DATA_NULL_STR_L) == pToken->n) &&
          (strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0));
}

static bool isNullValue(int8_t dataType, SToken* pToken) {
  return TK_NULL == pToken->type || (!IS_STR_DATA_TYPE(dataType) && isNullStr(pToken));
}

static FORCE_INLINE int32_t toDouble(SToken* pToken, double* value, char** endPtr) {
  errno = 0;
  *value = taosStr2Double(pToken->z, endPtr);

  // not a valid integer number, return error
  if ((*endPtr - pToken->z) != pToken->n) {
    return TK_NK_ILLEGAL;
  }

  return pToken->type;
}

static int32_t skipInsertInto(const char** pSql, SMsgBuf* pMsg) {
  SToken token;
  NEXT_TOKEN(*pSql, token);
  if (TK_INSERT != token.type && TK_IMPORT != token.type) {
    return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", token.z);
88
  }
X
Xiaoyu Wang 已提交
89 90 91
  NEXT_TOKEN(*pSql, token);
  if (TK_INTO != token.type) {
    return buildSyntaxErrMsg(pMsg, "keyword INTO is expected", token.z);
92 93 94 95
  }
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
96 97 98 99 100 101 102 103 104 105 106 107 108
static int32_t skipParentheses(SInsertParseContext* pCxt, const char** pSql) {
  SToken  token;
  int32_t expectRightParenthesis = 1;
  while (1) {
    NEXT_TOKEN(*pSql, token);
    if (TK_NK_LP == token.type) {
      ++expectRightParenthesis;
    } else if (TK_NK_RP == token.type && 0 == --expectRightParenthesis) {
      break;
    }
    if (0 == token.n) {
      return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL);
    }
109
  }
X
Xiaoyu Wang 已提交
110 111
  return TSDB_CODE_SUCCESS;
}
D
dapan1121 已提交
112

X
Xiaoyu Wang 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125
static int32_t skipTableOptions(SInsertParseContext* pCxt, const char** pSql) {
  do {
    int32_t index = 0;
    SToken  token;
    NEXT_TOKEN_KEEP_SQL(*pSql, token, index);
    if (TK_TTL == token.type || TK_COMMENT == token.type) {
      *pSql += index;
      NEXT_TOKEN_WITH_PREV(*pSql, token);
    } else {
      break;
    }
  } while (1);
  return TSDB_CODE_SUCCESS;
126 127
}

X
Xiaoyu Wang 已提交
128 129 130 131 132 133 134 135 136 137 138 139
// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)
static int32_t ignoreUsingClause(SInsertParseContext* pCxt, const char** pSql) {
  int32_t code = TSDB_CODE_SUCCESS;
  SToken  token;
  NEXT_TOKEN(*pSql, token);

  NEXT_TOKEN(*pSql, token);
  if (TK_NK_LP == token.type) {
    code = skipParentheses(pCxt, pSql);
    if (TSDB_CODE_SUCCESS == code) {
      NEXT_TOKEN(*pSql, token);
    }
140
  }
X
Xiaoyu Wang 已提交
141

X
Xiaoyu Wang 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154 155
  // pSql -> TAGS (tag1_value, ...)
  if (TSDB_CODE_SUCCESS == code) {
    if (TK_TAGS != token.type) {
      code = buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
    } else {
      NEXT_TOKEN(*pSql, token);
    }
  }
  if (TSDB_CODE_SUCCESS == code) {
    if (TK_NK_LP != token.type) {
      code = buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
    } else {
      code = skipParentheses(pCxt, pSql);
    }
156 157
  }

X
Xiaoyu Wang 已提交
158 159
  if (TSDB_CODE_SUCCESS == code) {
    code = skipTableOptions(pCxt, pSql);
160
  }
X
Xiaoyu Wang 已提交
161 162

  return code;
163
}
D
dapan 已提交
164

X
Xiaoyu Wang 已提交
165
static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pDuplicate) {
X
Xiaoyu Wang 已提交
166 167 168 169 170 171 172 173 174 175 176
  *pDuplicate = false;

  char tbFName[TSDB_TABLE_FNAME_LEN];
  tNameExtractFullName(&pStmt->targetTableName, tbFName);
  STableMeta** pMeta = taosHashGet(pStmt->pSubTableHashObj, tbFName, strlen(tbFName));
  if (NULL != pMeta) {
    *pDuplicate = true;
    int32_t code = ignoreUsingClause(pCxt, &pStmt->pSql);
    if (TSDB_CODE_SUCCESS == code) {
      return cloneTableMeta(*pMeta, &pStmt->pTableMeta);
    }
D
stmt  
dapan1121 已提交
177
  }
X
Xiaoyu Wang 已提交
178

H
refact  
Hongze Cheng 已提交
179
  return TSDB_CODE_SUCCESS;
D
stmt  
dapan1121 已提交
180 181
}

X
Xiaoyu Wang 已提交
182
// pStmt->pSql -> field1_name, ...)
X
Xiaoyu Wang 已提交
183 184 185 186 187
static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, bool isTags, SSchema* pSchema,
                                 SBoundColInfo* pBoundInfo) {
  bool* pUseCols = taosMemoryCalloc(pBoundInfo->numOfCols, sizeof(bool));
  if (NULL == pUseCols) {
    return TSDB_CODE_OUT_OF_MEMORY;
X
Xiaoyu Wang 已提交
188
  }
D
stmt  
dapan1121 已提交
189

X
Xiaoyu Wang 已提交
190 191
  pBoundInfo->numOfBound = 0;

D
dapan1121 已提交
192
  int16_t lastColIdx = -1;  // last column found
X
Xiaoyu Wang 已提交
193 194 195
  int32_t code = TSDB_CODE_SUCCESS;
  while (TSDB_CODE_SUCCESS == code) {
    SToken token;
X
Xiaoyu Wang 已提交
196 197 198 199 200 201 202 203 204 205 206
    NEXT_TOKEN(*pSql, token);

    if (TK_NK_RP == token.type) {
      break;
    }

    char tmpTokenBuf[TSDB_COL_NAME_LEN + 2] = {0};  // used for deleting Escape character backstick(`)
    strncpy(tmpTokenBuf, token.z, token.n);
    token.z = tmpTokenBuf;
    token.n = strdequote(token.z);

D
dapan1121 已提交
207 208
    int16_t t = lastColIdx + 1;
    int16_t index = insFindCol(&token, t, pBoundInfo->numOfCols, pSchema);
X
Xiaoyu Wang 已提交
209 210 211 212
    if (index < 0 && t > 0) {
      index = insFindCol(&token, 0, t, pSchema);
    }
    if (index < 0) {
X
Xiaoyu Wang 已提交
213 214 215 216 217 218 219 220
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z);
    } else if (pUseCols[index]) {
      code = buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z);
    } else {
      lastColIdx = index;
      pUseCols[index] = true;
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = index;
      ++pBoundInfo->numOfBound;
X
Xiaoyu Wang 已提交
221 222 223
    }
  }

X
Xiaoyu Wang 已提交
224 225
  if (TSDB_CODE_SUCCESS == code && !isTags && !pUseCols[0]) {
    code = buildInvalidOperationMsg(&pCxt->msg, "primary timestamp column can not be null");
X
Xiaoyu Wang 已提交
226 227
  }

X
Xiaoyu Wang 已提交
228
  taosMemoryFree(pUseCols);
X
Xiaoyu Wang 已提交
229

X
Xiaoyu Wang 已提交
230
  return code;
X
Xiaoyu Wang 已提交
231 232
}

X
Xiaoyu Wang 已提交
233 234 235 236 237
static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf) {
  int32_t     index = 0;
  int64_t     interval;
  int64_t     ts = 0;
  const char* pTokenEnd = *end;
238 239

  if (pToken->type == TK_NOW) {
240
    ts = taosGetTimestamp(timePrec);
241 242
  } else if (pToken->type == TK_TODAY) {
    ts = taosGetTimestampToday(timePrec);
243
  } else if (pToken->type == TK_NK_INTEGER) {
X
Xiaoyu Wang 已提交
244 245 246
    if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &ts)) {
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
    }
H
refact  
Hongze Cheng 已提交
247
  } else {  // parse the RFC-3339/ISO-8601 timestamp format string
S
os env  
Shengliang Guan 已提交
248
    if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) {
249
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
250 251 252 253 254 255 256
    }

    return TSDB_CODE_SUCCESS;
  }

  for (int k = pToken->n; pToken->z[k] != '\0'; k++) {
    if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue;
H
refact  
Hongze Cheng 已提交
257
    if (pToken->z[k] == '(' && pToken->z[k + 1] == ')') {  // for insert NOW()/TODAY()
258 259 260 261
      *end = pTokenEnd = &pToken->z[k + 2];
      k++;
      continue;
    }
262
    if (pToken->z[k] == ',') {
263 264
      *end = pTokenEnd;
      *time = ts;
265 266 267 268 269 270 271 272 273 274 275
      return 0;
    }

    break;
  }

  /*
   * time expression:
   * e.g., now+12a, now-5h
   */
  index = 0;
X
Xiaoyu Wang 已提交
276
  SToken token = tStrGetToken(pTokenEnd, &index, false, NULL);
277 278
  pTokenEnd += index;

X
Xiaoyu Wang 已提交
279
  if (token.type == TK_NK_MINUS || token.type == TK_NK_PLUS) {
280
    index = 0;
X
Xiaoyu Wang 已提交
281
    SToken valueToken = tStrGetToken(pTokenEnd, &index, false, NULL);
282 283 284
    pTokenEnd += index;

    if (valueToken.n < 2) {
X
Xiaoyu Wang 已提交
285
      return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", token.z);
286 287 288 289 290 291 292
    }

    char unit = 0;
    if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval, &unit, timePrec) != TSDB_CODE_SUCCESS) {
      return TSDB_CODE_TSC_INVALID_OPERATION;
    }

X
Xiaoyu Wang 已提交
293
    if (token.type == TK_NK_PLUS) {
294
      ts += interval;
295
    } else {
296
      ts = ts - interval;
297 298
    }

299
    *end = pTokenEnd;
300 301
  }

302
  *time = ts;
303 304
  return TSDB_CODE_SUCCESS;
}
305

X
Xiaoyu Wang 已提交
306 307
static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val,
                             SMsgBuf* pMsgBuf) {
X
Xiaoyu Wang 已提交
308 309 310
  int64_t  iv;
  uint64_t uv;
  char*    endptr = NULL;
X
Xiaoyu Wang 已提交
311

312
  if (isNullValue(pSchema->type, pToken)) {
X
Xiaoyu Wang 已提交
313
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
D
stmt  
dapan1121 已提交
314
      return buildSyntaxErrMsg(pMsgBuf, "primary timestamp should not be null", pToken->z);
X
Xiaoyu Wang 已提交
315 316
    }

X
Xiaoyu Wang 已提交
317
    return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
318 319
  }

X
Xiaoyu Wang 已提交
320 321 322
  //  strcpy(val->colName, pSchema->name);
  val->cid = pSchema->colId;
  val->type = pSchema->type;
X
Xiaoyu Wang 已提交
323

X
Xiaoyu Wang 已提交
324 325
  switch (pSchema->type) {
    case TSDB_DATA_TYPE_BOOL: {
326
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
X
Xiaoyu Wang 已提交
327
        if (strncmp(pToken->z, "true", pToken->n) == 0) {
X
Xiaoyu Wang 已提交
328
          *(int8_t*)(&val->i64) = TRUE_VALUE;
X
Xiaoyu Wang 已提交
329
        } else if (strncmp(pToken->z, "false", pToken->n) == 0) {
X
Xiaoyu Wang 已提交
330
          *(int8_t*)(&val->i64) = FALSE_VALUE;
X
Xiaoyu Wang 已提交
331 332 333
        } else {
          return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
        }
334
      } else if (pToken->type == TK_NK_INTEGER) {
X
Xiaoyu Wang 已提交
335
        *(int8_t*)(&val->i64) = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
336
      } else if (pToken->type == TK_NK_FLOAT) {
X
Xiaoyu Wang 已提交
337
        *(int8_t*)(&val->i64) = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
X
Xiaoyu Wang 已提交
338 339 340
      } else {
        return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
      }
X
Xiaoyu Wang 已提交
341
      break;
X
Xiaoyu Wang 已提交
342 343 344
    }

    case TSDB_DATA_TYPE_TINYINT: {
X
Xiaoyu Wang 已提交
345
      if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) {
X
Xiaoyu Wang 已提交
346 347 348 349 350
        return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z);
      } else if (!IS_VALID_TINYINT(iv)) {
        return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z);
      }

X
Xiaoyu Wang 已提交
351 352
      *(int8_t*)(&val->i64) = iv;
      break;
X
Xiaoyu Wang 已提交
353 354
    }

H
refact  
Hongze Cheng 已提交
355
    case TSDB_DATA_TYPE_UTINYINT: {
X
Xiaoyu Wang 已提交
356
      if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) {
X
Xiaoyu Wang 已提交
357
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z);
X
Xiaoyu Wang 已提交
358
      } else if (uv > UINT8_MAX) {
X
Xiaoyu Wang 已提交
359 360
        return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z);
      }
X
Xiaoyu Wang 已提交
361 362
      *(uint8_t*)(&val->i64) = uv;
      break;
X
Xiaoyu Wang 已提交
363 364 365
    }

    case TSDB_DATA_TYPE_SMALLINT: {
X
Xiaoyu Wang 已提交
366
      if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) {
X
Xiaoyu Wang 已提交
367 368 369 370
        return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z);
      } else if (!IS_VALID_SMALLINT(iv)) {
        return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z);
      }
X
Xiaoyu Wang 已提交
371 372
      *(int16_t*)(&val->i64) = iv;
      break;
X
Xiaoyu Wang 已提交
373 374 375
    }

    case TSDB_DATA_TYPE_USMALLINT: {
X
Xiaoyu Wang 已提交
376
      if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) {
X
Xiaoyu Wang 已提交
377
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z);
X
Xiaoyu Wang 已提交
378
      } else if (uv > UINT16_MAX) {
X
Xiaoyu Wang 已提交
379 380
        return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z);
      }
X
Xiaoyu Wang 已提交
381 382
      *(uint16_t*)(&val->i64) = uv;
      break;
X
Xiaoyu Wang 已提交
383 384 385
    }

    case TSDB_DATA_TYPE_INT: {
X
Xiaoyu Wang 已提交
386
      if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) {
X
Xiaoyu Wang 已提交
387 388 389 390
        return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z);
      } else if (!IS_VALID_INT(iv)) {
        return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z);
      }
X
Xiaoyu Wang 已提交
391 392
      *(int32_t*)(&val->i64) = iv;
      break;
X
Xiaoyu Wang 已提交
393 394 395
    }

    case TSDB_DATA_TYPE_UINT: {
X
Xiaoyu Wang 已提交
396
      if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) {
X
Xiaoyu Wang 已提交
397
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z);
X
Xiaoyu Wang 已提交
398
      } else if (uv > UINT32_MAX) {
X
Xiaoyu Wang 已提交
399 400
        return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z);
      }
X
Xiaoyu Wang 已提交
401 402
      *(uint32_t*)(&val->i64) = uv;
      break;
X
Xiaoyu Wang 已提交
403 404 405
    }

    case TSDB_DATA_TYPE_BIGINT: {
X
Xiaoyu Wang 已提交
406
      if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) {
X
Xiaoyu Wang 已提交
407 408
        return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z);
      }
X
Xiaoyu Wang 已提交
409 410
      val->i64 = iv;
      break;
X
Xiaoyu Wang 已提交
411 412 413
    }

    case TSDB_DATA_TYPE_UBIGINT: {
X
Xiaoyu Wang 已提交
414
      if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) {
X
Xiaoyu Wang 已提交
415 416
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z);
      }
X
Xiaoyu Wang 已提交
417 418
      *(uint64_t*)(&val->i64) = uv;
      break;
X
Xiaoyu Wang 已提交
419 420 421 422
    }

    case TSDB_DATA_TYPE_FLOAT: {
      double dv;
423
      if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
X
Xiaoyu Wang 已提交
424 425
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
      }
H
refact  
Hongze Cheng 已提交
426 427
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) ||
          isnan(dv)) {
X
Xiaoyu Wang 已提交
428 429
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
      }
X
Xiaoyu Wang 已提交
430 431
      *(float*)(&val->i64) = dv;
      break;
X
Xiaoyu Wang 已提交
432 433 434 435
    }

    case TSDB_DATA_TYPE_DOUBLE: {
      double dv;
436
      if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
X
Xiaoyu Wang 已提交
437 438 439 440 441
        return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
      }
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
        return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
      }
X
Xiaoyu Wang 已提交
442 443 444

      *(double*)(&val->i64) = dv;
      break;
X
Xiaoyu Wang 已提交
445 446 447 448 449
    }

    case TSDB_DATA_TYPE_BINARY: {
      // Too long values will raise the invalid sql error message
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
D
dapan1121 已提交
450
        return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
X
Xiaoyu Wang 已提交
451
      }
452
      val->pData = taosStrdup(pToken->z);
X
Xiaoyu Wang 已提交
453 454
      val->nData = pToken->n;
      break;
X
Xiaoyu Wang 已提交
455 456 457
    }

    case TSDB_DATA_TYPE_NCHAR: {
X
Xiaoyu Wang 已提交
458 459 460 461 462 463 464 465 466 467 468 469 470 471
      int32_t output = 0;
      void*   p = taosMemoryCalloc(1, pSchema->bytes - VARSTR_HEADER_SIZE);
      if (p == NULL) {
        return TSDB_CODE_OUT_OF_MEMORY;
      }
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)(p), pSchema->bytes - VARSTR_HEADER_SIZE, &output)) {
        if (errno == E2BIG) {
          taosMemoryFree(p);
          return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
        }
        char buf[512] = {0};
        snprintf(buf, tListLen(buf), " taosMbsToUcs4 error:%s", strerror(errno));
        taosMemoryFree(p);
        return buildSyntaxErrMsg(pMsgBuf, buf, pToken->z);
472
      }
X
Xiaoyu Wang 已提交
473 474 475
      val->pData = p;
      val->nData = output;
      break;
476
    }
X
Xiaoyu Wang 已提交
477
    case TSDB_DATA_TYPE_TIMESTAMP: {
X
Xiaoyu Wang 已提交
478
      if (parseTime(end, pToken, timePrec, &iv, pMsgBuf) != TSDB_CODE_SUCCESS) {
X
Xiaoyu Wang 已提交
479 480 481
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z);
      }

X
Xiaoyu Wang 已提交
482 483
      val->i64 = iv;
      break;
X
Xiaoyu Wang 已提交
484 485 486
    }
  }

X
Xiaoyu Wang 已提交
487
  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
488 489
}

X
Xiaoyu Wang 已提交
490 491
// input pStmt->pSql:  [(tag1_name, ...)] TAGS (tag1_value, ...) ...
// output pStmt->pSql: TAGS (tag1_value, ...) ...
X
Xiaoyu Wang 已提交
492
static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
493
  insInitBoundColsInfo(getNumOfTags(pStmt->pTableMeta), &pCxt->tags);
494

X
Xiaoyu Wang 已提交
495 496 497 498 499
  SToken  token;
  int32_t index = 0;
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
  if (TK_NK_LP != token.type) {
    return TSDB_CODE_SUCCESS;
500 501
  }

X
Xiaoyu Wang 已提交
502
  pStmt->pSql += index;
X
Xiaoyu Wang 已提交
503
  return parseBoundColumns(pCxt, &pStmt->pSql, true, getTableTagSchema(pStmt->pTableMeta), &pCxt->tags);
X
Xiaoyu Wang 已提交
504
}
505

X
Xiaoyu Wang 已提交
506
static int32_t parseTagValue(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SSchema* pTagSchema, SToken* pToken,
X
Xiaoyu Wang 已提交
507 508 509 510 511 512 513 514
                             SArray* pTagName, SArray* pTagVals, STag** pTag) {
  if (!isNullValue(pTagSchema->type, pToken)) {
    taosArrayPush(pTagName, pTagSchema->name);
  }

  if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
    if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
      return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z);
515 516
    }

X
Xiaoyu Wang 已提交
517 518 519 520 521 522
    if (isNullValue(pTagSchema->type, pToken)) {
      return tTagNew(pTagVals, 1, true, pTag);
    } else {
      return parseJsontoTagData(pToken->z, pTagVals, pTag, &pCxt->msg);
    }
  }
523

X
Xiaoyu Wang 已提交
524 525 526 527 528 529 530 531 532 533
  STagVal val = {0};
  int32_t code =
      parseTagToken(&pStmt->pSql, pToken, pTagSchema, pStmt->pTableMeta->tableInfo.precision, &val, &pCxt->msg);
  if (TSDB_CODE_SUCCESS == code) {
    taosArrayPush(pTagVals, &val);
  }

  return code;
}

X
Xiaoyu Wang 已提交
534
static int32_t buildCreateTbReq(SVnodeModifyOpStmt* pStmt, STag* pTag, SArray* pTagName) {
X
Xiaoyu Wang 已提交
535 536 537 538
  pStmt->pCreateTblReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
  if (NULL == pStmt->pCreateTblReq) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
X
Xiaoyu Wang 已提交
539
  insBuildCreateTbReq(pStmt->pCreateTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid,
X
Xiaoyu Wang 已提交
540 541
                      pStmt->usingTableName.tname, pTagName, pStmt->pTableMeta->tableInfo.numOfTags,
                      TSDB_DEFAULT_TABLE_TTL);
X
Xiaoyu Wang 已提交
542
  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
}

static int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf) {
  if ((pToken->type != TK_NOW && pToken->type != TK_TODAY && pToken->type != TK_NK_INTEGER &&
       pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL &&
       pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT &&
       pToken->type != TK_NK_BIN) ||
      (pToken->n == 0) || (pToken->type == TK_NK_RP)) {
    return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z);
  }

  // Remove quotation marks
  if (TK_NK_STRING == pToken->type) {
    if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) {
      return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z);
558
    }
X
Xiaoyu Wang 已提交
559 560 561 562 563 564 565 566 567 568

    int32_t len = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
    pToken->z = tmpTokenBuf;
    pToken->n = len;
  }

  return TSDB_CODE_SUCCESS;
}

// pSql -> tag1_value, ...)
X
Xiaoyu Wang 已提交
569
static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
  int32_t  code = TSDB_CODE_SUCCESS;
  SSchema* pSchema = getTableTagSchema(pStmt->pTableMeta);
  SArray*  pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal));
  SArray*  pTagName = taosArrayInit(8, TSDB_COL_NAME_LEN);
  SToken   token;
  bool     isParseBindParam = false;
  bool     isJson = false;
  STag*    pTag = NULL;
  for (int i = 0; TSDB_CODE_SUCCESS == code && i < pCxt->tags.numOfBound; ++i) {
    NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);

    if (token.type == TK_NK_QUESTION) {
      isParseBindParam = true;
      if (NULL == pCxt->pComCxt->pStmtCb) {
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", token.z);
        break;
      }

      continue;
589
    }
X
Xiaoyu Wang 已提交
590 591 592 593

    if (isParseBindParam) {
      code = buildInvalidOperationMsg(&pCxt->msg, "no mix usage for ? and tag values");
      break;
594
    }
X
Xiaoyu Wang 已提交
595

X
Xiaoyu Wang 已提交
596
    SSchema* pTagSchema = &pSchema[pCxt->tags.pColIndex[i]];
X
Xiaoyu Wang 已提交
597 598 599 600
    isJson = pTagSchema->type == TSDB_DATA_TYPE_JSON;
    code = checkAndTrimValue(&token, pCxt->tmpTokenBuf, &pCxt->msg);
    if (TSDB_CODE_SUCCESS == code) {
      code = parseTagValue(pCxt, pStmt, pTagSchema, &token, pTagName, pTagVals, &pTag);
C
Cary Xu 已提交
601
    }
602 603
  }

X
Xiaoyu Wang 已提交
604 605 606
  if (TSDB_CODE_SUCCESS == code && !isParseBindParam && !isJson) {
    code = tTagNew(pTagVals, 1, false, &pTag);
  }
607

X
Xiaoyu Wang 已提交
608
  if (TSDB_CODE_SUCCESS == code && !isParseBindParam) {
X
Xiaoyu Wang 已提交
609
    code = buildCreateTbReq(pStmt, pTag, pTagName);
X
Xiaoyu Wang 已提交
610 611 612 613 614 615 616
    pTag = NULL;
  }

  for (int i = 0; i < taosArrayGetSize(pTagVals); ++i) {
    STagVal* p = (STagVal*)taosArrayGet(pTagVals, i);
    if (IS_VAR_DATA_TYPE(p->type)) {
      taosMemoryFreeClear(p->pData);
617
    }
X
Xiaoyu Wang 已提交
618 619 620 621 622 623 624 625 626
  }
  taosArrayDestroy(pTagVals);
  taosArrayDestroy(pTagName);
  tTagFree(pTag);
  return code;
}

// input pStmt->pSql:  TAGS (tag1_value, ...) [table_options] ...
// output pStmt->pSql: [table_options] ...
X
Xiaoyu Wang 已提交
627
static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
  SToken token;
  NEXT_TOKEN(pStmt->pSql, token);
  if (TK_TAGS != token.type) {
    return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
  }

  NEXT_TOKEN(pStmt->pSql, token);
  if (TK_NK_LP != token.type) {
    return buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
  }

  int32_t code = parseTagsClauseImpl(pCxt, pStmt);
  if (TSDB_CODE_SUCCESS == code) {
    NEXT_VALID_TOKEN(pStmt->pSql, token);
    if (TK_NK_COMMA == token.type) {
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
    } else if (TK_NK_RP != token.type) {
      code = buildSyntaxErrMsg(&pCxt->msg, ") is expected", token.z);
646 647
    }
  }
X
Xiaoyu Wang 已提交
648 649
  return code;
}
650

X
Xiaoyu Wang 已提交
651
static int32_t storeTableMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
652
  pStmt->pTableMeta->suid = pStmt->pTableMeta->uid;
X
Xiaoyu Wang 已提交
653 654 655 656 657 658
  pStmt->pTableMeta->uid = pStmt->totalTbNum;
  pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;

  STableMeta* pBackup = NULL;
  if (TSDB_CODE_SUCCESS != cloneTableMeta(pStmt->pTableMeta, &pBackup)) {
    return TSDB_CODE_OUT_OF_MEMORY;
659
  }
660

X
Xiaoyu Wang 已提交
661 662 663 664 665
  char tbFName[TSDB_TABLE_FNAME_LEN];
  tNameExtractFullName(&pStmt->targetTableName, tbFName);
  return taosHashPut(pStmt->pSubTableHashObj, tbFName, strlen(tbFName), &pBackup, POINTER_BYTES);
}

X
Xiaoyu Wang 已提交
666
static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
667 668 669 670 671 672 673 674 675 676
  do {
    int32_t index = 0;
    SToken  token;
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
    if (TK_TTL == token.type) {
      pStmt->pSql += index;
      NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
      if (TK_NK_INTEGER != token.type) {
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
      }
X
Xiaoyu Wang 已提交
677 678
      pStmt->pCreateTblReq->ttl = taosStr2Int32(token.z, NULL, 10);
      if (pStmt->pCreateTblReq->ttl < 0) {
X
Xiaoyu Wang 已提交
679 680 681 682 683 684 685 686 687 688 689 690
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
      }
    } else if (TK_COMMENT == token.type) {
      pStmt->pSql += index;
      NEXT_TOKEN(pStmt->pSql, token);
      if (TK_NK_STRING != token.type) {
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option comment", token.z);
      }
      if (token.n >= TSDB_TB_COMMENT_LEN) {
        return buildSyntaxErrMsg(&pCxt->msg, "comment too long", token.z);
      }
      int32_t len = trimString(token.z, token.n, pCxt->tmpTokenBuf, TSDB_TB_COMMENT_LEN);
X
Xiaoyu Wang 已提交
691 692
      pStmt->pCreateTblReq->comment = strndup(pCxt->tmpTokenBuf, len);
      if (NULL == pStmt->pCreateTblReq->comment) {
X
Xiaoyu Wang 已提交
693 694
        return TSDB_CODE_OUT_OF_MEMORY;
      }
X
Xiaoyu Wang 已提交
695
      pStmt->pCreateTblReq->commentLen = len;
X
Xiaoyu Wang 已提交
696 697 698 699
    } else {
      break;
    }
  } while (1);
700 701 702
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
703 704 705 706 707 708
// input pStmt->pSql:
//   1. [(tag1_name, ...)] ...
//   2. VALUES ... | FILE ...
// output pStmt->pSql:
//   1. [(field1_name, ...)]
//   2. VALUES ... | FILE ...
X
Xiaoyu Wang 已提交
709
static int32_t parseUsingClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
710
  if (!pStmt->usingTableProcessing || pCxt->usingDuplicateTable) {
X
Xiaoyu Wang 已提交
711 712
    return TSDB_CODE_SUCCESS;
  }
wmmhello's avatar
wmmhello 已提交
713

X
Xiaoyu Wang 已提交
714 715 716 717 718 719 720 721 722 723 724
  int32_t code = parseBoundTagsClause(pCxt, pStmt);
  if (TSDB_CODE_SUCCESS == code) {
    code = parseTagsClause(pCxt, pStmt);
  }
  if (TSDB_CODE_SUCCESS == code) {
    code = parseTableOptions(pCxt, pStmt);
  }

  return code;
}

X
Xiaoyu Wang 已提交
725
static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool* pMissCache) {
X
Xiaoyu Wang 已提交
726 727
  char dbFName[TSDB_DB_FNAME_LEN];
  tNameGetFullDbName(pTbName, dbFName);
X
Xiaoyu Wang 已提交
728 729 730
  int32_t code = TSDB_CODE_SUCCESS;
  bool    pass = true;
  bool    exists = true;
X
Xiaoyu Wang 已提交
731
  if (pCxt->async) {
X
Xiaoyu Wang 已提交
732
    code = catalogChkAuthFromCache(pCxt->pCatalog, pCxt->pUser, dbFName, AUTH_TYPE_WRITE, &pass, &exists);
X
Xiaoyu Wang 已提交
733
  } else {
X
Xiaoyu Wang 已提交
734 735 736 737
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
                             .requestId = pCxt->requestId,
                             .requestObjRefId = pCxt->requestRid,
                             .mgmtEps = pCxt->mgmtEpSet};
X
Xiaoyu Wang 已提交
738 739
    code = catalogChkAuth(pCxt->pCatalog, &conn, pCxt->pUser, dbFName, AUTH_TYPE_WRITE, &pass);
  }
X
Xiaoyu Wang 已提交
740 741 742 743 744 745
  if (TSDB_CODE_SUCCESS == code) {
    if (!exists) {
      *pMissCache = true;
    } else if (!pass) {
      code = TSDB_CODE_PAR_PERMISSION_DENIED;
    }
X
Xiaoyu Wang 已提交
746 747 748 749 750 751
  }
  return code;
}

static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, bool isStb, STableMeta** pTableMeta,
                            bool* pMissCache) {
X
Xiaoyu Wang 已提交
752 753
  SParseContext* pComCxt = pCxt->pComCxt;
  int32_t        code = TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
754 755
  if (pComCxt->async) {
    if (isStb) {
X
Xiaoyu Wang 已提交
756
      code = catalogGetCachedSTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
X
Xiaoyu Wang 已提交
757
    } else {
X
Xiaoyu Wang 已提交
758
      code = catalogGetCachedTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
X
Xiaoyu Wang 已提交
759 760
    }
  } else {
X
Xiaoyu Wang 已提交
761 762 763 764
    SRequestConnInfo conn = {.pTrans = pComCxt->pTransporter,
                             .requestId = pComCxt->requestId,
                             .requestObjRefId = pComCxt->requestRid,
                             .mgmtEps = pComCxt->mgmtEpSet};
X
Xiaoyu Wang 已提交
765 766 767 768
    if (isStb) {
      code = catalogGetSTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
    } else {
      code = catalogGetTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
wmmhello's avatar
wmmhello 已提交
769
    }
X
Xiaoyu Wang 已提交
770 771 772 773 774 775
  }
  if (TSDB_CODE_SUCCESS == code) {
    if (NULL == *pTableMeta) {
      *pMissCache = true;
    } else if (isStb && TSDB_SUPER_TABLE != (*pTableMeta)->tableType) {
      code = buildInvalidOperationMsg(&pCxt->msg, "create table only from super table is allowed");
X
Xiaoyu Wang 已提交
776 777
    } else if (!isStb && TSDB_SUPER_TABLE == (*pTableMeta)->tableType) {
      code = buildInvalidOperationMsg(&pCxt->msg, "insert data into super table is not supported");
X
Xiaoyu Wang 已提交
778 779 780 781 782
    }
  }
  return code;
}

X
Xiaoyu Wang 已提交
783
static int32_t getTableVgroup(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool isStb, bool* pMissCache) {
X
Xiaoyu Wang 已提交
784 785 786
  int32_t     code = TSDB_CODE_SUCCESS;
  SVgroupInfo vg;
  bool        exists = true;
X
Xiaoyu Wang 已提交
787
  if (pCxt->async) {
X
Xiaoyu Wang 已提交
788
    code = catalogGetCachedTableHashVgroup(pCxt->pCatalog, &pStmt->targetTableName, &vg, &exists);
X
Xiaoyu Wang 已提交
789
  } else {
X
Xiaoyu Wang 已提交
790 791 792 793
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
                             .requestId = pCxt->requestId,
                             .requestObjRefId = pCxt->requestRid,
                             .mgmtEps = pCxt->mgmtEpSet};
X
Xiaoyu Wang 已提交
794 795 796 797 798 799 800 801 802 803 804 805 806
    code = catalogGetTableHashVgroup(pCxt->pCatalog, &conn, &pStmt->targetTableName, &vg);
  }
  if (TSDB_CODE_SUCCESS == code) {
    if (exists) {
      if (isStb) {
        pStmt->pTableMeta->vgId = vg.vgId;
      }
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
    }
    *pMissCache = !exists;
  }
  return code;
}
807

X
Xiaoyu Wang 已提交
808
static int32_t getTableMetaAndVgroupImpl(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) {
809
  SVgroupInfo vg;
810
  int32_t     code = catalogGetCachedTableVgMeta(pCxt->pCatalog, &pStmt->targetTableName, &vg, &pStmt->pTableMeta);
811
  if (TSDB_CODE_SUCCESS == code) {
812
    if (NULL != pStmt->pTableMeta) {
813 814
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
    }
815
    *pMissCache = (NULL == pStmt->pTableMeta);
816 817 818 819
  }
  return code;
}

X
Xiaoyu Wang 已提交
820
static int32_t getTableMetaAndVgroup(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) {
821 822 823
  SParseContext* pComCxt = pCxt->pComCxt;
  int32_t        code = TSDB_CODE_SUCCESS;
  if (pComCxt->async) {
D
dapan1121 已提交
824
    code = getTableMetaAndVgroupImpl(pComCxt, pStmt, pMissCache);
825 826 827 828 829 830 831 832 833
  } else {
    code = getTableMeta(pCxt, &pStmt->targetTableName, false, &pStmt->pTableMeta, pMissCache);
    if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
      code = getTableVgroup(pCxt->pComCxt, pStmt, false, &pCxt->missCache);
    }
  }
  return code;
}

834 835 836 837 838 839 840 841 842 843 844 845
static int32_t collectUseTable(const SName* pName, SHashObj* pTable) {
  char fullName[TSDB_TABLE_FNAME_LEN];
  tNameExtractFullName(pName, fullName);
  return taosHashPut(pTable, fullName, strlen(fullName), pName, sizeof(SName));
}

static int32_t collectUseDatabase(const SName* pName, SHashObj* pDbs) {
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
  tNameGetFullDbName(pName, dbFName);
  return taosHashPut(pDbs, dbFName, strlen(dbFName), dbFName, sizeof(dbFName));
}

X
Xiaoyu Wang 已提交
846
static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
847 848 849 850 851
  if (pCxt->forceUpdate) {
    pCxt->missCache = true;
    return TSDB_CODE_SUCCESS;
  }

X
Xiaoyu Wang 已提交
852 853
  int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache);
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
854
    code = getTableMetaAndVgroup(pCxt, pStmt, &pCxt->missCache);
X
Xiaoyu Wang 已提交
855
  }
856
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
857
    code = collectUseDatabase(&pStmt->targetTableName, pStmt->pDbFNameHashObj);
858 859 860
    if (TSDB_CODE_SUCCESS == code) {
      code = collectUseTable(&pStmt->targetTableName, pStmt->pTableNameHashObj);
    }
861
  }
X
Xiaoyu Wang 已提交
862 863 864
  return code;
}

X
Xiaoyu Wang 已提交
865
static int32_t preParseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
X
Xiaoyu Wang 已提交
866 867 868
  return insCreateSName(&pStmt->usingTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
}

X
Xiaoyu Wang 已提交
869
static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
870 871 872 873 874
  if (pCxt->forceUpdate) {
    pCxt->missCache = true;
    return TSDB_CODE_SUCCESS;
  }

X
Xiaoyu Wang 已提交
875 876
  int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache);
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
X
Xiaoyu Wang 已提交
877 878 879 880 881
    code = getTableMeta(pCxt, &pStmt->usingTableName, true, &pStmt->pTableMeta, &pCxt->missCache);
  }
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
    code = getTableVgroup(pCxt->pComCxt, pStmt, true, &pCxt->missCache);
  }
882 883 884 885 886 887
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
    code = collectUseDatabase(&pStmt->usingTableName, pStmt->pDbFNameHashObj);
    if (TSDB_CODE_SUCCESS == code) {
      code = collectUseTable(&pStmt->usingTableName, pStmt->pTableNameHashObj);
    }
  }
X
Xiaoyu Wang 已提交
888 889 890
  return code;
}

X
Xiaoyu Wang 已提交
891
static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
892 893 894 895 896 897
  SToken token;
  NEXT_TOKEN(pStmt->pSql, token);
  int32_t code = preParseUsingTableName(pCxt, pStmt, &token);
  if (TSDB_CODE_SUCCESS == code) {
    code = getUsingTableSchema(pCxt, pStmt);
  }
X
Xiaoyu Wang 已提交
898
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
X
Xiaoyu Wang 已提交
899 900 901 902 903 904 905 906 907 908 909
    code = storeTableMeta(pCxt, pStmt);
  }
  return code;
}

// input pStmt->pSql:
//   1(care). [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
//   2. VALUES ... | FILE ...
// output pStmt->pSql:
//   1. [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
//   2. VALUES ... | FILE ...
X
Xiaoyu Wang 已提交
910
static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
911 912 913 914 915 916 917
  SToken  token;
  int32_t index = 0;
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
  if (TK_USING != token.type) {
    return getTargetTableSchema(pCxt, pStmt);
  }

X
Xiaoyu Wang 已提交
918
  pStmt->usingTableProcessing = true;
X
Xiaoyu Wang 已提交
919 920
  // pStmt->pSql -> stb_name [(tag1_name, ...)
  pStmt->pSql += index;
X
Xiaoyu Wang 已提交
921 922
  int32_t code = parseDuplicateUsingClause(pCxt, pStmt, &pCxt->usingDuplicateTable);
  if (TSDB_CODE_SUCCESS == code && !pCxt->usingDuplicateTable) {
X
Xiaoyu Wang 已提交
923 924 925 926 927
    return parseUsingTableNameImpl(pCxt, pStmt);
  }
  return code;
}

X
Xiaoyu Wang 已提交
928
static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
X
Xiaoyu Wang 已提交
929 930 931 932 933 934 935 936 937 938
  return insCreateSName(&pStmt->targetTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
}

// input pStmt->pSql:
//   1(care). [(field1_name, ...)] ...
//   2. [ USING ... ] ...
//   3. VALUES ... | FILE ...
// output pStmt->pSql:
//   1. [ USING ... ] ...
//   2. VALUES ... | FILE ...
X
Xiaoyu Wang 已提交
939
static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
940 941 942 943
  SToken  token;
  int32_t index = 0;
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
  if (TK_NK_LP != token.type) {
944 945 946
    return TSDB_CODE_SUCCESS;
  }

X
Xiaoyu Wang 已提交
947 948 949 950 951 952
  // pStmt->pSql -> field1_name, ...)
  pStmt->pSql += index;
  pStmt->pBoundCols = pStmt->pSql;
  return skipParentheses(pCxt, &pStmt->pSql);
}

X
Xiaoyu Wang 已提交
953
static int32_t getTableDataCxt(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt** pTableCxt) {
X
Xiaoyu Wang 已提交
954
  if (pCxt->pComCxt->async) {
X
Xiaoyu Wang 已提交
955 956
    return insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid),
                              pStmt->pTableMeta, &pStmt->pCreateTblReq, pTableCxt, false);
X
Xiaoyu Wang 已提交
957
  }
X
Xiaoyu Wang 已提交
958

X
Xiaoyu Wang 已提交
959 960
  char tbFName[TSDB_TABLE_FNAME_LEN];
  tNameExtractFullName(&pStmt->targetTableName, tbFName);
D
dapan1121 已提交
961 962 963
  if (pStmt->usingTableProcessing) {
    pStmt->pTableMeta->uid = 0;
  }
X
Xiaoyu Wang 已提交
964
  return insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
D
dapan1121 已提交
965
                            &pStmt->pCreateTblReq, pTableCxt, NULL != pCxt->pComCxt->pStmtCb);
X
Xiaoyu Wang 已提交
966 967
}

X
Xiaoyu Wang 已提交
968
static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) {
X
Xiaoyu Wang 已提交
969 970 971 972 973 974 975 976 977
  SToken  token;
  int32_t index = 0;
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
  if (TK_NK_LP == token.type) {
    pStmt->pSql += index;
    if (NULL != pStmt->pBoundCols) {
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
    }
    // pStmt->pSql -> field1_name, ...)
X
Xiaoyu Wang 已提交
978 979
    return parseBoundColumns(pCxt, &pStmt->pSql, false, getTableColumnSchema(pStmt->pTableMeta),
                             &pTableCxt->boundColsInfo);
X
Xiaoyu Wang 已提交
980 981 982
  }

  if (NULL != pStmt->pBoundCols) {
X
Xiaoyu Wang 已提交
983 984
    return parseBoundColumns(pCxt, &pStmt->pBoundCols, false, getTableColumnSchema(pStmt->pTableMeta),
                             &pTableCxt->boundColsInfo);
X
Xiaoyu Wang 已提交
985 986 987 988 989
  }

  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
990 991 992 993 994 995
int32_t initTableColSubmitData(STableDataCxt* pTableCxt) {
  if (0 == (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT)) {
    return TSDB_CODE_SUCCESS;
  }

  for (int32_t i = 0; i < pTableCxt->boundColsInfo.numOfBound; ++i) {
X
Xiaoyu Wang 已提交
996
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
D
dapan1121 已提交
997 998 999 1000 1001 1002 1003 1004 1005 1006
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
    if (NULL == pCol) {
      return TSDB_CODE_OUT_OF_MEMORY;
    }
    tColDataInit(pCol, pSchema->colId, pSchema->type, 0);
  }

  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
1007 1008 1009 1010
// input pStmt->pSql:
//   1. [(tag1_name, ...)] ...
//   2. VALUES ... | FILE ...
// output pStmt->pSql: VALUES ... | FILE ...
X
Xiaoyu Wang 已提交
1011
static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
X
Xiaoyu Wang 已提交
1012
                                       STableDataCxt** pTableCxt) {
X
Xiaoyu Wang 已提交
1013 1014
  int32_t code = parseUsingClauseBottom(pCxt, pStmt);
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1015
    code = getTableDataCxt(pCxt, pStmt, pTableCxt);
X
Xiaoyu Wang 已提交
1016 1017
  }
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1018
    code = parseBoundColumnsClause(pCxt, pStmt, *pTableCxt);
X
Xiaoyu Wang 已提交
1019
  }
D
dapan1121 已提交
1020 1021 1022
  if (TSDB_CODE_SUCCESS == code) {
    code = initTableColSubmitData(*pTableCxt);
  }
X
Xiaoyu Wang 已提交
1023 1024 1025 1026 1027 1028 1029
  return code;
}

// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
// output pStmt->pSql:
//   1. [(tag1_name, ...)] ...
//   2. VALUES ... | FILE ...
X
Xiaoyu Wang 已提交
1030
static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
X
Xiaoyu Wang 已提交
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
  int32_t code = preParseTargetTableName(pCxt, pStmt, pTbName);
  if (TSDB_CODE_SUCCESS == code) {
    // option: [(field1_name, ...)]
    code = preParseBoundColumnsClause(pCxt, pStmt);
  }
  if (TSDB_CODE_SUCCESS == code) {
    // option: [USING stb_name]
    code = parseUsingTableName(pCxt, pStmt);
  }
  return code;
}

static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
X
Xiaoyu Wang 已提交
1044
                                   int16_t timePrec, SColVal* pVal) {
wmmhello's avatar
wmmhello 已提交
1045 1046 1047 1048
  switch (pSchema->type) {
    case TSDB_DATA_TYPE_BOOL: {
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
        if (strncmp(pToken->z, "true", pToken->n) == 0) {
X
Xiaoyu Wang 已提交
1049
          pVal->value.val = TRUE_VALUE;
wmmhello's avatar
wmmhello 已提交
1050
        } else if (strncmp(pToken->z, "false", pToken->n) == 0) {
X
Xiaoyu Wang 已提交
1051
          pVal->value.val = FALSE_VALUE;
wmmhello's avatar
wmmhello 已提交
1052
        } else {
X
Xiaoyu Wang 已提交
1053
          return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
wmmhello's avatar
wmmhello 已提交
1054 1055
        }
      } else if (pToken->type == TK_NK_INTEGER) {
X
Xiaoyu Wang 已提交
1056
        pVal->value.val = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
wmmhello's avatar
wmmhello 已提交
1057
      } else if (pToken->type == TK_NK_FLOAT) {
X
Xiaoyu Wang 已提交
1058
        pVal->value.val = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
wmmhello's avatar
wmmhello 已提交
1059
      } else {
X
Xiaoyu Wang 已提交
1060
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
D
dapan1121 已提交
1061
      }
X
Xiaoyu Wang 已提交
1062
      break;
wmmhello's avatar
wmmhello 已提交
1063 1064
    }
    case TSDB_DATA_TYPE_TINYINT: {
X
Xiaoyu Wang 已提交
1065
      if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
X
Xiaoyu Wang 已提交
1066
        return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z);
X
Xiaoyu Wang 已提交
1067
      } else if (!IS_VALID_TINYINT(pVal->value.val)) {
X
Xiaoyu Wang 已提交
1068
        return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z);
D
dapan1121 已提交
1069
      }
X
Xiaoyu Wang 已提交
1070
      break;
1071
    }
wmmhello's avatar
wmmhello 已提交
1072
    case TSDB_DATA_TYPE_UTINYINT: {
X
Xiaoyu Wang 已提交
1073
      if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
X
Xiaoyu Wang 已提交
1074
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z);
X
Xiaoyu Wang 已提交
1075
      } else if (pVal->value.val > UINT8_MAX) {
X
Xiaoyu Wang 已提交
1076
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z);
wmmhello's avatar
wmmhello 已提交
1077
      }
X
Xiaoyu Wang 已提交
1078
      break;
wmmhello's avatar
wmmhello 已提交
1079 1080
    }
    case TSDB_DATA_TYPE_SMALLINT: {
X
Xiaoyu Wang 已提交
1081
      if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
X
Xiaoyu Wang 已提交
1082
        return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z);
X
Xiaoyu Wang 已提交
1083
      } else if (!IS_VALID_SMALLINT(pVal->value.val)) {
X
Xiaoyu Wang 已提交
1084
        return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z);
wmmhello's avatar
wmmhello 已提交
1085
      }
X
Xiaoyu Wang 已提交
1086
      break;
wmmhello's avatar
wmmhello 已提交
1087 1088
    }
    case TSDB_DATA_TYPE_USMALLINT: {
X
Xiaoyu Wang 已提交
1089
      if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
X
Xiaoyu Wang 已提交
1090
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z);
X
Xiaoyu Wang 已提交
1091
      } else if (pVal->value.val > UINT16_MAX) {
X
Xiaoyu Wang 已提交
1092
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z);
wmmhello's avatar
wmmhello 已提交
1093
      }
X
Xiaoyu Wang 已提交
1094
      break;
wmmhello's avatar
wmmhello 已提交
1095 1096
    }
    case TSDB_DATA_TYPE_INT: {
X
Xiaoyu Wang 已提交
1097
      if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
X
Xiaoyu Wang 已提交
1098
        return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z);
X
Xiaoyu Wang 已提交
1099
      } else if (!IS_VALID_INT(pVal->value.val)) {
X
Xiaoyu Wang 已提交
1100
        return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z);
wmmhello's avatar
wmmhello 已提交
1101
      }
X
Xiaoyu Wang 已提交
1102
      break;
wmmhello's avatar
wmmhello 已提交
1103 1104
    }
    case TSDB_DATA_TYPE_UINT: {
X
Xiaoyu Wang 已提交
1105
      if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
X
Xiaoyu Wang 已提交
1106
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z);
X
Xiaoyu Wang 已提交
1107
      } else if (pVal->value.val > UINT32_MAX) {
X
Xiaoyu Wang 已提交
1108
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z);
wmmhello's avatar
wmmhello 已提交
1109
      }
X
Xiaoyu Wang 已提交
1110
      break;
wmmhello's avatar
wmmhello 已提交
1111 1112
    }
    case TSDB_DATA_TYPE_BIGINT: {
X
Xiaoyu Wang 已提交
1113
      if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
X
Xiaoyu Wang 已提交
1114
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z);
wmmhello's avatar
wmmhello 已提交
1115
      }
X
Xiaoyu Wang 已提交
1116
      break;
wmmhello's avatar
wmmhello 已提交
1117 1118
    }
    case TSDB_DATA_TYPE_UBIGINT: {
X
Xiaoyu Wang 已提交
1119
      if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
X
Xiaoyu Wang 已提交
1120
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z);
wmmhello's avatar
wmmhello 已提交
1121
      }
X
Xiaoyu Wang 已提交
1122
      break;
wmmhello's avatar
wmmhello 已提交
1123 1124
    }
    case TSDB_DATA_TYPE_FLOAT: {
X
Xiaoyu Wang 已提交
1125
      char*  endptr = NULL;
wmmhello's avatar
wmmhello 已提交
1126 1127
      double dv;
      if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
X
Xiaoyu Wang 已提交
1128
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
wmmhello's avatar
wmmhello 已提交
1129 1130 1131
      }
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) ||
          isnan(dv)) {
X
Xiaoyu Wang 已提交
1132
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
wmmhello's avatar
wmmhello 已提交
1133
      }
X
Xiaoyu Wang 已提交
1134 1135
      float f = dv;
      memcpy(&pVal->value.val, &f, sizeof(f));
X
Xiaoyu Wang 已提交
1136
      break;
wmmhello's avatar
wmmhello 已提交
1137 1138
    }
    case TSDB_DATA_TYPE_DOUBLE: {
X
Xiaoyu Wang 已提交
1139
      char*  endptr = NULL;
wmmhello's avatar
wmmhello 已提交
1140 1141
      double dv;
      if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
X
Xiaoyu Wang 已提交
1142
        return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
wmmhello's avatar
wmmhello 已提交
1143 1144
      }
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
X
Xiaoyu Wang 已提交
1145
        return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
wmmhello's avatar
wmmhello 已提交
1146
      }
X
Xiaoyu Wang 已提交
1147 1148
      pVal->value.val = *(int64_t*)&dv;
      break;
wmmhello's avatar
wmmhello 已提交
1149 1150 1151 1152
    }
    case TSDB_DATA_TYPE_BINARY: {
      // Too long values will raise the invalid sql error message
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
X
Xiaoyu Wang 已提交
1153
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
D
stmt  
dapan1121 已提交
1154
      }
X
Xiaoyu Wang 已提交
1155 1156 1157 1158 1159
      pVal->value.pData = taosMemoryMalloc(pToken->n);
      if (NULL == pVal->value.pData) {
        return TSDB_CODE_OUT_OF_MEMORY;
      }
      memcpy(pVal->value.pData, pToken->z, pToken->n);
X
Xiaoyu Wang 已提交
1160 1161
      pVal->value.nData = pToken->n;
      break;
X
Xiaoyu Wang 已提交
1162
    }
X
Xiaoyu Wang 已提交
1163
    case TSDB_DATA_TYPE_NCHAR: {
X
Xiaoyu Wang 已提交
1164 1165 1166 1167 1168 1169 1170
      // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
      int32_t len = 0;
      char*   pUcs4 = taosMemoryCalloc(1, pSchema->bytes - VARSTR_HEADER_SIZE);
      if (NULL == pUcs4) {
        return TSDB_CODE_OUT_OF_MEMORY;
      }
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)pUcs4, pSchema->bytes - VARSTR_HEADER_SIZE, &len)) {
1171
        taosMemoryFree(pUcs4);
X
Xiaoyu Wang 已提交
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
        if (errno == E2BIG) {
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
        }
        char buf[512] = {0};
        snprintf(buf, tListLen(buf), "%s", strerror(errno));
        return buildSyntaxErrMsg(&pCxt->msg, buf, pToken->z);
      }
      pVal->value.pData = pUcs4;
      pVal->value.nData = len;
      break;
1182
    }
X
Xiaoyu Wang 已提交
1183 1184 1185
    case TSDB_DATA_TYPE_JSON: {
      if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
        return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z);
1186
      }
X
Xiaoyu Wang 已提交
1187 1188 1189 1190 1191
      pVal->value.pData = taosMemoryMalloc(pToken->n);
      if (NULL == pVal->value.pData) {
        return TSDB_CODE_OUT_OF_MEMORY;
      }
      memcpy(pVal->value.pData, pToken->z, pToken->n);
X
Xiaoyu Wang 已提交
1192 1193
      pVal->value.nData = pToken->n;
      break;
1194
    }
X
Xiaoyu Wang 已提交
1195
    case TSDB_DATA_TYPE_TIMESTAMP: {
X
Xiaoyu Wang 已提交
1196
      if (parseTime(pSql, pToken, timePrec, &pVal->value.val, &pCxt->msg) != TSDB_CODE_SUCCESS) {
X
Xiaoyu Wang 已提交
1197 1198
        return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z);
      }
X
Xiaoyu Wang 已提交
1199
      break;
X
Xiaoyu Wang 已提交
1200
    }
X
Xiaoyu Wang 已提交
1201 1202
    default:
      return TSDB_CODE_FAILED;
X
Xiaoyu Wang 已提交
1203
  }
1204

X
Xiaoyu Wang 已提交
1205
  pVal->flag = CV_FLAG_VALUE;
X
Xiaoyu Wang 已提交
1206
  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
1207
}
D
dapan 已提交
1208

X
Xiaoyu Wang 已提交
1209
static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
X
Xiaoyu Wang 已提交
1210
                               int16_t timePrec, SColVal* pVal) {
X
Xiaoyu Wang 已提交
1211 1212 1213 1214 1215
  int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg);
  if (TSDB_CODE_SUCCESS == code && isNullValue(pSchema->type, pToken)) {
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
      return buildSyntaxErrMsg(&pCxt->msg, "primary timestamp should not be null", pToken->z);
    }
X
Xiaoyu Wang 已提交
1216 1217
    pVal->flag = CV_FLAG_NULL;
    return TSDB_CODE_SUCCESS;
1218 1219
  }

X
Xiaoyu Wang 已提交
1220 1221
  if (TSDB_CODE_SUCCESS == code && IS_NUMERIC_TYPE(pSchema->type) && pToken->n == 0) {
    return buildSyntaxErrMsg(&pCxt->msg, "invalid numeric data", pToken->z);
1222 1223
  }

X
Xiaoyu Wang 已提交
1224
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1225
    code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, timePrec, pVal);
X
Xiaoyu Wang 已提交
1226
  }
1227

X
Xiaoyu Wang 已提交
1228
  return code;
1229 1230
}

X
Xiaoyu Wang 已提交
1231 1232 1233 1234
static void clearColValArray(SArray* pCols) {
  int32_t num = taosArrayGetSize(pCols);
  for (int32_t i = 0; i < num; ++i) {
    SColVal* pCol = taosArrayGet(pCols, i);
X
Xiaoyu Wang 已提交
1235
    if (IS_VAR_DATA_TYPE(pCol->type)) {
X
Xiaoyu Wang 已提交
1236 1237 1238 1239 1240
      taosMemoryFreeClear(pCol->value.pData);
    }
  }
}

X
Xiaoyu Wang 已提交
1241
static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow,
X
Xiaoyu Wang 已提交
1242
                       SToken* pToken) {
X
Xiaoyu Wang 已提交
1243 1244 1245 1246 1247
  SBoundColInfo* pCols = &pTableCxt->boundColsInfo;
  bool           isParseBindParam = false;
  SSchema*       pSchemas = getTableColumnSchema(pTableCxt->pMeta);

  int32_t code = TSDB_CODE_SUCCESS;
1248
  // 1. set the parsed value from sql string
X
Xiaoyu Wang 已提交
1249
  for (int i = 0; i < pCols->numOfBound && TSDB_CODE_SUCCESS == code; ++i) {
X
Xiaoyu Wang 已提交
1250 1251 1252 1253 1254
    const char* pOrigSql = *pSql;
    bool        ignoreComma = false;
    NEXT_TOKEN_WITH_PREV_EXT(*pSql, *pToken, &ignoreComma);
    if (ignoreComma) {
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pOrigSql);
X
Xiaoyu Wang 已提交
1255
      break;
X
Xiaoyu Wang 已提交
1256
    }
D
stmt  
dapan1121 已提交
1257

X
Xiaoyu Wang 已提交
1258 1259
    SSchema* pSchema = &pSchemas[pCols->pColIndex[i]];
    SColVal* pVal = taosArrayGet(pTableCxt->pValues, pCols->pColIndex[i]);
D
stmt  
dapan1121 已提交
1260

X
Xiaoyu Wang 已提交
1261
    if (pToken->type == TK_NK_QUESTION) {
D
stmt  
dapan1121 已提交
1262
      isParseBindParam = true;
X
Xiaoyu Wang 已提交
1263 1264
      if (NULL == pCxt->pComCxt->pStmtCb) {
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pToken->z);
X
Xiaoyu Wang 已提交
1265 1266 1267 1268 1269 1270
        break;
      }
    } else {
      if (TK_NK_RP == pToken->type) {
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
        break;
D
stmt  
dapan1121 已提交
1271
      }
D
dapan1121 已提交
1272

X
Xiaoyu Wang 已提交
1273 1274 1275 1276
      if (isParseBindParam) {
        code = buildInvalidOperationMsg(&pCxt->msg, "no mix usage for ? and values");
        break;
      }
X
Xiaoyu Wang 已提交
1277

X
Xiaoyu Wang 已提交
1278 1279 1280
      if (TSDB_CODE_SUCCESS == code) {
        code = parseValueToken(pCxt, pSql, pToken, pSchema, getTableInfo(pTableCxt->pMeta).precision, pVal);
      }
X
Xiaoyu Wang 已提交
1281
    }
1282

X
Xiaoyu Wang 已提交
1283 1284 1285 1286
    if (TSDB_CODE_SUCCESS == code && i < pCols->numOfBound - 1) {
      NEXT_VALID_TOKEN(*pSql, *pToken);
      if (TK_NK_COMMA != pToken->type) {
        code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
X
Xiaoyu Wang 已提交
1287 1288
      }
    }
1289 1290
  }

D
dapan1121 已提交
1291
  if (TSDB_CODE_SUCCESS == code && !isParseBindParam) {
X
Xiaoyu Wang 已提交
1292
    SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1);
X
Xiaoyu Wang 已提交
1293
    code = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow);
X
Xiaoyu Wang 已提交
1294 1295 1296
    if (TSDB_CODE_SUCCESS == code) {
      insCheckTableDataOrder(pTableCxt, TD_ROW_KEY(*pRow));
    }
X
Xiaoyu Wang 已提交
1297
  }
1298

X
Xiaoyu Wang 已提交
1299 1300
  if (TSDB_CODE_SUCCESS == code && !isParseBindParam) {
    *pGotRow = true;
1301 1302
  }

X
Xiaoyu Wang 已提交
1303 1304
  clearColValArray(pTableCxt->pValues);

X
Xiaoyu Wang 已提交
1305
  return code;
1306 1307 1308
}

// pSql -> (field1_value, ...) [(field1_value2, ...) ...]
X
Xiaoyu Wang 已提交
1309
static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt,
X
Xiaoyu Wang 已提交
1310 1311
                           int32_t* pNumOfRows, SToken* pToken) {
  int32_t code = TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
1312 1313 1314

  (*pNumOfRows) = 0;
  while (TSDB_CODE_SUCCESS == code) {
1315
    int32_t index = 0;
X
Xiaoyu Wang 已提交
1316 1317
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, *pToken, index);
    if (TK_NK_LP != pToken->type) {
1318 1319
      break;
    }
X
Xiaoyu Wang 已提交
1320
    pStmt->pSql += index;
1321

D
stmt  
dapan1121 已提交
1322
    bool gotRow = false;
X
Xiaoyu Wang 已提交
1323
    if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1324
      code = parseOneRow(pCxt, &pStmt->pSql, pTableCxt, &gotRow, pToken);
D
stmt  
dapan1121 已提交
1325
    }
1326

X
Xiaoyu Wang 已提交
1327 1328 1329 1330 1331 1332 1333
    if (TSDB_CODE_SUCCESS == code) {
      NEXT_VALID_TOKEN(pStmt->pSql, *pToken);
      if (TK_NK_COMMA == pToken->type) {
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
      } else if (TK_NK_RP != pToken->type) {
        code = buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
      }
1334 1335
    }

X
Xiaoyu Wang 已提交
1336 1337
    if (TSDB_CODE_SUCCESS == code && gotRow) {
      (*pNumOfRows)++;
D
stmt  
dapan1121 已提交
1338
    }
1339 1340
  }

X
Xiaoyu Wang 已提交
1341 1342 1343
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) &&
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
1344
  }
X
Xiaoyu Wang 已提交
1345
  return code;
1346 1347
}

X
Xiaoyu Wang 已提交
1348
// VALUES (field1_value, ...) [(field1_value2, ...) ...]
X
Xiaoyu Wang 已提交
1349
static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt,
X
Xiaoyu Wang 已提交
1350
                                 SToken* pToken) {
1351
  int32_t numOfRows = 0;
X
Xiaoyu Wang 已提交
1352
  int32_t code = parseValues(pCxt, pStmt, pTableCxt, &numOfRows, pToken);
X
Xiaoyu Wang 已提交
1353 1354 1355 1356 1357 1358
  if (TSDB_CODE_SUCCESS == code) {
    pStmt->totalRowsNum += numOfRows;
    pStmt->totalTbNum += 1;
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_INSERT);
  }
  return code;
1359 1360
}

X
Xiaoyu Wang 已提交
1361
static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt,
X
Xiaoyu Wang 已提交
1362 1363
                            int32_t* pNumOfRows) {
  int32_t code = TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
1364
  (*pNumOfRows) = 0;
X
Xiaoyu Wang 已提交
1365 1366
  char*   pLine = NULL;
  int64_t readLen = 0;
D
dapan1121 已提交
1367
  bool    firstLine = (pStmt->fileProcessing == false);
X
Xiaoyu Wang 已提交
1368
  pStmt->fileProcessing = false;
X
Xiaoyu Wang 已提交
1369
  while (TSDB_CODE_SUCCESS == code && (readLen = taosGetLineFile(pStmt->fp, &pLine)) != -1) {
X
Xiaoyu Wang 已提交
1370 1371 1372 1373 1374
    if (('\r' == pLine[readLen - 1]) || ('\n' == pLine[readLen - 1])) {
      pLine[--readLen] = '\0';
    }

    if (readLen == 0) {
D
dapan1121 已提交
1375
      firstLine = false;
X
Xiaoyu Wang 已提交
1376 1377 1378
      continue;
    }

X
Xiaoyu Wang 已提交
1379 1380 1381 1382
    bool gotRow = false;
    if (TSDB_CODE_SUCCESS == code) {
      SToken token;
      strtolower(pLine, pLine);
X
Xiaoyu Wang 已提交
1383
      const char* pRow = pLine;
1384

H
Haojun Liao 已提交
1385
      code = parseOneRow(pCxt, (const char**)&pRow, pTableCxt, &gotRow, &token);
D
dapan1121 已提交
1386 1387 1388 1389 1390
      if (code && firstLine) {
        firstLine = false;
        code = 0;
        continue;
      }
X
Xiaoyu Wang 已提交
1391
    }
X
Xiaoyu Wang 已提交
1392 1393 1394

    if (TSDB_CODE_SUCCESS == code && gotRow) {
      (*pNumOfRows)++;
X
Xiaoyu Wang 已提交
1395
    }
1396

X
Xiaoyu Wang 已提交
1397
    if (TSDB_CODE_SUCCESS == code && (*pNumOfRows) > tsMaxMemUsedByInsert * 1024 * 1024) {
X
Xiaoyu Wang 已提交
1398
      pStmt->fileProcessing = true;
1399 1400
      break;
    }
D
dapan1121 已提交
1401 1402

    firstLine = false;
X
Xiaoyu Wang 已提交
1403
  }
X
Xiaoyu Wang 已提交
1404
  taosMemoryFree(pLine);
X
Xiaoyu Wang 已提交
1405

X
Xiaoyu Wang 已提交
1406
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) &&
X
Xiaoyu Wang 已提交
1407
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) && !pStmt->fileProcessing) {
X
Xiaoyu Wang 已提交
1408
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
X
Xiaoyu Wang 已提交
1409
  }
X
Xiaoyu Wang 已提交
1410
  return code;
X
Xiaoyu Wang 已提交
1411 1412
}

X
Xiaoyu Wang 已提交
1413
static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) {
X
Xiaoyu Wang 已提交
1414
  int32_t numOfRows = 0;
X
Xiaoyu Wang 已提交
1415
  int32_t code = parseCsvFile(pCxt, pStmt, pTableCxt, &numOfRows);
X
Xiaoyu Wang 已提交
1416 1417 1418 1419
  if (TSDB_CODE_SUCCESS == code) {
    pStmt->totalRowsNum += numOfRows;
    pStmt->totalTbNum += 1;
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT);
X
Xiaoyu Wang 已提交
1420
    if (!pStmt->fileProcessing) {
X
Xiaoyu Wang 已提交
1421 1422 1423 1424
      taosCloseFile(&pStmt->fp);
    } else {
      parserDebug("0x%" PRIx64 " insert from csv. File is too large, do it in batches.", pCxt->pComCxt->requestId);
    }
1425
  }
X
Xiaoyu Wang 已提交
1426
  return code;
X
Xiaoyu Wang 已提交
1427 1428
}

X
Xiaoyu Wang 已提交
1429
static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pFilePath,
X
Xiaoyu Wang 已提交
1430
                                 STableDataCxt* pTableCxt) {
1431
  char filePathStr[TSDB_FILENAME_LEN] = {0};
X
Xiaoyu Wang 已提交
1432 1433
  if (TK_NK_STRING == pFilePath->type) {
    trimString(pFilePath->z, pFilePath->n, filePathStr, sizeof(filePathStr));
1434
  } else {
X
Xiaoyu Wang 已提交
1435
    strncpy(filePathStr, pFilePath->z, pFilePath->n);
1436
  }
X
Xiaoyu Wang 已提交
1437 1438
  pStmt->fp = taosOpenFile(filePathStr, TD_FILE_READ | TD_FILE_STREAM);
  if (NULL == pStmt->fp) {
1439 1440 1441
    return TAOS_SYSTEM_ERROR(errno);
  }

X
Xiaoyu Wang 已提交
1442
  return parseDataFromFileImpl(pCxt, pStmt, pTableCxt);
1443 1444
}

X
Xiaoyu Wang 已提交
1445
static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt,
X
Xiaoyu Wang 已提交
1446
                               SToken* pToken) {
1447 1448 1449 1450
  if (tsUseAdapter) {
    return buildInvalidOperationMsg(&pCxt->msg, "proxy mode does not support csv loading");
  }

X
Xiaoyu Wang 已提交
1451 1452 1453
  NEXT_TOKEN(pStmt->pSql, *pToken);
  if (0 == pToken->n || (TK_NK_STRING != pToken->type && TK_NK_ID != pToken->type)) {
    return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", pToken->z);
1454
  }
X
Xiaoyu Wang 已提交
1455
  return parseDataFromFile(pCxt, pStmt, pToken, pTableCxt);
X
Xiaoyu Wang 已提交
1456 1457
}

X
Xiaoyu Wang 已提交
1458
// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
X
Xiaoyu Wang 已提交
1459
static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) {
X
Xiaoyu Wang 已提交
1460 1461 1462 1463
  SToken token;
  NEXT_TOKEN(pStmt->pSql, token);
  switch (token.type) {
    case TK_VALUES:
X
Xiaoyu Wang 已提交
1464
      return parseValuesClause(pCxt, pStmt, pTableCxt, &token);
X
Xiaoyu Wang 已提交
1465
    case TK_FILE:
X
Xiaoyu Wang 已提交
1466
      return parseFileClause(pCxt, pStmt, pTableCxt, &token);
X
Xiaoyu Wang 已提交
1467 1468 1469 1470
    default:
      break;
  }
  return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
X
Xiaoyu Wang 已提交
1471 1472
}

X
Xiaoyu Wang 已提交
1473 1474 1475
// input pStmt->pSql:
//   1. [(tag1_name, ...)] ...
//   2. VALUES ... | FILE ...
X
Xiaoyu Wang 已提交
1476
static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1477 1478
  STableDataCxt* pTableCxt = NULL;
  int32_t        code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt);
X
Xiaoyu Wang 已提交
1479
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1480
    code = parseDataClause(pCxt, pStmt, pTableCxt);
X
Xiaoyu Wang 已提交
1481 1482 1483 1484
  }
  return code;
}

X
Xiaoyu Wang 已提交
1485
static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1486
  insDestroyBoundColInfo(&pCxt->tags);
X
Xiaoyu Wang 已提交
1487
  taosMemoryFreeClear(pStmt->pTableMeta);
X
Xiaoyu Wang 已提交
1488 1489
  tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
  taosMemoryFreeClear(pStmt->pCreateTblReq);
X
Xiaoyu Wang 已提交
1490 1491
  pCxt->missCache = false;
  pCxt->usingDuplicateTable = false;
X
Xiaoyu Wang 已提交
1492
  pStmt->pBoundCols = NULL;
X
Xiaoyu Wang 已提交
1493 1494
  pStmt->usingTableProcessing = false;
  pStmt->fileProcessing = false;
1495
  pStmt->usingTableName.type = 0;
X
Xiaoyu Wang 已提交
1496 1497
}

X
Xiaoyu Wang 已提交
1498
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
X
Xiaoyu Wang 已提交
1499
static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
X
Xiaoyu Wang 已提交
1500
  resetEnvPreTable(pCxt, pStmt);
X
Xiaoyu Wang 已提交
1501 1502 1503 1504 1505 1506
  int32_t code = parseSchemaClauseTop(pCxt, pStmt, pTbName);
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
    code = parseInsertTableClauseBottom(pCxt, pStmt);
  }
  return code;
}
X
Xiaoyu Wang 已提交
1507

X
Xiaoyu Wang 已提交
1508
static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName,
X
Xiaoyu Wang 已提交
1509 1510 1511 1512 1513
                                          bool* pHasData) {
  // no data in the sql string anymore.
  if (0 == pTbName->n) {
    if (0 != pTbName->type && '\0' != pStmt->pSql[0]) {
      return buildSyntaxErrMsg(&pCxt->msg, "invalid charactor in SQL", pTbName->z);
1514 1515
    }

X
Xiaoyu Wang 已提交
1516 1517
    if (0 == pStmt->totalRowsNum && (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
      return buildInvalidOperationMsg(&pCxt->msg, "no data in sql");
D
stmt  
dapan1121 已提交
1518 1519
    }

X
Xiaoyu Wang 已提交
1520 1521 1522
    *pHasData = false;
    return TSDB_CODE_SUCCESS;
  }
X
Xiaoyu Wang 已提交
1523

X
Xiaoyu Wang 已提交
1524 1525 1526
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT) && pStmt->totalTbNum > 0) {
    return buildInvalidOperationMsg(&pCxt->msg, "single table allowed in one stmt");
  }
1527

X
Xiaoyu Wang 已提交
1528 1529 1530
  if (TK_NK_QUESTION == pTbName->type) {
    if (NULL == pCxt->pComCxt->pStmtCb) {
      return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
X
Xiaoyu Wang 已提交
1531
    }
X
Xiaoyu Wang 已提交
1532

X
Xiaoyu Wang 已提交
1533 1534 1535 1536 1537 1538 1539
    char*   tbName = NULL;
    int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
    if (TSDB_CODE_SUCCESS == code) {
      pTbName->z = tbName;
      pTbName->n = strlen(tbName);
    } else {
      return code;
1540
    }
X
Xiaoyu Wang 已提交
1541
  }
1542

1543 1544 1545 1546
  if (TK_NK_ID != pTbName->type && TK_NK_STRING != pTbName->type) {
    return buildSyntaxErrMsg(&pCxt->msg, "table_name is expected", pTbName->z);
  }

X
Xiaoyu Wang 已提交
1547 1548 1549
  *pHasData = true;
  return TSDB_CODE_SUCCESS;
}
1550

X
Xiaoyu Wang 已提交
1551
static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1552
  SBoundColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags));
X
Xiaoyu Wang 已提交
1553
  if (NULL == tags) {
S
Shengliang Guan 已提交
1554
    return TSDB_CODE_OUT_OF_MEMORY;
X
Xiaoyu Wang 已提交
1555 1556
  }
  memcpy(tags, &pCxt->tags, sizeof(pCxt->tags));
1557

X
Xiaoyu Wang 已提交
1558
  SStmtCallback* pStmtCb = pCxt->pComCxt->pStmtCb;
X
Xiaoyu Wang 已提交
1559 1560 1561
  int32_t        code = (*pStmtCb->setInfoFn)(pStmtCb->pStmt, pStmt->pTableMeta, tags, &pStmt->targetTableName,
                                       pStmt->usingTableProcessing, pStmt->pVgroupsHashObj, pStmt->pTableBlockHashObj,
                                       pStmt->usingTableName.tname);
1562

X
Xiaoyu Wang 已提交
1563 1564 1565 1566 1567
  memset(&pCxt->tags, 0, sizeof(pCxt->tags));
  pStmt->pVgroupsHashObj = NULL;
  pStmt->pTableBlockHashObj = NULL;
  return code;
}
1568

X
Xiaoyu Wang 已提交
1569
static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1570 1571 1572
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) {
    return setStmtInfo(pCxt, pStmt);
  }
D
stmt  
dapan1121 已提交
1573

X
Xiaoyu Wang 已提交
1574
  // merge according to vgId
X
Xiaoyu Wang 已提交
1575
  int32_t code = insMergeTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pVgDataBlocks);
X
Xiaoyu Wang 已提交
1576
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1577
    code = insBuildVgDataBlocks(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks);
X
Xiaoyu Wang 已提交
1578
  }
X
Xiaoyu Wang 已提交
1579

X
Xiaoyu Wang 已提交
1580 1581
  return code;
}
1582

X
Xiaoyu Wang 已提交
1583 1584 1585 1586 1587
// tb_name
//     [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
//     [(field1_name, ...)]
//     VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
// [...];
X
Xiaoyu Wang 已提交
1588
static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1589 1590 1591 1592
  SToken  token;
  int32_t code = TSDB_CODE_SUCCESS;
  bool    hasData = true;
  // for each table
X
Xiaoyu Wang 已提交
1593
  while (TSDB_CODE_SUCCESS == code && hasData && !pCxt->missCache && !pStmt->fileProcessing) {
X
Xiaoyu Wang 已提交
1594 1595 1596 1597 1598
    // pStmt->pSql -> tb_name ...
    NEXT_TOKEN(pStmt->pSql, token);
    code = checkTableClauseFirstToken(pCxt, pStmt, &token, &hasData);
    if (TSDB_CODE_SUCCESS == code && hasData) {
      code = parseInsertTableClause(pCxt, pStmt, &token);
1599 1600
    }
  }
X
Xiaoyu Wang 已提交
1601

X
Xiaoyu Wang 已提交
1602 1603 1604 1605 1606
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
    code = parseInsertBodyBottom(pCxt, pStmt);
  }
  return code;
}
D
stmt  
dapan1121 已提交
1607

X
Xiaoyu Wang 已提交
1608
static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); }
X
Xiaoyu Wang 已提交
1609

X
Xiaoyu Wang 已提交
1610
static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, SNode** pOutput) {
X
Xiaoyu Wang 已提交
1611
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT);
X
Xiaoyu Wang 已提交
1612 1613
  if (NULL == pStmt) {
    return TSDB_CODE_OUT_OF_MEMORY;
D
stmt  
dapan1121 已提交
1614
  }
X
Xiaoyu Wang 已提交
1615

X
Xiaoyu Wang 已提交
1616
  if (pCxt->pComCxt->pStmtCb) {
X
Xiaoyu Wang 已提交
1617
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT);
1618
  }
X
Xiaoyu Wang 已提交
1619
  pStmt->pSql = pCxt->pComCxt->pSql;
X
Xiaoyu Wang 已提交
1620 1621
  pStmt->freeHashFunc = insDestroyTableDataCxtHashMap;
  pStmt->freeArrayFunc = insDestroyVgroupDataCxtList;
X
Xiaoyu Wang 已提交
1622

X
Xiaoyu Wang 已提交
1623 1624 1625 1626 1627
  if (!reentry) {
    pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
    pStmt->pTableBlockHashObj =
        taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
  }
X
Xiaoyu Wang 已提交
1628 1629 1630
  pStmt->pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
  pStmt->pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
  pStmt->pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
X
Xiaoyu Wang 已提交
1631 1632
  if ((!reentry && (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj)) ||
      NULL == pStmt->pSubTableHashObj || NULL == pStmt->pTableNameHashObj || NULL == pStmt->pDbFNameHashObj) {
X
Xiaoyu Wang 已提交
1633 1634
    nodesDestroyNode((SNode*)pStmt);
    return TSDB_CODE_OUT_OF_MEMORY;
1635
  }
X
Xiaoyu Wang 已提交
1636 1637 1638 1639 1640

  taosHashSetFreeFp(pStmt->pSubTableHashObj, destroySubTableHashElem);

  *pOutput = (SNode*)pStmt;
  return TSDB_CODE_SUCCESS;
1641 1642
}

X
Xiaoyu Wang 已提交
1643
static int32_t createInsertQuery(SInsertParseContext* pCxt, SQuery** pOutput) {
X
Xiaoyu Wang 已提交
1644 1645 1646
  SQuery* pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY);
  if (NULL == pQuery) {
    return TSDB_CODE_OUT_OF_MEMORY;
D
stmt  
dapan1121 已提交
1647
  }
X
Xiaoyu Wang 已提交
1648

X
Xiaoyu Wang 已提交
1649 1650 1651
  pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
  pQuery->haveResultSet = false;
  pQuery->msgType = TDMT_VND_SUBMIT;
1652

X
Xiaoyu Wang 已提交
1653
  int32_t code = createVnodeModifOpStmt(pCxt, false, &pQuery->pRoot);
X
Xiaoyu Wang 已提交
1654 1655 1656 1657
  if (TSDB_CODE_SUCCESS == code) {
    *pOutput = pQuery;
  } else {
    nodesDestroyNode((SNode*)pQuery);
D
stmt  
dapan1121 已提交
1658
  }
X
Xiaoyu Wang 已提交
1659 1660
  return code;
}
D
stmt  
dapan1121 已提交
1661

X
Xiaoyu Wang 已提交
1662 1663 1664
static int32_t checkAuthFromMetaData(const SArray* pUsers) {
  if (1 != taosArrayGetSize(pUsers)) {
    return TSDB_CODE_FAILED;
1665
  }
1666

X
Xiaoyu Wang 已提交
1667 1668 1669 1670 1671 1672
  SMetaRes* pRes = taosArrayGet(pUsers, 0);
  if (TSDB_CODE_SUCCESS == pRes->code) {
    return (*(bool*)pRes->pRes) ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED;
  }
  return pRes->code;
}
X
Xiaoyu Wang 已提交
1673

X
Xiaoyu Wang 已提交
1674 1675 1676 1677
static int32_t getTableMetaFromMetaData(const SArray* pTables, STableMeta** pMeta) {
  if (1 != taosArrayGetSize(pTables)) {
    return TSDB_CODE_FAILED;
  }
X
Xiaoyu Wang 已提交
1678 1679

  taosMemoryFreeClear(*pMeta);
X
Xiaoyu Wang 已提交
1680 1681 1682 1683
  SMetaRes* pRes = taosArrayGet(pTables, 0);
  if (TSDB_CODE_SUCCESS == pRes->code) {
    *pMeta = tableMetaDup((const STableMeta*)pRes->pRes);
    if (NULL == *pMeta) {
D
dapan1121 已提交
1684 1685 1686
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  }
X
Xiaoyu Wang 已提交
1687 1688
  return pRes->code;
}
1689

X
Xiaoyu Wang 已提交
1690
static int32_t getTableVgroupFromMetaData(const SArray* pTables, SVnodeModifyOpStmt* pStmt, bool isStb) {
X
Xiaoyu Wang 已提交
1691 1692
  if (1 != taosArrayGetSize(pTables)) {
    return TSDB_CODE_FAILED;
D
dapan1121 已提交
1693 1694
  }

X
Xiaoyu Wang 已提交
1695 1696 1697
  SMetaRes* pRes = taosArrayGet(pTables, 0);
  if (TSDB_CODE_SUCCESS != pRes->code) {
    return pRes->code;
1698
  }
1699

X
Xiaoyu Wang 已提交
1700 1701 1702 1703 1704 1705 1706
  SVgroupInfo* pVg = pRes->pRes;
  if (isStb) {
    pStmt->pTableMeta->vgId = pVg->vgId;
  }
  return taosHashPut(pStmt->pVgroupsHashObj, (const char*)&pVg->vgId, sizeof(pVg->vgId), (char*)pVg,
                     sizeof(SVgroupInfo));
}
D
dapan1121 已提交
1707

X
Xiaoyu Wang 已提交
1708
static int32_t getTableSchemaFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData,
X
Xiaoyu Wang 已提交
1709
                                          SVnodeModifyOpStmt* pStmt, bool isStb) {
X
Xiaoyu Wang 已提交
1710 1711 1712
  int32_t code = checkAuthFromMetaData(pMetaData->pUser);
  if (TSDB_CODE_SUCCESS == code) {
    code = getTableMetaFromMetaData(pMetaData->pTableMeta, &pStmt->pTableMeta);
X
Xiaoyu Wang 已提交
1713
  }
X
Xiaoyu Wang 已提交
1714 1715 1716
  if (TSDB_CODE_SUCCESS == code && !isStb && TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
    code = buildInvalidOperationMsg(&pCxt->msg, "insert data into super table is not supported");
  }
1717 1718 1719
  if (TSDB_CODE_SUCCESS == code && isStb) {
    code = storeTableMeta(pCxt, pStmt);
  }
X
Xiaoyu Wang 已提交
1720 1721
  if (TSDB_CODE_SUCCESS == code) {
    code = getTableVgroupFromMetaData(pMetaData->pTableHash, pStmt, isStb);
1722
  }
X
Xiaoyu Wang 已提交
1723
  return code;
1724
}
D
stmt  
dapan1121 已提交
1725

X
Xiaoyu Wang 已提交
1726 1727 1728 1729 1730 1731
static void destoryTablesReq(void* p) {
  STablesReq* pRes = (STablesReq*)p;
  taosArrayDestroy(pRes->pTables);
}

static void clearCatalogReq(SCatalogReq* pCatalogReq) {
X
Xiaoyu Wang 已提交
1732 1733 1734 1735
  if (NULL == pCatalogReq) {
    return;
  }

X
Xiaoyu Wang 已提交
1736 1737 1738 1739 1740 1741 1742 1743
  taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq);
  pCatalogReq->pTableMeta = NULL;
  taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq);
  pCatalogReq->pTableHash = NULL;
  taosArrayDestroy(pCatalogReq->pUser);
  pCatalogReq->pUser = NULL;
}

X
Xiaoyu Wang 已提交
1744
static int32_t setVnodeModifOpStmt(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
X
Xiaoyu Wang 已提交
1745
                                   SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1746 1747
  clearCatalogReq(pCatalogReq);

X
Xiaoyu Wang 已提交
1748
  if (pStmt->usingTableProcessing) {
X
Xiaoyu Wang 已提交
1749
    return getTableSchemaFromMetaData(pCxt, pMetaData, pStmt, true);
X
Xiaoyu Wang 已提交
1750
  }
X
Xiaoyu Wang 已提交
1751
  return getTableSchemaFromMetaData(pCxt, pMetaData, pStmt, false);
X
Xiaoyu Wang 已提交
1752 1753
}

X
Xiaoyu Wang 已提交
1754
static int32_t resetVnodeModifOpStmt(SInsertParseContext* pCxt, SQuery* pQuery) {
X
Xiaoyu Wang 已提交
1755 1756 1757 1758
  nodesDestroyNode(pQuery->pRoot);

  int32_t code = createVnodeModifOpStmt(pCxt, true, &pQuery->pRoot);
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1759
    SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
X
Xiaoyu Wang 已提交
1760

X
Xiaoyu Wang 已提交
1761 1762
    (*pCxt->pComCxt->pStmtCb->getExecInfoFn)(pCxt->pComCxt->pStmtCb->pStmt, &pStmt->pVgroupsHashObj,
                                             &pStmt->pTableBlockHashObj);
X
Xiaoyu Wang 已提交
1763 1764 1765 1766 1767 1768
    if (NULL == pStmt->pVgroupsHashObj) {
      pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
    }
    if (NULL == pStmt->pTableBlockHashObj) {
      pStmt->pTableBlockHashObj =
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
1769
    }
X
Xiaoyu Wang 已提交
1770 1771 1772
    if (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj) {
      code = TSDB_CODE_OUT_OF_MEMORY;
    }
1773
  }
X
Xiaoyu Wang 已提交
1774

X
Xiaoyu Wang 已提交
1775
  return code;
1776 1777
}

X
Xiaoyu Wang 已提交
1778
static int32_t initInsertQuery(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
X
Xiaoyu Wang 已提交
1779
                               SQuery** pQuery) {
X
Xiaoyu Wang 已提交
1780 1781 1782
  if (NULL == *pQuery) {
    return createInsertQuery(pCxt, pQuery);
  }
X
Xiaoyu Wang 已提交
1783

X
Xiaoyu Wang 已提交
1784
  if (NULL != pCxt->pComCxt->pStmtCb) {
X
Xiaoyu Wang 已提交
1785 1786 1787
    return resetVnodeModifOpStmt(pCxt, *pQuery);
  }

X
Xiaoyu Wang 已提交
1788
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)(*pQuery)->pRoot;
X
Xiaoyu Wang 已提交
1789 1790 1791

  if (!pStmt->fileProcessing) {
    return setVnodeModifOpStmt(pCxt, pCatalogReq, pMetaData, pStmt);
X
Xiaoyu Wang 已提交
1792 1793 1794
  }

  return TSDB_CODE_SUCCESS;
1795 1796
}

X
Xiaoyu Wang 已提交
1797
static int32_t setRefreshMate(SQuery* pQuery) {
X
Xiaoyu Wang 已提交
1798
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
1799 1800 1801 1802 1803 1804 1805 1806 1807

  if (taosHashGetSize(pStmt->pTableNameHashObj) > 0) {
    taosArrayDestroy(pQuery->pTableList);
    pQuery->pTableList = taosArrayInit(taosHashGetSize(pStmt->pTableNameHashObj), sizeof(SName));
    SName* pTable = taosHashIterate(pStmt->pTableNameHashObj, NULL);
    while (NULL != pTable) {
      taosArrayPush(pQuery->pTableList, pTable);
      pTable = taosHashIterate(pStmt->pTableNameHashObj, pTable);
    }
1808 1809
  }

1810 1811 1812 1813 1814 1815 1816 1817
  if (taosHashGetSize(pStmt->pDbFNameHashObj) > 0) {
    taosArrayDestroy(pQuery->pDbList);
    pQuery->pDbList = taosArrayInit(taosHashGetSize(pStmt->pDbFNameHashObj), TSDB_DB_FNAME_LEN);
    char* pDb = taosHashIterate(pStmt->pDbFNameHashObj, NULL);
    while (NULL != pDb) {
      taosArrayPush(pQuery->pDbList, pDb);
      pDb = taosHashIterate(pStmt->pDbFNameHashObj, pDb);
    }
1818 1819 1820 1821 1822
  }

  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
1823 1824 1825 1826 1827 1828
// INSERT INTO
//   tb_name
//       [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]]
//       [(field1_name, ...)]
//       VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
//   [...];
X
Xiaoyu Wang 已提交
1829
static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1830 1831 1832 1833 1834
  int32_t code = skipInsertInto(&pStmt->pSql, &pCxt->msg);
  if (TSDB_CODE_SUCCESS == code) {
    code = parseInsertBody(pCxt, pStmt);
  }
  return code;
1835 1836
}

X
Xiaoyu Wang 已提交
1837
static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1838 1839
  STableDataCxt* pTableCxt = NULL;
  int32_t        code = getTableDataCxt(pCxt, pStmt, &pTableCxt);
X
Xiaoyu Wang 已提交
1840
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1841
    code = parseDataFromFileImpl(pCxt, pStmt, pTableCxt);
1842 1843
  }

X
Xiaoyu Wang 已提交
1844 1845 1846 1847 1848 1849 1850 1851 1852
  if (TSDB_CODE_SUCCESS == code) {
    if (pStmt->fileProcessing) {
      code = parseInsertBodyBottom(pCxt, pStmt);
    } else {
      code = parseInsertBody(pCxt, pStmt);
    }
  }

  return code;
X
Xiaoyu Wang 已提交
1853 1854
}

X
Xiaoyu Wang 已提交
1855
static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1856 1857 1858 1859 1860 1861
  int32_t code = parseInsertTableClauseBottom(pCxt, pStmt);
  if (TSDB_CODE_SUCCESS == code) {
    code = parseInsertBody(pCxt, pStmt);
  }
  return code;
}
1862

X
Xiaoyu Wang 已提交
1863
static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
X
Xiaoyu Wang 已提交
1864 1865 1866
  if (pStmt->pSql == pCxt->pComCxt->pSql || NULL != pCxt->pComCxt->pStmtCb) {
    return parseInsertSqlFromStart(pCxt, pStmt);
  }
1867

X
Xiaoyu Wang 已提交
1868 1869 1870
  if (pStmt->fileProcessing) {
    return parseInsertSqlFromCsv(pCxt, pStmt);
  }
1871

X
Xiaoyu Wang 已提交
1872 1873
  return parseInsertSqlFromTable(pCxt, pStmt);
}
1874

X
Xiaoyu Wang 已提交
1875 1876 1877 1878 1879
static int32_t buildInsertTableReq(SName* pName, SArray** pTables) {
  *pTables = taosArrayInit(1, sizeof(SName));
  if (NULL == *pTables) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
1880

X
Xiaoyu Wang 已提交
1881 1882 1883
  taosArrayPush(*pTables, pName);
  return TSDB_CODE_SUCCESS;
}
1884

X
Xiaoyu Wang 已提交
1885 1886 1887 1888 1889
static int32_t buildInsertDbReq(SName* pName, SArray** pDbs) {
  if (NULL == *pDbs) {
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
    if (NULL == *pDbs) {
      return TSDB_CODE_OUT_OF_MEMORY;
1890
    }
X
Xiaoyu Wang 已提交
1891
  }
1892

X
Xiaoyu Wang 已提交
1893 1894 1895 1896
  STablesReq req = {0};
  tNameGetFullDbName(pName, req.dbFName);
  buildInsertTableReq(pName, &req.pTables);
  taosArrayPush(*pDbs, &req);
1897

X
Xiaoyu Wang 已提交
1898 1899
  return TSDB_CODE_SUCCESS;
}
1900

X
Xiaoyu Wang 已提交
1901 1902 1903 1904 1905
static int32_t buildInsertUserAuthReq(const char* pUser, SName* pName, SArray** pUserAuth) {
  *pUserAuth = taosArrayInit(1, sizeof(SUserAuthInfo));
  if (NULL == *pUserAuth) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
X
Xiaoyu Wang 已提交
1906

X
Xiaoyu Wang 已提交
1907 1908 1909 1910
  SUserAuthInfo userAuth = {.type = AUTH_TYPE_WRITE};
  snprintf(userAuth.user, sizeof(userAuth.user), "%s", pUser);
  tNameGetFullDbName(pName, userAuth.dbFName);
  taosArrayPush(*pUserAuth, &userAuth);
1911

X
Xiaoyu Wang 已提交
1912 1913 1914
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
1915
static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SCatalogReq* pCatalogReq) {
X
Xiaoyu Wang 已提交
1916 1917 1918 1919 1920 1921
  int32_t code = buildInsertUserAuthReq(pCxt->pComCxt->pUser, &pStmt->targetTableName, &pCatalogReq->pUser);
  if (TSDB_CODE_SUCCESS == code) {
    if (0 == pStmt->usingTableName.type) {
      code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableMeta);
    } else {
      code = buildInsertDbReq(&pStmt->usingTableName, &pCatalogReq->pTableMeta);
1922
    }
X
Xiaoyu Wang 已提交
1923 1924 1925 1926 1927 1928
  }
  if (TSDB_CODE_SUCCESS == code) {
    code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableHash);
  }
  return code;
}
1929

X
Xiaoyu Wang 已提交
1930
static int32_t setNextStageInfo(SInsertParseContext* pCxt, SQuery* pQuery, SCatalogReq* pCatalogReq) {
X
Xiaoyu Wang 已提交
1931
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
X
Xiaoyu Wang 已提交
1932
  if (pCxt->missCache) {
1933 1934
    parserDebug("0x%" PRIx64 " %d rows of %d tables have been inserted before cache miss", pCxt->pComCxt->requestId,
                pStmt->totalRowsNum, pStmt->totalTbNum);
X
Xiaoyu Wang 已提交
1935

X
Xiaoyu Wang 已提交
1936
    pQuery->execStage = QUERY_EXEC_STAGE_PARSE;
1937
    return buildInsertCatalogReq(pCxt, pStmt, pCatalogReq);
1938 1939
  }

1940 1941
  parserDebug("0x%" PRIx64 " %d rows of %d tables have been inserted", pCxt->pComCxt->requestId, pStmt->totalRowsNum,
              pStmt->totalTbNum);
X
Xiaoyu Wang 已提交
1942

X
Xiaoyu Wang 已提交
1943
  pQuery->execStage = QUERY_EXEC_STAGE_SCHEDULE;
1944 1945 1946
  return TSDB_CODE_SUCCESS;
}

X
Xiaoyu Wang 已提交
1947
int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) {
X
Xiaoyu Wang 已提交
1948 1949 1950 1951 1952
  SInsertParseContext context = {.pComCxt = pCxt,
                                 .msg = {.buf = pCxt->pMsg, .len = pCxt->msgLen},
                                 .missCache = false,
                                 .usingDuplicateTable = false,
                                 .forceUpdate = (NULL != pCatalogReq ? pCatalogReq->forceUpdate : false)};
X
Xiaoyu Wang 已提交
1953

X
Xiaoyu Wang 已提交
1954
  int32_t code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery);
1955
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1956
    code = parseInsertSqlImpl(&context, (SVnodeModifyOpStmt*)(*pQuery)->pRoot);
1957 1958
  }
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
1959 1960 1961 1962 1963
    code = setNextStageInfo(&context, *pQuery, pCatalogReq);
  }
  if ((TSDB_CODE_SUCCESS == code || NEED_CLIENT_HANDLE_ERROR(code)) &&
      QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) {
    code = setRefreshMate(*pQuery);
1964
  }
X
Xiaoyu Wang 已提交
1965
  insDestroyBoundColInfo(&context.tags);
1966 1967
  return code;
}