• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #5034

24 Apr 2026 11:25AM UTC coverage: 73.058%. Remained the same
#5034

push

travis-ci

web-flow
merge: from main to 3.0 branch #35224

merge: from main to 3.0 branch[manual-only]

1336 of 1975 new or added lines in 48 files covered. (67.65%)

14149 existing lines in 164 files now uncovered.

275896 of 377640 relevant lines covered (73.06%)

132944440.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.41
/source/libs/parser/src/parInsertSql.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#include "crypt.h"
17
#include "decimal.h"
18
#include "geosWrapper.h"
19
#include "parInsertUtil.h"
20
#include "parToken.h"
21
#include "query.h"
22
#include "scalar.h"
23
#include "tbase64.h"
24
#include "tglobal.h"
25
#include "ttime.h"
26

27
// CSV delimiter and quote character definitions
28
#define CSV_DEFAULT_DELIMITER ','
29
#define CSV_QUOTE_SINGLE      '\''
30
#define CSV_QUOTE_DOUBLE      '"'
31
#define CSV_ESCAPE_CHAR       '\\'
32
#define CSV_QUOTE_NONE        '\0'
33

34
typedef struct SCsvParser {
35
  char      delimiter;            // Field delimiter (default: ',')
36
  char      quote;                // Quote character (default: '"')
37
  char      escape;               // Escape character (default: '\')
38
  bool      allowNewlineInField;  // Allow newlines in quoted fields
39
  char*     buffer;               // Read buffer
40
  size_t    bufferSize;           // Buffer size
41
  size_t    bufferPos;            // Current position in buffer
42
  size_t    bufferLen;            // Valid data length in buffer
43
  bool      eof;                  // End of file reached
44
  TdFilePtr pFile;                // File pointer
45
  // Line buffer for reuse to avoid frequent memory allocation
46
  char*  lineBuffer;          // Reusable line buffer
47
  size_t lineBufferCapacity;  // Line buffer capacity
48
} SCsvParser;
49

50
typedef struct SInsertParseContext {
51
  SParseContext* pComCxt;
52
  SMsgBuf        msg;
53
  char           tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW];
54
  SBoundColInfo  tags;  // for stmt
55
  bool           missCache;
56
  bool           usingDuplicateTable;
57
  bool           forceUpdate;
58
  bool           needTableTagVal;
59
  bool           needRequest;  // whether or not request server
60
  // bool           isStmtBind;   // whether is stmt bind
61
  uint8_t stmtTbNameFlag;
62
  SSHashObj* pParsedValues;  // <cid, SColVal> for stmt bind col
63
} SInsertParseContext;
64

65
typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param);
66
static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt);
67
static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool autoCreate);
68

69
// CSV parser function declarations
70
static int32_t csvParserInit(SCsvParser* parser, TdFilePtr pFile);
71
static void    csvParserDestroy(SCsvParser* parser);
72
static int32_t csvParserFillBuffer(SCsvParser* parser);
73
static int32_t csvParserReadLine(SCsvParser* parser);
74
static void    destroySavedCsvParser(SVnodeModifyOpStmt* pStmt);
75
static int32_t csvParserExpandLineBuffer(SCsvParser* parser, size_t requiredLen);
76

77
static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
78
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;
79

80
static FORCE_INLINE bool isNullValue(int8_t dataType, SToken* pToken) {
81
  return TK_NULL == pToken->type ||
2,147,483,647✔
82
         (TK_NK_STRING == pToken->type && !IS_STR_DATA_TYPE(dataType) && IS_NULL_STR(pToken->z, pToken->n));
2,147,483,647✔
83
}
84

85
static FORCE_INLINE int32_t toDouble(SToken* pToken, double* value, char** endPtr) {
86
  SET_ERRNO(0);
87
  *value = taosStr2Double(pToken->z, endPtr);
88

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

94
  return pToken->type;
95
}
96

97
static int32_t skipInsertInto(const char** pSql, SMsgBuf* pMsg) {
625,013,769✔
98
  SToken token;
99
  NEXT_TOKEN(*pSql, token);
625,013,769✔
100
  if (TK_INSERT != token.type && TK_IMPORT != token.type) {
625,063,508✔
101
    return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", token.z);
×
102
  }
103
  NEXT_TOKEN(*pSql, token);
625,063,508✔
104
  if (TK_INTO != token.type) {
625,064,225✔
105
    return buildSyntaxErrMsg(pMsg, "keyword INTO is expected", token.z);
×
106
  }
107
  return TSDB_CODE_SUCCESS;
625,064,225✔
108
}
109

110
static int32_t skipParentheses(SInsertParseContext* pCxt, const char** pSql) {
45,720,999✔
111
  SToken  token;
112
  int32_t expectRightParenthesis = 1;
45,720,999✔
113
  while (1) {
114
    NEXT_TOKEN(*pSql, token);
710,976,606✔
115
    if (TK_NK_LP == token.type) {
710,976,652✔
116
      ++expectRightParenthesis;
×
117
    } else if (TK_NK_RP == token.type && 0 == --expectRightParenthesis) {
710,976,652✔
118
      break;
45,721,045✔
119
    }
120
    if (0 == token.n) {
665,255,607✔
121
      return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL);
×
122
    }
123
  }
124
  return TSDB_CODE_SUCCESS;
45,721,045✔
125
}
126

127
static int32_t skipTableOptions(SInsertParseContext* pCxt, const char** pSql) {
8,082,479✔
128
  do {
1,376✔
129
    int32_t index = 0;
8,082,479✔
130
    SToken  token;
131
    NEXT_TOKEN_KEEP_SQL(*pSql, token, index);
8,082,479✔
132
    if (TK_TTL == token.type || TK_COMMENT == token.type) {
8,082,479✔
133
      *pSql += index;
1,376✔
134
      NEXT_TOKEN_WITH_PREV(*pSql, token);
1,376✔
135
    } else {
136
      break;
137
    }
138
  } while (1);
139
  return TSDB_CODE_SUCCESS;
8,081,103✔
140
}
141

142
// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)
143
static int32_t ignoreUsingClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
74,258✔
144
  const char** pSql = &pStmt->pSql;
74,258✔
145
  int32_t      code = TSDB_CODE_SUCCESS;
74,258✔
146
  SToken       token;
147
  NEXT_TOKEN(*pSql, token);
74,258✔
148

149
  NEXT_TOKEN(*pSql, token);
74,258✔
150
  if (TK_NK_LP == token.type) {
74,258✔
151
    code = skipParentheses(pCxt, pSql);
2,372✔
152
    if (TSDB_CODE_SUCCESS == code) {
2,372✔
153
      NEXT_TOKEN(*pSql, token);
2,372✔
154
    }
155
  }
156

157
  // pSql -> TAGS (tag1_value, ...)
158
  if (TSDB_CODE_SUCCESS == code) {
74,258✔
159
    if (TK_TAGS != token.type) {
74,258✔
160
      code = buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
×
161
    } else {
162
      NEXT_TOKEN(*pSql, token);
74,258✔
163
    }
164
  }
165
  if (TSDB_CODE_SUCCESS == code) {
74,258✔
166
    if (TK_NK_LP != token.type) {
74,258✔
167
      code = buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
×
168
    } else {
169
      code = skipParentheses(pCxt, pSql);
74,258✔
170
    }
171
  }
172

173
  if (TSDB_CODE_SUCCESS == code) {
74,258✔
174
    code = skipTableOptions(pCxt, pSql);
74,258✔
175
  }
176

177
  return code;
74,258✔
178
}
179

180
static int32_t ignoreUsingClauseAndCheckTagValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
8,015,721✔
181
  const char** pSql = &pStmt->pSql;
8,015,721✔
182
  int32_t      code = TSDB_CODE_SUCCESS;
8,015,721✔
183
  code = parseBoundTagsClause(pCxt, pStmt);
8,015,721✔
184
  if (TSDB_CODE_SUCCESS != code) {
8,015,721✔
185
    return code;
×
186
  }
187
  // pSql -> TAGS (tag1_value, ...)
188
  code = parseTagsClause(pCxt, pStmt, true);
8,015,721✔
189
  if (TSDB_CODE_SUCCESS != code) {
8,015,721✔
190
    return code;
8,876✔
191
  }
192

193
  if (TSDB_CODE_SUCCESS == code) {
8,006,845✔
194
    code = skipTableOptions(pCxt, pSql);
8,006,845✔
195
  }
196

197
  return code;
8,006,845✔
198
}
199

200
static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pDuplicate) {
21,393,326✔
201
  int32_t code = TSDB_CODE_SUCCESS;
21,393,326✔
202
  *pDuplicate = false;
21,393,326✔
203

204
  char tbFName[TSDB_TABLE_FNAME_LEN];
21,187,833✔
205
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
21,394,024✔
206
  if (TSDB_CODE_SUCCESS != code) {
21,394,024✔
207
    return code;
×
208
  }
209
  STableMeta** pMeta = taosHashGet(pStmt->pSubTableHashObj, tbFName, strlen(tbFName));
21,394,024✔
210
  if (NULL != pMeta) {
21,390,462✔
211
    *pDuplicate = true;
74,258✔
212
    pCxt->missCache = false;
74,258✔
213
    code = cloneTableMeta(*pMeta, &pStmt->pTableMeta);
74,258✔
214
    if (TSDB_CODE_SUCCESS != code) {
74,258✔
215
      return code;
×
216
    }
217
    return ignoreUsingClause(pCxt, pStmt);
74,258✔
218
  }
219

220
  return code;
21,316,204✔
221
}
222

223
typedef enum { BOUND_TAGS, BOUND_COLUMNS, BOUND_ALL_AND_TBNAME } EBoundColumnsType;
224

225
static int32_t getTbnameSchemaIndex(STableMeta* pTableMeta) {
1,196,567,532✔
226
  return pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns;
1,196,567,532✔
227
}
228

229
// pStmt->pSql -> field1_name, ...)
230
static int32_t parseBoundColumns(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** pSql,
45,996,451✔
231
                                 EBoundColumnsType boundColsType, STableMeta* pTableMeta, SBoundColInfo* pBoundInfo) {
232
  SSchema* pSchema = NULL;
45,996,451✔
233
  if (boundColsType == BOUND_TAGS) {
45,996,451✔
234
    pSchema = getTableTagSchema(pTableMeta);
260,236✔
235
  } else if (boundColsType == BOUND_COLUMNS) {
45,736,215✔
236
    pSchema = getTableColumnSchema(pTableMeta);
45,501,520✔
237
  } else {
238
    pSchema = pTableMeta->schema;
234,695✔
239
    if (pBoundInfo->numOfCols != getTbnameSchemaIndex(pTableMeta) + 1) {
234,732✔
240
      parserError("%s failed, invalid columns num:%d, tbname index:%d", __func__, pBoundInfo->numOfCols, getTbnameSchemaIndex(pTableMeta));
×
241
      return TSDB_CODE_PAR_INVALID_COLUMNS_NUM;
×
242
    }
243
  }
244
  int32_t tbnameSchemaIndex = getTbnameSchemaIndex(pTableMeta);
45,996,451✔
245

246
  bool* pUseCols = taosMemoryCalloc(pBoundInfo->numOfCols, sizeof(bool));
45,996,488✔
247
  if (NULL == pUseCols) {
45,996,451✔
248
    return terrno;
×
249
  }
250

251
  pBoundInfo->numOfBound = 0;
45,996,451✔
252
  pBoundInfo->hasBoundCols = true;
45,996,488✔
253

254
  bool    hasPK = pTableMeta->tableInfo.numOfPKs;
45,996,451✔
255
  int16_t numOfBoundPKs = 0;
45,996,451✔
256
  int16_t lastColIdx = -1;  // last column found
45,996,451✔
257
  SArray* pPrivCols = pStmt->pPrivCols;
45,996,451✔
258
  int32_t lastPrivColIdx = 0, nPrivCols = taosArrayGetSize(pPrivCols);
45,996,451✔
259
  int32_t code = TSDB_CODE_SUCCESS;
45,996,488✔
260
  while (TSDB_CODE_SUCCESS == code) {
712,534,230✔
261
    SToken token;
696,147,274✔
262
    NEXT_TOKEN(*pSql, token);
712,530,088✔
263

264
    if (TK_NK_RP == token.type) {
712,530,051✔
265
      break;
45,990,254✔
266
    }
267

268
    char tmpTokenBuf[TSDB_COL_NAME_LEN + 2] = {0};  // used for deleting Escape character backstick(`)
666,539,797✔
269
    if (token.n >= TSDB_COL_NAME_LEN + 2) {
666,539,797✔
270
      taosMemoryFree(pUseCols);
×
271
      return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z);
×
272
    }
273
    tstrncpy(tmpTokenBuf, token.z, token.n < sizeof(tmpTokenBuf) ? token.n + 1 : sizeof(tmpTokenBuf));
666,539,797✔
274
    token.z = tmpTokenBuf;
666,539,871✔
275
    token.n = strdequote(token.z);
666,539,871✔
276

277
    if (boundColsType == BOUND_ALL_AND_TBNAME && token.n == strlen("tbname") && (strcasecmp(token.z, "tbname") == 0)) {
666,539,797✔
278
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = tbnameSchemaIndex;
233,895✔
279
      pUseCols[tbnameSchemaIndex] = true;
233,895✔
280
      ++pBoundInfo->numOfBound;
233,895✔
281
      continue;
233,895✔
282
    }
283

284
    int16_t t = lastColIdx + 1;
666,305,902✔
285
    int16_t end = (boundColsType == BOUND_ALL_AND_TBNAME) ? (pBoundInfo->numOfCols - 1) : pBoundInfo->numOfCols;
666,305,902✔
286
    int16_t index = insFindCol(&token, t, end, pSchema);
666,305,902✔
287
    if (index < 0 && t > 0) {
666,305,939✔
288
      index = insFindCol(&token, 0, t, pSchema);
13,375,510✔
289
    }
290
    if (index < 0) {
666,305,939✔
291
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z);
4,142✔
292
    } else if (pUseCols[index]) {
666,301,797✔
293
      code = buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z);
×
294
    } else {
295
      lastColIdx = index;
666,301,834✔
296
      pUseCols[index] = true;
666,301,834✔
297
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = index;
666,301,834✔
298
      ++pBoundInfo->numOfBound;
666,301,797✔
299
      if (hasPK && (pSchema[index].flags & COL_IS_KEY)) ++numOfBoundPKs;
666,301,834✔
300

301
      if (pPrivCols) {  // check column-level privileges
666,301,834✔
302
        int32_t j = lastPrivColIdx;
9,012✔
303
        bool    found = false;
9,012✔
304
        for (; lastPrivColIdx < nPrivCols; ++lastPrivColIdx) {
15,932✔
305
          SColNameFlag* pColNameFlag = (SColNameFlag*)TARRAY_GET_ELEM(pPrivCols, lastPrivColIdx);
13,840✔
306
          if (pSchema[index].colId == pColNameFlag->colId) {
13,840✔
307
            found = true;
6,920✔
308
            break;
6,920✔
309
          }
310
        }
311
        if (!found) {
9,012✔
312
          for (int32_t k = 0; k < j; ++k) {
2,414✔
313
            SColNameFlag* pColNameFlag = (SColNameFlag*)TARRAY_GET_ELEM(pPrivCols, k);
322✔
314
            if (pSchema[index].colId == pColNameFlag->colId) {
322✔
315
              found = true;
×
316
              break;
×
317
            }
318
          }
319
        }
320
        if (!found) {
9,012✔
321
          taosMemoryFree(pUseCols);
2,092✔
322
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_COL_PERMISSION_DENIED, token.z);
2,092✔
323
        }
324
      }
325
    }
326
  }
327

328
  if (TSDB_CODE_SUCCESS == code && (BOUND_TAGS != boundColsType)) {
45,994,396✔
329
    if (!pUseCols[0]) {
45,730,018✔
330
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary timestamp column should not be null");
14,736✔
331
    }
332
    if (numOfBoundPKs != pTableMeta->tableInfo.numOfPKs) {
45,730,018✔
333
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary key column should not be none");
12,546✔
334
    }
335
  }
336
  if (TSDB_CODE_SUCCESS == code && (BOUND_ALL_AND_TBNAME == boundColsType) && !pUseCols[tbnameSchemaIndex]) {
45,994,396✔
337
    code = buildInvalidOperationMsg(&pCxt->msg, "tbname column should not be null");
837✔
338
  }
339
  taosMemoryFree(pUseCols);
45,994,396✔
340

341
  return code;
45,994,396✔
342
}
343

344
static int32_t parseTimestampOrInterval(const char** end, SToken* pToken, int16_t timePrec, int64_t* ts,
2,147,483,647✔
345
                                        int64_t* interval, SMsgBuf* pMsgBuf, bool* isTs, timezone_t tz) {
346
  if (pToken->type == TK_NOW) {
2,147,483,647✔
347
    *isTs = true;
2,147,483,647✔
348
    *ts = taosGetTimestamp(timePrec);
2,147,483,647✔
349
  } else if (pToken->type == TK_TODAY) {
2,147,483,647✔
350
    *isTs = true;
44,284✔
351
    *ts = taosGetTimestampToday(timePrec, tz);
44,284✔
352
  } else if (pToken->type == TK_NK_INTEGER) {
2,147,483,647✔
353
    *isTs = true;
2,147,483,647✔
354
    if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, ts)) {
2,147,483,647✔
355
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
6,178✔
356
    }
357
  } else if (pToken->type == TK_NK_VARIABLE) {
2,147,483,647✔
358
    char unit = 0;
2,147,483,647✔
359
    *isTs = false;
2,147,483,647✔
360
    if (parseAbsoluteDuration(pToken->z, pToken->n, interval, &unit, timePrec) != TSDB_CODE_SUCCESS) {
2,147,483,647✔
361
      return TSDB_CODE_TSC_INVALID_OPERATION;
5,555✔
362
    }
363
  } else {  // parse the RFC-3339/ISO-8601 timestamp format string
364
    *isTs = true;
2,147,483,647✔
365
    if (taosParseTime(pToken->z, ts, pToken->n, timePrec, tz) != TSDB_CODE_SUCCESS) {
2,147,483,647✔
366
      if ((pToken->n == 0) ||
10,832,496✔
367
          (pToken->type != TK_NK_STRING && pToken->type != TK_NK_HEX && pToken->type != TK_NK_BIN)) {
10,827,585✔
368
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
8,363✔
369
      }
370
      if (IS_NOW_STR(pToken->z, pToken->n)) {
10,824,133✔
371
        *isTs = true;
9,571✔
372
        *ts = taosGetTimestamp(timePrec);
19,142✔
373
      } else if (IS_TODAY_STR(pToken->z, pToken->n)) {
10,814,562✔
374
        *isTs = true;
9,571✔
375
        *ts = taosGetTimestampToday(timePrec, tz);
9,571✔
376
      } else if (TSDB_CODE_SUCCESS == toIntegerPure(pToken->z, pToken->n, 10, ts)) {
10,804,991✔
377
        *isTs = true;
10,782,652✔
378
      } else {
379
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
22,339✔
380
      }
381
    }
382
  }
383

384
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
385
}
386

387
static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf,
2,147,483,647✔
388
                     timezone_t tz) {
389
  int32_t     index = 0, i = 0;
2,147,483,647✔
390
  int64_t     interval = 0, tempInterval = 0;
2,147,483,647✔
391
  int64_t     ts = 0, tempTs = 0;
2,147,483,647✔
392
  bool        firstIsTS = false, secondIsTs = false;
2,147,483,647✔
393
  const char* pTokenEnd = *end;
2,147,483,647✔
394

395
  if (TSDB_CODE_SUCCESS !=
2,147,483,647✔
396
      parseTimestampOrInterval(&pTokenEnd, pToken, timePrec, &ts, &interval, pMsgBuf, &firstIsTS, tz)) {
2,147,483,647✔
397
    return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
31,983✔
398
  }
399

400
  if (firstIsTS) {
2,147,483,647✔
401
    *time = ts;
2,147,483,647✔
402
  }
403

404
  for (int k = pToken->n; pToken->z[k] != '\0'; k++) {
2,147,483,647✔
405
    if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue;
2,147,483,647✔
406
    if (pToken->z[k] == '(') {  // for insert NOW()/TODAY()
2,147,483,647✔
407
      if (pToken->z[k + 1] == ')') {
4,120,185✔
408
        *end = pTokenEnd = &pToken->z[k + 2];
4,119,370✔
409
        ++k;
4,119,370✔
410
        continue;
4,119,370✔
411
      } else {
412
        char nc = pToken->z[k + 1];
815✔
413
        while (nc == ' ' || nc == '\t' || nc == '\n' || nc == '\r' || nc == '\f') {
1,630✔
414
          nc = pToken->z[(++k) + 1];
815✔
415
        }
416
        if (nc == ')') {
815✔
417
          *end = pTokenEnd = &pToken->z[k + 2];
815✔
418
          ++k;
815✔
419
          continue;
815✔
420
        }
421
      }
422
    }
423
    if (pToken->z[k] == ',') {
2,147,483,647✔
424
      *end = pTokenEnd;
2,147,483,647✔
425
      if (!firstIsTS) {
2,147,483,647✔
426
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
427
      }
428
      *time = ts;
2,147,483,647✔
429
      return TSDB_CODE_SUCCESS;
2,147,483,647✔
430
    }
431
    break;
2,147,483,647✔
432
  }
433

434
  while (pTokenEnd[i] != '\0') {
2,147,483,647✔
435
    if (pTokenEnd[i] == ' ' || pTokenEnd[i] == '\t') {
2,147,483,647✔
436
      i++;
21,970,329✔
437
      continue;
21,970,329✔
438
    } else if (pTokenEnd[i] == ',' || pTokenEnd[i] == ')') {
2,147,483,647✔
439
      *end = pTokenEnd + i;
2,147,483,647✔
440
      if (!firstIsTS) {
2,147,483,647✔
441
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
442
      }
443
      *time = ts;
2,147,483,647✔
444
      return TSDB_CODE_SUCCESS;
2,147,483,647✔
445
    } else {
446
      break;
447
    }
448
  }
449
  pTokenEnd = pTokenEnd + i;
2,147,483,647✔
450

451
  index = 0;
2,147,483,647✔
452
  SToken token = tStrGetToken(pTokenEnd, &index, false, NULL);
2,147,483,647✔
453

454
  if (token.type == TK_NK_MINUS || token.type == TK_NK_PLUS) {
2,147,483,647✔
455
    pTokenEnd += index;
2,147,483,647✔
456
    index = 0;
2,147,483,647✔
457
    SToken valueToken = tStrGetToken(pTokenEnd, &index, false, NULL);
2,147,483,647✔
458
    pTokenEnd += index;
2,147,483,647✔
459
    char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW];
2,147,483,647✔
460
    if (TK_NK_STRING == valueToken.type) {
2,147,483,647✔
461
      if (valueToken.n >= TSDB_MAX_BYTES_PER_ROW) {
96✔
462
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", valueToken.z);
233,743✔
463
      }
464
      int32_t len = trimString(valueToken.z, valueToken.n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
96✔
465
      valueToken.z = tmpTokenBuf;
96✔
466
      valueToken.n = len;
96✔
467
    }
468

469
    if (TSDB_CODE_SUCCESS !=
2,147,483,647✔
470
        parseTimestampOrInterval(&pTokenEnd, &valueToken, timePrec, &tempTs, &tempInterval, pMsgBuf, &secondIsTs, tz)) {
2,147,483,647✔
471
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
5,555✔
472
    }
473

474
    if (valueToken.n < 2) {
2,147,483,647✔
475
      return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", token.z);
×
476
    }
477

478
    if (secondIsTs) {
2,147,483,647✔
479
      // not support operator between tow timestamp, such as today() + now()
480
      if (firstIsTS) {
3,804✔
481
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
3,420✔
482
      }
483
      ts = tempTs;
384✔
484
    } else {
485
      // not support operator between tow interval, such as 2h + 3s
486
      if (!firstIsTS) {
2,147,483,647✔
487
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
192✔
488
      }
489
      interval = tempInterval;
2,147,483,647✔
490
    }
491
    if (token.type == TK_NK_MINUS) {
2,147,483,647✔
492
      // not support interval - ts,such as 2h - today()
493
      if (secondIsTs) {
2,413,412✔
494
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
192✔
495
      }
496
      *time = ts - interval;
2,413,220✔
497
    } else {
498
      *time = ts + interval;
2,147,483,647✔
499
    }
500

501
    for (int k = valueToken.n; valueToken.z[k] != '\0'; k++) {
2,147,483,647✔
502
      if (valueToken.z[k] == ' ' || valueToken.z[k] == '\t') continue;
2,147,483,647✔
503
      if (valueToken.z[k] == '(' && valueToken.z[k + 1] == ')') {  // for insert NOW()/TODAY()
2,147,483,647✔
504
        *end = pTokenEnd = &valueToken.z[k + 2];
×
505
        k++;
×
506
        continue;
×
507
      }
508
      if (valueToken.z[k] == ',' || valueToken.z[k] == ')') {
2,147,483,647✔
509
        *end = pTokenEnd;
2,147,483,647✔
510
        return TSDB_CODE_SUCCESS;
2,147,483,647✔
511
      }
512
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
1,726✔
513
    }
514
  }
515

516
  *end = pTokenEnd;
2,336,005✔
517
  return TSDB_CODE_SUCCESS;
2,336,005✔
518
}
519

520
// need to call geosFreeBuffer(*output) later
521
static int parseGeometry(SToken* pToken, unsigned char** output, size_t* size) {
147,313,618✔
522
#ifdef USE_GEOS
523
  int32_t code = TSDB_CODE_FAILED;
147,313,618✔
524

525
  //[ToDo] support to parse WKB as well as WKT
526
  if (pToken->type == TK_NK_STRING) {
147,313,618✔
527
    code = initCtxGeomFromText();
147,296,870✔
528
    if (code != TSDB_CODE_SUCCESS) {
147,296,808✔
529
      return code;
×
530
    }
531

532
    code = doGeomFromText(pToken->z, output, size);
147,296,808✔
533
    if (code != TSDB_CODE_SUCCESS) {
147,296,870✔
534
      return code;
1,344✔
535
    }
536
  }
537

538
  return code;
147,312,274✔
539
#else
540
  TAOS_RETURN(TSDB_CODE_OPS_NOT_SUPPORT);
541
#endif
542
}
543

544
static int32_t parseSingleStrParam(SInsertParseContext* pCxt, const char** ppSql, SToken* pToken, SColVal* pVal,
6,516✔
545
                                   char* tokenBuf, int32_t* inputBytes, bool* final) {
546
  NEXT_VALID_TOKEN(*ppSql, *pToken);
6,516✔
547
  if (TK_NK_LP != pToken->type) {
6,516✔
548
    return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z);
×
549
  }
550

551
  NEXT_VALID_TOKEN(*ppSql, *pToken);
6,516✔
552
  if (TK_NULL == pToken->type) {
6,516✔
553
    NEXT_VALID_TOKEN(*ppSql, *pToken);
1,629✔
554
    if (TK_NK_RP == pToken->type) {
1,629✔
555
      pVal->flag = CV_FLAG_NULL;
1,629✔
556

557
      *final = true;
1,629✔
558
      return TSDB_CODE_SUCCESS;
1,629✔
559
    } else {
560
      return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
561
    }
562
  } else if (TK_NK_STRING != pToken->type) {
4,887✔
563
    return buildSyntaxErrMsg(&pCxt->msg, "string expected", pToken->z);
×
564
  }
565

566
  *inputBytes = trimString(pToken->z, pToken->n, tokenBuf, TSDB_MAX_BYTES_PER_ROW);
4,887✔
567

568
  NEXT_VALID_TOKEN(*ppSql, *pToken);
4,887✔
569
  if (TK_NK_RP != pToken->type) {
4,887✔
570
    return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
571
  }
572

573
  return TSDB_CODE_SUCCESS;
4,887✔
574
}
575

576
static int32_t parseBinary(SInsertParseContext* pCxt, const char** ppSql, SToken* pToken, SColVal* pVal,
2,147,483,647✔
577
                           SSchema* pSchema) {
578
  int32_t   code = 0;
2,147,483,647✔
579
  int32_t   bytes = pSchema->bytes;
2,147,483,647✔
580
  uint8_t** pData = &pVal->value.pData;
2,147,483,647✔
581
  uint32_t* nData = &pVal->value.nData;
2,147,483,647✔
582

583
  if (pToken->type == TK_FROM_BASE64 || pToken->type == TK_TO_BASE64 || pToken->type == TK_MD5 ||
2,147,483,647✔
584
      pToken->type == TK_SHA || pToken->type == TK_SHA1 || pToken->type == TK_SHA2 || pToken->type == TK_AES_ENCRYPT ||
2,147,483,647✔
585
      pToken->type == TK_AES_DECRYPT || pToken->type == TK_SM4_ENCRYPT || pToken->type == TK_SM4_DECRYPT) {
2,147,483,647✔
586
    char*   input = NULL;
12,168,910✔
587
    int32_t inputBytes = 0;
12,168,910✔
588
    int32_t outputBytes = 0;
27,693✔
589
    bool    final = false;
27,693✔
590

591
    char* tmpTokenBuf = taosMemoryMalloc(TSDB_MAX_BYTES_PER_ROW);
27,693✔
592
    if (NULL == tmpTokenBuf) {
27,693✔
593
      return terrno;
×
594
    }
595

596
    if (pToken->type == TK_FROM_BASE64) {
27,693✔
597
      code = parseSingleStrParam(pCxt, ppSql, pToken, pVal, tmpTokenBuf, &inputBytes, &final);
2,172✔
598
      if (TSDB_CODE_SUCCESS != code || final) {
2,172✔
599
        taosMemoryFree(tmpTokenBuf);
543✔
600

601
        return code;
543✔
602
      }
603

604
      input = tmpTokenBuf;
1,629✔
605

606
      outputBytes = tbase64_decode_len(inputBytes);
1,629✔
607
      if (outputBytes + VARSTR_HEADER_SIZE > bytes) {
1,629✔
608
        taosMemoryFree(tmpTokenBuf);
×
609

610
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
611
      }
612

613
      *pData = taosMemoryMalloc(outputBytes);
1,629✔
614
      if (NULL == *pData) {
1,629✔
615
        taosMemoryFree(tmpTokenBuf);
×
616

617
        return terrno;
×
618
      }
619

620
      if (TSDB_CODE_SUCCESS != tbase64_decode(*pData, (const uint8_t*)input, inputBytes, (VarDataLenT*)&outputBytes)) {
1,629✔
621
        pVal->flag = CV_FLAG_NULL;
543✔
622

623
        taosMemoryFree(tmpTokenBuf);
543✔
624

625
        return TSDB_CODE_SUCCESS;
543✔
626
      }
627
      *nData = outputBytes;
1,086✔
628
    } else if (pToken->type == TK_TO_BASE64) {
25,521✔
629
      code = parseSingleStrParam(pCxt, ppSql, pToken, pVal, tmpTokenBuf, &inputBytes, &final);
2,172✔
630
      if (TSDB_CODE_SUCCESS != code || final) {
2,172✔
631
        taosMemoryFree(tmpTokenBuf);
543✔
632

633
        return code;
543✔
634
      }
635

636
      input = tmpTokenBuf;
1,629✔
637

638
      outputBytes = tbase64_encode_len(inputBytes);
1,629✔
639
      if (outputBytes + VARSTR_HEADER_SIZE > bytes) {
1,629✔
640
        taosMemoryFree(tmpTokenBuf);
×
641

642
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
643
      }
644

645
      *pData = taosMemoryMalloc(outputBytes);
1,629✔
646
      if (NULL == *pData) {
1,629✔
647
        taosMemoryFree(tmpTokenBuf);
×
648

649
        return terrno;
×
650
      }
651

652
      tbase64_encode(*pData, input, inputBytes, outputBytes);
1,629✔
653
      *nData = outputBytes;
1,629✔
654
    } else if (pToken->type == TK_MD5) {
23,349✔
655
      code = parseSingleStrParam(pCxt, ppSql, pToken, pVal, tmpTokenBuf, &inputBytes, &final);
2,172✔
656
      if (TSDB_CODE_SUCCESS != code || final) {
2,172✔
657
        taosMemoryFree(tmpTokenBuf);
543✔
658

659
        return code;
543✔
660
      }
661

662
      input = tmpTokenBuf;
1,629✔
663

664
      if (MD5_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) {
1,629✔
665
        taosMemoryFree(tmpTokenBuf);
×
666

667
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
668
      }
669

670
      int32_t bufLen = TMAX(MD5_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, inputBytes);
1,629✔
671
      *pData = taosMemoryMalloc(bufLen);
1,629✔
672
      if (NULL == *pData) {
1,629✔
673
        taosMemoryFree(tmpTokenBuf);
×
674

675
        return terrno;
×
676
      }
677

678
      (void)memcpy(*pData, input, inputBytes);
1,629✔
679
      int32_t len = taosCreateMD5Hash(*pData, inputBytes, bufLen);
1,629✔
680
      *nData = len;
1,629✔
681
    } else if (pToken->type == TK_SHA2) {
21,177✔
682
      NEXT_VALID_TOKEN(*ppSql, *pToken);
8,688✔
683
      if (TK_NK_LP != pToken->type) {
8,688✔
684
        taosMemoryFree(tmpTokenBuf);
×
685

686
        return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z);
×
687
      }
688

689
      NEXT_VALID_TOKEN(*ppSql, *pToken);
8,688✔
690
      if (TK_NULL == pToken->type) {
8,688✔
691
        NEXT_VALID_TOKEN(*ppSql, *pToken);
2,172✔
692
        if (TK_NK_COMMA != pToken->type) {
2,172✔
693
          taosMemoryFree(tmpTokenBuf);
×
694

695
          return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
696
        }
697

698
        NEXT_VALID_TOKEN(*ppSql, *pToken);
4,344✔
699
        if (TK_NK_INTEGER != pToken->type) {
2,172✔
700
          taosMemoryFree(tmpTokenBuf);
×
701

702
          return buildSyntaxErrMsg(&pCxt->msg, "integer [224, 256, 384, 512] expected", pToken->z);
×
703
        }
704

705
        NEXT_VALID_TOKEN(*ppSql, *pToken);
2,172✔
706
        if (TK_NK_RP == pToken->type) {
2,172✔
707
          pVal->flag = CV_FLAG_NULL;
2,172✔
708

709
          taosMemoryFree(tmpTokenBuf);
2,172✔
710

711
          return TSDB_CODE_SUCCESS;
2,172✔
712
        }
713
      } else if (TK_NK_STRING != pToken->type) {
6,516✔
714
        taosMemoryFree(tmpTokenBuf);
×
715

716
        return buildSyntaxErrMsg(&pCxt->msg, "string expected", pToken->z);
×
717
      }
718

719
      inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
6,516✔
720
      input = tmpTokenBuf;
6,516✔
721

722
      NEXT_VALID_TOKEN(*ppSql, *pToken);
6,516✔
723
      if (TK_NK_COMMA != pToken->type) {
6,516✔
724
        taosMemoryFree(tmpTokenBuf);
×
725

726
        return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
727
      }
728

729
      int64_t digestLen = 224;
6,516✔
730
      NEXT_VALID_TOKEN(*ppSql, *pToken);
13,032✔
731
      if (TK_NK_INTEGER != pToken->type) {
6,516✔
732
        taosMemoryFree(tmpTokenBuf);
×
733

734
        return buildSyntaxErrMsg(&pCxt->msg, "integer [224, 256, 384, 512] expected", pToken->z);
×
735
      } else {
736
        if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &digestLen)) {
6,516✔
737
          taosMemoryFree(tmpTokenBuf);
×
738

739
          return buildSyntaxErrMsg(&pCxt->msg, "invalid integer format", pToken->z);
×
740
        }
741

742
        if (224 != digestLen && 256 != digestLen && 384 != digestLen && 512 != digestLen) {
6,516✔
743
          taosMemoryFree(tmpTokenBuf);
×
744

745
          return buildSyntaxErrMsg(&pCxt->msg, "sha2 digest length must be one of 224, 256, 384, 512", pToken->z);
×
746
        }
747
      }
748

749
      NEXT_VALID_TOKEN(*ppSql, *pToken);
6,516✔
750
      if (TK_NK_RP != pToken->type) {
6,516✔
751
        taosMemoryFree(tmpTokenBuf);
×
752

753
        return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
754
      }
755

756
      if (SHA2_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) {
6,516✔
757
        taosMemoryFree(tmpTokenBuf);
×
758

759
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
760
      }
761

762
      int32_t bufLen = TMAX(SHA2_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, inputBytes);
6,516✔
763
      *pData = taosMemoryMalloc(bufLen);
6,516✔
764
      if (NULL == *pData) {
6,516✔
765
        taosMemoryFree(tmpTokenBuf);
×
766

767
        return terrno;
×
768
      }
769

770
      (void)memcpy(*pData, input, inputBytes);
6,516✔
771
      int32_t len = taosCreateSHA2Hash((char *)*pData, inputBytes, digestLen, bufLen);
6,516✔
772
      *nData = len;
6,516✔
773
    } else if (pToken->type == TK_SHA || pToken->type == TK_SHA1) {
12,489✔
774
      NEXT_VALID_TOKEN(*ppSql, *pToken);
4,344✔
775
      if (TK_NK_LP != pToken->type) {
4,344✔
776
        taosMemoryFree(tmpTokenBuf);
×
777

778
        return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z);
×
779
      }
780

781
      NEXT_VALID_TOKEN(*ppSql, *pToken);
4,344✔
782
      if (TK_NULL == pToken->type) {
4,344✔
783
        NEXT_VALID_TOKEN(*ppSql, *pToken);
1,086✔
784
        if (TK_NK_RP == pToken->type) {
1,086✔
785
          pVal->flag = CV_FLAG_NULL;
1,086✔
786

787
          taosMemoryFree(tmpTokenBuf);
1,086✔
788

789
          return TSDB_CODE_SUCCESS;
1,086✔
790
        }
791
      } else if (TK_NK_STRING != pToken->type) {
3,258✔
792
        taosMemoryFree(tmpTokenBuf);
×
793

794
        return buildSyntaxErrMsg(&pCxt->msg, "string expected", pToken->z);
×
795
      }
796

797
      inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
3,258✔
798
      input = tmpTokenBuf;
3,258✔
799

800
      NEXT_VALID_TOKEN(*ppSql, *pToken);
3,258✔
801
      if (TK_NK_RP != pToken->type) {
3,258✔
802
        taosMemoryFree(tmpTokenBuf);
×
803

804
        return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
805
      }
806

807
      if (SHA1_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) {
3,258✔
808
        taosMemoryFree(tmpTokenBuf);
×
809

810
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
811
      }
812

813
      int32_t bufLen = TMAX(SHA1_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, inputBytes);
3,258✔
814
      *pData = taosMemoryMalloc(bufLen);
3,258✔
815
      if (NULL == *pData) {
3,258✔
816
        taosMemoryFree(tmpTokenBuf);
×
817

818
        return terrno;
×
819
      }
820

821
      (void)memcpy(*pData, input, inputBytes);
3,258✔
822
      int32_t len = taosCreateSHA1Hash((char *)(*pData), inputBytes, bufLen) ;
3,258✔
823
      *nData = len;
3,258✔
824
    } else if (pToken->type == TK_AES_ENCRYPT) {
8,145✔
825
      NEXT_VALID_TOKEN(*ppSql, *pToken);
3,258✔
826
      if (TK_NK_LP != pToken->type) {
3,258✔
827
        taosMemoryFree(tmpTokenBuf);
×
828

829
        return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z);
×
830
      }
831

832
      NEXT_VALID_TOKEN(*ppSql, *pToken);
3,258✔
833
      if (TK_NK_STRING != pToken->type && TK_NULL != pToken->type) {
3,258✔
834
        taosMemoryFree(tmpTokenBuf);
×
835

836
        return buildSyntaxErrMsg(&pCxt->msg, "string or null expected", pToken->z);
×
837
      } else if (TK_NULL == pToken->type) {
3,258✔
838
        NEXT_VALID_TOKEN(*ppSql, *pToken);
1,629✔
839
        if (TK_NK_COMMA != pToken->type) {
1,629✔
840
          taosMemoryFree(tmpTokenBuf);
×
841

842
          return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
843
        }
844

845
        NEXT_VALID_TOKEN(*ppSql, *pToken);
3,258✔
846
        if (TK_NK_STRING != pToken->type) {
1,629✔
847
          taosMemoryFree(tmpTokenBuf);
1,086✔
848

849
          return buildSyntaxErrMsg(&pCxt->msg, "key string expected", pToken->z);
1,086✔
850
        }
851

852
        NEXT_VALID_TOKEN(*ppSql, *pToken);
543✔
853
        if (TK_NK_RP == pToken->type) {
543✔
854
          pVal->flag = CV_FLAG_NULL;
543✔
855

856
          taosMemoryFree(tmpTokenBuf);
543✔
857

858
          return TSDB_CODE_SUCCESS;
543✔
859
        } else if (TK_NK_STRING == pToken->type) {
×
860
          NEXT_VALID_TOKEN(*ppSql, *pToken);
×
861
          if (TK_NK_RP == pToken->type) {
×
862
            pVal->flag = CV_FLAG_NULL;
×
863

864
            taosMemoryFree(tmpTokenBuf);
×
865

866
            return TSDB_CODE_SUCCESS;
×
867
          }
868
        } else {
869
          taosMemoryFree(tmpTokenBuf);
×
870

871
          return buildSyntaxErrMsg(&pCxt->msg, "iv string expected", pToken->z);
×
872
        }
873
      } else {
874
        inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
1,629✔
875
        input = tmpTokenBuf;
1,629✔
876
      }
877

878
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,629✔
879
      if (TK_NK_COMMA != pToken->type) {
1,629✔
880
        taosMemoryFree(tmpTokenBuf);
×
881

882
        return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
883
      }
884

885
      char*   key = NULL;
1,629✔
886
      int32_t keyBytes = 0;
1,629✔
887
      char    tmpKeyBuf[TSDB_MAX_BYTES_PER_ROW];
1,629✔
888

889
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,715✔
890
      if (TK_NK_STRING != pToken->type) {
1,629✔
891
        taosMemoryFree(tmpTokenBuf);
×
892

893
        return buildSyntaxErrMsg(&pCxt->msg, "key expected", pToken->z);
×
894
      } else {
895
        keyBytes = trimString(pToken->z, pToken->n, tmpKeyBuf, TSDB_MAX_BYTES_PER_ROW);
1,629✔
896
        key = tmpKeyBuf;
1,629✔
897
      }
898

899
      char*   iv = NULL;
1,629✔
900
      int32_t ivBytes = 0;
1,629✔
901
      char    tmpIvBuf[TSDB_MAX_BYTES_PER_ROW];
1,629✔
902

903
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,629✔
904
      if (TK_NK_RP != pToken->type && TK_NK_STRING != pToken->type) {
1,629✔
905
        taosMemoryFree(tmpTokenBuf);
×
906

907
        return buildSyntaxErrMsg(&pCxt->msg, ") or iv expected", pToken->z);
×
908
      } else if (TK_NK_STRING == pToken->type) {
1,629✔
909
        ivBytes = trimString(pToken->z, pToken->n, tmpIvBuf, TSDB_MAX_BYTES_PER_ROW);
×
910
        iv = tmpIvBuf;
×
911

912
        NEXT_VALID_TOKEN(*ppSql, *pToken);
×
913
        if (TK_NK_RP != pToken->type) {
×
914
          taosMemoryFree(tmpTokenBuf);
×
915

916
          return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
917
        }
918
      }
919

920
      int32_t outputBytes = taes_encrypt_len(inputBytes);
1,629✔
921
      if (outputBytes + VARSTR_HEADER_SIZE > bytes) {
1,629✔
922
        taosMemoryFree(tmpTokenBuf);
×
923

924
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
925
      }
926

927
      int32_t bufLen = outputBytes + VARSTR_HEADER_SIZE + 1;
1,629✔
928
      *pData = taosMemoryCalloc(1, bufLen);
1,629✔
929
      if (NULL == *pData) {
1,629✔
930
        taosMemoryFree(tmpTokenBuf);
×
931

932
        return terrno;
×
933
      }
934

935
      (void)memcpy(*pData, input, inputBytes);
1,629✔
936

937
      int32_t keypaddedlen = taes_encrypt_len(keyBytes);
1,629✔
938
      char*   pKeyPaddingBuf = taosMemoryMalloc(keypaddedlen);
1,629✔
939
      if (!pKeyPaddingBuf) {
1,629✔
940
        taosMemoryFree(tmpTokenBuf);
×
941

942
        return terrno;
×
943
      }
944
      (void)memcpy(pKeyPaddingBuf, key, keyBytes);
1,629✔
945

946
      int32_t len = taosAesEncrypt(pKeyPaddingBuf, keyBytes, *pData, inputBytes, iv);
1,629✔
947
      *nData = len;
1,629✔
948

949
      taosMemoryFree(pKeyPaddingBuf);
1,629✔
950
    } else if (pToken->type == TK_AES_DECRYPT) {
4,887✔
951
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,086✔
952
      if (TK_NK_LP != pToken->type) {
1,086✔
953
        taosMemoryFree(tmpTokenBuf);
×
954

955
        return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z);
×
956
      }
957

958
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,086✔
959
      if (TK_NK_STRING != pToken->type && TK_NULL != pToken->type) {
1,086✔
960
        taosMemoryFree(tmpTokenBuf);
×
961

962
        return buildSyntaxErrMsg(&pCxt->msg, "string or null expected", pToken->z);
×
963
      } else if (TK_NULL == pToken->type) {
1,086✔
964
        NEXT_VALID_TOKEN(*ppSql, *pToken);
1,086✔
965
        if (TK_NK_COMMA != pToken->type) {
1,086✔
966
          taosMemoryFree(tmpTokenBuf);
×
967

968
          return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
969
        }
970

971
        NEXT_VALID_TOKEN(*ppSql, *pToken);
2,172✔
972
        if (TK_NK_STRING != pToken->type) {
1,086✔
973
          taosMemoryFree(tmpTokenBuf);
543✔
974

975
          return buildSyntaxErrMsg(&pCxt->msg, "key string expected", pToken->z);
543✔
976
        }
977

978
        NEXT_VALID_TOKEN(*ppSql, *pToken);
543✔
979
        if (TK_NK_RP == pToken->type) {
543✔
980
          pVal->flag = CV_FLAG_NULL;
543✔
981

982
          taosMemoryFree(tmpTokenBuf);
543✔
983

984
          return TSDB_CODE_SUCCESS;
543✔
985
        } else if (TK_NK_STRING == pToken->type) {
×
986
          NEXT_VALID_TOKEN(*ppSql, *pToken);
×
987
          if (TK_NK_RP == pToken->type) {
×
988
            pVal->flag = CV_FLAG_NULL;
×
989

990
            taosMemoryFree(tmpTokenBuf);
×
991

992
            return TSDB_CODE_SUCCESS;
×
993
          }
994
        } else {
995
          taosMemoryFree(tmpTokenBuf);
×
996

997
          return buildSyntaxErrMsg(&pCxt->msg, "iv string expected", pToken->z);
×
998
        }
999
      } else {
1000
        inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
×
1001
        input = tmpTokenBuf;
×
1002
      }
1003

1004
      NEXT_VALID_TOKEN(*ppSql, *pToken);
×
1005
      if (TK_NK_COMMA != pToken->type) {
×
1006
        taosMemoryFree(tmpTokenBuf);
×
1007

1008
        return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
1009
      }
1010

1011
      char*   key = NULL;
×
1012
      int32_t keyBytes = 0;
×
1013
      char    tmpKeyBuf[TSDB_MAX_BYTES_PER_ROW];
×
1014

1015
      NEXT_VALID_TOKEN(*ppSql, *pToken);
×
1016
      if (TK_NK_STRING != pToken->type) {
×
1017
        taosMemoryFree(tmpTokenBuf);
×
1018

1019
        return buildSyntaxErrMsg(&pCxt->msg, "key expected", pToken->z);
×
1020
      } else {
1021
        keyBytes = trimString(pToken->z, pToken->n, tmpKeyBuf, TSDB_MAX_BYTES_PER_ROW);
×
1022
        key = tmpKeyBuf;
×
1023
      }
1024

1025
      char*   iv = NULL;
×
1026
      int32_t ivBytes = 0;
×
1027
      char    tmpIvBuf[TSDB_MAX_BYTES_PER_ROW];
×
1028

1029
      NEXT_VALID_TOKEN(*ppSql, *pToken);
×
1030
      if (TK_NK_RP != pToken->type && TK_NK_STRING != pToken->type) {
×
1031
        taosMemoryFree(tmpTokenBuf);
×
1032

1033
        return buildSyntaxErrMsg(&pCxt->msg, ") or iv expected", pToken->z);
×
1034
      } else if (TK_NK_STRING == pToken->type) {
×
1035
        ivBytes = trimString(pToken->z, pToken->n, tmpIvBuf, TSDB_MAX_BYTES_PER_ROW);
×
1036
        iv = tmpIvBuf;
×
1037

1038
        NEXT_VALID_TOKEN(*ppSql, *pToken);
×
1039
        if (TK_NK_RP != pToken->type) {
×
1040
          taosMemoryFree(tmpTokenBuf);
×
1041

1042
          return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
1043
        }
1044
      }
1045

1046
      int32_t outputBytes = taes_encrypt_len(inputBytes);
×
1047
      if (outputBytes + VARSTR_HEADER_SIZE > bytes) {
×
1048
        taosMemoryFree(tmpTokenBuf);
×
1049

1050
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1051
      }
1052

1053
      int32_t bufLen = outputBytes + VARSTR_HEADER_SIZE + 1;
×
1054
      *pData = taosMemoryMalloc(bufLen);
×
1055
      if (NULL == *pData) {
×
1056
        taosMemoryFree(tmpTokenBuf);
×
1057

1058
        return terrno;
×
1059
      }
1060

1061
      (void)memcpy(*pData, input, inputBytes);
×
1062

1063
      int32_t keypaddedlen = taes_encrypt_len(keyBytes);
×
1064
      char*   pKeyPaddingBuf = taosMemoryMalloc(keypaddedlen);
×
1065
      if (!pKeyPaddingBuf) {
×
1066
        taosMemoryFree(tmpTokenBuf);
×
1067

1068
        return terrno;
×
1069
      }
1070
      (void)memcpy(pKeyPaddingBuf, key, keyBytes);
×
1071

1072
      int32_t len = taosAesDecrypt(pKeyPaddingBuf, keyBytes, *pData, inputBytes, iv);
×
1073
      *nData = len;
×
1074

1075
      taosMemoryFree(pKeyPaddingBuf);
×
1076
    } else if (pToken->type == TK_SM4_ENCRYPT) {
3,801✔
1077
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,715✔
1078
      if (TK_NK_LP != pToken->type) {
2,715✔
1079
        taosMemoryFree(tmpTokenBuf);
×
1080

1081
        return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z);
×
1082
      }
1083

1084
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,715✔
1085
      if (TK_NK_STRING != pToken->type && TK_NULL != pToken->type) {
2,715✔
1086
        taosMemoryFree(tmpTokenBuf);
×
1087

1088
        return buildSyntaxErrMsg(&pCxt->msg, "string or null expected", pToken->z);
×
1089
      } else if (TK_NULL == pToken->type) {
2,715✔
1090
        NEXT_VALID_TOKEN(*ppSql, *pToken);
1,086✔
1091
        if (TK_NK_COMMA != pToken->type) {
1,086✔
1092
          taosMemoryFree(tmpTokenBuf);
×
1093

1094
          return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
1095
        }
1096

1097
        NEXT_VALID_TOKEN(*ppSql, *pToken);
2,172✔
1098
        if (TK_NK_STRING != pToken->type) {
1,086✔
1099
          taosMemoryFree(tmpTokenBuf);
543✔
1100

1101
          return buildSyntaxErrMsg(&pCxt->msg, "key string expected", pToken->z);
543✔
1102
        }
1103

1104
        NEXT_VALID_TOKEN(*ppSql, *pToken);
543✔
1105
        if (TK_NK_RP == pToken->type) {
543✔
1106
          pVal->flag = CV_FLAG_NULL;
543✔
1107

1108
          taosMemoryFree(tmpTokenBuf);
543✔
1109

1110
          return TSDB_CODE_SUCCESS;
543✔
1111
        } else {
1112
          taosMemoryFree(tmpTokenBuf);
×
1113

1114
          return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
1115
        }
1116
      } else {
1117
        inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
1,629✔
1118
        input = tmpTokenBuf;
1,629✔
1119
      }
1120

1121
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,629✔
1122
      if (TK_NK_COMMA != pToken->type) {
1,629✔
1123
        taosMemoryFree(tmpTokenBuf);
×
1124

1125
        return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
1126
      }
1127

1128
      char*   key = NULL;
1,629✔
1129
      int32_t keyBytes = 0;
1,629✔
1130
      char    tmpKeyBuf[TSDB_MAX_BYTES_PER_ROW];
1,629✔
1131

1132
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,715✔
1133
      if (TK_NK_STRING != pToken->type) {
1,629✔
1134
        taosMemoryFree(tmpTokenBuf);
×
1135

1136
        return buildSyntaxErrMsg(&pCxt->msg, "key expected", pToken->z);
×
1137
      } else {
1138
        keyBytes = trimString(pToken->z, pToken->n, tmpKeyBuf, TSDB_MAX_BYTES_PER_ROW);
1,629✔
1139
        key = tmpKeyBuf;
1,629✔
1140
      }
1141

1142
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,629✔
1143
      if (TK_NK_RP != pToken->type) {
1,629✔
1144
        taosMemoryFree(tmpTokenBuf);
×
1145

1146
        return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
1147
      }
1148

1149
      int32_t outputBytes = tsm4_encrypt_len(inputBytes);
1,629✔
1150
      if (outputBytes + VARSTR_HEADER_SIZE > bytes) {
1,629✔
1151
        taosMemoryFree(tmpTokenBuf);
×
1152

1153
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1154
      }
1155

1156
      int32_t bufLen = outputBytes + VARSTR_HEADER_SIZE + 1;
1,629✔
1157
      *pData = taosMemoryMalloc(bufLen);
1,629✔
1158
      if (NULL == *pData) {
1,629✔
1159
        taosMemoryFree(tmpTokenBuf);
×
1160

1161
        return terrno;
×
1162
      }
1163

1164
      (void)memcpy(*pData, input, inputBytes);
1,629✔
1165

1166
      int32_t keypaddedlen = tsm4_encrypt_len(keyBytes);
1,629✔
1167
      char*   pKeyPaddingBuf = taosMemoryMalloc(keypaddedlen);
1,629✔
1168
      if (!pKeyPaddingBuf) {
1,629✔
1169
        taosMemoryFree(tmpTokenBuf);
×
1170

1171
        return terrno;
×
1172
      }
1173
      (void)memcpy(pKeyPaddingBuf, key, keyBytes);
1,629✔
1174

1175
      int32_t len = taosSm4Encrypt(pKeyPaddingBuf, keyBytes, *pData, inputBytes);
1,629✔
1176
      *nData = len;
1,629✔
1177

1178
      taosMemoryFree(pKeyPaddingBuf);
1,629✔
1179
    } else if (pToken->type == TK_SM4_DECRYPT) {
1,086✔
1180
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,086✔
1181
      if (TK_NK_LP != pToken->type) {
1,086✔
1182
        taosMemoryFree(tmpTokenBuf);
×
1183

1184
        return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z);
×
1185
      }
1186

1187
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,086✔
1188
      if (TK_NK_STRING != pToken->type && TK_NULL != pToken->type) {
1,086✔
1189
        taosMemoryFree(tmpTokenBuf);
×
1190

1191
        return buildSyntaxErrMsg(&pCxt->msg, "string or null expected", pToken->z);
×
1192
      } else if (TK_NULL == pToken->type) {
1,086✔
1193
        NEXT_VALID_TOKEN(*ppSql, *pToken);
1,086✔
1194
        if (TK_NK_COMMA != pToken->type) {
1,086✔
1195
          taosMemoryFree(tmpTokenBuf);
×
1196

1197
          return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
1198
        }
1199

1200
        NEXT_VALID_TOKEN(*ppSql, *pToken);
2,172✔
1201
        if (TK_NK_STRING != pToken->type) {
1,086✔
1202
          taosMemoryFree(tmpTokenBuf);
543✔
1203

1204
          return buildSyntaxErrMsg(&pCxt->msg, "key string expected", pToken->z);
543✔
1205
        }
1206

1207
        NEXT_VALID_TOKEN(*ppSql, *pToken);
543✔
1208
        if (TK_NK_RP == pToken->type) {
543✔
1209
          pVal->flag = CV_FLAG_NULL;
543✔
1210

1211
          taosMemoryFree(tmpTokenBuf);
543✔
1212

1213
          return TSDB_CODE_SUCCESS;
543✔
1214
        } else {
1215
          taosMemoryFree(tmpTokenBuf);
×
1216

1217
          return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
1218
        }
1219
      } else {
1220
        inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
×
1221
        input = tmpTokenBuf;
×
1222
      }
1223

1224
      NEXT_VALID_TOKEN(*ppSql, *pToken);
×
1225
      if (TK_NK_COMMA != pToken->type) {
×
1226
        taosMemoryFree(tmpTokenBuf);
×
1227

1228
        return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
1229
      }
1230

1231
      char*   key = NULL;
×
1232
      int32_t keyBytes = 0;
×
1233
      char    tmpKeyBuf[TSDB_MAX_BYTES_PER_ROW];
×
1234

1235
      NEXT_VALID_TOKEN(*ppSql, *pToken);
×
1236
      if (TK_NK_STRING != pToken->type) {
×
1237
        taosMemoryFree(tmpTokenBuf);
×
1238

1239
        return buildSyntaxErrMsg(&pCxt->msg, "key expected", pToken->z);
×
1240
      } else {
1241
        keyBytes = trimString(pToken->z, pToken->n, tmpKeyBuf, TSDB_MAX_BYTES_PER_ROW);
×
1242
        key = tmpKeyBuf;
×
1243
      }
1244

1245
      NEXT_VALID_TOKEN(*ppSql, *pToken);
×
1246
      if (TK_NK_RP != pToken->type) {
×
1247
        taosMemoryFree(tmpTokenBuf);
×
1248

1249
        return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
1250
      }
1251

1252
      int32_t outputBytes = tsm4_encrypt_len(inputBytes);
×
1253
      if (outputBytes + VARSTR_HEADER_SIZE > bytes) {
×
1254
        taosMemoryFree(tmpTokenBuf);
×
1255

1256
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1257
      }
1258

1259
      int32_t bufLen = outputBytes + VARSTR_HEADER_SIZE + 1;
×
1260
      *pData = taosMemoryMalloc(bufLen);
×
1261
      if (NULL == *pData) {
×
1262
        taosMemoryFree(tmpTokenBuf);
×
1263

1264
        return terrno;
×
1265
      }
1266

1267
      (void)memcpy(*pData, input, inputBytes);
×
1268

1269
      int32_t keypaddedlen = tsm4_encrypt_len(keyBytes);
×
1270
      char*   pKeyPaddingBuf = taosMemoryMalloc(keypaddedlen);
×
1271
      if (!pKeyPaddingBuf) {
×
1272
        taosMemoryFree(tmpTokenBuf);
×
1273

1274
        return terrno;
×
1275
      }
1276
      (void)memcpy(pKeyPaddingBuf, key, keyBytes);
×
1277

1278
      int32_t len = taosSm4Decrypt(pKeyPaddingBuf, keyBytes, *pData, inputBytes);
×
1279
      *nData = len;
×
1280

1281
      taosMemoryFree(pKeyPaddingBuf);
×
1282
    } else {
1283
      taosMemoryFree(tmpTokenBuf);
×
1284

1285
      return buildSyntaxErrMsg(&pCxt->msg, "invalid identifier", pToken->z);
×
1286
    }
1287

1288
    taosMemoryFree(tmpTokenBuf);
17,376✔
1289
  } else {
1290
    if (pToken->n + VARSTR_HEADER_SIZE > bytes) {
2,147,483,647✔
1291
      return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
5,428✔
1292
    }
1293

1294
    *pData = taosMemoryMalloc(pToken->n);
2,147,483,647✔
1295
    if (NULL == *pData) {
2,147,483,647✔
1296
      return terrno;
×
1297
    }
1298
    memcpy(*pData, pToken->z, pToken->n);
2,147,483,647✔
1299
    *nData = pToken->n;
2,147,483,647✔
1300
  }
1301

1302
  pVal->flag = CV_FLAG_VALUE;
2,147,483,647✔
1303
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
1304
}
1305

1306
static int32_t parseVarbinary(SToken* pToken, uint8_t** pData, uint32_t* nData, int32_t bytes) {
2,147,483,647✔
1307
  if (pToken->type != TK_NK_STRING) {
2,147,483,647✔
1308
    return TSDB_CODE_PAR_INVALID_VARBINARY;
48,900✔
1309
  }
1310

1311
  if (isHex(pToken->z + 1, pToken->n - 2)) {
2,147,483,647✔
1312
    if (!isValidateHex(pToken->z + 1, pToken->n - 2)) {
3,869,371✔
1313
      return TSDB_CODE_PAR_INVALID_VARBINARY;
×
1314
    }
1315

1316
    void*    data = NULL;
3,869,371✔
1317
    uint32_t size = 0;
3,869,371✔
1318
    if (taosHex2Ascii(pToken->z + 1, pToken->n - 2, &data, &size) < 0) {
3,869,371✔
1319
      return TSDB_CODE_OUT_OF_MEMORY;
×
1320
    }
1321

1322
    if (size + VARSTR_HEADER_SIZE > bytes) {
3,869,371✔
1323
      taosMemoryFree(data);
1,140✔
1324
      return TSDB_CODE_PAR_VALUE_TOO_LONG;
1,140✔
1325
    }
1326
    *pData = data;
3,868,231✔
1327
    *nData = size;
3,868,231✔
1328
  } else {
1329
    *pData = taosMemoryCalloc(1, pToken->n);
2,147,483,647✔
1330
    if (!pData) return terrno;
2,147,483,647✔
1331
    int32_t len = trimString(pToken->z, pToken->n, *pData, pToken->n);
2,147,483,647✔
1332
    *nData = len;
2,147,483,647✔
1333

1334
    if (*nData + VARSTR_HEADER_SIZE > bytes) {
2,147,483,647✔
1335
      return TSDB_CODE_PAR_VALUE_TOO_LONG;
×
1336
    }
1337
  }
1338
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
1339
}
1340
static int32_t parseBlob(SToken* pToken, uint8_t** pData, uint32_t* nData, int32_t bytes) {
26,309,089✔
1341
  if (pToken->type != TK_NK_STRING) {
26,309,089✔
1342
    return TSDB_CODE_PAR_INVALID_VARBINARY;
9,780✔
1343
  }
1344
  int32_t  code = 0;
26,299,309✔
1345
  int32_t  lino = 0;
26,299,309✔
1346
  uint32_t size = 0;
26,299,309✔
1347
  *pData = NULL;
26,299,309✔
1348

1349
  if (isHex(pToken->z + 1, pToken->n - 2)) {
26,299,309✔
1350
    if (!isValidateHex(pToken->z + 1, pToken->n - 2)) {
3,347✔
1351
      return TSDB_CODE_PAR_INVALID_VARBINARY;
×
1352
    }
1353
    void* data = NULL;
3,347✔
1354

1355
    if (taosHex2Ascii(pToken->z + 1, pToken->n - 2, &data, &size) < 0) {
3,347✔
1356
      TSDB_CHECK_CODE(code, lino, _error);
×
1357
    }
1358
    *pData = data;
3,347✔
1359
    *nData = size;
3,347✔
1360
  } else {
1361
    *pData = taosMemoryCalloc(1, pToken->n);
26,295,962✔
1362
    if (!pData) return terrno;
26,295,962✔
1363
    size = trimString(pToken->z, pToken->n, (char*)*pData, pToken->n);
26,295,962✔
1364
    *nData = size;
26,295,962✔
1365
  }
1366

1367
  if (size + BLOBSTR_HEADER_SIZE > TSDB_MAX_BLOB_LEN) {
26,299,309✔
1368
    TSDB_CHECK_CODE(code = TSDB_CODE_BLOB_VALUE_TOO_LONG, lino, _error);
×
1369
  }
1370

1371
_error:
26,299,309✔
1372
  if (code != 0) {
26,299,309✔
1373
    taosMemoryFree(pData);
×
1374
    uError("parseBlob failed at lino %d code: %s", lino, tstrerror(code));
×
1375
    return code;
×
1376
  }
1377
  *nData = size;
26,299,309✔
1378
  return TSDB_CODE_SUCCESS;
26,299,309✔
1379
}
1380

1381
static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val,
183,566,548✔
1382
                             SMsgBuf* pMsgBuf, timezone_t tz, void* charsetCxt) {
1383
  int64_t  iv;
181,721,554✔
1384
  uint64_t uv;
181,725,164✔
1385
  char*    endptr = NULL;
183,570,981✔
1386
  int32_t  code = TSDB_CODE_SUCCESS;
183,570,981✔
1387

1388
#if 0
1389
  if (isNullValue(pSchema->type, pToken)) {
1390
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
1391
      return buildSyntaxErrMsg(pMsgBuf, "Primary timestamp column can not be null", pToken->z);
1392
    }
1393

1394
    return TSDB_CODE_SUCCESS;
1395
  }
1396
#endif
1397

1398
  val->cid = pSchema->colId;
183,570,981✔
1399
  val->type = pSchema->type;
183,574,626✔
1400

1401
  switch (pSchema->type) {
183,580,499✔
1402
    case TSDB_DATA_TYPE_BOOL: {
4,906,785✔
1403
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
4,906,785✔
1404
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
3,129,475✔
1405
          *(int8_t*)(&val->i64) = TRUE_VALUE;
2,114,520✔
1406
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
1,014,955✔
1407
          *(int8_t*)(&val->i64) = FALSE_VALUE;
980,028✔
1408
        } else if (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv)) {
34,927✔
1409
          *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
26,777✔
1410
        } else {
1411
          return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
8,150✔
1412
        }
1413
      } else if (pToken->type == TK_NK_INTEGER) {
1,777,310✔
1414
        *(int8_t*)(&val->i64) = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
1,752,045✔
1415
      } else if (pToken->type == TK_NK_FLOAT) {
25,265✔
1416
        *(int8_t*)(&val->i64) = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
11,410✔
1417
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
23,635✔
1418
                 (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv))) {
9,780✔
1419
        *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
9,780✔
1420
      } else {
1421
        return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
4,075✔
1422
      }
1423
      break;
4,894,560✔
1424
    }
1425

1426
    case TSDB_DATA_TYPE_TINYINT: {
4,103,205✔
1427
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
4,103,205✔
1428
      if (TSDB_CODE_SUCCESS != code) {
4,103,205✔
1429
        return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z);
10,595✔
1430
      } else if (!IS_VALID_TINYINT(iv)) {
4,092,610✔
1431
        return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z);
9,599✔
1432
      }
1433

1434
      *(int8_t*)(&val->i64) = iv;
4,083,011✔
1435
      break;
4,083,011✔
1436
    }
1437

1438
    case TSDB_DATA_TYPE_UTINYINT: {
1,014,426✔
1439
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,014,426✔
1440
      if (TSDB_CODE_SUCCESS != code) {
1,014,383✔
1441
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z);
1,512✔
1442
      } else if (uv > UINT8_MAX) {
1,012,871✔
1443
        return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z);
1,512✔
1444
      }
1445
      *(uint8_t*)(&val->i64) = uv;
1,011,359✔
1446
      break;
1,011,322✔
1447
    }
1448

1449
    case TSDB_DATA_TYPE_SMALLINT: {
4,172,716✔
1450
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
4,172,716✔
1451
      if (TSDB_CODE_SUCCESS != code) {
4,172,716✔
1452
        return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z);
10,595✔
1453
      } else if (!IS_VALID_SMALLINT(iv)) {
4,162,121✔
1454
        return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z);
9,544✔
1455
      }
1456
      *(int16_t*)(&val->i64) = iv;
4,152,577✔
1457
      break;
4,152,577✔
1458
    }
1459

1460
    case TSDB_DATA_TYPE_USMALLINT: {
1,033,070✔
1461
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,033,070✔
1462
      if (TSDB_CODE_SUCCESS != code) {
1,033,070✔
1463
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z);
1,512✔
1464
      } else if (uv > UINT16_MAX) {
1,031,558✔
1465
        return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z);
1,512✔
1466
      }
1467
      *(uint16_t*)(&val->i64) = uv;
1,030,046✔
1468
      break;
1,030,046✔
1469
    }
1470

1471
    case TSDB_DATA_TYPE_INT: {
59,874,692✔
1472
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
59,874,692✔
1473
      if (TSDB_CODE_SUCCESS != code) {
59,847,556✔
1474
        return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z);
13,319✔
1475
      } else if (!IS_VALID_INT(iv)) {
59,834,237✔
1476
        return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z);
3,806✔
1477
      }
1478
      *(int32_t*)(&val->i64) = iv;
59,848,078✔
1479
      break;
59,834,646✔
1480
    }
1481

1482
    case TSDB_DATA_TYPE_UINT: {
1,104,012✔
1483
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,104,012✔
1484
      if (TSDB_CODE_SUCCESS != code) {
1,104,000✔
1485
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z);
17,812✔
1486
      } else if (uv > UINT32_MAX) {
1,086,188✔
1487
        return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z);
2,327✔
1488
      }
1489
      *(uint32_t*)(&val->i64) = uv;
1,083,861✔
1490
      break;
1,083,861✔
1491
    }
1492

1493
    case TSDB_DATA_TYPE_BIGINT: {
11,156,799✔
1494
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
11,156,799✔
1495
      if (TSDB_CODE_SUCCESS != code) {
11,156,799✔
1496
        return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z);
21,585✔
1497
      }
1498
      val->i64 = iv;
11,135,214✔
1499
      break;
11,135,214✔
1500
    }
1501

1502
    case TSDB_DATA_TYPE_UBIGINT: {
947,605✔
1503
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
947,605✔
1504
      if (TSDB_CODE_SUCCESS != code) {
947,605✔
1505
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z);
5,694✔
1506
      }
1507
      *(uint64_t*)(&val->i64) = uv;
941,911✔
1508
      break;
941,911✔
1509
    }
1510

1511
    case TSDB_DATA_TYPE_FLOAT: {
3,404,524✔
1512
      double dv;
3,330,412✔
1513
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
3,404,524✔
1514
      if (TSDB_CODE_SUCCESS != code) {
3,404,487✔
1515
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
12,136✔
1516
      }
1517
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
3,392,351✔
1518
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
11,137✔
1519
      }
1520
      *(float*)(&val->i64) = dv;
3,381,214✔
1521
      break;
3,381,214✔
1522
    }
1523

1524
    case TSDB_DATA_TYPE_DOUBLE: {
13,330,410✔
1525
      double dv;
13,243,272✔
1526
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
13,330,410✔
1527
      if (TSDB_CODE_SUCCESS != code) {
13,330,410✔
1528
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
21,190✔
1529
      }
1530
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && ERRNO == ERANGE) || isinf(dv) || isnan(dv)) {
13,309,220✔
1531
        return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
×
1532
      }
1533

1534
      *(double*)(&val->i64) = dv;
13,309,220✔
1535
      break;
13,309,220✔
1536
    }
1537

1538
    case TSDB_DATA_TYPE_BINARY: {
61,416,292✔
1539
      // Too long values will raise the invalid sql error message
1540
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
61,416,292✔
1541
        return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
143,222✔
1542
      }
1543
      val->pData = taosStrdup(pToken->z);
61,263,401✔
1544
      if (!val->pData) {
61,277,953✔
1545
        return terrno;
×
1546
      }
1547
      val->nData = pToken->n;
61,260,748✔
1548
      break;
61,263,705✔
1549
    }
1550
    case TSDB_DATA_TYPE_VARBINARY: {
487,618✔
1551
      code = parseVarbinary(pToken, &val->pData, &val->nData, pSchema->bytes);
487,618✔
1552
      if (code != TSDB_CODE_SUCCESS) {
487,618✔
1553
        return generateSyntaxErrMsg(pMsgBuf, code, pSchema->name);
39,120✔
1554
      }
1555
      break;
448,498✔
1556
    }
1557
    case TSDB_DATA_TYPE_GEOMETRY: {
382,645✔
1558
      unsigned char* output = NULL;
382,645✔
1559
      size_t         size = 0;
382,645✔
1560

1561
      code = parseGeometry(pToken, &output, &size);
382,645✔
1562
      if (code != TSDB_CODE_SUCCESS) {
382,645✔
1563
        code = buildSyntaxErrMsg(pMsgBuf, getGeosErrMsg(code), pToken->z);
16,300✔
1564
      } else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
366,345✔
1565
        // Too long values will raise the invalid sql error message
1566
        code = generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1567
      } else {
1568
        val->pData = taosMemoryMalloc(size);
366,345✔
1569
        if (NULL == val->pData) {
366,345✔
1570
          code = terrno;
×
1571
        } else {
1572
          memcpy(val->pData, output, size);
366,345✔
1573
          val->nData = size;
366,345✔
1574
        }
1575
      }
1576

1577
      geosFreeBuffer(output);
382,645✔
1578
      break;
382,645✔
1579
    }
1580

1581
    case TSDB_DATA_TYPE_NCHAR: {
13,899,969✔
1582
      int32_t output = 0;
13,899,969✔
1583
      int64_t realLen = pToken->n << 2;
13,899,969✔
1584
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
13,899,969✔
1585
      void* p = taosMemoryMalloc(realLen);
13,899,969✔
1586
      if (p == NULL) {
13,899,969✔
1587
        return terrno;
196✔
1588
      }
1589
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)(p), realLen, &output, charsetCxt)) {
13,899,969✔
1590
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
136,408✔
1591
          taosMemoryFree(p);
136,173✔
1592
          return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
136,173✔
1593
        }
1594
        char buf[512] = {0};
196✔
1595
        snprintf(buf, tListLen(buf), " taosMbsToUcs4 error:%s %d %d", strerror(terrno), ERRNO, EILSEQ);
196✔
1596
        taosMemoryFree(p);
196✔
1597
        return buildSyntaxErrMsg(pMsgBuf, buf, pToken->z);
196✔
1598
      }
1599
      val->pData = p;
13,763,524✔
1600
      val->nData = output;
13,763,524✔
1601
      break;
13,763,561✔
1602
    }
1603
    case TSDB_DATA_TYPE_TIMESTAMP: {
2,357,729✔
1604
      if (parseTime(end, pToken, timePrec, &iv, pMsgBuf, tz) != TSDB_CODE_SUCCESS) {
2,357,729✔
1605
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z);
17,418✔
1606
      }
1607

1608
      val->i64 = iv;
2,340,311✔
1609
      break;
2,340,311✔
1610
    }
1611
    case TSDB_DATA_TYPE_MEDIUMBLOB:
×
1612
    case TSDB_DATA_TYPE_BLOB: {
1613
      code = generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_BLOB_NOT_SUPPORT_TAG, pSchema->name);
×
1614
      break;
×
1615
    }
1616
  }
1617

1618
  return code;
183,054,344✔
1619
}
1620

1621
// input pStmt->pSql:  [(tag1_name, ...)] TAGS (tag1_value, ...) ...
1622
// output pStmt->pSql: TAGS (tag1_value, ...) ...
1623
static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
21,275,185✔
1624
  int32_t code = insInitBoundColsInfo(getNumOfTags(pStmt->pTableMeta), &pCxt->tags);
21,275,185✔
1625
  if (TSDB_CODE_SUCCESS != code) {
21,278,049✔
1626
    return code;
×
1627
  }
1628

1629
  SToken  token;
1630
  int32_t index = 0;
21,278,049✔
1631
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
21,279,493✔
1632
  if (TK_NK_LP != token.type) {
21,274,806✔
1633
    return TSDB_CODE_SUCCESS;
21,014,570✔
1634
  }
1635

1636
  pStmt->pSql += index;
260,236✔
1637
  return parseBoundColumns(pCxt, pStmt, &pStmt->pSql, BOUND_TAGS, pStmt->pTableMeta, &pCxt->tags);
260,236✔
1638
}
1639

1640
int32_t parseTagValue(SMsgBuf* pMsgBuf, const char** pSql, uint8_t precision, SSchema* pTagSchema, SToken* pToken,
184,730,506✔
1641
                      SArray* pTagName, SArray* pTagVals, STag** pTag, timezone_t tz, void* charsetCxt) {
1642
  bool isNull = isNullValue(pTagSchema->type, pToken);
184,730,506✔
1643
  if (!isNull && pTagName) {
184,725,791✔
1644
    if (NULL == taosArrayPush(pTagName, pTagSchema->name)) {
349,564,758✔
1645
      return terrno;
×
1646
    }
1647
  }
1648

1649
  if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
184,712,209✔
1650
    if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
719,931✔
1651
      return buildSyntaxErrMsg(pMsgBuf, "json string too long than 4095", pToken->z);
507✔
1652
    }
1653

1654
    if (isNull) {
728,456✔
1655
      return tTagNew(pTagVals, 1, true, pTag);
30,992✔
1656
    } else {
1657
      return parseJsontoTagData(pToken->z, pTagVals, pTag, pMsgBuf, charsetCxt);
697,464✔
1658
    }
1659
  }
1660

1661
  if (isNull) return 0;
183,999,627✔
1662

1663
  STagVal val = {0};
183,601,656✔
1664
  int32_t code = parseTagToken(pSql, pToken, pTagSchema, precision, &val, pMsgBuf, tz, charsetCxt);
183,601,563✔
1665
  if (TSDB_CODE_SUCCESS == code) {
183,558,793✔
1666
    if (NULL == taosArrayPush(pTagVals, &val)) {
183,073,554✔
1667
      code = terrno;
×
1668
    }
1669
  }
1670

1671
  if (TSDB_CODE_SUCCESS != code && IS_VAR_DATA_TYPE(val.type)) {
183,602,235✔
1672
    taosMemoryFree(val.pData);
335,011✔
1673
  }
1674

1675
  return code;
183,591,856✔
1676
}
1677

1678
static int32_t buildCreateTbReq(SVnodeModifyOpStmt* pStmt, STag* pTag, SArray* pTagName) {
12,975,937✔
1679
  if (pStmt->pCreateTblReq) {
12,975,937✔
1680
    tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
×
1681
    taosMemoryFreeClear(pStmt->pCreateTblReq);
×
1682
  }
1683
  pStmt->pCreateTblReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
12,982,068✔
1684
  if (NULL == pStmt->pCreateTblReq) {
12,962,183✔
1685
    return terrno;
×
1686
  }
1687
  return insBuildCreateTbReq(pStmt->pCreateTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid,
12,974,848✔
1688
                             pStmt->usingTableName.tname, pTagName, pStmt->pTableMeta->tableInfo.numOfTags,
12,969,060✔
1689
                             TSDB_DEFAULT_TABLE_TTL);
1690
}
1691

1692
int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf, int8_t type) {
2,147,483,647✔
1693
  if (pToken->type == TK_NK_QUESTION) {
2,147,483,647✔
1694
    return buildInvalidOperationMsg(pMsgBuf, "insert into super table syntax is not supported for stmt");
×
1695
  }
1696
  if ((pToken->type != TK_NOW && pToken->type != TK_TODAY && pToken->type != TK_NK_INTEGER &&
2,147,483,647✔
1697
       pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL &&
2,147,483,647✔
1698
       pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && pToken->type != TK_NK_BIN &&
2,147,483,647✔
1699
       pToken->type != TK_NK_VARIABLE &&
688,644✔
1700
       pToken->type != TK_FROM_BASE64 && pToken->type != TK_TO_BASE64 &&
680,538✔
1701
       pToken->type != TK_MD5 && pToken->type != TK_SHA && pToken->type != TK_SHA1 && pToken->type != TK_SHA2 &&
676,194✔
1702
       pToken->type != TK_AES_ENCRYPT && pToken->type != TK_AES_DECRYPT &&
660,990✔
1703
       pToken->type != TK_SM4_ENCRYPT && pToken->type != TK_SM4_DECRYPT) ||
656,646✔
1704
      (pToken->n == 0) || (pToken->type == TK_NK_RP)) {
2,147,483,647✔
1705
    return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z);
1,333✔
1706
  }
1707

1708
  // Remove quotation marks
1709
  if (TK_NK_STRING == pToken->type && type != TSDB_DATA_TYPE_VARBINARY && !IS_STR_DATA_BLOB(type)) {
2,147,483,647✔
1710
    if (!IS_STR_DATA_BLOB(type)) {
2,147,483,647✔
1711
      if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) {
2,147,483,647✔
1712
        return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z);
×
1713
      }
1714

1715
      int32_t len = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
2,147,483,647✔
1716
      pToken->z = tmpTokenBuf;
2,147,483,647✔
1717
      pToken->n = len;
2,147,483,647✔
1718
    } else {
1719
      if (pToken->n >= TSDB_MAX_BLOB_LEN) {
91,332✔
1720
        return buildSyntaxErrMsg(pMsgBuf, "too long blob", pToken->z);
×
1721
      }
1722

1723
      int32_t len = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BLOB_LEN);
81,423✔
1724
      pToken->z = tmpTokenBuf;
×
1725
      pToken->n = len;
×
1726
    }
1727
  }
1728

1729
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
1730
}
1731

1732
typedef struct SRewriteTagCondCxt {
1733
  SArray* pTagVals;
1734
  SArray* pTagName;
1735
  int32_t code;
1736
} SRewriteTagCondCxt;
1737

1738
static int32_t rewriteTagCondColumnImpl(STagVal* pVal, SNode** pNode) {
5,679✔
1739
  SValueNode* pValue = NULL;
5,679✔
1740
  int32_t     code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pValue);
5,679✔
1741
  if (NULL == pValue) {
5,679✔
1742
    return code;
×
1743
  }
1744

1745
  pValue->node.resType = ((SColumnNode*)*pNode)->node.resType;
5,679✔
1746
  nodesDestroyNode(*pNode);
5,679✔
1747
  *pNode = (SNode*)pValue;
5,679✔
1748

1749
  switch (pVal->type) {
5,679✔
1750
    case TSDB_DATA_TYPE_BOOL:
×
1751
      pValue->datum.b = *(int8_t*)(&pVal->i64);
×
1752
      *(bool*)&pValue->typeData = pValue->datum.b;
×
1753
      break;
×
1754
    case TSDB_DATA_TYPE_TINYINT:
×
1755
      pValue->datum.i = *(int8_t*)(&pVal->i64);
×
1756
      *(int8_t*)&pValue->typeData = pValue->datum.i;
×
1757
      break;
×
1758
    case TSDB_DATA_TYPE_SMALLINT:
×
1759
      pValue->datum.i = *(int16_t*)(&pVal->i64);
×
1760
      *(int16_t*)&pValue->typeData = pValue->datum.i;
×
1761
      break;
×
1762
    case TSDB_DATA_TYPE_INT:
5,196✔
1763
      pValue->datum.i = *(int32_t*)(&pVal->i64);
5,196✔
1764
      *(int32_t*)&pValue->typeData = pValue->datum.i;
5,196✔
1765
      break;
5,196✔
1766
    case TSDB_DATA_TYPE_BIGINT:
×
1767
      pValue->datum.i = pVal->i64;
×
1768
      pValue->typeData = pValue->datum.i;
×
1769
      break;
×
1770
    case TSDB_DATA_TYPE_FLOAT:
×
1771
      pValue->datum.d = *(float*)(&pVal->i64);
×
1772
      *(float*)&pValue->typeData = pValue->datum.d;
×
1773
      break;
×
1774
    case TSDB_DATA_TYPE_DOUBLE:
×
1775
      pValue->datum.d = *(double*)(&pVal->i64);
×
1776
      *(double*)&pValue->typeData = pValue->datum.d;
×
1777
      break;
×
1778
    case TSDB_DATA_TYPE_VARCHAR:
483✔
1779
    case TSDB_DATA_TYPE_VARBINARY:
1780
    case TSDB_DATA_TYPE_NCHAR:
1781
      pValue->datum.p = taosMemoryCalloc(1, pVal->nData + VARSTR_HEADER_SIZE);
483✔
1782
      if (NULL == pValue->datum.p) {
483✔
1783
        return terrno;
×
1784
      }
1785
      varDataSetLen(pValue->datum.p, pVal->nData);
483✔
1786
      memcpy(varDataVal(pValue->datum.p), pVal->pData, pVal->nData);
483✔
1787
      break;
483✔
1788
    case TSDB_DATA_TYPE_TIMESTAMP:
×
1789
      pValue->datum.i = pVal->i64;
×
1790
      pValue->typeData = pValue->datum.i;
×
1791
      break;
×
1792
    case TSDB_DATA_TYPE_UTINYINT:
×
1793
      pValue->datum.i = *(uint8_t*)(&pVal->i64);
×
1794
      *(uint8_t*)&pValue->typeData = pValue->datum.i;
×
1795
      break;
×
1796
    case TSDB_DATA_TYPE_USMALLINT:
×
1797
      pValue->datum.i = *(uint16_t*)(&pVal->i64);
×
1798
      *(uint16_t*)&pValue->typeData = pValue->datum.i;
×
1799
      break;
×
1800
    case TSDB_DATA_TYPE_UINT:
×
1801
      pValue->datum.i = *(uint32_t*)(&pVal->i64);
×
1802
      *(uint32_t*)&pValue->typeData = pValue->datum.i;
×
1803
      break;
×
1804
    case TSDB_DATA_TYPE_UBIGINT:
×
1805
      pValue->datum.i = *(uint64_t*)(&pVal->i64);
×
1806
      *(uint64_t*)&pValue->typeData = pValue->datum.i;
×
1807
      break;
×
1808
    case TSDB_DATA_TYPE_JSON:
×
1809
    case TSDB_DATA_TYPE_DECIMAL:
1810
    case TSDB_DATA_TYPE_BLOB:
1811
    case TSDB_DATA_TYPE_MEDIUMBLOB:
1812
    default:
1813
      return TSDB_CODE_FAILED;
×
1814
  }
1815
  return TSDB_CODE_SUCCESS;
5,679✔
1816
}
1817

1818
static int32_t rewriteTagCondColumn(SArray* pTagVals, SArray* pTagName, SNode** pNode) {
5,679✔
1819
  SColumnNode* pCol = (SColumnNode*)*pNode;
5,679✔
1820
  int32_t      ntags = taosArrayGetSize(pTagName);
5,679✔
1821
  for (int32_t i = 0; i < ntags; ++i) {
5,679✔
1822
    char* pTagColName = taosArrayGet(pTagName, i);
5,679✔
1823
    if (0 == strcmp(pTagColName, pCol->colName)) {
5,679✔
1824
      return rewriteTagCondColumnImpl(taosArrayGet(pTagVals, i), pNode);
5,679✔
1825
    }
1826
  }
1827
  return TSDB_CODE_PAR_PERMISSION_DENIED;
×
1828
}
1829

1830
static EDealRes rewriteTagCond(SNode** pNode, void* pContext) {
17,037✔
1831
  if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
17,037✔
1832
    SRewriteTagCondCxt* pCxt = pContext;
5,679✔
1833
    pCxt->code = rewriteTagCondColumn(pCxt->pTagVals, pCxt->pTagName, pNode);
5,679✔
1834
    return (TSDB_CODE_SUCCESS == pCxt->code ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
5,679✔
1835
  }
1836
  return DEAL_RES_CONTINUE;
11,358✔
1837
}
1838

1839
static int32_t setTagVal(SArray* pTagVals, SArray* pTagName, SNode* pCond) {
5,679✔
1840
  SRewriteTagCondCxt cxt = {.code = TSDB_CODE_SUCCESS, .pTagVals = pTagVals, .pTagName = pTagName};
5,679✔
1841
  nodesRewriteExpr(&pCond, rewriteTagCond, &cxt);
5,679✔
1842
  return cxt.code;
5,679✔
1843
}
1844

1845
static int32_t checkTagCondResult(SNode* pResult) {
5,679✔
1846
  return (QUERY_NODE_VALUE == nodeType(pResult) && ((SValueNode*)pResult)->datum.b) ? TSDB_CODE_SUCCESS
11,358✔
1847
                                                                                    : TSDB_CODE_PAR_PERMISSION_DENIED;
11,358✔
1848
}
1849

1850
static int32_t checkSubtablePrivilege(SArray* pTagVals, SArray* pTagName, SNode** pCond) {
5,679✔
1851
  int32_t code = setTagVal(pTagVals, pTagName, *pCond);
5,679✔
1852
  if (TSDB_CODE_SUCCESS == code) {
5,679✔
1853
    code = scalarCalculateConstants(*pCond, pCond);
5,679✔
1854
  }
1855
  if (TSDB_CODE_SUCCESS == code) {
5,679✔
1856
    code = checkTagCondResult(*pCond);
5,679✔
1857
  }
1858
  NODES_DESTORY_NODE(*pCond);
5,679✔
1859
  return code;
5,679✔
1860
}
1861

1862
// pSql -> tag1_value, ...)
1863
static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool autoCreate) {
21,271,718✔
1864
  int32_t  code = TSDB_CODE_SUCCESS;
21,271,718✔
1865
  SSchema* pSchema = getTableTagSchema(pStmt->pTableMeta);
21,271,718✔
1866
  SArray*  pTagVals = NULL;
21,269,823✔
1867
  SArray*  pTagName = NULL;
21,269,823✔
1868
  uint8_t  precision = pStmt->pTableMeta->tableInfo.precision;
21,269,823✔
1869
  SToken   token;
21,058,272✔
1870
  bool     isJson = false;
21,268,451✔
1871
  STag*    pTag = NULL;
21,268,451✔
1872
  uint8_t* pTagsIndex;
1873
  int32_t  numOfTags = 0;
21,270,948✔
1874

1875
  if (pCxt->pComCxt->stmtBindVersion == 2) {  // only support stmt2
21,270,948✔
1876
    pTagsIndex = taosMemoryCalloc(pCxt->tags.numOfBound, sizeof(uint8_t));
14,571✔
1877
  }
1878

1879
  if (!(pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal))) ||
42,528,972✔
1880
      !(pTagName = taosArrayInit(pCxt->tags.numOfBound, TSDB_COL_NAME_LEN))) {
21,272,037✔
1881
    code = terrno;
×
1882
    goto _exit;
×
1883
  }
1884

1885
  for (int i = 0; TSDB_CODE_SUCCESS == code && i < pCxt->tags.numOfBound; ++i) {
52,423,385✔
1886
    NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
31,169,801✔
1887

1888
    if (token.type == TK_NK_QUESTION) {
31,160,283✔
1889
      if (pCxt->pComCxt->stmtBindVersion == 0) {
44,200✔
1890
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", token.z);
×
1891
        break;
×
1892
      }
1893

1894
      continue;
44,200✔
1895
    }
1896

1897
    SSchema* pTagSchema = &pSchema[pCxt->tags.pColIndex[i]];
31,116,083✔
1898
    isJson = pTagSchema->type == TSDB_DATA_TYPE_JSON;
31,125,126✔
1899
    code = checkAndTrimValue(&token, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
31,128,429✔
1900
    if (TSDB_CODE_SUCCESS == code && TK_NK_VARIABLE == token.type) {
31,129,223✔
1901
      code = buildSyntaxErrMsg(&pCxt->msg, "not expected tags values ", token.z);
×
1902
    }
1903
    if (TSDB_CODE_SUCCESS == code) {
31,129,885✔
1904
      code = parseTagValue(&pCxt->msg, &pStmt->pSql, precision, pTagSchema, &token, pTagName, pTagVals, &pTag,
61,831,470✔
1905
                           pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
61,832,902✔
1906
    }
1907
    if (pCxt->pComCxt->stmtBindVersion == 2) {
31,126,311✔
1908
      pTagsIndex[numOfTags++] = pCxt->tags.pColIndex[i];
11,732✔
1909
    }
1910
  }
1911

1912
  if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pTagCond) {
21,257,964✔
1913
    code = checkSubtablePrivilege(pTagVals, pTagName, &pStmt->pTagCond);
370✔
1914
  }
1915

1916
  if (TSDB_CODE_SUCCESS == code && pCxt->pComCxt->stmtBindVersion == 2) {
21,269,185✔
1917
    if (numOfTags > 0) {
14,375✔
1918
      if (pTagVals->size == pCxt->tags.numOfBound) {
6,454✔
1919
        pCxt->stmtTbNameFlag |= IS_FIXED_TAG;
5,866✔
1920
      } else {
1921
        pCxt->stmtTbNameFlag &= ~IS_FIXED_TAG;
588✔
1922
        pCxt->tags.parseredTags = taosMemoryMalloc(sizeof(STagsInfo));
588✔
1923
        if (pCxt->tags.parseredTags == NULL) {
588✔
1924
          code = terrno;
×
1925
          goto _exit;
×
1926
        }
1927
        pCxt->tags.parseredTags->numOfTags = numOfTags;
588✔
1928
        pCxt->tags.parseredTags->pTagIndex = pTagsIndex;
588✔
1929
        pCxt->tags.parseredTags->pTagVals = pTagVals;
588✔
1930
        pCxt->tags.parseredTags->STagNames = pTagName;
588✔
1931
      }
1932
    } else {
1933
      goto _exit;
7,921✔
1934
    }
1935
  }
1936

1937
  if (TSDB_CODE_SUCCESS == code && !isJson) {
21,266,318✔
1938
    code = tTagNew(pTagVals, 1, false, &pTag);
20,764,929✔
1939
  }
1940

1941
  if (TSDB_CODE_SUCCESS == code && !autoCreate) {
21,261,228✔
1942
    code = buildCreateTbReq(pStmt, pTag, pTagName);
12,978,458✔
1943
    pTag = NULL;
12,979,216✔
1944
  }
1945

1946
_exit:
21,246,549✔
1947
  if (pCxt->tags.parseredTags == NULL) {
21,272,440✔
1948
    for (int32_t i = 0; i < taosArrayGetSize(pTagVals); ++i) {
52,142,606✔
1949
      STagVal* p = (STagVal*)TARRAY_GET_ELEM(pTagVals, i);
30,881,313✔
1950
      if (IS_VAR_DATA_TYPE(p->type)) {
30,876,945✔
1951
        taosMemoryFreeClear(p->pData);
11,621,966✔
1952
      }
1953
    }
1954
    taosArrayDestroy(pTagVals);
21,260,547✔
1955
    taosArrayDestroy(pTagName);
21,271,816✔
1956
    if (pCxt->pComCxt->stmtBindVersion == 2) {
21,266,407✔
1957
      taosMemoryFreeClear(pTagsIndex);
13,983✔
1958
    }
1959
  }
1960

1961
  tTagFree(pTag);
21,271,658✔
1962
  return code;
21,270,617✔
1963
}
1964

1965
// input pStmt->pSql:  TAGS (tag1_value, ...) [table_options] ...
1966
// output pStmt->pSql: [table_options] ...
1967
static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool autoCreate) {
21,274,830✔
1968
  SToken token;
21,068,823✔
1969
  NEXT_TOKEN(pStmt->pSql, token);
21,279,162✔
1970
  if (TK_TAGS != token.type) {
21,278,049✔
1971
    return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
3,100✔
1972
  }
1973

1974
  NEXT_TOKEN(pStmt->pSql, token);
21,274,949✔
1975
  if (TK_NK_LP != token.type) {
21,261,857✔
1976
    return buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
×
1977
  }
1978

1979
  int32_t code = parseTagsClauseImpl(pCxt, pStmt, autoCreate);
21,261,857✔
1980
  if (TSDB_CODE_SUCCESS == code) {
21,271,718✔
1981
    NEXT_VALID_TOKEN(pStmt->pSql, token);
30,698,188✔
1982
    if (TK_NK_COMMA == token.type) {
20,982,358✔
1983
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
726✔
1984
    } else if (TK_NK_RP != token.type) {
20,981,632✔
1985
      code = buildSyntaxErrMsg(&pCxt->msg, ") is expected", token.z);
18,238✔
1986
    }
1987
  }
1988
  return code;
21,267,753✔
1989
}
1990

1991
static int32_t storeChildTableMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
13,260,565✔
1992
  pStmt->pTableMeta->suid = pStmt->pTableMeta->uid;
13,260,565✔
1993
  pStmt->pTableMeta->uid = pStmt->totalTbNum;
13,257,190✔
1994
  pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;
13,260,186✔
1995

1996
  STableMeta* pBackup = NULL;
13,261,558✔
1997
  if (TSDB_CODE_SUCCESS != cloneTableMeta(pStmt->pTableMeta, &pBackup)) {
13,261,215✔
1998
    return TSDB_CODE_OUT_OF_MEMORY;
×
1999
  }
2000

2001
  char    tbFName[TSDB_TABLE_FNAME_LEN];
13,239,324✔
2002
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
13,264,530✔
2003
  if (TSDB_CODE_SUCCESS != code) {
13,261,251✔
2004
    taosMemoryFree(pBackup);
×
2005
    return code;
×
2006
  }
2007
  code = taosHashPut(pStmt->pSubTableHashObj, tbFName, strlen(tbFName), &pBackup, POINTER_BYTES);
13,261,251✔
2008
  if (TSDB_CODE_SUCCESS != code) {
13,267,027✔
2009
    taosMemoryFree(pBackup);
×
2010
  }
2011
  return code;
13,263,796✔
2012
}
2013

2014
static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
12,973,340✔
2015
  do {
9,132✔
2016
    int32_t index = 0;
12,973,340✔
2017
    SToken  token;
2018
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
12,976,607✔
2019
    if (TK_TTL == token.type) {
12,975,837✔
2020
      pStmt->pSql += index;
9,132✔
2021
      NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
9,132✔
2022
      if (TK_NK_INTEGER != token.type) {
9,132✔
2023
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
×
2024
      }
2025
      pStmt->pCreateTblReq->ttl = taosStr2Int32(token.z, NULL, 10);
9,132✔
2026
      if (pStmt->pCreateTblReq->ttl < 0) {
9,132✔
2027
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
722✔
2028
      }
2029
    } else if (TK_COMMENT == token.type) {
12,966,705✔
2030
      pStmt->pSql += index;
722✔
2031
      NEXT_TOKEN(pStmt->pSql, token);
722✔
2032
      if (TK_NK_STRING != token.type) {
722✔
2033
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option comment", token.z);
×
2034
      }
2035
      if (token.n >= TSDB_TB_COMMENT_LEN) {
722✔
2036
        return buildSyntaxErrMsg(&pCxt->msg, "comment too long", token.z);
×
2037
      }
2038
      int32_t len = trimString(token.z, token.n, pCxt->tmpTokenBuf, TSDB_TB_COMMENT_LEN);
722✔
2039
      pStmt->pCreateTblReq->comment = taosStrndup(pCxt->tmpTokenBuf, len);
722✔
2040
      if (NULL == pStmt->pCreateTblReq->comment) {
722✔
2041
        return terrno;
×
2042
      }
2043
      pStmt->pCreateTblReq->commentLen = len;
722✔
2044
    } else {
2045
      break;
12,965,983✔
2046
    }
2047
  } while (1);
2048
  return TSDB_CODE_SUCCESS;
12,966,019✔
2049
}
2050

2051
// input pStmt->pSql:
2052
//   1. [(tag1_name, ...)] ...
2053
//   2. VALUES ... | FILE ...
2054
// output pStmt->pSql:
2055
//   1. [(field1_name, ...)]
2056
//   2. VALUES ... | FILE ...
2057
static int32_t parseUsingClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
731,846,438✔
2058
  if (!pStmt->usingTableProcessing || pCxt->usingDuplicateTable) {
731,846,438✔
2059
    return TSDB_CODE_SUCCESS;
718,593,669✔
2060
  }
2061

2062
  int32_t code = parseBoundTagsClause(pCxt, pStmt);
13,296,483✔
2063
  if (TSDB_CODE_SUCCESS == code) {
13,258,008✔
2064
    code = parseTagsClause(pCxt, pStmt, false);
13,258,742✔
2065
  }
2066
  if (TSDB_CODE_SUCCESS == code) {
13,250,764✔
2067
    code = parseTableOptions(pCxt, pStmt);
12,961,663✔
2068
  }
2069

2070
  return code;
13,258,327✔
2071
}
2072

2073
static void setUserAuthInfo(SParseContext* pCxt, SName* pTbName, SUserAuthInfo* pInfo) {
710,903,101✔
2074
  snprintf(pInfo->user, sizeof(pInfo->user), "%s", pCxt->pUser);
710,903,101✔
2075
  memcpy(&pInfo->tbName, pTbName, sizeof(SName));
710,939,154✔
2076
  pInfo->userId = pCxt->userId;
710,960,441✔
2077
  pInfo->privType = PRIV_TBL_INSERT;
710,900,962✔
2078
  pInfo->objType = PRIV_OBJ_TBL;
710,976,170✔
2079
}
710,982,795✔
2080

2081
static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool isAudit, bool* pMissCache, bool* pWithInsertCond, SNode** pTagCond,
710,875,516✔
2082
                         SArray** pPrivCols) {
2083
  int32_t       code = TSDB_CODE_SUCCESS;
710,875,516✔
2084
  SUserAuthInfo authInfo = {0};
710,875,516✔
2085
  setUserAuthInfo(pCxt, pTbName, &authInfo);
710,890,598✔
2086
  if (isAudit) {
710,951,070✔
2087
    authInfo.privType = PRIV_AUDIT_TBL_INSERT;
×
2088
    authInfo.objType = PRIV_OBJ_CLUSTER;
×
2089
  }
2090
  SUserAuthRes authRes = {0};
710,951,070✔
2091
  SUserAuthRsp authRsp = {.exists = 1};
710,897,895✔
2092
  if (pCxt->async) {
710,930,139✔
2093
    code = catalogChkAuthFromCache(pCxt->pCatalog, &authInfo, &authRes, &authRsp);
710,777,503✔
2094
  } else {
2095
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
289,735✔
2096
                             .requestId = pCxt->requestId,
161,481✔
2097
                             .requestObjRefId = pCxt->requestRid,
161,444✔
2098
                             .mgmtEps = pCxt->mgmtEpSet};
2099
    code = catalogChkAuth(pCxt->pCatalog, &conn, &authInfo, &authRes);
161,483✔
2100
  }
2101
  if (TSDB_CODE_SUCCESS == code) {
710,880,648✔
2102
    if (0 == authRsp.exists) {
710,880,652✔
2103
      *pMissCache = true;
33,071✔
2104
    } else if (!authRes.pass[AUTH_RES_BASIC]) {
710,847,581✔
2105
      code = TSDB_CODE_PAR_PERMISSION_DENIED;
4,484✔
2106
    } else {
2107
      if (pTagCond && authRes.pCond[AUTH_RES_BASIC]) {
710,843,097✔
2108
        *pTagCond = authRes.pCond[AUTH_RES_BASIC];
4,199✔
2109
      }
2110
      if (pPrivCols && authRes.pCols) {
710,843,097✔
2111
        *pPrivCols = authRes.pCols;
4,506✔
2112
      }
2113
      *pMissCache = false;
710,843,097✔
2114
    }
2115
    if (pWithInsertCond) {
710,915,076✔
2116
      *pWithInsertCond = (authRsp.withInsertCond == 1);
710,881,625✔
2117
    }
2118
  }
2119
  return code;
710,961,182✔
2120
}
2121

2122
static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, STableMeta** pTableMeta, bool* pMissCache,
35,405,904✔
2123
                            bool bUsingTable) {
2124
  SParseContext* pComCxt = pCxt->pComCxt;
35,405,904✔
2125
  int32_t        code = TSDB_CODE_SUCCESS;
35,406,963✔
2126
  if (pComCxt->async) {
35,406,963✔
2127
    if (bUsingTable) {
28,002,926✔
2128
      code = catalogGetCachedSTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
14,007,312✔
2129
    } else {
2130
      code = catalogGetCachedTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
13,995,614✔
2131
    }
2132
  } else {
2133
    SRequestConnInfo conn = {.pTrans = pComCxt->pTransporter,
14,751,755✔
2134
                             .requestId = pComCxt->requestId,
7,406,153✔
2135
                             .requestObjRefId = pComCxt->requestRid,
7,403,979✔
2136
                             .mgmtEps = pComCxt->mgmtEpSet};
2137
    if (bUsingTable) {
7,399,688✔
2138
      code = catalogGetSTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
7,235,296✔
2139
    } else {
2140
      code = catalogGetTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
164,392✔
2141
    }
2142
  }
2143
  if (TSDB_CODE_SUCCESS == code) {
35,406,129✔
2144
    if (NULL == *pTableMeta) {
35,405,110✔
2145
      *pMissCache = true;
6,056,626✔
2146
    } else if (bUsingTable && TSDB_SUPER_TABLE != (*pTableMeta)->tableType) {
29,348,201✔
2147
      code = buildInvalidOperationMsg(&pCxt->msg, "create table only from super table is allowed");
×
2148
    } else if (((*pTableMeta)->virtualStb) || TSDB_VIRTUAL_CHILD_TABLE == (*pTableMeta)->tableType ||
29,347,064✔
2149
               TSDB_VIRTUAL_NORMAL_TABLE == (*pTableMeta)->tableType) {
29,346,853✔
2150
      code = TSDB_CODE_VTABLE_NOT_SUPPORT_STMT;
1,959✔
2151
    }
2152
  }
2153
  return code;
35,407,577✔
2154
}
2155

2156
static int32_t getTargetTableVgroup(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool isStb, bool* pMissCache) {
15,400,563✔
2157
  int32_t     code = TSDB_CODE_SUCCESS;
15,400,563✔
2158
  SVgroupInfo vg;
15,181,844✔
2159
  bool        exists = true;
15,401,995✔
2160
  if (pCxt->async) {
15,402,744✔
2161
    code = catalogGetCachedTableHashVgroup(pCxt->pCatalog, &pStmt->targetTableName, &vg, &exists);
8,012,766✔
2162
  } else {
2163
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
14,732,251✔
2164
                             .requestId = pCxt->requestId,
7,388,110✔
2165
                             .requestObjRefId = pCxt->requestRid,
7,386,787✔
2166
                             .mgmtEps = pCxt->mgmtEpSet};
2167
    code = catalogGetTableHashVgroup(pCxt->pCatalog, &conn, &pStmt->targetTableName, &vg);
7,388,717✔
2168
  }
2169
  if (TSDB_CODE_SUCCESS == code) {
15,399,278✔
2170
    if (exists) {
15,399,278✔
2171
      if (isStb) {
15,403,231✔
2172
        pStmt->pTableMeta->vgId = vg.vgId;
15,255,789✔
2173
      }
2174
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
15,398,923✔
2175
    }
2176
    *pMissCache = !exists;
15,403,348✔
2177
  }
2178
  return code;
15,399,738✔
2179
}
2180

2181
static int32_t getTargetTableMetaAndVgroup(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) {
710,841,643✔
2182
  SParseContext* pComCxt = pCxt->pComCxt;
710,841,643✔
2183
  int32_t        code = TSDB_CODE_SUCCESS;
710,877,045✔
2184
  if (pComCxt->async) {
710,877,045✔
2185
    {
2186
      SVgroupInfo vg;
706,898,186✔
2187
      code = catalogGetCachedTableVgMeta(pComCxt->pCatalog, &pStmt->targetTableName, &vg, &pStmt->pTableMeta);
710,688,283✔
2188
      if (TSDB_CODE_SUCCESS == code) {
710,705,489✔
2189
        if (NULL != pStmt->pTableMeta) {
710,751,286✔
2190
          if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE) {
709,181,270✔
2191
            pStmt->stbSyntax = true;
260,065✔
2192
          } else {
2193
            code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
708,872,368✔
2194
          }
2195
        }
2196
        *pMissCache = (NULL == pStmt->pTableMeta);
710,806,743✔
2197
      }
2198
    }
2199
  } else {
2200
    bool bUsingTable = false;
161,321✔
2201
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pStmt->pTableMeta, pMissCache, bUsingTable);
161,321✔
2202
    if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
161,274✔
2203
      if (TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
160,061✔
2204
        pStmt->stbSyntax = true;
12,616✔
2205
      }
2206
      if (!pStmt->stbSyntax) {
159,861✔
2207
        code = getTargetTableVgroup(pCxt->pComCxt, pStmt, false, &pCxt->missCache);
147,314✔
2208
      }
2209
    }
2210
  }
2211
  return code;
710,895,177✔
2212
}
2213

2214
static int32_t collectUseTable(const SName* pName, SHashObj* pTable) {
10,640,215✔
2215
  char    fullName[TSDB_TABLE_FNAME_LEN];
10,567,624✔
2216
  int32_t code = tNameExtractFullName(pName, fullName);
10,642,014✔
2217
  if (TSDB_CODE_SUCCESS != code) {
10,643,446✔
2218
    return code;
×
2219
  }
2220
  return taosHashPut(pTable, fullName, strlen(fullName), pName, sizeof(SName));
10,643,446✔
2221
}
2222

2223
static int32_t collectUseDatabase(const SName* pName, SHashObj* pDbs) {
7,632,735✔
2224
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
7,632,735✔
2225
  (void)tNameGetFullDbName(pName, dbFName);
7,634,901✔
2226
  return taosHashPut(pDbs, dbFName, strlen(dbFName), dbFName, sizeof(dbFName));
7,637,504✔
2227
}
2228

2229
static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
711,008,101✔
2230
  if (pCxt->forceUpdate) {
711,008,101✔
2231
    pCxt->missCache = true;
78,990✔
2232
    return TSDB_CODE_SUCCESS;
78,990✔
2233
  }
2234
  SNode*  pTagCond = NULL;
710,952,688✔
2235
  SArray* pPrivCols = NULL;
710,917,702✔
2236
  bool    withInsertCond = false;
710,939,684✔
2237
  int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, false, &pCxt->missCache, &withInsertCond, &pTagCond,
710,920,149✔
2238
                           &pPrivCols);
2239
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
710,944,417✔
2240
    code = getTargetTableMetaAndVgroup(pCxt, pStmt, &pCxt->missCache);
710,930,823✔
2241
  }
2242
#ifdef TD_ENTERPRISE
2243
  // MAC NWD+NRU: for INSERT, user.minSecLevel <= table.secLvl <= user.maxSecLevel
2244
  // Only enforced when MAC is explicitly activated cluster-wide.
2245
  // Logic mirrors macCheckBySecLvl() in parAuthenticator.c (inline here because SInsertParseContext
2246
  // does not carry an SAuthCxt).
2247
  if (pCxt->pComCxt->macMode && TSDB_CODE_SUCCESS == code && !pCxt->missCache && pStmt->pTableMeta != NULL) {
710,844,594✔
2248
    int8_t secLvl = pStmt->pTableMeta->secLvl;
3,500✔
2249
    if (secLvl >= 0) {
3,500✔
2250
      if (pCxt->pComCxt->minSecLevel > secLvl) {
3,500✔
2251
        code = TSDB_CODE_MAC_NO_WRITE_DOWN;  // NWD violation
350✔
2252
      } else if (pCxt->pComCxt->maxSecLevel < secLvl) {
3,150✔
2253
        code = TSDB_CODE_MAC_INSUFFICIENT_LEVEL;  // NRU violation
1,050✔
2254
      }
2255
    }
2256
  }
2257
#endif
2258

2259
  if (TSDB_CODE_SUCCESS == code) {
710,915,995✔
2260
    if (pPrivCols) pStmt->pPrivCols = pPrivCols;
710,907,565✔
2261
#ifdef TD_ENTERPRISE
2262
#if 0
2263
    if (pStmt->pTableMeta && pStmt->pTableMeta->isAudit) {
2264
      // recheck for audit table
2265
      code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, true, &pCxt->missCache, NULL, NULL, NULL);
2266
      if (TSDB_CODE_SUCCESS != code) {
2267
        nodesDestroyNode(pTagCond);
2268
        return code;
2269
      }
2270
    }
2271
#endif
2272
    if (!pCxt->missCache) {
710,907,565✔
2273
      if (TSDB_SUPER_TABLE != pStmt->pTableMeta->tableType) {
709,305,183✔
2274
        pCxt->needTableTagVal = (NULL != pTagCond);
708,994,150✔
2275
        pCxt->missCache = (NULL != pTagCond);
709,068,177✔
2276
      } else {
2277
        pStmt->pTagCond = pTagCond;
272,668✔
2278
        pTagCond = NULL;
272,668✔
2279
      }
2280
    } else if (withInsertCond && !pCxt->pComCxt->isSuperUser) {
1,600,636✔
2281
      // If miss cache, always request tag value and reserved for permission check later if pTagCond exists. This may
2282
      // lead to redundant request but ensure correctness, and this only happens when cache is invalid or first time
2283
      // insert.
2284
      pCxt->needTableTagVal = true;
1,850✔
2285
    }
2286
#else
2287
    pStmt->pTagCond = NULL;
2288
#endif
2289
  }
2290
  if (pTagCond) nodesDestroyNode(pTagCond);
710,926,874✔
2291

2292
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
710,926,874✔
2293
    code = collectUseDatabase(&pStmt->targetTableName, pStmt->pDbFNameHashObj);
159,549✔
2294
    if (TSDB_CODE_SUCCESS == code) {
159,789✔
2295
      code = collectUseTable(&pStmt->targetTableName, pStmt->pTableNameHashObj);
159,789✔
2296
    }
2297
  }
2298
  return code;
710,893,162✔
2299
}
2300

2301
static int32_t preParseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
21,317,269✔
2302
  return insCreateSName(&pStmt->usingTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
21,317,269✔
2303
}
2304

2305
static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* ctbCacheHit) {
21,316,354✔
2306
  int32_t     code = TSDB_CODE_SUCCESS;
21,316,354✔
2307
  STableMeta* pStableMeta = NULL;
21,316,354✔
2308
  STableMeta* pCtableMeta = NULL;
21,317,419✔
2309
  if (pCxt->forceUpdate) {
21,318,496✔
2310
    pCxt->missCache = true;
2,701✔
2311
    return TSDB_CODE_SUCCESS;
2,701✔
2312
  }
2313
  char stableFName[TSDB_TABLE_FNAME_LEN];
21,108,160✔
2314
  code = tNameExtractFullName(&pStmt->usingTableName, stableFName);
21,314,718✔
2315
  if (TSDB_CODE_SUCCESS != code) {
21,316,505✔
UNCOV
2316
    return code;
×
2317
  }
2318

2319
  char ctableFName[TSDB_TABLE_FNAME_LEN];
21,110,302✔
2320
  code = tNameExtractFullName(&pStmt->targetTableName, ctableFName);
21,315,428✔
2321
  if (TSDB_CODE_SUCCESS != code) {
21,316,848✔
UNCOV
2322
    return code;
×
2323
  }
2324

2325
  if (strcmp(stableFName, ctableFName) == 0) {
21,316,848✔
2326
    return TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
726✔
2327
  }
2328
  if (!pCxt->missCache) {
21,316,122✔
2329
    char tbFName[TSDB_TABLE_FNAME_LEN];
21,107,067✔
2330
    code = tNameExtractFullName(&pStmt->usingTableName, tbFName);
21,313,980✔
2331
    if (TSDB_CODE_SUCCESS != code) {
21,316,477✔
2332
      return code;
×
2333
    }
2334
    STableMeta** ppStableMeta = taosHashGet(pStmt->pSuperTableHashObj, tbFName, strlen(tbFName));
21,316,477✔
2335
    if (NULL != ppStableMeta) {
21,311,790✔
2336
      pStableMeta = *ppStableMeta;
65,565✔
2337
    }
2338
    if (NULL == pStableMeta) {
21,311,790✔
2339
      bool bUsingTable = true;
21,246,976✔
2340
      code = getTableMeta(pCxt, &pStmt->usingTableName, &pStableMeta, &pCxt->missCache, bUsingTable);
21,246,976✔
2341
      if (TSDB_CODE_SUCCESS == code) {
21,244,786✔
2342
        code = taosHashPut(pStmt->pSuperTableHashObj, tbFName, strlen(tbFName), &pStableMeta, POINTER_BYTES);
21,243,277✔
2343
      } else {
2344
        taosMemoryFreeClear(pStableMeta);
1,509✔
2345
      }
2346
    }
2347
  }
2348
  if (pCxt->pComCxt->stmtBindVersion > 0) {
21,317,482✔
2349
    goto _no_ctb_cache;
7,238,756✔
2350
  }
2351

2352
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
14,074,490✔
2353
    bool bUsingTable = false;
13,998,569✔
2354
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pCtableMeta, &pCxt->missCache, bUsingTable);
13,998,569✔
2355
  }
2356

2357
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
14,074,490✔
2358
    code = (pStableMeta->suid == pCtableMeta->suid) ? TSDB_CODE_SUCCESS : TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
8,017,173✔
2359
    *ctbCacheHit = true;
8,017,173✔
2360
  }
2361
_no_ctb_cache:
21,114,720✔
2362
  if (TSDB_CODE_SUCCESS == code) {
21,311,447✔
2363
    if (*ctbCacheHit) {
21,310,273✔
2364
      code = cloneTableMeta(pCtableMeta, &pStmt->pTableMeta);
8,015,721✔
2365
    } else {
2366
      code = cloneTableMeta(pStableMeta, &pStmt->pTableMeta);
13,295,996✔
2367
    }
2368
  }
2369
  taosMemoryFree(pCtableMeta);
21,316,844✔
2370
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
21,315,045✔
2371
    code = getTargetTableVgroup(pCxt->pComCxt, pStmt, true, &pCxt->missCache);
15,256,180✔
2372
  }
2373
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
21,313,613✔
2374
    code = collectUseDatabase(&pStmt->usingTableName, pStmt->pDbFNameHashObj);
7,241,579✔
2375
    if (TSDB_CODE_SUCCESS == code) {
7,241,236✔
2376
      code = collectUseTable(&pStmt->usingTableName, pStmt->pTableNameHashObj);
7,241,236✔
2377
    }
2378
  }
2379
  return code;
21,316,477✔
2380
}
2381

2382
static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
21,316,559✔
2383
  SToken token;
21,110,368✔
2384
  NEXT_TOKEN(pStmt->pSql, token);
21,317,991✔
2385
  bool    ctbCacheHit = false;
21,318,713✔
2386
  int32_t code = preParseUsingTableName(pCxt, pStmt, &token);
21,318,713✔
2387
  if (TSDB_CODE_SUCCESS == code) {
21,319,056✔
2388
    code = getUsingTableSchema(pCxt, pStmt, &ctbCacheHit);
21,319,549✔
2389
    if (TSDB_CODE_SUCCESS == code && ctbCacheHit && !pCxt->missCache) {
21,317,016✔
2390
      pStmt->usingTableProcessing = false;
8,015,721✔
2391
      return ignoreUsingClauseAndCheckTagValues(pCxt, pStmt);
8,015,721✔
2392
    }
2393
  }
2394
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
13,300,802✔
2395
    code = storeChildTableMeta(pCxt, pStmt);
7,238,257✔
2396
  }
2397
  return code;
13,301,867✔
2398
}
2399

2400
// input pStmt->pSql:
2401
//   1(care). [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
2402
//   2. VALUES ... | FILE ...
2403
// output pStmt->pSql:
2404
//   1. [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
2405
//   2. VALUES ... | FILE ...
2406
static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
732,398,252✔
2407
  SToken  token;
2408
  int32_t index = 0;
732,398,252✔
2409
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
732,430,962✔
2410
  if (TK_USING != token.type) {
732,480,262✔
2411
    return getTargetTableSchema(pCxt, pStmt);
711,085,883✔
2412
  }
2413
  pStmt->usingTableProcessing = true;
21,394,379✔
2414
  pCxt->stmtTbNameFlag |= USING_CLAUSE;
21,393,314✔
2415
  // pStmt->pSql -> stb_name [(tag1_name, ...)
2416
  pStmt->pSql += index;
21,393,326✔
2417
  int32_t code = parseDuplicateUsingClause(pCxt, pStmt, &pCxt->usingDuplicateTable);
21,394,391✔
2418
  if (TSDB_CODE_SUCCESS == code && !pCxt->usingDuplicateTable) {
21,390,462✔
2419
    return parseUsingTableNameImpl(pCxt, pStmt);
21,316,938✔
2420
  }
2421
  return code;
74,258✔
2422
}
2423

2424
static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
732,431,201✔
2425
  int32_t code = insCreateSName(&pStmt->targetTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
732,431,201✔
2426
  if (TSDB_CODE_SUCCESS == code) {
732,442,330✔
2427
    if (IS_SYS_DBNAME(pStmt->targetTableName.dbname)) {
732,458,035✔
2428
      return TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED;
46,080✔
2429
    }
2430
  }
2431

2432
  return code;
732,391,942✔
2433
}
2434

2435
// input pStmt->pSql:
2436
//   1(care). [(field1_name, ...)] ...
2437
//   2. [ USING ... ] ...
2438
//   3. VALUES ... | FILE ...
2439
// output pStmt->pSql:
2440
//   1. [ USING ... ] ...
2441
//   2. VALUES ... | FILE ...
2442
static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
732,399,759✔
2443
  SToken  token;
2444
  int32_t index = 0;
732,399,759✔
2445
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
732,417,598✔
2446
  if (TK_NK_LP != token.type) {
732,479,200✔
2447
    return TSDB_CODE_SUCCESS;
686,834,785✔
2448
  }
2449

2450
  // pStmt->pSql -> field1_name, ...)
2451
  pStmt->pSql += index;
45,644,415✔
2452
  pStmt->pBoundCols = pStmt->pSql;
45,644,415✔
2453
  return skipParentheses(pCxt, &pStmt->pSql);
45,644,415✔
2454
}
2455

2456
static int32_t getTableDataCxt(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt** pTableCxt) {
731,574,091✔
2457
  if (pCxt->pComCxt->async) {
731,574,091✔
2458
    return insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid),
1,444,484,201✔
2459
                              pStmt->pTableMeta, &pStmt->pCreateTblReq, pTableCxt, false, false);
724,234,959✔
2460
  }
2461

2462
  char    tbFName[TSDB_TABLE_FNAME_LEN];
7,342,151✔
2463
  int32_t code = 0;
7,382,545✔
2464
  if ((pCxt->stmtTbNameFlag & NO_DATA_USING_CLAUSE) == USING_CLAUSE) {
7,382,545✔
2465
    tstrncpy(pStmt->targetTableName.tname, pStmt->usingTableName.tname, sizeof(pStmt->targetTableName.tname));
5,308✔
2466
    tstrncpy(pStmt->targetTableName.dbname, pStmt->usingTableName.dbname, sizeof(pStmt->targetTableName.dbname));
5,308✔
2467
    pStmt->targetTableName.type = TSDB_SUPER_TABLE;
5,308✔
2468
    pStmt->pTableMeta->tableType = TSDB_SUPER_TABLE;
5,308✔
2469
  }
2470

2471
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
7,386,498✔
2472

2473
  if (TSDB_CODE_SUCCESS != code) {
7,386,901✔
UNCOV
2474
    return code;
×
2475
  }
2476
  if (pStmt->usingTableProcessing) {
7,386,901✔
2477
    pStmt->pTableMeta->uid = 0;
7,233,912✔
2478
  }
2479
  return insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
7,385,776✔
2480
                            &pStmt->pCreateTblReq, pTableCxt, NULL != pCxt->pComCxt->pStmtCb, false);
7,386,865✔
2481
}
2482
#ifdef TD_ENTERPRISE
2483
static int32_t parseCheckNoBoundColPriv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
161✔
2484
  int32_t nPrivs = taosArrayGetSize(pStmt->pPrivCols);
161✔
2485
  if (nPrivs <= 0) {
161✔
UNCOV
2486
    return TSDB_CODE_SUCCESS;
×
2487
  }
2488
  int32_t nCols = pStmt->pTableMeta->tableInfo.numOfColumns;
161✔
2489
  /**
2490
   * It cann't provide the specific missing column info although with better performance. For better UE, we check each
2491
   * column one by one.
2492
   */
2493
  // if (nPrivs < nCols) return TSDB_CODE_PAR_COL_PERMISSION_DENIED;
2494

2495
  // both the schema and privCols are ordered by colId asc
2496
  SSchema* pSchemas = pStmt->pTableMeta->schema;
161✔
2497
  int32_t  j = 0;
161✔
2498
  for (int32_t i = 0; i < nCols; ++i) {
483✔
2499
    SSchema* pSchema = &pSchemas[i];
483✔
2500
    bool     found = false;
483✔
2501
    for (; j < nPrivs; ++j) {
483✔
2502
      SColNameFlag* pColFlag = (SColNameFlag*)TARRAY_GET_ELEM(pStmt->pPrivCols, j);
483✔
2503
      if (pColFlag->colId == pSchema->colId) {
483✔
2504
        found = true;
322✔
2505
        ++j;
322✔
2506
        break;
322✔
2507
      } else if (pColFlag->colId > pSchema->colId) {
161✔
2508
        break;
161✔
2509
      }
2510
    }
2511

2512
    if (!found) {
483✔
2513
      return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_COL_PERMISSION_DENIED, pSchema->name);
161✔
2514
    }
2515
  }
2516

UNCOV
2517
  return TSDB_CODE_SUCCESS;
×
2518
}
2519
#endif
2520

2521
static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) {
731,571,223✔
2522
  SToken  token;
2523
  int32_t index = 0;
731,571,223✔
2524
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
731,606,960✔
2525
  if (TK_NK_LP == token.type) {
731,543,224✔
2526
    pStmt->pSql += index;
98,650✔
2527
    if (NULL != pStmt->pBoundCols) {
98,650✔
2528
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
1,221✔
2529
    }
2530
    // pStmt->pSql -> field1_name, ...)
2531
    return parseBoundColumns(pCxt, pStmt, &pStmt->pSql, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo);
97,429✔
2532
  }
2533

2534
  if (NULL != pStmt->pBoundCols) {
731,444,574✔
2535
    return parseBoundColumns(pCxt, pStmt, &pStmt->pBoundCols, BOUND_COLUMNS, pStmt->pTableMeta,
45,404,091✔
2536
                             &pTableCxt->boundColsInfo);
2537
  } else if (pTableCxt->boundColsInfo.hasBoundCols) {
686,062,888✔
2538
    insResetBoundColsInfo(&pTableCxt->boundColsInfo);
3,204✔
2539
  } else if (NULL != pStmt->pPrivCols) {
686,033,255✔
2540
#ifdef TD_ENTERPRISE
2541
    PAR_ERR_RET(parseCheckNoBoundColPriv(pCxt, pStmt));
161✔
2542
#endif
2543
  }
2544

2545

2546
  return TSDB_CODE_SUCCESS;
686,028,792✔
2547
}
2548

2549
int32_t initTableColSubmitData(STableDataCxt* pTableCxt) {
1,881,598,189✔
2550
  if (0 == (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT)) {
1,881,598,189✔
2551
    return TSDB_CODE_SUCCESS;
1,874,269,316✔
2552
  }
2553

2554
  for (int32_t i = 0; i < pTableCxt->boundColsInfo.numOfBound; ++i) {
30,488,492✔
2555
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
23,050,518✔
2556
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
23,050,375✔
2557
    if (NULL == pCol) {
23,057,219✔
UNCOV
2558
      return terrno;
×
2559
    }
2560
    tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags);
23,057,219✔
2561
  }
2562

2563
  return TSDB_CODE_SUCCESS;
7,436,003✔
2564
}
2565

2566
int32_t initTableColSubmitDataWithBoundInfo(STableDataCxt* pTableCxt, SBoundColInfo pBoundColsInfo) {
8,046✔
2567
  qDestroyBoundColInfo(&(pTableCxt->boundColsInfo));
8,046✔
2568
  pTableCxt->boundColsInfo = pBoundColsInfo;
8,046✔
2569
  for (int32_t i = 0; i < pBoundColsInfo.numOfBound; ++i) {
25,922✔
2570
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
17,876✔
2571
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
17,876✔
2572
    if (NULL == pCol) {
17,876✔
UNCOV
2573
      return terrno;
×
2574
    }
2575
    tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags);
17,876✔
2576
  }
2577

2578
  return TSDB_CODE_SUCCESS;
8,046✔
2579
}
2580

2581
// input pStmt->pSql:
2582
//   1. [(tag1_name, ...)] ...
2583
//   2. VALUES ... | FILE ...
2584
// output pStmt->pSql: VALUES ... | FILE ...
2585
static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
731,853,637✔
2586
                                       STableDataCxt** pTableCxt) {
2587
  int32_t code = parseUsingClauseBottom(pCxt, pStmt);
731,853,637✔
2588
  if (TSDB_CODE_SUCCESS == code) {
731,872,798✔
2589
    code = getTableDataCxt(pCxt, pStmt, pTableCxt);
731,602,830✔
2590
  }
2591
  if (TSDB_CODE_SUCCESS == code) {
731,881,442✔
2592
    code = parseBoundColumnsClause(pCxt, pStmt, *pTableCxt);
731,619,264✔
2593
  }
2594
  if (TSDB_CODE_SUCCESS == code) {
731,855,162✔
2595
    code = initTableColSubmitData(*pTableCxt);
731,540,796✔
2596
  }
2597
  return code;
731,853,664✔
2598
}
2599

2600
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
2601
// output pStmt->pSql:
2602
//   1. [(tag1_name, ...)] ...
2603
//   2. VALUES ... | FILE ...
2604
static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
732,436,945✔
2605
  int32_t code = preParseTargetTableName(pCxt, pStmt, pTbName);
732,436,945✔
2606
  if (TSDB_CODE_SUCCESS == code) {
732,457,946✔
2607
    // option: [(field1_name, ...)]
2608
    code = preParseBoundColumnsClause(pCxt, pStmt);
732,417,034✔
2609
  }
2610
  if (TSDB_CODE_SUCCESS == code) {
732,474,690✔
2611
    // option: [USING stb_name]
2612
    code = parseUsingTableName(pCxt, pStmt);
732,419,948✔
2613
  }
2614
  return code;
732,402,326✔
2615
}
2616

2617
static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
2,147,483,647✔
2618
                                   const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) {
2619
  switch (pSchema->type) {
2,147,483,647✔
2620
    case TSDB_DATA_TYPE_BOOL: {
2,147,483,647✔
2621
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
2,147,483,647✔
2622
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
2,147,483,647✔
2623
          VALUE_SET_TRIVIAL_DATUM(&pVal->value, TRUE_VALUE);
2,147,483,647✔
2624
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
2,007,765,695✔
2625
          VALUE_SET_TRIVIAL_DATUM(&pVal->value, FALSE_VALUE);
2,008,360,868✔
2626
        } else if (TSDB_CODE_SUCCESS ==
22,005✔
2627
                   toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,133✔
2628
          int8_t v = (*(double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value) == 0 ? FALSE_VALUE : TRUE_VALUE);
17,115✔
2629
          valueSetDatum(&pVal->value, TSDB_DATA_TYPE_BOOL, &v, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes);
17,115✔
2630
        } else {
2631
          return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
4,890✔
2632
        }
2633
      } else if (pToken->type == TK_NK_INTEGER) {
2,147,483,647✔
2634
        int8_t v = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
2,147,483,647✔
2635
        VALUE_SET_TRIVIAL_DATUM(&pVal->value, v);
2,147,483,647✔
2636
      } else if (pToken->type == TK_NK_FLOAT) {
1,910,861✔
2637
        int8_t v = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
1,870,150✔
2638
        VALUE_SET_TRIVIAL_DATUM(&pVal->value, v);
1,870,150✔
2639
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
47,231✔
2640
                 (TSDB_CODE_SUCCESS ==
2641
                  toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value)))) {
39,896✔
2642
        int8_t v = *(double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value) == 0 ? FALSE_VALUE : TRUE_VALUE;
6,520✔
2643
        valueSetDatum(&pVal->value, TSDB_DATA_TYPE_BOOL, &v, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes);
6,520✔
2644
      } else {
2645
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
815✔
2646
      }
2647
      break;
2,147,483,647✔
2648
    }
2649
    case TSDB_DATA_TYPE_TINYINT: {
2,147,483,647✔
2650
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2651
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2652
        return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z);
10,188✔
2653
      } else if (!IS_VALID_TINYINT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2654
        return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z);
950,833✔
2655
      }
2656
      break;
2,147,483,647✔
2657
    }
2658
    case TSDB_DATA_TYPE_UTINYINT: {
2,147,483,647✔
2659
      int32_t code =
2660
          toUIntegerEx(pToken->z, pToken->n, pToken->type, (uint64_t*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2661
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2662
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z);
8,037✔
2663
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT8_MAX) {
2,147,483,647✔
2664
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z);
2,000✔
2665
      }
2666
      break;
2,147,483,647✔
2667
    }
2668
    case TSDB_DATA_TYPE_SMALLINT: {
2,147,483,647✔
2669
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2670
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2671
        return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z);
10,188✔
2672
      } else if (!IS_VALID_SMALLINT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2673
        return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z);
3,134,187✔
2674
      }
2675
      break;
2,147,483,647✔
2676
    }
2677
    case TSDB_DATA_TYPE_USMALLINT: {
2,147,483,647✔
2678
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2679
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2680
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z);
8,037✔
2681
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT16_MAX) {
2,147,483,647✔
2682
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z);
2,000✔
2683
      }
2684
      break;
2,147,483,647✔
2685
    }
2686
    case TSDB_DATA_TYPE_INT: {
2,147,483,647✔
2687
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2688
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2689
        return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z);
10,914✔
2690
      } else if (!IS_VALID_INT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2691
        return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z);
16,766,544✔
2692
      }
2693
      break;
2,147,483,647✔
2694
    }
2695
    case TSDB_DATA_TYPE_UINT: {
2,147,483,647✔
2696
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2697
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2698
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z);
16,187✔
2699
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT32_MAX) {
2,147,483,647✔
2700
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z);
3,630✔
2701
      }
2702
      break;
2,147,483,647✔
2703
    }
2704
    case TSDB_DATA_TYPE_BIGINT: {
2,147,483,647✔
2705
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2706
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2707
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z);
17,451✔
2708
      }
2709
      break;
2,147,483,647✔
2710
    }
2711
    case TSDB_DATA_TYPE_UBIGINT: {
2,147,483,647✔
2712
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2713
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2714
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z);
286,141✔
2715
      }
2716
      break;
2,147,483,647✔
2717
    }
2718
    case TSDB_DATA_TYPE_FLOAT: {
2,147,483,647✔
2719
      double  dv;
2,147,483,647✔
2720
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
2,147,483,647✔
2721
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2722
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
8,924✔
2723
      }
2724
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
2,147,483,647✔
2725
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
869✔
2726
      }
2727
      float f = dv;
2,147,483,647✔
2728
      valueSetDatum(&pVal->value, TSDB_DATA_TYPE_FLOAT, &f, sizeof(f));
2,147,483,647✔
2729
      break;
2,147,483,647✔
2730
    }
2731
    case TSDB_DATA_TYPE_DOUBLE: {
2,147,483,647✔
2732
      double  dv;
2,147,483,647✔
2733
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
2,147,483,647✔
2734
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2735
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
15,444✔
2736
      }
2737
      if (isinf(dv) || isnan(dv)) {
2,147,483,647✔
2738
        return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
4,310,556✔
2739
      }
2740
      VALUE_SET_TRIVIAL_DATUM(&pVal->value, (*(int64_t*)&dv));
2,147,483,647✔
2741
      break;
2,147,483,647✔
2742
    }
2743
    case TSDB_DATA_TYPE_BINARY: {
2,147,483,647✔
2744
      return parseBinary(pCxt, pSql, pToken, pVal, pSchema);
2,147,483,647✔
2745
    }
2746
    case TSDB_DATA_TYPE_VARBINARY: {
2,147,483,647✔
2747
      int32_t code = parseVarbinary(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes);
2,147,483,647✔
2748
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2749
        return generateSyntaxErrMsg(&pCxt->msg, code, pSchema->name);
10,920✔
2750
      }
2751
      break;
2,147,483,647✔
2752
    }
2753
    case TSDB_DATA_TYPE_NCHAR: {
2,147,483,647✔
2754
      // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
2755
      int32_t len = 0;
2,147,483,647✔
2756
      int64_t realLen = pToken->n << 2;
2,147,483,647✔
2757
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
2,147,483,647✔
2758
      char* pUcs4 = taosMemoryMalloc(realLen);
2,147,483,647✔
2759
      if (NULL == pUcs4) {
2,147,483,647✔
2760
        return terrno;
196✔
2761
      }
2762
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)pUcs4, realLen, &len, pCxt->pComCxt->charsetCxt)) {
2,147,483,647✔
2763
        taosMemoryFree(pUcs4);
56,876✔
2764
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
2,724✔
2765
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
2,528✔
2766
        }
2767
        char buf[512] = {0};
196✔
2768
        snprintf(buf, tListLen(buf), "%s", strerror(terrno));
196✔
2769
        return buildSyntaxErrMsg(&pCxt->msg, buf, pToken->z);
196✔
2770
      }
2771
      pVal->value.pData = pUcs4;
2,147,483,647✔
2772
      pVal->value.nData = len;
2,147,483,647✔
2773
      break;
2,147,483,647✔
2774
    }
UNCOV
2775
    case TSDB_DATA_TYPE_JSON: {
×
UNCOV
2776
      if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
×
UNCOV
2777
        return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z);
×
2778
      }
UNCOV
2779
      pVal->value.pData = taosMemoryMalloc(pToken->n);
×
UNCOV
2780
      if (NULL == pVal->value.pData) {
×
UNCOV
2781
        return terrno;
×
2782
      }
UNCOV
2783
      memcpy(pVal->value.pData, pToken->z, pToken->n);
×
UNCOV
2784
      pVal->value.nData = pToken->n;
×
UNCOV
2785
      break;
×
2786
    }
2787
    case TSDB_DATA_TYPE_GEOMETRY: {
146,930,973✔
2788
      int32_t        code = TSDB_CODE_FAILED;
146,930,973✔
2789
      unsigned char* output = NULL;
146,930,973✔
2790
      size_t         size = 0;
146,930,973✔
2791

2792
      code = parseGeometry(pToken, &output, &size);
146,930,973✔
2793
      if (code != TSDB_CODE_SUCCESS) {
146,930,973✔
2794
        code = buildSyntaxErrMsg(&pCxt->msg, getGeosErrMsg(code), pToken->z);
1,792✔
2795
      }
2796
      // Too long values will raise the invalid sql error message
2797
      else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
146,929,181✔
UNCOV
2798
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
2799
      } else {
2800
        pVal->value.pData = taosMemoryMalloc(size);
146,929,181✔
2801
        if (NULL == pVal->value.pData) {
146,929,150✔
UNCOV
2802
          code = terrno;
×
2803
        } else {
2804
          memcpy(pVal->value.pData, output, size);
146,928,995✔
2805
          pVal->value.nData = size;
146,929,026✔
2806
        }
2807
      }
2808

2809
      geosFreeBuffer(output);
146,930,942✔
2810
      if (code != TSDB_CODE_SUCCESS) {
146,930,973✔
2811
        return code;
1,792✔
2812
      }
2813

2814
      break;
146,929,181✔
2815
    }
2816
    case TSDB_DATA_TYPE_TIMESTAMP: {
2,147,483,647✔
2817
      if (parseTime(pSql, pToken, timePrec, &VALUE_GET_TRIVIAL_DATUM(&pVal->value), &pCxt->msg,
2,147,483,647✔
2818
                    pCxt->pComCxt->timezone) != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2819
        return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z);
25,386✔
2820
      }
2821
      break;
2,147,483,647✔
2822
    }
2823
    case TSDB_DATA_TYPE_BLOB:
442,357,802✔
2824
    case TSDB_DATA_TYPE_MEDIUMBLOB: {
2825
      int32_t code = parseBlob(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes);
442,357,802✔
2826
      if (code != TSDB_CODE_SUCCESS) {
26,309,089✔
2827
        return generateSyntaxErrMsg(&pCxt->msg, code, pSchema->name);
9,780✔
2828
      }
2829
    } break;
26,299,309✔
2830
    case TSDB_DATA_TYPE_DECIMAL: {
142,518,542✔
2831
      if (!pExtSchema) {
142,518,542✔
UNCOV
2832
        qError("Decimal type without ext schema info, cannot parse decimal values");
×
UNCOV
2833
        return TSDB_CODE_DECIMAL_PARSE_ERROR;
×
2834
      }
2835
      uint8_t precision = 0, scale = 0;
142,518,542✔
2836
      decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale);
142,527,396✔
2837
      Decimal128 dec = {0};
142,544,266✔
2838
      int32_t    code = decimal128FromStr(pToken->z, pToken->n, precision, scale, &dec);
142,546,470✔
2839
      if (TSDB_CODE_SUCCESS != code) {
142,579,376✔
UNCOV
2840
        return code;
×
2841
      }
2842

2843
      // precision check
2844
      // scale auto fit
2845

2846
      code = decimal128ToDataVal(&dec, &pVal->value);
142,579,376✔
2847
      if (TSDB_CODE_SUCCESS != code) {
142,595,116✔
2848
        return code;
×
2849
      }
2850
      break;
142,595,116✔
2851
    }
2852
    case TSDB_DATA_TYPE_DECIMAL64: {
315,017,039✔
2853
      if (!pExtSchema) {
315,017,039✔
UNCOV
2854
        qError("Decimal type without ext schema info, cannot parse decimal values");
×
UNCOV
2855
        return TSDB_CODE_DECIMAL_PARSE_ERROR;
×
2856
      }
2857
      uint8_t precision = 0, scale = 0;
315,017,039✔
2858
      decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale);
315,037,027✔
2859
      Decimal64 dec = {0};
315,061,075✔
2860
      int32_t   code = decimal64FromStr(pToken->z, pToken->n, precision, scale, &dec);
315,065,749✔
2861
      if (TSDB_CODE_SUCCESS != code) {
315,052,535✔
UNCOV
2862
        return code;
×
2863
      }
2864
      code = decimal64ToDataVal(&dec, &pVal->value);
315,052,535✔
2865
      if (TSDB_CODE_SUCCESS != code) {
315,065,797✔
UNCOV
2866
        return code;
×
2867
      }
2868
      break;
315,065,797✔
2869
    }
2870
    default:
×
2871

UNCOV
2872
      return TSDB_CODE_FAILED;
×
2873
  }
2874

2875
  pVal->flag = CV_FLAG_VALUE;
2,147,483,647✔
2876
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2877
}
2878

2879
static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
2,147,483,647✔
2880
                               const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) {
2881
  int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pSchema->type);
2,147,483,647✔
2882
  if (TSDB_CODE_SUCCESS == code && isNullValue(pSchema->type, pToken)) {
2,147,483,647✔
2883
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
2,147,483,647✔
2884
      return buildSyntaxErrMsg(&pCxt->msg, "Primary timestamp column should not be null", pToken->z);
96✔
2885
    }
2886

2887
    pVal->flag = CV_FLAG_NULL;
2,147,483,647✔
2888
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
2889
  }
2890

2891
  if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
2892
    if (pToken->n == 0 && IS_NUMERIC_TYPE(pSchema->type)) {
2,147,483,647✔
2893
      return buildSyntaxErrMsg(&pCxt->msg, "invalid numeric data", pToken->z);
1,106✔
2894
    }
2895
    code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, pExtSchema, timePrec, pVal);
2,147,483,647✔
2896
  }
2897

2898
  return code;
2,147,483,647✔
2899
}
2900

2901
static void clearColValArray(SArray* pCols) {
2,147,483,647✔
2902
  int32_t num = taosArrayGetSize(pCols);
2,147,483,647✔
2903
  for (int32_t i = 0; i < num; ++i) {
2,147,483,647✔
2904
    SColVal* pCol = taosArrayGet(pCols, i);
2,147,483,647✔
2905
    if (IS_VAR_DATA_TYPE(pCol->value.type) || pCol->value.type == TSDB_DATA_TYPE_DECIMAL) {
2,147,483,647✔
2906
      taosMemoryFreeClear(pCol->value.pData);
2,147,483,647✔
2907
    }
2908
  }
2909
}
2,147,483,647✔
2910

2911
typedef struct SStbRowsDataContext {
2912
  SName stbName;
2913

2914
  STableMeta*   pStbMeta;
2915
  SNode*        pTagCond;
2916
  SBoundColInfo boundColsInfo;
2917

2918
  // the following fields are for each stb row
2919
  SArray*        aTagVals;
2920
  SArray*        aColVals;
2921
  SArray*        aTagNames;
2922
  SName          ctbName;
2923
  STag*          pTag;
2924
  STableMeta*    pCtbMeta;
2925
  SVCreateTbReq* pCreateCtbReq;
2926
  bool           hasTimestampTag;
2927
  bool           isJsonTag;
2928
} SStbRowsDataContext;
2929

2930
typedef union SRowsDataContext {
2931
  STableDataCxt*       pTableDataCxt;
2932
  SStbRowsDataContext* pStbRowsCxt;
2933
} SRowsDataContext;
2934

2935
int32_t parseTbnameToken(SMsgBuf* pMsgBuf, char* tname, SToken* pToken, bool* pFoundCtbName) {
1,149,486,775✔
2936
  *pFoundCtbName = false;
1,149,486,775✔
2937

2938
  if (isNullValue(TSDB_DATA_TYPE_BINARY, pToken)) {
1,149,486,775✔
UNCOV
2939
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be null value");
×
2940
  }
2941

2942
  if (pToken->n > 0) {
1,149,486,775✔
2943
    if (pToken->n <= TSDB_TABLE_NAME_LEN - 1) {
1,149,486,134✔
2944
      for (int i = 0; i < pToken->n; ++i) {
2,147,483,647✔
2945
        if (pToken->z[i] == '.') {
2,147,483,647✔
2946
          return buildInvalidOperationMsg(pMsgBuf, "tbname can not contain '.'");
641✔
2947
        } else {
2948
          tname[i] = pToken->z[i];
2,147,483,647✔
2949
        }
2950
      }
2951
      tname[pToken->n] = '\0';
1,149,485,347✔
2952
      *pFoundCtbName = true;
1,149,485,347✔
2953
    } else {
2954
      return buildInvalidOperationMsg(pMsgBuf, "tbname is too long");
146✔
2955
    }
2956
  } else {
2957
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be empty");
641✔
2958
  }
2959
  return TSDB_CODE_SUCCESS;
1,149,485,347✔
2960
}
2961

2962
static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
1,149,304,045✔
2963
                                          SStbRowsDataContext* pStbRowsCxt, bool ctbFirst, const SToken* tagTokens,
2964
                                          SSchema* const* tagSchemas, int numOfTagTokens) {
2965
  int32_t code = TSDB_CODE_SUCCESS;
1,149,304,045✔
2966
  uint8_t precision = pStmt->pTableMeta->tableInfo.precision;
1,149,304,045✔
2967

2968
  if (code == TSDB_CODE_SUCCESS && ctbFirst) {
1,149,304,045✔
2969
    for (int32_t i = 0; code == TSDB_CODE_SUCCESS && i < numOfTagTokens; ++i) {
3,134,391✔
2970
      SToken*  pTagToken = (SToken*)(tagTokens + i);
129,223✔
2971
      SSchema* pTagSchema = tagSchemas[i];
129,223✔
2972
      code = checkAndTrimValue(pTagToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
129,223✔
2973
      if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pTagToken->type) {
129,223✔
UNCOV
2974
        code = buildInvalidOperationMsg(&pCxt->msg, "not expected tag");
×
2975
      }
2976

2977
      if (code == TSDB_CODE_SUCCESS) {
129,223✔
2978
        code = parseTagValue(&pCxt->msg, NULL, precision, pTagSchema, pTagToken, pStbRowsCxt->aTagNames,
257,662✔
2979
                             pStbRowsCxt->aTagVals, &pStbRowsCxt->pTag, pCxt->pComCxt->timezone,
129,223✔
2980
                             pCxt->pComCxt->charsetCxt);
129,223✔
2981
      }
2982
    }
2983
    if (code == TSDB_CODE_SUCCESS && !pStbRowsCxt->isJsonTag) {
3,005,168✔
2984
      code = tTagNew(pStbRowsCxt->aTagVals, 1, false, &pStbRowsCxt->pTag);
3,005,168✔
2985
    }
2986
  }
2987
  if (code == TSDB_CODE_SUCCESS && pStbRowsCxt->pTagCond) {
1,149,304,045✔
UNCOV
2988
    code = checkSubtablePrivilege(pStbRowsCxt->aTagVals, pStbRowsCxt->aTagNames, &pStbRowsCxt->pTagCond);
×
2989
  }
2990
  return code;
1,149,304,045✔
2991
}
2992

2993
static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
1,149,316,802✔
2994
                                 SStbRowsDataContext* pStbRowsCxt, SToken* pToken, const SBoundColInfo* pCols,
2995
                                 const SSchema* pSchemas, const SSchemaExt* pExtSchemas, SToken* tagTokens,
2996
                                 SSchema** tagSchemas, int* pNumOfTagTokens, bool* bFoundTbName, bool* setCtbName,
2997
                                 SBoundColInfo* ctbCols) {
2998
  int32_t code = TSDB_CODE_SUCCESS;
1,149,316,802✔
2999
  SArray* pTagNames = pStbRowsCxt->aTagNames;
1,149,316,802✔
3000
  SArray* pTagVals = pStbRowsCxt->aTagVals;
1,149,316,802✔
3001
  bool    canParseTagsAfter = !pStbRowsCxt->pTagCond && !pStbRowsCxt->hasTimestampTag;
1,149,316,802✔
3002
  int32_t numOfCols = getNumOfColumns(pStbRowsCxt->pStbMeta);
1,149,316,802✔
3003
  int32_t numOfTags = getNumOfTags(pStbRowsCxt->pStbMeta);
1,149,316,802✔
3004
  int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta);
1,149,316,802✔
3005
  uint8_t precision = getTableInfo(pStbRowsCxt->pStbMeta).precision;
1,149,316,802✔
3006
  int     tag_index = 0;
1,149,316,802✔
3007
  int     col_index = 0;
1,149,316,802✔
3008
  for (int i = 0; i < pCols->numOfBound && (code) == TSDB_CODE_SUCCESS; ++i) {
2,147,483,647✔
3009
    const char* pTmpSql = *ppSql;
2,147,483,647✔
3010
    bool        ignoreComma = false;
2,147,483,647✔
3011
    NEXT_TOKEN_WITH_PREV_EXT(*ppSql, *pToken, &ignoreComma);
2,147,483,647✔
3012

3013
    if (ignoreComma) {
2,147,483,647✔
UNCOV
3014
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pTmpSql);
×
UNCOV
3015
      break;
×
3016
    }
3017

3018
    if (TK_NK_RP == pToken->type) {
2,147,483,647✔
UNCOV
3019
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
×
UNCOV
3020
      break;
×
3021
    }
3022

3023
    // cols tags tbname
3024
    if (TK_NK_QUESTION == pToken->type) {
2,147,483,647✔
3025
      if (pCxt->pComCxt->stmtBindVersion != 2) {
54,040✔
3026
        return buildInvalidOperationMsg(&pCxt->msg,
196✔
3027
                                        "insert into stb(...tbname...)values(...,?,...) only support in stmt2");
3028
      }
3029
      if (pCols->pColIndex[i] == tbnameIdx) {
53,844✔
3030
        *bFoundTbName = true;
10,800✔
3031
        char* tbName = NULL;
10,800✔
3032
        if ((*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName) == TSDB_CODE_SUCCESS) {
10,800✔
3033
          tstrncpy(pStbRowsCxt->ctbName.tname, tbName, sizeof(pStbRowsCxt->ctbName.tname));
8,046✔
3034
          tstrncpy(pStmt->usingTableName.tname, pStmt->targetTableName.tname, sizeof(pStmt->usingTableName.tname));
8,046✔
3035
          tstrncpy(pStmt->targetTableName.tname, tbName, sizeof(pStmt->targetTableName.tname));
8,046✔
3036
          tstrncpy(pStmt->usingTableName.dbname, pStmt->targetTableName.dbname, sizeof(pStmt->usingTableName.dbname));
8,046✔
3037
          pStmt->usingTableName.type = 1;
8,046✔
3038
          pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;  // set the table type to child table for parse cache
8,046✔
3039
          *setCtbName = true;
8,046✔
3040
        }
3041
      } else if (pCols->pColIndex[i] < numOfCols) {
43,044✔
3042
        // bind column
3043
        if (ctbCols->pColIndex == NULL) {
24,972✔
3044
          ctbCols->pColIndex = taosMemoryCalloc(numOfCols, sizeof(int16_t));
10,800✔
3045
          if (NULL == ctbCols->pColIndex) {
10,800✔
UNCOV
3046
            return terrno;
×
3047
          }
3048
        }
3049
        ctbCols->pColIndex[col_index++] = pCols->pColIndex[i];
24,972✔
3050
        ctbCols->numOfBound++;
24,972✔
3051
        ctbCols->numOfCols++;
24,972✔
3052

3053
      } else if (pCols->pColIndex[i] < tbnameIdx) {
18,072✔
3054
        if (pCxt->tags.pColIndex == NULL) {
18,072✔
3055
          pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t));
7,076✔
3056
          if (NULL == pCxt->tags.pColIndex) {
7,076✔
UNCOV
3057
            return terrno;
×
3058
          }
3059
        }
3060
        if (!(tag_index < numOfTags)) {
18,072✔
UNCOV
3061
          return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags");
×
3062
        }
3063
        pStmt->usingTableProcessing = true;
18,072✔
3064
        pCxt->tags.pColIndex[tag_index++] = pCols->pColIndex[i] - numOfCols;
18,072✔
3065
        pCxt->tags.mixTagsCols = true;
18,072✔
3066
        pCxt->tags.numOfBound++;
18,072✔
3067
        pCxt->tags.numOfCols++;
18,072✔
3068
      } else {
UNCOV
3069
        return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfBound");
×
3070
      }
3071
    } else {
3072
      if (pCxt->pComCxt->stmtBindVersion == 2 && pCxt->pComCxt->pStmtCb != NULL) {
2,147,483,647✔
3073
        if (pCols->pColIndex[i] < numOfCols) {
2,156✔
3074
          const SSchema*    pSchema = &pSchemas[pCols->pColIndex[i]];
980✔
3075
          const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i];
980✔
3076
          SColVal*          pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]);
980✔
3077
          code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, pExtSchema, precision, pVal);
980✔
3078
          if (TK_NK_VARIABLE == pToken->type) {
980✔
UNCOV
3079
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
3080
          }
3081

3082
          if (ctbCols->pColIndex == NULL) {
980✔
UNCOV
3083
            ctbCols->pColIndex = taosMemoryCalloc(numOfCols, sizeof(int16_t));
×
UNCOV
3084
            if (NULL == ctbCols->pColIndex) {
×
3085
              return terrno;
×
3086
            }
3087
          }
3088
          ctbCols->pColIndex[col_index++] = pCols->pColIndex[i];
980✔
3089
          ctbCols->numOfBound++;
980✔
3090
          ctbCols->numOfCols++;
980✔
3091

3092
          if (code == TSDB_CODE_SUCCESS && pCxt->pParsedValues == NULL) {
980✔
3093
            pCxt->pParsedValues =
588✔
3094
                tSimpleHashInit(pCols->numOfBound, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT));
588✔
3095
            if (pCxt->pParsedValues == NULL) {
588✔
UNCOV
3096
              return terrno;
×
3097
            }
3098
            tSimpleHashSetFreeFp(pCxt->pParsedValues, destroyColVal);
588✔
3099
          }
3100

3101
          if (code == TSDB_CODE_SUCCESS) {
980✔
3102
            SColVal clonedVal = *pVal;
980✔
3103
            if (COL_VAL_IS_VALUE(&clonedVal) && IS_VAR_DATA_TYPE(clonedVal.value.type)) {
980✔
3104
              clonedVal.value.pData = taosMemoryMalloc(clonedVal.value.nData);
196✔
3105
              if (NULL == clonedVal.value.pData) {
196✔
UNCOV
3106
                code = terrno;
×
UNCOV
3107
                break;
×
3108
              }
3109
              memcpy(clonedVal.value.pData, pVal->value.pData, clonedVal.value.nData);
196✔
3110
            }
3111

3112
            clonedVal.cid = pSchema->colId;
980✔
3113
            code = tSimpleHashPut(pCxt->pParsedValues, &pSchema->colId, sizeof(int16_t), &clonedVal, sizeof(SColVal));
980✔
3114
            if (code != TSDB_CODE_SUCCESS) {
980✔
UNCOV
3115
              if (COL_VAL_IS_VALUE(&clonedVal) && IS_VAR_DATA_TYPE(clonedVal.value.type)) {
×
UNCOV
3116
                taosMemoryFree(clonedVal.value.pData);
×
UNCOV
3117
                clonedVal.value.pData = NULL;
×
3118
              }
UNCOV
3119
              return code;
×
3120
            }
3121
          }
3122
        } else if (pCols->pColIndex[i] < tbnameIdx) {
1,176✔
3123
          if (pCxt->tags.parseredTags == NULL) {
1,176✔
3124
            pCxt->tags.parseredTags = taosMemoryCalloc(1, sizeof(STagsInfo));
784✔
3125
            if (pCxt->tags.parseredTags == NULL) {
784✔
UNCOV
3126
              code = terrno;
×
3127
            } else {
3128
              pCxt->tags.parseredTags->STagNames = taosArrayInit(numOfTags, sizeof(STagVal));
784✔
3129
              pCxt->tags.parseredTags->pTagVals = taosArrayInit(numOfTags, sizeof(STagVal));
784✔
3130
              pCxt->tags.parseredTags->pTagIndex = taosMemoryCalloc(numOfTags, sizeof(uint8_t));
784✔
3131
              pCxt->tags.parseredTags->numOfTags = 0;
784✔
3132

3133
              if (pCxt->tags.parseredTags->STagNames == NULL || pCxt->tags.parseredTags->pTagVals == NULL ||
784✔
3134
                  pCxt->tags.parseredTags->pTagIndex == NULL) {
784✔
3135
                return terrno;
×
3136
              }
3137
            }
3138
          }
3139

3140
          const SSchema* pTagSchema = &pSchemas[pCols->pColIndex[i]];
1,176✔
3141
          // if (canParseTagsAfter) {
3142
          //   tagTokens[(*pNumOfTagTokens)] = *pToken;
3143
          //   tagSchemas[(*pNumOfTagTokens)] = (SSchema*)pTagSchema;
3144
          //   ++(*pNumOfTagTokens);
3145
          // } else {
3146
          code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
1,176✔
3147
          if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pToken->type) {
1,176✔
UNCOV
3148
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
3149
          }
3150
          if (code == TSDB_CODE_SUCCESS) {
1,176✔
3151
            code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken,
980✔
3152
                                 pCxt->tags.parseredTags->STagNames, pCxt->tags.parseredTags->pTagVals,
980✔
3153
                                 &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
980✔
3154
          }
3155

3156
          pCxt->tags.parseredTags->pTagIndex[pCxt->tags.parseredTags->numOfTags++] = pCols->pColIndex[i] - numOfCols;
1,176✔
3157

3158
          if (pCxt->tags.pColIndex == NULL) {
1,176✔
3159
            pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t));
784✔
3160
            if (NULL == pCxt->tags.pColIndex) {
784✔
UNCOV
3161
              return terrno;
×
3162
            }
3163
          }
3164
          if (!(tag_index < numOfTags)) {
1,176✔
UNCOV
3165
            return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags");
×
3166
          }
3167
          pStmt->usingTableProcessing = true;
1,176✔
3168
          pCxt->tags.pColIndex[tag_index++] = pCols->pColIndex[i] - numOfCols;
1,176✔
3169
          pCxt->tags.mixTagsCols = true;
1,176✔
3170
          pCxt->tags.numOfBound++;
1,176✔
3171
          pCxt->tags.numOfCols++;
1,176✔
3172
          // }
UNCOV
3173
        } else if (pCols->pColIndex[i] == tbnameIdx) {
×
UNCOV
3174
          return buildInvalidOperationMsg(&pCxt->msg, "STMT tbname in bound cols should not be a fixed value");
×
3175
        }
3176
      } else {
3177
        if (pCols->pColIndex[i] < numOfCols) {
2,147,483,647✔
3178
          const SSchema*    pSchema = &pSchemas[pCols->pColIndex[i]];
2,147,483,647✔
3179
          const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i];
2,147,483,647✔
3180
          SColVal*          pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]);
2,147,483,647✔
3181
          code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, pExtSchema, precision, pVal);
2,147,483,647✔
3182
          if (TK_NK_VARIABLE == pToken->type) {
2,147,483,647✔
UNCOV
3183
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
3184
          }
3185
        } else if (pCols->pColIndex[i] < tbnameIdx) {
1,149,481,111✔
3186
          const SSchema* pTagSchema = &pSchemas[pCols->pColIndex[i]];
176,142✔
3187
          if (canParseTagsAfter) {
176,142✔
3188
            tagTokens[(*pNumOfTagTokens)] = *pToken;
176,142✔
3189
            tagSchemas[(*pNumOfTagTokens)] = (SSchema*)pTagSchema;
176,142✔
3190
            ++(*pNumOfTagTokens);
176,142✔
3191
          } else {
UNCOV
3192
            code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
×
UNCOV
3193
            if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pToken->type) {
×
UNCOV
3194
              code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
3195
            }
UNCOV
3196
            if (code == TSDB_CODE_SUCCESS) {
×
UNCOV
3197
              code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, pTagNames, pTagVals,
×
UNCOV
3198
                                   &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
×
3199
            }
3200
          }
3201
        } else if (pCols->pColIndex[i] == tbnameIdx) {
1,149,304,969✔
3202
          code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, TSDB_DATA_TYPE_BINARY);
1,149,304,969✔
3203
          if (TK_NK_VARIABLE == pToken->type) {
1,149,304,969✔
UNCOV
3204
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected tbname");
×
3205
          }
3206

3207
          if (code == TSDB_CODE_SUCCESS) {
1,149,304,969✔
3208
            code = parseTbnameToken(&pCxt->msg, pStbRowsCxt->ctbName.tname, pToken, bFoundTbName);
1,149,301,609✔
3209
          }
3210
        }
3211
      }
3212
    }
3213

3214
    if (code == TSDB_CODE_SUCCESS && i < pCols->numOfBound - 1) {
2,147,483,647✔
3215
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,147,483,647✔
3216
      if (TK_NK_COMMA != pToken->type) {
2,147,483,647✔
3217
        code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
641✔
3218
      }
3219
    }
3220
  }
3221

3222
  return code;
1,149,316,606✔
3223
}
3224

3225
static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
1,149,316,802✔
3226
                               SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken, bool* pCtbFirst,
3227
                               bool* setCtbName, SBoundColInfo* ctbCols) {
3228
  SBoundColInfo* pCols = &pStbRowsCxt->boundColsInfo;
1,149,316,802✔
3229
  SSchema*       pSchemas = getTableColumnSchema(pStbRowsCxt->pStbMeta);
1,149,316,802✔
3230
  SSchemaExt*    pExtSchemas = getTableColumnExtSchema(pStbRowsCxt->pStbMeta);
1,149,316,802✔
3231

3232
  bool        bFoundTbName = false;
1,149,316,802✔
3233
  const char* pOrigSql = *ppSql;
1,149,316,802✔
3234

3235
  int32_t  code = TSDB_CODE_SUCCESS;
1,149,316,802✔
3236
  SToken   tagTokens[TSDB_MAX_TAGS] = {0};
1,149,316,802✔
3237
  SSchema* tagSchemas[TSDB_MAX_TAGS] = {0};
1,149,316,802✔
3238
  int      numOfTagTokens = 0;
1,149,316,802✔
3239

3240
  code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, pExtSchemas, tagTokens, tagSchemas,
1,149,316,802✔
3241
                           &numOfTagTokens, &bFoundTbName, setCtbName, ctbCols);
3242

3243
  if (code != TSDB_CODE_SUCCESS) {
1,149,316,802✔
3244
    return code;
10,003✔
3245
  }
3246

3247
  if (!bFoundTbName) {
1,149,306,799✔
UNCOV
3248
    code = buildSyntaxErrMsg(&pCxt->msg, "tbname value expected", pOrigSql);
×
3249
  }
3250

3251
  bool ctbFirst = true;
1,149,306,799✔
3252
  char ctbFName[TSDB_TABLE_FNAME_LEN];
1,149,295,215✔
3253
  if (code == TSDB_CODE_SUCCESS) {
1,149,306,799✔
3254
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
1,149,306,799✔
3255
  }
3256
  if (TSDB_CODE_SUCCESS == code) {
1,149,306,799✔
3257
    STableMeta** pCtbMeta = taosHashGet(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName));
1,149,304,045✔
3258
    ctbFirst = (pCtbMeta == NULL);
1,149,304,045✔
3259
    if (!ctbFirst) {
1,149,304,045✔
3260
      pStbRowsCxt->pCtbMeta->uid = (*pCtbMeta)->uid;
1,146,298,877✔
3261
      pStbRowsCxt->pCtbMeta->vgId = (*pCtbMeta)->vgId;
1,146,298,877✔
3262
    }
3263
    *pCtbFirst = ctbFirst;
1,149,304,045✔
3264
  }
3265

3266
  if (code == TSDB_CODE_SUCCESS) {
1,149,306,799✔
3267
    code = processCtbTagsAfterCtbName(pCxt, pStmt, pStbRowsCxt, ctbFirst, tagTokens, tagSchemas, numOfTagTokens);
1,149,304,045✔
3268
  }
3269

3270
  if (code == TSDB_CODE_SUCCESS) {
1,149,306,799✔
3271
    *pGotRow = true;
1,149,304,045✔
3272
  }
3273
  return code;
1,149,306,799✔
3274
}
3275

3276
static int32_t processCtbAutoCreationAndCtbMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
3,005,168✔
3277
                                                SStbRowsDataContext* pStbRowsCxt) {
3278
  int32_t code = TSDB_CODE_SUCCESS;
3,005,168✔
3279

3280
  pStbRowsCxt->pCreateCtbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
3,005,168✔
3281
  if (pStbRowsCxt->pCreateCtbReq == NULL) {
3,005,168✔
UNCOV
3282
    code = terrno;
×
3283
  }
3284
  if (code == TSDB_CODE_SUCCESS) {
3,005,168✔
3285
    code = insBuildCreateTbReq(pStbRowsCxt->pCreateCtbReq, pStbRowsCxt->ctbName.tname, pStbRowsCxt->pTag,
6,001,506✔
3286
                               pStbRowsCxt->pStbMeta->uid, pStbRowsCxt->stbName.tname, pStbRowsCxt->aTagNames,
3,005,168✔
3287
                               getNumOfTags(pStbRowsCxt->pStbMeta), TSDB_DEFAULT_TABLE_TTL);
3,005,168✔
3288
    pStbRowsCxt->pTag = NULL;
3,005,168✔
3289
  }
3290

3291
  if (code == TSDB_CODE_SUCCESS) {
3,005,168✔
3292
    char ctbFName[TSDB_TABLE_FNAME_LEN];
2,996,338✔
3293
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
3,005,168✔
3294
    SVgroupInfo      vg;
2,996,338✔
3295
    SRequestConnInfo conn = {.pTrans = pCxt->pComCxt->pTransporter,
6,001,506✔
3296
                             .requestId = pCxt->pComCxt->requestId,
3,005,168✔
3297
                             .requestObjRefId = pCxt->pComCxt->requestRid,
3,005,168✔
3298
                             .mgmtEps = pCxt->pComCxt->mgmtEpSet};
3,005,168✔
3299
    if (TSDB_CODE_SUCCESS == code) {
3,005,168✔
3300
      code = catalogGetTableHashVgroup(pCxt->pComCxt->pCatalog, &conn, &pStbRowsCxt->ctbName, &vg);
3,005,168✔
3301
    }
3302
    if (code == TSDB_CODE_SUCCESS) {
3,005,168✔
3303
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)(&vg.vgId), sizeof(vg.vgId), &vg, sizeof(vg));
3,005,168✔
3304
    }
3305
    STableMeta* pBackup = NULL;
3,005,168✔
3306
    if (TSDB_CODE_SUCCESS == code) {
3,005,168✔
3307
      pStbRowsCxt->pCtbMeta->uid = taosHashGetSize(pStmt->pSubTableHashObj) + 1;
3,005,168✔
3308
      pStbRowsCxt->pCtbMeta->vgId = vg.vgId;
3,005,168✔
3309

3310
      code = cloneTableMeta(pStbRowsCxt->pCtbMeta, &pBackup);
3,005,168✔
3311
    }
3312
    if (TSDB_CODE_SUCCESS == code) {
3,005,168✔
3313
      code = taosHashPut(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName), &pBackup, POINTER_BYTES);
3,005,168✔
3314
    }
3315
    if (TSDB_CODE_SUCCESS == code) {
3,005,168✔
3316
      code = collectUseTable(&pStbRowsCxt->ctbName, pStmt->pTableNameHashObj);
3,005,168✔
3317
    }
3318
  }
3319
  return code;
3,005,168✔
3320
}
3321

3322
static void clearStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
1,149,538,581✔
3323
  if (pStbRowsCxt == NULL) return;
1,149,538,581✔
3324

3325
  taosArrayClear(pStbRowsCxt->aTagNames);
1,149,538,581✔
3326
  for (int i = 0; i < taosArrayGetSize(pStbRowsCxt->aTagVals); ++i) {
1,149,665,240✔
3327
    STagVal* p = (STagVal*)taosArrayGet(pStbRowsCxt->aTagVals, i);
126,659✔
3328
    if (IS_VAR_DATA_TYPE(p->type)) {
126,659✔
3329
      taosMemoryFreeClear(p->pData);
13,449✔
3330
    }
3331
  }
3332
  taosArrayClear(pStbRowsCxt->aTagVals);
1,149,538,581✔
3333

3334
  clearColValArray(pStbRowsCxt->aColVals);
1,149,538,581✔
3335

3336
  tTagFree(pStbRowsCxt->pTag);
1,149,538,581✔
3337
  pStbRowsCxt->pTag = NULL;
1,149,538,581✔
3338
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
1,149,538,581✔
3339
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
1,149,538,581✔
3340

3341
  if (pStbRowsCxt->boundColsInfo.parseredTags != NULL) {
1,149,538,581✔
UNCOV
3342
    if (pStbRowsCxt->boundColsInfo.parseredTags->STagNames != NULL) {
×
UNCOV
3343
      taosArrayDestroy(pStbRowsCxt->boundColsInfo.parseredTags->STagNames);
×
3344
    }
UNCOV
3345
    if (pStbRowsCxt->boundColsInfo.parseredTags->pTagVals != NULL) {
×
UNCOV
3346
      taosArrayDestroy(pStbRowsCxt->boundColsInfo.parseredTags->pTagVals);
×
3347
    }
UNCOV
3348
    taosMemoryFreeClear(pStbRowsCxt->boundColsInfo.parseredTags);
×
3349
  }
3350
}
3351

3352
static void clearInsertParseContext(SInsertParseContext* pCxt) {
1,365,122,878✔
3353
  if (pCxt == NULL) return;
1,365,122,878✔
3354

3355
  if (pCxt->pParsedValues != NULL) {
1,365,122,878✔
UNCOV
3356
    tSimpleHashCleanup(pCxt->pParsedValues);
×
UNCOV
3357
    pCxt->pParsedValues = NULL;
×
3358
  }
3359
}
3360

3361
static int32_t parseStbBoundInfo(SVnodeModifyOpStmt* pStmt, SStbRowsDataContext* pStbRowsCxt,
2,950✔
3362
                                 STableDataCxt** ppTableDataCxt) {
UNCOV
3363
  char    tbFName[TSDB_TABLE_FNAME_LEN];
×
3364
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
2,950✔
3365
  if (TSDB_CODE_SUCCESS != code) {
2,950✔
UNCOV
3366
    return code;
×
3367
  }
3368
  if (pStmt->usingTableProcessing) {
2,950✔
3369
    pStmt->pTableMeta->uid = 0;
2,362✔
3370
  }
3371

3372
  code = insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
2,950✔
3373
                            &pStmt->pCreateTblReq, ppTableDataCxt, false, true);
3374
  if (code != TSDB_CODE_SUCCESS) {
2,950✔
UNCOV
3375
    return code;
×
3376
  }
3377

3378
  qDestroyBoundColInfo(&((*ppTableDataCxt)->boundColsInfo));
2,950✔
3379
  (*ppTableDataCxt)->boundColsInfo = pStbRowsCxt->boundColsInfo;
2,950✔
3380

3381
  (*ppTableDataCxt)->boundColsInfo.pColIndex = taosMemoryCalloc(pStbRowsCxt->boundColsInfo.numOfBound, sizeof(int16_t));
2,950✔
3382
  if (NULL == (*ppTableDataCxt)->boundColsInfo.pColIndex) {
2,950✔
UNCOV
3383
    return terrno;
×
3384
  }
3385
  (void)memcpy((*ppTableDataCxt)->boundColsInfo.pColIndex, pStbRowsCxt->boundColsInfo.pColIndex,
2,950✔
3386
               sizeof(int16_t) * pStmt->pStbRowsCxt->boundColsInfo.numOfBound);
2,950✔
3387
  return TSDB_CODE_SUCCESS;
2,950✔
3388
}
3389

3390
static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
1,149,316,802✔
3391
                              SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken,
3392
                              STableDataCxt** ppTableDataCxt) {
3393
  bool          bFirstTable = false;
1,149,316,802✔
3394
  bool          setCtbName = false;
1,149,316,802✔
3395
  SBoundColInfo ctbCols = {0};
1,149,316,802✔
3396
  int32_t code = getStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pGotRow, pToken, &bFirstTable, &setCtbName, &ctbCols);
1,149,316,802✔
3397

3398
  if (!setCtbName && pCxt->pComCxt->stmtBindVersion == 2) {
1,149,316,802✔
3399
    taosMemoryFreeClear(ctbCols.pColIndex);
2,950✔
3400
    return parseStbBoundInfo(pStmt, pStbRowsCxt, ppTableDataCxt);
2,950✔
3401
  }
3402

3403
  if (code != TSDB_CODE_SUCCESS || !*pGotRow) {
1,149,313,852✔
3404
    return code;
9,807✔
3405
  }
3406

3407
  if (code == TSDB_CODE_SUCCESS && bFirstTable) {
1,149,304,045✔
3408
    code = processCtbAutoCreationAndCtbMeta(pCxt, pStmt, pStbRowsCxt);
3,005,168✔
3409
  }
3410
  if (code == TSDB_CODE_SUCCESS) {
1,149,304,045✔
3411
    if (pCxt->pComCxt->stmtBindVersion == 2) {
1,149,304,045✔
UNCOV
3412
      char ctbFName[TSDB_TABLE_FNAME_LEN];
×
3413
      code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
8,046✔
3414
      if (code != TSDB_CODE_SUCCESS) {
8,046✔
UNCOV
3415
        return code;
×
3416
      }
3417
      code = insGetTableDataCxt(pStmt->pTableBlockHashObj, ctbFName, strlen(ctbFName), pStbRowsCxt->pCtbMeta,
8,046✔
3418
                                &pStbRowsCxt->pCreateCtbReq, ppTableDataCxt, true, true);
3419
    } else {
3420
      code =
3421
          insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid),
1,149,295,999✔
3422
                             pStbRowsCxt->pCtbMeta, &pStbRowsCxt->pCreateCtbReq, ppTableDataCxt, false, true);
3423
    }
3424
  }
3425
  if (code == TSDB_CODE_SUCCESS) {
1,149,304,045✔
3426
    if (pCxt->pComCxt->stmtBindVersion == 2) {
1,149,304,045✔
3427
      int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta);
8,046✔
3428
      code = initTableColSubmitDataWithBoundInfo(*ppTableDataCxt, ctbCols);
8,046✔
3429
    } else {
3430
      code = initTableColSubmitData(*ppTableDataCxt);
1,149,295,999✔
3431
    }
3432
  }
3433
  if (code == TSDB_CODE_SUCCESS && pCxt->pComCxt->stmtBindVersion == 0) {
1,149,304,045✔
3434
    SRow** pRow = taosArrayReserve((*ppTableDataCxt)->pData->aRowP, 1);
1,149,295,999✔
3435
    if ((*ppTableDataCxt)->hasBlob) {
1,149,295,999✔
3436
      SRowBuildScanInfo sinfo = {.hasBlob = 1, .scanType = ROW_BUILD_UPDATE};
815✔
3437
      if ((*ppTableDataCxt)->pData->pBlobSet == NULL) {
815✔
3438
        code = tBlobSetCreate(1024, 0, &(*ppTableDataCxt)->pData->pBlobSet);
815✔
3439
        TAOS_CHECK_RETURN(code);
815✔
3440
      }
3441
      code = tRowBuildWithBlob(pStbRowsCxt->aColVals, (*ppTableDataCxt)->pSchema, pRow,
815✔
3442
                               (*ppTableDataCxt)->pData->pBlobSet, &sinfo);
815✔
3443
    } else {
3444
      SRowBuildScanInfo sinfo = {0};
1,149,295,184✔
3445
      code = tRowBuild(pStbRowsCxt->aColVals, (*ppTableDataCxt)->pSchema, pRow, &sinfo);
1,149,295,184✔
3446
    }
3447
    if (TSDB_CODE_SUCCESS == code) {
1,149,295,999✔
3448
      SRowKey key;
1,149,286,851✔
3449
      tRowGetKey(*pRow, &key);
2,147,483,647✔
3450
      insCheckTableDataOrder(*ppTableDataCxt, &key);
1,149,287,635✔
3451
    }
3452
  }
3453

3454
  if (code == TSDB_CODE_SUCCESS) {
1,149,304,045✔
3455
    *pGotRow = true;
1,149,295,681✔
3456
  }
3457

3458
  clearStbRowsDataContext(pStbRowsCxt);
1,149,304,045✔
3459

3460
  return code;
1,149,304,045✔
3461
}
3462

3463
static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow,
2,147,483,647✔
3464
                       SToken* pToken) {
3465
  SBoundColInfo*    pCols = &pTableCxt->boundColsInfo;
2,147,483,647✔
3466
  SSchema*          pSchemas = getTableColumnSchema(pTableCxt->pMeta);
2,147,483,647✔
3467
  const SSchemaExt* pExtSchemas = getTableColumnExtSchema(pTableCxt->pMeta);
2,147,483,647✔
3468

3469
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3470
  // 1. set the parsed value from sql string
3471
  for (int i = 0; i < pCols->numOfBound && TSDB_CODE_SUCCESS == code; ++i) {
2,147,483,647✔
3472
    const char* pOrigSql = *pSql;
2,147,483,647✔
3473
    bool        ignoreComma = false;
2,147,483,647✔
3474
    NEXT_TOKEN_WITH_PREV_EXT(*pSql, *pToken, &ignoreComma);
2,147,483,647✔
3475
    if (ignoreComma) {
2,147,483,647✔
3476
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pOrigSql);
96✔
3477
      break;
96✔
3478
    }
3479

3480
    SSchema*          pSchema = &pSchemas[pCols->pColIndex[i]];
2,147,483,647✔
3481
    const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i];
2,147,483,647✔
3482
    SColVal*          pVal = taosArrayGet(pTableCxt->pValues, pCols->pColIndex[i]);
2,147,483,647✔
3483

3484
    if (pToken->type == TK_NK_QUESTION) {
2,147,483,647✔
3485
      if (pCxt->pComCxt->stmtBindVersion == 0) {
22,807,262✔
3486
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pToken->z);
2,344✔
3487
        break;
2,344✔
3488
      }
3489
    } else {
3490
      if (TK_NK_RP == pToken->type) {
2,147,483,647✔
3491
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
1,506✔
3492
        break;
1,506✔
3493
      }
3494

3495
      if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3496
        code = parseValueToken(pCxt, pSql, pToken, pSchema, pExtSchema, getTableInfo(pTableCxt->pMeta).precision, pVal);
2,147,483,647✔
3497

3498
        if (TSDB_CODE_SUCCESS == code && pCxt->pComCxt->stmtBindVersion!=0) {
2,147,483,647✔
3499
          if (NULL == pCxt->pParsedValues) {
2,352✔
3500
            pCxt->pParsedValues =
1,764✔
3501
                tSimpleHashInit(pCols->numOfBound, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT));
1,764✔
3502
            if (NULL == pCxt->pParsedValues) {
1,764✔
UNCOV
3503
              code = terrno;
×
UNCOV
3504
              break;
×
3505
            }
3506
            tSimpleHashSetFreeFp(pCxt->pParsedValues, destroyColVal);
1,764✔
3507
          }
3508

3509
          SColVal clonedVal = *pVal;
2,352✔
3510
          if (COL_VAL_IS_VALUE(&clonedVal) && IS_VAR_DATA_TYPE(clonedVal.value.type)) {
2,352✔
3511
            clonedVal.value.pData = taosMemoryMalloc(clonedVal.value.nData);
980✔
3512
            if (NULL == clonedVal.value.pData) {
980✔
UNCOV
3513
              code = terrno;
×
UNCOV
3514
              break;
×
3515
            }
3516
            memcpy(clonedVal.value.pData, pVal->value.pData, clonedVal.value.nData);
980✔
3517
          }
3518

3519
          code = tSimpleHashPut(pCxt->pParsedValues, &pSchema->colId, sizeof(int16_t), &clonedVal, sizeof(SColVal));
2,352✔
3520
          if (code != TSDB_CODE_SUCCESS) {
2,352✔
UNCOV
3521
            if (COL_VAL_IS_VALUE(&clonedVal) && IS_VAR_DATA_TYPE(clonedVal.value.type)) {
×
UNCOV
3522
              taosMemoryFree(clonedVal.value.pData);
×
UNCOV
3523
              clonedVal.value.pData = NULL;
×
3524
            }
UNCOV
3525
            break;
×
3526
          }
3527
        }
3528
      }
3529
    }
3530

3531
    if (TSDB_CODE_SUCCESS == code && i < pCols->numOfBound - 1) {
2,147,483,647✔
3532
      NEXT_VALID_TOKEN(*pSql, *pToken);
2,147,483,647✔
3533
      if (TK_NK_COMMA != pToken->type) {
2,147,483,647✔
3534
        if (!pCxt->forceUpdate) {
4,288✔
3535
          code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
2,507✔
3536
          parserWarn("QID:0x%" PRIx64 ", column number is smaller than %d, need retry", pCxt->pComCxt->requestId,
2,507✔
3537
                     pCols->numOfBound);
3538
        } else {
3539
          code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
1,781✔
3540
        }
3541
      }
3542
    }
3543
  }
3544

3545
  if (TSDB_CODE_SUCCESS == code && pCxt->pComCxt->stmtBindVersion == 0) {
2,147,483,647✔
3546
    SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1);
2,147,483,647✔
3547
    if (pTableCxt->hasBlob) {
2,147,483,647✔
3548
      SRowBuildScanInfo sinfo = {.hasBlob = 1, .scanType = ROW_BUILD_UPDATE};
26,843,323✔
3549
      if (pTableCxt->pData->pBlobSet == NULL) {
26,843,323✔
3550
        code = tBlobSetCreate(1024, 0, &pTableCxt->pData->pBlobSet);
47,558✔
3551
        TAOS_CHECK_RETURN(code);
47,558✔
3552
      }
3553
      code = tRowBuildWithBlob(pTableCxt->pValues, pTableCxt->pSchema, pRow, pTableCxt->pData->pBlobSet, &sinfo);
26,843,323✔
3554
    } else {
3555
      SRowBuildScanInfo sinfo = {0};
2,147,483,647✔
3556
      code = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow, &sinfo);
2,147,483,647✔
3557
    }
3558
    if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3559
      SRowKey key;
2,147,483,647✔
3560
      tRowGetKey(*pRow, &key);
2,147,483,647✔
3561
      insCheckTableDataOrder(pTableCxt, &key);
2,147,483,647✔
3562
    }
3563
  }
3564

3565
  if (TSDB_CODE_SUCCESS == code && pCxt->pComCxt->stmtBindVersion == 0) {
2,147,483,647✔
3566
    *pGotRow = true;
2,147,483,647✔
3567
  }
3568

3569
  clearColValArray(pTableCxt->pValues);
2,147,483,647✔
3570

3571
  return code;
2,147,483,647✔
3572
}
3573

3574
// pSql -> (field1_value, ...) [(field1_value2, ...) ...]
3575
static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
731,159,882✔
3576
                           int32_t* pNumOfRows, SToken* pToken) {
3577
  int32_t code = TSDB_CODE_SUCCESS;
731,159,882✔
3578

3579
  (*pNumOfRows) = 0;
731,159,882✔
3580
  while (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3581
    int32_t index = 0;
2,147,483,647✔
3582
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, *pToken, index);
2,147,483,647✔
3583
    if (TK_NK_LP != pToken->type) {
2,147,483,647✔
3584
      break;
730,695,932✔
3585
    }
3586
    pStmt->pSql += index;
2,147,483,647✔
3587

3588
    bool gotRow = false;
2,147,483,647✔
3589
    if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3590
      if (!pStmt->stbSyntax) {
2,147,483,647✔
3591
        code = parseOneRow(pCxt, &pStmt->pSql, rowsDataCxt.pTableDataCxt, &gotRow, pToken);
2,147,483,647✔
3592
      } else {
3593
        // foreach subtable
3594
        STableDataCxt* pTableDataCxt = NULL;
10,374✔
3595
        code = parseOneStbRow(pCxt, pStmt, &pStmt->pSql, rowsDataCxt.pStbRowsCxt, &gotRow, pToken, &pTableDataCxt);
261,086✔
3596
      }
3597
    }
3598

3599
    if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3600
      NEXT_VALID_TOKEN(pStmt->pSql, *pToken);
2,147,483,647✔
3601
      if (TK_NK_COMMA == pToken->type) {
2,147,483,647✔
3602
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
9,566✔
3603
      } else if (TK_NK_RP != pToken->type) {
2,147,483,647✔
3604
        code = buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
19,460✔
3605
      }
3606
    }
3607

3608
    if (TSDB_CODE_SUCCESS == code && gotRow) {
2,147,483,647✔
3609
      (*pNumOfRows)++;
2,147,483,647✔
3610
    }
3611
  }
3612

3613
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) &&
569,494,039✔
3614
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
7,382,907✔
UNCOV
3615
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
3616
  }
3617
  return code;
731,186,619✔
3618
}
3619

3620
// VALUES (field1_value, ...) [(field1_value2, ...) ...]
3621
static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataContext,
731,191,795✔
3622
                                 SToken* pToken) {
3623
  int32_t numOfRows = 0;
731,191,795✔
3624
  int32_t code = parseValues(pCxt, pStmt, rowsDataContext, &numOfRows, pToken);
731,243,554✔
3625
  if (TSDB_CODE_SUCCESS == code) {
731,202,048✔
3626
    pStmt->totalRowsNum += numOfRows;
730,638,039✔
3627
    pStmt->totalTbNum += 1;
730,656,401✔
3628
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_INSERT);
730,640,330✔
3629
  }
3630
  return code;
731,243,090✔
3631
}
3632

3633
// Simplified CSV parser - only handles newlines within quotes
3634
static int32_t csvParserReadLine(SCsvParser* parser) {
2,147,483,647✔
3635
  if (!parser) {
2,147,483,647✔
UNCOV
3636
    return TSDB_CODE_INVALID_PARA;
×
3637
  }
3638

3639
  size_t  lineLen = 0;
2,147,483,647✔
3640
  bool    inQuotes = false;
2,147,483,647✔
3641
  char    currentQuote = '\0';  // Track which quote character we're inside
2,147,483,647✔
3642
  bool    fieldStart = true;    // Track if we're at the start of a field
2,147,483,647✔
3643
  bool    afterQuote = false;   // Track if we just closed a quoted field
2,147,483,647✔
3644
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3645

3646
  while (true) {
2,147,483,647✔
3647
    // Fill buffer if needed
3648
    if (parser->bufferPos >= parser->bufferLen) {
2,147,483,647✔
3649
      code = csvParserFillBuffer(parser);
23,955,387✔
3650
      if (code != TSDB_CODE_SUCCESS) {
23,955,387✔
UNCOV
3651
        break;
×
3652
      }
3653
      if (parser->bufferPos >= parser->bufferLen && parser->eof) {
23,955,387✔
3654
        // End of file
3655
        if (lineLen == 0) {
558,712✔
3656
          code = TSDB_CODE_TSC_QUERY_CANCELLED;  // Use this to indicate EOF
554,286✔
3657
        } else if (inQuotes) {
4,426✔
3658
          // Unclosed quote at end of file
UNCOV
3659
          code = TSDB_CODE_TSC_INVALID_INPUT;
×
3660
        }
3661
        break;
558,712✔
3662
      }
3663
    }
3664

3665
    char ch = parser->buffer[parser->bufferPos++];
2,147,483,647✔
3666

3667
    // Handle quotes - support both single and double quotes
3668
    if (!inQuotes && (ch == CSV_QUOTE_SINGLE || ch == CSV_QUOTE_DOUBLE)) {
2,147,483,647✔
3669
      // Quote can only start a field at the beginning of a field
3670
      if (!fieldStart) {
2,147,483,647✔
3671
        // Invalid: quote appears in the middle of an unquoted field
3672
        code = TSDB_CODE_TSC_INVALID_INPUT;
1,284✔
3673
        break;
1,284✔
3674
      }
3675
      // Starting a quoted section
3676
      inQuotes = true;
2,147,483,647✔
3677
      currentQuote = ch;
2,147,483,647✔
3678
      fieldStart = false;
2,147,483,647✔
3679
      afterQuote = false;
2,147,483,647✔
3680
    } else if (inQuotes && ch == currentQuote) {
2,147,483,647✔
3681
      // Check for escaped quote (double quote)
3682
      if (parser->bufferPos < parser->bufferLen && parser->buffer[parser->bufferPos] == currentQuote) {
2,147,483,647✔
3683
        // Escaped quote - keep both quotes in line for subsequent processing
3684
        // Ensure enough space for both quote characters
3685
        code = csvParserExpandLineBuffer(parser, lineLen + 2);
13,618✔
3686
        if (code != TSDB_CODE_SUCCESS) {
13,618✔
UNCOV
3687
          break;
×
3688
        }
3689

3690
        // Add the first quote character to the line
3691
        parser->lineBuffer[lineLen++] = ch;
13,618✔
3692

3693
        // Consume and add the second quote character
3694
        parser->bufferPos++;
13,618✔
3695
        ch = parser->buffer[parser->bufferPos - 1];  // The second quote
13,618✔
3696
        parser->lineBuffer[lineLen++] = ch;
13,618✔
3697
        continue;
13,618✔
3698
      } else {
3699
        // End of quoted section
3700
        inQuotes = false;
2,147,483,647✔
3701
        currentQuote = '\0';
2,147,483,647✔
3702
        afterQuote = true;  // Mark that we just closed a quote
2,147,483,647✔
3703
      }
3704
    } else if (ch == CSV_DEFAULT_DELIMITER && !inQuotes) {
2,147,483,647✔
3705
      // Comma marks the start of a new field
3706
      fieldStart = true;
2,147,483,647✔
3707
      afterQuote = false;
2,147,483,647✔
3708
    } else if (ch != '\r' && ch != '\n' && ch != ' ') {
2,147,483,647✔
3709
      // Non-space, non-newline character processing
3710
      // Check if we have invalid characters after closing quote
3711
      if (afterQuote) {
2,147,483,647✔
3712
        // Invalid: non-whitespace character after closing quote
3713
        // RFC 4180: after closing quote, only comma, space, or line end is allowed
UNCOV
3714
        code = TSDB_CODE_TSC_INVALID_INPUT;
×
UNCOV
3715
        break;
×
3716
      }
3717
      // Non-space character means we're no longer at field start
3718
      fieldStart = false;
2,147,483,647✔
3719
      afterQuote = false;
2,147,483,647✔
3720
    }
3721

3722
    // Handle newlines
3723
    if (ch == '\n' && !inQuotes) {
2,147,483,647✔
3724
      // End of line (not inside quotes)
3725
      break;
2,147,483,647✔
3726
    }
3727

3728
    // Skip \r characters only when outside quotes
3729
    if (ch == '\r' && !inQuotes) {
2,147,483,647✔
3730
      continue;
2,147,483,647✔
3731
    }
3732

3733
    // Expand buffer if needed
3734
    code = csvParserExpandLineBuffer(parser, lineLen + 1);
2,147,483,647✔
3735
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
UNCOV
3736
      break;
×
3737
    }
3738

3739
    // Add character to line
3740
    parser->lineBuffer[lineLen++] = ch;
2,147,483,647✔
3741
  }
3742

3743
  if (code == TSDB_CODE_SUCCESS) {
2,147,483,647✔
3744
    parser->lineBuffer[lineLen] = '\0';
2,147,483,647✔
3745
  } else if (code == TSDB_CODE_TSC_INVALID_INPUT) {
555,570✔
3746
    // Set a more descriptive error for invalid CSV format
3747
    parser->lineBuffer[lineLen] = '\0';  // Null-terminate for error reporting
1,284✔
3748
  }
3749

3750
  return code;
2,147,483,647✔
3751
}
3752

3753
static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
596,244✔
3754
                            int32_t* pNumOfRows) {
3755
  int32_t code = TSDB_CODE_SUCCESS;
596,244✔
3756
  (*pNumOfRows) = 0;
596,244✔
3757

3758
  // Initialize or use existing CSV parser in pStmt
3759
  if (pStmt->pCsvParser == NULL) {
596,244✔
3760
    // First time - allocate and initialize CSV parser
3761
    pStmt->pCsvParser = taosMemoryMalloc(sizeof(SCsvParser));
584,844✔
3762
    if (!pStmt->pCsvParser) {
584,844✔
UNCOV
3763
      return terrno;
×
3764
    }
3765
    code = csvParserInit(pStmt->pCsvParser, pStmt->fp);
584,844✔
3766
    if (code != TSDB_CODE_SUCCESS) {
584,844✔
UNCOV
3767
      taosMemoryFree(pStmt->pCsvParser);
×
UNCOV
3768
      pStmt->pCsvParser = NULL;
×
UNCOV
3769
      return code;
×
3770
    }
3771
  }
3772
  // If pStmt->pCsvParser exists, we continue from where we left off
3773

3774
  bool firstLine = (pStmt->fileProcessing == false);
596,244✔
3775
  pStmt->fileProcessing = false;
596,244✔
3776

3777
  while (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3778
    // Read one line from CSV using the parser in pStmt
3779
    code = csvParserReadLine(pStmt->pCsvParser);
2,147,483,647✔
3780
    if (code == TSDB_CODE_TSC_QUERY_CANCELLED) {
2,147,483,647✔
3781
      // End of file
3782
      code = TSDB_CODE_SUCCESS;
554,286✔
3783
      break;
554,286✔
3784
    }
3785
    if (code == TSDB_CODE_TSC_INVALID_INPUT) {
2,147,483,647✔
3786
      // Invalid CSV format detected
3787
      code = buildSyntaxErrMsg(&pCxt->msg, "Invalid CSV format", pStmt->pCsvParser->lineBuffer);
1,284✔
3788
      break;
1,284✔
3789
    }
3790
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
UNCOV
3791
      break;
×
3792
    }
3793

3794
    // Skip empty lines
3795
    if (!pStmt->pCsvParser->lineBuffer || strlen(pStmt->pCsvParser->lineBuffer) == 0) {
2,147,483,647✔
UNCOV
3796
      firstLine = false;
×
UNCOV
3797
      continue;
×
3798
    }
3799

3800
    bool   gotRow = false;
2,147,483,647✔
3801
    SToken token;
2,147,483,647✔
3802
    (void)strtolower(pStmt->pCsvParser->lineBuffer, pStmt->pCsvParser->lineBuffer);
2,147,483,647✔
3803
    const char* pRow = pStmt->pCsvParser->lineBuffer;
2,147,483,647✔
3804

3805
    if (!pStmt->stbSyntax) {
2,147,483,647✔
3806
      code = parseOneRow(pCxt, (const char**)&pRow, rowsDataCxt.pTableDataCxt, &gotRow, &token);
2,147,483,647✔
3807
    } else {
3808
      STableDataCxt* pTableDataCxt = NULL;
1,149,054,087✔
3809
      code = parseOneStbRow(pCxt, pStmt, (const char**)&pRow, rowsDataCxt.pStbRowsCxt, &gotRow, &token, &pTableDataCxt);
1,149,054,087✔
3810
      if (code == TSDB_CODE_SUCCESS) {
1,149,054,087✔
3811
        SStbRowsDataContext* pStbRowsCxt = rowsDataCxt.pStbRowsCxt;
1,149,050,727✔
3812
        void*                pData = pTableDataCxt;
1,149,050,727✔
3813
        code = taosHashPut(pStmt->pTableCxtHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid),
1,149,050,727✔
3814
                           &pData, POINTER_BYTES);
3815
        if (TSDB_CODE_SUCCESS != code) {
1,149,050,727✔
UNCOV
3816
          break;
×
3817
        }
3818
      }
3819
    }
3820

3821
    if (code && firstLine) {
2,147,483,647✔
3822
      firstLine = false;
561,030✔
3823
      code = 0;
561,030✔
3824
      continue;
561,030✔
3825
    }
3826

3827
    if (TSDB_CODE_SUCCESS == code && gotRow) {
2,147,483,647✔
3828
      (*pNumOfRows)++;
2,147,483,647✔
3829
    }
3830

3831
    if (TSDB_CODE_SUCCESS == code && (*pNumOfRows) >= tsMaxInsertBatchRows) {
2,147,483,647✔
3832
      // Reached batch limit - keep the parser in pStmt for next batch
3833
      pStmt->fileProcessing = true;
11,400✔
3834
      break;
11,400✔
3835
    }
3836
    firstLine = false;
2,147,483,647✔
3837
  }
3838

3839
  // Don't destroy the parser here - it will be cleaned up when file processing is complete
3840

3841
  parserDebug("QID:0x%" PRIx64 ", %d rows have been parsed", pCxt->pComCxt->requestId, *pNumOfRows);
596,244✔
3842

3843
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) && 0 == pStmt->totalRowsNum &&
596,244✔
UNCOV
3844
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) && !pStmt->fileProcessing) {
×
UNCOV
3845
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
3846
  }
3847
  return code;
596,244✔
3848
}
3849

3850
static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
596,244✔
3851
                                     SRowsDataContext rowsDataCxt) {
3852
  // init only for file
3853
  if (NULL == pStmt->pTableCxtHashObj) {
596,244✔
3854
    pStmt->pTableCxtHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
570,230✔
3855
    if (!pStmt->pTableCxtHashObj) {
570,230✔
UNCOV
3856
      return terrno;
×
3857
    }
3858
  }
3859
  int32_t numOfRows = 0;
596,244✔
3860
  int32_t code = parseCsvFile(pCxt, pStmt, rowsDataCxt, &numOfRows);
596,244✔
3861
  if (TSDB_CODE_SUCCESS == code) {
596,244✔
3862
    pStmt->totalRowsNum += numOfRows;
565,686✔
3863
    pStmt->totalTbNum += 1;
565,686✔
3864
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT);
565,686✔
3865
    if (rowsDataCxt.pTableDataCxt && rowsDataCxt.pTableDataCxt->pData) {
565,686✔
3866
      rowsDataCxt.pTableDataCxt->pData->flags |= SUBMIT_REQ_FROM_FILE;
558,868✔
3867
    }
3868
    if (!pStmt->fileProcessing) {
565,686✔
3869
      // File processing is complete, clean up saved CSV parser
3870
      destroySavedCsvParser(pStmt);
554,286✔
3871
      code = taosCloseFile(&pStmt->fp);
554,286✔
3872
      if (TSDB_CODE_SUCCESS != code) {
554,286✔
UNCOV
3873
        parserWarn("QID:0x%" PRIx64 ", failed to close file.", pCxt->pComCxt->requestId);
×
3874
      }
3875
    } else {
3876
      parserDebug("QID:0x%" PRIx64 ", insert from csv. File is too large, do it in batches.", pCxt->pComCxt->requestId);
11,400✔
3877
    }
3878
    if (pStmt->insertType != TSDB_QUERY_TYPE_FILE_INSERT) {
565,686✔
UNCOV
3879
      destroySavedCsvParser(pStmt);
×
UNCOV
3880
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", NULL);
×
3881
    }
3882
  } else {
3883
    // On error, also clean up saved CSV parser
3884
    destroySavedCsvParser(pStmt);
30,558✔
3885
    if (code == TSDB_CODE_TSC_SQL_SYNTAX_ERROR) {
30,558✔
3886
      return code;
13,830✔
3887
    }
3888
    return buildInvalidOperationMsg(&pCxt->msg, tstrerror(code));
16,728✔
3889
  }
3890

3891
  // just record pTableCxt whose data come from file
3892
  if (!pStmt->stbSyntax && numOfRows > 0) {
565,686✔
3893
    void* pData = rowsDataCxt.pTableDataCxt;
553,738✔
3894
    code = taosHashPut(pStmt->pTableCxtHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid), &pData,
553,738✔
3895
                       POINTER_BYTES);
3896
  }
3897

3898
  return code;
565,686✔
3899
}
3900

3901
static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pFilePath,
584,844✔
3902
                                 SRowsDataContext rowsDataCxt) {
3903
  char filePathStr[PATH_MAX + 16] = {0};
584,844✔
3904
  if (TK_NK_STRING == pFilePath->type) {
584,844✔
3905
    (void)trimString(pFilePath->z, pFilePath->n, filePathStr, sizeof(filePathStr));
584,796✔
3906
    if (strlen(filePathStr) >= PATH_MAX) {
584,796✔
UNCOV
3907
      return buildSyntaxErrMsg(&pCxt->msg, "file path is too long, max length is 4096", pFilePath->z);
×
3908
    }
3909
  } else {
3910
    if (pFilePath->n >= PATH_MAX) {
48✔
UNCOV
3911
      return buildSyntaxErrMsg(&pCxt->msg, "file path is too long, max length is 4096", pFilePath->z);
×
3912
    }
3913
    tstrncpy(filePathStr, pFilePath->z, pFilePath->n < sizeof(filePathStr) ? pFilePath->n + 1 : sizeof(filePathStr));
48✔
3914
  }
3915
  pStmt->fp = taosOpenFile(filePathStr, TD_FILE_READ);
584,844✔
3916
  if (NULL == pStmt->fp) {
584,844✔
UNCOV
3917
    return terrno;
×
3918
  }
3919

3920
  return parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
584,844✔
3921
}
3922

3923
static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
584,844✔
3924
                               SToken* pToken) {
3925
  if (tsUseAdapter) {
584,844✔
UNCOV
3926
    return buildInvalidOperationMsg(&pCxt->msg, "proxy mode does not support csv loading");
×
3927
  }
3928

3929
  NEXT_TOKEN(pStmt->pSql, *pToken);
584,844✔
3930
  if (0 == pToken->n || (TK_NK_STRING != pToken->type && TK_NK_ID != pToken->type)) {
584,844✔
UNCOV
3931
    return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", pToken->z);
×
3932
  }
3933
  return parseDataFromFile(pCxt, pStmt, pToken, rowsDataCxt);
584,844✔
3934
}
3935

3936
// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
3937
static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt) {
731,741,837✔
3938
  SToken token;
727,718,499✔
3939
  NEXT_TOKEN(pStmt->pSql, token);
731,806,973✔
3940
  switch (token.type) {
731,839,965✔
3941
    case TK_VALUES:
731,255,121✔
3942
      if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT)) {
731,255,121✔
3943
        return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", token.z);
570✔
3944
      }
3945
      return parseValuesClause(pCxt, pStmt, rowsDataCxt, &token);
731,244,911✔
3946
    case TK_FILE:
584,844✔
3947
      return parseFileClause(pCxt, pStmt, rowsDataCxt, &token);
584,844✔
UNCOV
3948
    default:
×
UNCOV
3949
      break;
×
3950
  }
UNCOV
3951
  return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
×
3952
}
3953

3954
static void destroyStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
1,357,350,858✔
3955
  if (pStbRowsCxt == NULL) return;
1,357,350,858✔
3956
  clearStbRowsDataContext(pStbRowsCxt);
191,135✔
3957
  taosArrayDestroy(pStbRowsCxt->aColVals);
234,536✔
3958
  pStbRowsCxt->aColVals = NULL;
234,536✔
3959
  taosArrayDestroy(pStbRowsCxt->aTagVals);
234,536✔
3960
  pStbRowsCxt->aTagVals = NULL;
234,536✔
3961
  taosArrayDestroy(pStbRowsCxt->aTagNames);
234,536✔
3962
  pStbRowsCxt->aTagNames = NULL;
234,536✔
3963
  qDestroyBoundColInfo(&pStbRowsCxt->boundColsInfo);
234,536✔
3964
  tTagFree(pStbRowsCxt->pTag);
234,536✔
3965
  pStbRowsCxt->pTag = NULL;
234,536✔
3966
  taosMemoryFreeClear(pStbRowsCxt->pCtbMeta);
234,536✔
3967
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
234,536✔
3968
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
234,536✔
3969
}
3970

3971
static int32_t constructStbRowsDataContext(SVnodeModifyOpStmt* pStmt, SStbRowsDataContext** ppStbRowsCxt) {
234,732✔
3972
  SStbRowsDataContext* pStbRowsCxt = taosMemoryCalloc(1, sizeof(SStbRowsDataContext));
234,732✔
3973
  if (!pStbRowsCxt) {
234,732✔
UNCOV
3974
    return terrno;
×
3975
  }
3976
  tNameAssign(&pStbRowsCxt->stbName, &pStmt->targetTableName);
234,732✔
3977
  int32_t code = collectUseTable(&pStbRowsCxt->stbName, pStmt->pTableNameHashObj);
234,732✔
3978
  if (TSDB_CODE_SUCCESS == code) {
234,732✔
3979
    code = collectUseDatabase(&pStbRowsCxt->stbName, pStmt->pDbFNameHashObj);
234,732✔
3980
  }
3981
  if (TSDB_CODE_SUCCESS == code) {
234,732✔
3982
    pStbRowsCxt->ctbName.type = TSDB_TABLE_NAME_T;
234,732✔
3983
    pStbRowsCxt->ctbName.acctId = pStbRowsCxt->stbName.acctId;
234,732✔
3984
    memcpy(pStbRowsCxt->ctbName.dbname, pStbRowsCxt->stbName.dbname, sizeof(pStbRowsCxt->stbName.dbname));
234,732✔
3985

3986
    pStbRowsCxt->pTagCond = pStmt->pTagCond;
234,732✔
3987
    pStbRowsCxt->pStbMeta = pStmt->pTableMeta;
234,732✔
3988

3989
    code = cloneTableMeta(pStbRowsCxt->pStbMeta, &pStbRowsCxt->pCtbMeta);
234,732✔
3990
  }
3991
  if (TSDB_CODE_SUCCESS == code) {
234,732✔
3992
    pStbRowsCxt->pCtbMeta->tableType = TSDB_CHILD_TABLE;
234,732✔
3993
    pStbRowsCxt->pCtbMeta->suid = pStbRowsCxt->pStbMeta->uid;
234,732✔
3994

3995
    pStbRowsCxt->aTagNames = taosArrayInit(8, TSDB_COL_NAME_LEN);
234,732✔
3996
    if (!pStbRowsCxt->aTagNames) {
234,732✔
UNCOV
3997
      code = terrno;
×
3998
    }
3999
  }
4000
  if (TSDB_CODE_SUCCESS == code) {
234,732✔
4001
    pStbRowsCxt->aTagVals = taosArrayInit(8, sizeof(STagVal));
234,732✔
4002
    if (!pStbRowsCxt->aTagVals) {
234,732✔
UNCOV
4003
      code = terrno;
×
4004
    }
4005
  }
4006
  if (TSDB_CODE_SUCCESS == code) {
234,732✔
4007
    // col values and bound cols info of STableDataContext is not used
4008
    pStbRowsCxt->aColVals = taosArrayInit(getNumOfColumns(pStbRowsCxt->pStbMeta), sizeof(SColVal));
234,732✔
4009
    if (!pStbRowsCxt->aColVals) code = terrno;
234,732✔
4010
  }
4011
  if (TSDB_CODE_SUCCESS == code) {
234,732✔
4012
    code = insInitColValues(pStbRowsCxt->pStbMeta, pStbRowsCxt->aColVals);
234,732✔
4013
  }
4014
  if (TSDB_CODE_SUCCESS == code) {
234,732✔
4015
    STableComInfo tblInfo = getTableInfo(pStmt->pTableMeta);
234,732✔
4016
    code = insInitBoundColsInfo(tblInfo.numOfColumns + tblInfo.numOfTags + 1, &pStbRowsCxt->boundColsInfo);
234,732✔
4017
  }
4018
  if (TSDB_CODE_SUCCESS == code) {
234,732✔
4019
    *ppStbRowsCxt = pStbRowsCxt;
234,732✔
4020
  } else {
UNCOV
4021
    clearStbRowsDataContext(pStbRowsCxt);
×
4022
  }
4023
  return code;
234,732✔
4024
}
4025

4026
static int32_t parseInsertStbClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
276,194✔
4027
  int32_t code = TSDB_CODE_SUCCESS;
276,194✔
4028
  if (!pStmt->pBoundCols) {
276,194✔
4029
    return buildSyntaxErrMsg(&pCxt->msg, "(...tbname, ts...) bounded cols is expected for supertable insertion",
41,462✔
4030
                             pStmt->pSql);
4031
  }
4032

4033
  SStbRowsDataContext* pStbRowsCxt = NULL;
234,732✔
4034
  code = constructStbRowsDataContext(pStmt, &pStbRowsCxt);
234,732✔
4035

4036
  if (code == TSDB_CODE_SUCCESS) {
234,732✔
4037
    code = parseBoundColumns(pCxt, pStmt, &pStmt->pBoundCols, BOUND_ALL_AND_TBNAME, pStmt->pTableMeta,
234,732✔
4038
                             &pStbRowsCxt->boundColsInfo);
234,732✔
4039
    pStbRowsCxt->hasTimestampTag = false;
234,732✔
4040
    for (int32_t i = 0; i < pStbRowsCxt->boundColsInfo.numOfBound; ++i) {
1,246,196✔
4041
      int16_t schemaIndex = pStbRowsCxt->boundColsInfo.pColIndex[i];
1,011,464✔
4042
      if (schemaIndex != getTbnameSchemaIndex(pStmt->pTableMeta) && schemaIndex >= getNumOfColumns(pStmt->pTableMeta)) {
1,011,464✔
4043
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_TIMESTAMP) {
139,527✔
4044
          pStbRowsCxt->hasTimestampTag = true;
588✔
4045
        }
4046
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_JSON) {
139,527✔
UNCOV
4047
          pStbRowsCxt->isJsonTag = true;
×
4048
        }
4049
      }
4050
    }
4051
    pStmt->pStbRowsCxt = pStbRowsCxt;
234,732✔
4052
  }
4053

4054
  if (code == TSDB_CODE_SUCCESS) {
234,732✔
4055
    SRowsDataContext rowsDataCxt;
4056
    rowsDataCxt.pStbRowsCxt = pStbRowsCxt;
221,739✔
4057
    code = parseDataClause(pCxt, pStmt, rowsDataCxt);
221,739✔
4058
  }
4059

4060
  return code;
234,732✔
4061
}
4062

4063
// input pStmt->pSql:
4064
//   1. [(tag1_name, ...)] ...
4065
//   2. VALUES ... | FILE ...
4066
static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
732,131,310✔
4067
  if (!pStmt->stbSyntax) {
732,131,310✔
4068
    STableDataCxt*   pTableCxt = NULL;
731,909,105✔
4069
    int32_t          code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt);
731,874,468✔
4070
    SRowsDataContext rowsDataCxt;
4071
    rowsDataCxt.pTableDataCxt = pTableCxt;
731,837,392✔
4072
    if (TSDB_CODE_SUCCESS == code) {
731,837,392✔
4073
      code = parseDataClause(pCxt, pStmt, rowsDataCxt);
731,559,599✔
4074
    }
4075
    return code;
731,816,573✔
4076
  } else {
4077
    int32_t code = parseInsertStbClauseBottom(pCxt, pStmt);
258,151✔
4078
    return code;
276,194✔
4079
  }
4080
}
4081

4082
static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
732,442,848✔
4083
  qDestroyBoundColInfo(&pCxt->tags);
732,442,848✔
4084
  clearInsertParseContext(pCxt);
732,476,356✔
4085
  taosMemoryFreeClear(pStmt->pTableMeta);
732,449,322✔
4086
  if (pStmt->pTagCond) nodesDestroyNode(pStmt->pTagCond);
732,464,813✔
4087
  if (pStmt->pPrivCols) taosArrayDestroy(pStmt->pPrivCols);
732,469,502✔
4088
  if (pStmt->pTableTag) taosArrayDestroy(pStmt->pTableTag);
732,486,536✔
4089
  tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
732,445,231✔
4090
  taosMemoryFreeClear(pStmt->pCreateTblReq);
732,467,596✔
4091
  pCxt->missCache = false;
732,484,048✔
4092
  pCxt->usingDuplicateTable = false;
732,471,217✔
4093
  pStmt->pBoundCols = NULL;
732,481,444✔
4094
  pStmt->pPrivCols = NULL;
732,445,403✔
4095
  pStmt->pTagCond = NULL;
732,511,098✔
4096
  pStmt->usingTableProcessing = false;
732,470,238✔
4097
  pStmt->fileProcessing = false;
732,490,976✔
4098
  pStmt->usingTableName.type = 0;
732,442,435✔
4099

4100
  destroyStbRowsDataContext(pStmt->pStbRowsCxt);
732,511,783✔
4101
  taosMemoryFreeClear(pStmt->pStbRowsCxt);
732,423,437✔
4102
  pStmt->stbSyntax = false;
732,433,827✔
4103
}
732,476,601✔
4104

4105
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
4106
static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
732,443,417✔
4107
  resetEnvPreTable(pCxt, pStmt);
732,443,417✔
4108
  int32_t code = parseSchemaClauseTop(pCxt, pStmt, pTbName);
732,466,568✔
4109
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
732,379,538✔
4110
    code = parseInsertTableClauseBottom(pCxt, pStmt);
724,602,598✔
4111
  }
4112

4113
  return code;
732,395,469✔
4114
}
4115

4116
static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName,
1,356,239,262✔
4117
                                          bool* pHasData) {
4118
  // no data in the sql string anymore.
4119
  if (0 == pTbName->n) {
1,356,239,262✔
4120
    if (0 != pTbName->type && '\0' != pStmt->pSql[0]) {
623,792,334✔
UNCOV
4121
      return buildSyntaxErrMsg(&pCxt->msg, "invalid table name", pTbName->z);
×
4122
    }
4123

4124
    if (0 == pStmt->totalRowsNum && (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
623,730,480✔
UNCOV
4125
      return buildInvalidOperationMsg(&pCxt->msg, "no data in sql");
×
4126
    }
4127

4128
    *pHasData = false;
623,702,098✔
4129
    return TSDB_CODE_SUCCESS;
623,694,825✔
4130
  }
4131

4132
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT) && pStmt->totalTbNum > 0) {
732,500,146✔
UNCOV
4133
    return buildInvalidOperationMsg(&pCxt->msg, "single table allowed in one stmt");
×
4134
  }
4135

4136
  if (TK_NK_QUESTION == pTbName->type) {
732,487,957✔
4137
    pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
7,239,837✔
4138
    if (pCxt->pComCxt->stmtBindVersion == 0) {
7,238,772✔
UNCOV
4139
      return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
4140
    }
4141

4142
    char*   tbName = NULL;
7,237,671✔
4143
    int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
7,239,127✔
4144
    if (TSDB_CODE_SUCCESS == code) {
7,239,879✔
4145
      pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
7,238,099✔
4146
      pTbName->z = tbName;
7,237,401✔
4147
      pTbName->n = strlen(tbName);
7,237,702✔
4148
    }
4149
    if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
7,239,127✔
4150
      pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
1,780✔
4151
      code = TSDB_CODE_SUCCESS;
1,780✔
4152
    }
4153
    return code;
7,238,417✔
4154
  }
4155

4156
  if (TK_NK_ID != pTbName->type && TK_NK_STRING != pTbName->type && TK_NK_QUESTION != pTbName->type) {
725,206,839✔
4157
    return buildSyntaxErrMsg(&pCxt->msg, "table_name is expected", pTbName->z);
196✔
4158
  }
4159

4160
  // db.? situation,ensure that the only thing following the '.' mark is '?'
4161
  char* tbNameAfterDbName = strnchr(pTbName->z, '.', pTbName->n, true);
725,243,545✔
4162
  if (tbNameAfterDbName != NULL) {
725,199,412✔
4163
    if (*(tbNameAfterDbName + 1) == '?') {
210,565,304✔
4164
      pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
11,760✔
4165
      char* tbName = NULL;
11,760✔
4166
      if (NULL == pCxt->pComCxt->pStmtCb) {
11,760✔
UNCOV
4167
        return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
4168
      }
4169
      int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
11,760✔
4170
      if (TSDB_CODE_SUCCESS == code) {
11,760✔
4171
        pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
7,252✔
4172
        pTbName->z = tbName;
7,252✔
4173
        pTbName->n = strlen(tbName);
7,252✔
4174
      }
4175
      if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
11,760✔
4176
        pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
4,508✔
4177
        code = TSDB_CODE_SUCCESS;
4,508✔
4178
      }
4179
    } else {
4180
      pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
210,550,794✔
4181
      parserTrace("QID:0x%" PRIx64 ", stmt tbname:%s is specified in sql", pCxt->pComCxt->requestId, pTbName->z);
210,554,077✔
4182
      *pHasData = true;
210,554,089✔
4183
    }
4184
    return TSDB_CODE_SUCCESS;
210,568,164✔
4185
  }
4186

4187
  if (TK_NK_ID == pTbName->type) {
514,634,108✔
4188
    pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
511,149,146✔
4189
  }
4190

4191
  *pHasData = true;
514,704,535✔
4192
  return TSDB_CODE_SUCCESS;
514,701,269✔
4193
}
4194

4195
static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
7,385,364✔
4196
  SBoundColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags));
7,385,364✔
4197
  if (NULL == tags) {
7,384,407✔
UNCOV
4198
    return terrno;
×
4199
  }
4200
  memcpy(tags, &pCxt->tags, sizeof(pCxt->tags));
7,384,407✔
4201

4202
  SStmtCallback* pStmtCb = pCxt->pComCxt->pStmtCb;
7,386,566✔
4203
  int32_t        code = (*pStmtCb->setInfoFn)(pStmtCb->pStmt, pStmt->pTableMeta, tags, &pCxt->pParsedValues,
22,063,672✔
4204
                                       &pStmt->targetTableName, pStmt->usingTableProcessing, pStmt->pVgroupsHashObj,
7,390,373✔
4205
                                       pStmt->pTableBlockHashObj, pStmt->usingTableName.tname, pCxt->stmtTbNameFlag);
7,385,065✔
4206

4207
  memset(&pCxt->tags, 0, sizeof(pCxt->tags));
7,364,311✔
4208
  pStmt->pVgroupsHashObj = NULL;
7,363,932✔
4209
  pStmt->pTableBlockHashObj = NULL;
7,380,026✔
4210
  return code;
7,384,711✔
4211
}
4212

4213
static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
623,697,217✔
4214
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) {
623,697,217✔
4215
    return setStmtInfo(pCxt, pStmt);
7,386,818✔
4216
  }
4217

4218
  // release old array alloced by merge
4219
  pStmt->freeArrayFunc(pStmt->pVgDataBlocks);
616,338,992✔
4220
  pStmt->pVgDataBlocks = NULL;
616,324,549✔
4221

4222
  bool fileOnly = (pStmt->insertType == TSDB_QUERY_TYPE_FILE_INSERT);
616,336,059✔
4223
  if (fileOnly) {
616,328,861✔
4224
    // none data, skip merge & buildvgdata
4225
    if (0 == taosHashGetSize(pStmt->pTableCxtHashObj)) {
550,502✔
4226
      pCxt->needRequest = false;
5,700✔
4227
      return TSDB_CODE_SUCCESS;
5,700✔
4228
    }
4229
  }
4230

4231
  // merge according to vgId
4232
  int32_t code = insMergeTableDataCxt(fileOnly ? pStmt->pTableCxtHashObj : pStmt->pTableBlockHashObj,
616,338,557✔
4233
                                      &pStmt->pVgDataBlocks, pStmt->fileProcessing);
616,323,161✔
4234
  // clear tmp hashobj only
4235
  taosHashClear(pStmt->pTableCxtHashObj);
616,387,583✔
4236

4237
  if (TSDB_CODE_SUCCESS == code) {
616,379,272✔
4238
    code = insBuildVgDataBlocks(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks, false);
616,395,017✔
4239
  }
4240

4241
  return code;
616,390,358✔
4242
}
4243

4244
// tb_name
4245
//     [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
4246
//     [(field1_name, ...)]
4247
//     VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
4248
// [...];
4249
static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
632,187,212✔
4250
  SToken  token;
629,592,878✔
4251
  int32_t code = TSDB_CODE_SUCCESS;
632,206,004✔
4252
  bool    hasData = true;
632,206,004✔
4253
  // for each table
4254
  while (TSDB_CODE_SUCCESS == code && hasData && !pCxt->missCache && !pStmt->fileProcessing) {
1,988,422,407✔
4255
    // pStmt->pSql -> tb_name ...
4256
    NEXT_TOKEN(pStmt->pSql, token);
1,356,161,251✔
4257
    code = checkTableClauseFirstToken(pCxt, pStmt, &token, &hasData);
1,356,302,144✔
4258
    if (TSDB_CODE_SUCCESS == code && hasData) {
1,356,156,666✔
4259
      code = parseInsertTableClause(pCxt, pStmt, &token);
732,497,866✔
4260
    }
4261

4262
    if (TSDB_CODE_SUCCESS == code && pStmt->pTableMeta &&
1,356,047,418✔
4263
        (((pStmt->pTableMeta->virtualStb == 1) && (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE)) ||
1,353,833,326✔
4264
         (pStmt->pTableMeta->tableType == TSDB_VIRTUAL_NORMAL_TABLE ||
1,353,855,560✔
4265
          pStmt->pTableMeta->tableType == TSDB_VIRTUAL_CHILD_TABLE))) {
1,353,833,258✔
4266
      code = buildInvalidOperationMsg(&pCxt->msg, "Virtual table can not be written");
8,425✔
4267
    }
4268
  }
4269

4270
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
632,266,813✔
4271
    code = parseInsertBodyBottom(pCxt, pStmt);
623,754,316✔
4272
  }
4273
  return code;
632,251,430✔
4274
}
4275

4276
static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); }
37,522,483✔
4277

4278
static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, SNode** pOutput) {
625,023,785✔
4279
  SVnodeModifyOpStmt* pStmt = NULL;
625,023,785✔
4280
  int32_t             code = nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT, (SNode**)&pStmt);
625,038,872✔
4281
  if (NULL == pStmt) {
625,064,658✔
UNCOV
4282
    return code;
×
4283
  }
4284

4285
  if (pCxt->pComCxt->pStmtCb) {
625,064,658✔
4286
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT);
7,400,166✔
4287
  }
4288
  pStmt->pSql = pCxt->pComCxt->pSql;
625,065,074✔
4289

4290
  pStmt->freeHashFunc = insDestroyTableDataCxtHashMap;
625,048,341✔
4291
  pStmt->freeArrayFunc = insDestroyVgroupDataCxtList;
625,067,194✔
4292
  pStmt->freeStbRowsCxtFunc = destroyStbRowsDataContext;
625,043,760✔
4293
  pStmt->pCsvParser = NULL;
625,046,902✔
4294

4295
  if (!reentry) {
625,034,911✔
4296
    pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
625,051,692✔
4297
    if (pCxt->pComCxt->pStmtCb) {
625,015,822✔
4298
      pStmt->pTableBlockHashObj =
7,396,257✔
4299
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
7,394,024✔
4300
    } else {
4301
      pStmt->pTableBlockHashObj =
617,668,790✔
4302
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
617,601,019✔
4303
    }
4304
  }
4305
  pStmt->pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
625,047,131✔
4306
  pStmt->pSuperTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
625,065,419✔
4307
  pStmt->pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
625,067,663✔
4308
  pStmt->pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
625,070,202✔
4309
  if ((!reentry && (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj)) ||
625,066,146✔
4310
      NULL == pStmt->pSubTableHashObj || NULL == pStmt->pTableNameHashObj || NULL == pStmt->pDbFNameHashObj) {
625,052,110✔
UNCOV
4311
    nodesDestroyNode((SNode*)pStmt);
×
UNCOV
4312
    return TSDB_CODE_OUT_OF_MEMORY;
×
4313
  }
4314

4315
  taosHashSetFreeFp(pStmt->pSubTableHashObj, destroySubTableHashElem);
625,068,018✔
4316
  taosHashSetFreeFp(pStmt->pSuperTableHashObj, destroySubTableHashElem);
625,048,774✔
4317

4318
  *pOutput = (SNode*)pStmt;
625,040,880✔
4319
  return TSDB_CODE_SUCCESS;
625,052,786✔
4320
}
4321

4322
static int32_t createInsertQuery(SInsertParseContext* pCxt, SQuery** pOutput) {
625,014,466✔
4323
  SQuery* pQuery = NULL;
625,014,466✔
4324
  int32_t code = nodesMakeNode(QUERY_NODE_QUERY, (SNode**)&pQuery);
625,019,963✔
4325
  if (NULL == pQuery) {
625,041,329✔
UNCOV
4326
    return code;
×
4327
  }
4328

4329
  pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
625,041,329✔
4330
  pQuery->haveResultSet = false;
625,051,364✔
4331
  pQuery->msgType = TDMT_VND_SUBMIT;
625,045,510✔
4332

4333
  code = createVnodeModifOpStmt(pCxt, false, &pQuery->pRoot);
625,047,249✔
4334
  if (TSDB_CODE_SUCCESS == code) {
625,045,921✔
4335
    *pOutput = pQuery;
625,045,921✔
4336
  } else {
UNCOV
4337
    nodesDestroyNode((SNode*)pQuery);
×
4338
  }
4339
  return code;
625,049,467✔
4340
}
4341

4342
static int32_t checkAuthFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData, SVnodeModifyOpStmt* pStmt) {
7,736,918✔
4343
  int32_t code = TSDB_CODE_SUCCESS;
7,736,918✔
4344
  if (1 != taosArrayGetSize(pMetaData->pUser)) {
7,736,918✔
UNCOV
4345
    code = TSDB_CODE_INTERNAL_ERROR;
×
UNCOV
4346
    uError("unexpected meta data size: %d since %s", (int32_t)taosArrayGetSize(pMetaData->pUser), tstrerror(code));
×
UNCOV
4347
    return code;
×
4348
  }
4349

4350
  SMetaRes* pRes = TARRAY_GET_ELEM(pMetaData->pUser, 0);
7,736,918✔
4351
  if (TSDB_CODE_SUCCESS == pRes->code) {
7,736,918✔
4352
    SUserAuthRes* pAuth = pRes->pRes;
7,736,548✔
4353
    pRes->code = nodesCloneNode(pAuth->pCond[AUTH_RES_BASIC], &pStmt->pTagCond);
7,736,548✔
4354
    if (pAuth->pCols && (TSDB_CODE_SUCCESS == pRes->code)) {
7,736,548✔
4355
      if (!(pStmt->pPrivCols = taosArrayDup(pAuth->pCols, NULL))) {
4,023✔
UNCOV
4356
        pRes->code = terrno;
×
4357
      }
4358
    }
4359
    if (TSDB_CODE_SUCCESS == pRes->code) {
7,736,548✔
4360
      return pAuth->pass[AUTH_RES_BASIC] ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED;
7,736,548✔
4361
    }
4362
  }
4363
  return pRes->code;
370✔
4364
}
4365

4366
static int32_t getTableMetaFromMetaData(const SArray* pTables, STableMeta** pMeta) {
7,725,310✔
4367
  if (1 != taosArrayGetSize(pTables) && 2 != taosArrayGetSize(pTables)) {
7,725,310✔
UNCOV
4368
    return TSDB_CODE_FAILED;
×
4369
  }
4370

4371
  taosMemoryFreeClear(*pMeta);
7,725,310✔
4372
  SMetaRes* pRes = taosArrayGet(pTables, 0);
7,725,310✔
4373
  if (TSDB_CODE_SUCCESS == pRes->code) {
7,725,310✔
4374
    *pMeta = tableMetaDup((const STableMeta*)pRes->pRes);
7,583,948✔
4375
    if (NULL == *pMeta) {
7,583,948✔
UNCOV
4376
      return TSDB_CODE_OUT_OF_MEMORY;
×
4377
    }
4378
  }
4379
  return pRes->code;
7,725,310✔
4380
}
4381

4382
static int32_t checkAuthUseDb(SParseContext* pCxt, SName* pTbName, bool isAudit) {
7,583,948✔
4383
  int32_t       code = TSDB_CODE_SUCCESS;
7,583,948✔
4384
  SUserAuthInfo authInfo = {.userId = pCxt->userId, .privType = PRIV_DB_USE, .objType = PRIV_OBJ_DB};
7,583,948✔
4385
  (void)snprintf(authInfo.user, sizeof(authInfo.user), "%s", pCxt->pUser);
7,583,948✔
4386
  (void)snprintf(authInfo.tbName.dbname, sizeof(authInfo.tbName.dbname), "%s", pTbName->dbname);
7,583,948✔
4387
  authInfo.tbName.acctId = pTbName->acctId;
7,583,948✔
4388
  authInfo.tbName.type = TSDB_DB_NAME_T;
7,583,948✔
4389
  authInfo.useDb = isAudit ? AUTH_OWNED_MASK : (AUTH_AUTHORIZED_MASK | AUTH_OWNED_MASK);
7,583,948✔
4390

4391
  if (isAudit) {
7,583,948✔
4392
    // for audit db, recheck insert privilege
UNCOV
4393
    authInfo.privType = PRIV_AUDIT_TBL_INSERT;
×
UNCOV
4394
    authInfo.objType = PRIV_OBJ_TBL;
×
4395
  }
4396

4397
  SUserAuthRes     authRes = {0};
7,583,948✔
4398
  SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
15,154,604✔
4399
                           .requestId = pCxt->requestId,
7,583,948✔
4400
                           .requestObjRefId = pCxt->requestRid,
7,583,948✔
4401
                           .mgmtEps = pCxt->mgmtEpSet};
4402
  code = catalogChkAuth(pCxt->pCatalog, &conn, &authInfo, &authRes);  // cache used firstly inside the function
7,583,948✔
4403
  if (TSDB_CODE_SUCCESS == code && !authRes.pass[AUTH_RES_BASIC]) {
7,583,948✔
UNCOV
4404
    code = TSDB_CODE_PAR_DB_USE_PERMISSION_DENIED;
×
4405
  }
4406
  return code;
7,583,948✔
4407
}
4408

4409
static int32_t addTableVgroupFromMetaData(const SArray* pTables, SVnodeModifyOpStmt* pStmt, bool isStb) {
7,580,435✔
4410
  if (1 != taosArrayGetSize(pTables)) {
7,580,435✔
UNCOV
4411
    return TSDB_CODE_FAILED;
×
4412
  }
4413

4414
  SMetaRes* pRes = taosArrayGet(pTables, 0);
7,580,435✔
4415
  if (TSDB_CODE_SUCCESS != pRes->code) {
7,580,435✔
UNCOV
4416
    return pRes->code;
×
4417
  }
4418

4419
  SVgroupInfo* pVg = pRes->pRes;
7,580,435✔
4420
  if (isStb) {
7,580,435✔
4421
    pStmt->pTableMeta->vgId = pVg->vgId;
6,025,870✔
4422
  }
4423
  return taosHashPut(pStmt->pVgroupsHashObj, (const char*)&pVg->vgId, sizeof(pVg->vgId), (char*)pVg,
7,580,435✔
4424
                     sizeof(SVgroupInfo));
4425
}
4426

4427
static int32_t buildTagNameFromMeta(STableMeta* pMeta, SArray** pTagName) {
5,309✔
4428
  *pTagName = taosArrayInit(pMeta->tableInfo.numOfTags, TSDB_COL_NAME_LEN);
5,309✔
4429
  if (NULL == *pTagName) {
5,309✔
UNCOV
4430
    return terrno;
×
4431
  }
4432
  SSchema* pSchema = getTableTagSchema(pMeta);
5,309✔
4433
  int32_t  code = 0;
5,309✔
4434
  for (int32_t i = 0; i < pMeta->tableInfo.numOfTags; ++i) {
11,904✔
4435
    if (NULL == taosArrayPush(*pTagName, pSchema[i].name)) {
13,190✔
UNCOV
4436
      code = terrno;
×
UNCOV
4437
      taosArrayDestroy(*pTagName);
×
UNCOV
4438
      *pTagName = NULL;
×
UNCOV
4439
      break;
×
4440
    }
4441
  }
4442
  return code;
5,309✔
4443
}
4444

4445
static int32_t checkSubtablePrivilegeForTable(const SArray* pTables, SVnodeModifyOpStmt* pStmt) {
5,309✔
4446
#ifdef TD_ENTERPRISE
4447
  if (1 != taosArrayGetSize(pTables)) {
5,309✔
UNCOV
4448
    return TSDB_CODE_FAILED;
×
4449
  }
4450

4451
  SMetaRes* pRes = taosArrayGet(pTables, 0);
5,309✔
4452
  if (TSDB_CODE_SUCCESS != pRes->code) {
5,309✔
4453
    return pRes->code;
×
4454
  }
4455

4456
  SArray* pTagName = NULL;
5,309✔
4457
  int32_t code = buildTagNameFromMeta(pStmt->pTableMeta, &pTagName);
5,309✔
4458
  if (TSDB_CODE_SUCCESS == code) {
5,309✔
4459
    code = checkSubtablePrivilege((SArray*)pRes->pRes, pTagName, &pStmt->pTagCond);
5,309✔
4460
  }
4461
  taosArrayDestroy(pTagName);
5,309✔
4462
  return code;
5,309✔
4463
#else
4464
  return TSDB_CODE_SUCCESS;
4465
#endif
4466
}
4467

4468
static int32_t processTableSchemaFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData,
7,580,435✔
4469
                                              SVnodeModifyOpStmt* pStmt, bool isStb) {
4470
  int32_t code = TSDB_CODE_SUCCESS;
7,580,435✔
4471
  if (!isStb && TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
7,580,435✔
UNCOV
4472
    code = buildInvalidOperationMsg(&pCxt->msg, "insert data into super table is not supported");
×
4473
  }
4474

4475
  if (TSDB_CODE_SUCCESS == code && isStb) {
7,580,435✔
4476
    code = storeChildTableMeta(pCxt, pStmt);
6,025,870✔
4477
  }
4478
  if (TSDB_CODE_SUCCESS == code) {
7,580,435✔
4479
    code = addTableVgroupFromMetaData(pMetaData->pTableHash, pStmt, isStb);
7,580,435✔
4480
  }
4481
  if (TSDB_CODE_SUCCESS == code && !isStb && NULL != pStmt->pTagCond) {
7,580,435✔
4482
    code = checkSubtablePrivilegeForTable(pMetaData->pTableTag, pStmt);
5,309✔
4483
  }
4484
  return code;
7,580,435✔
4485
}
4486

4487
static void destoryTablesReq(void* p) {
15,473,836✔
4488
  STablesReq* pRes = (STablesReq*)p;
15,473,836✔
4489
  taosArrayDestroy(pRes->pTables);
15,473,836✔
4490
}
15,473,836✔
4491

4492
static void clearCatalogReq(SCatalogReq* pCatalogReq) {
7,736,918✔
4493
  if (NULL == pCatalogReq) {
7,736,918✔
UNCOV
4494
    return;
×
4495
  }
4496

4497
  taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq);
7,736,918✔
4498
  pCatalogReq->pTableMeta = NULL;
7,736,918✔
4499
  taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq);
7,736,918✔
4500
  pCatalogReq->pTableHash = NULL;
7,736,918✔
4501
  taosArrayDestroy(pCatalogReq->pUser);
7,736,918✔
4502
  pCatalogReq->pUser = NULL;
7,736,918✔
4503
  taosArrayDestroy(pCatalogReq->pTableTag);
7,736,918✔
4504
  pCatalogReq->pTableTag = NULL;
7,736,918✔
4505
}
4506

4507
static int32_t setVnodeModifOpStmt(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
7,736,918✔
4508
                                   SVnodeModifyOpStmt* pStmt) {
4509
  clearCatalogReq(pCatalogReq);
7,736,918✔
4510
  if (pStmt->pPrivCols) {
7,736,918✔
4511
    taosArrayDestroy(pStmt->pPrivCols);
4,023✔
4512
    pStmt->pPrivCols = NULL;
4,023✔
4513
  }
4514
  if (pStmt->pTagCond) {
7,736,918✔
UNCOV
4515
    nodesDestroyNode(pStmt->pTagCond);
×
UNCOV
4516
    pStmt->pTagCond = NULL;
×
4517
  }
4518

4519
  int32_t code = checkAuthFromMetaData(pCxt, pMetaData, pStmt);
7,736,918✔
4520

4521
  if (code == TSDB_CODE_SUCCESS) {
7,736,918✔
4522
    code = getTableMetaFromMetaData(pMetaData->pTableMeta, &pStmt->pTableMeta);
7,725,310✔
4523
  }
4524
  if (code == TSDB_CODE_SUCCESS) {
7,736,918✔
4525
    code = checkAuthUseDb(pCxt->pComCxt, &pStmt->targetTableName, pStmt->pTableMeta->isAudit);
7,583,948✔
4526
  }
4527
  if (code == TSDB_CODE_SUCCESS) {
7,736,918✔
4528
    if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE && !pStmt->usingTableProcessing) {
7,583,948✔
4529
      pStmt->stbSyntax = true;
3,513✔
4530
    }
4531
    if (!pStmt->stbSyntax) {
7,583,948✔
4532
      if (pStmt->usingTableProcessing) {
7,580,435✔
4533
        return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, true);
6,025,870✔
4534
      }
4535
      return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, false);
1,554,565✔
4536
    }
4537
  }
4538
  return code;
156,483✔
4539
}
4540

4541
static int32_t resetVnodeModifOpStmt(SInsertParseContext* pCxt, SQuery* pQuery) {
3,554✔
4542
  nodesDestroyNode(pQuery->pRoot);
3,554✔
4543

4544
  int32_t code = createVnodeModifOpStmt(pCxt, true, &pQuery->pRoot);
3,554✔
4545
  if (TSDB_CODE_SUCCESS == code) {
3,554✔
4546
    SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
3,554✔
4547

4548
    code = (*pCxt->pComCxt->pStmtCb->getExecInfoFn)(pCxt->pComCxt->pStmtCb->pStmt, &pStmt->pVgroupsHashObj,
3,554✔
4549
                                                    &pStmt->pTableBlockHashObj);
4550
    if (TSDB_CODE_SUCCESS == code) {
3,554✔
4551
      if (NULL == pStmt->pVgroupsHashObj) {
3,554✔
UNCOV
4552
        pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
×
4553
      }
4554
      if (NULL == pStmt->pTableBlockHashObj) {
3,554✔
UNCOV
4555
        pStmt->pTableBlockHashObj =
×
UNCOV
4556
            taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
×
4557
      }
4558
      if (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj) {
3,554✔
UNCOV
4559
        code = TSDB_CODE_OUT_OF_MEMORY;
×
4560
      }
4561
    }
4562
  }
4563

4564
  return code;
3,554✔
4565
}
4566

4567
static int32_t initInsertQuery(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
632,802,598✔
4568
                               SQuery** pQuery) {
4569
  if (NULL == *pQuery) {
632,802,598✔
4570
    return createInsertQuery(pCxt, pQuery);
625,066,265✔
4571
  }
4572

4573
  if (NULL != pCxt->pComCxt->pStmtCb) {
7,746,481✔
4574
    return resetVnodeModifOpStmt(pCxt, *pQuery);
3,554✔
4575
  }
4576

4577
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)(*pQuery)->pRoot;
7,748,318✔
4578

4579
  if (!pStmt->fileProcessing) {
7,748,318✔
4580
    return setVnodeModifOpStmt(pCxt, pCatalogReq, pMetaData, pStmt);
7,736,918✔
4581
  }
4582

4583
  return TSDB_CODE_SUCCESS;
11,400✔
4584
}
4585

4586
static int32_t setRefreshMeta(SQuery* pQuery) {
623,759,068✔
4587
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
623,759,068✔
4588
  int32_t             code = 0;
623,804,584✔
4589

4590
  if (taosHashGetSize(pStmt->pTableNameHashObj) > 0) {
623,804,584✔
4591
    taosArrayDestroy(pQuery->pTableList);
7,553,111✔
4592
    pQuery->pTableList = taosArrayInit(taosHashGetSize(pStmt->pTableNameHashObj), sizeof(SName));
7,546,141✔
4593
    if (!pQuery->pTableList) {
7,527,732✔
UNCOV
4594
      code = terrno;
×
4595
    } else {
4596
      SName* pTable = taosHashIterate(pStmt->pTableNameHashObj, NULL);
7,535,861✔
4597
      while (NULL != pTable) {
18,099,742✔
4598
        if (NULL == taosArrayPush(pQuery->pTableList, pTable)) {
21,091,828✔
UNCOV
4599
          code = terrno;
×
UNCOV
4600
          taosHashCancelIterate(pStmt->pTableNameHashObj, pTable);
×
UNCOV
4601
          break;
×
4602
        }
4603
        pTable = taosHashIterate(pStmt->pTableNameHashObj, pTable);
10,547,912✔
4604
      }
4605
    }
4606
  }
4607

4608
  if (TSDB_CODE_SUCCESS == code && taosHashGetSize(pStmt->pDbFNameHashObj) > 0) {
623,807,075✔
4609
    taosArrayDestroy(pQuery->pDbList);
7,556,181✔
4610
    pQuery->pDbList = taosArrayInit(taosHashGetSize(pStmt->pDbFNameHashObj), TSDB_DB_FNAME_LEN);
7,556,193✔
4611
    if (!pQuery->pDbList) {
7,539,508✔
UNCOV
4612
      code = terrno;
×
4613
    } else {
4614
      char* pDb = taosHashIterate(pStmt->pDbFNameHashObj, NULL);
7,544,171✔
4615
      while (NULL != pDb) {
15,102,875✔
4616
        if (NULL == taosArrayPush(pQuery->pDbList, pDb)) {
15,113,215✔
4617
          code = terrno;
×
UNCOV
4618
          taosHashCancelIterate(pStmt->pDbFNameHashObj, pDb);
×
UNCOV
4619
          break;
×
4620
        }
4621
        pDb = taosHashIterate(pStmt->pDbFNameHashObj, pDb);
7,557,513✔
4622
      }
4623
    }
4624
  }
4625

4626
  return code;
623,794,608✔
4627
}
4628

4629
// INSERT INTO
4630
//   tb_name
4631
//       [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]]
4632
//       [(field1_name, ...)]
4633
//       VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
4634
//   [...];
4635
static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
625,015,324✔
4636
  int32_t code = skipInsertInto(&pStmt->pSql, &pCxt->msg);
625,015,324✔
4637
  if (TSDB_CODE_SUCCESS == code) {
625,063,865✔
4638
    code = parseInsertBody(pCxt, pStmt);
625,065,269✔
4639
  }
4640
  return code;
624,958,431✔
4641
}
4642

4643
static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
11,400✔
4644
  int32_t          code = TSDB_CODE_SUCCESS;
11,400✔
4645
  SRowsDataContext rowsDataCxt;
4646

4647
  if (!pStmt->stbSyntax) {
11,400✔
4648
    STableDataCxt* pTableCxt = NULL;
10,260✔
4649
    code = getTableDataCxt(pCxt, pStmt, &pTableCxt);
10,260✔
4650
    rowsDataCxt.pTableDataCxt = pTableCxt;
10,260✔
4651
  } else {
4652
    rowsDataCxt.pStbRowsCxt = pStmt->pStbRowsCxt;
1,140✔
4653
  }
4654
  if (TSDB_CODE_SUCCESS == code) {
11,400✔
4655
    code = parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
11,400✔
4656
  }
4657

4658
  if (TSDB_CODE_SUCCESS == code) {
11,400✔
4659
    if (pStmt->fileProcessing) {
11,400✔
UNCOV
4660
      code = parseInsertBodyBottom(pCxt, pStmt);
×
4661
    } else {
4662
      code = parseInsertBody(pCxt, pStmt);
11,400✔
4663
    }
4664
  }
4665

4666
  return code;
11,400✔
4667
}
4668

4669
static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
7,583,232✔
4670
  int32_t code = parseInsertTableClauseBottom(pCxt, pStmt);
7,583,232✔
4671
  if (TSDB_CODE_SUCCESS == code) {
7,583,232✔
4672
    code = parseInsertBody(pCxt, pStmt);
7,157,267✔
4673
  }
4674
  return code;
7,583,232✔
4675
}
4676

4677
static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
632,619,386✔
4678
  if (pStmt->pSql == pCxt->pComCxt->pSql || NULL != pCxt->pComCxt->pStmtCb) {
632,619,386✔
4679
    return parseInsertSqlFromStart(pCxt, pStmt);
625,044,393✔
4680
  }
4681

4682
  if (pStmt->fileProcessing) {
7,594,632✔
4683
    return parseInsertSqlFromCsv(pCxt, pStmt);
11,400✔
4684
  }
4685

4686
  return parseInsertSqlFromTable(pCxt, pStmt);
7,583,232✔
4687
}
4688

4689
static int32_t buildUsingInsertTableReq(SName* pSName, SName* pCName, SArray** pTables) {
6,059,303✔
4690
  if (NULL == *pTables) {
6,059,303✔
4691
    *pTables = taosArrayInit(2, sizeof(SName));
6,059,303✔
4692
    if (NULL == *pTables) {
6,059,315✔
UNCOV
4693
      goto _err;
×
4694
    }
4695
  }
4696
  if (NULL == taosArrayPush(*pTables, pSName)) {
12,118,642✔
UNCOV
4697
    goto _err;
×
4698
  }
4699
  if (NULL == taosArrayPush(*pTables, pCName)) {
12,118,654✔
UNCOV
4700
    goto _err;
×
4701
  }
4702
  return TSDB_CODE_SUCCESS;
6,059,327✔
4703

UNCOV
4704
_err:
×
UNCOV
4705
  if (NULL != *pTables) {
×
UNCOV
4706
    taosArrayDestroy(*pTables);
×
UNCOV
4707
    *pTables = NULL;
×
4708
  }
4709
  return terrno;
×
4710
}
4711

4712
static int32_t buildInsertTableReq(SName* pName, SArray** pTables) {
9,490,914✔
4713
  *pTables = taosArrayInit(1, sizeof(SName));
9,490,914✔
4714
  if (NULL == *pTables) {
9,490,746✔
UNCOV
4715
    return terrno;
×
4716
  }
4717

4718
  if (NULL == taosArrayPush(*pTables, pName)) {
18,981,972✔
UNCOV
4719
    taosArrayDestroy(*pTables);
×
4720
    *pTables = NULL;
×
4721
    return terrno;
×
4722
  }
4723
  return TSDB_CODE_SUCCESS;
9,491,226✔
4724
}
4725

4726
static int32_t buildInsertUsingDbReq(SName* pSName, SName* pCName, SArray** pDbs) {
6,059,315✔
4727
  if (NULL == *pDbs) {
6,059,315✔
4728
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
6,059,327✔
4729
    if (NULL == *pDbs) {
6,059,315✔
UNCOV
4730
      return terrno;
×
4731
    }
4732
  }
4733

4734
  STablesReq req = {0};
6,059,303✔
4735
  req.autoCreate = 1;
6,059,303✔
4736
  (void)tNameGetFullDbName(pSName, req.dbFName);
6,059,303✔
4737
  (void)tNameGetFullDbName(pCName, req.dbFName);
6,059,303✔
4738

4739
  int32_t code = buildUsingInsertTableReq(pSName, pCName, &req.pTables);
6,059,327✔
4740
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
12,118,654✔
UNCOV
4741
    code = TSDB_CODE_OUT_OF_MEMORY;
×
4742
  }
4743
  return code;
6,059,327✔
4744
}
4745

4746
static int32_t buildInsertDbReq(SName* pName, SArray** pDbs) {
9,485,009✔
4747
  if (NULL == *pDbs) {
9,485,009✔
4748
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
9,485,177✔
4749
    if (NULL == *pDbs) {
9,484,709✔
UNCOV
4750
      return terrno;
×
4751
    }
4752
  }
4753

4754
  STablesReq req = {0};
9,484,541✔
4755
  (void)tNameGetFullDbName(pName, req.dbFName);
9,484,697✔
4756
  int32_t code = buildInsertTableReq(pName, &req.pTables);
9,484,865✔
4757
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
18,970,354✔
UNCOV
4758
    code = TSDB_CODE_OUT_OF_MEMORY;
×
4759
  }
4760

4761
  return code;
9,485,177✔
4762
}
4763

4764
static int32_t buildInsertUserAuthReq(SParseContext* pCxt, SName* pName, SArray** pUserAuth) {
7,772,071✔
4765
  *pUserAuth = taosArrayInit(1, sizeof(SUserAuthInfo));
7,772,071✔
4766
  if (NULL == *pUserAuth) {
7,771,916✔
UNCOV
4767
    return terrno;
×
4768
  }
4769

4770
  SUserAuthInfo userAuth = {.privType = PRIV_TBL_INSERT, .objType = PRIV_OBJ_TBL, .userId = pCxt->userId};
7,772,228✔
4771
  snprintf(userAuth.user, sizeof(userAuth.user), "%s", pCxt->pUser);
7,772,228✔
4772
  memcpy(&userAuth.tbName, pName, sizeof(SName));
7,772,228✔
4773
  if (NULL == taosArrayPush(*pUserAuth, &userAuth)) {
15,544,324✔
4774
    taosArrayDestroy(*pUserAuth);
×
UNCOV
4775
    *pUserAuth = NULL;
×
UNCOV
4776
    return terrno;
×
4777
  }
4778

4779
  return TSDB_CODE_SUCCESS;
7,772,096✔
4780
}
4781

4782
static int32_t buildInsertTableTagReq(SName* pName, SArray** pTables) { return buildInsertTableReq(pName, pTables); }
6,049✔
4783

4784
static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SCatalogReq* pCatalogReq) {
7,772,252✔
4785
  int32_t code = buildInsertUserAuthReq(
15,523,596✔
4786
      pCxt->pComCxt, (0 == pStmt->usingTableName.type ? &pStmt->targetTableName : &pStmt->usingTableName),
7,772,252✔
4787
      &pCatalogReq->pUser);
4788
  if (TSDB_CODE_SUCCESS == code && pCxt->needTableTagVal) {
7,772,252✔
4789
    code = buildInsertTableTagReq(&pStmt->targetTableName, &pCatalogReq->pTableTag);
6,049✔
4790
  }
4791
  if (TSDB_CODE_SUCCESS == code) {
7,772,096✔
4792
    if (0 == pStmt->usingTableName.type) {
7,772,096✔
4793
      code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableMeta);
1,712,769✔
4794
    } else {
4795
      code = buildInsertUsingDbReq(&pStmt->usingTableName, &pStmt->targetTableName, &pCatalogReq->pTableMeta);
6,059,327✔
4796
    }
4797
  }
4798
  if (TSDB_CODE_SUCCESS == code) {
7,772,252✔
4799
    code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableHash);
7,772,252✔
4800
  }
4801
  return code;
7,772,252✔
4802
}
4803

4804
static int32_t setNextStageInfo(SInsertParseContext* pCxt, SQuery* pQuery, SCatalogReq* pCatalogReq) {
631,574,746✔
4805
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
631,574,746✔
4806
  if (pCxt->missCache) {
631,583,342✔
4807
    parserDebug("QID:0x%" PRIx64 ", %d rows of %d tables will be inserted before obtain the cache",
7,772,252✔
4808
                pCxt->pComCxt->requestId, pStmt->totalRowsNum, pStmt->totalTbNum);
4809

4810
    pQuery->execStage = QUERY_EXEC_STAGE_PARSE;
7,772,252✔
4811
    return buildInsertCatalogReq(pCxt, pStmt, pCatalogReq);
7,772,252✔
4812
  }
4813

4814
  parserDebug("QID:0x%" PRIx64 ", %d rows of %d tables will be inserted", pCxt->pComCxt->requestId, pStmt->totalRowsNum,
623,807,579✔
4815
              pStmt->totalTbNum);
4816

4817
  pQuery->execStage = QUERY_EXEC_STAGE_SCHEDULE;
623,807,579✔
4818
  return TSDB_CODE_SUCCESS;
623,815,372✔
4819
}
4820

4821
int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) {
632,741,007✔
4822
  SInsertParseContext context = {.pComCxt = pCxt,
635,342,869✔
4823
                                 .msg = {.buf = pCxt->pMsg, .len = pCxt->msgLen},
632,768,630✔
4824
                                 .missCache = false,
4825
                                 .usingDuplicateTable = false,
4826
                                 .needRequest = true,
4827
                                 .forceUpdate = (NULL != pCatalogReq ? pCatalogReq->forceUpdate : false)};
632,811,371✔
4828

4829
  int32_t code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery);
632,810,447✔
4830
  if (TSDB_CODE_SUCCESS == code) {
632,781,657✔
4831
    code = parseInsertSqlImpl(&context, (SVnodeModifyOpStmt*)((*pQuery)->pRoot));
632,633,263✔
4832
  }
4833

4834
  if (TSDB_CODE_SUCCESS == code) {
632,712,832✔
4835
    code = setNextStageInfo(&context, *pQuery, pCatalogReq);
631,495,565✔
4836
  }
4837
  if ((TSDB_CODE_SUCCESS == code || NEED_CLIENT_HANDLE_ERROR(code)) &&
632,793,051✔
4838
      QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) {
631,774,291✔
4839
    code = setRefreshMeta(*pQuery);
623,791,608✔
4840
  }
4841

4842
  qDestroyBoundColInfo(&context.tags);
632,805,721✔
4843
  clearInsertParseContext(&context);
632,743,801✔
4844
  // if no data to insert, set emptyMode to avoid request server
4845
  if (!context.needRequest) {
632,711,902✔
4846
    (*pQuery)->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
5,700✔
4847
  }
4848
  return code;
632,711,902✔
4849
}
4850

4851
// CSV Parser Implementation
4852
static int32_t csvParserInit(SCsvParser* parser, TdFilePtr pFile) {
584,844✔
4853
  if (!parser || !pFile) {
584,844✔
UNCOV
4854
    return TSDB_CODE_INVALID_PARA;
×
4855
  }
4856

4857
  memset(parser, 0, sizeof(SCsvParser));
584,844✔
4858

4859
  // Set default CSV format
4860
  parser->delimiter = CSV_DEFAULT_DELIMITER;
584,844✔
4861
  parser->quote = CSV_QUOTE_SINGLE;  // Default to single quote for TDengine compatibility
584,844✔
4862
  parser->escape = CSV_ESCAPE_CHAR;
584,844✔
4863
  parser->allowNewlineInField = true;
584,844✔
4864

4865
  // Initialize buffer
4866
  parser->bufferSize = 64 * 1024;  // 64KB buffer
584,844✔
4867
  parser->buffer = taosMemoryMalloc(parser->bufferSize);
584,844✔
4868
  if (!parser->buffer) {
584,844✔
UNCOV
4869
    return terrno;
×
4870
  }
4871

4872
  // Initialize line buffer for reuse
4873
  parser->lineBufferCapacity = 64 * 1024;  // Initial 64KB line buffer
584,844✔
4874
  parser->lineBuffer = taosMemoryMalloc(parser->lineBufferCapacity);
584,844✔
4875
  if (!parser->lineBuffer) {
584,844✔
UNCOV
4876
    return terrno;
×
4877
  }
4878

4879
  parser->bufferPos = 0;
584,844✔
4880
  parser->bufferLen = 0;
584,844✔
4881
  parser->eof = false;
584,844✔
4882
  parser->pFile = pFile;
584,844✔
4883

4884
  // Fill initial buffer to detect quote type
4885
  int32_t code = csvParserFillBuffer(parser);
584,844✔
4886
  if (code != TSDB_CODE_SUCCESS) {
584,844✔
UNCOV
4887
    return code;
×
4888
  }
4889

4890
  // Auto-detect quote character by finding the first quote in the file
4891
  // Skip the header line and look for the first quote character in data
4892
  bool foundFirstQuote = false;
584,844✔
4893
  bool inFirstLine = true;
584,844✔
4894

4895
  for (size_t i = 0; i < parser->bufferLen && !foundFirstQuote; i++) {
771,712,528✔
4896
    char ch = parser->buffer[i];
771,127,684✔
4897

4898
    // Skip the first line (header)
4899
    if (inFirstLine) {
771,127,684✔
4900
      if (ch == '\n') {
96,612,034✔
4901
        inFirstLine = false;
583,560✔
4902
      }
4903
      continue;
96,612,034✔
4904
    }
4905

4906
    // Look for the first quote character in data lines
4907
    if (ch == CSV_QUOTE_SINGLE) {
674,515,650✔
4908
      parser->quote = CSV_QUOTE_SINGLE;
74,890✔
4909
      foundFirstQuote = true;
74,890✔
4910
    } else if (ch == CSV_QUOTE_DOUBLE) {
674,440,760✔
4911
      parser->quote = CSV_QUOTE_DOUBLE;
497,840✔
4912
      foundFirstQuote = true;
497,840✔
4913
    }
4914
  }
4915

4916
  // If no quotes found, keep default (single quote for TDengine compatibility)
4917

4918
  // Reset buffer position for actual parsing
4919
  parser->bufferPos = 0;
584,844✔
4920

4921
  return TSDB_CODE_SUCCESS;
584,844✔
4922
}
4923

4924
static void csvParserDestroy(SCsvParser* parser) {
584,844✔
4925
  if (parser) {
584,844✔
4926
    taosMemoryFree(parser->buffer);
584,844✔
4927
    taosMemoryFree(parser->lineBuffer);
584,844✔
4928
    memset(parser, 0, sizeof(SCsvParser));
584,844✔
4929
  }
4930
}
584,844✔
4931

4932
static int32_t csvParserFillBuffer(SCsvParser* parser) {
24,540,231✔
4933
  if (!parser || parser->eof) {
24,540,231✔
4934
    return TSDB_CODE_SUCCESS;
4,426✔
4935
  }
4936

4937
  // Move remaining data to beginning of buffer
4938
  // Since this function is only called when bufferPos >= bufferLen,
4939
  // we can simplify by always resetting the buffer
4940
  parser->bufferLen = 0;
24,535,805✔
4941
  parser->bufferPos = 0;
24,535,805✔
4942

4943
  // Read more data
4944
  size_t spaceLeft = parser->bufferSize - parser->bufferLen;
24,535,805✔
4945
  if (spaceLeft > 0) {
24,535,805✔
4946
    int64_t bytesRead = taosReadFile(parser->pFile, parser->buffer + parser->bufferLen, spaceLeft);
24,535,805✔
4947
    if (bytesRead < 0) {
24,535,805✔
UNCOV
4948
      return TAOS_SYSTEM_ERROR(errno);
×
4949
    }
4950
    if (bytesRead == 0) {
24,535,805✔
4951
      parser->eof = true;
554,286✔
4952
    } else {
4953
      parser->bufferLen += bytesRead;
23,981,519✔
4954
    }
4955
  }
4956

4957
  return TSDB_CODE_SUCCESS;
24,535,805✔
4958
}
4959

4960
// Destroy saved CSV parser in SVnodeModifyOpStmt
4961
static void destroySavedCsvParser(SVnodeModifyOpStmt* pStmt) {
584,844✔
4962
  if (pStmt && pStmt->pCsvParser) {
584,844✔
4963
    csvParserDestroy(pStmt->pCsvParser);
584,844✔
4964
    taosMemoryFree(pStmt->pCsvParser);
584,844✔
4965
    pStmt->pCsvParser = NULL;
584,844✔
4966
  }
4967
}
584,844✔
4968

4969
static int32_t csvParserExpandLineBuffer(SCsvParser* parser, size_t requiredLen) {
2,147,483,647✔
4970
  if (!parser || requiredLen <= parser->lineBufferCapacity) {
2,147,483,647✔
4971
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
4972
  }
4973

UNCOV
4974
  size_t newCapacity = parser->lineBufferCapacity;
×
UNCOV
4975
  while (newCapacity < requiredLen) {
×
UNCOV
4976
    newCapacity *= 2;
×
4977
  }
4978

UNCOV
4979
  char* newLineBuffer = taosMemoryRealloc(parser->lineBuffer, newCapacity);
×
UNCOV
4980
  if (!newLineBuffer) {
×
UNCOV
4981
    return TSDB_CODE_OUT_OF_MEMORY;
×
4982
  }
4983

UNCOV
4984
  parser->lineBuffer = newLineBuffer;
×
UNCOV
4985
  parser->lineBufferCapacity = newCapacity;
×
UNCOV
4986
  return TSDB_CODE_SUCCESS;
×
4987
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc