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

taosdata / TDengine / #3630

06 Mar 2025 11:35AM UTC coverage: 63.629% (-0.06%) from 63.692%
#3630

push

travis-ci

web-flow
Merge pull request #30042 from taosdata/doc/internal

docs: format

149060 of 300532 branches covered (49.6%)

Branch coverage included in aggregate %.

233739 of 301077 relevant lines covered (77.63%)

17473135.72 hits per line

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

57.57
/source/client/src/clientMain.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 "catalog.h"
17
#include "clientInt.h"
18
#include "clientLog.h"
19
#include "clientMonitor.h"
20
#include "clientStmt.h"
21
#include "clientStmt2.h"
22
#include "functionMgt.h"
23
#include "os.h"
24
#include "query.h"
25
#include "scheduler.h"
26
#include "tcompare.h"
27
#include "tconv.h"
28
#include "tdatablock.h"
29
#include "tglobal.h"
30
#include "tmsg.h"
31
#include "tref.h"
32
#include "trpc.h"
33
#include "version.h"
34

35
#define TSC_VAR_NOT_RELEASE 1
36
#define TSC_VAR_RELEASED    0
37

38
static int32_t sentinel = TSC_VAR_NOT_RELEASE;
39
static int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper);
40

41
int taos_options(TSDB_OPTION option, const void *arg, ...) {
2,143✔
42
  if (arg == NULL) {
2,143!
43
    return TSDB_CODE_INVALID_PARA;
×
44
  }
45
  static int32_t lock = 0;
46

47
  for (int i = 1; atomic_val_compare_exchange_32(&lock, 0, 1) != 0; ++i) {
52,413✔
48
    if (i % 1000 == 0) {
50,270✔
49
      (void)sched_yield();
49✔
50
    }
51
  }
52

53
  int ret = taos_options_imp(option, (const char *)arg);
2,143✔
54
  atomic_store_32(&lock, 0);
2,143✔
55
  return ret;
2,143✔
56
}
57

58
#ifndef WINDOWS
59
static void freeTz(void *p) {
10✔
60
  timezone_t tz = *(timezone_t *)p;
10✔
61
  tzfree(tz);
10✔
62
}
10✔
63

64
int32_t tzInit() {
3,207✔
65
  pTimezoneMap = taosHashInit(0, MurmurHash3_32, false, HASH_ENTRY_LOCK);
3,207✔
66
  if (pTimezoneMap == NULL) {
3,207!
67
    return terrno;
×
68
  }
69
  taosHashSetFreeFp(pTimezoneMap, freeTz);
3,207✔
70

71
  pTimezoneNameMap = taosHashInit(0, taosIntHash_64, false, HASH_ENTRY_LOCK);
3,207✔
72
  if (pTimezoneNameMap == NULL) {
3,207!
73
    return terrno;
×
74
  }
75
  return 0;
3,207✔
76
}
77

78
void tzCleanup() {
3,208✔
79
  taosHashCleanup(pTimezoneMap);
3,208✔
80
  taosHashCleanup(pTimezoneNameMap);
3,208✔
81
}
3,208✔
82

83
static timezone_t setConnnectionTz(const char *val) {
17✔
84
  timezone_t  tz = NULL;
17✔
85
  timezone_t *tmp = taosHashGet(pTimezoneMap, val, strlen(val));
17✔
86
  if (tmp != NULL && *tmp != NULL) {
17!
87
    tz = *tmp;
7✔
88
    goto END;
7✔
89
  }
90

91
  tscDebug("set timezone to %s", val);
10!
92
  tz = tzalloc(val);
10✔
93
  if (tz == NULL) {
10✔
94
    tscWarn("%s unknown timezone %s change to UTC", __func__, val);
1!
95
    tz = tzalloc("UTC");
1✔
96
    if (tz == NULL) {
1!
97
      tscError("%s set timezone UTC error", __func__);
×
98
      terrno = TAOS_SYSTEM_ERROR(errno);
×
99
      goto END;
×
100
    }
101
  }
102
  int32_t code = taosHashPut(pTimezoneMap, val, strlen(val), &tz, sizeof(timezone_t));
10✔
103
  if (code != 0) {
10!
104
    tscError("%s put timezone to tz map error:%d", __func__, code);
×
105
    tzfree(tz);
×
106
    tz = NULL;
×
107
    goto END;
×
108
  }
109

110
  time_t tx1 = taosGetTimestampSec();
10✔
111
  char   output[TD_TIMEZONE_LEN] = {0};
10✔
112
  code = taosFormatTimezoneStr(tx1, val, tz, output);
10✔
113
  if (code == 0) {
10!
114
    code = taosHashPut(pTimezoneNameMap, &tz, sizeof(timezone_t), output, strlen(output) + 1);
10✔
115
  }
116
  if (code != 0) {
10!
117
    tscError("failed to put timezone %s to map", val);
×
118
  }
119

120
END:
10✔
121
  return tz;
17✔
122
}
123
#endif
124

125
static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, const char *val) {
38✔
126
  if (taos == NULL) {
38✔
127
    return terrno = TSDB_CODE_INVALID_PARA;
1✔
128
  }
129

130
#ifdef WINDOWS
131
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE) {
132
    return terrno = TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS;
133
  }
134
#endif
135

136
  if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION) {
37!
137
    return terrno = TSDB_CODE_INVALID_PARA;
1✔
138
  }
139

140
  int32_t code = taos_init();
36✔
141
  // initialize global config
142
  if (code != 0) {
36!
143
    return terrno = code;
×
144
  }
145

146
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
36✔
147
  if (NULL == pObj) {
36!
148
    tscError("invalid parameter for %s", __func__);
×
149
    return terrno;
×
150
  }
151

152
  if (option == TSDB_OPTION_CONNECTION_CLEAR) {
36✔
153
    val = NULL;
1✔
154
  }
155

156
  if (option == TSDB_OPTION_CONNECTION_CHARSET || option == TSDB_OPTION_CONNECTION_CLEAR) {
36✔
157
    if (val != NULL) {
8✔
158
      if (!taosValidateEncodec(val)) {
5✔
159
        code = terrno;
1✔
160
        goto END;
1✔
161
      }
162
      void *tmp = taosConvInit(val);
4✔
163
      if (tmp == NULL) {
4✔
164
        code = terrno;
1✔
165
        goto END;
1✔
166
      }
167
      pObj->optionInfo.charsetCxt = tmp;
3✔
168
    } else {
169
      pObj->optionInfo.charsetCxt = NULL;
3✔
170
    }
171
  }
172

173
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) {
34✔
174
#ifndef WINDOWS
175
    if (val != NULL) {
19✔
176
      if (val[0] == 0) {
17✔
177
        val = "UTC";
1✔
178
      }
179
      timezone_t tz = setConnnectionTz(val);
17✔
180
      if (tz == NULL) {
17!
181
        code = terrno;
×
182
        goto END;
×
183
      }
184
      pObj->optionInfo.timezone = tz;
17✔
185
    } else {
186
      pObj->optionInfo.timezone = NULL;
2✔
187
    }
188
#endif
189
  }
190

191
  if (option == TSDB_OPTION_CONNECTION_USER_APP || option == TSDB_OPTION_CONNECTION_CLEAR) {
34✔
192
    if (val != NULL) {
5✔
193
      tstrncpy(pObj->optionInfo.userApp, val, sizeof(pObj->optionInfo.userApp));
3✔
194
    } else {
195
      pObj->optionInfo.userApp[0] = 0;
2✔
196
    }
197
  }
198

199
  if (option == TSDB_OPTION_CONNECTION_USER_IP || option == TSDB_OPTION_CONNECTION_CLEAR) {
34✔
200
    if (val != NULL) {
7✔
201
      pObj->optionInfo.userIp = taosInetAddr(val);
5✔
202
      if (pObj->optionInfo.userIp == INADDR_NONE) {
5✔
203
        code = TSDB_CODE_INVALID_PARA;
3✔
204
        goto END;
3✔
205
      }
206
    } else {
207
      pObj->optionInfo.userIp = INADDR_NONE;
2✔
208
    }
209
  }
210

211
END:
27✔
212
  releaseTscObj(*(int64_t *)taos);
36✔
213
  return terrno = code;
36✔
214
}
215

216
int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...) {
38✔
217
  return setConnectionOption(taos, option, (const char *)arg);
38✔
218
}
219

220
// this function may be called by user or system, or by both simultaneously.
221
void taos_cleanup(void) {
3,223✔
222
  tscDebug("start to cleanup client environment");
3,223✔
223
  if (atomic_val_compare_exchange_32(&sentinel, TSC_VAR_NOT_RELEASE, TSC_VAR_RELEASED) != TSC_VAR_NOT_RELEASE) {
3,223✔
224
    return;
15✔
225
  }
226

227
  monitorClose();
3,208✔
228
  tscStopCrashReport();
3,208✔
229

230
  hbMgrCleanUp();
3,208✔
231

232
  catalogDestroy();
3,208✔
233
  schedulerDestroy();
3,208✔
234

235
  fmFuncMgtDestroy();
3,208✔
236
  qCleanupKeywordsTable();
3,208✔
237

238
  if (TSDB_CODE_SUCCESS != cleanupTaskQueue()) {
3,208!
239
    tscWarn("failed to cleanup task queue");
×
240
  }
241

242
#ifndef WINDOWS
243
  tzCleanup();
3,208✔
244
#endif
245
  tmqMgmtClose();
3,208✔
246

247
  int32_t id = clientReqRefPool;
3,208✔
248
  clientReqRefPool = -1;
3,208✔
249
  taosCloseRef(id);
3,208✔
250

251
  id = clientConnRefPool;
3,208✔
252
  clientConnRefPool = -1;
3,208✔
253
  taosCloseRef(id);
3,208✔
254

255
  nodesDestroyAllocatorSet();
3,208✔
256
  cleanupAppInfo();
3,208✔
257
  rpcCleanup();
3,208✔
258
  tscDebug("rpc cleanup");
3,208✔
259

260
  taosConvDestroy();
3,208✔
261
  DestroyRegexCache();
3,208✔
262

263
  tscInfo("all local resources released");
3,208!
264
  taosCleanupCfg();
3,208✔
265
  taosCloseLog();
3,208✔
266
}
267

268
static setConfRet taos_set_config_imp(const char *config) {
×
269
  setConfRet ret = {SET_CONF_RET_SUCC, {0}};
×
270
  // TODO: need re-implementation
271
  return ret;
×
272
}
273

274
setConfRet taos_set_config(const char *config) {
×
275
  // TODO  pthread_mutex_lock(&setConfMutex);
276
  setConfRet ret = taos_set_config_imp(config);
×
277
  //  pthread_mutex_unlock(&setConfMutex);
278
  return ret;
×
279
}
280

281
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
14,680✔
282
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
14,680!
283
  if (user == NULL) {
14,680!
284
    user = TSDB_DEFAULT_USER;
×
285
  }
286

287
  if (pass == NULL) {
14,680!
288
    pass = TSDB_DEFAULT_PASS;
×
289
  }
290

291
  STscObj *pObj = NULL;
14,680✔
292
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY, &pObj);
14,680✔
293
  if (TSDB_CODE_SUCCESS == code) {
14,680✔
294
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
14,629!
295
    if (NULL == rid) {
14,629!
296
      tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db);
×
297
      return NULL;
×
298
    }
299
    *rid = pObj->id;
14,629✔
300
    return (TAOS *)rid;
14,629✔
301
  } else {
302
    terrno = code;
51✔
303
  }
304

305
  return NULL;
51✔
306
}
307

308
int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type) {
70✔
309
  if (taos == NULL) {
70!
310
    terrno = TSDB_CODE_INVALID_PARA;
×
311
    return terrno;
×
312
  }
313

314
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
70✔
315
  if (NULL == pObj) {
70!
316
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
317
    tscError("invalid parameter for %s", __func__);
×
318
    return terrno;
×
319
  }
320

321
  switch (type) {
70!
322
    case TAOS_NOTIFY_PASSVER: {
20✔
323
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
20!
324
      pObj->passInfo.fp = fp;
20✔
325
      pObj->passInfo.param = param;
20✔
326
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
20!
327
      break;
20✔
328
    }
329
    case TAOS_NOTIFY_WHITELIST_VER: {
×
330
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
331
      pObj->whiteListInfo.fp = fp;
×
332
      pObj->whiteListInfo.param = param;
×
333
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
334
      break;
×
335
    }
336
    case TAOS_NOTIFY_USER_DROPPED: {
50✔
337
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
50!
338
      pObj->userDroppedInfo.fp = fp;
50✔
339
      pObj->userDroppedInfo.param = param;
50✔
340
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
50!
341
      break;
50✔
342
    }
343
    default: {
×
344
      terrno = TSDB_CODE_INVALID_PARA;
×
345
      releaseTscObj(*(int64_t *)taos);
×
346
      return terrno;
×
347
    }
348
  }
349

350
  releaseTscObj(*(int64_t *)taos);
70✔
351
  return 0;
70✔
352
}
353

354
typedef struct SFetchWhiteListInfo {
355
  int64_t                     connId;
356
  __taos_async_whitelist_fn_t userCbFn;
357
  void                       *userParam;
358
} SFetchWhiteListInfo;
359

360
int32_t fetchWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
361
  SFetchWhiteListInfo *pInfo = (SFetchWhiteListInfo *)param;
×
362
  TAOS                *taos = &pInfo->connId;
×
363
  if (code != TSDB_CODE_SUCCESS) {
×
364
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
365
    taosMemoryFree(pMsg->pData);
×
366
    taosMemoryFree(pMsg->pEpSet);
×
367
    taosMemoryFree(pInfo);
×
368
    return code;
×
369
  }
370

371
  SGetUserWhiteListRsp wlRsp;
372
  if (TSDB_CODE_SUCCESS != tDeserializeSGetUserWhiteListRsp(pMsg->pData, pMsg->len, &wlRsp)) {
×
373
    taosMemoryFree(pMsg->pData);
×
374
    taosMemoryFree(pMsg->pEpSet);
×
375
    taosMemoryFree(pInfo);
×
376
    tFreeSGetUserWhiteListRsp(&wlRsp);
×
377
    return terrno;
×
378
  }
379

380
  uint64_t *pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(uint64_t));
×
381
  if (pWhiteLists == NULL) {
×
382
    taosMemoryFree(pMsg->pData);
×
383
    taosMemoryFree(pMsg->pEpSet);
×
384
    taosMemoryFree(pInfo);
×
385
    tFreeSGetUserWhiteListRsp(&wlRsp);
×
386
    return terrno;
×
387
  }
388

389
  for (int i = 0; i < wlRsp.numWhiteLists; ++i) {
×
390
    pWhiteLists[i] = ((uint64_t)wlRsp.pWhiteLists[i].mask << 32) | wlRsp.pWhiteLists[i].ip;
×
391
  }
392

393
  pInfo->userCbFn(pInfo->userParam, code, taos, wlRsp.numWhiteLists, pWhiteLists);
×
394

395
  taosMemoryFree(pWhiteLists);
×
396
  taosMemoryFree(pMsg->pData);
×
397
  taosMemoryFree(pMsg->pEpSet);
×
398
  taosMemoryFree(pInfo);
×
399
  tFreeSGetUserWhiteListRsp(&wlRsp);
×
400
  return code;
×
401
}
402

403
void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *param) {
×
404
  if (NULL == taos) {
×
405
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
406
    return;
×
407
  }
408

409
  int64_t connId = *(int64_t *)taos;
×
410

411
  STscObj *pTsc = acquireTscObj(connId);
×
412
  if (NULL == pTsc) {
×
413
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
414
    return;
×
415
  }
416

417
  SGetUserWhiteListReq req;
418
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
419
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
420
  if (msgLen < 0) {
×
421
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
422
    releaseTscObj(connId);
×
423
    return;
×
424
  }
425

426
  void *pReq = taosMemoryMalloc(msgLen);
×
427
  if (pReq == NULL) {
×
428
    fp(param, terrno, taos, 0, NULL);
×
429
    releaseTscObj(connId);
×
430
    return;
×
431
  }
432

433
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
434
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
435
    taosMemoryFree(pReq);
×
436
    releaseTscObj(connId);
×
437
    return;
×
438
  }
439

440
  SFetchWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchWhiteListInfo));
×
441
  if (pParam == NULL) {
×
442
    fp(param, terrno, taos, 0, NULL);
×
443
    taosMemoryFree(pReq);
×
444
    releaseTscObj(connId);
×
445
    return;
×
446
  }
447

448
  pParam->connId = connId;
×
449
  pParam->userCbFn = fp;
×
450
  pParam->userParam = param;
×
451
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
452
  if (pSendInfo == NULL) {
×
453
    fp(param, terrno, taos, 0, NULL);
×
454
    taosMemoryFree(pParam);
×
455
    taosMemoryFree(pReq);
×
456
    releaseTscObj(connId);
×
457
    return;
×
458
  }
459

460
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
461
  pSendInfo->requestId = generateRequestId();
×
462
  pSendInfo->requestObjRefId = 0;
×
463
  pSendInfo->param = pParam;
×
464
  pSendInfo->fp = fetchWhiteListCallbackFn;
×
465
  pSendInfo->msgType = TDMT_MND_GET_USER_WHITELIST;
×
466

467
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
468
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
469
    tscWarn("failed to async send msg to server");
×
470
  }
471
  releaseTscObj(connId);
×
472
  return;
×
473
}
474

475
void taos_close_internal(void *taos) {
15,089✔
476
  if (taos == NULL) {
15,089!
477
    return;
×
478
  }
479

480
  STscObj *pTscObj = (STscObj *)taos;
15,089✔
481
  tscDebug("connObj:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
15,089✔
482

483
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
15,089!
484
    tscError("connObj:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
×
485
  }
486
}
487

488
void taos_close(TAOS *taos) {
15,511✔
489
  if (taos == NULL) {
15,511✔
490
    return;
888✔
491
  }
492

493
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
14,623✔
494
  if (NULL == pObj) {
14,623!
495
    taosMemoryFree(taos);
×
496
    return;
×
497
  }
498

499
  taos_close_internal(pObj);
14,623✔
500
  releaseTscObj(*(int64_t *)taos);
14,623✔
501
  taosMemoryFree(taos);
14,623!
502
}
503

504
int taos_errno(TAOS_RES *res) {
4,636,252✔
505
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
4,636,252!
506
    return terrno;
×
507
  }
508

509
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
4,636,463✔
510
    return 0;
479✔
511
  }
512

513
  return ((SRequestObj *)res)->code;
4,635,984✔
514
}
515

516
const char *taos_errstr(TAOS_RES *res) {
92,357✔
517
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
92,357!
518
    return (const char *)tstrerror(terrno);
118✔
519
  }
520

521
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
92,239!
522
    return "success";
×
523
  }
524

525
  SRequestObj *pRequest = (SRequestObj *)res;
92,239✔
526
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
92,239!
527
    return pRequest->msgBuf;
84,080✔
528
  } else {
529
    return (const char *)tstrerror(pRequest->code);
8,159✔
530
  }
531
}
532

533
void taos_free_result(TAOS_RES *res) {
3,408,158✔
534
  if (NULL == res) {
3,408,158✔
535
    return;
2,058✔
536
  }
537

538
  tscTrace("res:%p, will be freed", res);
3,406,100✔
539

540
  if (TD_RES_QUERY(res)) {
3,406,306✔
541
    SRequestObj *pRequest = (SRequestObj *)res;
3,295,373✔
542
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query", pRequest->requestId);
3,295,373✔
543
    destroyRequest(pRequest);
3,295,373✔
544
    return;
3,295,427✔
545
  }
546

547
  SMqRspObj *pRsp = (SMqRspObj *)res;
110,933✔
548
  if (TD_RES_TMQ(res)) {
110,933✔
549
    tDeleteMqDataRsp(&pRsp->dataRsp);
110,659✔
550
    doFreeReqResultInfo(&pRsp->resInfo);
110,658✔
551
  } else if (TD_RES_TMQ_METADATA(res)) {
274✔
552
    tDeleteSTaosxRsp(&pRsp->dataRsp);
13✔
553
    doFreeReqResultInfo(&pRsp->resInfo);
13✔
554
  } else if (TD_RES_TMQ_META(res)) {
261✔
555
    tDeleteMqMetaRsp(&pRsp->metaRsp);
227✔
556
  } else if (TD_RES_TMQ_BATCH_META(res)) {
34✔
557
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
17✔
558
  } else if (TD_RES_TMQ_RAW(res)) {
17!
559
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
17✔
560
  }
561
  taosMemoryFree(pRsp);
110,931!
562
}
563

564
void taos_kill_query(TAOS *taos) {
10✔
565
  if (NULL == taos) {
10✔
566
    return;
5✔
567
  }
568

569
  int64_t  rid = *(int64_t *)taos;
5✔
570
  STscObj *pTscObj = acquireTscObj(rid);
5✔
571
  if (pTscObj) {
5!
572
    stopAllRequests(pTscObj->pRequests);
5✔
573
  }
574
  releaseTscObj(rid);
5✔
575
}
576

577
int taos_field_count(TAOS_RES *res) {
67,355,945✔
578
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
67,355,945!
579
    return 0;
1,055✔
580
  }
581

582
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
67,354,890✔
583
  return pResInfo->numOfCols;
67,354,890✔
584
}
585

586
int taos_num_fields(TAOS_RES *res) { return taos_field_count(res); }
47,864,694✔
587

588
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
16,812,790✔
589
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
16,812,790!
590
    return NULL;
132,532✔
591
  }
592

593
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
16,680,044✔
594
  return pResInfo->userFields;
16,680,044✔
595
}
596

597
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
3,181,539✔
598
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
×
599
  return taosQueryImplWithReqid(taos, sql, false, reqid);
×
600
}
601

602
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
43,644,408✔
603
  if (res == NULL) {
43,644,408!
604
    return NULL;
×
605
  }
606

607
  if (TD_RES_QUERY(res)) {
43,644,408✔
608
    SRequestObj *pRequest = (SRequestObj *)res;
28,164,097✔
609
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
28,164,097✔
610
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0 || pRequest->killed) {
28,163,535✔
611
      return NULL;
551✔
612
    }
613

614
    if (pRequest->inCallback) {
28,158,775!
615
      tscError("can not call taos_fetch_row before query callback ends.");
×
616
      terrno = TSDB_CODE_TSC_INVALID_OPERATION;
×
617
      return NULL;
×
618
    }
619

620
    return doAsyncFetchRows(pRequest, true, true);
28,158,775✔
621
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
15,480,311!
622
    SMqRspObj      *msg = ((SMqRspObj *)res);
15,480,311✔
623
    SReqResultInfo *pResultInfo = NULL;
15,480,311✔
624
    if (msg->resIter == -1) {
15,480,311✔
625
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
110,165!
626
        return NULL;
×
627
      }
628
    } else {
629
      pResultInfo = tmqGetCurResInfo(res);
15,370,146✔
630
    }
631

632
    if (pResultInfo->current < pResultInfo->numOfRows) {
15,480,310✔
633
      doSetOneRowPtr(pResultInfo);
15,147,207✔
634
      pResultInfo->current += 1;
15,146,710✔
635
      return pResultInfo->row;
15,146,710✔
636
    } else {
637
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
333,103✔
638
        return NULL;
110,159✔
639
      }
640

641
      doSetOneRowPtr(pResultInfo);
223,046✔
642
      pResultInfo->current += 1;
223,048✔
643
      return pResultInfo->row;
223,048✔
644
    }
645
  } else if (TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
646
    return NULL;
×
647
  } else {
648
    tscError("invalid result passed to taos_fetch_row");
×
649
    terrno = TSDB_CODE_TMQ_INVALID_DATA;
×
650
    return NULL;
×
651
  }
652
}
653

654
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
15,451,135✔
655
  return taos_print_row_with_size(str, INT32_MAX, row, fields, num_fields);
15,451,135✔
656
}
657
int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
15,451,078✔
658
  int32_t len = 0;
15,451,078✔
659
  for (int i = 0; i < num_fields; ++i) {
92,640,211✔
660
    if (i > 0 && len < size - 1) {
77,186,005!
661
      str[len++] = ' ';
61,749,635✔
662
    }
663

664
    if (row[i] == NULL) {
77,186,005✔
665
      len += tsnprintf(str + len, size - len, "%s", TSDB_DATA_NULL_STR);
556,145✔
666
      continue;
556,142✔
667
    }
668

669
    switch (fields[i].type) {
76,629,860!
670
      case TSDB_DATA_TYPE_TINYINT:
26,526✔
671
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
26,526✔
672
        break;
26,526✔
673

674
      case TSDB_DATA_TYPE_UTINYINT:
27,570✔
675
        len += tsnprintf(str + len, size - len, "%u", *((uint8_t *)row[i]));
27,570✔
676
        break;
27,570✔
677

678
      case TSDB_DATA_TYPE_SMALLINT:
27,382✔
679
        len += tsnprintf(str + len, size - len, "%d", *((int16_t *)row[i]));
27,382✔
680
        break;
27,382✔
681

682
      case TSDB_DATA_TYPE_USMALLINT:
25,970✔
683
        len += tsnprintf(str + len, size - len, "%u", *((uint16_t *)row[i]));
25,970✔
684
        break;
25,970✔
685

686
      case TSDB_DATA_TYPE_INT:
16,311,874✔
687
        len += tsnprintf(str + len, size - len, "%d", *((int32_t *)row[i]));
16,311,874✔
688
        break;
16,312,476✔
689

690
      case TSDB_DATA_TYPE_UINT:
25,970✔
691
        len += tsnprintf(str + len, size - len, "%u", *((uint32_t *)row[i]));
25,970✔
692
        break;
25,970✔
693

694
      case TSDB_DATA_TYPE_BIGINT:
13,970,630✔
695
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
13,970,630✔
696
        break;
13,971,602✔
697

698
      case TSDB_DATA_TYPE_UBIGINT:
26,590✔
699
        len += tsnprintf(str + len, size - len, "%" PRIu64, *((uint64_t *)row[i]));
26,590✔
700
        break;
26,590✔
701

702
      case TSDB_DATA_TYPE_FLOAT: {
26,831✔
703
        float fv = 0;
26,831✔
704
        fv = GET_FLOAT_VAL(row[i]);
26,831✔
705
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
26,831✔
706
      } break;
26,831✔
707

708
      case TSDB_DATA_TYPE_DOUBLE: {
8,116,535✔
709
        double dv = 0;
8,116,535✔
710
        dv = GET_DOUBLE_VAL(row[i]);
8,116,535✔
711
        len += snprintf(str + len, size - len, "%.*g", DBL_DIG, dv);
8,116,535✔
712
      } break;
8,116,535✔
713

714
      case TSDB_DATA_TYPE_VARBINARY: {
202✔
715
        void    *data = NULL;
202✔
716
        uint32_t tmp = 0;
202✔
717
        int32_t  charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
202✔
718
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
202!
719
          break;
×
720
        }
721
        uint32_t copyLen = TMIN(size - len - 1, tmp);
202✔
722
        (void)memcpy(str + len, data, copyLen);
202✔
723
        len += copyLen;
202✔
724
        taosMemoryFree(data);
202!
725
      } break;
202✔
726
      case TSDB_DATA_TYPE_BINARY:
17,081,318✔
727
      case TSDB_DATA_TYPE_NCHAR:
728
      case TSDB_DATA_TYPE_GEOMETRY: {
729
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
17,081,318✔
730
        if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_VARBINARY ||
17,081,318!
731
            fields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
5,486,673✔
732
          if (charLen > fields[i].bytes || charLen < 0) {
11,594,839!
733
            tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
×
734
            break;
×
735
          }
736
        } else {
737
          if (charLen > fields[i].bytes * TSDB_NCHAR_SIZE || charLen < 0) {
5,486,479✔
738
            tscError("taos_print_row error. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
2,169!
739
            break;
×
740
          }
741
        }
742

743
        uint32_t copyLen = TMIN(size - len - 1, charLen);
17,080,640✔
744
        (void)memcpy(str + len, row[i], copyLen);
17,080,640✔
745
        len += copyLen;
17,080,640✔
746
      } break;
17,080,640✔
747

748
      case TSDB_DATA_TYPE_TIMESTAMP:
20,922,465✔
749
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
20,922,465✔
750
        break;
20,924,700✔
751

752
      case TSDB_DATA_TYPE_BOOL:
71,570✔
753
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
71,570✔
754
      default:
39,997✔
755
        break;
39,997✔
756
    }
757

758
    if (len >= size - 1) {
76,632,991!
759
      break;
×
760
    }
761
  }
762
  if (len < size) {
15,454,206✔
763
    str[len] = 0;
15,450,923✔
764
  }
765

766
  return len;
15,454,206✔
767
}
768

769
int *taos_fetch_lengths(TAOS_RES *res) {
19,886,782✔
770
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
19,886,782!
771
    return NULL;
×
772
  }
773

774
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
19,886,887✔
775
  return pResInfo->length;
19,886,887✔
776
}
777

778
TAOS_ROW *taos_result_block(TAOS_RES *res) {
×
779
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
780
    terrno = TSDB_CODE_INVALID_PARA;
×
781
    return NULL;
×
782
  }
783

784
  if (taos_is_update_query(res)) {
×
785
    return NULL;
×
786
  }
787

788
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
789
  return &pResInfo->row;
×
790
}
791

792
// todo intergrate with tDataTypes
793
const char *taos_data_type(int type) {
×
794
  switch (type) {
×
795
    case TSDB_DATA_TYPE_NULL:
×
796
      return "TSDB_DATA_TYPE_NULL";
×
797
    case TSDB_DATA_TYPE_BOOL:
×
798
      return "TSDB_DATA_TYPE_BOOL";
×
799
    case TSDB_DATA_TYPE_TINYINT:
×
800
      return "TSDB_DATA_TYPE_TINYINT";
×
801
    case TSDB_DATA_TYPE_SMALLINT:
×
802
      return "TSDB_DATA_TYPE_SMALLINT";
×
803
    case TSDB_DATA_TYPE_INT:
×
804
      return "TSDB_DATA_TYPE_INT";
×
805
    case TSDB_DATA_TYPE_BIGINT:
×
806
      return "TSDB_DATA_TYPE_BIGINT";
×
807
    case TSDB_DATA_TYPE_FLOAT:
×
808
      return "TSDB_DATA_TYPE_FLOAT";
×
809
    case TSDB_DATA_TYPE_DOUBLE:
×
810
      return "TSDB_DATA_TYPE_DOUBLE";
×
811
    case TSDB_DATA_TYPE_VARCHAR:
×
812
      return "TSDB_DATA_TYPE_VARCHAR";
×
813
      //    case TSDB_DATA_TYPE_BINARY:          return "TSDB_DATA_TYPE_VARCHAR";
814
    case TSDB_DATA_TYPE_TIMESTAMP:
×
815
      return "TSDB_DATA_TYPE_TIMESTAMP";
×
816
    case TSDB_DATA_TYPE_NCHAR:
×
817
      return "TSDB_DATA_TYPE_NCHAR";
×
818
    case TSDB_DATA_TYPE_JSON:
×
819
      return "TSDB_DATA_TYPE_JSON";
×
820
    case TSDB_DATA_TYPE_GEOMETRY:
×
821
      return "TSDB_DATA_TYPE_GEOMETRY";
×
822
    case TSDB_DATA_TYPE_UTINYINT:
×
823
      return "TSDB_DATA_TYPE_UTINYINT";
×
824
    case TSDB_DATA_TYPE_USMALLINT:
×
825
      return "TSDB_DATA_TYPE_USMALLINT";
×
826
    case TSDB_DATA_TYPE_UINT:
×
827
      return "TSDB_DATA_TYPE_UINT";
×
828
    case TSDB_DATA_TYPE_UBIGINT:
×
829
      return "TSDB_DATA_TYPE_UBIGINT";
×
830
    case TSDB_DATA_TYPE_VARBINARY:
×
831
      return "TSDB_DATA_TYPE_VARBINARY";
×
832
    case TSDB_DATA_TYPE_DECIMAL:
×
833
      return "TSDB_DATA_TYPE_DECIMAL";
×
834
    case TSDB_DATA_TYPE_BLOB:
×
835
      return "TSDB_DATA_TYPE_BLOB";
×
836
    case TSDB_DATA_TYPE_MEDIUMBLOB:
×
837
      return "TSDB_DATA_TYPE_MEDIUMBLOB";
×
838
    default:
×
839
      return "UNKNOWN";
×
840
  }
841
}
842

843
const char *taos_get_client_info() { return td_version; }
3,251✔
844

845
// return int32_t
846
int taos_affected_rows(TAOS_RES *res) {
1,592,623✔
847
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,592,623!
848
      TD_RES_TMQ_BATCH_META(res)) {
1,592,624✔
849
    return 0;
×
850
  }
851

852
  SRequestObj    *pRequest = (SRequestObj *)res;
1,592,623✔
853
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
1,592,623✔
854
  return (int)pResInfo->numOfRows;
1,592,623✔
855
}
856

857
// return int64_t
858
int64_t taos_affected_rows64(TAOS_RES *res) {
125,002✔
859
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
125,002!
860
      TD_RES_TMQ_BATCH_META(res)) {
125,002!
861
    return 0;
×
862
  }
863

864
  SRequestObj    *pRequest = (SRequestObj *)res;
125,002✔
865
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
125,002✔
866
  return pResInfo->numOfRows;
125,002✔
867
}
868

869
int taos_result_precision(TAOS_RES *res) {
16,373,403✔
870
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
16,373,403!
871
    return TSDB_TIME_PRECISION_MILLI;
×
872
  }
873

874
  if (TD_RES_QUERY(res)) {
16,373,422✔
875
    SRequestObj *pRequest = (SRequestObj *)res;
1,001,301✔
876
    return pRequest->body.resInfo.precision;
1,001,301✔
877
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
15,372,121!
878
    SReqResultInfo *info = tmqGetCurResInfo(res);
15,372,121✔
879
    return info->precision;
15,372,121✔
880
  }
881
  return TSDB_TIME_PRECISION_MILLI;
×
882
}
883

884
int taos_select_db(TAOS *taos, const char *db) {
390✔
885
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
390✔
886
  if (pObj == NULL) {
390!
887
    releaseTscObj(*(int64_t *)taos);
×
888
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
889
    return TSDB_CODE_TSC_DISCONNECTED;
×
890
  }
891

892
  if (db == NULL || strlen(db) == 0) {
390!
893
    releaseTscObj(*(int64_t *)taos);
×
894
    tscError("invalid parameter for %s", db == NULL ? "db is NULL" : "db is empty");
×
895
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
896
    return terrno;
×
897
  }
898

899
  char sql[256] = {0};
390✔
900
  (void)snprintf(sql, tListLen(sql), "use %s", db);
390✔
901

902
  TAOS_RES *pRequest = taos_query(taos, sql);
390✔
903
  int32_t   code = taos_errno(pRequest);
390✔
904

905
  taos_free_result(pRequest);
390✔
906
  releaseTscObj(*(int64_t *)taos);
390✔
907
  return code;
390✔
908
}
909

910
void taos_stop_query(TAOS_RES *res) {
3,312,293✔
911
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
3,312,293!
912
      TD_RES_TMQ_BATCH_META(res)) {
3,312,491!
913
    return;
×
914
  }
915

916
  stopAllQueries((SRequestObj *)res);
3,312,515✔
917
}
918

919
bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
304,278,483✔
920
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
304,278,483!
921
    return true;
×
922
  }
923
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
304,278,503✔
924
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
304,278,503!
925
    return true;
×
926
  }
927

928
  SResultColumn *pCol = &pResultInfo->pCol[col];
304,278,520✔
929
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
304,278,520!
930
    return (pCol->offset[row] == -1);
22✔
931
  } else {
932
    return colDataIsNull_f(pCol->nullbitmap, row);
304,278,498✔
933
  }
934
}
935

936
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
×
937

938
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
1,288,278✔
939
  int32_t numOfRows = 0;
1,288,278✔
940
  /*int32_t code = */ terrno = taos_fetch_block_s(res, &numOfRows, rows);
1,288,278✔
941
  return numOfRows;
1,288,278✔
942
}
943

944
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
1,288,278✔
945
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,288,278!
946
    return 0;
×
947
  }
948

949
  if (TD_RES_QUERY(res)) {
1,288,278✔
950
    SRequestObj *pRequest = (SRequestObj *)res;
1,284,186✔
951

952
    (*rows) = NULL;
1,284,186✔
953
    (*numOfRows) = 0;
1,284,186✔
954

955
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
1,284,186!
956
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
1,281,677!
957
      return pRequest->code;
6,282✔
958
    }
959

960
    (void)doAsyncFetchRows(pRequest, false, true);
1,277,904✔
961

962
    // TODO refactor
963
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
1,277,904✔
964
    pResultInfo->current = pResultInfo->numOfRows;
1,277,904✔
965

966
    (*rows) = pResultInfo->row;
1,277,904✔
967
    (*numOfRows) = pResultInfo->numOfRows;
1,277,904✔
968
    return pRequest->code;
1,277,904✔
969
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
4,092!
970
    SReqResultInfo *pResultInfo = NULL;
4,092✔
971
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
4,092✔
972
    if (code != 0) return code;
4,092✔
973

974
    pResultInfo->current = pResultInfo->numOfRows;
3,662✔
975
    (*rows) = pResultInfo->row;
3,662✔
976
    (*numOfRows) = pResultInfo->numOfRows;
3,662✔
977
    return 0;
3,662✔
978
  } else {
979
    tscError("taos_fetch_block_s invalid res type");
×
980
    return TSDB_CODE_TMQ_INVALID_DATA;
×
981
  }
982
}
983

984
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
8✔
985
  *numOfRows = 0;
8✔
986
  *pData = NULL;
8✔
987

988
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
8!
989
    return 0;
×
990
  }
991

992
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
8!
993
    SReqResultInfo *pResultInfo = NULL;
×
994
    int32_t         code = tmqGetNextResInfo(res, false, &pResultInfo);
×
995
    if (code != 0) {
×
996
      (*numOfRows) = 0;
×
997
      return 0;
×
998
    }
999

1000
    pResultInfo->current = pResultInfo->numOfRows;
×
1001
    (*numOfRows) = pResultInfo->numOfRows;
×
1002
    (*pData) = (void *)pResultInfo->pData;
×
1003
    return 0;
×
1004
  }
1005

1006
  SRequestObj *pRequest = (SRequestObj *)res;
8✔
1007

1008
  if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
8!
1009
      pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
8!
1010
    return pRequest->code;
×
1011
  }
1012

1013
  (void)doAsyncFetchRows(pRequest, false, false);
8✔
1014

1015
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
8✔
1016

1017
  pResultInfo->current = pResultInfo->numOfRows;
8✔
1018
  (*numOfRows) = pResultInfo->numOfRows;
8✔
1019
  (*pData) = (void *)pResultInfo->pData;
8✔
1020

1021
  return pRequest->code;
8✔
1022
}
1023

1024
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
524,167✔
1025
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
524,167!
1026
    return 0;
×
1027
  }
1028

1029
  int32_t numOfFields = taos_num_fields(res);
524,167✔
1030
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
524,167!
1031
    return 0;
×
1032
  }
1033

1034
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
524,167✔
1035
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
524,167✔
1036
  if (!IS_VAR_DATA_TYPE(pField->type)) {
524,167!
1037
    return 0;
×
1038
  }
1039

1040
  return pResInfo->pCol[columnIndex].offset;
524,167✔
1041
}
1042

1043
int taos_is_null_by_column(TAOS_RES *res, int columnIndex, bool result[], int *rows) {
×
1044
  if (res == NULL || result == NULL || rows == NULL || *rows <= 0 || columnIndex < 0 || TD_RES_TMQ_META(res) ||
×
1045
      TD_RES_TMQ_RAW(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1046
    return TSDB_CODE_INVALID_PARA;
×
1047
  }
1048

1049
  int32_t numOfFields = taos_num_fields(res);
×
1050
  if (columnIndex >= numOfFields || numOfFields == 0) {
×
1051
    return TSDB_CODE_INVALID_PARA;
×
1052
  }
1053

1054
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
1055
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
×
1056
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
×
1057

1058
  if (*rows > pResInfo->numOfRows) {
×
1059
    *rows = pResInfo->numOfRows;
×
1060
  }
1061
  if (IS_VAR_DATA_TYPE(pField->type)) {
×
1062
    for (int i = 0; i < *rows; i++) {
×
1063
      if (pCol->offset[i] == -1) {
×
1064
        result[i] = true;
×
1065
      } else {
1066
        result[i] = false;
×
1067
      }
1068
    }
1069
  } else {
1070
    for (int i = 0; i < *rows; i++) {
×
1071
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
×
1072
        result[i] = true;
×
1073
      } else {
1074
        result[i] = false;
×
1075
      }
1076
    }
1077
  }
1078
  return 0;
×
1079
}
1080

1081
int taos_validate_sql(TAOS *taos, const char *sql) {
×
1082
  TAOS_RES *pObj = taosQueryImpl(taos, sql, true, TD_REQ_FROM_APP);
×
1083

1084
  int code = taos_errno(pObj);
×
1085

1086
  taos_free_result(pObj);
×
1087
  return code;
×
1088
}
1089

1090
void taos_reset_current_db(TAOS *taos) {
×
1091
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
1092
  if (pTscObj == NULL) {
×
1093
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1094
    return;
×
1095
  }
1096

1097
  resetConnectDB(pTscObj);
×
1098

1099
  releaseTscObj(*(int64_t *)taos);
×
1100
}
1101

1102
const char *taos_get_server_info(TAOS *taos) {
120✔
1103
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
120✔
1104
  if (pTscObj == NULL) {
120!
1105
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1106
    return NULL;
×
1107
  }
1108

1109
  releaseTscObj(*(int64_t *)taos);
120✔
1110

1111
  return pTscObj->sDetailVer;
120✔
1112
}
1113

1114
int taos_get_current_db(TAOS *taos, char *database, int len, int *required) {
4✔
1115
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
4✔
1116
  if (pTscObj == NULL) {
4!
1117
    return TSDB_CODE_TSC_DISCONNECTED;
×
1118
  }
1119

1120
  int code = TSDB_CODE_SUCCESS;
4✔
1121
  (void)taosThreadMutexLock(&pTscObj->mutex);
4✔
1122
  if (database == NULL || len <= 0) {
4!
1123
    if (required != NULL) *required = strlen(pTscObj->db) + 1;
2✔
1124
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
2!
1125
  } else if (len < strlen(pTscObj->db) + 1) {
2✔
1126
    tstrncpy(database, pTscObj->db, len);
1✔
1127
    if (required) *required = strlen(pTscObj->db) + 1;
1!
1128
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
1!
1129
  } else {
1130
    tstrncpy(database, pTscObj->db, len);
1✔
1131
    code = 0;
1✔
1132
  }
1133
_return:
4✔
1134
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
4✔
1135
  releaseTscObj(*(int64_t *)taos);
4✔
1136
  return code;
4✔
1137
}
1138

1139
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
6,522,169✔
1140
  if (NULL == pWrapper) {
6,522,169✔
1141
    return;
3,327,850✔
1142
  }
1143
  destoryCatalogReq(pWrapper->pCatalogReq);
3,194,319✔
1144
  taosMemoryFree(pWrapper->pCatalogReq);
3,194,540!
1145
  qDestroyParseContext(pWrapper->pParseCtx);
3,194,594✔
1146
  taosMemoryFree(pWrapper);
3,194,598!
1147
}
1148

1149
void destroyCtxInRequest(SRequestObj *pRequest) {
16,384✔
1150
  schedulerFreeJob(&pRequest->body.queryJob, 0);
16,384✔
1151
  qDestroyQuery(pRequest->pQuery);
16,384✔
1152
  pRequest->pQuery = NULL;
16,384✔
1153
  destorySqlCallbackWrapper(pRequest->pWrapper);
16,384✔
1154
  pRequest->pWrapper = NULL;
16,384✔
1155
}
16,384✔
1156

1157
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
1,150,017✔
1158
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
1,150,017✔
1159
  SRequestObj         *pRequest = pWrapper->pRequest;
1,150,017✔
1160
  SQuery              *pQuery = pRequest->pQuery;
1,150,017✔
1161

1162
  qDebug("req:0x%" PRIx64 ", start to semantic analysis, QID:0x%" PRIx64, pRequest->self, pRequest->requestId);
1,150,017✔
1163

1164
  int64_t analyseStart = taosGetTimestampUs();
1,150,016✔
1165
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
1,150,016✔
1166
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
1,150,016✔
1167

1168
  if (TSDB_CODE_SUCCESS == code) {
1,150,016✔
1169
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
1,150,006✔
1170
  }
1171

1172
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
1,150,008✔
1173

1174
  if (pRequest->parseOnly) {
1,150,008✔
1175
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
616✔
1176
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
616✔
1177
  }
1178

1179
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
1,150,008✔
1180
}
1,149,958✔
1181

1182
int32_t cloneCatalogReq(SCatalogReq **ppTarget, SCatalogReq *pSrc) {
525✔
1183
  int32_t      code = TSDB_CODE_SUCCESS;
525✔
1184
  SCatalogReq *pTarget = taosMemoryCalloc(1, sizeof(SCatalogReq));
525!
1185
  if (pTarget == NULL) {
525!
1186
    code = terrno;
×
1187
  } else {
1188
    pTarget->pDbVgroup = taosArrayDup(pSrc->pDbVgroup, NULL);
525✔
1189
    pTarget->pDbCfg = taosArrayDup(pSrc->pDbCfg, NULL);
525✔
1190
    pTarget->pDbInfo = taosArrayDup(pSrc->pDbInfo, NULL);
525✔
1191
    pTarget->pTableMeta = taosArrayDup(pSrc->pTableMeta, NULL);
525✔
1192
    pTarget->pTableHash = taosArrayDup(pSrc->pTableHash, NULL);
525✔
1193
    pTarget->pUdf = taosArrayDup(pSrc->pUdf, NULL);
525✔
1194
    pTarget->pIndex = taosArrayDup(pSrc->pIndex, NULL);
525✔
1195
    pTarget->pUser = taosArrayDup(pSrc->pUser, NULL);
525✔
1196
    pTarget->pTableIndex = taosArrayDup(pSrc->pTableIndex, NULL);
525✔
1197
    pTarget->pTableCfg = taosArrayDup(pSrc->pTableCfg, NULL);
525✔
1198
    pTarget->pTableTag = taosArrayDup(pSrc->pTableTag, NULL);
525✔
1199
    pTarget->pView = taosArrayDup(pSrc->pView, NULL);
525✔
1200
    pTarget->pTableTSMAs = taosArrayDup(pSrc->pTableTSMAs, NULL);
525✔
1201
    pTarget->pTSMAs = taosArrayDup(pSrc->pTSMAs, NULL);
525✔
1202
    pTarget->qNodeRequired = pSrc->qNodeRequired;
525✔
1203
    pTarget->dNodeRequired = pSrc->dNodeRequired;
525✔
1204
    pTarget->svrVerRequired = pSrc->svrVerRequired;
525✔
1205
    pTarget->forceUpdate = pSrc->forceUpdate;
525✔
1206
    pTarget->cloned = true;
525✔
1207

1208
    *ppTarget = pTarget;
525✔
1209
  }
1210

1211
  return code;
525✔
1212
}
1213

1214
void handleSubQueryFromAnalyse(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, SNode *pRoot) {
525✔
1215
  SRequestObj         *pNewRequest = NULL;
525✔
1216
  SSqlCallbackWrapper *pNewWrapper = NULL;
525✔
1217
  int32_t              code = buildPreviousRequest(pWrapper->pRequest, pWrapper->pRequest->sqlstr, &pNewRequest);
525✔
1218
  if (code) {
525!
1219
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1220
    return;
×
1221
  }
1222

1223
  pNewRequest->pQuery = NULL;
525✔
1224
  code = nodesMakeNode(QUERY_NODE_QUERY, (SNode **)&pNewRequest->pQuery);
525✔
1225
  if (pNewRequest->pQuery) {
525!
1226
    pNewRequest->pQuery->pRoot = pRoot;
525✔
1227
    pRoot = NULL;
525✔
1228
    pNewRequest->pQuery->execStage = QUERY_EXEC_STAGE_ANALYSE;
525✔
1229
  }
1230
  if (TSDB_CODE_SUCCESS == code) {
525!
1231
    code = prepareAndParseSqlSyntax(&pNewWrapper, pNewRequest, false);
525✔
1232
  }
1233
  if (TSDB_CODE_SUCCESS == code) {
525!
1234
    code = cloneCatalogReq(&pNewWrapper->pCatalogReq, pWrapper->pCatalogReq);
525✔
1235
  }
1236
  if (TSDB_CODE_SUCCESS == code) {
525!
1237
    doAsyncQueryFromAnalyse(pResultMeta, pNewWrapper, code);
525✔
1238
    nodesDestroyNode(pRoot);
525✔
1239
  } else {
1240
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1241
    return;
×
1242
  }
1243
}
1244

1245
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
1,150,468✔
1246
  SRequestObj *pRequest = pWrapper->pRequest;
1,150,468✔
1247
  SQuery      *pQuery = pRequest->pQuery;
1,150,468✔
1248

1249
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
1,150,468✔
1250
    SNode *prevRoot = pQuery->pPrevRoot;
525✔
1251
    pQuery->pPrevRoot = NULL;
525✔
1252
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
525✔
1253
    return;
525✔
1254
  }
1255

1256
  if (code == TSDB_CODE_SUCCESS) {
1,149,943✔
1257
    pRequest->stableQuery = pQuery->stableQuery;
1,071,517✔
1258
    if (pQuery->pRoot) {
1,071,517!
1259
      pRequest->stmtType = pQuery->pRoot->type;
1,071,522✔
1260
    }
1261

1262
    if (pQuery->haveResultSet) {
1,071,517✔
1263
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols);
887,379✔
1264
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
887,382✔
1265
    }
1266
  }
1267

1268
  if (code == TSDB_CODE_SUCCESS) {
1,149,950✔
1269
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
1,071,489✔
1270
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
1,071,489✔
1271
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
1,071,489✔
1272

1273
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
1,071,489✔
1274
  } else {
1275
    destorySqlCallbackWrapper(pWrapper);
78,461✔
1276
    pRequest->pWrapper = NULL;
78,461✔
1277
    qDestroyQuery(pRequest->pQuery);
78,461✔
1278
    pRequest->pQuery = NULL;
78,461✔
1279

1280
    if (NEED_CLIENT_HANDLE_ERROR(code)) {
78,461!
1281
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
16,117✔
1282
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1283
      restartAsyncQuery(pRequest, code);
16,117✔
1284
      return;
16,117✔
1285
    }
1286

1287
    // return to app directly
1288
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self, tstrerror(code),
62,344!
1289
             pRequest->requestId);
1290
    pRequest->code = code;
62,344✔
1291
    returnToUser(pRequest);
62,344✔
1292
  }
1293
}
1294

1295
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
1,201,879✔
1296
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
1,201,879✔
1297
                           .requestId = pWrapper->pParseCtx->requestId,
1,201,879✔
1298
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
1,201,879✔
1299
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
1,201,879✔
1300

1301
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
1,201,879✔
1302

1303
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
2,403,822✔
1304
                                &pWrapper->pRequest->body.queryJob);
1,201,924✔
1305
}
1306

1307
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1308

1309
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
3,217,981✔
1310
  int32_t code = TSDB_CODE_SUCCESS;
3,217,981✔
1311
  switch (pWrapper->pRequest->pQuery->execStage) {
3,217,981!
1312
    case QUERY_EXEC_STAGE_PARSE: {
52,442✔
1313
      // continue parse after get metadata
1314
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
52,442✔
1315
      break;
52,442✔
1316
    }
1317
    case QUERY_EXEC_STAGE_ANALYSE: {
1,149,465✔
1318
      // analysis after get metadata
1319
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
1,149,465✔
1320
      break;
1,149,458✔
1321
    }
1322
    case QUERY_EXEC_STAGE_SCHEDULE: {
2,016,337✔
1323
      launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper);
2,016,337✔
1324
      break;
2,016,297✔
1325
    }
1326
    default:
×
1327
      break;
×
1328
  }
1329
  return code;
3,217,934✔
1330
}
1331

1332
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
52,442✔
1333
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
52,442✔
1334
  SRequestObj         *pRequest = pWrapper->pRequest;
52,442✔
1335
  SQuery              *pQuery = pRequest->pQuery;
52,442✔
1336

1337
  pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart;
52,443✔
1338
  qDebug("req:0x%" PRIx64 ", start to continue parse, QID:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId,
52,443✔
1339
         tstrerror(code));
1340

1341
  if (code == TSDB_CODE_SUCCESS) {
52,443✔
1342
    // pWrapper->pCatalogReq->forceUpdate = false;
1343
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
52,207✔
1344
  }
1345

1346
  if (TSDB_CODE_SUCCESS == code) {
52,440✔
1347
    code = phaseAsyncQuery(pWrapper);
51,229✔
1348
  }
1349

1350
  if (TSDB_CODE_SUCCESS != code) {
52,437✔
1351
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
1,211!
1352
             tstrerror(code), pWrapper->pRequest->requestId);
1353
    destorySqlCallbackWrapper(pWrapper);
1,211✔
1354
    pRequest->pWrapper = NULL;
1,211✔
1355
    terrno = code;
1,211✔
1356
    pRequest->code = code;
1,211✔
1357
    doRequestCallback(pRequest, code);
1,211✔
1358
  }
1359
}
52,437✔
1360

1361
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
×
1362
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
×
1363
  if (TSDB_CODE_SUCCESS == code) {
×
1364
    code = phaseAsyncQuery(pWrapper);
×
1365
  }
1366

1367
  if (TSDB_CODE_SUCCESS != code) {
×
1368
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
×
1369
             tstrerror(code), pWrapper->pRequest->requestId);
1370
    destorySqlCallbackWrapper(pWrapper);
×
1371
    pRequest->pWrapper = NULL;
×
1372
    terrno = code;
×
1373
    pRequest->code = code;
×
1374
    doRequestCallback(pRequest, code);
×
1375
  }
1376
}
×
1377

1378
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
517✔
1379
  int64_t connId = *(int64_t *)taos;
517✔
1380
  tscDebug("taos_query_a start with sql:%s", sql);
517✔
1381
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
517✔
1382
  tscDebug("taos_query_a end with sql:%s", sql);
517✔
1383
}
517✔
1384

1385
void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) {
×
1386
  int64_t connId = *(int64_t *)taos;
×
1387
  taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid);
×
1388
}
×
1389

1390
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
3,194,364✔
1391
  const STscObj *pTscObj = pRequest->pTscObj;
3,194,364✔
1392

1393
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
3,194,364!
1394
  if (*pCxt == NULL) {
3,194,418!
1395
    return terrno;
×
1396
  }
1397

1398
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
3,194,418✔
1399
                           .requestRid = pRequest->self,
3,194,418✔
1400
                           .acctId = pTscObj->acctId,
3,194,418✔
1401
                           .db = pRequest->pDb,
3,194,418✔
1402
                           .topicQuery = false,
1403
                           .pSql = pRequest->sqlstr,
3,194,418✔
1404
                           .sqlLen = pRequest->sqlLen,
3,194,418✔
1405
                           .pMsg = pRequest->msgBuf,
3,194,418✔
1406
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
1407
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
3,194,418✔
1408
                           .pStmtCb = NULL,
1409
                           .pUser = pTscObj->user,
3,194,418✔
1410
                           .pEffectiveUser = pRequest->effectiveUser,
3,194,418✔
1411
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
3,194,418✔
1412
                           .enableSysInfo = pTscObj->sysInfo,
3,194,418✔
1413
                           .async = true,
1414
                           .svrVer = pTscObj->sVer,
3,194,418✔
1415
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
3,194,418✔
1416
                           .allocatorId = pRequest->allocatorRefId,
3,194,418✔
1417
                           .parseSqlFp = clientParseSql,
1418
                           .parseSqlParam = pWrapper,
1419
                           .setQueryFp = setQueryRequest,
1420
                           .timezone = pTscObj->optionInfo.timezone,
3,194,418✔
1421
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
3,194,418✔
1422
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
3,194,418✔
1423
  (*pCxt)->biMode = biMode;
3,194,482✔
1424
  return TSDB_CODE_SUCCESS;
3,194,482✔
1425
}
1426

1427
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
3,194,266✔
1428
  int32_t              code = TSDB_CODE_SUCCESS;
3,194,266✔
1429
  STscObj             *pTscObj = pRequest->pTscObj;
3,194,266✔
1430
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
3,194,266!
1431
  if (pWrapper == NULL) {
3,194,521!
1432
    code = terrno;
×
1433
  } else {
1434
    pWrapper->pRequest = pRequest;
3,194,521✔
1435
    pRequest->pWrapper = pWrapper;
3,194,521✔
1436
    *ppWrapper = pWrapper;
3,194,521✔
1437
  }
1438

1439
  if (TSDB_CODE_SUCCESS == code) {
3,194,521✔
1440
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
3,194,500✔
1441
  }
1442

1443
  if (TSDB_CODE_SUCCESS == code) {
3,194,522!
1444
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
3,194,531✔
1445
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
3,194,607✔
1446
  }
1447

1448
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
3,194,432✔
1449
    int64_t syntaxStart = taosGetTimestampUs();
3,193,941✔
1450

1451
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
3,193,941!
1452
    if (pWrapper->pCatalogReq == NULL) {
3,193,901!
1453
      code = terrno;
×
1454
    } else {
1455
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
3,193,901✔
1456
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
3,193,901!
1457
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
3,193,763✔
1458
    }
1459

1460
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
3,193,807✔
1461
  }
1462

1463
  return code;
3,194,455✔
1464
}
1465

1466
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
3,199,118✔
1467
  SSqlCallbackWrapper *pWrapper = NULL;
3,199,118✔
1468
  int32_t              code = TSDB_CODE_SUCCESS;
3,199,118✔
1469

1470
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
3,199,118✔
1471
    code = pRequest->prevCode;
5,378✔
1472
    terrno = code;
5,378✔
1473
    pRequest->code = code;
5,378✔
1474
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
5,378✔
1475
    doRequestCallback(pRequest, code);
5,378✔
1476
    return;
5,393✔
1477
  }
1478

1479
  if (TSDB_CODE_SUCCESS == code) {
3,193,740!
1480
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
3,193,862✔
1481
  }
1482

1483
  if (TSDB_CODE_SUCCESS == code) {
3,193,291✔
1484
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
3,166,945✔
1485
    code = phaseAsyncQuery(pWrapper);
3,166,945✔
1486
  }
1487

1488
  if (TSDB_CODE_SUCCESS != code) {
3,193,265✔
1489
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
26,644!
1490
             pRequest->requestId);
1491
    destorySqlCallbackWrapper(pWrapper);
26,644✔
1492
    pRequest->pWrapper = NULL;
26,644✔
1493
    qDestroyQuery(pRequest->pQuery);
26,644✔
1494
    pRequest->pQuery = NULL;
26,644✔
1495

1496
    if (NEED_CLIENT_HANDLE_ERROR(code)) {
26,644!
1497
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
15!
1498
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1499
      code = refreshMeta(pRequest->pTscObj, pRequest);
15✔
1500
      if (code != 0) {
15!
1501
        tscWarn("req:0x%" PRIx64 ", refresh meta failed, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
15!
1502
                pRequest->requestId);
1503
      }
1504
      pRequest->prevCode = code;
15✔
1505
      doAsyncQuery(pRequest, true);
15✔
1506
      return;
15✔
1507
    }
1508

1509
    terrno = code;
26,629✔
1510
    pRequest->code = code;
26,629✔
1511
    doRequestCallback(pRequest, code);
26,629✔
1512
  }
1513
}
1514

1515
void restartAsyncQuery(SRequestObj *pRequest, int32_t code) {
16,384✔
1516
  tscInfo("restart request:%s p:%p", pRequest->sqlstr, pRequest);
16,384!
1517
  SRequestObj *pUserReq = pRequest;
16,384✔
1518
  (void)acquireRequest(pRequest->self);
16,384✔
1519
  while (pUserReq) {
16,407!
1520
    if (pUserReq->self == pUserReq->relation.userRefId || pUserReq->relation.userRefId == 0) {
16,407!
1521
      break;
1522
    } else {
1523
      int64_t nextRefId = pUserReq->relation.nextRefId;
23✔
1524
      (void)releaseRequest(pUserReq->self);
23✔
1525
      if (nextRefId) {
23!
1526
        pUserReq = acquireRequest(nextRefId);
23✔
1527
      }
1528
    }
1529
  }
1530
  bool hasSubRequest = pUserReq != pRequest || pRequest->relation.prevRefId != 0;
16,384!
1531
  if (pUserReq) {
16,384!
1532
    destroyCtxInRequest(pUserReq);
16,384✔
1533
    pUserReq->prevCode = code;
16,384✔
1534
    (void)memset(&pUserReq->relation, 0, sizeof(pUserReq->relation));
16,384✔
1535
  } else {
1536
    tscError("User req is missing");
×
1537
    (void)removeFromMostPrevReq(pRequest);
×
1538
    return;
×
1539
  }
1540
  if (hasSubRequest)
16,384✔
1541
    (void)removeFromMostPrevReq(pRequest);
23✔
1542
  else
1543
    (void)releaseRequest(pUserReq->self);
16,361✔
1544
  doAsyncQuery(pUserReq, true);
16,384✔
1545
}
1546

1547
typedef struct SAsyncFetchParam {
1548
  SRequestObj      *pReq;
1549
  __taos_async_fn_t fp;
1550
  void             *param;
1551
} SAsyncFetchParam;
1552

1553
static int32_t doAsyncFetch(void *pParam) {
955,152✔
1554
  SAsyncFetchParam *param = pParam;
955,152✔
1555
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
955,152✔
1556
  taosMemoryFree(param);
955,148!
1557
  return TSDB_CODE_SUCCESS;
955,148✔
1558
}
1559

1560
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
955,146✔
1561
  if (res == NULL || fp == NULL) {
955,146!
1562
    tscError("taos_fetch_rows_a invalid paras");
×
1563
    return;
×
1564
  }
1565
  if (!TD_RES_QUERY(res)) {
955,152!
1566
    tscError("taos_fetch_rows_a res is NULL");
×
1567
    fp(param, res, TSDB_CODE_APP_ERROR);
×
1568
    return;
×
1569
  }
1570

1571
  SRequestObj *pRequest = res;
955,152✔
1572
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
955,152✔
1573
    fp(param, res, 0);
5✔
1574
    return;
5✔
1575
  }
1576

1577
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
955,147!
1578
  if (!pParam) {
955,147!
1579
    fp(param, res, terrno);
×
1580
    return;
×
1581
  }
1582
  pParam->pReq = pRequest;
955,147✔
1583
  pParam->fp = fp;
955,147✔
1584
  pParam->param = param;
955,147✔
1585
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
955,147✔
1586
  if (TSDB_CODE_SUCCESS != code) {
955,152!
1587
    taosMemoryFree(pParam);
×
1588
    fp(param, res, code);
×
1589
    return;
×
1590
  }
1591
}
1592

1593
void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
×
1594
  if (res == NULL || fp == NULL) {
×
1595
    tscError("taos_fetch_raw_block_a invalid paras");
×
1596
    return;
×
1597
  }
1598
  if (!TD_RES_QUERY(res)) {
×
1599
    tscError("taos_fetch_raw_block_a res is NULL");
×
1600
    return;
×
1601
  }
1602
  SRequestObj    *pRequest = res;
×
1603
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
×
1604

1605
  // set the current block is all consumed
1606
  pResultInfo->convertUcs4 = false;
×
1607

1608
  // it is a local executed query, no need to do async fetch
1609
  taos_fetch_rows_a(pRequest, fp, param);
×
1610
}
1611

1612
const void *taos_get_raw_block(TAOS_RES *res) {
×
1613
  if (res == NULL) {
×
1614
    tscError("taos_get_raw_block invalid paras");
×
1615
    return NULL;
×
1616
  }
1617
  if (!TD_RES_QUERY(res)) {
×
1618
    tscError("taos_get_raw_block res is NULL");
×
1619
    return NULL;
×
1620
  }
1621
  SRequestObj *pRequest = res;
×
1622

1623
  return pRequest->body.resInfo.pData;
×
1624
}
1625

1626
int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInfo) {
2✔
1627
  if (NULL == taos) {
2!
1628
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1629
    return terrno;
×
1630
  }
1631

1632
  if (NULL == db || NULL == dbInfo) {
2!
1633
    tscError("invalid input param, db:%p, dbInfo:%p", db, dbInfo);
×
1634
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
1635
    return terrno;
×
1636
  }
1637

1638
  int64_t      connId = *(int64_t *)taos;
2✔
1639
  SRequestObj *pRequest = NULL;
2✔
1640
  char        *sql = "taos_get_db_route_info";
2✔
1641
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
2✔
1642
  if (code != TSDB_CODE_SUCCESS) {
2!
1643
    terrno = code;
×
1644
    return terrno;
×
1645
  }
1646

1647
  STscObj  *pTscObj = pRequest->pTscObj;
2✔
1648
  SCatalog *pCtg = NULL;
2✔
1649
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
2✔
1650
  if (code != TSDB_CODE_SUCCESS) {
2!
1651
    goto _return;
×
1652
  }
1653

1654
  SRequestConnInfo conn = {
2✔
1655
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
2✔
1656

1657
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
2✔
1658

1659
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
2✔
1660
  (void)snprintf(dbFName, sizeof(dbFName), "%d.%s", pTscObj->acctId, db);
2✔
1661

1662
  code = catalogGetDBVgInfo(pCtg, &conn, dbFName, dbInfo);
2✔
1663
  if (code) {
2!
1664
    goto _return;
×
1665
  }
1666

1667
_return:
2✔
1668

1669
  terrno = code;
2✔
1670

1671
  destroyRequest(pRequest);
2✔
1672
  return code;
2✔
1673
}
1674

1675
int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId) {
200✔
1676
  if (NULL == taos) {
200!
1677
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1678
    return terrno;
×
1679
  }
1680

1681
  if (NULL == db || NULL == table || NULL == vgId) {
200!
1682
    tscError("invalid input param, db:%p, table:%p, vgId:%p", db, table, vgId);
×
1683
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
1684
    return terrno;
×
1685
  }
1686

1687
  int64_t      connId = *(int64_t *)taos;
200✔
1688
  SRequestObj *pRequest = NULL;
200✔
1689
  char        *sql = "taos_get_table_vgId";
200✔
1690
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
200✔
1691
  if (code != TSDB_CODE_SUCCESS) {
200!
1692
    return terrno;
×
1693
  }
1694

1695
  pRequest->syncQuery = true;
200✔
1696

1697
  STscObj  *pTscObj = pRequest->pTscObj;
200✔
1698
  SCatalog *pCtg = NULL;
200✔
1699
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
200✔
1700
  if (code != TSDB_CODE_SUCCESS) {
200!
1701
    goto _return;
×
1702
  }
1703

1704
  SRequestConnInfo conn = {
200✔
1705
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
200✔
1706

1707
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
200✔
1708

1709
  SName tableName = {0};
200✔
1710
  toName(pTscObj->acctId, db, table, &tableName);
200✔
1711

1712
  SVgroupInfo vgInfo;
1713
  code = catalogGetTableHashVgroup(pCtg, &conn, &tableName, &vgInfo);
200✔
1714
  if (code) {
200!
1715
    goto _return;
×
1716
  }
1717

1718
  *vgId = vgInfo.vgId;
200✔
1719

1720
_return:
200✔
1721

1722
  terrno = code;
200✔
1723

1724
  destroyRequest(pRequest);
200✔
1725
  return code;
200✔
1726
}
1727

1728
int taos_get_tables_vgId(TAOS *taos, const char *db, const char *table[], int tableNum, int *vgId) {
1✔
1729
  if (NULL == taos) {
1!
1730
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1731
    return terrno;
×
1732
  }
1733

1734
  if (NULL == db || NULL == table || NULL == vgId || tableNum <= 0) {
1!
1735
    tscError("invalid input param, db:%p, table:%p, vgId:%p, tbNum:%d", db, table, vgId, tableNum);
×
1736
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
1737
    return terrno;
×
1738
  }
1739

1740
  int64_t      connId = *(int64_t *)taos;
1✔
1741
  SRequestObj *pRequest = NULL;
1✔
1742
  char        *sql = "taos_get_table_vgId";
1✔
1743
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
1✔
1744
  if (code != TSDB_CODE_SUCCESS) {
1!
1745
    return terrno;
×
1746
  }
1747

1748
  pRequest->syncQuery = true;
1✔
1749

1750
  STscObj  *pTscObj = pRequest->pTscObj;
1✔
1751
  SCatalog *pCtg = NULL;
1✔
1752
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
1✔
1753
  if (code != TSDB_CODE_SUCCESS) {
1!
1754
    goto _return;
×
1755
  }
1756

1757
  SRequestConnInfo conn = {
1✔
1758
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
1✔
1759

1760
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
1✔
1761

1762
  code = catalogGetTablesHashVgId(pCtg, &conn, pTscObj->acctId, db, table, tableNum, vgId);
1✔
1763
  if (code) {
1!
1764
    goto _return;
×
1765
  }
1766

1767
_return:
1✔
1768

1769
  terrno = code;
1✔
1770

1771
  destroyRequest(pRequest);
1✔
1772
  return code;
1✔
1773
}
1774

1775
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
3✔
1776
  if (NULL == taos) {
3!
1777
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1778
    return terrno;
×
1779
  }
1780

1781
  int64_t       connId = *(int64_t *)taos;
3✔
1782
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
3✔
1783
  int32_t       code = 0;
3✔
1784
  SRequestObj  *pRequest = NULL;
3✔
1785
  SCatalogReq   catalogReq = {0};
3✔
1786

1787
  if (NULL == tableNameList) {
3!
1788
    return TSDB_CODE_SUCCESS;
×
1789
  }
1790

1791
  int32_t length = (int32_t)strlen(tableNameList);
3✔
1792
  if (0 == length) {
3!
1793
    return TSDB_CODE_SUCCESS;
×
1794
  } else if (length > MAX_TABLE_NAME_LENGTH) {
3!
1795
    tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH);
×
1796
    return TSDB_CODE_TSC_INVALID_OPERATION;
×
1797
  }
1798

1799
  char *sql = "taos_load_table_info";
3✔
1800
  code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
3✔
1801
  if (code != TSDB_CODE_SUCCESS) {
3!
1802
    terrno = code;
×
1803
    goto _return;
×
1804
  }
1805

1806
  pRequest->syncQuery = true;
3✔
1807

1808
  STscObj *pTscObj = pRequest->pTscObj;
3✔
1809
  code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
3✔
1810
  if (code) {
3!
1811
    goto _return;
×
1812
  }
1813

1814
  SCatalog *pCtg = NULL;
3✔
1815
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
3✔
1816
  if (code != TSDB_CODE_SUCCESS) {
3!
1817
    goto _return;
×
1818
  }
1819

1820
  SRequestConnInfo conn = {
3✔
1821
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
3✔
1822

1823
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
3✔
1824

1825
  code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, pRequest->body.interParam, NULL);
3✔
1826
  if (code) {
3!
1827
    goto _return;
×
1828
  }
1829

1830
  SSyncQueryParam *pParam = pRequest->body.interParam;
3✔
1831
  code = tsem_wait(&pParam->sem);
3✔
1832
  if (code) {
3!
1833
    tscError("tsem wait failed, code:%d - %s", code, tstrerror(code));
×
1834
    goto _return;
×
1835
  }
1836
_return:
3✔
1837
  destoryCatalogReq(&catalogReq);
3✔
1838
  destroyRequest(pRequest);
3✔
1839
  return code;
3✔
1840
}
1841

1842
TAOS_STMT *taos_stmt_init(TAOS *taos) {
618✔
1843
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
618✔
1844
  if (NULL == pObj) {
618!
1845
    tscError("invalid parameter for %s", __FUNCTION__);
×
1846
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1847
    return NULL;
×
1848
  }
1849

1850
  TAOS_STMT *pStmt = stmtInit(pObj, 0, NULL);
618✔
1851
  if (NULL == pStmt) {
618!
1852
    tscError("stmt init failed, errcode:%s", terrstr());
×
1853
  }
1854
  releaseTscObj(*(int64_t *)taos);
618✔
1855

1856
  return pStmt;
618✔
1857
}
1858

1859
TAOS_STMT *taos_stmt_init_with_reqid(TAOS *taos, int64_t reqid) {
×
1860
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
1861
  if (NULL == pObj) {
×
1862
    tscError("invalid parameter for %s", __FUNCTION__);
×
1863
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1864
    return NULL;
×
1865
  }
1866

1867
  TAOS_STMT *pStmt = stmtInit(pObj, reqid, NULL);
×
1868
  if (NULL == pStmt) {
×
1869
    tscError("stmt init failed, errcode:%s", terrstr());
×
1870
  }
1871
  releaseTscObj(*(int64_t *)taos);
×
1872

1873
  return pStmt;
×
1874
}
1875

1876
TAOS_STMT *taos_stmt_init_with_options(TAOS *taos, TAOS_STMT_OPTIONS *options) {
54✔
1877
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
54✔
1878
  if (NULL == pObj) {
54!
1879
    tscError("invalid parameter for %s", __FUNCTION__);
×
1880
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1881
    return NULL;
×
1882
  }
1883

1884
  TAOS_STMT *pStmt = stmtInit(pObj, options->reqId, options);
54✔
1885
  if (NULL == pStmt) {
54!
1886
    tscError("stmt init failed, errcode:%s", terrstr());
×
1887
  }
1888
  releaseTscObj(*(int64_t *)taos);
54✔
1889

1890
  return pStmt;
54✔
1891
}
1892

1893
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
1,105✔
1894
  if (stmt == NULL || sql == NULL) {
1,105!
1895
    tscError("NULL parameter for %s", __FUNCTION__);
×
1896
    terrno = TSDB_CODE_INVALID_PARA;
×
1897
    return terrno;
×
1898
  }
1899

1900
  return stmtPrepare(stmt, sql, length);
1,105✔
1901
}
1902

1903
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
19,913✔
1904
  if (stmt == NULL || name == NULL) {
19,913!
1905
    tscError("NULL parameter for %s", __FUNCTION__);
×
1906
    terrno = TSDB_CODE_INVALID_PARA;
×
1907
    return terrno;
×
1908
  }
1909

1910
  int32_t code = stmtSetTbName(stmt, name);
19,913✔
1911
  if (code) {
19,913!
1912
    return code;
×
1913
  }
1914

1915
  if (tags) {
19,913!
1916
    return stmtSetTbTags(stmt, tags);
19,913✔
1917
  }
1918

1919
  return TSDB_CODE_SUCCESS;
×
1920
}
1921

1922
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
106,296✔
1923
  if (stmt == NULL || name == NULL) {
106,296!
1924
    tscError("NULL parameter for %s", __FUNCTION__);
×
1925
    terrno = TSDB_CODE_INVALID_PARA;
×
1926
    return terrno;
×
1927
  }
1928

1929
  return stmtSetTbName(stmt, name);
106,296✔
1930
}
1931

1932
int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) {
20,039✔
1933
  if (stmt == NULL || tags == NULL) {
20,039!
1934
    tscError("NULL parameter for %s", __FUNCTION__);
×
1935
    terrno = TSDB_CODE_INVALID_PARA;
×
1936
    return terrno;
×
1937
  }
1938

1939
  return stmtSetTbTags(stmt, tags);
20,039✔
1940
}
1941

1942
int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); }
2✔
1943

1944
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
20,039✔
1945
  if (stmt == NULL || NULL == fieldNum) {
20,039!
1946
    tscError("NULL parameter for %s", __FUNCTION__);
×
1947
    terrno = TSDB_CODE_INVALID_PARA;
×
1948
    return terrno;
×
1949
  }
1950

1951
  return stmtGetTagFields(stmt, fieldNum, fields);
20,039✔
1952
}
1953

1954
int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
267,368✔
1955
  if (stmt == NULL || NULL == fieldNum) {
267,368!
1956
    tscError("NULL parameter for %s", __FUNCTION__);
×
1957
    terrno = TSDB_CODE_INVALID_PARA;
×
1958
    return terrno;
×
1959
  }
1960

1961
  return stmtGetColFields(stmt, fieldNum, fields);
267,368✔
1962
}
1963

1964
// let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields`
1965
void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) {
×
1966
  (void)stmt;
1967
  if (!fields) return;
×
1968
  taosMemoryFree(fields);
×
1969
}
1970

1971
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
13,812✔
1972
  if (stmt == NULL || bind == NULL) {
13,812!
1973
    tscError("NULL parameter for %s", __FUNCTION__);
×
1974
    terrno = TSDB_CODE_INVALID_PARA;
×
1975
    return terrno;
×
1976
  }
1977

1978
  if (bind->num > 1) {
13,812!
1979
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
×
1980
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
1981
    return terrno;
×
1982
  }
1983

1984
  return stmtBindBatch(stmt, bind, -1);
13,812✔
1985
}
1986

1987
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
1,194,278✔
1988
  if (stmt == NULL || bind == NULL) {
1,194,278!
1989
    tscError("NULL parameter for %s", __FUNCTION__);
×
1990
    terrno = TSDB_CODE_INVALID_PARA;
×
1991
    return terrno;
×
1992
  }
1993

1994
  if (bind->num <= 0 || bind->num > INT16_MAX) {
1,194,514!
1995
    tscError("invalid bind num %d", bind->num);
32!
1996
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
32✔
1997
    return terrno;
×
1998
  }
1999

2000
  int32_t insert = 0;
1,194,482✔
2001
  int32_t code = stmtIsInsert(stmt, &insert);
1,194,482✔
2002
  if (TSDB_CODE_SUCCESS != code) {
1,193,451!
2003
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2004
    return code;
×
2005
  }
2006
  if (0 == insert && bind->num > 1) {
1,193,451!
2007
    tscError("only one row data allowed for query");
×
2008
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2009
    return terrno;
×
2010
  }
2011

2012
  return stmtBindBatch(stmt, bind, -1);
1,193,451✔
2013
}
2014

2015
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
1,099,452✔
2016
  if (stmt == NULL || bind == NULL) {
1,099,452!
2017
    tscError("NULL parameter for %s", __FUNCTION__);
×
2018
    terrno = TSDB_CODE_INVALID_PARA;
×
2019
    return terrno;
×
2020
  }
2021

2022
  if (colIdx < 0) {
1,099,452!
2023
    tscError("invalid bind column idx %d", colIdx);
×
2024
    terrno = TSDB_CODE_INVALID_PARA;
×
2025
    return terrno;
×
2026
  }
2027

2028
  int32_t insert = 0;
1,099,452✔
2029
  int32_t code = stmtIsInsert(stmt, &insert);
1,099,452✔
2030
  if (TSDB_CODE_SUCCESS != code) {
1,099,452!
2031
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2032
    return code;
×
2033
  }
2034
  if (0 == insert && bind->num > 1) {
1,099,452!
2035
    tscError("only one row data allowed for query");
×
2036
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2037
    return terrno;
×
2038
  }
2039

2040
  return stmtBindBatch(stmt, bind, colIdx);
1,099,452✔
2041
}
2042

2043
int taos_stmt_add_batch(TAOS_STMT *stmt) {
1,256,009✔
2044
  if (stmt == NULL) {
1,256,009!
2045
    tscError("NULL parameter for %s", __FUNCTION__);
×
2046
    terrno = TSDB_CODE_INVALID_PARA;
×
2047
    return terrno;
×
2048
  }
2049

2050
  return stmtAddBatch(stmt);
1,256,009✔
2051
}
2052

2053
int taos_stmt_execute(TAOS_STMT *stmt) {
114,607✔
2054
  if (stmt == NULL) {
114,607!
2055
    tscError("NULL parameter for %s", __FUNCTION__);
×
2056
    terrno = TSDB_CODE_INVALID_PARA;
×
2057
    return terrno;
×
2058
  }
2059

2060
  return stmtExec(stmt);
114,607✔
2061
}
2062

2063
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
22,814✔
2064
  if (stmt == NULL || insert == NULL) {
22,814!
2065
    tscError("NULL parameter for %s", __FUNCTION__);
×
2066
    terrno = TSDB_CODE_INVALID_PARA;
×
2067
    return terrno;
×
2068
  }
2069

2070
  return stmtIsInsert(stmt, insert);
22,814✔
2071
}
2072

2073
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
1,331✔
2074
  if (stmt == NULL || nums == NULL) {
1,331!
2075
    tscError("NULL parameter for %s", __FUNCTION__);
×
2076
    terrno = TSDB_CODE_INVALID_PARA;
×
2077
    return terrno;
×
2078
  }
2079

2080
  return stmtGetParamNum(stmt, nums);
1,331✔
2081
}
2082

2083
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
2,318,538✔
2084
  if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) {
2,318,538!
2085
    tscError("invalid parameter for %s", __FUNCTION__);
×
2086
    terrno = TSDB_CODE_INVALID_PARA;
×
2087
    return terrno;
×
2088
  }
2089

2090
  return stmtGetParam(stmt, idx, type, bytes);
2,318,538✔
2091
}
2092

2093
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
21,603✔
2094
  if (stmt == NULL) {
21,603!
2095
    tscError("NULL parameter for %s", __FUNCTION__);
×
2096
    terrno = TSDB_CODE_INVALID_PARA;
×
2097
    return NULL;
×
2098
  }
2099

2100
  return stmtUseResult(stmt);
21,603✔
2101
}
2102

2103
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
4✔
2104

2105
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
281✔
2106
  if (stmt == NULL) {
281!
2107
    tscError("NULL parameter for %s", __FUNCTION__);
×
2108
    terrno = TSDB_CODE_INVALID_PARA;
×
2109
    return 0;
×
2110
  }
2111

2112
  return stmtAffectedRows(stmt);
281✔
2113
}
2114

2115
int taos_stmt_affected_rows_once(TAOS_STMT *stmt) {
28✔
2116
  if (stmt == NULL) {
28!
2117
    tscError("NULL parameter for %s", __FUNCTION__);
×
2118
    terrno = TSDB_CODE_INVALID_PARA;
×
2119
    return 0;
×
2120
  }
2121

2122
  return stmtAffectedRowsOnce(stmt);
28✔
2123
}
2124

2125
int taos_stmt_close(TAOS_STMT *stmt) {
671✔
2126
  if (stmt == NULL) {
671!
2127
    tscError("NULL parameter for %s", __FUNCTION__);
×
2128
    terrno = TSDB_CODE_INVALID_PARA;
×
2129
    return terrno;
×
2130
  }
2131

2132
  return stmtClose(stmt);
671✔
2133
}
2134

2135
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
96✔
2136
  if (NULL == taos) {
96✔
2137
    tscError("NULL parameter for %s", __FUNCTION__);
1!
2138
    terrno = TSDB_CODE_INVALID_PARA;
1✔
2139
    return NULL;
1✔
2140
  }
2141
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
95✔
2142
  if (NULL == pObj) {
95!
2143
    tscError("invalid parameter for %s", __FUNCTION__);
×
2144
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2145
    return NULL;
×
2146
  }
2147

2148
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
95✔
2149

2150
  releaseTscObj(*(int64_t *)taos);
95✔
2151

2152
  return pStmt;
95✔
2153
}
2154

2155
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
96✔
2156
  if (stmt == NULL || sql == NULL) {
96!
2157
    tscError("NULL parameter for %s", __FUNCTION__);
1!
2158
    terrno = TSDB_CODE_INVALID_PARA;
1✔
2159
    return terrno;
1✔
2160
  }
2161

2162
  return stmtPrepare2(stmt, sql, length);
95✔
2163
}
2164

2165
int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx) {
144✔
2166
  if (stmt == NULL) {
144!
2167
    tscError("NULL parameter for %s", __FUNCTION__);
×
2168
    terrno = TSDB_CODE_INVALID_PARA;
×
2169
    return terrno;
×
2170
  }
2171

2172
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
144✔
2173
  if( atomic_load_8((int8_t*)&pStmt->asyncBindParam.asyncBindNum)>1) {
144!
2174
    tscError("async bind param is still working, please try again later");
×
2175
    return TSDB_CODE_TSC_STMT_API_ERROR;
×
2176
  }
2177

2178
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
144✔
2179
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
16!
2180
      tscError("wait asyncExecSem failed");
×
2181
    }
2182
    pStmt->execSemWaited = true;
16✔
2183
  }
2184

2185
  SSHashObj *hashTbnames = tSimpleHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR));
144✔
2186
  if (NULL == hashTbnames) {
144!
2187
    tscError("stmt2 bind failed, %s", tstrerror(terrno));
×
2188
    return terrno;
×
2189
  }
2190

2191
  int32_t code = TSDB_CODE_SUCCESS;
144✔
2192
  for (int i = 0; i < bindv->count; ++i) {
360✔
2193
    if (bindv->tbnames && bindv->tbnames[i]) {
221!
2194
      if (pStmt->sql.stbInterlaceMode) {
209✔
2195
        if (tSimpleHashGet(hashTbnames, bindv->tbnames[i], strlen(bindv->tbnames[i])) != NULL) {
99!
2196
          code = terrno = TSDB_CODE_PAR_TBNAME_DUPLICATED;
×
2197
          tscError("stmt2 bind failed, %s %s", tstrerror(terrno), bindv->tbnames[i]);
×
2198
          goto out;
×
2199
        }
2200

2201
        code = tSimpleHashPut(hashTbnames, bindv->tbnames[i], strlen(bindv->tbnames[i]), NULL, 0);
99✔
2202
        if (code) {
99!
2203
          goto out;
×
2204
        }
2205
      }
2206

2207
      code = stmtSetTbName2(stmt, bindv->tbnames[i]);
209✔
2208
      if (code) {
209!
2209
        goto out;
×
2210
      }
2211
    }
2212

2213
    if (bindv->tags && bindv->tags[i]) {
221!
2214
      code = stmtSetTbTags2(stmt, bindv->tags[i]);
67✔
2215
      if (code) {
67!
2216
        goto out;
×
2217
      }
2218
    } else if (pStmt->bInfo.tbType == TSDB_CHILD_TABLE && pStmt->sql.autoCreateTbl) {
154✔
2219
      code = stmtSetTbTags2(stmt, NULL);
41✔
2220
      if (code) {
41!
2221
        return code;
×
2222
      }
2223
    }
2224

2225
    if (bindv->bind_cols && bindv->bind_cols[i]) {
221!
2226
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
221✔
2227

2228
      if (bind->num <= 0 || bind->num > INT16_MAX) {
221!
2229
        tscError("invalid bind num %d", bind->num);
×
2230
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2231
        goto out;
4✔
2232
      }
2233

2234
      int32_t insert = 0;
221✔
2235
      (void)stmtIsInsert2(stmt, &insert);
221✔
2236
      if (0 == insert && bind->num > 1) {
221✔
2237
        tscError("only one row data allowed for query");
1!
2238
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
1✔
2239
        goto out;
1✔
2240
      }
2241

2242
      code = stmtBindBatch2(stmt, bind, col_idx);
220✔
2243
      if (TSDB_CODE_SUCCESS != code) {
219✔
2244
        goto out;
3✔
2245
      }
2246
    }
2247
  }
2248

2249
out:
139✔
2250
  tSimpleHashCleanup(hashTbnames);
143✔
2251

2252
  return code;
144✔
2253
}
2254

2255
int taos_stmt2_bind_param_a(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx, __taos_async_fn_t fp,
10✔
2256
                            void *param) {
2257
  if (stmt == NULL || bindv == NULL || fp == NULL) {
10!
2258
    terrno = TSDB_CODE_INVALID_PARA;
×
2259
    return terrno;
×
2260
  }
2261

2262
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
10✔
2263

2264
  ThreadArgs *args = (ThreadArgs *)taosMemoryMalloc(sizeof(ThreadArgs));
10!
2265
  args->stmt = stmt;
10✔
2266
  args->bindv = bindv;
10✔
2267
  args->col_idx = col_idx;
10✔
2268
  args->fp = fp;
10✔
2269
  args->param = param;
10✔
2270

2271
  (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
10✔
2272
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 0) {
10✔
2273
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
1✔
2274
    tscError("async bind param is still working, please try again later");
1!
2275
    return TSDB_CODE_TSC_STMT_API_ERROR;
1✔
2276
  }
2277
  (void)atomic_add_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
9✔
2278
  (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
9✔
2279

2280
  int code_s = taosStmt2AsyncBind(stmtAsyncBindThreadFunc, (void *)args);
9✔
2281
  if (code_s != TSDB_CODE_SUCCESS) {
9!
2282
    (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2283
    (void)taosThreadCondSignal(&(pStmt->asyncBindParam.waitCond));
×
2284
    (void)atomic_sub_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2285
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2286
     tscError("async bind failed, code:%d , %s", code_s, tstrerror(code_s));
×
2287
  }
2288

2289
  return code_s;
9✔
2290
}
2291

2292
int taos_stmt2_exec(TAOS_STMT2 *stmt, int *affected_rows) {
133✔
2293
  if (stmt == NULL) {
133!
2294
    tscError("NULL parameter for %s", __FUNCTION__);
×
2295
    terrno = TSDB_CODE_INVALID_PARA;
×
2296
    return terrno;
×
2297
  }
2298

2299
  return stmtExec2(stmt, affected_rows);
133✔
2300
}
2301

2302
int taos_stmt2_close(TAOS_STMT2 *stmt) {
94✔
2303
  if (stmt == NULL) {
94!
2304
    tscError("NULL parameter for %s", __FUNCTION__);
×
2305
    terrno = TSDB_CODE_INVALID_PARA;
×
2306
    return terrno;
×
2307
  }
2308

2309
  return stmtClose2(stmt);
94✔
2310
}
2311

2312
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
×
2313
  if (stmt == NULL || insert == NULL) {
×
2314
    tscError("NULL parameter for %s", __FUNCTION__);
×
2315
    terrno = TSDB_CODE_INVALID_PARA;
×
2316
    return terrno;
×
2317
  }
2318

2319
  return stmtIsInsert2(stmt, insert);
×
2320
}
2321

2322
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
44✔
2323
  if (stmt == NULL || count == NULL) {
44!
2324
    tscError("NULL parameter for %s", __FUNCTION__);
1!
2325
    terrno = TSDB_CODE_INVALID_PARA;
1✔
2326
    return terrno;
1✔
2327
  }
2328

2329
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
43✔
2330
  if (pStmt->sql.type == 0) {
43!
2331
    int isInsert = 0;
43✔
2332
    (void)stmtIsInsert2(stmt, &isInsert);
43✔
2333
    if (!isInsert) {
43✔
2334
      pStmt->sql.type = STMT_TYPE_QUERY;
9✔
2335
    }
2336
  }
2337
  if (pStmt->sql.type == STMT_TYPE_QUERY) {
43✔
2338
    return stmtGetParamNum2(stmt, count);
9✔
2339
  }
2340

2341
  return stmtGetStbColFields2(stmt, count, fields);
34✔
2342
}
2343

2344
DLL_EXPORT void taos_stmt2_free_fields(TAOS_STMT2 *stmt, TAOS_FIELD_ALL *fields) {
42✔
2345
  (void)stmt;
2346
  if (!fields) return;
42✔
2347
  taosMemoryFree(fields);
22!
2348
}
2349

2350
TAOS_RES *taos_stmt2_result(TAOS_STMT2 *stmt) {
3✔
2351
  if (stmt == NULL) {
3!
2352
    tscError("NULL parameter for %s", __FUNCTION__);
×
2353
    terrno = TSDB_CODE_INVALID_PARA;
×
2354
    return NULL;
×
2355
  }
2356

2357
  return stmtUseResult2(stmt);
3✔
2358
}
2359

2360
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmtErrstr2(stmt); }
3✔
2361

2362
int taos_set_conn_mode(TAOS *taos, int mode, int value) {
4✔
2363
  if (taos == NULL) {
4!
2364
    terrno = TSDB_CODE_INVALID_PARA;
×
2365
    return terrno;
×
2366
  }
2367

2368
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
4✔
2369
  if (NULL == pObj) {
4!
2370
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2371
    tscError("invalid parameter for %s", __func__);
×
2372
    return terrno;
×
2373
  }
2374
  switch (mode) {
4!
2375
    case TAOS_CONN_MODE_BI:
4✔
2376
      atomic_store_8(&pObj->biMode, value);
4✔
2377
      break;
4✔
2378
    default:
×
2379
      tscError("not supported mode.");
×
2380
      return TSDB_CODE_INVALID_PARA;
×
2381
  }
2382
  return 0;
4✔
2383
}
2384

2385
char *getBuildInfo() { return td_buildinfo; }
×
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