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

taosdata / TDengine / #5081

17 May 2026 01:15AM UTC coverage: 73.368% (-0.04%) from 73.403%
#5081

push

travis-ci

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

* refactor: do some internal refactor.

* fix: fix multiprocess sync issue.

* feat: add dynamic anomaly detection and forecasting services

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

* fix: handle undeploy when model exists only on disk

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

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

* fix: guard dynamic registry concurrent access

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

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

* fix: tighten service list locking scope

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

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

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

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

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

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

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

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

* Potential fix for pull request finding

Co-au... (continued)

281582 of 383795 relevant lines covered (73.37%)

137177705.18 hits per line

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

78.89
/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 "decimal.h"
22
#include "parInsertUtil.h"
23
#include "parInt.h"
24
#include "parToken.h"
25
#include "parUtil.h"
26
#include "tname.h"
27
#include "ttime.h"
28

29
bool qIsInsertValuesSql(const char* pStr, size_t length) {
2,147,483,647✔
30
  if (NULL == pStr) {
2,147,483,647✔
31
    return false;
×
32
  }
33

34
  const char* pSql = pStr;
2,147,483,647✔
35

36
  int32_t index = 0;
2,147,483,647✔
37
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
2,147,483,647✔
38
  if (TK_INSERT != t.type && TK_IMPORT != t.type) {
2,147,483,647✔
39
    return false;
1,016,033,178✔
40
  }
41

42
  do {
43
    pStr += index;
2,147,483,647✔
44
    index = 0;
2,147,483,647✔
45
    t = tStrGetToken((char*)pStr, &index, false, NULL);
2,147,483,647✔
46
    if (TK_USING == t.type || TK_VALUES == t.type || TK_FILE == t.type) {
2,147,483,647✔
47
      return true;
1,476,071,001✔
48
    } else if (TK_SELECT == t.type) {
2,147,483,647✔
49
      return false;
1,169,244✔
50
    }
51
    if (0 == t.type || 0 == t.n) {
2,147,483,647✔
52
      break;
53
    }
54
  } while (pStr - pSql < length);
2,147,483,647✔
55
  return false;
2,648✔
56
}
57

58
bool qIsUpdateSetSql(const char* pStr, size_t length, SName* pTableName, int32_t acctId, const char* dbName,
7,842,573✔
59
                     char* msgBuf, int32_t msgBufLen, int* pCode) {
60
                        if (NULL == pStr) {
7,842,573✔
61
    return false;
×
62
  }
63

64
  const char* pSql = pStr;
7,842,573✔
65

66
  int32_t index = 0;
7,842,573✔
67
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
7,845,329✔
68
    if (TK_UPDATE != t.type) {
7,849,647✔
69
    return false;
7,847,073✔
70
  }
71
  SMsgBuf pMsgBuf = {.len = msgBufLen, .buf = msgBuf};
2,574✔
72
  pStr += index;
2,574✔
73
  index = 0;
2,574✔
74
  t = tStrGetToken((char*)pStr, &index, false, NULL);
2,574✔
75
  if (t.n == 0 || t.z == NULL) {
2,574✔
76
    *pCode = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_TSC_STMT_TBNAME_ERROR, "Invalid table name");
198✔
77
    return false;
198✔
78
  }
79

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

100
bool qIsSelectFromSql(const char* pStr, size_t length) {
179,083✔
101
  if (NULL == pStr) {
179,083✔
102
    return false;
198✔
103
  }
104

105
  const char* pSql = pStr;
178,885✔
106

107
  int32_t index = 0;
178,885✔
108
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
178,869✔
109
  if (TK_SELECT != t.type) {
178,885✔
110
    return false;
168,148✔
111
  }
112

113
  do {
114
    pStr += index;
94,194✔
115
    index = 0;
94,194✔
116
    t = tStrGetToken((char*)pStr, &index, false, NULL);
94,194✔
117
    if (TK_FROM == t.type) {
94,194✔
118
      return true;
10,737✔
119
    }
120
    if (0 == t.type || 0 == t.n) {
83,457✔
121
      break;
122
    }
123
  } while (pStr - pSql < length);
83,457✔
124

125
  return false;
×
126
}
127

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

133
  for (int32_t i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) {
18,810✔
134
    const SSchema* pSchema = &pTableMeta->schema[i];
18,810✔
135
    if (strncmp(pSchema->name, colName, colNameLen) == 0 && strlen(pSchema->name) == colNameLen) {
18,810✔
136
      if (colId) {
6,336✔
137
        *colId = i;
1,980✔
138
      }
139
      if ((pSchema->flags & COL_IS_KEY || pSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID)) {
6,336✔
140
        return true;
1,584✔
141
      }
142
      return false;
4,752✔
143
    }
144
  }
145
  return false;
×
146
}
147

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

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

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

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

184
  {
185
    size_t rem = maxSqlLen - (p - newSql);
1,980✔
186
    int written = snprintf(p, rem, "INSERT INTO %.*s (", (int)t.n, t.z);
1,980✔
187
    if (written < 0 || (size_t)written >= rem) {
1,980✔
188
      taosMemoryFree(newSql);
×
189
      code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "sql too long");
×
190
      return code;
×
191
    }
192
    p += written;
1,980✔
193
  }
194
  pSql += index;
1,980✔
195

196
  // SET
197
  index = 0;
1,980✔
198
  t = tStrGetToken((char*)pSql, &index, false, NULL);
1,980✔
199
  if (TK_SET != t.type) {
1,980✔
200
    taosMemoryFree(newSql);
198✔
201
    code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected SET keyword");
198✔
202
    return code;
198✔
203
  }
204
  pSql += index;
1,782✔
205

206
  bool    firstColumn = true;
1,782✔
207
  int32_t columnCount = 0;
1,782✔
208
  bool inSetClause = true;
1,782✔
209
  int32_t numOfCols = 0;
1,782✔
210

211
  // col name
212
  while (inSetClause && pSql < pEnd) {
5,544✔
213
    index = 0;
4,356✔
214
    t = tStrGetToken((char*)pSql, &index, false, NULL);
4,356✔
215
    if (t.n == 0 || t.z == NULL) {
4,356✔
216
      break;
217
    }
218

219
    // pk can't set
220
    if (pTableMeta != NULL && isColumnPrimaryKey(pTableMeta, t.z, t.n, NULL)) {
4,356✔
221
      taosMemoryFree(newSql);
396✔
222
      code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Cannot update primary key column '%.*s'",
396✔
223
                                     t.n, t.z);
224
      return code;
396✔
225
    }
226

227
    if (!firstColumn) {
3,960✔
228
      *p++ = ',';
2,376✔
229
    }
230
    numOfCols++;
3,960✔
231
    memcpy(p, t.z, t.n);
3,960✔
232
    p += t.n;
3,960✔
233
    firstColumn = false;
3,960✔
234
    columnCount++;
3,960✔
235
    pSql += index;
3,960✔
236

237
    index = 0;
3,960✔
238
    t = tStrGetToken((char*)pSql, &index, false, NULL);
3,960✔
239
    if (t.type != TK_NK_EQ) {
3,960✔
240
      taosMemoryFree(newSql);
×
241
      code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected '=' after column name");
×
242
      return code;
×
243
    }
244
    pSql += index;
3,960✔
245

246
    // value must be ?
247
    index = 0;
3,960✔
248
    t = tStrGetToken((char*)pSql, &index, false, NULL);
3,960✔
249
    if (t.n == 0 || t.z == NULL) {
3,960✔
250
      break;
251
    }
252
    if (t.type != TK_NK_QUESTION) {
3,960✔
253
      taosMemoryFree(newSql);
198✔
254
      code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected '?' placeholder");
198✔
255
      return code;
198✔
256
    }
257
    pSql += index;
3,762✔
258

259
    index = 0;
3,762✔
260
    t = tStrGetToken((char*)pSql, &index, false, NULL);
3,762✔
261
    if (t.type == TK_WHERE) {
3,762✔
262
      inSetClause = false;
990✔
263
      pSql += index;
990✔
264
    }
265
  }
266

267
  // where clause
268
  if (pSql < pEnd) {
1,188✔
269
    bool inWhereClause = true;
990✔
270
    int32_t bracketLevel = 0;
990✔
271

272
    while (inWhereClause && pSql < pEnd) {
3,762✔
273
      index = 0;
3,366✔
274
      t = tStrGetToken((char*)pSql, &index, false, NULL);
3,366✔
275
      if (t.n == 0 || t.z == NULL) {
3,366✔
276
        break;
277
      }
278

279
      if (t.type == TK_NK_LP) {
3,366✔
280
        bracketLevel++;
198✔
281
        pSql += index;
198✔
282
        continue;
594✔
283
      } else if (t.type == TK_NK_RP) {
3,168✔
284
        bracketLevel--;
198✔
285
        pSql += index;
198✔
286
        continue;
198✔
287
      } else if (t.type == TK_IN || t.type == TK_EXISTS) {
2,970✔
288
        while (pSql < pEnd) {
2,574✔
289
          pSql += index;
2,574✔
290
          index = 0;
2,574✔
291
          t = tStrGetToken((char*)pSql, &index, false, NULL);
2,574✔
292
          if (t.type == TK_AND || t.type == TK_OR || t.n == 0 || t.z == NULL) {
2,574✔
293
            break;
294
          }
295
        }
296
        continue;
198✔
297
      }
298

299
      const char* colName = t.z;
2,772✔
300
      int32_t     colNameLen = t.n;
2,772✔
301
      pSql += index;
2,772✔
302

303
      index = 0;
2,772✔
304
      t = tStrGetToken((char*)pSql, &index, false, NULL);
2,772✔
305
      if (t.n == 0 || t.z == NULL) {
2,772✔
306
        break;
307
      }
308
      pSql += index;
2,772✔
309

310
      index = 0;
2,772✔
311
      t = tStrGetToken((char*)pSql, &index, false, NULL);
2,772✔
312
      if (t.n == 0 || t.z == NULL) {
2,772✔
313
        break;
314
      }
315

316
      // where cols muset be pk, ignore others
317
      int32_t colId = -1;
2,772✔
318
      if (t.type == TK_NK_QUESTION) {
2,772✔
319
        if (pTableMeta != NULL && isColumnPrimaryKey(pTableMeta, colName, colNameLen, &colId)) {
1,980✔
320
          if (!firstColumn) {
1,188✔
321
            *p++ = ',';
1,188✔
322
          }
323
          memcpy(p, colName, colNameLen);
1,188✔
324
          p += colNameLen;
1,188✔
325
          firstColumn = false;
1,188✔
326
          columnCount++;
1,188✔
327
        } else {
328
          if (tSimpleHashPut(predicateCols, &numOfCols, sizeof(int32_t), &colId, sizeof(int32_t))) {
792✔
329
            taosMemoryFree(newSql);
×
330
            code = generateSyntaxErrMsgExt(&pMsgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Expected '?' placeholder");
×
331
            return code;
×
332
          }
333
        }
334
        numOfCols++;
1,980✔
335
      }
336
      pSql += index;
2,772✔
337

338
      index = 0;
2,772✔
339
      t = tStrGetToken((char*)pSql, &index, false, NULL);
2,772✔
340
      if (t.type == TK_AND || t.type == TK_OR) {
2,772✔
341
        pSql += index;
1,980✔
342
      } else {
343
        if (bracketLevel == 0) {
792✔
344
          break;
594✔
345
        }
346
        pSql += index;
198✔
347
      }
348
    }
349
  }
350

351
  p += snprintf(p, maxSqlLen - (p - newSql), ") VALUES (");
1,188✔
352
  for (int32_t i = 0; i < columnCount; i++) {
5,742✔
353
    if (i > 0) {
4,554✔
354
      *p++ = ',';
3,366✔
355
    }
356
    *p++ = '?';
4,554✔
357
  }
358
  *p++ = ')';
1,188✔
359
  *p = '\0';
1,188✔
360

361
  *pNewSql = newSql;
1,188✔
362
  return code;
1,188✔
363
}
364

365
bool qIsCreateTbFromFileSql(const char* pStr, size_t length) {
508,848,505✔
366
  if (NULL == pStr) {
508,848,505✔
367
    return false;
×
368
  }
369

370
  const char* pSql = pStr;
508,848,505✔
371

372
  int32_t index = 0;
508,848,505✔
373
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
508,852,438✔
374
  if (TK_CREATE != t.type) {
508,873,936✔
375
    return false;
453,715,182✔
376
  }
377

378
  do {
379
    pStr += index;
2,147,483,647✔
380
    index = 0;
2,147,483,647✔
381
    t = tStrGetToken((char*)pStr, &index, false, NULL);
2,147,483,647✔
382
    if (TK_FILE == t.type) {
2,147,483,647✔
383
      return true;
3,088✔
384
    }
385
    if (0 == t.type || 0 == t.n) {
2,147,483,647✔
386
      break;
387
    }
388
  } while (pStr - pSql < length);
2,102,073,496✔
389
  return false;
55,154,236✔
390
}
391

392
bool qParseDbName(const char* pStr, size_t length, char** pDbName) {
8,023,818✔
393
  (void)length;
394
  int32_t index = 0;
8,023,818✔
395
  SToken  t;
396

397
  if (NULL == pStr) {
8,024,967✔
398
    *pDbName = NULL;
×
399
    return false;
×
400
  }
401

402
  t = tStrGetToken((char*)pStr, &index, false, NULL);
8,024,967✔
403
  if (TK_INSERT != t.type && TK_IMPORT != t.type) {
8,028,519✔
404
    *pDbName = NULL;
18,617✔
405
    return false;
18,617✔
406
  }
407

408
  t = tStrGetToken((char*)pStr, &index, false, NULL);
8,009,902✔
409
  if (TK_INTO != t.type) {
8,009,489✔
410
    *pDbName = NULL;
×
411
    return false;
×
412
  }
413

414
  t = tStrGetToken((char*)pStr, &index, false, NULL);
8,009,489✔
415
  if (t.n == 0 || t.z == NULL) {
8,009,902✔
416
    *pDbName = NULL;
×
417
    return false;
×
418
  }
419
  char* dotPos = strnchr(t.z, '.', t.n, true);
8,009,902✔
420
  if (dotPos != NULL) {
8,006,266✔
421
    int dbNameLen = dotPos - t.z;
163,551✔
422
    *pDbName = taosMemoryMalloc(dbNameLen + 1);
163,551✔
423
    if (*pDbName == NULL) {
160,067✔
424
      return false;
×
425
    }
426
    tstrncpy(*pDbName, t.z, dbNameLen + 1);
160,127✔
427
    return true;
160,067✔
428
  }
429
  return false;
7,842,715✔
430
}
431

432
static int32_t analyseSemantic(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
494,551,894✔
433
  int32_t code = authenticate(pCxt, pQuery, pMetaCache);
494,551,894✔
434

435
  if (pCxt->parseOnly) {
494,542,731✔
436
    return code;
332,944✔
437
  }
438

439
  if (TSDB_CODE_SUCCESS == code && pQuery->placeholderNum > 0) {
494,209,277✔
440
    TSWAP(pQuery->pPrepareRoot, pQuery->pRoot);
24,798✔
441
    return TSDB_CODE_SUCCESS;
24,798✔
442
  }
443

444
  if (TSDB_CODE_SUCCESS == code) {
494,184,055✔
445
    code = translate(pCxt, pQuery, pMetaCache);
493,930,567✔
446
  }
447
  if (TSDB_CODE_SUCCESS == code) {
494,175,447✔
448
    code = calculateConstant(pCxt, pQuery);
408,172,965✔
449
  }
450
  return code;
494,171,354✔
451
}
452

453
static int32_t parseSqlIntoAst(SParseContext* pCxt, SQuery** pQuery) {
212,952✔
454
  int32_t code = parse(pCxt, pQuery);
212,952✔
455
  if (TSDB_CODE_SUCCESS == code) {
212,952✔
456
    code = analyseSemantic(pCxt, *pQuery, NULL);
205,032✔
457
  }
458
  return code;
212,952✔
459
}
460

461
static int32_t parseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, SParseMetaCache* pMetaCache) {
508,839,779✔
462
  int32_t code = parse(pCxt, pQuery);
508,839,779✔
463
  if (TSDB_CODE_SUCCESS == code) {
508,811,049✔
464
    code = collectMetaKey(pCxt, *pQuery, pMetaCache);
494,315,419✔
465
  }
466
  return code;
508,851,043✔
467
}
468

469
static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam, void *charsetCxt) {
17,074✔
470
  if (!pParam || IS_NULL_TYPE(pParam->buffer_type)) {
17,074✔
471
    return TSDB_CODE_APP_ERROR;
×
472
  }
473
  if (IS_VAR_DATA_TYPE(pVal->node.resType.type)) {
17,074✔
474
    taosMemoryFreeClear(pVal->datum.p);
×
475
  }
476

477
  if (pParam->is_null && 1 == *(pParam->is_null)) {
17,074✔
478
    pVal->node.resType.type = TSDB_DATA_TYPE_NULL;
×
479
    pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
×
480
    return TSDB_CODE_SUCCESS;
×
481
  }
482

483
  int32_t inputSize = (NULL != pParam->length ? *(pParam->length) : tDataTypes[pParam->buffer_type].bytes);
17,074✔
484
  pVal->node.resType.type = pParam->buffer_type;
17,074✔
485
  pVal->node.resType.bytes = inputSize;
17,074✔
486

487
  switch (pParam->buffer_type) {
17,074✔
488
    case TSDB_DATA_TYPE_VARBINARY:
×
489
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
490
      if (NULL == pVal->datum.p) {
×
491
        return terrno;
×
492
      }
493
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
×
494
      memcpy(varDataVal(pVal->datum.p), pParam->buffer, pVal->node.resType.bytes);
×
495
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
×
496
      break;
×
497
    case TSDB_DATA_TYPE_VARCHAR:
4,235✔
498
    case TSDB_DATA_TYPE_GEOMETRY:
499
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
4,235✔
500
      if (NULL == pVal->datum.p) {
4,235✔
501
        return terrno;
×
502
      }
503
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
4,235✔
504
      TAOS_STRNCPY(varDataVal(pVal->datum.p), (const char*)pParam->buffer, pVal->node.resType.bytes);
4,235✔
505
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
4,235✔
506
      break;
4,235✔
507
    case TSDB_DATA_TYPE_NCHAR: {
×
508
      pVal->node.resType.bytes *= TSDB_NCHAR_SIZE;
×
509
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
510
      if (NULL == pVal->datum.p) {
×
511
        return terrno;
×
512
      }
513

514
      int32_t output = 0;
×
515
      if (!taosMbsToUcs4(pParam->buffer, inputSize, (TdUcs4*)varDataVal(pVal->datum.p), pVal->node.resType.bytes,
×
516
                         &output, charsetCxt)) {
517
        return terrno;
×
518
      }
519
      varDataSetLen(pVal->datum.p, output);
×
520
      pVal->node.resType.bytes = output + VARSTR_HEADER_SIZE;
×
521
      break;
×
522
    }
523
    default: {
12,839✔
524
      int32_t code = nodesSetValueNodeValue(pVal, pParam->buffer);
12,839✔
525
      if (code) {
12,839✔
526
        return code;
×
527
      }
528
      break;
12,839✔
529
    }
530
  }
531
  pVal->translate = true;
17,074✔
532
  return TSDB_CODE_SUCCESS;
17,074✔
533
}
534

535
static EDealRes rewriteQueryExprAliasImpl(SNode* pNode, void* pContext) {
262,183✔
536
  if (nodesIsExprNode(pNode) && QUERY_NODE_COLUMN != nodeType(pNode)) {
262,183✔
537
    snprintf(((SExprNode*)pNode)->aliasName, TSDB_COL_NAME_LEN, "#%d", *(int32_t*)pContext);
134,527✔
538
    ++(*(int32_t*)pContext);
134,527✔
539
  }
540
  return DEAL_RES_CONTINUE;
262,183✔
541
}
542

543
static void rewriteQueryExprAlias(SNode* pRoot, int32_t* pNo) {
26,436✔
544
  switch (nodeType(pRoot)) {
26,436✔
545
    case QUERY_NODE_SELECT_STMT:
26,436✔
546
      nodesWalkSelectStmt((SSelectStmt*)pRoot, SQL_CLAUSE_FROM, rewriteQueryExprAliasImpl, pNo);
26,436✔
547
      break;
26,436✔
548
    case QUERY_NODE_SET_OPERATOR: {
×
549
      SSetOperator* pSetOper = (SSetOperator*)pRoot;
×
550
      rewriteQueryExprAlias(pSetOper->pLeft, pNo);
×
551
      rewriteQueryExprAlias(pSetOper->pRight, pNo);
×
552
      break;
×
553
    }
554
    default:
×
555
      break;
×
556
  }
557
}
26,436✔
558

559
static void rewriteExprAlias(SNode* pRoot) {
26,436✔
560
  int32_t no = 1;
26,436✔
561
  rewriteQueryExprAlias(pRoot, &no);
26,436✔
562
}
26,436✔
563

564
int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery) {
8,220,618✔
565
  int32_t code = TSDB_CODE_SUCCESS;
8,220,618✔
566
  if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) {
8,220,618✔
567
    code = parseInsertSql(pCxt, pQuery, NULL, NULL);
8,016,447✔
568
  } else {
569
    code = parseSqlIntoAst(pCxt, pQuery);
212,952✔
570
  }
571
  terrno = code;
8,212,710✔
572
  return code;
8,225,863✔
573
}
574

575
static int32_t parseQuerySyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
508,847,440✔
576
  SParseMetaCache metaCache = {0};
508,847,440✔
577
  int32_t         code = parseSqlSyntax(pCxt, pQuery, &metaCache);
508,850,105✔
578
  if (TSDB_CODE_SUCCESS == code) {
508,841,043✔
579
    code = buildCatalogReq(&metaCache, pCatalogReq);
494,340,301✔
580
  }
581
  destoryParseMetaCache(&metaCache, true);
508,851,548✔
582
  return code;
508,826,327✔
583
}
584

585
static int32_t parseCreateTbFromFileSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
3,088✔
586
  if (NULL == *pQuery) return parseQuerySyntax(pCxt, pQuery, pCatalogReq);
3,088✔
587

588
  return continueCreateTbFromFile(pCxt, pQuery);
1,544✔
589
}
590

591
int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
1,234,720,172✔
592
  int32_t code = nodesAcquireAllocator(pCxt->allocatorId);
1,234,720,172✔
593
  if (TSDB_CODE_SUCCESS == code) {
1,234,745,127✔
594
    if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) {
1,234,752,377✔
595
      code = parseInsertSql(pCxt, pQuery, pCatalogReq, NULL);
726,014,509✔
596
    } else if (qIsCreateTbFromFileSql(pCxt->pSql, pCxt->sqlLen)) {
508,868,618✔
597
      code = parseCreateTbFromFileSyntax(pCxt, pQuery, pCatalogReq);
3,088✔
598
    } else {
599
      code = parseQuerySyntax(pCxt, pQuery, pCatalogReq);
508,856,942✔
600
    }
601
  }
602
  (void)nodesReleaseAllocator(pCxt->allocatorId);
1,234,679,311✔
603
  terrno = code;
1,234,734,731✔
604
  return code;
1,234,800,792✔
605
}
606

607
int32_t qAnalyseSqlSemantic(SParseContext* pCxt, const struct SCatalogReq* pCatalogReq,
494,354,148✔
608
                            struct SMetaData* pMetaData, SQuery* pQuery) {
609
  SParseMetaCache metaCache = {0};
494,354,148✔
610
  int32_t         code = nodesAcquireAllocator(pCxt->allocatorId);
494,354,548✔
611
  if (TSDB_CODE_SUCCESS == code && pCatalogReq) {
494,362,484✔
612
    code = putMetaDataToCache(pCatalogReq, pMetaData, &metaCache);
494,362,667✔
613
  }
614
  if (TSDB_CODE_SUCCESS == code) {
494,358,183✔
615
    code = analyseSemantic(pCxt, pQuery, &metaCache);
494,359,069✔
616
  }
617
  (void)nodesReleaseAllocator(pCxt->allocatorId);
494,306,282✔
618
  destoryParseMetaCache(&metaCache, false);
494,349,858✔
619
  terrno = code;
494,328,723✔
620
  return code;
494,322,948✔
621
}
622

623
int32_t qContinueParseSql(SParseContext* pCxt, struct SCatalogReq* pCatalogReq, const struct SMetaData* pMetaData,
8,395,128✔
624
                          SQuery* pQuery) {
625
  return parseInsertSql(pCxt, &pQuery, pCatalogReq, pMetaData);
8,395,128✔
626
}
627

628
int32_t qContinueParsePostQuery(SParseContext* pCxt, SQuery* pQuery, SSDataBlock* pBlock) {
×
629
  int32_t code = TSDB_CODE_SUCCESS;
×
630
  switch (nodeType(pQuery->pRoot)) {
×
631
    default:
632
      break;
×
633
  }
634

635
  return code;
×
636
}
637

638
static void destoryTablesReq(void* p) {
1,489,002,154✔
639
  STablesReq* pRes = (STablesReq*)p;
1,489,002,154✔
640
  taosArrayDestroy(pRes->pTables);
1,489,002,154✔
641
}
1,489,014,444✔
642

643
void destoryCatalogReq(SCatalogReq* pCatalogReq) {
1,235,048,923✔
644
  if (NULL == pCatalogReq) {
1,235,048,923✔
645
    return;
338,488✔
646
  }
647
  taosArrayDestroy(pCatalogReq->pDbVgroup);
1,234,710,435✔
648
  taosArrayDestroy(pCatalogReq->pDbCfg);
1,234,761,328✔
649
  taosArrayDestroy(pCatalogReq->pDbInfo);
1,234,779,003✔
650
  if (pCatalogReq->cloned) {
1,234,771,183✔
651
    taosArrayDestroy(pCatalogReq->pTableMeta);
×
652
    taosArrayDestroy(pCatalogReq->pTableHash);
×
653
#ifdef TD_ENTERPRISE
654
    taosArrayDestroy(pCatalogReq->pView);
×
655
#endif
656
    taosArrayDestroy(pCatalogReq->pTableTSMAs);
×
657
    taosArrayDestroy(pCatalogReq->pTSMAs);
×
658
    taosArrayDestroy(pCatalogReq->pTableName);
×
659
  } else {
660
    taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq);
1,234,730,147✔
661
    taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq);
1,234,701,626✔
662
#ifdef TD_ENTERPRISE
663
    taosArrayDestroyEx(pCatalogReq->pView, destoryTablesReq);
1,234,765,012✔
664
#endif
665
    taosArrayDestroyEx(pCatalogReq->pTableTSMAs, destoryTablesReq);
1,234,765,577✔
666
    taosArrayDestroyEx(pCatalogReq->pTSMAs, destoryTablesReq);
1,234,759,923✔
667
    taosArrayDestroyEx(pCatalogReq->pTableName, destoryTablesReq);
1,234,753,698✔
668
  }
669
  taosArrayDestroy(pCatalogReq->pUdf);
1,234,748,030✔
670
  taosArrayDestroy(pCatalogReq->pIndex);
1,234,760,820✔
671
  taosArrayDestroy(pCatalogReq->pUser);
1,234,756,040✔
672
  taosArrayDestroy(pCatalogReq->pTableIndex);
1,234,738,090✔
673
  taosArrayDestroy(pCatalogReq->pTableCfg);
1,234,748,702✔
674
  taosArrayDestroy(pCatalogReq->pTableTag);
1,234,744,475✔
675
  taosArrayDestroy(pCatalogReq->pVStbRefDbs);
1,234,732,540✔
676
}
677

678
void tfreeSParseQueryRes(void* p) {
332,944✔
679
  if (NULL == p) {
332,944✔
680
    return;
×
681
  }
682

683
  SParseQueryRes* pRes = p;
332,944✔
684
  destoryCatalogReq(pRes->pCatalogReq);
332,944✔
685
  taosMemoryFree(pRes->pCatalogReq);
332,944✔
686
  catalogFreeMetaData(&pRes->meta);
332,944✔
687
}
688

689
void qDestroyParseContext(SParseContext* pCxt) {
1,234,688,960✔
690
  if (NULL == pCxt) {
1,234,688,960✔
691
    return;
×
692
  }
693

694
  taosArrayDestroyEx(pCxt->pSubMetaList, tfreeSParseQueryRes);
1,234,688,960✔
695
  taosArrayDestroy(pCxt->pTableMetaPos);
1,234,767,371✔
696
  taosArrayDestroy(pCxt->pTableVgroupPos);
1,234,772,000✔
697
  taosMemoryFree(pCxt);
1,234,769,775✔
698
}
699

700
void qDestroyQuery(SQuery* pQueryNode) { nodesDestroyNode((SNode*)pQueryNode); }
1,453,595,824✔
701

702
int32_t qExtractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema) {
125,951✔
703
  return extractResultSchema(pRoot, numOfCols, pSchema, NULL);
125,951✔
704
}
705

706
int32_t qSetSTableIdForRsma(SNode* pStmt, int64_t uid) {
×
707
  if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
×
708
    SNode* pTable = ((SSelectStmt*)pStmt)->pFromTable;
×
709
    if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) {
×
710
      ((SRealTableNode*)pTable)->pMeta->uid = uid;
×
711
      ((SRealTableNode*)pTable)->pMeta->suid = uid;
×
712
      return TSDB_CODE_SUCCESS;
×
713
    }
714
  }
715
  return TSDB_CODE_FAILED;
×
716
}
717

718
int32_t qInitKeywordsTable() { return taosInitKeywordsTable(); }
1,645,671✔
719

720
void qCleanupKeywordsTable() { taosCleanupKeywordsTable(); }
1,626,138✔
721

722
int32_t qStmtBindParams(SQuery* pQuery, TAOS_MULTI_BIND* pParams, int32_t colIdx, void *charsetCxt) {
15,555✔
723
  int32_t code = TSDB_CODE_SUCCESS;
15,555✔
724

725
  if (colIdx < 0) {
15,555✔
726
    int32_t size = taosArrayGetSize(pQuery->pPlaceholderValues);
14,763✔
727
    for (int32_t i = 0; i < size; ++i) {
31,045✔
728
      code = setValueByBindParam((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, i), pParams + i, charsetCxt);
16,282✔
729
      if (TSDB_CODE_SUCCESS != code) {
16,282✔
730
        return code;
×
731
      }
732
    }
733
  } else {
734
    code = setValueByBindParam((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, colIdx), pParams, charsetCxt);
792✔
735
  }
736

737
  if (TSDB_CODE_SUCCESS == code && (colIdx < 0 || colIdx + 1 == pQuery->placeholderNum)) {
15,555✔
738
    nodesDestroyNode(pQuery->pRoot);
15,555✔
739
    pQuery->pRoot = NULL;
15,555✔
740
    code = nodesCloneNode(pQuery->pPrepareRoot, &pQuery->pRoot);
15,555✔
741
  }
742
  if (TSDB_CODE_SUCCESS == code) {
15,555✔
743
    rewriteExprAlias(pQuery->pRoot);
15,555✔
744
  }
745
  return code;
15,555✔
746
}
747

748
static int32_t setValueByBindParam2(SValueNode* pVal, TAOS_STMT2_BIND* pParam, void* charsetCxt) {
17,478✔
749
  if (!pParam || IS_NULL_TYPE(pParam->buffer_type)) {
17,478✔
750
    return TSDB_CODE_APP_ERROR;
×
751
  }
752
  if (IS_VAR_DATA_TYPE(pVal->node.resType.type) || pVal->node.resType.type == TSDB_DATA_TYPE_DECIMAL) {
17,478✔
753
    taosMemoryFreeClear(pVal->datum.p);
×
754
  }
755

756
  if (pParam->is_null && 1 == *(pParam->is_null)) {
17,478✔
757
    pVal->node.resType.type = TSDB_DATA_TYPE_NULL;
×
758
    pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
×
759
    return TSDB_CODE_SUCCESS;
×
760
  }
761

762
  int32_t inputSize = (NULL != pParam->length ? *(pParam->length) : tDataTypes[pParam->buffer_type].bytes);
17,478✔
763
  pVal->node.resType.type = pParam->buffer_type;
17,478✔
764
  pVal->node.resType.bytes = inputSize;
17,478✔
765

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

812
      int32_t output = 0;
×
813
      if (!taosMbsToUcs4(pParam->buffer, inputSize, (TdUcs4*)varDataVal(pVal->datum.p), pVal->node.resType.bytes,
×
814
                         &output, charsetCxt)) {
815
        return terrno;
×
816
      }
817
      varDataSetLen(pVal->datum.p, output);
×
818
      pVal->node.resType.bytes = output + VARSTR_HEADER_SIZE;
×
819
      break;
×
820
    }
821
    case TSDB_DATA_TYPE_DECIMAL64: {
198✔
822
      // TSDB_DATA_TYPE_DECIMAL64: buffer may be string, need to convert to int64_t
823
      // If buffer is string, convert it to decimal64 value first
824
      if (pParam->length && *(pParam->length) > 0 && *(pParam->length) != sizeof(int64_t)) {
198✔
825
        // Buffer is string, need to convert
826
        uint8_t precision = pVal->node.resType.precision;
198✔
827
        uint8_t scale = pVal->node.resType.scale;
198✔
828
        // If precision/scale not set, use default (should not happen in normal case)
829
        if (precision == 0 && scale == 0) {
198✔
830
          precision = 18;
198✔
831
          scale = 0;
198✔
832
        }
833
        Decimal64 dec = {0};
198✔
834
        int32_t   code = decimal64FromStr((const char*)pParam->buffer, *(pParam->length), precision, scale, &dec);
198✔
835
        if (code != TSDB_CODE_SUCCESS) {
198✔
836
          return code;
×
837
        }
838
        int64_t value = DECIMAL64_GET_VALUE(&dec);
198✔
839
        pVal->datum.i = value;
198✔
840
        pVal->typeData = value;
198✔
841
        pVal->node.resType.bytes = sizeof(int64_t);
198✔
842
      } else {
843
        // Buffer is already int64_t value, use it directly
844
        int32_t code = nodesSetValueNodeValue(pVal, pParam->buffer);
×
845
        if (code) {
×
846
          return code;
×
847
        }
848
      }
849
      break;
198✔
850
    }
851
    case TSDB_DATA_TYPE_DECIMAL: {
198✔
852
      // TSDB_DATA_TYPE_DECIMAL: buffer is string, need to convert to decimal128 binary format
853
      pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes;
198✔
854
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes);
198✔
855
      if (NULL == pVal->datum.p) {
198✔
856
        return terrno;
×
857
      }
858

859
      // Check if buffer is string or already binary format
860
      int32_t strLen = (pParam->length && *(pParam->length) > 0) ? *(pParam->length) : 0;
198✔
861
      if (strLen > 0 && strLen != pVal->node.resType.bytes) {
198✔
862
        // Buffer is string, need to convert to decimal128
863
        uint8_t precision = pVal->node.resType.precision;
198✔
864
        uint8_t scale = pVal->node.resType.scale;
198✔
865
        // If precision/scale not set, use default (should not happen in normal case)
866
        if (precision == 0 && scale == 0) {
198✔
867
          precision = 38;
198✔
868
          scale = 0;
198✔
869
        }
870
        Decimal128 dec = {0};
198✔
871
        int32_t    code = decimal128FromStr((const char*)pParam->buffer, strLen, precision, scale, &dec);
198✔
872
        if (code != TSDB_CODE_SUCCESS) {
198✔
873
          taosMemoryFree(pVal->datum.p);
×
874
          pVal->datum.p = NULL;
×
875
          return code;
×
876
        }
877
        // Copy decimal128 binary data
878
        memcpy(pVal->datum.p, &dec, sizeof(Decimal128));
198✔
879
      } else {
880
        // Buffer is already binary format, copy directly
881
        memcpy(pVal->datum.p, pParam->buffer, pVal->node.resType.bytes);
×
882
      }
883
      break;
198✔
884
    }
885
    case TSDB_DATA_TYPE_BLOB:
×
886
    case TSDB_DATA_TYPE_MEDIUMBLOB:
887
      return TSDB_CODE_BLOB_NOT_SUPPORT;  // BLOB data type is not supported in stmt2
×
888
    default: {
13,518✔
889
      int32_t code = nodesSetValueNodeValue(pVal, pParam->buffer);
13,518✔
890
      if (code) {
13,518✔
891
        return code;
×
892
      }
893
      break;
13,518✔
894
    }
895
  }
896
  pVal->translate = true;
17,478✔
897
  return TSDB_CODE_SUCCESS;
17,478✔
898
}
899

900
int32_t qStmtBindParams2(SQuery* pQuery, TAOS_STMT2_BIND* pParams, int32_t colIdx, void* charsetCxt) {
10,881✔
901
  int32_t code = TSDB_CODE_SUCCESS;
10,881✔
902

903
  if (colIdx < 0) {
10,881✔
904
    int32_t size = taosArrayGetSize(pQuery->pPlaceholderValues);
10,881✔
905
    for (int32_t i = 0; i < size; ++i) {
28,359✔
906
      code = setValueByBindParam2((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, i), pParams + i, charsetCxt);
17,478✔
907
      if (TSDB_CODE_SUCCESS != code) {
17,478✔
908
        return code;
×
909
      }
910
    }
911
  } else {
912
    code = setValueByBindParam2((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, colIdx), pParams, charsetCxt);
×
913
  }
914

915
  if (TSDB_CODE_SUCCESS == code && (colIdx < 0 || colIdx + 1 == pQuery->placeholderNum)) {
10,881✔
916
    nodesDestroyNode(pQuery->pRoot);
10,881✔
917
    pQuery->pRoot = NULL;
10,881✔
918
    code = nodesCloneNode(pQuery->pPrepareRoot, &pQuery->pRoot);
10,881✔
919
  }
920
  if (TSDB_CODE_SUCCESS == code) {
10,881✔
921
    rewriteExprAlias(pQuery->pRoot);
10,881✔
922
  }
923
  return code;
10,881✔
924
}
925

926
int32_t qStmtParseQuerySql(SParseContext* pCxt, SQuery* pQuery, SMetaData* pMetaData) {
26,436✔
927
  SParseMetaCache metaCache = {0};
26,436✔
928
  int32_t         code = TSDB_CODE_SUCCESS;
26,436✔
929

930
  // If metaData is provided, we need to collect metadata keys first to build SCatalogReq
931
  // Then put the metaData into cache
932
  if (pMetaData) {
26,436✔
933
    SCatalogReq catalogReq = {0};
10,881✔
934
    // After collectMetaKey/buildCatalogReq, metaCache contains "request/reserved" hashes.
935
    // We must clear them before putMetaDataToCache, otherwise the hash ends up mixed
936
    // (db-keyed request entries + tb-keyed metadata entries) and destoryParseMetaCache(false)
937
    // will not release nested request hashes (leading to LeakSanitizer reports).
938
    bool metaCacheIsRequest = true;
10,881✔
939
    // Collect metadata requirements from query
940
    code = collectMetaKey(pCxt, pQuery, &metaCache);
10,881✔
941
    if (TSDB_CODE_SUCCESS == code) {
10,881✔
942
      // Build catalog request from collected metadata requirements
943
      code = buildCatalogReq(&metaCache, &catalogReq);
10,881✔
944
    }
945
    if (TSDB_CODE_SUCCESS == code) {
10,881✔
946
      // Switch metaCache from request-mode to metadata-mode.
947
      destoryParseMetaCache(&metaCache, true);
10,881✔
948
      (void)memset(&metaCache, 0, sizeof(metaCache));
10,881✔
949
      metaCacheIsRequest = false;
10,881✔
950

951
      // Put metadata to cache using the catalogReq to match data
952
      code = putMetaDataToCache(&catalogReq, pMetaData, &metaCache);
10,881✔
953
    }
954
    // Clean up catalog request
955
    destoryCatalogReq(&catalogReq);
10,881✔
956
    if (TSDB_CODE_SUCCESS != code) {
10,881✔
957
      destoryParseMetaCache(&metaCache, metaCacheIsRequest);
×
958
      return code;
×
959
    }
960
  }
961

962
  code = translate(pCxt, pQuery, &metaCache);
26,436✔
963
  if (TSDB_CODE_SUCCESS == code) {
26,436✔
964
    code = calculateConstant(pCxt, pQuery);
26,238✔
965
  }
966
  destoryParseMetaCache(&metaCache, false);
26,436✔
967
  return code;
26,436✔
968
}
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