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

taosdata / TDengine / #3559

18 Dec 2024 12:59AM UTC coverage: 59.805% (+0.03%) from 59.778%
#3559

push

travis-ci

web-flow
Merge pull request #29187 from taosdata/merge/mainto3.0

merge: main to 3.0 branch

132705 of 287544 branches covered (46.15%)

Branch coverage included in aggregate %.

87 of 95 new or added lines in 19 files covered. (91.58%)

1132 existing lines in 133 files now uncovered.

209591 of 284807 relevant lines covered (73.59%)

8125235.78 hits per line

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

72.46
/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 "geosWrapper.h"
17
#include "parInsertUtil.h"
18
#include "parToken.h"
19
#include "scalar.h"
20
#include "tglobal.h"
21
#include "ttime.h"
22

23
typedef struct SInsertParseContext {
24
  SParseContext* pComCxt;
25
  SMsgBuf        msg;
26
  char           tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW];
27
  SBoundColInfo  tags;  // for stmt
28
  bool           missCache;
29
  bool           usingDuplicateTable;
30
  bool           forceUpdate;
31
  bool           needTableTagVal;
32
  bool           needRequest;  // whether or not request server
33
  bool           isStmtBind;   // whether is stmt bind
34
  bool           preCtbname;
35
} SInsertParseContext;
36

37
typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param);
38

39
static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
40
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;
41

42
static FORCE_INLINE bool isNullValue(int8_t dataType, SToken* pToken) {
43
  return TK_NULL == pToken->type ||
1,720,638,821✔
44
         (TK_NK_STRING == pToken->type && !IS_STR_DATA_TYPE(dataType) && IS_NULL_STR(pToken->z, pToken->n));
1,715,324,318!
45
}
46

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

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

56
  return pToken->type;
57
}
58

59
static int32_t skipInsertInto(const char** pSql, SMsgBuf* pMsg) {
9,385,645✔
60
  SToken token;
61
  NEXT_TOKEN(*pSql, token);
9,385,645✔
62
  if (TK_INSERT != token.type && TK_IMPORT != token.type) {
9,396,014!
63
    return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", token.z);
×
64
  }
65
  NEXT_TOKEN(*pSql, token);
9,396,014✔
66
  if (TK_INTO != token.type) {
9,394,437!
67
    return buildSyntaxErrMsg(pMsg, "keyword INTO is expected", token.z);
×
68
  }
69
  return TSDB_CODE_SUCCESS;
9,395,746✔
70
}
71

72
static int32_t skipParentheses(SInsertParseContext* pCxt, const char** pSql) {
418,833✔
73
  SToken  token;
74
  int32_t expectRightParenthesis = 1;
418,833✔
75
  while (1) {
76
    NEXT_TOKEN(*pSql, token);
9,142,028✔
77
    if (TK_NK_LP == token.type) {
9,142,032!
78
      ++expectRightParenthesis;
×
79
    } else if (TK_NK_RP == token.type && 0 == --expectRightParenthesis) {
9,142,032!
80
      break;
418,837✔
81
    }
82
    if (0 == token.n) {
8,723,195!
83
      return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL);
×
84
    }
85
  }
86
  return TSDB_CODE_SUCCESS;
418,837✔
87
}
88

89
static int32_t skipTableOptions(SInsertParseContext* pCxt, const char** pSql) {
3✔
90
  do {
×
91
    int32_t index = 0;
3✔
92
    SToken  token;
93
    NEXT_TOKEN_KEEP_SQL(*pSql, token, index);
3✔
94
    if (TK_TTL == token.type || TK_COMMENT == token.type) {
3!
95
      *pSql += index;
×
96
      NEXT_TOKEN_WITH_PREV(*pSql, token);
×
97
    } else {
98
      break;
99
    }
100
  } while (1);
101
  return TSDB_CODE_SUCCESS;
3✔
102
}
103

104
// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)
105
static int32_t ignoreUsingClause(SInsertParseContext* pCxt, const char** pSql) {
3✔
106
  int32_t code = TSDB_CODE_SUCCESS;
3✔
107
  SToken  token;
108
  NEXT_TOKEN(*pSql, token);
3✔
109

110
  NEXT_TOKEN(*pSql, token);
3✔
111
  if (TK_NK_LP == token.type) {
3✔
112
    code = skipParentheses(pCxt, pSql);
1✔
113
    if (TSDB_CODE_SUCCESS == code) {
1!
114
      NEXT_TOKEN(*pSql, token);
1✔
115
    }
116
  }
117

118
  // pSql -> TAGS (tag1_value, ...)
119
  if (TSDB_CODE_SUCCESS == code) {
3!
120
    if (TK_TAGS != token.type) {
3!
121
      code = buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
×
122
    } else {
123
      NEXT_TOKEN(*pSql, token);
3✔
124
    }
125
  }
126
  if (TSDB_CODE_SUCCESS == code) {
3!
127
    if (TK_NK_LP != token.type) {
3!
128
      code = buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
×
129
    } else {
130
      code = skipParentheses(pCxt, pSql);
3✔
131
    }
132
  }
133

134
  if (TSDB_CODE_SUCCESS == code) {
3!
135
    code = skipTableOptions(pCxt, pSql);
3✔
136
  }
137

138
  return code;
3✔
139
}
140

141
static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pDuplicate) {
42,332✔
142
  int32_t code = TSDB_CODE_SUCCESS;
42,332✔
143
  *pDuplicate = false;
42,332✔
144

145
  char tbFName[TSDB_TABLE_FNAME_LEN];
146
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
42,332✔
147
  if (TSDB_CODE_SUCCESS != code) {
42,332!
148
    return code;
×
149
  }
150
  STableMeta** pMeta = taosHashGet(pStmt->pSubTableHashObj, tbFName, strlen(tbFName));
42,332✔
151
  if (NULL != pMeta) {
42,332✔
152
    *pDuplicate = true;
3✔
153
    code = ignoreUsingClause(pCxt, &pStmt->pSql);
3✔
154
    if (TSDB_CODE_SUCCESS == code) {
3!
155
      return cloneTableMeta(*pMeta, &pStmt->pTableMeta);
3✔
156
    }
157
  }
158

159
  return code;
42,329✔
160
}
161

162
typedef enum { BOUND_TAGS, BOUND_COLUMNS, BOUND_ALL_AND_TBNAME } EBoundColumnsType;
163

164
static int32_t getTbnameSchemaIndex(STableMeta* pTableMeta) {
430,598✔
165
  return pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns;
430,598✔
166
}
167

168
// pStmt->pSql -> field1_name, ...)
169
static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, EBoundColumnsType boundColsType,
419,183✔
170
                                 STableMeta* pTableMeta, SBoundColInfo* pBoundInfo) {
171
  SSchema* pSchema = NULL;
419,183✔
172
  if (boundColsType == BOUND_TAGS) {
419,183✔
173
    pSchema = getTableTagSchema(pTableMeta);
219✔
174
  } else if (boundColsType == BOUND_COLUMNS) {
418,964✔
175
    pSchema = getTableColumnSchema(pTableMeta);
418,318✔
176
  } else {
177
    pSchema = pTableMeta->schema;
646✔
178
    if (pBoundInfo->numOfCols != getTbnameSchemaIndex(pTableMeta) + 1) {
646!
179
      return TSDB_CODE_PAR_INTERNAL_ERROR;
×
180
    }
181
  }
182
  int32_t tbnameSchemaIndex = getTbnameSchemaIndex(pTableMeta);
419,183✔
183

184
  bool* pUseCols = taosMemoryCalloc(pBoundInfo->numOfCols, sizeof(bool));
419,183!
185
  if (NULL == pUseCols) {
419,184!
186
    return terrno;
×
187
  }
188

189
  pBoundInfo->numOfBound = 0;
419,184✔
190
  pBoundInfo->hasBoundCols = true;
419,184✔
191

192
  bool    hasPK = pTableMeta->tableInfo.numOfPKs;
419,184✔
193
  int16_t numOfBoundPKs = 0;
419,184✔
194
  int16_t lastColIdx = -1;  // last column found
419,184✔
195
  int32_t code = TSDB_CODE_SUCCESS;
419,184✔
196
  while (TSDB_CODE_SUCCESS == code) {
9,144,727✔
197
    SToken token;
198
    NEXT_TOKEN(*pSql, token);
9,144,722✔
199

200
    if (TK_NK_RP == token.type) {
9,144,711✔
201
      break;
419,178✔
202
    }
203

204
    char tmpTokenBuf[TSDB_COL_NAME_LEN + 2] = {0};  // used for deleting Escape character backstick(`)
8,725,533✔
205
    strncpy(tmpTokenBuf, token.z, token.n);
8,725,533✔
206
    token.z = tmpTokenBuf;
8,725,533✔
207
    token.n = strdequote(token.z);
8,725,533✔
208

209
    if (boundColsType == BOUND_ALL_AND_TBNAME && token.n == strlen("tbname") && (strcasecmp(token.z, "tbname") == 0)) {
8,725,542✔
210
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = tbnameSchemaIndex;
645✔
211
      pUseCols[tbnameSchemaIndex] = true;
645✔
212
      ++pBoundInfo->numOfBound;
645✔
213
      continue;
645✔
214
    }
215
    int16_t t = lastColIdx + 1;
8,724,897✔
216
    int16_t end = (boundColsType == BOUND_ALL_AND_TBNAME) ? (pBoundInfo->numOfCols - 1) : pBoundInfo->numOfCols;
8,724,897✔
217
    int16_t index = insFindCol(&token, t, end, pSchema);
8,724,897✔
218
    if (index < 0 && t > 0) {
8,724,898!
219
      index = insFindCol(&token, 0, t, pSchema);
10,971✔
220
    }
221
    if (index < 0) {
8,724,897✔
222
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z);
4✔
223
    } else if (pUseCols[index]) {
8,724,893!
224
      code = buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z);
×
225
    } else {
226
      lastColIdx = index;
8,724,893✔
227
      pUseCols[index] = true;
8,724,893✔
228
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = index;
8,724,893✔
229
      ++pBoundInfo->numOfBound;
8,724,893✔
230
      if (hasPK && (pSchema[index].flags & COL_IS_KEY)) ++numOfBoundPKs;
8,724,893✔
231
    }
232
  }
233

234
  if (TSDB_CODE_SUCCESS == code && (BOUND_TAGS != boundColsType)) {
419,183✔
235
    if (!pUseCols[0]) {
418,959✔
236
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary timestamp column should not be null");
5✔
237
    }
238
    if (numOfBoundPKs != pTableMeta->tableInfo.numOfPKs) {
418,959!
239
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary key column should not be none");
×
240
    }
241
  }
242
  if (TSDB_CODE_SUCCESS == code && (BOUND_ALL_AND_TBNAME == boundColsType) && !pUseCols[tbnameSchemaIndex]) {
419,183✔
243
    code = buildInvalidOperationMsg(&pCxt->msg, "tbname column should not be null");
1✔
244
  }
245
  taosMemoryFree(pUseCols);
419,183!
246

247
  return code;
419,183✔
248
}
249

250
static int32_t parseTimestampOrInterval(const char** end, SToken* pToken, int16_t timePrec, int64_t* ts, int64_t* interval,
373,138,863✔
251
                                    SMsgBuf* pMsgBuf, bool* isTs, timezone_t tz) {
252
  if (pToken->type == TK_NOW) {
373,138,863✔
253
    *isTs = true;
12,008,129✔
254
    *ts = taosGetTimestamp(timePrec);
24,016,258✔
255
  } else if (pToken->type == TK_TODAY) {
361,130,734✔
256
    *isTs = true;
203✔
257
    *ts = taosGetTimestampToday(timePrec, tz);
203✔
258
  } else if (pToken->type == TK_NK_INTEGER) {
361,130,531!
259
    *isTs = true;
362,289,793✔
260
    if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, ts)) {
362,289,793✔
261
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
8✔
262
    }
263
  } else if (pToken->type == TK_NK_VARIABLE) {
×
264
    char unit = 0;
148,580✔
265
    *isTs = false;
148,580✔
266
    if (parseAbsoluteDuration(pToken->z, pToken->n, interval, &unit, timePrec) != TSDB_CODE_SUCCESS) {
148,580✔
267
      return TSDB_CODE_TSC_INVALID_OPERATION;
7✔
268
    }
269
  } else {  // parse the RFC-3339/ISO-8601 timestamp format string
270
    *isTs = true;
×
271
    if (taosParseTime(pToken->z, ts, pToken->n, timePrec, tz) != TSDB_CODE_SUCCESS) {
×
272
      if ((pToken->n == 0) ||
1,190,248✔
273
          (pToken->type != TK_NK_STRING && pToken->type != TK_NK_HEX && pToken->type != TK_NK_BIN)) {
4,307✔
274
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
1,185,945✔
275
      }
276
      if (IS_NOW_STR(pToken->z, pToken->n)) {
4,303!
277
        *isTs = true;
5✔
278
        *ts = taosGetTimestamp(timePrec);
10!
279
      } else if (IS_TODAY_STR(pToken->z, pToken->n)) {
4,298!
280
        *isTs = true;
5✔
281
        *ts = taosGetTimestampToday(timePrec, tz);
5✔
282
      } else if (TSDB_CODE_SUCCESS == toIntegerPure(pToken->z, pToken->n, 10, ts)) {
4,293✔
283
        *isTs = true;
4,271✔
284
      } else {
285
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
22✔
286
      }
287
    }
288
  }
289

290
  return TSDB_CODE_SUCCESS;
374,014,440✔
291
}
292

293
static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf, timezone_t tz) {
374,107,429✔
294
  int32_t     index = 0, i = 0;
374,107,429✔
295
  int64_t     interval = 0, tempInterval = 0;
374,107,429✔
296
  int64_t     ts = 0, tempTs = 0;
374,107,429✔
297
  bool        firstIsTS = false, secondIsTs = false;
374,107,429✔
298
  const char* pTokenEnd = *end;
374,107,429✔
299

300
  if (TSDB_CODE_SUCCESS !=
373,998,115!
301
      parseTimestampOrInterval(&pTokenEnd, pToken, timePrec, &ts, &interval, pMsgBuf, &firstIsTS, tz)) {
374,107,429✔
UNCOV
302
    return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
303
  }
304

305
  if (firstIsTS) {
374,493,830✔
306
    *time = ts;
374,170,019✔
307
  }
308

309
  for (int k = pToken->n; pToken->z[k] != '\0'; k++) {
374,987,480!
310
    if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue;
375,294,317!
311
    if (pToken->z[k] == '(') {  // for insert NOW()/TODAY()
374,825,090✔
312
      if (pToken->z[k + 1] == ')') {
24,423✔
313
        *end = pTokenEnd = &pToken->z[k + 2];
24,422✔
314
        ++k;
24,422✔
315
        continue;
24,422✔
316
      } else {
317
        char nc = pToken->z[k + 1];
1✔
318
        while (nc == ' ' || nc == '\t' || nc == '\n' || nc == '\r' || nc == '\f') {
2!
319
          nc = pToken->z[(++k) + 1];
1✔
320
        }
321
        if (nc == ')') {
1!
322
          *end = pTokenEnd = &pToken->z[k + 2];
1✔
323
          ++k;
1✔
324
          continue;
1✔
325
        }
326
      }
327
    }
328
    if (pToken->z[k] == ',') {
374,800,667✔
329
      *end = pTokenEnd;
361,327,440✔
330
      if (!firstIsTS) {
361,327,440!
331
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
332
      }
333
      *time = ts;
361,327,440✔
334
      return TSDB_CODE_SUCCESS;
361,327,440✔
335
    }
336
    break;
13,473,227✔
337
  }
338

339
  while (pTokenEnd[i] != '\0') {
13,213,056✔
340
    if (pTokenEnd[i] == ' ' || pTokenEnd[i] == '\t') {
12,733,213!
341
      i++;
46,666✔
342
      continue;
46,666✔
343
    } else if (pTokenEnd[i] == ',' || pTokenEnd[i] == ')') {
12,686,547✔
344
      *end = pTokenEnd + i;
12,537,661✔
345
      if (!firstIsTS) {
12,537,661!
346
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
347
      }
348
      *time = ts;
12,537,661✔
349
      return TSDB_CODE_SUCCESS;
12,537,661✔
350
    } else {
351
      break;
352
    }
353
  }
354
  pTokenEnd = pTokenEnd + i;
628,729✔
355

356
  index = 0;
628,729✔
357
  SToken token = tStrGetToken(pTokenEnd, &index, false, NULL);
628,729✔
358

359
  if (token.type == TK_NK_MINUS || token.type == TK_NK_PLUS) {
155,215✔
360
    pTokenEnd += index;
148,580✔
361
    index = 0;
148,580✔
362
    SToken valueToken = tStrGetToken(pTokenEnd, &index, false, NULL);
148,580✔
363
    pTokenEnd += index;
148,580✔
364
    char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW];
365
    if (TK_NK_STRING == valueToken.type) {
148,580!
366
      if (valueToken.n >= TSDB_MAX_BYTES_PER_ROW) {
×
367
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", valueToken.z);
148,548✔
368
      }
369
      int32_t len = trimString(valueToken.z, valueToken.n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
×
370
      valueToken.z = tmpTokenBuf;
×
371
      valueToken.n = len;
×
372
    }
373

374
    if (TSDB_CODE_SUCCESS !=
148,580✔
375
        parseTimestampOrInterval(&pTokenEnd, &valueToken, timePrec, &tempTs, &tempInterval, pMsgBuf, &secondIsTs, tz)) {
148,580✔
376
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
7✔
377
    }
378

379
    if (valueToken.n < 2) {
148,573!
380
      return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", token.z);
×
381
    }
382

383
    if (secondIsTs) {
148,573!
384
      // not support operator between tow timestamp, such as today() + now()
385
      if (firstIsTS) {
×
386
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
387
      }
388
      ts = tempTs;
×
389
    } else {
390
      // not support operator between tow interval, such as 2h + 3s
391
      if (!firstIsTS) {
148,573!
392
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
393
      }
394
      interval = tempInterval;
148,573✔
395
    }
396
    if (token.type == TK_NK_MINUS) {
148,573✔
397
      // not support interval - ts,such as 2h - today()
398
      if (secondIsTs) {
11,882!
399
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
400
      }
401
      *time = ts - interval;
11,882✔
402
    } else {
403
      *time = ts + interval;
136,691✔
404
    }
405

406
    for (int k = valueToken.n; valueToken.z[k] != '\0'; k++) {
198,492✔
407
      if (valueToken.z[k] == ' ' || valueToken.z[k] == '\t') continue;
198,460!
408
      if (valueToken.z[k] == '(' && valueToken.z[k + 1] == ')') {  // for insert NOW()/TODAY()
148,541!
409
        *end = pTokenEnd = &valueToken.z[k + 2];
×
410
        k++;
×
411
        continue;
×
412
      }
413
      if (valueToken.z[k] == ',' || valueToken.z[k] == ')') {
148,541✔
414
        *end = pTokenEnd;
148,539✔
415
        return TSDB_CODE_SUCCESS;
148,539✔
416
      }
417
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
2✔
418
    }
419
  }
420

421
  *end = pTokenEnd;
6,667✔
422
  return TSDB_CODE_SUCCESS;
6,667✔
423
}
424

425
// need to call geosFreeBuffer(*output) later
426
static int parseGeometry(SToken* pToken, unsigned char** output, size_t* size) {
5,201✔
427
  int32_t code = TSDB_CODE_FAILED;
5,201✔
428

429
  //[ToDo] support to parse WKB as well as WKT
430
  if (pToken->type == TK_NK_STRING) {
5,201✔
431
    code = initCtxGeomFromText();
5,181✔
432
    if (code != TSDB_CODE_SUCCESS) {
5,181!
433
      return code;
×
434
    }
435

436
    code = doGeomFromText(pToken->z, output, size);
5,181✔
437
    if (code != TSDB_CODE_SUCCESS) {
5,181!
438
      return code;
×
439
    }
440
  }
441

442
  return code;
5,201✔
443
}
444

445
static int32_t parseVarbinary(SToken* pToken, uint8_t** pData, uint32_t* nData, int32_t bytes) {
658,050✔
446
  if (pToken->type != TK_NK_STRING) {
658,050✔
447
    return TSDB_CODE_PAR_INVALID_VARBINARY;
36✔
448
  }
449

450
  if (isHex(pToken->z + 1, pToken->n - 2)) {
658,014✔
451
    if (!isValidateHex(pToken->z + 1, pToken->n - 2)) {
4,811!
452
      return TSDB_CODE_PAR_INVALID_VARBINARY;
×
453
    }
454

455
    void*    data = NULL;
4,811✔
456
    uint32_t size = 0;
4,811✔
457
    if (taosHex2Ascii(pToken->z + 1, pToken->n - 2, &data, &size) < 0) {
4,811!
458
      return TSDB_CODE_OUT_OF_MEMORY;
×
459
    }
460

461
    if (size + VARSTR_HEADER_SIZE > bytes) {
4,811!
462
      taosMemoryFree(data);
×
463
      return TSDB_CODE_PAR_VALUE_TOO_LONG;
×
464
    }
465
    *pData = data;
4,811✔
466
    *nData = size;
4,811✔
467
  } else {
468
    *pData = taosMemoryCalloc(1, pToken->n);
653,203!
469
    if (!pData) return terrno;
653,203!
470
    int32_t len = trimString(pToken->z, pToken->n, *pData, pToken->n);
653,203✔
471
    *nData = len;
653,203✔
472

473
    if (*nData + VARSTR_HEADER_SIZE > bytes) {
653,203!
474
      return TSDB_CODE_PAR_VALUE_TOO_LONG;
×
475
    }
476
  }
477
  return TSDB_CODE_SUCCESS;
658,014✔
478
}
479

480
static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val,
295,210✔
481
                             SMsgBuf* pMsgBuf, timezone_t tz, void *charsetCxt) {
482
  int64_t  iv;
483
  uint64_t uv;
484
  char*    endptr = NULL;
295,210✔
485
  int32_t  code = TSDB_CODE_SUCCESS;
295,210✔
486

487
#if 0
488
  if (isNullValue(pSchema->type, pToken)) {
489
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
490
      return buildSyntaxErrMsg(pMsgBuf, "Primary timestamp column can not be null", pToken->z);
491
    }
492

493
    return TSDB_CODE_SUCCESS;
494
  }
495
#endif
496

497
  //  strcpy(val->colName, pSchema->name);
498
  val->cid = pSchema->colId;
295,210✔
499
  val->type = pSchema->type;
295,210✔
500

501
  switch (pSchema->type) {
295,210!
502
    case TSDB_DATA_TYPE_BOOL: {
14,785✔
503
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
14,785✔
504
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
9,196!
505
          *(int8_t*)(&val->i64) = TRUE_VALUE;
8,521✔
506
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
675!
507
          *(int8_t*)(&val->i64) = FALSE_VALUE;
632✔
508
        } else if (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv)) {
43✔
509
          *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
33✔
510
        } else {
511
          return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
10✔
512
        }
513
      } else if (pToken->type == TK_NK_INTEGER) {
5,589✔
514
        *(int8_t*)(&val->i64) = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
5,557✔
515
      } else if (pToken->type == TK_NK_FLOAT) {
32✔
516
        *(int8_t*)(&val->i64) = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
14!
517
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
30!
518
                 (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv))) {
12✔
519
        *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
12✔
520
      } else {
521
        return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
6✔
522
      }
523
      break;
14,769✔
524
    }
525

526
    case TSDB_DATA_TYPE_TINYINT: {
8,833✔
527
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
8,833✔
528
      if (TSDB_CODE_SUCCESS != code) {
8,834✔
529
        return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z);
13✔
530
      } else if (!IS_VALID_TINYINT(iv)) {
8,821✔
531
        return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z);
10✔
532
      }
533

534
      *(int8_t*)(&val->i64) = iv;
8,811✔
535
      break;
8,811✔
536
    }
537

538
    case TSDB_DATA_TYPE_UTINYINT: {
1,055✔
539
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,055✔
540
      if (TSDB_CODE_SUCCESS != code) {
1,055✔
541
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z);
1✔
542
      } else if (uv > UINT8_MAX) {
1,054✔
543
        return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z);
1✔
544
      }
545
      *(uint8_t*)(&val->i64) = uv;
1,053✔
546
      break;
1,053✔
547
    }
548

549
    case TSDB_DATA_TYPE_SMALLINT: {
10,683✔
550
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
10,683✔
551
      if (TSDB_CODE_SUCCESS != code) {
10,683✔
552
        return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z);
13✔
553
      } else if (!IS_VALID_SMALLINT(iv)) {
10,670✔
554
        return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z);
10✔
555
      }
556
      *(int16_t*)(&val->i64) = iv;
10,660✔
557
      break;
10,660✔
558
    }
559

560
    case TSDB_DATA_TYPE_USMALLINT: {
1,122✔
561
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,122✔
562
      if (TSDB_CODE_SUCCESS != code) {
1,122✔
563
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z);
1✔
564
      } else if (uv > UINT16_MAX) {
1,121✔
565
        return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z);
1✔
566
      }
567
      *(uint16_t*)(&val->i64) = uv;
1,120✔
568
      break;
1,120✔
569
    }
570

571
    case TSDB_DATA_TYPE_INT: {
93,308✔
572
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
93,308✔
573
      if (TSDB_CODE_SUCCESS != code) {
93,312✔
574
        return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z);
15✔
575
      } else if (!IS_VALID_INT(iv)) {
93,297!
576
        return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z);
2✔
577
      }
578
      *(int32_t*)(&val->i64) = iv;
93,295✔
579
      break;
93,295✔
580
    }
581

582
    case TSDB_DATA_TYPE_UINT: {
896✔
583
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
896✔
584
      if (TSDB_CODE_SUCCESS != code) {
896✔
585
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z);
21✔
586
      } else if (uv > UINT32_MAX) {
875✔
587
        return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z);
2✔
588
      }
589
      *(uint32_t*)(&val->i64) = uv;
873✔
590
      break;
873✔
591
    }
592

593
    case TSDB_DATA_TYPE_BIGINT: {
31,453✔
594
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
31,453✔
595
      if (TSDB_CODE_SUCCESS != code) {
31,453✔
596
        return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z);
26✔
597
      }
598
      val->i64 = iv;
31,427✔
599
      break;
31,427✔
600
    }
601

602
    case TSDB_DATA_TYPE_UBIGINT: {
648✔
603
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
648✔
604
      if (TSDB_CODE_SUCCESS != code) {
648✔
605
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z);
6✔
606
      }
607
      *(uint64_t*)(&val->i64) = uv;
642✔
608
      break;
642✔
609
    }
610

611
    case TSDB_DATA_TYPE_FLOAT: {
7,141✔
612
      double dv;
613
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
7,141✔
614
      if (TSDB_CODE_SUCCESS != code) {
7,141✔
615
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
28✔
616
      }
617
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
7,125!
618
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
12✔
619
      }
620
      *(float*)(&val->i64) = dv;
7,113✔
621
      break;
7,113✔
622
    }
623

624
    case TSDB_DATA_TYPE_DOUBLE: {
32,399✔
625
      double dv;
626
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
32,399✔
627
      if (TSDB_CODE_SUCCESS != code) {
32,399✔
628
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
27✔
629
      }
630
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
32,372!
631
        return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
×
632
      }
633

634
      *(double*)(&val->i64) = dv;
32,372✔
635
      break;
32,372✔
636
    }
637

638
    case TSDB_DATA_TYPE_BINARY: {
49,603✔
639
      // Too long values will raise the invalid sql error message
640
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
49,603✔
641
        return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
10✔
642
      }
643
      val->pData = taosStrdup(pToken->z);
49,593!
644
      if (!val->pData) {
49,595!
645
        return terrno;
×
646
      }
647
      val->nData = pToken->n;
49,595✔
648
      break;
49,595✔
649
    }
650
    case TSDB_DATA_TYPE_VARBINARY: {
120✔
651
      code = parseVarbinary(pToken, &val->pData, &val->nData, pSchema->bytes);
120✔
652
      if (code != TSDB_CODE_SUCCESS) {
120✔
653
        return generateSyntaxErrMsg(pMsgBuf, code, pSchema->name);
24✔
654
      }
655
      break;
96✔
656
    }
657
    case TSDB_DATA_TYPE_GEOMETRY: {
102✔
658
      unsigned char* output = NULL;
102✔
659
      size_t         size = 0;
102✔
660

661
      code = parseGeometry(pToken, &output, &size);
102✔
662
      if (code != TSDB_CODE_SUCCESS) {
102✔
663
        code = buildSyntaxErrMsg(pMsgBuf, getGeosErrMsg(code), pToken->z);
20✔
664
      } else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
82!
665
        // Too long values will raise the invalid sql error message
666
        code = generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
667
      } else {
668
        val->pData = taosMemoryMalloc(size);
82!
669
        if (NULL == val->pData) {
82!
670
          code = terrno;
×
671
        } else {
672
          memcpy(val->pData, output, size);
82✔
673
          val->nData = size;
82✔
674
        }
675
      }
676

677
      geosFreeBuffer(output);
102✔
678
      break;
102✔
679
    }
680

681
    case TSDB_DATA_TYPE_NCHAR: {
36,599✔
682
      int32_t output = 0;
36,599✔
683
      int64_t realLen = pToken->n << 2;
36,599✔
684
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
36,599✔
685
      void* p = taosMemoryMalloc(realLen);
36,599!
686
      if (p == NULL) {
36,599!
687
        return terrno;
3✔
688
      }
689
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)(p), realLen, &output, charsetCxt)) {
36,599✔
690
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
3!
691
          taosMemoryFree(p);
3!
692
          return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
3✔
693
        }
694
        char buf[512] = {0};
×
695
        snprintf(buf, tListLen(buf), " taosMbsToUcs4 error:%s %d %d", strerror(terrno), errno, EILSEQ);
×
696
        taosMemoryFree(p);
×
697
        return buildSyntaxErrMsg(pMsgBuf, buf, pToken->z);
×
698
      }
699
      val->pData = p;
36,596✔
700
      val->nData = output;
36,596✔
701
      break;
36,596✔
702
    }
703
    case TSDB_DATA_TYPE_TIMESTAMP: {
6,470✔
704
      if (parseTime(end, pToken, timePrec, &iv, pMsgBuf, tz) != TSDB_CODE_SUCCESS) {
6,470✔
705
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z);
18✔
706
      }
707

708
      val->i64 = iv;
6,452✔
709
      break;
6,452✔
710
    }
711
  }
712

713
  return code;
294,969✔
714
}
715

716
// input pStmt->pSql:  [(tag1_name, ...)] TAGS (tag1_value, ...) ...
717
// output pStmt->pSql: TAGS (tag1_value, ...) ...
718
static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
42,318✔
719
  int32_t code = insInitBoundColsInfo(getNumOfTags(pStmt->pTableMeta), &pCxt->tags);
42,318✔
720
  if (TSDB_CODE_SUCCESS != code) {
42,318!
721
    return code;
×
722
  }
723

724
  SToken  token;
725
  int32_t index = 0;
42,318✔
726
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
42,318✔
727
  if (TK_NK_LP != token.type) {
42,318✔
728
    return TSDB_CODE_SUCCESS;
42,099✔
729
  }
730

731
  pStmt->pSql += index;
219✔
732
  return parseBoundColumns(pCxt, &pStmt->pSql, BOUND_TAGS, pStmt->pTableMeta, &pCxt->tags);
219✔
733
}
734

735
int32_t parseTagValue(SMsgBuf* pMsgBuf, const char** pSql, uint8_t precision, SSchema* pTagSchema, SToken* pToken,
295,880✔
736
                      SArray* pTagName, SArray* pTagVals, STag** pTag, timezone_t tz, void *charsetCxt) {
737
  bool isNull = isNullValue(pTagSchema->type, pToken);
295,880✔
738
  if (!isNull && pTagName) {
295,880✔
739
    if (NULL == taosArrayPush(pTagName, pTagSchema->name)) {
589,441!
740
      return terrno;
×
741
    }
742
  }
743

744
  if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
295,867✔
745
    if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
248✔
746
      return buildSyntaxErrMsg(pMsgBuf, "json string too long than 4095", pToken->z);
3✔
747
    }
748

749
    if (isNull) {
245✔
750
      return tTagNew(pTagVals, 1, true, pTag);
45✔
751
    } else {
752
      return parseJsontoTagData(pToken->z, pTagVals, pTag, pMsgBuf, charsetCxt);
200✔
753
    }
754
  }
755

756
  if (isNull) return 0;
295,619✔
757

758
  STagVal val = {0};
295,212✔
759
  int32_t code = parseTagToken(pSql, pToken, pTagSchema, precision, &val, pMsgBuf, tz, charsetCxt);
295,212✔
760
  if (TSDB_CODE_SUCCESS == code) {
295,227✔
761
    if (NULL == taosArrayPush(pTagVals, &val)) {
294,946!
762
      code = terrno;
×
763
    }
764
  }
765

766
  return code;
295,227✔
767
}
768

769
static int32_t buildCreateTbReq(SVnodeModifyOpStmt* pStmt, STag* pTag, SArray* pTagName) {
42,208✔
770
  if (pStmt->pCreateTblReq) {
42,208!
771
    tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
×
772
    taosMemoryFreeClear(pStmt->pCreateTblReq);
×
773
  }
774
  pStmt->pCreateTblReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
42,208!
775
  if (NULL == pStmt->pCreateTblReq) {
42,208!
776
    return terrno;
×
777
  }
778
  return insBuildCreateTbReq(pStmt->pCreateTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid,
42,208✔
779
                             pStmt->usingTableName.tname, pTagName, pStmt->pTableMeta->tableInfo.numOfTags,
42,208✔
780
                             TSDB_DEFAULT_TABLE_TTL);
781
}
782

783
int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf, int8_t type) {
1,725,774,783✔
784
  if (pToken->type == TK_NK_QUESTION) {
1,725,774,783!
785
    return buildInvalidOperationMsg(pMsgBuf, "insert into super table syntax is not supported for stmt");
×
786
  }
787
  if ((pToken->type != TK_NOW && pToken->type != TK_TODAY && pToken->type != TK_NK_INTEGER &&
1,725,774,783✔
788
       pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL &&
427,105,366✔
789
       pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && pToken->type != TK_NK_BIN &&
12,526,983!
790
       pToken->type != TK_NK_VARIABLE) ||
75✔
791
      (pToken->n == 0) || (pToken->type == TK_NK_RP)) {
1,725,774,718!
792
    return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z);
×
793
  }
794

795
  // Remove quotation marks
796
  if (TK_NK_STRING == pToken->type && type != TSDB_DATA_TYPE_VARBINARY) {
1,729,214,963✔
797
    if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) {
118,691,370!
798
      return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z);
×
799
    }
800

801
    int32_t len = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
118,691,370✔
802
    pToken->z = tmpTokenBuf;
120,201,683✔
803
    pToken->n = len;
120,201,683✔
804
  }
805

806
  return TSDB_CODE_SUCCESS;
1,730,725,276✔
807
}
808

809
typedef struct SRewriteTagCondCxt {
810
  SArray* pTagVals;
811
  SArray* pTagName;
812
  int32_t code;
813
} SRewriteTagCondCxt;
814

815
static int32_t rewriteTagCondColumnImpl(STagVal* pVal, SNode** pNode) {
5✔
816
  SValueNode* pValue = NULL;
5✔
817
  int32_t     code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pValue);
5✔
818
  if (NULL == pValue) {
5!
819
    return code;
×
820
  }
821

822
  pValue->node.resType = ((SColumnNode*)*pNode)->node.resType;
5✔
823
  nodesDestroyNode(*pNode);
5✔
824
  *pNode = (SNode*)pValue;
5✔
825

826
  switch (pVal->type) {
5!
827
    case TSDB_DATA_TYPE_BOOL:
×
828
      pValue->datum.b = *(int8_t*)(&pVal->i64);
×
829
      *(bool*)&pValue->typeData = pValue->datum.b;
×
830
      break;
×
831
    case TSDB_DATA_TYPE_TINYINT:
×
832
      pValue->datum.i = *(int8_t*)(&pVal->i64);
×
833
      *(int8_t*)&pValue->typeData = pValue->datum.i;
×
834
      break;
×
835
    case TSDB_DATA_TYPE_SMALLINT:
×
836
      pValue->datum.i = *(int16_t*)(&pVal->i64);
×
837
      *(int16_t*)&pValue->typeData = pValue->datum.i;
×
838
      break;
×
839
    case TSDB_DATA_TYPE_INT:
5✔
840
      pValue->datum.i = *(int32_t*)(&pVal->i64);
5✔
841
      *(int32_t*)&pValue->typeData = pValue->datum.i;
5✔
842
      break;
5✔
843
    case TSDB_DATA_TYPE_BIGINT:
×
844
      pValue->datum.i = pVal->i64;
×
845
      pValue->typeData = pValue->datum.i;
×
846
      break;
×
847
    case TSDB_DATA_TYPE_FLOAT:
×
848
      pValue->datum.d = *(float*)(&pVal->i64);
×
849
      *(float*)&pValue->typeData = pValue->datum.d;
×
850
      break;
×
851
    case TSDB_DATA_TYPE_DOUBLE:
×
852
      pValue->datum.d = *(double*)(&pVal->i64);
×
853
      *(double*)&pValue->typeData = pValue->datum.d;
×
854
      break;
×
855
    case TSDB_DATA_TYPE_VARCHAR:
×
856
    case TSDB_DATA_TYPE_VARBINARY:
857
    case TSDB_DATA_TYPE_NCHAR:
858
      pValue->datum.p = taosMemoryCalloc(1, pVal->nData + VARSTR_HEADER_SIZE);
×
859
      if (NULL == pValue->datum.p) {
×
860
        return terrno;
×
861
      }
862
      varDataSetLen(pValue->datum.p, pVal->nData);
×
863
      memcpy(varDataVal(pValue->datum.p), pVal->pData, pVal->nData);
×
864
      break;
×
865
    case TSDB_DATA_TYPE_TIMESTAMP:
×
866
      pValue->datum.i = pVal->i64;
×
867
      pValue->typeData = pValue->datum.i;
×
868
      break;
×
869
    case TSDB_DATA_TYPE_UTINYINT:
×
870
      pValue->datum.i = *(uint8_t*)(&pVal->i64);
×
871
      *(uint8_t*)&pValue->typeData = pValue->datum.i;
×
872
      break;
×
873
    case TSDB_DATA_TYPE_USMALLINT:
×
874
      pValue->datum.i = *(uint16_t*)(&pVal->i64);
×
875
      *(uint16_t*)&pValue->typeData = pValue->datum.i;
×
876
      break;
×
877
    case TSDB_DATA_TYPE_UINT:
×
878
      pValue->datum.i = *(uint32_t*)(&pVal->i64);
×
879
      *(uint32_t*)&pValue->typeData = pValue->datum.i;
×
880
      break;
×
881
    case TSDB_DATA_TYPE_UBIGINT:
×
882
      pValue->datum.i = *(uint64_t*)(&pVal->i64);
×
883
      *(uint64_t*)&pValue->typeData = pValue->datum.i;
×
884
      break;
×
885
    case TSDB_DATA_TYPE_JSON:
×
886
    case TSDB_DATA_TYPE_DECIMAL:
887
    case TSDB_DATA_TYPE_BLOB:
888
    case TSDB_DATA_TYPE_MEDIUMBLOB:
889
    default:
890
      return TSDB_CODE_FAILED;
×
891
  }
892
  return TSDB_CODE_SUCCESS;
5✔
893
}
894

895
static int32_t rewriteTagCondColumn(SArray* pTagVals, SArray* pTagName, SNode** pNode) {
5✔
896
  SColumnNode* pCol = (SColumnNode*)*pNode;
5✔
897
  int32_t      ntags = taosArrayGetSize(pTagName);
5✔
898
  for (int32_t i = 0; i < ntags; ++i) {
5!
899
    char* pTagColName = taosArrayGet(pTagName, i);
5✔
900
    if (0 == strcmp(pTagColName, pCol->colName)) {
5!
901
      return rewriteTagCondColumnImpl(taosArrayGet(pTagVals, i), pNode);
5✔
902
    }
903
  }
904
  return TSDB_CODE_PAR_PERMISSION_DENIED;
×
905
}
906

907
static EDealRes rewriteTagCond(SNode** pNode, void* pContext) {
15✔
908
  if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
15✔
909
    SRewriteTagCondCxt* pCxt = pContext;
5✔
910
    pCxt->code = rewriteTagCondColumn(pCxt->pTagVals, pCxt->pTagName, pNode);
5✔
911
    return (TSDB_CODE_SUCCESS == pCxt->code ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
5!
912
  }
913
  return DEAL_RES_CONTINUE;
10✔
914
}
915

916
static int32_t setTagVal(SArray* pTagVals, SArray* pTagName, SNode* pCond) {
5✔
917
  SRewriteTagCondCxt cxt = {.code = TSDB_CODE_SUCCESS, .pTagVals = pTagVals, .pTagName = pTagName};
5✔
918
  nodesRewriteExpr(&pCond, rewriteTagCond, &cxt);
5✔
919
  return cxt.code;
5✔
920
}
921

922
static int32_t checkTagCondResult(SNode* pResult) {
5✔
923
  return (QUERY_NODE_VALUE == nodeType(pResult) && ((SValueNode*)pResult)->datum.b) ? TSDB_CODE_SUCCESS
5✔
924
                                                                                    : TSDB_CODE_PAR_PERMISSION_DENIED;
10!
925
}
926

927
static int32_t checkSubtablePrivilege(SArray* pTagVals, SArray* pTagName, SNode** pCond) {
5✔
928
  int32_t code = setTagVal(pTagVals, pTagName, *pCond);
5✔
929
  if (TSDB_CODE_SUCCESS == code) {
5!
930
    code = scalarCalculateConstants(*pCond, pCond);
5✔
931
  }
932
  if (TSDB_CODE_SUCCESS == code) {
5!
933
    code = checkTagCondResult(*pCond);
5✔
934
  }
935
  NODES_DESTORY_NODE(*pCond);
5✔
936
  return code;
5✔
937
}
938

939
// pSql -> tag1_value, ...)
940
static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
42,318✔
941
  int32_t  code = TSDB_CODE_SUCCESS;
42,318✔
942
  SSchema* pSchema = getTableTagSchema(pStmt->pTableMeta);
42,318✔
943
  SArray*  pTagVals = NULL;
42,318✔
944
  SArray*  pTagName = NULL;
42,318✔
945
  uint8_t  precision = pStmt->pTableMeta->tableInfo.precision;
42,318✔
946
  SToken   token;
947
  bool     isParseBindParam = false;
42,318✔
948
  bool     isJson = false;
42,318✔
949
  STag*    pTag = NULL;
42,318✔
950

951
  if (!(pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal))) ||
84,636!
952
      !(pTagName = taosArrayInit(pCxt->tags.numOfBound, TSDB_COL_NAME_LEN))) {
42,318✔
953
    code = terrno;
×
954
    goto _exit;
×
955
  }
956

957
  for (int i = 0; TSDB_CODE_SUCCESS == code && i < pCxt->tags.numOfBound; ++i) {
112,279✔
958
    NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
69,961✔
959

960
    if (token.type == TK_NK_QUESTION) {
69,963!
961
      isParseBindParam = true;
×
962
      if (NULL == pCxt->pComCxt->pStmtCb) {
×
963
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", token.z);
×
964
        break;
×
965
      }
966

967
      continue;
×
968
    }
969

970
    if (isParseBindParam) {
69,963!
971
      code = buildInvalidOperationMsg(&pCxt->msg, "no mix usage for ? and tag values");
×
972
      break;
×
973
    }
974

975
    SSchema* pTagSchema = &pSchema[pCxt->tags.pColIndex[i]];
69,963✔
976
    isJson = pTagSchema->type == TSDB_DATA_TYPE_JSON;
69,963✔
977
    code = checkAndTrimValue(&token, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
69,963✔
978
    if (TSDB_CODE_SUCCESS == code && TK_NK_VARIABLE == token.type) {
69,960!
979
      code = buildSyntaxErrMsg(&pCxt->msg, "not expected tags values ", token.z);
×
980
    }
981
    if (TSDB_CODE_SUCCESS == code) {
69,960✔
982
      code = parseTagValue(&pCxt->msg, &pStmt->pSql, precision, pTagSchema, &token, pTagName, pTagVals, &pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
69,945✔
983
    }
984
  }
985

986
  if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pTagCond) {
42,318✔
987
    code = checkSubtablePrivilege(pTagVals, pTagName, &pStmt->pTagCond);
2✔
988
  }
989

990
  if (TSDB_CODE_SUCCESS == code && !isParseBindParam && !isJson) {
42,318!
991
    code = tTagNew(pTagVals, 1, false, &pTag);
42,132✔
992
  }
993

994
  if (TSDB_CODE_SUCCESS == code && !isParseBindParam) {
42,318!
995
    code = buildCreateTbReq(pStmt, pTag, pTagName);
42,208✔
996
    pTag = NULL;
42,208✔
997
  }
998

999
_exit:
110✔
1000
  for (int32_t i = 0; i < taosArrayGetSize(pTagVals); ++i) {
112,130✔
1001
    STagVal* p = (STagVal*)TARRAY_GET_ELEM(pTagVals, i);
69,812✔
1002
    if (IS_VAR_DATA_TYPE(p->type)) {
69,812!
1003
      taosMemoryFreeClear(p->pData);
22,085!
1004
    }
1005
  }
1006
  taosArrayDestroy(pTagVals);
42,317✔
1007
  taosArrayDestroy(pTagName);
42,318✔
1008
  tTagFree(pTag);
42,318✔
1009
  return code;
42,318✔
1010
}
1011

1012
// input pStmt->pSql:  TAGS (tag1_value, ...) [table_options] ...
1013
// output pStmt->pSql: [table_options] ...
1014
static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
42,318✔
1015
  SToken token;
1016
  NEXT_TOKEN(pStmt->pSql, token);
42,318✔
1017
  if (TK_TAGS != token.type) {
42,318!
1018
    return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
×
1019
  }
1020

1021
  NEXT_TOKEN(pStmt->pSql, token);
42,318✔
1022
  if (TK_NK_LP != token.type) {
42,318!
1023
    return buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
×
1024
  }
1025

1026
  int32_t code = parseTagsClauseImpl(pCxt, pStmt);
42,318✔
1027
  if (TSDB_CODE_SUCCESS == code) {
42,318✔
1028
    NEXT_VALID_TOKEN(pStmt->pSql, token);
70,695✔
1029
    if (TK_NK_COMMA == token.type) {
42,208✔
1030
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
2✔
1031
    } else if (TK_NK_RP != token.type) {
42,206✔
1032
      code = buildSyntaxErrMsg(&pCxt->msg, ") is expected", token.z);
9✔
1033
    }
1034
  }
1035
  return code;
42,318✔
1036
}
1037

1038
static int32_t storeChildTableMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
42,318✔
1039
  pStmt->pTableMeta->suid = pStmt->pTableMeta->uid;
42,318✔
1040
  pStmt->pTableMeta->uid = pStmt->totalTbNum;
42,318✔
1041
  pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;
42,318✔
1042

1043
  STableMeta* pBackup = NULL;
42,318✔
1044
  if (TSDB_CODE_SUCCESS != cloneTableMeta(pStmt->pTableMeta, &pBackup)) {
42,318!
1045
    return TSDB_CODE_OUT_OF_MEMORY;
×
1046
  }
1047

1048
  char    tbFName[TSDB_TABLE_FNAME_LEN];
1049
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
42,318✔
1050
  if (TSDB_CODE_SUCCESS != code) {
42,318!
1051
    taosMemoryFree(pBackup);
×
1052
    return code;
×
1053
  }
1054
  code = taosHashPut(pStmt->pSubTableHashObj, tbFName, strlen(tbFName), &pBackup, POINTER_BYTES);
42,318✔
1055
  if (TSDB_CODE_SUCCESS != code) {
42,318!
1056
    taosMemoryFree(pBackup);
×
1057
  }
1058
  return code;
42,318✔
1059
}
1060

1061
static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
42,203✔
1062
  do {
6✔
1063
    int32_t index = 0;
42,203✔
1064
    SToken  token;
1065
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
42,203✔
1066
    if (TK_TTL == token.type) {
42,203✔
1067
      pStmt->pSql += index;
6✔
1068
      NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
6✔
1069
      if (TK_NK_INTEGER != token.type) {
6!
1070
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
3✔
1071
      }
1072
      pStmt->pCreateTblReq->ttl = taosStr2Int32(token.z, NULL, 10);
6✔
1073
      if (pStmt->pCreateTblReq->ttl < 0) {
6✔
1074
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
3✔
1075
      }
1076
    } else if (TK_COMMENT == token.type) {
42,197✔
1077
      pStmt->pSql += index;
3✔
1078
      NEXT_TOKEN(pStmt->pSql, token);
3✔
1079
      if (TK_NK_STRING != token.type) {
3!
1080
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option comment", token.z);
×
1081
      }
1082
      if (token.n >= TSDB_TB_COMMENT_LEN) {
3!
1083
        return buildSyntaxErrMsg(&pCxt->msg, "comment too long", token.z);
×
1084
      }
1085
      int32_t len = trimString(token.z, token.n, pCxt->tmpTokenBuf, TSDB_TB_COMMENT_LEN);
3✔
1086
      pStmt->pCreateTblReq->comment = taosStrndup(pCxt->tmpTokenBuf, len);
3!
1087
      if (NULL == pStmt->pCreateTblReq->comment) {
3!
1088
        return terrno;
×
1089
      }
1090
      pStmt->pCreateTblReq->commentLen = len;
3✔
1091
    } else {
1092
      break;
42,194✔
1093
    }
1094
  } while (1);
1095
  return TSDB_CODE_SUCCESS;
42,194✔
1096
}
1097

1098
// input pStmt->pSql:
1099
//   1. [(tag1_name, ...)] ...
1100
//   2. VALUES ... | FILE ...
1101
// output pStmt->pSql:
1102
//   1. [(field1_name, ...)]
1103
//   2. VALUES ... | FILE ...
1104
static int32_t parseUsingClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,458,457✔
1105
  if (!pStmt->usingTableProcessing || pCxt->usingDuplicateTable) {
9,458,457✔
1106
    return TSDB_CODE_SUCCESS;
9,416,139✔
1107
  }
1108

1109
  int32_t code = parseBoundTagsClause(pCxt, pStmt);
42,318✔
1110
  if (TSDB_CODE_SUCCESS == code) {
42,318!
1111
    code = parseTagsClause(pCxt, pStmt);
42,318✔
1112
  }
1113
  if (TSDB_CODE_SUCCESS == code) {
42,318✔
1114
    code = parseTableOptions(pCxt, pStmt);
42,197✔
1115
  }
1116

1117
  return code;
42,318✔
1118
}
1119

1120
static void setUserAuthInfo(SParseContext* pCxt, SName* pTbName, SUserAuthInfo* pInfo) {
9,459,869✔
1121
  snprintf(pInfo->user, sizeof(pInfo->user), "%s", pCxt->pUser);
9,459,869✔
1122
  memcpy(&pInfo->tbName, pTbName, sizeof(SName));
9,459,869✔
1123
  pInfo->type = AUTH_TYPE_WRITE;
9,459,869✔
1124
}
9,459,869✔
1125

1126
static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool* pMissCache, SNode** pTagCond) {
9,460,039✔
1127
  int32_t       code = TSDB_CODE_SUCCESS;
9,460,039✔
1128
  SUserAuthInfo authInfo = {0};
9,460,039✔
1129
  setUserAuthInfo(pCxt, pTbName, &authInfo);
9,460,039✔
1130
  SUserAuthRes authRes = {0};
9,468,253✔
1131
  bool         exists = true;
9,468,253✔
1132
  if (pCxt->async) {
9,468,253!
1133
    code = catalogChkAuthFromCache(pCxt->pCatalog, &authInfo, &authRes, &exists);
9,472,537✔
1134
  } else {
1135
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
×
1136
                             .requestId = pCxt->requestId,
×
1137
                             .requestObjRefId = pCxt->requestRid,
×
1138
                             .mgmtEps = pCxt->mgmtEpSet};
1139
    code = catalogChkAuth(pCxt->pCatalog, &conn, &authInfo, &authRes);
×
1140
  }
1141
  if (TSDB_CODE_SUCCESS == code) {
9,440,040✔
1142
    if (!exists) {
9,439,880✔
1143
      *pMissCache = true;
403✔
1144
    } else if (!authRes.pass[AUTH_RES_BASIC]) {
9,439,477✔
1145
      code = TSDB_CODE_PAR_PERMISSION_DENIED;
24✔
1146
    } else if (NULL != authRes.pCond[AUTH_RES_BASIC]) {
9,439,453✔
1147
      *pTagCond = authRes.pCond[AUTH_RES_BASIC];
5✔
1148
    }
1149
  }
1150
  return code;
9,440,040✔
1151
}
1152

1153
static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, STableMeta** pTableMeta, bool* pMissCache,
42,353✔
1154
                            bool bUsingTable) {
1155
  SParseContext* pComCxt = pCxt->pComCxt;
42,353✔
1156
  int32_t        code = TSDB_CODE_SUCCESS;
42,353✔
1157
  if (pComCxt->async) {
42,353✔
1158
    if (bUsingTable) {
42,295!
1159
      code = catalogGetCachedSTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
42,295✔
1160
    } else {
1161
      code = catalogGetCachedTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
×
1162
    }
1163
  } else {
1164
    SRequestConnInfo conn = {.pTrans = pComCxt->pTransporter,
58✔
1165
                             .requestId = pComCxt->requestId,
58✔
1166
                             .requestObjRefId = pComCxt->requestRid,
58✔
1167
                             .mgmtEps = pComCxt->mgmtEpSet};
1168
    if (bUsingTable) {
58✔
1169
      code = catalogGetSTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
31✔
1170
    } else {
1171
      code = catalogGetTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
27✔
1172
    }
1173
  }
1174
  if (TSDB_CODE_SUCCESS == code) {
42,353!
1175
    if (NULL == *pTableMeta) {
42,353✔
1176
      *pMissCache = true;
11✔
1177
    } else if (bUsingTable && TSDB_SUPER_TABLE != (*pTableMeta)->tableType) {
42,342!
1178
      code = buildInvalidOperationMsg(&pCxt->msg, "create table only from super table is allowed");
×
1179
    }
1180
  }
1181
  return code;
42,353✔
1182
}
1183

1184
static int32_t getTargetTableVgroup(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool isStb, bool* pMissCache) {
42,341✔
1185
  int32_t     code = TSDB_CODE_SUCCESS;
42,341✔
1186
  SVgroupInfo vg;
1187
  bool        exists = true;
42,341✔
1188
  if (pCxt->async) {
42,341✔
1189
    code = catalogGetCachedTableHashVgroup(pCxt->pCatalog, &pStmt->targetTableName, &vg, &exists);
42,284✔
1190
  } else {
1191
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
57✔
1192
                             .requestId = pCxt->requestId,
57✔
1193
                             .requestObjRefId = pCxt->requestRid,
57✔
1194
                             .mgmtEps = pCxt->mgmtEpSet};
1195
    code = catalogGetTableHashVgroup(pCxt->pCatalog, &conn, &pStmt->targetTableName, &vg);
57✔
1196
  }
1197
  if (TSDB_CODE_SUCCESS == code) {
42,341!
1198
    if (exists) {
42,341✔
1199
      if (isStb) {
42,327✔
1200
        pStmt->pTableMeta->vgId = vg.vgId;
42,301✔
1201
      }
1202
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
42,327✔
1203
    }
1204
    *pMissCache = !exists;
42,341✔
1205
  }
1206
  return code;
42,341✔
1207
}
1208

1209
static int32_t getTargetTableMetaAndVgroup(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) {
9,393,923✔
1210
  SParseContext* pComCxt = pCxt->pComCxt;
9,393,923✔
1211
  int32_t        code = TSDB_CODE_SUCCESS;
9,393,923✔
1212
  if (pComCxt->async) {
9,393,923!
1213
    {
1214
      SVgroupInfo vg;
1215
      code = catalogGetCachedTableVgMeta(pComCxt->pCatalog, &pStmt->targetTableName, &vg, &pStmt->pTableMeta);
9,395,641✔
1216
      if (TSDB_CODE_SUCCESS == code) {
9,428,344✔
1217
        if (NULL != pStmt->pTableMeta) {
9,428,160✔
1218
          if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE) {
9,408,199✔
1219
            pStmt->stbSyntax = true;
645✔
1220
          } else {
1221
            code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
9,407,554✔
1222
          }
1223
        }
1224
        *pMissCache = (NULL == pStmt->pTableMeta);
9,429,004✔
1225
      }
1226
    }
1227
  } else {
1228
    bool bUsingTable = false;
×
1229
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pStmt->pTableMeta, pMissCache, bUsingTable);
×
1230
    if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
27!
1231
      if (TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
27✔
1232
        pStmt->stbSyntax = true;
1✔
1233
      }
1234
      if (!pStmt->stbSyntax) {
27✔
1235
        code = getTargetTableVgroup(pCxt->pComCxt, pStmt, false, &pCxt->missCache);
26✔
1236
      }
1237
    }
1238
  }
1239
  return code;
9,428,097✔
1240
}
1241

1242
static int32_t collectUseTable(const SName* pName, SHashObj* pTable) {
6,216✔
1243
  char    fullName[TSDB_TABLE_FNAME_LEN];
1244
  int32_t code = tNameExtractFullName(pName, fullName);
6,216✔
1245
  if (TSDB_CODE_SUCCESS != code) {
6,216!
1246
    return code;
×
1247
  }
1248
  return taosHashPut(pTable, fullName, strlen(fullName), pName, sizeof(SName));
6,216✔
1249
}
1250

1251
static int32_t collectUseDatabase(const SName* pName, SHashObj* pDbs) {
704✔
1252
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
704✔
1253
  (void)tNameGetFullDbName(pName, dbFName);
704✔
1254
  return taosHashPut(pDbs, dbFName, strlen(dbFName), dbFName, sizeof(dbFName));
704✔
1255
}
1256

1257
static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,425,775✔
1258
  if (pCxt->forceUpdate) {
9,425,775✔
1259
    pCxt->missCache = true;
274✔
1260
    return TSDB_CODE_SUCCESS;
274✔
1261
  }
1262
  SNode*  pTagCond = NULL;
9,425,501✔
1263
  int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache, &pTagCond);
9,425,501✔
1264
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
9,397,509!
1265
    code = getTargetTableMetaAndVgroup(pCxt, pStmt, &pCxt->missCache);
9,395,874✔
1266
  }
1267
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
9,429,459✔
1268
    if (TSDB_SUPER_TABLE != pStmt->pTableMeta->tableType) {
9,407,684✔
1269
      pCxt->needTableTagVal = (NULL != pTagCond);
9,407,112✔
1270
      pCxt->missCache = (NULL != pTagCond);
9,407,112✔
1271
    } else {
1272
      pStmt->pTagCond = NULL;
572✔
1273
      code = nodesCloneNode(pTagCond, &pStmt->pTagCond);
572✔
1274
    }
1275
  }
1276
  nodesDestroyNode(pTagCond);
9,429,533✔
1277

1278
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
9,425,752!
1279
    code = collectUseDatabase(&pStmt->targetTableName, pStmt->pDbFNameHashObj);
27✔
1280
    if (TSDB_CODE_SUCCESS == code) {
27!
1281
      code = collectUseTable(&pStmt->targetTableName, pStmt->pTableNameHashObj);
27✔
1282
    }
1283
  }
1284
  return code;
9,426,007✔
1285
}
1286

1287
static int32_t preParseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
42,329✔
1288
  return insCreateSName(&pStmt->usingTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
42,329✔
1289
}
1290

1291
static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
42,329✔
1292
  if (pCxt->forceUpdate) {
42,329✔
1293
    pCxt->missCache = true;
1✔
1294
    return TSDB_CODE_SUCCESS;
1✔
1295
  }
1296

1297
  int32_t code = checkAuth(pCxt->pComCxt, &pStmt->usingTableName, &pCxt->missCache, &pStmt->pTagCond);
42,328✔
1298
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
42,328!
1299
    bool bUsingTable = true;
42,326✔
1300
    code = getTableMeta(pCxt, &pStmt->usingTableName, &pStmt->pTableMeta, &pCxt->missCache, bUsingTable);
42,326✔
1301
  }
1302
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
42,328!
1303
    code = getTargetTableVgroup(pCxt->pComCxt, pStmt, true, &pCxt->missCache);
42,315✔
1304
  }
1305
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
42,328!
1306
    code = collectUseDatabase(&pStmt->usingTableName, pStmt->pDbFNameHashObj);
31✔
1307
    if (TSDB_CODE_SUCCESS == code) {
31!
1308
      code = collectUseTable(&pStmt->usingTableName, pStmt->pTableNameHashObj);
31✔
1309
    }
1310
  }
1311
  return code;
42,328✔
1312
}
1313

1314
static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
42,329✔
1315
  SToken token;
1316
  NEXT_TOKEN(pStmt->pSql, token);
42,329✔
1317
  int32_t code = preParseUsingTableName(pCxt, pStmt, &token);
42,329✔
1318
  if (TSDB_CODE_SUCCESS == code) {
42,329!
1319
    code = getUsingTableSchema(pCxt, pStmt);
42,329✔
1320
  }
1321
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
42,329!
1322
    code = storeChildTableMeta(pCxt, pStmt);
42,301✔
1323
  }
1324
  return code;
42,329✔
1325
}
1326

1327
// input pStmt->pSql:
1328
//   1(care). [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
1329
//   2. VALUES ... | FILE ...
1330
// output pStmt->pSql:
1331
//   1. [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
1332
//   2. VALUES ... | FILE ...
1333
static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,466,683✔
1334
  SToken  token;
1335
  int32_t index = 0;
9,466,683✔
1336
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
9,466,683✔
1337
  if (TK_USING != token.type) {
9,470,232✔
1338
    return getTargetTableSchema(pCxt, pStmt);
9,428,645✔
1339
  }
1340

1341
  pStmt->usingTableProcessing = true;
41,587✔
1342
  // pStmt->pSql -> stb_name [(tag1_name, ...)
1343
  pStmt->pSql += index;
41,587✔
1344
  int32_t code = parseDuplicateUsingClause(pCxt, pStmt, &pCxt->usingDuplicateTable);
41,587✔
1345
  if (TSDB_CODE_SUCCESS == code && !pCxt->usingDuplicateTable) {
42,332!
1346
    return parseUsingTableNameImpl(pCxt, pStmt);
42,329✔
1347
  }
1348
  return code;
3✔
1349
}
1350

1351
static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
9,447,299✔
1352
  int32_t code = insCreateSName(&pStmt->targetTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
9,447,299✔
1353
  if (TSDB_CODE_SUCCESS == code) {
9,463,476!
1354
    if (IS_SYS_DBNAME(pStmt->targetTableName.dbname)) {
9,468,337!
1355
      return TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED;
×
1356
    }
1357
  }
1358

1359
  return code;
9,463,476✔
1360
}
1361

1362
// input pStmt->pSql:
1363
//   1(care). [(field1_name, ...)] ...
1364
//   2. [ USING ... ] ...
1365
//   3. VALUES ... | FILE ...
1366
// output pStmt->pSql:
1367
//   1. [ USING ... ] ...
1368
//   2. VALUES ... | FILE ...
1369
static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,468,873✔
1370
  SToken  token;
1371
  int32_t index = 0;
9,468,873✔
1372
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
9,468,873✔
1373
  if (TK_NK_LP != token.type) {
9,469,724✔
1374
    return TSDB_CODE_SUCCESS;
9,051,612✔
1375
  }
1376

1377
  // pStmt->pSql -> field1_name, ...)
1378
  pStmt->pSql += index;
418,112✔
1379
  pStmt->pBoundCols = pStmt->pSql;
418,112✔
1380
  return skipParentheses(pCxt, &pStmt->pSql);
418,112✔
1381
}
1382

1383
static int32_t getTableDataCxt(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt** pTableCxt) {
9,455,956✔
1384
  if (pCxt->pComCxt->async) {
9,455,956!
1385
    return insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid),
9,469,672✔
1386
                              pStmt->pTableMeta, &pStmt->pCreateTblReq, pTableCxt, false, false);
9,458,698✔
1387
  }
1388

1389
  char    tbFName[TSDB_TABLE_FNAME_LEN];
1390
  int32_t code = 0;
×
1391
  if (pCxt->preCtbname) {
×
1392
    tstrncpy(pStmt->targetTableName.tname, pStmt->usingTableName.tname, sizeof(pStmt->targetTableName.tname));
×
1393
    tstrncpy(pStmt->targetTableName.dbname, pStmt->usingTableName.dbname, sizeof(pStmt->targetTableName.dbname));
×
1394
    pStmt->targetTableName.type = TSDB_SUPER_TABLE;
×
1395
    pStmt->pTableMeta->tableType = TSDB_SUPER_TABLE;
×
1396
  }
1397

1398
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
×
1399

1400
  if (TSDB_CODE_SUCCESS != code) {
57!
1401
    return code;
×
1402
  }
1403
  if (pStmt->usingTableProcessing) {
57✔
1404
    pStmt->pTableMeta->uid = 0;
31✔
1405
  }
1406
  return insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
57✔
1407
                            &pStmt->pCreateTblReq, pTableCxt, NULL != pCxt->pComCxt->pStmtCb, false);
57✔
1408
}
1409

1410
static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) {
9,465,306✔
1411
  SToken  token;
1412
  int32_t index = 0;
9,465,306✔
1413
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
9,465,306✔
1414
  if (TK_NK_LP == token.type) {
9,468,831✔
1415
    pStmt->pSql += index;
142✔
1416
    if (NULL != pStmt->pBoundCols) {
142✔
1417
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
3✔
1418
    }
1419
    // pStmt->pSql -> field1_name, ...)
1420
    return parseBoundColumns(pCxt, &pStmt->pSql, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo);
139✔
1421
  }
1422

1423
  if (NULL != pStmt->pBoundCols) {
9,468,689✔
1424
    return parseBoundColumns(pCxt, &pStmt->pBoundCols, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo);
418,179✔
1425
  } else if (pTableCxt->boundColsInfo.hasBoundCols) {
9,050,510✔
1426
    insResetBoundColsInfo(&pTableCxt->boundColsInfo);
20✔
1427
  }
1428

1429
  return TSDB_CODE_SUCCESS;
9,047,596✔
1430
}
1431

1432
int32_t initTableColSubmitData(STableDataCxt* pTableCxt) {
9,477,521✔
1433
  if (0 == (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT)) {
9,477,521!
1434
    return TSDB_CODE_SUCCESS;
9,478,167✔
1435
  }
1436

1437
  for (int32_t i = 0; i < pTableCxt->boundColsInfo.numOfBound; ++i) {
148!
1438
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
795✔
1439
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
795✔
1440
    if (NULL == pCol) {
792!
1441
      return terrno;
×
1442
    }
1443
    tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags);
792✔
1444
  }
1445

1446
  return TSDB_CODE_SUCCESS;
×
1447
}
1448

1449
// input pStmt->pSql:
1450
//   1. [(tag1_name, ...)] ...
1451
//   2. VALUES ... | FILE ...
1452
// output pStmt->pSql: VALUES ... | FILE ...
1453
static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
9,460,355✔
1454
                                       STableDataCxt** pTableCxt) {
1455
  int32_t code = parseUsingClauseBottom(pCxt, pStmt);
9,460,355✔
1456
  if (TSDB_CODE_SUCCESS == code) {
9,458,689!
1457
    code = getTableDataCxt(pCxt, pStmt, pTableCxt);
9,460,121✔
1458
  }
1459
  if (TSDB_CODE_SUCCESS == code) {
9,467,192!
1460
    code = parseBoundColumnsClause(pCxt, pStmt, *pTableCxt);
9,467,246✔
1461
  }
1462
  if (TSDB_CODE_SUCCESS == code) {
9,466,831!
1463
    code = initTableColSubmitData(*pTableCxt);
9,467,670✔
1464
  }
1465
  return code;
9,470,169✔
1466
}
1467

1468
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
1469
// output pStmt->pSql:
1470
//   1. [(tag1_name, ...)] ...
1471
//   2. VALUES ... | FILE ...
1472
static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
9,448,073✔
1473
  int32_t code = preParseTargetTableName(pCxt, pStmt, pTbName);
9,448,073✔
1474
  if (TSDB_CODE_SUCCESS == code) {
9,468,360!
1475
    // option: [(field1_name, ...)]
1476
    code = preParseBoundColumnsClause(pCxt, pStmt);
9,469,904✔
1477
  }
1478
  if (TSDB_CODE_SUCCESS == code) {
9,469,119✔
1479
    // option: [USING stb_name]
1480
    code = parseUsingTableName(pCxt, pStmt);
9,468,456✔
1481
  }
1482
  return code;
9,465,209✔
1483
}
1484

1485
static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
1,704,981,055✔
1486
                                   int16_t timePrec, SColVal* pVal) {
1487
  switch (pSchema->type) {
1,704,981,055!
1488
    case TSDB_DATA_TYPE_BOOL: {
38,641,427✔
1489
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
38,641,427!
1490
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
31,736,199!
1491
          pVal->value.val = TRUE_VALUE;
19,373,901✔
1492
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
12,362,298!
1493
          pVal->value.val = FALSE_VALUE;
12,691,100✔
1494
        } else if (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&pVal->value.val)) {
✔
1495
          *(int8_t*)(&pVal->value.val) = (*(double*)&pVal->value.val == 0 ? FALSE_VALUE : TRUE_VALUE);
21✔
1496
        } else {
1497
          return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
6✔
1498
        }
1499
      } else if (pToken->type == TK_NK_INTEGER) {
6,905,228!
1500
        pVal->value.val = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
6,924,156✔
1501
      } else if (pToken->type == TK_NK_FLOAT) {
×
1502
        pVal->value.val = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
10!
1503
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
×
1504
                 (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&pVal->value.val))) {
×
1505
        *(int8_t*)(&pVal->value.val) = (*(double*)&pVal->value.val == 0 ? FALSE_VALUE : TRUE_VALUE);
8✔
1506
      } else {
1507
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
1✔
1508
      }
1509
      break;
38,990,659✔
1510
    }
1511
    case TSDB_DATA_TYPE_TINYINT: {
42,814,859✔
1512
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
42,814,859✔
1513
      if (TSDB_CODE_SUCCESS != code) {
42,894,628✔
1514
        return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z);
8✔
1515
      } else if (!IS_VALID_TINYINT(pVal->value.val)) {
42,894,620!
1516
        return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z);
×
1517
      }
1518
      break;
42,917,376✔
1519
    }
1520
    case TSDB_DATA_TYPE_UTINYINT: {
36,642,927✔
1521
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
36,642,927✔
1522
      if (TSDB_CODE_SUCCESS != code) {
36,677,319!
1523
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z);
×
1524
      } else if (pVal->value.val > UINT8_MAX) {
36,715,677!
1525
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z);
×
1526
      }
1527
      break;
36,715,677✔
1528
    }
1529
    case TSDB_DATA_TYPE_SMALLINT: {
42,695,607✔
1530
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
42,695,607✔
1531
      if (TSDB_CODE_SUCCESS != code) {
42,821,904✔
1532
        return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z);
8✔
1533
      } else if (!IS_VALID_SMALLINT(pVal->value.val)) {
42,821,896!
UNCOV
1534
        return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z);
×
1535
      }
1536
      break;
42,851,973✔
1537
    }
1538
    case TSDB_DATA_TYPE_USMALLINT: {
36,536,129✔
1539
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
36,536,129✔
1540
      if (TSDB_CODE_SUCCESS != code) {
36,627,717!
1541
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z);
×
1542
      } else if (pVal->value.val > UINT16_MAX) {
36,634,952!
1543
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z);
×
1544
      }
1545
      break;
36,634,952✔
1546
    }
1547
    case TSDB_DATA_TYPE_INT: {
517,997,489✔
1548
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
517,997,489✔
1549
      if (TSDB_CODE_SUCCESS != code) {
529,255,977✔
1550
        return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z);
8✔
1551
      } else if (!IS_VALID_INT(pVal->value.val)) {
529,255,969!
1552
        return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z);
×
1553
      }
1554
      break;
532,129,926✔
1555
    }
1556
    case TSDB_DATA_TYPE_UINT: {
36,542,058✔
1557
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
36,542,058✔
1558
      if (TSDB_CODE_SUCCESS != code) {
36,660,220!
UNCOV
1559
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z);
×
1560
      } else if (pVal->value.val > UINT32_MAX) {
36,681,804✔
1561
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z);
2✔
1562
      }
1563
      break;
36,681,802✔
1564
    }
1565
    case TSDB_DATA_TYPE_BIGINT: {
219,200,334✔
1566
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
219,200,334✔
1567
      if (TSDB_CODE_SUCCESS != code) {
222,520,983✔
1568
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z);
19,171✔
1569
      }
1570
      break;
222,501,812✔
1571
    }
1572
    case TSDB_DATA_TYPE_UBIGINT: {
36,568,386✔
1573
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
36,568,386✔
1574
      if (TSDB_CODE_SUCCESS != code) {
36,685,485!
1575
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z);
×
1576
      }
1577
      break;
36,701,481✔
1578
    }
1579
    case TSDB_DATA_TYPE_FLOAT: {
236,008,083✔
1580
      double  dv;
1581
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
236,008,083✔
1582
      if (TSDB_CODE_SUCCESS != code) {
237,777,932✔
1583
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
19✔
1584
      }
1585
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
237,777,924!
1586
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
36,634✔
1587
      }
1588
      float f = dv;
237,741,290✔
1589
      memcpy(&pVal->value.val, &f, sizeof(f));
237,741,290✔
1590
      break;
237,741,290✔
1591
    }
1592
    case TSDB_DATA_TYPE_DOUBLE: {
57,000,129✔
1593
      double  dv;
1594
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
57,000,129✔
1595
      if (TSDB_CODE_SUCCESS != code) {
57,789,094!
1596
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
×
1597
      }
1598
      if (isinf(dv) || isnan(dv)) {
57,846,223!
1599
        return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
66,298✔
1600
      }
1601
      pVal->value.val = *(int64_t*)&dv;
57,779,925✔
1602
      break;
57,779,925✔
1603
    }
1604
    case TSDB_DATA_TYPE_BINARY: {
65,204,234✔
1605
      // Too long values will raise the invalid sql error message
1606
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
65,204,234✔
1607
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
4✔
1608
      }
1609
      pVal->value.pData = taosMemoryMalloc(pToken->n);
65,204,230!
1610
      if (NULL == pVal->value.pData) {
65,133,777!
1611
        return terrno;
×
1612
      }
1613
      memcpy(pVal->value.pData, pToken->z, pToken->n);
65,133,777✔
1614
      pVal->value.nData = pToken->n;
65,133,777✔
1615
      break;
65,133,777✔
1616
    }
1617
    case TSDB_DATA_TYPE_VARBINARY: {
657,930✔
1618
      int32_t code = parseVarbinary(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes);
657,930✔
1619
      if (code != TSDB_CODE_SUCCESS) {
657,930✔
1620
        return generateSyntaxErrMsg(&pCxt->msg, code, pSchema->name);
12✔
1621
      }
1622
      break;
657,918✔
1623
    }
1624
    case TSDB_DATA_TYPE_NCHAR: {
54,972,794✔
1625
      // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
1626
      int32_t len = 0;
54,972,794✔
1627
      int64_t realLen = pToken->n << 2;
54,972,794✔
1628
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
54,972,794✔
1629
      char* pUcs4 = taosMemoryMalloc(realLen);
54,972,794!
1630
      if (NULL == pUcs4) {
54,969,891!
1631
        return terrno;
×
1632
      }
1633
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)pUcs4, realLen, &len, pCxt->pComCxt->charsetCxt)) {
54,969,891✔
1634
        taosMemoryFree(pUcs4);
17,981!
1635
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
×
1636
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1637
        }
1638
        char buf[512] = {0};
×
1639
        snprintf(buf, tListLen(buf), "%s", strerror(terrno));
×
1640
        return buildSyntaxErrMsg(&pCxt->msg, buf, pToken->z);
×
1641
      }
1642
      pVal->value.pData = pUcs4;
55,438,928✔
1643
      pVal->value.nData = len;
55,438,928✔
1644
      break;
55,438,928✔
1645
    }
1646
    case TSDB_DATA_TYPE_JSON: {
×
1647
      if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
×
1648
        return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z);
×
1649
      }
1650
      pVal->value.pData = taosMemoryMalloc(pToken->n);
×
1651
      if (NULL == pVal->value.pData) {
×
1652
        return terrno;
×
1653
      }
1654
      memcpy(pVal->value.pData, pToken->z, pToken->n);
×
1655
      pVal->value.nData = pToken->n;
×
1656
      break;
×
1657
    }
1658
    case TSDB_DATA_TYPE_GEOMETRY: {
5,099✔
1659
      int32_t        code = TSDB_CODE_FAILED;
5,099✔
1660
      unsigned char* output = NULL;
5,099✔
1661
      size_t         size = 0;
5,099✔
1662

1663
      code = parseGeometry(pToken, &output, &size);
5,099✔
1664
      if (code != TSDB_CODE_SUCCESS) {
5,099!
1665
        code = buildSyntaxErrMsg(&pCxt->msg, getGeosErrMsg(code), pToken->z);
×
1666
      }
1667
      // Too long values will raise the invalid sql error message
1668
      else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
5,099!
1669
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1670
      } else {
1671
        pVal->value.pData = taosMemoryMalloc(size);
5,099!
1672
        if (NULL == pVal->value.pData) {
5,099!
1673
          code = terrno;
×
1674
        } else {
1675
          memcpy(pVal->value.pData, output, size);
5,099✔
1676
          pVal->value.nData = size;
5,099✔
1677
        }
1678
      }
1679

1680
      geosFreeBuffer(output);
5,099✔
1681
      if (code != TSDB_CODE_SUCCESS) {
5,099!
1682
        return code;
×
1683
      }
1684

1685
      break;
5,099✔
1686
    }
1687
    case TSDB_DATA_TYPE_TIMESTAMP: {
366,782,679✔
1688
      if (parseTime(pSql, pToken, timePrec, &pVal->value.val, &pCxt->msg, pCxt->pComCxt->timezone) != TSDB_CODE_SUCCESS) {
366,782,679!
1689
        return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z);
×
1690
      }
1691
      break;
373,501,952✔
1692
    }
1693
    default:
×
1694
      return TSDB_CODE_FAILED;
×
1695
  }
1696

1697
  pVal->flag = CV_FLAG_VALUE;
1,816,384,547✔
1698
  return TSDB_CODE_SUCCESS;
1,816,384,547✔
1699
}
1700

1701
static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
1,725,961,877✔
1702
                               int16_t timePrec, SColVal* pVal) {
1703
  int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pSchema->type);
1,725,961,877✔
1704
  if (TSDB_CODE_SUCCESS == code && isNullValue(pSchema->type, pToken)) {
2,147,483,647✔
1705
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
12,525,903!
1706
      return buildSyntaxErrMsg(&pCxt->msg, "Primary timestamp column should not be null", pToken->z);
×
1707
    }
1708

1709
    pVal->flag = CV_FLAG_NULL;
12,525,903✔
1710
    return TSDB_CODE_SUCCESS;
12,525,903✔
1711
  }
1712

1713
  if (TSDB_CODE_SUCCESS == code) {
1,711,589,449✔
1714
    if (pToken->n == 0 && IS_NUMERIC_TYPE(pSchema->type)) {
1,706,716,332!
UNCOV
1715
      return buildSyntaxErrMsg(&pCxt->msg, "invalid numeric data", pToken->z);
×
1716
    }
1717
    code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, timePrec, pVal);
1,706,716,389✔
1718
  }
1719

1720
  return code;
1,736,487,060✔
1721
}
1722

1723
static void clearColValArray(SArray* pCols) {
352,613,223✔
1724
  int32_t num = taosArrayGetSize(pCols);
352,613,223✔
1725
  for (int32_t i = 0; i < num; ++i) {
2,132,440,447✔
1726
    SColVal* pCol = taosArrayGet(pCols, i);
1,780,206,159✔
1727
    if (IS_VAR_DATA_TYPE(pCol->value.type)) {
1,779,419,618!
1728
      taosMemoryFreeClear(pCol->value.pData);
116,874,826!
1729
    }
1730
  }
1731
}
352,234,288✔
1732

1733
typedef struct SStbRowsDataContext {
1734
  SName stbName;
1735

1736
  STableMeta*   pStbMeta;
1737
  SNode*        pTagCond;
1738
  SBoundColInfo boundColsInfo;
1739

1740
  // the following fields are for each stb row
1741
  SArray*        aTagVals;
1742
  SArray*        aColVals;
1743
  SArray*        aTagNames;
1744
  SName          ctbName;
1745
  STag*          pTag;
1746
  STableMeta*    pCtbMeta;
1747
  SVCreateTbReq* pCreateCtbReq;
1748
  bool           hasTimestampTag;
1749
  bool           isJsonTag;
1750
} SStbRowsDataContext;
1751

1752
typedef union SRowsDataContext {
1753
  STableDataCxt*       pTableDataCxt;
1754
  SStbRowsDataContext* pStbRowsCxt;
1755
} SRowsDataContext;
1756

1757
int32_t parseTbnameToken(SMsgBuf* pMsgBuf, char* tname, SToken* pToken, bool* pFoundCtbName) {
8,578✔
1758
  *pFoundCtbName = false;
8,578!
1759

1760
  if (isNullValue(TSDB_DATA_TYPE_BINARY, pToken)) {
8,578!
1761
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be null value");
×
1762
  }
1763

1764
  if (pToken->n > 0) {
8,578✔
1765
    if (pToken->n <= TSDB_TABLE_NAME_LEN - 1) {
8,577!
1766
      for (int i = 0; i < pToken->n; ++i) {
101,125✔
1767
        if (pToken->z[i] == '.') {
92,549✔
1768
          return buildInvalidOperationMsg(pMsgBuf, "tbname can not contain '.'");
1✔
1769
        } else {
1770
          tname[i] = pToken->z[i];
92,548✔
1771
        }
1772
      }
1773
      tname[pToken->n] = '\0';
8,576✔
1774
      *pFoundCtbName = true;
8,576✔
1775
    } else {
1776
      return buildInvalidOperationMsg(pMsgBuf, "tbname is too long");
×
1777
    }
1778
  } else {
1779
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be empty");
1✔
1780
  }
1781
  return TSDB_CODE_SUCCESS;
8,576✔
1782
}
1783

1784
static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
8,576✔
1785
                                          SStbRowsDataContext* pStbRowsCxt, bool ctbFirst, const SToken* tagTokens,
1786
                                          SSchema* const* tagSchemas, int numOfTagTokens) {
1787
  int32_t code = TSDB_CODE_SUCCESS;
8,576✔
1788
  uint8_t precision = pStmt->pTableMeta->tableInfo.precision;
8,576✔
1789

1790
  if (code == TSDB_CODE_SUCCESS && ctbFirst) {
8,576!
1791
    for (int32_t i = 0; code == TSDB_CODE_SUCCESS && i < numOfTagTokens; ++i) {
5,584!
1792
      SToken*  pTagToken = (SToken*)(tagTokens + i);
72✔
1793
      SSchema* pTagSchema = tagSchemas[i];
72✔
1794
      code = checkAndTrimValue(pTagToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
72✔
1795
      if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pTagToken->type) {
72!
1796
        code = buildInvalidOperationMsg(&pCxt->msg, "not expected tag");
×
1797
      }
1798

1799
      if (code == TSDB_CODE_SUCCESS) {
72!
1800
        code = parseTagValue(&pCxt->msg, NULL, precision, pTagSchema, pTagToken, pStbRowsCxt->aTagNames,
72✔
1801
                             pStbRowsCxt->aTagVals, &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
72✔
1802
      }
1803
    }
1804
    if (code == TSDB_CODE_SUCCESS && !pStbRowsCxt->isJsonTag) {
5,512!
1805
      code = tTagNew(pStbRowsCxt->aTagVals, 1, false, &pStbRowsCxt->pTag);
5,512✔
1806
    }
1807
  }
1808

1809
  if (code == TSDB_CODE_SUCCESS && pStbRowsCxt->pTagCond) {
8,576!
1810
    code = checkSubtablePrivilege(pStbRowsCxt->aTagVals, pStbRowsCxt->aTagNames, &pStbRowsCxt->pTagCond);
×
1811
  }
1812
  return code;
8,576✔
1813
}
1814

1815
static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
8,597✔
1816
                                 SStbRowsDataContext* pStbRowsCxt, SToken* pToken, const SBoundColInfo* pCols,
1817
                                 const SSchema* pSchemas, SToken* tagTokens, SSchema** tagSchemas, int* pNumOfTagTokens,
1818
                                 bool* bFoundTbName) {
1819
  int32_t code = TSDB_CODE_SUCCESS;
8,597✔
1820
  SArray* pTagNames = pStbRowsCxt->aTagNames;
8,597✔
1821
  SArray* pTagVals = pStbRowsCxt->aTagVals;
8,597✔
1822
  bool    canParseTagsAfter = !pStbRowsCxt->pTagCond && !pStbRowsCxt->hasTimestampTag;
8,597!
1823
  int32_t numOfCols = getNumOfColumns(pStbRowsCxt->pStbMeta);
8,597✔
1824
  int32_t numOfTags = getNumOfTags(pStbRowsCxt->pStbMeta);
8,597✔
1825
  int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta);
8,597✔
1826
  uint8_t precision = getTableInfo(pStbRowsCxt->pStbMeta).precision;
8,597✔
1827
  int     idx = 0;
8,597✔
1828
  for (int i = 0; i < pCols->numOfBound && (code) == TSDB_CODE_SUCCESS; ++i) {
107,586✔
1829
    const char* pTmpSql = *ppSql;
98,989✔
1830
    bool        ignoreComma = false;
98,989✔
1831
    NEXT_TOKEN_WITH_PREV_EXT(*ppSql, *pToken, &ignoreComma);
98,989✔
1832

1833
    if (ignoreComma) {
98,989!
1834
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pTmpSql);
×
1835
      break;
×
1836
    }
1837

1838
    if (TK_NK_RP == pToken->type) {
98,989!
1839
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
×
1840
      break;
×
1841
    }
1842

1843
    if (TK_NK_QUESTION == pToken->type) {
98,989!
1844
      pCxt->isStmtBind = true;
×
1845
      pStmt->usingTableProcessing = true;
×
1846
      if (pCols->pColIndex[i] == tbnameIdx) {
×
1847
        char* tbName = NULL;
×
1848
        if ((*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName) == TSDB_CODE_SUCCESS) {
×
1849
          tstrncpy(pStbRowsCxt->ctbName.tname, tbName, sizeof(pStbRowsCxt->ctbName.tname));
×
1850
          tstrncpy(pStmt->usingTableName.tname, pStmt->targetTableName.tname, sizeof(pStmt->usingTableName.tname));
×
1851
          tstrncpy(pStmt->targetTableName.tname, tbName, sizeof(pStmt->targetTableName.tname));
×
1852
          tstrncpy(pStmt->usingTableName.dbname, pStmt->targetTableName.dbname, sizeof(pStmt->usingTableName.dbname));
×
1853
          pStmt->usingTableName.type = 1;
×
1854
          pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;  // set the table type to child table for parse cache
×
1855
          *bFoundTbName = true;
×
1856
        }
1857
      } else if (pCols->pColIndex[i] < numOfCols) {
×
1858
        // bind column
1859
      } else if (pCols->pColIndex[i] < tbnameIdx) {
×
1860
        if (pCxt->tags.pColIndex == NULL) {
×
1861
          pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t));
×
1862
          if (NULL == pCxt->tags.pColIndex) {
×
1863
            return terrno;
×
1864
          }
1865
        }
1866
        if (!(idx < numOfTags)) {
×
1867
          return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags");
×
1868
        }
1869
        pCxt->tags.pColIndex[idx++] = pCols->pColIndex[i] - numOfCols;
×
1870
        pCxt->tags.mixTagsCols = true;
×
1871
        pCxt->tags.numOfBound++;
×
1872
        pCxt->tags.numOfCols++;
×
1873
      } else {
1874
        return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfBound");
×
1875
      }
1876
    } else {
1877
      if (pCols->pColIndex[i] < numOfCols) {
98,989✔
1878
        const SSchema* pSchema = &pSchemas[pCols->pColIndex[i]];
90,291✔
1879
        SColVal*       pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]);
90,291✔
1880
        code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, precision, pVal);
90,291✔
1881
        if (TK_NK_VARIABLE == pToken->type) {
90,291!
1882
          code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
1883
        }
1884
      } else if (pCols->pColIndex[i] < tbnameIdx) {
8,698✔
1885
        const SSchema* pTagSchema = &pSchemas[pCols->pColIndex[i]];
102✔
1886
        if (canParseTagsAfter) {
102!
1887
          tagTokens[(*pNumOfTagTokens)] = *pToken;
102✔
1888
          tagSchemas[(*pNumOfTagTokens)] = (SSchema*)pTagSchema;
102✔
1889
          ++(*pNumOfTagTokens);
102✔
1890
        } else {
1891
          code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
×
1892
          if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pToken->type) {
×
1893
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
1894
          }
1895
          if (code == TSDB_CODE_SUCCESS) {
×
1896
            code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, pTagNames, pTagVals,
×
1897
                                 &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
×
1898
          }
1899
        }
1900
      } else if (pCols->pColIndex[i] == tbnameIdx) {
8,596!
1901
        code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, TSDB_DATA_TYPE_BINARY);
8,596✔
1902
        if (TK_NK_VARIABLE == pToken->type) {
8,596!
1903
          code = buildInvalidOperationMsg(&pCxt->msg, "not expected tbname");
×
1904
        }
1905

1906
        if (code == TSDB_CODE_SUCCESS) {
8,596✔
1907
          code = parseTbnameToken(&pCxt->msg, pStbRowsCxt->ctbName.tname, pToken, bFoundTbName);
8,578✔
1908
        }
1909
      }
1910
    }
1911

1912
    if (code == TSDB_CODE_SUCCESS && i < pCols->numOfBound - 1) {
98,989✔
1913
      NEXT_VALID_TOKEN(*ppSql, *pToken);
90,393!
1914
      if (TK_NK_COMMA != pToken->type) {
90,393✔
1915
        code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
1✔
1916
      }
1917
    }
1918
  }
1919

1920
  return code;
8,597✔
1921
}
1922

1923
static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
8,597✔
1924
                               SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken, bool* pCtbFirst) {
1925
  SBoundColInfo* pCols = &pStbRowsCxt->boundColsInfo;
8,597✔
1926
  SSchema*       pSchemas = getTableColumnSchema(pStbRowsCxt->pStbMeta);
8,597✔
1927

1928
  bool        bFoundTbName = false;
8,597✔
1929
  const char* pOrigSql = *ppSql;
8,597✔
1930

1931
  int32_t  code = TSDB_CODE_SUCCESS;
8,597✔
1932
  SToken   tagTokens[TSDB_MAX_TAGS] = {0};
8,597✔
1933
  SSchema* tagSchemas[TSDB_MAX_TAGS] = {0};
8,597✔
1934
  int      numOfTagTokens = 0;
8,597✔
1935

1936
  code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, tagTokens, tagSchemas,
8,597✔
1937
                           &numOfTagTokens, &bFoundTbName);
1938

1939
  if (code != TSDB_CODE_SUCCESS) {
8,597✔
1940
    return code;
21✔
1941
  }
1942

1943
  if (!bFoundTbName) {
8,576!
1944
    if (!pCxt->isStmtBind) {
×
1945
      code = buildSyntaxErrMsg(&pCxt->msg, "tbname value expected", pOrigSql);
×
1946
    } else {
1947
      *pGotRow = true;
×
1948
      return TSDB_CODE_TSC_STMT_TBNAME_ERROR;
×
1949
    }
1950
  }
1951

1952
  bool ctbFirst = true;
8,576✔
1953
  char ctbFName[TSDB_TABLE_FNAME_LEN];
1954
  if (code == TSDB_CODE_SUCCESS) {
8,576!
1955
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
8,576✔
1956
  }
1957
  if (TSDB_CODE_SUCCESS == code) {
8,576!
1958
    STableMeta** pCtbMeta = taosHashGet(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName));
8,576✔
1959
    ctbFirst = (pCtbMeta == NULL);
8,576✔
1960
    if (!ctbFirst) {
8,576✔
1961
      pStbRowsCxt->pCtbMeta->uid = (*pCtbMeta)->uid;
3,064✔
1962
      pStbRowsCxt->pCtbMeta->vgId = (*pCtbMeta)->vgId;
3,064✔
1963
    }
1964
    *pCtbFirst = ctbFirst;
8,576✔
1965
  }
1966

1967
  if (code == TSDB_CODE_SUCCESS) {
8,576!
1968
    code = processCtbTagsAfterCtbName(pCxt, pStmt, pStbRowsCxt, ctbFirst, tagTokens, tagSchemas, numOfTagTokens);
8,576✔
1969
  }
1970

1971
  if (code == TSDB_CODE_SUCCESS) {
8,576!
1972
    *pGotRow = true;
8,576✔
1973
  }
1974
  return code;
8,576✔
1975
}
1976

1977
static int32_t processCtbAutoCreationAndCtbMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
5,512✔
1978
                                                SStbRowsDataContext* pStbRowsCxt) {
1979
  int32_t code = TSDB_CODE_SUCCESS;
5,512✔
1980

1981
  pStbRowsCxt->pCreateCtbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
5,512!
1982
  if (pStbRowsCxt->pCreateCtbReq == NULL) {
5,512!
1983
    code = terrno;
×
1984
  }
1985
  if (code == TSDB_CODE_SUCCESS) {
5,512!
1986
    code = insBuildCreateTbReq(pStbRowsCxt->pCreateCtbReq, pStbRowsCxt->ctbName.tname, pStbRowsCxt->pTag,
5,512✔
1987
                               pStbRowsCxt->pStbMeta->uid, pStbRowsCxt->stbName.tname, pStbRowsCxt->aTagNames,
5,512✔
1988
                               getNumOfTags(pStbRowsCxt->pStbMeta), TSDB_DEFAULT_TABLE_TTL);
5,512✔
1989
    pStbRowsCxt->pTag = NULL;
5,512✔
1990
  }
1991

1992
  if (code == TSDB_CODE_SUCCESS) {
5,512!
1993
    char ctbFName[TSDB_TABLE_FNAME_LEN];
1994
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
5,512✔
1995
    SVgroupInfo      vg;
1996
    SRequestConnInfo conn = {.pTrans = pCxt->pComCxt->pTransporter,
5,512✔
1997
                             .requestId = pCxt->pComCxt->requestId,
5,512✔
1998
                             .requestObjRefId = pCxt->pComCxt->requestRid,
5,512✔
1999
                             .mgmtEps = pCxt->pComCxt->mgmtEpSet};
5,512✔
2000
    if (TSDB_CODE_SUCCESS == code) {
5,512!
2001
      code = catalogGetTableHashVgroup(pCxt->pComCxt->pCatalog, &conn, &pStbRowsCxt->ctbName, &vg);
5,512✔
2002
    }
2003
    if (code == TSDB_CODE_SUCCESS) {
5,512!
2004
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)(&vg.vgId), sizeof(vg.vgId), &vg, sizeof(vg));
5,512✔
2005
    }
2006
    STableMeta* pBackup = NULL;
5,512✔
2007
    if (TSDB_CODE_SUCCESS == code) {
5,512!
2008
      pStbRowsCxt->pCtbMeta->uid = taosHashGetSize(pStmt->pSubTableHashObj) + 1;
5,512✔
2009
      pStbRowsCxt->pCtbMeta->vgId = vg.vgId;
5,512✔
2010

2011
      code = cloneTableMeta(pStbRowsCxt->pCtbMeta, &pBackup);
5,512✔
2012
    }
2013
    if (TSDB_CODE_SUCCESS == code) {
5,512!
2014
      code = taosHashPut(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName), &pBackup, POINTER_BYTES);
5,512✔
2015
    }
2016
    if (TSDB_CODE_SUCCESS == code) {
5,512!
2017
      code = collectUseTable(&pStbRowsCxt->ctbName, pStmt->pTableNameHashObj);
5,512✔
2018
    }
2019
  }
2020
  return code;
5,512✔
2021
}
2022

2023
static void clearStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
9,222✔
2024
  if (pStbRowsCxt == NULL) return;
9,222!
2025

2026
  taosArrayClear(pStbRowsCxt->aTagNames);
9,222✔
2027
  for (int i = 0; i < taosArrayGetSize(pStbRowsCxt->aTagVals); ++i) {
9,290✔
2028
    STagVal* p = (STagVal*)taosArrayGet(pStbRowsCxt->aTagVals, i);
68✔
2029
    if (IS_VAR_DATA_TYPE(p->type)) {
68!
2030
      taosMemoryFreeClear(p->pData);
18!
2031
    }
2032
  }
2033
  taosArrayClear(pStbRowsCxt->aTagVals);
9,222✔
2034

2035
  clearColValArray(pStbRowsCxt->aColVals);
9,222✔
2036

2037
  tTagFree(pStbRowsCxt->pTag);
9,222✔
2038
  pStbRowsCxt->pTag = NULL;
9,222✔
2039
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
9,222!
2040
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
9,222!
2041
}
2042

2043
static int32_t parseStbBoundInfo(SVnodeModifyOpStmt* pStmt, SStbRowsDataContext* pStbRowsCxt,
×
2044
                                 STableDataCxt** ppTableDataCxt) {
2045
  char    tbFName[TSDB_TABLE_FNAME_LEN];
2046
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
×
2047
  if (TSDB_CODE_SUCCESS != code) {
×
2048
    return code;
×
2049
  }
2050
  if (pStmt->usingTableProcessing) {
×
2051
    pStmt->pTableMeta->uid = 0;
×
2052
  }
2053

2054
  code = insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
×
2055
                            &pStmt->pCreateTblReq, ppTableDataCxt, false, true);
2056
  if (code != TSDB_CODE_SUCCESS) {
×
2057
    return code;
×
2058
  }
2059

2060
  insDestroyBoundColInfo(&((*ppTableDataCxt)->boundColsInfo));
×
2061
  (*ppTableDataCxt)->boundColsInfo = pStbRowsCxt->boundColsInfo;
×
2062

2063
  (*ppTableDataCxt)->boundColsInfo.pColIndex = taosMemoryCalloc(pStbRowsCxt->boundColsInfo.numOfBound, sizeof(int16_t));
×
2064
  if (NULL == (*ppTableDataCxt)->boundColsInfo.pColIndex) {
×
2065
    return terrno;
×
2066
  }
2067
  (void)memcpy((*ppTableDataCxt)->boundColsInfo.pColIndex, pStbRowsCxt->boundColsInfo.pColIndex,
×
2068
               sizeof(int16_t) * pStmt->pStbRowsCxt->boundColsInfo.numOfBound);
×
2069
  return TSDB_CODE_SUCCESS;
×
2070
}
2071

2072
static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
8,597✔
2073
                              SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken,
2074
                              STableDataCxt** ppTableDataCxt) {
2075
  bool    bFirstTable = false;
8,597✔
2076
  int32_t code = getStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pGotRow, pToken, &bFirstTable);
8,597✔
2077

2078
  if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR && *pGotRow) {
8,597!
2079
    return parseStbBoundInfo(pStmt, pStbRowsCxt, ppTableDataCxt);
×
2080
  }
2081

2082
  if (code != TSDB_CODE_SUCCESS || !*pGotRow) {
8,597!
2083
    return code;
21✔
2084
  }
2085

2086
  if (code == TSDB_CODE_SUCCESS && bFirstTable) {
8,576!
2087
    code = processCtbAutoCreationAndCtbMeta(pCxt, pStmt, pStbRowsCxt);
5,512✔
2088
  }
2089
  if (code == TSDB_CODE_SUCCESS) {
8,576!
2090
    if (pCxt->isStmtBind) {
8,576!
2091
      char ctbFName[TSDB_TABLE_FNAME_LEN];
2092
      code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
×
2093
      if (code != TSDB_CODE_SUCCESS) {
×
2094
        return code;
×
2095
      }
2096
      code = insGetTableDataCxt(pStmt->pTableBlockHashObj, ctbFName, strlen(ctbFName), pStbRowsCxt->pCtbMeta,
×
2097
                                &pStbRowsCxt->pCreateCtbReq, ppTableDataCxt, true, true);
2098
    } else {
2099
      code =
2100
          insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid),
8,576✔
2101
                             pStbRowsCxt->pCtbMeta, &pStbRowsCxt->pCreateCtbReq, ppTableDataCxt, false, true);
2102
    }
2103
  }
2104
  if (code == TSDB_CODE_SUCCESS) {
8,576!
2105
    code = initTableColSubmitData(*ppTableDataCxt);
8,576✔
2106
  }
2107
  if (code == TSDB_CODE_SUCCESS && !pCxt->isStmtBind) {
8,576!
2108
    SRow** pRow = taosArrayReserve((*ppTableDataCxt)->pData->aRowP, 1);
8,576✔
2109
    code = tRowBuild(pStbRowsCxt->aColVals, (*ppTableDataCxt)->pSchema, pRow);
8,576✔
2110
    if (TSDB_CODE_SUCCESS == code) {
8,576!
2111
      SRowKey key;
2112
      tRowGetKey(*pRow, &key);
8,576!
2113
      insCheckTableDataOrder(*ppTableDataCxt, &key);
8,576✔
2114
    }
2115
  }
2116

2117
  if (code == TSDB_CODE_SUCCESS) {
8,576!
2118
    *pGotRow = true;
8,576✔
2119
  }
2120

2121
  clearStbRowsDataContext(pStbRowsCxt);
8,576✔
2122

2123
  return code;
8,576✔
2124
}
2125

2126
static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow,
354,278,891✔
2127
                       SToken* pToken) {
2128
  SBoundColInfo* pCols = &pTableCxt->boundColsInfo;
354,278,891✔
2129
  SSchema*       pSchemas = getTableColumnSchema(pTableCxt->pMeta);
354,278,891✔
2130

2131
  int32_t code = TSDB_CODE_SUCCESS;
353,514,194✔
2132
  // 1. set the parsed value from sql string
2133
  for (int i = 0; i < pCols->numOfBound && TSDB_CODE_SUCCESS == code; ++i) {
2,047,637,393!
2134
    const char* pOrigSql = *pSql;
1,703,680,262✔
2135
    bool        ignoreComma = false;
1,703,680,262✔
2136
    NEXT_TOKEN_WITH_PREV_EXT(*pSql, *pToken, &ignoreComma);
1,703,680,262✔
2137
    if (ignoreComma) {
1,799,058,761!
2138
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pOrigSql);
×
2139
      break;
6✔
2140
    }
2141

2142
    SSchema* pSchema = &pSchemas[pCols->pColIndex[i]];
1,799,058,761✔
2143
    SColVal* pVal = taosArrayGet(pTableCxt->pValues, pCols->pColIndex[i]);
1,799,058,761✔
2144

2145
    if (pToken->type == TK_NK_QUESTION) {
1,778,830,265✔
2146
      pCxt->isStmtBind = true;
17,752,242✔
2147
      if (NULL == pCxt->pComCxt->pStmtCb) {
17,752,242✔
2148
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pToken->z);
4✔
2149
        break;
4✔
2150
      }
2151
    } else {
2152
      if (TK_NK_RP == pToken->type) {
1,761,078,023✔
2153
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
2✔
2154
        break;
2✔
2155
      }
2156

2157
      if (pCxt->isStmtBind) {
1,761,078,021!
2158
        code = buildInvalidOperationMsg(&pCxt->msg, "stmt bind param does not support normal value in sql");
×
2159
        break;
×
2160
      }
2161

2162
      if (TSDB_CODE_SUCCESS == code) {
1,761,078,021!
2163
        code = parseValueToken(pCxt, pSql, pToken, pSchema, getTableInfo(pTableCxt->pMeta).precision, pVal);
1,763,376,219✔
2164
      }
2165
    }
2166

2167
    if (TSDB_CODE_SUCCESS == code && i < pCols->numOfBound - 1) {
1,725,499,451✔
2168
      NEXT_VALID_TOKEN(*pSql, *pToken);
1,395,553,155✔
2169
      if (TK_NK_COMMA != pToken->type) {
1,374,295,930✔
2170
        code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
2✔
2171
      }
2172
    }
2173
  }
2174

2175
  if (TSDB_CODE_SUCCESS == code && !pCxt->isStmtBind) {
343,957,137!
2176
    SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1);
352,230,366✔
2177
    code = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow);
350,703,262✔
2178
    if (TSDB_CODE_SUCCESS == code) {
354,122,045!
2179
      SRowKey key;
2180
      tRowGetKey(*pRow, &key);
354,343,163✔
2181
      insCheckTableDataOrder(pTableCxt, &key);
354,002,071✔
2182
    }
2183
  }
2184

2185
  if (TSDB_CODE_SUCCESS == code && !pCxt->isStmtBind) {
344,944,008!
2186
    *pGotRow = true;
353,599,446✔
2187
  }
2188

2189
  clearColValArray(pTableCxt->pValues);
344,944,008✔
2190

2191
  return code;
345,859,640✔
2192
}
2193

2194
// pSql -> (field1_value, ...) [(field1_value2, ...) ...]
2195
static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
9,457,890✔
2196
                           int32_t* pNumOfRows, SToken* pToken) {
2197
  int32_t code = TSDB_CODE_SUCCESS;
9,457,890✔
2198

2199
  (*pNumOfRows) = 0;
9,457,890✔
2200
  while (TSDB_CODE_SUCCESS == code) {
354,900,697✔
2201
    int32_t index = 0;
354,504,412✔
2202
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, *pToken, index);
354,504,412✔
2203
    if (TK_NK_LP != pToken->type) {
364,639,480✔
2204
      break;
9,468,361✔
2205
    }
2206
    pStmt->pSql += index;
355,171,119✔
2207

2208
    bool gotRow = false;
355,171,119✔
2209
    if (TSDB_CODE_SUCCESS == code) {
355,171,119!
2210
      if (!pStmt->stbSyntax) {
355,457,892!
2211
        code = parseOneRow(pCxt, &pStmt->pSql, rowsDataCxt.pTableDataCxt, &gotRow, pToken);
355,581,448✔
2212
      } else {
UNCOV
2213
        STableDataCxt* pTableDataCxt = NULL;
×
UNCOV
2214
        code = parseOneStbRow(pCxt, pStmt, &pStmt->pSql, rowsDataCxt.pStbRowsCxt, &gotRow, pToken, &pTableDataCxt);
×
2215
      }
2216
    }
2217

2218
    if (TSDB_CODE_SUCCESS == code) {
345,020,059!
2219
      NEXT_VALID_TOKEN(pStmt->pSql, *pToken);
346,945,734✔
2220
      if (TK_NK_COMMA == pToken->type) {
344,772,526✔
2221
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
12✔
2222
      } else if (TK_NK_RP != pToken->type) {
344,772,514✔
2223
        code = buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
20✔
2224
      }
2225
    }
2226

2227
    if (TSDB_CODE_SUCCESS == code && gotRow) {
345,442,807!
2228
      (*pNumOfRows)++;
345,247,514✔
2229
    }
2230
  }
2231

2232
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) &&
9,864,646✔
2233
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
21!
2234
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
2235
  }
2236
  return code;
9,467,144✔
2237
}
2238

2239
// VALUES (field1_value, ...) [(field1_value2, ...) ...]
2240
static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataContext,
9,460,817✔
2241
                                 SToken* pToken) {
2242
  int32_t numOfRows = 0;
9,460,817✔
2243
  int32_t code = parseValues(pCxt, pStmt, rowsDataContext, &numOfRows, pToken);
9,460,817✔
2244
  if (TSDB_CODE_SUCCESS == code) {
9,462,676✔
2245
    pStmt->totalRowsNum += numOfRows;
9,462,438✔
2246
    pStmt->totalTbNum += 1;
9,462,438✔
2247
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_INSERT);
9,462,438✔
2248
  }
2249
  return code;
9,462,676✔
2250
}
2251

2252
static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
28✔
2253
                            int32_t* pNumOfRows) {
2254
  int32_t code = TSDB_CODE_SUCCESS;
28✔
2255
  (*pNumOfRows) = 0;
28✔
2256
  char*   pLine = NULL;
28✔
2257
  int64_t readLen = 0;
28✔
2258
  bool    firstLine = (pStmt->fileProcessing == false);
28✔
2259
  pStmt->fileProcessing = false;
28✔
2260
  while (TSDB_CODE_SUCCESS == code && (readLen = taosGetLineFile(pStmt->fp, &pLine)) != -1) {
108,298!
2261
    if (('\r' == pLine[readLen - 1]) || ('\n' == pLine[readLen - 1])) {
108,270!
2262
      pLine[--readLen] = '\0';
108,270✔
2263
    }
2264

2265
    if (readLen == 0) {
108,270!
2266
      firstLine = false;
×
2267
      continue;
18✔
2268
    }
2269

2270
    bool gotRow = false;
108,270✔
2271
    if (TSDB_CODE_SUCCESS == code) {
108,270!
2272
      SToken token;
2273
      (void)strtolower(pLine, pLine);
108,270✔
2274
      const char* pRow = pLine;
108,270✔
2275
      if (!pStmt->stbSyntax) {
108,270✔
2276
        code = parseOneRow(pCxt, (const char**)&pRow, rowsDataCxt.pTableDataCxt, &gotRow, &token);
100,318✔
2277
      } else {
2278
        STableDataCxt* pTableDataCxt = NULL;
7,952✔
2279
        code =
2280
            parseOneStbRow(pCxt, pStmt, (const char**)&pRow, rowsDataCxt.pStbRowsCxt, &gotRow, &token, &pTableDataCxt);
7,952✔
2281
        if (code == TSDB_CODE_SUCCESS) {
7,952✔
2282
          SStbRowsDataContext* pStbRowsCxt = rowsDataCxt.pStbRowsCxt;
7,934✔
2283
          void*                pData = pTableDataCxt;
7,934✔
2284
          code = taosHashPut(pStmt->pTableCxtHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid),
7,934✔
2285
                             &pData, POINTER_BYTES);
2286
          if (TSDB_CODE_SUCCESS != code) {
7,934!
2287
            break;
×
2288
          }
2289
        }
2290
      }
2291
      if (code && firstLine) {
108,270!
2292
        firstLine = false;
18✔
2293
        code = 0;
18✔
2294
        continue;
18✔
2295
      }
2296
    }
2297

2298
    if (TSDB_CODE_SUCCESS == code && gotRow) {
108,252!
2299
      (*pNumOfRows)++;
108,252✔
2300
    }
2301

2302
    if (TSDB_CODE_SUCCESS == code && (*pNumOfRows) >= tsMaxInsertBatchRows) {
108,252!
2303
      pStmt->fileProcessing = true;
×
2304
      break;
×
2305
    }
2306

2307
    firstLine = false;
108,252✔
2308
  }
2309
  taosMemoryFree(pLine);
28!
2310

2311
  parserDebug("0x%" PRIx64 " %d rows have been parsed", pCxt->pComCxt->requestId, *pNumOfRows);
28✔
2312

2313
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) && 0 == pStmt->totalRowsNum &&
28!
2314
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) && !pStmt->fileProcessing) {
×
2315
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
2316
  }
2317
  return code;
28✔
2318
}
2319

2320
static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
28✔
2321
                                     SRowsDataContext rowsDataCxt) {
2322
  // init only for file
2323
  if (NULL == pStmt->pTableCxtHashObj) {
28✔
2324
    pStmt->pTableCxtHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
22✔
2325
    if (!pStmt->pTableCxtHashObj) {
22!
2326
      return terrno;
×
2327
    }
2328
  }
2329
  int32_t numOfRows = 0;
28✔
2330
  int32_t code = parseCsvFile(pCxt, pStmt, rowsDataCxt, &numOfRows);
28✔
2331
  if (TSDB_CODE_SUCCESS == code) {
28!
2332
    pStmt->totalRowsNum += numOfRows;
28✔
2333
    pStmt->totalTbNum += 1;
28✔
2334
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT);
28✔
2335
    if (rowsDataCxt.pTableDataCxt && rowsDataCxt.pTableDataCxt->pData) {
28!
2336
      rowsDataCxt.pTableDataCxt->pData->flags |= SUBMIT_REQ_FROM_FILE;
9✔
2337
    }
2338
    if (!pStmt->fileProcessing) {
28!
2339
      code = taosCloseFile(&pStmt->fp);
28✔
2340
      if (TSDB_CODE_SUCCESS != code) {
28!
2341
        parserWarn("0x%" PRIx64 " failed to close file.", pCxt->pComCxt->requestId);
×
2342
      }
2343
    } else {
2344
      parserDebug("0x%" PRIx64 " insert from csv. File is too large, do it in batches.", pCxt->pComCxt->requestId);
×
2345
    }
2346
    if (pStmt->insertType != TSDB_QUERY_TYPE_FILE_INSERT) {
28!
2347
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", NULL);
×
2348
    }
2349
  } else {
2350
    return buildInvalidOperationMsg(&pCxt->msg, tstrerror(code));
×
2351
  }
2352

2353
  // just record pTableCxt whose data come from file
2354
  if (!pStmt->stbSyntax && numOfRows > 0) {
28!
2355
    void* pData = rowsDataCxt.pTableDataCxt;
9✔
2356
    code = taosHashPut(pStmt->pTableCxtHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid), &pData,
9✔
2357
                       POINTER_BYTES);
2358
  }
2359

2360
  return code;
28✔
2361
}
2362

2363
static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pFilePath,
28✔
2364
                                 SRowsDataContext rowsDataCxt) {
2365
  char filePathStr[PATH_MAX + 16] = {0};
28✔
2366
  if (TK_NK_STRING == pFilePath->type) {
28!
2367
    (void)trimString(pFilePath->z, pFilePath->n, filePathStr, sizeof(filePathStr));
28✔
2368
    if (strlen(filePathStr) >= PATH_MAX) {
28!
2369
      return buildSyntaxErrMsg(&pCxt->msg, "file path is too long, max length is 4096", pFilePath->z);
×
2370
    }
2371
  } else {
2372
    if (pFilePath->n >= PATH_MAX) {
×
2373
      return buildSyntaxErrMsg(&pCxt->msg, "file path is too long, max length is 4096", pFilePath->z);
×
2374
    }
2375
    strncpy(filePathStr, pFilePath->z, pFilePath->n);
×
2376
  }
2377
  pStmt->fp = taosOpenFile(filePathStr, TD_FILE_READ | TD_FILE_STREAM);
28✔
2378
  if (NULL == pStmt->fp) {
28!
2379
    return terrno;
×
2380
  }
2381

2382
  return parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
28✔
2383
}
2384

2385
static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
28✔
2386
                               SToken* pToken) {
2387
  if (tsUseAdapter) {
28!
2388
    return buildInvalidOperationMsg(&pCxt->msg, "proxy mode does not support csv loading");
×
2389
  }
2390

2391
  NEXT_TOKEN(pStmt->pSql, *pToken);
28✔
2392
  if (0 == pToken->n || (TK_NK_STRING != pToken->type && TK_NK_ID != pToken->type)) {
28!
2393
    return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", pToken->z);
×
2394
  }
2395
  return parseDataFromFile(pCxt, pStmt, pToken, rowsDataCxt);
28✔
2396
}
2397

2398
// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
2399
static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt) {
9,459,158✔
2400
  SToken token;
2401
  NEXT_TOKEN(pStmt->pSql, token);
9,459,158✔
2402
  switch (token.type) {
9,469,069!
2403
    case TK_VALUES:
9,470,615✔
2404
      if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT)) {
9,470,615!
2405
        return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", token.z);
×
2406
      }
2407
      return parseValuesClause(pCxt, pStmt, rowsDataCxt, &token);
9,470,615✔
2408
    case TK_FILE:
×
2409
      return parseFileClause(pCxt, pStmt, rowsDataCxt, &token);
×
2410
    default:
×
2411
      break;
×
2412
  }
2413
  return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
×
2414
}
2415

2416
static void destroyStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
18,828,981✔
2417
  if (pStbRowsCxt == NULL) return;
18,828,981!
2418
  clearStbRowsDataContext(pStbRowsCxt);
×
2419
  taosArrayDestroy(pStbRowsCxt->aColVals);
646✔
2420
  pStbRowsCxt->aColVals = NULL;
646✔
2421
  taosArrayDestroy(pStbRowsCxt->aTagVals);
646✔
2422
  pStbRowsCxt->aTagVals = NULL;
646✔
2423
  taosArrayDestroy(pStbRowsCxt->aTagNames);
646✔
2424
  pStbRowsCxt->aTagNames = NULL;
646✔
2425
  insDestroyBoundColInfo(&pStbRowsCxt->boundColsInfo);
646✔
2426
  tTagFree(pStbRowsCxt->pTag);
646✔
2427
  pStbRowsCxt->pTag = NULL;
646✔
2428
  taosMemoryFreeClear(pStbRowsCxt->pCtbMeta);
646!
2429
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
646!
2430
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
646!
2431
}
2432

2433
static int32_t constructStbRowsDataContext(SVnodeModifyOpStmt* pStmt, SStbRowsDataContext** ppStbRowsCxt) {
646✔
2434
  SStbRowsDataContext* pStbRowsCxt = taosMemoryCalloc(1, sizeof(SStbRowsDataContext));
646!
2435
  if (!pStbRowsCxt) {
646!
2436
    return terrno;
×
2437
  }
2438
  tNameAssign(&pStbRowsCxt->stbName, &pStmt->targetTableName);
646✔
2439
  int32_t code = collectUseTable(&pStbRowsCxt->stbName, pStmt->pTableNameHashObj);
646✔
2440
  if (TSDB_CODE_SUCCESS == code) {
646!
2441
    code = collectUseDatabase(&pStbRowsCxt->stbName, pStmt->pDbFNameHashObj);
646✔
2442
  }
2443
  if (TSDB_CODE_SUCCESS == code) {
646!
2444
    pStbRowsCxt->ctbName.type = TSDB_TABLE_NAME_T;
646✔
2445
    pStbRowsCxt->ctbName.acctId = pStbRowsCxt->stbName.acctId;
646✔
2446
    memcpy(pStbRowsCxt->ctbName.dbname, pStbRowsCxt->stbName.dbname, sizeof(pStbRowsCxt->stbName.dbname));
646✔
2447

2448
    pStbRowsCxt->pTagCond = pStmt->pTagCond;
646✔
2449
    pStbRowsCxt->pStbMeta = pStmt->pTableMeta;
646✔
2450

2451
    code = cloneTableMeta(pStbRowsCxt->pStbMeta, &pStbRowsCxt->pCtbMeta);
646✔
2452
  }
2453
  if (TSDB_CODE_SUCCESS == code) {
646!
2454
    pStbRowsCxt->pCtbMeta->tableType = TSDB_CHILD_TABLE;
646✔
2455
    pStbRowsCxt->pCtbMeta->suid = pStbRowsCxt->pStbMeta->uid;
646✔
2456

2457
    pStbRowsCxt->aTagNames = taosArrayInit(8, TSDB_COL_NAME_LEN);
646✔
2458
    if (!pStbRowsCxt->aTagNames) {
646!
2459
      code = terrno;
×
2460
    }
2461
  }
2462
  if (TSDB_CODE_SUCCESS == code) {
646!
2463
    pStbRowsCxt->aTagVals = taosArrayInit(8, sizeof(STagVal));
646✔
2464
    if (!pStbRowsCxt->aTagVals) {
646!
2465
      code = terrno;
×
2466
    }
2467
  }
2468
  if (TSDB_CODE_SUCCESS == code) {
646!
2469
    // col values and bound cols info of STableDataContext is not used
2470
    pStbRowsCxt->aColVals = taosArrayInit(getNumOfColumns(pStbRowsCxt->pStbMeta), sizeof(SColVal));
646✔
2471
    if (!pStbRowsCxt->aColVals) code = terrno;
646!
2472
  }
2473
  if (TSDB_CODE_SUCCESS == code) {
646!
2474
    code = insInitColValues(pStbRowsCxt->pStbMeta, pStbRowsCxt->aColVals);
646✔
2475
  }
2476
  if (TSDB_CODE_SUCCESS == code) {
646!
2477
    STableComInfo tblInfo = getTableInfo(pStmt->pTableMeta);
646✔
2478
    code = insInitBoundColsInfo(tblInfo.numOfColumns + tblInfo.numOfTags + 1, &pStbRowsCxt->boundColsInfo);
646✔
2479
  }
2480
  if (TSDB_CODE_SUCCESS == code) {
646!
2481
    *ppStbRowsCxt = pStbRowsCxt;
646✔
2482
  } else {
2483
    clearStbRowsDataContext(pStbRowsCxt);
×
2484
  }
2485
  return code;
646✔
2486
}
2487

2488
static int32_t parseInsertStbClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
647✔
2489
  int32_t code = TSDB_CODE_SUCCESS;
647✔
2490
  if (!pStmt->pBoundCols) {
647✔
2491
    return buildSyntaxErrMsg(&pCxt->msg, "(...tbname, ts...) bounded cols is expected for supertable insertion",
1✔
2492
                             pStmt->pSql);
2493
  }
2494

2495
  SStbRowsDataContext* pStbRowsCxt = NULL;
646✔
2496
  code = constructStbRowsDataContext(pStmt, &pStbRowsCxt);
646✔
2497

2498
  if (code == TSDB_CODE_SUCCESS) {
646!
2499
    code = parseBoundColumns(pCxt, &pStmt->pBoundCols, BOUND_ALL_AND_TBNAME, pStmt->pTableMeta,
646✔
2500
                             &pStbRowsCxt->boundColsInfo);
646✔
2501
    pStbRowsCxt->hasTimestampTag = false;
646✔
2502
    for (int32_t i = 0; i < pStbRowsCxt->boundColsInfo.numOfBound; ++i) {
2,818✔
2503
      int16_t schemaIndex = pStbRowsCxt->boundColsInfo.pColIndex[i];
2,172✔
2504
      if (schemaIndex != getTbnameSchemaIndex(pStmt->pTableMeta) && schemaIndex >= getNumOfColumns(pStmt->pTableMeta)) {
2,172✔
2505
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_TIMESTAMP) {
65!
2506
          pStbRowsCxt->hasTimestampTag = true;
×
2507
        }
2508
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_JSON) {
65!
2509
          pStbRowsCxt->isJsonTag = true;
×
2510
        }
2511
      }
2512
    }
2513
    pStmt->pStbRowsCxt = pStbRowsCxt;
646✔
2514
  }
2515

2516
  if (code == TSDB_CODE_SUCCESS) {
646✔
2517
    SRowsDataContext rowsDataCxt;
2518
    rowsDataCxt.pStbRowsCxt = pStbRowsCxt;
644✔
2519
    code = parseDataClause(pCxt, pStmt, rowsDataCxt);
644✔
2520
  }
2521

2522
  return code;
646✔
2523
}
2524

2525
// input pStmt->pSql:
2526
//   1. [(tag1_name, ...)] ...
2527
//   2. VALUES ... | FILE ...
2528
static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,461,521✔
2529
  if (!pStmt->stbSyntax) {
9,461,521!
2530
    STableDataCxt*   pTableCxt = NULL;
9,462,709✔
2531
    int32_t          code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt);
9,462,709✔
2532
    SRowsDataContext rowsDataCxt;
2533
    rowsDataCxt.pTableDataCxt = pTableCxt;
9,466,287✔
2534
    if (TSDB_CODE_SUCCESS == code) {
9,466,287!
2535
      code = parseDataClause(pCxt, pStmt, rowsDataCxt);
9,467,316✔
2536
    }
2537
    return code;
9,445,967✔
2538
  } else {
2539
    int32_t code = parseInsertStbClauseBottom(pCxt, pStmt);
×
2540
    return code;
647✔
2541
  }
2542
}
2543

2544
static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,451,171✔
2545
  insDestroyBoundColInfo(&pCxt->tags);
9,451,171✔
2546
  taosMemoryFreeClear(pStmt->pTableMeta);
9,449,557!
2547
  nodesDestroyNode(pStmt->pTagCond);
9,449,557✔
2548
  taosArrayDestroy(pStmt->pTableTag);
9,450,864✔
2549
  tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
9,448,677!
2550
  taosMemoryFreeClear(pStmt->pCreateTblReq);
9,448,677!
2551
  pCxt->missCache = false;
9,448,677✔
2552
  pCxt->usingDuplicateTable = false;
9,448,677✔
2553
  pStmt->pBoundCols = NULL;
9,448,677✔
2554
  pStmt->usingTableProcessing = false;
9,448,677✔
2555
  pStmt->fileProcessing = false;
9,448,677✔
2556
  pStmt->usingTableName.type = 0;
9,448,677✔
2557

2558
  destroyStbRowsDataContext(pStmt->pStbRowsCxt);
9,448,677✔
2559
  taosMemoryFreeClear(pStmt->pStbRowsCxt);
9,448,403!
2560
  pStmt->stbSyntax = false;
9,448,403✔
2561
}
9,448,403✔
2562

2563
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
2564
static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
9,453,608✔
2565
  resetEnvPreTable(pCxt, pStmt);
9,453,608✔
2566
  int32_t code = parseSchemaClauseTop(pCxt, pStmt, pTbName);
9,448,962✔
2567
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
9,464,193!
2568
    code = parseInsertTableClauseBottom(pCxt, pStmt);
9,443,130✔
2569
  }
2570

2571
  return code;
9,444,316✔
2572
}
2573

2574
static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName,
18,823,536✔
2575
                                          bool* pHasData) {
2576
  // no data in the sql string anymore.
2577
  if (0 == pTbName->n) {
18,823,536✔
2578
    if (0 != pTbName->type && '\0' != pStmt->pSql[0]) {
9,373,248!
2579
      return buildSyntaxErrMsg(&pCxt->msg, "invalid table name", pTbName->z);
×
2580
    }
2581

2582
    if (0 == pStmt->totalRowsNum && (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
9,373,248!
2583
      return buildInvalidOperationMsg(&pCxt->msg, "no data in sql");
×
2584
    }
2585

2586
    *pHasData = false;
9,373,248✔
2587
    return TSDB_CODE_SUCCESS;
9,373,248✔
2588
  }
2589

2590
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT) && pStmt->totalTbNum > 0) {
9,450,288!
2591
    return buildInvalidOperationMsg(&pCxt->msg, "single table allowed in one stmt");
×
2592
  }
2593

2594
  if (TK_NK_QUESTION == pTbName->type) {
9,450,288✔
2595
    pCxt->isStmtBind = true;
20✔
2596
    if (NULL == pCxt->pComCxt->pStmtCb) {
20!
2597
      return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
2598
    }
2599

2600
    char*   tbName = NULL;
20✔
2601
    int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
20✔
2602
    if (TSDB_CODE_SUCCESS == code) {
20!
2603
      pTbName->z = tbName;
20✔
2604
      pTbName->n = strlen(tbName);
20✔
2605
    } else if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
×
2606
      pCxt->preCtbname = true;
×
2607
      code = TSDB_CODE_SUCCESS;
×
2608
    } else {
2609
      return code;
×
2610
    }
2611
  }
2612

2613
  if (TK_NK_ID != pTbName->type && TK_NK_STRING != pTbName->type && TK_NK_QUESTION != pTbName->type) {
9,450,288!
2614
    return buildSyntaxErrMsg(&pCxt->msg, "table_name is expected", pTbName->z);
×
2615
  }
2616

2617
  // db.? situation,ensure that the only thing following the '.' mark is '?'
2618
  char* tbNameAfterDbName = strnchr(pTbName->z, '.', pTbName->n, true);
9,450,288✔
2619
  if ((tbNameAfterDbName != NULL) && (*(tbNameAfterDbName + 1) == '?')) {
9,454,047!
2620
    char* tbName = NULL;
×
2621
    if (NULL == pCxt->pComCxt->pStmtCb) {
×
2622
      return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
2623
    }
2624
    int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
×
2625
    if (code != TSDB_CODE_SUCCESS) {
×
2626
      pCxt->preCtbname = true;
×
2627
    } else {
2628
      pTbName->z = tbName;
×
2629
      pTbName->n = strlen(tbName);
×
2630
    }
2631
  }
2632

2633
  if (pCxt->isStmtBind) {
9,454,047✔
2634
    if (TK_NK_ID == pTbName->type || (tbNameAfterDbName != NULL && *(tbNameAfterDbName + 1) != '?')) {
22!
2635
      // In SQL statements, the table name has already been specified.
2636
      parserWarn("0x%" PRIx64 " table name is specified in sql, ignore the table name in bind param",
2!
2637
                 pCxt->pComCxt->requestId);
2638
    }
2639
  }
2640

2641
  *pHasData = true;
9,453,284✔
2642
  return TSDB_CODE_SUCCESS;
9,453,284✔
2643
}
2644

2645
static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
21✔
2646
  SBoundColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags));
21!
2647
  if (NULL == tags) {
21!
2648
    return terrno;
×
2649
  }
2650
  memcpy(tags, &pCxt->tags, sizeof(pCxt->tags));
21✔
2651

2652
  SStmtCallback* pStmtCb = pCxt->pComCxt->pStmtCb;
21✔
2653
  int32_t        code = (*pStmtCb->setInfoFn)(pStmtCb->pStmt, pStmt->pTableMeta, tags, &pStmt->targetTableName,
21✔
2654
                                       pStmt->usingTableProcessing, pStmt->pVgroupsHashObj, pStmt->pTableBlockHashObj,
21✔
2655
                                       pStmt->usingTableName.tname, pCxt->preCtbname);
21✔
2656

2657
  memset(&pCxt->tags, 0, sizeof(pCxt->tags));
20✔
2658
  pStmt->pVgroupsHashObj = NULL;
20✔
2659
  pStmt->pTableBlockHashObj = NULL;
20✔
2660
  return code;
20✔
2661
}
2662

2663
static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,375,789✔
2664
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) {
9,375,789✔
2665
    return setStmtInfo(pCxt, pStmt);
21✔
2666
  }
2667

2668
  // release old array alloced by merge
2669
  pStmt->freeArrayFunc(pStmt->pVgDataBlocks);
9,375,768✔
2670
  pStmt->pVgDataBlocks = NULL;
9,361,952✔
2671

2672
  bool fileOnly = (pStmt->insertType == TSDB_QUERY_TYPE_FILE_INSERT);
9,361,952✔
2673
  if (fileOnly) {
9,361,952✔
2674
    // none data, skip merge & buildvgdata
2675
    if (0 == taosHashGetSize(pStmt->pTableCxtHashObj)) {
4,337!
2676
      pCxt->needRequest = false;
×
2677
      return TSDB_CODE_SUCCESS;
×
2678
    }
2679
  }
2680

2681
  // merge according to vgId
2682
  int32_t code = insMergeTableDataCxt(fileOnly ? pStmt->pTableCxtHashObj : pStmt->pTableBlockHashObj,
9,357,637✔
2683
                                      &pStmt->pVgDataBlocks, pStmt->fileProcessing);
9,357,637✔
2684
  // clear tmp hashobj only
2685
  taosHashClear(pStmt->pTableCxtHashObj);
9,374,126✔
2686

2687
  if (TSDB_CODE_SUCCESS == code) {
9,375,000!
2688
    code = insBuildVgDataBlocks(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks, false);
9,376,950✔
2689
  }
2690

2691
  return code;
9,363,900✔
2692
}
2693

2694
// tb_name
2695
//     [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
2696
//     [(field1_name, ...)]
2697
//     VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
2698
// [...];
2699
static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,414,014✔
2700
  SToken  token;
2701
  int32_t code = TSDB_CODE_SUCCESS;
9,414,014✔
2702
  bool    hasData = true;
9,414,014✔
2703
  // for each table
2704
  while (TSDB_CODE_SUCCESS == code && hasData && !pCxt->missCache && !pStmt->fileProcessing) {
28,207,696✔
2705
    // pStmt->pSql -> tb_name ...
2706
    NEXT_TOKEN(pStmt->pSql, token);
18,817,888✔
2707
    code = checkTableClauseFirstToken(pCxt, pStmt, &token, &hasData);
18,837,487✔
2708
    if (TSDB_CODE_SUCCESS == code && hasData) {
18,808,787!
2709
      code = parseInsertTableClause(pCxt, pStmt, &token);
9,454,291✔
2710
    }
2711
  }
2712

2713
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
9,389,808!
2714
    code = parseInsertBodyBottom(pCxt, pStmt);
9,377,974✔
2715
  }
2716
  return code;
9,376,837✔
2717
}
2718

2719
static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); }
47,830!
2720

2721
static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, SNode** pOutput) {
9,382,744✔
2722
  SVnodeModifyOpStmt* pStmt = NULL;
9,382,744✔
2723
  int32_t             code = nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT, (SNode**)&pStmt);
9,382,744✔
2724
  if (NULL == pStmt) {
9,387,518!
2725
    return code;
×
2726
  }
2727

2728
  if (pCxt->pComCxt->pStmtCb) {
9,387,518✔
2729
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT);
22✔
2730
  }
2731
  pStmt->pSql = pCxt->pComCxt->pSql;
9,387,518✔
2732

2733
  pStmt->freeHashFunc = insDestroyTableDataCxtHashMap;
9,387,518✔
2734
  pStmt->freeArrayFunc = insDestroyVgroupDataCxtList;
9,387,518✔
2735
  pStmt->freeStbRowsCxtFunc = destroyStbRowsDataContext;
9,387,518✔
2736

2737
  if (!reentry) {
9,387,518!
2738
    pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
9,388,092✔
2739
    if (pCxt->pComCxt->pStmtCb) {
9,384,051✔
2740
      pStmt->pTableBlockHashObj =
22✔
2741
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
22✔
2742
    } else {
2743
      pStmt->pTableBlockHashObj =
9,382,744✔
2744
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
9,384,029✔
2745
    }
2746
  }
2747
  pStmt->pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
9,382,192✔
2748
  pStmt->pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
9,384,506✔
2749
  pStmt->pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
9,384,433✔
2750
  if ((!reentry && (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj)) ||
9,384,422!
2751
      NULL == pStmt->pSubTableHashObj || NULL == pStmt->pTableNameHashObj || NULL == pStmt->pDbFNameHashObj) {
9,384,663!
2752
    nodesDestroyNode((SNode*)pStmt);
×
2753
    return TSDB_CODE_OUT_OF_MEMORY;
×
2754
  }
2755

2756
  taosHashSetFreeFp(pStmt->pSubTableHashObj, destroySubTableHashElem);
9,385,460✔
2757

2758
  *pOutput = (SNode*)pStmt;
9,385,111✔
2759
  return TSDB_CODE_SUCCESS;
9,385,111✔
2760
}
2761

2762
static int32_t createInsertQuery(SInsertParseContext* pCxt, SQuery** pOutput) {
9,390,962✔
2763
  SQuery* pQuery = NULL;
9,390,962✔
2764
  int32_t code = nodesMakeNode(QUERY_NODE_QUERY, (SNode**)&pQuery);
9,390,962✔
2765
  if (NULL == pQuery) {
9,384,512!
2766
    return code;
×
2767
  }
2768

2769
  pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
9,384,512✔
2770
  pQuery->haveResultSet = false;
9,384,512✔
2771
  pQuery->msgType = TDMT_VND_SUBMIT;
9,384,512✔
2772

2773
  code = createVnodeModifOpStmt(pCxt, false, &pQuery->pRoot);
9,384,512✔
2774
  if (TSDB_CODE_SUCCESS == code) {
9,384,827!
2775
    *pOutput = pQuery;
9,384,886✔
2776
  } else {
UNCOV
2777
    nodesDestroyNode((SNode*)pQuery);
×
2778
  }
2779
  return code;
9,385,846✔
2780
}
2781

2782
static int32_t checkAuthFromMetaData(const SArray* pUsers, SNode** pTagCond) {
21,294✔
2783
  if (1 != taosArrayGetSize(pUsers)) {
21,294!
2784
    return TSDB_CODE_FAILED;
×
2785
  }
2786

2787
  SMetaRes* pRes = taosArrayGet(pUsers, 0);
21,294✔
2788
  if (TSDB_CODE_SUCCESS == pRes->code) {
21,293✔
2789
    SUserAuthRes* pAuth = pRes->pRes;
21,291✔
2790
    pRes->code = nodesCloneNode(pAuth->pCond[AUTH_RES_BASIC], pTagCond);
21,291✔
2791
    if (TSDB_CODE_SUCCESS == pRes->code) {
21,289!
2792
      return pAuth->pass[AUTH_RES_BASIC] ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED;
21,289✔
2793
    }
2794
  }
2795
  return pRes->code;
2✔
2796
}
2797

2798
static int32_t getTableMetaFromMetaData(const SArray* pTables, STableMeta** pMeta) {
21,285✔
2799
  if (1 != taosArrayGetSize(pTables)) {
21,285!
2800
    return TSDB_CODE_FAILED;
×
2801
  }
2802

2803
  taosMemoryFreeClear(*pMeta);
21,285!
2804
  SMetaRes* pRes = taosArrayGet(pTables, 0);
21,285✔
2805
  if (TSDB_CODE_SUCCESS == pRes->code) {
21,285✔
2806
    *pMeta = tableMetaDup((const STableMeta*)pRes->pRes);
20,780✔
2807
    if (NULL == *pMeta) {
20,781!
2808
      return TSDB_CODE_OUT_OF_MEMORY;
×
2809
    }
2810
  }
2811
  return pRes->code;
21,286✔
2812
}
2813

2814
static int32_t addTableVgroupFromMetaData(const SArray* pTables, SVnodeModifyOpStmt* pStmt, bool isStb) {
20,780✔
2815
  if (1 != taosArrayGetSize(pTables)) {
20,780!
2816
    return TSDB_CODE_FAILED;
×
2817
  }
2818

2819
  SMetaRes* pRes = taosArrayGet(pTables, 0);
20,779✔
2820
  if (TSDB_CODE_SUCCESS != pRes->code) {
20,779!
2821
    return pRes->code;
×
2822
  }
2823

2824
  SVgroupInfo* pVg = pRes->pRes;
20,779✔
2825
  if (isStb) {
20,779✔
2826
    pStmt->pTableMeta->vgId = pVg->vgId;
17✔
2827
  }
2828
  return taosHashPut(pStmt->pVgroupsHashObj, (const char*)&pVg->vgId, sizeof(pVg->vgId), (char*)pVg,
20,779✔
2829
                     sizeof(SVgroupInfo));
2830
}
2831

2832
static int32_t buildTagNameFromMeta(STableMeta* pMeta, SArray** pTagName) {
3✔
2833
  *pTagName = taosArrayInit(pMeta->tableInfo.numOfTags, TSDB_COL_NAME_LEN);
3✔
2834
  if (NULL == *pTagName) {
3!
2835
    return terrno;
×
2836
  }
2837
  SSchema* pSchema = getTableTagSchema(pMeta);
3✔
2838
  int32_t  code = 0;
3✔
2839
  for (int32_t i = 0; i < pMeta->tableInfo.numOfTags; ++i) {
9✔
2840
    if (NULL == taosArrayPush(*pTagName, pSchema[i].name)) {
12!
2841
      code = terrno;
×
2842
      taosArrayDestroy(*pTagName);
×
2843
      *pTagName = NULL;
×
2844
      break;
×
2845
    }
2846
  }
2847
  return code;
3✔
2848
}
2849

2850
static int32_t checkSubtablePrivilegeForTable(const SArray* pTables, SVnodeModifyOpStmt* pStmt) {
9✔
2851
  if (1 != taosArrayGetSize(pTables)) {
9✔
2852
    return TSDB_CODE_FAILED;
6✔
2853
  }
2854

2855
  SMetaRes* pRes = taosArrayGet(pTables, 0);
3✔
2856
  if (TSDB_CODE_SUCCESS != pRes->code) {
3!
2857
    return pRes->code;
×
2858
  }
2859

2860
  SArray* pTagName = NULL;
3✔
2861
  int32_t code = buildTagNameFromMeta(pStmt->pTableMeta, &pTagName);
3✔
2862
  if (TSDB_CODE_SUCCESS == code) {
3!
2863
    code = checkSubtablePrivilege((SArray*)pRes->pRes, pTagName, &pStmt->pTagCond);
3✔
2864
  }
2865
  taosArrayDestroy(pTagName);
3✔
2866
  return code;
3✔
2867
}
2868

2869
static int32_t processTableSchemaFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData,
20,780✔
2870
                                              SVnodeModifyOpStmt* pStmt, bool isStb) {
2871
  int32_t code = TSDB_CODE_SUCCESS;
20,780✔
2872
  if (!isStb && TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
20,780!
2873
    code = buildInvalidOperationMsg(&pCxt->msg, "insert data into super table is not supported");
×
2874
  }
2875
  if (TSDB_CODE_SUCCESS == code && isStb) {
20,780!
2876
    code = storeChildTableMeta(pCxt, pStmt);
17✔
2877
  }
2878
  if (TSDB_CODE_SUCCESS == code) {
20,780!
2879
    code = addTableVgroupFromMetaData(pMetaData->pTableHash, pStmt, isStb);
20,780✔
2880
  }
2881
  if (TSDB_CODE_SUCCESS == code && !isStb && NULL != pStmt->pTagCond) {
20,782!
2882
    code = checkSubtablePrivilegeForTable(pMetaData->pTableTag, pStmt);
9✔
2883
  }
2884
  return code;
20,782✔
2885
}
2886

2887
static void destoryTablesReq(void* p) {
42,587✔
2888
  STablesReq* pRes = (STablesReq*)p;
42,587✔
2889
  taosArrayDestroy(pRes->pTables);
42,587✔
2890
}
42,586✔
2891

2892
static void clearCatalogReq(SCatalogReq* pCatalogReq) {
21,294✔
2893
  if (NULL == pCatalogReq) {
21,294!
2894
    return;
×
2895
  }
2896

2897
  taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq);
21,294✔
2898
  pCatalogReq->pTableMeta = NULL;
21,294✔
2899
  taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq);
21,294✔
2900
  pCatalogReq->pTableHash = NULL;
21,294✔
2901
  taosArrayDestroy(pCatalogReq->pUser);
21,294✔
2902
  pCatalogReq->pUser = NULL;
21,294✔
2903
  taosArrayDestroy(pCatalogReq->pTableTag);
21,294✔
2904
  pCatalogReq->pTableTag = NULL;
21,294✔
2905
}
2906

2907
static int32_t setVnodeModifOpStmt(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
21,294✔
2908
                                   SVnodeModifyOpStmt* pStmt) {
2909
  clearCatalogReq(pCatalogReq);
21,294✔
2910
  int32_t code = checkAuthFromMetaData(pMetaData->pUser, &pStmt->pTagCond);
21,294✔
2911
  if (code == TSDB_CODE_SUCCESS) {
21,290✔
2912
    code = getTableMetaFromMetaData(pMetaData->pTableMeta, &pStmt->pTableMeta);
21,285✔
2913
  }
2914
  if (code == TSDB_CODE_SUCCESS) {
21,292✔
2915
    if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE && !pStmt->usingTableProcessing) {
20,781✔
2916
      pStmt->stbSyntax = true;
1✔
2917
    }
2918
    if (!pStmt->stbSyntax) {
20,781✔
2919
      if (pStmt->usingTableProcessing) {
20,780✔
2920
        return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, true);
17✔
2921
      }
2922
      return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, false);
20,763✔
2923
    }
2924
  }
2925
  return code;
512✔
2926
}
2927

2928
static int32_t resetVnodeModifOpStmt(SInsertParseContext* pCxt, SQuery* pQuery) {
×
2929
  nodesDestroyNode(pQuery->pRoot);
×
2930

2931
  int32_t code = createVnodeModifOpStmt(pCxt, true, &pQuery->pRoot);
×
2932
  if (TSDB_CODE_SUCCESS == code) {
×
2933
    SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
×
2934

2935
    code = (*pCxt->pComCxt->pStmtCb->getExecInfoFn)(pCxt->pComCxt->pStmtCb->pStmt, &pStmt->pVgroupsHashObj,
×
2936
                                                    &pStmt->pTableBlockHashObj);
2937
    if (TSDB_CODE_SUCCESS == code) {
×
2938
      if (NULL == pStmt->pVgroupsHashObj) {
×
2939
        pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
×
2940
      }
2941
      if (NULL == pStmt->pTableBlockHashObj) {
×
2942
        pStmt->pTableBlockHashObj =
×
2943
            taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
×
2944
      }
2945
      if (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj) {
×
2946
        code = TSDB_CODE_OUT_OF_MEMORY;
×
2947
      }
2948
    }
2949
  }
2950

2951
  return code;
×
2952
}
2953

2954
static int32_t initInsertQuery(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
9,413,605✔
2955
                               SQuery** pQuery) {
2956
  if (NULL == *pQuery) {
9,413,605✔
2957
    return createInsertQuery(pCxt, pQuery);
9,394,538✔
2958
  }
2959

2960
  if (NULL != pCxt->pComCxt->pStmtCb) {
19,067!
2961
    return resetVnodeModifOpStmt(pCxt, *pQuery);
×
2962
  }
2963

2964
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)(*pQuery)->pRoot;
19,067✔
2965

2966
  if (!pStmt->fileProcessing) {
19,067!
2967
    return setVnodeModifOpStmt(pCxt, pCatalogReq, pMetaData, pStmt);
21,294✔
2968
  }
2969

2970
  return TSDB_CODE_SUCCESS;
×
2971
}
2972

2973
static int32_t setRefreshMeta(SQuery* pQuery) {
9,340,716✔
2974
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
9,340,716✔
2975
  int32_t             code = 0;
9,340,716✔
2976

2977
  if (taosHashGetSize(pStmt->pTableNameHashObj) > 0) {
9,340,716✔
2978
    taosArrayDestroy(pQuery->pTableList);
498✔
2979
    pQuery->pTableList = taosArrayInit(taosHashGetSize(pStmt->pTableNameHashObj), sizeof(SName));
498✔
2980
    if (!pQuery->pTableList) {
499!
2981
      code = terrno;
×
2982
    } else {
2983
      SName* pTable = taosHashIterate(pStmt->pTableNameHashObj, NULL);
499✔
2984
      while (NULL != pTable) {
6,530✔
2985
        if (NULL == taosArrayPush(pQuery->pTableList, pTable)) {
12,064!
2986
          code = terrno;
×
2987
          taosHashCancelIterate(pStmt->pTableNameHashObj, pTable);
×
2988
          break;
×
2989
        }
2990
        pTable = taosHashIterate(pStmt->pTableNameHashObj, pTable);
6,032✔
2991
      }
2992
    }
2993
  }
2994

2995
  if (TSDB_CODE_SUCCESS == code && taosHashGetSize(pStmt->pDbFNameHashObj) > 0) {
9,297,069✔
2996
    taosArrayDestroy(pQuery->pDbList);
498✔
2997
    pQuery->pDbList = taosArrayInit(taosHashGetSize(pStmt->pDbFNameHashObj), TSDB_DB_FNAME_LEN);
498✔
2998
    if (!pQuery->pDbList) {
499!
2999
      code = terrno;
×
3000
    } else {
3001
      char* pDb = taosHashIterate(pStmt->pDbFNameHashObj, NULL);
499✔
3002
      while (NULL != pDb) {
×
3003
        if (NULL == taosArrayPush(pQuery->pDbList, pDb)) {
1,002!
3004
          code = terrno;
×
3005
          taosHashCancelIterate(pStmt->pDbFNameHashObj, pDb);
×
3006
          break;
×
3007
        }
3008
        pDb = taosHashIterate(pStmt->pDbFNameHashObj, pDb);
501✔
3009
      }
3010
    }
3011
  }
3012

3013
  return code;
9,288,300✔
3014
}
3015

3016
// INSERT INTO
3017
//   tb_name
3018
//       [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]]
3019
//       [(field1_name, ...)]
3020
//       VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
3021
//   [...];
3022
static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,386,188✔
3023
  int32_t code = skipInsertInto(&pStmt->pSql, &pCxt->msg);
9,386,188✔
3024
  if (TSDB_CODE_SUCCESS == code) {
9,395,368!
3025
    code = parseInsertBody(pCxt, pStmt);
9,395,572✔
3026
  }
3027
  return code;
9,346,005✔
3028
}
3029

3030
static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
×
3031
  int32_t          code = TSDB_CODE_SUCCESS;
×
3032
  SRowsDataContext rowsDataCxt;
3033

3034
  if (!pStmt->stbSyntax) {
×
3035
    STableDataCxt* pTableCxt = NULL;
×
3036
    code = getTableDataCxt(pCxt, pStmt, &pTableCxt);
×
3037
    rowsDataCxt.pTableDataCxt = pTableCxt;
×
3038
  } else {
3039
    rowsDataCxt.pStbRowsCxt = pStmt->pStbRowsCxt;
×
3040
  }
3041
  if (TSDB_CODE_SUCCESS == code) {
×
3042
    code = parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
×
3043
  }
3044

3045
  if (TSDB_CODE_SUCCESS == code) {
×
3046
    if (pStmt->fileProcessing) {
×
3047
      code = parseInsertBodyBottom(pCxt, pStmt);
×
3048
    } else {
3049
      code = parseInsertBody(pCxt, pStmt);
×
3050
    }
3051
  }
3052

3053
  return code;
×
3054
}
3055

3056
static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
20,777✔
3057
  int32_t code = parseInsertTableClauseBottom(pCxt, pStmt);
20,777✔
3058
  if (TSDB_CODE_SUCCESS == code) {
20,776✔
3059
    code = parseInsertBody(pCxt, pStmt);
20,764✔
3060
  }
3061
  return code;
20,774✔
3062
}
3063

3064
static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
9,407,193✔
3065
  if (pStmt->pSql == pCxt->pComCxt->pSql || NULL != pCxt->pComCxt->pStmtCb) {
9,407,193!
3066
    return parseInsertSqlFromStart(pCxt, pStmt);
9,386,416✔
3067
  }
3068

3069
  if (pStmt->fileProcessing) {
20,777!
3070
    return parseInsertSqlFromCsv(pCxt, pStmt);
×
3071
  }
3072

3073
  return parseInsertSqlFromTable(pCxt, pStmt);
20,777✔
3074
}
3075

3076
static int32_t buildInsertTableReq(SName* pName, SArray** pTables) {
43,253✔
3077
  *pTables = taosArrayInit(1, sizeof(SName));
43,253✔
3078
  if (NULL == *pTables) {
43,253!
3079
    return terrno;
×
3080
  }
3081

3082
  if (NULL == taosArrayPush(*pTables, pName)) {
86,507!
3083
    taosArrayDestroy(*pTables);
×
3084
    *pTables = NULL;
×
3085
    return terrno;
×
3086
  }
3087
  return TSDB_CODE_SUCCESS;
43,254✔
3088
}
3089

3090
static int32_t buildInsertDbReq(SName* pName, SArray** pDbs) {
43,245✔
3091
  if (NULL == *pDbs) {
43,245!
3092
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
43,248✔
3093
    if (NULL == *pDbs) {
43,249!
3094
      return terrno;
×
3095
    }
3096
  }
3097

3098
  STablesReq req = {0};
43,246✔
3099
  (void)tNameGetFullDbName(pName, req.dbFName);
43,246✔
3100
  int32_t code = buildInsertTableReq(pName, &req.pTables);
43,252✔
3101
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
86,504!
3102
    code = TSDB_CODE_OUT_OF_MEMORY;
×
3103
  }
3104

3105
  return code;
43,252✔
3106
}
3107

3108
static int32_t buildInsertUserAuthReq(const char* pUser, SName* pName, SArray** pUserAuth) {
21,624✔
3109
  *pUserAuth = taosArrayInit(1, sizeof(SUserAuthInfo));
21,624✔
3110
  if (NULL == *pUserAuth) {
21,623!
3111
    return terrno;
×
3112
  }
3113

3114
  SUserAuthInfo userAuth = {.type = AUTH_TYPE_WRITE};
21,623✔
3115
  snprintf(userAuth.user, sizeof(userAuth.user), "%s", pUser);
21,623✔
3116
  memcpy(&userAuth.tbName, pName, sizeof(SName));
21,623✔
3117
  if (NULL == taosArrayPush(*pUserAuth, &userAuth)) {
43,246!
3118
    taosArrayDestroy(*pUserAuth);
×
3119
    *pUserAuth = NULL;
×
3120
    return terrno;
×
3121
  }
3122

3123
  return TSDB_CODE_SUCCESS;
21,623✔
3124
}
3125

3126
static int32_t buildInsertTableTagReq(SName* pName, SArray** pTables) { return buildInsertTableReq(pName, pTables); }
3✔
3127

3128
static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SCatalogReq* pCatalogReq) {
21,627✔
3129
  int32_t code = buildInsertUserAuthReq(
21,627✔
3130
      pCxt->pComCxt->pUser, (0 == pStmt->usingTableName.type ? &pStmt->targetTableName : &pStmt->usingTableName),
43,254✔
3131
      &pCatalogReq->pUser);
3132
  if (TSDB_CODE_SUCCESS == code && pCxt->needTableTagVal) {
21,625!
3133
    code = buildInsertTableTagReq(&pStmt->targetTableName, &pCatalogReq->pTableTag);
3✔
3134
  }
3135
  if (TSDB_CODE_SUCCESS == code) {
21,625!
3136
    if (0 == pStmt->usingTableName.type) {
21,626✔
3137
      code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableMeta);
21,598✔
3138
    } else {
3139
      code = buildInsertDbReq(&pStmt->usingTableName, &pCatalogReq->pTableMeta);
28✔
3140
    }
3141
  }
3142
  if (TSDB_CODE_SUCCESS == code) {
21,626!
3143
    code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableHash);
21,627✔
3144
  }
3145
  return code;
21,627✔
3146
}
3147

3148
static int32_t setNextStageInfo(SInsertParseContext* pCxt, SQuery* pQuery, SCatalogReq* pCatalogReq) {
9,367,466✔
3149
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
9,367,466✔
3150
  if (pCxt->missCache) {
9,367,466✔
3151
    parserDebug("0x%" PRIx64 " %d rows of %d tables have been inserted before cache miss", pCxt->pComCxt->requestId,
21,627✔
3152
                pStmt->totalRowsNum, pStmt->totalTbNum);
3153

3154
    pQuery->execStage = QUERY_EXEC_STAGE_PARSE;
21,627✔
3155
    return buildInsertCatalogReq(pCxt, pStmt, pCatalogReq);
21,627✔
3156
  }
3157

3158
  parserDebug("0x%" PRIx64 " %d rows of %d tables have been inserted", pCxt->pComCxt->requestId, pStmt->totalRowsNum,
9,345,839✔
3159
              pStmt->totalTbNum);
3160

3161
  pQuery->execStage = QUERY_EXEC_STAGE_SCHEDULE;
9,358,633✔
3162
  return TSDB_CODE_SUCCESS;
9,358,633✔
3163
}
3164

3165
int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) {
9,411,978✔
3166
  SInsertParseContext context = {.pComCxt = pCxt,
18,823,956✔
3167
                                 .msg = {.buf = pCxt->pMsg, .len = pCxt->msgLen},
9,411,978✔
3168
                                 .missCache = false,
3169
                                 .usingDuplicateTable = false,
3170
                                 .needRequest = true,
3171
                                 .forceUpdate = (NULL != pCatalogReq ? pCatalogReq->forceUpdate : false),
9,411,978!
3172
                                 .isStmtBind = pCxt->isStmtBind};
9,411,978✔
3173

3174
  int32_t             code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery);
9,411,978✔
3175
  if (TSDB_CODE_SUCCESS == code) {
9,408,001✔
3176
    code = parseInsertSqlImpl(&context, (SVnodeModifyOpStmt*)((*pQuery)->pRoot));
9,407,574✔
3177
  }
3178
  if (TSDB_CODE_SUCCESS == code) {
9,365,628!
3179
    code = setNextStageInfo(&context, *pQuery, pCatalogReq);
9,372,847✔
3180
  }
3181
  if ((TSDB_CODE_SUCCESS == code || NEED_CLIENT_HANDLE_ERROR(code)) &&
9,371,317!
3182
      QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) {
9,370,330✔
3183
    code = setRefreshMeta(*pQuery);
9,343,293✔
3184
  }
3185

3186
  insDestroyBoundColInfo(&context.tags);
9,316,244✔
3187
  // if no data to insert, set emptyMode to avoid request server
3188
  if (!context.needRequest) {
9,312,210!
3189
    (*pQuery)->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
×
3190
  }
3191
  return code;
9,312,210✔
3192
}
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