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

taosdata / TDengine / #3610

12 Feb 2025 09:54AM UTC coverage: 54.713% (-8.4%) from 63.066%
#3610

push

travis-ci

web-flow
Merge pull request #29745 from taosdata/fix/TD33664-3.0

fix: --version show information check for 3.0

120957 of 286549 branches covered (42.21%)

Branch coverage included in aggregate %.

190849 of 283342 relevant lines covered (67.36%)

4969786.97 hits per line

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

50.54
/source/client/src/clientStmt.c
1

2
#include "clientInt.h"
3
#include "clientLog.h"
4
#include "tdef.h"
5

6
#include "clientStmt.h"
7

8
char* gStmtStatusStr[] = {"unknown",     "init", "prepare", "settbname", "settags",
9
                          "fetchFields", "bind", "bindCol", "addBatch",  "exec"};
10

11
static FORCE_INLINE int32_t stmtAllocQNodeFromBuf(STableBufInfo* pTblBuf, void** pBuf) {
12
  if (pTblBuf->buffOffset < pTblBuf->buffSize) {
37,803✔
13
    *pBuf = (char*)pTblBuf->pCurBuff + pTblBuf->buffOffset;
37,809✔
14
    pTblBuf->buffOffset += pTblBuf->buffUnit;
37,809✔
15
  } else if (pTblBuf->buffIdx < taosArrayGetSize(pTblBuf->pBufList)) {
×
16
    pTblBuf->pCurBuff = taosArrayGetP(pTblBuf->pBufList, pTblBuf->buffIdx++);
×
17
    if (NULL == pTblBuf->pCurBuff) {
×
18
      return TAOS_GET_TERRNO(terrno);
×
19
    }
20
    *pBuf = pTblBuf->pCurBuff;
×
21
    pTblBuf->buffOffset = pTblBuf->buffUnit;
×
22
  } else {
23
    void* buff = taosMemoryMalloc(pTblBuf->buffSize);
×
24
    if (NULL == buff) {
×
25
      return terrno;
×
26
    }
27

28
    if (taosArrayPush(pTblBuf->pBufList, &buff) == NULL) {
×
29
      return terrno;
×
30
    }
31

32
    pTblBuf->buffIdx++;
×
33
    pTblBuf->pCurBuff = buff;
×
34
    *pBuf = buff;
×
35
    pTblBuf->buffOffset = pTblBuf->buffUnit;
×
36
  }
37

38
  return TSDB_CODE_SUCCESS;
37,809✔
39
}
40

41
bool stmtDequeue(STscStmt* pStmt, SStmtQNode** param) {
38,080✔
42
  (void)taosThreadMutexLock(&pStmt->queue.mutex);
38,080✔
43
  while (0 == atomic_load_64((int64_t*)&pStmt->queue.qRemainNum)) {
58,021✔
44
    (void)taosThreadCondWait(&pStmt->queue.waitCond, &pStmt->queue.mutex);
19,961✔
45
    if (atomic_load_8((int8_t*)&pStmt->queue.stopQueue)) {
19,940✔
46
      (void)taosThreadMutexUnlock(&pStmt->queue.mutex);
47✔
47
      return false;
47✔
48
    }
49
  }
50
  SStmtQNode* orig = pStmt->queue.head;
37,838✔
51
  SStmtQNode* node = pStmt->queue.head->next;
37,838✔
52
  pStmt->queue.head = pStmt->queue.head->next;
37,838✔
53
  *param = node;
37,838✔
54

55
  (void)atomic_sub_fetch_64((int64_t*)&pStmt->queue.qRemainNum, 1);
37,838✔
56
  (void)taosThreadMutexUnlock(&pStmt->queue.mutex);
38,094✔
57

58

59
  *param = node;
38,061✔
60

61
  return true;
38,061✔
62
}
63

64
void stmtEnqueue(STscStmt* pStmt, SStmtQNode* param) {
38,080✔
65
  (void)taosThreadMutexLock(&pStmt->queue.mutex);
38,080✔
66

67
  pStmt->queue.tail->next = param;
38,104✔
68
  pStmt->queue.tail = param;
38,104✔
69

70
  pStmt->stat.bindDataNum++;
38,104✔
71
  (void)atomic_add_fetch_64(&pStmt->queue.qRemainNum, 1);
38,104✔
72
  (void)taosThreadCondSignal(&(pStmt->queue.waitCond));
38,093✔
73

74
  (void)taosThreadMutexUnlock(&pStmt->queue.mutex);
38,025✔
75
}
38,078✔
76

77
static int32_t stmtCreateRequest(STscStmt* pStmt) {
910,503✔
78
  int32_t code = 0;
910,503✔
79

80
  if (pStmt->exec.pRequest == NULL) {
910,503✔
81
    code = buildRequest(pStmt->taos->id, pStmt->sql.sqlStr, pStmt->sql.sqlLen, NULL, false, &pStmt->exec.pRequest,
457✔
82
                        pStmt->reqid);
83
    if (pStmt->reqid != 0) {
460!
84
      pStmt->reqid++;
×
85
    }
86
    if (TSDB_CODE_SUCCESS == code) {
460✔
87
      pStmt->exec.pRequest->syncQuery = true;
459✔
88
      pStmt->exec.pRequest->isStmtBind = true;
459✔
89
    }
90
  }
91

92
  return code;
910,506✔
93
}
94

95
int32_t stmtSwitchStatus(STscStmt* pStmt, STMT_STATUS newStatus) {
1,795,385✔
96
  int32_t code = 0;
1,795,385✔
97

98
  if (newStatus >= STMT_INIT && newStatus < STMT_MAX) {
1,795,385!
99
    STMT_LOG_SEQ(newStatus);
1,833,893✔
100
  }
101

102
  if (pStmt->errCode && newStatus != STMT_PREPARE) {
1,870,998!
103
    STMT_DLOG("stmt already failed with err: %s", tstrerror(pStmt->errCode));
×
104
    return pStmt->errCode;
×
105
  }
106

107
  switch (newStatus) {
1,870,998!
108
    case STMT_PREPARE:
382✔
109
      pStmt->errCode = 0;
382✔
110
      break;
382✔
111
    case STMT_SETTBNAME:
35,788✔
112
      if (STMT_STATUS_EQ(INIT)) {
35,788!
113
        code = TSDB_CODE_TSC_STMT_API_ERROR;
×
114
      }
115
      if (!pStmt->sql.stbInterlaceMode && (STMT_STATUS_EQ(BIND) || STMT_STATUS_EQ(BIND_COL))) {
35,788!
116
        code = TSDB_CODE_TSC_STMT_API_ERROR;
×
117
      }
118
      break;
35,788✔
119
    case STMT_SETTAGS:
1✔
120
      if (STMT_STATUS_NE(SETTBNAME) && STMT_STATUS_NE(FETCH_FIELDS)) {
1!
121
        code = TSDB_CODE_TSC_STMT_API_ERROR;
×
122
      }
123
      break;
1✔
124
    case STMT_FETCH_FIELDS:
×
125
      if (STMT_STATUS_EQ(INIT)) {
×
126
        code = TSDB_CODE_TSC_STMT_API_ERROR;
×
127
      }
128
      break;
×
129
    case STMT_BIND:
918,679✔
130
      if (STMT_STATUS_EQ(INIT) || STMT_STATUS_EQ(BIND_COL)) {
918,679!
131
        code = TSDB_CODE_TSC_STMT_API_ERROR;
×
132
      }
133
      /*
134
            if ((pStmt->sql.type == STMT_TYPE_MULTI_INSERT) && ()) {
135
              code = TSDB_CODE_TSC_STMT_API_ERROR;
136
            }
137
      */
138
      break;
918,679✔
139
    case STMT_BIND_COL:
×
140
      if (STMT_STATUS_EQ(INIT) || STMT_STATUS_EQ(BIND)) {
×
141
        code = TSDB_CODE_TSC_STMT_API_ERROR;
×
142
      }
143
      break;
×
144
    case STMT_ADD_BATCH:
913,231✔
145
      if (STMT_STATUS_NE(BIND) && STMT_STATUS_NE(BIND_COL) && STMT_STATUS_NE(FETCH_FIELDS)) {
913,231!
146
        code = TSDB_CODE_TSC_STMT_API_ERROR;
×
147
      }
148
      break;
913,231✔
149
    case STMT_EXECUTE:
2,917✔
150
      if (STMT_TYPE_QUERY == pStmt->sql.type) {
2,917✔
151
        if (STMT_STATUS_NE(ADD_BATCH) && STMT_STATUS_NE(FETCH_FIELDS) && STMT_STATUS_NE(BIND) &&
3!
152
            STMT_STATUS_NE(BIND_COL)) {
×
153
          code = TSDB_CODE_TSC_STMT_API_ERROR;
×
154
        }
155
      } else {
156
        if (STMT_STATUS_NE(ADD_BATCH) && STMT_STATUS_NE(FETCH_FIELDS)) {
2,914!
157
          code = TSDB_CODE_TSC_STMT_API_ERROR;
×
158
        }
159
      }
160
      break;
2,917✔
161
    default:
×
162
      code = TSDB_CODE_APP_ERROR;
×
163
      break;
×
164
  }
165

166
  STMT_ERR_RET(code);
1,870,998!
167

168
  pStmt->sql.status = newStatus;
1,870,998✔
169

170
  return TSDB_CODE_SUCCESS;
1,870,998✔
171
}
172

173
int32_t stmtGetTbName(TAOS_STMT* stmt, char** tbName) {
371✔
174
  STscStmt* pStmt = (STscStmt*)stmt;
371✔
175

176
  pStmt->sql.type = STMT_TYPE_MULTI_INSERT;
371✔
177

178
  if ('\0' == pStmt->bInfo.tbName[0]) {
371!
179
    tscError("no table name set");
×
180
    STMT_ERR_RET(TSDB_CODE_TSC_STMT_TBNAME_ERROR);
×
181
  }
182

183
  *tbName = pStmt->bInfo.tbName;
371✔
184

185
  return TSDB_CODE_SUCCESS;
371✔
186
}
187
/*
188
int32_t stmtBackupQueryFields(STscStmt* pStmt) {
189
  SStmtQueryResInfo* pRes = &pStmt->sql.queryRes;
190
  pRes->numOfCols = pStmt->exec.pRequest->body.resInfo.numOfCols;
191
  pRes->precision = pStmt->exec.pRequest->body.resInfo.precision;
192

193
  int32_t size = pRes->numOfCols * sizeof(TAOS_FIELD);
194
  pRes->fields = taosMemoryMalloc(size);
195
  if (pRes->fields == NULL) {
196
    STMT_ERR_RET(terrno);
197
  }
198

199
  pRes->userFields = taosMemoryMalloc(size);
200
  if (pRes->userFields == NULL) {
201
    taosMemoryFreeClear(pRes->fields);
202
    STMT_ERR_RET(terrno);
203
  }
204

205
  (void)memcpy(pRes->fields, pStmt->exec.pRequest->body.resInfo.fields, size);
206
  (void)memcpy(pRes->userFields, pStmt->exec.pRequest->body.resInfo.userFields, size);
207

208
  return TSDB_CODE_SUCCESS;
209
}
210

211
int32_t stmtRestoreQueryFields(STscStmt* pStmt) {
212
  SStmtQueryResInfo* pRes = &pStmt->sql.queryRes;
213
  int32_t            size = pRes->numOfCols * sizeof(TAOS_FIELD);
214

215
  pStmt->exec.pRequest->body.resInfo.numOfCols = pRes->numOfCols;
216
  pStmt->exec.pRequest->body.resInfo.precision = pRes->precision;
217

218
  if (NULL == pStmt->exec.pRequest->body.resInfo.fields) {
219
    pStmt->exec.pRequest->body.resInfo.fields = taosMemoryMalloc(size);
220
    if (NULL == pStmt->exec.pRequest->body.resInfo.fields) {
221
      STMT_ERR_RET(terrno);
222
    }
223
    (void)memcpy(pStmt->exec.pRequest->body.resInfo.fields, pRes->fields, size);
224
  }
225

226
  if (NULL == pStmt->exec.pRequest->body.resInfo.userFields) {
227
    pStmt->exec.pRequest->body.resInfo.userFields = taosMemoryMalloc(size);
228
    if (NULL == pStmt->exec.pRequest->body.resInfo.userFields) {
229
      STMT_ERR_RET(terrno);
230
    }
231
    (void)memcpy(pStmt->exec.pRequest->body.resInfo.userFields, pRes->userFields, size);
232
  }
233

234
  return TSDB_CODE_SUCCESS;
235
}
236
*/
237
int32_t stmtUpdateBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, SName* tbName, const char* sTableName,
371✔
238
                           bool autoCreateTbl) {
239
  STscStmt* pStmt = (STscStmt*)stmt;
371✔
240
  char      tbFName[TSDB_TABLE_FNAME_LEN];
241
  int32_t   code = tNameExtractFullName(tbName, tbFName);
371✔
242
  if (code != 0) {
373!
243
    return code;
×
244
  }
245

246
  (void)memcpy(&pStmt->bInfo.sname, tbName, sizeof(*tbName));
373✔
247
  tstrncpy(pStmt->bInfo.tbFName, tbFName, TSDB_TABLE_FNAME_LEN);
373✔
248
  pStmt->bInfo.tbFName[sizeof(pStmt->bInfo.tbFName) - 1] = 0;
373✔
249

250
  pStmt->bInfo.tbUid = autoCreateTbl ? 0 : pTableMeta->uid;
373✔
251
  pStmt->bInfo.tbSuid = pTableMeta->suid;
373✔
252
  pStmt->bInfo.tbVgId = pTableMeta->vgId;
373✔
253
  pStmt->bInfo.tbType = pTableMeta->tableType;
373✔
254
  pStmt->bInfo.boundTags = tags;
373✔
255
  pStmt->bInfo.tagsCached = false;
373✔
256
  tstrncpy(pStmt->bInfo.stbFName, sTableName, sizeof(pStmt->bInfo.stbFName));
373✔
257

258
  return TSDB_CODE_SUCCESS;
373✔
259
}
260

261
int32_t stmtUpdateExecInfo(TAOS_STMT* stmt, SHashObj* pVgHash, SHashObj* pBlockHash) {
362✔
262
  STscStmt* pStmt = (STscStmt*)stmt;
362✔
263

264
  pStmt->sql.pVgHash = pVgHash;
362✔
265
  pStmt->exec.pBlockHash = pBlockHash;
362✔
266

267
  return TSDB_CODE_SUCCESS;
362✔
268
}
269

270
int32_t stmtUpdateInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, SName* tbName, bool autoCreateTbl,
373✔
271
                       SHashObj* pVgHash, SHashObj* pBlockHash, const char* sTableName, bool preCtbname) {
272
  STscStmt* pStmt = (STscStmt*)stmt;
373✔
273

274
  STMT_ERR_RET(stmtUpdateBindInfo(stmt, pTableMeta, tags, tbName, sTableName, autoCreateTbl));
373!
275
  STMT_ERR_RET(stmtUpdateExecInfo(stmt, pVgHash, pBlockHash));
376!
276

277
  pStmt->sql.autoCreateTbl = autoCreateTbl;
368✔
278
  if (pStmt->sql.autoCreateTbl) {
368✔
279
    pStmt->sql.stbInterlaceMode = false;
16✔
280
  }
281

282
  return TSDB_CODE_SUCCESS;
368✔
283
}
284

285
int32_t stmtGetExecInfo(TAOS_STMT* stmt, SHashObj** pVgHash, SHashObj** pBlockHash) {
×
286
  STscStmt* pStmt = (STscStmt*)stmt;
×
287

288
  *pVgHash = pStmt->sql.pVgHash;
×
289
  pStmt->sql.pVgHash = NULL;
×
290

291
  *pBlockHash = pStmt->exec.pBlockHash;
×
292
  pStmt->exec.pBlockHash = NULL;
×
293

294
  return TSDB_CODE_SUCCESS;
×
295
}
296

297
int32_t stmtCacheBlock(STscStmt* pStmt) {
893,154✔
298
  if (pStmt->sql.type != STMT_TYPE_MULTI_INSERT) {
893,154✔
299
    return TSDB_CODE_SUCCESS;
14✔
300
  }
301

302
  uint64_t uid = pStmt->bInfo.tbUid;
893,140✔
303
  uint64_t cacheUid = (TSDB_CHILD_TABLE == pStmt->bInfo.tbType) ? pStmt->bInfo.tbSuid : uid;
893,140!
304

305
  if (taosHashGet(pStmt->sql.pTableCache, &cacheUid, sizeof(cacheUid))) {
893,140✔
306
    return TSDB_CODE_SUCCESS;
930,723✔
307
  }
308

309
  STableDataCxt** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
2,273✔
310
  if (!pSrc) {
322!
311
    return terrno;
×
312
  }
313
  STableDataCxt* pDst = NULL;
322✔
314

315
  STMT_ERR_RET(qCloneStmtDataBlock(&pDst, *pSrc, true));
322!
316

317
  SStmtTableCache cache = {
320✔
318
      .pDataCtx = pDst,
319
      .boundTags = pStmt->bInfo.boundTags,
320✔
320
  };
321

322
  if (taosHashPut(pStmt->sql.pTableCache, &cacheUid, sizeof(cacheUid), &cache, sizeof(cache))) {
320!
323
    return terrno;
×
324
  }
325

326
  if (pStmt->sql.autoCreateTbl) {
326✔
327
    pStmt->bInfo.tagsCached = true;
17✔
328
  } else {
329
    pStmt->bInfo.boundTags = NULL;
309✔
330
  }
331

332
  return TSDB_CODE_SUCCESS;
326✔
333
}
334

335
int32_t stmtParseSql(STscStmt* pStmt) {
375✔
336
  pStmt->exec.pCurrBlock = NULL;
375✔
337

338
  SStmtCallback stmtCb = {
375✔
339
      .pStmt = pStmt,
340
      .getTbNameFn = stmtGetTbName,
341
      .setInfoFn = stmtUpdateInfo,
342
      .getExecInfoFn = stmtGetExecInfo,
343
  };
344

345
  STMT_ERR_RET(stmtCreateRequest(pStmt));
375!
346

347
  pStmt->stat.parseSqlNum++;
377✔
348
  STMT_ERR_RET(parseSql(pStmt->exec.pRequest, false, &pStmt->sql.pQuery, &stmtCb));
377✔
349
  pStmt->sql.siInfo.pQuery = pStmt->sql.pQuery;
375✔
350

351
  pStmt->bInfo.needParse = false;
375✔
352

353
  if (pStmt->sql.pQuery->pRoot && 0 == pStmt->sql.type) {
375✔
354
    pStmt->sql.type = STMT_TYPE_INSERT;
3✔
355
    pStmt->sql.stbInterlaceMode = false;
3✔
356
  } else if (pStmt->sql.pQuery->pPrepareRoot) {
372✔
357
    pStmt->sql.type = STMT_TYPE_QUERY;
3✔
358
    pStmt->sql.stbInterlaceMode = false;
3✔
359

360
    return TSDB_CODE_SUCCESS;
3✔
361
  }
362

363
  STableDataCxt** pSrc =
364
      (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
372✔
365
  if (NULL == pSrc || NULL == *pSrc) {
374!
366
    return terrno;
×
367
  }
368

369
  STableDataCxt* pTableCtx = *pSrc;
374✔
370
  if (pStmt->sql.stbInterlaceMode) {
374✔
371
    int16_t lastIdx = -1;
44✔
372

373
    for (int32_t i = 0; i < pTableCtx->boundColsInfo.numOfBound; ++i) {
307✔
374
      if (pTableCtx->boundColsInfo.pColIndex[i] < lastIdx) {
263!
375
        pStmt->sql.stbInterlaceMode = false;
×
376
        break;
×
377
      }
378

379
      lastIdx = pTableCtx->boundColsInfo.pColIndex[i];
263✔
380
    }
381
  }
382

383
  if (NULL == pStmt->sql.pBindInfo) {
374!
384
    pStmt->sql.pBindInfo = taosMemoryMalloc(pTableCtx->boundColsInfo.numOfBound * sizeof(*pStmt->sql.pBindInfo));
376!
385
    if (NULL == pStmt->sql.pBindInfo) {
377!
386
      return terrno;
×
387
    }
388
  }
389

390
  return TSDB_CODE_SUCCESS;
375✔
391
}
392

393
int32_t stmtCleanBindInfo(STscStmt* pStmt) {
3,276✔
394
  pStmt->bInfo.tbUid = 0;
3,276✔
395
  pStmt->bInfo.tbSuid = 0;
3,276✔
396
  pStmt->bInfo.tbVgId = -1;
3,276✔
397
  pStmt->bInfo.tbType = 0;
3,276✔
398
  pStmt->bInfo.needParse = true;
3,276✔
399
  pStmt->bInfo.inExecCache = false;
3,276✔
400

401
  pStmt->bInfo.tbName[0] = 0;
3,276✔
402
  pStmt->bInfo.tbFName[0] = 0;
3,276✔
403
  if (!pStmt->bInfo.tagsCached) {
3,276✔
404
    qDestroyBoundColInfo(pStmt->bInfo.boundTags);
3,244✔
405
    taosMemoryFreeClear(pStmt->bInfo.boundTags);
3,244!
406
  }
407
  pStmt->bInfo.stbFName[0] = 0;
3,278✔
408

409
  return TSDB_CODE_SUCCESS;
3,278✔
410
}
411

412
void stmtFreeTableBlkList(STableColsData* pTb) {
×
413
  (void)qResetStmtColumns(pTb->aCol, true);
×
414
  taosArrayDestroy(pTb->aCol);
×
415
}
×
416

417
void stmtResetQueueTableBuf(STableBufInfo* pTblBuf, SStmtQueue* pQueue) {
2,513✔
418
  pTblBuf->pCurBuff = taosArrayGetP(pTblBuf->pBufList, 0);
2,513✔
419
  if (NULL == pTblBuf->pCurBuff) {
2,511!
420
    tscError("QInfo:%p, failed to get buffer from list", pTblBuf);
×
421
    return;
×
422
  }
423
  pTblBuf->buffIdx = 1;
2,511✔
424
  pTblBuf->buffOffset = sizeof(*pQueue->head);
2,511✔
425

426
  (void)taosThreadMutexLock(&pQueue->mutex);
2,511✔
427
  pQueue->head = pQueue->tail = pTblBuf->pCurBuff;
2,513✔
428
  pQueue->qRemainNum = 0;
2,513✔
429
  pQueue->head->next = NULL;
2,513✔
430
  (void)taosThreadMutexUnlock(&pQueue->mutex);
2,513✔
431
}
432

433
int32_t stmtCleanExecInfo(STscStmt* pStmt, bool keepTable, bool deepClean) {
3,304✔
434
  if (pStmt->sql.stbInterlaceMode) {
3,304✔
435
    if (deepClean) {
2,561✔
436
      taosHashCleanup(pStmt->exec.pBlockHash);
47✔
437
      pStmt->exec.pBlockHash = NULL;
47✔
438

439
      if (NULL != pStmt->exec.pCurrBlock) {
47!
440
        taosMemoryFreeClear(pStmt->exec.pCurrBlock->pData);
47!
441
        qDestroyStmtDataBlock(pStmt->exec.pCurrBlock);
47✔
442
      }
443
    } else {
444
      pStmt->sql.siInfo.pTableColsIdx = 0;
2,514✔
445
      stmtResetQueueTableBuf(&pStmt->sql.siInfo.tbBuf, &pStmt->queue);
2,514✔
446
    }
447
  } else {
448
    if (STMT_TYPE_QUERY != pStmt->sql.type || deepClean) {
743✔
449
      taos_free_result(pStmt->exec.pRequest);
740✔
450
      pStmt->exec.pRequest = NULL;
744✔
451
    }
452

453
    size_t keyLen = 0;
747✔
454
    void*  pIter = taosHashIterate(pStmt->exec.pBlockHash, NULL);
747✔
455
    while (pIter) {
1,483✔
456
      STableDataCxt* pBlocks = *(STableDataCxt**)pIter;
737✔
457
      char*          key = taosHashGetKey(pIter, &keyLen);
737✔
458
      STableMeta*    pMeta = qGetTableMetaInDataBlock(pBlocks);
738✔
459

460
      if (keepTable && pBlocks == pStmt->exec.pCurrBlock) {
738!
461
        TSWAP(pBlocks->pData, pStmt->exec.pCurrTbData);
407✔
462
        STMT_ERR_RET(qResetStmtDataBlock(pBlocks, false));
815!
463

464
        pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter);
404✔
465
        continue;
405✔
466
      }
467

468
      qDestroyStmtDataBlock(pBlocks);
331✔
469
      STMT_ERR_RET(taosHashRemove(pStmt->exec.pBlockHash, key, keyLen));
331!
470

471
      pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter);
330✔
472
    }
473

474
    if (keepTable) {
746✔
475
      return TSDB_CODE_SUCCESS;
408✔
476
    }
477

478
    taosHashCleanup(pStmt->exec.pBlockHash);
338✔
479
    pStmt->exec.pBlockHash = NULL;
338✔
480

481
    tDestroySubmitTbData(pStmt->exec.pCurrTbData, TSDB_MSG_FLG_ENCODE);
338✔
482
    taosMemoryFreeClear(pStmt->exec.pCurrTbData);
338!
483
  }
484

485
  STMT_ERR_RET(stmtCleanBindInfo(pStmt));
2,900!
486

487
  return TSDB_CODE_SUCCESS;
2,896✔
488
}
489

490
void stmtFreeTbBuf(void* buf) {
47✔
491
  void* pBuf = *(void**)buf;
47✔
492
  taosMemoryFree(pBuf);
47!
493
}
47✔
494

495
void stmtFreeTbCols(void* buf) {
47,000✔
496
  SArray* pCols = *(SArray**)buf;
47,000✔
497
  taosArrayDestroy(pCols);
47,000✔
498
}
47,000✔
499

500
int32_t stmtCleanSQLInfo(STscStmt* pStmt) {
381✔
501
  STMT_DLOG_E("start to free SQL info");
381✔
502

503
  taosMemoryFree(pStmt->sql.pBindInfo);
381!
504
  taosMemoryFree(pStmt->sql.queryRes.fields);
380!
505
  taosMemoryFree(pStmt->sql.queryRes.userFields);
382!
506
  taosMemoryFree(pStmt->sql.sqlStr);
379!
507
  qDestroyQuery(pStmt->sql.pQuery);
379✔
508
  taosArrayDestroy(pStmt->sql.nodeList);
384✔
509
  taosHashCleanup(pStmt->sql.pVgHash);
384✔
510
  pStmt->sql.pVgHash = NULL;
384✔
511

512
  void* pIter = taosHashIterate(pStmt->sql.pTableCache, NULL);
384✔
513
  while (pIter) {
710✔
514
    SStmtTableCache* pCache = (SStmtTableCache*)pIter;
328✔
515

516
    qDestroyStmtDataBlock(pCache->pDataCtx);
328✔
517
    qDestroyBoundColInfo(pCache->boundTags);
327✔
518
    taosMemoryFreeClear(pCache->boundTags);
325!
519

520
    pIter = taosHashIterate(pStmt->sql.pTableCache, pIter);
326✔
521
  }
522
  taosHashCleanup(pStmt->sql.pTableCache);
382✔
523
  pStmt->sql.pTableCache = NULL;
384✔
524

525
  STMT_ERR_RET(stmtCleanExecInfo(pStmt, false, true));
384!
526
  STMT_ERR_RET(stmtCleanBindInfo(pStmt));
384!
527

528
  taos_free_result(pStmt->sql.siInfo.pRequest);
383✔
529
  taosHashCleanup(pStmt->sql.siInfo.pVgroupHash);
383✔
530
  tSimpleHashCleanup(pStmt->sql.siInfo.pTableHash);
383✔
531
  taosArrayDestroyEx(pStmt->sql.siInfo.tbBuf.pBufList, stmtFreeTbBuf);
381✔
532
  taosMemoryFree(pStmt->sql.siInfo.pTSchema);
381!
533
  qDestroyStmtDataBlock(pStmt->sql.siInfo.pDataCtx);
381✔
534
  taosArrayDestroyEx(pStmt->sql.siInfo.pTableCols, stmtFreeTbCols);
382✔
535

536
  (void)memset(&pStmt->sql, 0, sizeof(pStmt->sql));
382✔
537
  pStmt->sql.siInfo.tableColsReady = true;
382✔
538

539
  STMT_DLOG_E("end to free SQL info");
382✔
540

541
  return TSDB_CODE_SUCCESS;
381✔
542
}
543

544
int32_t stmtTryAddTableVgroupInfo(STscStmt* pStmt, int32_t* vgId) {
×
545
  if (*vgId >= 0 && taosHashGet(pStmt->sql.pVgHash, (const char*)vgId, sizeof(*vgId))) {
×
546
    return TSDB_CODE_SUCCESS;
×
547
  }
548

549
  SVgroupInfo      vgInfo = {0};
×
550
  SRequestConnInfo conn = {.pTrans = pStmt->taos->pAppInfo->pTransporter,
×
551
                           .requestId = pStmt->exec.pRequest->requestId,
×
552
                           .requestObjRefId = pStmt->exec.pRequest->self,
×
553
                           .mgmtEps = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp)};
×
554

555
  int32_t code = catalogGetTableHashVgroup(pStmt->pCatalog, &conn, &pStmt->bInfo.sname, &vgInfo);
×
556
  if (TSDB_CODE_SUCCESS != code) {
×
557
    return code;
×
558
  }
559

560
  code =
561
      taosHashPut(pStmt->sql.pVgHash, (const char*)&vgInfo.vgId, sizeof(vgInfo.vgId), (char*)&vgInfo, sizeof(vgInfo));
×
562
  if (TSDB_CODE_SUCCESS != code) {
×
563
    return code;
×
564
  }
565

566
  *vgId = vgInfo.vgId;
×
567

568
  return TSDB_CODE_SUCCESS;
×
569
}
570

571
int32_t stmtRebuildDataBlock(STscStmt* pStmt, STableDataCxt* pDataBlock, STableDataCxt** newBlock, uint64_t uid,
×
572
                             uint64_t suid, int32_t vgId) {
573
  STMT_ERR_RET(stmtTryAddTableVgroupInfo(pStmt, &vgId));
×
574
  STMT_ERR_RET(qRebuildStmtDataBlock(newBlock, pDataBlock, uid, suid, vgId, pStmt->sql.autoCreateTbl));
×
575

576
  STMT_DLOG("tableDataCxt rebuilt, uid:%" PRId64 ", vgId:%d", uid, vgId);
×
577

578
  return TSDB_CODE_SUCCESS;
×
579
}
580

581
int32_t stmtGetFromCache(STscStmt* pStmt) {
380✔
582
  if (pStmt->sql.stbInterlaceMode && pStmt->sql.siInfo.pDataCtx) {
380!
583
    pStmt->bInfo.needParse = false;
×
584
    pStmt->bInfo.inExecCache = false;
×
585
    return TSDB_CODE_SUCCESS;
×
586
  }
587

588
  pStmt->bInfo.needParse = true;
380✔
589
  pStmt->bInfo.inExecCache = false;
380✔
590

591
  STableDataCxt** pCxtInExec = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
380✔
592
  if (pCxtInExec) {
382✔
593
    pStmt->bInfo.needParse = false;
16✔
594
    pStmt->bInfo.inExecCache = true;
16✔
595

596
    pStmt->exec.pCurrBlock = *pCxtInExec;
16✔
597

598
    if (pStmt->sql.autoCreateTbl) {
16!
599
      tscDebug("reuse stmt block for tb %s in execBlock", pStmt->bInfo.tbFName);
16!
600
      return TSDB_CODE_SUCCESS;
16✔
601
    }
602
  }
603

604
  if (NULL == pStmt->pCatalog) {
366✔
605
    STMT_ERR_RET(catalogGetHandle(pStmt->taos->pAppInfo->clusterId, &pStmt->pCatalog));
328!
606
    pStmt->sql.siInfo.pCatalog = pStmt->pCatalog;
330✔
607
  }
608

609
  if (NULL == pStmt->sql.pTableCache || taosHashGetSize(pStmt->sql.pTableCache) <= 0) {
368!
610
    if (pStmt->bInfo.inExecCache) {
370!
611
      pStmt->bInfo.needParse = false;
×
612
      tscDebug("reuse stmt block for tb %s in execBlock", pStmt->bInfo.tbFName);
×
613
      return TSDB_CODE_SUCCESS;
×
614
    }
615

616
    tscDebug("no stmt block cache for tb %s", pStmt->bInfo.tbFName);
370✔
617
    return TSDB_CODE_SUCCESS;
369✔
618
  }
619

620
  if (pStmt->sql.autoCreateTbl) {
×
621
    SStmtTableCache* pCache = taosHashGet(pStmt->sql.pTableCache, &pStmt->bInfo.tbSuid, sizeof(pStmt->bInfo.tbSuid));
×
622
    if (pCache) {
×
623
      pStmt->bInfo.needParse = false;
×
624
      pStmt->bInfo.tbUid = 0;
×
625

626
      STableDataCxt* pNewBlock = NULL;
×
627
      STMT_ERR_RET(stmtRebuildDataBlock(pStmt, pCache->pDataCtx, &pNewBlock, 0, pStmt->bInfo.tbSuid, -1));
×
628

629
      if (taosHashPut(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName), &pNewBlock,
×
630
                      POINTER_BYTES)) {
631
        STMT_ERR_RET(terrno);
×
632
      }
633

634
      pStmt->exec.pCurrBlock = pNewBlock;
×
635

636
      tscDebug("reuse stmt block for tb %s in sqlBlock, suid:0x%" PRIx64, pStmt->bInfo.tbFName, pStmt->bInfo.tbSuid);
×
637

638
      return TSDB_CODE_SUCCESS;
×
639
    }
640

641
    STMT_RET(stmtCleanBindInfo(pStmt));
×
642
  }
643

644
  uint64_t uid, suid;
645
  int32_t  vgId;
646
  int8_t   tableType;
647

648
  STableMeta*      pTableMeta = NULL;
×
649
  SRequestConnInfo conn = {.pTrans = pStmt->taos->pAppInfo->pTransporter,
×
650
                           .requestId = pStmt->exec.pRequest->requestId,
×
651
                           .requestObjRefId = pStmt->exec.pRequest->self,
×
652
                           .mgmtEps = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp)};
×
653
  int32_t          code = catalogGetTableMeta(pStmt->pCatalog, &conn, &pStmt->bInfo.sname, &pTableMeta);
×
654

655
  pStmt->stat.ctgGetTbMetaNum++;
×
656

657
  if (TSDB_CODE_PAR_TABLE_NOT_EXIST == code) {
×
658
    tscDebug("tb %s not exist", pStmt->bInfo.tbFName);
×
659
    STMT_ERR_RET(stmtCleanBindInfo(pStmt));
×
660

661
    STMT_ERR_RET(code);
×
662
  }
663

664
  STMT_ERR_RET(code);
×
665

666
  uid = pTableMeta->uid;
×
667
  suid = pTableMeta->suid;
×
668
  tableType = pTableMeta->tableType;
×
669
  pStmt->bInfo.tbVgId = pTableMeta->vgId;
×
670
  vgId = pTableMeta->vgId;
×
671

672
  taosMemoryFree(pTableMeta);
×
673

674
  uint64_t cacheUid = (TSDB_CHILD_TABLE == tableType) ? suid : uid;
×
675

676
  if (uid == pStmt->bInfo.tbUid) {
×
677
    pStmt->bInfo.needParse = false;
×
678

679
    tscDebug("tb %s is current table", pStmt->bInfo.tbFName);
×
680

681
    return TSDB_CODE_SUCCESS;
×
682
  }
683

684
  if (pStmt->bInfo.inExecCache) {
×
685
    SStmtTableCache* pCache = taosHashGet(pStmt->sql.pTableCache, &cacheUid, sizeof(cacheUid));
×
686
    if (NULL == pCache) {
×
687
      tscError("table [%s, %" PRIx64 ", %" PRIx64 "] found in exec blockHash, but not in sql blockHash",
×
688
               pStmt->bInfo.tbFName, uid, cacheUid);
689

690
      STMT_ERR_RET(TSDB_CODE_APP_ERROR);
×
691
    }
692

693
    pStmt->bInfo.needParse = false;
×
694

695
    pStmt->bInfo.tbUid = uid;
×
696
    pStmt->bInfo.tbSuid = suid;
×
697
    pStmt->bInfo.tbType = tableType;
×
698
    pStmt->bInfo.boundTags = pCache->boundTags;
×
699
    pStmt->bInfo.tagsCached = true;
×
700

701
    tscDebug("tb %s in execBlock list, set to current", pStmt->bInfo.tbFName);
×
702

703
    return TSDB_CODE_SUCCESS;
×
704
  }
705

706
  SStmtTableCache* pCache = taosHashGet(pStmt->sql.pTableCache, &cacheUid, sizeof(cacheUid));
×
707
  if (pCache) {
×
708
    pStmt->bInfo.needParse = false;
×
709

710
    pStmt->bInfo.tbUid = uid;
×
711
    pStmt->bInfo.tbSuid = suid;
×
712
    pStmt->bInfo.tbType = tableType;
×
713
    pStmt->bInfo.boundTags = pCache->boundTags;
×
714
    pStmt->bInfo.tagsCached = true;
×
715

716
    STableDataCxt* pNewBlock = NULL;
×
717
    STMT_ERR_RET(stmtRebuildDataBlock(pStmt, pCache->pDataCtx, &pNewBlock, uid, suid, vgId));
×
718

719
    if (taosHashPut(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName), &pNewBlock,
×
720
                    POINTER_BYTES)) {
721
      STMT_ERR_RET(terrno);
×
722
    }
723

724
    pStmt->exec.pCurrBlock = pNewBlock;
×
725

726
    tscDebug("tb %s in sqlBlock list, set to current", pStmt->bInfo.tbFName);
×
727

728
    return TSDB_CODE_SUCCESS;
×
729
  }
730

731
  STMT_ERR_RET(stmtCleanBindInfo(pStmt));
×
732

733
  return TSDB_CODE_SUCCESS;
×
734
}
735

736
int32_t stmtResetStmt(STscStmt* pStmt) {
38✔
737
  STMT_ERR_RET(stmtCleanSQLInfo(pStmt));
38!
738

739
  pStmt->sql.pTableCache = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
39✔
740
  if (NULL == pStmt->sql.pTableCache) {
38!
741
    STMT_ERR_RET(terrno);
×
742
  }
743

744
  pStmt->sql.status = STMT_INIT;
38✔
745

746
  return TSDB_CODE_SUCCESS;
38✔
747
}
748

749
int32_t stmtAsyncOutput(STscStmt* pStmt, void* param) {
38,039✔
750
  SStmtQNode* pParam = (SStmtQNode*)param;
38,039✔
751

752
  if (pParam->restoreTbCols) {
38,039✔
753
    for (int32_t i = 0; i < pStmt->sql.siInfo.pTableColsIdx; ++i) {
38,056✔
754
      SArray** p = (SArray**)TARRAY_GET_ELEM(pStmt->sql.siInfo.pTableCols, i);
35,543✔
755
      *p = taosArrayInit(20, POINTER_BYTES);
35,543✔
756
      if (*p == NULL) {
35,539!
757
        STMT_ERR_RET(terrno);
×
758
      }
759
    }
760

761
    atomic_store_8((int8_t*)&pStmt->sql.siInfo.tableColsReady, true);
2,513✔
762
  } else {
763
    STMT_ERR_RET(qAppendStmtTableOutput(pStmt->sql.pQuery, pStmt->sql.pVgHash, &pParam->tblData, pStmt->exec.pCurrBlock,
35,524!
764
                                        &pStmt->sql.siInfo));
765

766
    // taosMemoryFree(pParam->pTbData);
767

768
    (void)atomic_sub_fetch_64(&pStmt->sql.siInfo.tbRemainNum, 1);
35,257✔
769
  }
770
  return TSDB_CODE_SUCCESS;
38,089✔
771
}
772

773
void* stmtBindThreadFunc(void* param) {
47✔
774
  setThreadName("stmtBind");
47✔
775

776
  qInfo("stmt bind thread started");
47!
777

778
  STscStmt* pStmt = (STscStmt*)param;
47✔
779

780
  while (true) {
38,119✔
781
    if (atomic_load_8((int8_t*)&pStmt->queue.stopQueue)) {
38,166✔
782
      break;
47✔
783
    }
784

785
    SStmtQNode* asyncParam = NULL;
38,102✔
786
    if (!stmtDequeue(pStmt, &asyncParam)) {
38,102✔
787
      continue;
47✔
788
    }
789

790
    int ret = stmtAsyncOutput(pStmt, asyncParam);
38,054✔
791
    if (ret != 0) {
38,083!
792
      qError("stmtAsyncOutput failed, reason:%s", tstrerror(ret));
×
793
    }
794
  }
795

796
  qInfo("stmt bind thread stopped");
47!
797

798
  return NULL;
47✔
799
}
800

801
int32_t stmtStartBindThread(STscStmt* pStmt) {
47✔
802
  TdThreadAttr thAttr;
803
  if (taosThreadAttrInit(&thAttr) != 0) {
47!
804
    return TSDB_CODE_TSC_INTERNAL_ERROR;
×
805
  }
806
  if (taosThreadAttrSetDetachState(&thAttr, PTHREAD_CREATE_JOINABLE) != 0) {
47!
807
    return TSDB_CODE_TSC_INTERNAL_ERROR;
×
808
  }
809

810
  if (taosThreadCreate(&pStmt->bindThread, &thAttr, stmtBindThreadFunc, pStmt) != 0) {
47!
811
    terrno = TAOS_SYSTEM_ERROR(errno);
×
812
    STMT_ERR_RET(terrno);
×
813
  }
814

815
  pStmt->bindThreadInUse = true;
47✔
816

817
  (void)taosThreadAttrDestroy(&thAttr);
47✔
818
  return TSDB_CODE_SUCCESS;
47✔
819
}
820

821
int32_t stmtInitQueue(STscStmt* pStmt) {
47✔
822
  (void)taosThreadCondInit(&pStmt->queue.waitCond, NULL);
47✔
823
  (void)taosThreadMutexInit(&pStmt->queue.mutex, NULL);
47✔
824
  STMT_ERR_RET(stmtAllocQNodeFromBuf(&pStmt->sql.siInfo.tbBuf, (void**)&pStmt->queue.head));
94!
825
  pStmt->queue.tail = pStmt->queue.head;
47✔
826

827
  return TSDB_CODE_SUCCESS;
47✔
828
}
829

830
int32_t stmtInitTableBuf(STableBufInfo* pTblBuf) {
47✔
831
  pTblBuf->buffUnit = sizeof(SStmtQNode);
47✔
832
  pTblBuf->buffSize = pTblBuf->buffUnit * 1000;
47✔
833
  pTblBuf->pBufList = taosArrayInit(100, POINTER_BYTES);
47✔
834
  if (NULL == pTblBuf->pBufList) {
47!
835
    return terrno;
×
836
  }
837
  void* buff = taosMemoryMalloc(pTblBuf->buffSize);
47!
838
  if (NULL == buff) {
47!
839
    return terrno;
×
840
  }
841

842
  if (taosArrayPush(pTblBuf->pBufList, &buff) == NULL) {
94!
843
    return terrno;
×
844
  }
845

846
  pTblBuf->pCurBuff = buff;
47✔
847
  pTblBuf->buffIdx = 1;
47✔
848
  pTblBuf->buffOffset = 0;
47✔
849

850
  return TSDB_CODE_SUCCESS;
47✔
851
}
852

853
TAOS_STMT* stmtInit(STscObj* taos, int64_t reqid, TAOS_STMT_OPTIONS* pOptions) {
345✔
854
  STscObj*  pObj = (STscObj*)taos;
345✔
855
  STscStmt* pStmt = NULL;
345✔
856
  int32_t   code = 0;
345✔
857

858
  pStmt = taosMemoryCalloc(1, sizeof(STscStmt));
345!
859
  if (NULL == pStmt) {
345!
860
    return NULL;
×
861
  }
862

863
  pStmt->sql.pTableCache = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
345✔
864
  if (NULL == pStmt->sql.pTableCache) {
345!
865
    taosMemoryFree(pStmt);
×
866
    return NULL;
×
867
  }
868

869
  pStmt->taos = pObj;
345✔
870
  pStmt->bInfo.needParse = true;
345✔
871
  pStmt->sql.status = STMT_INIT;
345✔
872
  pStmt->reqid = reqid;
345✔
873
  pStmt->errCode = TSDB_CODE_SUCCESS;
345✔
874

875
  if (NULL != pOptions) {
345✔
876
    (void)memcpy(&pStmt->options, pOptions, sizeof(pStmt->options));
47✔
877
    if (pOptions->singleStbInsert && pOptions->singleTableBindOnce) {
47!
878
      pStmt->stbInterlaceMode = true;
47✔
879
    }
880
  }
881

882
  if (pStmt->stbInterlaceMode) {
345✔
883
    pStmt->sql.siInfo.transport = taos->pAppInfo->pTransporter;
47✔
884
    pStmt->sql.siInfo.acctId = taos->acctId;
47✔
885
    pStmt->sql.siInfo.dbname = taos->db;
47✔
886
    pStmt->sql.siInfo.mgmtEpSet = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp);
47✔
887
    pStmt->sql.siInfo.pTableHash = tSimpleHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY));
47✔
888
    if (NULL == pStmt->sql.siInfo.pTableHash) {
47!
889
      (void)stmtClose(pStmt);
×
890
      return NULL;
×
891
    }
892
    pStmt->sql.siInfo.pTableCols = taosArrayInit(STMT_TABLE_COLS_NUM, POINTER_BYTES);
47✔
893
    if (NULL == pStmt->sql.siInfo.pTableCols) {
47!
894
      (void)stmtClose(pStmt);
×
895
      return NULL;
×
896
    }
897

898
    code = stmtInitTableBuf(&pStmt->sql.siInfo.tbBuf);
47✔
899
    if (TSDB_CODE_SUCCESS == code) {
47!
900
      code = stmtInitQueue(pStmt);
47✔
901
    }
902
    if (TSDB_CODE_SUCCESS == code) {
47!
903
      code = stmtStartBindThread(pStmt);
47✔
904
    }
905
    if (TSDB_CODE_SUCCESS != code) {
47!
906
      terrno = code;
×
907
      (void)stmtClose(pStmt);
×
908
      return NULL;
×
909
    }
910
  }
911

912
  pStmt->sql.siInfo.tableColsReady = true;
345✔
913

914
  STMT_LOG_SEQ(STMT_INIT);
345✔
915

916
  tscDebug("stmt:%p initialized", pStmt);
345✔
917

918
  return pStmt;
345✔
919
}
920

921
int stmtPrepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
384✔
922
  STscStmt* pStmt = (STscStmt*)stmt;
384✔
923

924
  STMT_DLOG_E("start to prepare");
384✔
925

926
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
384!
927
    return pStmt->errCode;
×
928
  }
929

930
  if (pStmt->sql.status >= STMT_PREPARE) {
384✔
931
    STMT_ERR_RET(stmtResetStmt(pStmt));
39!
932
  }
933

934
  STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_PREPARE));
383!
935

936
  if (length <= 0) {
382✔
937
    length = strlen(sql);
272✔
938
  }
939

940
  pStmt->sql.sqlStr = taosStrndup(sql, length);
382!
941
  if (!pStmt->sql.sqlStr) {
380!
942
    return terrno;
×
943
  }
944
  pStmt->sql.sqlLen = length;
380✔
945
  pStmt->sql.stbInterlaceMode = pStmt->stbInterlaceMode;
380✔
946

947
  char* dbName = NULL;
380✔
948
  if (qParseDbName(sql, length, &dbName)) {
380!
949
    STMT_ERR_RET(stmtSetDbName(stmt, dbName));
×
950
    taosMemoryFreeClear(dbName);
×
951
  }
952

953
  return TSDB_CODE_SUCCESS;
379✔
954
}
955

956
int32_t stmtInitStbInterlaceTableInfo(STscStmt* pStmt) {
45✔
957
  STableDataCxt** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
45✔
958
  if (!pSrc) {
44!
959
    return terrno;
×
960
  }
961
  STableDataCxt* pDst = NULL;
44✔
962

963
  STMT_ERR_RET(qCloneStmtDataBlock(&pDst, *pSrc, true));
44!
964
  pStmt->sql.siInfo.pDataCtx = pDst;
35✔
965

966
  SArray* pTblCols = NULL;
35✔
967
  for (int32_t i = 0; i < STMT_TABLE_COLS_NUM; i++) {
35,001✔
968
    pTblCols = taosArrayInit(20, POINTER_BYTES);
34,823✔
969
    if (NULL == pTblCols) {
38,812!
970
      return terrno;
×
971
    }
972

973
    if (taosArrayPush(pStmt->sql.siInfo.pTableCols, &pTblCols) == NULL) {
73,778!
974
      return terrno;
×
975
    }
976
  }
977

978
  pStmt->sql.siInfo.boundTags = pStmt->bInfo.boundTags;
178✔
979

980
  return TSDB_CODE_SUCCESS;
178✔
981
}
982

983
int stmtSetDbName(TAOS_STMT* stmt, const char* dbName) {
×
984
  STscStmt* pStmt = (STscStmt*)stmt;
×
985

986
  STMT_DLOG("start to set dbName: %s", dbName);
×
987

988
  STMT_ERR_RET(stmtCreateRequest(pStmt));
×
989

990
  // The SQL statement specifies a database name, overriding the previously specified database
991
  taosMemoryFreeClear(pStmt->exec.pRequest->pDb);
×
992
  pStmt->exec.pRequest->pDb = taosStrdup(dbName);
×
993
  if (pStmt->exec.pRequest->pDb == NULL) {
×
994
    return terrno;
×
995
  }
996
  return TSDB_CODE_SUCCESS;
×
997
}
998

999
int stmtSetTbName(TAOS_STMT* stmt, const char* tbName) {
35,812✔
1000
  STscStmt* pStmt = (STscStmt*)stmt;
35,812✔
1001

1002
  int64_t startUs = taosGetTimestampUs();
35,817✔
1003

1004
  STMT_DLOG("start to set tbName: %s", tbName);
35,817✔
1005

1006
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
35,821!
1007
    return pStmt->errCode;
×
1008
  }
1009

1010
  STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTBNAME));
35,821!
1011

1012
  int32_t insert = 0;
35,738✔
1013
  STMT_ERR_RET(stmtIsInsert(stmt, &insert));
35,738!
1014
  if (0 == insert) {
35,703!
1015
    tscError("set tb name not available for none insert statement");
×
1016
    STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR);
×
1017
  }
1018

1019
  if (!pStmt->sql.stbInterlaceMode || NULL == pStmt->sql.siInfo.pDataCtx) {
35,703✔
1020
    STMT_ERR_RET(stmtCreateRequest(pStmt));
372!
1021

1022
    STMT_ERR_RET(qCreateSName(&pStmt->bInfo.sname, tbName, pStmt->taos->acctId, pStmt->exec.pRequest->pDb,
389!
1023
                              pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen));
1024
    STMT_ERR_RET(tNameExtractFullName(&pStmt->bInfo.sname, pStmt->bInfo.tbFName));
389!
1025

1026
    STMT_ERR_RET(stmtGetFromCache(pStmt));
384!
1027

1028
    if (pStmt->bInfo.needParse) {
385✔
1029
      tstrncpy(pStmt->bInfo.tbName, tbName, sizeof(pStmt->bInfo.tbName));
369✔
1030
      pStmt->bInfo.tbName[sizeof(pStmt->bInfo.tbName) - 1] = 0;
369✔
1031

1032
      STMT_ERR_RET(stmtParseSql(pStmt));
369✔
1033
    }
1034
  } else {
1035
    tstrncpy(pStmt->bInfo.tbName, tbName, sizeof(pStmt->bInfo.tbName));
35,331✔
1036
    pStmt->bInfo.tbName[sizeof(pStmt->bInfo.tbName) - 1] = 0;
35,331✔
1037
    pStmt->exec.pRequest->requestId++;
35,331✔
1038
    pStmt->bInfo.needParse = false;
35,331✔
1039
  }
1040

1041
  if (pStmt->sql.stbInterlaceMode && NULL == pStmt->sql.siInfo.pDataCtx) {
35,718✔
1042
    STMT_ERR_RET(stmtInitStbInterlaceTableInfo(pStmt));
46!
1043
  }
1044

1045
  int64_t startUs2 = taosGetTimestampUs();
35,702✔
1046
  pStmt->stat.setTbNameUs += startUs2 - startUs;
35,702✔
1047

1048
  return TSDB_CODE_SUCCESS;
35,702✔
1049
}
1050

1051
int stmtSetTbTags(TAOS_STMT* stmt, TAOS_MULTI_BIND* tags) {
1✔
1052
  STscStmt* pStmt = (STscStmt*)stmt;
1✔
1053

1054
  STMT_DLOG_E("start to set tbTags");
1!
1055

1056
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
1!
1057
    return pStmt->errCode;
×
1058
  }
1059

1060
  STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_SETTAGS));
1!
1061

1062
  SBoundColInfo* tags_info = (SBoundColInfo*)pStmt->bInfo.boundTags;
1✔
1063
  if (tags_info->numOfBound <= 0 || tags_info->numOfCols <= 0) {
1!
1064
    tscWarn("no tags bound in sql, will not bound tags");
×
1065
    return TSDB_CODE_SUCCESS;
×
1066
  }
1067

1068
  if (pStmt->bInfo.inExecCache) {
1!
1069
    return TSDB_CODE_SUCCESS;
×
1070
  }
1071

1072
  STableDataCxt** pDataBlock =
1073
      (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
1✔
1074
  if (NULL == pDataBlock) {
1!
1075
    tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName);
×
1076
    STMT_ERR_RET(TSDB_CODE_APP_ERROR);
×
1077
  }
1078

1079
  tscDebug("start to bind stmt tag values");
1!
1080
  STMT_ERR_RET(qBindStmtTagsValue(*pDataBlock, pStmt->bInfo.boundTags, pStmt->bInfo.tbSuid, pStmt->bInfo.stbFName,
1!
1081
                                  pStmt->bInfo.sname.tname, tags, pStmt->exec.pRequest->msgBuf,
1082
                                  pStmt->exec.pRequest->msgBufLen, pStmt->taos->optionInfo.charsetCxt));
1083

1084
  return TSDB_CODE_SUCCESS;
1✔
1085
}
1086

1087
int stmtFetchTagFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields) {
×
1088
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
×
1089
    return pStmt->errCode;
×
1090
  }
1091

1092
  if (STMT_TYPE_QUERY == pStmt->sql.type) {
×
1093
    tscError("invalid operation to get query tag fileds");
×
1094
    STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR);
×
1095
  }
1096

1097
  STableDataCxt** pDataBlock =
1098
      (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
×
1099
  if (NULL == pDataBlock) {
×
1100
    tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName);
×
1101
    STMT_ERR_RET(TSDB_CODE_APP_ERROR);
×
1102
  }
1103

1104
  STMT_ERR_RET(qBuildStmtTagFields(*pDataBlock, pStmt->bInfo.boundTags, fieldNum, fields));
×
1105

1106
  return TSDB_CODE_SUCCESS;
×
1107
}
1108

1109
int stmtFetchColFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields) {
×
1110
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
×
1111
    return pStmt->errCode;
×
1112
  }
1113

1114
  if (STMT_TYPE_QUERY == pStmt->sql.type) {
×
1115
    tscError("invalid operation to get query column fileds");
×
1116
    STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR);
×
1117
  }
1118

1119
  STableDataCxt** pDataBlock = NULL;
×
1120

1121
  if (pStmt->sql.stbInterlaceMode) {
×
1122
    pDataBlock = &pStmt->sql.siInfo.pDataCtx;
×
1123
  } else {
1124
    pDataBlock =
1125
        (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
×
1126
    if (NULL == pDataBlock) {
×
1127
      tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName);
×
1128
      STMT_ERR_RET(TSDB_CODE_APP_ERROR);
×
1129
    }
1130
  }
1131

1132
  STMT_ERR_RET(qBuildStmtColFields(*pDataBlock, fieldNum, fields));
×
1133

1134
  return TSDB_CODE_SUCCESS;
×
1135
}
1136

1137
/*
1138
SArray* stmtGetFreeCol(STscStmt* pStmt, int32_t* idx) {
1139
  while (true) {
1140
    if (pStmt->exec.smInfo.pColIdx >= STMT_COL_BUF_SIZE) {
1141
      pStmt->exec.smInfo.pColIdx = 0;
1142
    }
1143

1144
    if ((pStmt->exec.smInfo.pColIdx + 1) == atomic_load_32(&pStmt->exec.smInfo.pColFreeIdx)) {
1145
      taosUsleep(1);
1146
      continue;
1147
    }
1148

1149
    *idx = pStmt->exec.smInfo.pColIdx;
1150
    return pStmt->exec.smInfo.pCols[pStmt->exec.smInfo.pColIdx++];
1151
  }
1152
}
1153
*/
1154

1155
int32_t stmtAppendTablePostHandle(STscStmt* pStmt, SStmtQNode* param) {
35,399✔
1156
  if (NULL == pStmt->sql.siInfo.pVgroupHash) {
35,399✔
1157
    pStmt->sql.siInfo.pVgroupHash =
2,513✔
1158
        taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
2,507✔
1159
  }
1160
  if (NULL == pStmt->sql.siInfo.pVgroupList) {
35,405✔
1161
    pStmt->sql.siInfo.pVgroupList = taosArrayInit(64, POINTER_BYTES);
2,514✔
1162
  }
1163

1164
  if (NULL == pStmt->sql.siInfo.pRequest) {
35,400✔
1165
    STMT_ERR_RET(buildRequest(pStmt->taos->id, pStmt->sql.sqlStr, pStmt->sql.sqlLen, NULL, false,
47!
1166
                              (SRequestObj**)&pStmt->sql.siInfo.pRequest, pStmt->reqid));
1167

1168
    if (pStmt->reqid != 0) {
47!
1169
      pStmt->reqid++;
×
1170
    }
1171
    pStmt->exec.pRequest->syncQuery = true;
47✔
1172

1173
    pStmt->sql.siInfo.requestId = ((SRequestObj*)pStmt->sql.siInfo.pRequest)->requestId;
47✔
1174
    pStmt->sql.siInfo.requestSelf = ((SRequestObj*)pStmt->sql.siInfo.pRequest)->self;
47✔
1175
  }
1176

1177
  if (!pStmt->sql.siInfo.tbFromHash && pStmt->sql.siInfo.firstName[0] &&
35,400✔
1178
      0 == strcmp(pStmt->sql.siInfo.firstName, pStmt->bInfo.tbName)) {
265✔
1179
    pStmt->sql.siInfo.tbFromHash = true;
25✔
1180
  }
1181

1182
  if (0 == pStmt->sql.siInfo.firstName[0]) {
35,400✔
1183
    tstrncpy(pStmt->sql.siInfo.firstName, pStmt->bInfo.tbName, TSDB_TABLE_NAME_LEN);
47✔
1184
  }
1185

1186
  param->tblData.getFromHash = pStmt->sql.siInfo.tbFromHash;
35,400✔
1187
  param->next = NULL;
35,400✔
1188

1189
  (void)atomic_add_fetch_64(&pStmt->sql.siInfo.tbRemainNum, 1);
35,400✔
1190

1191
  stmtEnqueue(pStmt, param);
35,594✔
1192

1193
  return TSDB_CODE_SUCCESS;
35,560✔
1194
}
1195

1196
static FORCE_INLINE int32_t stmtGetTableColsFromCache(STscStmt* pStmt, SArray** pTableCols) {
1197
  while (true) {
1198
    if (pStmt->sql.siInfo.pTableColsIdx < taosArrayGetSize(pStmt->sql.siInfo.pTableCols)) {
35,247!
1199
      *pTableCols = (SArray*)taosArrayGetP(pStmt->sql.siInfo.pTableCols, pStmt->sql.siInfo.pTableColsIdx++);
35,180✔
1200
      break;
35,150✔
1201
    } else {
1202
      SArray* pTblCols = NULL;
×
1203
      for (int32_t i = 0; i < 100; i++) {
×
1204
        pTblCols = taosArrayInit(20, POINTER_BYTES);
×
1205
        if (NULL == pTblCols) {
×
1206
          return terrno;
×
1207
        }
1208

1209
        if (taosArrayPush(pStmt->sql.siInfo.pTableCols, &pTblCols) == NULL) {
×
1210
          return terrno;
×
1211
        }
1212
      }
1213
    }
1214
  }
1215

1216
  return TSDB_CODE_SUCCESS;
35,150✔
1217
}
1218

1219
int stmtBindBatch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int32_t colIdx) {
930,256✔
1220
  STscStmt* pStmt = (STscStmt*)stmt;
930,256✔
1221
  int32_t   code = 0;
930,256✔
1222

1223
  int64_t startUs = taosGetTimestampUs();
943,178✔
1224

1225
  STMT_DLOG("start to bind stmt data, colIdx: %d", colIdx);
943,178✔
1226

1227
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
939,755!
1228
    return pStmt->errCode;
×
1229
  }
1230

1231
  STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_BIND));
939,755!
1232

1233
  if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
923,212!
1234
      STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
×
1235
    pStmt->bInfo.needParse = false;
×
1236
  }
1237

1238
  if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
923,212!
1239
    taos_free_result(pStmt->exec.pRequest);
×
1240
    pStmt->exec.pRequest = NULL;
×
1241
  }
1242

1243
  STMT_ERR_RET(stmtCreateRequest(pStmt));
923,212!
1244

1245
  if (pStmt->bInfo.needParse) {
919,338✔
1246
    STMT_ERR_RET(stmtParseSql(pStmt));
9!
1247
  }
1248

1249
  if (STMT_TYPE_QUERY == pStmt->sql.type) {
914,848✔
1250
    STMT_ERR_RET(qStmtBindParams(pStmt->sql.pQuery, bind, colIdx, pStmt->taos->optionInfo.charsetCxt));
3!
1251

1252
    SParseContext ctx = {.requestId = pStmt->exec.pRequest->requestId,
3✔
1253
                         .acctId = pStmt->taos->acctId,
3✔
1254
                         .db = pStmt->exec.pRequest->pDb,
3✔
1255
                         .topicQuery = false,
1256
                         .pSql = pStmt->sql.sqlStr,
3✔
1257
                         .sqlLen = pStmt->sql.sqlLen,
3✔
1258
                         .pMsg = pStmt->exec.pRequest->msgBuf,
3✔
1259
                         .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
1260
                         .pTransporter = pStmt->taos->pAppInfo->pTransporter,
3✔
1261
                         .pStmtCb = NULL,
1262
                         .pUser = pStmt->taos->user,
3✔
1263
                         .setQueryFp = setQueryRequest};
1264

1265
    ctx.mgmtEpSet = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp);
3✔
1266
    STMT_ERR_RET(catalogGetHandle(pStmt->taos->pAppInfo->clusterId, &ctx.pCatalog));
3!
1267

1268
    STMT_ERR_RET(qStmtParseQuerySql(&ctx, pStmt->sql.pQuery));
3!
1269

1270
    if (pStmt->sql.pQuery->haveResultSet) {
3!
1271
      STMT_ERR_RET(setResSchemaInfo(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->pResSchema,
3!
1272
                                    pStmt->sql.pQuery->numOfResCols));
1273
      taosMemoryFreeClear(pStmt->sql.pQuery->pResSchema);
3!
1274
      setResPrecision(&pStmt->exec.pRequest->body.resInfo, pStmt->sql.pQuery->precision);
3✔
1275
    }
1276

1277
    TSWAP(pStmt->exec.pRequest->dbList, pStmt->sql.pQuery->pDbList);
3✔
1278
    TSWAP(pStmt->exec.pRequest->tableList, pStmt->sql.pQuery->pTableList);
3✔
1279
    TSWAP(pStmt->exec.pRequest->targetTableList, pStmt->sql.pQuery->pTargetTableList);
3✔
1280

1281
    // if (STMT_TYPE_QUERY == pStmt->sql.queryRes) {
1282
    //   STMT_ERR_RET(stmtRestoreQueryFields(pStmt));
1283
    // }
1284

1285
    // STMT_ERR_RET(stmtBackupQueryFields(pStmt));
1286

1287
    return TSDB_CODE_SUCCESS;
3✔
1288
  }
1289

1290
  if (pStmt->sql.stbInterlaceMode && NULL == pStmt->sql.siInfo.pDataCtx) {
914,845!
1291
    STMT_ERR_RET(stmtInitStbInterlaceTableInfo(pStmt));
×
1292
  }
1293

1294
  STableDataCxt** pDataBlock = NULL;
907,152✔
1295

1296
  if (pStmt->exec.pCurrBlock) {
907,152✔
1297
    pDataBlock = &pStmt->exec.pCurrBlock;
906,776✔
1298
  } else {
1299
    pDataBlock =
1300
        (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
376✔
1301
    if (NULL == pDataBlock) {
376!
1302
      tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName);
×
1303
      STMT_ERR_RET(TSDB_CODE_TSC_STMT_CACHE_ERROR);
×
1304
    }
1305
    pStmt->exec.pCurrBlock = *pDataBlock;
376✔
1306
    if (pStmt->sql.stbInterlaceMode) {
376✔
1307
      taosArrayDestroy(pStmt->exec.pCurrBlock->pData->aCol);
47✔
1308
      pStmt->exec.pCurrBlock->pData->aCol = NULL;
46✔
1309
    }
1310
  }
1311

1312
  int64_t startUs2 = taosGetTimestampUs();
924,182✔
1313
  pStmt->stat.bindDataUs1 += startUs2 - startUs;
924,182✔
1314

1315
  SStmtQNode* param = NULL;
924,182✔
1316
  if (pStmt->sql.stbInterlaceMode) {
924,182✔
1317
    STMT_ERR_RET(stmtAllocQNodeFromBuf(&pStmt->sql.siInfo.tbBuf, (void**)&param));
70,488!
1318
    STMT_ERR_RET(stmtGetTableColsFromCache(pStmt, &param->tblData.aCol));
70,397!
1319
    taosArrayClear(param->tblData.aCol);
35,150✔
1320

1321
    // param->tblData.aCol = taosArrayInit(20, POINTER_BYTES);
1322

1323
    param->restoreTbCols = false;
35,086✔
1324
    tstrncpy(param->tblData.tbName, pStmt->bInfo.tbName, TSDB_TABLE_NAME_LEN);
35,086✔
1325
  }
1326

1327
  int64_t startUs3 = taosGetTimestampUs();
945,283✔
1328
  pStmt->stat.bindDataUs2 += startUs3 - startUs2;
945,283✔
1329

1330
  SArray* pCols = pStmt->sql.stbInterlaceMode ? param->tblData.aCol : (*pDataBlock)->pData->aCol;
945,283✔
1331

1332
  if (colIdx < 0) {
945,283!
1333
    if (pStmt->sql.stbInterlaceMode) {
946,477✔
1334
      (*pDataBlock)->pData->flags = 0;
35,233✔
1335
      code =
1336
          qBindStmtStbColsValue(*pDataBlock, pCols, bind, pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen,
35,233✔
1337
                                &pStmt->sql.siInfo.pTSchema, pStmt->sql.pBindInfo, pStmt->taos->optionInfo.charsetCxt);
35,233✔
1338
    } else {
1339
      code = qBindStmtColsValue(*pDataBlock, pCols, bind, pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen,
911,244✔
1340
                                pStmt->taos->optionInfo.charsetCxt);
911,244✔
1341
    }
1342

1343
    if (code) {
946,252!
1344
      tscError("qBindStmtColsValue failed, error:%s", tstrerror(code));
×
1345
      STMT_ERR_RET(code);
×
1346
    }
1347
  } else {
1348
    if (pStmt->sql.stbInterlaceMode) {
×
1349
      tscError("bind single column not allowed in stb insert mode");
×
1350
      STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR);
×
1351
    }
1352

1353
    if (colIdx != (pStmt->bInfo.sBindLastIdx + 1) && colIdx != 0) {
×
1354
      tscError("bind column index not in sequence");
×
1355
      STMT_ERR_RET(TSDB_CODE_APP_ERROR);
×
1356
    }
1357

1358
    pStmt->bInfo.sBindLastIdx = colIdx;
×
1359

1360
    if (0 == colIdx) {
×
1361
      pStmt->bInfo.sBindRowNum = bind->num;
×
1362
    }
1363

1364
    code =
1365
        qBindStmtSingleColValue(*pDataBlock, pCols, bind, pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen,
×
1366
                                colIdx, pStmt->bInfo.sBindRowNum, pStmt->taos->optionInfo.charsetCxt);
×
1367
    if (code) {
×
1368
      tscError("qBindStmtSingleColValue failed, error:%s", tstrerror(code));
×
1369
      STMT_ERR_RET(code);
×
1370
    }
1371
  }
1372

1373
  int64_t startUs4 = taosGetTimestampUs();
964,830✔
1374
  pStmt->stat.bindDataUs3 += startUs4 - startUs3;
964,830✔
1375

1376
  if (pStmt->sql.stbInterlaceMode) {
964,830✔
1377
    STMT_ERR_RET(stmtAppendTablePostHandle(pStmt, param));
35,412!
1378
  }
1379

1380
  pStmt->stat.bindDataUs4 += taosGetTimestampUs() - startUs4;
971,601✔
1381

1382
  return TSDB_CODE_SUCCESS;
971,601✔
1383
}
1384

1385
int stmtAddBatch(TAOS_STMT* stmt) {
904,649✔
1386
  STscStmt* pStmt = (STscStmt*)stmt;
904,649✔
1387

1388
  int64_t startUs = taosGetTimestampUs();
912,435✔
1389

1390
  STMT_DLOG_E("start to add batch");
912,435✔
1391

1392
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
914,310!
1393
    return pStmt->errCode;
×
1394
  }
1395

1396
  STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_ADD_BATCH));
914,310!
1397

1398
  if (pStmt->sql.stbInterlaceMode) {
913,980✔
1399
    int64_t startUs2 = taosGetTimestampUs();
2,515✔
1400
    pStmt->stat.addBatchUs += startUs2 - startUs;
2,515✔
1401

1402
    pStmt->sql.siInfo.tableColsReady = false;
2,515✔
1403

1404
    SStmtQNode* param = NULL;
2,515✔
1405
    STMT_ERR_RET(stmtAllocQNodeFromBuf(&pStmt->sql.siInfo.tbBuf, (void**)&param));
5,030!
1406
    param->restoreTbCols = true;
2,515✔
1407
    param->next = NULL;
2,515✔
1408

1409
    stmtEnqueue(pStmt, param);
2,515✔
1410

1411
    return TSDB_CODE_SUCCESS;
2,513✔
1412
  }
1413

1414
  STMT_ERR_RET(stmtCacheBlock(pStmt));
911,465!
1415

1416
  return TSDB_CODE_SUCCESS;
918,663✔
1417
}
1418
/*
1419
int stmtUpdateTableUid(STscStmt* pStmt, SSubmitRsp* pRsp) {
1420
  tscDebug("stmt start to update tbUid, blockNum: %d", pRsp->nBlocks);
1421

1422
  int32_t code = 0;
1423
  int32_t finalCode = 0;
1424
  size_t  keyLen = 0;
1425
  void*   pIter = taosHashIterate(pStmt->exec.pBlockHash, NULL);
1426
  while (pIter) {
1427
    STableDataCxt* pBlock = *(STableDataCxt**)pIter;
1428
    char*          key = taosHashGetKey(pIter, &keyLen);
1429

1430
    STableMeta* pMeta = qGetTableMetaInDataBlock(pBlock);
1431
    if (pMeta->uid) {
1432
      pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter);
1433
      continue;
1434
    }
1435

1436
    SSubmitBlkRsp* blkRsp = NULL;
1437
    int32_t        i = 0;
1438
    for (; i < pRsp->nBlocks; ++i) {
1439
      blkRsp = pRsp->pBlocks + i;
1440
      if (strlen(blkRsp->tblFName) != keyLen) {
1441
        continue;
1442
      }
1443

1444
      if (strncmp(blkRsp->tblFName, key, keyLen)) {
1445
        continue;
1446
      }
1447

1448
      break;
1449
    }
1450

1451
    if (i < pRsp->nBlocks) {
1452
      tscDebug("auto created table %s uid updated from %" PRIx64 " to %" PRIx64, blkRsp->tblFName, pMeta->uid,
1453
               blkRsp->uid);
1454

1455
      pMeta->uid = blkRsp->uid;
1456
      pStmt->bInfo.tbUid = blkRsp->uid;
1457
    } else {
1458
      tscDebug("table %s not found in submit rsp, will update from catalog", pStmt->bInfo.tbFName);
1459
      if (NULL == pStmt->pCatalog) {
1460
        code = catalogGetHandle(pStmt->taos->pAppInfo->clusterId, &pStmt->pCatalog);
1461
        if (code) {
1462
          pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter);
1463
          finalCode = code;
1464
          continue;
1465
        }
1466
      }
1467

1468
      code = stmtCreateRequest(pStmt);
1469
      if (code) {
1470
        pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter);
1471
        finalCode = code;
1472
        continue;
1473
      }
1474

1475
      STableMeta*      pTableMeta = NULL;
1476
      SRequestConnInfo conn = {.pTrans = pStmt->taos->pAppInfo->pTransporter,
1477
                               .requestId = pStmt->exec.pRequest->requestId,
1478
                               .requestObjRefId = pStmt->exec.pRequest->self,
1479
                               .mgmtEps = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp)};
1480
      code = catalogGetTableMeta(pStmt->pCatalog, &conn, &pStmt->bInfo.sname, &pTableMeta);
1481

1482
      pStmt->stat.ctgGetTbMetaNum++;
1483

1484
      taos_free_result(pStmt->exec.pRequest);
1485
      pStmt->exec.pRequest = NULL;
1486

1487
      if (code || NULL == pTableMeta) {
1488
        pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter);
1489
        finalCode = code;
1490
        taosMemoryFree(pTableMeta);
1491
        continue;
1492
      }
1493

1494
      pMeta->uid = pTableMeta->uid;
1495
      pStmt->bInfo.tbUid = pTableMeta->uid;
1496
      taosMemoryFree(pTableMeta);
1497
    }
1498

1499
    pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter);
1500
  }
1501

1502
  return finalCode;
1503
}
1504
*/
1505

1506
/*
1507
int stmtStaticModeExec(TAOS_STMT* stmt) {
1508
  STscStmt*   pStmt = (STscStmt*)stmt;
1509
  int32_t     code = 0;
1510
  SSubmitRsp* pRsp = NULL;
1511
  if (pStmt->sql.staticMode) {
1512
    return TSDB_CODE_TSC_STMT_API_ERROR;
1513
  }
1514

1515
  STMT_DLOG_E("start to exec");
1516

1517
  STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_EXECUTE));
1518

1519
  STMT_ERR_RET(qBuildStmtOutputFromTbList(pStmt->sql.pQuery, pStmt->sql.pVgHash, pStmt->exec.pTbBlkList,
1520
pStmt->exec.pCurrBlock, pStmt->exec.tbBlkNum));
1521

1522
  launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
1523

1524
  if (pStmt->exec.pRequest->code && NEED_CLIENT_HANDLE_ERROR(pStmt->exec.pRequest->code)) {
1525
    code = refreshMeta(pStmt->exec.pRequest->pTscObj, pStmt->exec.pRequest);
1526
    if (code) {
1527
      pStmt->exec.pRequest->code = code;
1528
    } else {
1529
      tFreeSSubmitRsp(pRsp);
1530
      STMT_ERR_RET(stmtResetStmt(pStmt));
1531
      STMT_ERR_RET(TSDB_CODE_NEED_RETRY);
1532
    }
1533
  }
1534

1535
  STMT_ERR_JRET(pStmt->exec.pRequest->code);
1536

1537
  pStmt->exec.affectedRows = taos_affected_rows(pStmt->exec.pRequest);
1538
  pStmt->affectedRows += pStmt->exec.affectedRows;
1539

1540
_return:
1541

1542
  stmtCleanExecInfo(pStmt, (code ? false : true), false);
1543

1544
  tFreeSSubmitRsp(pRsp);
1545

1546
  ++pStmt->sql.runTimes;
1547

1548
  STMT_RET(code);
1549
}
1550
*/
1551

1552
int stmtExec(TAOS_STMT* stmt) {
2,916✔
1553
  STscStmt*   pStmt = (STscStmt*)stmt;
2,916✔
1554
  int32_t     code = 0;
2,916✔
1555
  SSubmitRsp* pRsp = NULL;
2,916✔
1556

1557
  int64_t startUs = taosGetTimestampUs();
2,918✔
1558

1559
  STMT_DLOG_E("start to exec");
2,918✔
1560

1561
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
2,916!
1562
    return pStmt->errCode;
×
1563
  }
1564

1565
  STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_EXECUTE));
2,916!
1566

1567
  if (STMT_TYPE_QUERY == pStmt->sql.type) {
2,917✔
1568
    launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
3✔
1569
  } else {
1570
    if (pStmt->sql.stbInterlaceMode) {
2,914✔
1571
      int64_t startTs = taosGetTimestampUs();
2,513✔
1572
      while (atomic_load_64(&pStmt->sql.siInfo.tbRemainNum)) {
4,831✔
1573
        taosUsleep(1);
2,316✔
1574
      }
1575
      pStmt->stat.execWaitUs += taosGetTimestampUs() - startTs;
2,515✔
1576

1577
      STMT_ERR_RET(qBuildStmtFinOutput(pStmt->sql.pQuery, pStmt->sql.pVgHash, pStmt->sql.siInfo.pVgroupList));
2,515!
1578
      taosHashCleanup(pStmt->sql.siInfo.pVgroupHash);
2,510✔
1579
      pStmt->sql.siInfo.pVgroupHash = NULL;
2,512✔
1580
      pStmt->sql.siInfo.pVgroupList = NULL;
2,512✔
1581
    } else {
1582
      tDestroySubmitTbData(pStmt->exec.pCurrTbData, TSDB_MSG_FLG_ENCODE);
401✔
1583
      taosMemoryFreeClear(pStmt->exec.pCurrTbData);
407!
1584

1585
      STMT_ERR_RET(qCloneCurrentTbData(pStmt->exec.pCurrBlock, &pStmt->exec.pCurrTbData));
407!
1586

1587
      STMT_ERR_RET(qBuildStmtOutput(pStmt->sql.pQuery, pStmt->sql.pVgHash, pStmt->exec.pBlockHash));
402!
1588
    }
1589

1590
    launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL);
2,917✔
1591
  }
1592

1593
  if (pStmt->exec.pRequest->code && NEED_CLIENT_HANDLE_ERROR(pStmt->exec.pRequest->code)) {
2,924!
1594
    code = refreshMeta(pStmt->exec.pRequest->pTscObj, pStmt->exec.pRequest);
×
1595
    if (code) {
×
1596
      pStmt->exec.pRequest->code = code;
×
1597
    } else {
1598
      tFreeSSubmitRsp(pRsp);
×
1599
      STMT_ERR_RET(stmtResetStmt(pStmt));
×
1600
      STMT_ERR_RET(TSDB_CODE_NEED_RETRY);
×
1601
    }
1602
  }
1603

1604
  STMT_ERR_JRET(pStmt->exec.pRequest->code);
2,924✔
1605

1606
  pStmt->exec.affectedRows = taos_affected_rows(pStmt->exec.pRequest);
2,923✔
1607
  pStmt->affectedRows += pStmt->exec.affectedRows;
2,924✔
1608

1609
_return:
2,925✔
1610

1611
  while (0 == atomic_load_8((int8_t*)&pStmt->sql.siInfo.tableColsReady)) {
2,925!
1612
    taosUsleep(1);
×
1613
  }
1614

1615
  STMT_ERR_RET(stmtCleanExecInfo(pStmt, (code ? false : true), false));
2,922!
1616

1617
  tFreeSSubmitRsp(pRsp);
2,920✔
1618

1619
  ++pStmt->sql.runTimes;
2,919✔
1620

1621
  int64_t startUs2 = taosGetTimestampUs();
2,922✔
1622
  pStmt->stat.execUseUs += startUs2 - startUs;
2,922✔
1623

1624
  STMT_RET(code);
2,922✔
1625
}
1626

1627
int stmtClose(TAOS_STMT* stmt) {
343✔
1628
  STscStmt* pStmt = (STscStmt*)stmt;
343✔
1629

1630
  STMT_DLOG_E("start to free stmt");
343✔
1631

1632
  pStmt->queue.stopQueue = true;
343✔
1633

1634
  (void)taosThreadMutexLock(&pStmt->queue.mutex);
343✔
1635
  (void)taosThreadCondSignal(&(pStmt->queue.waitCond));
344✔
1636
  (void)taosThreadMutexUnlock(&pStmt->queue.mutex);
341✔
1637

1638
  if (pStmt->bindThreadInUse) {
344✔
1639
    (void)taosThreadJoin(pStmt->bindThread, NULL);
47✔
1640
    pStmt->bindThreadInUse = false;
47✔
1641
  }
1642

1643
  (void)taosThreadCondDestroy(&pStmt->queue.waitCond);
344✔
1644
  (void)taosThreadMutexDestroy(&pStmt->queue.mutex);
341✔
1645

1646
  STMT_DLOG("stmt %p closed, stbInterlaceMode: %d, statInfo: ctgGetTbMetaNum=>%" PRId64 ", getCacheTbInfo=>%" PRId64
341✔
1647
            ", parseSqlNum=>%" PRId64 ", pStmt->stat.bindDataNum=>%" PRId64
1648
            ", settbnameAPI:%u, bindAPI:%u, addbatchAPI:%u, execAPI:%u"
1649
            ", setTbNameUs:%" PRId64 ", bindDataUs:%" PRId64 ",%" PRId64 ",%" PRId64 ",%" PRId64 " addBatchUs:%" PRId64
1650
            ", execWaitUs:%" PRId64 ", execUseUs:%" PRId64,
1651
            pStmt, pStmt->sql.stbInterlaceMode, pStmt->stat.ctgGetTbMetaNum, pStmt->stat.getCacheTbInfo,
1652
            pStmt->stat.parseSqlNum, pStmt->stat.bindDataNum, pStmt->seqIds[STMT_SETTBNAME], pStmt->seqIds[STMT_BIND],
1653
            pStmt->seqIds[STMT_ADD_BATCH], pStmt->seqIds[STMT_EXECUTE], pStmt->stat.setTbNameUs,
1654
            pStmt->stat.bindDataUs1, pStmt->stat.bindDataUs2, pStmt->stat.bindDataUs3, pStmt->stat.bindDataUs4,
1655
            pStmt->stat.addBatchUs, pStmt->stat.execWaitUs, pStmt->stat.execUseUs);
1656

1657
  STMT_ERR_RET(stmtCleanSQLInfo(pStmt));
341!
1658
  taosMemoryFree(stmt);
342!
1659

1660
  return TSDB_CODE_SUCCESS;
345✔
1661
}
1662

1663
const char* stmtErrstr(TAOS_STMT* stmt) {
4✔
1664
  STscStmt* pStmt = (STscStmt*)stmt;
4✔
1665

1666
  if (stmt == NULL || NULL == pStmt->exec.pRequest) {
4!
1667
    return (char*)tstrerror(terrno);
1✔
1668
  }
1669

1670
  pStmt->exec.pRequest->code = terrno;
3✔
1671

1672
  return taos_errstr(pStmt->exec.pRequest);
3✔
1673
}
1674

1675
int stmtAffectedRows(TAOS_STMT* stmt) { return ((STscStmt*)stmt)->affectedRows; }
3✔
1676

1677
int stmtAffectedRowsOnce(TAOS_STMT* stmt) { return ((STscStmt*)stmt)->exec.affectedRows; }
×
1678

1679
int stmtIsInsert(TAOS_STMT* stmt, int* insert) {
975,000✔
1680
  STscStmt* pStmt = (STscStmt*)stmt;
975,000✔
1681

1682
  STMT_DLOG_E("start is insert");
975,000✔
1683

1684
  if (pStmt->sql.type) {
989,557✔
1685
    *insert = (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type);
989,184!
1686
  } else {
1687
    *insert = qIsInsertValuesSql(pStmt->sql.sqlStr, pStmt->sql.sqlLen);
373✔
1688
  }
1689

1690
  return TSDB_CODE_SUCCESS;
989,560✔
1691
}
1692

1693
int stmtGetTagFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) {
×
1694
  int32_t   code = 0;
×
1695
  STscStmt* pStmt = (STscStmt*)stmt;
×
1696
  int32_t   preCode = pStmt->errCode;
×
1697

1698
  STMT_DLOG_E("start to get tag fields");
×
1699

1700
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
×
1701
    return pStmt->errCode;
×
1702
  }
1703

1704
  if (STMT_TYPE_QUERY == pStmt->sql.type) {
×
1705
    STMT_ERRI_JRET(TSDB_CODE_TSC_STMT_API_ERROR);
×
1706
  }
1707

1708
  STMT_ERRI_JRET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
×
1709

1710
  if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
×
1711
      STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
×
1712
    pStmt->bInfo.needParse = false;
×
1713
  }
1714

1715
  if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
×
1716
    taos_free_result(pStmt->exec.pRequest);
×
1717
    pStmt->exec.pRequest = NULL;
×
1718
  }
1719

1720
  STMT_ERRI_JRET(stmtCreateRequest(pStmt));
×
1721

1722
  if (pStmt->bInfo.needParse) {
×
1723
    STMT_ERRI_JRET(stmtParseSql(pStmt));
×
1724
  }
1725

1726
  STMT_ERRI_JRET(stmtFetchTagFields(stmt, nums, fields));
×
1727

1728
_return:
×
1729

1730
  pStmt->errCode = preCode;
×
1731

1732
  return code;
×
1733
}
1734

1735
int stmtGetColFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) {
×
1736
  int32_t   code = 0;
×
1737
  STscStmt* pStmt = (STscStmt*)stmt;
×
1738
  int32_t   preCode = pStmt->errCode;
×
1739

1740
  STMT_DLOG_E("start to get col fields");
×
1741

1742
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
×
1743
    return pStmt->errCode;
×
1744
  }
1745

1746
  if (STMT_TYPE_QUERY == pStmt->sql.type) {
×
1747
    STMT_ERRI_JRET(TSDB_CODE_TSC_STMT_API_ERROR);
×
1748
  }
1749

1750
  STMT_ERRI_JRET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
×
1751

1752
  if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
×
1753
      STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
×
1754
    pStmt->bInfo.needParse = false;
×
1755
  }
1756

1757
  if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
×
1758
    taos_free_result(pStmt->exec.pRequest);
×
1759
    pStmt->exec.pRequest = NULL;
×
1760
    STMT_ERR_RET(stmtCreateRequest(pStmt));
×
1761
  }
1762

1763
  STMT_ERRI_JRET(stmtCreateRequest(pStmt));
×
1764

1765
  if (pStmt->bInfo.needParse) {
×
1766
    STMT_ERRI_JRET(stmtParseSql(pStmt));
×
1767
  }
1768

1769
  STMT_ERRI_JRET(stmtFetchColFields(stmt, nums, fields));
×
1770

1771
_return:
×
1772

1773
  pStmt->errCode = preCode;
×
1774

1775
  return code;
×
1776
}
1777

1778
int stmtGetParamNum(TAOS_STMT* stmt, int* nums) {
×
1779
  int       code = 0;
×
1780
  STscStmt* pStmt = (STscStmt*)stmt;
×
1781
  int32_t   preCode = pStmt->errCode;
×
1782

1783
  STMT_DLOG_E("start to get param num");
×
1784

1785
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
×
1786
    return pStmt->errCode;
×
1787
  }
1788

1789
  STMT_ERRI_JRET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
×
1790

1791
  if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
×
1792
      STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
×
1793
    pStmt->bInfo.needParse = false;
×
1794
  }
1795

1796
  if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
×
1797
    taos_free_result(pStmt->exec.pRequest);
×
1798
    pStmt->exec.pRequest = NULL;
×
1799
  }
1800

1801
  STMT_ERRI_JRET(stmtCreateRequest(pStmt));
×
1802

1803
  if (pStmt->bInfo.needParse) {
×
1804
    STMT_ERRI_JRET(stmtParseSql(pStmt));
×
1805
  }
1806

1807
  if (STMT_TYPE_QUERY == pStmt->sql.type) {
×
1808
    *nums = taosArrayGetSize(pStmt->sql.pQuery->pPlaceholderValues);
×
1809
  } else {
1810
    STMT_ERRI_JRET(stmtFetchColFields(stmt, nums, NULL));
×
1811
  }
1812

1813
_return:
×
1814

1815
  pStmt->errCode = preCode;
×
1816

1817
  return code;
×
1818
}
1819

1820
int stmtGetParam(TAOS_STMT* stmt, int idx, int* type, int* bytes) {
×
1821
  int       code = 0;
×
1822
  STscStmt* pStmt = (STscStmt*)stmt;
×
1823
  int32_t   preCode = pStmt->errCode;
×
1824

1825
  STMT_DLOG_E("start to get param");
×
1826

1827
  if (pStmt->errCode != TSDB_CODE_SUCCESS) {
×
1828
    return pStmt->errCode;
×
1829
  }
1830

1831
  if (STMT_TYPE_QUERY == pStmt->sql.type) {
×
1832
    STMT_ERRI_JRET(TSDB_CODE_TSC_STMT_API_ERROR);
×
1833
  }
1834

1835
  STMT_ERRI_JRET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
×
1836

1837
  if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
×
1838
      STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
×
1839
    pStmt->bInfo.needParse = false;
×
1840
  }
1841

1842
  if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
×
1843
    taos_free_result(pStmt->exec.pRequest);
×
1844
    pStmt->exec.pRequest = NULL;
×
1845
  }
1846

1847
  STMT_ERRI_JRET(stmtCreateRequest(pStmt));
×
1848

1849
  if (pStmt->bInfo.needParse) {
×
1850
    STMT_ERRI_JRET(stmtParseSql(pStmt));
×
1851
  }
1852

1853
  int32_t       nums = 0;
×
1854
  TAOS_FIELD_E* pField = NULL;
×
1855
  STMT_ERRI_JRET(stmtFetchColFields(stmt, &nums, &pField));
×
1856
  if (idx >= nums) {
×
1857
    tscError("idx %d is too big", idx);
×
1858
    STMT_ERRI_JRET(TSDB_CODE_INVALID_PARA);
×
1859
  }
1860

1861
  *type = pField[idx].type;
×
1862
  *bytes = pField[idx].bytes;
×
1863

1864
_return:
×
1865

1866
  taosMemoryFree(pField);
×
1867
  pStmt->errCode = preCode;
×
1868

1869
  return code;
×
1870
}
1871

1872
TAOS_RES* stmtUseResult(TAOS_STMT* stmt) {
3✔
1873
  STscStmt* pStmt = (STscStmt*)stmt;
3✔
1874

1875
  STMT_DLOG_E("start to use result");
3✔
1876

1877
  if (STMT_TYPE_QUERY != pStmt->sql.type) {
3!
1878
    tscError("useResult only for query statement");
×
1879
    return NULL;
×
1880
  }
1881

1882
  return pStmt->exec.pRequest;
3✔
1883
}
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