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

taosdata / TDengine / #5011

03 Apr 2026 03:59PM UTC coverage: 72.3% (+0.008%) from 72.292%
#5011

push

travis-ci

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

4053 of 5985 new or added lines in 68 files covered. (67.72%)

732 existing lines in 143 files now uncovered.

257430 of 356056 relevant lines covered (72.3%)

131834103.52 hits per line

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

82.4
/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) {
481,539,325✔
98
  SToken token;
99
  NEXT_TOKEN(*pSql, token);
481,539,325✔
100
  if (TK_INSERT != token.type && TK_IMPORT != token.type) {
481,544,775✔
101
    return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", token.z);
×
102
  }
103
  NEXT_TOKEN(*pSql, token);
481,544,775✔
104
  if (TK_INTO != token.type) {
481,544,935✔
105
    return buildSyntaxErrMsg(pMsg, "keyword INTO is expected", token.z);
×
106
  }
107
  return TSDB_CODE_SUCCESS;
481,544,935✔
108
}
109

110
static int32_t skipParentheses(SInsertParseContext* pCxt, const char** pSql) {
43,340,071✔
111
  SToken  token;
112
  int32_t expectRightParenthesis = 1;
43,340,071✔
113
  while (1) {
114
    NEXT_TOKEN(*pSql, token);
678,372,068✔
115
    if (TK_NK_LP == token.type) {
678,372,068✔
116
      ++expectRightParenthesis;
×
117
    } else if (TK_NK_RP == token.type && 0 == --expectRightParenthesis) {
678,372,068✔
118
      break;
43,340,071✔
119
    }
120
    if (0 == token.n) {
635,031,997✔
121
      return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL);
×
122
    }
123
  }
124
  return TSDB_CODE_SUCCESS;
43,340,071✔
125
}
126

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

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

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

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

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

177
  return code;
71,116✔
178
}
179

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

193
  if (TSDB_CODE_SUCCESS == code) {
7,824,559✔
194
    code = skipTableOptions(pCxt, pSql);
7,824,559✔
195
  }
196

197
  return code;
7,824,559✔
198
}
199

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

204
  char tbFName[TSDB_TABLE_FNAME_LEN];
20,090,954✔
205
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
20,299,580✔
206
  if (TSDB_CODE_SUCCESS != code) {
20,302,340✔
207
    return code;
×
208
  }
209
  STableMeta** pMeta = taosHashGet(pStmt->pSubTableHashObj, tbFName, strlen(tbFName));
20,302,340✔
210
  if (NULL != pMeta) {
20,296,128✔
211
    *pDuplicate = true;
71,116✔
212
    pCxt->missCache = false;
71,116✔
213
    code = cloneTableMeta(*pMeta, &pStmt->pTableMeta);
71,116✔
214
    if (TSDB_CODE_SUCCESS != code) {
71,116✔
215
      return code;
×
216
    }
217
    return ignoreUsingClause(pCxt, pStmt);
71,116✔
218
  }
219

220
  return code;
20,225,012✔
221
}
222

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

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

229
// pStmt->pSql -> field1_name, ...)
230
static int32_t parseBoundColumns(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** pSql,
43,603,512✔
231
                                 EBoundColumnsType boundColsType, STableMeta* pTableMeta, SBoundColInfo* pBoundInfo) {
232
  SSchema* pSchema = NULL;
43,603,512✔
233
  if (boundColsType == BOUND_TAGS) {
43,603,512✔
234
    pSchema = getTableTagSchema(pTableMeta);
248,546✔
235
  } else if (boundColsType == BOUND_COLUMNS) {
43,354,966✔
236
    pSchema = getTableColumnSchema(pTableMeta);
43,128,438✔
237
  } else {
238
    pSchema = pTableMeta->schema;
226,528✔
239
    if (pBoundInfo->numOfCols != getTbnameSchemaIndex(pTableMeta) + 1) {
226,528✔
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);
43,603,512✔
245

246
  bool* pUseCols = taosMemoryCalloc(pBoundInfo->numOfCols, sizeof(bool));
43,603,512✔
247
  if (NULL == pUseCols) {
43,603,512✔
248
    return terrno;
×
249
  }
250

251
  pBoundInfo->numOfBound = 0;
43,603,512✔
252
  pBoundInfo->hasBoundCols = true;
43,603,512✔
253

254
  bool    hasPK = pTableMeta->tableInfo.numOfPKs;
43,603,512✔
255
  int16_t numOfBoundPKs = 0;
43,603,512✔
256
  int16_t lastColIdx = -1;  // last column found
43,603,512✔
257
  SArray* pPrivCols = pStmt->pPrivCols;
43,603,512✔
258
  int32_t lastPrivColIdx = 0, nPrivCols = taosArrayGetSize(pPrivCols);
43,603,512✔
259
  int32_t code = TSDB_CODE_SUCCESS;
43,603,512✔
260
  while (TSDB_CODE_SUCCESS == code) {
679,877,656✔
261
    SToken token;
664,766,425✔
262
    NEXT_TOKEN(*pSql, token);
679,873,616✔
263

264
    if (TK_NK_RP == token.type) {
679,873,616✔
265
      break;
43,597,578✔
266
    }
267

268
    char tmpTokenBuf[TSDB_COL_NAME_LEN + 2] = {0};  // used for deleting Escape character backstick(`)
636,276,038✔
269
    if (token.n >= TSDB_COL_NAME_LEN + 2) {
636,276,038✔
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));
636,276,038✔
274
    token.z = tmpTokenBuf;
636,276,038✔
275
    token.n = strdequote(token.z);
636,276,038✔
276

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

284
    int16_t t = lastColIdx + 1;
636,050,330✔
285
    int16_t end = (boundColsType == BOUND_ALL_AND_TBNAME) ? (pBoundInfo->numOfCols - 1) : pBoundInfo->numOfCols;
636,050,330✔
286
    int16_t index = insFindCol(&token, t, end, pSchema);
636,050,330✔
287
    if (index < 0 && t > 0) {
636,050,330✔
288
      index = insFindCol(&token, 0, t, pSchema);
12,595,642✔
289
    }
290
    if (index < 0) {
636,050,330✔
291
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z);
4,040✔
292
    } else if (pUseCols[index]) {
636,046,290✔
293
      code = buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z);
×
294
    } else {
295
      lastColIdx = index;
636,046,290✔
296
      pUseCols[index] = true;
636,046,290✔
297
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = index;
636,046,290✔
298
      ++pBoundInfo->numOfBound;
636,046,290✔
299
      if (hasPK && (pSchema[index].flags & COL_IS_KEY)) ++numOfBoundPKs;
636,046,290✔
300

301
      if (pPrivCols) {  // check column-level privileges
636,046,290✔
302
        int32_t j = lastPrivColIdx;
8,144✔
303
        bool    found = false;
8,144✔
304
        for (; lastPrivColIdx < nPrivCols; ++lastPrivColIdx) {
14,394✔
305
          SColNameFlag* pColNameFlag = (SColNameFlag*)TARRAY_GET_ELEM(pPrivCols, lastPrivColIdx);
12,500✔
306
          if (pSchema[index].colId == pColNameFlag->colId) {
12,500✔
307
            found = true;
6,250✔
308
            break;
6,250✔
309
          }
310
        }
311
        if (!found) {
8,144✔
312
          for (int32_t k = 0; k < j; ++k) {
2,178✔
313
            SColNameFlag* pColNameFlag = (SColNameFlag*)TARRAY_GET_ELEM(pPrivCols, k);
284✔
314
            if (pSchema[index].colId == pColNameFlag->colId) {
284✔
315
              found = true;
×
316
              break;
×
317
            }
318
          }
319
        }
320
        if (!found) {
8,144✔
321
          taosMemoryFree(pUseCols);
1,894✔
322
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_COL_PERMISSION_DENIED, token.z);
1,894✔
323
        }
324
      }
325
    }
326
  }
327

328
  if (TSDB_CODE_SUCCESS == code && (BOUND_TAGS != boundColsType)) {
43,601,618✔
329
    if (!pUseCols[0]) {
43,349,032✔
330
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary timestamp column should not be null");
14,210✔
331
    }
332
    if (numOfBoundPKs != pTableMeta->tableInfo.numOfPKs) {
43,349,032✔
333
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary key column should not be none");
12,060✔
334
    }
335
  }
336
  if (TSDB_CODE_SUCCESS == code && (BOUND_ALL_AND_TBNAME == boundColsType) && !pUseCols[tbnameSchemaIndex]) {
43,601,618✔
337
    code = buildInvalidOperationMsg(&pCxt->msg, "tbname column should not be null");
820✔
338
  }
339
  taosMemoryFree(pUseCols);
43,601,618✔
340

341
  return code;
43,601,618✔
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;
42,689✔
351
    *ts = taosGetTimestampToday(timePrec, tz);
42,689✔
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,044✔
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,438✔
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,627,927✔
367
          (pToken->type != TK_NK_STRING && pToken->type != TK_NK_HEX && pToken->type != TK_NK_BIN)) {
10,434,553✔
368
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
196,748✔
369
      }
370
      if (IS_NOW_STR(pToken->z, pToken->n)) {
10,431,179✔
371
        *isTs = true;
9,276✔
372
        *ts = taosGetTimestamp(timePrec);
18,552✔
373
      } else if (IS_TODAY_STR(pToken->z, pToken->n)) {
10,421,903✔
374
        *isTs = true;
9,276✔
375
        *ts = taosGetTimestampToday(timePrec, tz);
9,276✔
376
      } else if (TSDB_CODE_SUCCESS == toIntegerPure(pToken->z, pToken->n, 10, ts)) {
10,412,627✔
377
        *isTs = true;
10,392,192✔
378
      } else {
379
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
20,435✔
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);
29,794✔
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] == ')') {
3,991,533✔
408
        *end = pTokenEnd = &pToken->z[k + 2];
3,990,737✔
409
        ++k;
3,990,737✔
410
        continue;
3,990,737✔
411
      } else {
412
        char nc = pToken->z[k + 1];
796✔
413
        while (nc == ' ' || nc == '\t' || nc == '\n' || nc == '\r' || nc == '\f') {
1,592✔
414
          nc = pToken->z[(++k) + 1];
796✔
415
        }
416
        if (nc == ')') {
796✔
417
          *end = pTokenEnd = &pToken->z[k + 2];
796✔
418
          ++k;
796✔
419
          continue;
796✔
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,015,920✔
437
      continue;
21,015,920✔
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) {
95✔
462
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", valueToken.z);
235,177✔
463
      }
464
      int32_t len = trimString(valueToken.z, valueToken.n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
95✔
465
      valueToken.z = tmpTokenBuf;
95✔
466
      valueToken.n = len;
95✔
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,438✔
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,693✔
481
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
3,313✔
482
      }
483
      ts = tempTs;
380✔
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);
190✔
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,339,680✔
494
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
190✔
495
      }
496
      *time = ts - interval;
2,339,490✔
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,687✔
513
    }
514
  }
515

516
  *end = pTokenEnd;
2,272,790✔
517
  return TSDB_CODE_SUCCESS;
2,272,790✔
518
}
519

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

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

532
    code = doGeomFromText(pToken->z, output, size);
147,798,313✔
533
    if (code != TSDB_CODE_SUCCESS) {
147,798,341✔
534
      return code;
1,323✔
535
    }
536
  }
537

538
  return code;
147,813,463✔
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,360✔
545
                                   char* tokenBuf, int32_t* inputBytes, bool* final) {
546
  NEXT_VALID_TOKEN(*ppSql, *pToken);
6,360✔
547
  if (TK_NK_LP != pToken->type) {
6,360✔
548
    return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z);
×
549
  }
550

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

557
      *final = true;
1,590✔
558
      return TSDB_CODE_SUCCESS;
1,590✔
559
    } else {
560
      return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
561
    }
562
  } else if (TK_NK_STRING != pToken->type) {
4,770✔
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,770✔
567

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

573
  return TSDB_CODE_SUCCESS;
4,770✔
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;
9,978,626✔
587
    int32_t inputBytes = 0;
9,978,626✔
588
    int32_t outputBytes = 0;
27,030✔
589
    bool    final = false;
27,030✔
590

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

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

601
        return code;
530✔
602
      }
603

604
      input = tmpTokenBuf;
1,590✔
605

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

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

613
      *pData = taosMemoryMalloc(outputBytes);
1,590✔
614
      if (NULL == *pData) {
1,590✔
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,590✔
621
        pVal->flag = CV_FLAG_NULL;
530✔
622

623
        taosMemoryFree(tmpTokenBuf);
530✔
624

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

633
        return code;
530✔
634
      }
635

636
      input = tmpTokenBuf;
1,590✔
637

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

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

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

649
        return terrno;
×
650
      }
651

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

659
        return code;
530✔
660
      }
661

662
      input = tmpTokenBuf;
1,590✔
663

664
      if (MD5_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) {
1,590✔
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,590✔
671
      *pData = taosMemoryMalloc(bufLen);
1,590✔
672
      if (NULL == *pData) {
1,590✔
673
        taosMemoryFree(tmpTokenBuf);
×
674

675
        return terrno;
×
676
      }
677

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

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

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

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

698
        NEXT_VALID_TOKEN(*ppSql, *pToken);
4,240✔
699
        if (TK_NK_INTEGER != pToken->type) {
2,120✔
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,120✔
706
        if (TK_NK_RP == pToken->type) {
2,120✔
707
          pVal->flag = CV_FLAG_NULL;
2,120✔
708

709
          taosMemoryFree(tmpTokenBuf);
2,120✔
710

711
          return TSDB_CODE_SUCCESS;
2,120✔
712
        }
713
      } else if (TK_NK_STRING != pToken->type) {
6,360✔
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,360✔
720
      input = tmpTokenBuf;
6,360✔
721

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

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

729
      int64_t digestLen = 224;
6,360✔
730
      NEXT_VALID_TOKEN(*ppSql, *pToken);
12,720✔
731
      if (TK_NK_INTEGER != pToken->type) {
6,360✔
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,360✔
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,360✔
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,360✔
750
      if (TK_NK_RP != pToken->type) {
6,360✔
751
        taosMemoryFree(tmpTokenBuf);
×
752

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

756
      if (SHA2_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) {
6,360✔
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,360✔
763
      *pData = taosMemoryMalloc(bufLen);
6,360✔
764
      if (NULL == *pData) {
6,360✔
765
        taosMemoryFree(tmpTokenBuf);
×
766

767
        return terrno;
×
768
      }
769

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

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

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

787
          taosMemoryFree(tmpTokenBuf);
1,060✔
788

789
          return TSDB_CODE_SUCCESS;
1,060✔
790
        }
791
      } else if (TK_NK_STRING != pToken->type) {
3,180✔
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,180✔
798
      input = tmpTokenBuf;
3,180✔
799

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

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

807
      if (SHA1_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) {
3,180✔
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,180✔
814
      *pData = taosMemoryMalloc(bufLen);
3,180✔
815
      if (NULL == *pData) {
3,180✔
816
        taosMemoryFree(tmpTokenBuf);
×
817

818
        return terrno;
×
819
      }
820

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

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

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

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

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

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

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

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

856
          taosMemoryFree(tmpTokenBuf);
530✔
857

858
          return TSDB_CODE_SUCCESS;
530✔
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,590✔
875
        input = tmpTokenBuf;
1,590✔
876
      }
877

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

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

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

889
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,650✔
890
      if (TK_NK_STRING != pToken->type) {
1,590✔
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,590✔
896
        key = tmpKeyBuf;
1,590✔
897
      }
898

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

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

907
        return buildSyntaxErrMsg(&pCxt->msg, ") or iv expected", pToken->z);
×
908
      } else if (TK_NK_STRING == pToken->type) {
1,590✔
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,590✔
921
      if (outputBytes + VARSTR_HEADER_SIZE > bytes) {
1,590✔
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,590✔
928
      *pData = taosMemoryCalloc(1, bufLen);
1,590✔
929
      if (NULL == *pData) {
1,590✔
930
        taosMemoryFree(tmpTokenBuf);
×
931

932
        return terrno;
×
933
      }
934

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

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

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

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

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

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

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

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

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

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

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

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

982
          taosMemoryFree(tmpTokenBuf);
530✔
983

984
          return TSDB_CODE_SUCCESS;
530✔
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,710✔
1077
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,650✔
1078
      if (TK_NK_LP != pToken->type) {
2,650✔
1079
        taosMemoryFree(tmpTokenBuf);
×
1080

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

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

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

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

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

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

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

1108
          taosMemoryFree(tmpTokenBuf);
530✔
1109

1110
          return TSDB_CODE_SUCCESS;
530✔
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,590✔
1118
        input = tmpTokenBuf;
1,590✔
1119
      }
1120

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

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

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

1132
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,650✔
1133
      if (TK_NK_STRING != pToken->type) {
1,590✔
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,590✔
1139
        key = tmpKeyBuf;
1,590✔
1140
      }
1141

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

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

1149
      int32_t outputBytes = tsm4_encrypt_len(inputBytes);
1,590✔
1150
      if (outputBytes + VARSTR_HEADER_SIZE > bytes) {
1,590✔
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,590✔
1157
      *pData = taosMemoryMalloc(bufLen);
1,590✔
1158
      if (NULL == *pData) {
1,590✔
1159
        taosMemoryFree(tmpTokenBuf);
×
1160

1161
        return terrno;
×
1162
      }
1163

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

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

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

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

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

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

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

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

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

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

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

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

1211
          taosMemoryFree(tmpTokenBuf);
530✔
1212

1213
          return TSDB_CODE_SUCCESS;
530✔
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);
16,960✔
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,246✔
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;
47,760✔
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,747,319✔
1313
      return TSDB_CODE_PAR_INVALID_VARBINARY;
×
1314
    }
1315

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

1322
    if (size + VARSTR_HEADER_SIZE > bytes) {
3,747,319✔
1323
      taosMemoryFree(data);
1,112✔
1324
      return TSDB_CODE_PAR_VALUE_TOO_LONG;
1,112✔
1325
    }
1326
    *pData = data;
3,746,207✔
1327
    *nData = size;
3,746,207✔
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) {
25,478,859✔
1341
  if (pToken->type != TK_NK_STRING) {
25,478,859✔
1342
    return TSDB_CODE_PAR_INVALID_VARBINARY;
9,552✔
1343
  }
1344
  int32_t  code = 0;
25,469,307✔
1345
  int32_t  lino = 0;
25,469,307✔
1346
  uint32_t size = 0;
25,469,307✔
1347
  *pData = NULL;
25,469,307✔
1348

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

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

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

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

1381
static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val,
176,490,859✔
1382
                             SMsgBuf* pMsgBuf, timezone_t tz, void* charsetCxt) {
1383
  int64_t  iv;
174,499,686✔
1384
  uint64_t uv;
174,500,409✔
1385
  char*    endptr = NULL;
176,493,859✔
1386
  int32_t  code = TSDB_CODE_SUCCESS;
176,493,859✔
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;
176,493,859✔
1399
  val->type = pSchema->type;
176,496,626✔
1400

1401
  switch (pSchema->type) {
176,502,244✔
1402
    case TSDB_DATA_TYPE_BOOL: {
4,761,921✔
1403
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
4,761,921✔
1404
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
3,032,610✔
1405
          *(int8_t*)(&val->i64) = TRUE_VALUE;
2,009,497✔
1406
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
1,023,113✔
1407
          *(int8_t*)(&val->i64) = FALSE_VALUE;
989,002✔
1408
        } else if (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv)) {
34,111✔
1409
          *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
26,151✔
1410
        } else {
1411
          return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
7,960✔
1412
        }
1413
      } else if (pToken->type == TK_NK_INTEGER) {
1,729,311✔
1414
        *(int8_t*)(&val->i64) = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
1,704,635✔
1415
      } else if (pToken->type == TK_NK_FLOAT) {
24,676✔
1416
        *(int8_t*)(&val->i64) = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
11,144✔
1417
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
23,084✔
1418
                 (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv))) {
9,552✔
1419
        *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
9,552✔
1420
      } else {
1421
        return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
3,980✔
1422
      }
1423
      break;
4,749,981✔
1424
    }
1425

1426
    case TSDB_DATA_TYPE_TINYINT: {
3,939,452✔
1427
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
3,939,452✔
1428
      if (TSDB_CODE_SUCCESS != code) {
3,938,686✔
1429
        return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z);
10,348✔
1430
      } else if (!IS_VALID_TINYINT(iv)) {
3,928,338✔
1431
        return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z);
9,324✔
1432
      }
1433

1434
      *(int8_t*)(&val->i64) = iv;
3,919,014✔
1435
      break;
3,918,248✔
1436
    }
1437

1438
    case TSDB_DATA_TYPE_UTINYINT: {
997,399✔
1439
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
997,399✔
1440
      if (TSDB_CODE_SUCCESS != code) {
997,399✔
1441
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z);
1,478✔
1442
      } else if (uv > UINT8_MAX) {
995,921✔
1443
        return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z);
1,478✔
1444
      }
1445
      *(uint8_t*)(&val->i64) = uv;
994,443✔
1446
      break;
994,443✔
1447
    }
1448

1449
    case TSDB_DATA_TYPE_SMALLINT: {
4,061,802✔
1450
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
4,061,802✔
1451
      if (TSDB_CODE_SUCCESS != code) {
4,061,802✔
1452
        return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z);
10,348✔
1453
      } else if (!IS_VALID_SMALLINT(iv)) {
4,051,454✔
1454
        return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z);
9,324✔
1455
      }
1456
      *(int16_t*)(&val->i64) = iv;
4,042,130✔
1457
      break;
4,042,130✔
1458
    }
1459

1460
    case TSDB_DATA_TYPE_USMALLINT: {
1,016,896✔
1461
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,016,896✔
1462
      if (TSDB_CODE_SUCCESS != code) {
1,016,896✔
1463
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z);
1,478✔
1464
      } else if (uv > UINT16_MAX) {
1,015,418✔
1465
        return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z);
1,478✔
1466
      }
1467
      *(uint16_t*)(&val->i64) = uv;
1,013,940✔
1468
      break;
1,013,940✔
1469
    }
1470

1471
    case TSDB_DATA_TYPE_INT: {
56,938,359✔
1472
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
56,938,359✔
1473
      if (TSDB_CODE_SUCCESS != code) {
56,928,020✔
1474
        return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z);
13,008✔
1475
      } else if (!IS_VALID_INT(iv)) {
56,915,012✔
1476
        return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z);
4,746✔
1477
      }
1478
      *(int32_t*)(&val->i64) = iv;
56,911,022✔
1479
      break;
56,887,079✔
1480
    }
1481

1482
    case TSDB_DATA_TYPE_UINT: {
1,088,378✔
1483
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,088,378✔
1484
      if (TSDB_CODE_SUCCESS != code) {
1,088,378✔
1485
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z);
17,398✔
1486
      } else if (uv > UINT32_MAX) {
1,070,980✔
1487
        return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z);
2,274✔
1488
      }
1489
      *(uint32_t*)(&val->i64) = uv;
1,068,706✔
1490
      break;
1,068,706✔
1491
    }
1492

1493
    case TSDB_DATA_TYPE_BIGINT: {
10,790,497✔
1494
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
10,790,497✔
1495
      if (TSDB_CODE_SUCCESS != code) {
10,790,497✔
1496
        return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z);
21,092✔
1497
      }
1498
      val->i64 = iv;
10,769,405✔
1499
      break;
10,769,405✔
1500
    }
1501

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

1511
    case TSDB_DATA_TYPE_FLOAT: {
3,359,924✔
1512
      double dv;
3,276,520✔
1513
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
3,359,924✔
1514
      if (TSDB_CODE_SUCCESS != code) {
3,359,924✔
1515
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
11,856✔
1516
      }
1517
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
3,348,068✔
1518
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
10,916✔
1519
      }
1520
      *(float*)(&val->i64) = dv;
3,337,152✔
1521
      break;
3,337,152✔
1522
    }
1523

1524
    case TSDB_DATA_TYPE_DOUBLE: {
12,923,809✔
1525
      double dv;
12,827,594✔
1526
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
12,923,809✔
1527
      if (TSDB_CODE_SUCCESS != code) {
12,923,809✔
1528
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
20,696✔
1529
      }
1530
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && ERRNO == ERANGE) || isinf(dv) || isnan(dv)) {
12,903,113✔
UNCOV
1531
        return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
×
1532
      }
1533

1534
      *(double*)(&val->i64) = dv;
12,903,113✔
1535
      break;
12,903,113✔
1536
    }
1537

1538
    case TSDB_DATA_TYPE_BINARY: {
59,093,891✔
1539
      // Too long values will raise the invalid sql error message
1540
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
59,093,891✔
1541
        return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
138,166✔
1542
      }
1543
      val->pData = taosStrdup(pToken->z);
58,949,453✔
1544
      if (!val->pData) {
58,955,413✔
1545
        return terrno;
×
1546
      }
1547
      val->nData = pToken->n;
58,935,985✔
1548
      break;
58,947,189✔
1549
    }
1550
    case TSDB_DATA_TYPE_VARBINARY: {
484,417✔
1551
      code = parseVarbinary(pToken, &val->pData, &val->nData, pSchema->bytes);
484,417✔
1552
      if (code != TSDB_CODE_SUCCESS) {
484,417✔
1553
        return generateSyntaxErrMsg(pMsgBuf, code, pSchema->name);
38,208✔
1554
      }
1555
      break;
446,209✔
1556
    }
1557
    case TSDB_DATA_TYPE_GEOMETRY: {
381,604✔
1558
      unsigned char* output = NULL;
381,604✔
1559
      size_t         size = 0;
381,604✔
1560

1561
      code = parseGeometry(pToken, &output, &size);
381,604✔
1562
      if (code != TSDB_CODE_SUCCESS) {
381,604✔
1563
        code = buildSyntaxErrMsg(pMsgBuf, getGeosErrMsg(code), pToken->z);
15,920✔
1564
      } else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
365,684✔
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);
365,684✔
1569
        if (NULL == val->pData) {
365,684✔
1570
          code = terrno;
×
1571
        } else {
1572
          memcpy(val->pData, output, size);
365,684✔
1573
          val->nData = size;
365,684✔
1574
        }
1575
      }
1576

1577
      geosFreeBuffer(output);
381,604✔
1578
      break;
381,604✔
1579
    }
1580

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

1608
      val->i64 = iv;
2,276,885✔
1609
      break;
2,276,885✔
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;
175,995,833✔
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) {
20,183,748✔
1624
  int32_t code = insInitBoundColsInfo(getNumOfTags(pStmt->pTableMeta), &pCxt->tags);
20,183,748✔
1625
  if (TSDB_CODE_SUCCESS != code) {
20,187,900✔
1626
    return code;
×
1627
  }
1628

1629
  SToken  token;
1630
  int32_t index = 0;
20,187,900✔
1631
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
20,189,614✔
1632
  if (TK_NK_LP != token.type) {
20,184,086✔
1633
    return TSDB_CODE_SUCCESS;
19,935,540✔
1634
  }
1635

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

1640
int32_t parseTagValue(SMsgBuf* pMsgBuf, const char** pSql, uint8_t precision, SSchema* pTagSchema, SToken* pToken,
177,600,597✔
1641
                      SArray* pTagName, SArray* pTagVals, STag** pTag, timezone_t tz, void* charsetCxt) {
1642
  bool isNull = isNullValue(pTagSchema->type, pToken);
177,600,597✔
1643
  if (!isNull && pTagName) {
177,601,539✔
1644
    if (NULL == taosArrayPush(pTagName, pTagSchema->name)) {
336,203,598✔
1645
      return terrno;
×
1646
    }
1647
  }
1648

1649
  if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
177,583,015✔
1650
    if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
699,195✔
1651
      return buildSyntaxErrMsg(pMsgBuf, "json string too long than 4095", pToken->z);
501✔
1652
    }
1653

1654
    if (isNull) {
705,845✔
1655
      return tTagNew(pTagVals, 1, true, pTag);
30,254✔
1656
    } else {
1657
      return parseJsontoTagData(pToken->z, pTagVals, pTag, pMsgBuf, charsetCxt);
675,591✔
1658
    }
1659
  }
1660

1661
  if (isNull) return 0;
176,890,361✔
1662

1663
  STagVal val = {0};
176,517,104✔
1664
  int32_t code = parseTagToken(pSql, pToken, pTagSchema, precision, &val, pMsgBuf, tz, charsetCxt);
176,521,124✔
1665
  if (TSDB_CODE_SUCCESS == code) {
176,485,317✔
1666
    if (NULL == taosArrayPush(pTagVals, &val)) {
176,014,850✔
1667
      code = terrno;
×
1668
    }
1669
  }
1670

1671
  if (TSDB_CODE_SUCCESS != code && IS_VAR_DATA_TYPE(val.type)) {
176,526,935✔
1672
    taosMemoryFree(val.pData);
323,775✔
1673
  }
1674

1675
  return code;
176,515,163✔
1676
}
1677

1678
static int32_t buildCreateTbReq(SVnodeModifyOpStmt* pStmt, STag* pTag, SArray* pTagName) {
12,069,017✔
1679
  if (pStmt->pCreateTblReq) {
12,069,017✔
1680
    tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
×
1681
    taosMemoryFreeClear(pStmt->pCreateTblReq);
×
1682
  }
1683
  pStmt->pCreateTblReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
12,076,219✔
1684
  if (NULL == pStmt->pCreateTblReq) {
12,052,199✔
1685
    return terrno;
×
1686
  }
1687
  return insBuildCreateTbReq(pStmt->pCreateTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid,
12,074,497✔
1688
                             pStmt->usingTableName.tname, pTagName, pStmt->pTableMeta->tableInfo.numOfTags,
12,056,665✔
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 &&
709,947✔
1700
       pToken->type != TK_FROM_BASE64 && pToken->type != TK_TO_BASE64 &&
702,117✔
1701
       pToken->type != TK_MD5 && pToken->type != TK_SHA && pToken->type != TK_SHA1 && pToken->type != TK_SHA2 &&
697,877✔
1702
       pToken->type != TK_AES_ENCRYPT && pToken->type != TK_AES_DECRYPT &&
683,037✔
1703
       pToken->type != TK_SM4_ENCRYPT && pToken->type != TK_SM4_DECRYPT) ||
678,797✔
1704
      (pToken->n == 0) || (pToken->type == TK_NK_RP)) {
2,147,483,647✔
1705
    return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z);
1,482✔
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) {
354,967✔
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);
40,833✔
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,262✔
1739
  SValueNode* pValue = NULL;
5,262✔
1740
  int32_t     code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pValue);
5,262✔
1741
  if (NULL == pValue) {
5,262✔
1742
    return code;
×
1743
  }
1744

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

1749
  switch (pVal->type) {
5,262✔
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:
4,836✔
1763
      pValue->datum.i = *(int32_t*)(&pVal->i64);
4,836✔
1764
      *(int32_t*)&pValue->typeData = pValue->datum.i;
4,836✔
1765
      break;
4,836✔
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:
426✔
1779
    case TSDB_DATA_TYPE_VARBINARY:
1780
    case TSDB_DATA_TYPE_NCHAR:
1781
      pValue->datum.p = taosMemoryCalloc(1, pVal->nData + VARSTR_HEADER_SIZE);
426✔
1782
      if (NULL == pValue->datum.p) {
426✔
1783
        return terrno;
×
1784
      }
1785
      varDataSetLen(pValue->datum.p, pVal->nData);
426✔
1786
      memcpy(varDataVal(pValue->datum.p), pVal->pData, pVal->nData);
426✔
1787
      break;
426✔
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,262✔
1816
}
1817

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

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

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

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

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

1862
// pSql -> tag1_value, ...)
1863
static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool autoCreate) {
20,180,351✔
1864
  int32_t  code = TSDB_CODE_SUCCESS;
20,180,351✔
1865
  SSchema* pSchema = getTableTagSchema(pStmt->pTableMeta);
20,180,351✔
1866
  SArray*  pTagVals = NULL;
20,182,089✔
1867
  SArray*  pTagName = NULL;
20,182,089✔
1868
  uint8_t  precision = pStmt->pTableMeta->tableInfo.precision;
20,182,089✔
1869
  SToken   token;
19,972,131✔
1870
  bool     isJson = false;
20,175,885✔
1871
  STag*    pTag = NULL;
20,175,885✔
1872
  uint8_t* pTagsIndex;
1873
  int32_t  numOfTags = 0;
20,176,231✔
1874

1875
  if (pCxt->pComCxt->stmtBindVersion == 2) {  // only support stmt2
20,176,231✔
1876
    pTagsIndex = taosMemoryCalloc(pCxt->tags.numOfBound, sizeof(uint8_t));
14,313✔
1877
  }
1878

1879
  if (!(pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal))) ||
40,352,840✔
1880
      !(pTagName = taosArrayInit(pCxt->tags.numOfBound, TSDB_COL_NAME_LEN))) {
20,174,203✔
1881
    code = terrno;
×
1882
    goto _exit;
×
1883
  }
1884

1885
  for (int i = 0; TSDB_CODE_SUCCESS == code && i < pCxt->tags.numOfBound; ++i) {
49,798,800✔
1886
    NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
29,642,099✔
1887

1888
    if (token.type == TK_NK_QUESTION) {
29,630,439✔
1889
      if (pCxt->pComCxt->stmtBindVersion == 0) {
43,408✔
1890
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", token.z);
×
1891
        break;
×
1892
      }
1893

1894
      continue;
43,408✔
1895
    }
1896

1897
    SSchema* pTagSchema = &pSchema[pCxt->tags.pColIndex[i]];
29,587,031✔
1898
    isJson = pTagSchema->type == TSDB_DATA_TYPE_JSON;
29,590,813✔
1899
    code = checkAndTrimValue(&token, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
29,591,827✔
1900
    if (TSDB_CODE_SUCCESS == code && TK_NK_VARIABLE == token.type) {
29,595,247✔
1901
      code = buildSyntaxErrMsg(&pCxt->msg, "not expected tags values ", token.z);
×
1902
    }
1903
    if (TSDB_CODE_SUCCESS == code) {
29,597,291✔
1904
      code = parseTagValue(&pCxt->msg, &pStmt->pSql, precision, pTagSchema, &token, pTagName, pTagVals, &pTag,
58,769,081✔
1905
                           pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
58,764,977✔
1906
    }
1907
    if (pCxt->pComCxt->stmtBindVersion == 2) {
29,591,497✔
1908
      pTagsIndex[numOfTags++] = pCxt->tags.pColIndex[i];
11,694✔
1909
    }
1910
  }
1911

1912
  if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pTagCond) {
20,162,551✔
1913
    code = checkSubtablePrivilege(pTagVals, pTagName, &pStmt->pTagCond);
364✔
1914
  }
1915

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

1937
  if (TSDB_CODE_SUCCESS == code && !isJson) {
20,168,899✔
1938
    code = tTagNew(pTagVals, 1, false, &pTag);
19,687,495✔
1939
  }
1940

1941
  if (TSDB_CODE_SUCCESS == code && !autoCreate) {
20,165,833✔
1942
    code = buildCreateTbReq(pStmt, pTag, pTagName);
12,074,505✔
1943
    pTag = NULL;
12,076,211✔
1944
  }
1945

1946
_exit:
20,151,944✔
1947
  if (pCxt->tags.parseredTags == NULL) {
20,182,451✔
1948
    for (int32_t i = 0; i < taosArrayGetSize(pTagVals); ++i) {
49,518,995✔
1949
      STagVal* p = (STagVal*)TARRAY_GET_ELEM(pTagVals, i);
29,359,427✔
1950
      if (IS_VAR_DATA_TYPE(p->type)) {
29,342,625✔
1951
        taosMemoryFreeClear(p->pData);
11,245,333✔
1952
      }
1953
    }
1954
    taosArrayDestroy(pTagVals);
20,165,764✔
1955
    taosArrayDestroy(pTagName);
20,178,438✔
1956
    if (pCxt->pComCxt->stmtBindVersion == 2) {
20,171,204✔
1957
      taosMemoryFreeClear(pTagsIndex);
13,728✔
1958
    }
1959
  }
1960

1961
  tTagFree(pTag);
20,181,405✔
1962
  return code;
20,173,181✔
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) {
20,184,440✔
1968
  SToken token;
19,976,701✔
1969
  NEXT_TOKEN(pStmt->pSql, token);
20,185,792✔
1970
  if (TK_TAGS != token.type) {
20,185,108✔
1971
    return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
3,043✔
1972
  }
1973

1974
  NEXT_TOKEN(pStmt->pSql, token);
20,182,065✔
1975
  if (TK_NK_LP != token.type) {
20,177,969✔
1976
    return buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
×
1977
  }
1978

1979
  int32_t code = parseTagsClauseImpl(pCxt, pStmt, autoCreate);
20,177,969✔
1980
  if (TSDB_CODE_SUCCESS == code) {
20,179,015✔
1981
    NEXT_VALID_TOKEN(pStmt->pSql, token);
29,101,728✔
1982
    if (TK_NK_COMMA == token.type) {
19,897,826✔
1983
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
712✔
1984
    } else if (TK_NK_RP != token.type) {
19,897,114✔
1985
      code = buildSyntaxErrMsg(&pCxt->msg, ") is expected", token.z);
17,672✔
1986
    }
1987
  }
1988
  return code;
20,177,985✔
1989
}
1990

1991
static int32_t storeChildTableMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
12,354,307✔
1992
  pStmt->pTableMeta->suid = pStmt->pTableMeta->uid;
12,354,307✔
1993
  pStmt->pTableMeta->uid = pStmt->totalTbNum;
12,356,713✔
1994
  pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;
12,351,201✔
1995

1996
  STableMeta* pBackup = NULL;
12,353,599✔
1997
  if (TSDB_CODE_SUCCESS != cloneTableMeta(pStmt->pTableMeta, &pBackup)) {
12,352,577✔
1998
    return TSDB_CODE_OUT_OF_MEMORY;
×
1999
  }
2000

2001
  char    tbFName[TSDB_TABLE_FNAME_LEN];
12,330,628✔
2002
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
12,356,705✔
2003
  if (TSDB_CODE_SUCCESS != code) {
12,353,253✔
2004
    taosMemoryFree(pBackup);
×
2005
    return code;
×
2006
  }
2007
  code = taosHashPut(pStmt->pSubTableHashObj, tbFName, strlen(tbFName), &pBackup, POINTER_BYTES);
12,353,253✔
2008
  if (TSDB_CODE_SUCCESS != code) {
12,361,179✔
2009
    taosMemoryFree(pBackup);
×
2010
  }
2011
  return code;
12,357,035✔
2012
}
2013

2014
static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
12,073,177✔
2015
  do {
9,016✔
2016
    int32_t index = 0;
12,073,177✔
2017
    SToken  token;
2018
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
12,077,289✔
2019
    if (TK_TTL == token.type) {
12,074,891✔
2020
      pStmt->pSql += index;
9,016✔
2021
      NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
9,016✔
2022
      if (TK_NK_INTEGER != token.type) {
9,016✔
2023
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
×
2024
      }
2025
      pStmt->pCreateTblReq->ttl = taosStr2Int32(token.z, NULL, 10);
9,016✔
2026
      if (pStmt->pCreateTblReq->ttl < 0) {
9,016✔
2027
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
709✔
2028
      }
2029
    } else if (TK_COMMENT == token.type) {
12,065,875✔
2030
      pStmt->pSql += index;
709✔
2031
      NEXT_TOKEN(pStmt->pSql, token);
709✔
2032
      if (TK_NK_STRING != token.type) {
709✔
2033
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option comment", token.z);
×
2034
      }
2035
      if (token.n >= TSDB_TB_COMMENT_LEN) {
709✔
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);
709✔
2039
      pStmt->pCreateTblReq->comment = taosStrndup(pCxt->tmpTokenBuf, len);
709✔
2040
      if (NULL == pStmt->pCreateTblReq->comment) {
709✔
2041
        return terrno;
×
2042
      }
2043
      pStmt->pCreateTblReq->commentLen = len;
709✔
2044
    } else {
2045
      break;
12,065,166✔
2046
    }
2047
  } while (1);
2048
  return TSDB_CODE_SUCCESS;
12,066,896✔
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) {
554,064,573✔
2058
  if (!pStmt->usingTableProcessing || pCxt->usingDuplicateTable) {
554,064,573✔
2059
    return TSDB_CODE_SUCCESS;
541,713,250✔
2060
  }
2061

2062
  int32_t code = parseBoundTagsClause(pCxt, pStmt);
12,357,798✔
2063
  if (TSDB_CODE_SUCCESS == code) {
12,351,877✔
2064
    code = parseTagsClause(pCxt, pStmt, false);
12,352,915✔
2065
  }
2066
  if (TSDB_CODE_SUCCESS == code) {
12,345,037✔
2067
    code = parseTableOptions(pCxt, pStmt);
12,064,829✔
2068
  }
2069

2070
  return code;
12,351,941✔
2071
}
2072

2073
static void setUserAuthInfo(SParseContext* pCxt, SName* pTbName, SUserAuthInfo* pInfo) {
534,155,542✔
2074
  snprintf(pInfo->user, sizeof(pInfo->user), "%s", pCxt->pUser);
534,155,542✔
2075
  memcpy(&pInfo->tbName, pTbName, sizeof(SName));
534,154,119✔
2076
  pInfo->userId = pCxt->userId;
534,161,000✔
2077
  pInfo->privType = PRIV_TBL_INSERT;
534,158,293✔
2078
  pInfo->objType = PRIV_OBJ_TBL;
534,162,987✔
2079
}
534,161,392✔
2080

2081
static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool isAudit, bool* pMissCache, bool* pWithInsertCond, SNode** pTagCond,
534,150,823✔
2082
                         SArray** pPrivCols) {
2083
  int32_t       code = TSDB_CODE_SUCCESS;
534,150,823✔
2084
  SUserAuthInfo authInfo = {0};
534,150,823✔
2085
  setUserAuthInfo(pCxt, pTbName, &authInfo);
534,151,162✔
2086
  if (isAudit) {
534,156,047✔
2087
    authInfo.privType = PRIV_AUDIT_TBL_INSERT;
×
2088
    authInfo.objType = PRIV_OBJ_CLUSTER;
×
2089
  }
2090
  SUserAuthRes authRes = {0};
534,156,047✔
2091
  SUserAuthRsp authRsp = {.exists = 1};
534,156,435✔
2092
  if (pCxt->async) {
534,158,616✔
2093
    code = catalogChkAuthFromCache(pCxt->pCatalog, &authInfo, &authRes, &authRsp);
534,017,010✔
2094
  } else {
2095
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
257,338✔
2096
                             .requestId = pCxt->requestId,
144,172✔
2097
                             .requestObjRefId = pCxt->requestRid,
144,172✔
2098
                             .mgmtEps = pCxt->mgmtEpSet};
2099
    code = catalogChkAuth(pCxt->pCatalog, &conn, &authInfo, &authRes);
144,968✔
2100
  }
2101
  if (TSDB_CODE_SUCCESS == code) {
534,156,039✔
2102
    if (0 == authRsp.exists) {
534,156,007✔
2103
      *pMissCache = true;
32,664✔
2104
    } else if (!authRes.pass[AUTH_RES_BASIC]) {
534,123,343✔
2105
      code = TSDB_CODE_PAR_PERMISSION_DENIED;
4,416✔
2106
    } else {
2107
      if (pTagCond && authRes.pCond[AUTH_RES_BASIC]) {
534,118,927✔
2108
        *pTagCond = authRes.pCond[AUTH_RES_BASIC];
3,806✔
2109
      }
2110
      if (pPrivCols && authRes.pCols) {
534,118,927✔
2111
        *pPrivCols = authRes.pCols;
4,072✔
2112
      }
2113
      *pMissCache = false;
534,118,927✔
2114
    }
2115
    if (pWithInsertCond) {
534,148,648✔
2116
      *pWithInsertCond = (authRsp.withInsertCond == 1);
534,154,979✔
2117
    }
2118
  }
2119
  return code;
534,151,806✔
2120
}
2121

2122
static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, STableMeta** pTableMeta, bool* pMissCache,
33,610,008✔
2123
                            bool bUsingTable) {
2124
  SParseContext* pComCxt = pCxt->pComCxt;
33,610,008✔
2125
  int32_t        code = TSDB_CODE_SUCCESS;
33,609,612✔
2126
  if (pComCxt->async) {
33,609,612✔
2127
    if (bUsingTable) {
26,606,600✔
2128
      code = catalogGetCachedSTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
13,310,065✔
2129
    } else {
2130
      code = catalogGetCachedTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
13,296,535✔
2131
    }
2132
  } else {
2133
    SRequestConnInfo conn = {.pTrans = pComCxt->pTransporter,
13,954,803✔
2134
                             .requestId = pComCxt->requestId,
7,004,150✔
2135
                             .requestObjRefId = pComCxt->requestRid,
7,002,383✔
2136
                             .mgmtEps = pComCxt->mgmtEpSet};
2137
    if (bUsingTable) {
6,997,329✔
2138
      code = catalogGetSTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
6,849,459✔
2139
    } else {
2140
      code = catalogGetTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
147,870✔
2141
    }
2142
  }
2143
  if (TSDB_CODE_SUCCESS == code) {
33,609,015✔
2144
    if (NULL == *pTableMeta) {
33,608,039✔
2145
      *pMissCache = true;
5,532,836✔
2146
    } else if (bUsingTable && TSDB_SUPER_TABLE != (*pTableMeta)->tableType) {
28,072,105✔
2147
      code = buildInvalidOperationMsg(&pCxt->msg, "create table only from super table is allowed");
×
2148
    } else if (((*pTableMeta)->virtualStb) || TSDB_VIRTUAL_CHILD_TABLE == (*pTableMeta)->tableType ||
28,073,127✔
2149
               TSDB_VIRTUAL_NORMAL_TABLE == (*pTableMeta)->tableType) {
28,073,932✔
2150
      code = TSDB_CODE_VTABLE_NOT_SUPPORT_STMT;
1,902✔
2151
    }
2152
  }
2153
  return code;
33,604,973✔
2154
}
2155

2156
static int32_t getTargetTableVgroup(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool isStb, bool* pMissCache) {
14,811,908✔
2157
  int32_t     code = TSDB_CODE_SUCCESS;
14,811,908✔
2158
  SVgroupInfo vg;
14,592,066✔
2159
  bool        exists = true;
14,815,456✔
2160
  if (pCxt->async) {
14,817,186✔
2161
    code = catalogGetCachedTableHashVgroup(pCxt->pCatalog, &pStmt->targetTableName, &vg, &exists);
7,830,291✔
2162
  } else {
2163
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
13,911,305✔
2164
                             .requestId = pCxt->requestId,
6,978,508✔
2165
                             .requestObjRefId = pCxt->requestRid,
6,977,037✔
2166
                             .mgmtEps = pCxt->mgmtEpSet};
2167
    code = catalogGetTableHashVgroup(pCxt->pCatalog, &conn, &pStmt->targetTableName, &vg);
6,983,324✔
2168
  }
2169
  if (TSDB_CODE_SUCCESS == code) {
14,815,715✔
2170
    if (exists) {
14,815,715✔
2171
      if (isStb) {
14,817,419✔
2172
        pStmt->pTableMeta->vgId = vg.vgId;
14,688,451✔
2173
      }
2174
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
14,813,629✔
2175
    }
2176
    *pMissCache = !exists;
14,825,845✔
2177
  }
2178
  return code;
14,825,169✔
2179
}
2180

2181
static int32_t getTargetTableMetaAndVgroup(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) {
534,118,695✔
2182
  SParseContext* pComCxt = pCxt->pComCxt;
534,118,695✔
2183
  int32_t        code = TSDB_CODE_SUCCESS;
534,118,610✔
2184
  if (pComCxt->async) {
534,118,610✔
2185
    {
2186
      SVgroupInfo vg;
530,256,448✔
2187
      code = catalogGetCachedTableVgMeta(pComCxt->pCatalog, &pStmt->targetTableName, &vg, &pStmt->pTableMeta);
533,975,498✔
2188
      if (TSDB_CODE_SUCCESS == code) {
533,970,066✔
2189
        if (NULL != pStmt->pTableMeta) {
533,972,727✔
2190
          if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE) {
532,526,443✔
2191
            pStmt->stbSyntax = true;
251,398✔
2192
          } else {
2193
            code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
532,268,028✔
2194
          }
2195
        }
2196
        *pMissCache = (NULL == pStmt->pTableMeta);
533,983,662✔
2197
      }
2198
    }
2199
  } else {
2200
    bool bUsingTable = false;
144,008✔
2201
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pStmt->pTableMeta, pMissCache, bUsingTable);
144,008✔
2202
    if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
144,122✔
2203
      if (TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
143,478✔
2204
        pStmt->stbSyntax = true;
11,751✔
2205
      }
2206
      if (!pStmt->stbSyntax) {
143,562✔
2207
        code = getTargetTableVgroup(pCxt->pComCxt, pStmt, false, &pCxt->missCache);
130,960✔
2208
      }
2209
    }
2210
  }
2211
  return code;
534,122,145✔
2212
}
2213

2214
static int32_t collectUseTable(const SName* pName, SHashObj* pTable) {
10,144,875✔
2215
  char    fullName[TSDB_TABLE_FNAME_LEN];
10,075,501✔
2216
  int32_t code = tNameExtractFullName(pName, fullName);
10,146,943✔
2217
  if (TSDB_CODE_SUCCESS != code) {
10,151,071✔
2218
    return code;
×
2219
  }
2220
  return taosHashPut(pTable, fullName, strlen(fullName), pName, sizeof(SName));
10,151,071✔
2221
}
2222

2223
static int32_t collectUseDatabase(const SName* pName, SHashObj* pDbs) {
7,223,059✔
2224
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
7,223,059✔
2225
  (void)tNameGetFullDbName(pName, dbFName);
7,225,127✔
2226
  return taosHashPut(pDbs, dbFName, strlen(dbFName), dbFName, sizeof(dbFName));
7,232,093✔
2227
}
2228

2229
static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
534,239,001✔
2230
  if (pCxt->forceUpdate) {
534,239,001✔
2231
    pCxt->missCache = true;
80,708✔
2232
    return TSDB_CODE_SUCCESS;
80,708✔
2233
  }
2234
  SNode*  pTagCond = NULL;
534,162,065✔
2235
  SArray* pPrivCols = NULL;
534,162,178✔
2236
  bool    withInsertCond = false;
534,158,355✔
2237
  int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, false, &pCxt->missCache, &withInsertCond, &pTagCond,
534,158,773✔
2238
                           &pPrivCols);
2239
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
534,158,940✔
2240
    code = getTargetTableMetaAndVgroup(pCxt, pStmt, &pCxt->missCache);
534,120,842✔
2241
  }
2242

2243
  if (TSDB_CODE_SUCCESS == code) {
534,152,031✔
2244
    if (pPrivCols) pStmt->pPrivCols = pPrivCols;
534,146,214✔
2245
#ifdef TD_ENTERPRISE
2246
#if 0
2247
    if (pStmt->pTableMeta && pStmt->pTableMeta->isAudit) {
2248
      // recheck for audit table
2249
      code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, true, &pCxt->missCache, NULL, NULL, NULL);
2250
      if (TSDB_CODE_SUCCESS != code) {
2251
        nodesDestroyNode(pTagCond);
2252
        return code;
2253
      }
2254
    }
2255
#endif
2256
    if (!pCxt->missCache) {
534,146,214✔
2257
      if (TSDB_SUPER_TABLE != pStmt->pTableMeta->tableType) {
532,668,439✔
2258
        pCxt->needTableTagVal = (NULL != pTagCond);
532,400,378✔
2259
        pCxt->missCache = (NULL != pTagCond);
532,411,736✔
2260
      } else {
2261
        pStmt->pTagCond = pTagCond;
263,149✔
2262
        pTagCond = NULL;
263,149✔
2263
      }
2264
    } else if (withInsertCond && !pCxt->pComCxt->isSuperUser) {
1,477,278✔
2265
      // If miss cache, always request tag value and reserved for permission check later if pTagCond exists. This may
2266
      // lead to redundant request but ensure correctness, and this only happens when cache is invalid or first time
2267
      // insert.
2268
      pCxt->needTableTagVal = true;
1,820✔
2269
    }
2270
#else
2271
    pStmt->pTagCond = NULL;
2272
#endif
2273
  }
2274
  if (pTagCond) nodesDestroyNode(pTagCond);
534,155,208✔
2275

2276
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
534,155,208✔
2277
    code = collectUseDatabase(&pStmt->targetTableName, pStmt->pDbFNameHashObj);
143,649✔
2278
    if (TSDB_CODE_SUCCESS == code) {
143,649✔
2279
      code = collectUseTable(&pStmt->targetTableName, pStmt->pTableNameHashObj);
143,649✔
2280
    }
2281
  }
2282
  return code;
534,152,225✔
2283
}
2284

2285
static int32_t preParseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
20,225,358✔
2286
  return insCreateSName(&pStmt->usingTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
20,225,358✔
2287
}
2288

2289
static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* ctbCacheHit) {
20,224,456✔
2290
  int32_t     code = TSDB_CODE_SUCCESS;
20,224,456✔
2291
  STableMeta* pStableMeta = NULL;
20,224,456✔
2292
  STableMeta* pCtableMeta = NULL;
20,225,148✔
2293
  if (pCxt->forceUpdate) {
20,227,224✔
2294
    pCxt->missCache = true;
614✔
2295
    return TSDB_CODE_SUCCESS;
614✔
2296
  }
2297
  char stableFName[TSDB_TABLE_FNAME_LEN];
20,015,924✔
2298
  code = tNameExtractFullName(&pStmt->usingTableName, stableFName);
20,225,918✔
2299
  if (TSDB_CODE_SUCCESS != code) {
20,230,408✔
2300
    return code;
×
2301
  }
2302

2303
  char ctableFName[TSDB_TABLE_FNAME_LEN];
20,022,474✔
2304
  code = tNameExtractFullName(&pStmt->targetTableName, ctableFName);
20,227,648✔
2305
  if (TSDB_CODE_SUCCESS != code) {
20,229,362✔
2306
    return code;
×
2307
  }
2308

2309
  if (strcmp(stableFName, ctableFName) == 0) {
20,229,362✔
2310
    return TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
712✔
2311
  }
2312
  if (!pCxt->missCache) {
20,228,650✔
2313
    char tbFName[TSDB_TABLE_FNAME_LEN];
20,017,602✔
2314
    code = tNameExtractFullName(&pStmt->usingTableName, tbFName);
20,225,882✔
2315
    if (TSDB_CODE_SUCCESS != code) {
20,229,350✔
2316
      return code;
×
2317
    }
2318
    STableMeta** ppStableMeta = taosHashGet(pStmt->pSuperTableHashObj, tbFName, strlen(tbFName));
20,229,350✔
2319
    if (NULL != ppStableMeta) {
20,223,484✔
2320
      pStableMeta = *ppStableMeta;
56,491✔
2321
    }
2322
    if (NULL == pStableMeta) {
20,223,484✔
2323
      bool bUsingTable = true;
20,168,086✔
2324
      code = getTableMeta(pCxt, &pStmt->usingTableName, &pStableMeta, &pCxt->missCache, bUsingTable);
20,168,086✔
2325
      if (TSDB_CODE_SUCCESS == code) {
20,156,796✔
2326
        code = taosHashPut(pStmt->pSuperTableHashObj, tbFName, strlen(tbFName), &pStableMeta, POINTER_BYTES);
20,155,315✔
2327
      } else {
2328
        taosMemoryFreeClear(pStableMeta);
1,481✔
2329
      }
2330
    }
2331
  }
2332
  if (pCxt->pComCxt->stmtBindVersion > 0) {
20,228,360✔
2333
    goto _no_ctb_cache;
6,849,843✔
2334
  }
2335

2336
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
13,368,161✔
2337
    bool bUsingTable = false;
13,299,475✔
2338
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pCtableMeta, &pCxt->missCache, bUsingTable);
13,299,475✔
2339
  }
2340

2341
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
13,368,161✔
2342
    code = (pStableMeta->suid == pCtableMeta->suid) ? TSDB_CODE_SUCCESS : TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
7,834,655✔
2343
    *ctbCacheHit = true;
7,834,655✔
2344
  }
2345
_no_ctb_cache:
20,017,933✔
2346
  if (TSDB_CODE_SUCCESS == code) {
20,217,320✔
2347
    if (*ctbCacheHit) {
20,218,197✔
2348
      code = cloneTableMeta(pCtableMeta, &pStmt->pTableMeta);
7,833,231✔
2349
    } else {
2350
      code = cloneTableMeta(pStableMeta, &pStmt->pTableMeta);
12,388,394✔
2351
    }
2352
  }
2353
  taosMemoryFree(pCtableMeta);
20,212,556✔
2354
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
20,210,842✔
2355
    code = getTargetTableVgroup(pCxt->pComCxt, pStmt, true, &pCxt->missCache);
14,683,993✔
2356
  }
2357
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
20,228,666✔
2358
    code = collectUseDatabase(&pStmt->usingTableName, pStmt->pDbFNameHashObj);
6,861,596✔
2359
    if (TSDB_CODE_SUCCESS == code) {
6,861,258✔
2360
      code = collectUseTable(&pStmt->usingTableName, pStmt->pTableNameHashObj);
6,861,596✔
2361
    }
2362
  }
2363
  return code;
20,230,034✔
2364
}
2365

2366
static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
20,226,050✔
2367
  SToken token;
20,018,116✔
2368
  NEXT_TOKEN(pStmt->pSql, token);
20,228,810✔
2369
  bool    ctbCacheHit = false;
20,229,494✔
2370
  int32_t code = preParseUsingTableName(pCxt, pStmt, &token);
20,230,186✔
2371
  if (TSDB_CODE_SUCCESS == code) {
20,230,878✔
2372
    code = getUsingTableSchema(pCxt, pStmt, &ctbCacheHit);
20,230,668✔
2373
    if (TSDB_CODE_SUCCESS == code && ctbCacheHit && !pCxt->missCache) {
20,228,616✔
2374
      pStmt->usingTableProcessing = false;
7,833,231✔
2375
      return ignoreUsingClauseAndCheckTagValues(pCxt, pStmt);
7,833,231✔
2376
    }
2377
  }
2378
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
12,395,595✔
2379
    code = storeChildTableMeta(pCxt, pStmt);
6,858,664✔
2380
  }
2381
  return code;
12,393,165✔
2382
}
2383

2384
// input pStmt->pSql:
2385
//   1(care). [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
2386
//   2. VALUES ... | FILE ...
2387
// output pStmt->pSql:
2388
//   1. [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
2389
//   2. VALUES ... | FILE ...
2390
static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
554,537,193✔
2391
  SToken  token;
2392
  int32_t index = 0;
554,537,193✔
2393
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
554,541,511✔
2394
  if (TK_USING != token.type) {
554,549,065✔
2395
    return getTargetTableSchema(pCxt, pStmt);
534,246,379✔
2396
  }
2397
  pStmt->usingTableProcessing = true;
20,302,686✔
2398
  pCxt->stmtTbNameFlag |= USING_CLAUSE;
20,299,918✔
2399
  // pStmt->pSql -> stb_name [(tag1_name, ...)
2400
  pStmt->pSql += index;
20,299,580✔
2401
  int32_t code = parseDuplicateUsingClause(pCxt, pStmt, &pCxt->usingDuplicateTable);
20,299,226✔
2402
  if (TSDB_CODE_SUCCESS == code && !pCxt->usingDuplicateTable) {
20,297,174✔
2403
    return parseUsingTableNameImpl(pCxt, pStmt);
20,226,742✔
2404
  }
2405
  return code;
71,116✔
2406
}
2407

2408
static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
554,579,136✔
2409
  int32_t code = insCreateSName(&pStmt->targetTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
554,579,136✔
2410
  if (TSDB_CODE_SUCCESS == code) {
554,574,478✔
2411
    if (IS_SYS_DBNAME(pStmt->targetTableName.dbname)) {
554,574,120✔
2412
      return TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED;
39,680✔
2413
    }
2414
  }
2415

2416
  return code;
554,537,838✔
2417
}
2418

2419
// input pStmt->pSql:
2420
//   1(care). [(field1_name, ...)] ...
2421
//   2. [ USING ... ] ...
2422
//   3. VALUES ... | FILE ...
2423
// output pStmt->pSql:
2424
//   1. [ USING ... ] ...
2425
//   2. VALUES ... | FILE ...
2426
static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
554,534,321✔
2427
  SToken  token;
2428
  int32_t index = 0;
554,534,321✔
2429
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
554,538,807✔
2430
  if (TK_NK_LP != token.type) {
554,549,044✔
2431
    return TSDB_CODE_SUCCESS;
511,282,361✔
2432
  }
2433

2434
  // pStmt->pSql -> field1_name, ...)
2435
  pStmt->pSql += index;
43,266,683✔
2436
  pStmt->pBoundCols = pStmt->pSql;
43,266,683✔
2437
  return skipParentheses(pCxt, &pStmt->pSql);
43,266,683✔
2438
}
2439

2440
static int32_t getTableDataCxt(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt** pTableCxt) {
553,786,613✔
2441
  if (pCxt->pComCxt->async) {
553,786,613✔
2442
    return insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid),
1,089,728,671✔
2443
                              pStmt->pTableMeta, &pStmt->pCreateTblReq, pTableCxt, false, false);
546,811,208✔
2444
  }
2445

2446
  char    tbFName[TSDB_TABLE_FNAME_LEN];
6,942,340✔
2447
  int32_t code = 0;
6,981,326✔
2448
  if ((pCxt->stmtTbNameFlag & NO_DATA_USING_CLAUSE) == USING_CLAUSE) {
6,981,326✔
2449
    tstrncpy(pStmt->targetTableName.tname, pStmt->usingTableName.tname, sizeof(pStmt->targetTableName.tname));
5,282✔
2450
    tstrncpy(pStmt->targetTableName.dbname, pStmt->usingTableName.dbname, sizeof(pStmt->targetTableName.dbname));
5,282✔
2451
    pStmt->targetTableName.type = TSDB_SUPER_TABLE;
5,282✔
2452
    pStmt->pTableMeta->tableType = TSDB_SUPER_TABLE;
5,282✔
2453
  }
2454

2455
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
6,987,860✔
2456

2457
  if (TSDB_CODE_SUCCESS != code) {
6,990,352✔
2458
    return code;
×
2459
  }
2460
  if (pStmt->usingTableProcessing) {
6,990,352✔
2461
    pStmt->pTableMeta->uid = 0;
6,852,746✔
2462
  }
2463
  return insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
6,988,992✔
2464
                            &pStmt->pCreateTblReq, pTableCxt, NULL != pCxt->pComCxt->pStmtCb, false);
6,987,978✔
2465
}
2466
#ifdef TD_ENTERPRISE
2467
static int32_t parseCheckNoBoundColPriv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
142✔
2468
  int32_t nPrivs = taosArrayGetSize(pStmt->pPrivCols);
142✔
2469
  if (nPrivs <= 0) {
142✔
2470
    return TSDB_CODE_SUCCESS;
×
2471
  }
2472
  int32_t nCols = pStmt->pTableMeta->tableInfo.numOfColumns;
142✔
2473
  /**
2474
   * It cann't provide the specific missing column info although with better performance. For better UE, we check each
2475
   * column one by one.
2476
   */
2477
  // if (nPrivs < nCols) return TSDB_CODE_PAR_COL_PERMISSION_DENIED;
2478

2479
  // both the schema and privCols are ordered by colId asc
2480
  SSchema* pSchemas = pStmt->pTableMeta->schema;
142✔
2481
  int32_t  j = 0;
142✔
2482
  for (int32_t i = 0; i < nCols; ++i) {
426✔
2483
    SSchema* pSchema = &pSchemas[i];
426✔
2484
    bool     found = false;
426✔
2485
    for (; j < nPrivs; ++j) {
426✔
2486
      SColNameFlag* pColFlag = (SColNameFlag*)TARRAY_GET_ELEM(pStmt->pPrivCols, j);
426✔
2487
      if (pColFlag->colId == pSchema->colId) {
426✔
2488
        found = true;
284✔
2489
        ++j;
284✔
2490
        break;
284✔
2491
      } else if (pColFlag->colId > pSchema->colId) {
142✔
2492
        break;
142✔
2493
      }
2494
    }
2495

2496
    if (!found) {
426✔
2497
      return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_COL_PERMISSION_DENIED, pSchema->name);
142✔
2498
    }
2499
  }
2500

2501
  return TSDB_CODE_SUCCESS;
×
2502
}
2503
#endif
2504

2505
static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) {
553,789,209✔
2506
  SToken  token;
2507
  int32_t index = 0;
553,789,209✔
2508
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
553,794,394✔
2509
  if (TK_NK_LP == token.type) {
553,790,999✔
2510
    pStmt->pSql += index;
94,878✔
2511
    if (NULL != pStmt->pBoundCols) {
94,878✔
2512
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
1,149✔
2513
    }
2514
    // pStmt->pSql -> field1_name, ...)
2515
    return parseBoundColumns(pCxt, pStmt, &pStmt->pSql, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo);
93,729✔
2516
  }
2517

2518
  if (NULL != pStmt->pBoundCols) {
553,696,121✔
2519
    return parseBoundColumns(pCxt, pStmt, &pStmt->pBoundCols, BOUND_COLUMNS, pStmt->pTableMeta,
43,034,709✔
2520
                             &pTableCxt->boundColsInfo);
2521
  } else if (pTableCxt->boundColsInfo.hasBoundCols) {
510,666,224✔
2522
    insResetBoundColsInfo(&pTableCxt->boundColsInfo);
3,156✔
2523
  } else if (NULL != pStmt->pPrivCols) {
510,655,935✔
2524
#ifdef TD_ENTERPRISE
2525
    PAR_ERR_RET(parseCheckNoBoundColPriv(pCxt, pStmt));
142✔
2526
#endif
2527
  }
2528

2529

2530
  return TSDB_CODE_SUCCESS;
510,658,270✔
2531
}
2532

2533
int32_t initTableColSubmitData(STableDataCxt* pTableCxt) {
1,675,555,734✔
2534
  if (0 == (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT)) {
1,675,555,734✔
2535
    return TSDB_CODE_SUCCESS;
1,668,576,592✔
2536
  }
2537

2538
  for (int32_t i = 0; i < pTableCxt->boundColsInfo.numOfBound; ++i) {
28,653,320✔
2539
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
21,660,403✔
2540
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
21,663,469✔
2541
    if (NULL == pCol) {
21,666,741✔
2542
      return terrno;
×
2543
    }
2544
    tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags);
21,666,741✔
2545
  }
2546

2547
  return TSDB_CODE_SUCCESS;
6,997,387✔
2548
}
2549

2550
int32_t initTableColSubmitDataWithBoundInfo(STableDataCxt* pTableCxt, SBoundColInfo pBoundColsInfo) {
7,224✔
2551
  qDestroyBoundColInfo(&(pTableCxt->boundColsInfo));
7,224✔
2552
  pTableCxt->boundColsInfo = pBoundColsInfo;
7,224✔
2553
  for (int32_t i = 0; i < pBoundColsInfo.numOfBound; ++i) {
23,445✔
2554
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
16,221✔
2555
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
16,221✔
2556
    if (NULL == pCol) {
16,221✔
2557
      return terrno;
×
2558
    }
2559
    tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags);
16,221✔
2560
  }
2561

2562
  return TSDB_CODE_SUCCESS;
7,224✔
2563
}
2564

2565
// input pStmt->pSql:
2566
//   1. [(tag1_name, ...)] ...
2567
//   2. VALUES ... | FILE ...
2568
// output pStmt->pSql: VALUES ... | FILE ...
2569
static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
554,064,608✔
2570
                                       STableDataCxt** pTableCxt) {
2571
  int32_t code = parseUsingClauseBottom(pCxt, pStmt);
554,064,608✔
2572
  if (TSDB_CODE_SUCCESS == code) {
554,066,895✔
2573
    code = getTableDataCxt(pCxt, pStmt, pTableCxt);
553,784,197✔
2574
  }
2575
  if (TSDB_CODE_SUCCESS == code) {
554,079,943✔
2576
    code = parseBoundColumnsClause(pCxt, pStmt, *pTableCxt);
553,798,875✔
2577
  }
2578
  if (TSDB_CODE_SUCCESS == code) {
554,075,744✔
2579
    code = initTableColSubmitData(*pTableCxt);
553,769,986✔
2580
  }
2581
  return code;
554,088,290✔
2582
}
2583

2584
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
2585
// output pStmt->pSql:
2586
//   1. [(tag1_name, ...)] ...
2587
//   2. VALUES ... | FILE ...
2588
static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
554,578,484✔
2589
  int32_t code = preParseTargetTableName(pCxt, pStmt, pTbName);
554,578,484✔
2590
  if (TSDB_CODE_SUCCESS == code) {
554,578,483✔
2591
    // option: [(field1_name, ...)]
2592
    code = preParseBoundColumnsClause(pCxt, pStmt);
554,537,346✔
2593
  }
2594
  if (TSDB_CODE_SUCCESS == code) {
554,583,845✔
2595
    // option: [USING stb_name]
2596
    code = parseUsingTableName(pCxt, pStmt);
554,540,040✔
2597
  }
2598
  return code;
554,567,858✔
2599
}
2600

2601
static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
2,147,483,647✔
2602
                                   const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) {
2603
  switch (pSchema->type) {
2,147,483,647✔
2604
    case TSDB_DATA_TYPE_BOOL: {
2,147,483,647✔
2605
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
2,147,483,647✔
2606
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
2,147,483,647✔
2607
          VALUE_SET_TRIVIAL_DATUM(&pVal->value, TRUE_VALUE);
2,147,483,647✔
2608
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
1,956,575,199✔
2609
          VALUE_SET_TRIVIAL_DATUM(&pVal->value, FALSE_VALUE);
1,953,476,837✔
2610
        } else if (TSDB_CODE_SUCCESS ==
21,492✔
2611
                   toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,160✔
2612
          int8_t v = (*(double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value) == 0 ? FALSE_VALUE : TRUE_VALUE);
16,716✔
2613
          valueSetDatum(&pVal->value, TSDB_DATA_TYPE_BOOL, &v, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes);
16,716✔
2614
        } else {
2615
          return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
4,776✔
2616
        }
2617
      } else if (pToken->type == TK_NK_INTEGER) {
2,147,483,647✔
2618
        int8_t v = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
2,147,483,647✔
2619
        VALUE_SET_TRIVIAL_DATUM(&pVal->value, v);
2,147,483,647✔
2620
      } else if (pToken->type == TK_NK_FLOAT) {
1,755,123✔
2621
        int8_t v = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
1,722,960✔
2622
        VALUE_SET_TRIVIAL_DATUM(&pVal->value, v);
1,722,960✔
2623
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
38,531✔
2624
                 (TSDB_CODE_SUCCESS ==
2625
                  toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value)))) {
31,367✔
2626
        int8_t v = *(double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value) == 0 ? FALSE_VALUE : TRUE_VALUE;
6,368✔
2627
        valueSetDatum(&pVal->value, TSDB_DATA_TYPE_BOOL, &v, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes);
6,368✔
2628
      } else {
2629
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
796✔
2630
      }
2631
      break;
2,147,483,647✔
2632
    }
2633
    case TSDB_DATA_TYPE_TINYINT: {
2,147,483,647✔
2634
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2635
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2636
        return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z);
9,882✔
2637
      } else if (!IS_VALID_TINYINT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2638
        return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z);
12,310,790✔
2639
      }
2640
      break;
2,147,483,647✔
2641
    }
2642
    case TSDB_DATA_TYPE_UTINYINT: {
2,147,483,647✔
2643
      int32_t code =
2644
          toUIntegerEx(pToken->z, pToken->n, pToken->type, (uint64_t*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2645
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2646
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z);
7,756✔
2647
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT8_MAX) {
2,147,483,647✔
2648
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z);
1,927✔
2649
      }
2650
      break;
2,147,483,647✔
2651
    }
2652
    case TSDB_DATA_TYPE_SMALLINT: {
2,147,483,647✔
2653
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2654
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2655
        return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z);
9,882✔
2656
      } else if (!IS_VALID_SMALLINT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2657
        return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z);
2,598,669✔
2658
      }
2659
      break;
2,147,483,647✔
2660
    }
2661
    case TSDB_DATA_TYPE_USMALLINT: {
2,147,483,647✔
2662
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2663
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2664
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z);
7,756✔
2665
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT16_MAX) {
2,147,483,647✔
2666
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z);
1,927✔
2667
      }
2668
      break;
2,147,483,647✔
2669
    }
2670
    case TSDB_DATA_TYPE_INT: {
2,147,483,647✔
2671
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2672
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2673
        return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z);
10,594✔
2674
      } else if (!IS_VALID_INT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2675
        return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z);
76,843,175✔
2676
      }
2677
      break;
2,147,483,647✔
2678
    }
2679
    case TSDB_DATA_TYPE_UINT: {
2,147,483,647✔
2680
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2681
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2682
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z);
21,865✔
2683
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT32_MAX) {
2,147,483,647✔
2684
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z);
3,519✔
2685
      }
2686
      break;
2,147,483,647✔
2687
    }
2688
    case TSDB_DATA_TYPE_BIGINT: {
2,147,483,647✔
2689
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2690
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2691
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z);
16,934✔
2692
      }
2693
      break;
2,147,483,647✔
2694
    }
2695
    case TSDB_DATA_TYPE_UBIGINT: {
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 bigint data", pToken->z);
213,370✔
2699
      }
2700
      break;
2,147,483,647✔
2701
    }
2702
    case TSDB_DATA_TYPE_FLOAT: {
2,147,483,647✔
2703
      double  dv;
2,147,483,647✔
2704
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
2,147,483,647✔
2705
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2706
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
8,664✔
2707
      }
2708
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
2,147,483,647✔
2709
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
880✔
2710
      }
2711
      float f = dv;
2,147,483,647✔
2712
      valueSetDatum(&pVal->value, TSDB_DATA_TYPE_FLOAT, &f, sizeof(f));
2,147,483,647✔
2713
      break;
2,147,483,647✔
2714
    }
2715
    case TSDB_DATA_TYPE_DOUBLE: {
2,147,483,647✔
2716
      double  dv;
2,147,483,647✔
2717
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
2,147,483,647✔
2718
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2719
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
15,032✔
2720
      }
2721
      if (isinf(dv) || isnan(dv)) {
2,147,483,647✔
2722
        return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
13,351✔
2723
      }
2724
      VALUE_SET_TRIVIAL_DATUM(&pVal->value, (*(int64_t*)&dv));
2,147,483,647✔
2725
      break;
2,147,483,647✔
2726
    }
2727
    case TSDB_DATA_TYPE_BINARY: {
2,147,483,647✔
2728
      return parseBinary(pCxt, pSql, pToken, pVal, pSchema);
2,147,483,647✔
2729
    }
2730
    case TSDB_DATA_TYPE_VARBINARY: {
2,147,483,647✔
2731
      int32_t code = parseVarbinary(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes);
2,147,483,647✔
2732
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2733
        return generateSyntaxErrMsg(&pCxt->msg, code, pSchema->name);
10,664✔
2734
      }
2735
      break;
2,147,483,647✔
2736
    }
2737
    case TSDB_DATA_TYPE_NCHAR: {
2,147,483,647✔
2738
      // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
2739
      int32_t len = 0;
2,147,483,647✔
2740
      int64_t realLen = pToken->n << 2;
2,147,483,647✔
2741
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
2,147,483,647✔
2742
      char* pUcs4 = taosMemoryMalloc(realLen);
2,147,483,647✔
2743
      if (NULL == pUcs4) {
2,147,483,647✔
2744
        return terrno;
195✔
2745
      }
2746
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)pUcs4, realLen, &len, pCxt->pComCxt->charsetCxt)) {
2,147,483,647✔
2747
        taosMemoryFree(pUcs4);
67,683✔
2748
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
2,631✔
2749
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
2,436✔
2750
        }
2751
        char buf[512] = {0};
195✔
2752
        snprintf(buf, tListLen(buf), "%s", strerror(terrno));
195✔
2753
        return buildSyntaxErrMsg(&pCxt->msg, buf, pToken->z);
195✔
2754
      }
2755
      pVal->value.pData = pUcs4;
2,147,483,647✔
2756
      pVal->value.nData = len;
2,147,483,647✔
2757
      break;
2,147,483,647✔
2758
    }
2759
    case TSDB_DATA_TYPE_JSON: {
×
2760
      if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
×
2761
        return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z);
×
2762
      }
2763
      pVal->value.pData = taosMemoryMalloc(pToken->n);
×
2764
      if (NULL == pVal->value.pData) {
×
2765
        return terrno;
×
2766
      }
2767
      memcpy(pVal->value.pData, pToken->z, pToken->n);
×
2768
      pVal->value.nData = pToken->n;
×
2769
      break;
×
2770
    }
2771
    case TSDB_DATA_TYPE_GEOMETRY: {
147,433,294✔
2772
      int32_t        code = TSDB_CODE_FAILED;
147,433,294✔
2773
      unsigned char* output = NULL;
147,433,294✔
2774
      size_t         size = 0;
147,433,294✔
2775

2776
      code = parseGeometry(pToken, &output, &size);
147,433,350✔
2777
      if (code != TSDB_CODE_SUCCESS) {
147,433,042✔
2778
        code = buildSyntaxErrMsg(&pCxt->msg, getGeosErrMsg(code), pToken->z);
1,764✔
2779
      }
2780
      // Too long values will raise the invalid sql error message
2781
      else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
147,431,278✔
2782
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
2783
      } else {
2784
        pVal->value.pData = taosMemoryMalloc(size);
147,431,614✔
2785
        if (NULL == pVal->value.pData) {
147,431,586✔
2786
          code = terrno;
×
2787
        } else {
2788
          memcpy(pVal->value.pData, output, size);
147,431,670✔
2789
          pVal->value.nData = size;
147,431,670✔
2790
        }
2791
      }
2792

2793
      geosFreeBuffer(output);
147,433,322✔
2794
      if (code != TSDB_CODE_SUCCESS) {
147,433,266✔
2795
        return code;
1,764✔
2796
      }
2797

2798
      break;
147,431,502✔
2799
    }
2800
    case TSDB_DATA_TYPE_TIMESTAMP: {
2,147,483,647✔
2801
      if (parseTime(pSql, pToken, timePrec, &VALUE_GET_TRIVIAL_DATUM(&pVal->value), &pCxt->msg,
2,147,483,647✔
2802
                    pCxt->pComCxt->timezone) != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2803
        return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z);
23,426✔
2804
      }
2805
      break;
2,147,483,647✔
2806
    }
2807
    case TSDB_DATA_TYPE_BLOB:
155,480,790✔
2808
    case TSDB_DATA_TYPE_MEDIUMBLOB: {
2809
      int32_t code = parseBlob(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes);
155,480,790✔
2810
      if (code != TSDB_CODE_SUCCESS) {
25,478,859✔
2811
        return generateSyntaxErrMsg(&pCxt->msg, code, pSchema->name);
9,552✔
2812
      }
2813
    } break;
25,469,307✔
2814
    case TSDB_DATA_TYPE_DECIMAL: {
138,123,346✔
2815
      if (!pExtSchema) {
138,123,346✔
2816
        qError("Decimal type without ext schema info, cannot parse decimal values");
×
2817
        return TSDB_CODE_DECIMAL_PARSE_ERROR;
×
2818
      }
2819
      uint8_t precision = 0, scale = 0;
138,123,346✔
2820
      decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale);
138,132,706✔
2821
      Decimal128 dec = {0};
138,170,302✔
2822
      int32_t    code = decimal128FromStr(pToken->z, pToken->n, precision, scale, &dec);
138,175,255✔
2823
      if (TSDB_CODE_SUCCESS != code) {
138,179,233✔
2824
        return code;
×
2825
      }
2826

2827
      // precision check
2828
      // scale auto fit
2829

2830
      code = decimal128ToDataVal(&dec, &pVal->value);
138,179,233✔
2831
      if (TSDB_CODE_SUCCESS != code) {
138,217,999✔
2832
        return code;
×
2833
      }
2834
      break;
138,217,999✔
2835
    }
2836
    case TSDB_DATA_TYPE_DECIMAL64: {
315,544,318✔
2837
      if (!pExtSchema) {
315,544,318✔
2838
        qError("Decimal type without ext schema info, cannot parse decimal values");
×
2839
        return TSDB_CODE_DECIMAL_PARSE_ERROR;
×
2840
      }
2841
      uint8_t precision = 0, scale = 0;
315,544,318✔
2842
      decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale);
315,588,700✔
2843
      Decimal64 dec = {0};
315,594,485✔
2844
      int32_t   code = decimal64FromStr(pToken->z, pToken->n, precision, scale, &dec);
315,601,817✔
2845
      if (TSDB_CODE_SUCCESS != code) {
315,568,628✔
2846
        return code;
×
2847
      }
2848
      code = decimal64ToDataVal(&dec, &pVal->value);
315,568,628✔
2849
      if (TSDB_CODE_SUCCESS != code) {
315,586,802✔
2850
        return code;
×
2851
      }
2852
      break;
315,586,802✔
2853
    }
2854
    default:
×
2855

2856
      return TSDB_CODE_FAILED;
×
2857
  }
2858

2859
  pVal->flag = CV_FLAG_VALUE;
2,147,483,647✔
2860
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2861
}
2862

2863
static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
2,147,483,647✔
2864
                               const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) {
2865
  int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pSchema->type);
2,147,483,647✔
2866
  if (TSDB_CODE_SUCCESS == code && isNullValue(pSchema->type, pToken)) {
2,147,483,647✔
2867
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
2,147,483,647✔
2868
      return buildSyntaxErrMsg(&pCxt->msg, "Primary timestamp column should not be null", pToken->z);
95✔
2869
    }
2870

2871
    pVal->flag = CV_FLAG_NULL;
2,147,483,647✔
2872
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
2873
  }
2874

2875
  if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
2876
    if (pToken->n == 0 && IS_NUMERIC_TYPE(pSchema->type)) {
2,147,483,647✔
2877
      return buildSyntaxErrMsg(&pCxt->msg, "invalid numeric data", pToken->z);
1,120✔
2878
    }
2879
    code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, pExtSchema, timePrec, pVal);
2,147,483,647✔
2880
  }
2881

2882
  return code;
2,147,483,647✔
2883
}
2884

2885
static void clearColValArray(SArray* pCols) {
2,147,483,647✔
2886
  int32_t num = taosArrayGetSize(pCols);
2,147,483,647✔
2887
  for (int32_t i = 0; i < num; ++i) {
2,147,483,647✔
2888
    SColVal* pCol = taosArrayGet(pCols, i);
2,147,483,647✔
2889
    if (IS_VAR_DATA_TYPE(pCol->value.type) || pCol->value.type == TSDB_DATA_TYPE_DECIMAL) {
2,147,483,647✔
2890
      taosMemoryFreeClear(pCol->value.pData);
2,147,483,647✔
2891
    }
2892
  }
2893
}
2,147,483,647✔
2894

2895
typedef struct SStbRowsDataContext {
2896
  SName stbName;
2897

2898
  STableMeta*   pStbMeta;
2899
  SNode*        pTagCond;
2900
  SBoundColInfo boundColsInfo;
2901

2902
  // the following fields are for each stb row
2903
  SArray*        aTagVals;
2904
  SArray*        aColVals;
2905
  SArray*        aTagNames;
2906
  SName          ctbName;
2907
  STag*          pTag;
2908
  STableMeta*    pCtbMeta;
2909
  SVCreateTbReq* pCreateCtbReq;
2910
  bool           hasTimestampTag;
2911
  bool           isJsonTag;
2912
} SStbRowsDataContext;
2913

2914
typedef union SRowsDataContext {
2915
  STableDataCxt*       pTableDataCxt;
2916
  SStbRowsDataContext* pStbRowsCxt;
2917
} SRowsDataContext;
2918

2919
int32_t parseTbnameToken(SMsgBuf* pMsgBuf, char* tname, SToken* pToken, bool* pFoundCtbName) {
1,121,238,216✔
2920
  *pFoundCtbName = false;
1,121,238,216✔
2921

2922
  if (isNullValue(TSDB_DATA_TYPE_BINARY, pToken)) {
1,121,238,216✔
2923
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be null value");
×
2924
  }
2925

2926
  if (pToken->n > 0) {
1,121,238,216✔
2927
    if (pToken->n <= TSDB_TABLE_NAME_LEN - 1) {
1,121,237,591✔
2928
      for (int i = 0; i < pToken->n; ++i) {
2,147,483,647✔
2929
        if (pToken->z[i] == '.') {
2,147,483,647✔
2930
          return buildInvalidOperationMsg(pMsgBuf, "tbname can not contain '.'");
625✔
2931
        } else {
2932
          tname[i] = pToken->z[i];
2,147,483,647✔
2933
        }
2934
      }
2935
      tname[pToken->n] = '\0';
1,121,236,824✔
2936
      *pFoundCtbName = true;
1,121,236,824✔
2937
    } else {
2938
      return buildInvalidOperationMsg(pMsgBuf, "tbname is too long");
142✔
2939
    }
2940
  } else {
2941
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be empty");
625✔
2942
  }
2943
  return TSDB_CODE_SUCCESS;
1,121,236,824✔
2944
}
2945

2946
static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
1,121,058,164✔
2947
                                          SStbRowsDataContext* pStbRowsCxt, bool ctbFirst, const SToken* tagTokens,
2948
                                          SSchema* const* tagSchemas, int numOfTagTokens) {
2949
  int32_t code = TSDB_CODE_SUCCESS;
1,121,058,164✔
2950
  uint8_t precision = pStmt->pTableMeta->tableInfo.precision;
1,121,058,164✔
2951

2952
  if (code == TSDB_CODE_SUCCESS && ctbFirst) {
1,121,058,164✔
2953
    for (int32_t i = 0; code == TSDB_CODE_SUCCESS && i < numOfTagTokens; ++i) {
3,042,129✔
2954
      SToken*  pTagToken = (SToken*)(tagTokens + i);
124,553✔
2955
      SSchema* pTagSchema = tagSchemas[i];
124,553✔
2956
      code = checkAndTrimValue(pTagToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
124,553✔
2957
      if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pTagToken->type) {
124,553✔
2958
        code = buildInvalidOperationMsg(&pCxt->msg, "not expected tag");
×
2959
      }
2960

2961
      if (code == TSDB_CODE_SUCCESS) {
124,553✔
2962
        code = parseTagValue(&pCxt->msg, NULL, precision, pTagSchema, pTagToken, pStbRowsCxt->aTagNames,
248,326✔
2963
                             pStbRowsCxt->aTagVals, &pStbRowsCxt->pTag, pCxt->pComCxt->timezone,
124,553✔
2964
                             pCxt->pComCxt->charsetCxt);
124,553✔
2965
      }
2966
    }
2967
    if (code == TSDB_CODE_SUCCESS && !pStbRowsCxt->isJsonTag) {
2,917,576✔
2968
      code = tTagNew(pStbRowsCxt->aTagVals, 1, false, &pStbRowsCxt->pTag);
2,917,576✔
2969
    }
2970
  }
2971
  if (code == TSDB_CODE_SUCCESS && pStbRowsCxt->pTagCond) {
1,121,058,164✔
2972
    code = checkSubtablePrivilege(pStbRowsCxt->aTagVals, pStbRowsCxt->aTagNames, &pStbRowsCxt->pTagCond);
×
2973
  }
2974
  return code;
1,121,058,164✔
2975
}
2976

2977
static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
1,121,070,588✔
2978
                                 SStbRowsDataContext* pStbRowsCxt, SToken* pToken, const SBoundColInfo* pCols,
2979
                                 const SSchema* pSchemas, const SSchemaExt* pExtSchemas, SToken* tagTokens,
2980
                                 SSchema** tagSchemas, int* pNumOfTagTokens, bool* bFoundTbName, bool* setCtbName,
2981
                                 SBoundColInfo* ctbCols) {
2982
  int32_t code = TSDB_CODE_SUCCESS;
1,121,070,588✔
2983
  SArray* pTagNames = pStbRowsCxt->aTagNames;
1,121,070,588✔
2984
  SArray* pTagVals = pStbRowsCxt->aTagVals;
1,121,070,588✔
2985
  bool    canParseTagsAfter = !pStbRowsCxt->pTagCond && !pStbRowsCxt->hasTimestampTag;
1,121,070,588✔
2986
  int32_t numOfCols = getNumOfColumns(pStbRowsCxt->pStbMeta);
1,121,070,588✔
2987
  int32_t numOfTags = getNumOfTags(pStbRowsCxt->pStbMeta);
1,121,070,588✔
2988
  int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta);
1,121,070,588✔
2989
  uint8_t precision = getTableInfo(pStbRowsCxt->pStbMeta).precision;
1,121,070,588✔
2990
  int     tag_index = 0;
1,121,070,588✔
2991
  int     col_index = 0;
1,121,070,588✔
2992
  for (int i = 0; i < pCols->numOfBound && (code) == TSDB_CODE_SUCCESS; ++i) {
2,147,483,647✔
2993
    const char* pTmpSql = *ppSql;
2,147,483,647✔
2994
    bool        ignoreComma = false;
2,147,483,647✔
2995
    NEXT_TOKEN_WITH_PREV_EXT(*ppSql, *pToken, &ignoreComma);
2,147,483,647✔
2996

2997
    if (ignoreComma) {
2,147,483,647✔
2998
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pTmpSql);
×
2999
      break;
×
3000
    }
3001

3002
    if (TK_NK_RP == pToken->type) {
2,147,483,647✔
3003
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
×
3004
      break;
×
3005
    }
3006

3007
    // cols tags tbname
3008
    if (TK_NK_QUESTION == pToken->type) {
2,147,483,647✔
3009
      if (pCxt->pComCxt->stmtBindVersion != 2) {
51,411✔
3010
        return buildInvalidOperationMsg(&pCxt->msg,
195✔
3011
                                        "insert into stb(...tbname...)values(...,?,...) only support in stmt2");
3012
      }
3013
      if (pCols->pColIndex[i] == tbnameIdx) {
51,216✔
3014
        *bFoundTbName = true;
9,963✔
3015
        char* tbName = NULL;
9,963✔
3016
        if ((*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName) == TSDB_CODE_SUCCESS) {
9,963✔
3017
          tstrncpy(pStbRowsCxt->ctbName.tname, tbName, sizeof(pStbRowsCxt->ctbName.tname));
7,224✔
3018
          tstrncpy(pStmt->usingTableName.tname, pStmt->targetTableName.tname, sizeof(pStmt->usingTableName.tname));
7,224✔
3019
          tstrncpy(pStmt->targetTableName.tname, tbName, sizeof(pStmt->targetTableName.tname));
7,224✔
3020
          tstrncpy(pStmt->usingTableName.dbname, pStmt->targetTableName.dbname, sizeof(pStmt->usingTableName.dbname));
7,224✔
3021
          pStmt->usingTableName.type = 1;
7,224✔
3022
          pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;  // set the table type to child table for parse cache
7,224✔
3023
          *setCtbName = true;
7,224✔
3024
        }
3025
      } else if (pCols->pColIndex[i] < numOfCols) {
41,253✔
3026
        // bind column
3027
        if (ctbCols->pColIndex == NULL) {
23,277✔
3028
          ctbCols->pColIndex = taosMemoryCalloc(numOfCols, sizeof(int16_t));
9,963✔
3029
          if (NULL == ctbCols->pColIndex) {
9,963✔
3030
            return terrno;
×
3031
          }
3032
        }
3033
        ctbCols->pColIndex[col_index++] = pCols->pColIndex[i];
23,277✔
3034
        ctbCols->numOfBound++;
23,277✔
3035
        ctbCols->numOfCols++;
23,277✔
3036

3037
      } else if (pCols->pColIndex[i] < tbnameIdx) {
17,976✔
3038
        if (pCxt->tags.pColIndex == NULL) {
17,976✔
3039
          pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t));
7,038✔
3040
          if (NULL == pCxt->tags.pColIndex) {
7,038✔
3041
            return terrno;
×
3042
          }
3043
        }
3044
        if (!(tag_index < numOfTags)) {
17,976✔
3045
          return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags");
×
3046
        }
3047
        pStmt->usingTableProcessing = true;
17,976✔
3048
        pCxt->tags.pColIndex[tag_index++] = pCols->pColIndex[i] - numOfCols;
17,976✔
3049
        pCxt->tags.mixTagsCols = true;
17,976✔
3050
        pCxt->tags.numOfBound++;
17,976✔
3051
        pCxt->tags.numOfCols++;
17,976✔
3052
      } else {
3053
        return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfBound");
×
3054
      }
3055
    } else {
3056
      if (pCxt->pComCxt->stmtBindVersion == 2 && pCxt->pComCxt->pStmtCb != NULL) {
2,147,483,647✔
3057
        if (pCols->pColIndex[i] < numOfCols) {
2,145✔
3058
          const SSchema*    pSchema = &pSchemas[pCols->pColIndex[i]];
975✔
3059
          const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i];
975✔
3060
          SColVal*          pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]);
975✔
3061
          code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, pExtSchema, precision, pVal);
975✔
3062
          if (TK_NK_VARIABLE == pToken->type) {
975✔
3063
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
3064
          }
3065

3066
          if (ctbCols->pColIndex == NULL) {
975✔
3067
            ctbCols->pColIndex = taosMemoryCalloc(numOfCols, sizeof(int16_t));
×
3068
            if (NULL == ctbCols->pColIndex) {
×
3069
              return terrno;
×
3070
            }
3071
          }
3072
          ctbCols->pColIndex[col_index++] = pCols->pColIndex[i];
975✔
3073
          ctbCols->numOfBound++;
975✔
3074
          ctbCols->numOfCols++;
975✔
3075

3076
          if (code == TSDB_CODE_SUCCESS && pCxt->pParsedValues == NULL) {
975✔
3077
            pCxt->pParsedValues =
585✔
3078
                tSimpleHashInit(pCols->numOfBound, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT));
585✔
3079
            if (pCxt->pParsedValues == NULL) {
585✔
3080
              return terrno;
×
3081
            }
3082
            tSimpleHashSetFreeFp(pCxt->pParsedValues, destroyColVal);
585✔
3083
          }
3084

3085
          if (code == TSDB_CODE_SUCCESS) {
975✔
3086
            SColVal clonedVal = *pVal;
975✔
3087
            if (COL_VAL_IS_VALUE(&clonedVal) && IS_VAR_DATA_TYPE(clonedVal.value.type)) {
975✔
3088
              clonedVal.value.pData = taosMemoryMalloc(clonedVal.value.nData);
195✔
3089
              if (NULL == clonedVal.value.pData) {
195✔
3090
                code = terrno;
×
3091
                break;
×
3092
              }
3093
              memcpy(clonedVal.value.pData, pVal->value.pData, clonedVal.value.nData);
195✔
3094
            }
3095

3096
            clonedVal.cid = pSchema->colId;
975✔
3097
            code = tSimpleHashPut(pCxt->pParsedValues, &pSchema->colId, sizeof(int16_t), &clonedVal, sizeof(SColVal));
975✔
3098
            if (code != TSDB_CODE_SUCCESS) {
975✔
3099
              if (COL_VAL_IS_VALUE(&clonedVal) && IS_VAR_DATA_TYPE(clonedVal.value.type)) {
×
3100
                taosMemoryFree(clonedVal.value.pData);
×
3101
                clonedVal.value.pData = NULL;
×
3102
              }
3103
              return code;
×
3104
            }
3105
          }
3106
        } else if (pCols->pColIndex[i] < tbnameIdx) {
1,170✔
3107
          if (pCxt->tags.parseredTags == NULL) {
1,170✔
3108
            pCxt->tags.parseredTags = taosMemoryCalloc(1, sizeof(STagsInfo));
780✔
3109
            if (pCxt->tags.parseredTags == NULL) {
780✔
3110
              code = terrno;
×
3111
            } else {
3112
              pCxt->tags.parseredTags->STagNames = taosArrayInit(numOfTags, sizeof(STagVal));
780✔
3113
              pCxt->tags.parseredTags->pTagVals = taosArrayInit(numOfTags, sizeof(STagVal));
780✔
3114
              pCxt->tags.parseredTags->pTagIndex = taosMemoryCalloc(numOfTags, sizeof(uint8_t));
780✔
3115
              pCxt->tags.parseredTags->numOfTags = 0;
780✔
3116

3117
              if (pCxt->tags.parseredTags->STagNames == NULL || pCxt->tags.parseredTags->pTagVals == NULL ||
780✔
3118
                  pCxt->tags.parseredTags->pTagIndex == NULL) {
780✔
3119
                return terrno;
×
3120
              }
3121
            }
3122
          }
3123

3124
          const SSchema* pTagSchema = &pSchemas[pCols->pColIndex[i]];
1,170✔
3125
          // if (canParseTagsAfter) {
3126
          //   tagTokens[(*pNumOfTagTokens)] = *pToken;
3127
          //   tagSchemas[(*pNumOfTagTokens)] = (SSchema*)pTagSchema;
3128
          //   ++(*pNumOfTagTokens);
3129
          // } else {
3130
          code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
1,170✔
3131
          if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pToken->type) {
1,170✔
3132
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
3133
          }
3134
          if (code == TSDB_CODE_SUCCESS) {
1,170✔
3135
            code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken,
975✔
3136
                                 pCxt->tags.parseredTags->STagNames, pCxt->tags.parseredTags->pTagVals,
975✔
3137
                                 &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
975✔
3138
          }
3139

3140
          pCxt->tags.parseredTags->pTagIndex[pCxt->tags.parseredTags->numOfTags++] = pCols->pColIndex[i] - numOfCols;
1,170✔
3141

3142
          if (pCxt->tags.pColIndex == NULL) {
1,170✔
3143
            pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t));
780✔
3144
            if (NULL == pCxt->tags.pColIndex) {
780✔
3145
              return terrno;
×
3146
            }
3147
          }
3148
          if (!(tag_index < numOfTags)) {
1,170✔
3149
            return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags");
×
3150
          }
3151
          pStmt->usingTableProcessing = true;
1,170✔
3152
          pCxt->tags.pColIndex[tag_index++] = pCols->pColIndex[i] - numOfCols;
1,170✔
3153
          pCxt->tags.mixTagsCols = true;
1,170✔
3154
          pCxt->tags.numOfBound++;
1,170✔
3155
          pCxt->tags.numOfCols++;
1,170✔
3156
          // }
3157
        } else if (pCols->pColIndex[i] == tbnameIdx) {
×
3158
          return buildInvalidOperationMsg(&pCxt->msg, "STMT tbname in bound cols should not be a fixed value");
×
3159
        }
3160
      } else {
3161
        if (pCols->pColIndex[i] < numOfCols) {
2,147,483,647✔
3162
          const SSchema*    pSchema = &pSchemas[pCols->pColIndex[i]];
2,147,483,647✔
3163
          const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i];
2,147,483,647✔
3164
          SColVal*          pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]);
2,147,483,647✔
3165
          code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, pExtSchema, precision, pVal);
2,147,483,647✔
3166
          if (TK_NK_VARIABLE == pToken->type) {
2,147,483,647✔
3167
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
3168
          }
3169
        } else if (pCols->pColIndex[i] < tbnameIdx) {
1,121,229,469✔
3170
          const SSchema* pTagSchema = &pSchemas[pCols->pColIndex[i]];
169,859✔
3171
          if (canParseTagsAfter) {
169,859✔
3172
            tagTokens[(*pNumOfTagTokens)] = *pToken;
169,859✔
3173
            tagSchemas[(*pNumOfTagTokens)] = (SSchema*)pTagSchema;
169,859✔
3174
            ++(*pNumOfTagTokens);
169,859✔
3175
          } else {
3176
            code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
×
3177
            if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pToken->type) {
×
3178
              code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
3179
            }
3180
            if (code == TSDB_CODE_SUCCESS) {
×
3181
              code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, pTagNames, pTagVals,
×
3182
                                   &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
×
3183
            }
3184
          }
3185
        } else if (pCols->pColIndex[i] == tbnameIdx) {
1,121,059,610✔
3186
          code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, TSDB_DATA_TYPE_BINARY);
1,121,059,610✔
3187
          if (TK_NK_VARIABLE == pToken->type) {
1,121,059,610✔
3188
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected tbname");
×
3189
          }
3190

3191
          if (code == TSDB_CODE_SUCCESS) {
1,121,059,610✔
3192
            code = parseTbnameToken(&pCxt->msg, pStbRowsCxt->ctbName.tname, pToken, bFoundTbName);
1,121,056,352✔
3193
          }
3194
        }
3195
      }
3196
    }
3197

3198
    if (code == TSDB_CODE_SUCCESS && i < pCols->numOfBound - 1) {
2,147,483,647✔
3199
      NEXT_VALID_TOKEN(*ppSql, *pToken);
2,147,483,647✔
3200
      if (TK_NK_COMMA != pToken->type) {
2,147,483,647✔
3201
        code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
625✔
3202
      }
3203
    }
3204
  }
3205

3206
  return code;
1,121,070,393✔
3207
}
3208

3209
static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
1,121,070,588✔
3210
                               SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken, bool* pCtbFirst,
3211
                               bool* setCtbName, SBoundColInfo* ctbCols) {
3212
  SBoundColInfo* pCols = &pStbRowsCxt->boundColsInfo;
1,121,070,588✔
3213
  SSchema*       pSchemas = getTableColumnSchema(pStbRowsCxt->pStbMeta);
1,121,070,588✔
3214
  SSchemaExt*    pExtSchemas = getTableColumnExtSchema(pStbRowsCxt->pStbMeta);
1,121,070,588✔
3215

3216
  bool        bFoundTbName = false;
1,121,070,588✔
3217
  const char* pOrigSql = *ppSql;
1,121,070,588✔
3218

3219
  int32_t  code = TSDB_CODE_SUCCESS;
1,121,070,588✔
3220
  SToken   tagTokens[TSDB_MAX_TAGS] = {0};
1,121,070,588✔
3221
  SSchema* tagSchemas[TSDB_MAX_TAGS] = {0};
1,121,070,588✔
3222
  int      numOfTagTokens = 0;
1,121,070,588✔
3223

3224
  code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, pExtSchemas, tagTokens, tagSchemas,
1,121,070,588✔
3225
                           &numOfTagTokens, &bFoundTbName, setCtbName, ctbCols);
3226

3227
  if (code != TSDB_CODE_SUCCESS) {
1,121,070,588✔
3228
    return code;
9,685✔
3229
  }
3230

3231
  if (!bFoundTbName) {
1,121,060,903✔
3232
    code = buildSyntaxErrMsg(&pCxt->msg, "tbname value expected", pOrigSql);
×
3233
  }
3234

3235
  bool ctbFirst = true;
1,121,060,903✔
3236
  char ctbFName[TSDB_TABLE_FNAME_LEN];
1,121,050,160✔
3237
  if (code == TSDB_CODE_SUCCESS) {
1,121,060,903✔
3238
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
1,121,060,903✔
3239
  }
3240
  if (TSDB_CODE_SUCCESS == code) {
1,121,060,903✔
3241
    STableMeta** pCtbMeta = taosHashGet(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName));
1,121,058,164✔
3242
    ctbFirst = (pCtbMeta == NULL);
1,121,058,164✔
3243
    if (!ctbFirst) {
1,121,058,164✔
3244
      pStbRowsCxt->pCtbMeta->uid = (*pCtbMeta)->uid;
1,118,140,588✔
3245
      pStbRowsCxt->pCtbMeta->vgId = (*pCtbMeta)->vgId;
1,118,140,588✔
3246
    }
3247
    *pCtbFirst = ctbFirst;
1,121,058,164✔
3248
  }
3249

3250
  if (code == TSDB_CODE_SUCCESS) {
1,121,060,903✔
3251
    code = processCtbTagsAfterCtbName(pCxt, pStmt, pStbRowsCxt, ctbFirst, tagTokens, tagSchemas, numOfTagTokens);
1,121,058,164✔
3252
  }
3253

3254
  if (code == TSDB_CODE_SUCCESS) {
1,121,060,903✔
3255
    *pGotRow = true;
1,121,058,164✔
3256
  }
3257
  return code;
1,121,060,903✔
3258
}
3259

3260
static int32_t processCtbAutoCreationAndCtbMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
2,917,576✔
3261
                                                SStbRowsDataContext* pStbRowsCxt) {
3262
  int32_t code = TSDB_CODE_SUCCESS;
2,917,576✔
3263

3264
  pStbRowsCxt->pCreateCtbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
2,917,576✔
3265
  if (pStbRowsCxt->pCreateCtbReq == NULL) {
2,917,576✔
3266
    code = terrno;
×
3267
  }
3268
  if (code == TSDB_CODE_SUCCESS) {
2,917,576✔
3269
    code = insBuildCreateTbReq(pStbRowsCxt->pCreateCtbReq, pStbRowsCxt->ctbName.tname, pStbRowsCxt->pTag,
5,827,148✔
3270
                               pStbRowsCxt->pStbMeta->uid, pStbRowsCxt->stbName.tname, pStbRowsCxt->aTagNames,
2,917,576✔
3271
                               getNumOfTags(pStbRowsCxt->pStbMeta), TSDB_DEFAULT_TABLE_TTL);
2,917,576✔
3272
    pStbRowsCxt->pTag = NULL;
2,917,576✔
3273
  }
3274

3275
  if (code == TSDB_CODE_SUCCESS) {
2,917,576✔
3276
    char ctbFName[TSDB_TABLE_FNAME_LEN];
2,909,572✔
3277
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
2,917,576✔
3278
    SVgroupInfo      vg;
2,909,572✔
3279
    SRequestConnInfo conn = {.pTrans = pCxt->pComCxt->pTransporter,
5,827,148✔
3280
                             .requestId = pCxt->pComCxt->requestId,
2,917,576✔
3281
                             .requestObjRefId = pCxt->pComCxt->requestRid,
2,917,576✔
3282
                             .mgmtEps = pCxt->pComCxt->mgmtEpSet};
2,917,576✔
3283
    if (TSDB_CODE_SUCCESS == code) {
2,917,576✔
3284
      code = catalogGetTableHashVgroup(pCxt->pComCxt->pCatalog, &conn, &pStbRowsCxt->ctbName, &vg);
2,917,576✔
3285
    }
3286
    if (code == TSDB_CODE_SUCCESS) {
2,917,576✔
3287
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)(&vg.vgId), sizeof(vg.vgId), &vg, sizeof(vg));
2,917,576✔
3288
    }
3289
    STableMeta* pBackup = NULL;
2,917,576✔
3290
    if (TSDB_CODE_SUCCESS == code) {
2,917,576✔
3291
      pStbRowsCxt->pCtbMeta->uid = taosHashGetSize(pStmt->pSubTableHashObj) + 1;
2,917,576✔
3292
      pStbRowsCxt->pCtbMeta->vgId = vg.vgId;
2,917,576✔
3293

3294
      code = cloneTableMeta(pStbRowsCxt->pCtbMeta, &pBackup);
2,917,576✔
3295
    }
3296
    if (TSDB_CODE_SUCCESS == code) {
2,917,576✔
3297
      code = taosHashPut(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName), &pBackup, POINTER_BYTES);
2,917,576✔
3298
    }
3299
    if (TSDB_CODE_SUCCESS == code) {
2,917,576✔
3300
      code = collectUseTable(&pStbRowsCxt->ctbName, pStmt->pTableNameHashObj);
2,917,576✔
3301
    }
3302
  }
3303
  return code;
2,917,576✔
3304
}
3305

3306
static void clearStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
1,121,284,497✔
3307
  if (pStbRowsCxt == NULL) return;
1,121,284,497✔
3308

3309
  taosArrayClear(pStbRowsCxt->aTagNames);
1,121,284,497✔
3310
  for (int i = 0; i < taosArrayGetSize(pStbRowsCxt->aTagVals); ++i) {
1,121,406,550✔
3311
    STagVal* p = (STagVal*)taosArrayGet(pStbRowsCxt->aTagVals, i);
122,053✔
3312
    if (IS_VAR_DATA_TYPE(p->type)) {
122,053✔
3313
      taosMemoryFreeClear(p->pData);
13,006✔
3314
    }
3315
  }
3316
  taosArrayClear(pStbRowsCxt->aTagVals);
1,121,284,497✔
3317

3318
  clearColValArray(pStbRowsCxt->aColVals);
1,121,284,497✔
3319

3320
  tTagFree(pStbRowsCxt->pTag);
1,121,284,497✔
3321
  pStbRowsCxt->pTag = NULL;
1,121,284,497✔
3322
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
1,121,284,497✔
3323
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
1,121,284,497✔
3324

3325
  if (pStbRowsCxt->boundColsInfo.parseredTags != NULL) {
1,121,284,497✔
3326
    if (pStbRowsCxt->boundColsInfo.parseredTags->STagNames != NULL) {
×
3327
      taosArrayDestroy(pStbRowsCxt->boundColsInfo.parseredTags->STagNames);
×
3328
    }
3329
    if (pStbRowsCxt->boundColsInfo.parseredTags->pTagVals != NULL) {
×
3330
      taosArrayDestroy(pStbRowsCxt->boundColsInfo.parseredTags->pTagVals);
×
3331
    }
3332
    taosMemoryFreeClear(pStbRowsCxt->boundColsInfo.parseredTags);
×
3333
  }
3334
}
3335

3336
static void clearInsertParseContext(SInsertParseContext* pCxt) {
1,043,187,579✔
3337
  if (pCxt == NULL) return;
1,043,187,579✔
3338

3339
  if (pCxt->pParsedValues != NULL) {
1,043,187,579✔
3340
    tSimpleHashCleanup(pCxt->pParsedValues);
×
3341
    pCxt->pParsedValues = NULL;
×
3342
  }
3343
}
3344

3345
static int32_t parseStbBoundInfo(SVnodeModifyOpStmt* pStmt, SStbRowsDataContext* pStbRowsCxt,
2,934✔
3346
                                 STableDataCxt** ppTableDataCxt) {
3347
  char    tbFName[TSDB_TABLE_FNAME_LEN];
×
3348
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
2,934✔
3349
  if (TSDB_CODE_SUCCESS != code) {
2,934✔
3350
    return code;
×
3351
  }
3352
  if (pStmt->usingTableProcessing) {
2,934✔
3353
    pStmt->pTableMeta->uid = 0;
2,349✔
3354
  }
3355

3356
  code = insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
2,934✔
3357
                            &pStmt->pCreateTblReq, ppTableDataCxt, false, true);
3358
  if (code != TSDB_CODE_SUCCESS) {
2,934✔
3359
    return code;
×
3360
  }
3361

3362
  qDestroyBoundColInfo(&((*ppTableDataCxt)->boundColsInfo));
2,934✔
3363
  (*ppTableDataCxt)->boundColsInfo = pStbRowsCxt->boundColsInfo;
2,934✔
3364

3365
  (*ppTableDataCxt)->boundColsInfo.pColIndex = taosMemoryCalloc(pStbRowsCxt->boundColsInfo.numOfBound, sizeof(int16_t));
2,934✔
3366
  if (NULL == (*ppTableDataCxt)->boundColsInfo.pColIndex) {
2,934✔
3367
    return terrno;
×
3368
  }
3369
  (void)memcpy((*ppTableDataCxt)->boundColsInfo.pColIndex, pStbRowsCxt->boundColsInfo.pColIndex,
2,934✔
3370
               sizeof(int16_t) * pStmt->pStbRowsCxt->boundColsInfo.numOfBound);
2,934✔
3371
  return TSDB_CODE_SUCCESS;
2,934✔
3372
}
3373

3374
static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
1,121,070,588✔
3375
                              SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken,
3376
                              STableDataCxt** ppTableDataCxt) {
3377
  bool          bFirstTable = false;
1,121,070,588✔
3378
  bool          setCtbName = false;
1,121,070,588✔
3379
  SBoundColInfo ctbCols = {0};
1,121,070,588✔
3380
  int32_t code = getStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pGotRow, pToken, &bFirstTable, &setCtbName, &ctbCols);
1,121,070,588✔
3381

3382
  if (!setCtbName && pCxt->pComCxt->stmtBindVersion == 2) {
1,121,070,588✔
3383
    taosMemoryFreeClear(ctbCols.pColIndex);
2,934✔
3384
    return parseStbBoundInfo(pStmt, pStbRowsCxt, ppTableDataCxt);
2,934✔
3385
  }
3386

3387
  if (code != TSDB_CODE_SUCCESS || !*pGotRow) {
1,121,067,654✔
3388
    return code;
9,490✔
3389
  }
3390

3391
  if (code == TSDB_CODE_SUCCESS && bFirstTable) {
1,121,058,164✔
3392
    code = processCtbAutoCreationAndCtbMeta(pCxt, pStmt, pStbRowsCxt);
2,917,576✔
3393
  }
3394
  if (code == TSDB_CODE_SUCCESS) {
1,121,058,164✔
3395
    if (pCxt->pComCxt->stmtBindVersion == 2) {
1,121,058,164✔
3396
      char ctbFName[TSDB_TABLE_FNAME_LEN];
×
3397
      code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
7,224✔
3398
      if (code != TSDB_CODE_SUCCESS) {
7,224✔
3399
        return code;
×
3400
      }
3401
      code = insGetTableDataCxt(pStmt->pTableBlockHashObj, ctbFName, strlen(ctbFName), pStbRowsCxt->pCtbMeta,
7,224✔
3402
                                &pStbRowsCxt->pCreateCtbReq, ppTableDataCxt, true, true);
3403
    } else {
3404
      code =
3405
          insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid),
1,121,050,940✔
3406
                             pStbRowsCxt->pCtbMeta, &pStbRowsCxt->pCreateCtbReq, ppTableDataCxt, false, true);
3407
    }
3408
  }
3409
  if (code == TSDB_CODE_SUCCESS) {
1,121,058,164✔
3410
    if (pCxt->pComCxt->stmtBindVersion == 2) {
1,121,058,164✔
3411
      int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta);
7,224✔
3412
      code = initTableColSubmitDataWithBoundInfo(*ppTableDataCxt, ctbCols);
7,224✔
3413
    } else {
3414
      code = initTableColSubmitData(*ppTableDataCxt);
1,121,050,940✔
3415
    }
3416
  }
3417
  if (code == TSDB_CODE_SUCCESS && pCxt->pComCxt->stmtBindVersion == 0) {
1,121,058,164✔
3418
    SRow** pRow = taosArrayReserve((*ppTableDataCxt)->pData->aRowP, 1);
1,121,050,940✔
3419
    if ((*ppTableDataCxt)->hasBlob) {
1,121,050,940✔
3420
      SRowBuildScanInfo sinfo = {.hasBlob = 1, .scanType = ROW_BUILD_UPDATE};
796✔
3421
      if ((*ppTableDataCxt)->pData->pBlobSet == NULL) {
796✔
3422
        code = tBlobSetCreate(1024, 0, &(*ppTableDataCxt)->pData->pBlobSet);
796✔
3423
        TAOS_CHECK_RETURN(code);
796✔
3424
      }
3425
      code = tRowBuildWithBlob(pStbRowsCxt->aColVals, (*ppTableDataCxt)->pSchema, pRow,
796✔
3426
                               (*ppTableDataCxt)->pData->pBlobSet, &sinfo);
796✔
3427
    } else {
3428
      SRowBuildScanInfo sinfo = {0};
1,121,050,144✔
3429
      code = tRowBuild(pStbRowsCxt->aColVals, (*ppTableDataCxt)->pSchema, pRow, &sinfo);
1,121,050,144✔
3430
    }
3431
    if (TSDB_CODE_SUCCESS == code) {
1,121,050,940✔
3432
      SRowKey key;
1,121,042,120✔
3433
      tRowGetKey(*pRow, &key);
2,147,483,647✔
3434
      insCheckTableDataOrder(*ppTableDataCxt, &key);
1,121,042,900✔
3435
    }
3436
  }
3437

3438
  if (code == TSDB_CODE_SUCCESS) {
1,121,058,164✔
3439
    *pGotRow = true;
1,121,050,124✔
3440
  }
3441

3442
  clearStbRowsDataContext(pStbRowsCxt);
1,121,058,164✔
3443

3444
  return code;
1,121,058,164✔
3445
}
3446

3447
static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow,
2,147,483,647✔
3448
                       SToken* pToken) {
3449
  SBoundColInfo*    pCols = &pTableCxt->boundColsInfo;
2,147,483,647✔
3450
  SSchema*          pSchemas = getTableColumnSchema(pTableCxt->pMeta);
2,147,483,647✔
3451
  const SSchemaExt* pExtSchemas = getTableColumnExtSchema(pTableCxt->pMeta);
2,147,483,647✔
3452

3453
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3454
  // 1. set the parsed value from sql string
3455
  for (int i = 0; i < pCols->numOfBound && TSDB_CODE_SUCCESS == code; ++i) {
2,147,483,647✔
3456
    const char* pOrigSql = *pSql;
2,147,483,647✔
3457
    bool        ignoreComma = false;
2,147,483,647✔
3458
    NEXT_TOKEN_WITH_PREV_EXT(*pSql, *pToken, &ignoreComma);
2,147,483,647✔
3459
    if (ignoreComma) {
2,147,483,647✔
3460
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pOrigSql);
95✔
3461
      break;
95✔
3462
    }
3463

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

3468
    if (pToken->type == TK_NK_QUESTION) {
2,147,483,647✔
3469
      if (pCxt->pComCxt->stmtBindVersion == 0) {
21,575,271✔
3470
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pToken->z);
2,260✔
3471
        break;
2,260✔
3472
      }
3473
    } else {
3474
      if (TK_NK_RP == pToken->type) {
2,147,483,647✔
3475
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
1,452✔
3476
        break;
1,452✔
3477
      }
3478

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

3482
        if (TSDB_CODE_SUCCESS == code && pCxt->pComCxt->stmtBindVersion!=0) {
2,147,483,647✔
3483
          if (NULL == pCxt->pParsedValues) {
2,340✔
3484
            pCxt->pParsedValues =
1,755✔
3485
                tSimpleHashInit(pCols->numOfBound, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT));
1,755✔
3486
            if (NULL == pCxt->pParsedValues) {
1,755✔
3487
              code = terrno;
×
3488
              break;
×
3489
            }
3490
            tSimpleHashSetFreeFp(pCxt->pParsedValues, destroyColVal);
1,755✔
3491
          }
3492

3493
          SColVal clonedVal = *pVal;
2,340✔
3494
          if (COL_VAL_IS_VALUE(&clonedVal) && IS_VAR_DATA_TYPE(clonedVal.value.type)) {
2,340✔
3495
            clonedVal.value.pData = taosMemoryMalloc(clonedVal.value.nData);
975✔
3496
            if (NULL == clonedVal.value.pData) {
975✔
3497
              code = terrno;
×
3498
              break;
×
3499
            }
3500
            memcpy(clonedVal.value.pData, pVal->value.pData, clonedVal.value.nData);
975✔
3501
          }
3502

3503
          code = tSimpleHashPut(pCxt->pParsedValues, &pSchema->colId, sizeof(int16_t), &clonedVal, sizeof(SColVal));
2,340✔
3504
          if (code != TSDB_CODE_SUCCESS) {
2,340✔
3505
            if (COL_VAL_IS_VALUE(&clonedVal) && IS_VAR_DATA_TYPE(clonedVal.value.type)) {
×
3506
              taosMemoryFree(clonedVal.value.pData);
×
3507
              clonedVal.value.pData = NULL;
×
3508
            }
3509
            break;
×
3510
          }
3511
        }
3512
      }
3513
    }
3514

3515
    if (TSDB_CODE_SUCCESS == code && i < pCols->numOfBound - 1) {
2,147,483,647✔
3516
      NEXT_VALID_TOKEN(*pSql, *pToken);
2,147,483,647✔
3517
      if (TK_NK_COMMA != pToken->type) {
2,147,483,647✔
3518
        if (!pCxt->forceUpdate) {
4,158✔
3519
          code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
2,435✔
3520
          parserWarn("QID:0x%" PRIx64 ", column number is smaller than %d, need retry", pCxt->pComCxt->requestId,
2,435✔
3521
                     pCols->numOfBound);
3522
        } else {
3523
          code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
1,723✔
3524
        }
3525
      }
3526
    }
3527
  }
3528

3529
  if (TSDB_CODE_SUCCESS == code && pCxt->pComCxt->stmtBindVersion == 0) {
2,147,483,647✔
3530
    SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1);
2,147,483,647✔
3531
    if (pTableCxt->hasBlob) {
2,147,483,647✔
3532
      SRowBuildScanInfo sinfo = {.hasBlob = 1, .scanType = ROW_BUILD_UPDATE};
25,996,063✔
3533
      if (pTableCxt->pData->pBlobSet == NULL) {
25,996,063✔
3534
        code = tBlobSetCreate(1024, 0, &pTableCxt->pData->pBlobSet);
45,909✔
3535
        TAOS_CHECK_RETURN(code);
45,909✔
3536
      }
3537
      code = tRowBuildWithBlob(pTableCxt->pValues, pTableCxt->pSchema, pRow, pTableCxt->pData->pBlobSet, &sinfo);
25,996,063✔
3538
    } else {
3539
      SRowBuildScanInfo sinfo = {0};
2,147,483,647✔
3540
      code = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow, &sinfo);
2,147,483,647✔
3541
    }
3542
    if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3543
      SRowKey key;
2,147,483,647✔
3544
      tRowGetKey(*pRow, &key);
2,147,483,647✔
3545
      insCheckTableDataOrder(pTableCxt, &key);
2,147,483,647✔
3546
    }
3547
  }
3548

3549
  if (TSDB_CODE_SUCCESS == code && pCxt->pComCxt->stmtBindVersion == 0) {
2,147,483,647✔
3550
    *pGotRow = true;
2,147,483,647✔
3551
  }
3552

3553
  clearColValArray(pTableCxt->pValues);
2,147,483,647✔
3554

3555
  return code;
2,147,483,647✔
3556
}
3557

3558
// pSql -> (field1_value, ...) [(field1_value2, ...) ...]
3559
static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
553,369,286✔
3560
                           int32_t* pNumOfRows, SToken* pToken) {
3561
  int32_t code = TSDB_CODE_SUCCESS;
553,369,286✔
3562

3563
  (*pNumOfRows) = 0;
553,369,286✔
3564
  while (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3565
    int32_t index = 0;
2,147,483,647✔
3566
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, *pToken, index);
2,147,483,647✔
3567
    if (TK_NK_LP != pToken->type) {
2,147,483,647✔
3568
      break;
552,821,018✔
3569
    }
3570
    pStmt->pSql += index;
2,147,483,647✔
3571

3572
    bool gotRow = false;
2,147,483,647✔
3573
    if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3574
      if (!pStmt->stbSyntax) {
2,147,483,647✔
3575
        code = parseOneRow(pCxt, &pStmt->pSql, rowsDataCxt.pTableDataCxt, &gotRow, pToken);
2,147,483,647✔
3576
      } else {
3577
        // foreach subtable
3578
        STableDataCxt* pTableDataCxt = NULL;
11,958✔
3579
        code = parseOneStbRow(pCxt, pStmt, &pStmt->pSql, rowsDataCxt.pStbRowsCxt, &gotRow, pToken, &pTableDataCxt);
254,163✔
3580
      }
3581
    }
3582

3583
    if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3584
      NEXT_VALID_TOKEN(pStmt->pSql, *pToken);
2,147,483,647✔
3585
      if (TK_NK_COMMA == pToken->type) {
2,147,483,647✔
3586
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
9,337✔
3587
      } else if (TK_NK_RP != pToken->type) {
2,147,483,647✔
3588
        code = buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
18,356✔
3589
      }
3590
    }
3591

3592
    if (TSDB_CODE_SUCCESS == code && gotRow) {
2,147,483,647✔
3593
      (*pNumOfRows)++;
2,147,483,647✔
3594
    }
3595
  }
3596

3597
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) &&
410,927,453✔
3598
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
6,985,207✔
3599
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
3600
  }
3601
  return code;
553,373,057✔
3602
}
3603

3604
// VALUES (field1_value, ...) [(field1_value2, ...) ...]
3605
static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataContext,
553,366,399✔
3606
                                 SToken* pToken) {
3607
  int32_t numOfRows = 0;
553,366,399✔
3608
  int32_t code = parseValues(pCxt, pStmt, rowsDataContext, &numOfRows, pToken);
553,376,019✔
3609
  if (TSDB_CODE_SUCCESS == code) {
553,376,551✔
3610
    pStmt->totalRowsNum += numOfRows;
552,811,329✔
3611
    pStmt->totalTbNum += 1;
552,814,445✔
3612
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_INSERT);
552,814,163✔
3613
  }
3614
  return code;
553,384,554✔
3615
}
3616

3617
// Simplified CSV parser - only handles newlines within quotes
3618
static int32_t csvParserReadLine(SCsvParser* parser) {
2,147,483,647✔
3619
  if (!parser) {
2,147,483,647✔
3620
    return TSDB_CODE_INVALID_PARA;
×
3621
  }
3622

3623
  size_t  lineLen = 0;
2,147,483,647✔
3624
  bool    inQuotes = false;
2,147,483,647✔
3625
  char    currentQuote = '\0';  // Track which quote character we're inside
2,147,483,647✔
3626
  bool    fieldStart = true;    // Track if we're at the start of a field
2,147,483,647✔
3627
  bool    afterQuote = false;   // Track if we just closed a quoted field
2,147,483,647✔
3628
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3629

3630
  while (true) {
2,147,483,647✔
3631
    // Fill buffer if needed
3632
    if (parser->bufferPos >= parser->bufferLen) {
2,147,483,647✔
3633
      code = csvParserFillBuffer(parser);
24,773,975✔
3634
      if (code != TSDB_CODE_SUCCESS) {
24,773,975✔
3635
        break;
×
3636
      }
3637
      if (parser->bufferPos >= parser->bufferLen && parser->eof) {
24,773,975✔
3638
        // End of file
3639
        if (lineLen == 0) {
583,509✔
3640
          code = TSDB_CODE_TSC_QUERY_CANCELLED;  // Use this to indicate EOF
579,231✔
3641
        } else if (inQuotes) {
4,278✔
3642
          // Unclosed quote at end of file
3643
          code = TSDB_CODE_TSC_INVALID_INPUT;
×
3644
        }
3645
        break;
583,509✔
3646
      }
3647
    }
3648

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

3651
    // Handle quotes - support both single and double quotes
3652
    if (!inQuotes && (ch == CSV_QUOTE_SINGLE || ch == CSV_QUOTE_DOUBLE)) {
2,147,483,647✔
3653
      // Quote can only start a field at the beginning of a field
3654
      if (!fieldStart) {
2,147,483,647✔
3655
        // Invalid: quote appears in the middle of an unquoted field
3656
        code = TSDB_CODE_TSC_INVALID_INPUT;
1,254✔
3657
        break;
1,254✔
3658
      }
3659
      // Starting a quoted section
3660
      inQuotes = true;
2,147,483,647✔
3661
      currentQuote = ch;
2,147,483,647✔
3662
      fieldStart = false;
2,147,483,647✔
3663
      afterQuote = false;
2,147,483,647✔
3664
    } else if (inQuotes && ch == currentQuote) {
2,147,483,647✔
3665
      // Check for escaped quote (double quote)
3666
      if (parser->bufferPos < parser->bufferLen && parser->buffer[parser->bufferPos] == currentQuote) {
2,147,483,647✔
3667
        // Escaped quote - keep both quotes in line for subsequent processing
3668
        // Ensure enough space for both quote characters
3669
        code = csvParserExpandLineBuffer(parser, lineLen + 2);
13,332✔
3670
        if (code != TSDB_CODE_SUCCESS) {
13,332✔
3671
          break;
×
3672
        }
3673

3674
        // Add the first quote character to the line
3675
        parser->lineBuffer[lineLen++] = ch;
13,332✔
3676

3677
        // Consume and add the second quote character
3678
        parser->bufferPos++;
13,332✔
3679
        ch = parser->buffer[parser->bufferPos - 1];  // The second quote
13,332✔
3680
        parser->lineBuffer[lineLen++] = ch;
13,332✔
3681
        continue;
13,332✔
3682
      } else {
3683
        // End of quoted section
3684
        inQuotes = false;
2,147,483,647✔
3685
        currentQuote = '\0';
2,147,483,647✔
3686
        afterQuote = true;  // Mark that we just closed a quote
2,147,483,647✔
3687
      }
3688
    } else if (ch == CSV_DEFAULT_DELIMITER && !inQuotes) {
2,147,483,647✔
3689
      // Comma marks the start of a new field
3690
      fieldStart = true;
2,147,483,647✔
3691
      afterQuote = false;
2,147,483,647✔
3692
    } else if (ch != '\r' && ch != '\n' && ch != ' ') {
2,147,483,647✔
3693
      // Non-space, non-newline character processing
3694
      // Check if we have invalid characters after closing quote
3695
      if (afterQuote) {
2,147,483,647✔
3696
        // Invalid: non-whitespace character after closing quote
3697
        // RFC 4180: after closing quote, only comma, space, or line end is allowed
3698
        code = TSDB_CODE_TSC_INVALID_INPUT;
×
3699
        break;
×
3700
      }
3701
      // Non-space character means we're no longer at field start
3702
      fieldStart = false;
2,147,483,647✔
3703
      afterQuote = false;
2,147,483,647✔
3704
    }
3705

3706
    // Handle newlines
3707
    if (ch == '\n' && !inQuotes) {
2,147,483,647✔
3708
      // End of line (not inside quotes)
3709
      break;
2,147,483,647✔
3710
    }
3711

3712
    // Skip \r characters only when outside quotes
3713
    if (ch == '\r' && !inQuotes) {
2,147,483,647✔
3714
      continue;
2,147,483,647✔
3715
    }
3716

3717
    // Expand buffer if needed
3718
    code = csvParserExpandLineBuffer(parser, lineLen + 1);
2,147,483,647✔
3719
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3720
      break;
×
3721
    }
3722

3723
    // Add character to line
3724
    parser->lineBuffer[lineLen++] = ch;
2,147,483,647✔
3725
  }
3726

3727
  if (code == TSDB_CODE_SUCCESS) {
2,147,483,647✔
3728
    parser->lineBuffer[lineLen] = '\0';
2,147,483,647✔
3729
  } else if (code == TSDB_CODE_TSC_INVALID_INPUT) {
580,485✔
3730
    // Set a more descriptive error for invalid CSV format
3731
    parser->lineBuffer[lineLen] = '\0';  // Null-terminate for error reporting
1,254✔
3732
  }
3733

3734
  return code;
2,147,483,647✔
3735
}
3736

3737
static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
619,745✔
3738
                            int32_t* pNumOfRows) {
3739
  int32_t code = TSDB_CODE_SUCCESS;
619,745✔
3740
  (*pNumOfRows) = 0;
619,745✔
3741

3742
  // Initialize or use existing CSV parser in pStmt
3743
  if (pStmt->pCsvParser == NULL) {
619,745✔
3744
    // First time - allocate and initialize CSV parser
3745
    pStmt->pCsvParser = taosMemoryMalloc(sizeof(SCsvParser));
608,625✔
3746
    if (!pStmt->pCsvParser) {
608,625✔
3747
      return terrno;
×
3748
    }
3749
    code = csvParserInit(pStmt->pCsvParser, pStmt->fp);
608,625✔
3750
    if (code != TSDB_CODE_SUCCESS) {
608,625✔
3751
      taosMemoryFree(pStmt->pCsvParser);
×
3752
      pStmt->pCsvParser = NULL;
×
3753
      return code;
×
3754
    }
3755
  }
3756
  // If pStmt->pCsvParser exists, we continue from where we left off
3757

3758
  bool firstLine = (pStmt->fileProcessing == false);
619,745✔
3759
  pStmt->fileProcessing = false;
619,745✔
3760

3761
  while (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3762
    // Read one line from CSV using the parser in pStmt
3763
    code = csvParserReadLine(pStmt->pCsvParser);
2,147,483,647✔
3764
    if (code == TSDB_CODE_TSC_QUERY_CANCELLED) {
2,147,483,647✔
3765
      // End of file
3766
      code = TSDB_CODE_SUCCESS;
579,231✔
3767
      break;
579,231✔
3768
    }
3769
    if (code == TSDB_CODE_TSC_INVALID_INPUT) {
2,147,483,647✔
3770
      // Invalid CSV format detected
3771
      code = buildSyntaxErrMsg(&pCxt->msg, "Invalid CSV format", pStmt->pCsvParser->lineBuffer);
1,254✔
3772
      break;
1,254✔
3773
    }
3774
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3775
      break;
×
3776
    }
3777

3778
    // Skip empty lines
3779
    if (!pStmt->pCsvParser->lineBuffer || strlen(pStmt->pCsvParser->lineBuffer) == 0) {
2,147,483,647✔
3780
      firstLine = false;
×
3781
      continue;
×
3782
    }
3783

3784
    bool   gotRow = false;
2,147,483,647✔
3785
    SToken token;
2,147,483,647✔
3786
    (void)strtolower(pStmt->pCsvParser->lineBuffer, pStmt->pCsvParser->lineBuffer);
2,147,483,647✔
3787
    const char* pRow = pStmt->pCsvParser->lineBuffer;
2,147,483,647✔
3788

3789
    if (!pStmt->stbSyntax) {
2,147,483,647✔
3790
      code = parseOneRow(pCxt, (const char**)&pRow, rowsDataCxt.pTableDataCxt, &gotRow, &token);
2,147,483,647✔
3791
    } else {
3792
      STableDataCxt* pTableDataCxt = NULL;
1,120,817,190✔
3793
      code = parseOneStbRow(pCxt, pStmt, (const char**)&pRow, rowsDataCxt.pStbRowsCxt, &gotRow, &token, &pTableDataCxt);
1,120,817,190✔
3794
      if (code == TSDB_CODE_SUCCESS) {
1,120,817,190✔
3795
        SStbRowsDataContext* pStbRowsCxt = rowsDataCxt.pStbRowsCxt;
1,120,813,932✔
3796
        void*                pData = pTableDataCxt;
1,120,813,932✔
3797
        code = taosHashPut(pStmt->pTableCxtHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid),
1,120,813,932✔
3798
                           &pData, POINTER_BYTES);
3799
        if (TSDB_CODE_SUCCESS != code) {
1,120,813,932✔
3800
          break;
×
3801
        }
3802
      }
3803
    }
3804

3805
    if (code && firstLine) {
2,147,483,647✔
3806
      firstLine = false;
585,465✔
3807
      code = 0;
585,465✔
3808
      continue;
585,465✔
3809
    }
3810

3811
    if (TSDB_CODE_SUCCESS == code && gotRow) {
2,147,483,647✔
3812
      (*pNumOfRows)++;
2,147,483,647✔
3813
    }
3814

3815
    if (TSDB_CODE_SUCCESS == code && (*pNumOfRows) >= tsMaxInsertBatchRows) {
2,147,483,647✔
3816
      // Reached batch limit - keep the parser in pStmt for next batch
3817
      pStmt->fileProcessing = true;
11,120✔
3818
      break;
11,120✔
3819
    }
3820
    firstLine = false;
2,147,483,647✔
3821
  }
3822

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

3825
  parserDebug("QID:0x%" PRIx64 ", %d rows have been parsed", pCxt->pComCxt->requestId, *pNumOfRows);
619,745✔
3826

3827
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) && 0 == pStmt->totalRowsNum &&
619,745✔
3828
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) && !pStmt->fileProcessing) {
×
3829
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
3830
  }
3831
  return code;
619,745✔
3832
}
3833

3834
static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
619,745✔
3835
                                     SRowsDataContext rowsDataCxt) {
3836
  // init only for file
3837
  if (NULL == pStmt->pTableCxtHashObj) {
619,745✔
3838
    pStmt->pTableCxtHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
594,495✔
3839
    if (!pStmt->pTableCxtHashObj) {
594,495✔
3840
      return terrno;
×
3841
    }
3842
  }
3843
  int32_t numOfRows = 0;
619,745✔
3844
  int32_t code = parseCsvFile(pCxt, pStmt, rowsDataCxt, &numOfRows);
619,745✔
3845
  if (TSDB_CODE_SUCCESS == code) {
619,745✔
3846
    pStmt->totalRowsNum += numOfRows;
590,351✔
3847
    pStmt->totalTbNum += 1;
590,351✔
3848
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT);
590,351✔
3849
    if (rowsDataCxt.pTableDataCxt && rowsDataCxt.pTableDataCxt->pData) {
590,351✔
3850
      rowsDataCxt.pTableDataCxt->pData->flags |= SUBMIT_REQ_FROM_FILE;
583,720✔
3851
    }
3852
    if (!pStmt->fileProcessing) {
590,351✔
3853
      // File processing is complete, clean up saved CSV parser
3854
      destroySavedCsvParser(pStmt);
579,231✔
3855
      code = taosCloseFile(&pStmt->fp);
579,231✔
3856
      if (TSDB_CODE_SUCCESS != code) {
579,231✔
3857
        parserWarn("QID:0x%" PRIx64 ", failed to close file.", pCxt->pComCxt->requestId);
×
3858
      }
3859
    } else {
3860
      parserDebug("QID:0x%" PRIx64 ", insert from csv. File is too large, do it in batches.", pCxt->pComCxt->requestId);
11,120✔
3861
    }
3862
    if (pStmt->insertType != TSDB_QUERY_TYPE_FILE_INSERT) {
590,351✔
3863
      destroySavedCsvParser(pStmt);
×
3864
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", NULL);
×
3865
    }
3866
  } else {
3867
    // On error, also clean up saved CSV parser
3868
    destroySavedCsvParser(pStmt);
29,394✔
3869
    if (code == TSDB_CODE_TSC_SQL_SYNTAX_ERROR) {
29,394✔
3870
      return code;
13,314✔
3871
    }
3872
    return buildInvalidOperationMsg(&pCxt->msg, tstrerror(code));
16,080✔
3873
  }
3874

3875
  // just record pTableCxt whose data come from file
3876
  if (!pStmt->stbSyntax && numOfRows > 0) {
590,351✔
3877
    void* pData = rowsDataCxt.pTableDataCxt;
578,716✔
3878
    code = taosHashPut(pStmt->pTableCxtHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid), &pData,
578,716✔
3879
                       POINTER_BYTES);
3880
  }
3881

3882
  return code;
590,351✔
3883
}
3884

3885
static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pFilePath,
608,625✔
3886
                                 SRowsDataContext rowsDataCxt) {
3887
  char filePathStr[PATH_MAX + 16] = {0};
608,625✔
3888
  if (TK_NK_STRING == pFilePath->type) {
608,625✔
3889
    (void)trimString(pFilePath->z, pFilePath->n, filePathStr, sizeof(filePathStr));
608,580✔
3890
    if (strlen(filePathStr) >= PATH_MAX) {
608,580✔
3891
      return buildSyntaxErrMsg(&pCxt->msg, "file path is too long, max length is 4096", pFilePath->z);
×
3892
    }
3893
  } else {
3894
    if (pFilePath->n >= PATH_MAX) {
45✔
3895
      return buildSyntaxErrMsg(&pCxt->msg, "file path is too long, max length is 4096", pFilePath->z);
×
3896
    }
3897
    tstrncpy(filePathStr, pFilePath->z, pFilePath->n < sizeof(filePathStr) ? pFilePath->n + 1 : sizeof(filePathStr));
45✔
3898
  }
3899
  pStmt->fp = taosOpenFile(filePathStr, TD_FILE_READ);
608,625✔
3900
  if (NULL == pStmt->fp) {
608,625✔
3901
    return terrno;
×
3902
  }
3903

3904
  return parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
608,625✔
3905
}
3906

3907
static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
608,625✔
3908
                               SToken* pToken) {
3909
  if (tsUseAdapter) {
608,625✔
3910
    return buildInvalidOperationMsg(&pCxt->msg, "proxy mode does not support csv loading");
×
3911
  }
3912

3913
  NEXT_TOKEN(pStmt->pSql, *pToken);
608,625✔
3914
  if (0 == pToken->n || (TK_NK_STRING != pToken->type && TK_NK_ID != pToken->type)) {
608,625✔
3915
    return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", pToken->z);
×
3916
  }
3917
  return parseDataFromFile(pCxt, pStmt, pToken, rowsDataCxt);
608,625✔
3918
}
3919

3920
// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
3921
static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt) {
553,977,229✔
3922
  SToken token;
550,030,330✔
3923
  NEXT_TOKEN(pStmt->pSql, token);
553,988,562✔
3924
  switch (token.type) {
553,985,260✔
3925
    case TK_VALUES:
553,376,635✔
3926
      if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT)) {
553,376,635✔
3927
        return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", token.z);
556✔
3928
      }
3929
      return parseValuesClause(pCxt, pStmt, rowsDataCxt, &token);
553,379,805✔
3930
    case TK_FILE:
608,625✔
3931
      return parseFileClause(pCxt, pStmt, rowsDataCxt, &token);
608,625✔
3932
    default:
×
3933
      break;
×
3934
  }
3935
  return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
×
3936
}
3937

3938
static void destroyStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
1,035,983,611✔
3939
  if (pStbRowsCxt == NULL) return;
1,035,983,611✔
3940
  clearStbRowsDataContext(pStbRowsCxt);
220,678✔
3941
  taosArrayDestroy(pStbRowsCxt->aColVals);
226,333✔
3942
  pStbRowsCxt->aColVals = NULL;
226,333✔
3943
  taosArrayDestroy(pStbRowsCxt->aTagVals);
226,333✔
3944
  pStbRowsCxt->aTagVals = NULL;
226,333✔
3945
  taosArrayDestroy(pStbRowsCxt->aTagNames);
226,333✔
3946
  pStbRowsCxt->aTagNames = NULL;
226,333✔
3947
  qDestroyBoundColInfo(&pStbRowsCxt->boundColsInfo);
226,333✔
3948
  tTagFree(pStbRowsCxt->pTag);
226,333✔
3949
  pStbRowsCxt->pTag = NULL;
226,333✔
3950
  taosMemoryFreeClear(pStbRowsCxt->pCtbMeta);
226,333✔
3951
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
226,333✔
3952
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
226,333✔
3953
}
3954

3955
static int32_t constructStbRowsDataContext(SVnodeModifyOpStmt* pStmt, SStbRowsDataContext** ppStbRowsCxt) {
226,528✔
3956
  SStbRowsDataContext* pStbRowsCxt = taosMemoryCalloc(1, sizeof(SStbRowsDataContext));
226,528✔
3957
  if (!pStbRowsCxt) {
226,528✔
3958
    return terrno;
×
3959
  }
3960
  tNameAssign(&pStbRowsCxt->stbName, &pStmt->targetTableName);
226,528✔
3961
  int32_t code = collectUseTable(&pStbRowsCxt->stbName, pStmt->pTableNameHashObj);
226,528✔
3962
  if (TSDB_CODE_SUCCESS == code) {
226,528✔
3963
    code = collectUseDatabase(&pStbRowsCxt->stbName, pStmt->pDbFNameHashObj);
226,528✔
3964
  }
3965
  if (TSDB_CODE_SUCCESS == code) {
226,528✔
3966
    pStbRowsCxt->ctbName.type = TSDB_TABLE_NAME_T;
226,528✔
3967
    pStbRowsCxt->ctbName.acctId = pStbRowsCxt->stbName.acctId;
226,528✔
3968
    memcpy(pStbRowsCxt->ctbName.dbname, pStbRowsCxt->stbName.dbname, sizeof(pStbRowsCxt->stbName.dbname));
226,528✔
3969

3970
    pStbRowsCxt->pTagCond = pStmt->pTagCond;
226,528✔
3971
    pStbRowsCxt->pStbMeta = pStmt->pTableMeta;
226,528✔
3972

3973
    code = cloneTableMeta(pStbRowsCxt->pStbMeta, &pStbRowsCxt->pCtbMeta);
226,528✔
3974
  }
3975
  if (TSDB_CODE_SUCCESS == code) {
226,528✔
3976
    pStbRowsCxt->pCtbMeta->tableType = TSDB_CHILD_TABLE;
226,528✔
3977
    pStbRowsCxt->pCtbMeta->suid = pStbRowsCxt->pStbMeta->uid;
226,528✔
3978

3979
    pStbRowsCxt->aTagNames = taosArrayInit(8, TSDB_COL_NAME_LEN);
226,528✔
3980
    if (!pStbRowsCxt->aTagNames) {
226,528✔
3981
      code = terrno;
×
3982
    }
3983
  }
3984
  if (TSDB_CODE_SUCCESS == code) {
226,528✔
3985
    pStbRowsCxt->aTagVals = taosArrayInit(8, sizeof(STagVal));
226,528✔
3986
    if (!pStbRowsCxt->aTagVals) {
226,528✔
3987
      code = terrno;
×
3988
    }
3989
  }
3990
  if (TSDB_CODE_SUCCESS == code) {
226,528✔
3991
    // col values and bound cols info of STableDataContext is not used
3992
    pStbRowsCxt->aColVals = taosArrayInit(getNumOfColumns(pStbRowsCxt->pStbMeta), sizeof(SColVal));
226,528✔
3993
    if (!pStbRowsCxt->aColVals) code = terrno;
226,528✔
3994
  }
3995
  if (TSDB_CODE_SUCCESS == code) {
226,528✔
3996
    code = insInitColValues(pStbRowsCxt->pStbMeta, pStbRowsCxt->aColVals);
226,528✔
3997
  }
3998
  if (TSDB_CODE_SUCCESS == code) {
226,528✔
3999
    STableComInfo tblInfo = getTableInfo(pStmt->pTableMeta);
226,528✔
4000
    code = insInitBoundColsInfo(tblInfo.numOfColumns + tblInfo.numOfTags + 1, &pStbRowsCxt->boundColsInfo);
226,528✔
4001
  }
4002
  if (TSDB_CODE_SUCCESS == code) {
226,528✔
4003
    *ppStbRowsCxt = pStbRowsCxt;
226,528✔
4004
  } else {
4005
    clearStbRowsDataContext(pStbRowsCxt);
×
4006
  }
4007
  return code;
226,528✔
4008
}
4009

4010
static int32_t parseInsertStbClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
266,507✔
4011
  int32_t code = TSDB_CODE_SUCCESS;
266,507✔
4012
  if (!pStmt->pBoundCols) {
266,507✔
4013
    return buildSyntaxErrMsg(&pCxt->msg, "(...tbname, ts...) bounded cols is expected for supertable insertion",
39,979✔
4014
                             pStmt->pSql);
4015
  }
4016

4017
  SStbRowsDataContext* pStbRowsCxt = NULL;
226,528✔
4018
  code = constructStbRowsDataContext(pStmt, &pStbRowsCxt);
226,528✔
4019

4020
  if (code == TSDB_CODE_SUCCESS) {
226,528✔
4021
    code = parseBoundColumns(pCxt, pStmt, &pStmt->pBoundCols, BOUND_ALL_AND_TBNAME, pStmt->pTableMeta,
226,528✔
4022
                             &pStbRowsCxt->boundColsInfo);
226,528✔
4023
    pStbRowsCxt->hasTimestampTag = false;
226,528✔
4024
    for (int32_t i = 0; i < pStbRowsCxt->boundColsInfo.numOfBound; ++i) {
1,202,999✔
4025
      int16_t schemaIndex = pStbRowsCxt->boundColsInfo.pColIndex[i];
976,471✔
4026
      if (schemaIndex != getTbnameSchemaIndex(pStmt->pTableMeta) && schemaIndex >= getNumOfColumns(pStmt->pTableMeta)) {
976,471✔
4027
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_TIMESTAMP) {
135,049✔
4028
          pStbRowsCxt->hasTimestampTag = true;
585✔
4029
        }
4030
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_JSON) {
135,049✔
4031
          pStbRowsCxt->isJsonTag = true;
×
4032
        }
4033
      }
4034
    }
4035
    pStmt->pStbRowsCxt = pStbRowsCxt;
226,528✔
4036
  }
4037

4038
  if (code == TSDB_CODE_SUCCESS) {
226,528✔
4039
    SRowsDataContext rowsDataCxt;
4040
    rowsDataCxt.pStbRowsCxt = pStbRowsCxt;
213,965✔
4041
    code = parseDataClause(pCxt, pStmt, rowsDataCxt);
213,965✔
4042
  }
4043

4044
  return code;
226,528✔
4045
}
4046

4047
// input pStmt->pSql:
4048
//   1. [(tag1_name, ...)] ...
4049
//   2. VALUES ... | FILE ...
4050
static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
554,332,597✔
4051
  if (!pStmt->stbSyntax) {
554,332,597✔
4052
    STableDataCxt*   pTableCxt = NULL;
554,074,946✔
4053
    int32_t          code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt);
554,067,200✔
4054
    SRowsDataContext rowsDataCxt;
4055
    rowsDataCxt.pTableDataCxt = pTableCxt;
554,080,797✔
4056
    if (TSDB_CODE_SUCCESS == code) {
554,080,797✔
4057
      code = parseDataClause(pCxt, pStmt, rowsDataCxt);
553,777,368✔
4058
    }
4059
    return code;
554,070,423✔
4060
  } else {
4061
    int32_t code = parseInsertStbClauseBottom(pCxt, pStmt);
264,812✔
4062
    return code;
266,507✔
4063
  }
4064
}
4065

4066
static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
554,580,716✔
4067
  qDestroyBoundColInfo(&pCxt->tags);
554,580,716✔
4068
  clearInsertParseContext(pCxt);
554,584,005✔
4069
  taosMemoryFreeClear(pStmt->pTableMeta);
554,581,998✔
4070
  if (pStmt->pTagCond) nodesDestroyNode(pStmt->pTagCond);
554,581,065✔
4071
  if (pStmt->pPrivCols) taosArrayDestroy(pStmt->pPrivCols);
554,579,275✔
4072
  if (pStmt->pTableTag) taosArrayDestroy(pStmt->pTableTag);
554,583,102✔
4073
  tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
554,579,785✔
4074
  taosMemoryFreeClear(pStmt->pCreateTblReq);
554,581,806✔
4075
  pCxt->missCache = false;
554,584,433✔
4076
  pCxt->usingDuplicateTable = false;
554,581,205✔
4077
  pStmt->pBoundCols = NULL;
554,585,916✔
4078
  pStmt->pPrivCols = NULL;
554,580,052✔
4079
  pStmt->pTagCond = NULL;
554,586,567✔
4080
  pStmt->usingTableProcessing = false;
554,578,092✔
4081
  pStmt->fileProcessing = false;
554,583,246✔
4082
  pStmt->usingTableName.type = 0;
554,580,986✔
4083

4084
  destroyStbRowsDataContext(pStmt->pStbRowsCxt);
554,587,533✔
4085
  taosMemoryFreeClear(pStmt->pStbRowsCxt);
554,570,789✔
4086
  pStmt->stbSyntax = false;
554,573,693✔
4087
}
554,581,925✔
4088

4089
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
4090
static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
554,581,033✔
4091
  resetEnvPreTable(pCxt, pStmt);
554,581,033✔
4092
  int32_t code = parseSchemaClauseTop(pCxt, pStmt, pTbName);
554,579,551✔
4093
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
554,570,642✔
4094
    code = parseInsertTableClauseBottom(pCxt, pStmt);
547,419,353✔
4095
  }
4096

4097
  return code;
554,569,492✔
4098
}
4099

4100
static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName,
1,034,925,588✔
4101
                                          bool* pHasData) {
4102
  // no data in the sql string anymore.
4103
  if (0 == pTbName->n) {
1,034,925,588✔
4104
    if (0 != pTbName->type && '\0' != pStmt->pSql[0]) {
480,347,023✔
4105
      return buildSyntaxErrMsg(&pCxt->msg, "invalid table name", pTbName->z);
×
4106
    }
4107

4108
    if (0 == pStmt->totalRowsNum && (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
480,345,435✔
4109
      return buildInvalidOperationMsg(&pCxt->msg, "no data in sql");
×
4110
    }
4111

4112
    *pHasData = false;
480,332,198✔
4113
    return TSDB_CODE_SUCCESS;
480,335,298✔
4114
  }
4115

4116
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT) && pStmt->totalTbNum > 0) {
554,586,217✔
4117
    return buildInvalidOperationMsg(&pCxt->msg, "single table allowed in one stmt");
×
4118
  }
4119

4120
  if (TK_NK_QUESTION == pTbName->type) {
554,585,215✔
4121
    pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
6,856,850✔
4122
    if (pCxt->pComCxt->stmtBindVersion == 0) {
6,855,508✔
4123
      return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
4124
    }
4125

4126
    char*   tbName = NULL;
6,854,090✔
4127
    int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
6,854,090✔
4128
    if (TSDB_CODE_SUCCESS == code) {
6,855,820✔
4129
      pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
6,854,089✔
4130
      pTbName->z = tbName;
6,855,415✔
4131
      pTbName->n = strlen(tbName);
6,855,803✔
4132
    }
4133
    if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
6,855,778✔
4134
      pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
1,773✔
4135
      code = TSDB_CODE_SUCCESS;
1,773✔
4136
    }
4137
    return code;
6,855,154✔
4138
  }
4139

4140
  if (TK_NK_ID != pTbName->type && TK_NK_STRING != pTbName->type && TK_NK_QUESTION != pTbName->type) {
547,723,659✔
4141
    return buildSyntaxErrMsg(&pCxt->msg, "table_name is expected", pTbName->z);
195✔
4142
  }
4143

4144
  // db.? situation,ensure that the only thing following the '.' mark is '?'
4145
  char* tbNameAfterDbName = strnchr(pTbName->z, '.', pTbName->n, true);
547,728,748✔
4146
  if (tbNameAfterDbName != NULL) {
547,728,826✔
4147
    if (*(tbNameAfterDbName + 1) == '?') {
202,405,085✔
4148
      pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
11,312✔
4149
      char* tbName = NULL;
11,312✔
4150
      if (NULL == pCxt->pComCxt->pStmtCb) {
11,312✔
4151
        return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
4152
      }
4153
      int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
11,312✔
4154
      if (TSDB_CODE_SUCCESS == code) {
11,312✔
4155
        pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
6,827✔
4156
        pTbName->z = tbName;
6,827✔
4157
        pTbName->n = strlen(tbName);
6,827✔
4158
      }
4159
      if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
11,312✔
4160
        pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
4,485✔
4161
        code = TSDB_CODE_SUCCESS;
4,485✔
4162
      }
4163
    } else {
4164
      pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
202,389,588✔
4165
      parserTrace("QID:0x%" PRIx64 ", stmt tbname:%s is specified in sql", pCxt->pComCxt->requestId, pTbName->z);
202,391,390✔
4166
      *pHasData = true;
202,391,390✔
4167
    }
4168
    return TSDB_CODE_SUCCESS;
202,404,431✔
4169
  }
4170

4171
  if (TK_NK_ID == pTbName->type) {
345,323,741✔
4172
    pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
341,934,474✔
4173
  }
4174

4175
  *pHasData = true;
345,324,798✔
4176
  return TSDB_CODE_SUCCESS;
345,325,655✔
4177
}
4178

4179
static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
6,987,376✔
4180
  SBoundColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags));
6,987,376✔
4181
  if (NULL == tags) {
6,982,087✔
4182
    return terrno;
×
4183
  }
4184
  memcpy(tags, &pCxt->tags, sizeof(pCxt->tags));
6,982,087✔
4185

4186
  SStmtCallback* pStmtCb = pCxt->pComCxt->pStmtCb;
6,982,529✔
4187
  int32_t        code = (*pStmtCb->setInfoFn)(pStmtCb->pStmt, pStmt->pTableMeta, tags, &pCxt->pParsedValues,
20,874,850✔
4188
                                       &pStmt->targetTableName, pStmt->usingTableProcessing, pStmt->pVgroupsHashObj,
6,988,335✔
4189
                                       pStmt->pTableBlockHashObj, pStmt->usingTableName.tname, pCxt->stmtTbNameFlag);
6,990,391✔
4190

4191
  memset(&pCxt->tags, 0, sizeof(pCxt->tags));
6,960,517✔
4192
  pStmt->pVgroupsHashObj = NULL;
6,962,585✔
4193
  pStmt->pTableBlockHashObj = NULL;
6,977,899✔
4194
  return code;
6,979,793✔
4195
}
4196

4197
static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
480,344,619✔
4198
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) {
480,344,619✔
4199
    return setStmtInfo(pCxt, pStmt);
6,987,722✔
4200
  }
4201

4202
  // release old array alloced by merge
4203
  pStmt->freeArrayFunc(pStmt->pVgDataBlocks);
473,364,755✔
4204
  pStmt->pVgDataBlocks = NULL;
473,363,186✔
4205

4206
  bool fileOnly = (pStmt->insertType == TSDB_QUERY_TYPE_FILE_INSERT);
473,363,139✔
4207
  if (fileOnly) {
473,362,931✔
4208
    // none data, skip merge & buildvgdata
4209
    if (0 == taosHashGetSize(pStmt->pTableCxtHashObj)) {
575,665✔
4210
      pCxt->needRequest = false;
5,560✔
4211
      return TSDB_CODE_SUCCESS;
5,560✔
4212
    }
4213
  }
4214

4215
  // merge according to vgId
4216
  int32_t code = insMergeTableDataCxt(fileOnly ? pStmt->pTableCxtHashObj : pStmt->pTableBlockHashObj,
473,358,472✔
4217
                                      &pStmt->pVgDataBlocks, pStmt->fileProcessing);
473,357,371✔
4218
  // clear tmp hashobj only
4219
  taosHashClear(pStmt->pTableCxtHashObj);
473,358,105✔
4220

4221
  if (TSDB_CODE_SUCCESS == code) {
473,358,641✔
4222
    code = insBuildVgDataBlocks(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks, false);
473,358,641✔
4223
  }
4224

4225
  return code;
473,354,708✔
4226
}
4227

4228
// tb_name
4229
//     [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
4230
//     [(field1_name, ...)]
4231
//     VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
4232
// [...];
4233
static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
488,065,076✔
4234
  SToken  token;
485,433,946✔
4235
  int32_t code = TSDB_CODE_SUCCESS;
488,069,364✔
4236
  bool    hasData = true;
488,069,364✔
4237
  // for each table
4238
  while (TSDB_CODE_SUCCESS == code && hasData && !pCxt->missCache && !pStmt->fileProcessing) {
1,522,985,135✔
4239
    // pStmt->pSql -> tb_name ...
4240
    NEXT_TOKEN(pStmt->pSql, token);
1,034,916,748✔
4241
    code = checkTableClauseFirstToken(pCxt, pStmt, &token, &hasData);
1,034,931,300✔
4242
    if (TSDB_CODE_SUCCESS == code && hasData) {
1,034,908,369✔
4243
      code = parseInsertTableClause(pCxt, pStmt, &token);
554,580,138✔
4244
    }
4245

4246
    if (TSDB_CODE_SUCCESS == code && pStmt->pTableMeta &&
1,034,900,079✔
4247
        (((pStmt->pTableMeta->virtualStb == 1) && (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE)) ||
1,032,692,707✔
4248
         (pStmt->pTableMeta->tableType == TSDB_VIRTUAL_NORMAL_TABLE ||
1,032,689,895✔
4249
          pStmt->pTableMeta->tableType == TSDB_VIRTUAL_CHILD_TABLE))) {
1,032,686,195✔
4250
      code = buildInvalidOperationMsg(&pCxt->msg, "Virtual table can not be written");
7,345✔
4251
    }
4252
  }
4253

4254
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
488,070,341✔
4255
    code = parseInsertBodyBottom(pCxt, pStmt);
480,355,743✔
4256
  }
4257
  return code;
488,045,619✔
4258
}
4259

4260
static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); }
35,450,633✔
4261

4262
static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, SNode** pOutput) {
481,536,676✔
4263
  SVnodeModifyOpStmt* pStmt = NULL;
481,536,676✔
4264
  int32_t             code = nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT, (SNode**)&pStmt);
481,539,068✔
4265
  if (NULL == pStmt) {
481,545,032✔
4266
    return code;
×
4267
  }
4268

4269
  if (pCxt->pComCxt->pStmtCb) {
481,545,032✔
4270
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT);
7,002,163✔
4271
  }
4272
  pStmt->pSql = pCxt->pComCxt->pSql;
481,544,295✔
4273

4274
  pStmt->freeHashFunc = insDestroyTableDataCxtHashMap;
481,540,779✔
4275
  pStmt->freeArrayFunc = insDestroyVgroupDataCxtList;
481,544,796✔
4276
  pStmt->freeStbRowsCxtFunc = destroyStbRowsDataContext;
481,540,146✔
4277
  pStmt->pCsvParser = NULL;
481,540,584✔
4278

4279
  if (!reentry) {
481,538,874✔
4280
    pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
481,538,972✔
4281
    if (pCxt->pComCxt->pStmtCb) {
481,534,857✔
4282
      pStmt->pTableBlockHashObj =
6,999,312✔
4283
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
6,994,830✔
4284
    } else {
4285
      pStmt->pTableBlockHashObj =
474,543,016✔
4286
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
474,539,232✔
4287
    }
4288
  }
4289
  pStmt->pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
481,542,576✔
4290
  pStmt->pSuperTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
481,545,614✔
4291
  pStmt->pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
481,544,751✔
4292
  pStmt->pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
481,545,752✔
4293
  if ((!reentry && (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj)) ||
481,545,406✔
4294
      NULL == pStmt->pSubTableHashObj || NULL == pStmt->pTableNameHashObj || NULL == pStmt->pDbFNameHashObj) {
481,542,104✔
4295
    nodesDestroyNode((SNode*)pStmt);
1,193✔
4296
    return TSDB_CODE_OUT_OF_MEMORY;
×
4297
  }
4298

4299
  taosHashSetFreeFp(pStmt->pSubTableHashObj, destroySubTableHashElem);
481,544,766✔
4300
  taosHashSetFreeFp(pStmt->pSuperTableHashObj, destroySubTableHashElem);
481,541,652✔
4301

4302
  *pOutput = (SNode*)pStmt;
481,541,693✔
4303
  return TSDB_CODE_SUCCESS;
481,543,825✔
4304
}
4305

4306
static int32_t createInsertQuery(SInsertParseContext* pCxt, SQuery** pOutput) {
481,530,978✔
4307
  SQuery* pQuery = NULL;
481,530,978✔
4308
  int32_t code = nodesMakeNode(QUERY_NODE_QUERY, (SNode**)&pQuery);
481,534,184✔
4309
  if (NULL == pQuery) {
481,536,914✔
4310
    return code;
×
4311
  }
4312

4313
  pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
481,536,914✔
4314
  pQuery->haveResultSet = false;
481,538,800✔
4315
  pQuery->msgType = TDMT_VND_SUBMIT;
481,535,432✔
4316

4317
  code = createVnodeModifOpStmt(pCxt, false, &pQuery->pRoot);
481,535,998✔
4318
  if (TSDB_CODE_SUCCESS == code) {
481,539,911✔
4319
    *pOutput = pQuery;
481,539,911✔
4320
  } else {
4321
    nodesDestroyNode((SNode*)pQuery);
×
4322
  }
4323
  return code;
481,536,297✔
4324
}
4325

4326
static int32_t checkAuthFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData, SVnodeModifyOpStmt* pStmt) {
7,075,415✔
4327
  int32_t code = TSDB_CODE_SUCCESS;
7,075,415✔
4328
  if (1 != taosArrayGetSize(pMetaData->pUser)) {
7,075,415✔
4329
    code = TSDB_CODE_INTERNAL_ERROR;
×
4330
    uError("unexpected meta data size: %d since %s", (int32_t)taosArrayGetSize(pMetaData->pUser), tstrerror(code));
×
4331
    return code;
×
4332
  }
4333

4334
  SMetaRes* pRes = TARRAY_GET_ELEM(pMetaData->pUser, 0);
7,075,415✔
4335
  if (TSDB_CODE_SUCCESS == pRes->code) {
7,075,415✔
4336
    SUserAuthRes* pAuth = pRes->pRes;
7,075,051✔
4337
    pRes->code = nodesCloneNode(pAuth->pCond[AUTH_RES_BASIC], &pStmt->pTagCond);
7,075,051✔
4338
    if (pAuth->pCols && (TSDB_CODE_SUCCESS == pRes->code)) {
7,075,051✔
4339
      if (!(pStmt->pPrivCols = taosArrayDup(pAuth->pCols, NULL))) {
3,646✔
4340
        pRes->code = terrno;
×
4341
      }
4342
    }
4343
    if (TSDB_CODE_SUCCESS == pRes->code) {
7,075,051✔
4344
      return pAuth->pass[AUTH_RES_BASIC] ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED;
7,075,051✔
4345
    }
4346
  }
4347
  return pRes->code;
364✔
4348
}
4349

4350
static int32_t getTableMetaFromMetaData(const SArray* pTables, STableMeta** pMeta) {
7,063,950✔
4351
  if (1 != taosArrayGetSize(pTables) && 2 != taosArrayGetSize(pTables)) {
7,063,950✔
4352
    return TSDB_CODE_FAILED;
×
4353
  }
4354

4355
  taosMemoryFreeClear(*pMeta);
7,063,963✔
4356
  SMetaRes* pRes = taosArrayGet(pTables, 0);
7,063,963✔
4357
  if (TSDB_CODE_SUCCESS == pRes->code) {
7,063,950✔
4358
    *pMeta = tableMetaDup((const STableMeta*)pRes->pRes);
6,927,979✔
4359
    if (NULL == *pMeta) {
6,927,979✔
4360
      return TSDB_CODE_OUT_OF_MEMORY;
×
4361
    }
4362
  }
4363
  return pRes->code;
7,063,950✔
4364
}
4365

4366
static int32_t checkAuthUseDb(SParseContext* pCxt, SName* pTbName, bool isAudit) {
6,927,979✔
4367
  int32_t       code = TSDB_CODE_SUCCESS;
6,927,979✔
4368
  SUserAuthInfo authInfo = {.userId = pCxt->userId, .privType = PRIV_DB_USE, .objType = PRIV_OBJ_DB};
6,927,979✔
4369
  (void)snprintf(authInfo.user, sizeof(authInfo.user), "%s", pCxt->pUser);
6,927,979✔
4370
  (void)snprintf(authInfo.tbName.dbname, sizeof(authInfo.tbName.dbname), "%s", pTbName->dbname);
6,927,979✔
4371
  authInfo.tbName.acctId = pTbName->acctId;
6,927,979✔
4372
  authInfo.tbName.type = TSDB_DB_NAME_T;
6,927,979✔
4373
  authInfo.useDb = isAudit ? AUTH_OWNED_MASK : (AUTH_AUTHORIZED_MASK | AUTH_OWNED_MASK);
6,927,979✔
4374

4375
  if (isAudit) {
6,927,979✔
4376
    // for audit db, recheck insert privilege
4377
    authInfo.privType = PRIV_AUDIT_TBL_INSERT;
×
4378
    authInfo.objType = PRIV_OBJ_TBL;
×
4379
  }
4380

4381
  SUserAuthRes     authRes = {0};
6,927,979✔
4382
  SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
13,842,723✔
4383
                           .requestId = pCxt->requestId,
6,927,979✔
4384
                           .requestObjRefId = pCxt->requestRid,
6,927,979✔
4385
                           .mgmtEps = pCxt->mgmtEpSet};
4386
  code = catalogChkAuth(pCxt->pCatalog, &conn, &authInfo, &authRes);  // cache used firstly inside the function
6,927,979✔
4387
  if (TSDB_CODE_SUCCESS == code && !authRes.pass[AUTH_RES_BASIC]) {
6,927,979✔
4388
    code = TSDB_CODE_PAR_DB_USE_PERMISSION_DENIED;
×
4389
  }
4390
  return code;
6,927,979✔
4391
}
4392

4393
static int32_t addTableVgroupFromMetaData(const SArray* pTables, SVnodeModifyOpStmt* pStmt, bool isStb) {
6,924,621✔
4394
  if (1 != taosArrayGetSize(pTables)) {
6,924,621✔
4395
    return TSDB_CODE_FAILED;
×
4396
  }
4397

4398
  SMetaRes* pRes = taosArrayGet(pTables, 0);
6,924,621✔
4399
  if (TSDB_CODE_SUCCESS != pRes->code) {
6,924,634✔
4400
    return pRes->code;
×
4401
  }
4402

4403
  SVgroupInfo* pVg = pRes->pRes;
6,924,634✔
4404
  if (isStb) {
6,924,634✔
4405
    pStmt->pTableMeta->vgId = pVg->vgId;
5,500,801✔
4406
  }
4407
  return taosHashPut(pStmt->pVgroupsHashObj, (const char*)&pVg->vgId, sizeof(pVg->vgId), (char*)pVg,
6,924,634✔
4408
                     sizeof(SVgroupInfo));
4409
}
4410

4411
static int32_t buildTagNameFromMeta(STableMeta* pMeta, SArray** pTagName) {
4,898✔
4412
  *pTagName = taosArrayInit(pMeta->tableInfo.numOfTags, TSDB_COL_NAME_LEN);
4,898✔
4413
  if (NULL == *pTagName) {
4,898✔
4414
    return terrno;
×
4415
  }
4416
  SSchema* pSchema = getTableTagSchema(pMeta);
4,898✔
4417
  int32_t  code = 0;
4,898✔
4418
  for (int32_t i = 0; i < pMeta->tableInfo.numOfTags; ++i) {
11,048✔
4419
    if (NULL == taosArrayPush(*pTagName, pSchema[i].name)) {
12,300✔
4420
      code = terrno;
×
4421
      taosArrayDestroy(*pTagName);
×
4422
      *pTagName = NULL;
×
4423
      break;
×
4424
    }
4425
  }
4426
  return code;
4,898✔
4427
}
4428

4429
static int32_t checkSubtablePrivilegeForTable(const SArray* pTables, SVnodeModifyOpStmt* pStmt) {
4,898✔
4430
#ifdef TD_ENTERPRISE
4431
  if (1 != taosArrayGetSize(pTables)) {
4,898✔
4432
    return TSDB_CODE_FAILED;
×
4433
  }
4434

4435
  SMetaRes* pRes = taosArrayGet(pTables, 0);
4,898✔
4436
  if (TSDB_CODE_SUCCESS != pRes->code) {
4,898✔
4437
    return pRes->code;
×
4438
  }
4439

4440
  SArray* pTagName = NULL;
4,898✔
4441
  int32_t code = buildTagNameFromMeta(pStmt->pTableMeta, &pTagName);
4,898✔
4442
  if (TSDB_CODE_SUCCESS == code) {
4,898✔
4443
    code = checkSubtablePrivilege((SArray*)pRes->pRes, pTagName, &pStmt->pTagCond);
4,898✔
4444
  }
4445
  taosArrayDestroy(pTagName);
4,898✔
4446
  return code;
4,898✔
4447
#else
4448
  return TSDB_CODE_SUCCESS;
4449
#endif
4450
}
4451

4452
static int32_t processTableSchemaFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData,
6,924,621✔
4453
                                              SVnodeModifyOpStmt* pStmt, bool isStb) {
4454
  int32_t code = TSDB_CODE_SUCCESS;
6,924,621✔
4455
  if (!isStb && TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
6,924,621✔
4456
    code = buildInvalidOperationMsg(&pCxt->msg, "insert data into super table is not supported");
×
4457
  }
4458

4459
  if (TSDB_CODE_SUCCESS == code && isStb) {
6,924,621✔
4460
    code = storeChildTableMeta(pCxt, pStmt);
5,500,801✔
4461
  }
4462
  if (TSDB_CODE_SUCCESS == code) {
6,924,621✔
4463
    code = addTableVgroupFromMetaData(pMetaData->pTableHash, pStmt, isStb);
6,924,621✔
4464
  }
4465
  if (TSDB_CODE_SUCCESS == code && !isStb && NULL != pStmt->pTagCond) {
6,924,621✔
4466
    code = checkSubtablePrivilegeForTable(pMetaData->pTableTag, pStmt);
4,898✔
4467
  }
4468
  return code;
6,924,621✔
4469
}
4470

4471
static void destoryTablesReq(void* p) {
14,150,830✔
4472
  STablesReq* pRes = (STablesReq*)p;
14,150,830✔
4473
  taosArrayDestroy(pRes->pTables);
14,150,830✔
4474
}
14,150,830✔
4475

4476
static void clearCatalogReq(SCatalogReq* pCatalogReq) {
7,075,415✔
4477
  if (NULL == pCatalogReq) {
7,075,415✔
4478
    return;
×
4479
  }
4480

4481
  taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq);
7,075,415✔
4482
  pCatalogReq->pTableMeta = NULL;
7,075,415✔
4483
  taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq);
7,075,415✔
4484
  pCatalogReq->pTableHash = NULL;
7,075,415✔
4485
  taosArrayDestroy(pCatalogReq->pUser);
7,075,415✔
4486
  pCatalogReq->pUser = NULL;
7,075,415✔
4487
  taosArrayDestroy(pCatalogReq->pTableTag);
7,075,415✔
4488
  pCatalogReq->pTableTag = NULL;
7,075,415✔
4489
}
4490

4491
static int32_t setVnodeModifOpStmt(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
7,075,415✔
4492
                                   SVnodeModifyOpStmt* pStmt) {
4493
  clearCatalogReq(pCatalogReq);
7,075,415✔
4494
  if (pStmt->pPrivCols) {
7,075,415✔
4495
    taosArrayDestroy(pStmt->pPrivCols);
3,646✔
4496
    pStmt->pPrivCols = NULL;
3,646✔
4497
  }
4498
  if (pStmt->pTagCond) {
7,075,415✔
4499
    nodesDestroyNode(pStmt->pTagCond);
×
4500
    pStmt->pTagCond = NULL;
×
4501
  }
4502

4503
  int32_t code = checkAuthFromMetaData(pCxt, pMetaData, pStmt);
7,075,415✔
4504

4505
  if (code == TSDB_CODE_SUCCESS) {
7,075,415✔
4506
    code = getTableMetaFromMetaData(pMetaData->pTableMeta, &pStmt->pTableMeta);
7,063,963✔
4507
  }
4508
  if (code == TSDB_CODE_SUCCESS) {
7,075,402✔
4509
    code = checkAuthUseDb(pCxt->pComCxt, &pStmt->targetTableName, pStmt->pTableMeta->isAudit);
6,927,979✔
4510
  }
4511
  if (code == TSDB_CODE_SUCCESS) {
7,075,402✔
4512
    if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE && !pStmt->usingTableProcessing) {
6,927,979✔
4513
      pStmt->stbSyntax = true;
3,358✔
4514
    }
4515
    if (!pStmt->stbSyntax) {
6,927,979✔
4516
      if (pStmt->usingTableProcessing) {
6,924,621✔
4517
        return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, true);
5,500,801✔
4518
      }
4519
      return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, false);
1,423,820✔
4520
    }
4521
  }
4522
  return code;
150,781✔
4523
}
4524

4525
static int32_t resetVnodeModifOpStmt(SInsertParseContext* pCxt, SQuery* pQuery) {
3,535✔
4526
  nodesDestroyNode(pQuery->pRoot);
3,535✔
4527

4528
  int32_t code = createVnodeModifOpStmt(pCxt, true, &pQuery->pRoot);
3,535✔
4529
  if (TSDB_CODE_SUCCESS == code) {
3,535✔
4530
    SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
3,535✔
4531

4532
    code = (*pCxt->pComCxt->pStmtCb->getExecInfoFn)(pCxt->pComCxt->pStmtCb->pStmt, &pStmt->pVgroupsHashObj,
3,535✔
4533
                                                    &pStmt->pTableBlockHashObj);
4534
    if (TSDB_CODE_SUCCESS == code) {
3,535✔
4535
      if (NULL == pStmt->pVgroupsHashObj) {
3,535✔
4536
        pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
×
4537
      }
4538
      if (NULL == pStmt->pTableBlockHashObj) {
3,535✔
4539
        pStmt->pTableBlockHashObj =
×
4540
            taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
×
4541
      }
4542
      if (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj) {
3,535✔
4543
        code = TSDB_CODE_OUT_OF_MEMORY;
×
4544
      }
4545
    }
4546
  }
4547

4548
  return code;
3,535✔
4549
}
4550

4551
static int32_t initInsertQuery(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
488,627,506✔
4552
                               SQuery** pQuery) {
4553
  if (NULL == *pQuery) {
488,627,506✔
4554
    return createInsertQuery(pCxt, pQuery);
481,540,718✔
4555
  }
4556

4557
  if (NULL != pCxt->pComCxt->pStmtCb) {
7,088,636✔
4558
    return resetVnodeModifOpStmt(pCxt, *pQuery);
3,535✔
4559
  }
4560

4561
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)(*pQuery)->pRoot;
7,086,535✔
4562

4563
  if (!pStmt->fileProcessing) {
7,086,535✔
4564
    return setVnodeModifOpStmt(pCxt, pCatalogReq, pMetaData, pStmt);
7,075,415✔
4565
  }
4566

4567
  return TSDB_CODE_SUCCESS;
11,120✔
4568
}
4569

4570
static int32_t setRefreshMeta(SQuery* pQuery) {
480,343,692✔
4571
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
480,343,692✔
4572
  int32_t             code = 0;
480,351,700✔
4573

4574
  if (taosHashGetSize(pStmt->pTableNameHashObj) > 0) {
480,351,700✔
4575
    taosArrayDestroy(pQuery->pTableList);
7,148,602✔
4576
    pQuery->pTableList = taosArrayInit(taosHashGetSize(pStmt->pTableNameHashObj), sizeof(SName));
7,137,824✔
4577
    if (!pQuery->pTableList) {
7,123,540✔
4578
      code = terrno;
×
4579
    } else {
4580
      SName* pTable = taosHashIterate(pStmt->pTableNameHashObj, NULL);
7,130,595✔
4581
      while (NULL != pTable) {
17,205,812✔
4582
        if (NULL == taosArrayPush(pQuery->pTableList, pTable)) {
20,105,424✔
4583
          code = terrno;
×
4584
          taosHashCancelIterate(pStmt->pTableNameHashObj, pTable);
×
4585
          break;
×
4586
        }
4587
        pTable = taosHashIterate(pStmt->pTableNameHashObj, pTable);
10,054,434✔
4588
      }
4589
    }
4590
  }
4591

4592
  if (TSDB_CODE_SUCCESS == code && taosHashGetSize(pStmt->pDbFNameHashObj) > 0) {
480,359,882✔
4593
    taosArrayDestroy(pQuery->pDbList);
7,154,460✔
4594
    pQuery->pDbList = taosArrayInit(taosHashGetSize(pStmt->pDbFNameHashObj), TSDB_DB_FNAME_LEN);
7,153,784✔
4595
    if (!pQuery->pDbList) {
7,133,458✔
4596
      code = terrno;
×
4597
    } else {
4598
      char* pDb = taosHashIterate(pStmt->pDbFNameHashObj, NULL);
7,138,930✔
4599
      while (NULL != pDb) {
14,306,890✔
4600
        if (NULL == taosArrayPush(pQuery->pDbList, pDb)) {
14,305,090✔
4601
          code = terrno;
×
4602
          taosHashCancelIterate(pStmt->pDbFNameHashObj, pDb);
×
4603
          break;
×
4604
        }
4605
        pDb = taosHashIterate(pStmt->pDbFNameHashObj, pDb);
7,154,327✔
4606
      }
4607
    }
4608
  }
4609

4610
  return code;
480,362,435✔
4611
}
4612

4613
// INSERT INTO
4614
//   tb_name
4615
//       [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]]
4616
//       [(field1_name, ...)]
4617
//       VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
4618
//   [...];
4619
static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
481,539,945✔
4620
  int32_t code = skipInsertInto(&pStmt->pSql, &pCxt->msg);
481,539,945✔
4621
  if (TSDB_CODE_SUCCESS == code) {
481,544,884✔
4622
    code = parseInsertBody(pCxt, pStmt);
481,545,773✔
4623
  }
4624
  return code;
481,514,691✔
4625
}
4626

4627
static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
11,120✔
4628
  int32_t          code = TSDB_CODE_SUCCESS;
11,120✔
4629
  SRowsDataContext rowsDataCxt;
4630

4631
  if (!pStmt->stbSyntax) {
11,120✔
4632
    STableDataCxt* pTableCxt = NULL;
10,008✔
4633
    code = getTableDataCxt(pCxt, pStmt, &pTableCxt);
10,008✔
4634
    rowsDataCxt.pTableDataCxt = pTableCxt;
10,008✔
4635
  } else {
4636
    rowsDataCxt.pStbRowsCxt = pStmt->pStbRowsCxt;
1,112✔
4637
  }
4638
  if (TSDB_CODE_SUCCESS == code) {
11,120✔
4639
    code = parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
11,120✔
4640
  }
4641

4642
  if (TSDB_CODE_SUCCESS == code) {
11,120✔
4643
    if (pStmt->fileProcessing) {
11,120✔
4644
      code = parseInsertBodyBottom(pCxt, pStmt);
×
4645
    } else {
4646
      code = parseInsertBody(pCxt, pStmt);
11,120✔
4647
    }
4648
  }
4649

4650
  return code;
11,120✔
4651
}
4652

4653
static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
6,927,291✔
4654
  int32_t code = parseInsertTableClauseBottom(pCxt, pStmt);
6,927,291✔
4655
  if (TSDB_CODE_SUCCESS == code) {
6,927,291✔
4656
    code = parseInsertBody(pCxt, pStmt);
6,516,196✔
4657
  }
4658
  return code;
6,927,291✔
4659
}
4660

4661
static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
488,478,488✔
4662
  if (pStmt->pSql == pCxt->pComCxt->pSql || NULL != pCxt->pComCxt->pStmtCb) {
488,478,488✔
4663
    return parseInsertSqlFromStart(pCxt, pStmt);
481,543,429✔
4664
  }
4665

4666
  if (pStmt->fileProcessing) {
6,938,424✔
4667
    return parseInsertSqlFromCsv(pCxt, pStmt);
11,120✔
4668
  }
4669

4670
  return parseInsertSqlFromTable(pCxt, pStmt);
6,927,304✔
4671
}
4672

4673
static int32_t buildUsingInsertTableReq(SName* pSName, SName* pCName, SArray** pTables) {
5,533,450✔
4674
  if (NULL == *pTables) {
5,533,450✔
4675
    *pTables = taosArrayInit(2, sizeof(SName));
5,533,450✔
4676
    if (NULL == *pTables) {
5,533,437✔
4677
      goto _err;
×
4678
    }
4679
  }
4680
  if (NULL == taosArrayPush(*pTables, pSName)) {
11,066,887✔
4681
    goto _err;
×
4682
  }
4683
  if (NULL == taosArrayPush(*pTables, pCName)) {
11,066,887✔
4684
    goto _err;
×
4685
  }
4686
  return TSDB_CODE_SUCCESS;
5,533,437✔
4687

4688
_err:
×
4689
  if (NULL != *pTables) {
×
4690
    taosArrayDestroy(*pTables);
×
4691
    *pTables = NULL;
×
4692
  }
4693
  return terrno;
×
4694
}
4695

4696
static int32_t buildInsertTableReq(SName* pName, SArray** pTables) {
8,671,512✔
4697
  *pTables = taosArrayInit(1, sizeof(SName));
8,671,512✔
4698
  if (NULL == *pTables) {
8,671,736✔
4699
    return terrno;
×
4700
  }
4701

4702
  if (NULL == taosArrayPush(*pTables, pName)) {
17,343,472✔
4703
    taosArrayDestroy(*pTables);
×
4704
    *pTables = NULL;
×
4705
    return terrno;
×
4706
  }
4707
  return TSDB_CODE_SUCCESS;
8,671,736✔
4708
}
4709

4710
static int32_t buildInsertUsingDbReq(SName* pSName, SName* pCName, SArray** pDbs) {
5,533,450✔
4711
  if (NULL == *pDbs) {
5,533,450✔
4712
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
5,533,450✔
4713
    if (NULL == *pDbs) {
5,533,437✔
4714
      return terrno;
×
4715
    }
4716
  }
4717

4718
  STablesReq req = {0};
5,533,437✔
4719
  req.autoCreate = 1;
5,533,437✔
4720
  (void)tNameGetFullDbName(pSName, req.dbFName);
5,533,437✔
4721
  (void)tNameGetFullDbName(pCName, req.dbFName);
5,533,450✔
4722

4723
  int32_t code = buildUsingInsertTableReq(pSName, pCName, &req.pTables);
5,533,450✔
4724
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
11,066,887✔
4725
    code = TSDB_CODE_OUT_OF_MEMORY;
×
4726
  }
4727
  return code;
5,533,450✔
4728
}
4729

4730
static int32_t buildInsertDbReq(SName* pName, SArray** pDbs) {
8,666,110✔
4731
  if (NULL == *pDbs) {
8,666,110✔
4732
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
8,666,110✔
4733
    if (NULL == *pDbs) {
8,666,097✔
4734
      return terrno;
×
4735
    }
4736
  }
4737

4738
  STablesReq req = {0};
8,666,097✔
4739
  (void)tNameGetFullDbName(pName, req.dbFName);
8,666,097✔
4740
  int32_t code = buildInsertTableReq(pName, &req.pTables);
8,666,110✔
4741
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
17,332,220✔
4742
    code = TSDB_CODE_OUT_OF_MEMORY;
×
4743
  }
4744

4745
  return code;
8,666,110✔
4746
}
4747

4748
static int32_t buildInsertUserAuthReq(SParseContext* pCxt, SName* pName, SArray** pUserAuth) {
7,099,780✔
4749
  *pUserAuth = taosArrayInit(1, sizeof(SUserAuthInfo));
7,099,780✔
4750
  if (NULL == *pUserAuth) {
7,099,780✔
4751
    return terrno;
×
4752
  }
4753

4754
  SUserAuthInfo userAuth = {.privType = PRIV_TBL_INSERT, .objType = PRIV_OBJ_TBL, .userId = pCxt->userId};
7,099,780✔
4755
  snprintf(userAuth.user, sizeof(userAuth.user), "%s", pCxt->pUser);
7,099,780✔
4756
  memcpy(&userAuth.tbName, pName, sizeof(SName));
7,099,780✔
4757
  if (NULL == taosArrayPush(*pUserAuth, &userAuth)) {
14,199,560✔
4758
    taosArrayDestroy(*pUserAuth);
×
4759
    *pUserAuth = NULL;
×
4760
    return terrno;
×
4761
  }
4762

4763
  return TSDB_CODE_SUCCESS;
7,099,780✔
4764
}
4765

4766
static int32_t buildInsertTableTagReq(SName* pName, SArray** pTables) { return buildInsertTableReq(pName, pTables); }
5,626✔
4767

4768
static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SCatalogReq* pCatalogReq) {
7,099,780✔
4769
  int32_t code = buildInsertUserAuthReq(
14,178,832✔
4770
      pCxt->pComCxt, (0 == pStmt->usingTableName.type ? &pStmt->targetTableName : &pStmt->usingTableName),
7,099,780✔
4771
      &pCatalogReq->pUser);
4772
  if (TSDB_CODE_SUCCESS == code && pCxt->needTableTagVal) {
7,099,780✔
4773
    code = buildInsertTableTagReq(&pStmt->targetTableName, &pCatalogReq->pTableTag);
5,626✔
4774
  }
4775
  if (TSDB_CODE_SUCCESS == code) {
7,099,780✔
4776
    if (0 == pStmt->usingTableName.type) {
7,099,780✔
4777
      code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableMeta);
1,566,330✔
4778
    } else {
4779
      code = buildInsertUsingDbReq(&pStmt->usingTableName, &pStmt->targetTableName, &pCatalogReq->pTableMeta);
5,533,450✔
4780
    }
4781
  }
4782
  if (TSDB_CODE_SUCCESS == code) {
7,099,780✔
4783
    code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableHash);
7,099,780✔
4784
  }
4785
  return code;
7,099,780✔
4786
}
4787

4788
static int32_t setNextStageInfo(SInsertParseContext* pCxt, SQuery* pQuery, SCatalogReq* pCatalogReq) {
487,439,981✔
4789
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
487,439,981✔
4790
  if (pCxt->missCache) {
487,450,495✔
4791
    parserDebug("QID:0x%" PRIx64 ", %d rows of %d tables will be inserted before obtain the cache",
7,099,780✔
4792
                pCxt->pComCxt->requestId, pStmt->totalRowsNum, pStmt->totalTbNum);
4793

4794
    pQuery->execStage = QUERY_EXEC_STAGE_PARSE;
7,099,780✔
4795
    return buildInsertCatalogReq(pCxt, pStmt, pCatalogReq);
7,099,780✔
4796
  }
4797

4798
  parserDebug("QID:0x%" PRIx64 ", %d rows of %d tables will be inserted", pCxt->pComCxt->requestId, pStmt->totalRowsNum,
480,347,920✔
4799
              pStmt->totalTbNum);
4800

4801
  pQuery->execStage = QUERY_EXEC_STAGE_SCHEDULE;
480,348,825✔
4802
  return TSDB_CODE_SUCCESS;
480,354,098✔
4803
}
4804

4805
int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) {
488,622,344✔
4806
  SInsertParseContext context = {.pComCxt = pCxt,
491,260,941✔
4807
                                 .msg = {.buf = pCxt->pMsg, .len = pCxt->msgLen},
488,624,389✔
4808
                                 .missCache = false,
4809
                                 .usingDuplicateTable = false,
4810
                                 .needRequest = true,
4811
                                 .forceUpdate = (NULL != pCatalogReq ? pCatalogReq->forceUpdate : false)};
488,630,263✔
4812

4813
  int32_t code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery);
488,630,263✔
4814
  if (TSDB_CODE_SUCCESS == code) {
488,627,291✔
4815
    code = parseInsertSqlImpl(&context, (SVnodeModifyOpStmt*)((*pQuery)->pRoot));
488,479,962✔
4816
  }
4817

4818
  if (TSDB_CODE_SUCCESS == code) {
488,602,687✔
4819
    code = setNextStageInfo(&context, *pQuery, pCatalogReq);
487,433,186✔
4820
  }
4821
  if ((TSDB_CODE_SUCCESS == code || NEED_CLIENT_HANDLE_ERROR(code)) &&
488,620,212✔
4822
      QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) {
487,642,842✔
4823
    code = setRefreshMeta(*pQuery);
480,346,440✔
4824
  }
4825

4826
  qDestroyBoundColInfo(&context.tags);
488,639,024✔
4827
  clearInsertParseContext(&context);
488,622,295✔
4828
  // if no data to insert, set emptyMode to avoid request server
4829
  if (!context.needRequest) {
488,612,136✔
4830
    (*pQuery)->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
5,560✔
4831
  }
4832
  return code;
488,612,136✔
4833
}
4834

4835
// CSV Parser Implementation
4836
static int32_t csvParserInit(SCsvParser* parser, TdFilePtr pFile) {
608,625✔
4837
  if (!parser || !pFile) {
608,625✔
4838
    return TSDB_CODE_INVALID_PARA;
×
4839
  }
4840

4841
  memset(parser, 0, sizeof(SCsvParser));
608,625✔
4842

4843
  // Set default CSV format
4844
  parser->delimiter = CSV_DEFAULT_DELIMITER;
608,625✔
4845
  parser->quote = CSV_QUOTE_SINGLE;  // Default to single quote for TDengine compatibility
608,625✔
4846
  parser->escape = CSV_ESCAPE_CHAR;
608,625✔
4847
  parser->allowNewlineInField = true;
608,625✔
4848

4849
  // Initialize buffer
4850
  parser->bufferSize = 64 * 1024;  // 64KB buffer
608,625✔
4851
  parser->buffer = taosMemoryMalloc(parser->bufferSize);
608,625✔
4852
  if (!parser->buffer) {
608,625✔
4853
    return terrno;
×
4854
  }
4855

4856
  // Initialize line buffer for reuse
4857
  parser->lineBufferCapacity = 64 * 1024;  // Initial 64KB line buffer
608,625✔
4858
  parser->lineBuffer = taosMemoryMalloc(parser->lineBufferCapacity);
608,625✔
4859
  if (!parser->lineBuffer) {
608,625✔
4860
    return terrno;
×
4861
  }
4862

4863
  parser->bufferPos = 0;
608,625✔
4864
  parser->bufferLen = 0;
608,625✔
4865
  parser->eof = false;
608,625✔
4866
  parser->pFile = pFile;
608,625✔
4867

4868
  // Fill initial buffer to detect quote type
4869
  int32_t code = csvParserFillBuffer(parser);
608,625✔
4870
  if (code != TSDB_CODE_SUCCESS) {
608,625✔
4871
    return code;
×
4872
  }
4873

4874
  // Auto-detect quote character by finding the first quote in the file
4875
  // Skip the header line and look for the first quote character in data
4876
  bool foundFirstQuote = false;
608,625✔
4877
  bool inFirstLine = true;
608,625✔
4878

4879
  for (size_t i = 0; i < parser->bufferLen && !foundFirstQuote; i++) {
760,225,796✔
4880
    char ch = parser->buffer[i];
759,617,171✔
4881

4882
    // Skip the first line (header)
4883
    if (inFirstLine) {
759,617,171✔
4884
      if (ch == '\n') {
101,630,428✔
4885
        inFirstLine = false;
607,371✔
4886
      }
4887
      continue;
101,630,428✔
4888
    }
4889

4890
    // Look for the first quote character in data lines
4891
    if (ch == CSV_QUOTE_SINGLE) {
657,986,743✔
4892
      parser->quote = CSV_QUOTE_SINGLE;
72,059✔
4893
      foundFirstQuote = true;
72,059✔
4894
    } else if (ch == CSV_QUOTE_DOUBLE) {
657,914,684✔
4895
      parser->quote = CSV_QUOTE_DOUBLE;
524,748✔
4896
      foundFirstQuote = true;
524,748✔
4897
    }
4898
  }
4899

4900
  // If no quotes found, keep default (single quote for TDengine compatibility)
4901

4902
  // Reset buffer position for actual parsing
4903
  parser->bufferPos = 0;
608,625✔
4904

4905
  return TSDB_CODE_SUCCESS;
608,625✔
4906
}
4907

4908
static void csvParserDestroy(SCsvParser* parser) {
608,625✔
4909
  if (parser) {
608,625✔
4910
    taosMemoryFree(parser->buffer);
608,625✔
4911
    taosMemoryFree(parser->lineBuffer);
608,625✔
4912
    memset(parser, 0, sizeof(SCsvParser));
608,625✔
4913
  }
4914
}
608,625✔
4915

4916
static int32_t csvParserFillBuffer(SCsvParser* parser) {
25,382,600✔
4917
  if (!parser || parser->eof) {
25,382,600✔
4918
    return TSDB_CODE_SUCCESS;
4,278✔
4919
  }
4920

4921
  // Move remaining data to beginning of buffer
4922
  // Since this function is only called when bufferPos >= bufferLen,
4923
  // we can simplify by always resetting the buffer
4924
  parser->bufferLen = 0;
25,378,322✔
4925
  parser->bufferPos = 0;
25,378,322✔
4926

4927
  // Read more data
4928
  size_t spaceLeft = parser->bufferSize - parser->bufferLen;
25,378,322✔
4929
  if (spaceLeft > 0) {
25,378,322✔
4930
    int64_t bytesRead = taosReadFile(parser->pFile, parser->buffer + parser->bufferLen, spaceLeft);
25,378,322✔
4931
    if (bytesRead < 0) {
25,378,322✔
4932
      return TAOS_SYSTEM_ERROR(errno);
×
4933
    }
4934
    if (bytesRead == 0) {
25,378,322✔
4935
      parser->eof = true;
579,231✔
4936
    } else {
4937
      parser->bufferLen += bytesRead;
24,799,091✔
4938
    }
4939
  }
4940

4941
  return TSDB_CODE_SUCCESS;
25,378,322✔
4942
}
4943

4944
// Destroy saved CSV parser in SVnodeModifyOpStmt
4945
static void destroySavedCsvParser(SVnodeModifyOpStmt* pStmt) {
608,625✔
4946
  if (pStmt && pStmt->pCsvParser) {
608,625✔
4947
    csvParserDestroy(pStmt->pCsvParser);
608,625✔
4948
    taosMemoryFree(pStmt->pCsvParser);
608,625✔
4949
    pStmt->pCsvParser = NULL;
608,625✔
4950
  }
4951
}
608,625✔
4952

4953
static int32_t csvParserExpandLineBuffer(SCsvParser* parser, size_t requiredLen) {
2,147,483,647✔
4954
  if (!parser || requiredLen <= parser->lineBufferCapacity) {
2,147,483,647✔
4955
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
4956
  }
4957

4958
  size_t newCapacity = parser->lineBufferCapacity;
×
4959
  while (newCapacity < requiredLen) {
×
4960
    newCapacity *= 2;
×
4961
  }
4962

4963
  char* newLineBuffer = taosMemoryRealloc(parser->lineBuffer, newCapacity);
×
4964
  if (!newLineBuffer) {
×
4965
    return TSDB_CODE_OUT_OF_MEMORY;
×
4966
  }
4967

4968
  parser->lineBuffer = newLineBuffer;
×
4969
  parser->lineBufferCapacity = newCapacity;
×
4970
  return TSDB_CODE_SUCCESS;
×
4971
}
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