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

taosdata / TDengine / #4934

21 Jan 2026 06:06AM UTC coverage: 66.691% (+0.02%) from 66.671%
#4934

push

travis-ci

web-flow
 enh:stmt support interval opt (#34335)

0 of 26 new or added lines in 3 files covered. (0.0%)

562 existing lines in 98 files now uncovered.

203203 of 304692 relevant lines covered (66.69%)

129902664.38 hits per line

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

47.37
/source/libs/parser/src/parser.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 "parser.h"
17
#include "os.h"
18

19
#include <stdio.h>
20
#include <string.h>
21
#include "parInsertUtil.h"
22
#include "parInt.h"
23
#include "parToken.h"
24
#include "tname.h"
25
#include "ttime.h"
26

27
bool qIsInsertValuesSql(const char* pStr, size_t length) {
1,703,960,909✔
28
  if (NULL == pStr) {
1,703,960,909✔
29
    return false;
×
30
  }
31

32
  const char* pSql = pStr;
1,703,960,909✔
33

34
  int32_t index = 0;
1,703,960,909✔
35
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
1,703,964,618✔
36
  if (TK_INSERT != t.type && TK_IMPORT != t.type) {
1,703,964,864✔
37
    return false;
626,052,397✔
38
  }
39

40
  do {
41
    pStr += index;
2,147,483,647✔
42
    index = 0;
2,147,483,647✔
43
    t = tStrGetToken((char*)pStr, &index, false, NULL);
2,147,483,647✔
44
    if (TK_USING == t.type || TK_VALUES == t.type || TK_FILE == t.type) {
2,147,483,647✔
45
      return true;
1,077,357,366✔
46
    } else if (TK_SELECT == t.type) {
2,147,483,647✔
47
      return false;
557,058✔
48
    }
49
    if (0 == t.type || 0 == t.n) {
2,147,483,647✔
50
      break;
51
    }
52
  } while (pStr - pSql < length);
2,147,483,647✔
53
  return false;
2,228✔
54
}
55

56
bool qIsUpdateSetSql(const char* pStr, size_t length, SName* pTableName, int32_t acctId, const char* dbName,
3,314,908✔
57
                     char* msgBuf, int32_t msgBufLen, int* pCode) {
58
                        if (NULL == pStr) {
3,314,908✔
59
    return false;
×
60
  }
61

62
  const char* pSql = pStr;
3,314,908✔
63

64
  int32_t index = 0;
3,314,908✔
65
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
3,315,546✔
66
    if (TK_UPDATE != t.type) {
3,317,779✔
67
    return false;
3,317,779✔
68
  }
69
  SMsgBuf pMsgBuf = {.len = msgBufLen, .buf = msgBuf};
×
70
  pStr += index;
×
71
  index = 0;
×
72
  t = tStrGetToken((char*)pStr, &index, false, NULL);
×
73
  if (t.n == 0 || t.z == NULL) {
×
74
    *pCode = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_TSC_STMT_TBNAME_ERROR, "Invalid table name");
×
75
    return false;
×
76
  }
77

78
  if (pTableName != NULL) {
×
79
    *pCode = insCreateSName(pTableName, &t, acctId, dbName, &pMsgBuf);
×
80
    if ((*pCode) != TSDB_CODE_SUCCESS) {
×
81
      return false;
×
82
    }
83
  }
84
    do {
85
    pStr += index;
×
86
    index = 0;
×
87
    t = tStrGetToken((char*)pStr, &index, false, NULL);
×
88
        if (TK_SET == t.type) {
×
89
      return true;
×
90
    }
91
    if (0 == t.type || 0 == t.n) {
×
92
      break;
93
    }
94
  } while (pStr - pSql < length);
×
95
  return false;
×
96
}
97

98
bool qIsSelectFromSql(const char* pStr, size_t length) {
2,512✔
99
  if (NULL == pStr) {
2,512✔
100
    return false;
×
101
  }
102

103
  const char* pSql = pStr;
2,512✔
104

105
  int32_t index = 0;
2,512✔
106
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
2,512✔
107
  if (TK_SELECT != t.type) {
2,512✔
108
    return false;
2,504✔
109
  }
110

111
  do {
112
    pStr += index;
16✔
113
    index = 0;
16✔
114
    t = tStrGetToken((char*)pStr, &index, false, NULL);
16✔
115
    if (TK_FROM == t.type) {
16✔
116
      return true;
8✔
117
    }
118
    if (0 == t.type || 0 == t.n) {
8✔
119
      break;
120
    }
121
  } while (pStr - pSql < length);
8✔
122

123
  return false;
×
124
}
125

126
static bool isColumnPrimaryKey(const STableMeta* pTableMeta, const char* colName, int32_t colNameLen, int32_t* colId) {
×
127
  if (pTableMeta == NULL || colName == NULL) {
×
128
    return false;
×
129
  }
130

131
  for (int32_t i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) {
×
132
    const SSchema* pSchema = &pTableMeta->schema[i];
×
133
    if (strncmp(pSchema->name, colName, colNameLen) == 0 && strlen(pSchema->name) == colNameLen) {
×
134
      if (colId) {
×
135
        *colId = i;
×
136
      }
137
      if ((pSchema->flags & COL_IS_KEY || pSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID)) {
×
138
        return true;
×
139
      }
140
      return false;
×
141
    }
142
  }
143
  return false;
×
144
}
145

146
int32_t convertUpdateToInsert(const char* pSql, char** pNewSql, STableMeta* pTableMeta, SSHashObj* predicateCols,
×
147
                              char* msgBuf, int32_t msgBufLen) {
148
  if (NULL == pSql || NULL == pNewSql) {
×
149
    return TSDB_CODE_INVALID_PARA;
×
150
  }
151

152
  const char* pEnd = pSql + strlen(pSql);
×
153
  size_t      maxSqlLen = strlen(pSql) * 2;
×
154
  char*  newSql = taosMemoryMalloc(maxSqlLen);
×
155
  if (newSql == NULL) {
×
156
    return terrno;
×
157
  }
158
  char*   p = newSql;
×
159
  int32_t index = 0;
×
160
  SToken  t;
161
  int32_t code = TSDB_CODE_SUCCESS;
×
162
  SMsgBuf pMsgBuf = {msgBufLen, msgBuf};
×
163

164
  // UPDATE
165
  t = tStrGetToken((char*)pSql, &index, false, NULL);
×
166
  if (TK_UPDATE != t.type) {
×
167
    taosMemoryFree(newSql);
×
168
    code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected UPDATE keyword");
×
169
    return code;
×
170
  }
171
  pSql += index;
×
172

173
  // tbname
174
  index = 0;
×
175
  t = tStrGetToken((char*)pSql, &index, false, NULL);
×
176
  if (t.n == 0 || t.z == NULL) {
×
177
    taosMemoryFree(newSql);
×
178
    code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Invalid table name");
×
179
    return code;
×
180
  }
181

182
  p += sprintf(p, "INSERT INTO ");
×
183
  memcpy(p, t.z, t.n);
×
184
  p += t.n;
×
185
  p += sprintf(p, " (");
×
186
  pSql += index;
×
187

188
  // SET
189
  index = 0;
×
190
  t = tStrGetToken((char*)pSql, &index, false, NULL);
×
191
  if (TK_SET != t.type) {
×
192
    taosMemoryFree(newSql);
×
193
    code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected SET keyword");
×
194
    return code;
×
195
  }
196
  pSql += index;
×
197

198
  bool    firstColumn = true;
×
199
  int32_t columnCount = 0;
×
200
  bool inSetClause = true;
×
201
  int32_t numOfCols = 0;
×
202

203
  // col name
204
  while (inSetClause && pSql < pEnd) {
×
205
    index = 0;
×
206
    t = tStrGetToken((char*)pSql, &index, false, NULL);
×
207
    if (t.n == 0 || t.z == NULL) {
×
208
      break;
209
    }
210

211
    // pk can't set
212
    if (pTableMeta != NULL && isColumnPrimaryKey(pTableMeta, t.z, t.n, NULL)) {
×
213
      taosMemoryFree(newSql);
×
214
      code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Cannot update primary key column '%.*s'",
×
215
                                     t.n, t.z);
216
      return code;
×
217
    }
218

219
    if (!firstColumn) {
×
220
      *p++ = ',';
×
221
    }
222
    numOfCols++;
×
223
    memcpy(p, t.z, t.n);
×
224
    p += t.n;
×
225
    firstColumn = false;
×
226
    columnCount++;
×
227
    pSql += index;
×
228

229
    index = 0;
×
230
    t = tStrGetToken((char*)pSql, &index, false, NULL);
×
231
    if (t.type != TK_NK_EQ) {
×
232
      taosMemoryFree(newSql);
×
233
      code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected '=' after column name");
×
234
      return code;
×
235
    }
236
    pSql += index;
×
237

238
    // value must be ?
239
    index = 0;
×
240
    t = tStrGetToken((char*)pSql, &index, false, NULL);
×
241
    if (t.n == 0 || t.z == NULL) {
×
242
      break;
243
    }
244
    if (t.type != TK_NK_QUESTION) {
×
245
      taosMemoryFree(newSql);
×
246
      code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected '?' placeholder");
×
247
      return code;
×
248
    }
249
    pSql += index;
×
250

251
    index = 0;
×
252
    t = tStrGetToken((char*)pSql, &index, false, NULL);
×
253
    if (t.type == TK_WHERE) {
×
254
      inSetClause = false;
×
255
      pSql += index;
×
256
    }
257
  }
258

259
  // where clause
260
  if (pSql < pEnd) {
×
261
    bool inWhereClause = true;
×
262
    int32_t bracketLevel = 0;
×
263

264
    while (inWhereClause && pSql < pEnd) {
×
265
      index = 0;
×
266
      t = tStrGetToken((char*)pSql, &index, false, NULL);
×
267
      if (t.n == 0 || t.z == NULL) {
×
268
        break;
269
      }
270

271
      if (t.type == TK_NK_LP) {
×
272
        bracketLevel++;
×
273
        pSql += index;
×
274
        continue;
×
275
      } else if (t.type == TK_NK_RP) {
×
276
        bracketLevel--;
×
277
        pSql += index;
×
278
        continue;
×
279
      } else if (t.type == TK_IN || t.type == TK_EXISTS) {
×
280
        while (pSql < pEnd) {
×
281
          pSql += index;
×
282
          index = 0;
×
283
          t = tStrGetToken((char*)pSql, &index, false, NULL);
×
284
          if (t.type == TK_AND || t.type == TK_OR || t.n == 0 || t.z == NULL) {
×
285
            break;
286
          }
287
        }
288
        continue;
×
289
      }
290

291
      const char* colName = t.z;
×
292
      int32_t     colNameLen = t.n;
×
293
      pSql += index;
×
294

295
      index = 0;
×
296
      t = tStrGetToken((char*)pSql, &index, false, NULL);
×
297
      if (t.n == 0 || t.z == NULL) {
×
298
        break;
299
      }
300
      pSql += index;
×
301

302
      index = 0;
×
303
      t = tStrGetToken((char*)pSql, &index, false, NULL);
×
304
      if (t.n == 0 || t.z == NULL) {
×
305
        break;
306
      }
307

308
      // where cols muset be pk, ignore others
309
      int32_t colId = -1;
×
310
      if (t.type == TK_NK_QUESTION) {
×
311
        if (pTableMeta != NULL && isColumnPrimaryKey(pTableMeta, colName, colNameLen, &colId)) {
×
312
          if (!firstColumn) {
×
313
            *p++ = ',';
×
314
          }
315
          memcpy(p, colName, colNameLen);
×
316
          p += colNameLen;
×
317
          firstColumn = false;
×
318
          columnCount++;
×
319
        } else {
320
          if (tSimpleHashPut(predicateCols, &numOfCols, sizeof(int32_t), &colId, sizeof(int32_t))) {
×
321
            taosMemoryFree(newSql);
×
322
            code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected '?' placeholder");
×
323
            return code;
×
324
          }
325
        }
326
        numOfCols++;
×
327
      }
328
      pSql += index;
×
329

330
      index = 0;
×
331
      t = tStrGetToken((char*)pSql, &index, false, NULL);
×
332
      if (t.type == TK_AND || t.type == TK_OR) {
×
333
        pSql += index;
×
334
      } else {
335
        if (bracketLevel == 0) {
×
336
          break;
×
337
        }
338
        pSql += index;
×
339
      }
340
    }
341
  }
342

343
  p += sprintf(p, ") VALUES (");
×
344
  for (int32_t i = 0; i < columnCount; i++) {
×
345
    if (i > 0) {
×
346
      *p++ = ',';
×
347
    }
348
    *p++ = '?';
×
349
  }
350
  *p++ = ')';
×
351
  *p = '\0';
×
352

353
  *pNewSql = newSql;
×
354
  return code;
×
355
}
356

357
bool qIsCreateTbFromFileSql(const char* pStr, size_t length) {
313,565,414✔
358
  if (NULL == pStr) {
313,565,414✔
359
    return false;
×
360
  }
361

362
  const char* pSql = pStr;
313,565,414✔
363

364
  int32_t index = 0;
313,565,414✔
365
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
313,567,947✔
366
  if (TK_CREATE != t.type) {
313,571,222✔
367
    return false;
273,249,503✔
368
  }
369

370
  do {
371
    pStr += index;
1,680,820,375✔
372
    index = 0;
1,680,824,998✔
373
    t = tStrGetToken((char*)pStr, &index, false, NULL);
1,680,824,998✔
374
    if (TK_FILE == t.type) {
1,680,821,031✔
375
      return true;
2,622✔
376
    }
377
    if (0 == t.type || 0 == t.n) {
1,680,818,409✔
378
      break;
379
    }
380
  } while (pStr - pSql < length);
1,640,505,386✔
381
  return false;
40,319,753✔
382
}
383

384
bool qParseDbName(const char* pStr, size_t length, char** pDbName) {
3,317,112✔
385
  (void)length;
386
  int32_t index = 0;
3,317,112✔
387
  SToken  t;
388

389
  if (NULL == pStr) {
3,317,431✔
390
    *pDbName = NULL;
×
391
    return false;
×
392
  }
393

394
  t = tStrGetToken((char*)pStr, &index, false, NULL);
3,317,431✔
395
  if (TK_INSERT != t.type && TK_IMPORT != t.type) {
3,320,093✔
396
    *pDbName = NULL;
10,332✔
397
    return false;
10,332✔
398
  }
399

400
  t = tStrGetToken((char*)pStr, &index, false, NULL);
3,309,761✔
401
  if (TK_INTO != t.type) {
3,309,651✔
402
    *pDbName = NULL;
×
403
    return false;
×
404
  }
405

406
  t = tStrGetToken((char*)pStr, &index, false, NULL);
3,309,651✔
407
  if (t.n == 0 || t.z == NULL) {
3,309,970✔
408
    *pDbName = NULL;
1,276✔
409
    return false;
×
410
  }
411
  char* dotPos = strnchr(t.z, '.', t.n, true);
3,308,694✔
412
  if (dotPos != NULL) {
3,304,586✔
413
    int dbNameLen = dotPos - t.z;
101,596✔
414
    *pDbName = taosMemoryMalloc(dbNameLen + 1);
101,596✔
415
    if (*pDbName == NULL) {
103,435✔
416
      return false;
×
417
    }
418
    strncpy(*pDbName, t.z, dbNameLen);
103,435✔
419
    (*pDbName)[dbNameLen] = '\0';
103,435✔
420
    return true;
103,435✔
421
  }
422
  return false;
3,202,990✔
423
}
424

425
static int32_t analyseSemantic(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
301,480,655✔
426
  int32_t code = authenticate(pCxt, pQuery, pMetaCache);
301,480,655✔
427

428
  if (pCxt->parseOnly) {
301,481,520✔
429
    return code;
11,283✔
430
  }
431

432
  if (TSDB_CODE_SUCCESS == code && pQuery->placeholderNum > 0) {
301,470,721✔
433
    TSWAP(pQuery->pPrepareRoot, pQuery->pRoot);
9,192✔
434
    return TSDB_CODE_SUCCESS;
9,192✔
435
  }
436

437
  if (TSDB_CODE_SUCCESS == code) {
301,461,785✔
438
    code = translate(pCxt, pQuery, pMetaCache);
301,308,714✔
439
  }
440
  if (TSDB_CODE_SUCCESS == code) {
301,454,001✔
441
    code = calculateConstant(pCxt, pQuery);
224,585,445✔
442
  }
443
  return code;
301,427,582✔
444
}
445

446
static int32_t parseSqlIntoAst(SParseContext* pCxt, SQuery** pQuery) {
9,192✔
447
  int32_t code = parse(pCxt, pQuery);
9,192✔
448
  if (TSDB_CODE_SUCCESS == code) {
9,192✔
449
    code = analyseSemantic(pCxt, *pQuery, NULL);
9,192✔
450
  }
451
  return code;
9,192✔
452
}
453

454
static int32_t parseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, SParseMetaCache* pMetaCache) {
313,564,085✔
455
  int32_t code = parse(pCxt, pQuery);
313,564,085✔
456
  if (TSDB_CODE_SUCCESS == code) {
313,548,675✔
457
    code = collectMetaKey(pCxt, *pQuery, pMetaCache);
301,457,562✔
458
  }
459
  return code;
313,570,123✔
460
}
461

462
static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam, void *charsetCxt) {
9,758✔
463
  if (!pParam || IS_NULL_TYPE(pParam->buffer_type)) {
9,758✔
464
    return TSDB_CODE_APP_ERROR;
×
465
  }
466
  if (IS_VAR_DATA_TYPE(pVal->node.resType.type)) {
9,758✔
467
    taosMemoryFreeClear(pVal->datum.p);
×
468
  }
469

470
  if (pParam->is_null && 1 == *(pParam->is_null)) {
9,758✔
471
    pVal->node.resType.type = TSDB_DATA_TYPE_NULL;
×
472
    pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
×
473
    return TSDB_CODE_SUCCESS;
×
474
  }
475

476
  int32_t inputSize = (NULL != pParam->length ? *(pParam->length) : tDataTypes[pParam->buffer_type].bytes);
9,758✔
477
  pVal->node.resType.type = pParam->buffer_type;
9,758✔
478
  pVal->node.resType.bytes = inputSize;
9,758✔
479

480
  switch (pParam->buffer_type) {
9,758✔
481
    case TSDB_DATA_TYPE_VARBINARY:
×
482
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
483
      if (NULL == pVal->datum.p) {
×
484
        return terrno;
×
485
      }
486
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
×
487
      memcpy(varDataVal(pVal->datum.p), pParam->buffer, pVal->node.resType.bytes);
×
488
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
×
489
      break;
×
490
    case TSDB_DATA_TYPE_VARCHAR:
3,444✔
491
    case TSDB_DATA_TYPE_GEOMETRY:
492
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
3,444✔
493
      if (NULL == pVal->datum.p) {
3,444✔
494
        return terrno;
×
495
      }
496
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
3,444✔
497
      strncpy(varDataVal(pVal->datum.p), (const char*)pParam->buffer, pVal->node.resType.bytes);
3,444✔
498
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
3,444✔
499
      break;
3,444✔
500
    case TSDB_DATA_TYPE_NCHAR: {
×
501
      pVal->node.resType.bytes *= TSDB_NCHAR_SIZE;
×
502
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
503
      if (NULL == pVal->datum.p) {
×
504
        return terrno;
×
505
      }
506

507
      int32_t output = 0;
×
508
      if (!taosMbsToUcs4(pParam->buffer, inputSize, (TdUcs4*)varDataVal(pVal->datum.p), pVal->node.resType.bytes,
×
509
                         &output, charsetCxt)) {
510
        return terrno;
×
511
      }
512
      varDataSetLen(pVal->datum.p, output);
×
513
      pVal->node.resType.bytes = output + VARSTR_HEADER_SIZE;
×
514
      break;
×
515
    }
516
    default: {
6,314✔
517
      int32_t code = nodesSetValueNodeValue(pVal, pParam->buffer);
6,314✔
518
      if (code) {
6,314✔
519
        return code;
×
520
      }
521
      break;
6,314✔
522
    }
523
  }
524
  pVal->translate = true;
9,758✔
525
  return TSDB_CODE_SUCCESS;
9,758✔
526
}
527

528
static EDealRes rewriteQueryExprAliasImpl(SNode* pNode, void* pContext) {
47,714✔
529
  if (nodesIsExprNode(pNode) && QUERY_NODE_COLUMN != nodeType(pNode)) {
47,714✔
530
    snprintf(((SExprNode*)pNode)->aliasName, TSDB_COL_NAME_LEN, "#%d", *(int32_t*)pContext);
21,278✔
531
    ++(*(int32_t*)pContext);
21,278✔
532
  }
533
  return DEAL_RES_CONTINUE;
47,714✔
534
}
535

536
static void rewriteQueryExprAlias(SNode* pRoot, int32_t* pNo) {
9,192✔
537
  switch (nodeType(pRoot)) {
9,192✔
538
    case QUERY_NODE_SELECT_STMT:
9,192✔
539
      nodesWalkSelectStmt((SSelectStmt*)pRoot, SQL_CLAUSE_FROM, rewriteQueryExprAliasImpl, pNo);
9,192✔
540
      break;
9,192✔
541
    case QUERY_NODE_SET_OPERATOR: {
×
542
      SSetOperator* pSetOper = (SSetOperator*)pRoot;
×
543
      rewriteQueryExprAlias(pSetOper->pLeft, pNo);
×
544
      rewriteQueryExprAlias(pSetOper->pRight, pNo);
×
545
      break;
×
546
    }
547
    default:
×
548
      break;
×
549
  }
550
}
9,192✔
551

552
static void rewriteExprAlias(SNode* pRoot) {
9,192✔
553
  int32_t no = 1;
9,192✔
554
  rewriteQueryExprAlias(pRoot, &no);
9,192✔
555
}
9,192✔
556

557
int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery) {
3,313,319✔
558
  int32_t code = TSDB_CODE_SUCCESS;
3,313,319✔
559
  if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) {
3,313,319✔
560
    code = parseInsertSql(pCxt, pQuery, NULL, NULL);
3,308,639✔
561
  } else {
562
    code = parseSqlIntoAst(pCxt, pQuery);
9,192✔
563
  }
564
  terrno = code;
3,307,301✔
565
  return code;
3,316,233✔
566
}
567

568
static int32_t parseQuerySyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
313,564,942✔
569
  SParseMetaCache metaCache = {0};
313,564,942✔
570
  int32_t         code = parseSqlSyntax(pCxt, pQuery, &metaCache);
313,566,767✔
571
  if (TSDB_CODE_SUCCESS == code) {
313,567,405✔
572
    code = buildCatalogReq(&metaCache, pCatalogReq);
301,474,078✔
573
  }
574
  destoryParseMetaCache(&metaCache, true);
313,567,507✔
575
  return code;
313,556,446✔
576
}
577

578
static int32_t parseCreateTbFromFileSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
2,622✔
579
  if (NULL == *pQuery) return parseQuerySyntax(pCxt, pQuery, pCatalogReq);
2,622✔
580

581
  return continueCreateTbFromFile(pCxt, pQuery);
1,311✔
582
}
583

584
int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
847,306,703✔
585
  int32_t code = nodesAcquireAllocator(pCxt->allocatorId);
847,306,703✔
586
  if (TSDB_CODE_SUCCESS == code) {
847,304,467✔
587
    if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) {
847,304,467✔
588
      code = parseInsertSql(pCxt, pQuery, pCatalogReq, NULL);
533,744,586✔
589
    } else if (qIsCreateTbFromFileSql(pCxt->pSql, pCxt->sqlLen)) {
313,570,769✔
590
      code = parseCreateTbFromFileSyntax(pCxt, pQuery, pCatalogReq);
2,622✔
591
    } else {
592
      code = parseQuerySyntax(pCxt, pQuery, pCatalogReq);
313,568,187✔
593
    }
594
  }
595
  (void)nodesReleaseAllocator(pCxt->allocatorId);
847,292,734✔
596
  terrno = code;
847,308,602✔
597
  return code;
847,305,345✔
598
}
599

600
int32_t qAnalyseSqlSemantic(SParseContext* pCxt, const struct SCatalogReq* pCatalogReq,
301,477,029✔
601
                            struct SMetaData* pMetaData, SQuery* pQuery) {
602
  SParseMetaCache metaCache = {0};
301,477,029✔
603
  int32_t         code = nodesAcquireAllocator(pCxt->allocatorId);
301,477,035✔
604
  if (TSDB_CODE_SUCCESS == code && pCatalogReq) {
301,475,975✔
605
    code = putMetaDataToCache(pCatalogReq, pMetaData, &metaCache);
301,475,985✔
606
  }
607
  if (TSDB_CODE_SUCCESS == code) {
301,476,648✔
608
    code = analyseSemantic(pCxt, pQuery, &metaCache);
301,476,210✔
609
  }
610
  (void)nodesReleaseAllocator(pCxt->allocatorId);
301,457,178✔
611
  destoryParseMetaCache(&metaCache, false);
301,472,896✔
612
  terrno = code;
301,457,914✔
613
  return code;
301,462,697✔
614
}
615

616
int32_t qContinueParseSql(SParseContext* pCxt, struct SCatalogReq* pCatalogReq, const struct SMetaData* pMetaData,
6,282,395✔
617
                          SQuery* pQuery) {
618
  return parseInsertSql(pCxt, &pQuery, pCatalogReq, pMetaData);
6,282,395✔
619
}
620

621
int32_t qContinueParsePostQuery(SParseContext* pCxt, SQuery* pQuery, SSDataBlock* pBlock) {
×
622
  int32_t code = TSDB_CODE_SUCCESS;
×
623
  switch (nodeType(pQuery->pRoot)) {
×
624
    default:
625
      break;
×
626
  }
627

628
  return code;
×
629
}
630

631
static void destoryTablesReq(void* p) {
1,129,702,515✔
632
  STablesReq* pRes = (STablesReq*)p;
1,129,702,515✔
633
  taosArrayDestroy(pRes->pTables);
1,129,702,515✔
634
}
1,129,691,602✔
635

636
void destoryCatalogReq(SCatalogReq* pCatalogReq) {
847,313,385✔
637
  if (NULL == pCatalogReq) {
847,313,385✔
638
    return;
11,283✔
639
  }
640
  taosArrayDestroy(pCatalogReq->pDbVgroup);
847,302,102✔
641
  taosArrayDestroy(pCatalogReq->pDbCfg);
847,306,598✔
642
  taosArrayDestroy(pCatalogReq->pDbInfo);
847,304,151✔
643
  if (pCatalogReq->cloned) {
847,304,365✔
644
    taosArrayDestroy(pCatalogReq->pTableMeta);
×
645
    taosArrayDestroy(pCatalogReq->pTableHash);
×
646
#ifdef TD_ENTERPRISE
647
    taosArrayDestroy(pCatalogReq->pView);
×
648
#endif
649
    taosArrayDestroy(pCatalogReq->pTableTSMAs);
×
650
    taosArrayDestroy(pCatalogReq->pTSMAs);
×
651
    taosArrayDestroy(pCatalogReq->pTableName);
×
652
  } else {
653
    taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq);
847,302,539✔
654
    taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq);
847,298,262✔
655
#ifdef TD_ENTERPRISE
656
    taosArrayDestroyEx(pCatalogReq->pView, destoryTablesReq);
847,300,922✔
657
#endif
658
    taosArrayDestroyEx(pCatalogReq->pTableTSMAs, destoryTablesReq);
847,296,163✔
659
    taosArrayDestroyEx(pCatalogReq->pTSMAs, destoryTablesReq);
847,299,068✔
660
    taosArrayDestroyEx(pCatalogReq->pTableName, destoryTablesReq);
847,300,850✔
661
  }
662
  taosArrayDestroy(pCatalogReq->pUdf);
847,296,520✔
663
  taosArrayDestroy(pCatalogReq->pIndex);
847,300,720✔
664
  taosArrayDestroy(pCatalogReq->pUser);
847,300,080✔
665
  taosArrayDestroy(pCatalogReq->pTableIndex);
847,291,526✔
666
  taosArrayDestroy(pCatalogReq->pTableCfg);
847,296,066✔
667
  taosArrayDestroy(pCatalogReq->pTableTag);
847,295,562✔
668
  taosArrayDestroy(pCatalogReq->pVStbRefDbs);
847,291,994✔
669
}
670

671
void tfreeSParseQueryRes(void* p) {
11,283✔
672
  if (NULL == p) {
11,283✔
673
    return;
×
674
  }
675

676
  SParseQueryRes* pRes = p;
11,283✔
677
  destoryCatalogReq(pRes->pCatalogReq);
11,283✔
678
  taosMemoryFree(pRes->pCatalogReq);
11,283✔
679
  catalogFreeMetaData(&pRes->meta);
11,283✔
680
}
681

682
void qDestroyParseContext(SParseContext* pCxt) {
847,285,864✔
683
  if (NULL == pCxt) {
847,285,864✔
684
    return;
×
685
  }
686

687
  taosArrayDestroyEx(pCxt->pSubMetaList, tfreeSParseQueryRes);
847,285,864✔
688
  taosArrayDestroy(pCxt->pTableMetaPos);
847,301,635✔
689
  taosArrayDestroy(pCxt->pTableVgroupPos);
847,301,560✔
690
  taosMemoryFree(pCxt);
847,302,005✔
691
}
692

693
void qDestroyQuery(SQuery* pQueryNode) { nodesDestroyNode((SNode*)pQueryNode); }
947,778,542✔
694

695
int32_t qExtractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema) {
91,542✔
696
  return extractResultSchema(pRoot, numOfCols, pSchema, NULL);
91,542✔
697
}
698

699
int32_t qSetSTableIdForRsma(SNode* pStmt, int64_t uid) {
×
700
  if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
×
701
    SNode* pTable = ((SSelectStmt*)pStmt)->pFromTable;
×
702
    if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) {
×
703
      ((SRealTableNode*)pTable)->pMeta->uid = uid;
×
704
      ((SRealTableNode*)pTable)->pMeta->suid = uid;
×
705
      return TSDB_CODE_SUCCESS;
×
706
    }
707
  }
708
  return TSDB_CODE_FAILED;
×
709
}
710

711
int32_t qInitKeywordsTable() { return taosInitKeywordsTable(); }
1,618,900✔
712

713
void qCleanupKeywordsTable() { taosCleanupKeywordsTable(); }
1,618,942✔
714

715
int32_t qStmtBindParams(SQuery* pQuery, TAOS_MULTI_BIND* pParams, int32_t colIdx, void *charsetCxt) {
9,184✔
716
  int32_t code = TSDB_CODE_SUCCESS;
9,184✔
717

718
  if (colIdx < 0) {
9,184✔
719
    int32_t size = taosArrayGetSize(pQuery->pPlaceholderValues);
9,184✔
720
    for (int32_t i = 0; i < size; ++i) {
18,942✔
721
      code = setValueByBindParam((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, i), pParams + i, charsetCxt);
9,758✔
722
      if (TSDB_CODE_SUCCESS != code) {
9,758✔
723
        return code;
×
724
      }
725
    }
726
  } else {
727
    code = setValueByBindParam((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, colIdx), pParams, charsetCxt);
×
728
  }
729

730
  if (TSDB_CODE_SUCCESS == code && (colIdx < 0 || colIdx + 1 == pQuery->placeholderNum)) {
9,184✔
731
    nodesDestroyNode(pQuery->pRoot);
9,184✔
732
    pQuery->pRoot = NULL;
9,184✔
733
    code = nodesCloneNode(pQuery->pPrepareRoot, &pQuery->pRoot);
9,184✔
734
  }
735
  if (TSDB_CODE_SUCCESS == code) {
9,184✔
736
    rewriteExprAlias(pQuery->pRoot);
9,184✔
737
  }
738
  return code;
9,184✔
739
}
740

741
static int32_t setValueByBindParam2(SValueNode* pVal, TAOS_STMT2_BIND* pParam, void* charsetCxt) {
16✔
742
  if (!pParam || IS_NULL_TYPE(pParam->buffer_type)) {
16✔
743
    return TSDB_CODE_APP_ERROR;
×
744
  }
745
  if (IS_VAR_DATA_TYPE(pVal->node.resType.type)) {
16✔
746
    taosMemoryFreeClear(pVal->datum.p);
×
747
  }
748

749
  if (pParam->is_null && 1 == *(pParam->is_null)) {
16✔
750
    pVal->node.resType.type = TSDB_DATA_TYPE_NULL;
×
751
    pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
×
752
    return TSDB_CODE_SUCCESS;
×
753
  }
754

755
  int32_t inputSize = (NULL != pParam->length ? *(pParam->length) : tDataTypes[pParam->buffer_type].bytes);
16✔
756
  pVal->node.resType.type = pParam->buffer_type;
16✔
757
  pVal->node.resType.bytes = inputSize;
16✔
758

759
  switch (pParam->buffer_type) {
16✔
760
    case TSDB_DATA_TYPE_VARBINARY:
×
761
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
762
      if (NULL == pVal->datum.p) {
×
763
        return terrno;
×
764
      }
765
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
×
766
      memcpy(varDataVal(pVal->datum.p), pParam->buffer, pVal->node.resType.bytes);
×
767
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
×
768
      break;
×
769
    case TSDB_DATA_TYPE_VARCHAR:
×
770
    case TSDB_DATA_TYPE_GEOMETRY:
771
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
772
      if (NULL == pVal->datum.p) {
×
773
        return terrno;
×
774
      }
775
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
×
776
      strncpy(varDataVal(pVal->datum.p), (const char*)pParam->buffer, pVal->node.resType.bytes);
×
777
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
×
NEW
778
      if (IS_DURATION_VAL(pVal->flag)) {
×
NEW
779
        taosMemoryFreeClear(pVal->literal);
×
NEW
780
        taosMemoryFreeClear(pVal->datum.p);
×
NEW
781
        pVal->literal = taosStrndup((const char*)pParam->buffer, pVal->node.resType.bytes - VARSTR_HEADER_SIZE);
×
NEW
782
        if (!pVal->literal) {
×
NEW
783
          return terrno;
×
784
        }
NEW
785
        int64_t duration = 0;
×
NEW
786
        char    unit = 0;
×
NEW
787
        if (parseNatualDuration(pVal->literal, strlen(pVal->literal), &duration, &unit,
×
NEW
788
                                pVal->node.resType.precision, true) != TSDB_CODE_SUCCESS) {
×
NEW
789
          return TSDB_CODE_PAR_WRONG_VALUE_TYPE;
×
790
        }
NEW
791
        pVal->datum.i = duration;
×
NEW
792
        pVal->unit = unit;
×
NEW
793
        *(int64_t*)&pVal->typeData = duration;
×
NEW
794
        pVal->node.resType.type = TSDB_DATA_TYPE_BIGINT;
×
NEW
795
        pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
×
796
      }
797
      break;
×
798
    case TSDB_DATA_TYPE_NCHAR: {
×
799
      pVal->node.resType.bytes *= TSDB_NCHAR_SIZE;
×
800
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
801
      if (NULL == pVal->datum.p) {
×
802
        return terrno;
×
803
      }
804

805
      int32_t output = 0;
×
806
      if (!taosMbsToUcs4(pParam->buffer, inputSize, (TdUcs4*)varDataVal(pVal->datum.p), pVal->node.resType.bytes,
×
807
                         &output, charsetCxt)) {
808
        return terrno;
×
809
      }
810
      varDataSetLen(pVal->datum.p, output);
×
811
      pVal->node.resType.bytes = output + VARSTR_HEADER_SIZE;
×
812
      break;
×
813
    }
814
    case TSDB_DATA_TYPE_BLOB:
×
815
    case TSDB_DATA_TYPE_MEDIUMBLOB:
816
      return TSDB_CODE_BLOB_NOT_SUPPORT;  // BLOB data type is not supported in stmt2
×
817
    default: {
16✔
818
      int32_t code = nodesSetValueNodeValue(pVal, pParam->buffer);
16✔
819
      if (code) {
16✔
820
        return code;
×
821
      }
822
      break;
16✔
823
    }
824
  }
825
  pVal->translate = true;
16✔
826
  return TSDB_CODE_SUCCESS;
16✔
827
}
828

829
int32_t qStmtBindParams2(SQuery* pQuery, TAOS_STMT2_BIND* pParams, int32_t colIdx, void* charsetCxt) {
8✔
830
  int32_t code = TSDB_CODE_SUCCESS;
8✔
831

832
  if (colIdx < 0) {
8✔
833
    int32_t size = taosArrayGetSize(pQuery->pPlaceholderValues);
8✔
834
    for (int32_t i = 0; i < size; ++i) {
24✔
835
      code = setValueByBindParam2((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, i), pParams + i, charsetCxt);
16✔
836
      if (TSDB_CODE_SUCCESS != code) {
16✔
837
        return code;
×
838
      }
839
    }
840
  } else {
841
    code = setValueByBindParam2((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, colIdx), pParams, charsetCxt);
×
842
  }
843

844
  if (TSDB_CODE_SUCCESS == code && (colIdx < 0 || colIdx + 1 == pQuery->placeholderNum)) {
8✔
845
    nodesDestroyNode(pQuery->pRoot);
8✔
846
    pQuery->pRoot = NULL;
8✔
847
    code = nodesCloneNode(pQuery->pPrepareRoot, &pQuery->pRoot);
8✔
848
  }
849
  if (TSDB_CODE_SUCCESS == code) {
8✔
850
    rewriteExprAlias(pQuery->pRoot);
8✔
851
  }
852
  return code;
8✔
853
}
854

855
int32_t qStmtParseQuerySql(SParseContext* pCxt, SQuery* pQuery) {
9,192✔
856
  int32_t code = translate(pCxt, pQuery, NULL);
9,192✔
857
  if (TSDB_CODE_SUCCESS == code) {
9,192✔
858
    code = calculateConstant(pCxt, pQuery);
9,192✔
859
  }
860
  return code;
9,192✔
861
}
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