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

taosdata / TDengine / #5059

17 May 2026 01:15AM UTC coverage: 73.443% (+0.06%) from 73.387%
#5059

push

travis-ci

web-flow
feat (TDgpt): Dynamic Model Synchronization Enhancements (#35344)

* refactor: do some internal refactor.

* fix: fix multiprocess sync issue.

* feat: add dynamic anomaly detection and forecasting services

* fix: log error message for undeploying model in exception handling

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: handle undeploy when model exists only on disk

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/286aafa0-c3ce-4c27-b803-2707571e9dc1

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: guard dynamic registry concurrent access

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: tighten service list locking scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: restore prophet support and update tests per review feedback

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: improve test name and move copy inside lock scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* Potential fix for pull request finding

Co-au... (continued)

281870 of 383795 relevant lines covered (73.44%)

135516561.93 hits per line

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

82.38
/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) {
725,021,525✔
98
  SToken token;
99
  NEXT_TOKEN(*pSql, token);
725,021,525✔
100
  if (TK_INSERT != token.type && TK_IMPORT != token.type) {
725,095,467✔
101
    return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", token.z);
×
102
  }
103
  NEXT_TOKEN(*pSql, token);
725,095,467✔
104
  if (TK_INTO != token.type) {
725,098,978✔
105
    return buildSyntaxErrMsg(pMsg, "keyword INTO is expected", token.z);
×
106
  }
107
  return TSDB_CODE_SUCCESS;
725,098,978✔
108
}
109

110
static int32_t skipParentheses(SInsertParseContext* pCxt, const char** pSql) {
47,732,456✔
111
  SToken  token;
112
  int32_t expectRightParenthesis = 1;
47,732,456✔
113
  while (1) {
114
    NEXT_TOKEN(*pSql, token);
746,369,030✔
115
    if (TK_NK_LP == token.type) {
746,369,093✔
116
      ++expectRightParenthesis;
×
117
    } else if (TK_NK_RP == token.type && 0 == --expectRightParenthesis) {
746,369,093✔
118
      break;
47,732,519✔
119
    }
120
    if (0 == token.n) {
698,636,574✔
121
      return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL);
×
122
    }
123
  }
124
  return TSDB_CODE_SUCCESS;
47,732,519✔
125
}
126

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

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

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

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

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

177
  return code;
78,185✔
178
}
179

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

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

197
  return code;
8,476,218✔
198
}
199

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

204
  char tbFName[TSDB_TABLE_FNAME_LEN];
22,522,276✔
205
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
22,706,621✔
206
  if (TSDB_CODE_SUCCESS != code) {
22,708,145✔
207
    return code;
×
208
  }
209
  STableMeta** pMeta = taosHashGet(pStmt->pSubTableHashObj, tbFName, strlen(tbFName));
22,708,145✔
210
  if (NULL != pMeta) {
22,704,770✔
211
    *pDuplicate = true;
78,185✔
212
    pCxt->missCache = false;
78,185✔
213
    code = cloneTableMeta(*pMeta, &pStmt->pTableMeta);
78,185✔
214
    if (TSDB_CODE_SUCCESS != code) {
78,185✔
215
      return code;
×
216
    }
217
    return ignoreUsingClause(pCxt, pStmt);
78,185✔
218
  }
219

220
  return code;
22,626,585✔
221
}
222

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

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

229
// pStmt->pSql -> field1_name, ...)
230
static int32_t parseBoundColumns(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** pSql,
48,016,107✔
231
                                 EBoundColumnsType boundColsType, STableMeta* pTableMeta, SBoundColInfo* pBoundInfo) {
232
  SSchema* pSchema = NULL;
48,016,107✔
233
  if (boundColsType == BOUND_TAGS) {
48,016,107✔
234
    pSchema = getTableTagSchema(pTableMeta);
270,375✔
235
  } else if (boundColsType == BOUND_COLUMNS) {
47,745,732✔
236
    pSchema = getTableColumnSchema(pTableMeta);
47,503,999✔
237
  } else {
238
    pSchema = pTableMeta->schema;
241,733✔
239
    if (pBoundInfo->numOfCols != getTbnameSchemaIndex(pTableMeta) + 1) {
241,791✔
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);
48,016,165✔
245

246
  bool* pUseCols = taosMemoryCalloc(pBoundInfo->numOfCols, sizeof(bool));
48,016,165✔
247
  if (NULL == pUseCols) {
48,016,188✔
248
    return terrno;
×
249
  }
250

251
  pBoundInfo->numOfBound = 0;
48,016,188✔
252
  pBoundInfo->hasBoundCols = true;
48,016,213✔
253

254
  bool    hasPK = pTableMeta->tableInfo.numOfPKs;
48,016,188✔
255
  int16_t numOfBoundPKs = 0;
48,016,165✔
256
  int16_t lastColIdx = -1;  // last column found
48,016,165✔
257
  SArray* pPrivCols = pStmt->pPrivCols;
48,016,165✔
258
  int32_t lastPrivColIdx = 0, nPrivCols = taosArrayGetSize(pPrivCols);
48,016,188✔
259
  int32_t code = TSDB_CODE_SUCCESS;
48,016,276✔
260
  while (TSDB_CODE_SUCCESS == code) {
748,011,149✔
261
    SToken token;
731,693,516✔
262
    NEXT_TOKEN(*pSql, token);
748,006,719✔
263

264
    if (TK_NK_RP == token.type) {
748,006,514✔
265
      break;
48,009,598✔
266
    }
267

268
    char tmpTokenBuf[TSDB_COL_NAME_LEN + 2] = {0};  // used for deleting Escape character backstick(`)
699,996,916✔
269
    if (token.n >= TSDB_COL_NAME_LEN + 2) {
699,997,211✔
270
      taosMemoryFree(pUseCols);
88✔
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));
699,997,123✔
274
    token.z = tmpTokenBuf;
699,997,204✔
275
    token.n = strdequote(token.z);
699,997,204✔
276

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

284
    int16_t t = lastColIdx + 1;
699,756,054✔
285
    int16_t end = (boundColsType == BOUND_ALL_AND_TBNAME) ? (pBoundInfo->numOfCols - 1) : pBoundInfo->numOfCols;
699,756,054✔
286
    int16_t index = insFindCol(&token, t, end, pSchema);
699,756,054✔
287
    if (index < 0 && t > 0) {
699,756,112✔
288
      index = insFindCol(&token, 0, t, pSchema);
13,682,602✔
289
    }
290
    if (index < 0) {
699,756,112✔
291
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z);
4,372✔
292
    } else if (pUseCols[index]) {
699,751,740✔
293
      code = buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z);
×
294
    } else {
295
      lastColIdx = index;
699,751,798✔
296
      pUseCols[index] = true;
699,751,798✔
297
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = index;
699,751,823✔
298
      ++pBoundInfo->numOfBound;
699,751,823✔
299
      if (hasPK && (pSchema[index].flags & COL_IS_KEY)) ++numOfBoundPKs;
699,751,846✔
300

301
      if (pPrivCols) {  // check column-level privileges
699,751,846✔
302
        int32_t j = lastPrivColIdx;
9,936✔
303
        bool    found = false;
9,936✔
304
        for (; lastPrivColIdx < nPrivCols; ++lastPrivColIdx) {
17,566✔
305
          SColNameFlag* pColNameFlag = (SColNameFlag*)TARRAY_GET_ELEM(pPrivCols, lastPrivColIdx);
15,260✔
306
          if (pSchema[index].colId == pColNameFlag->colId) {
15,260✔
307
            found = true;
7,630✔
308
            break;
7,630✔
309
          }
310
        }
311
        if (!found) {
9,936✔
312
          for (int32_t k = 0; k < j; ++k) {
2,662✔
313
            SColNameFlag* pColNameFlag = (SColNameFlag*)TARRAY_GET_ELEM(pPrivCols, k);
356✔
314
            if (pSchema[index].colId == pColNameFlag->colId) {
356✔
315
              found = true;
×
316
              break;
×
317
            }
318
          }
319
        }
320
        if (!found) {
9,936✔
321
          taosMemoryFree(pUseCols);
2,306✔
322
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_COL_PERMISSION_DENIED, token.z);
2,306✔
323
        }
324
      }
325
    }
326
  }
327

328
  if (TSDB_CODE_SUCCESS == code && (BOUND_TAGS != boundColsType)) {
48,013,945✔
329
    if (!pUseCols[0]) {
47,739,198✔
330
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary timestamp column should not be null");
14,922✔
331
    }
332
    if (numOfBoundPKs != pTableMeta->tableInfo.numOfPKs) {
47,739,223✔
333
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary key column should not be none");
13,140✔
334
    }
335
  }
336
  if (TSDB_CODE_SUCCESS == code && (BOUND_ALL_AND_TBNAME == boundColsType) && !pUseCols[tbnameSchemaIndex]) {
48,013,882✔
337
    code = buildInvalidOperationMsg(&pCxt->msg, "tbname column should not be null");
780✔
338
  }
339
  taosMemoryFree(pUseCols);
48,013,882✔
340

341
  return code;
48,013,945✔
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;
46,898✔
351
    *ts = taosGetTimestampToday(timePrec, tz);
46,898✔
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,500✔
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,841✔
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) ||
11,465,517✔
367
          (pToken->type != TK_NK_STRING && pToken->type != TK_NK_HEX && pToken->type != TK_NK_BIN)) {
11,286,330✔
368
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
182,793✔
369
      }
370
      if (IS_NOW_STR(pToken->z, pToken->n)) {
11,282,724✔
371
        *isTs = true;
10,057✔
372
        *ts = taosGetTimestamp(timePrec);
20,114✔
373
      } else if (IS_TODAY_STR(pToken->z, pToken->n)) {
11,272,667✔
374
        *isTs = true;
10,057✔
375
        *ts = taosGetTimestampToday(timePrec, tz);
10,057✔
376
      } else if (TSDB_CODE_SUCCESS == toIntegerPure(pToken->z, pToken->n, 10, ts)) {
11,262,610✔
377
        *isTs = true;
11,239,238✔
378
      } else {
379
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
23,372✔
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);
51,530✔
398
  }
399

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

404
  for (int k = pToken->n; pToken->z[k] != '\0'; k++) {
2,147,483,647✔
405
    if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue;
2,147,483,647✔
406
    if (pToken->z[k] == '(') {  // for insert NOW()/TODAY()
2,147,483,647✔
407
      if (pToken->z[k + 1] == ')') {
4,421,399✔
408
        *end = pTokenEnd = &pToken->z[k + 2];
4,420,546✔
409
        ++k;
4,420,546✔
410
        continue;
4,420,546✔
411
      } else {
412
        char nc = pToken->z[k + 1];
853✔
413
        while (nc == ' ' || nc == '\t' || nc == '\n' || nc == '\r' || nc == '\f') {
1,706✔
414
          nc = pToken->z[(++k) + 1];
853✔
415
        }
416
        if (nc == ')') {
853✔
417
          *end = pTokenEnd = &pToken->z[k + 2];
853✔
418
          ++k;
853✔
419
          continue;
853✔
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++;
23,199,814✔
437
      continue;
23,199,814✔
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) {
97✔
462
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", valueToken.z);
223,976✔
463
      }
464
      int32_t len = trimString(valueToken.z, valueToken.n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
97✔
465
      valueToken.z = tmpTokenBuf;
97✔
466
      valueToken.n = len;
97✔
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,841✔
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,963✔
481
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
3,575✔
482
      }
483
      ts = tempTs;
388✔
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);
194✔
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,568,020✔
494
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
194✔
495
      }
496
      *time = ts - interval;
2,567,826✔
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,803✔
513
    }
514
  }
515

516
  *end = pTokenEnd;
2,484,198✔
517
  return TSDB_CODE_SUCCESS;
2,484,198✔
518
}
519

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

525
  //[ToDo] support to parse WKB as well as WKT
526
  if (pToken->type == TK_NK_STRING) {
158,735,807✔
527
    code = initCtxGeomFromText();
158,718,576✔
528
    if (code != TSDB_CODE_SUCCESS) {
158,718,366✔
529
      return code;
×
530
    }
531

532
    code = doGeomFromText(pToken->z, output, size);
158,718,366✔
533
    if (code != TSDB_CODE_SUCCESS) {
158,718,140✔
534
      return code;
1,464✔
535
    }
536
  }
537

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

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

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

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

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

573
  return TSDB_CODE_SUCCESS;
5,247✔
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;
53✔
587
    int32_t inputBytes = 0;
53✔
588
    int32_t outputBytes = 0;
29,733✔
589
    bool    final = false;
29,733✔
590

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

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

601
        return code;
583✔
602
      }
603

604
      input = tmpTokenBuf;
1,749✔
605

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

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

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

623
        taosMemoryFree(tmpTokenBuf);
583✔
624

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

633
        return code;
583✔
634
      }
635

636
      input = tmpTokenBuf;
1,749✔
637

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

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

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

649
        return terrno;
×
650
      }
651

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

659
        return code;
583✔
660
      }
661

662
      input = tmpTokenBuf;
1,749✔
663

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

675
        return terrno;
×
676
      }
677

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

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

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

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

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

709
          taosMemoryFree(tmpTokenBuf);
2,332✔
710

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

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

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

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

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

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

767
        return terrno;
×
768
      }
769

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

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

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

787
          taosMemoryFree(tmpTokenBuf);
1,166✔
788

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

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

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

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

818
        return terrno;
×
819
      }
820

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

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

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

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

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

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

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

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

856
          taosMemoryFree(tmpTokenBuf);
583✔
857

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

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

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

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

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

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

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

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

932
        return terrno;
×
933
      }
934

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

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

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

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

949
      taosMemoryFree(pKeyPaddingBuf);
1,749✔
950
    } else if (pToken->type == TK_AES_DECRYPT) {
5,247✔
951
      NEXT_VALID_TOKEN(*ppSql, *pToken);
1,166✔
952
      if (TK_NK_LP != pToken->type) {
1,166✔
953
        taosMemoryFree(tmpTokenBuf);
×
954

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

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

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

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

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

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

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

982
          taosMemoryFree(tmpTokenBuf);
583✔
983

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

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

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

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

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

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

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

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

1108
          taosMemoryFree(tmpTokenBuf);
583✔
1109

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

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

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

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

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

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

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

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

1161
        return terrno;
×
1162
      }
1163

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

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

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

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

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

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

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

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

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

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

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

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

1211
          taosMemoryFree(tmpTokenBuf);
583✔
1212

1213
          return TSDB_CODE_SUCCESS;
583✔
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);
18,656✔
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,742✔
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;
51,180✔
1309
  }
1310

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

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

1322
    if (size + VARSTR_HEADER_SIZE > bytes) {
4,047,233✔
1323
      taosMemoryFree(data);
1,200✔
1324
      return TSDB_CODE_PAR_VALUE_TOO_LONG;
1,200✔
1325
    }
1326
    *pData = data;
4,046,033✔
1327
    *nData = size;
4,046,033✔
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) {
28,027,438✔
1341
  if (pToken->type != TK_NK_STRING) {
28,027,438✔
1342
    return TSDB_CODE_PAR_INVALID_VARBINARY;
10,236✔
1343
  }
1344
  int32_t  code = 0;
28,017,202✔
1345
  int32_t  lino = 0;
28,017,202✔
1346
  uint32_t size = 0;
28,017,202✔
1347
  *pData = NULL;
28,017,202✔
1348

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

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

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

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

1381
static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val,
195,047,855✔
1382
                             SMsgBuf* pMsgBuf, timezone_t tz, void* charsetCxt) {
1383
  int64_t  iv;
193,204,987✔
1384
  uint64_t uv;
193,209,932✔
1385
  char*    endptr = NULL;
195,054,538✔
1386
  int32_t  code = TSDB_CODE_SUCCESS;
195,054,538✔
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;
195,054,538✔
1399
  val->type = pSchema->type;
195,061,803✔
1400

1401
  switch (pSchema->type) {
195,077,849✔
1402
    case TSDB_DATA_TYPE_BOOL: {
5,371,688✔
1403
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
5,371,688✔
1404
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
3,489,688✔
1405
          *(int8_t*)(&val->i64) = TRUE_VALUE;
2,379,171✔
1406
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
1,110,517✔
1407
          *(int8_t*)(&val->i64) = FALSE_VALUE;
1,073,957✔
1408
        } else if (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv)) {
36,560✔
1409
          *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
28,030✔
1410
        } else {
1411
          return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
8,530✔
1412
        }
1413
      } else if (pToken->type == TK_NK_INTEGER) {
1,882,000✔
1414
        *(int8_t*)(&val->i64) = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
1,855,557✔
1415
      } else if (pToken->type == TK_NK_FLOAT) {
26,443✔
1416
        *(int8_t*)(&val->i64) = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
11,942✔
1417
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
24,737✔
1418
                 (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv))) {
10,236✔
1419
        *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
10,236✔
1420
      } else {
1421
        return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
4,265✔
1422
      }
1423
      break;
5,358,892✔
1424
    }
1425

1426
    case TSDB_DATA_TYPE_TINYINT: {
4,337,647✔
1427
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
4,337,647✔
1428
      if (TSDB_CODE_SUCCESS != code) {
4,337,583✔
1429
        return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z);
11,089✔
1430
      } else if (!IS_VALID_TINYINT(iv)) {
4,326,494✔
1431
        return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z);
9,881✔
1432
      }
1433

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

1438
    case TSDB_DATA_TYPE_UTINYINT: {
1,118,137✔
1439
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,118,137✔
1440
      if (TSDB_CODE_SUCCESS != code) {
1,117,946✔
1441
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z);
1,592✔
1442
      } else if (uv > UINT8_MAX) {
1,116,354✔
1443
        return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z);
1,592✔
1444
      }
1445
      *(uint8_t*)(&val->i64) = uv;
1,114,762✔
1446
      break;
1,114,887✔
1447
    }
1448

1449
    case TSDB_DATA_TYPE_SMALLINT: {
4,463,826✔
1450
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
4,463,826✔
1451
      if (TSDB_CODE_SUCCESS != code) {
4,463,827✔
1452
        return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z);
11,089✔
1453
      } else if (!IS_VALID_SMALLINT(iv)) {
4,452,738✔
1454
        return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z);
10,009✔
1455
      }
1456
      *(int16_t*)(&val->i64) = iv;
4,442,729✔
1457
      break;
4,442,729✔
1458
    }
1459

1460
    case TSDB_DATA_TYPE_USMALLINT: {
1,142,609✔
1461
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,142,609✔
1462
      if (TSDB_CODE_SUCCESS != code) {
1,142,545✔
1463
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z);
1,592✔
1464
      } else if (uv > UINT16_MAX) {
1,140,953✔
1465
        return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z);
1,592✔
1466
      }
1467
      *(uint16_t*)(&val->i64) = uv;
1,139,361✔
1468
      break;
1,139,425✔
1469
    }
1470

1471
    case TSDB_DATA_TYPE_INT: {
63,089,394✔
1472
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
63,089,394✔
1473
      if (TSDB_CODE_SUCCESS != code) {
63,101,976✔
1474
        return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z);
14,079✔
1475
      } else if (!IS_VALID_INT(iv)) {
63,087,897✔
1476
        return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z);
4,331✔
1477
      }
1478
      *(int32_t*)(&val->i64) = iv;
63,084,647✔
1479
      break;
63,092,558✔
1480
    }
1481

1482
    case TSDB_DATA_TYPE_UINT: {
1,210,584✔
1483
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,210,584✔
1484
      if (TSDB_CODE_SUCCESS != code) {
1,210,394✔
1485
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z);
18,652✔
1486
      } else if (uv > UINT32_MAX) {
1,191,742✔
1487
        return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z);
2,445✔
1488
      }
1489
      *(uint32_t*)(&val->i64) = uv;
1,189,297✔
1490
      break;
1,189,487✔
1491
    }
1492

1493
    case TSDB_DATA_TYPE_BIGINT: {
11,977,040✔
1494
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
11,977,040✔
1495
      if (TSDB_CODE_SUCCESS != code) {
11,977,040✔
1496
        return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z);
22,633✔
1497
      }
1498
      val->i64 = iv;
11,954,407✔
1499
      break;
11,954,407✔
1500
    }
1501

1502
    case TSDB_DATA_TYPE_UBIGINT: {
1,045,061✔
1503
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,045,061✔
1504
      if (TSDB_CODE_SUCCESS != code) {
1,045,061✔
1505
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z);
6,001✔
1506
      }
1507
      *(uint64_t*)(&val->i64) = uv;
1,039,060✔
1508
      break;
1,038,996✔
1509
    }
1510

1511
    case TSDB_DATA_TYPE_FLOAT: {
3,664,282✔
1512
      double dv;
3,590,052✔
1513
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
3,664,282✔
1514
      if (TSDB_CODE_SUCCESS != code) {
3,664,280✔
1515
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
12,711✔
1516
      }
1517
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
3,651,569✔
1518
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
11,712✔
1519
      }
1520
      *(float*)(&val->i64) = dv;
3,639,857✔
1521
      break;
3,639,857✔
1522
    }
1523

1524
    case TSDB_DATA_TYPE_DOUBLE: {
14,286,041✔
1525
      double dv;
14,198,954✔
1526
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
14,286,041✔
1527
      if (TSDB_CODE_SUCCESS != code) {
14,286,041✔
1528
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
22,178✔
1529
      }
1530
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && ERRNO == ERANGE) || isinf(dv) || isnan(dv)) {
14,263,863✔
1531
        return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
×
1532
      }
1533

1534
      *(double*)(&val->i64) = dv;
14,263,863✔
1535
      break;
14,263,863✔
1536
    }
1537

1538
    case TSDB_DATA_TYPE_BINARY: {
64,976,673✔
1539
      // Too long values will raise the invalid sql error message
1540
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
64,976,673✔
1541
        return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
150,574✔
1542
      }
1543
      val->pData = taosStrdup(pToken->z);
64,824,078✔
1544
      if (!val->pData) {
64,825,678✔
1545
        return terrno;
×
1546
      }
1547
      val->nData = pToken->n;
64,818,776✔
1548
      break;
64,800,179✔
1549
    }
1550
    case TSDB_DATA_TYPE_VARBINARY: {
543,922✔
1551
      code = parseVarbinary(pToken, &val->pData, &val->nData, pSchema->bytes);
543,922✔
1552
      if (code != TSDB_CODE_SUCCESS) {
543,922✔
1553
        return generateSyntaxErrMsg(pMsgBuf, code, pSchema->name);
40,944✔
1554
      }
1555
      break;
502,978✔
1556
    }
1557
    case TSDB_DATA_TYPE_GEOMETRY: {
415,841✔
1558
      unsigned char* output = NULL;
415,841✔
1559
      size_t         size = 0;
415,841✔
1560

1561
      code = parseGeometry(pToken, &output, &size);
415,841✔
1562
      if (code != TSDB_CODE_SUCCESS) {
415,839✔
1563
        code = buildSyntaxErrMsg(pMsgBuf, getGeosErrMsg(code), pToken->z);
17,060✔
1564
      } else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
398,779✔
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);
398,781✔
1569
        if (NULL == val->pData) {
398,781✔
1570
          code = terrno;
×
1571
        } else {
1572
          memcpy(val->pData, output, size);
398,780✔
1573
          val->nData = size;
398,780✔
1574
        }
1575
      }
1576

1577
      geosFreeBuffer(output);
415,841✔
1578
      break;
415,839✔
1579
    }
1580

1581
    case TSDB_DATA_TYPE_NCHAR: {
14,898,512✔
1582
      int32_t output = 0;
14,898,512✔
1583
      int64_t realLen = pToken->n << 2;
14,898,384✔
1584
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
14,898,512✔
1585
      void* p = taosMemoryMalloc(realLen);
14,898,448✔
1586
      if (p == NULL) {
14,898,321✔
1587
        return terrno;
200✔
1588
      }
1589
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)(p), realLen, &output, charsetCxt)) {
14,898,321✔
1590
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
143,732✔
1591
          taosMemoryFree(p);
143,532✔
1592
          return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
143,532✔
1593
        }
1594
        char buf[512] = {0};
200✔
1595
        snprintf(buf, tListLen(buf), " taosMbsToUcs4 error:%s %d %d", strerror(terrno), ERRNO, EILSEQ);
200✔
1596
        taosMemoryFree(p);
200✔
1597
        return buildSyntaxErrMsg(pMsgBuf, buf, pToken->z);
200✔
1598
      }
1599
      val->pData = p;
14,754,590✔
1600
      val->nData = output;
14,754,716✔
1601
      break;
14,754,716✔
1602
    }
1603
    case TSDB_DATA_TYPE_TIMESTAMP: {
2,502,978✔
1604
      if (parseTime(end, pToken, timePrec, &iv, pMsgBuf, tz) != TSDB_CODE_SUCCESS) {
2,502,978✔
1605
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z);
18,250✔
1606
      }
1607

1608
      val->i64 = iv;
2,484,728✔
1609
      break;
2,484,728✔
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;
194,509,442✔
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) {
22,579,456✔
1624
  int32_t code = insInitBoundColsInfo(getNumOfTags(pStmt->pTableMeta), &pCxt->tags);
22,579,456✔
1625
  if (TSDB_CODE_SUCCESS != code) {
22,585,480✔
1626
    return code;
×
1627
  }
1628

1629
  SToken  token;
1630
  int32_t index = 0;
22,585,480✔
1631
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
22,583,239✔
1632
  if (TK_NK_LP != token.type) {
22,590,370✔
1633
    return TSDB_CODE_SUCCESS;
22,319,995✔
1634
  }
1635

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

1640
int32_t parseTagValue(SMsgBuf* pMsgBuf, const char** pSql, uint8_t precision, SSchema* pTagSchema, SToken* pToken,
196,371,695✔
1641
                      SArray* pTagName, SArray* pTagVals, STag** pTag, timezone_t tz, void* charsetCxt) {
1642
  bool isNull = isNullValue(pTagSchema->type, pToken);
196,371,695✔
1643
  if (!isNull && pTagName) {
196,372,765✔
1644
    if (NULL == taosArrayPush(pTagName, pTagSchema->name)) {
372,087,928✔
1645
      return terrno;
×
1646
    }
1647
  }
1648

1649
  if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
196,373,791✔
1650
    if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
782,533✔
1651
      return buildSyntaxErrMsg(pMsgBuf, "json string too long than 4095", pToken->z);
553✔
1652
    }
1653

1654
    if (isNull) {
778,376✔
1655
      return tTagNew(pTagVals, 1, true, pTag);
32,842✔
1656
    } else {
1657
      return parseJsontoTagData(pToken->z, pTagVals, pTag, pMsgBuf, charsetCxt);
745,534✔
1658
    }
1659
  }
1660

1661
  if (isNull) return 0;
195,590,892✔
1662

1663
  STagVal val = {0};
195,084,437✔
1664
  int32_t code = parseTagToken(pSql, pToken, pTagSchema, precision, &val, pMsgBuf, tz, charsetCxt);
195,087,998✔
1665
  if (TSDB_CODE_SUCCESS == code) {
195,041,966✔
1666
    if (NULL == taosArrayPush(pTagVals, &val)) {
194,534,581✔
1667
      code = terrno;
×
1668
    }
1669
  }
1670

1671
  if (TSDB_CODE_SUCCESS != code && IS_VAR_DATA_TYPE(val.type)) {
195,087,446✔
1672
    taosMemoryFree(val.pData);
352,310✔
1673
  }
1674

1675
  return code;
195,073,929✔
1676
}
1677

1678
static int32_t buildCreateTbReq(SVnodeModifyOpStmt* pStmt, STag* pTag, SArray* pTagName) {
13,801,091✔
1679
  if (pStmt->pCreateTblReq) {
13,801,091✔
1680
    tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
×
1681
    taosMemoryFreeClear(pStmt->pCreateTblReq);
×
1682
  }
1683
  pStmt->pCreateTblReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
13,811,597✔
1684
  if (NULL == pStmt->pCreateTblReq) {
13,788,599✔
1685
    return terrno;
×
1686
  }
1687
  return insBuildCreateTbReq(pStmt->pCreateTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid,
13,799,858✔
1688
                             pStmt->usingTableName.tname, pTagName, pStmt->pTableMeta->tableInfo.numOfTags,
13,788,227✔
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 &&
761,617✔
1700
       pToken->type != TK_FROM_BASE64 && pToken->type != TK_TO_BASE64 &&
753,085✔
1701
       pToken->type != TK_MD5 && pToken->type != TK_SHA && pToken->type != TK_SHA1 && pToken->type != TK_SHA2 &&
748,421✔
1702
       pToken->type != TK_AES_ENCRYPT && pToken->type != TK_AES_DECRYPT &&
732,097✔
1703
       pToken->type != TK_SM4_ENCRYPT && pToken->type != TK_SM4_DECRYPT) ||
727,433✔
1704
      (pToken->n == 0) || (pToken->type == TK_NK_RP)) {
2,147,483,647✔
1705
    return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z);
1,455✔
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) {
×
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);
×
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) {
6,335✔
1739
  SValueNode* pValue = NULL;
6,335✔
1740
  int32_t     code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pValue);
6,335✔
1741
  if (NULL == pValue) {
6,335✔
1742
    return code;
×
1743
  }
1744

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

1749
  switch (pVal->type) {
6,335✔
1750
    case TSDB_DATA_TYPE_BOOL:
×
1751
      pValue->datum.b = *(int8_t*)(&pVal->i64);
×
1752
      *(bool*)&pValue->typeData = pValue->datum.b;
×
1753
      break;
×
1754
    case TSDB_DATA_TYPE_TINYINT:
×
1755
      pValue->datum.i = *(int8_t*)(&pVal->i64);
×
1756
      *(int8_t*)&pValue->typeData = pValue->datum.i;
×
1757
      break;
×
1758
    case TSDB_DATA_TYPE_SMALLINT:
×
1759
      pValue->datum.i = *(int16_t*)(&pVal->i64);
×
1760
      *(int16_t*)&pValue->typeData = pValue->datum.i;
×
1761
      break;
×
1762
    case TSDB_DATA_TYPE_INT:
5,801✔
1763
      pValue->datum.i = *(int32_t*)(&pVal->i64);
5,801✔
1764
      *(int32_t*)&pValue->typeData = pValue->datum.i;
5,801✔
1765
      break;
5,801✔
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:
534✔
1779
    case TSDB_DATA_TYPE_VARBINARY:
1780
    case TSDB_DATA_TYPE_NCHAR:
1781
      pValue->datum.p = taosMemoryCalloc(1, pVal->nData + VARSTR_HEADER_SIZE);
534✔
1782
      if (NULL == pValue->datum.p) {
534✔
1783
        return terrno;
×
1784
      }
1785
      varDataSetLen(pValue->datum.p, pVal->nData);
534✔
1786
      memcpy(varDataVal(pValue->datum.p), pVal->pData, pVal->nData);
534✔
1787
      break;
534✔
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;
6,335✔
1816
}
1817

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

1830
static EDealRes rewriteTagCond(SNode** pNode, void* pContext) {
19,005✔
1831
  if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
19,005✔
1832
    SRewriteTagCondCxt* pCxt = pContext;
6,335✔
1833
    pCxt->code = rewriteTagCondColumn(pCxt->pTagVals, pCxt->pTagName, pNode);
6,335✔
1834
    return (TSDB_CODE_SUCCESS == pCxt->code ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
6,335✔
1835
  }
1836
  return DEAL_RES_CONTINUE;
12,670✔
1837
}
1838

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

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

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

1862
// pSql -> tag1_value, ...)
1863
static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool autoCreate) {
22,577,794✔
1864
  int32_t  code = TSDB_CODE_SUCCESS;
22,577,794✔
1865
  SSchema* pSchema = getTableTagSchema(pStmt->pTableMeta);
22,577,794✔
1866
  SArray*  pTagVals = NULL;
22,581,523✔
1867
  SArray*  pTagName = NULL;
22,581,523✔
1868
  uint8_t  precision = pStmt->pTableMeta->tableInfo.precision;
22,581,523✔
1869
  SToken   token;
22,396,264✔
1870
  bool     isJson = false;
22,577,422✔
1871
  STag*    pTag = NULL;
22,577,422✔
1872
  uint8_t* pTagsIndex;
1873
  int32_t  numOfTags = 0;
22,582,657✔
1874

1875
  if (pCxt->pComCxt->stmtBindVersion == 2) {  // only support stmt2
22,582,657✔
1876
    pTagsIndex = taosMemoryCalloc(pCxt->tags.numOfBound, sizeof(uint8_t));
7,630✔
1877
  }
1878

1879
  if (!(pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal))) ||
45,154,781✔
1880
      !(pTagName = taosArrayInit(pCxt->tags.numOfBound, TSDB_COL_NAME_LEN))) {
22,579,627✔
1881
    code = terrno;
×
1882
    goto _exit;
×
1883
  }
1884

1885
  for (int i = 0; TSDB_CODE_SUCCESS == code && i < pCxt->tags.numOfBound; ++i) {
55,727,601✔
1886
    NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
33,157,355✔
1887

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

1894
      continue;
31,093✔
1895
    }
1896

1897
    SSchema* pTagSchema = &pSchema[pCxt->tags.pColIndex[i]];
33,122,506✔
1898
    isJson = pTagSchema->type == TSDB_DATA_TYPE_JSON;
33,130,399✔
1899
    code = checkAndTrimValue(&token, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
33,123,649✔
1900
    if (TSDB_CODE_SUCCESS == code && TK_NK_VARIABLE == token.type) {
33,125,908✔
1901
      code = buildSyntaxErrMsg(&pCxt->msg, "not expected tags values ", token.z);
×
1902
    }
1903
    if (TSDB_CODE_SUCCESS == code) {
33,125,182✔
1904
      code = parseTagValue(&pCxt->msg, &pStmt->pSql, precision, pTagSchema, &token, pTagName, pTagVals, &pTag,
65,866,616✔
1905
                           pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
65,859,512✔
1906
    }
1907
    if (pCxt->pComCxt->stmtBindVersion == 2) {
33,121,753✔
1908
      pTagsIndex[numOfTags++] = pCxt->tags.pColIndex[i];
6,214✔
1909
    }
1910
  }
1911

1912
  if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pTagCond) {
22,577,023✔
1913
    code = checkSubtablePrivilege(pTagVals, pTagName, &pStmt->pTagCond);
426✔
1914
  }
1915

1916
  if (TSDB_CODE_SUCCESS == code && pCxt->pComCxt->stmtBindVersion == 2) {
22,582,648✔
1917
    if (numOfTags > 0) {
7,529✔
1918
      if (pTagVals->size == pCxt->tags.numOfBound) {
3,410✔
1919
        pCxt->stmtTbNameFlag |= IS_FIXED_TAG;
3,107✔
1920
      } else {
1921
        pCxt->stmtTbNameFlag &= ~IS_FIXED_TAG;
303✔
1922
        pCxt->tags.parseredTags = taosMemoryMalloc(sizeof(STagsInfo));
303✔
1923
        if (pCxt->tags.parseredTags == NULL) {
303✔
1924
          code = terrno;
×
1925
          goto _exit;
×
1926
        }
1927
        pCxt->tags.parseredTags->numOfTags = numOfTags;
303✔
1928
        pCxt->tags.parseredTags->pTagIndex = pTagsIndex;
303✔
1929
        pCxt->tags.parseredTags->pTagVals = pTagVals;
303✔
1930
        pCxt->tags.parseredTags->STagNames = pTagName;
303✔
1931
      }
1932
    } else {
1933
      goto _exit;
4,119✔
1934
    }
1935
  }
1936

1937
  if (TSDB_CODE_SUCCESS == code && !isJson) {
22,573,312✔
1938
    code = tTagNew(pTagVals, 1, false, &pTag);
22,043,955✔
1939
  }
1940

1941
  if (TSDB_CODE_SUCCESS == code && !autoCreate) {
22,568,341✔
1942
    code = buildCreateTbReq(pStmt, pTag, pTagName);
13,801,382✔
1943
    pTag = NULL;
13,801,799✔
1944
  }
1945

1946
_exit:
22,552,734✔
1947
  if (pCxt->tags.parseredTags == NULL) {
22,576,297✔
1948
    for (int32_t i = 0; i < taosArrayGetSize(pTagVals); ++i) {
55,430,701✔
1949
      STagVal* p = (STagVal*)TARRAY_GET_ELEM(pTagVals, i);
32,874,702✔
1950
      if (IS_VAR_DATA_TYPE(p->type)) {
32,876,244✔
1951
        taosMemoryFreeClear(p->pData);
12,357,329✔
1952
      }
1953
    }
1954
    taosArrayDestroy(pTagVals);
22,566,142✔
1955
    taosArrayDestroy(pTagName);
22,580,857✔
1956
    if (pCxt->pComCxt->stmtBindVersion == 2) {
22,574,134✔
1957
      taosMemoryFreeClear(pTagsIndex);
7,327✔
1958
    }
1959
  }
1960

1961
  tTagFree(pTag);
22,586,077✔
1962
  return code;
22,575,562✔
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) {
22,581,343✔
1968
  SToken token;
22,396,346✔
1969
  NEXT_TOKEN(pStmt->pSql, token);
22,585,462✔
1970
  if (TK_TAGS != token.type) {
22,586,215✔
1971
    return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
3,177✔
1972
  }
1973

1974
  NEXT_TOKEN(pStmt->pSql, token);
22,583,038✔
1975
  if (TK_NK_LP != token.type) {
22,575,907✔
1976
    return buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
×
1977
  }
1978

1979
  int32_t code = parseTagsClauseImpl(pCxt, pStmt, autoCreate);
22,575,907✔
1980
  if (TSDB_CODE_SUCCESS == code) {
22,582,702✔
1981
    NEXT_VALID_TOKEN(pStmt->pSql, token);
32,746,735✔
1982
    if (TK_NK_COMMA == token.type) {
22,275,359✔
1983
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
769✔
1984
    } else if (TK_NK_RP != token.type) {
22,274,590✔
1985
      code = buildSyntaxErrMsg(&pCxt->msg, ") is expected", token.z);
19,177✔
1986
    }
1987
  }
1988
  return code;
22,572,922✔
1989
}
1990

1991
static int32_t storeChildTableMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
14,098,094✔
1992
  pStmt->pTableMeta->suid = pStmt->pTableMeta->uid;
14,098,094✔
1993
  pStmt->pTableMeta->uid = pStmt->totalTbNum;
14,101,097✔
1994
  pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;
14,098,421✔
1995

1996
  STableMeta* pBackup = NULL;
14,096,570✔
1997
  if (TSDB_CODE_SUCCESS != cloneTableMeta(pStmt->pTableMeta, &pBackup)) {
14,102,585✔
1998
    return TSDB_CODE_OUT_OF_MEMORY;
×
1999
  }
2000

2001
  char    tbFName[TSDB_TABLE_FNAME_LEN];
14,085,234✔
2002
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
14,106,704✔
2003
  if (TSDB_CODE_SUCCESS != code) {
14,098,430✔
2004
    taosMemoryFree(pBackup);
×
2005
    return code;
×
2006
  }
2007
  code = taosHashPut(pStmt->pSubTableHashObj, tbFName, strlen(tbFName), &pBackup, POINTER_BYTES);
14,098,430✔
2008
  if (TSDB_CODE_SUCCESS != code) {
14,107,838✔
2009
    taosMemoryFree(pBackup);
×
2010
  }
2011
  return code;
14,103,347✔
2012
}
2013

2014
static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
13,796,265✔
2015
  do {
9,876✔
2016
    int32_t index = 0;
13,796,265✔
2017
    SToken  token;
2018
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
13,802,679✔
2019
    if (TK_TTL == token.type) {
13,794,351✔
2020
      pStmt->pSql += index;
9,876✔
2021
      NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
9,876✔
2022
      if (TK_NK_INTEGER != token.type) {
9,876✔
2023
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
×
2024
      }
2025
      pStmt->pCreateTblReq->ttl = taosStr2Int32(token.z, NULL, 10);
9,876✔
2026
      if (pStmt->pCreateTblReq->ttl < 0) {
9,876✔
2027
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
764✔
2028
      }
2029
    } else if (TK_COMMENT == token.type) {
13,784,475✔
2030
      pStmt->pSql += index;
764✔
2031
      NEXT_TOKEN(pStmt->pSql, token);
764✔
2032
      if (TK_NK_STRING != token.type) {
764✔
2033
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option comment", token.z);
×
2034
      }
2035
      if (token.n >= TSDB_TB_COMMENT_LEN) {
764✔
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);
764✔
2039
      pStmt->pCreateTblReq->comment = taosStrndup(pCxt->tmpTokenBuf, len);
764✔
2040
      if (NULL == pStmt->pCreateTblReq->comment) {
764✔
2041
        return terrno;
×
2042
      }
2043
      pStmt->pCreateTblReq->commentLen = len;
764✔
2044
    } else {
2045
      break;
13,783,711✔
2046
    }
2047
  } while (1);
2048
  return TSDB_CODE_SUCCESS;
13,788,946✔
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) {
852,996,092✔
2058
  if (!pStmt->usingTableProcessing || pCxt->usingDuplicateTable) {
852,996,092✔
2059
    return TSDB_CODE_SUCCESS;
838,915,553✔
2060
  }
2061

2062
  int32_t code = parseBoundTagsClause(pCxt, pStmt);
14,153,493✔
2063
  if (TSDB_CODE_SUCCESS == code) {
14,099,582✔
2064
    code = parseTagsClause(pCxt, pStmt, false);
14,098,094✔
2065
  }
2066
  if (TSDB_CODE_SUCCESS == code) {
14,092,442✔
2067
    code = parseTableOptions(pCxt, pStmt);
13,785,636✔
2068
  }
2069

2070
  return code;
14,097,677✔
2071
}
2072

2073
static void setUserAuthInfo(SParseContext* pCxt, SName* pTbName, SUserAuthInfo* pInfo) {
830,803,034✔
2074
  snprintf(pInfo->user, sizeof(pInfo->user), "%s", pCxt->pUser);
830,803,034✔
2075
  memcpy(&pInfo->tbName, pTbName, sizeof(SName));
830,842,360✔
2076
  pInfo->userId = pCxt->userId;
830,882,591✔
2077
  pInfo->privType = PRIV_TBL_INSERT;
830,877,223✔
2078
  pInfo->objType = PRIV_OBJ_TBL;
830,880,169✔
2079
}
830,800,379✔
2080

2081
static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool isAudit, bool* pMissCache, bool* pWithInsertCond, SNode** pTagCond,
830,754,673✔
2082
                         SArray** pPrivCols) {
2083
  int32_t       code = TSDB_CODE_SUCCESS;
830,754,673✔
2084
  SUserAuthInfo authInfo = {0};
830,754,673✔
2085
  setUserAuthInfo(pCxt, pTbName, &authInfo);
830,771,034✔
2086
  if (isAudit) {
830,846,695✔
2087
    authInfo.privType = PRIV_AUDIT_TBL_INSERT;
×
2088
    authInfo.objType = PRIV_OBJ_CLUSTER;
×
2089
  }
2090
  SUserAuthRes authRes = {0};
830,846,695✔
2091
  SUserAuthRsp authRsp = {.exists = 1};
830,862,444✔
2092
  if (pCxt->async) {
830,853,596✔
2093
    code = catalogChkAuthFromCache(pCxt->pCatalog, &authInfo, &authRes, &authRsp);
830,699,104✔
2094
  } else {
2095
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
325,901✔
2096
                             .requestId = pCxt->requestId,
174,120✔
2097
                             .requestObjRefId = pCxt->requestRid,
174,046✔
2098
                             .mgmtEps = pCxt->mgmtEpSet};
2099
    code = catalogChkAuth(pCxt->pCatalog, &conn, &authInfo, &authRes);
174,046✔
2100
  }
2101
  if (TSDB_CODE_SUCCESS == code) {
830,749,857✔
2102
    if (0 == authRsp.exists) {
830,749,871✔
2103
      *pMissCache = true;
37,079✔
2104
    } else if (!authRes.pass[AUTH_RES_BASIC]) {
830,712,792✔
2105
      code = TSDB_CODE_PAR_PERMISSION_DENIED;
5,386✔
2106
    } else {
2107
      if (pTagCond && authRes.pCond[AUTH_RES_BASIC]) {
830,707,406✔
2108
        *pTagCond = authRes.pCond[AUTH_RES_BASIC];
4,631✔
2109
      }
2110
      if (pPrivCols && authRes.pCols) {
830,707,406✔
2111
        *pPrivCols = authRes.pCols;
4,968✔
2112
      }
2113
      *pMissCache = false;
830,707,406✔
2114
    }
2115
    if (pWithInsertCond) {
830,837,767✔
2116
      *pWithInsertCond = (authRsp.withInsertCond == 1);
830,800,801✔
2117
    }
2118
  }
2119
  return code;
830,857,975✔
2120
}
2121

2122
static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, STableMeta** pTableMeta, bool* pMissCache,
37,732,950✔
2123
                            bool bUsingTable) {
2124
  SParseContext* pComCxt = pCxt->pComCxt;
37,732,950✔
2125
  int32_t        code = TSDB_CODE_SUCCESS;
37,732,498✔
2126
  if (pComCxt->async) {
37,732,498✔
2127
    if (bUsingTable) {
30,018,803✔
2128
      code = catalogGetCachedSTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
15,016,393✔
2129
    } else {
2130
      code = catalogGetCachedTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
15,002,410✔
2131
    }
2132
  } else {
2133
    SRequestConnInfo conn = {.pTrans = pComCxt->pTransporter,
15,393,663✔
2134
                             .requestId = pComCxt->requestId,
7,716,406✔
2135
                             .requestObjRefId = pComCxt->requestRid,
7,713,776✔
2136
                             .mgmtEps = pComCxt->mgmtEpSet};
2137
    if (bUsingTable) {
7,710,191✔
2138
      code = catalogGetSTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
7,534,671✔
2139
    } else {
2140
      code = catalogGetTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
175,520✔
2141
    }
2142
  }
2143
  if (TSDB_CODE_SUCCESS == code) {
37,731,432✔
2144
    if (NULL == *pTableMeta) {
37,730,927✔
2145
      *pMissCache = true;
6,597,335✔
2146
    } else if (bUsingTable && TSDB_SUPER_TABLE != (*pTableMeta)->tableType) {
31,139,519✔
2147
      code = buildInvalidOperationMsg(&pCxt->msg, "create table only from super table is allowed");
×
2148
    } else if (((*pTableMeta)->virtualStb) || TSDB_VIRTUAL_CHILD_TABLE == (*pTableMeta)->tableType ||
31,143,593✔
2149
               TSDB_VIRTUAL_NORMAL_TABLE == (*pTableMeta)->tableType) {
31,129,593✔
2150
      code = TSDB_CODE_VTABLE_NOT_SUPPORT_STMT;
2,080✔
2151
    }
2152
  }
2153
  return code;
37,727,787✔
2154
}
2155

2156
static int32_t getTargetTableVgroup(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool isStb, bool* pMissCache) {
16,187,568✔
2157
  int32_t     code = TSDB_CODE_SUCCESS;
16,187,568✔
2158
  SVgroupInfo vg;
15,998,627✔
2159
  bool        exists = true;
16,190,599✔
2160
  if (pCxt->async) {
16,192,087✔
2161
    code = catalogGetCachedTableHashVgroup(pCxt->pCatalog, &pStmt->targetTableName, &vg, &exists);
8,483,927✔
2162
  } else {
2163
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
15,371,056✔
2164
                             .requestId = pCxt->requestId,
7,704,719✔
2165
                             .requestObjRefId = pCxt->requestRid,
7,690,790✔
2166
                             .mgmtEps = pCxt->mgmtEpSet};
2167
    code = catalogGetTableHashVgroup(pCxt->pCatalog, &conn, &pStmt->targetTableName, &vg);
7,694,628✔
2168
  }
2169
  if (TSDB_CODE_SUCCESS == code) {
16,190,861✔
2170
    if (exists) {
16,190,861✔
2171
      if (isStb) {
16,183,861✔
2172
        pStmt->pTableMeta->vgId = vg.vgId;
16,018,158✔
2173
      }
2174
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
16,184,923✔
2175
    }
2176
    *pMissCache = !exists;
16,195,039✔
2177
  }
2178
  return code;
16,190,149✔
2179
}
2180

2181
static int32_t getTargetTableMetaAndVgroup(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) {
830,721,823✔
2182
  SParseContext* pComCxt = pCxt->pComCxt;
830,721,823✔
2183
  int32_t        code = TSDB_CODE_SUCCESS;
830,766,536✔
2184
  if (pComCxt->async) {
830,766,536✔
2185
    {
2186
      SVgroupInfo vg;
826,687,812✔
2187
      code = catalogGetCachedTableVgMeta(pComCxt->pCatalog, &pStmt->targetTableName, &vg, &pStmt->pTableMeta);
830,601,682✔
2188
      if (TSDB_CODE_SUCCESS == code) {
830,538,821✔
2189
        if (NULL != pStmt->pTableMeta) {
830,599,263✔
2190
          if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE) {
828,887,609✔
2191
            pStmt->stbSyntax = true;
275,968✔
2192
          } else {
2193
            code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
828,567,367✔
2194
          }
2195
        }
2196
        *pMissCache = (NULL == pStmt->pTableMeta);
830,794,827✔
2197
      }
2198
    }
2199
  } else {
2200
    bool bUsingTable = false;
173,769✔
2201
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pStmt->pTableMeta, pMissCache, bUsingTable);
173,769✔
2202
    if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
174,142✔
2203
      if (TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
172,927✔
2204
        pStmt->stbSyntax = true;
6,856✔
2205
      }
2206
      if (!pStmt->stbSyntax) {
172,765✔
2207
        code = getTargetTableVgroup(pCxt->pComCxt, pStmt, false, &pCxt->missCache);
165,955✔
2208
      }
2209
    }
2210
  }
2211
  return code;
830,786,490✔
2212
}
2213

2214
static int32_t collectUseTable(const SName* pName, SHashObj* pTable) {
11,150,001✔
2215
  char    fullName[TSDB_TABLE_FNAME_LEN];
11,106,995✔
2216
  int32_t code = tNameExtractFullName(pName, fullName);
11,152,242✔
2217
  if (TSDB_CODE_SUCCESS != code) {
11,157,567✔
2218
    return code;
×
2219
  }
2220
  return taosHashPut(pTable, fullName, strlen(fullName), pName, sizeof(SName));
11,157,567✔
2221
}
2222

2223
static int32_t collectUseDatabase(const SName* pName, SHashObj* pDbs) {
7,948,727✔
2224
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
7,948,727✔
2225
  (void)tNameGetFullDbName(pName, dbFName);
7,951,658✔
2226
  return taosHashPut(pDbs, dbFName, strlen(dbFName), dbFName, sizeof(dbFName));
7,957,800✔
2227
}
2228

2229
static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
830,911,930✔
2230
  if (pCxt->forceUpdate) {
830,911,930✔
2231
    pCxt->missCache = true;
73,088✔
2232
    return TSDB_CODE_SUCCESS;
73,088✔
2233
  }
2234
  SNode*  pTagCond = NULL;
830,876,862✔
2235
  SArray* pPrivCols = NULL;
830,830,975✔
2236
  bool    withInsertCond = false;
830,897,182✔
2237
  int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, false, &pCxt->missCache, &withInsertCond, &pTagCond,
830,917,774✔
2238
                           &pPrivCols);
2239
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
830,799,312✔
2240
    code = getTargetTableMetaAndVgroup(pCxt, pStmt, &pCxt->missCache);
830,821,267✔
2241
  }
2242
#ifdef TD_ENTERPRISE
2243
  // MAC NWD+NRU: for INSERT, user.minSecLevel <= table.secLvl <= user.maxSecLevel
2244
  // Only enforced when MAC is explicitly activated cluster-wide.
2245
  // Logic mirrors macCheckBySecLvl() in parAuthenticator.c (inline here because SInsertParseContext
2246
  // does not carry an SAuthCxt).
2247
  if (pCxt->pComCxt->macMode && TSDB_CODE_SUCCESS == code && !pCxt->missCache && pStmt->pTableMeta != NULL) {
830,812,702✔
2248
    int8_t secLvl = pStmt->pTableMeta->secLvl;
6,912✔
2249
    if (secLvl >= 0) {
6,912✔
2250
      if (pCxt->pComCxt->minSecLevel > secLvl) {
6,912✔
2251
        code = TSDB_CODE_MAC_NO_WRITE_DOWN;  // NWD violation
1,152✔
2252
      } else if (pCxt->pComCxt->maxSecLevel < secLvl) {
5,760✔
2253
        code = TSDB_CODE_MAC_INSUFFICIENT_LEVEL;  // NRU violation
1,728✔
2254
      }
2255
    }
2256
  }
2257
#endif
2258

2259
  if (TSDB_CODE_SUCCESS == code) {
830,878,842✔
2260
    if (pPrivCols) pStmt->pPrivCols = pPrivCols;
830,825,229✔
2261
#ifdef TD_ENTERPRISE
2262
#if 0
2263
    if (pStmt->pTableMeta && pStmt->pTableMeta->isAudit) {
2264
      // recheck for audit table
2265
      code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, true, &pCxt->missCache, NULL, NULL, NULL);
2266
      if (TSDB_CODE_SUCCESS != code) {
2267
        nodesDestroyNode(pTagCond);
2268
        return code;
2269
      }
2270
    }
2271
#endif
2272
    if (!pCxt->missCache) {
830,825,229✔
2273
      if (TSDB_SUPER_TABLE != pStmt->pTableMeta->tableType) {
829,098,139✔
2274
        pCxt->needTableTagVal = (NULL != pTagCond);
828,849,048✔
2275
        pCxt->missCache = (NULL != pTagCond);
828,860,168✔
2276
      } else {
2277
        pStmt->pTagCond = pTagCond;
282,833✔
2278
        pTagCond = NULL;
282,833✔
2279
      }
2280
    } else if (withInsertCond && !pCxt->pComCxt->isSuperUser) {
1,733,202✔
2281
      // If miss cache, always request tag value and reserved for permission check later if pTagCond exists. This may
2282
      // lead to redundant request but ensure correctness, and this only happens when cache is invalid or first time
2283
      // insert.
2284
      pCxt->needTableTagVal = true;
2,130✔
2285
    }
2286
#else
2287
    pStmt->pTagCond = NULL;
2288
#endif
2289
  }
2290
  if (pTagCond) nodesDestroyNode(pTagCond);
830,963,437✔
2291

2292
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
830,963,437✔
2293
    code = collectUseDatabase(&pStmt->targetTableName, pStmt->pDbFNameHashObj);
172,705✔
2294
    if (TSDB_CODE_SUCCESS == code) {
172,838✔
2295
      code = collectUseTable(&pStmt->targetTableName, pStmt->pTableNameHashObj);
172,838✔
2296
    }
2297
  }
2298
  return code;
830,758,958✔
2299
}
2300

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

2305
static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* ctbCacheHit) {
22,622,965✔
2306
  int32_t     code = TSDB_CODE_SUCCESS;
22,622,965✔
2307
  STableMeta* pStableMeta = NULL;
22,622,965✔
2308
  STableMeta* pCtableMeta = NULL;
22,625,977✔
2309
  if (pCxt->forceUpdate) {
22,628,236✔
2310
    pCxt->missCache = true;
1,400✔
2311
    return TSDB_CODE_SUCCESS;
1,400✔
2312
  }
2313
  char stableFName[TSDB_TABLE_FNAME_LEN];
22,438,717✔
2314
  code = tNameExtractFullName(&pStmt->usingTableName, stableFName);
22,622,699✔
2315
  if (TSDB_CODE_SUCCESS != code) {
22,630,202✔
2316
    return code;
×
2317
  }
2318

2319
  char ctableFName[TSDB_TABLE_FNAME_LEN];
22,445,104✔
2320
  code = tNameExtractFullName(&pStmt->targetTableName, ctableFName);
22,630,574✔
2321
  if (TSDB_CODE_SUCCESS != code) {
22,627,943✔
2322
    return code;
×
2323
  }
2324

2325
  if (strcmp(stableFName, ctableFName) == 0) {
22,627,943✔
2326
    return TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
769✔
2327
  }
2328
  if (!pCxt->missCache) {
22,627,174✔
2329
    char tbFName[TSDB_TABLE_FNAME_LEN];
22,443,564✔
2330
    code = tNameExtractFullName(&pStmt->usingTableName, tbFName);
22,628,671✔
2331
    if (TSDB_CODE_SUCCESS != code) {
22,625,668✔
2332
      return code;
×
2333
    }
2334
    STableMeta** ppStableMeta = taosHashGet(pStmt->pSuperTableHashObj, tbFName, strlen(tbFName));
22,625,668✔
2335
    if (NULL != ppStableMeta) {
22,623,037✔
2336
      pStableMeta = *ppStableMeta;
69,017✔
2337
    }
2338
    if (NULL == pStableMeta) {
22,623,037✔
2339
      bool bUsingTable = true;
22,556,344✔
2340
      code = getTableMeta(pCxt, &pStmt->usingTableName, &pStableMeta, &pCxt->missCache, bUsingTable);
22,556,344✔
2341
      if (TSDB_CODE_SUCCESS == code) {
22,549,192✔
2342
        code = taosHashPut(pStmt->pSuperTableHashObj, tbFName, strlen(tbFName), &pStableMeta, POINTER_BYTES);
22,547,686✔
2343
      } else {
2344
        taosMemoryFreeClear(pStableMeta);
1,506✔
2345
      }
2346
    }
2347
  }
2348
  if (pCxt->pComCxt->stmtBindVersion > 0) {
22,620,823✔
2349
    goto _no_ctb_cache;
7,540,929✔
2350
  }
2351

2352
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
15,085,120✔
2353
    bool bUsingTable = false;
15,004,000✔
2354
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pCtableMeta, &pCxt->missCache, bUsingTable);
15,004,000✔
2355
  }
2356

2357
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
15,085,120✔
2358
    code = (pStableMeta->suid == pCtableMeta->suid) ? TSDB_CODE_SUCCESS : TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
8,487,055✔
2359
    *ctbCacheHit = true;
8,487,055✔
2360
  }
2361
_no_ctb_cache:
22,452,746✔
2362
  if (TSDB_CODE_SUCCESS == code) {
22,626,058✔
2363
    if (*ctbCacheHit) {
22,622,642✔
2364
      code = cloneTableMeta(pCtableMeta, &pStmt->pTableMeta);
8,485,517✔
2365
    } else {
2366
      code = cloneTableMeta(pStableMeta, &pStmt->pTableMeta);
14,138,250✔
2367
    }
2368
  }
2369
  taosMemoryFree(pCtableMeta);
22,629,061✔
2370
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
22,624,180✔
2371
    code = getTargetTableVgroup(pCxt->pComCxt, pStmt, true, &pCxt->missCache);
16,025,670✔
2372
  }
2373
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
22,624,906✔
2374
    code = collectUseDatabase(&pStmt->usingTableName, pStmt->pDbFNameHashObj);
7,537,216✔
2375
    if (TSDB_CODE_SUCCESS == code) {
7,545,499✔
2376
      code = collectUseTable(&pStmt->usingTableName, pStmt->pTableNameHashObj);
7,545,118✔
2377
    }
2378
  }
2379
  return code;
22,628,290✔
2380
}
2381

2382
static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
22,625,841✔
2383
  SToken token;
22,440,743✔
2384
  NEXT_TOKEN(pStmt->pSql, token);
22,628,109✔
2385
  bool    ctbCacheHit = false;
22,629,960✔
2386
  int32_t code = preParseUsingTableName(pCxt, pStmt, &token);
22,626,948✔
2387
  if (TSDB_CODE_SUCCESS == code) {
22,626,957✔
2388
    code = getUsingTableSchema(pCxt, pStmt, &ctbCacheHit);
22,629,343✔
2389
    if (TSDB_CODE_SUCCESS == code && ctbCacheHit && !pCxt->missCache) {
22,630,087✔
2390
      pStmt->usingTableProcessing = false;
8,485,517✔
2391
      return ignoreUsingClauseAndCheckTagValues(pCxt, pStmt);
8,485,517✔
2392
    }
2393
  }
2394
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
14,142,184✔
2395
    code = storeChildTableMeta(pCxt, pStmt);
7,535,281✔
2396
  }
2397
  return code;
14,142,202✔
2398
}
2399

2400
// input pStmt->pSql:
2401
//   1(care). [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
2402
//   2. VALUES ... | FILE ...
2403
// output pStmt->pSql:
2404
//   1. [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
2405
//   2. VALUES ... | FILE ...
2406
static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
853,611,845✔
2407
  SToken  token;
2408
  int32_t index = 0;
853,611,845✔
2409
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
853,661,041✔
2410
  if (TK_USING != token.type) {
853,675,878✔
2411
    return getTargetTableSchema(pCxt, pStmt);
830,968,123✔
2412
  }
2413
  pStmt->usingTableProcessing = true;
22,707,755✔
2414
  pCxt->stmtTbNameFlag |= USING_CLAUSE;
22,709,261✔
2415
  // pStmt->pSql -> stb_name [(tag1_name, ...)
2416
  pStmt->pSql += index;
22,705,859✔
2417
  int32_t code = parseDuplicateUsingClause(pCxt, pStmt, &pCxt->usingDuplicateTable);
22,708,517✔
2418
  if (TSDB_CODE_SUCCESS == code && !pCxt->usingDuplicateTable) {
22,705,142✔
2419
    return parseUsingTableNameImpl(pCxt, pStmt);
22,628,454✔
2420
  }
2421
  return code;
78,185✔
2422
}
2423

2424
static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
853,621,968✔
2425
  int32_t code = insCreateSName(&pStmt->targetTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
853,621,968✔
2426
  if (TSDB_CODE_SUCCESS == code) {
853,642,374✔
2427
    if (IS_SYS_DBNAME(pStmt->targetTableName.dbname)) {
853,600,623✔
2428
      return TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED;
50,944✔
2429
    }
2430
  }
2431

2432
  return code;
853,664,260✔
2433
}
2434

2435
// input pStmt->pSql:
2436
//   1(care). [(field1_name, ...)] ...
2437
//   2. [ USING ... ] ...
2438
//   3. VALUES ... | FILE ...
2439
// output pStmt->pSql:
2440
//   1. [ USING ... ] ...
2441
//   2. VALUES ... | FILE ...
2442
static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
853,586,674✔
2443
  SToken  token;
2444
  int32_t index = 0;
853,586,674✔
2445
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
853,625,963✔
2446
  if (TK_NK_LP != token.type) {
853,660,699✔
2447
    return TSDB_CODE_SUCCESS;
806,008,924✔
2448
  }
2449

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

2456
static int32_t getTableDataCxt(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt** pTableCxt) {
852,691,645✔
2457
  if (pCxt->pComCxt->async) {
852,691,645✔
2458
    return insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid),
1,686,170,697✔
2459
                              pStmt->pTableMeta, &pStmt->pCreateTblReq, pTableCxt, false, false);
845,075,575✔
2460
  }
2461

2462
  char    tbFName[TSDB_TABLE_FNAME_LEN];
7,668,602✔
2463
  int32_t code = 0;
7,694,286✔
2464
  if ((pCxt->stmtTbNameFlag & NO_DATA_USING_CLAUSE) == USING_CLAUSE) {
7,694,286✔
2465
    tstrncpy(pStmt->targetTableName.tname, pStmt->usingTableName.tname, sizeof(pStmt->targetTableName.tname));
2,742✔
2466
    tstrncpy(pStmt->targetTableName.dbname, pStmt->usingTableName.dbname, sizeof(pStmt->targetTableName.dbname));
2,742✔
2467
    pStmt->targetTableName.type = TSDB_SUPER_TABLE;
2,742✔
2468
    pStmt->pTableMeta->tableType = TSDB_SUPER_TABLE;
2,742✔
2469
  }
2470

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

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

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

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

2517
  return TSDB_CODE_SUCCESS;
×
2518
}
2519
#endif
2520

2521
static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) {
852,682,266✔
2522
  SToken  token;
2523
  int32_t index = 0;
852,682,266✔
2524
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
852,762,770✔
2525
  if (TK_NK_LP == token.type) {
852,775,986✔
2526
    pStmt->pSql += index;
101,850✔
2527
    if (NULL != pStmt->pBoundCols) {
101,850✔
2528
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
1,287✔
2529
    }
2530
    // pStmt->pSql -> field1_name, ...)
2531
    return parseBoundColumns(pCxt, pStmt, &pStmt->pSql, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo);
100,563✔
2532
  }
2533

2534
  if (NULL != pStmt->pBoundCols) {
852,674,136✔
2535
    return parseBoundColumns(pCxt, pStmt, &pStmt->pBoundCols, BOUND_COLUMNS, pStmt->pTableMeta,
47,403,489✔
2536
                             &pTableCxt->boundColsInfo);
2537
  } else if (pTableCxt->boundColsInfo.hasBoundCols) {
805,274,938✔
2538
    insResetBoundColsInfo(&pTableCxt->boundColsInfo);
3,300✔
2539
  } else if (NULL != pStmt->pPrivCols) {
805,189,938✔
2540
#ifdef TD_ENTERPRISE
2541
    PAR_ERR_RET(parseCheckNoBoundColPriv(pCxt, pStmt));
178✔
2542
#endif
2543
  }
2544

2545

2546
  return TSDB_CODE_SUCCESS;
805,182,642✔
2547
}
2548

2549
int32_t initTableColSubmitData(STableDataCxt* pTableCxt) {
2,063,354,339✔
2550
  if (0 == (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT)) {
2,063,354,339✔
2551
    return TSDB_CODE_SUCCESS;
2,055,673,558✔
2552
  }
2553

2554
  for (int32_t i = 0; i < pTableCxt->boundColsInfo.numOfBound; ++i) {
32,016,260✔
2555
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
24,263,133✔
2556
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
24,264,890✔
2557
    if (NULL == pCol) {
24,269,431✔
2558
      return terrno;
×
2559
    }
2560
    tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags);
24,269,431✔
2561
  }
2562

2563
  return TSDB_CODE_SUCCESS;
7,756,957✔
2564
}
2565

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

2578
  return TSDB_CODE_SUCCESS;
4,150✔
2579
}
2580

2581
// input pStmt->pSql:
2582
//   1. [(tag1_name, ...)] ...
2583
//   2. VALUES ... | FILE ...
2584
// output pStmt->pSql: VALUES ... | FILE ...
2585
static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
852,997,846✔
2586
                                       STableDataCxt** pTableCxt) {
2587
  int32_t code = parseUsingClauseBottom(pCxt, pStmt);
852,997,846✔
2588
  if (TSDB_CODE_SUCCESS == code) {
853,002,097✔
2589
    code = getTableDataCxt(pCxt, pStmt, pTableCxt);
852,774,313✔
2590
  }
2591
  if (TSDB_CODE_SUCCESS == code) {
852,993,175✔
2592
    code = parseBoundColumnsClause(pCxt, pStmt, *pTableCxt);
852,725,166✔
2593
  }
2594
  if (TSDB_CODE_SUCCESS == code) {
852,957,153✔
2595
    code = initTableColSubmitData(*pTableCxt);
852,626,200✔
2596
  }
2597
  return code;
853,006,563✔
2598
}
2599

2600
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
2601
// output pStmt->pSql:
2602
//   1. [(tag1_name, ...)] ...
2603
//   2. VALUES ... | FILE ...
2604
static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
853,627,868✔
2605
  int32_t code = preParseTargetTableName(pCxt, pStmt, pTbName);
853,627,868✔
2606
  if (TSDB_CODE_SUCCESS == code) {
853,690,628✔
2607
    // option: [(field1_name, ...)]
2608
    code = preParseBoundColumnsClause(pCxt, pStmt);
853,643,408✔
2609
  }
2610
  if (TSDB_CODE_SUCCESS == code) {
853,695,207✔
2611
    // option: [USING stb_name]
2612
    code = parseUsingTableName(pCxt, pStmt);
853,655,463✔
2613
  }
2614
  return code;
853,592,245✔
2615
}
2616

2617
static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
2,147,483,647✔
2618
                                   const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) {
2619
  switch (pSchema->type) {
2,147,483,647✔
2620
    case TSDB_DATA_TYPE_BOOL: {
2,147,483,647✔
2621
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
2,147,483,647✔
2622
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
2,147,483,647✔
2623
          VALUE_SET_TRIVIAL_DATUM(&pVal->value, TRUE_VALUE);
2,147,483,647✔
2624
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
2,139,826,077✔
2625
          VALUE_SET_TRIVIAL_DATUM(&pVal->value, FALSE_VALUE);
2,138,201,678✔
2626
        } else if (TSDB_CODE_SUCCESS ==
23,031✔
2627
                   toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,160✔
2628
          int8_t v = (*(double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value) == 0 ? FALSE_VALUE : TRUE_VALUE);
17,913✔
2629
          valueSetDatum(&pVal->value, TSDB_DATA_TYPE_BOOL, &v, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes);
17,913✔
2630
        } else {
2631
          return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
5,118✔
2632
        }
2633
      } else if (pToken->type == TK_NK_INTEGER) {
2,147,483,647✔
2634
        int8_t v = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
2,147,483,647✔
2635
        VALUE_SET_TRIVIAL_DATUM(&pVal->value, v);
2,147,483,647✔
2636
      } else if (pToken->type == TK_NK_FLOAT) {
1,930,357✔
2637
        int8_t v = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
1,870,530✔
2638
        VALUE_SET_TRIVIAL_DATUM(&pVal->value, v);
1,870,530✔
2639
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
66,651✔
2640
                 (TSDB_CODE_SUCCESS ==
2641
                  toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value)))) {
58,974✔
2642
        int8_t v = *(double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value) == 0 ? FALSE_VALUE : TRUE_VALUE;
6,824✔
2643
        valueSetDatum(&pVal->value, TSDB_DATA_TYPE_BOOL, &v, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes);
6,824✔
2644
      } else {
2645
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
853✔
2646
      }
2647
      break;
2,147,483,647✔
2648
    }
2649
    case TSDB_DATA_TYPE_TINYINT: {
2,147,483,647✔
2650
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2651
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2652
        return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z);
10,734✔
2653
      } else if (!IS_VALID_TINYINT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2654
        return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z);
751✔
2655
      }
2656
      break;
2,147,483,647✔
2657
    }
2658
    case TSDB_DATA_TYPE_UTINYINT: {
2,147,483,647✔
2659
      int32_t code =
2660
          toUIntegerEx(pToken->z, pToken->n, pToken->type, (uint64_t*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2661
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2662
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z);
8,498✔
2663
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT8_MAX) {
2,147,483,647✔
2664
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z);
2,115✔
2665
      }
2666
      break;
2,147,483,647✔
2667
    }
2668
    case TSDB_DATA_TYPE_SMALLINT: {
2,147,483,647✔
2669
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2670
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2671
        return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z);
10,734✔
2672
      } else if (!IS_VALID_SMALLINT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2673
        return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z);
26,888,864✔
2674
      }
2675
      break;
2,147,483,647✔
2676
    }
2677
    case TSDB_DATA_TYPE_USMALLINT: {
2,147,483,647✔
2678
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2679
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2680
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z);
8,498✔
2681
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT16_MAX) {
2,147,483,647✔
2682
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z);
2,115✔
2683
      }
2684
      break;
2,147,483,647✔
2685
    }
2686
    case TSDB_DATA_TYPE_INT: {
2,147,483,647✔
2687
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2688
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2689
        return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z);
11,503✔
2690
      } else if (!IS_VALID_INT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
2,147,483,647✔
2691
        return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z);
801✔
2692
      }
2693
      break;
2,147,483,647✔
2694
    }
2695
    case TSDB_DATA_TYPE_UINT: {
2,147,483,647✔
2696
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2697
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2698
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z);
17,028✔
2699
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT32_MAX) {
2,147,483,647✔
2700
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z);
3,821✔
2701
      }
2702
      break;
2,147,483,647✔
2703
    }
2704
    case TSDB_DATA_TYPE_BIGINT: {
2,147,483,647✔
2705
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2706
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2707
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z);
86,648✔
2708
      }
2709
      break;
2,147,483,647✔
2710
    }
2711
    case TSDB_DATA_TYPE_UBIGINT: {
2,147,483,647✔
2712
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
2,147,483,647✔
2713
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2714
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z);
230,799✔
2715
      }
2716
      break;
2,147,483,647✔
2717
    }
2718
    case TSDB_DATA_TYPE_FLOAT: {
2,147,483,647✔
2719
      double  dv;
2,147,483,647✔
2720
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
2,147,483,647✔
2721
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2722
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
9,392✔
2723
      }
2724
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
2,147,483,647✔
2725
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
880✔
2726
      }
2727
      float f = dv;
2,147,483,647✔
2728
      valueSetDatum(&pVal->value, TSDB_DATA_TYPE_FLOAT, &f, sizeof(f));
2,147,483,647✔
2729
      break;
2,147,483,647✔
2730
    }
2731
    case TSDB_DATA_TYPE_DOUBLE: {
2,147,483,647✔
2732
      double  dv;
2,147,483,647✔
2733
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
2,147,483,647✔
2734
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
2735
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
102,708✔
2736
      }
2737
      if (isinf(dv) || isnan(dv)) {
2,147,483,647✔
2738
        return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
×
2739
      }
2740
      VALUE_SET_TRIVIAL_DATUM(&pVal->value, (*(int64_t*)&dv));
2,147,483,647✔
2741
      break;
2,147,483,647✔
2742
    }
2743
    case TSDB_DATA_TYPE_BINARY: {
2,147,483,647✔
2744
      return parseBinary(pCxt, pSql, pToken, pVal, pSchema);
2,147,483,647✔
2745
    }
2746
    case TSDB_DATA_TYPE_VARBINARY: {
2,147,483,647✔
2747
      int32_t code = parseVarbinary(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes);
2,147,483,647✔
2748
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2749
        return generateSyntaxErrMsg(&pCxt->msg, code, pSchema->name);
11,436✔
2750
      }
2751
      break;
2,147,483,647✔
2752
    }
2753
    case TSDB_DATA_TYPE_NCHAR: {
2,147,483,647✔
2754
      // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
2755
      int32_t len = 0;
2,147,483,647✔
2756
      int64_t realLen = pToken->n << 2;
2,147,483,647✔
2757
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
2,147,483,647✔
2758
      char* pUcs4 = taosMemoryMalloc(realLen);
2,147,483,647✔
2759
      if (NULL == pUcs4) {
2,147,483,647✔
2760
        return terrno;
200✔
2761
      }
2762
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)pUcs4, realLen, &len, pCxt->pComCxt->charsetCxt)) {
2,147,483,647✔
2763
        taosMemoryFree(pUcs4);
26,670✔
2764
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
2,884✔
2765
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
2,684✔
2766
        }
2767
        char buf[512] = {0};
200✔
2768
        snprintf(buf, tListLen(buf), "%s", strerror(terrno));
200✔
2769
        return buildSyntaxErrMsg(&pCxt->msg, buf, pToken->z);
200✔
2770
      }
2771
      pVal->value.pData = pUcs4;
2,147,483,647✔
2772
      pVal->value.nData = len;
2,147,483,647✔
2773
      break;
2,147,483,647✔
2774
    }
2775
    case TSDB_DATA_TYPE_JSON: {
×
2776
      if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
×
2777
        return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z);
×
2778
      }
2779
      pVal->value.pData = taosMemoryMalloc(pToken->n);
×
2780
      if (NULL == pVal->value.pData) {
×
2781
        return terrno;
×
2782
      }
2783
      memcpy(pVal->value.pData, pToken->z, pToken->n);
×
2784
      pVal->value.nData = pToken->n;
×
2785
      break;
×
2786
    }
2787
    case TSDB_DATA_TYPE_GEOMETRY: {
158,320,010✔
2788
      int32_t        code = TSDB_CODE_FAILED;
158,320,010✔
2789
      unsigned char* output = NULL;
158,320,010✔
2790
      size_t         size = 0;
158,320,010✔
2791

2792
      code = parseGeometry(pToken, &output, &size);
158,320,262✔
2793
      if (code != TSDB_CODE_SUCCESS) {
158,319,933✔
2794
        code = buildSyntaxErrMsg(&pCxt->msg, getGeosErrMsg(code), pToken->z);
1,952✔
2795
      }
2796
      // Too long values will raise the invalid sql error message
2797
      else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
158,317,981✔
2798
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
2799
      } else {
2800
        pVal->value.pData = taosMemoryMalloc(size);
158,318,464✔
2801
        if (NULL == pVal->value.pData) {
158,318,044✔
2802
          code = terrno;
×
2803
        } else {
2804
          memcpy(pVal->value.pData, output, size);
158,318,275✔
2805
          pVal->value.nData = size;
158,318,149✔
2806
        }
2807
      }
2808

2809
      geosFreeBuffer(output);
158,320,395✔
2810
      if (code != TSDB_CODE_SUCCESS) {
158,320,157✔
2811
        return code;
1,952✔
2812
      }
2813

2814
      break;
158,318,205✔
2815
    }
2816
    case TSDB_DATA_TYPE_TIMESTAMP: {
2,147,483,647✔
2817
      if (parseTime(pSql, pToken, timePrec, &VALUE_GET_TRIVIAL_DATUM(&pVal->value), &pCxt->msg,
2,147,483,647✔
2818
                    pCxt->pComCxt->timezone) != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2819
        return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z);
26,623✔
2820
      }
2821
      break;
2,147,483,647✔
2822
    }
2823
    case TSDB_DATA_TYPE_BLOB:
1,085✔
2824
    case TSDB_DATA_TYPE_MEDIUMBLOB: {
2825
      int32_t code = parseBlob(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes);
1,085✔
2826
      if (code != TSDB_CODE_SUCCESS) {
28,027,438✔
2827
        return generateSyntaxErrMsg(&pCxt->msg, code, pSchema->name);
10,236✔
2828
      }
2829
    } break;
28,017,202✔
2830
    case TSDB_DATA_TYPE_DECIMAL: {
174,308,811✔
2831
      if (!pExtSchema) {
174,308,811✔
2832
        qError("Decimal type without ext schema info, cannot parse decimal values");
×
2833
        return TSDB_CODE_DECIMAL_PARSE_ERROR;
×
2834
      }
2835
      uint8_t precision = 0, scale = 0;
174,308,811✔
2836
      decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale);
174,449,775✔
2837
      Decimal128 dec = {0};
174,452,560✔
2838
      int32_t    code = decimal128FromStr(pToken->z, pToken->n, precision, scale, &dec);
174,348,630✔
2839
      if (TSDB_CODE_SUCCESS != code) {
174,489,971✔
2840
        return code;
×
2841
      }
2842

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

2846
      code = decimal128ToDataVal(&dec, &pVal->value);
174,489,971✔
2847
      if (TSDB_CODE_SUCCESS != code) {
174,461,700✔
2848
        return code;
×
2849
      }
2850
      break;
174,461,700✔
2851
    }
2852
    case TSDB_DATA_TYPE_DECIMAL64: {
364,778,551✔
2853
      if (!pExtSchema) {
364,778,551✔
2854
        qError("Decimal type without ext schema info, cannot parse decimal values");
×
2855
        return TSDB_CODE_DECIMAL_PARSE_ERROR;
×
2856
      }
2857
      uint8_t precision = 0, scale = 0;
364,778,551✔
2858
      decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale);
364,889,574✔
2859
      Decimal64 dec = {0};
364,912,233✔
2860
      int32_t   code = decimal64FromStr(pToken->z, pToken->n, precision, scale, &dec);
364,938,336✔
2861
      if (TSDB_CODE_SUCCESS != code) {
364,891,409✔
2862
        return code;
×
2863
      }
2864
      code = decimal64ToDataVal(&dec, &pVal->value);
364,891,409✔
2865
      if (TSDB_CODE_SUCCESS != code) {
364,911,086✔
2866
        return code;
×
2867
      }
2868
      break;
364,911,086✔
2869
    }
2870
    default:
×
2871

2872
      return TSDB_CODE_FAILED;
×
2873
  }
2874

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

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

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

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

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

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

2911
typedef struct SStbRowsDataContext {
2912
  SName stbName;
2913

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

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

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

2935
int32_t parseTbnameToken(SMsgBuf* pMsgBuf, char* tname, SToken* pToken, bool* pFoundCtbName) {
1,210,033,137✔
2936
  *pFoundCtbName = false;
1,210,033,137✔
2937

2938
  if (isNullValue(TSDB_DATA_TYPE_BINARY, pToken)) {
1,210,033,137✔
2939
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be null value");
×
2940
  }
2941

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

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

2968
  if (code == TSDB_CODE_SUCCESS && ctbFirst) {
1,209,835,544✔
2969
    for (int32_t i = 0; code == TSDB_CODE_SUCCESS && i < numOfTagTokens; ++i) {
3,332,912✔
2970
      SToken*  pTagToken = (SToken*)(tagTokens + i);
135,464✔
2971
      SSchema* pTagSchema = tagSchemas[i];
135,464✔
2972
      code = checkAndTrimValue(pTagToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
135,464✔
2973
      if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pTagToken->type) {
135,464✔
2974
        code = buildInvalidOperationMsg(&pCxt->msg, "not expected tag");
×
2975
      }
2976

2977
      if (code == TSDB_CODE_SUCCESS) {
135,464✔
2978
        code = parseTagValue(&pCxt->msg, NULL, precision, pTagSchema, pTagToken, pStbRowsCxt->aTagNames,
270,524✔
2979
                             pStbRowsCxt->aTagVals, &pStbRowsCxt->pTag, pCxt->pComCxt->timezone,
135,464✔
2980
                             pCxt->pComCxt->charsetCxt);
135,464✔
2981
      }
2982
    }
2983
    if (code == TSDB_CODE_SUCCESS && !pStbRowsCxt->isJsonTag) {
3,197,448✔
2984
      code = tTagNew(pStbRowsCxt->aTagVals, 1, false, &pStbRowsCxt->pTag);
3,197,448✔
2985
    }
2986
  }
2987
  if (code == TSDB_CODE_SUCCESS && pStbRowsCxt->pTagCond) {
1,209,835,544✔
2988
    code = checkSubtablePrivilege(pStbRowsCxt->aTagVals, pStbRowsCxt->aTagNames, &pStbRowsCxt->pTagCond);
×
2989
  }
2990
  return code;
1,209,835,544✔
2991
}
2992

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

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

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

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

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

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

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

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

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

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

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

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

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

3207
          if (code == TSDB_CODE_SUCCESS) {
1,209,840,885✔
3208
            code = parseTbnameToken(&pCxt->msg, pStbRowsCxt->ctbName.tname, pToken, bFoundTbName);
1,209,837,303✔
3209
          }
3210
        }
3211
      }
3212
    }
3213

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

3222
  return code;
1,209,847,238✔
3223
}
3224

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

3232
  bool        bFoundTbName = false;
1,209,847,339✔
3233
  const char* pOrigSql = *ppSql;
1,209,847,339✔
3234

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

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

3243
  if (code != TSDB_CODE_SUCCESS) {
1,209,847,339✔
3244
    return code;
10,372✔
3245
  }
3246

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

3251
  bool ctbFirst = true;
1,209,836,967✔
3252
  char ctbFName[TSDB_TABLE_FNAME_LEN];
1,209,830,990✔
3253
  if (code == TSDB_CODE_SUCCESS) {
1,209,836,967✔
3254
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
1,209,836,967✔
3255
  }
3256
  if (TSDB_CODE_SUCCESS == code) {
1,209,836,967✔
3257
    STableMeta** pCtbMeta = taosHashGet(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName));
1,209,835,544✔
3258
    ctbFirst = (pCtbMeta == NULL);
1,209,835,544✔
3259
    if (!ctbFirst) {
1,209,835,544✔
3260
      pStbRowsCxt->pCtbMeta->uid = (*pCtbMeta)->uid;
1,206,638,096✔
3261
      pStbRowsCxt->pCtbMeta->vgId = (*pCtbMeta)->vgId;
1,206,638,096✔
3262
    }
3263
    *pCtbFirst = ctbFirst;
1,209,835,544✔
3264
  }
3265

3266
  if (code == TSDB_CODE_SUCCESS) {
1,209,836,967✔
3267
    code = processCtbTagsAfterCtbName(pCxt, pStmt, pStbRowsCxt, ctbFirst, tagTokens, tagSchemas, numOfTagTokens);
1,209,835,544✔
3268
  }
3269

3270
  if (code == TSDB_CODE_SUCCESS) {
1,209,836,967✔
3271
    *pGotRow = true;
1,209,835,544✔
3272
  }
3273
  return code;
1,209,836,967✔
3274
}
3275

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

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

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

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

3322
static void clearStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
1,210,077,234✔
3323
  if (pStbRowsCxt == NULL) return;
1,210,077,234✔
3324

3325
  taosArrayClear(pStbRowsCxt->aTagNames);
1,210,077,234✔
3326
  for (int i = 0; i < taosArrayGetSize(pStbRowsCxt->aTagVals); ++i) {
1,210,209,982✔
3327
    STagVal* p = (STagVal*)taosArrayGet(pStbRowsCxt->aTagVals, i);
132,748✔
3328
    if (IS_VAR_DATA_TYPE(p->type)) {
132,748✔
3329
      taosMemoryFreeClear(p->pData);
14,236✔
3330
    }
3331
  }
3332
  taosArrayClear(pStbRowsCxt->aTagVals);
1,210,077,234✔
3333

3334
  clearColValArray(pStbRowsCxt->aColVals);
1,210,077,234✔
3335

3336
  tTagFree(pStbRowsCxt->pTag);
1,210,077,234✔
3337
  pStbRowsCxt->pTag = NULL;
1,210,077,234✔
3338
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
1,210,077,234✔
3339
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
1,210,077,234✔
3340

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

3352
static void clearInsertParseContext(SInsertParseContext* pCxt) {
1,586,893,151✔
3353
  if (pCxt == NULL) return;
1,586,893,151✔
3354

3355
  if (pCxt->pParsedValues != NULL) {
1,586,893,151✔
3356
    tSimpleHashCleanup(pCxt->pParsedValues);
×
3357
    pCxt->pParsedValues = NULL;
×
3358
  }
3359
}
3360

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

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

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

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

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

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

3403
  if (code != TSDB_CODE_SUCCESS || !*pGotRow) {
1,209,845,815✔
3404
    return code;
10,271✔
3405
  }
3406

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

3454
  if (code == TSDB_CODE_SUCCESS) {
1,209,835,544✔
3455
    *pGotRow = true;
1,209,826,784✔
3456
  }
3457

3458
  clearStbRowsDataContext(pStbRowsCxt);
1,209,835,544✔
3459

3460
  return code;
1,209,835,544✔
3461
}
3462

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3579
  (*pNumOfRows) = 0;
852,217,988✔
3580
  while (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
3581
    int32_t index = 0;
2,147,483,647✔
3582
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, *pToken, index);
2,147,483,647✔
3583
    if (TK_NK_LP != pToken->type) {
2,147,483,647✔
3584
      break;
851,775,591✔
3585
    }
3586
    pStmt->pSql += index;
2,147,483,647✔
3587

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

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

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

3613
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) &&
876,984,691✔
3614
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
7,704,863✔
3615
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
3616
  }
3617
  return code;
852,399,009✔
3618
}
3619

3620
// VALUES (field1_value, ...) [(field1_value2, ...) ...]
3621
static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataContext,
852,230,150✔
3622
                                 SToken* pToken) {
3623
  int32_t numOfRows = 0;
852,230,150✔
3624
  int32_t code = parseValues(pCxt, pStmt, rowsDataContext, &numOfRows, pToken);
852,315,906✔
3625
  if (TSDB_CODE_SUCCESS == code) {
852,361,590✔
3626
    pStmt->totalRowsNum += numOfRows;
851,768,191✔
3627
    pStmt->totalTbNum += 1;
851,759,499✔
3628
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_INSERT);
851,762,503✔
3629
  }
3630
  return code;
852,357,937✔
3631
}
3632

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3898
  return code;
631,361✔
3899
}
3900

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

3920
  return parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
651,385✔
3921
}
3922

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

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

3936
// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
3937
static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt) {
852,852,063✔
3938
  SToken token;
848,782,339✔
3939
  NEXT_TOKEN(pStmt->pSql, token);
852,945,971✔
3940
  switch (token.type) {
853,023,717✔
3941
    case TK_VALUES:
852,372,332✔
3942
      if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT)) {
852,372,332✔
3943
        return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", token.z);
600✔
3944
      }
3945
      return parseValuesClause(pCxt, pStmt, rowsDataCxt, &token);
852,273,902✔
3946
    case TK_FILE:
651,385✔
3947
      return parseFileClause(pCxt, pStmt, rowsDataCxt, &token);
651,385✔
3948
    default:
×
3949
      break;
×
3950
  }
3951
  return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
×
3952
}
3953

3954
static void destroyStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
1,578,544,001✔
3955
  if (pStbRowsCxt == NULL) return;
1,578,544,001✔
3956
  clearStbRowsDataContext(pStbRowsCxt);
197,046✔
3957
  taosArrayDestroy(pStbRowsCxt->aColVals);
241,690✔
3958
  pStbRowsCxt->aColVals = NULL;
241,690✔
3959
  taosArrayDestroy(pStbRowsCxt->aTagVals);
241,690✔
3960
  pStbRowsCxt->aTagVals = NULL;
241,690✔
3961
  taosArrayDestroy(pStbRowsCxt->aTagNames);
241,690✔
3962
  pStbRowsCxt->aTagNames = NULL;
241,690✔
3963
  qDestroyBoundColInfo(&pStbRowsCxt->boundColsInfo);
241,690✔
3964
  tTagFree(pStbRowsCxt->pTag);
241,690✔
3965
  pStbRowsCxt->pTag = NULL;
241,690✔
3966
  taosMemoryFreeClear(pStbRowsCxt->pCtbMeta);
241,690✔
3967
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
241,690✔
3968
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
241,690✔
3969
}
3970

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

3986
    pStbRowsCxt->pTagCond = pStmt->pTagCond;
241,791✔
3987
    pStbRowsCxt->pStbMeta = pStmt->pTableMeta;
241,791✔
3988

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

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

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

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

4036
  if (code == TSDB_CODE_SUCCESS) {
241,791✔
4037
    code = parseBoundColumns(pCxt, pStmt, &pStmt->pBoundCols, BOUND_ALL_AND_TBNAME, pStmt->pTableMeta,
241,791✔
4038
                             &pStbRowsCxt->boundColsInfo);
241,791✔
4039
    pStbRowsCxt->hasTimestampTag = false;
241,791✔
4040
    for (int32_t i = 0; i < pStbRowsCxt->boundColsInfo.numOfBound; ++i) {
1,278,561✔
4041
      int16_t schemaIndex = pStbRowsCxt->boundColsInfo.pColIndex[i];
1,036,770✔
4042
      if (schemaIndex != getTbnameSchemaIndex(pStmt->pTableMeta) && schemaIndex >= getNumOfColumns(pStmt->pTableMeta)) {
1,036,770✔
4043
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_TIMESTAMP) {
135,881✔
4044
          pStbRowsCxt->hasTimestampTag = true;
303✔
4045
        }
4046
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_JSON) {
135,881✔
4047
          pStbRowsCxt->isJsonTag = true;
×
4048
        }
4049
      }
4050
    }
4051
    pStmt->pStbRowsCxt = pStbRowsCxt;
241,791✔
4052
  }
4053

4054
  if (code == TSDB_CODE_SUCCESS) {
241,791✔
4055
    SRowsDataContext rowsDataCxt;
4056
    rowsDataCxt.pStbRowsCxt = pStbRowsCxt;
228,555✔
4057
    code = parseDataClause(pCxt, pStmt, rowsDataCxt);
228,555✔
4058
  }
4059

4060
  return code;
241,791✔
4061
}
4062

4063
// input pStmt->pSql:
4064
//   1. [(tag1_name, ...)] ...
4065
//   2. VALUES ... | FILE ...
4066
static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
853,294,756✔
4067
  if (!pStmt->stbSyntax) {
853,294,756✔
4068
    STableDataCxt*   pTableCxt = NULL;
853,080,676✔
4069
    int32_t          code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt);
853,115,024✔
4070
    SRowsDataContext rowsDataCxt;
4071
    rowsDataCxt.pTableDataCxt = pTableCxt;
852,966,017✔
4072
    if (TSDB_CODE_SUCCESS == code) {
852,966,017✔
4073
      code = parseDataClause(pCxt, pStmt, rowsDataCxt);
852,726,884✔
4074
    }
4075
    return code;
852,927,377✔
4076
  } else {
4077
    int32_t code = parseInsertStbClauseBottom(pCxt, pStmt);
262,317✔
4078
    return code;
285,692✔
4079
  }
4080
}
4081

4082
static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
853,631,618✔
4083
  qDestroyBoundColInfo(&pCxt->tags);
853,631,618✔
4084
  clearInsertParseContext(pCxt);
853,657,608✔
4085
  taosMemoryFreeClear(pStmt->pTableMeta);
853,670,480✔
4086
  if (pStmt->pTagCond) nodesDestroyNode(pStmt->pTagCond);
853,742,353✔
4087
  if (pStmt->pPrivCols) taosArrayDestroy(pStmt->pPrivCols);
853,642,461✔
4088
  if (pStmt->pTableTag) taosArrayDestroy(pStmt->pTableTag);
853,689,947✔
4089
  tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
853,681,721✔
4090
  taosMemoryFreeClear(pStmt->pCreateTblReq);
853,712,531✔
4091
  pCxt->missCache = false;
853,684,367✔
4092
  pCxt->usingDuplicateTable = false;
853,642,856✔
4093
  pStmt->pBoundCols = NULL;
853,732,111✔
4094
  pStmt->pPrivCols = NULL;
853,729,809✔
4095
  pStmt->pTagCond = NULL;
853,728,230✔
4096
  pStmt->usingTableProcessing = false;
853,635,366✔
4097
  pStmt->fileProcessing = false;
853,735,746✔
4098
  pStmt->usingTableName.type = 0;
853,704,634✔
4099

4100
  destroyStbRowsDataContext(pStmt->pStbRowsCxt);
853,720,796✔
4101
  taosMemoryFreeClear(pStmt->pStbRowsCxt);
853,638,614✔
4102
  pStmt->stbSyntax = false;
853,654,149✔
4103
}
853,688,301✔
4104

4105
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
4106
static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
853,634,004✔
4107
  resetEnvPreTable(pCxt, pStmt);
853,634,004✔
4108
  int32_t code = parseSchemaClauseTop(pCxt, pStmt, pTbName);
853,675,791✔
4109
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
853,557,456✔
4110
    code = parseInsertTableClauseBottom(pCxt, pStmt);
845,194,522✔
4111
  }
4112

4113
  return code;
853,587,282✔
4114
}
4115

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

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

4128
    *pHasData = false;
723,660,796✔
4129
    return TSDB_CODE_SUCCESS;
723,561,162✔
4130
  }
4131

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

4136
  if (TK_NK_QUESTION == pTbName->type) {
853,727,526✔
4137
    pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
7,556,810✔
4138
    if (pCxt->pComCxt->stmtBindVersion == 0) {
7,556,362✔
4139
      return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
4140
    }
4141

4142
    char*   tbName = NULL;
7,553,054✔
4143
    int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
7,554,179✔
4144
    if (TSDB_CODE_SUCCESS == code) {
7,553,012✔
4145
      pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
7,553,585✔
4146
      pTbName->z = tbName;
7,554,625✔
4147
      pTbName->n = strlen(tbName);
7,555,489✔
4148
    }
4149
    if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
7,552,691✔
4150
      pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
924✔
4151
      code = TSDB_CODE_SUCCESS;
3,080✔
4152
    }
4153
    return code;
7,554,847✔
4154
  }
4155

4156
  if (TK_NK_ID != pTbName->type && TK_NK_STRING != pTbName->type && TK_NK_QUESTION != pTbName->type) {
846,111,122✔
4157
    return buildSyntaxErrMsg(&pCxt->msg, "table_name is expected", pTbName->z);
101✔
4158
  }
4159

4160
  // db.? situation,ensure that the only thing following the '.' mark is '?'
4161
  char* tbNameAfterDbName = strnchr(pTbName->z, '.', pTbName->n, true);
846,152,638✔
4162
  if (tbNameAfterDbName != NULL) {
846,082,351✔
4163
    if (*(tbNameAfterDbName + 1) == '?') {
224,629,113✔
4164
      pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
6,060✔
4165
      char* tbName = NULL;
6,060✔
4166
      if (NULL == pCxt->pComCxt->pStmtCb) {
6,060✔
4167
        return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
4168
      }
4169
      int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
6,060✔
4170
      if (TSDB_CODE_SUCCESS == code) {
6,060✔
4171
        pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
3,737✔
4172
        pTbName->z = tbName;
3,737✔
4173
        pTbName->n = strlen(tbName);
3,737✔
4174
      }
4175
      if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
6,060✔
4176
        pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
2,323✔
4177
        code = TSDB_CODE_SUCCESS;
2,323✔
4178
      }
4179
    } else {
4180
      pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
224,616,622✔
4181
      parserTrace("QID:0x%" PRIx64 ", stmt tbname:%s is specified in sql", pCxt->pComCxt->requestId, pTbName->z);
224,618,264✔
4182
      *pHasData = true;
224,618,264✔
4183
    }
4184
    return TSDB_CODE_SUCCESS;
224,625,346✔
4185
  }
4186

4187
  if (TK_NK_ID == pTbName->type) {
621,453,238✔
4188
    pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
617,784,077✔
4189
  }
4190

4191
  *pHasData = true;
621,522,727✔
4192
  return TSDB_CODE_SUCCESS;
621,473,972✔
4193
}
4194

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

4202
  SStmtCallback* pStmtCb = pCxt->pComCxt->pStmtCb;
7,696,885✔
4203
  int32_t        code = (*pStmtCb->setInfoFn)(pStmtCb->pStmt, pStmt->pTableMeta, tags, &pCxt->pParsedValues,
23,057,220✔
4204
                                       &pStmt->targetTableName, pStmt->usingTableProcessing, pStmt->pVgroupsHashObj,
7,702,514✔
4205
                                       pStmt->pTableBlockHashObj, pStmt->usingTableName.tname, pCxt->stmtTbNameFlag);
7,705,436✔
4206

4207
  memset(&pCxt->tags, 0, sizeof(pCxt->tags));
7,694,168✔
4208
  pStmt->pVgroupsHashObj = NULL;
7,697,993✔
4209
  pStmt->pTableBlockHashObj = NULL;
7,695,144✔
4210
  return code;
7,686,540✔
4211
}
4212

4213
static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
723,602,064✔
4214
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) {
723,602,064✔
4215
    return setStmtInfo(pCxt, pStmt);
7,695,711✔
4216
  }
4217

4218
  // release old array alloced by merge
4219
  pStmt->freeArrayFunc(pStmt->pVgDataBlocks);
715,934,875✔
4220
  pStmt->pVgDataBlocks = NULL;
715,910,957✔
4221

4222
  bool fileOnly = (pStmt->insertType == TSDB_QUERY_TYPE_FILE_INSERT);
715,941,568✔
4223
  if (fileOnly) {
715,982,516✔
4224
    // none data, skip merge & buildvgdata
4225
    if (0 == taosHashGetSize(pStmt->pTableCxtHashObj)) {
615,407✔
4226
      pCxt->needRequest = false;
6,000✔
4227
      return TSDB_CODE_SUCCESS;
6,000✔
4228
    }
4229
  }
4230

4231
  // merge according to vgId
4232
  int32_t code = insMergeTableDataCxt(fileOnly ? pStmt->pTableCxtHashObj : pStmt->pTableBlockHashObj,
715,969,939✔
4233
                                      &pStmt->pVgDataBlocks, pStmt->fileProcessing);
715,976,516✔
4234
  // clear tmp hashobj only
4235
  taosHashClear(pStmt->pTableCxtHashObj);
716,008,402✔
4236

4237
  if (TSDB_CODE_SUCCESS == code) {
716,015,943✔
4238
    code = insBuildVgDataBlocks(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks, false);
716,029,198✔
4239
  }
4240

4241
  return code;
716,012,377✔
4242
}
4243

4244
// tb_name
4245
//     [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
4246
//     [(field1_name, ...)]
4247
//     VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
4248
// [...];
4249
static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
732,784,751✔
4250
  SToken  token;
730,138,420✔
4251
  int32_t code = TSDB_CODE_SUCCESS;
732,815,614✔
4252
  bool    hasData = true;
732,815,614✔
4253
  // for each table
4254
  while (TSDB_CODE_SUCCESS == code && hasData && !pCxt->missCache && !pStmt->fileProcessing) {
2,147,483,647✔
4255
    // pStmt->pSql -> tb_name ...
4256
    NEXT_TOKEN(pStmt->pSql, token);
1,577,408,560✔
4257
    code = checkTableClauseFirstToken(pCxt, pStmt, &token, &hasData);
1,577,514,533✔
4258
    if (TSDB_CODE_SUCCESS == code && hasData) {
1,577,205,180✔
4259
      code = parseInsertTableClause(pCxt, pStmt, &token);
853,648,376✔
4260
    }
4261

4262
    if (TSDB_CODE_SUCCESS == code && pStmt->pTableMeta &&
1,577,142,436✔
4263
        (((pStmt->pTableMeta->virtualStb == 1) && (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE)) ||
1,574,807,921✔
4264
         (pStmt->pTableMeta->tableType == TSDB_VIRTUAL_NORMAL_TABLE ||
1,574,834,891✔
4265
          pStmt->pTableMeta->tableType == TSDB_VIRTUAL_CHILD_TABLE))) {
1,574,874,385✔
4266
      code = buildInvalidOperationMsg(&pCxt->msg, "Virtual table can not be written");
10,883✔
4267
    }
4268
  }
4269

4270
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
732,718,232✔
4271
    code = parseInsertBodyBottom(pCxt, pStmt);
723,610,027✔
4272
  }
4273
  return code;
732,784,806✔
4274
}
4275

4276
static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); }
39,865,818✔
4277

4278
static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, SNode** pOutput) {
725,023,719✔
4279
  SVnodeModifyOpStmt* pStmt = NULL;
725,023,719✔
4280
  int32_t             code = nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT, (SNode**)&pStmt);
725,055,271✔
4281
  if (NULL == pStmt) {
725,093,504✔
4282
    return code;
×
4283
  }
4284

4285
  if (pCxt->pComCxt->pStmtCb) {
725,093,504✔
4286
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT);
7,716,962✔
4287
  }
4288
  pStmt->pSql = pCxt->pComCxt->pSql;
725,093,394✔
4289

4290
  pStmt->freeHashFunc = insDestroyTableDataCxtHashMap;
725,051,545✔
4291
  pStmt->freeArrayFunc = insDestroyVgroupDataCxtList;
725,054,293✔
4292
  pStmt->freeStbRowsCxtFunc = destroyStbRowsDataContext;
725,025,465✔
4293
  pStmt->pCsvParser = NULL;
725,056,764✔
4294

4295
  if (!reentry) {
725,063,660✔
4296
    pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
725,058,222✔
4297
    if (pCxt->pComCxt->pStmtCb) {
725,023,822✔
4298
      pStmt->pTableBlockHashObj =
7,715,111✔
4299
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
7,713,233✔
4300
    } else {
4301
      pStmt->pTableBlockHashObj =
717,380,203✔
4302
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
717,284,246✔
4303
    }
4304
  }
4305
  pStmt->pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
725,102,680✔
4306
  pStmt->pSuperTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
725,096,024✔
4307
  pStmt->pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
725,098,509✔
4308
  pStmt->pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
725,097,037✔
4309
  if ((!reentry && (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj)) ||
725,099,648✔
4310
      NULL == pStmt->pSubTableHashObj || NULL == pStmt->pTableNameHashObj || NULL == pStmt->pDbFNameHashObj) {
725,097,194✔
4311
    nodesDestroyNode((SNode*)pStmt);
945✔
4312
    return TSDB_CODE_OUT_OF_MEMORY;
×
4313
  }
4314

4315
  taosHashSetFreeFp(pStmt->pSubTableHashObj, destroySubTableHashElem);
725,089,768✔
4316
  taosHashSetFreeFp(pStmt->pSuperTableHashObj, destroySubTableHashElem);
725,065,919✔
4317

4318
  *pOutput = (SNode*)pStmt;
725,091,377✔
4319
  return TSDB_CODE_SUCCESS;
725,087,911✔
4320
}
4321

4322
static int32_t createInsertQuery(SInsertParseContext* pCxt, SQuery** pOutput) {
725,036,914✔
4323
  SQuery* pQuery = NULL;
725,036,914✔
4324
  int32_t code = nodesMakeNode(QUERY_NODE_QUERY, (SNode**)&pQuery);
725,047,107✔
4325
  if (NULL == pQuery) {
725,069,046✔
4326
    return code;
×
4327
  }
4328

4329
  pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
725,069,046✔
4330
  pQuery->haveResultSet = false;
725,072,163✔
4331
  pQuery->msgType = TDMT_VND_SUBMIT;
725,073,158✔
4332

4333
  code = createVnodeModifOpStmt(pCxt, false, &pQuery->pRoot);
725,056,829✔
4334
  if (TSDB_CODE_SUCCESS == code) {
725,048,904✔
4335
    *pOutput = pQuery;
725,048,904✔
4336
  } else {
4337
    nodesDestroyNode((SNode*)pQuery);
×
4338
  }
4339
  return code;
725,076,785✔
4340
}
4341

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

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

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

4371
  taosMemoryFreeClear(*pMeta);
8,347,017✔
4372
  SMetaRes* pRes = taosArrayGet(pTables, 0);
8,347,017✔
4373
  if (TSDB_CODE_SUCCESS == pRes->code) {
8,347,017✔
4374
    *pMeta = tableMetaDup((const STableMeta*)pRes->pRes);
8,200,664✔
4375
    if (NULL == *pMeta) {
8,200,664✔
4376
      return TSDB_CODE_OUT_OF_MEMORY;
×
4377
    }
4378
  }
4379
  return pRes->code;
8,347,017✔
4380
}
4381

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

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

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

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

4414
  SMetaRes* pRes = taosArrayGet(pTables, 0);
8,197,597✔
4415
  if (TSDB_CODE_SUCCESS != pRes->code) {
8,197,597✔
4416
    return pRes->code;
×
4417
  }
4418

4419
  SVgroupInfo* pVg = pRes->pRes;
8,197,597✔
4420
  if (isStb) {
8,197,597✔
4421
    pStmt->pTableMeta->vgId = pVg->vgId;
6,563,557✔
4422
  }
4423
  return taosHashPut(pStmt->pVgroupsHashObj, (const char*)&pVg->vgId, sizeof(pVg->vgId), (char*)pVg,
8,197,597✔
4424
                     sizeof(SVgroupInfo));
4425
}
4426

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

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

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

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

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

4475
  if (TSDB_CODE_SUCCESS == code && isStb) {
8,197,597✔
4476
    code = storeChildTableMeta(pCxt, pStmt);
6,563,557✔
4477
  }
4478
  if (TSDB_CODE_SUCCESS == code) {
8,197,597✔
4479
    code = addTableVgroupFromMetaData(pMetaData->pTableHash, pStmt, isStb);
8,197,597✔
4480
  }
4481
  if (TSDB_CODE_SUCCESS == code && !isStb && NULL != pStmt->pTagCond) {
8,197,597✔
4482
    code = checkSubtablePrivilegeForTable(pMetaData->pTableTag, pStmt);
5,909✔
4483
  }
4484
  return code;
8,197,597✔
4485
}
4486

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

4492
static void clearCatalogReq(SCatalogReq* pCatalogReq) {
8,359,689✔
4493
  if (NULL == pCatalogReq) {
8,359,689✔
4494
    return;
×
4495
  }
4496

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

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

4519
  int32_t code = checkAuthFromMetaData(pCxt, pMetaData, pStmt);
8,359,689✔
4520

4521
  if (code == TSDB_CODE_SUCCESS) {
8,359,689✔
4522
    code = getTableMetaFromMetaData(pMetaData->pTableMeta, &pStmt->pTableMeta);
8,347,017✔
4523
  }
4524
#ifdef TD_ENTERPRISE
4525
  // MAC NWD+NRU: retry path — metadata was just fetched from server, check must be enforced here too.
4526
  // (The primary NWD check in getTargetTableSchema is guarded by !missCache and therefore does not run
4527
  // when the first parse attempt hits a cache miss, e.g. fresh connections used by "taos -s".)
4528
  if (pCxt->pComCxt->macMode && code == TSDB_CODE_SUCCESS && pStmt->pTableMeta != NULL) {
8,359,689✔
4529
    int8_t secLvl = pStmt->pTableMeta->secLvl;
782✔
4530
    if (secLvl >= 0) {
782✔
4531
      if (pCxt->pComCxt->minSecLevel > secLvl) {
782✔
4532
        code = TSDB_CODE_MAC_NO_WRITE_DOWN;  // NWD violation
199✔
4533
      } else if (pCxt->pComCxt->maxSecLevel < secLvl) {
583✔
4534
        code = TSDB_CODE_MAC_INSUFFICIENT_LEVEL;  // NRU violation
×
4535
      }
4536
    }
4537
  }
4538
#endif
4539
  if (code == TSDB_CODE_SUCCESS) {
8,359,689✔
4540
    code = checkAuthUseDb(pCxt->pComCxt, &pStmt->targetTableName, pStmt->pTableMeta->isAudit);
8,200,465✔
4541
  }
4542
  if (code == TSDB_CODE_SUCCESS) {
8,359,689✔
4543
    if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE && !pStmt->usingTableProcessing) {
8,200,465✔
4544
      pStmt->stbSyntax = true;
2,868✔
4545
    }
4546
    if (!pStmt->stbSyntax) {
8,200,465✔
4547
      if (pStmt->usingTableProcessing) {
8,197,597✔
4548
        return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, true);
6,563,557✔
4549
      }
4550
      return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, false);
1,634,040✔
4551
    }
4552
  }
4553
  return code;
162,092✔
4554
}
4555

4556
static int32_t resetVnodeModifOpStmt(SInsertParseContext* pCxt, SQuery* pQuery) {
1,842✔
4557
  nodesDestroyNode(pQuery->pRoot);
1,842✔
4558

4559
  int32_t code = createVnodeModifOpStmt(pCxt, true, &pQuery->pRoot);
1,842✔
4560
  if (TSDB_CODE_SUCCESS == code) {
1,842✔
4561
    SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
1,842✔
4562

4563
    code = (*pCxt->pComCxt->pStmtCb->getExecInfoFn)(pCxt->pComCxt->pStmtCb->pStmt, &pStmt->pVgroupsHashObj,
1,842✔
4564
                                                    &pStmt->pTableBlockHashObj);
4565
    if (TSDB_CODE_SUCCESS == code) {
1,842✔
4566
      if (NULL == pStmt->pVgroupsHashObj) {
1,842✔
4567
        pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
×
4568
      }
4569
      if (NULL == pStmt->pTableBlockHashObj) {
1,842✔
4570
        pStmt->pTableBlockHashObj =
×
4571
            taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
×
4572
      }
4573
      if (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj) {
1,842✔
4574
        code = TSDB_CODE_OUT_OF_MEMORY;
×
4575
      }
4576
    }
4577
  }
4578

4579
  return code;
1,842✔
4580
}
4581

4582
static int32_t initInsertQuery(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
733,446,653✔
4583
                               SQuery** pQuery) {
4584
  if (NULL == *pQuery) {
733,446,653✔
4585
    return createInsertQuery(pCxt, pQuery);
725,094,939✔
4586
  }
4587

4588
  if (NULL != pCxt->pComCxt->pStmtCb) {
8,364,288✔
4589
    return resetVnodeModifOpStmt(pCxt, *pQuery);
1,842✔
4590
  }
4591

4592
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)(*pQuery)->pRoot;
8,371,689✔
4593

4594
  if (!pStmt->fileProcessing) {
8,371,689✔
4595
    return setVnodeModifOpStmt(pCxt, pCatalogReq, pMetaData, pStmt);
8,359,689✔
4596
  }
4597

4598
  return TSDB_CODE_SUCCESS;
12,000✔
4599
}
4600

4601
static int32_t setRefreshMeta(SQuery* pQuery) {
723,650,713✔
4602
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
723,650,713✔
4603
  int32_t             code = 0;
723,745,296✔
4604

4605
  if (taosHashGetSize(pStmt->pTableNameHashObj) > 0) {
723,745,296✔
4606
    taosArrayDestroy(pQuery->pTableList);
7,877,984✔
4607
    pQuery->pTableList = taosArrayInit(taosHashGetSize(pStmt->pTableNameHashObj), sizeof(SName));
7,867,841✔
4608
    if (!pQuery->pTableList) {
7,854,300✔
4609
      code = terrno;
×
4610
    } else {
4611
      SName* pTable = taosHashIterate(pStmt->pTableNameHashObj, NULL);
7,863,905✔
4612
      while (NULL != pTable) {
18,937,629✔
4613
        if (NULL == taosArrayPush(pQuery->pTableList, pTable)) {
22,121,622✔
4614
          code = terrno;
×
4615
          taosHashCancelIterate(pStmt->pTableNameHashObj, pTable);
×
4616
          break;
×
4617
        }
4618
        pTable = taosHashIterate(pStmt->pTableNameHashObj, pTable);
11,064,558✔
4619
      }
4620
    }
4621
  }
4622

4623
  if (TSDB_CODE_SUCCESS == code && taosHashGetSize(pStmt->pDbFNameHashObj) > 0) {
723,755,822✔
4624
    taosArrayDestroy(pQuery->pDbList);
7,882,138✔
4625
    pQuery->pDbList = taosArrayInit(taosHashGetSize(pStmt->pDbFNameHashObj), TSDB_DB_FNAME_LEN);
7,881,013✔
4626
    if (!pQuery->pDbList) {
7,856,818✔
4627
      code = terrno;
×
4628
    } else {
4629
      char* pDb = taosHashIterate(pStmt->pDbFNameHashObj, NULL);
7,860,262✔
4630
      while (NULL != pDb) {
15,742,043✔
4631
        if (NULL == taosArrayPush(pQuery->pDbList, pDb)) {
15,766,985✔
4632
          code = terrno;
×
4633
          taosHashCancelIterate(pStmt->pDbFNameHashObj, pDb);
×
4634
          break;
×
4635
        }
4636
        pDb = taosHashIterate(pStmt->pDbFNameHashObj, pDb);
7,884,616✔
4637
      }
4638
    }
4639
  }
4640

4641
  return code;
723,721,416✔
4642
}
4643

4644
// INSERT INTO
4645
//   tb_name
4646
//       [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]]
4647
//       [(field1_name, ...)]
4648
//       VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
4649
//   [...];
4650
static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
725,027,874✔
4651
  int32_t code = skipInsertInto(&pStmt->pSql, &pCxt->msg);
725,027,874✔
4652
  if (TSDB_CODE_SUCCESS == code) {
725,087,488✔
4653
    code = parseInsertBody(pCxt, pStmt);
725,090,304✔
4654
  }
4655
  return code;
724,961,822✔
4656
}
4657

4658
static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
12,000✔
4659
  int32_t          code = TSDB_CODE_SUCCESS;
12,000✔
4660
  SRowsDataContext rowsDataCxt;
4661

4662
  if (!pStmt->stbSyntax) {
12,000✔
4663
    STableDataCxt* pTableCxt = NULL;
10,800✔
4664
    code = getTableDataCxt(pCxt, pStmt, &pTableCxt);
10,800✔
4665
    rowsDataCxt.pTableDataCxt = pTableCxt;
10,800✔
4666
  } else {
4667
    rowsDataCxt.pStbRowsCxt = pStmt->pStbRowsCxt;
1,200✔
4668
  }
4669
  if (TSDB_CODE_SUCCESS == code) {
12,000✔
4670
    code = parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
12,000✔
4671
  }
4672

4673
  if (TSDB_CODE_SUCCESS == code) {
12,000✔
4674
    if (pStmt->fileProcessing) {
12,000✔
4675
      code = parseInsertBodyBottom(pCxt, pStmt);
×
4676
    } else {
4677
      code = parseInsertBody(pCxt, pStmt);
12,000✔
4678
    }
4679
  }
4680

4681
  return code;
12,000✔
4682
}
4683

4684
static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
8,199,648✔
4685
  int32_t code = parseInsertTableClauseBottom(pCxt, pStmt);
8,199,648✔
4686
  if (TSDB_CODE_SUCCESS == code) {
8,199,648✔
4687
    code = parseInsertBody(pCxt, pStmt);
7,752,539✔
4688
  }
4689
  return code;
8,199,648✔
4690
}
4691

4692
static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
733,239,552✔
4693
  if (pStmt->pSql == pCxt->pComCxt->pSql || NULL != pCxt->pComCxt->pStmtCb) {
733,239,552✔
4694
    return parseInsertSqlFromStart(pCxt, pStmt);
725,065,999✔
4695
  }
4696

4697
  if (pStmt->fileProcessing) {
8,211,648✔
4698
    return parseInsertSqlFromCsv(pCxt, pStmt);
12,000✔
4699
  }
4700

4701
  return parseInsertSqlFromTable(pCxt, pStmt);
8,199,648✔
4702
}
4703

4704
static int32_t buildUsingInsertTableReq(SName* pSName, SName* pCName, SArray** pTables) {
6,598,735✔
4705
  if (NULL == *pTables) {
6,598,735✔
4706
    *pTables = taosArrayInit(2, sizeof(SName));
6,598,735✔
4707
    if (NULL == *pTables) {
6,598,735✔
4708
      goto _err;
×
4709
    }
4710
  }
4711
  if (NULL == taosArrayPush(*pTables, pSName)) {
13,197,470✔
4712
    goto _err;
×
4713
  }
4714
  if (NULL == taosArrayPush(*pTables, pCName)) {
13,197,470✔
4715
    goto _err;
×
4716
  }
4717
  return TSDB_CODE_SUCCESS;
6,598,735✔
4718

4719
_err:
×
4720
  if (NULL != *pTables) {
×
4721
    taosArrayDestroy(*pTables);
×
4722
    *pTables = NULL;
×
4723
  }
4724
  return terrno;
×
4725
}
4726

4727
static int32_t buildInsertTableReq(SName* pName, SArray** pTables) {
10,201,340✔
4728
  *pTables = taosArrayInit(1, sizeof(SName));
10,201,340✔
4729
  if (NULL == *pTables) {
10,201,087✔
4730
    return terrno;
×
4731
  }
4732

4733
  if (NULL == taosArrayPush(*pTables, pName)) {
20,402,656✔
4734
    taosArrayDestroy(*pTables);
×
4735
    *pTables = NULL;
×
4736
    return terrno;
×
4737
  }
4738
  return TSDB_CODE_SUCCESS;
10,201,328✔
4739
}
4740

4741
static int32_t buildInsertUsingDbReq(SName* pSName, SName* pCName, SArray** pDbs) {
6,598,735✔
4742
  if (NULL == *pDbs) {
6,598,735✔
4743
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
6,598,735✔
4744
    if (NULL == *pDbs) {
6,598,735✔
4745
      return terrno;
×
4746
    }
4747
  }
4748

4749
  STablesReq req = {0};
6,598,735✔
4750
  req.autoCreate = 1;
6,598,735✔
4751
  (void)tNameGetFullDbName(pSName, req.dbFName);
6,598,735✔
4752
  (void)tNameGetFullDbName(pCName, req.dbFName);
6,598,735✔
4753

4754
  int32_t code = buildUsingInsertTableReq(pSName, pCName, &req.pTables);
6,598,735✔
4755
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
13,197,470✔
4756
    code = TSDB_CODE_OUT_OF_MEMORY;
×
4757
  }
4758
  return code;
6,598,735✔
4759
}
4760

4761
static int32_t buildInsertDbReq(SName* pName, SArray** pDbs) {
10,194,338✔
4762
  if (NULL == *pDbs) {
10,194,338✔
4763
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
10,194,579✔
4764
    if (NULL == *pDbs) {
10,194,338✔
4765
      return terrno;
×
4766
    }
4767
  }
4768

4769
  STablesReq req = {0};
10,194,579✔
4770
  (void)tNameGetFullDbName(pName, req.dbFName);
10,194,338✔
4771
  int32_t code = buildInsertTableReq(pName, &req.pTables);
10,194,579✔
4772
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
20,389,134✔
4773
    code = TSDB_CODE_OUT_OF_MEMORY;
×
4774
  }
4775

4776
  return code;
10,194,567✔
4777
}
4778

4779
static int32_t buildInsertUserAuthReq(SParseContext* pCxt, SName* pName, SArray** pUserAuth) {
8,396,416✔
4780
  *pUserAuth = taosArrayInit(1, sizeof(SUserAuthInfo));
8,396,416✔
4781
  if (NULL == *pUserAuth) {
8,396,416✔
4782
    return terrno;
×
4783
  }
4784

4785
  SUserAuthInfo userAuth = {.privType = PRIV_TBL_INSERT, .objType = PRIV_OBJ_TBL, .userId = pCxt->userId};
8,396,657✔
4786
  snprintf(userAuth.user, sizeof(userAuth.user), "%s", pCxt->pUser);
8,396,657✔
4787
  memcpy(&userAuth.tbName, pName, sizeof(SName));
8,396,657✔
4788
  if (NULL == taosArrayPush(*pUserAuth, &userAuth)) {
16,793,314✔
4789
    taosArrayDestroy(*pUserAuth);
×
4790
    *pUserAuth = NULL;
×
4791
    return terrno;
×
4792
  }
4793

4794
  return TSDB_CODE_SUCCESS;
8,396,657✔
4795
}
4796

4797
static int32_t buildInsertTableTagReq(SName* pName, SArray** pTables) { return buildInsertTableReq(pName, pTables); }
6,761✔
4798

4799
static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SCatalogReq* pCatalogReq) {
8,396,404✔
4800
  int32_t code = buildInsertUserAuthReq(
16,767,014✔
4801
      pCxt->pComCxt, (0 == pStmt->usingTableName.type ? &pStmt->targetTableName : &pStmt->usingTableName),
8,396,404✔
4802
      &pCatalogReq->pUser);
4803
  if (TSDB_CODE_SUCCESS == code && pCxt->needTableTagVal) {
8,396,416✔
4804
    code = buildInsertTableTagReq(&pStmt->targetTableName, &pCatalogReq->pTableTag);
6,761✔
4805
  }
4806
  if (TSDB_CODE_SUCCESS == code) {
8,396,657✔
4807
    if (0 == pStmt->usingTableName.type) {
8,396,657✔
4808
      code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableMeta);
1,797,922✔
4809
    } else {
4810
      code = buildInsertUsingDbReq(&pStmt->usingTableName, &pStmt->targetTableName, &pCatalogReq->pTableMeta);
6,598,735✔
4811
    }
4812
  }
4813
  if (TSDB_CODE_SUCCESS == code) {
8,396,657✔
4814
    code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableHash);
8,396,657✔
4815
  }
4816
  return code;
8,396,645✔
4817
}
4818

4819
static int32_t setNextStageInfo(SInsertParseContext* pCxt, SQuery* pQuery, SCatalogReq* pCatalogReq) {
732,047,572✔
4820
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
732,047,572✔
4821
  if (pCxt->missCache) {
732,130,380✔
4822
    parserDebug("QID:0x%" PRIx64 ", %d rows of %d tables will be inserted before obtain the cache",
8,396,645✔
4823
                pCxt->pComCxt->requestId, pStmt->totalRowsNum, pStmt->totalTbNum);
4824

4825
    pQuery->execStage = QUERY_EXEC_STAGE_PARSE;
8,396,645✔
4826
    return buildInsertCatalogReq(pCxt, pStmt, pCatalogReq);
8,396,645✔
4827
  }
4828

4829
  parserDebug("QID:0x%" PRIx64 ", %d rows of %d tables will be inserted", pCxt->pComCxt->requestId, pStmt->totalRowsNum,
723,749,204✔
4830
              pStmt->totalTbNum);
4831

4832
  pQuery->execStage = QUERY_EXEC_STAGE_SCHEDULE;
723,751,248✔
4833
  return TSDB_CODE_SUCCESS;
723,771,487✔
4834
}
4835

4836
int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) {
733,346,529✔
4837
  SInsertParseContext context = {.pComCxt = pCxt,
736,001,094✔
4838
                                 .msg = {.buf = pCxt->pMsg, .len = pCxt->msgLen},
733,376,156✔
4839
                                 .missCache = false,
4840
                                 .usingDuplicateTable = false,
4841
                                 .needRequest = true,
4842
                                 .forceUpdate = (NULL != pCatalogReq ? pCatalogReq->forceUpdate : false)};
733,463,901✔
4843

4844
  int32_t code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery);
733,462,944✔
4845
  if (TSDB_CODE_SUCCESS == code) {
733,410,855✔
4846
    code = parseInsertSqlImpl(&context, (SVnodeModifyOpStmt*)((*pQuery)->pRoot));
733,265,216✔
4847
  }
4848

4849
  if (TSDB_CODE_SUCCESS == code) {
733,309,702✔
4850
    code = setNextStageInfo(&context, *pQuery, pCatalogReq);
732,026,168✔
4851
  }
4852
  if ((TSDB_CODE_SUCCESS == code || NEED_CLIENT_HANDLE_ERROR(code)) &&
733,424,326✔
4853
      QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) {
732,349,383✔
4854
    code = setRefreshMeta(*pQuery);
723,731,099✔
4855
  }
4856

4857
  qDestroyBoundColInfo(&context.tags);
733,427,876✔
4858
  clearInsertParseContext(&context);
733,321,034✔
4859
  // if no data to insert, set emptyMode to avoid request server
4860
  if (!context.needRequest) {
733,308,668✔
4861
    (*pQuery)->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
6,000✔
4862
  }
4863
  return code;
733,308,668✔
4864
}
4865

4866
// CSV Parser Implementation
4867
static int32_t csvParserInit(SCsvParser* parser, TdFilePtr pFile) {
651,385✔
4868
  if (!parser || !pFile) {
651,385✔
4869
    return TSDB_CODE_INVALID_PARA;
×
4870
  }
4871

4872
  memset(parser, 0, sizeof(SCsvParser));
651,385✔
4873

4874
  // Set default CSV format
4875
  parser->delimiter = CSV_DEFAULT_DELIMITER;
651,385✔
4876
  parser->quote = CSV_QUOTE_SINGLE;  // Default to single quote for TDengine compatibility
651,385✔
4877
  parser->escape = CSV_ESCAPE_CHAR;
651,385✔
4878
  parser->allowNewlineInField = true;
651,385✔
4879

4880
  // Initialize buffer
4881
  parser->bufferSize = 64 * 1024;  // 64KB buffer
651,385✔
4882
  parser->buffer = taosMemoryMalloc(parser->bufferSize);
651,385✔
4883
  if (!parser->buffer) {
651,385✔
4884
    return terrno;
×
4885
  }
4886

4887
  // Initialize line buffer for reuse
4888
  parser->lineBufferCapacity = 64 * 1024;  // Initial 64KB line buffer
651,385✔
4889
  parser->lineBuffer = taosMemoryMalloc(parser->lineBufferCapacity);
651,385✔
4890
  if (!parser->lineBuffer) {
651,385✔
4891
    return terrno;
×
4892
  }
4893

4894
  parser->bufferPos = 0;
651,385✔
4895
  parser->bufferLen = 0;
651,385✔
4896
  parser->eof = false;
651,385✔
4897
  parser->pFile = pFile;
651,385✔
4898

4899
  // Fill initial buffer to detect quote type
4900
  int32_t code = csvParserFillBuffer(parser);
651,385✔
4901
  if (code != TSDB_CODE_SUCCESS) {
651,385✔
4902
    return code;
×
4903
  }
4904

4905
  // Auto-detect quote character by finding the first quote in the file
4906
  // Skip the header line and look for the first quote character in data
4907
  bool foundFirstQuote = false;
651,385✔
4908
  bool inFirstLine = true;
651,385✔
4909

4910
  for (size_t i = 0; i < parser->bufferLen && !foundFirstQuote; i++) {
819,117,747✔
4911
    char ch = parser->buffer[i];
818,466,362✔
4912

4913
    // Skip the first line (header)
4914
    if (inFirstLine) {
818,466,362✔
4915
      if (ch == '\n') {
108,414,717✔
4916
        inFirstLine = false;
650,021✔
4917
      }
4918
      continue;
108,414,717✔
4919
    }
4920

4921
    // Look for the first quote character in data lines
4922
    if (ch == CSV_QUOTE_SINGLE) {
710,051,645✔
4923
      parser->quote = CSV_QUOTE_SINGLE;
78,584✔
4924
      foundFirstQuote = true;
78,584✔
4925
    } else if (ch == CSV_QUOTE_DOUBLE) {
709,973,061✔
4926
      parser->quote = CSV_QUOTE_DOUBLE;
559,461✔
4927
      foundFirstQuote = true;
559,461✔
4928
    }
4929
  }
4930

4931
  // If no quotes found, keep default (single quote for TDengine compatibility)
4932

4933
  // Reset buffer position for actual parsing
4934
  parser->bufferPos = 0;
651,385✔
4935

4936
  return TSDB_CODE_SUCCESS;
651,385✔
4937
}
4938

4939
static void csvParserDestroy(SCsvParser* parser) {
651,385✔
4940
  if (parser) {
651,385✔
4941
    taosMemoryFree(parser->buffer);
651,385✔
4942
    taosMemoryFree(parser->lineBuffer);
651,385✔
4943
    memset(parser, 0, sizeof(SCsvParser));
651,385✔
4944
  }
4945
}
651,385✔
4946

4947
static int32_t csvParserFillBuffer(SCsvParser* parser) {
27,144,680✔
4948
  if (!parser || parser->eof) {
27,144,680✔
4949
    return TSDB_CODE_SUCCESS;
4,702✔
4950
  }
4951

4952
  // Move remaining data to beginning of buffer
4953
  // Since this function is only called when bufferPos >= bufferLen,
4954
  // we can simplify by always resetting the buffer
4955
  parser->bufferLen = 0;
27,139,978✔
4956
  parser->bufferPos = 0;
27,139,978✔
4957

4958
  // Read more data
4959
  size_t spaceLeft = parser->bufferSize - parser->bufferLen;
27,139,978✔
4960
  if (spaceLeft > 0) {
27,139,978✔
4961
    int64_t bytesRead = taosReadFile(parser->pFile, parser->buffer + parser->bufferLen, spaceLeft);
27,139,978✔
4962
    if (bytesRead < 0) {
27,139,978✔
4963
      return TAOS_SYSTEM_ERROR(errno);
×
4964
    }
4965
    if (bytesRead == 0) {
27,139,978✔
4966
      parser->eof = true;
619,361✔
4967
    } else {
4968
      parser->bufferLen += bytesRead;
26,520,617✔
4969
    }
4970
  }
4971

4972
  return TSDB_CODE_SUCCESS;
27,139,978✔
4973
}
4974

4975
// Destroy saved CSV parser in SVnodeModifyOpStmt
4976
static void destroySavedCsvParser(SVnodeModifyOpStmt* pStmt) {
651,385✔
4977
  if (pStmt && pStmt->pCsvParser) {
651,385✔
4978
    csvParserDestroy(pStmt->pCsvParser);
651,385✔
4979
    taosMemoryFree(pStmt->pCsvParser);
651,385✔
4980
    pStmt->pCsvParser = NULL;
651,385✔
4981
  }
4982
}
651,385✔
4983

4984
static int32_t csvParserExpandLineBuffer(SCsvParser* parser, size_t requiredLen) {
2,147,483,647✔
4985
  if (!parser || requiredLen <= parser->lineBufferCapacity) {
2,147,483,647✔
4986
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
4987
  }
4988

4989
  size_t newCapacity = parser->lineBufferCapacity;
×
4990
  while (newCapacity < requiredLen) {
×
4991
    newCapacity *= 2;
×
4992
  }
4993

4994
  char* newLineBuffer = taosMemoryRealloc(parser->lineBuffer, newCapacity);
×
4995
  if (!newLineBuffer) {
×
4996
    return TSDB_CODE_OUT_OF_MEMORY;
×
4997
  }
4998

4999
  parser->lineBuffer = newLineBuffer;
×
5000
  parser->lineBufferCapacity = newCapacity;
×
5001
  return TSDB_CODE_SUCCESS;
×
5002
}
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