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

taosdata / TDengine / #3768

28 Mar 2025 10:15AM UTC coverage: 33.726% (-0.3%) from 33.993%
#3768

push

travis-ci

happyguoxy
test:alter lcov result

144891 of 592084 branches covered (24.47%)

Branch coverage included in aggregate %.

218795 of 486283 relevant lines covered (44.99%)

765715.29 hits per line

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

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

16
#include "geosWrapper.h"
17
#include "parInsertUtil.h"
18
#include "parToken.h"
19
#include "scalar.h"
20
#include "tglobal.h"
21
#include "ttime.h"
22
#include "decimal.h"
23

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

38
typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param);
39
static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt);
40
static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool autoCreate);
41

42
static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
43
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;
44

45
static FORCE_INLINE bool isNullValue(int8_t dataType, SToken* pToken) {
46
  return TK_NULL == pToken->type ||
298,164,058✔
47
         (TK_NK_STRING == pToken->type && !IS_STR_DATA_TYPE(dataType) && IS_NULL_STR(pToken->z, pToken->n));
299,669,529!
48
}
49

50
static FORCE_INLINE int32_t toDouble(SToken* pToken, double* value, char** endPtr) {
51
  SET_ERRNO(0);
52
  *value = taosStr2Double(pToken->z, endPtr);
53

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

59
  return pToken->type;
60
}
61

62
static int32_t skipInsertInto(const char** pSql, SMsgBuf* pMsg) {
99,361✔
63
  SToken token;
64
  NEXT_TOKEN(*pSql, token);
99,361✔
65
  if (TK_INSERT != token.type && TK_IMPORT != token.type) {
99,365!
66
    return buildSyntaxErrMsg(pMsg, "keyword INSERT is expected", token.z);
×
67
  }
68
  NEXT_TOKEN(*pSql, token);
99,365✔
69
  if (TK_INTO != token.type) {
99,364!
70
    return buildSyntaxErrMsg(pMsg, "keyword INTO is expected", token.z);
71
  }
72
  return TSDB_CODE_SUCCESS;
99,366✔
73
}
74

75
static int32_t skipParentheses(SInsertParseContext* pCxt, const char** pSql) {
729✔
76
  SToken  token;
77
  int32_t expectRightParenthesis = 1;
729✔
78
  while (1) {
79
    NEXT_TOKEN(*pSql, token);
10,585✔
80
    if (TK_NK_LP == token.type) {
10,585!
81
      ++expectRightParenthesis;
×
82
    } else if (TK_NK_RP == token.type && 0 == --expectRightParenthesis) {
10,585!
83
      break;
729✔
84
    }
85
    if (0 == token.n) {
9,856!
86
      return buildSyntaxErrMsg(&pCxt->msg, ") expected", NULL);
×
87
    }
88
  }
89
  return TSDB_CODE_SUCCESS;
729✔
90
}
91

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

107
// pSql -> stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)
108
static int32_t ignoreUsingClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
×
109
  const char** pSql = &pStmt->pSql;
×
110
  int32_t code = TSDB_CODE_SUCCESS;
×
111
  SToken  token;
112
  NEXT_TOKEN(*pSql, token);
×
113

114
  NEXT_TOKEN(*pSql, token);
×
115
  if (TK_NK_LP == token.type) {
×
116
    code = skipParentheses(pCxt, pSql);
×
117
    if (TSDB_CODE_SUCCESS == code) {
×
118
      NEXT_TOKEN(*pSql, token);
×
119
    }
120
  }
121

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

138
  if (TSDB_CODE_SUCCESS == code) {
×
139
    code = skipTableOptions(pCxt, pSql);
×
140
  }
141

142
  return code;
×
143
}
144

145
static int32_t ignoreUsingClauseAndCheckTagValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
13,044✔
146
  const char** pSql = &pStmt->pSql;
13,044✔
147
  int32_t      code = TSDB_CODE_SUCCESS;
13,044✔
148
  code = parseBoundTagsClause(pCxt, pStmt);
13,044✔
149
  if (TSDB_CODE_SUCCESS != code) {
13,044!
150
    return code;
×
151
  }
152
  // pSql -> TAGS (tag1_value, ...)
153
  code = parseTagsClause(pCxt, pStmt, true);
13,044✔
154
  if (TSDB_CODE_SUCCESS != code) {
13,044!
155
    return code;
×
156
  }
157

158
  if (TSDB_CODE_SUCCESS == code) {
13,044!
159
    code = skipTableOptions(pCxt, pSql);
13,044✔
160
  }
161

162
  return code;
13,044✔
163
}
164

165
static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pDuplicate) {
13,134✔
166
  int32_t code = TSDB_CODE_SUCCESS;
13,134✔
167
  *pDuplicate = false;
13,134✔
168

169
  char tbFName[TSDB_TABLE_FNAME_LEN];
170
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
13,134✔
171
  if (TSDB_CODE_SUCCESS != code) {
13,134!
172
    return code;
×
173
  }
174
  STableMeta** pMeta = taosHashGet(pStmt->pSubTableHashObj, tbFName, strlen(tbFName));
13,134✔
175
  if (NULL != pMeta) {
13,134!
176
    *pDuplicate = true;
×
177
    pCxt->missCache = false;
×
178
    code = cloneTableMeta(*pMeta, &pStmt->pTableMeta);
×
179
    if (TSDB_CODE_SUCCESS != code) {
×
180
      return code;
×
181
    }
182
    return ignoreUsingClause(pCxt, pStmt);
×
183
  }
184

185
  return code;
13,134✔
186
}
187

188
typedef enum { BOUND_TAGS, BOUND_COLUMNS, BOUND_ALL_AND_TBNAME } EBoundColumnsType;
189

190
static int32_t getTbnameSchemaIndex(STableMeta* pTableMeta) {
983✔
191
  return pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns;
983✔
192
}
193

194
// pStmt->pSql -> field1_name, ...)
195
static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, EBoundColumnsType boundColsType,
795✔
196
                                 STableMeta* pTableMeta, SBoundColInfo* pBoundInfo) {
197
  SSchema* pSchema = NULL;
795✔
198
  if (boundColsType == BOUND_TAGS) {
795✔
199
    pSchema = getTableTagSchema(pTableMeta);
40✔
200
  } else if (boundColsType == BOUND_COLUMNS) {
755✔
201
    pSchema = getTableColumnSchema(pTableMeta);
729✔
202
  } else {
203
    pSchema = pTableMeta->schema;
26✔
204
    if (pBoundInfo->numOfCols != getTbnameSchemaIndex(pTableMeta) + 1) {
26!
205
      return TSDB_CODE_PAR_INTERNAL_ERROR;
×
206
    }
207
  }
208
  int32_t tbnameSchemaIndex = getTbnameSchemaIndex(pTableMeta);
795✔
209

210
  bool* pUseCols = taosMemoryCalloc(pBoundInfo->numOfCols, sizeof(bool));
795!
211
  if (NULL == pUseCols) {
795!
212
    return terrno;
×
213
  }
214

215
  pBoundInfo->numOfBound = 0;
795✔
216
  pBoundInfo->hasBoundCols = true;
795✔
217

218
  bool    hasPK = pTableMeta->tableInfo.numOfPKs;
795✔
219
  int16_t numOfBoundPKs = 0;
795✔
220
  int16_t lastColIdx = -1;  // last column found
795✔
221
  int32_t code = TSDB_CODE_SUCCESS;
795✔
222
  while (TSDB_CODE_SUCCESS == code) {
10,782!
223
    SToken token;
224
    NEXT_TOKEN(*pSql, token);
10,782✔
225

226
    if (TK_NK_RP == token.type) {
10,782✔
227
      break;
795✔
228
    }
229

230
    char tmpTokenBuf[TSDB_COL_NAME_LEN + 2] = {0};  // used for deleting Escape character backstick(`)
9,987✔
231
    strncpy(tmpTokenBuf, token.z, token.n);
9,987✔
232
    token.z = tmpTokenBuf;
9,987✔
233
    token.n = strdequote(token.z);
9,987✔
234

235
    if (boundColsType == BOUND_ALL_AND_TBNAME && token.n == strlen("tbname") && (strcasecmp(token.z, "tbname") == 0)) {
9,987!
236
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = tbnameSchemaIndex;
25✔
237
      pUseCols[tbnameSchemaIndex] = true;
25✔
238
      ++pBoundInfo->numOfBound;
25✔
239
      continue;
25✔
240
    }
241
    int16_t t = lastColIdx + 1;
9,962✔
242
    int16_t end = (boundColsType == BOUND_ALL_AND_TBNAME) ? (pBoundInfo->numOfCols - 1) : pBoundInfo->numOfCols;
9,962✔
243
    int16_t index = insFindCol(&token, t, end, pSchema);
9,962✔
244
    if (index < 0 && t > 0) {
9,962!
245
      index = insFindCol(&token, 0, t, pSchema);
19✔
246
    }
247
    if (index < 0) {
9,962!
248
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z);
×
249
    } else if (pUseCols[index]) {
9,962!
250
      code = buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z);
×
251
    } else {
252
      lastColIdx = index;
9,962✔
253
      pUseCols[index] = true;
9,962✔
254
      pBoundInfo->pColIndex[pBoundInfo->numOfBound] = index;
9,962✔
255
      ++pBoundInfo->numOfBound;
9,962✔
256
      if (hasPK && (pSchema[index].flags & COL_IS_KEY)) ++numOfBoundPKs;
9,962✔
257
    }
258
  }
259

260
  if (TSDB_CODE_SUCCESS == code && (BOUND_TAGS != boundColsType)) {
795!
261
    if (!pUseCols[0]) {
755✔
262
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary timestamp column should not be null");
3✔
263
    }
264
    if (numOfBoundPKs != pTableMeta->tableInfo.numOfPKs) {
755!
265
      code = buildInvalidOperationMsg(&pCxt->msg, "Primary key column should not be none");
×
266
    }
267
  }
268
  if (TSDB_CODE_SUCCESS == code && (BOUND_ALL_AND_TBNAME == boundColsType) && !pUseCols[tbnameSchemaIndex]) {
795✔
269
    code = buildInvalidOperationMsg(&pCxt->msg, "tbname column should not be null");
1✔
270
  }
271
  taosMemoryFree(pUseCols);
795!
272

273
  return code;
795✔
274
}
275

276
static int32_t parseTimestampOrInterval(const char** end, SToken* pToken, int16_t timePrec, int64_t* ts, int64_t* interval,
28,492,329✔
277
                                    SMsgBuf* pMsgBuf, bool* isTs, timezone_t tz) {
278
  if (pToken->type == TK_NOW) {
28,492,329✔
279
    *isTs = true;
750,681✔
280
    *ts = taosGetTimestamp(timePrec);
1,501,362✔
281
  } else if (pToken->type == TK_TODAY) {
27,741,648!
282
    *isTs = true;
×
283
    *ts = taosGetTimestampToday(timePrec, tz);
×
284
  } else if (pToken->type == TK_NK_INTEGER) {
27,741,648!
285
    *isTs = true;
27,762,901✔
286
    if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, ts)) {
27,762,901!
287
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
288
    }
289
  } else if (pToken->type == TK_NK_VARIABLE) {
25,442!
290
    char unit = 0;
25,442✔
291
    *isTs = false;
25,442✔
292
    if (parseAbsoluteDuration(pToken->z, pToken->n, interval, &unit, timePrec) != TSDB_CODE_SUCCESS) {
25,442!
293
      return TSDB_CODE_TSC_INVALID_OPERATION;
×
294
    }
295
  } else {  // parse the RFC-3339/ISO-8601 timestamp format string
296
    *isTs = true;
297
    if (taosParseTime(pToken->z, ts, pToken->n, timePrec, tz) != TSDB_CODE_SUCCESS) {
129,730!
298
      if ((pToken->n == 0) ||
129,730✔
299
          (pToken->type != TK_NK_STRING && pToken->type != TK_NK_HEX && pToken->type != TK_NK_BIN)) {
25!
300
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
129,705✔
301
      }
302
      if (IS_NOW_STR(pToken->z, pToken->n)) {
25!
303
        *isTs = true;
×
304
        *ts = taosGetTimestamp(timePrec);
×
305
      } else if (IS_TODAY_STR(pToken->z, pToken->n)) {
25!
306
        *isTs = true;
×
307
        *ts = taosGetTimestampToday(timePrec, tz);
×
308
      } else if (TSDB_CODE_SUCCESS == toIntegerPure(pToken->z, pToken->n, 10, ts)) {
25!
309
        *isTs = true;
×
310
      } else {
311
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
25✔
312
      }
313
    }
314
  }
315

316
  return TSDB_CODE_SUCCESS;
28,511,484✔
317
}
318

319
static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf, timezone_t tz) {
28,494,098✔
320
  int32_t     index = 0, i = 0;
28,494,098✔
321
  int64_t     interval = 0, tempInterval = 0;
28,494,098✔
322
  int64_t     ts = 0, tempTs = 0;
28,494,098✔
323
  bool        firstIsTS = false, secondIsTs = false;
28,494,098✔
324
  const char* pTokenEnd = *end;
28,494,098✔
325

326
  if (TSDB_CODE_SUCCESS !=
28,536,208!
327
      parseTimestampOrInterval(&pTokenEnd, pToken, timePrec, &ts, &interval, pMsgBuf, &firstIsTS, tz)) {
28,494,098✔
328
    return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
329
  }
330

331
  if (firstIsTS) {
28,570,817✔
332
    *time = ts;
28,552,822✔
333
  }
334

335
  for (int k = pToken->n; pToken->z[k] != '\0'; k++) {
28,582,272!
336
    if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue;
28,625,831!
337
    if (pToken->z[k] == '(') {  // for insert NOW()/TODAY()
28,614,593✔
338
      if (pToken->z[k + 1] == ')') {
217!
339
        *end = pTokenEnd = &pToken->z[k + 2];
217✔
340
        ++k;
217✔
341
        continue;
217✔
342
      } else {
343
        char nc = pToken->z[k + 1];
×
344
        while (nc == ' ' || nc == '\t' || nc == '\n' || nc == '\r' || nc == '\f') {
×
345
          nc = pToken->z[(++k) + 1];
×
346
        }
347
        if (nc == ')') {
×
348
          *end = pTokenEnd = &pToken->z[k + 2];
×
349
          ++k;
×
350
          continue;
×
351
        }
352
      }
353
    }
354
    if (pToken->z[k] == ',') {
28,614,376✔
355
      *end = pTokenEnd;
27,425,230✔
356
      if (!firstIsTS) {
27,425,230!
357
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
358
      }
359
      *time = ts;
27,425,230✔
360
      return TSDB_CODE_SUCCESS;
27,425,230✔
361
    }
362
    break;
1,189,146✔
363
  }
364

365
  while (pTokenEnd[i] != '\0') {
1,156,711!
366
    if (pTokenEnd[i] == ' ' || pTokenEnd[i] == '\t') {
1,160,942!
367
      i++;
11,124✔
368
      continue;
11,124✔
369
    } else if (pTokenEnd[i] == ',' || pTokenEnd[i] == ')') {
1,149,818✔
370
      *end = pTokenEnd + i;
1,124,376✔
371
      if (!firstIsTS) {
1,124,376!
372
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
373
      }
374
      *time = ts;
1,124,376✔
375
      return TSDB_CODE_SUCCESS;
1,124,376✔
376
    } else {
377
      break;
378
    }
379
  }
380
  pTokenEnd = pTokenEnd + i;
21,211✔
381

382
  index = 0;
21,211✔
383
  SToken token = tStrGetToken(pTokenEnd, &index, false, NULL);
21,211✔
384

385
  if (token.type == TK_NK_MINUS || token.type == TK_NK_PLUS) {
26,459✔
386
    pTokenEnd += index;
25,442✔
387
    index = 0;
25,442✔
388
    SToken valueToken = tStrGetToken(pTokenEnd, &index, false, NULL);
25,442✔
389
    pTokenEnd += index;
25,442✔
390
    char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW];
391
    if (TK_NK_STRING == valueToken.type) {
25,442!
392
      if (valueToken.n >= TSDB_MAX_BYTES_PER_ROW) {
×
393
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", valueToken.z);
25,438✔
394
      }
395
      int32_t len = trimString(valueToken.z, valueToken.n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
×
396
      valueToken.z = tmpTokenBuf;
×
397
      valueToken.n = len;
×
398
    }
399

400
    if (TSDB_CODE_SUCCESS !=
25,442!
401
        parseTimestampOrInterval(&pTokenEnd, &valueToken, timePrec, &tempTs, &tempInterval, pMsgBuf, &secondIsTs, tz)) {
25,442✔
402
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
403
    }
404

405
    if (valueToken.n < 2) {
25,442!
406
      return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", token.z);
×
407
    }
408

409
    if (secondIsTs) {
25,442!
410
      // not support operator between tow timestamp, such as today() + now()
411
      if (firstIsTS) {
×
412
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
413
      }
414
      ts = tempTs;
×
415
    } else {
416
      // not support operator between tow interval, such as 2h + 3s
417
      if (!firstIsTS) {
25,442!
418
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
419
      }
420
      interval = tempInterval;
25,442✔
421
    }
422
    if (token.type == TK_NK_MINUS) {
25,442✔
423
      // not support interval - ts,such as 2h - today()
424
      if (secondIsTs) {
71!
425
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
426
      }
427
      *time = ts - interval;
71✔
428
    } else {
429
      *time = ts + interval;
25,371✔
430
    }
431

432
    for (int k = valueToken.n; valueToken.z[k] != '\0'; k++) {
25,502✔
433
      if (valueToken.z[k] == ' ' || valueToken.z[k] == '\t') continue;
25,498!
434
      if (valueToken.z[k] == '(' && valueToken.z[k + 1] == ')') {  // for insert NOW()/TODAY()
25,438!
435
        *end = pTokenEnd = &valueToken.z[k + 2];
×
436
        k++;
×
437
        continue;
×
438
      }
439
      if (valueToken.z[k] == ',' || valueToken.z[k] == ')') {
25,438!
440
        *end = pTokenEnd;
25,438✔
441
        return TSDB_CODE_SUCCESS;
25,438✔
442
      }
443
      return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z);
×
444
    }
445
  }
446

447
  *end = pTokenEnd;
1,021✔
448
  return TSDB_CODE_SUCCESS;
1,021✔
449
}
450

451
// need to call geosFreeBuffer(*output) later
452
static int parseGeometry(SToken* pToken, unsigned char** output, size_t* size) {
204✔
453
#ifdef USE_GEOS
454
  int32_t code = TSDB_CODE_FAILED;
204✔
455

456
  //[ToDo] support to parse WKB as well as WKT
457
  if (pToken->type == TK_NK_STRING) {
204!
458
    code = initCtxGeomFromText();
204✔
459
    if (code != TSDB_CODE_SUCCESS) {
204!
460
      return code;
×
461
    }
462

463
    code = doGeomFromText(pToken->z, output, size);
204✔
464
    if (code != TSDB_CODE_SUCCESS) {
204!
465
      return code;
×
466
    }
467
  }
468

469
  return code;
204✔
470
#else
471
  TAOS_RETURN(TSDB_CODE_OPS_NOT_SUPPORT);
472
#endif
473
}
474

475
static int32_t parseVarbinary(SToken* pToken, uint8_t** pData, uint32_t* nData, int32_t bytes) {
204✔
476
  if (pToken->type != TK_NK_STRING) {
204!
477
    return TSDB_CODE_PAR_INVALID_VARBINARY;
×
478
  }
479

480
  if (isHex(pToken->z + 1, pToken->n - 2)) {
204✔
481
    if (!isValidateHex(pToken->z + 1, pToken->n - 2)) {
2!
482
      return TSDB_CODE_PAR_INVALID_VARBINARY;
×
483
    }
484

485
    void*    data = NULL;
2✔
486
    uint32_t size = 0;
2✔
487
    if (taosHex2Ascii(pToken->z + 1, pToken->n - 2, &data, &size) < 0) {
2!
488
      return TSDB_CODE_OUT_OF_MEMORY;
×
489
    }
490

491
    if (size + VARSTR_HEADER_SIZE > bytes) {
2!
492
      taosMemoryFree(data);
×
493
      return TSDB_CODE_PAR_VALUE_TOO_LONG;
×
494
    }
495
    *pData = data;
2✔
496
    *nData = size;
2✔
497
  } else {
498
    *pData = taosMemoryCalloc(1, pToken->n);
202!
499
    if (!pData) return terrno;
202!
500
    int32_t len = trimString(pToken->z, pToken->n, *pData, pToken->n);
202✔
501
    *nData = len;
202✔
502

503
    if (*nData + VARSTR_HEADER_SIZE > bytes) {
202!
504
      return TSDB_CODE_PAR_VALUE_TOO_LONG;
×
505
    }
506
  }
507
  return TSDB_CODE_SUCCESS;
204✔
508
}
509

510
static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val,
50,760✔
511
                             SMsgBuf* pMsgBuf, timezone_t tz, void *charsetCxt) {
512
  int64_t  iv;
513
  uint64_t uv;
514
  char*    endptr = NULL;
50,760✔
515
  int32_t  code = TSDB_CODE_SUCCESS;
50,760✔
516

517
#if 0
518
  if (isNullValue(pSchema->type, pToken)) {
519
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
520
      return buildSyntaxErrMsg(pMsgBuf, "Primary timestamp column can not be null", pToken->z);
521
    }
522

523
    return TSDB_CODE_SUCCESS;
524
  }
525
#endif
526

527
  //  strcpy(val->colName, pSchema->name);
528
  val->cid = pSchema->colId;
50,760✔
529
  val->type = pSchema->type;
50,760✔
530

531
  switch (pSchema->type) {
50,760!
532
    case TSDB_DATA_TYPE_BOOL: {
1,067✔
533
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
1,067!
534
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
1,062!
535
          *(int8_t*)(&val->i64) = TRUE_VALUE;
1,044✔
536
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
18!
537
          *(int8_t*)(&val->i64) = FALSE_VALUE;
18✔
538
        } else if (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv)) {
×
539
          *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
×
540
        } else {
541
          return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
×
542
        }
543
      } else if (pToken->type == TK_NK_INTEGER) {
5!
544
        *(int8_t*)(&val->i64) = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
5✔
545
      } else if (pToken->type == TK_NK_FLOAT) {
×
546
        *(int8_t*)(&val->i64) = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
×
547
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
×
548
                 (TSDB_CODE_SUCCESS == toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&iv))) {
×
549
        *(int8_t*)(&val->i64) = (*(double*)&iv == 0 ? FALSE_VALUE : TRUE_VALUE);
×
550
      } else {
551
        return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z);
×
552
      }
553
      break;
1,067✔
554
    }
555

556
    case TSDB_DATA_TYPE_TINYINT: {
1,402✔
557
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
1,402✔
558
      if (TSDB_CODE_SUCCESS != code) {
1,402!
559
        return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z);
×
560
      } else if (!IS_VALID_TINYINT(iv)) {
1,402!
561
        return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z);
×
562
      }
563

564
      *(int8_t*)(&val->i64) = iv;
1,402✔
565
      break;
1,402✔
566
    }
567

568
    case TSDB_DATA_TYPE_UTINYINT: {
1,067✔
569
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,067✔
570
      if (TSDB_CODE_SUCCESS != code) {
1,067!
571
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z);
×
572
      } else if (uv > UINT8_MAX) {
1,067!
573
        return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z);
×
574
      }
575
      *(uint8_t*)(&val->i64) = uv;
1,067✔
576
      break;
1,067✔
577
    }
578

579
    case TSDB_DATA_TYPE_SMALLINT: {
1,069✔
580
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
1,069✔
581
      if (TSDB_CODE_SUCCESS != code) {
1,069!
582
        return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z);
×
583
      } else if (!IS_VALID_SMALLINT(iv)) {
1,069!
584
        return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z);
×
585
      }
586
      *(int16_t*)(&val->i64) = iv;
1,069✔
587
      break;
1,069✔
588
    }
589

590
    case TSDB_DATA_TYPE_USMALLINT: {
1,067✔
591
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,067✔
592
      if (TSDB_CODE_SUCCESS != code) {
1,067!
593
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z);
×
594
      } else if (uv > UINT16_MAX) {
1,067!
595
        return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z);
×
596
      }
597
      *(uint16_t*)(&val->i64) = uv;
1,067✔
598
      break;
1,067✔
599
    }
600

601
    case TSDB_DATA_TYPE_INT: {
18,326✔
602
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
18,326✔
603
      if (TSDB_CODE_SUCCESS != code) {
18,325✔
604
        return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z);
1✔
605
      } else if (!IS_VALID_INT(iv)) {
18,324!
606
        return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z);
607
      }
608
      *(int32_t*)(&val->i64) = iv;
18,326✔
609
      break;
18,326✔
610
    }
611

612
    case TSDB_DATA_TYPE_UINT: {
1,107✔
613
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,107✔
614
      if (TSDB_CODE_SUCCESS != code) {
1,107!
615
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z);
×
616
      } else if (uv > UINT32_MAX) {
1,107!
617
        return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z);
×
618
      }
619
      *(uint32_t*)(&val->i64) = uv;
1,107✔
620
      break;
1,107✔
621
    }
622

623
    case TSDB_DATA_TYPE_BIGINT: {
1,680✔
624
      code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
1,680✔
625
      if (TSDB_CODE_SUCCESS != code) {
1,680!
626
        return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z);
×
627
      }
628
      val->i64 = iv;
1,680✔
629
      break;
1,680✔
630
    }
631

632
    case TSDB_DATA_TYPE_UBIGINT: {
1,069✔
633
      code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
1,069✔
634
      if (TSDB_CODE_SUCCESS != code) {
1,069!
635
        return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z);
×
636
      }
637
      *(uint64_t*)(&val->i64) = uv;
1,069✔
638
      break;
1,069✔
639
    }
640

641
    case TSDB_DATA_TYPE_FLOAT: {
1,372✔
642
      double dv;
643
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
1,372✔
644
      if (TSDB_CODE_SUCCESS != code) {
1,372!
645
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
×
646
      }
647
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
1,372!
648
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
×
649
      }
650
      *(float*)(&val->i64) = dv;
1,372✔
651
      break;
1,372✔
652
    }
653

654
    case TSDB_DATA_TYPE_DOUBLE: {
1,714✔
655
      double dv;
656
      code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
1,714✔
657
      if (TSDB_CODE_SUCCESS != code) {
1,714!
658
        return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
×
659
      }
660
      if (((dv == HUGE_VAL || dv == -HUGE_VAL) && ERRNO == ERANGE) || isinf(dv) || isnan(dv)) {
1,714!
661
        return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
×
662
      }
663

664
      *(double*)(&val->i64) = dv;
1,714✔
665
      break;
1,714✔
666
    }
667

668
    case TSDB_DATA_TYPE_BINARY: {
17,106✔
669
      // Too long values will raise the invalid sql error message
670
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
17,106✔
671
        return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
4✔
672
      }
673
      val->pData = taosStrdup(pToken->z);
17,102!
674
      if (!val->pData) {
17,102!
675
        return terrno;
×
676
      }
677
      val->nData = pToken->n;
17,102✔
678
      break;
17,102✔
679
    }
680
    case TSDB_DATA_TYPE_VARBINARY: {
4✔
681
      code = parseVarbinary(pToken, &val->pData, &val->nData, pSchema->bytes);
4✔
682
      if (code != TSDB_CODE_SUCCESS) {
4!
683
        return generateSyntaxErrMsg(pMsgBuf, code, pSchema->name);
×
684
      }
685
      break;
4✔
686
    }
687
    case TSDB_DATA_TYPE_GEOMETRY: {
4✔
688
      unsigned char* output = NULL;
4✔
689
      size_t         size = 0;
4✔
690

691
      code = parseGeometry(pToken, &output, &size);
4✔
692
      if (code != TSDB_CODE_SUCCESS) {
4!
693
        code = buildSyntaxErrMsg(pMsgBuf, getGeosErrMsg(code), pToken->z);
×
694
      } else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
4!
695
        // Too long values will raise the invalid sql error message
696
        code = generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
697
      } else {
698
        val->pData = taosMemoryMalloc(size);
4!
699
        if (NULL == val->pData) {
4!
700
          code = terrno;
×
701
        } else {
702
          memcpy(val->pData, output, size);
4✔
703
          val->nData = size;
4✔
704
        }
705
      }
706

707
      geosFreeBuffer(output);
4✔
708
      break;
4✔
709
    }
710

711
    case TSDB_DATA_TYPE_NCHAR: {
1,675✔
712
      int32_t output = 0;
1,675✔
713
      int64_t realLen = pToken->n << 2;
1,675✔
714
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
1,675!
715
      void* p = taosMemoryMalloc(realLen);
1,675!
716
      if (p == NULL) {
1,675!
717
        return terrno;
1✔
718
      }
719
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)(p), realLen, &output, charsetCxt)) {
1,675✔
720
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
1!
721
          taosMemoryFree(p);
×
722
          return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
723
        }
724
        char buf[512] = {0};
1✔
725
        snprintf(buf, tListLen(buf), " taosMbsToUcs4 error:%s %d %d", strerror(terrno), ERRNO, EILSEQ);
1✔
726
        taosMemoryFree(p);
1!
727
        return buildSyntaxErrMsg(pMsgBuf, buf, pToken->z);
1✔
728
      }
729
      val->pData = p;
1,674✔
730
      val->nData = output;
1,674✔
731
      break;
1,674✔
732
    }
733
    case TSDB_DATA_TYPE_TIMESTAMP: {
1,031✔
734
      if (parseTime(end, pToken, timePrec, &iv, pMsgBuf, tz) != TSDB_CODE_SUCCESS) {
1,031!
735
        return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z);
×
736
      }
737

738
      val->i64 = iv;
1,031✔
739
      break;
1,031✔
740
    }
741
  }
742

743
  return code;
50,755✔
744
}
745

746
// input pStmt->pSql:  [(tag1_name, ...)] TAGS (tag1_value, ...) ...
747
// output pStmt->pSql: TAGS (tag1_value, ...) ...
748
static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
13,134✔
749
  int32_t code = insInitBoundColsInfo(getNumOfTags(pStmt->pTableMeta), &pCxt->tags);
13,134✔
750
  if (TSDB_CODE_SUCCESS != code) {
13,134!
751
    return code;
×
752
  }
753

754
  SToken  token;
755
  int32_t index = 0;
13,134✔
756
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
13,134✔
757
  if (TK_NK_LP != token.type) {
13,134✔
758
    return TSDB_CODE_SUCCESS;
13,094✔
759
  }
760

761
  pStmt->pSql += index;
40✔
762
  return parseBoundColumns(pCxt, &pStmt->pSql, BOUND_TAGS, pStmt->pTableMeta, &pCxt->tags);
40✔
763
}
764

765
int32_t parseTagValue(SMsgBuf* pMsgBuf, const char** pSql, uint8_t precision, SSchema* pTagSchema, SToken* pToken,
50,835✔
766
                      SArray* pTagName, SArray* pTagVals, STag** pTag, timezone_t tz, void *charsetCxt) {
767
  bool isNull = isNullValue(pTagSchema->type, pToken);
50,835✔
768
  if (!isNull && pTagName) {
50,835✔
769
    if (NULL == taosArrayPush(pTagName, pTagSchema->name)) {
101,513!
770
      return terrno;
×
771
    }
772
  }
773

774
  if (pTagSchema->type == TSDB_DATA_TYPE_JSON) {
50,836✔
775
    if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
7!
776
      return buildSyntaxErrMsg(pMsgBuf, "json string too long than 4095", pToken->z);
×
777
    }
778

779
    if (isNull) {
7✔
780
      return tTagNew(pTagVals, 1, true, pTag);
3✔
781
    } else {
782
      return parseJsontoTagData(pToken->z, pTagVals, pTag, pMsgBuf, charsetCxt);
4✔
783
    }
784
  }
785

786
  if (isNull) return 0;
50,829✔
787

788
  STagVal val = {0};
50,763✔
789
  int32_t code = parseTagToken(pSql, pToken, pTagSchema, precision, &val, pMsgBuf, tz, charsetCxt);
50,763✔
790
  if (TSDB_CODE_SUCCESS == code) {
50,762✔
791
    if (NULL == taosArrayPush(pTagVals, &val)) {
50,755!
792
      code = terrno;
×
793
    }
794
  }
795

796
  return code;
50,762✔
797
}
798

799
static int32_t buildCreateTbReq(SVnodeModifyOpStmt* pStmt, STag* pTag, SArray* pTagName) {
53✔
800
  if (pStmt->pCreateTblReq) {
53!
801
    tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
×
802
    taosMemoryFreeClear(pStmt->pCreateTblReq);
×
803
  }
804
  pStmt->pCreateTblReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
53!
805
  if (NULL == pStmt->pCreateTblReq) {
53!
806
    return terrno;
×
807
  }
808
  return insBuildCreateTbReq(pStmt->pCreateTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid,
53✔
809
                             pStmt->usingTableName.tname, pTagName, pStmt->pTableMeta->tableInfo.numOfTags,
53✔
810
                             TSDB_DEFAULT_TABLE_TTL);
811
}
812

813
int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf, int8_t type) {
296,330,575✔
814
  if (pToken->type == TK_NK_QUESTION) {
296,330,575!
815
    return buildInvalidOperationMsg(pMsgBuf, "insert into super table syntax is not supported for stmt");
×
816
  }
817
  if ((pToken->type != TK_NOW && pToken->type != TK_TODAY && pToken->type != TK_NK_INTEGER &&
296,330,575!
818
       pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL &&
110,518,770✔
819
       pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && pToken->type != TK_NK_BIN &&
693,453!
820
       pToken->type != TK_NK_VARIABLE) ||
×
821
      (pToken->n == 0) || (pToken->type == TK_NK_RP)) {
296,330,575!
822
    return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z);
823
  }
824

825
  // Remove quotation marks
826
  if (TK_NK_STRING == pToken->type && type != TSDB_DATA_TYPE_VARBINARY) {
301,231,556!
827
    if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) {
41,547,202!
828
      return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z);
×
829
    }
830

831
    int32_t len = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW);
41,547,202✔
832
    pToken->z = tmpTokenBuf;
41,535,663✔
833
    pToken->n = len;
41,535,663✔
834
  }
835

836
  return TSDB_CODE_SUCCESS;
301,220,017✔
837
}
838

839
typedef struct SRewriteTagCondCxt {
840
  SArray* pTagVals;
841
  SArray* pTagName;
842
  int32_t code;
843
} SRewriteTagCondCxt;
844

845
static int32_t rewriteTagCondColumnImpl(STagVal* pVal, SNode** pNode) {
×
846
  SValueNode* pValue = NULL;
×
847
  int32_t     code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pValue);
×
848
  if (NULL == pValue) {
×
849
    return code;
×
850
  }
851

852
  pValue->node.resType = ((SColumnNode*)*pNode)->node.resType;
×
853
  nodesDestroyNode(*pNode);
×
854
  *pNode = (SNode*)pValue;
×
855

856
  switch (pVal->type) {
×
857
    case TSDB_DATA_TYPE_BOOL:
×
858
      pValue->datum.b = *(int8_t*)(&pVal->i64);
×
859
      *(bool*)&pValue->typeData = pValue->datum.b;
×
860
      break;
×
861
    case TSDB_DATA_TYPE_TINYINT:
×
862
      pValue->datum.i = *(int8_t*)(&pVal->i64);
×
863
      *(int8_t*)&pValue->typeData = pValue->datum.i;
×
864
      break;
×
865
    case TSDB_DATA_TYPE_SMALLINT:
×
866
      pValue->datum.i = *(int16_t*)(&pVal->i64);
×
867
      *(int16_t*)&pValue->typeData = pValue->datum.i;
×
868
      break;
×
869
    case TSDB_DATA_TYPE_INT:
×
870
      pValue->datum.i = *(int32_t*)(&pVal->i64);
×
871
      *(int32_t*)&pValue->typeData = pValue->datum.i;
×
872
      break;
×
873
    case TSDB_DATA_TYPE_BIGINT:
×
874
      pValue->datum.i = pVal->i64;
×
875
      pValue->typeData = pValue->datum.i;
×
876
      break;
×
877
    case TSDB_DATA_TYPE_FLOAT:
×
878
      pValue->datum.d = *(float*)(&pVal->i64);
×
879
      *(float*)&pValue->typeData = pValue->datum.d;
×
880
      break;
×
881
    case TSDB_DATA_TYPE_DOUBLE:
×
882
      pValue->datum.d = *(double*)(&pVal->i64);
×
883
      *(double*)&pValue->typeData = pValue->datum.d;
×
884
      break;
×
885
    case TSDB_DATA_TYPE_VARCHAR:
×
886
    case TSDB_DATA_TYPE_VARBINARY:
887
    case TSDB_DATA_TYPE_NCHAR:
888
      pValue->datum.p = taosMemoryCalloc(1, pVal->nData + VARSTR_HEADER_SIZE);
×
889
      if (NULL == pValue->datum.p) {
×
890
        return terrno;
×
891
      }
892
      varDataSetLen(pValue->datum.p, pVal->nData);
×
893
      memcpy(varDataVal(pValue->datum.p), pVal->pData, pVal->nData);
×
894
      break;
×
895
    case TSDB_DATA_TYPE_TIMESTAMP:
×
896
      pValue->datum.i = pVal->i64;
×
897
      pValue->typeData = pValue->datum.i;
×
898
      break;
×
899
    case TSDB_DATA_TYPE_UTINYINT:
×
900
      pValue->datum.i = *(uint8_t*)(&pVal->i64);
×
901
      *(uint8_t*)&pValue->typeData = pValue->datum.i;
×
902
      break;
×
903
    case TSDB_DATA_TYPE_USMALLINT:
×
904
      pValue->datum.i = *(uint16_t*)(&pVal->i64);
×
905
      *(uint16_t*)&pValue->typeData = pValue->datum.i;
×
906
      break;
×
907
    case TSDB_DATA_TYPE_UINT:
×
908
      pValue->datum.i = *(uint32_t*)(&pVal->i64);
×
909
      *(uint32_t*)&pValue->typeData = pValue->datum.i;
×
910
      break;
×
911
    case TSDB_DATA_TYPE_UBIGINT:
×
912
      pValue->datum.i = *(uint64_t*)(&pVal->i64);
×
913
      *(uint64_t*)&pValue->typeData = pValue->datum.i;
×
914
      break;
×
915
    case TSDB_DATA_TYPE_JSON:
×
916
    case TSDB_DATA_TYPE_DECIMAL:
917
    case TSDB_DATA_TYPE_BLOB:
918
    case TSDB_DATA_TYPE_MEDIUMBLOB:
919
    default:
920
      return TSDB_CODE_FAILED;
×
921
  }
922
  return TSDB_CODE_SUCCESS;
×
923
}
924

925
static int32_t rewriteTagCondColumn(SArray* pTagVals, SArray* pTagName, SNode** pNode) {
×
926
  SColumnNode* pCol = (SColumnNode*)*pNode;
×
927
  int32_t      ntags = taosArrayGetSize(pTagName);
×
928
  for (int32_t i = 0; i < ntags; ++i) {
×
929
    char* pTagColName = taosArrayGet(pTagName, i);
×
930
    if (0 == strcmp(pTagColName, pCol->colName)) {
×
931
      return rewriteTagCondColumnImpl(taosArrayGet(pTagVals, i), pNode);
×
932
    }
933
  }
934
  return TSDB_CODE_PAR_PERMISSION_DENIED;
×
935
}
936

937
static EDealRes rewriteTagCond(SNode** pNode, void* pContext) {
×
938
  if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
×
939
    SRewriteTagCondCxt* pCxt = pContext;
×
940
    pCxt->code = rewriteTagCondColumn(pCxt->pTagVals, pCxt->pTagName, pNode);
×
941
    return (TSDB_CODE_SUCCESS == pCxt->code ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
×
942
  }
943
  return DEAL_RES_CONTINUE;
×
944
}
945

946
static int32_t setTagVal(SArray* pTagVals, SArray* pTagName, SNode* pCond) {
×
947
  SRewriteTagCondCxt cxt = {.code = TSDB_CODE_SUCCESS, .pTagVals = pTagVals, .pTagName = pTagName};
×
948
  nodesRewriteExpr(&pCond, rewriteTagCond, &cxt);
×
949
  return cxt.code;
×
950
}
951

952
static int32_t checkTagCondResult(SNode* pResult) {
×
953
  return (QUERY_NODE_VALUE == nodeType(pResult) && ((SValueNode*)pResult)->datum.b) ? TSDB_CODE_SUCCESS
×
954
                                                                                    : TSDB_CODE_PAR_PERMISSION_DENIED;
×
955
}
956

957
static int32_t checkSubtablePrivilege(SArray* pTagVals, SArray* pTagName, SNode** pCond) {
×
958
  int32_t code = setTagVal(pTagVals, pTagName, *pCond);
×
959
  if (TSDB_CODE_SUCCESS == code) {
×
960
    code = scalarCalculateConstants(*pCond, pCond);
×
961
  }
962
  if (TSDB_CODE_SUCCESS == code) {
×
963
    code = checkTagCondResult(*pCond);
×
964
  }
965
  NODES_DESTORY_NODE(*pCond);
×
966
  return code;
×
967
}
968

969
// pSql -> tag1_value, ...)
970
static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool autoCreate) {
13,133✔
971
  int32_t  code = TSDB_CODE_SUCCESS;
13,133✔
972
  SSchema* pSchema = getTableTagSchema(pStmt->pTableMeta);
13,133✔
973
  SArray*  pTagVals = NULL;
13,133✔
974
  SArray*  pTagName = NULL;
13,133✔
975
  uint8_t  precision = pStmt->pTableMeta->tableInfo.precision;
13,133✔
976
  SToken   token;
977
  bool     isParseBindParam = false;
13,133✔
978
  bool     isJson = false;
13,133✔
979
  STag*    pTag = NULL;
13,133✔
980

981
  if (!(pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal))) ||
26,266!
982
      !(pTagName = taosArrayInit(pCxt->tags.numOfBound, TSDB_COL_NAME_LEN))) {
13,133✔
983
    code = terrno;
×
984
    goto _exit;
×
985
  }
986

987
  for (int i = 0; TSDB_CODE_SUCCESS == code && i < pCxt->tags.numOfBound; ++i) {
37,464!
988
    NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
24,332✔
989

990
    if (token.type == TK_NK_QUESTION) {
24,332✔
991
      isParseBindParam = true;
115✔
992
      if (NULL == pCxt->pComCxt->pStmtCb) {
115!
993
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", token.z);
×
994
        break;
×
995
      }
996
      if (pTagVals->size != 0) {
115✔
997
        code = buildSyntaxErrMsg(&pCxt->msg, "no mix usage for ? and tag values", token.z);
1✔
998
        break;
1✔
999
      }
1000

1001
      continue;
114✔
1002
    }
1003

1004
    if (isParseBindParam) {
24,217!
1005
      code = buildInvalidOperationMsg(&pCxt->msg, "no mix usage for ? and tag values");
×
1006
      break;
×
1007
    }
1008

1009
    SSchema* pTagSchema = &pSchema[pCxt->tags.pColIndex[i]];
24,217✔
1010
    isJson = pTagSchema->type == TSDB_DATA_TYPE_JSON;
24,217✔
1011
    code = checkAndTrimValue(&token, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
24,217✔
1012
    if (TSDB_CODE_SUCCESS == code && TK_NK_VARIABLE == token.type) {
24,217!
1013
      code = buildSyntaxErrMsg(&pCxt->msg, "not expected tags values ", token.z);
×
1014
    }
1015
    if (TSDB_CODE_SUCCESS == code) {
24,217!
1016
      code = parseTagValue(&pCxt->msg, &pStmt->pSql, precision, pTagSchema, &token, pTagName, pTagVals, &pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
24,217✔
1017
    }
1018
  }
1019

1020
  if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pTagCond) {
13,133!
1021
    code = checkSubtablePrivilege(pTagVals, pTagName, &pStmt->pTagCond);
×
1022
  }
1023

1024
  if (TSDB_CODE_SUCCESS == code && !isParseBindParam && !isJson) {
13,133!
1025
    code = tTagNew(pTagVals, 1, false, &pTag);
13,097✔
1026
  }
1027

1028
  if (TSDB_CODE_SUCCESS == code && !isParseBindParam && !autoCreate) {
13,133✔
1029
    code = buildCreateTbReq(pStmt, pTag, pTagName);
53✔
1030
    pTag = NULL;
53✔
1031
  }
1032

1033
  if (code == TSDB_CODE_SUCCESS && !isParseBindParam) {
13,133✔
1034
    pCxt->stmtTbNameFlag |= IS_FIXED_TAG;
13,097✔
1035
  }
1036

1037
_exit:
36✔
1038
  for (int32_t i = 0; i < taosArrayGetSize(pTagVals); ++i) {
37,350✔
1039
    STagVal* p = (STagVal*)TARRAY_GET_ELEM(pTagVals, i);
24,217✔
1040
    if (IS_VAR_DATA_TYPE(p->type)) {
24,217!
1041
      taosMemoryFreeClear(p->pData);
11,089!
1042
    }
1043
  }
1044
  taosArrayDestroy(pTagVals);
13,133✔
1045
  taosArrayDestroy(pTagName);
13,133✔
1046
  tTagFree(pTag);
13,133✔
1047
  return code;
13,133✔
1048
}
1049

1050
// input pStmt->pSql:  TAGS (tag1_value, ...) [table_options] ...
1051
// output pStmt->pSql: [table_options] ...
1052
static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool autoCreate) {
13,134✔
1053
  SToken token;
1054
  NEXT_TOKEN(pStmt->pSql, token);
13,134✔
1055
  if (TK_TAGS != token.type) {
13,134✔
1056
    return buildSyntaxErrMsg(&pCxt->msg, "TAGS is expected", token.z);
1✔
1057
  }
1058

1059
  NEXT_TOKEN(pStmt->pSql, token);
13,133✔
1060
  if (TK_NK_LP != token.type) {
13,133!
1061
    return buildSyntaxErrMsg(&pCxt->msg, "( is expected", token.z);
×
1062
  }
1063

1064
  int32_t code = parseTagsClauseImpl(pCxt, pStmt, autoCreate);
13,133✔
1065
  if (TSDB_CODE_SUCCESS == code) {
13,133✔
1066
    NEXT_VALID_TOKEN(pStmt->pSql, token);
13,132!
1067
    if (TK_NK_COMMA == token.type) {
13,132!
1068
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
×
1069
    } else if (TK_NK_RP != token.type) {
13,132!
1070
      code = buildSyntaxErrMsg(&pCxt->msg, ") is expected", token.z);
×
1071
    }
1072
  }
1073
  return code;
13,133✔
1074
}
1075

1076
static int32_t storeChildTableMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
90✔
1077
  pStmt->pTableMeta->suid = pStmt->pTableMeta->uid;
90✔
1078
  pStmt->pTableMeta->uid = pStmt->totalTbNum;
90✔
1079
  pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;
90✔
1080

1081
  STableMeta* pBackup = NULL;
90✔
1082
  if (TSDB_CODE_SUCCESS != cloneTableMeta(pStmt->pTableMeta, &pBackup)) {
90!
1083
    return TSDB_CODE_OUT_OF_MEMORY;
×
1084
  }
1085

1086
  char    tbFName[TSDB_TABLE_FNAME_LEN];
1087
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
90✔
1088
  if (TSDB_CODE_SUCCESS != code) {
90!
1089
    taosMemoryFree(pBackup);
×
1090
    return code;
×
1091
  }
1092
  code = taosHashPut(pStmt->pSubTableHashObj, tbFName, strlen(tbFName), &pBackup, POINTER_BYTES);
90✔
1093
  if (TSDB_CODE_SUCCESS != code) {
90!
1094
    taosMemoryFree(pBackup);
×
1095
  }
1096
  return code;
90✔
1097
}
1098

1099
static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
88✔
1100
  do {
×
1101
    int32_t index = 0;
88✔
1102
    SToken  token;
1103
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
88✔
1104
    if (TK_TTL == token.type) {
88!
1105
      pStmt->pSql += index;
×
1106
      NEXT_TOKEN_WITH_PREV(pStmt->pSql, token);
×
1107
      if (TK_NK_INTEGER != token.type) {
×
1108
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
×
1109
      }
1110
      pStmt->pCreateTblReq->ttl = taosStr2Int32(token.z, NULL, 10);
×
1111
      if (pStmt->pCreateTblReq->ttl < 0) {
×
1112
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z);
×
1113
      }
1114
    } else if (TK_COMMENT == token.type) {
88!
1115
      pStmt->pSql += index;
×
1116
      NEXT_TOKEN(pStmt->pSql, token);
×
1117
      if (TK_NK_STRING != token.type) {
×
1118
        return buildSyntaxErrMsg(&pCxt->msg, "Invalid option comment", token.z);
×
1119
      }
1120
      if (token.n >= TSDB_TB_COMMENT_LEN) {
×
1121
        return buildSyntaxErrMsg(&pCxt->msg, "comment too long", token.z);
×
1122
      }
1123
      int32_t len = trimString(token.z, token.n, pCxt->tmpTokenBuf, TSDB_TB_COMMENT_LEN);
×
1124
      pStmt->pCreateTblReq->comment = taosStrndup(pCxt->tmpTokenBuf, len);
×
1125
      if (NULL == pStmt->pCreateTblReq->comment) {
×
1126
        return terrno;
×
1127
      }
1128
      pStmt->pCreateTblReq->commentLen = len;
×
1129
    } else {
1130
      break;
88✔
1131
    }
1132
  } while (1);
1133
  return TSDB_CODE_SUCCESS;
88✔
1134
}
1135

1136
// input pStmt->pSql:
1137
//   1. [(tag1_name, ...)] ...
1138
//   2. VALUES ... | FILE ...
1139
// output pStmt->pSql:
1140
//   1. [(field1_name, ...)]
1141
//   2. VALUES ... | FILE ...
1142
static int32_t parseUsingClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
101,998✔
1143
  if (!pStmt->usingTableProcessing || pCxt->usingDuplicateTable) {
101,998!
1144
    return TSDB_CODE_SUCCESS;
101,908✔
1145
  }
1146

1147
  int32_t code = parseBoundTagsClause(pCxt, pStmt);
90✔
1148
  if (TSDB_CODE_SUCCESS == code) {
90!
1149
    code = parseTagsClause(pCxt, pStmt, false);
90✔
1150
  }
1151
  if (TSDB_CODE_SUCCESS == code) {
90✔
1152
    code = parseTableOptions(pCxt, pStmt);
88✔
1153
  }
1154

1155
  return code;
90✔
1156
}
1157

1158
static void setUserAuthInfo(SParseContext* pCxt, SName* pTbName, SUserAuthInfo* pInfo) {
88,901✔
1159
  snprintf(pInfo->user, sizeof(pInfo->user), "%s", pCxt->pUser);
88,901✔
1160
  memcpy(&pInfo->tbName, pTbName, sizeof(SName));
88,901✔
1161
  pInfo->type = AUTH_TYPE_WRITE;
88,901✔
1162
}
88,901✔
1163

1164
static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool* pMissCache, SNode** pTagCond) {
88,900✔
1165
  int32_t       code = TSDB_CODE_SUCCESS;
88,900✔
1166
  SUserAuthInfo authInfo = {0};
88,900✔
1167
  setUserAuthInfo(pCxt, pTbName, &authInfo);
88,900✔
1168
  SUserAuthRes authRes = {0};
88,903✔
1169
  bool         exists = true;
88,903✔
1170
  if (pCxt->async) {
88,903✔
1171
    code = catalogChkAuthFromCache(pCxt->pCatalog, &authInfo, &authRes, &exists);
88,759✔
1172
  } else {
1173
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
144✔
1174
                             .requestId = pCxt->requestId,
144✔
1175
                             .requestObjRefId = pCxt->requestRid,
144✔
1176
                             .mgmtEps = pCxt->mgmtEpSet};
1177
    code = catalogChkAuth(pCxt->pCatalog, &conn, &authInfo, &authRes);
144✔
1178
  }
1179
  if (TSDB_CODE_SUCCESS == code) {
88,896!
1180
    if (!exists) {
88,896✔
1181
      *pMissCache = true;
1✔
1182
    } else if (!authRes.pass[AUTH_RES_BASIC]) {
88,895!
1183
      code = TSDB_CODE_PAR_PERMISSION_DENIED;
×
1184
    } else if (NULL != authRes.pCond[AUTH_RES_BASIC]) {
88,895!
1185
      *pTagCond = authRes.pCond[AUTH_RES_BASIC];
×
1186
    }
1187
  }
1188
  return code;
88,896✔
1189
}
1190

1191
static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, STableMeta** pTableMeta, bool* pMissCache,
26,349✔
1192
                            bool bUsingTable) {
1193
  SParseContext* pComCxt = pCxt->pComCxt;
26,349✔
1194
  int32_t        code = TSDB_CODE_SUCCESS;
26,349✔
1195
  if (pComCxt->async) {
26,349✔
1196
    if (bUsingTable) {
26,134✔
1197
      code = catalogGetCachedSTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
13,068✔
1198
    } else {
1199
      code = catalogGetCachedTableMeta(pComCxt->pCatalog, pTbName, pTableMeta);
13,066✔
1200
    }
1201
  } else {
1202
    SRequestConnInfo conn = {.pTrans = pComCxt->pTransporter,
215✔
1203
                             .requestId = pComCxt->requestId,
215✔
1204
                             .requestObjRefId = pComCxt->requestRid,
215✔
1205
                             .mgmtEps = pComCxt->mgmtEpSet};
1206
    if (bUsingTable) {
215✔
1207
      code = catalogGetSTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
56✔
1208
    } else {
1209
      code = catalogGetTableMeta(pComCxt->pCatalog, &conn, pTbName, pTableMeta);
159✔
1210
    }
1211
  }
1212
  if (TSDB_CODE_SUCCESS == code) {
26,349✔
1213
    if (NULL == *pTableMeta) {
26,347✔
1214
      *pMissCache = true;
46✔
1215
    } else if (bUsingTable && TSDB_SUPER_TABLE != (*pTableMeta)->tableType) {
26,301!
1216
      code = buildInvalidOperationMsg(&pCxt->msg, "create table only from super table is allowed");
×
1217
    } else if (((*pTableMeta)->virtualStb) ||
26,301!
1218
               TSDB_VIRTUAL_CHILD_TABLE == (*pTableMeta)->tableType ||
26,301!
1219
               TSDB_VIRTUAL_NORMAL_TABLE == (*pTableMeta)->tableType) {
26,301!
1220
      code = TSDB_CODE_VTABLE_NOT_SUPPORT_STMT;
×
1221
    }
1222
  }
1223
  return code;
26,349✔
1224
}
1225

1226
static int32_t getTargetTableVgroup(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool isStb, bool* pMissCache) {
13,206✔
1227
  int32_t     code = TSDB_CODE_SUCCESS;
13,206✔
1228
  SVgroupInfo vg;
1229
  bool        exists = true;
13,206✔
1230
  if (pCxt->async) {
13,206✔
1231
    code = catalogGetCachedTableHashVgroup(pCxt->pCatalog, &pStmt->targetTableName, &vg, &exists);
13,029✔
1232
  } else {
1233
    SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
177✔
1234
                             .requestId = pCxt->requestId,
177✔
1235
                             .requestObjRefId = pCxt->requestRid,
177✔
1236
                             .mgmtEps = pCxt->mgmtEpSet};
1237
    code = catalogGetTableHashVgroup(pCxt->pCatalog, &conn, &pStmt->targetTableName, &vg);
177✔
1238
  }
1239
  if (TSDB_CODE_SUCCESS == code) {
13,206!
1240
    if (exists) {
13,206!
1241
      if (isStb) {
13,206✔
1242
        pStmt->pTableMeta->vgId = vg.vgId;
13,088✔
1243
      }
1244
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
13,206✔
1245
    }
1246
    *pMissCache = !exists;
13,206✔
1247
  }
1248
  return code;
13,206✔
1249
}
1250

1251
static int32_t getTargetTableMetaAndVgroup(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) {
88,899✔
1252
  SParseContext* pComCxt = pCxt->pComCxt;
88,899✔
1253
  int32_t        code = TSDB_CODE_SUCCESS;
88,899✔
1254
  if (pComCxt->async) {
88,899✔
1255
    {
1256
      SVgroupInfo vg;
1257
      code = catalogGetCachedTableVgMeta(pComCxt->pCatalog, &pStmt->targetTableName, &vg, &pStmt->pTableMeta);
88,755✔
1258
      if (TSDB_CODE_SUCCESS == code) {
88,751!
1259
        if (NULL != pStmt->pTableMeta) {
88,751✔
1260
          if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE) {
88,714✔
1261
            pStmt->stbSyntax = true;
1✔
1262
          } else {
1263
            code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg));
88,713✔
1264
          }
1265
        }
1266
        *pMissCache = (NULL == pStmt->pTableMeta);
88,762✔
1267
      }
1268
    }
1269
  } else {
1270
    bool bUsingTable = false;
144✔
1271
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pStmt->pTableMeta, pMissCache, bUsingTable);
144✔
1272
    if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
144!
1273
      if (TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
142✔
1274
        pStmt->stbSyntax = true;
24✔
1275
      }
1276
      if (!pStmt->stbSyntax) {
142✔
1277
        code = getTargetTableVgroup(pCxt->pComCxt, pStmt, false, &pCxt->missCache);
118✔
1278
      }
1279
    }
1280
  }
1281
  return code;
88,900✔
1282
}
1283

1284
static int32_t collectUseTable(const SName* pName, SHashObj* pTable) {
240✔
1285
  char    fullName[TSDB_TABLE_FNAME_LEN];
1286
  int32_t code = tNameExtractFullName(pName, fullName);
240✔
1287
  if (TSDB_CODE_SUCCESS != code) {
240!
1288
    return code;
×
1289
  }
1290
  return taosHashPut(pTable, fullName, strlen(fullName), pName, sizeof(SName));
240✔
1291
}
1292

1293
static int32_t collectUseDatabase(const SName* pName, SHashObj* pDbs) {
227✔
1294
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
227✔
1295
  (void)tNameGetFullDbName(pName, dbFName);
227✔
1296
  return taosHashPut(pDbs, dbFName, strlen(dbFName), dbFName, sizeof(dbFName));
227✔
1297
}
1298

1299
static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
88,901✔
1300
  if (pCxt->forceUpdate) {
88,901!
1301
    pCxt->missCache = true;
×
1302
    return TSDB_CODE_SUCCESS;
×
1303
  }
1304
  SNode*  pTagCond = NULL;
88,901✔
1305
  int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache, &pTagCond);
88,901✔
1306
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
88,898!
1307
    code = getTargetTableMetaAndVgroup(pCxt, pStmt, &pCxt->missCache);
88,897✔
1308
  }
1309
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
88,902!
1310
    if (TSDB_SUPER_TABLE != pStmt->pTableMeta->tableType) {
88,862✔
1311
      pCxt->needTableTagVal = (NULL != pTagCond);
88,837✔
1312
      pCxt->missCache = (NULL != pTagCond);
88,837✔
1313
    } else {
1314
      pStmt->pTagCond = NULL;
25✔
1315
      code = nodesCloneNode(pTagCond, &pStmt->pTagCond);
25✔
1316
    }
1317
  }
1318
  nodesDestroyNode(pTagCond);
88,902✔
1319

1320
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
88,906✔
1321
    code = collectUseDatabase(&pStmt->targetTableName, pStmt->pDbFNameHashObj);
142✔
1322
    if (TSDB_CODE_SUCCESS == code) {
142!
1323
      code = collectUseTable(&pStmt->targetTableName, pStmt->pTableNameHashObj);
142✔
1324
    }
1325
  }
1326
  return code;
88,900✔
1327
}
1328

1329
static int32_t preParseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
13,134✔
1330
  return insCreateSName(&pStmt->usingTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
13,134✔
1331
}
1332

1333
static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* ctbCacheHit) {
13,134✔
1334
  int32_t code = TSDB_CODE_SUCCESS;
13,134✔
1335
  STableMeta* pStableMeta = NULL;
13,134✔
1336
  STableMeta* pCtableMeta = NULL;
13,134✔
1337
  if (pCxt->forceUpdate) {
13,134!
1338
    pCxt->missCache = true;
×
1339
    return TSDB_CODE_SUCCESS;
×
1340
  }
1341
  if (!pCxt->missCache) {
13,134!
1342
    char tbFName[TSDB_TABLE_FNAME_LEN];
1343
    code = tNameExtractFullName(&pStmt->usingTableName, tbFName);
13,134✔
1344
    if (TSDB_CODE_SUCCESS != code) {
13,134!
1345
      return code;
×
1346
    }
1347
    STableMeta** ppStableMeta = taosHashGet(pStmt->pSuperTableHashObj, tbFName, strlen(tbFName));
13,134✔
1348
    if (NULL != ppStableMeta) {
13,134✔
1349
      pStableMeta = *ppStableMeta;
16✔
1350
    }
1351
    if (NULL == pStableMeta) {
13,134✔
1352
      bool bUsingTable = true;
13,124✔
1353
      code = getTableMeta(pCxt, &pStmt->usingTableName, &pStableMeta, &pCxt->missCache, bUsingTable);
13,124✔
1354
      if (TSDB_CODE_SUCCESS == code) {
13,124!
1355
        code = taosHashPut(pStmt->pSuperTableHashObj, tbFName, strlen(tbFName), &pStableMeta, POINTER_BYTES);
13,124✔
1356
      } else {
1357
        taosMemoryFreeClear(pStableMeta);
×
1358
      }
1359
    }
1360
  }
1361
  if (pCxt->isStmtBind) {
13,134✔
1362
    goto _no_ctb_cache;
44✔
1363
  }
1364

1365
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
13,090!
1366
    bool bUsingTable = false;
13,081✔
1367
    code = getTableMeta(pCxt, &pStmt->targetTableName, &pCtableMeta, &pCxt->missCache, bUsingTable);
13,081✔
1368
  }
1369

1370
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
13,090!
1371
    code = (pStableMeta->suid == pCtableMeta->suid) ? TSDB_CODE_SUCCESS : TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
13,044!
1372
    *ctbCacheHit = true;
13,044✔
1373
  }
1374
_no_ctb_cache:
46✔
1375
  if (TSDB_CODE_SUCCESS == code) {
13,134!
1376
    if (*ctbCacheHit) {
13,134✔
1377
      code = cloneTableMeta(pCtableMeta, &pStmt->pTableMeta);
13,044✔
1378
    } else {
1379
      code = cloneTableMeta(pStableMeta, &pStmt->pTableMeta);
90✔
1380
    }
1381
  }
1382
  taosMemoryFree(pCtableMeta);
13,134!
1383
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
13,134!
1384
    code = getTargetTableVgroup(pCxt->pComCxt, pStmt, true, &pCxt->missCache);
13,088✔
1385
  }
1386
  if (TSDB_CODE_SUCCESS == code && !pCxt->pComCxt->async) {
13,134!
1387
    code = collectUseDatabase(&pStmt->usingTableName, pStmt->pDbFNameHashObj);
59✔
1388
    if (TSDB_CODE_SUCCESS == code) {
59!
1389
      code = collectUseTable(&pStmt->usingTableName, pStmt->pTableNameHashObj);
59✔
1390
    }
1391
  }
1392
  return code;
13,134✔
1393
}
1394

1395
static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
13,134✔
1396
  SToken token;
1397
  NEXT_TOKEN(pStmt->pSql, token);
13,134✔
1398
  bool    ctbCacheHit = false;
13,134✔
1399
  int32_t code = preParseUsingTableName(pCxt, pStmt, &token);
13,134✔
1400
  if (TSDB_CODE_SUCCESS == code) {
13,134!
1401
    code = getUsingTableSchema(pCxt, pStmt, &ctbCacheHit);
13,134✔
1402
    if (TSDB_CODE_SUCCESS == code && ctbCacheHit) {
13,134!
1403
      pStmt->usingTableProcessing = false;
13,044✔
1404
      return ignoreUsingClauseAndCheckTagValues(pCxt, pStmt);
13,044✔
1405
    }
1406
  }
1407
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
90!
1408
    code = storeChildTableMeta(pCxt, pStmt);
44✔
1409
  }
1410
  return code;
90✔
1411
}
1412

1413
// input pStmt->pSql:
1414
//   1(care). [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
1415
//   2. VALUES ... | FILE ...
1416
// output pStmt->pSql:
1417
//   1. [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ...
1418
//   2. VALUES ... | FILE ...
1419
static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
102,036✔
1420
  SToken  token;
1421
  int32_t index = 0;
102,036✔
1422
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
102,036✔
1423
  if (TK_USING != token.type) {
102,038✔
1424
    return getTargetTableSchema(pCxt, pStmt);
88,905✔
1425
  }
1426
  pStmt->usingTableProcessing = true;
13,133✔
1427
  pCxt->stmtTbNameFlag |= USING_CLAUSE;
13,133✔
1428
  // pStmt->pSql -> stb_name [(tag1_name, ...)
1429
  pStmt->pSql += index;
13,133✔
1430
  int32_t code = parseDuplicateUsingClause(pCxt, pStmt, &pCxt->usingDuplicateTable);
13,133✔
1431
  if (TSDB_CODE_SUCCESS == code && !pCxt->usingDuplicateTable) {
13,134!
1432
    return parseUsingTableNameImpl(pCxt, pStmt);
13,134✔
1433
  }
1434
  return code;
×
1435
}
1436

1437
static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
102,043✔
1438
  int32_t code = insCreateSName(&pStmt->targetTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg);
102,043✔
1439
  if (TSDB_CODE_SUCCESS == code) {
102,036✔
1440
    if (IS_SYS_DBNAME(pStmt->targetTableName.dbname)) {
102,034!
1441
      return TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED;
×
1442
    }
1443
  }
1444

1445
  return code;
102,036✔
1446
}
1447

1448
// input pStmt->pSql:
1449
//   1(care). [(field1_name, ...)] ...
1450
//   2. [ USING ... ] ...
1451
//   3. VALUES ... | FILE ...
1452
// output pStmt->pSql:
1453
//   1. [ USING ... ] ...
1454
//   2. VALUES ... | FILE ...
1455
static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
102,034✔
1456
  SToken  token;
1457
  int32_t index = 0;
102,034✔
1458
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
102,034✔
1459
  if (TK_NK_LP != token.type) {
102,038✔
1460
    return TSDB_CODE_SUCCESS;
101,309✔
1461
  }
1462

1463
  // pStmt->pSql -> field1_name, ...)
1464
  pStmt->pSql += index;
729✔
1465
  pStmt->pBoundCols = pStmt->pSql;
729✔
1466
  return skipParentheses(pCxt, &pStmt->pSql);
729✔
1467
}
1468

1469
static int32_t getTableDataCxt(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt** pTableCxt) {
101,997✔
1470
  if (pCxt->pComCxt->async) {
101,997✔
1471
    return insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid),
101,829✔
1472
                              pStmt->pTableMeta, &pStmt->pCreateTblReq, pTableCxt, false, false);
101,827✔
1473
  }
1474

1475
  char    tbFName[TSDB_TABLE_FNAME_LEN];
1476
  int32_t code = 0;
170✔
1477
  if ((pCxt->stmtTbNameFlag & NO_DATA_USING_CLAUSE) == USING_CLAUSE) {
170✔
1478
    tstrncpy(pStmt->targetTableName.tname, pStmt->usingTableName.tname, sizeof(pStmt->targetTableName.tname));
14✔
1479
    tstrncpy(pStmt->targetTableName.dbname, pStmt->usingTableName.dbname, sizeof(pStmt->targetTableName.dbname));
14✔
1480
    pStmt->targetTableName.type = TSDB_SUPER_TABLE;
14✔
1481
    pStmt->pTableMeta->tableType = TSDB_SUPER_TABLE;
14✔
1482
  }
1483

1484
  code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
170✔
1485

1486
  if (TSDB_CODE_SUCCESS != code) {
175!
1487
    return code;
×
1488
  }
1489
  if (pStmt->usingTableProcessing) {
175✔
1490
    pStmt->pTableMeta->uid = 0;
42✔
1491
  }
1492
  return insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
175✔
1493
                            &pStmt->pCreateTblReq, pTableCxt, NULL != pCxt->pComCxt->pStmtCb, false);
175✔
1494
}
1495

1496
static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) {
101,997✔
1497
  SToken  token;
1498
  int32_t index = 0;
101,997✔
1499
  NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index);
101,997✔
1500
  if (TK_NK_LP == token.type) {
101,999✔
1501
    pStmt->pSql += index;
27✔
1502
    if (NULL != pStmt->pBoundCols) {
27!
1503
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
×
1504
    }
1505
    // pStmt->pSql -> field1_name, ...)
1506
    return parseBoundColumns(pCxt, &pStmt->pSql, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo);
27✔
1507
  }
1508

1509
  if (NULL != pStmt->pBoundCols) {
101,972✔
1510
    return parseBoundColumns(pCxt, &pStmt->pBoundCols, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo);
702✔
1511
  } else if (pTableCxt->boundColsInfo.hasBoundCols) {
101,270!
1512
    insResetBoundColsInfo(&pTableCxt->boundColsInfo);
×
1513
  }
1514

1515
  return TSDB_CODE_SUCCESS;
101,264✔
1516
}
1517

1518
int32_t initTableColSubmitData(STableDataCxt* pTableCxt) {
102,343✔
1519
  if (0 == (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT)) {
102,343✔
1520
    return TSDB_CODE_SUCCESS;
102,207✔
1521
  }
1522

1523
  for (int32_t i = 0; i < pTableCxt->boundColsInfo.numOfBound; ++i) {
853✔
1524
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
717✔
1525
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
717✔
1526
    if (NULL == pCol) {
717!
1527
      return terrno;
×
1528
    }
1529
    tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags);
717✔
1530
  }
1531

1532
  return TSDB_CODE_SUCCESS;
136✔
1533
}
1534

1535
int32_t initTableColSubmitDataWithBoundInfo(STableDataCxt* pTableCxt, SBoundColInfo pBoundColsInfo) {
9✔
1536
  insDestroyBoundColInfo(&(pTableCxt->boundColsInfo));
9✔
1537
  pTableCxt->boundColsInfo = pBoundColsInfo;
9✔
1538
  pTableCxt->boundColsInfo.pColIndex = taosMemoryCalloc(pBoundColsInfo.numOfBound, sizeof(int16_t));
9!
1539
  if (NULL == pTableCxt->boundColsInfo.pColIndex) {
9!
1540
    return terrno;
×
1541
  }
1542
  (void)memcpy(pTableCxt->boundColsInfo.pColIndex, pBoundColsInfo.pColIndex,
9✔
1543
               sizeof(int16_t) * pBoundColsInfo.numOfBound);
9✔
1544
  for (int32_t i = 0; i < pBoundColsInfo.numOfBound; ++i) {
25✔
1545
    SSchema*  pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]];
16✔
1546
    SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1);
16✔
1547
    if (NULL == pCol) {
16!
1548
      return terrno;
×
1549
    }
1550
    tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags);
16✔
1551
  }
1552

1553
  return TSDB_CODE_SUCCESS;
9✔
1554
}
1555

1556
// input pStmt->pSql:
1557
//   1. [(tag1_name, ...)] ...
1558
//   2. VALUES ... | FILE ...
1559
// output pStmt->pSql: VALUES ... | FILE ...
1560
static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
101,991✔
1561
                                       STableDataCxt** pTableCxt) {
1562
  int32_t code = parseUsingClauseBottom(pCxt, pStmt);
101,991✔
1563
  if (TSDB_CODE_SUCCESS == code) {
101,995!
1564
    code = getTableDataCxt(pCxt, pStmt, pTableCxt);
101,996✔
1565
  }
1566
  if (TSDB_CODE_SUCCESS == code) {
101,999✔
1567
    code = parseBoundColumnsClause(pCxt, pStmt, *pTableCxt);
101,997✔
1568
  }
1569
  if (TSDB_CODE_SUCCESS == code) {
101,995!
1570
    code = initTableColSubmitData(*pTableCxt);
101,996✔
1571
  }
1572
  return code;
101,989✔
1573
}
1574

1575
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
1576
// output pStmt->pSql:
1577
//   1. [(tag1_name, ...)] ...
1578
//   2. VALUES ... | FILE ...
1579
static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
102,041✔
1580
  int32_t code = preParseTargetTableName(pCxt, pStmt, pTbName);
102,041✔
1581
  if (TSDB_CODE_SUCCESS == code) {
102,039✔
1582
    // option: [(field1_name, ...)]
1583
    code = preParseBoundColumnsClause(pCxt, pStmt);
102,037✔
1584
  }
1585
  if (TSDB_CODE_SUCCESS == code) {
102,040✔
1586
    // option: [USING stb_name]
1587
    code = parseUsingTableName(pCxt, pStmt);
102,035✔
1588
  }
1589
  return code;
102,041✔
1590
}
1591

1592
static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
296,772,106✔
1593
                                   const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) {
1594
  switch (pSchema->type) {
296,772,106!
1595
    case TSDB_DATA_TYPE_BOOL: {
19,011,873✔
1596
      if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) {
19,011,873!
1597
        if (IS_TRUE_STR(pToken->z, pToken->n)) {
18,043,370!
1598
          VALUE_SET_TRIVIAL_DATUM(&pVal->value, TRUE_VALUE);
9,693,238✔
1599
        } else if (IS_FALSE_STR(pToken->z, pToken->n)) {
8,350,132!
1600
          VALUE_SET_TRIVIAL_DATUM(&pVal->value, FALSE_VALUE);
8,384,914✔
1601
        } else if (TSDB_CODE_SUCCESS ==
×
1602
                   toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
1603
          int8_t v = (*(double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value) == 0 ? FALSE_VALUE : TRUE_VALUE);
×
1604
          valueSetDatum(&pVal->value, TSDB_DATA_TYPE_BOOL, &v, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes);
×
1605
        } else {
1606
          return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
×
1607
        }
1608
      } else if (pToken->type == TK_NK_INTEGER) {
968,503✔
1609
        int8_t v = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE);
959,319✔
1610
        VALUE_SET_TRIVIAL_DATUM(&pVal->value, v);
959,935✔
1611
      } else if (pToken->type == TK_NK_FLOAT) {
9,184!
1612
        int8_t v = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE);
×
1613
        VALUE_SET_TRIVIAL_DATUM(&pVal->value, v);
×
1614
      } else if ((pToken->type == TK_NK_HEX || pToken->type == TK_NK_BIN) &&
9,184!
1615
                 (TSDB_CODE_SUCCESS ==
1616
                  toDoubleEx(pToken->z, pToken->n, pToken->type, (double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value)))) {
9,184✔
1617
        int8_t v = *(double*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value) == 0 ? FALSE_VALUE : TRUE_VALUE;
×
1618
        valueSetDatum(&pVal->value, TSDB_DATA_TYPE_BOOL, &v, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes);
×
1619
      } else {
1620
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z);
×
1621
      }
1622
      break;
19,038,087✔
1623
    }
1624
    case TSDB_DATA_TYPE_TINYINT: {
19,025,099✔
1625
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
19,025,099✔
1626
      if (TSDB_CODE_SUCCESS != code) {
19,010,845!
1627
        return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z);
×
1628
      } else if (!IS_VALID_TINYINT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
19,010,845!
1629
        return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z);
1630
      }
1631
      break;
19,026,794✔
1632
    }
1633
    case TSDB_DATA_TYPE_UTINYINT: {
19,014,399✔
1634
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, (uint64_t*)&VALUE_GET_TRIVIAL_DATUM(&pVal->value));
19,014,399✔
1635
      if (TSDB_CODE_SUCCESS != code) {
19,016,226!
1636
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z);
1637
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT8_MAX) {
19,027,062!
1638
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z);
×
1639
      }
1640
      break;
19,027,062✔
1641
    }
1642
    case TSDB_DATA_TYPE_SMALLINT: {
19,030,609✔
1643
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
19,030,609✔
1644
      if (TSDB_CODE_SUCCESS != code) {
19,035,749!
1645
        return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z);
×
1646
      } else if (!IS_VALID_SMALLINT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
19,035,749!
1647
        return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z);
1648
      }
1649
      break;
19,061,924✔
1650
    }
1651
    case TSDB_DATA_TYPE_USMALLINT: {
19,017,537✔
1652
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
19,017,537✔
1653
      if (TSDB_CODE_SUCCESS != code) {
19,035,722✔
1654
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z);
2,544✔
1655
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT16_MAX) {
19,033,178!
1656
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z);
×
1657
      }
1658
      break;
19,033,178✔
1659
    }
1660
    case TSDB_DATA_TYPE_INT: {
28,418,062✔
1661
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
28,418,062✔
1662
      if (TSDB_CODE_SUCCESS != code) {
28,382,811!
1663
        return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z);
×
1664
      } else if (!IS_VALID_INT(VALUE_GET_TRIVIAL_DATUM(&pVal->value))) {
28,382,811!
1665
        return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z);
1666
      }
1667
      break;
28,492,615✔
1668
    }
1669
    case TSDB_DATA_TYPE_UINT: {
19,025,259✔
1670
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
19,025,259✔
1671
      if (TSDB_CODE_SUCCESS != code) {
19,042,545!
1672
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z);
1673
      } else if (VALUE_GET_TRIVIAL_DATUM(&pVal->value) > UINT32_MAX) {
19,047,901!
1674
        return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z);
×
1675
      }
1676
      break;
19,047,901✔
1677
    }
1678
    case TSDB_DATA_TYPE_BIGINT: {
20,053,477✔
1679
      int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
20,053,477✔
1680
      if (TSDB_CODE_SUCCESS != code) {
20,061,136✔
1681
        return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z);
8,516✔
1682
      }
1683
      break;
20,052,620✔
1684
    }
1685
    case TSDB_DATA_TYPE_UBIGINT: {
19,021,362✔
1686
      int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &VALUE_GET_TRIVIAL_DATUM(&pVal->value));
19,021,362✔
1687
      if (TSDB_CODE_SUCCESS != code) {
19,029,402!
1688
        return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z);
1689
      }
1690
      break;
19,042,366✔
1691
    }
1692
    case TSDB_DATA_TYPE_FLOAT: {
31,335,532✔
1693
      double  dv;
1694
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
31,335,532✔
1695
      if (TSDB_CODE_SUCCESS != code) {
31,152,213!
1696
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
×
1697
      }
1698
      if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
31,152,213!
1699
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
1700
      }
1701
      float f = dv;
31,395,498✔
1702
      valueSetDatum(&pVal->value, TSDB_DATA_TYPE_FLOAT, &f, sizeof(f));
31,395,498✔
1703
      break;
31,329,928✔
1704
    }
1705
    case TSDB_DATA_TYPE_DOUBLE: {
19,752,616✔
1706
      double  dv;
1707
      int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
19,752,616✔
1708
      if (TSDB_CODE_SUCCESS != code) {
19,768,492✔
1709
        return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
14,548✔
1710
      }
1711
      if (isinf(dv) || isnan(dv)) {
19,753,944!
1712
        return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
1713
      }
1714
      VALUE_SET_TRIVIAL_DATUM(&pVal->value, (*(int64_t*)&dv));
19,770,739✔
1715
      break;
19,770,739✔
1716
    }
1717
    case TSDB_DATA_TYPE_BINARY: {
19,879,680✔
1718
      // Too long values will raise the invalid sql error message
1719
      if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
19,879,680!
1720
        return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1721
      }
1722
      pVal->value.pData = taosMemoryMalloc(pToken->n);
19,879,680!
1723
      if (NULL == pVal->value.pData) {
19,875,843!
1724
        return terrno;
×
1725
      }
1726
      memcpy(pVal->value.pData, pToken->z, pToken->n);
19,875,843✔
1727
      pVal->value.nData = pToken->n;
19,875,843✔
1728
      break;
19,875,843✔
1729
    }
1730
    case TSDB_DATA_TYPE_VARBINARY: {
200✔
1731
      int32_t code = parseVarbinary(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes);
200✔
1732
      if (code != TSDB_CODE_SUCCESS) {
200!
1733
        return generateSyntaxErrMsg(&pCxt->msg, code, pSchema->name);
×
1734
      }
1735
      break;
200✔
1736
    }
1737
    case TSDB_DATA_TYPE_NCHAR: {
21,725,601✔
1738
      // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
1739
      int32_t len = 0;
21,725,601✔
1740
      int64_t realLen = pToken->n << 2;
21,725,601✔
1741
      if (realLen > pSchema->bytes - VARSTR_HEADER_SIZE) realLen = pSchema->bytes - VARSTR_HEADER_SIZE;
21,725,601!
1742
      char* pUcs4 = taosMemoryMalloc(realLen);
21,725,601!
1743
      if (NULL == pUcs4) {
21,720,378!
1744
        return terrno;
1✔
1745
      }
1746
      if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)pUcs4, realLen, &len, pCxt->pComCxt->charsetCxt)) {
21,720,378✔
1747
        taosMemoryFree(pUcs4);
6,056!
1748
        if (terrno == TAOS_SYSTEM_ERROR(E2BIG)) {
1!
1749
          return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1750
        }
1751
        char buf[512] = {0};
1✔
1752
        snprintf(buf, tListLen(buf), "%s", strerror(terrno));
1✔
1753
        return buildSyntaxErrMsg(&pCxt->msg, buf, pToken->z);
1✔
1754
      }
1755
      pVal->value.pData = pUcs4;
21,733,633✔
1756
      pVal->value.nData = len;
21,733,633✔
1757
      break;
21,733,633✔
1758
    }
1759
    case TSDB_DATA_TYPE_JSON: {
×
1760
      if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
×
1761
        return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z);
×
1762
      }
1763
      pVal->value.pData = taosMemoryMalloc(pToken->n);
×
1764
      if (NULL == pVal->value.pData) {
×
1765
        return terrno;
×
1766
      }
1767
      memcpy(pVal->value.pData, pToken->z, pToken->n);
×
1768
      pVal->value.nData = pToken->n;
×
1769
      break;
×
1770
    }
1771
    case TSDB_DATA_TYPE_GEOMETRY: {
200✔
1772
      int32_t        code = TSDB_CODE_FAILED;
200✔
1773
      unsigned char* output = NULL;
200✔
1774
      size_t         size = 0;
200✔
1775

1776
      code = parseGeometry(pToken, &output, &size);
200✔
1777
      if (code != TSDB_CODE_SUCCESS) {
200!
1778
        code = buildSyntaxErrMsg(&pCxt->msg, getGeosErrMsg(code), pToken->z);
×
1779
      }
1780
      // Too long values will raise the invalid sql error message
1781
      else if (size + VARSTR_HEADER_SIZE > pSchema->bytes) {
200!
1782
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
×
1783
      } else {
1784
        pVal->value.pData = taosMemoryMalloc(size);
200!
1785
        if (NULL == pVal->value.pData) {
200!
1786
          code = terrno;
×
1787
        } else {
1788
          memcpy(pVal->value.pData, output, size);
200✔
1789
          pVal->value.nData = size;
200✔
1790
        }
1791
      }
1792

1793
      geosFreeBuffer(output);
200✔
1794
      if (code != TSDB_CODE_SUCCESS) {
200!
1795
        return code;
×
1796
      }
1797

1798
      break;
200✔
1799
    }
1800
    case TSDB_DATA_TYPE_TIMESTAMP: {
28,517,027✔
1801
      if (parseTime(pSql, pToken, timePrec, &VALUE_GET_TRIVIAL_DATUM(&pVal->value), &pCxt->msg,
28,518,091!
1802
                    pCxt->pComCxt->timezone) != TSDB_CODE_SUCCESS) {
28,517,027✔
1803
        return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z);
1804
      }
1805
      break;
28,539,743✔
1806
    }
1807
    case TSDB_DATA_TYPE_DECIMAL: {
×
1808
      if (!pExtSchema) {
×
1809
        qError("Decimal type without ext schema info, cannot parse decimal values");
×
1810
        return TSDB_CODE_PAR_INTERNAL_ERROR;
×
1811
      }
1812
      uint8_t precision = 0, scale = 0;
×
1813
      decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale);
×
1814
      Decimal128 dec = {0};
×
1815
      int32_t code = decimal128FromStr(pToken->z, pToken->n, precision, scale, &dec);
×
1816
      if (TSDB_CODE_SUCCESS != code) {
×
1817
        return code;
×
1818
      }
1819

1820
      // precision check
1821
      // scale auto fit
1822

1823
      code = decimal128ToDataVal(&dec, &pVal->value);
×
1824
      if (TSDB_CODE_SUCCESS != code) {
×
1825
        return code;
×
1826
      }
1827
      break;
×
1828
    }
1829
    case TSDB_DATA_TYPE_DECIMAL64: {
×
1830
      if (!pExtSchema) {
×
1831
        qError("Decimal type without ext schema info, cannot parse decimal values");
×
1832
        return TSDB_CODE_PAR_INTERNAL_ERROR;
×
1833
      }
1834
      uint8_t precision = 0, scale = 0;
×
1835
      decimalFromTypeMod(pExtSchema->typeMod, &precision, &scale);
×
1836
      Decimal64 dec = {0};
×
1837
      int32_t code = decimal64FromStr(pToken->z, pToken->n, precision, scale, &dec);
×
1838
      if (TSDB_CODE_SUCCESS != code) {
×
1839
        return code;
×
1840
      }
1841
      code = decimal64ToDataVal(&dec, &pVal->value);
×
1842
      if (TSDB_CODE_SUCCESS != code) {
×
1843
        return code;
×
1844
      }
1845
      break;
×
1846
    }
1847
    default:
1848
      return TSDB_CODE_FAILED;
1849
  }
1850

1851
  pVal->flag = CV_FLAG_VALUE;
303,072,833✔
1852
  return TSDB_CODE_SUCCESS;
303,072,833✔
1853
}
1854

1855
static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema,
296,356,943✔
1856
                               const SSchemaExt* pExtSchema, int16_t timePrec, SColVal* pVal) {
1857
  int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pSchema->type);
296,356,943✔
1858
  if (TSDB_CODE_SUCCESS == code && isNullValue(pSchema->type, pToken)) {
596,915,623!
1859
    if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) {
693,304!
1860
      return buildSyntaxErrMsg(&pCxt->msg, "Primary timestamp column should not be null", pToken->z);
×
1861
    }
1862

1863
    pVal->flag = CV_FLAG_NULL;
693,304✔
1864
    return TSDB_CODE_SUCCESS;
693,304✔
1865
  }
1866

1867
  if (TSDB_CODE_SUCCESS == code) {
298,109,100!
1868
    if (pToken->n == 0 && IS_NUMERIC_TYPE(pSchema->type)) {
298,379,577!
1869
      return buildSyntaxErrMsg(&pCxt->msg, "invalid numeric data", pToken->z);
1870
    }
1871
    code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, pExtSchema, timePrec, pVal);
298,379,614✔
1872
  }
1873

1874
  return code;
295,910,930✔
1875
}
1876

1877
static void clearColValArray(SArray* pCols) {
27,381,017✔
1878
  int32_t num = taosArrayGetSize(pCols);
27,381,017✔
1879
  for (int32_t i = 0; i < num; ++i) {
327,987,132✔
1880
    SColVal* pCol = taosArrayGet(pCols, i);
300,365,559✔
1881
    if (IS_VAR_DATA_TYPE(pCol->value.type) || pCol->value.type == TSDB_DATA_TYPE_DECIMAL) {
300,553,476!
1882
      taosMemoryFreeClear(pCol->value.pData);
40,770,650!
1883
    }
1884
  }
1885
}
27,621,573✔
1886

1887
typedef struct SStbRowsDataContext {
1888
  SName stbName;
1889

1890
  STableMeta*   pStbMeta;
1891
  SNode*        pTagCond;
1892
  SBoundColInfo boundColsInfo;
1893

1894
  // the following fields are for each stb row
1895
  SArray*        aTagVals;
1896
  SArray*        aColVals;
1897
  SArray*        aTagNames;
1898
  SName          ctbName;
1899
  STag*          pTag;
1900
  STableMeta*    pCtbMeta;
1901
  SVCreateTbReq* pCreateCtbReq;
1902
  bool           hasTimestampTag;
1903
  bool           isJsonTag;
1904
} SStbRowsDataContext;
1905

1906
typedef union SRowsDataContext {
1907
  STableDataCxt*       pTableDataCxt;
1908
  SStbRowsDataContext* pStbRowsCxt;
1909
} SRowsDataContext;
1910

1911
int32_t parseTbnameToken(SMsgBuf* pMsgBuf, char* tname, SToken* pToken, bool* pFoundCtbName) {
4✔
1912
  *pFoundCtbName = false;
4!
1913

1914
  if (isNullValue(TSDB_DATA_TYPE_BINARY, pToken)) {
4!
1915
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be null value");
×
1916
  }
1917

1918
  if (pToken->n > 0) {
4!
1919
    if (pToken->n <= TSDB_TABLE_NAME_LEN - 1) {
4!
1920
      for (int i = 0; i < pToken->n; ++i) {
16✔
1921
        if (pToken->z[i] == '.') {
12!
1922
          return buildInvalidOperationMsg(pMsgBuf, "tbname can not contain '.'");
×
1923
        } else {
1924
          tname[i] = pToken->z[i];
12✔
1925
        }
1926
      }
1927
      tname[pToken->n] = '\0';
4✔
1928
      *pFoundCtbName = true;
4✔
1929
    } else {
1930
      return buildInvalidOperationMsg(pMsgBuf, "tbname is too long");
×
1931
    }
1932
  } else {
1933
    return buildInvalidOperationMsg(pMsgBuf, "tbname can not be empty");
×
1934
  }
1935
  return TSDB_CODE_SUCCESS;
4✔
1936
}
1937

1938
static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
13✔
1939
                                          SStbRowsDataContext* pStbRowsCxt, bool ctbFirst, const SToken* tagTokens,
1940
                                          SSchema* const* tagSchemas, int numOfTagTokens) {
1941
  int32_t code = TSDB_CODE_SUCCESS;
13✔
1942
  uint8_t precision = pStmt->pTableMeta->tableInfo.precision;
13✔
1943

1944
  if (code == TSDB_CODE_SUCCESS && ctbFirst) {
13!
1945
    for (int32_t i = 0; code == TSDB_CODE_SUCCESS && i < numOfTagTokens; ++i) {
17!
1946
      SToken*  pTagToken = (SToken*)(tagTokens + i);
4✔
1947
      SSchema* pTagSchema = tagSchemas[i];
4✔
1948
      code = checkAndTrimValue(pTagToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
4✔
1949
      if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pTagToken->type) {
4!
1950
        code = buildInvalidOperationMsg(&pCxt->msg, "not expected tag");
×
1951
      }
1952

1953
      if (code == TSDB_CODE_SUCCESS) {
4!
1954
        code = parseTagValue(&pCxt->msg, NULL, precision, pTagSchema, pTagToken, pStbRowsCxt->aTagNames,
4✔
1955
                             pStbRowsCxt->aTagVals, &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
4✔
1956
      }
1957
    }
1958
    if (code == TSDB_CODE_SUCCESS && !pStbRowsCxt->isJsonTag) {
13!
1959
      code = tTagNew(pStbRowsCxt->aTagVals, 1, false, &pStbRowsCxt->pTag);
13✔
1960
    }
1961
  }
1962

1963
  if (code == TSDB_CODE_SUCCESS && pStbRowsCxt->pTagCond) {
13!
1964
    code = checkSubtablePrivilege(pStbRowsCxt->aTagVals, pStbRowsCxt->aTagNames, &pStbRowsCxt->pTagCond);
×
1965
  }
1966
  return code;
13✔
1967
}
1968

1969
static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
24✔
1970
                                 SStbRowsDataContext* pStbRowsCxt, SToken* pToken, const SBoundColInfo* pCols,
1971
                                 const SSchema* pSchemas, const SSchemaExt* pExtSchemas, SToken* tagTokens,
1972
                                 SSchema** tagSchemas, int* pNumOfTagTokens, bool* bFoundTbName, bool* setCtbName,
1973
                                 SBoundColInfo* ctbCols) {
1974
  int32_t code = TSDB_CODE_SUCCESS;
24✔
1975
  SArray* pTagNames = pStbRowsCxt->aTagNames;
24✔
1976
  SArray* pTagVals = pStbRowsCxt->aTagVals;
24✔
1977
  bool    canParseTagsAfter = !pStbRowsCxt->pTagCond && !pStbRowsCxt->hasTimestampTag;
24!
1978
  int32_t numOfCols = getNumOfColumns(pStbRowsCxt->pStbMeta);
24✔
1979
  int32_t numOfTags = getNumOfTags(pStbRowsCxt->pStbMeta);
24✔
1980
  int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta);
24✔
1981
  uint8_t precision = getTableInfo(pStbRowsCxt->pStbMeta).precision;
24✔
1982
  int     tag_index = 0;
24✔
1983
  int     col_index = 0;
24✔
1984
  for (int i = 0; i < pCols->numOfBound && (code) == TSDB_CODE_SUCCESS; ++i) {
141!
1985
    const char* pTmpSql = *ppSql;
119✔
1986
    bool        ignoreComma = false;
119✔
1987
    NEXT_TOKEN_WITH_PREV_EXT(*ppSql, *pToken, &ignoreComma);
119✔
1988

1989
    if (ignoreComma) {
119!
1990
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pTmpSql);
×
1991
      break;
×
1992
    }
1993

1994
    if (TK_NK_RP == pToken->type) {
119!
1995
      code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
×
1996
      break;
×
1997
    }
1998

1999
    if (TK_NK_QUESTION == pToken->type) {
119✔
2000
      if (!pCxt->pComCxt->isStmtBind && i != 0) {
105!
2001
        return buildInvalidOperationMsg(&pCxt->msg, "not support mixed bind and non-bind values");
2✔
2002
      }
2003
      pCxt->isStmtBind = true;
105✔
2004
      if (pCols->pColIndex[i] == tbnameIdx) {
105✔
2005
        *bFoundTbName = true;
18✔
2006
        char* tbName = NULL;
18✔
2007
        if ((*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName) == TSDB_CODE_SUCCESS) {
18✔
2008
          tstrncpy(pStbRowsCxt->ctbName.tname, tbName, sizeof(pStbRowsCxt->ctbName.tname));
9✔
2009
          tstrncpy(pStmt->usingTableName.tname, pStmt->targetTableName.tname, sizeof(pStmt->usingTableName.tname));
9✔
2010
          tstrncpy(pStmt->targetTableName.tname, tbName, sizeof(pStmt->targetTableName.tname));
9✔
2011
          tstrncpy(pStmt->usingTableName.dbname, pStmt->targetTableName.dbname, sizeof(pStmt->usingTableName.dbname));
9✔
2012
          pStmt->usingTableName.type = 1;
9✔
2013
          pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE;  // set the table type to child table for parse cache
9✔
2014
          *setCtbName = true;
9✔
2015
        }
2016
      } else if (pCols->pColIndex[i] < numOfCols) {
87✔
2017
        // bind column
2018
        if (ctbCols->pColIndex == NULL) {
47✔
2019
          ctbCols->pColIndex = taosMemoryCalloc(numOfCols, sizeof(int16_t));
18!
2020
          if (NULL == ctbCols->pColIndex) {
18!
2021
            return terrno;
×
2022
          }
2023
        }
2024
        ctbCols->pColIndex[col_index++] = pCols->pColIndex[i];
47✔
2025
        ctbCols->numOfBound++;
47✔
2026
        ctbCols->numOfCols++;
47✔
2027

2028
      } else if (pCols->pColIndex[i] < tbnameIdx) {
40!
2029
        if (pCxt->tags.pColIndex == NULL) {
40✔
2030
          pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t));
14!
2031
          if (NULL == pCxt->tags.pColIndex) {
14!
2032
            return terrno;
×
2033
          }
2034
        }
2035
        if (!(tag_index < numOfTags)) {
40!
2036
          return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags");
×
2037
        }
2038
        pStmt->usingTableProcessing = true;
40✔
2039
        pCxt->tags.pColIndex[tag_index++] = pCols->pColIndex[i] - numOfCols;
40✔
2040
        pCxt->tags.mixTagsCols = true;
40✔
2041
        pCxt->tags.numOfBound++;
40✔
2042
        pCxt->tags.numOfCols++;
40✔
2043
      } else {
2044
        return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfBound");
×
2045
      }
2046
    } else {
2047
      if (pCxt->pComCxt->isStmtBind) {
14✔
2048
        return buildInvalidOperationMsg(&pCxt->msg, "not support mixed bind and non-bind values");
2✔
2049
      }
2050
      if (pCols->pColIndex[i] < numOfCols) {
12✔
2051
        const SSchema*    pSchema = &pSchemas[pCols->pColIndex[i]];
4✔
2052
        const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i];
4✔
2053
        SColVal*       pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]);
4✔
2054
        code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, pExtSchema, precision, pVal);
4✔
2055
        if (TK_NK_VARIABLE == pToken->type) {
4!
2056
          code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
2057
        }
2058
      } else if (pCols->pColIndex[i] < tbnameIdx) {
8✔
2059
        const SSchema* pTagSchema = &pSchemas[pCols->pColIndex[i]];
4✔
2060
        if (canParseTagsAfter) {
4!
2061
          tagTokens[(*pNumOfTagTokens)] = *pToken;
4✔
2062
          tagSchemas[(*pNumOfTagTokens)] = (SSchema*)pTagSchema;
4✔
2063
          ++(*pNumOfTagTokens);
4✔
2064
        } else {
2065
          code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, pTagSchema->type);
×
2066
          if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pToken->type) {
×
2067
            code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value");
×
2068
          }
2069
          if (code == TSDB_CODE_SUCCESS) {
×
2070
            code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, pTagNames, pTagVals,
×
2071
                                 &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt);
×
2072
          }
2073
        }
2074
      } else if (pCols->pColIndex[i] == tbnameIdx) {
4!
2075
        code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, TSDB_DATA_TYPE_BINARY);
4✔
2076
        if (TK_NK_VARIABLE == pToken->type) {
4!
2077
          code = buildInvalidOperationMsg(&pCxt->msg, "not expected tbname");
×
2078
        }
2079

2080
        if (code == TSDB_CODE_SUCCESS) {
4!
2081
          code = parseTbnameToken(&pCxt->msg, pStbRowsCxt->ctbName.tname, pToken, bFoundTbName);
4✔
2082
        }
2083
      }
2084
    }
2085

2086
    if (code == TSDB_CODE_SUCCESS && i < pCols->numOfBound - 1) {
117!
2087
      NEXT_VALID_TOKEN(*ppSql, *pToken);
95!
2088
      if (TK_NK_COMMA != pToken->type) {
95!
2089
        code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
2090
      }
2091
    }
2092
  }
2093

2094
  return code;
22✔
2095
}
2096

2097
static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
24✔
2098
                               SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken, bool* pCtbFirst,
2099
                               bool* setCtbName, SBoundColInfo* ctbCols) {
2100
  SBoundColInfo* pCols = &pStbRowsCxt->boundColsInfo;
24✔
2101
  SSchema*       pSchemas = getTableColumnSchema(pStbRowsCxt->pStbMeta);
24✔
2102
  SSchemaExt*    pExtSchemas = getTableColumnExtSchema(pStbRowsCxt->pStbMeta);
24✔
2103

2104
  bool        bFoundTbName = false;
24✔
2105
  const char* pOrigSql = *ppSql;
24✔
2106

2107
  int32_t  code = TSDB_CODE_SUCCESS;
24✔
2108
  SToken   tagTokens[TSDB_MAX_TAGS] = {0};
24✔
2109
  SSchema* tagSchemas[TSDB_MAX_TAGS] = {0};
24✔
2110
  int      numOfTagTokens = 0;
24✔
2111

2112
  code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, pExtSchemas, tagTokens, tagSchemas,
24✔
2113
                           &numOfTagTokens, &bFoundTbName, setCtbName, ctbCols);
2114

2115
  if (code != TSDB_CODE_SUCCESS) {
24✔
2116
    return code;
2✔
2117
  }
2118

2119
  if (!bFoundTbName) {
22!
2120
    code = buildSyntaxErrMsg(&pCxt->msg, "tbname value expected", pOrigSql);
×
2121
  }
2122

2123
  bool ctbFirst = true;
22✔
2124
  char ctbFName[TSDB_TABLE_FNAME_LEN];
2125
  if (code == TSDB_CODE_SUCCESS) {
22!
2126
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
22✔
2127
  }
2128
  if (TSDB_CODE_SUCCESS == code) {
22✔
2129
    STableMeta** pCtbMeta = taosHashGet(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName));
13✔
2130
    ctbFirst = (pCtbMeta == NULL);
13✔
2131
    if (!ctbFirst) {
13!
2132
      pStbRowsCxt->pCtbMeta->uid = (*pCtbMeta)->uid;
×
2133
      pStbRowsCxt->pCtbMeta->vgId = (*pCtbMeta)->vgId;
×
2134
    }
2135
    *pCtbFirst = ctbFirst;
13✔
2136
  }
2137

2138
  if (code == TSDB_CODE_SUCCESS) {
22✔
2139
    code = processCtbTagsAfterCtbName(pCxt, pStmt, pStbRowsCxt, ctbFirst, tagTokens, tagSchemas, numOfTagTokens);
13✔
2140
  }
2141

2142
  if (code == TSDB_CODE_SUCCESS) {
22✔
2143
    *pGotRow = true;
13✔
2144
  }
2145
  return code;
22✔
2146
}
2147

2148
static int32_t processCtbAutoCreationAndCtbMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
13✔
2149
                                                SStbRowsDataContext* pStbRowsCxt) {
2150
  int32_t code = TSDB_CODE_SUCCESS;
13✔
2151

2152
  pStbRowsCxt->pCreateCtbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
13!
2153
  if (pStbRowsCxt->pCreateCtbReq == NULL) {
13!
2154
    code = terrno;
×
2155
  }
2156
  if (code == TSDB_CODE_SUCCESS) {
13!
2157
    code = insBuildCreateTbReq(pStbRowsCxt->pCreateCtbReq, pStbRowsCxt->ctbName.tname, pStbRowsCxt->pTag,
13✔
2158
                               pStbRowsCxt->pStbMeta->uid, pStbRowsCxt->stbName.tname, pStbRowsCxt->aTagNames,
13✔
2159
                               getNumOfTags(pStbRowsCxt->pStbMeta), TSDB_DEFAULT_TABLE_TTL);
13✔
2160
    pStbRowsCxt->pTag = NULL;
13✔
2161
  }
2162

2163
  if (code == TSDB_CODE_SUCCESS) {
13!
2164
    char ctbFName[TSDB_TABLE_FNAME_LEN];
2165
    code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
13✔
2166
    SVgroupInfo      vg;
2167
    SRequestConnInfo conn = {.pTrans = pCxt->pComCxt->pTransporter,
13✔
2168
                             .requestId = pCxt->pComCxt->requestId,
13✔
2169
                             .requestObjRefId = pCxt->pComCxt->requestRid,
13✔
2170
                             .mgmtEps = pCxt->pComCxt->mgmtEpSet};
13✔
2171
    if (TSDB_CODE_SUCCESS == code) {
13!
2172
      code = catalogGetTableHashVgroup(pCxt->pComCxt->pCatalog, &conn, &pStbRowsCxt->ctbName, &vg);
13✔
2173
    }
2174
    if (code == TSDB_CODE_SUCCESS) {
13!
2175
      code = taosHashPut(pStmt->pVgroupsHashObj, (const char*)(&vg.vgId), sizeof(vg.vgId), &vg, sizeof(vg));
13✔
2176
    }
2177
    STableMeta* pBackup = NULL;
13✔
2178
    if (TSDB_CODE_SUCCESS == code) {
13!
2179
      pStbRowsCxt->pCtbMeta->uid = taosHashGetSize(pStmt->pSubTableHashObj) + 1;
13✔
2180
      pStbRowsCxt->pCtbMeta->vgId = vg.vgId;
13✔
2181

2182
      code = cloneTableMeta(pStbRowsCxt->pCtbMeta, &pBackup);
13✔
2183
    }
2184
    if (TSDB_CODE_SUCCESS == code) {
13!
2185
      code = taosHashPut(pStmt->pSubTableHashObj, ctbFName, strlen(ctbFName), &pBackup, POINTER_BYTES);
13✔
2186
    }
2187
    if (TSDB_CODE_SUCCESS == code) {
13!
2188
      code = collectUseTable(&pStbRowsCxt->ctbName, pStmt->pTableNameHashObj);
13✔
2189
    }
2190
  }
2191
  return code;
13✔
2192
}
2193

2194
static void clearStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
39✔
2195
  if (pStbRowsCxt == NULL) return;
39!
2196

2197
  taosArrayClear(pStbRowsCxt->aTagNames);
39✔
2198
  for (int i = 0; i < taosArrayGetSize(pStbRowsCxt->aTagVals); ++i) {
43✔
2199
    STagVal* p = (STagVal*)taosArrayGet(pStbRowsCxt->aTagVals, i);
4✔
2200
    if (IS_VAR_DATA_TYPE(p->type)) {
4!
2201
      taosMemoryFreeClear(p->pData);
×
2202
    }
2203
  }
2204
  taosArrayClear(pStbRowsCxt->aTagVals);
39✔
2205

2206
  clearColValArray(pStbRowsCxt->aColVals);
39✔
2207

2208
  tTagFree(pStbRowsCxt->pTag);
39✔
2209
  pStbRowsCxt->pTag = NULL;
39✔
2210
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
39!
2211
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
39!
2212
}
2213

2214
static int32_t parseStbBoundInfo(SVnodeModifyOpStmt* pStmt, SStbRowsDataContext* pStbRowsCxt,
11✔
2215
                                 STableDataCxt** ppTableDataCxt) {
2216
  char    tbFName[TSDB_TABLE_FNAME_LEN];
2217
  int32_t code = tNameExtractFullName(&pStmt->targetTableName, tbFName);
11✔
2218
  if (TSDB_CODE_SUCCESS != code) {
11!
2219
    return code;
×
2220
  }
2221
  if (pStmt->usingTableProcessing) {
11✔
2222
    pStmt->pTableMeta->uid = 0;
6✔
2223
  }
2224

2225
  code = insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta,
11✔
2226
                            &pStmt->pCreateTblReq, ppTableDataCxt, false, true);
2227
  if (code != TSDB_CODE_SUCCESS) {
11!
2228
    return code;
×
2229
  }
2230

2231
  insDestroyBoundColInfo(&((*ppTableDataCxt)->boundColsInfo));
11✔
2232
  (*ppTableDataCxt)->boundColsInfo = pStbRowsCxt->boundColsInfo;
11✔
2233

2234
  (*ppTableDataCxt)->boundColsInfo.pColIndex = taosMemoryCalloc(pStbRowsCxt->boundColsInfo.numOfBound, sizeof(int16_t));
11!
2235
  if (NULL == (*ppTableDataCxt)->boundColsInfo.pColIndex) {
11!
2236
    return terrno;
×
2237
  }
2238
  (void)memcpy((*ppTableDataCxt)->boundColsInfo.pColIndex, pStbRowsCxt->boundColsInfo.pColIndex,
11✔
2239
               sizeof(int16_t) * pStmt->pStbRowsCxt->boundColsInfo.numOfBound);
11✔
2240
  return TSDB_CODE_SUCCESS;
11✔
2241
}
2242

2243
static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql,
24✔
2244
                              SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken,
2245
                              STableDataCxt** ppTableDataCxt) {
2246
  bool    bFirstTable = false;
24✔
2247
  bool    setCtbName = false;
24✔
2248
  SBoundColInfo ctbCols = {0};
24✔
2249
  int32_t code = getStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pGotRow, pToken, &bFirstTable, &setCtbName, &ctbCols);
24✔
2250

2251
  if (!setCtbName && pCxt->isStmtBind) {
24✔
2252
    return parseStbBoundInfo(pStmt, pStbRowsCxt, ppTableDataCxt);
11✔
2253
  }
2254

2255
  if (code != TSDB_CODE_SUCCESS || !*pGotRow) {
13!
2256
    return code;
×
2257
  }
2258

2259
  if (code == TSDB_CODE_SUCCESS && bFirstTable) {
13!
2260
    code = processCtbAutoCreationAndCtbMeta(pCxt, pStmt, pStbRowsCxt);
13✔
2261
  }
2262
  if (code == TSDB_CODE_SUCCESS) {
13!
2263
    if (pCxt->isStmtBind) {
13✔
2264
      char ctbFName[TSDB_TABLE_FNAME_LEN];
2265
      code = tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName);
9✔
2266
      if (code != TSDB_CODE_SUCCESS) {
9!
2267
        return code;
×
2268
      }
2269
      code = insGetTableDataCxt(pStmt->pTableBlockHashObj, ctbFName, strlen(ctbFName), pStbRowsCxt->pCtbMeta,
9✔
2270
                                &pStbRowsCxt->pCreateCtbReq, ppTableDataCxt, true, true);
2271
    } else {
2272
      code =
2273
          insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid),
4✔
2274
                             pStbRowsCxt->pCtbMeta, &pStbRowsCxt->pCreateCtbReq, ppTableDataCxt, false, true);
2275
    }
2276
  }
2277
  if (code == TSDB_CODE_SUCCESS) {
13!
2278
    if (pCxt->isStmtBind) {
13✔
2279
      int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta);
9✔
2280
      code = initTableColSubmitDataWithBoundInfo(*ppTableDataCxt, ctbCols);
9✔
2281
    } else {
2282
      code = initTableColSubmitData(*ppTableDataCxt);
4✔
2283
    }
2284
  }
2285
  if (code == TSDB_CODE_SUCCESS && !pCxt->isStmtBind) {
13!
2286
    SRow** pRow = taosArrayReserve((*ppTableDataCxt)->pData->aRowP, 1);
4✔
2287
    code = tRowBuild(pStbRowsCxt->aColVals, (*ppTableDataCxt)->pSchema, pRow);
4✔
2288
    if (TSDB_CODE_SUCCESS == code) {
4!
2289
      SRowKey key;
2290
      tRowGetKey(*pRow, &key);
8!
2291
      insCheckTableDataOrder(*ppTableDataCxt, &key);
4✔
2292
    }
2293
  }
2294

2295
  if (code == TSDB_CODE_SUCCESS) {
13!
2296
    *pGotRow = true;
13✔
2297
  }
2298

2299
  clearStbRowsDataContext(pStbRowsCxt);
13✔
2300
  insDestroyBoundColInfo(&ctbCols);
13✔
2301

2302
  return code;
13✔
2303
}
2304

2305
static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow,
27,446,653✔
2306
                       SToken* pToken) {
2307
  SBoundColInfo*    pCols = &pTableCxt->boundColsInfo;
27,446,653✔
2308
  SSchema*          pSchemas = getTableColumnSchema(pTableCxt->pMeta);
27,446,653✔
2309
  const SSchemaExt* pExtSchemas = getTableColumnExtSchema(pTableCxt->pMeta);
27,428,499✔
2310

2311
  int32_t code = TSDB_CODE_SUCCESS;
27,406,230✔
2312
  // 1. set the parsed value from sql string
2313
  for (int i = 0; i < pCols->numOfBound && TSDB_CODE_SUCCESS == code; ++i) {
322,843,950!
2314
    const char* pOrigSql = *pSql;
295,619,757✔
2315
    bool        ignoreComma = false;
295,619,757✔
2316
    NEXT_TOKEN_WITH_PREV_EXT(*pSql, *pToken, &ignoreComma);
295,619,757✔
2317
    if (ignoreComma) {
300,988,232!
2318
      code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pOrigSql);
×
2319
      break;
2✔
2320
    }
2321

2322
    SSchema*          pSchema = &pSchemas[pCols->pColIndex[i]];
300,988,232✔
2323
    const SSchemaExt* pExtSchema = pExtSchemas + pCols->pColIndex[i];
300,988,232✔
2324
    SColVal*          pVal = taosArrayGet(pTableCxt->pValues, pCols->pColIndex[i]);
300,988,232✔
2325

2326
    if (pToken->type == TK_NK_QUESTION) {
300,433,645!
2327
      pCxt->isStmtBind = true;
2328
      if (NULL == pCxt->pComCxt->pStmtCb) {
×
2329
        code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pToken->z);
×
2330
        break;
×
2331
      }
2332
    } else {
2333
      if (TK_NK_RP == pToken->type) {
301,876,721!
2334
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
×
2335
        break;
×
2336
      }
2337

2338
      if (pCxt->isStmtBind) {
301,876,721✔
2339
        code = buildInvalidOperationMsg(&pCxt->msg, "stmt bind param does not support normal value in sql");
2✔
2340
        break;
2✔
2341
      }
2342

2343
      if (TSDB_CODE_SUCCESS == code) {
301,876,719✔
2344
        code = parseValueToken(pCxt, pSql, pToken, pSchema, pExtSchema, getTableInfo(pTableCxt->pMeta).precision, pVal);
299,714,864✔
2345
      }
2346
    }
2347

2348
    if (TSDB_CODE_SUCCESS == code && i < pCols->numOfBound - 1) {
295,235,436✔
2349
      NEXT_VALID_TOKEN(*pSql, *pToken);
271,242,437✔
2350
      if (TK_NK_COMMA != pToken->type) {
268,685,494!
2351
        code = buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z);
×
2352
      }
2353
    }
2354
  }
2355

2356
  if (TSDB_CODE_SUCCESS == code && !pCxt->isStmtBind) {
27,224,195!
2357
    SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1);
27,451,475✔
2358
    code = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow);
27,392,450✔
2359
    if (TSDB_CODE_SUCCESS == code) {
27,415,878!
2360
      SRowKey key;
2361
      tRowGetKey(*pRow, &key);
54,911,708✔
2362
      insCheckTableDataOrder(pTableCxt, &key);
27,455,855✔
2363
    }
2364
  }
2365

2366
  if (TSDB_CODE_SUCCESS == code && !pCxt->isStmtBind) {
27,146,928!
2367
    *pGotRow = true;
27,433,901✔
2368
  }
2369

2370
  clearColValArray(pTableCxt->pValues);
27,146,928✔
2371

2372
  return code;
27,403,583✔
2373
}
2374

2375
// pSql -> (field1_value, ...) [(field1_value2, ...) ...]
2376
static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
102,012✔
2377
                           int32_t* pNumOfRows, SToken* pToken) {
2378
  int32_t code = TSDB_CODE_SUCCESS;
102,012✔
2379

2380
  (*pNumOfRows) = 0;
102,012✔
2381
  while (TSDB_CODE_SUCCESS == code) {
27,512,969✔
2382
    int32_t index = 0;
27,509,197✔
2383
    NEXT_TOKEN_KEEP_SQL(pStmt->pSql, *pToken, index);
27,509,197✔
2384
    if (TK_NK_LP != pToken->type) {
27,557,700✔
2385
      break;
101,996✔
2386
    }
2387
    pStmt->pSql += index;
27,455,704✔
2388

2389
    bool gotRow = false;
27,455,704✔
2390
    if (TSDB_CODE_SUCCESS == code) {
27,455,704!
2391
      if (!pStmt->stbSyntax) {
27,482,198✔
2392
        code = parseOneRow(pCxt, &pStmt->pSql, rowsDataCxt.pTableDataCxt, &gotRow, pToken);
27,479,609✔
2393
      } else {
2394
        STableDataCxt* pTableDataCxt = NULL;
2,589✔
2395
        code = parseOneStbRow(pCxt, pStmt, &pStmt->pSql, rowsDataCxt.pStbRowsCxt, &gotRow, pToken, &pTableDataCxt);
2,589✔
2396
      }
2397
    }
2398

2399
    if (TSDB_CODE_SUCCESS == code) {
27,296,521!
2400
      NEXT_VALID_TOKEN(pStmt->pSql, *pToken);
27,388,822!
2401
      if (TK_NK_COMMA == pToken->type) {
27,400,287✔
2402
        code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
4✔
2403
      } else if (TK_NK_RP != pToken->type) {
27,400,283!
2404
        code = buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z);
×
2405
      }
2406
    }
2407

2408
    if (TSDB_CODE_SUCCESS == code && gotRow) {
27,410,957!
2409
      (*pNumOfRows)++;
27,408,306✔
2410
    }
2411
  }
2412

2413
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) &&
105,768✔
2414
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
144!
2415
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
2416
  }
2417
  return code;
102,027✔
2418
}
2419

2420
// VALUES (field1_value, ...) [(field1_value2, ...) ...]
2421
static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataContext,
102,015✔
2422
                                 SToken* pToken) {
2423
  int32_t numOfRows = 0;
102,015✔
2424
  int32_t code = parseValues(pCxt, pStmt, rowsDataContext, &numOfRows, pToken);
102,015✔
2425
  if (TSDB_CODE_SUCCESS == code) {
102,027✔
2426
    pStmt->totalRowsNum += numOfRows;
101,996✔
2427
    pStmt->totalTbNum += 1;
101,996✔
2428
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_INSERT);
101,996✔
2429
  }
2430
  return code;
102,027✔
2431
}
2432

2433
static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
×
2434
                            int32_t* pNumOfRows) {
2435
  int32_t code = TSDB_CODE_SUCCESS;
×
2436
  (*pNumOfRows) = 0;
×
2437
  char*   pLine = NULL;
×
2438
  int64_t readLen = 0;
×
2439
  bool    firstLine = (pStmt->fileProcessing == false);
×
2440
  pStmt->fileProcessing = false;
×
2441
  while (TSDB_CODE_SUCCESS == code && (readLen = taosGetLineFile(pStmt->fp, &pLine)) != -1) {
×
2442
    if (('\r' == pLine[readLen - 1]) || ('\n' == pLine[readLen - 1])) {
×
2443
      pLine[--readLen] = '\0';
×
2444
    }
2445

2446
    if (readLen == 0) {
×
2447
      firstLine = false;
×
2448
      continue;
×
2449
    }
2450

2451
    bool gotRow = false;
×
2452
    if (TSDB_CODE_SUCCESS == code) {
×
2453
      SToken token;
2454
      (void)strtolower(pLine, pLine);
×
2455
      const char* pRow = pLine;
×
2456
      if (!pStmt->stbSyntax) {
×
2457
        code = parseOneRow(pCxt, (const char**)&pRow, rowsDataCxt.pTableDataCxt, &gotRow, &token);
×
2458
      } else {
2459
        STableDataCxt* pTableDataCxt = NULL;
×
2460
        code =
2461
            parseOneStbRow(pCxt, pStmt, (const char**)&pRow, rowsDataCxt.pStbRowsCxt, &gotRow, &token, &pTableDataCxt);
×
2462
        if (code == TSDB_CODE_SUCCESS) {
×
2463
          SStbRowsDataContext* pStbRowsCxt = rowsDataCxt.pStbRowsCxt;
×
2464
          void*                pData = pTableDataCxt;
×
2465
          code = taosHashPut(pStmt->pTableCxtHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid),
×
2466
                             &pData, POINTER_BYTES);
2467
          if (TSDB_CODE_SUCCESS != code) {
×
2468
            break;
×
2469
          }
2470
        }
2471
      }
2472
      if (code && firstLine) {
×
2473
        firstLine = false;
×
2474
        code = 0;
×
2475
        continue;
×
2476
      }
2477
    }
2478

2479
    if (TSDB_CODE_SUCCESS == code && gotRow) {
×
2480
      (*pNumOfRows)++;
×
2481
    }
2482

2483
    if (TSDB_CODE_SUCCESS == code && (*pNumOfRows) >= tsMaxInsertBatchRows) {
×
2484
      pStmt->fileProcessing = true;
×
2485
      break;
×
2486
    }
2487

2488
    firstLine = false;
×
2489
  }
2490
  taosMemoryFree(pLine);
×
2491

2492
  parserDebug("QID:0x%" PRIx64 ", %d rows have been parsed", pCxt->pComCxt->requestId, *pNumOfRows);
×
2493

2494
  if (TSDB_CODE_SUCCESS == code && 0 == (*pNumOfRows) && 0 == pStmt->totalRowsNum &&
×
2495
      (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) && !pStmt->fileProcessing) {
×
2496
    code = buildSyntaxErrMsg(&pCxt->msg, "no any data points", NULL);
×
2497
  }
2498
  return code;
×
2499
}
2500

2501
static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt,
×
2502
                                     SRowsDataContext rowsDataCxt) {
2503
  // init only for file
2504
  if (NULL == pStmt->pTableCxtHashObj) {
×
2505
    pStmt->pTableCxtHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
×
2506
    if (!pStmt->pTableCxtHashObj) {
×
2507
      return terrno;
×
2508
    }
2509
  }
2510
  int32_t numOfRows = 0;
×
2511
  int32_t code = parseCsvFile(pCxt, pStmt, rowsDataCxt, &numOfRows);
×
2512
  if (TSDB_CODE_SUCCESS == code) {
×
2513
    pStmt->totalRowsNum += numOfRows;
×
2514
    pStmt->totalTbNum += 1;
×
2515
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT);
×
2516
    if (rowsDataCxt.pTableDataCxt && rowsDataCxt.pTableDataCxt->pData) {
×
2517
      rowsDataCxt.pTableDataCxt->pData->flags |= SUBMIT_REQ_FROM_FILE;
×
2518
    }
2519
    if (!pStmt->fileProcessing) {
×
2520
      code = taosCloseFile(&pStmt->fp);
×
2521
      if (TSDB_CODE_SUCCESS != code) {
×
2522
        parserWarn("QID:0x%" PRIx64 ", failed to close file.", pCxt->pComCxt->requestId);
×
2523
      }
2524
    } else {
2525
      parserDebug("QID:0x%" PRIx64 ", insert from csv. File is too large, do it in batches.", pCxt->pComCxt->requestId);
×
2526
    }
2527
    if (pStmt->insertType != TSDB_QUERY_TYPE_FILE_INSERT) {
×
2528
      return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", NULL);
×
2529
    }
2530
  } else {
2531
    return buildInvalidOperationMsg(&pCxt->msg, tstrerror(code));
×
2532
  }
2533

2534
  // just record pTableCxt whose data come from file
2535
  if (!pStmt->stbSyntax && numOfRows > 0) {
×
2536
    void* pData = rowsDataCxt.pTableDataCxt;
×
2537
    code = taosHashPut(pStmt->pTableCxtHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid), &pData,
×
2538
                       POINTER_BYTES);
2539
  }
2540

2541
  return code;
×
2542
}
2543

2544
static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pFilePath,
×
2545
                                 SRowsDataContext rowsDataCxt) {
2546
  char filePathStr[PATH_MAX + 16] = {0};
×
2547
  if (TK_NK_STRING == pFilePath->type) {
×
2548
    (void)trimString(pFilePath->z, pFilePath->n, filePathStr, sizeof(filePathStr));
×
2549
    if (strlen(filePathStr) >= PATH_MAX) {
×
2550
      return buildSyntaxErrMsg(&pCxt->msg, "file path is too long, max length is 4096", pFilePath->z);
×
2551
    }
2552
  } else {
2553
    if (pFilePath->n >= PATH_MAX) {
×
2554
      return buildSyntaxErrMsg(&pCxt->msg, "file path is too long, max length is 4096", pFilePath->z);
×
2555
    }
2556
    strncpy(filePathStr, pFilePath->z, pFilePath->n);
×
2557
  }
2558
  pStmt->fp = taosOpenFile(filePathStr, TD_FILE_READ | TD_FILE_STREAM);
×
2559
  if (NULL == pStmt->fp) {
×
2560
    return terrno;
×
2561
  }
2562

2563
  return parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
×
2564
}
2565

2566
static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt,
×
2567
                               SToken* pToken) {
2568
  if (tsUseAdapter) {
×
2569
    return buildInvalidOperationMsg(&pCxt->msg, "proxy mode does not support csv loading");
×
2570
  }
2571

2572
  NEXT_TOKEN(pStmt->pSql, *pToken);
×
2573
  if (0 == pToken->n || (TK_NK_STRING != pToken->type && TK_NK_ID != pToken->type)) {
×
2574
    return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", pToken->z);
×
2575
  }
2576
  return parseDataFromFile(pCxt, pStmt, pToken, rowsDataCxt);
×
2577
}
2578

2579
// VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
2580
static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt) {
102,009✔
2581
  SToken token;
2582
  NEXT_TOKEN(pStmt->pSql, token);
102,009✔
2583
  switch (token.type) {
102,026!
2584
    case TK_VALUES:
102,026✔
2585
      if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT)) {
102,026!
2586
        return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is exclusive", token.z);
×
2587
      }
2588
      return parseValuesClause(pCxt, pStmt, rowsDataCxt, &token);
102,026✔
2589
    case TK_FILE:
×
2590
      return parseFileClause(pCxt, pStmt, rowsDataCxt, &token);
×
2591
    default:
×
2592
      break;
×
2593
  }
2594
  return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z);
×
2595
}
2596

2597
static void destroyStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) {
201,393✔
2598
  if (pStbRowsCxt == NULL) return;
201,393✔
2599
  clearStbRowsDataContext(pStbRowsCxt);
24✔
2600
  taosArrayDestroy(pStbRowsCxt->aColVals);
26✔
2601
  pStbRowsCxt->aColVals = NULL;
26✔
2602
  taosArrayDestroy(pStbRowsCxt->aTagVals);
26✔
2603
  pStbRowsCxt->aTagVals = NULL;
26✔
2604
  taosArrayDestroy(pStbRowsCxt->aTagNames);
26✔
2605
  pStbRowsCxt->aTagNames = NULL;
26✔
2606
  insDestroyBoundColInfo(&pStbRowsCxt->boundColsInfo);
26✔
2607
  tTagFree(pStbRowsCxt->pTag);
26✔
2608
  pStbRowsCxt->pTag = NULL;
26✔
2609
  taosMemoryFreeClear(pStbRowsCxt->pCtbMeta);
26!
2610
  tdDestroySVCreateTbReq(pStbRowsCxt->pCreateCtbReq);
26!
2611
  taosMemoryFreeClear(pStbRowsCxt->pCreateCtbReq);
26!
2612
}
2613

2614
static int32_t constructStbRowsDataContext(SVnodeModifyOpStmt* pStmt, SStbRowsDataContext** ppStbRowsCxt) {
26✔
2615
  SStbRowsDataContext* pStbRowsCxt = taosMemoryCalloc(1, sizeof(SStbRowsDataContext));
26!
2616
  if (!pStbRowsCxt) {
26!
2617
    return terrno;
×
2618
  }
2619
  tNameAssign(&pStbRowsCxt->stbName, &pStmt->targetTableName);
26✔
2620
  int32_t code = collectUseTable(&pStbRowsCxt->stbName, pStmt->pTableNameHashObj);
26✔
2621
  if (TSDB_CODE_SUCCESS == code) {
26!
2622
    code = collectUseDatabase(&pStbRowsCxt->stbName, pStmt->pDbFNameHashObj);
26✔
2623
  }
2624
  if (TSDB_CODE_SUCCESS == code) {
26!
2625
    pStbRowsCxt->ctbName.type = TSDB_TABLE_NAME_T;
26✔
2626
    pStbRowsCxt->ctbName.acctId = pStbRowsCxt->stbName.acctId;
26✔
2627
    memcpy(pStbRowsCxt->ctbName.dbname, pStbRowsCxt->stbName.dbname, sizeof(pStbRowsCxt->stbName.dbname));
26✔
2628

2629
    pStbRowsCxt->pTagCond = pStmt->pTagCond;
26✔
2630
    pStbRowsCxt->pStbMeta = pStmt->pTableMeta;
26✔
2631

2632
    code = cloneTableMeta(pStbRowsCxt->pStbMeta, &pStbRowsCxt->pCtbMeta);
26✔
2633
  }
2634
  if (TSDB_CODE_SUCCESS == code) {
26!
2635
    pStbRowsCxt->pCtbMeta->tableType = TSDB_CHILD_TABLE;
26✔
2636
    pStbRowsCxt->pCtbMeta->suid = pStbRowsCxt->pStbMeta->uid;
26✔
2637

2638
    pStbRowsCxt->aTagNames = taosArrayInit(8, TSDB_COL_NAME_LEN);
26✔
2639
    if (!pStbRowsCxt->aTagNames) {
26!
2640
      code = terrno;
×
2641
    }
2642
  }
2643
  if (TSDB_CODE_SUCCESS == code) {
26!
2644
    pStbRowsCxt->aTagVals = taosArrayInit(8, sizeof(STagVal));
26✔
2645
    if (!pStbRowsCxt->aTagVals) {
26!
2646
      code = terrno;
×
2647
    }
2648
  }
2649
  if (TSDB_CODE_SUCCESS == code) {
26!
2650
    // col values and bound cols info of STableDataContext is not used
2651
    pStbRowsCxt->aColVals = taosArrayInit(getNumOfColumns(pStbRowsCxt->pStbMeta), sizeof(SColVal));
26✔
2652
    if (!pStbRowsCxt->aColVals) code = terrno;
26!
2653
  }
2654
  if (TSDB_CODE_SUCCESS == code) {
26!
2655
    code = insInitColValues(pStbRowsCxt->pStbMeta, pStbRowsCxt->aColVals);
26✔
2656
  }
2657
  if (TSDB_CODE_SUCCESS == code) {
26!
2658
    STableComInfo tblInfo = getTableInfo(pStmt->pTableMeta);
26✔
2659
    code = insInitBoundColsInfo(tblInfo.numOfColumns + tblInfo.numOfTags + 1, &pStbRowsCxt->boundColsInfo);
26✔
2660
  }
2661
  if (TSDB_CODE_SUCCESS == code) {
26!
2662
    *ppStbRowsCxt = pStbRowsCxt;
26✔
2663
  } else {
2664
    clearStbRowsDataContext(pStbRowsCxt);
×
2665
  }
2666
  return code;
26✔
2667
}
2668

2669
static int32_t parseInsertStbClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
26✔
2670
  int32_t code = TSDB_CODE_SUCCESS;
26✔
2671
  if (!pStmt->pBoundCols) {
26!
2672
    return buildSyntaxErrMsg(&pCxt->msg, "(...tbname, ts...) bounded cols is expected for supertable insertion",
×
2673
                             pStmt->pSql);
2674
  }
2675

2676
  SStbRowsDataContext* pStbRowsCxt = NULL;
26✔
2677
  code = constructStbRowsDataContext(pStmt, &pStbRowsCxt);
26✔
2678

2679
  if (code == TSDB_CODE_SUCCESS) {
26!
2680
    code = parseBoundColumns(pCxt, &pStmt->pBoundCols, BOUND_ALL_AND_TBNAME, pStmt->pTableMeta,
26✔
2681
                             &pStbRowsCxt->boundColsInfo);
26✔
2682
    pStbRowsCxt->hasTimestampTag = false;
26✔
2683
    for (int32_t i = 0; i < pStbRowsCxt->boundColsInfo.numOfBound; ++i) {
155✔
2684
      int16_t schemaIndex = pStbRowsCxt->boundColsInfo.pColIndex[i];
129✔
2685
      if (schemaIndex != getTbnameSchemaIndex(pStmt->pTableMeta) && schemaIndex >= getNumOfColumns(pStmt->pTableMeta)) {
129✔
2686
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_TIMESTAMP) {
48✔
2687
          pStbRowsCxt->hasTimestampTag = true;
1✔
2688
        }
2689
        if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_JSON) {
48!
2690
          pStbRowsCxt->isJsonTag = true;
×
2691
        }
2692
      }
2693
    }
2694
    pStmt->pStbRowsCxt = pStbRowsCxt;
26✔
2695
  }
2696

2697
  if (code == TSDB_CODE_SUCCESS) {
26✔
2698
    SRowsDataContext rowsDataCxt;
2699
    rowsDataCxt.pStbRowsCxt = pStbRowsCxt;
22✔
2700
    code = parseDataClause(pCxt, pStmt, rowsDataCxt);
22✔
2701
  }
2702

2703
  return code;
26✔
2704
}
2705

2706
// input pStmt->pSql:
2707
//   1. [(tag1_name, ...)] ...
2708
//   2. VALUES ... | FILE ...
2709
static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
102,022✔
2710
  if (!pStmt->stbSyntax) {
102,022✔
2711
    STableDataCxt*   pTableCxt = NULL;
102,003✔
2712
    int32_t          code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt);
102,003✔
2713
    SRowsDataContext rowsDataCxt;
2714
    rowsDataCxt.pTableDataCxt = pTableCxt;
101,988✔
2715
    if (TSDB_CODE_SUCCESS == code) {
101,988!
2716
      code = parseDataClause(pCxt, pStmt, rowsDataCxt);
101,990✔
2717
    }
2718
    return code;
102,006✔
2719
  } else {
2720
    int32_t code = parseInsertStbClauseBottom(pCxt, pStmt);
19✔
2721
    return code;
26✔
2722
  }
2723
}
2724

2725
static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
102,044✔
2726
  insDestroyBoundColInfo(&pCxt->tags);
102,044✔
2727
  taosMemoryFreeClear(pStmt->pTableMeta);
102,043!
2728
  nodesDestroyNode(pStmt->pTagCond);
102,042✔
2729
  taosArrayDestroy(pStmt->pTableTag);
102,041✔
2730
  tdDestroySVCreateTbReq(pStmt->pCreateTblReq);
102,042!
2731
  taosMemoryFreeClear(pStmt->pCreateTblReq);
102,042!
2732
  pCxt->missCache = false;
102,042✔
2733
  pCxt->usingDuplicateTable = false;
102,042✔
2734
  pStmt->pBoundCols = NULL;
102,042✔
2735
  pStmt->usingTableProcessing = false;
102,042✔
2736
  pStmt->fileProcessing = false;
102,042✔
2737
  pStmt->usingTableName.type = 0;
102,042✔
2738

2739
  destroyStbRowsDataContext(pStmt->pStbRowsCxt);
102,042✔
2740
  taosMemoryFreeClear(pStmt->pStbRowsCxt);
102,041!
2741
  pStmt->stbSyntax = false;
102,041✔
2742
}
102,041✔
2743

2744
// input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ...
2745
static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) {
102,045✔
2746
  resetEnvPreTable(pCxt, pStmt);
102,045✔
2747
  int32_t code = parseSchemaClauseTop(pCxt, pStmt, pTbName);
102,041✔
2748
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
102,037✔
2749
    code = parseInsertTableClauseBottom(pCxt, pStmt);
101,946✔
2750
  }
2751

2752
  return code;
102,040✔
2753
}
2754

2755
static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName,
201,353✔
2756
                                          bool* pHasData) {
2757
  // no data in the sql string anymore.
2758
  if (0 == pTbName->n) {
201,353✔
2759
    if (0 != pTbName->type && '\0' != pStmt->pSql[0]) {
99,315!
2760
      return buildSyntaxErrMsg(&pCxt->msg, "invalid table name", pTbName->z);
×
2761
    }
2762

2763
    if (0 == pStmt->totalRowsNum && (!TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT))) {
99,315!
2764
      return buildInvalidOperationMsg(&pCxt->msg, "no data in sql");
×
2765
    }
2766

2767
    *pHasData = false;
99,315✔
2768
    return TSDB_CODE_SUCCESS;
99,315✔
2769
  }
2770

2771
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT) && pStmt->totalTbNum > 0) {
102,038!
2772
    return buildInvalidOperationMsg(&pCxt->msg, "single table allowed in one stmt");
×
2773
  }
2774

2775
  if (TK_NK_QUESTION == pTbName->type) {
102,038✔
2776
    pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
42✔
2777
    pCxt->isStmtBind = true;
42✔
2778
    if (NULL == pCxt->pComCxt->pStmtCb) {
42!
2779
      return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
2780
    }
2781

2782
    char*   tbName = NULL;
42✔
2783
    int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
42✔
2784
    if (TSDB_CODE_SUCCESS == code) {
42✔
2785
      pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
32✔
2786
      pTbName->z = tbName;
32✔
2787
      pTbName->n = strlen(tbName);
32✔
2788
    }
2789
    if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
42✔
2790
      pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
10✔
2791
      code = TSDB_CODE_SUCCESS;
10✔
2792
    }
2793
    return code;
42✔
2794
  }
2795

2796
  if (TK_NK_ID != pTbName->type && TK_NK_STRING != pTbName->type && TK_NK_QUESTION != pTbName->type) {
101,996!
2797
    return buildSyntaxErrMsg(&pCxt->msg, "table_name is expected", pTbName->z);
1✔
2798
  }
2799

2800
  // db.? situation,ensure that the only thing following the '.' mark is '?'
2801
  char* tbNameAfterDbName = strnchr(pTbName->z, '.', pTbName->n, true);
101,995✔
2802
  if (tbNameAfterDbName != NULL) {
101,996✔
2803
    if (*(tbNameAfterDbName + 1) == '?') {
68,529✔
2804
      pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
17✔
2805
      char* tbName = NULL;
17✔
2806
      if (NULL == pCxt->pComCxt->pStmtCb) {
17!
2807
        return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
×
2808
      }
2809
      int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
17✔
2810
      if (TSDB_CODE_SUCCESS == code) {
17✔
2811
        pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
10✔
2812
        pTbName->z = tbName;
10✔
2813
        pTbName->n = strlen(tbName);
10✔
2814
      }
2815
      if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
17✔
2816
        pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
7✔
2817
        code = TSDB_CODE_SUCCESS;
7✔
2818
      }
2819
    } else {
2820
      pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
68,512✔
2821
      parserWarn("QID:0x%" PRIx64 ", table name is specified in sql, ignore the table name in bind param",
68,512!
2822
                 pCxt->pComCxt->requestId);
2823
      *pHasData = true;
68,519✔
2824
    }
2825
    return TSDB_CODE_SUCCESS;
68,536✔
2826
  }
2827

2828
  if (TK_NK_ID == pTbName->type) {
33,467✔
2829
    pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
33,442✔
2830
  }
2831

2832
  *pHasData = true;
33,467✔
2833
  return TSDB_CODE_SUCCESS;
33,467✔
2834
}
2835

2836
static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
153✔
2837
  SBoundColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags));
153!
2838
  if (NULL == tags) {
153!
2839
    return terrno;
×
2840
  }
2841
  memcpy(tags, &pCxt->tags, sizeof(pCxt->tags));
153✔
2842

2843
  SStmtCallback* pStmtCb = pCxt->pComCxt->pStmtCb;
153✔
2844
  int32_t        code = (*pStmtCb->setInfoFn)(pStmtCb->pStmt, pStmt->pTableMeta, tags, &pStmt->targetTableName,
153✔
2845
                                       pStmt->usingTableProcessing, pStmt->pVgroupsHashObj, pStmt->pTableBlockHashObj,
153✔
2846
                                       pStmt->usingTableName.tname, pCxt->stmtTbNameFlag);
153✔
2847

2848
  memset(&pCxt->tags, 0, sizeof(pCxt->tags));
152✔
2849
  pStmt->pVgroupsHashObj = NULL;
152✔
2850
  pStmt->pTableBlockHashObj = NULL;
152✔
2851
  return code;
152✔
2852
}
2853

2854
static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
99,314✔
2855
  if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) {
99,314✔
2856
    return setStmtInfo(pCxt, pStmt);
153✔
2857
  }
2858

2859
  // release old array alloced by merge
2860
  pStmt->freeArrayFunc(pStmt->pVgDataBlocks);
99,161✔
2861
  pStmt->pVgDataBlocks = NULL;
99,161✔
2862

2863
  bool fileOnly = (pStmt->insertType == TSDB_QUERY_TYPE_FILE_INSERT);
99,161✔
2864
  if (fileOnly) {
99,161!
2865
    // none data, skip merge & buildvgdata
2866
    if (0 == taosHashGetSize(pStmt->pTableCxtHashObj)) {
×
2867
      pCxt->needRequest = false;
×
2868
      return TSDB_CODE_SUCCESS;
×
2869
    }
2870
  }
2871

2872
  // merge according to vgId
2873
  int32_t code = insMergeTableDataCxt(fileOnly ? pStmt->pTableCxtHashObj : pStmt->pTableBlockHashObj,
99,162✔
2874
                                      &pStmt->pVgDataBlocks, pStmt->fileProcessing);
99,162!
2875
  // clear tmp hashobj only
2876
  taosHashClear(pStmt->pTableCxtHashObj);
99,158✔
2877

2878
  if (TSDB_CODE_SUCCESS == code) {
99,160!
2879
    code = insBuildVgDataBlocks(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks, false);
99,161✔
2880
  }
2881

2882
  return code;
99,161✔
2883
}
2884

2885
// tb_name
2886
//     [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
2887
//     [(field1_name, ...)]
2888
//     VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
2889
// [...];
2890
static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
99,444✔
2891
  SToken  token;
2892
  int32_t code = TSDB_CODE_SUCCESS;
99,444✔
2893
  bool    hasData = true;
99,444✔
2894
  // for each table
2895
  while (TSDB_CODE_SUCCESS == code && hasData && !pCxt->missCache && !pStmt->fileProcessing) {
300,803!
2896
    // pStmt->pSql -> tb_name ...
2897
    NEXT_TOKEN(pStmt->pSql, token);
201,357✔
2898
    code = checkTableClauseFirstToken(pCxt, pStmt, &token, &hasData);
201,362✔
2899
    if (TSDB_CODE_SUCCESS == code && hasData) {
201,361!
2900
      code = parseInsertTableClause(pCxt, pStmt, &token);
102,045✔
2901
    }
2902
  }
2903

2904
  if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
99,446✔
2905
    code = parseInsertBodyBottom(pCxt, pStmt);
99,316✔
2906
  }
2907
  return code;
99,444✔
2908
}
2909

2910
static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); }
13,227!
2911

2912
static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, SNode** pOutput) {
99,363✔
2913
  SVnodeModifyOpStmt* pStmt = NULL;
99,363✔
2914
  int32_t             code = nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT, (SNode**)&pStmt);
99,363✔
2915
  if (NULL == pStmt) {
99,367!
2916
    return code;
×
2917
  }
2918

2919
  if (pCxt->pComCxt->pStmtCb) {
99,367✔
2920
    TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT);
169✔
2921
  }
2922
  pStmt->pSql = pCxt->pComCxt->pSql;
99,367✔
2923

2924
  pStmt->freeHashFunc = insDestroyTableDataCxtHashMap;
99,367✔
2925
  pStmt->freeArrayFunc = insDestroyVgroupDataCxtList;
99,367✔
2926
  pStmt->freeStbRowsCxtFunc = destroyStbRowsDataContext;
99,367✔
2927

2928
  if (!reentry) {
99,367✔
2929
    pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
99,365✔
2930
    if (pCxt->pComCxt->pStmtCb) {
99,362✔
2931
      pStmt->pTableBlockHashObj =
167✔
2932
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
167✔
2933
    } else {
2934
      pStmt->pTableBlockHashObj =
99,197✔
2935
          taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK);
99,195✔
2936
    }
2937
  }
2938
  pStmt->pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
99,366✔
2939
  pStmt->pSuperTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
99,367✔
2940
  pStmt->pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
99,366✔
2941
  pStmt->pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK);
99,366✔
2942
  if ((!reentry && (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj)) ||
99,367!
2943
      NULL == pStmt->pSubTableHashObj || NULL == pStmt->pTableNameHashObj || NULL == pStmt->pDbFNameHashObj) {
99,367!
2944
    nodesDestroyNode((SNode*)pStmt);
×
2945
    return TSDB_CODE_OUT_OF_MEMORY;
×
2946
  }
2947

2948
  taosHashSetFreeFp(pStmt->pSubTableHashObj, destroySubTableHashElem);
99,367✔
2949
  taosHashSetFreeFp(pStmt->pSuperTableHashObj, destroySubTableHashElem);
99,364✔
2950

2951
  *pOutput = (SNode*)pStmt;
99,366✔
2952
  return TSDB_CODE_SUCCESS;
99,366✔
2953
}
2954

2955
static int32_t createInsertQuery(SInsertParseContext* pCxt, SQuery** pOutput) {
99,362✔
2956
  SQuery* pQuery = NULL;
99,362✔
2957
  int32_t code = nodesMakeNode(QUERY_NODE_QUERY, (SNode**)&pQuery);
99,362✔
2958
  if (NULL == pQuery) {
99,360!
2959
    return code;
×
2960
  }
2961

2962
  pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
99,360✔
2963
  pQuery->haveResultSet = false;
99,360✔
2964
  pQuery->msgType = TDMT_VND_SUBMIT;
99,360✔
2965

2966
  code = createVnodeModifOpStmt(pCxt, false, &pQuery->pRoot);
99,360✔
2967
  if (TSDB_CODE_SUCCESS == code) {
99,364!
2968
    *pOutput = pQuery;
99,364✔
2969
  } else {
2970
    nodesDestroyNode((SNode*)pQuery);
×
2971
  }
2972
  return code;
99,364✔
2973
}
2974

2975
static int32_t checkAuthFromMetaData(const SArray* pUsers, SNode** pTagCond) {
88✔
2976
  if (1 != taosArrayGetSize(pUsers)) {
88!
2977
    return TSDB_CODE_FAILED;
×
2978
  }
2979

2980
  SMetaRes* pRes = taosArrayGet(pUsers, 0);
88✔
2981
  if (TSDB_CODE_SUCCESS == pRes->code) {
88!
2982
    SUserAuthRes* pAuth = pRes->pRes;
88✔
2983
    pRes->code = nodesCloneNode(pAuth->pCond[AUTH_RES_BASIC], pTagCond);
88✔
2984
    if (TSDB_CODE_SUCCESS == pRes->code) {
88!
2985
      return pAuth->pass[AUTH_RES_BASIC] ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED;
88!
2986
    }
2987
  }
2988
  return pRes->code;
×
2989
}
2990

2991
static int32_t getTableMetaFromMetaData(const SArray* pTables, STableMeta** pMeta) {
88✔
2992
  if (1 != taosArrayGetSize(pTables) && 2 != taosArrayGetSize(pTables)) {
88!
2993
    return TSDB_CODE_FAILED;
×
2994
  }
2995

2996
  taosMemoryFreeClear(*pMeta);
88!
2997
  SMetaRes* pRes = taosArrayGet(pTables, 0);
88✔
2998
  if (TSDB_CODE_SUCCESS == pRes->code) {
88✔
2999
    *pMeta = tableMetaDup((const STableMeta*)pRes->pRes);
82✔
3000
    if (NULL == *pMeta) {
82!
3001
      return TSDB_CODE_OUT_OF_MEMORY;
×
3002
    }
3003
  }
3004
  return pRes->code;
88✔
3005
}
3006

3007
static int32_t addTableVgroupFromMetaData(const SArray* pTables, SVnodeModifyOpStmt* pStmt, bool isStb) {
81✔
3008
  if (1 != taosArrayGetSize(pTables)) {
81!
3009
    return TSDB_CODE_FAILED;
×
3010
  }
3011

3012
  SMetaRes* pRes = taosArrayGet(pTables, 0);
81✔
3013
  if (TSDB_CODE_SUCCESS != pRes->code) {
81!
3014
    return pRes->code;
×
3015
  }
3016

3017
  SVgroupInfo* pVg = pRes->pRes;
81✔
3018
  if (isStb) {
81✔
3019
    pStmt->pTableMeta->vgId = pVg->vgId;
46✔
3020
  }
3021
  return taosHashPut(pStmt->pVgroupsHashObj, (const char*)&pVg->vgId, sizeof(pVg->vgId), (char*)pVg,
81✔
3022
                     sizeof(SVgroupInfo));
3023
}
3024

3025
static int32_t buildTagNameFromMeta(STableMeta* pMeta, SArray** pTagName) {
×
3026
  *pTagName = taosArrayInit(pMeta->tableInfo.numOfTags, TSDB_COL_NAME_LEN);
×
3027
  if (NULL == *pTagName) {
×
3028
    return terrno;
×
3029
  }
3030
  SSchema* pSchema = getTableTagSchema(pMeta);
×
3031
  int32_t  code = 0;
×
3032
  for (int32_t i = 0; i < pMeta->tableInfo.numOfTags; ++i) {
×
3033
    if (NULL == taosArrayPush(*pTagName, pSchema[i].name)) {
×
3034
      code = terrno;
×
3035
      taosArrayDestroy(*pTagName);
×
3036
      *pTagName = NULL;
×
3037
      break;
×
3038
    }
3039
  }
3040
  return code;
×
3041
}
3042

3043
static int32_t checkSubtablePrivilegeForTable(const SArray* pTables, SVnodeModifyOpStmt* pStmt) {
×
3044
  if (1 != taosArrayGetSize(pTables)) {
×
3045
    return TSDB_CODE_FAILED;
×
3046
  }
3047

3048
  SMetaRes* pRes = taosArrayGet(pTables, 0);
×
3049
  if (TSDB_CODE_SUCCESS != pRes->code) {
×
3050
    return pRes->code;
×
3051
  }
3052

3053
  SArray* pTagName = NULL;
×
3054
  int32_t code = buildTagNameFromMeta(pStmt->pTableMeta, &pTagName);
×
3055
  if (TSDB_CODE_SUCCESS == code) {
×
3056
    code = checkSubtablePrivilege((SArray*)pRes->pRes, pTagName, &pStmt->pTagCond);
×
3057
  }
3058
  taosArrayDestroy(pTagName);
×
3059
  return code;
×
3060
}
3061

3062
static int32_t processTableSchemaFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData,
81✔
3063
                                              SVnodeModifyOpStmt* pStmt, bool isStb) {
3064
  int32_t code = TSDB_CODE_SUCCESS;
81✔
3065
  if (!isStb && TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) {
81!
3066
    code = buildInvalidOperationMsg(&pCxt->msg, "insert data into super table is not supported");
×
3067
  }
3068
  if (TSDB_CODE_SUCCESS == code && isStb) {
81!
3069
    code = storeChildTableMeta(pCxt, pStmt);
46✔
3070
  }
3071
  if (TSDB_CODE_SUCCESS == code) {
81!
3072
    code = addTableVgroupFromMetaData(pMetaData->pTableHash, pStmt, isStb);
81✔
3073
  }
3074
  if (TSDB_CODE_SUCCESS == code && !isStb && NULL != pStmt->pTagCond) {
81!
3075
    code = checkSubtablePrivilegeForTable(pMetaData->pTableTag, pStmt);
×
3076
  }
3077
  return code;
81✔
3078
}
3079

3080
static void destoryTablesReq(void* p) {
176✔
3081
  STablesReq* pRes = (STablesReq*)p;
176✔
3082
  taosArrayDestroy(pRes->pTables);
176✔
3083
}
176✔
3084

3085
static void clearCatalogReq(SCatalogReq* pCatalogReq) {
88✔
3086
  if (NULL == pCatalogReq) {
88!
3087
    return;
×
3088
  }
3089

3090
  taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq);
88✔
3091
  pCatalogReq->pTableMeta = NULL;
88✔
3092
  taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq);
88✔
3093
  pCatalogReq->pTableHash = NULL;
88✔
3094
  taosArrayDestroy(pCatalogReq->pUser);
88✔
3095
  pCatalogReq->pUser = NULL;
88✔
3096
  taosArrayDestroy(pCatalogReq->pTableTag);
88✔
3097
  pCatalogReq->pTableTag = NULL;
88✔
3098
}
3099

3100
static int32_t setVnodeModifOpStmt(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
88✔
3101
                                   SVnodeModifyOpStmt* pStmt) {
3102
  clearCatalogReq(pCatalogReq);
88✔
3103
  int32_t code = checkAuthFromMetaData(pMetaData->pUser, &pStmt->pTagCond);
88✔
3104
  if (code == TSDB_CODE_SUCCESS) {
88!
3105
    code = getTableMetaFromMetaData(pMetaData->pTableMeta, &pStmt->pTableMeta);
88✔
3106
  }
3107
  if (code == TSDB_CODE_SUCCESS) {
88✔
3108
    if (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE && !pStmt->usingTableProcessing) {
82✔
3109
      pStmt->stbSyntax = true;
1✔
3110
    }
3111
    if (!pStmt->stbSyntax) {
82✔
3112
      if (pStmt->usingTableProcessing) {
81✔
3113
        return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, true);
46✔
3114
      }
3115
      return processTableSchemaFromMetaData(pCxt, pMetaData, pStmt, false);
35✔
3116
    }
3117
  }
3118
  return code;
7✔
3119
}
3120

3121
static int32_t resetVnodeModifOpStmt(SInsertParseContext* pCxt, SQuery* pQuery) {
2✔
3122
  nodesDestroyNode(pQuery->pRoot);
2✔
3123

3124
  int32_t code = createVnodeModifOpStmt(pCxt, true, &pQuery->pRoot);
2✔
3125
  if (TSDB_CODE_SUCCESS == code) {
2!
3126
    SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
2✔
3127

3128
    code = (*pCxt->pComCxt->pStmtCb->getExecInfoFn)(pCxt->pComCxt->pStmtCb->pStmt, &pStmt->pVgroupsHashObj,
2✔
3129
                                                    &pStmt->pTableBlockHashObj);
3130
    if (TSDB_CODE_SUCCESS == code) {
2!
3131
      if (NULL == pStmt->pVgroupsHashObj) {
2!
3132
        pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK);
×
3133
      }
3134
      if (NULL == pStmt->pTableBlockHashObj) {
2!
3135
        pStmt->pTableBlockHashObj =
×
3136
            taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
×
3137
      }
3138
      if (NULL == pStmt->pVgroupsHashObj || NULL == pStmt->pTableBlockHashObj) {
2!
3139
        code = TSDB_CODE_OUT_OF_MEMORY;
×
3140
      }
3141
    }
3142
  }
3143

3144
  return code;
2✔
3145
}
3146

3147
static int32_t initInsertQuery(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
99,452✔
3148
                               SQuery** pQuery) {
3149
  if (NULL == *pQuery) {
99,452✔
3150
    return createInsertQuery(pCxt, pQuery);
99,364✔
3151
  }
3152

3153
  if (NULL != pCxt->pComCxt->pStmtCb) {
88✔
3154
    return resetVnodeModifOpStmt(pCxt, *pQuery);
2✔
3155
  }
3156

3157
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)(*pQuery)->pRoot;
86✔
3158

3159
  if (!pStmt->fileProcessing) {
86!
3160
    return setVnodeModifOpStmt(pCxt, pCatalogReq, pMetaData, pStmt);
88✔
3161
  }
3162

3163
  return TSDB_CODE_SUCCESS;
3164
}
3165

3166
static int32_t setRefreshMeta(SQuery* pQuery) {
99,314✔
3167
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
99,314✔
3168
  int32_t             code = 0;
99,314✔
3169

3170
  if (taosHashGetSize(pStmt->pTableNameHashObj) > 0) {
99,314✔
3171
    taosArrayDestroy(pQuery->pTableList);
182✔
3172
    pQuery->pTableList = taosArrayInit(taosHashGetSize(pStmt->pTableNameHashObj), sizeof(SName));
182✔
3173
    if (!pQuery->pTableList) {
182!
3174
      code = terrno;
×
3175
    } else {
3176
      SName* pTable = taosHashIterate(pStmt->pTableNameHashObj, NULL);
182✔
3177
      while (NULL != pTable) {
383✔
3178
        if (NULL == taosArrayPush(pQuery->pTableList, pTable)) {
402!
3179
          code = terrno;
×
3180
          taosHashCancelIterate(pStmt->pTableNameHashObj, pTable);
×
3181
          break;
×
3182
        }
3183
        pTable = taosHashIterate(pStmt->pTableNameHashObj, pTable);
201✔
3184
      }
3185
    }
3186
  }
3187

3188
  if (TSDB_CODE_SUCCESS == code && taosHashGetSize(pStmt->pDbFNameHashObj) > 0) {
99,316!
3189
    taosArrayDestroy(pQuery->pDbList);
182✔
3190
    pQuery->pDbList = taosArrayInit(taosHashGetSize(pStmt->pDbFNameHashObj), TSDB_DB_FNAME_LEN);
182✔
3191
    if (!pQuery->pDbList) {
182!
3192
      code = terrno;
×
3193
    } else {
3194
      char* pDb = taosHashIterate(pStmt->pDbFNameHashObj, NULL);
182✔
3195
      while (NULL != pDb) {
363✔
3196
        if (NULL == taosArrayPush(pQuery->pDbList, pDb)) {
364!
3197
          code = terrno;
×
3198
          taosHashCancelIterate(pStmt->pDbFNameHashObj, pDb);
×
3199
          break;
×
3200
        }
3201
        pDb = taosHashIterate(pStmt->pDbFNameHashObj, pDb);
182✔
3202
      }
3203
    }
3204
  }
3205

3206
  return code;
99,312✔
3207
}
3208

3209
// INSERT INTO
3210
//   tb_name
3211
//       [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]]
3212
//       [(field1_name, ...)]
3213
//       VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
3214
//   [...];
3215
static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
99,360✔
3216
  int32_t code = skipInsertInto(&pStmt->pSql, &pCxt->msg);
99,360✔
3217
  if (TSDB_CODE_SUCCESS == code) {
99,366!
3218
    code = parseInsertBody(pCxt, pStmt);
99,366✔
3219
  }
3220
  return code;
99,363✔
3221
}
3222

3223
static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
×
3224
  int32_t          code = TSDB_CODE_SUCCESS;
×
3225
  SRowsDataContext rowsDataCxt;
3226

3227
  if (!pStmt->stbSyntax) {
×
3228
    STableDataCxt* pTableCxt = NULL;
×
3229
    code = getTableDataCxt(pCxt, pStmt, &pTableCxt);
×
3230
    rowsDataCxt.pTableDataCxt = pTableCxt;
×
3231
  } else {
3232
    rowsDataCxt.pStbRowsCxt = pStmt->pStbRowsCxt;
×
3233
  }
3234
  if (TSDB_CODE_SUCCESS == code) {
×
3235
    code = parseDataFromFileImpl(pCxt, pStmt, rowsDataCxt);
×
3236
  }
3237

3238
  if (TSDB_CODE_SUCCESS == code) {
×
3239
    if (pStmt->fileProcessing) {
×
3240
      code = parseInsertBodyBottom(pCxt, pStmt);
×
3241
    } else {
3242
      code = parseInsertBody(pCxt, pStmt);
×
3243
    }
3244
  }
3245

3246
  return code;
×
3247
}
3248

3249
static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
82✔
3250
  int32_t code = parseInsertTableClauseBottom(pCxt, pStmt);
82✔
3251
  if (TSDB_CODE_SUCCESS == code) {
82!
3252
    code = parseInsertBody(pCxt, pStmt);
82✔
3253
  }
3254
  return code;
82✔
3255
}
3256

3257
static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) {
99,445✔
3258
  if (pStmt->pSql == pCxt->pComCxt->pSql || NULL != pCxt->pComCxt->pStmtCb) {
99,445!
3259
    return parseInsertSqlFromStart(pCxt, pStmt);
99,363✔
3260
  }
3261

3262
  if (pStmt->fileProcessing) {
82!
3263
    return parseInsertSqlFromCsv(pCxt, pStmt);
×
3264
  }
3265

3266
  return parseInsertSqlFromTable(pCxt, pStmt);
82✔
3267
}
3268

3269
static int32_t buildUsingInsertTableReq(SName* pSName, SName* pCName, SArray** pTables) {
46✔
3270
  if (NULL == *pTables) {
46!
3271
    *pTables = taosArrayInit(2, sizeof(SName));
46✔
3272
    if (NULL == *pTables) {
46!
3273
      goto _err;
×
3274
    }
3275
  }
3276
  if (NULL == taosArrayPush(*pTables, pSName)) {
92!
3277
    goto _err;
×
3278
  }
3279
  if (NULL == taosArrayPush(*pTables, pCName)) {
92!
3280
    goto _err;
×
3281
  }
3282
  return TSDB_CODE_SUCCESS;
46✔
3283

3284
_err:
×
3285
  if (NULL != *pTables) {
×
3286
    taosArrayDestroy(*pTables);
×
3287
    *pTables = NULL;
×
3288
  }
3289
  return terrno;
×
3290
}
3291

3292
static int32_t buildInsertTableReq(SName* pName, SArray** pTables) {
130✔
3293
  *pTables = taosArrayInit(1, sizeof(SName));
130✔
3294
  if (NULL == *pTables) {
130!
3295
    return terrno;
×
3296
  }
3297

3298
  if (NULL == taosArrayPush(*pTables, pName)) {
260!
3299
    taosArrayDestroy(*pTables);
×
3300
    *pTables = NULL;
×
3301
    return terrno;
×
3302
  }
3303
  return TSDB_CODE_SUCCESS;
130✔
3304
}
3305

3306
static int32_t buildInsertUsingDbReq(SName* pSName, SName* pCName, SArray** pDbs) {
46✔
3307
  if (NULL == *pDbs) {
46!
3308
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
46✔
3309
    if (NULL == *pDbs) {
46!
3310
      return terrno;
×
3311
    }
3312
  }
3313

3314
  STablesReq req = {0};
46✔
3315
  req.autoCreate = 1;
46✔
3316
  (void)tNameGetFullDbName(pSName, req.dbFName);
46✔
3317
  (void)tNameGetFullDbName(pCName, req.dbFName);
46✔
3318

3319
  int32_t code = buildUsingInsertTableReq(pSName, pCName, &req.pTables);
46✔
3320
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
92!
3321
    code = TSDB_CODE_OUT_OF_MEMORY;
×
3322
  }
3323
  return code;
46✔
3324
}
3325

3326
static int32_t buildInsertDbReq(SName* pName, SArray** pDbs) {
130✔
3327
  if (NULL == *pDbs) {
130!
3328
    *pDbs = taosArrayInit(1, sizeof(STablesReq));
130✔
3329
    if (NULL == *pDbs) {
130!
3330
      return terrno;
×
3331
    }
3332
  }
3333

3334
  STablesReq req = {0};
130✔
3335
  (void)tNameGetFullDbName(pName, req.dbFName);
130✔
3336
  int32_t code = buildInsertTableReq(pName, &req.pTables);
130✔
3337
  if (TSDB_CODE_SUCCESS == code && NULL == taosArrayPush(*pDbs, &req)) {
260!
3338
    code = TSDB_CODE_OUT_OF_MEMORY;
×
3339
  }
3340

3341
  return code;
130✔
3342
}
3343

3344
static int32_t buildInsertUserAuthReq(const char* pUser, SName* pName, SArray** pUserAuth) {
88✔
3345
  *pUserAuth = taosArrayInit(1, sizeof(SUserAuthInfo));
88✔
3346
  if (NULL == *pUserAuth) {
88!
3347
    return terrno;
×
3348
  }
3349

3350
  SUserAuthInfo userAuth = {.type = AUTH_TYPE_WRITE};
88✔
3351
  snprintf(userAuth.user, sizeof(userAuth.user), "%s", pUser);
88✔
3352
  memcpy(&userAuth.tbName, pName, sizeof(SName));
88✔
3353
  if (NULL == taosArrayPush(*pUserAuth, &userAuth)) {
176!
3354
    taosArrayDestroy(*pUserAuth);
×
3355
    *pUserAuth = NULL;
×
3356
    return terrno;
×
3357
  }
3358

3359
  return TSDB_CODE_SUCCESS;
88✔
3360
}
3361

3362
static int32_t buildInsertTableTagReq(SName* pName, SArray** pTables) { return buildInsertTableReq(pName, pTables); }
×
3363

3364
static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SCatalogReq* pCatalogReq) {
88✔
3365
  int32_t code = buildInsertUserAuthReq(
88✔
3366
      pCxt->pComCxt->pUser, (0 == pStmt->usingTableName.type ? &pStmt->targetTableName : &pStmt->usingTableName),
176✔
3367
      &pCatalogReq->pUser);
3368
  if (TSDB_CODE_SUCCESS == code && pCxt->needTableTagVal) {
88!
3369
    code = buildInsertTableTagReq(&pStmt->targetTableName, &pCatalogReq->pTableTag);
×
3370
  }
3371
  if (TSDB_CODE_SUCCESS == code) {
88!
3372
    if (0 == pStmt->usingTableName.type) {
88✔
3373
      code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableMeta);
42✔
3374
    } else {
3375
      code = buildInsertUsingDbReq(&pStmt->usingTableName, &pStmt->targetTableName, &pCatalogReq->pTableMeta);
46✔
3376
    }
3377
  }
3378
  if (TSDB_CODE_SUCCESS == code) {
88!
3379
    code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableHash);
88✔
3380
  }
3381
  return code;
88✔
3382
}
3383

3384
static int32_t setNextStageInfo(SInsertParseContext* pCxt, SQuery* pQuery, SCatalogReq* pCatalogReq) {
99,400✔
3385
  SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot;
99,400✔
3386
  if (pCxt->missCache) {
99,400✔
3387
    parserDebug("QID:0x%" PRIx64 ", %d rows of %d tables will be inserted before obtain the cache", pCxt->pComCxt->requestId,
88✔
3388
                pStmt->totalRowsNum, pStmt->totalTbNum);
3389

3390
    pQuery->execStage = QUERY_EXEC_STAGE_PARSE;
88✔
3391
    return buildInsertCatalogReq(pCxt, pStmt, pCatalogReq);
88✔
3392
  }
3393

3394
  parserDebug("QID:0x%" PRIx64 ", %d rows of %d tables will be inserted", pCxt->pComCxt->requestId, pStmt->totalRowsNum,
99,312✔
3395
              pStmt->totalTbNum);
3396

3397
  pQuery->execStage = QUERY_EXEC_STAGE_SCHEDULE;
99,314✔
3398
  return TSDB_CODE_SUCCESS;
99,314✔
3399
}
3400

3401
int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) {
99,449✔
3402
  SInsertParseContext context = {.pComCxt = pCxt,
198,898✔
3403
                                 .msg = {.buf = pCxt->pMsg, .len = pCxt->msgLen},
99,449✔
3404
                                 .missCache = false,
3405
                                 .usingDuplicateTable = false,
3406
                                 .needRequest = true,
3407
                                 .forceUpdate = (NULL != pCatalogReq ? pCatalogReq->forceUpdate : false),
99,449!
3408
                                 .isStmtBind = pCxt->isStmtBind};
99,449✔
3409

3410
  int32_t code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery);
99,449✔
3411
  if (TSDB_CODE_SUCCESS == code) {
99,454✔
3412
    code = parseInsertSqlImpl(&context, (SVnodeModifyOpStmt*)((*pQuery)->pRoot));
99,448✔
3413
  }
3414
  if (TSDB_CODE_SUCCESS == code) {
99,450✔
3415
    code = setNextStageInfo(&context, *pQuery, pCatalogReq);
99,400✔
3416
  }
3417
  if ((TSDB_CODE_SUCCESS == code || NEED_CLIENT_HANDLE_ERROR(code)) &&
99,453!
3418
      QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) {
99,415✔
3419
    code = setRefreshMeta(*pQuery);
99,314✔
3420
  }
3421

3422
  insDestroyBoundColInfo(&context.tags);
99,451✔
3423
  // if no data to insert, set emptyMode to avoid request server
3424
  if (!context.needRequest) {
99,452!
3425
    (*pQuery)->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
×
3426
  }
3427
  return code;
99,452✔
3428
}
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