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

taosdata / TDengine / #3660

15 Mar 2025 09:06AM UTC coverage: 62.039% (-1.3%) from 63.314%
#3660

push

travis-ci

web-flow
feat(stream): support stream processing for virtual tables (#30144)

* enh: add client processing

* enh: add mnode vtables processing

* enh: add mnode vtable processing

* enh: add normal child vtable support

* fix: compile issues

* fix: compile issues

* fix: create stream issues

* fix: multi stream scan issue

* fix: remove debug info

* fix: agg task and task level issues

* fix: correct task output type

* fix: split vtablescan from agg

* fix: memory leak issues

* fix: add limitations

* Update 09-error-code.md

* Update 09-error-code.md

* fix: remove usless case

* feat(stream): extract original table data in source scan task

Implemented functionality in the source task to extract data
corresponding to the virtual table from the original table using WAL.
The extracted data is then sent to the downstream merge task for further
processing.

* feat(stream): multi-way merge using loser tree in virtual merge task

Implemented multi-way merge in the merge task using a loser tree to
combine data from multiple original table into a single virtual table.
The merged virtual table data is then pushed downstream for further
processing.  Introduced memory limit handling during the merge process
with configurable behavior when the memory limit is reached.

* fix(test): remove useless cases

---------

Co-authored-by: dapan1121 <wpan@taosdata.com>
Co-authored-by: Pan Wei <72057773+dapan1121@users.noreply.github.com>

154078 of 317582 branches covered (48.52%)

Branch coverage included in aggregate %.

313 of 2391 new or added lines in 34 files covered. (13.09%)

26134 existing lines in 205 files now uncovered.

240261 of 318051 relevant lines covered (75.54%)

16655189.27 hits per line

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

57.69
/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 "parInt.h"
20
#include "parToken.h"
21

22
bool qIsInsertValuesSql(const char* pStr, size_t length) {
21,475,514✔
23
  if (NULL == pStr) {
21,475,514!
24
    return false;
×
25
  }
26

27
  const char* pSql = pStr;
21,475,514✔
28

29
  int32_t index = 0;
21,475,514✔
30
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
21,475,514✔
31
  if (TK_INSERT != t.type && TK_IMPORT != t.type) {
21,501,920✔
32
    return false;
2,351,975✔
33
  }
34

35
  do {
36
    pStr += index;
77,475,477✔
37
    index = 0;
77,475,477✔
38
    t = tStrGetToken((char*)pStr, &index, false, NULL);
77,475,477✔
39
    if (TK_USING == t.type || TK_VALUES == t.type || TK_FILE == t.type) {
77,426,225!
40
      return true;
19,100,418✔
41
    } else if (TK_SELECT == t.type) {
58,325,807✔
42
      return false;
251✔
43
    }
44
    if (0 == t.type || 0 == t.n) {
58,325,556!
45
      break;
46
    }
47
  } while (pStr - pSql < length);
58,325,772✔
48
  return false;
24✔
49
}
50

51
bool qIsCreateTbFromFileSql(const char* pStr, size_t length) {
1,179,323✔
52
  if (NULL == pStr) {
1,179,323!
53
    return false;
×
54
  }
55

56
  const char* pSql = pStr;
1,179,323✔
57

58
  int32_t index = 0;
1,179,323✔
59
  SToken  t = tStrGetToken((char*)pStr, &index, false, NULL);
1,179,323✔
60
  if (TK_CREATE != t.type) {
1,179,356✔
61
    return false;
1,101,136✔
62
  }
63

64
  do {
65
    pStr += index;
2,266,895✔
66
    index = 0;
2,266,895✔
67
    t = tStrGetToken((char*)pStr, &index, false, NULL);
2,266,895✔
68
    if (TK_FILE == t.type) {
2,266,895!
69
      return true;
×
70
    }
71
    if (0 == t.type || 0 == t.n) {
2,266,895✔
72
      break;
73
    }
74
  } while (pStr - pSql < length);
2,188,700✔
75
  return false;
78,220✔
76
}
77

78
bool qParseDbName(const char* pStr, size_t length, char** pDbName) {
10,585✔
79
  (void)length;
80
  int32_t index = 0;
10,585✔
81
  SToken  t;
82

83
  if (NULL == pStr) {
10,585!
84
    *pDbName = NULL;
×
85
    return false;
×
86
  }
87

88
  t = tStrGetToken((char*)pStr, &index, false, NULL);
10,585✔
89
  if (TK_INSERT != t.type && TK_IMPORT != t.type) {
10,586!
90
    *pDbName = NULL;
72✔
91
    return false;
72✔
92
  }
93

94
  t = tStrGetToken((char*)pStr, &index, false, NULL);
10,514✔
95
  if (TK_INTO != t.type) {
10,516!
96
    *pDbName = NULL;
×
97
    return false;
×
98
  }
99

100
  t = tStrGetToken((char*)pStr, &index, false, NULL);
10,516✔
101
  if (t.n == 0 || t.z == NULL) {
10,516!
102
    *pDbName = NULL;
1✔
103
    return false;
1✔
104
  }
105
  char* dotPos = strnchr(t.z, '.', t.n, true);
10,515✔
106
  if (dotPos != NULL) {
10,513✔
107
    int dbNameLen = dotPos - t.z;
5✔
108
    *pDbName = taosMemoryMalloc(dbNameLen + 1);
5!
109
    if (*pDbName == NULL) {
3!
110
      return false;
×
111
    }
112
    strncpy(*pDbName, t.z, dbNameLen);
3✔
113
    (*pDbName)[dbNameLen] = '\0';
3✔
114
    return true;
3✔
115
  }
116
  return false;
10,508✔
117
}
118

119
static int32_t analyseSemantic(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
1,155,337✔
120
  int32_t code = authenticate(pCxt, pQuery, pMetaCache);
1,155,337✔
121

122
  if (pCxt->parseOnly) {
1,155,326✔
123
    return code;
620✔
124
  }
125

126
  if (TSDB_CODE_SUCCESS == code && pQuery->placeholderNum > 0) {
1,154,706✔
127
    TSWAP(pQuery->pPrepareRoot, pQuery->pRoot);
6✔
128
    return TSDB_CODE_SUCCESS;
6✔
129
  }
130

131
  if (TSDB_CODE_SUCCESS == code) {
1,154,700✔
132
    code = translate(pCxt, pQuery, pMetaCache);
1,154,349✔
133
  }
134
  if (TSDB_CODE_SUCCESS == code) {
1,154,688✔
135
    code = calculateConstant(pCxt, pQuery);
1,082,848✔
136
  }
137
  return code;
1,154,617✔
138
}
139

140
static int32_t parseSqlIntoAst(SParseContext* pCxt, SQuery** pQuery) {
703✔
141
  int32_t code = parse(pCxt, pQuery);
703✔
142
  if (TSDB_CODE_SUCCESS == code) {
703✔
143
    code = analyseSemantic(pCxt, *pQuery, NULL);
697✔
144
  }
145
  return code;
703✔
146
}
147

148
static int32_t parseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, SParseMetaCache* pMetaCache) {
1,179,313✔
149
  int32_t code = parse(pCxt, pQuery);
1,179,313✔
150
  if (TSDB_CODE_SUCCESS == code) {
1,179,282✔
151
    code = collectMetaKey(pCxt, *pQuery, pMetaCache);
1,154,072✔
152
  }
153
  return code;
1,179,323✔
154
}
155

156
static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam, void *charsetCxt) {
11✔
157
  if (!pParam || IS_NULL_TYPE(pParam->buffer_type)) {
11!
158
    return TSDB_CODE_APP_ERROR;
×
159
  }
160
  if (IS_VAR_DATA_TYPE(pVal->node.resType.type)) {
11!
UNCOV
161
    taosMemoryFreeClear(pVal->datum.p);
×
162
  }
163

164
  if (pParam->is_null && 1 == *(pParam->is_null)) {
11!
UNCOV
165
    pVal->node.resType.type = TSDB_DATA_TYPE_NULL;
×
UNCOV
166
    pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
×
UNCOV
167
    return TSDB_CODE_SUCCESS;
×
168
  }
169

170
  int32_t inputSize = (NULL != pParam->length ? *(pParam->length) : tDataTypes[pParam->buffer_type].bytes);
11!
171
  pVal->node.resType.type = pParam->buffer_type;
11✔
172
  pVal->node.resType.bytes = inputSize;
11✔
173

174
  switch (pParam->buffer_type) {
11!
UNCOV
175
    case TSDB_DATA_TYPE_VARBINARY:
×
UNCOV
176
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
UNCOV
177
      if (NULL == pVal->datum.p) {
×
178
        return terrno;
×
179
      }
UNCOV
180
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
×
UNCOV
181
      memcpy(varDataVal(pVal->datum.p), pParam->buffer, pVal->node.resType.bytes);
×
UNCOV
182
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
×
UNCOV
183
      break;
×
184
    case TSDB_DATA_TYPE_VARCHAR:
2✔
185
    case TSDB_DATA_TYPE_GEOMETRY:
186
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
2!
187
      if (NULL == pVal->datum.p) {
2!
188
        return terrno;
×
189
      }
190
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
2✔
191
      strncpy(varDataVal(pVal->datum.p), (const char*)pParam->buffer, pVal->node.resType.bytes);
2✔
192
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
2✔
193
      break;
2✔
UNCOV
194
    case TSDB_DATA_TYPE_NCHAR: {
×
UNCOV
195
      pVal->node.resType.bytes *= TSDB_NCHAR_SIZE;
×
UNCOV
196
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
UNCOV
197
      if (NULL == pVal->datum.p) {
×
198
        return terrno;
×
199
      }
200

UNCOV
201
      int32_t output = 0;
×
UNCOV
202
      if (!taosMbsToUcs4(pParam->buffer, inputSize, (TdUcs4*)varDataVal(pVal->datum.p), pVal->node.resType.bytes,
×
203
                         &output, charsetCxt)) {
204
        return terrno;
×
205
      }
UNCOV
206
      varDataSetLen(pVal->datum.p, output);
×
UNCOV
207
      pVal->node.resType.bytes = output + VARSTR_HEADER_SIZE;
×
UNCOV
208
      break;
×
209
    }
210
    default: {
9✔
211
      int32_t code = nodesSetValueNodeValue(pVal, pParam->buffer);
9✔
212
      if (code) {
9!
213
        return code;
×
214
      }
215
      break;
9✔
216
    }
217
  }
218
  pVal->translate = true;
11✔
219
  return TSDB_CODE_SUCCESS;
11✔
220
}
221

222
static EDealRes rewriteQueryExprAliasImpl(SNode* pNode, void* pContext) {
60✔
223
  if (nodesIsExprNode(pNode) && QUERY_NODE_COLUMN != nodeType(pNode)) {
60✔
224
    snprintf(((SExprNode*)pNode)->aliasName, TSDB_COL_NAME_LEN, "#%d", *(int32_t*)pContext);
23✔
225
    ++(*(int32_t*)pContext);
23✔
226
  }
227
  return DEAL_RES_CONTINUE;
60✔
228
}
229

230
static void rewriteQueryExprAlias(SNode* pRoot, int32_t* pNo) {
8✔
231
  switch (nodeType(pRoot)) {
8!
232
    case QUERY_NODE_SELECT_STMT:
8✔
233
      nodesWalkSelectStmt((SSelectStmt*)pRoot, SQL_CLAUSE_FROM, rewriteQueryExprAliasImpl, pNo);
8✔
234
      break;
8✔
235
    case QUERY_NODE_SET_OPERATOR: {
×
236
      SSetOperator* pSetOper = (SSetOperator*)pRoot;
×
237
      rewriteQueryExprAlias(pSetOper->pLeft, pNo);
×
238
      rewriteQueryExprAlias(pSetOper->pRight, pNo);
×
239
      break;
×
240
    }
241
    default:
×
242
      break;
×
243
  }
244
}
8✔
245

246
static void rewriteExprAlias(SNode* pRoot) {
8✔
247
  int32_t no = 1;
8✔
248
  rewriteQueryExprAlias(pRoot, &no);
8✔
249
}
8✔
250

251
int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery) {
11,156✔
252
  int32_t code = TSDB_CODE_SUCCESS;
11,156✔
253
  if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) {
11,156✔
254
    code = parseInsertSql(pCxt, pQuery, NULL, NULL);
10,457✔
255
  } else {
256
    code = parseSqlIntoAst(pCxt, pQuery);
703✔
257
  }
258
  terrno = code;
11,159✔
259
  return code;
11,160✔
260
}
261

262
static int32_t parseQuerySyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
1,179,324✔
263
  SParseMetaCache metaCache = {0};
1,179,324✔
264
  int32_t         code = parseSqlSyntax(pCxt, pQuery, &metaCache);
1,179,324✔
265
  if (TSDB_CODE_SUCCESS == code) {
1,179,317✔
266
    code = buildCatalogReq(&metaCache, pCatalogReq);
1,154,106✔
267
  }
268
  destoryParseMetaCache(&metaCache, true);
1,179,336✔
269
  return code;
1,179,340✔
270
}
271

272
static int32_t parseCreateTbFromFileSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
×
273
  if (NULL == *pQuery) return parseQuerySyntax(pCxt, pQuery, pCatalogReq);
×
274

275
  return continueCreateTbFromFile(pCxt, pQuery);
×
276
}
277

278
int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq) {
10,720,489✔
279
  int32_t code = nodesAcquireAllocator(pCxt->allocatorId);
10,720,489✔
280
  if (TSDB_CODE_SUCCESS == code) {
10,721,980!
281
    if (qIsInsertValuesSql(pCxt->pSql, pCxt->sqlLen)) {
10,722,747✔
282
      code = parseInsertSql(pCxt, pQuery, pCatalogReq, NULL);
9,556,894✔
283
    } else if (qIsCreateTbFromFileSql(pCxt->pSql, pCxt->sqlLen)) {
1,178,854!
284
      code = parseCreateTbFromFileSyntax(pCxt, pQuery, pCatalogReq);
×
285
    } else {
286
      code = parseQuerySyntax(pCxt, pQuery, pCatalogReq);
1,179,357✔
287
    }
288
  }
289
  (void)nodesReleaseAllocator(pCxt->allocatorId);
10,644,839✔
290
  terrno = code;
10,683,728✔
291
  return code;
10,687,301✔
292
}
293

294
int32_t qAnalyseSqlSemantic(SParseContext* pCxt, const struct SCatalogReq* pCatalogReq,
1,154,636✔
295
                            struct SMetaData* pMetaData, SQuery* pQuery) {
296
  SParseMetaCache metaCache = {0};
1,154,636✔
297
  int32_t         code = nodesAcquireAllocator(pCxt->allocatorId);
1,154,636✔
298
  if (TSDB_CODE_SUCCESS == code && pCatalogReq) {
1,154,626!
299
    code = putMetaDataToCache(pCatalogReq, pMetaData, &metaCache);
1,154,628✔
300
  }
301
  if (TSDB_CODE_SUCCESS == code) {
1,154,643!
302
    code = analyseSemantic(pCxt, pQuery, &metaCache);
1,154,645✔
303
  }
304
  (void)nodesReleaseAllocator(pCxt->allocatorId);
1,154,518✔
305
  destoryParseMetaCache(&metaCache, false);
1,154,593✔
306
  terrno = code;
1,154,627✔
307
  return code;
1,154,616✔
308
}
309

310
int32_t qContinueParseSql(SParseContext* pCxt, struct SCatalogReq* pCatalogReq, const struct SMetaData* pMetaData,
67,782✔
311
                          SQuery* pQuery) {
312
  return parseInsertSql(pCxt, &pQuery, pCatalogReq, pMetaData);
67,782✔
313
}
314

315
int32_t qContinueParsePostQuery(SParseContext* pCxt, SQuery* pQuery, SSDataBlock* pBlock) {
489✔
316
  int32_t code = TSDB_CODE_SUCCESS;
489✔
317
  switch (nodeType(pQuery->pRoot)) {
489!
318
    case QUERY_NODE_CREATE_STREAM_STMT: {
265✔
319
      code = translatePostCreateStream(pCxt, pQuery, pBlock);
265✔
320
      break;
265✔
321
    }
UNCOV
322
    case QUERY_NODE_CREATE_INDEX_STMT: {
×
UNCOV
323
      code = translatePostCreateSmaIndex(pCxt, pQuery, pBlock);
×
UNCOV
324
      break;
×
325
    }
326
    case QUERY_NODE_CREATE_TSMA_STMT: {
224✔
327
      code = translatePostCreateTSMA(pCxt, pQuery, pBlock);
224✔
328
      break;
224✔
329
    }
330
    default:
×
331
      break;
×
332
  }
333

334
  return code;
489✔
335
}
336

337
static void destoryTablesReq(void* p) {
3,944,384✔
338
  STablesReq* pRes = (STablesReq*)p;
3,944,384✔
339
  taosArrayDestroy(pRes->pTables);
3,944,384✔
340
}
3,944,406✔
341

342
void destoryCatalogReq(SCatalogReq* pCatalogReq) {
10,718,186✔
343
  if (NULL == pCatalogReq) {
10,718,186✔
344
    return;
620✔
345
  }
346
  taosArrayDestroy(pCatalogReq->pDbVgroup);
10,717,566✔
347
  taosArrayDestroy(pCatalogReq->pDbCfg);
10,714,447✔
348
  taosArrayDestroy(pCatalogReq->pDbInfo);
10,720,756✔
349
  if (pCatalogReq->cloned) {
10,724,187✔
350
    taosArrayDestroy(pCatalogReq->pTableMeta);
514✔
351
    taosArrayDestroy(pCatalogReq->pTableHash);
514✔
352
#ifdef TD_ENTERPRISE
353
    taosArrayDestroy(pCatalogReq->pView);
514✔
354
#endif
355
    taosArrayDestroy(pCatalogReq->pTableTSMAs);
514✔
356
    taosArrayDestroy(pCatalogReq->pTSMAs);
514✔
357
    taosArrayDestroy(pCatalogReq->pTableName);
514✔
358
  } else {
359
    taosArrayDestroyEx(pCatalogReq->pTableMeta, destoryTablesReq);
10,723,673✔
360
    taosArrayDestroyEx(pCatalogReq->pTableHash, destoryTablesReq);
10,711,307✔
361
#ifdef TD_ENTERPRISE
362
    taosArrayDestroyEx(pCatalogReq->pView, destoryTablesReq);
10,717,562✔
363
#endif
364
    taosArrayDestroyEx(pCatalogReq->pTableTSMAs, destoryTablesReq);
10,725,468✔
365
    taosArrayDestroyEx(pCatalogReq->pTSMAs, destoryTablesReq);
10,731,021✔
366
    taosArrayDestroyEx(pCatalogReq->pTableName, destoryTablesReq);
10,731,935✔
367
  }
368
  taosArrayDestroy(pCatalogReq->pUdf);
10,732,371✔
369
  taosArrayDestroy(pCatalogReq->pIndex);
10,728,035✔
370
  taosArrayDestroy(pCatalogReq->pUser);
10,727,077✔
371
  taosArrayDestroy(pCatalogReq->pTableIndex);
10,724,507✔
372
  taosArrayDestroy(pCatalogReq->pTableCfg);
10,722,156✔
373
  taosArrayDestroy(pCatalogReq->pTableTag);
10,723,642✔
374
  taosArrayDestroy(pCatalogReq->pVSubTable);
10,726,677✔
375
}
376

377
void tfreeSParseQueryRes(void* p) {
620✔
378
  if (NULL == p) {
620!
379
    return;
×
380
  }
381

382
  SParseQueryRes* pRes = p;
620✔
383
  destoryCatalogReq(pRes->pCatalogReq);
620✔
384
  taosMemoryFree(pRes->pCatalogReq);
620!
385
  catalogFreeMetaData(&pRes->meta);
620✔
386
}
387

388
void qDestroyParseContext(SParseContext* pCxt) {
10,733,601✔
389
  if (NULL == pCxt) {
10,733,601!
390
    return;
×
391
  }
392

393
  taosArrayDestroyEx(pCxt->pSubMetaList, tfreeSParseQueryRes);
10,733,601✔
394
  taosArrayDestroy(pCxt->pTableMetaPos);
10,735,744✔
395
  taosArrayDestroy(pCxt->pTableVgroupPos);
10,734,374✔
396
  taosMemoryFree(pCxt);
10,732,962!
397
}
398

399
void qDestroyQuery(SQuery* pQueryNode) { nodesDestroyNode((SNode*)pQueryNode); }
10,916,248✔
400

401
int32_t qExtractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema) {
409✔
402
  return extractResultSchema(pRoot, numOfCols, pSchema, NULL);
409✔
403
}
404

405
int32_t qSetSTableIdForRsma(SNode* pStmt, int64_t uid) {
8✔
406
  if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
8!
407
    SNode* pTable = ((SSelectStmt*)pStmt)->pFromTable;
8✔
408
    if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) {
8!
409
      ((SRealTableNode*)pTable)->pMeta->uid = uid;
8✔
410
      ((SRealTableNode*)pTable)->pMeta->suid = uid;
8✔
411
      return TSDB_CODE_SUCCESS;
8✔
412
    }
413
  }
414
  return TSDB_CODE_FAILED;
×
415
}
416

417
int32_t qInitKeywordsTable() { return taosInitKeywordsTable(); }
15,947✔
418

419
void qCleanupKeywordsTable() { taosCleanupKeywordsTable(); }
15,720✔
420

421
int32_t qStmtBindParams(SQuery* pQuery, TAOS_MULTI_BIND* pParams, int32_t colIdx, void *charsetCxt) {
8✔
422
  int32_t code = TSDB_CODE_SUCCESS;
8✔
423

424
  if (colIdx < 0) {
8✔
425
    int32_t size = taosArrayGetSize(pQuery->pPlaceholderValues);
4✔
426
    for (int32_t i = 0; i < size; ++i) {
11✔
427
      code = setValueByBindParam((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, i), pParams + i, charsetCxt);
7✔
428
      if (TSDB_CODE_SUCCESS != code) {
7!
429
        return code;
×
430
      }
431
    }
432
  } else {
433
    code = setValueByBindParam((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, colIdx), pParams, charsetCxt);
4✔
434
  }
435

436
  if (TSDB_CODE_SUCCESS == code && (colIdx < 0 || colIdx + 1 == pQuery->placeholderNum)) {
8!
437
    nodesDestroyNode(pQuery->pRoot);
8✔
438
    pQuery->pRoot = NULL;
8✔
439
    code = nodesCloneNode(pQuery->pPrepareRoot, &pQuery->pRoot);
8✔
440
  }
441
  if (TSDB_CODE_SUCCESS == code) {
8!
442
    rewriteExprAlias(pQuery->pRoot);
8✔
443
  }
444
  return code;
8✔
445
}
446

447
static int32_t setValueByBindParam2(SValueNode* pVal, TAOS_STMT2_BIND* pParam, void* charsetCxt) {
×
448
  if (!pParam || IS_NULL_TYPE(pParam->buffer_type)) {
×
449
    return TSDB_CODE_APP_ERROR;
×
450
  }
451
  if (IS_VAR_DATA_TYPE(pVal->node.resType.type)) {
×
452
    taosMemoryFreeClear(pVal->datum.p);
×
453
  }
454

455
  if (pParam->is_null && 1 == *(pParam->is_null)) {
×
456
    pVal->node.resType.type = TSDB_DATA_TYPE_NULL;
×
457
    pVal->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes;
×
458
    return TSDB_CODE_SUCCESS;
×
459
  }
460

461
  int32_t inputSize = (NULL != pParam->length ? *(pParam->length) : tDataTypes[pParam->buffer_type].bytes);
×
462
  pVal->node.resType.type = pParam->buffer_type;
×
463
  pVal->node.resType.bytes = inputSize;
×
464

465
  switch (pParam->buffer_type) {
×
466
    case TSDB_DATA_TYPE_VARBINARY:
×
467
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
468
      if (NULL == pVal->datum.p) {
×
469
        return terrno;
×
470
      }
471
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
×
472
      memcpy(varDataVal(pVal->datum.p), pParam->buffer, pVal->node.resType.bytes);
×
473
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
×
474
      break;
×
475
    case TSDB_DATA_TYPE_VARCHAR:
×
476
    case TSDB_DATA_TYPE_GEOMETRY:
477
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
478
      if (NULL == pVal->datum.p) {
×
479
        return terrno;
×
480
      }
481
      varDataSetLen(pVal->datum.p, pVal->node.resType.bytes);
×
482
      strncpy(varDataVal(pVal->datum.p), (const char*)pParam->buffer, pVal->node.resType.bytes);
×
483
      pVal->node.resType.bytes += VARSTR_HEADER_SIZE;
×
484
      break;
×
485
    case TSDB_DATA_TYPE_NCHAR: {
×
486
      pVal->node.resType.bytes *= TSDB_NCHAR_SIZE;
×
487
      pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
×
488
      if (NULL == pVal->datum.p) {
×
489
        return terrno;
×
490
      }
491

492
      int32_t output = 0;
×
493
      if (!taosMbsToUcs4(pParam->buffer, inputSize, (TdUcs4*)varDataVal(pVal->datum.p), pVal->node.resType.bytes,
×
494
                         &output, charsetCxt)) {
495
        return terrno;
×
496
      }
497
      varDataSetLen(pVal->datum.p, output);
×
498
      pVal->node.resType.bytes = output + VARSTR_HEADER_SIZE;
×
499
      break;
×
500
    }
501
    default: {
×
502
      int32_t code = nodesSetValueNodeValue(pVal, pParam->buffer);
×
503
      if (code) {
×
504
        return code;
×
505
      }
506
      break;
×
507
    }
508
  }
509
  pVal->translate = true;
×
510
  return TSDB_CODE_SUCCESS;
×
511
}
512

513
int32_t qStmtBindParams2(SQuery* pQuery, TAOS_STMT2_BIND* pParams, int32_t colIdx, void* charsetCxt) {
×
514
  int32_t code = TSDB_CODE_SUCCESS;
×
515

516
  if (colIdx < 0) {
×
517
    int32_t size = taosArrayGetSize(pQuery->pPlaceholderValues);
×
518
    for (int32_t i = 0; i < size; ++i) {
×
519
      code = setValueByBindParam2((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, i), pParams + i, charsetCxt);
×
520
      if (TSDB_CODE_SUCCESS != code) {
×
521
        return code;
×
522
      }
523
    }
524
  } else {
525
    code = setValueByBindParam2((SValueNode*)taosArrayGetP(pQuery->pPlaceholderValues, colIdx), pParams, charsetCxt);
×
526
  }
527

528
  if (TSDB_CODE_SUCCESS == code && (colIdx < 0 || colIdx + 1 == pQuery->placeholderNum)) {
×
529
    nodesDestroyNode(pQuery->pRoot);
×
530
    pQuery->pRoot = NULL;
×
531
    code = nodesCloneNode(pQuery->pPrepareRoot, &pQuery->pRoot);
×
532
  }
533
  if (TSDB_CODE_SUCCESS == code) {
×
534
    rewriteExprAlias(pQuery->pRoot);
×
535
  }
536
  return code;
×
537
}
538

539
int32_t qStmtParseQuerySql(SParseContext* pCxt, SQuery* pQuery) {
8✔
540
  int32_t code = translate(pCxt, pQuery, NULL);
8✔
541
  if (TSDB_CODE_SUCCESS == code) {
8!
542
    code = calculateConstant(pCxt, pQuery);
8✔
543
  }
544
  return code;
8✔
545
}
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