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

taosdata / TDengine / #4876

10 Dec 2025 05:56AM UTC coverage: 64.632% (+0.2%) from 64.472%
#4876

push

travis-ci

guanshengliang
test: fix idmp case with checkDataMemLoop checked (#33862)

4 of 9 new or added lines in 3 files covered. (44.44%)

380 existing lines in 104 files now uncovered.

162866 of 251990 relevant lines covered (64.63%)

107950382.52 hits per line

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

38.08
/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 "tmisce.h"
31
#include "tmsg.h"
32
#include "tref.h"
33
#include "trpc.h"
34
#include "tversion.h"
35
#include "version.h"
36
#include "ttime.h"
37

38
#define TSC_VAR_NOT_RELEASE 1
39
#define TSC_VAR_RELEASED    0
40

41
#ifdef TAOSD_INTEGRATED
42
extern void shellStopDaemon();
43
#endif
44

45
static int32_t sentinel = TSC_VAR_NOT_RELEASE;
46
static int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper);
47

48
int taos_options(TSDB_OPTION option, const void *arg, ...) {
619,300✔
49
  if (arg == NULL) {
619,300✔
50
    return TSDB_CODE_INVALID_PARA;
×
51
  }
52
  static int32_t lock = 0;
53

54
  for (int i = 1; atomic_val_compare_exchange_32(&lock, 0, 1) != 0; ++i) {
7,209,092✔
55
    if (i % 1000 == 0) {
6,589,792✔
56
      (void)sched_yield();
6,562✔
57
    }
58
  }
59

60
  int ret = taos_options_imp(option, (const char *)arg);
619,300✔
61
  atomic_store_32(&lock, 0);
619,300✔
62
  return ret;
619,300✔
63
}
64

65
#if !defined(WINDOWS) && !defined(TD_ASTRA)
66
static void freeTz(void *p) {
×
67
  timezone_t tz = *(timezone_t *)p;
×
68
  tzfree(tz);
×
69
}
×
70

71
int32_t tzInit() {
1,791,073✔
72
  pTimezoneMap = taosHashInit(0, MurmurHash3_32, false, HASH_ENTRY_LOCK);
1,791,073✔
73
  if (pTimezoneMap == NULL) {
1,791,073✔
74
    return terrno;
×
75
  }
76
  taosHashSetFreeFp(pTimezoneMap, freeTz);
1,791,073✔
77

78
  pTimezoneNameMap = taosHashInit(0, taosIntHash_64, false, HASH_ENTRY_LOCK);
1,791,073✔
79
  if (pTimezoneNameMap == NULL) {
1,791,073✔
80
    return terrno;
×
81
  }
82
  return 0;
1,791,073✔
83
}
84

85
void tzCleanup() {
1,791,357✔
86
  taosHashCleanup(pTimezoneMap);
1,791,357✔
87
  taosHashCleanup(pTimezoneNameMap);
1,791,357✔
88
}
1,791,357✔
89

90
static timezone_t setConnnectionTz(const char *val) {
×
91
  timezone_t  tz = NULL;
×
92
  timezone_t *tmp = taosHashGet(pTimezoneMap, val, strlen(val));
×
93
  if (tmp != NULL && *tmp != NULL) {
×
94
    tz = *tmp;
×
95
    goto END;
×
96
  }
97

98
  tscDebug("set timezone to %s", val);
×
99
  tz = tzalloc(val);
×
100
  if (tz == NULL) {
×
101
    tscWarn("%s unknown timezone %s change to UTC", __func__, val);
×
102
    tz = tzalloc("UTC");
×
103
    if (tz == NULL) {
×
104
      tscError("%s set timezone UTC error", __func__);
×
105
      terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
106
      goto END;
×
107
    }
108
  }
109
  int32_t code = taosHashPut(pTimezoneMap, val, strlen(val), &tz, sizeof(timezone_t));
×
110
  if (code != 0) {
×
111
    tscError("%s put timezone to tz map error:%d", __func__, code);
×
112
    tzfree(tz);
×
113
    tz = NULL;
×
114
    goto END;
×
115
  }
116

117
  time_t tx1 = taosGetTimestampSec();
×
118
  char   output[TD_TIMEZONE_LEN] = {0};
×
119
  code = taosFormatTimezoneStr(tx1, val, tz, output);
×
120
  if (code == 0) {
×
121
    code = taosHashPut(pTimezoneNameMap, &tz, sizeof(timezone_t), output, strlen(output) + 1);
×
122
  }
123
  if (code != 0) {
×
124
    tscError("failed to put timezone %s to map", val);
×
125
  }
126

127
END:
×
128
  return tz;
×
129
}
130
#endif
131

132
static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, const char *val) {
×
133
  if (taos == NULL) {
×
134
    return terrno = TSDB_CODE_INVALID_PARA;
×
135
  }
136

137
#ifdef WINDOWS
138
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE) {
139
    return terrno = TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS;
140
  }
141
#endif
142

143
  if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION) {
×
144
    return terrno = TSDB_CODE_INVALID_PARA;
×
145
  }
146

147
  int32_t code = taos_init();
×
148
  // initialize global config
149
  if (code != 0) {
×
150
    return terrno = code;
×
151
  }
152

153
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
154
  if (NULL == pObj) {
×
155
    tscError("invalid parameter for %s", __func__);
×
156
    return terrno;
×
157
  }
158

159
  if (option == TSDB_OPTION_CONNECTION_CLEAR) {
×
160
    val = NULL;
×
161
  }
162

163
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
164
  if (option == TSDB_OPTION_CONNECTION_CHARSET || option == TSDB_OPTION_CONNECTION_CLEAR) {
×
165
    if (val != NULL) {
×
166
      if (!taosValidateEncodec(val)) {
×
167
        code = terrno;
×
168
        goto END;
×
169
      }
170
      void *tmp = taosConvInit(val);
×
171
      if (tmp == NULL) {
×
172
        code = terrno;
×
173
        goto END;
×
174
      }
175
      pObj->optionInfo.charsetCxt = tmp;
×
176
    } else {
177
      pObj->optionInfo.charsetCxt = NULL;
×
178
    }
179
  }
180
#endif
181
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) {
×
182
#if !defined(WINDOWS) && !defined(TD_ASTRA)
183
    if (val != NULL) {
×
184
      if (val[0] == 0) {
×
185
        val = "UTC";
×
186
      }
187
      timezone_t tz = setConnnectionTz(val);
×
188
      if (tz == NULL) {
×
189
        code = terrno;
×
190
        goto END;
×
191
      }
192
      pObj->optionInfo.timezone = tz;
×
193
    } else {
194
      pObj->optionInfo.timezone = NULL;
×
195
    }
196
#endif
197
  }
198

199
  if (option == TSDB_OPTION_CONNECTION_USER_APP || option == TSDB_OPTION_CONNECTION_CLEAR) {
×
200
    if (val != NULL) {
×
201
      tstrncpy(pObj->optionInfo.userApp, val, sizeof(pObj->optionInfo.userApp));
×
202
    } else {
203
      pObj->optionInfo.userApp[0] = 0;
×
204
    }
205
  }
206

207
  if (option == TSDB_OPTION_CONNECTION_CONNECTOR_INFO || option == TSDB_OPTION_CONNECTION_CLEAR) {
×
208
    if (val != NULL) {
×
209
      tstrncpy(pObj->optionInfo.cInfo, val, sizeof(pObj->optionInfo.cInfo));
×
210
    } else {
211
      pObj->optionInfo.cInfo[0] = 0;
×
212
    }
213
  }
214

215
  if (option == TSDB_OPTION_CONNECTION_USER_IP || option == TSDB_OPTION_CONNECTION_CLEAR) {
×
216
    SIpRange dualIp = {0};
×
217
    if (val != NULL) {
×
218
      pObj->optionInfo.userIp = taosInetAddr(val);
×
219
      SIpAddr addr = {0};
×
220
      code = taosGetIpFromFqdn(tsEnableIpv6, val, &addr);
×
221
      if (code == 0) {
×
222
        code = tIpStrToUint(&addr, &pObj->optionInfo.userDualIp);
×
223
      }
224
      if (code != 0) {
×
225
        tscError("ipv6 flag %d failed to convert user ip %s to dual ip since %s", tsEnableIpv6 ? 1 : 0, val,
×
226
                 tstrerror(code));
227
        pObj->optionInfo.userIp = INADDR_NONE;
×
228
        pObj->optionInfo.userDualIp = dualIp;
×
229
        code = 0;
×
230
      }
231
    } else {
232
      pObj->optionInfo.userIp = INADDR_NONE;
×
233
      pObj->optionInfo.userDualIp = dualIp;
×
234
    }
235
  }
236

237
END:
×
238
  releaseTscObj(*(int64_t *)taos);
×
239
  return terrno = code;
×
240
}
241

242
int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...) {
×
243
  return setConnectionOption(taos, option, (const char *)arg);
×
244
}
245

246
// this function may be called by user or system, or by both simultaneously.
247
void taos_cleanup(void) {
1,794,576✔
248
  tscInfo("start to cleanup client environment");
1,794,576✔
249
  if (atomic_val_compare_exchange_32(&sentinel, TSC_VAR_NOT_RELEASE, TSC_VAR_RELEASED) != TSC_VAR_NOT_RELEASE) {
1,794,576✔
250
    return;
3,219✔
251
  }
252

253
  monitorClose();
1,791,357✔
254
  tscStopCrashReport();
1,791,357✔
255

256
  hbMgrCleanUp();
1,791,357✔
257

258
  catalogDestroy();
1,791,357✔
259
  schedulerDestroy();
1,791,357✔
260

261
  fmFuncMgtDestroy();
1,791,357✔
262
  qCleanupKeywordsTable();
1,791,357✔
263

264
#if !defined(WINDOWS) && !defined(TD_ASTRA)
265
  tzCleanup();
1,791,357✔
266
#endif
267
  tmqMgmtClose();
1,791,357✔
268

269
  int32_t id = clientReqRefPool;
1,791,357✔
270
  clientReqRefPool = -1;
1,791,357✔
271
  taosCloseRef(id);
1,791,357✔
272

273
  id = clientConnRefPool;
1,791,357✔
274
  clientConnRefPool = -1;
1,791,357✔
275
  taosCloseRef(id);
1,791,357✔
276

277
  nodesDestroyAllocatorSet();
1,791,357✔
278
  cleanupAppInfo();
1,791,357✔
279
  rpcCleanup();
1,791,357✔
280
  tscDebug("rpc cleanup");
1,791,357✔
281

282
  if (TSDB_CODE_SUCCESS != cleanupTaskQueue()) {
1,791,357✔
283
    tscWarn("failed to cleanup task queue");
×
284
  }
285

286
  taosConvDestroy();
1,791,357✔
287
  DestroyRegexCache();
1,791,357✔
288
#ifdef TAOSD_INTEGRATED
289
  shellStopDaemon();
290
#endif
291
  tscInfo("all local resources released");
1,791,357✔
292
  taosCleanupCfg();
1,791,357✔
293
#ifndef TAOSD_INTEGRATED
294
  taosCloseLog();
1,791,357✔
295
#endif
296
}
297

298
static setConfRet taos_set_config_imp(const char *config) {
478✔
299
  setConfRet ret = {SET_CONF_RET_SUCC, {0}};
478✔
300
  // TODO: need re-implementation
301
  return ret;
478✔
302
}
303

304
setConfRet taos_set_config(const char *config) {
478✔
305
  // TODO  pthread_mutex_lock(&setConfMutex);
306
  setConfRet ret = taos_set_config_imp(config);
478✔
307
  //  pthread_mutex_unlock(&setConfMutex);
308
  return ret;
478✔
309
}
310

311
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
3,704,118✔
312
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
3,704,118✔
313
  if (user == NULL) {
3,705,015✔
314
    user = TSDB_DEFAULT_USER;
379,934✔
315
  }
316

317
  if (pass == NULL) {
3,705,015✔
318
    pass = TSDB_DEFAULT_PASS;
379,934✔
319
  }
320

321
  STscObj *pObj = NULL;
3,705,015✔
322
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY, &pObj);
3,705,015✔
323
  if (TSDB_CODE_SUCCESS == code) {
3,704,546✔
324
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
3,689,464✔
325
    if (NULL == rid) {
3,689,656✔
326
      tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db);
×
327
      return NULL;
×
328
    }
329
    *rid = pObj->id;
3,689,656✔
330
    return (TAOS *)rid;
3,689,656✔
331
  } else {
332
    terrno = code;
15,082✔
333
  }
334

335
  return NULL;
15,177✔
336
}
337

338
TAOS *taos_connect_with_dsn(const char *dsn) {
×
339
  terrno = TSDB_CODE_OPS_NOT_SUPPORT;
×
340
  tscError("taos_connect_with_dsn not supported");
×
341
  return NULL;
×
342
}
343

344
int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type) {
18,550✔
345
  if (taos == NULL) {
18,550✔
346
    terrno = TSDB_CODE_INVALID_PARA;
×
347
    return terrno;
×
348
  }
349

350
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
18,550✔
351
  if (NULL == pObj) {
18,550✔
352
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
353
    tscError("invalid parameter for %s", __func__);
×
354
    return terrno;
×
355
  }
356

357
  switch (type) {
18,550✔
358
    case TAOS_NOTIFY_PASSVER: {
5,300✔
359
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
5,300✔
360
      pObj->passInfo.fp = fp;
5,300✔
361
      pObj->passInfo.param = param;
5,300✔
362
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
5,300✔
363
      break;
5,300✔
364
    }
365
    case TAOS_NOTIFY_WHITELIST_VER: {
×
366
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
367
      pObj->whiteListInfo.fp = fp;
×
368
      pObj->whiteListInfo.param = param;
×
369
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
370
      break;
×
371
    }
372
    case TAOS_NOTIFY_USER_DROPPED: {
13,250✔
373
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
13,250✔
374
      pObj->userDroppedInfo.fp = fp;
13,250✔
375
      pObj->userDroppedInfo.param = param;
13,250✔
376
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
13,250✔
377
      break;
13,250✔
378
    }
379
    case TAOS_NOTIFY_DATETIME_WHITELIST_VER: {
×
380
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
381
      pObj->dateTimeWhiteListInfo.fp = fp;
×
382
      pObj->dateTimeWhiteListInfo.param = param;
×
383
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
384
      break;
×
385
    }
386
    default: {
×
387
      terrno = TSDB_CODE_INVALID_PARA;
×
388
      releaseTscObj(*(int64_t *)taos);
×
389
      return terrno;
×
390
    }
391
  }
392

393
  releaseTscObj(*(int64_t *)taos);
18,550✔
394
  return 0;
18,550✔
395
}
396

397
typedef struct SFetchWhiteListInfo {
398
  int64_t                     connId;
399
  __taos_async_whitelist_fn_t userCbFn;
400
  void                       *userParam;
401
} SFetchWhiteListInfo;
402

403
int32_t fetchWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
404
  SFetchWhiteListInfo *pInfo = (SFetchWhiteListInfo *)param;
×
405
  TAOS                *taos = &pInfo->connId;
×
406
  if (code != TSDB_CODE_SUCCESS) {
×
407
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
408
    taosMemoryFree(pMsg->pData);
×
409
    taosMemoryFree(pMsg->pEpSet);
×
410
    taosMemoryFree(pInfo);
×
411
    return code;
×
412
  }
413

414
  SGetUserIpWhiteListRsp wlRsp;
×
415
  if (TSDB_CODE_SUCCESS != tDeserializeSGetUserIpWhiteListRsp(pMsg->pData, pMsg->len, &wlRsp)) {
×
416
    taosMemoryFree(pMsg->pData);
×
417
    taosMemoryFree(pMsg->pEpSet);
×
418
    taosMemoryFree(pInfo);
×
419
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
420
    return terrno;
×
421
  }
422

423
  uint64_t *pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(uint64_t));
×
424
  if (pWhiteLists == NULL) {
×
425
    taosMemoryFree(pMsg->pData);
×
426
    taosMemoryFree(pMsg->pEpSet);
×
427
    taosMemoryFree(pInfo);
×
428
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
429
    return terrno;
×
430
  }
431

432
  for (int i = 0; i < wlRsp.numWhiteLists; ++i) {
×
433
    pWhiteLists[i] = ((uint64_t)wlRsp.pWhiteLists[i].mask << 32) | wlRsp.pWhiteLists[i].ip;
×
434
  }
435

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

438
  taosMemoryFree(pWhiteLists);
×
439
  taosMemoryFree(pMsg->pData);
×
440
  taosMemoryFree(pMsg->pEpSet);
×
441
  taosMemoryFree(pInfo);
×
442
  tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
443
  return code;
×
444
}
445

446
void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *param) {
×
447
  if (NULL == taos) {
×
448
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
449
    return;
×
450
  }
451

452
  int64_t connId = *(int64_t *)taos;
×
453

454
  STscObj *pTsc = acquireTscObj(connId);
×
455
  if (NULL == pTsc) {
×
456
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
457
    return;
×
458
  }
459

460
  SGetUserWhiteListReq req;
×
461
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
462
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
463
  if (msgLen < 0) {
×
464
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
465
    releaseTscObj(connId);
×
466
    return;
×
467
  }
468

469
  void *pReq = taosMemoryMalloc(msgLen);
×
470
  if (pReq == NULL) {
×
471
    fp(param, terrno, taos, 0, NULL);
×
472
    releaseTscObj(connId);
×
473
    return;
×
474
  }
475

476
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
477
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
478
    taosMemoryFree(pReq);
×
479
    releaseTscObj(connId);
×
480
    return;
×
481
  }
482

483
  SFetchWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchWhiteListInfo));
×
484
  if (pParam == NULL) {
×
485
    fp(param, terrno, taos, 0, NULL);
×
486
    taosMemoryFree(pReq);
×
487
    releaseTscObj(connId);
×
488
    return;
×
489
  }
490

491
  pParam->connId = connId;
×
492
  pParam->userCbFn = fp;
×
493

494
  pParam->userParam = param;
×
495
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
496
  if (pSendInfo == NULL) {
×
497
    fp(param, terrno, taos, 0, NULL);
×
498
    taosMemoryFree(pParam);
×
499
    taosMemoryFree(pReq);
×
500
    releaseTscObj(connId);
×
501
    return;
×
502
  }
503

504
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
505
  pSendInfo->requestId = generateRequestId();
×
506
  pSendInfo->requestObjRefId = 0;
×
507
  pSendInfo->param = pParam;
×
508
  pSendInfo->fp = fetchWhiteListCallbackFn;
×
509
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST;
×
510

511
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
512
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
513
    tscWarn("failed to async send msg to server");
×
514
  }
515
  releaseTscObj(connId);
×
516
  return;
×
517
}
518

519

520

521
typedef struct SFetchIpWhiteListInfo {
522
  int64_t connId;
523
  bool supportNeg;
524
  void   *userParam;
525

526
  __taos_async_ip_whitelist_fn_t userCbFn;
527
} SFetchIpWhiteListInfo;
528

529

530

531
int32_t fetchIpWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
532
  int32_t lino = 0;
×
533
  char  **pWhiteLists = NULL;
×
534

535
  SGetUserIpWhiteListRsp wlRsp = {0};
×
536

537
  SFetchIpWhiteListInfo *pInfo = (SFetchIpWhiteListInfo *)param;
×
538
  TAOS *taos = &pInfo->connId;
×
539

540
  if (code != TSDB_CODE_SUCCESS) {
×
541
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
542
    TAOS_CHECK_GOTO(code, &lino, _error);
×
543
  }
544

545
  if ((code = tDeserializeSGetUserIpWhiteListDualRsp(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
546
    TAOS_CHECK_GOTO(code, &lino, _error);
×
547
  }
548

549
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
550
  if (pWhiteLists == NULL) {
×
551
    code = terrno;
×
552
    TAOS_CHECK_GOTO(code, &lino, _error);
×
553
  }
554

555
  int32_t numWhiteLists =0;
×
556
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
557
    SIpRange *pIpRange = &wlRsp.pWhiteListsDual[i];
×
558
    if (!pInfo->supportNeg && pIpRange->neg) {
×
559
      continue;
×
560
    }
561
    SIpAddr   ipAddr = {0};
×
562

563
    code = tIpUintToStr(pIpRange, &ipAddr);
×
564
    TAOS_CHECK_GOTO(code, &lino, _error);
×
565

566
    char *ip = taosMemCalloc(1, IP_RESERVE_CAP);
×
567
    if (ip == NULL) {
×
568
      code = terrno;
×
569
      TAOS_CHECK_GOTO(code, &lino, _error);
×
570
    }
571
    if (ipAddr.type == 0) {
×
572
      if (pInfo->supportNeg) {
×
573
        snprintf(ip, IP_RESERVE_CAP, "%c %s/%d", pIpRange->neg ? '-' : '+', ipAddr.ipv4, ipAddr.mask);
×
574
      } else {
575
        snprintf(ip, IP_RESERVE_CAP, "%s/%d", ipAddr.ipv4, ipAddr.mask);
×
576
      }
577
    } else {
578
      if (ipAddr.ipv6[0] == 0) {
×
579
        memcpy(ipAddr.ipv6, "::", 2);
×
580
      }
581
      if (pInfo->supportNeg) {
×
582
        snprintf(ip, IP_RESERVE_CAP, "%c %s/%d", pIpRange->neg ? '-' : '+', ipAddr.ipv6, ipAddr.mask);
×
583
      } else {
584
        snprintf(ip, IP_RESERVE_CAP, "%s/%d", ipAddr.ipv6, ipAddr.mask);
×
585
      }
586
    }
587
    pWhiteLists[numWhiteLists++] = ip;
×
588
  }
589

590
  pInfo->userCbFn(pInfo->userParam, code, taos, numWhiteLists, pWhiteLists);
×
591
_error:
×
592
  if (pWhiteLists != NULL) {
×
593
    for (int32_t i = 0; i < numWhiteLists; i++) {
×
594
      taosMemFree(pWhiteLists[i]);
×
595
    }
596
    taosMemoryFree(pWhiteLists);
×
597
  }
598
  taosMemoryFree(pMsg->pData);
×
599
  taosMemoryFree(pMsg->pEpSet);
×
600
  taosMemoryFree(pInfo);
×
601
  tFreeSGetUserIpWhiteListDualRsp(&wlRsp);
×
602
  return code;
×
603
}
604

605

606

607
static void taosFetchIpWhiteList(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param, bool supportNeg) {
×
608
  if (NULL == taos) {
×
609
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
610
    return;
×
611
  }
612
  int64_t connId = *(int64_t *)taos;
×
613

614
  STscObj *pTsc = acquireTscObj(connId);
×
615
  if (NULL == pTsc) {
×
616
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
617
    return;
×
618
  }
619

620
  SGetUserWhiteListReq req;
×
621
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
622
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
623
  if (msgLen < 0) {
×
624
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
625
    releaseTscObj(connId);
×
626
    return;
×
627
  }
628

629
  void *pReq = taosMemoryMalloc(msgLen);
×
630
  if (pReq == NULL) {
×
631
    fp(param, terrno, taos, 0, NULL);
×
632
    releaseTscObj(connId);
×
633
    return;
×
634
  }
635

636
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
637
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
638
    taosMemoryFree(pReq);
×
639
    releaseTscObj(connId);
×
640
    return;
×
641
  }
642

643
  SFetchIpWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchIpWhiteListInfo));
×
644
  if (pParam == NULL) {
×
645
    fp(param, terrno, taos, 0, NULL);
×
646
    taosMemoryFree(pReq);
×
647
    releaseTscObj(connId);
×
648
    return;
×
649
  }
650

651
  pParam->connId = connId;
×
652
  pParam->supportNeg = supportNeg;
×
653
  pParam->userCbFn = fp;
×
654
  pParam->userParam = param;
×
655

656
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
657
  if (pSendInfo == NULL) {
×
658
    fp(param, terrno, taos, 0, NULL);
×
659
    taosMemoryFree(pParam);
×
660
    taosMemoryFree(pReq);
×
661
    releaseTscObj(connId);
×
662
    return;
×
663
  }
664

665
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
666
  pSendInfo->requestId = generateRequestId();
×
667
  pSendInfo->requestObjRefId = 0;
×
668
  pSendInfo->param = pParam;
×
669
  pSendInfo->fp = fetchIpWhiteListCallbackFn;
×
670
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST_DUAL;
×
671

672
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
673
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
674
    tscWarn("failed to async send msg to server");
×
675
  }
676
  releaseTscObj(connId);
×
677
  return;
×
678
}
679

680

681

682
void taos_fetch_whitelist_dual_stack_a(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param) {
×
683
  taosFetchIpWhiteList(taos, fp, param, false);
×
684
}
×
685

686

687

688
void taos_fetch_ip_whitelist_a(TAOS *taos, __taos_async_ip_whitelist_fn_t fp, void *param) {
×
689
  taosFetchIpWhiteList(taos, fp, param, true);
×
690
}
×
691

692

693
typedef struct SFetchDateTimeWhiteListInfo {
694
  int64_t                              connId;
695
  void                                *userParam;
696
  __taos_async_datetime_whitelist_fn_t userCbFn;
697
} SFetchDateTimeWhiteListInfo;
698

699

700

701
static const char* weekdays[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
702
int32_t fetchDateTimeWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
703
  int32_t lino = 0;
×
704
  char  **pWhiteLists = NULL;
×
705

706
  SUserDateTimeWhiteList wlRsp = {0};
×
707

708
  SFetchDateTimeWhiteListInfo *pInfo = (SFetchDateTimeWhiteListInfo *)param;
×
709
  TAOS *taos = &pInfo->connId;
×
710

711
  if (code != TSDB_CODE_SUCCESS) {
×
712
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
713
    TAOS_CHECK_GOTO(code, &lino, _error);
×
714
  }
715

716
  if ((code = tDeserializeSUserDateTimeWhiteList(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
717
    TAOS_CHECK_GOTO(code, &lino, _error);
×
718
  }
719

720
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
721
  if (pWhiteLists == NULL) {
×
722
    code = terrno;
×
723
    TAOS_CHECK_GOTO(code, &lino, _error);
×
724
  }
725

726
  int32_t numWhiteLists =0;
×
727
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
728
    SDateTimeWhiteListItem *item = &wlRsp.pWhiteLists[i];
×
729

730
    char *p = taosMemCalloc(1, 128);
×
731
    if (p == NULL) {
×
732
      code = terrno;
×
733
      TAOS_CHECK_GOTO(code, &lino, _error);
×
734
    }
735

736
    int duration = item->duration / 60;
×
737

738
    if (item->absolute) {
×
739
      struct STm tm;
×
740
      (void)taosTs2Tm(item->start, TSDB_TIME_PRECISION_SECONDS, &tm, NULL);
×
741
      snprintf(p, 128, "%c %04d-%02d-%02d %02d:%02d %d", item->neg ? '-' : '+', tm.tm.tm_year + 1900, tm.tm.tm_mon + 1, tm.tm.tm_mday, tm.tm.tm_hour, tm.tm.tm_min, duration);
×
742
    } else {
743
      int day = item->start / 86400;
×
744
      int hour = (item->start % 86400) / 3600;
×
745
      int minute = (item->start % 3600) / 60;
×
746
      snprintf(p, 128, "%c %s %02d:%02d %d", item->neg ? '-' : '+', weekdays[day], hour, minute, duration);
×
747
    }
748
    pWhiteLists[numWhiteLists++] = p;
×
749
  }
750

751
  pInfo->userCbFn(pInfo->userParam, code, taos, numWhiteLists, pWhiteLists);
×
752
_error:
×
753
  if (pWhiteLists != NULL) {
×
754
    for (int32_t i = 0; i < numWhiteLists; i++) {
×
755
      taosMemFree(pWhiteLists[i]);
×
756
    }
757
    taosMemoryFree(pWhiteLists);
×
758
  }
759
  taosMemoryFree(pMsg->pData);
×
760
  taosMemoryFree(pMsg->pEpSet);
×
761
  taosMemoryFree(pInfo);
×
762
  tFreeSUserDateTimeWhiteList(&wlRsp);
×
763
  return code;
×
764
}
765

766

767

768
void taos_fetch_datetime_whitelist_a(TAOS *taos, __taos_async_datetime_whitelist_fn_t fp, void *param) {
×
769
  if (NULL == taos) {
×
770
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
771
    return;
×
772
  }
773
  int64_t connId = *(int64_t *)taos;
×
774

775
  STscObj *pTsc = acquireTscObj(connId);
×
776
  if (NULL == pTsc) {
×
777
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
778
    return;
×
779
  }
780

781
  SGetUserWhiteListReq req;
×
782
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
783
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
784
  if (msgLen < 0) {
×
785
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
786
    releaseTscObj(connId);
×
787
    return;
×
788
  }
789

790
  void *pReq = taosMemoryMalloc(msgLen);
×
791
  if (pReq == NULL) {
×
792
    fp(param, terrno, taos, 0, NULL);
×
793
    releaseTscObj(connId);
×
794
    return;
×
795
  }
796

797
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
798
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
799
    taosMemoryFree(pReq);
×
800
    releaseTscObj(connId);
×
801
    return;
×
802
  }
803

804
  SFetchDateTimeWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchDateTimeWhiteListInfo));
×
805
  if (pParam == NULL) {
×
806
    fp(param, terrno, taos, 0, NULL);
×
807
    taosMemoryFree(pReq);
×
808
    releaseTscObj(connId);
×
809
    return;
×
810
  }
811

812
  pParam->connId = connId;
×
813
  pParam->userCbFn = fp;
×
814
  pParam->userParam = param;
×
815

816
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
817
  if (pSendInfo == NULL) {
×
818
    fp(param, terrno, taos, 0, NULL);
×
819
    taosMemoryFree(pParam);
×
820
    taosMemoryFree(pReq);
×
821
    releaseTscObj(connId);
×
822
    return;
×
823
  }
824

825
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
826
  pSendInfo->requestId = generateRequestId();
×
827
  pSendInfo->requestObjRefId = 0;
×
828
  pSendInfo->param = pParam;
×
829
  pSendInfo->fp = fetchDateTimeWhiteListCallbackFn;
×
830
  pSendInfo->msgType = TDMT_MND_GET_USER_DATETIME_WHITELIST;
×
831

832
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
833
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
834
    tscWarn("failed to async send msg to server");
×
835
  }
836
  releaseTscObj(connId);
×
837
  return;
×
838
}
839

840

841

842
void taos_close_internal(void *taos) {
3,781,938✔
843
  if (taos == NULL) {
3,781,938✔
844
    return;
×
845
  }
846

847
  STscObj *pTscObj = (STscObj *)taos;
3,781,938✔
848
  tscDebug("conn:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
3,781,938✔
849

850
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
3,781,938✔
851
    tscError("conn:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
×
852
  }
853
}
854

855
void taos_close(TAOS *taos) {
3,684,579✔
856
  if (taos == NULL) {
3,684,579✔
UNCOV
857
    return;
×
858
  }
859

860
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
3,684,579✔
861
  if (NULL == pObj) {
3,684,697✔
862
    taosMemoryFree(taos);
×
863
    return;
×
864
  }
865

866
  taos_close_internal(pObj);
3,684,697✔
867
  releaseTscObj(*(int64_t *)taos);
3,684,579✔
868
  taosMemoryFree(taos);
3,684,697✔
869
}
870

871
int taos_errno(TAOS_RES *res) {
839,979,790✔
872
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
839,979,790✔
873
    return terrno;
37,145✔
874
  }
875

876
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
839,943,061✔
877
    return 0;
324,592✔
878
  }
879

880
  return ((SRequestObj *)res)->code;
839,617,831✔
881
}
882

883
const char *taos_errstr(TAOS_RES *res) {
21,996,212✔
884
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
21,996,212✔
885
    return (const char *)tstrerror(terrno);
37,029✔
886
  }
887

888
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
21,959,183✔
889
    return "success";
×
890
  }
891

892
  SRequestObj *pRequest = (SRequestObj *)res;
21,959,183✔
893
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
21,959,183✔
894
    return pRequest->msgBuf;
17,878,732✔
895
  } else {
896
    return (const char *)tstrerror(pRequest->code);
4,080,451✔
897
  }
898
}
899

900
void taos_free_result(TAOS_RES *res) {
663,026,746✔
901
  if (NULL == res) {
663,026,746✔
902
    return;
1,906,403✔
903
  }
904

905
  tscTrace("res:%p, will be freed", res);
661,120,343✔
906

907
  if (TD_RES_QUERY(res)) {
661,120,858✔
908
    SRequestObj *pRequest = (SRequestObj *)res;
657,042,219✔
909
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query, res:%p", pRequest->requestId, res);
657,042,219✔
910
    destroyRequest(pRequest);
657,042,984✔
911
    return;
657,044,882✔
912
  }
913

914
  SMqRspObj *pRsp = (SMqRspObj *)res;
4,079,395✔
915
  if (TD_RES_TMQ(res)) {
4,079,395✔
916
    tDeleteMqDataRsp(&pRsp->dataRsp);
4,064,956✔
917
    doFreeReqResultInfo(&pRsp->resInfo);
4,064,849✔
918
  } else if (TD_RES_TMQ_METADATA(res)) {
14,126✔
919
    tDeleteSTaosxRsp(&pRsp->dataRsp);
531✔
920
    doFreeReqResultInfo(&pRsp->resInfo);
531✔
921
  } else if (TD_RES_TMQ_META(res)) {
13,595✔
922
    tDeleteMqMetaRsp(&pRsp->metaRsp);
11,928✔
923
  } else if (TD_RES_TMQ_BATCH_META(res)) {
1,667✔
924
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
1,667✔
925
  } else if (TD_RES_TMQ_RAW(res)) {
×
926
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
×
927
  }
928
  taosMemoryFree(pRsp);
4,079,082✔
929
}
930

UNCOV
931
void taos_kill_query(TAOS *taos) {
×
UNCOV
932
  if (NULL == taos) {
×
UNCOV
933
    return;
×
934
  }
935

UNCOV
936
  int64_t  rid = *(int64_t *)taos;
×
UNCOV
937
  STscObj *pTscObj = acquireTscObj(rid);
×
UNCOV
938
  if (pTscObj) {
×
UNCOV
939
    stopAllRequests(pTscObj->pRequests);
×
940
  }
UNCOV
941
  releaseTscObj(rid);
×
942
}
943

944
int taos_field_count(TAOS_RES *res) {
2,147,483,647✔
945
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
946
    return 0;
×
947
  }
948

949
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
950
  return pResInfo->numOfCols;
2,147,483,647✔
951
}
952

953
int taos_num_fields(TAOS_RES *res) { return taos_field_count(res); }
2,147,483,647✔
954

955
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
1,603,179,635✔
956
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,603,179,635✔
957
    return NULL;
2,625,531✔
958
  }
959

960
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
1,600,703,433✔
961
  return pResInfo->userFields;
1,600,703,433✔
962
}
963

964
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
655,273,646✔
965
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
7,417✔
966
  return taosQueryImplWithReqid(taos, sql, false, reqid);
7,417✔
967
}
968

969
TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res) {
1,521✔
970
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,521✔
971
    return NULL;
×
972
  }
973
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
1,521✔
974
  return pResInfo->fields;
1,521✔
975
}
976

977
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
2,147,483,647✔
978
  if (res == NULL) {
2,147,483,647✔
979
    return NULL;
×
980
  }
981

982
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
983
    SRequestObj *pRequest = (SRequestObj *)res;
1,663,638,891✔
984
    if (pRequest->killed) {
1,663,638,891✔
985
      tscInfo("query has been killed, can not fetch more row.");
×
986
      pRequest->code = TSDB_CODE_TSC_QUERY_KILLED;
×
987
      return NULL;
×
988
    }
989

990
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
1,663,642,966✔
991
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
1,663,607,272✔
992
      return NULL;
×
993
    }
994

995
    if (pRequest->inCallback) {
1,663,650,871✔
996
      tscError("can not call taos_fetch_row before query callback ends.");
×
997
      terrno = TSDB_CODE_TSC_INVALID_OPERATION;
×
998
      return NULL;
×
999
    }
1000

1001
    return doAsyncFetchRows(pRequest, true, true);
1,663,625,302✔
1002
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,501,573,438✔
1003
    SMqRspObj      *msg = ((SMqRspObj *)res);
1,501,631,153✔
1004
    SReqResultInfo *pResultInfo = NULL;
1,501,631,153✔
1005
    if (msg->resIter == -1) {
1,501,604,819✔
1006
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
3,707,069✔
1007
        return NULL;
×
1008
      }
1009
    } else {
1010
      pResultInfo = tmqGetCurResInfo(res);
1,497,988,444✔
1011
    }
1012

1013
    if (pResultInfo->current < pResultInfo->numOfRows) {
1,501,695,406✔
1014
      doSetOneRowPtr(pResultInfo);
1,471,524,693✔
1015
      pResultInfo->current += 1;
1,471,826,275✔
1016
      return pResultInfo->row;
1,471,927,063✔
1017
    } else {
1018
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
30,242,520✔
1019
        return NULL;
3,706,844✔
1020
      }
1021

1022
      doSetOneRowPtr(pResultInfo);
26,535,599✔
1023
      pResultInfo->current += 1;
26,535,599✔
1024
      return pResultInfo->row;
26,535,599✔
1025
    }
1026
  } else if (TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1027
    return NULL;
×
1028
  } else {
1029
    tscError("invalid result passed to taos_fetch_row");
×
1030
    terrno = TSDB_CODE_TMQ_INVALID_DATA;
×
1031
    return NULL;
×
1032
  }
1033
}
1034

1035
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
1,500,881,030✔
1036
  return taos_print_row_with_size(str, INT32_MAX, row, fields, num_fields);
1,500,881,030✔
1037
}
1038
int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
1,501,240,239✔
1039
  int32_t len = 0;
1,501,240,239✔
1040
  for (int i = 0; i < num_fields; ++i) {
2,147,483,647✔
1041
    if (i > 0 && len < size - 1) {
2,147,483,647✔
1042
      str[len++] = ' ';
2,147,483,647✔
1043
    }
1044

1045
    if (row[i] == NULL) {
2,147,483,647✔
1046
      len += tsnprintf(str + len, size - len, "%s", TSDB_DATA_NULL_STR);
33,705,480✔
1047
      continue;
33,705,326✔
1048
    }
1049

1050
    switch (fields[i].type) {
2,147,483,647✔
1051
      case TSDB_DATA_TYPE_TINYINT:
77,303,570✔
1052
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
77,303,570✔
1053
        break;
77,345,975✔
1054

1055
      case TSDB_DATA_TYPE_UTINYINT:
663,442✔
1056
        len += tsnprintf(str + len, size - len, "%u", *((uint8_t *)row[i]));
663,442✔
1057
        break;
663,442✔
1058

1059
      case TSDB_DATA_TYPE_SMALLINT:
663,600✔
1060
        len += tsnprintf(str + len, size - len, "%d", *((int16_t *)row[i]));
663,600✔
1061
        break;
663,600✔
1062

1063
      case TSDB_DATA_TYPE_USMALLINT:
663,600✔
1064
        len += tsnprintf(str + len, size - len, "%u", *((uint16_t *)row[i]));
663,600✔
1065
        break;
663,600✔
1066

1067
      case TSDB_DATA_TYPE_INT:
1,551,416,379✔
1068
        len += tsnprintf(str + len, size - len, "%d", *((int32_t *)row[i]));
1,551,416,379✔
1069
        break;
1,551,528,557✔
1070

1071
      case TSDB_DATA_TYPE_UINT:
663,600✔
1072
        len += tsnprintf(str + len, size - len, "%u", *((uint32_t *)row[i]));
663,600✔
1073
        break;
663,600✔
1074

1075
      case TSDB_DATA_TYPE_BIGINT:
1,185,285,836✔
1076
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
1,185,285,836✔
1077
        break;
1,185,292,578✔
1078

1079
      case TSDB_DATA_TYPE_UBIGINT:
663,600✔
1080
        len += tsnprintf(str + len, size - len, "%" PRIu64, *((uint64_t *)row[i]));
663,600✔
1081
        break;
663,442✔
1082

1083
      case TSDB_DATA_TYPE_FLOAT: {
152,448,728✔
1084
        float fv = 0;
152,448,728✔
1085
        fv = GET_FLOAT_VAL(row[i]);
152,448,728✔
1086
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
152,480,082✔
1087
      } break;
153,868,139✔
1088

1089
      case TSDB_DATA_TYPE_DOUBLE: {
808,618,218✔
1090
        double dv = 0;
808,618,218✔
1091
        dv = GET_DOUBLE_VAL(row[i]);
808,618,218✔
1092
        len += snprintf(str + len, size - len, "%.*g", DBL_DIG, dv);
808,614,610✔
1093
      } break;
808,619,489✔
1094

1095
      case TSDB_DATA_TYPE_VARBINARY: {
663,312✔
1096
        void    *data = NULL;
663,312✔
1097
        uint32_t tmp = 0;
663,312✔
1098
        int32_t  charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
663,312✔
1099
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
663,312✔
1100
          break;
×
1101
        }
1102
        uint32_t copyLen = TMIN(size - len - 1, tmp);
663,786✔
1103
        (void)memcpy(str + len, data, copyLen);
663,786✔
1104
        len += copyLen;
663,786✔
1105
        taosMemoryFree(data);
663,786✔
1106
      } break;
663,944✔
1107
      case TSDB_DATA_TYPE_BINARY:
1,536,616,832✔
1108
      case TSDB_DATA_TYPE_NCHAR:
1109
      case TSDB_DATA_TYPE_GEOMETRY: {
1110
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
1,536,616,832✔
1111
        if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_VARBINARY ||
1,536,352,921✔
1112
            fields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
418,516,543✔
1113
          if (charLen > fields[i].bytes || charLen < 0) {
1,118,682,322✔
1114
            tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
6,264✔
1115
            break;
×
1116
          }
1117
        } else {
1118
          if (charLen > fields[i].bytes * TSDB_NCHAR_SIZE || charLen < 0) {
417,855,747✔
1119
            tscError("taos_print_row error. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
2,212✔
1120
            break;
×
1121
          }
1122
        }
1123

1124
        uint32_t copyLen = TMIN(size - len - 1, charLen);
1,536,521,624✔
1125
        (void)memcpy(str + len, row[i], copyLen);
1,536,521,624✔
1126
        len += copyLen;
1,536,705,620✔
1127
      } break;
1,536,705,620✔
1128
      case TSDB_DATA_TYPE_BLOB:
×
1129
      case TSDB_DATA_TYPE_MEDIUMBLOB: {
1130
        void    *data = NULL;
×
1131
        uint32_t tmp = 0;
×
1132
        int32_t  charLen = blobDataLen((char *)row[i] - BLOBSTR_HEADER_SIZE);
×
1133
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
×
1134
          break;
×
1135
        }
1136

1137
        uint32_t copyLen = TMIN(size - len - 1, tmp);
×
1138
        (void)memcpy(str + len, data, copyLen);
×
1139
        len += copyLen;
×
1140

1141
        taosMemoryFree(data);
×
1142
      } break;
×
1143

1144
      case TSDB_DATA_TYPE_TIMESTAMP:
1,941,678,706✔
1145
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
1,941,678,706✔
1146
        break;
1,942,053,103✔
1147

1148
      case TSDB_DATA_TYPE_BOOL:
663,442✔
1149
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
663,442✔
1150
        break;
663,600✔
1151
      case TSDB_DATA_TYPE_DECIMAL64:
×
1152
      case TSDB_DATA_TYPE_DECIMAL: {
1153
        uint32_t decimalLen = strlen(row[i]);
×
1154
        uint32_t copyLen = TMIN(size - len - 1, decimalLen);
×
1155
        (void)memcpy(str + len, row[i], copyLen);
×
1156
        len += copyLen;
×
1157
      } break;
×
1158
      default:
×
1159
        break;
×
1160
    }
1161

1162
    if (len >= size - 1) {
2,147,483,647✔
1163
      break;
×
1164
    }
1165
  }
1166
  if (len < size) {
1,499,311,416✔
1167
    str[len] = 0;
1,501,857,756✔
1168
  }
1169

1170
  return len;
1,501,882,957✔
1171
}
1172

1173
int *taos_fetch_lengths(TAOS_RES *res) {
2,147,483,647✔
1174
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1175
    return NULL;
×
1176
  }
1177

1178
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1179
  return pResInfo->length;
2,147,483,647✔
1180
}
1181

1182
TAOS_ROW *taos_result_block(TAOS_RES *res) {
×
1183
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1184
    terrno = TSDB_CODE_INVALID_PARA;
×
1185
    return NULL;
×
1186
  }
1187

1188
  if (taos_is_update_query(res)) {
×
1189
    return NULL;
×
1190
  }
1191

1192
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
1193
  return &pResInfo->row;
×
1194
}
1195

1196
// todo intergrate with tDataTypes
1197
const char *taos_data_type(int type) {
×
1198
  switch (type) {
×
1199
    case TSDB_DATA_TYPE_NULL:
×
1200
      return "TSDB_DATA_TYPE_NULL";
×
1201
    case TSDB_DATA_TYPE_BOOL:
×
1202
      return "TSDB_DATA_TYPE_BOOL";
×
1203
    case TSDB_DATA_TYPE_TINYINT:
×
1204
      return "TSDB_DATA_TYPE_TINYINT";
×
1205
    case TSDB_DATA_TYPE_SMALLINT:
×
1206
      return "TSDB_DATA_TYPE_SMALLINT";
×
1207
    case TSDB_DATA_TYPE_INT:
×
1208
      return "TSDB_DATA_TYPE_INT";
×
1209
    case TSDB_DATA_TYPE_BIGINT:
×
1210
      return "TSDB_DATA_TYPE_BIGINT";
×
1211
    case TSDB_DATA_TYPE_FLOAT:
×
1212
      return "TSDB_DATA_TYPE_FLOAT";
×
1213
    case TSDB_DATA_TYPE_DOUBLE:
×
1214
      return "TSDB_DATA_TYPE_DOUBLE";
×
1215
    case TSDB_DATA_TYPE_VARCHAR:
×
1216
      return "TSDB_DATA_TYPE_VARCHAR";
×
1217
      //    case TSDB_DATA_TYPE_BINARY:          return "TSDB_DATA_TYPE_VARCHAR";
1218
    case TSDB_DATA_TYPE_TIMESTAMP:
×
1219
      return "TSDB_DATA_TYPE_TIMESTAMP";
×
1220
    case TSDB_DATA_TYPE_NCHAR:
×
1221
      return "TSDB_DATA_TYPE_NCHAR";
×
1222
    case TSDB_DATA_TYPE_JSON:
×
1223
      return "TSDB_DATA_TYPE_JSON";
×
1224
    case TSDB_DATA_TYPE_GEOMETRY:
×
1225
      return "TSDB_DATA_TYPE_GEOMETRY";
×
1226
    case TSDB_DATA_TYPE_UTINYINT:
×
1227
      return "TSDB_DATA_TYPE_UTINYINT";
×
1228
    case TSDB_DATA_TYPE_USMALLINT:
×
1229
      return "TSDB_DATA_TYPE_USMALLINT";
×
1230
    case TSDB_DATA_TYPE_UINT:
×
1231
      return "TSDB_DATA_TYPE_UINT";
×
1232
    case TSDB_DATA_TYPE_UBIGINT:
×
1233
      return "TSDB_DATA_TYPE_UBIGINT";
×
1234
    case TSDB_DATA_TYPE_VARBINARY:
×
1235
      return "TSDB_DATA_TYPE_VARBINARY";
×
1236
    case TSDB_DATA_TYPE_DECIMAL:
×
1237
      return "TSDB_DATA_TYPE_DECIMAL";
×
1238
    case TSDB_DATA_TYPE_BLOB:
×
1239
      return "TSDB_DATA_TYPE_BLOB";
×
1240
    case TSDB_DATA_TYPE_MEDIUMBLOB:
×
1241
      return "TSDB_DATA_TYPE_MEDIUMBLOB";
×
1242
    default:
×
1243
      return "UNKNOWN";
×
1244
  }
1245
}
1246

1247
const char *taos_get_client_info() { return td_version; }
1,256,159✔
1248

1249
// return int32_t
1250
int taos_affected_rows(TAOS_RES *res) {
511,688,199✔
1251
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
511,688,199✔
1252
      TD_RES_TMQ_BATCH_META(res)) {
511,695,583✔
1253
    return 0;
×
1254
  }
1255

1256
  SRequestObj    *pRequest = (SRequestObj *)res;
511,693,238✔
1257
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
511,693,238✔
1258
  return (int)pResInfo->numOfRows;
511,694,327✔
1259
}
1260

1261
// return int64_t
1262
int64_t taos_affected_rows64(TAOS_RES *res) {
1,336,955✔
1263
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,336,955✔
1264
      TD_RES_TMQ_BATCH_META(res)) {
1,336,955✔
1265
    return 0;
×
1266
  }
1267

1268
  SRequestObj    *pRequest = (SRequestObj *)res;
1,336,955✔
1269
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
1,336,955✔
1270
  return pResInfo->numOfRows;
1,336,955✔
1271
}
1272

1273
int taos_result_precision(TAOS_RES *res) {
1,522,528,197✔
1274
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,522,528,197✔
1275
    return TSDB_TIME_PRECISION_MILLI;
×
1276
  }
1277

1278
  if (TD_RES_QUERY(res)) {
1,522,527,582✔
1279
    SRequestObj *pRequest = (SRequestObj *)res;
97,236,319✔
1280
    return pRequest->body.resInfo.precision;
97,236,319✔
1281
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,425,293,848✔
1282
    SReqResultInfo *info = tmqGetCurResInfo(res);
1,425,295,329✔
1283
    return info->precision;
1,425,295,329✔
1284
  }
1285
  return TSDB_TIME_PRECISION_MILLI;
×
1286
}
1287

1288
int taos_select_db(TAOS *taos, const char *db) {
154,077✔
1289
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
154,077✔
1290
  if (pObj == NULL) {
154,077✔
1291
    releaseTscObj(*(int64_t *)taos);
×
1292
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1293
    return TSDB_CODE_TSC_DISCONNECTED;
×
1294
  }
1295

1296
  if (db == NULL || strlen(db) == 0) {
154,077✔
1297
    releaseTscObj(*(int64_t *)taos);
×
1298
    tscError("invalid parameter for %s", db == NULL ? "db is NULL" : "db is empty");
×
1299
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
1300
    return terrno;
×
1301
  }
1302

1303
  char sql[256] = {0};
154,077✔
1304
  (void)snprintf(sql, tListLen(sql), "use %s", db);
154,077✔
1305

1306
  TAOS_RES *pRequest = taos_query(taos, sql);
154,077✔
1307
  int32_t   code = taos_errno(pRequest);
154,077✔
1308

1309
  taos_free_result(pRequest);
154,077✔
1310
  releaseTscObj(*(int64_t *)taos);
154,077✔
1311
  return code;
154,077✔
1312
}
1313

1314
void taos_stop_query(TAOS_RES *res) {
661,829,496✔
1315
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
661,829,496✔
1316
      TD_RES_TMQ_BATCH_META(res)) {
661,830,521✔
UNCOV
1317
    return;
×
1318
  }
1319

1320
  stopAllQueries((SRequestObj *)res);
661,831,420✔
1321
}
1322

1323
bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
×
1324
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1325
    return true;
×
1326
  }
1327
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
×
1328
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
×
1329
    return true;
×
1330
  }
1331

1332
  SResultColumn *pCol = &pResultInfo->pCol[col];
×
1333
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
×
1334
    return (pCol->offset[row] == -1);
×
1335
  } else {
1336
    return colDataIsNull_f(pCol, row);
×
1337
  }
1338
}
1339

1340
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
8,419,524✔
1341

1342
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
177,808,059✔
1343
  int32_t numOfRows = 0;
177,808,059✔
1344
  /*int32_t code = */ terrno = taos_fetch_block_s(res, &numOfRows, rows);
177,808,059✔
1345
  return numOfRows;
177,807,597✔
1346
}
1347

1348
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
177,808,059✔
1349
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
177,808,059✔
1350
    return 0;
×
1351
  }
1352

1353
  if (TD_RES_QUERY(res)) {
177,808,059✔
1354
    SRequestObj *pRequest = (SRequestObj *)res;
173,438,446✔
1355

1356
    (*rows) = NULL;
173,438,446✔
1357
    (*numOfRows) = 0;
173,438,446✔
1358

1359
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
173,438,446✔
1360
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
173,269,513✔
1361
      return pRequest->code;
813,221✔
1362
    }
1363

1364
    (void)doAsyncFetchRows(pRequest, false, true);
172,625,225✔
1365

1366
    // TODO refactor
1367
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
172,625,225✔
1368
    pResultInfo->current = pResultInfo->numOfRows;
172,625,225✔
1369

1370
    (*rows) = pResultInfo->row;
172,625,225✔
1371
    (*numOfRows) = pResultInfo->numOfRows;
172,625,225✔
1372
    return pRequest->code;
172,625,225✔
1373
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
4,369,613✔
1374
    SReqResultInfo *pResultInfo = NULL;
4,369,613✔
1375
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
4,369,613✔
1376
    if (code != 0) return code;
4,369,613✔
1377

1378
    pResultInfo->current = pResultInfo->numOfRows;
4,053,581✔
1379
    (*rows) = pResultInfo->row;
4,053,119✔
1380
    (*numOfRows) = pResultInfo->numOfRows;
4,053,119✔
1381
    return 0;
4,053,119✔
1382
  } else {
1383
    tscError("taos_fetch_block_s invalid res type");
×
1384
    return TSDB_CODE_TMQ_INVALID_DATA;
×
1385
  }
1386
}
1387

1388
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
1,208,701✔
1389
  *numOfRows = 0;
1,208,701✔
1390
  *pData = NULL;
1,208,701✔
1391

1392
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,208,701✔
1393
    return 0;
×
1394
  }
1395

1396
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,208,701✔
1397
    SReqResultInfo *pResultInfo = NULL;
1,165,108✔
1398
    int32_t         code = tmqGetNextResInfo(res, false, &pResultInfo);
1,165,108✔
1399
    if (code != 0) {
1,165,108✔
1400
      (*numOfRows) = 0;
29,567✔
1401
      return 0;
29,567✔
1402
    }
1403

1404
    pResultInfo->current = pResultInfo->numOfRows;
1,135,541✔
1405
    (*numOfRows) = pResultInfo->numOfRows;
1,135,541✔
1406
    (*pData) = (void *)pResultInfo->pData;
1,135,541✔
1407
    return 0;
1,135,541✔
1408
  }
1409

1410
  SRequestObj *pRequest = (SRequestObj *)res;
43,593✔
1411

1412
  if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
43,593✔
1413
      pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
43,593✔
1414
    return pRequest->code;
×
1415
  }
1416

1417
  (void)doAsyncFetchRows(pRequest, false, false);
43,593✔
1418

1419
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
43,593✔
1420

1421
  pResultInfo->current = pResultInfo->numOfRows;
43,593✔
1422
  (*numOfRows) = pResultInfo->numOfRows;
43,593✔
1423
  (*pData) = (void *)pResultInfo->pData;
43,593✔
1424

1425
  return pRequest->code;
43,593✔
1426
}
1427

1428
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
123,361,369✔
1429
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
123,361,369✔
1430
    return 0;
×
1431
  }
1432

1433
  int32_t numOfFields = taos_num_fields(res);
123,361,369✔
1434
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
123,361,369✔
1435
    return 0;
×
1436
  }
1437

1438
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
123,361,369✔
1439
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
123,361,369✔
1440
  if (!IS_VAR_DATA_TYPE(pField->type)) {
123,361,369✔
1441
    return 0;
×
1442
  }
1443

1444
  return pResInfo->pCol[columnIndex].offset;
123,361,369✔
1445
}
1446

1447
int taos_is_null_by_column(TAOS_RES *res, int columnIndex, bool result[], int *rows) {
331,004,119✔
1448
  if (res == NULL || result == NULL || rows == NULL || *rows <= 0 || columnIndex < 0 || TD_RES_TMQ_META(res) ||
331,004,119✔
1449
      TD_RES_TMQ_RAW(res) || TD_RES_TMQ_BATCH_META(res)) {
331,004,119✔
1450
    return TSDB_CODE_INVALID_PARA;
×
1451
  }
1452

1453
  int32_t numOfFields = taos_num_fields(res);
331,003,489✔
1454
  if (columnIndex >= numOfFields || numOfFields == 0) {
331,004,119✔
1455
    return TSDB_CODE_INVALID_PARA;
×
1456
  }
1457

1458
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
331,004,119✔
1459
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
331,004,119✔
1460
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
331,004,119✔
1461

1462
  if (*rows > pResInfo->numOfRows) {
331,004,119✔
1463
    *rows = pResInfo->numOfRows;
×
1464
  }
1465
  if (IS_VAR_DATA_TYPE(pField->type)) {
331,004,119✔
1466
    for (int i = 0; i < *rows; i++) {
×
1467
      if (pCol->offset[i] == -1) {
×
1468
        result[i] = true;
×
1469
      } else {
1470
        result[i] = false;
×
1471
      }
1472
    }
1473
  } else {
1474
    for (int i = 0; i < *rows; i++) {
2,147,483,647✔
1475
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1476
        result[i] = true;
2,147,483,647✔
1477
      } else {
1478
        result[i] = false;
2,147,483,647✔
1479
      }
1480
    }
1481
  }
1482
  return 0;
331,004,119✔
1483
}
1484

1485
int taos_validate_sql(TAOS *taos, const char *sql) {
×
1486
  TAOS_RES *pObj = taosQueryImpl(taos, sql, true, TD_REQ_FROM_APP);
×
1487

1488
  int code = taos_errno(pObj);
×
1489

1490
  taos_free_result(pObj);
×
1491
  return code;
×
1492
}
1493

1494
void taos_reset_current_db(TAOS *taos) {
×
1495
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
1496
  if (pTscObj == NULL) {
×
1497
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1498
    return;
×
1499
  }
1500

1501
  resetConnectDB(pTscObj);
×
1502

1503
  releaseTscObj(*(int64_t *)taos);
×
1504
}
1505

1506
const char *taos_get_server_info(TAOS *taos) {
38,009✔
1507
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
38,009✔
1508
  if (pTscObj == NULL) {
38,009✔
1509
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1510
    return NULL;
×
1511
  }
1512

1513
  releaseTscObj(*(int64_t *)taos);
38,009✔
1514

1515
  return pTscObj->sDetailVer;
38,009✔
1516
}
1517

1518
int taos_get_current_db(TAOS *taos, char *database, int len, int *required) {
600✔
1519
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
600✔
1520
  if (pTscObj == NULL) {
600✔
1521
    return TSDB_CODE_TSC_DISCONNECTED;
×
1522
  }
1523

1524
  int code = TSDB_CODE_SUCCESS;
600✔
1525
  (void)taosThreadMutexLock(&pTscObj->mutex);
600✔
1526
  if (database == NULL || len <= 0) {
600✔
1527
    if (required != NULL) *required = strlen(pTscObj->db) + 1;
300✔
1528
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
300✔
1529
  } else if (len < strlen(pTscObj->db) + 1) {
300✔
1530
    tstrncpy(database, pTscObj->db, len);
150✔
1531
    if (required) *required = strlen(pTscObj->db) + 1;
150✔
1532
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
150✔
1533
  } else {
1534
    tstrncpy(database, pTscObj->db, len);
150✔
1535
    code = 0;
150✔
1536
  }
1537
_return:
600✔
1538
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
600✔
1539
  releaseTscObj(*(int64_t *)taos);
600✔
1540
  return code;
600✔
1541
}
1542

1543
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
1,322,009,690✔
1544
  if (NULL == pWrapper) {
1,322,009,690✔
1545
    return;
664,197,136✔
1546
  }
1547
  destoryCatalogReq(pWrapper->pCatalogReq);
657,812,554✔
1548
  taosMemoryFree(pWrapper->pCatalogReq);
657,811,043✔
1549
  qDestroyParseContext(pWrapper->pParseCtx);
657,806,082✔
1550
  taosMemoryFree(pWrapper);
657,809,669✔
1551
}
1552

1553
void destroyCtxInRequest(SRequestObj *pRequest) {
2,716,197✔
1554
  schedulerFreeJob(&pRequest->body.queryJob, 0);
2,716,197✔
1555
  qDestroyQuery(pRequest->pQuery);
2,716,197✔
1556
  pRequest->pQuery = NULL;
2,716,197✔
1557
  destorySqlCallbackWrapper(pRequest->pWrapper);
2,716,197✔
1558
  pRequest->pWrapper = NULL;
2,716,197✔
1559
}
2,716,197✔
1560

1561
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
183,413,270✔
1562
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
183,413,270✔
1563
  SRequestObj         *pRequest = pWrapper->pRequest;
183,413,270✔
1564
  SQuery              *pQuery = pRequest->pQuery;
183,413,270✔
1565

1566
  qDebug("req:0x%" PRIx64 ", start to semantic analysis, QID:0x%" PRIx64, pRequest->self, pRequest->requestId);
183,414,281✔
1567

1568
  int64_t analyseStart = taosGetTimestampUs();
183,413,984✔
1569
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
183,413,984✔
1570
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
183,413,984✔
1571

1572
  if (TSDB_CODE_SUCCESS == code) {
183,413,483✔
1573
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
183,407,109✔
1574
  }
1575

1576
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
183,409,315✔
1577

1578
  if (pRequest->parseOnly) {
183,411,920✔
1579
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
305,474✔
1580
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
305,474✔
1581
  }
1582

1583
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
183,412,940✔
1584
}
183,408,416✔
1585

1586
int32_t cloneCatalogReq(SCatalogReq **ppTarget, SCatalogReq *pSrc) {
×
1587
  int32_t      code = TSDB_CODE_SUCCESS;
×
1588
  SCatalogReq *pTarget = taosMemoryCalloc(1, sizeof(SCatalogReq));
×
1589
  if (pTarget == NULL) {
×
1590
    code = terrno;
×
1591
  } else {
1592
    pTarget->pDbVgroup = taosArrayDup(pSrc->pDbVgroup, NULL);
×
1593
    pTarget->pDbCfg = taosArrayDup(pSrc->pDbCfg, NULL);
×
1594
    pTarget->pDbInfo = taosArrayDup(pSrc->pDbInfo, NULL);
×
1595
    pTarget->pTableMeta = taosArrayDup(pSrc->pTableMeta, NULL);
×
1596
    pTarget->pTableHash = taosArrayDup(pSrc->pTableHash, NULL);
×
1597
    pTarget->pUdf = taosArrayDup(pSrc->pUdf, NULL);
×
1598
    pTarget->pIndex = taosArrayDup(pSrc->pIndex, NULL);
×
1599
    pTarget->pUser = taosArrayDup(pSrc->pUser, NULL);
×
1600
    pTarget->pTableIndex = taosArrayDup(pSrc->pTableIndex, NULL);
×
1601
    pTarget->pTableCfg = taosArrayDup(pSrc->pTableCfg, NULL);
×
1602
    pTarget->pTableTag = taosArrayDup(pSrc->pTableTag, NULL);
×
1603
    pTarget->pView = taosArrayDup(pSrc->pView, NULL);
×
1604
    pTarget->pTableTSMAs = taosArrayDup(pSrc->pTableTSMAs, NULL);
×
1605
    pTarget->pTSMAs = taosArrayDup(pSrc->pTSMAs, NULL);
×
1606
    pTarget->pVStbRefDbs = taosArrayDup(pSrc->pVStbRefDbs, NULL);
×
1607
    pTarget->qNodeRequired = pSrc->qNodeRequired;
×
1608
    pTarget->dNodeRequired = pSrc->dNodeRequired;
×
1609
    pTarget->svrVerRequired = pSrc->svrVerRequired;
×
1610
    pTarget->forceUpdate = pSrc->forceUpdate;
×
1611
    pTarget->cloned = true;
×
1612

1613
    *ppTarget = pTarget;
×
1614
  }
1615

1616
  return code;
×
1617
}
1618

1619
void handleSubQueryFromAnalyse(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, SNode *pRoot) {
×
1620
  SRequestObj         *pNewRequest = NULL;
×
1621
  SSqlCallbackWrapper *pNewWrapper = NULL;
×
1622
  int32_t              code = buildPreviousRequest(pWrapper->pRequest, pWrapper->pRequest->sqlstr, &pNewRequest);
×
1623
  if (code) {
×
1624
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1625
    return;
×
1626
  }
1627

1628
  pNewRequest->pQuery = NULL;
×
1629
  code = nodesMakeNode(QUERY_NODE_QUERY, (SNode **)&pNewRequest->pQuery);
×
1630
  if (pNewRequest->pQuery) {
×
1631
    pNewRequest->pQuery->pRoot = pRoot;
×
1632
    pRoot = NULL;
×
1633
    pNewRequest->pQuery->execStage = QUERY_EXEC_STAGE_ANALYSE;
×
1634
  }
1635
  if (TSDB_CODE_SUCCESS == code) {
×
1636
    code = prepareAndParseSqlSyntax(&pNewWrapper, pNewRequest, false);
×
1637
  }
1638
  if (TSDB_CODE_SUCCESS == code) {
×
1639
    code = cloneCatalogReq(&pNewWrapper->pCatalogReq, pWrapper->pCatalogReq);
×
1640
  }
1641
  if (TSDB_CODE_SUCCESS == code) {
×
1642
    doAsyncQueryFromAnalyse(pResultMeta, pNewWrapper, code);
×
1643
    nodesDestroyNode(pRoot);
×
1644
  } else {
1645
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1646
    return;
×
1647
  }
1648
}
1649

1650
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
183,394,533✔
1651
  SRequestObj *pRequest = pWrapper->pRequest;
183,394,533✔
1652
  SQuery      *pQuery = pRequest->pQuery;
183,402,464✔
1653

1654
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
183,406,945✔
1655
    SNode *prevRoot = pQuery->pPrevRoot;
×
1656
    pQuery->pPrevRoot = NULL;
×
1657
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
×
1658
    return;
×
1659
  }
1660

1661
  if (code == TSDB_CODE_SUCCESS) {
183,406,908✔
1662
    pRequest->stableQuery = pQuery->stableQuery;
167,951,415✔
1663
    if (pQuery->pRoot) {
167,955,365✔
1664
      pRequest->stmtType = pQuery->pRoot->type;
167,951,639✔
1665
    }
1666

1667
    if (pQuery->haveResultSet) {
167,951,651✔
1668
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema,
93,602,982✔
1669
                              pRequest->stmtBindVersion > 0);
93,601,698✔
1670
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
93,603,275✔
1671
    }
1672
  }
1673

1674
  if (code == TSDB_CODE_SUCCESS) {
183,397,211✔
1675
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
167,952,858✔
1676
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
167,951,441✔
1677
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
167,956,090✔
1678

1679
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
167,950,546✔
1680
  } else {
1681
    destorySqlCallbackWrapper(pWrapper);
15,444,353✔
1682
    pRequest->pWrapper = NULL;
15,444,353✔
1683
    qDestroyQuery(pRequest->pQuery);
15,444,353✔
1684
    pRequest->pQuery = NULL;
15,444,353✔
1685

1686
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
15,444,353✔
1687
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
2,669,698✔
1688
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1689
      restartAsyncQuery(pRequest, code);
2,669,698✔
1690
      return;
2,669,698✔
1691
    }
1692

1693
    // return to app directly
1694
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self,
12,774,655✔
1695
             tstrerror(code), pRequest->requestId);
1696
    pRequest->code = code;
12,774,655✔
1697
    returnToUser(pRequest);
12,774,655✔
1698
  }
1699
}
1700

1701
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
193,626,354✔
1702
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
379,008,852✔
1703
                           .requestId = pWrapper->pParseCtx->requestId,
193,634,623✔
1704
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
193,631,852✔
1705
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
193,630,363✔
1706

1707
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
379,015,440✔
1708

1709
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
201,880,261✔
1710
                                &pWrapper->pRequest->body.queryJob);
193,633,372✔
1711
}
1712

1713
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1714

1715
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
662,498,700✔
1716
  int32_t code = TSDB_CODE_SUCCESS;
662,498,700✔
1717
  switch (pWrapper->pRequest->pQuery->execStage) {
662,498,700✔
1718
    case QUERY_EXEC_STAGE_PARSE: {
10,227,862✔
1719
      // continue parse after get metadata
1720
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
10,227,862✔
1721
      break;
10,227,862✔
1722
    }
1723
    case QUERY_EXEC_STAGE_ANALYSE: {
183,407,801✔
1724
      // analysis after get metadata
1725
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
183,407,801✔
1726
      break;
183,407,107✔
1727
    }
1728
    case QUERY_EXEC_STAGE_SCHEDULE: {
468,872,644✔
1729
      launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper);
468,872,644✔
1730
      break;
468,870,765✔
1731
    }
1732
    default:
×
1733
      break;
×
1734
  }
1735
  return code;
662,504,871✔
1736
}
1737

1738
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
10,227,774✔
1739
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
10,227,774✔
1740
  SRequestObj         *pRequest = pWrapper->pRequest;
10,227,774✔
1741
  SQuery              *pQuery = pRequest->pQuery;
10,227,774✔
1742

1743
  pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart;
10,227,774✔
1744
  qDebug("req:0x%" PRIx64 ", continue parse query, QID:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId,
10,227,774✔
1745
         tstrerror(code));
1746

1747
  if (code == TSDB_CODE_SUCCESS) {
10,227,862✔
1748
    // pWrapper->pCatalogReq->forceUpdate = false;
1749
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
10,224,332✔
1750
  }
1751

1752
  if (TSDB_CODE_SUCCESS == code) {
10,227,862✔
1753
    code = phaseAsyncQuery(pWrapper);
9,723,311✔
1754
  }
1755

1756
  if (TSDB_CODE_SUCCESS != code) {
10,227,862✔
1757
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
504,551✔
1758
             tstrerror(code), pWrapper->pRequest->requestId);
1759
    destorySqlCallbackWrapper(pWrapper);
504,551✔
1760
    pRequest->pWrapper = NULL;
504,551✔
1761
    terrno = code;
504,551✔
1762
    pRequest->code = code;
504,551✔
1763
    doRequestCallback(pRequest, code);
504,551✔
1764
  }
1765
}
10,227,862✔
1766

1767
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
10,651✔
1768
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
10,651✔
1769
  if (TSDB_CODE_SUCCESS == code) {
10,651✔
1770
    code = phaseAsyncQuery(pWrapper);
10,651✔
1771
  }
1772

1773
  if (TSDB_CODE_SUCCESS != code) {
10,651✔
1774
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
×
1775
             tstrerror(code), pWrapper->pRequest->requestId);
1776
    destorySqlCallbackWrapper(pWrapper);
×
1777
    pRequest->pWrapper = NULL;
×
1778
    terrno = code;
×
1779
    pRequest->code = code;
×
1780
    doRequestCallback(pRequest, code);
×
1781
  }
1782
}
10,651✔
1783

1784
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
113,906✔
1785
  int64_t connId = *(int64_t *)taos;
113,906✔
1786
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
113,906✔
1787
}
113,906✔
1788

1789
void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) {
×
1790
  int64_t connId = *(int64_t *)taos;
×
1791
  taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid);
×
1792
}
×
1793

1794
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
657,809,895✔
1795
  const STscObj *pTscObj = pRequest->pTscObj;
657,809,895✔
1796

1797
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
657,816,025✔
1798
  if (*pCxt == NULL) {
657,803,562✔
1799
    return terrno;
×
1800
  }
1801

1802
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
1,290,696,392✔
1803
                           .requestRid = pRequest->self,
657,807,872✔
1804
                           .acctId = pTscObj->acctId,
657,809,142✔
1805
                           .db = pRequest->pDb,
657,810,660✔
1806
                           .topicQuery = false,
1807
                           .pSql = pRequest->sqlstr,
657,812,201✔
1808
                           .sqlLen = pRequest->sqlLen,
657,813,460✔
1809
                           .pMsg = pRequest->msgBuf,
657,812,203✔
1810
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
1811
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
657,814,527✔
1812
                           .pStmtCb = NULL,
1813
                           .pUser = pTscObj->user,
657,812,709✔
1814
                           .pEffectiveUser = pRequest->effectiveUser,
657,808,338✔
1815
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
657,812,968✔
1816
                           .enableSysInfo = pTscObj->sysInfo,
657,813,722✔
1817
                           .async = true,
1818
                           .svrVer = pTscObj->sVer,
657,813,538✔
1819
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
657,816,256✔
1820
                           .allocatorId = pRequest->allocatorRefId,
657,808,667✔
1821
                           .parseSqlFp = clientParseSql,
1822
                           .parseSqlParam = pWrapper,
1823
                           .setQueryFp = setQueryRequest,
1824
                           .timezone = pTscObj->optionInfo.timezone,
657,810,217✔
1825
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
657,810,707✔
1826
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
657,810,200✔
1827
  (*pCxt)->biMode = biMode;
657,804,910✔
1828
  return TSDB_CODE_SUCCESS;
657,805,941✔
1829
}
1830

1831
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
657,809,636✔
1832
  int32_t              code = TSDB_CODE_SUCCESS;
657,809,636✔
1833
  STscObj             *pTscObj = pRequest->pTscObj;
657,809,636✔
1834
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
657,814,699✔
1835
  if (pWrapper == NULL) {
657,812,186✔
1836
    code = terrno;
×
1837
  } else {
1838
    pWrapper->pRequest = pRequest;
657,812,186✔
1839
    pRequest->pWrapper = pWrapper;
657,810,182✔
1840
    *ppWrapper = pWrapper;
657,814,971✔
1841
  }
1842

1843
  if (TSDB_CODE_SUCCESS == code) {
657,813,416✔
1844
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
657,814,180✔
1845
  }
1846

1847
  if (TSDB_CODE_SUCCESS == code) {
657,807,693✔
1848
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
657,807,903✔
1849
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
657,816,654✔
1850
  }
1851

1852
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
657,814,089✔
1853
    int64_t syntaxStart = taosGetTimestampUs();
657,814,322✔
1854

1855
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
657,814,322✔
1856
    if (pWrapper->pCatalogReq == NULL) {
657,805,297✔
1857
      code = terrno;
×
1858
    } else {
1859
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
657,806,119✔
1860
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
657,807,842✔
1861
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
657,804,291✔
1862
    }
1863

1864
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
657,810,148✔
1865
  }
1866

1867
  return code;
657,817,190✔
1868
}
1869

1870
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
658,699,547✔
1871
  SSqlCallbackWrapper *pWrapper = NULL;
658,699,547✔
1872
  int32_t              code = TSDB_CODE_SUCCESS;
658,702,808✔
1873

1874
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
658,702,808✔
1875
    code = pRequest->prevCode;
889,543✔
1876
    terrno = code;
889,543✔
1877
    pRequest->code = code;
889,543✔
1878
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
889,543✔
1879
    doRequestCallback(pRequest, code);
889,543✔
1880
    return;
889,543✔
1881
  }
1882

1883
  if (TSDB_CODE_SUCCESS == code) {
657,812,093✔
1884
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
657,810,147✔
1885
  }
1886

1887
  if (TSDB_CODE_SUCCESS == code) {
657,805,081✔
1888
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
652,771,813✔
1889
    code = phaseAsyncQuery(pWrapper);
652,772,926✔
1890
  }
1891

1892
  if (TSDB_CODE_SUCCESS != code) {
657,807,619✔
1893
    if (NULL != pRequest->msgBuf && strlen(pRequest->msgBuf) > 0) {
5,036,364✔
1894
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, pRequest->msgBuf,
4,908,258✔
1895
               pRequest->requestId);
1896
    } else {
1897
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
128,106✔
1898
               pRequest->requestId);
1899
    }
1900

1901
    destorySqlCallbackWrapper(pWrapper);
5,036,364✔
1902
    pRequest->pWrapper = NULL;
5,036,364✔
1903
    qDestroyQuery(pRequest->pQuery);
5,036,364✔
1904
    pRequest->pQuery = NULL;
5,036,364✔
1905

1906
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
5,036,364✔
1907
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
10,667✔
1908
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1909
      code = refreshMeta(pRequest->pTscObj, pRequest);
10,667✔
1910
      if (code != 0) {
10,667✔
1911
        tscWarn("req:0x%" PRIx64 ", refresh meta failed, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code,
10,667✔
1912
                tstrerror(code), pRequest->requestId);
1913
      }
1914
      pRequest->prevCode = code;
10,667✔
1915
      doAsyncQuery(pRequest, true);
10,667✔
1916
      return;
10,667✔
1917
    }
1918

1919
    terrno = code;
5,025,697✔
1920
    pRequest->code = code;
5,025,697✔
1921
    doRequestCallback(pRequest, code);
5,025,697✔
1922
  }
1923
}
1924

1925
void restartAsyncQuery(SRequestObj *pRequest, int32_t code) {
2,716,197✔
1926
  tscInfo("restart request:%s p:%p", pRequest->sqlstr, pRequest);
2,716,197✔
1927
  SRequestObj *pUserReq = pRequest;
2,716,197✔
1928
  (void)acquireRequest(pRequest->self);
2,716,197✔
1929
  while (pUserReq) {
2,716,197✔
1930
    if (pUserReq->self == pUserReq->relation.userRefId || pUserReq->relation.userRefId == 0) {
2,716,197✔
1931
      break;
1932
    } else {
1933
      int64_t nextRefId = pUserReq->relation.nextRefId;
×
1934
      (void)releaseRequest(pUserReq->self);
×
1935
      if (nextRefId) {
×
1936
        pUserReq = acquireRequest(nextRefId);
×
1937
      }
1938
    }
1939
  }
1940
  bool hasSubRequest = pUserReq != pRequest || pRequest->relation.prevRefId != 0;
2,716,197✔
1941
  if (pUserReq) {
2,716,197✔
1942
    destroyCtxInRequest(pUserReq);
2,716,197✔
1943
    pUserReq->prevCode = code;
2,716,197✔
1944
    (void)memset(&pUserReq->relation, 0, sizeof(pUserReq->relation));
2,716,197✔
1945
  } else {
1946
    tscError("User req is missing");
×
1947
    (void)removeFromMostPrevReq(pRequest);
×
1948
    return;
×
1949
  }
1950
  if (hasSubRequest)
2,716,197✔
1951
    (void)removeFromMostPrevReq(pRequest);
×
1952
  else
1953
    (void)releaseRequest(pUserReq->self);
2,716,197✔
1954
  doAsyncQuery(pUserReq, true);
2,716,197✔
1955
}
1956

1957
typedef struct SAsyncFetchParam {
1958
  SRequestObj      *pReq;
1959
  __taos_async_fn_t fp;
1960
  void             *param;
1961
} SAsyncFetchParam;
1962

1963
static int32_t doAsyncFetch(void *pParam) {
109,794,955✔
1964
  SAsyncFetchParam *param = pParam;
109,794,955✔
1965
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
109,794,955✔
1966
  taosMemoryFree(param);
109,793,651✔
1967
  return TSDB_CODE_SUCCESS;
109,793,824✔
1968
}
1969

1970
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
109,796,378✔
1971
  if (res == NULL || fp == NULL) {
109,796,378✔
1972
    tscError("taos_fetch_rows_a invalid paras");
×
1973
    return;
×
1974
  }
1975
  if (!TD_RES_QUERY(res)) {
109,796,892✔
1976
    tscError("taos_fetch_rows_a res is NULL");
×
1977
    fp(param, res, TSDB_CODE_APP_ERROR);
×
1978
    return;
×
1979
  }
1980

1981
  SRequestObj *pRequest = res;
109,796,887✔
1982
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
109,796,887✔
1983
    fp(param, res, 0);
2,955✔
1984
    return;
2,955✔
1985
  }
1986

1987
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
109,793,144✔
1988
  if (!pParam) {
109,794,184✔
1989
    fp(param, res, terrno);
×
1990
    return;
×
1991
  }
1992
  pParam->pReq = pRequest;
109,794,184✔
1993
  pParam->fp = fp;
109,794,184✔
1994
  pParam->param = param;
109,794,441✔
1995
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
109,794,441✔
1996
  if (TSDB_CODE_SUCCESS != code) {
109,794,955✔
1997
    taosMemoryFree(pParam);
×
1998
    fp(param, res, code);
×
1999
    return;
×
2000
  }
2001
}
2002

2003
void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
4,116✔
2004
  if (res == NULL || fp == NULL) {
4,116✔
2005
    tscError("taos_fetch_raw_block_a invalid paras");
×
2006
    return;
×
2007
  }
2008
  if (!TD_RES_QUERY(res)) {
4,116✔
2009
    tscError("taos_fetch_raw_block_a res is NULL");
×
2010
    return;
×
2011
  }
2012
  SRequestObj    *pRequest = res;
4,116✔
2013
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
4,116✔
2014

2015
  // set the current block is all consumed
2016
  pResultInfo->convertUcs4 = false;
4,116✔
2017

2018
  // it is a local executed query, no need to do async fetch
2019
  taos_fetch_rows_a(pRequest, fp, param);
4,116✔
2020
}
2021

2022
const void *taos_get_raw_block(TAOS_RES *res) {
2,421✔
2023
  if (res == NULL) {
2,421✔
2024
    tscError("taos_get_raw_block invalid paras");
×
2025
    return NULL;
×
2026
  }
2027
  if (!TD_RES_QUERY(res)) {
2,421✔
2028
    tscError("taos_get_raw_block res is NULL");
×
2029
    return NULL;
×
2030
  }
2031
  SRequestObj *pRequest = res;
2,421✔
2032

2033
  return pRequest->body.resInfo.pData;
2,421✔
2034
}
2035

2036
int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInfo) {
×
2037
  if (NULL == taos) {
×
2038
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2039
    return terrno;
×
2040
  }
2041

2042
  if (NULL == db || NULL == dbInfo) {
×
2043
    tscError("invalid input param, db:%p, dbInfo:%p", db, dbInfo);
×
2044
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2045
    return terrno;
×
2046
  }
2047

2048
  int64_t      connId = *(int64_t *)taos;
×
2049
  SRequestObj *pRequest = NULL;
×
2050
  char        *sql = "taos_get_db_route_info";
×
2051
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2052
  if (code != TSDB_CODE_SUCCESS) {
×
2053
    terrno = code;
×
2054
    return terrno;
×
2055
  }
2056

2057
  STscObj  *pTscObj = pRequest->pTscObj;
×
2058
  SCatalog *pCtg = NULL;
×
2059
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2060
  if (code != TSDB_CODE_SUCCESS) {
×
2061
    goto _return;
×
2062
  }
2063

2064
  SRequestConnInfo conn = {
×
2065
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2066

2067
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2068

2069
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
×
2070
  (void)snprintf(dbFName, sizeof(dbFName), "%d.%s", pTscObj->acctId, db);
×
2071

2072
  code = catalogGetDBVgInfo(pCtg, &conn, dbFName, dbInfo);
×
2073
  if (code) {
×
2074
    goto _return;
×
2075
  }
2076

2077
_return:
×
2078

2079
  terrno = code;
×
2080

2081
  destroyRequest(pRequest);
×
2082
  return code;
×
2083
}
2084

2085
int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId) {
×
2086
  if (NULL == taos) {
×
2087
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2088
    return terrno;
×
2089
  }
2090

2091
  if (NULL == db || NULL == table || NULL == vgId) {
×
2092
    tscError("invalid input param, db:%p, table:%p, vgId:%p", db, table, vgId);
×
2093
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2094
    return terrno;
×
2095
  }
2096

2097
  int64_t      connId = *(int64_t *)taos;
×
2098
  SRequestObj *pRequest = NULL;
×
2099
  char        *sql = "taos_get_table_vgId";
×
2100
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2101
  if (code != TSDB_CODE_SUCCESS) {
×
2102
    return terrno;
×
2103
  }
2104

2105
  pRequest->syncQuery = true;
×
2106

2107
  STscObj  *pTscObj = pRequest->pTscObj;
×
2108
  SCatalog *pCtg = NULL;
×
2109
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2110
  if (code != TSDB_CODE_SUCCESS) {
×
2111
    goto _return;
×
2112
  }
2113

2114
  SRequestConnInfo conn = {
×
2115
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2116

2117
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2118

2119
  SName tableName = {0};
×
2120
  toName(pTscObj->acctId, db, table, &tableName);
×
2121

2122
  SVgroupInfo vgInfo;
×
2123
  code = catalogGetTableHashVgroup(pCtg, &conn, &tableName, &vgInfo);
×
2124
  if (code) {
×
2125
    goto _return;
×
2126
  }
2127

2128
  *vgId = vgInfo.vgId;
×
2129

2130
_return:
×
2131

2132
  terrno = code;
×
2133

2134
  destroyRequest(pRequest);
×
2135
  return code;
×
2136
}
2137

2138
int taos_get_tables_vgId(TAOS *taos, const char *db, const char *table[], int tableNum, int *vgId) {
×
2139
  if (NULL == taos) {
×
2140
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2141
    return terrno;
×
2142
  }
2143

2144
  if (NULL == db || NULL == table || NULL == vgId || tableNum <= 0) {
×
2145
    tscError("invalid input param, db:%p, table:%p, vgId:%p, tbNum:%d", db, table, vgId, tableNum);
×
2146
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2147
    return terrno;
×
2148
  }
2149

2150
  int64_t      connId = *(int64_t *)taos;
×
2151
  SRequestObj *pRequest = NULL;
×
2152
  char        *sql = "taos_get_table_vgId";
×
2153
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2154
  if (code != TSDB_CODE_SUCCESS) {
×
2155
    return terrno;
×
2156
  }
2157

2158
  pRequest->syncQuery = true;
×
2159

2160
  STscObj  *pTscObj = pRequest->pTscObj;
×
2161
  SCatalog *pCtg = NULL;
×
2162
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2163
  if (code != TSDB_CODE_SUCCESS) {
×
2164
    goto _return;
×
2165
  }
2166

2167
  SRequestConnInfo conn = {
×
2168
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2169

2170
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2171

2172
  code = catalogGetTablesHashVgId(pCtg, &conn, pTscObj->acctId, db, table, tableNum, vgId);
×
2173
  if (code) {
×
2174
    goto _return;
×
2175
  }
2176

2177
_return:
×
2178

2179
  terrno = code;
×
2180

2181
  destroyRequest(pRequest);
×
2182
  return code;
×
2183
}
2184

2185
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
1,264✔
2186
  if (NULL == taos) {
1,264✔
2187
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2188
    return terrno;
×
2189
  }
2190

2191
  int64_t       connId = *(int64_t *)taos;
1,264✔
2192
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
1,264✔
2193
  int32_t       code = 0;
1,264✔
2194
  SRequestObj  *pRequest = NULL;
1,264✔
2195
  SCatalogReq   catalogReq = {0};
1,264✔
2196

2197
  if (NULL == tableNameList) {
1,264✔
2198
    return TSDB_CODE_SUCCESS;
×
2199
  }
2200

2201
  int32_t length = (int32_t)strlen(tableNameList);
1,264✔
2202
  if (0 == length) {
1,264✔
2203
    return TSDB_CODE_SUCCESS;
×
2204
  } else if (length > MAX_TABLE_NAME_LENGTH) {
1,264✔
2205
    tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH);
×
2206
    return TSDB_CODE_TSC_INVALID_OPERATION;
×
2207
  }
2208

2209
  char *sql = "taos_load_table_info";
1,264✔
2210
  code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
1,264✔
2211
  if (code != TSDB_CODE_SUCCESS) {
1,264✔
2212
    terrno = code;
×
2213
    goto _return;
×
2214
  }
2215

2216
  pRequest->syncQuery = true;
1,264✔
2217

2218
  STscObj *pTscObj = pRequest->pTscObj;
1,264✔
2219
  code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
1,264✔
2220
  if (code) {
1,264✔
2221
    goto _return;
×
2222
  }
2223

2224
  SCatalog *pCtg = NULL;
1,264✔
2225
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
1,264✔
2226
  if (code != TSDB_CODE_SUCCESS) {
1,264✔
2227
    goto _return;
×
2228
  }
2229

2230
  SRequestConnInfo conn = {
1,264✔
2231
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
1,264✔
2232

2233
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
1,264✔
2234

2235
  code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, pRequest->body.interParam, NULL);
1,264✔
2236
  if (code) {
1,264✔
2237
    goto _return;
×
2238
  }
2239

2240
  SSyncQueryParam *pParam = pRequest->body.interParam;
1,264✔
2241
  code = tsem_wait(&pParam->sem);
1,264✔
2242
  if (code) {
1,264✔
2243
    tscError("tsem wait failed, code:%d - %s", code, tstrerror(code));
×
2244
    goto _return;
×
2245
  }
2246
_return:
1,264✔
2247
  destoryCatalogReq(&catalogReq);
1,264✔
2248
  destroyRequest(pRequest);
1,264✔
2249
  return code;
1,264✔
2250
}
2251

2252
TAOS_STMT *taos_stmt_init(TAOS *taos) {
401,448✔
2253
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
401,448✔
2254
  if (NULL == pObj) {
403,218✔
2255
    tscError("invalid parameter for %s", __FUNCTION__);
×
2256
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2257
    return NULL;
×
2258
  }
2259

2260
  TAOS_STMT *pStmt = stmtInit(pObj, 0, NULL);
403,218✔
2261
  if (NULL == pStmt) {
403,218✔
2262
    tscError("stmt init failed, errcode:%s", terrstr());
×
2263
  }
2264
  releaseTscObj(*(int64_t *)taos);
403,218✔
2265

2266
  return pStmt;
403,218✔
2267
}
2268

2269
TAOS_STMT *taos_stmt_init_with_reqid(TAOS *taos, int64_t reqid) {
×
2270
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
2271
  if (NULL == pObj) {
×
2272
    tscError("invalid parameter for %s", __FUNCTION__);
×
2273
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2274
    return NULL;
×
2275
  }
2276

2277
  TAOS_STMT *pStmt = stmtInit(pObj, reqid, NULL);
×
2278
  if (NULL == pStmt) {
×
2279
    tscError("stmt init failed, errcode:%s", terrstr());
×
2280
  }
2281
  releaseTscObj(*(int64_t *)taos);
×
2282

2283
  return pStmt;
×
2284
}
2285

2286
TAOS_STMT *taos_stmt_init_with_options(TAOS *taos, TAOS_STMT_OPTIONS *options) {
27,176✔
2287
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
27,176✔
2288
  if (NULL == pObj) {
27,176✔
2289
    tscError("invalid parameter for %s", __FUNCTION__);
×
2290
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2291
    return NULL;
×
2292
  }
2293

2294
  TAOS_STMT *pStmt = stmtInit(pObj, options->reqId, options);
27,176✔
2295
  if (NULL == pStmt) {
27,176✔
2296
    tscError("stmt init failed, errcode:%s", terrstr());
×
2297
  }
2298
  releaseTscObj(*(int64_t *)taos);
27,176✔
2299

2300
  return pStmt;
27,176✔
2301
}
2302

2303
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
980,908✔
2304
  if (stmt == NULL || sql == NULL) {
980,908✔
2305
    tscError("NULL parameter for %s", __FUNCTION__);
×
2306
    terrno = TSDB_CODE_INVALID_PARA;
×
2307
    return terrno;
×
2308
  }
2309

2310
  return stmtPrepare(stmt, sql, length);
981,586✔
2311
}
2312

2313
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
19,582✔
2314
  if (stmt == NULL || name == NULL) {
19,582✔
2315
    tscError("NULL parameter for %s", __FUNCTION__);
×
2316
    terrno = TSDB_CODE_INVALID_PARA;
×
2317
    return terrno;
×
2318
  }
2319

2320
  int32_t code = stmtSetTbName(stmt, name);
19,582✔
2321
  if (code) {
19,582✔
2322
    return code;
632✔
2323
  }
2324

2325
  if (tags) {
18,950✔
2326
    return stmtSetTbTags(stmt, tags);
18,950✔
2327
  }
2328

2329
  return TSDB_CODE_SUCCESS;
×
2330
}
2331

2332
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
11,658,914✔
2333
  if (stmt == NULL || name == NULL) {
11,658,914✔
UNCOV
2334
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2335
    terrno = TSDB_CODE_INVALID_PARA;
×
2336
    return terrno;
×
2337
  }
2338

2339
  return stmtSetTbName(stmt, name);
11,683,972✔
2340
}
2341

2342
int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) {
5,304✔
2343
  if (stmt == NULL || tags == NULL) {
5,304✔
2344
    tscError("NULL parameter for %s", __FUNCTION__);
×
2345
    terrno = TSDB_CODE_INVALID_PARA;
×
2346
    return terrno;
×
2347
  }
2348

2349
  return stmtSetTbTags(stmt, tags);
5,304✔
2350
}
2351

2352
int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); }
×
2353

2354
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
×
2355
  if (stmt == NULL || NULL == fieldNum) {
×
2356
    tscError("NULL parameter for %s", __FUNCTION__);
×
2357
    terrno = TSDB_CODE_INVALID_PARA;
×
2358
    return terrno;
×
2359
  }
2360

2361
  return stmtGetTagFields(stmt, fieldNum, fields);
×
2362
}
2363

2364
int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
×
2365
  if (stmt == NULL || NULL == fieldNum) {
×
2366
    tscError("NULL parameter for %s", __FUNCTION__);
×
2367
    terrno = TSDB_CODE_INVALID_PARA;
×
2368
    return terrno;
×
2369
  }
2370

2371
  return stmtGetColFields(stmt, fieldNum, fields);
×
2372
}
2373

2374
// let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields`
2375
void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) {
×
2376
  (void)stmt;
2377
  if (!fields) return;
×
2378
  taosMemoryFree(fields);
×
2379
}
2380

2381
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
57,037✔
2382
  if (stmt == NULL || bind == NULL) {
57,037✔
2383
    tscError("NULL parameter for %s", __FUNCTION__);
×
2384
    terrno = TSDB_CODE_INVALID_PARA;
×
2385
    return terrno;
×
2386
  }
2387

2388
  if (bind->num > 1) {
57,037✔
2389
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
4,044✔
2390
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
4,044✔
2391
    return terrno;
4,044✔
2392
  }
2393

2394
  return stmtBindBatch(stmt, bind, -1);
52,993✔
2395
}
2396

2397
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
565,792,942✔
2398
  if (stmt == NULL || bind == NULL) {
565,792,942✔
2399
    tscError("NULL parameter for %s", __FUNCTION__);
×
2400
    terrno = TSDB_CODE_INVALID_PARA;
×
2401
    return terrno;
×
2402
  }
2403

2404
  if (bind->num <= 0 || bind->num > INT16_MAX) {
577,180,754✔
2405
    tscError("invalid bind num %d", bind->num);
767✔
2406
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
767✔
2407
    return terrno;
×
2408
  }
2409

2410
  int32_t insert = 0;
580,610,194✔
2411
  int32_t code = stmtIsInsert(stmt, &insert);
579,780,087✔
2412
  if (TSDB_CODE_SUCCESS != code) {
573,674,319✔
2413
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2414
    return code;
×
2415
  }
2416
  if (0 == insert && bind->num > 1) {
573,674,319✔
2417
    tscError("only one row data allowed for query");
×
2418
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2419
    return terrno;
×
2420
  }
2421

2422
  return stmtBindBatch(stmt, bind, -1);
573,674,319✔
2423
}
2424

2425
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
32,620✔
2426
  if (stmt == NULL || bind == NULL) {
32,620✔
2427
    tscError("NULL parameter for %s", __FUNCTION__);
×
2428
    terrno = TSDB_CODE_INVALID_PARA;
×
2429
    return terrno;
×
2430
  }
2431

2432
  if (colIdx < 0) {
32,620✔
2433
    tscError("invalid bind column idx %d", colIdx);
×
2434
    terrno = TSDB_CODE_INVALID_PARA;
×
2435
    return terrno;
×
2436
  }
2437

2438
  int32_t insert = 0;
32,620✔
2439
  int32_t code = stmtIsInsert(stmt, &insert);
32,620✔
2440
  if (TSDB_CODE_SUCCESS != code) {
32,620✔
2441
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2442
    return code;
×
2443
  }
2444
  if (0 == insert && bind->num > 1) {
32,620✔
2445
    tscError("only one row data allowed for query");
×
2446
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2447
    return terrno;
×
2448
  }
2449

2450
  return stmtBindBatch(stmt, bind, colIdx);
32,620✔
2451
}
2452

2453
int taos_stmt_add_batch(TAOS_STMT *stmt) {
554,906,587✔
2454
  if (stmt == NULL) {
554,906,587✔
2455
    tscError("NULL parameter for %s", __FUNCTION__);
×
2456
    terrno = TSDB_CODE_INVALID_PARA;
×
2457
    return terrno;
×
2458
  }
2459

2460
  return stmtAddBatch(stmt);
554,906,587✔
2461
}
2462

2463
int taos_stmt_execute(TAOS_STMT *stmt) {
2,848,655✔
2464
  if (stmt == NULL) {
2,848,655✔
2465
    tscError("NULL parameter for %s", __FUNCTION__);
×
2466
    terrno = TSDB_CODE_INVALID_PARA;
×
2467
    return terrno;
×
2468
  }
2469

2470
  return stmtExec(stmt);
2,848,655✔
2471
}
2472

2473
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
×
2474
  if (stmt == NULL || insert == NULL) {
×
2475
    tscError("NULL parameter for %s", __FUNCTION__);
×
2476
    terrno = TSDB_CODE_INVALID_PARA;
×
2477
    return terrno;
×
2478
  }
2479

2480
  return stmtIsInsert(stmt, insert);
×
2481
}
2482

2483
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
×
2484
  if (stmt == NULL || nums == NULL) {
×
2485
    tscError("NULL parameter for %s", __FUNCTION__);
×
2486
    terrno = TSDB_CODE_INVALID_PARA;
×
2487
    return terrno;
×
2488
  }
2489

2490
  return stmtGetParamNum(stmt, nums);
×
2491
}
2492

2493
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
×
2494
  if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) {
×
2495
    tscError("invalid parameter for %s", __FUNCTION__);
×
2496
    terrno = TSDB_CODE_INVALID_PARA;
×
2497
    return terrno;
×
2498
  }
2499

2500
  return stmtGetParam(stmt, idx, type, bytes);
×
2501
}
2502

2503
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
10,456✔
2504
  if (stmt == NULL) {
10,456✔
2505
    tscError("NULL parameter for %s", __FUNCTION__);
×
2506
    terrno = TSDB_CODE_INVALID_PARA;
×
2507
    return NULL;
×
2508
  }
2509

2510
  return stmtUseResult(stmt);
10,456✔
2511
}
2512

2513
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
10,621✔
2514

2515
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
5,056✔
2516
  if (stmt == NULL) {
5,056✔
2517
    tscError("NULL parameter for %s", __FUNCTION__);
×
2518
    terrno = TSDB_CODE_INVALID_PARA;
×
2519
    return 0;
×
2520
  }
2521

2522
  return stmtAffectedRows(stmt);
5,056✔
2523
}
2524

2525
int taos_stmt_affected_rows_once(TAOS_STMT *stmt) {
2,480✔
2526
  if (stmt == NULL) {
2,480✔
2527
    tscError("NULL parameter for %s", __FUNCTION__);
×
2528
    terrno = TSDB_CODE_INVALID_PARA;
×
2529
    return 0;
×
2530
  }
2531

2532
  return stmtAffectedRowsOnce(stmt);
2,480✔
2533
}
2534

2535
int taos_stmt_close(TAOS_STMT *stmt) {
430,394✔
2536
  if (stmt == NULL) {
430,394✔
2537
    tscError("NULL parameter for %s", __FUNCTION__);
×
2538
    terrno = TSDB_CODE_INVALID_PARA;
×
2539
    return terrno;
×
2540
  }
2541

2542
  return stmtClose(stmt);
430,394✔
2543
}
2544

2545
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
19,589✔
2546
  if (NULL == taos) {
19,589✔
2547
    tscError("NULL parameter for %s", __FUNCTION__);
×
2548
    terrno = TSDB_CODE_INVALID_PARA;
×
2549
    return NULL;
×
2550
  }
2551
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
19,589✔
2552
  if (NULL == pObj) {
19,589✔
2553
    tscError("invalid parameter for %s", __FUNCTION__);
×
2554
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2555
    return NULL;
×
2556
  }
2557

2558
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
19,589✔
2559

2560
  releaseTscObj(*(int64_t *)taos);
19,589✔
2561

2562
  return pStmt;
19,589✔
2563
}
2564

2565
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
21,511✔
2566
  if (stmt == NULL || sql == NULL) {
21,511✔
2567
    tscError("NULL parameter for %s", __FUNCTION__);
×
2568
    terrno = TSDB_CODE_INVALID_PARA;
×
2569
    return terrno;
×
2570
  }
2571

2572
  return stmtPrepare2(stmt, sql, length);
21,511✔
2573
}
2574

2575
int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx) {
7,387,087✔
2576
  if (stmt == NULL) {
7,387,087✔
2577
    tscError("NULL parameter for %s", __FUNCTION__);
×
2578
    terrno = TSDB_CODE_INVALID_PARA;
×
2579
    return terrno;
×
2580
  }
2581

2582
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
7,387,087✔
2583
  STMT2_DLOG_E("start to bind param");
7,387,087✔
2584
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 1) {
7,387,087✔
2585
    STMT2_ELOG_E("async bind param is still working, please try again later");
1,179✔
2586
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
1,179✔
2587
    return terrno;
×
2588
  }
2589

2590
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
7,388,509✔
2591
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
×
2592
      STMT2_ELOG_E("bind param wait asyncExecSem failed");
×
2593
    }
2594
    pStmt->execSemWaited = true;
×
2595
  }
2596

2597
  int32_t code = TSDB_CODE_SUCCESS;
7,388,509✔
2598
  for (int i = 0; i < bindv->count; ++i) {
23,611,104✔
2599
    if (bindv->tbnames && bindv->tbnames[i]) {
16,218,253✔
2600
      code = stmtSetTbName2(stmt, bindv->tbnames[i]);
16,221,282✔
2601
      if (code) {
16,219,295✔
UNCOV
2602
        terrno = code;
×
2603
        STMT2_ELOG("set tbname failed, code:%s", tstrerror(code));
×
2604
        return terrno;
×
2605
      }
2606
    }
2607

2608
    SVCreateTbReq *pCreateTbReq = NULL;
16,216,833✔
2609
    if (bindv->tags && bindv->tags[i]) {
16,217,092✔
2610
      code = stmtSetTbTags2(stmt, bindv->tags[i], &pCreateTbReq);
10,024,594✔
2611
    } else if (pStmt->bInfo.tbNameFlag & IS_FIXED_TAG) {
6,194,107✔
2612
      code = stmtCheckTags2(stmt, &pCreateTbReq);
2,014,424✔
2613
    } else if (pStmt->sql.autoCreateTbl) {
4,178,612✔
2614
      // if (pStmt->sql.autoCreateTbl) {
2615
      //   pStmt->sql.autoCreateTbl = false;
2616
      //   STMT2_WLOG_E("sql is autoCreateTbl, but no tags");
2617
      // }
2618
      code = stmtSetTbTags2(stmt, NULL, &pCreateTbReq);
×
2619
    }
2620

2621
    if (code) {
16,216,864✔
2622
      terrno = code;
×
2623
      STMT2_ELOG("set tags failed, code:%s", tstrerror(code));
×
2624
      return terrno;
×
2625
    }
2626

2627
    if (bindv->bind_cols && bindv->bind_cols[i]) {
16,216,864✔
2628
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
16,220,636✔
2629

2630
      if (bind->num <= 0 || bind->num > INT16_MAX) {
16,220,650✔
2631
        STMT2_ELOG("bind num:%d must > 0 and < INT16_MAX", bind->num);
196✔
2632
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
196✔
2633
        return terrno;
×
2634
      }
2635

2636
      if (!stmt2IsInsert(stmt) && bind->num > 1) {
16,220,259✔
2637
        STMT2_ELOG_E("only one row data allowed for query");
×
2638
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2639
        return terrno;
×
2640
      }
2641

2642
      code = stmtBindBatch2(stmt, bind, col_idx, pCreateTbReq);
16,221,938✔
2643
      if (TSDB_CODE_SUCCESS != code) {
16,221,917✔
2644
        terrno = code;
815✔
2645
        STMT2_ELOG("bind batch failed, code:%s", tstrerror(code));
×
2646
        return terrno;
×
2647
      }
2648
    }
2649
  }
2650

2651
  return code;
7,392,313✔
2652
}
2653

2654
int taos_stmt2_bind_param_a(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx, __taos_async_fn_t fp,
×
2655
                            void *param) {
2656
  if (stmt == NULL || bindv == NULL || fp == NULL) {
×
2657
    terrno = TSDB_CODE_INVALID_PARA;
×
2658
    return terrno;
×
2659
  }
2660

2661
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
×
2662

2663
  ThreadArgs *args = (ThreadArgs *)taosMemoryMalloc(sizeof(ThreadArgs));
×
2664
  args->stmt = stmt;
×
2665
  args->bindv = bindv;
×
2666
  args->col_idx = col_idx;
×
2667
  args->fp = fp;
×
2668
  args->param = param;
×
2669

2670
  (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2671
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 0) {
×
2672
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2673
    tscError("async bind param is still working, please try again later");
×
2674
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
×
2675
    return terrno;
×
2676
  }
2677
  (void)atomic_add_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2678
  (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2679

2680
  int code_s = taosStmt2AsyncBind(stmtAsyncBindThreadFunc, (void *)args);
×
2681
  if (code_s != TSDB_CODE_SUCCESS) {
×
2682
    terrno = code_s;
×
2683
    (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2684
    (void)taosThreadCondSignal(&(pStmt->asyncBindParam.waitCond));
×
2685
    (void)atomic_sub_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2686
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2687
    tscError("async bind failed, code:%d , %s", code_s, tstrerror(code_s));
×
2688
  }
2689

2690
  return code_s;
×
2691
}
2692

2693
int taos_stmt2_exec(TAOS_STMT2 *stmt, int *affected_rows) {
7,389,662✔
2694
  if (stmt == NULL) {
7,389,662✔
2695
    tscError("NULL parameter for %s", __FUNCTION__);
×
2696
    terrno = TSDB_CODE_INVALID_PARA;
×
2697
    return terrno;
×
2698
  }
2699

2700
  return stmtExec2(stmt, affected_rows);
7,389,662✔
2701
}
2702

2703
int taos_stmt2_close(TAOS_STMT2 *stmt) {
19,589✔
2704
  if (stmt == NULL) {
19,589✔
2705
    tscError("NULL parameter for %s", __FUNCTION__);
×
2706
    terrno = TSDB_CODE_INVALID_PARA;
×
2707
    return terrno;
×
2708
  }
2709

2710
  return stmtClose2(stmt);
19,589✔
2711
}
2712

2713
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
945✔
2714
  if (stmt == NULL || insert == NULL) {
945✔
2715
    tscError("NULL parameter for %s", __FUNCTION__);
×
2716
    terrno = TSDB_CODE_INVALID_PARA;
×
2717
    return terrno;
×
2718
  }
2719
  *insert = stmt2IsInsert(stmt);
945✔
2720
  return TSDB_CODE_SUCCESS;
945✔
2721
}
2722

2723
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
703✔
2724
  if (stmt == NULL || count == NULL) {
703✔
2725
    tscError("NULL parameter for %s", __FUNCTION__);
×
2726
    terrno = TSDB_CODE_INVALID_PARA;
×
2727
    return terrno;
×
2728
  }
2729

2730
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
703✔
2731
  if (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type ||
703✔
2732
      (pStmt->sql.type == 0 && stmt2IsInsert(stmt))) {
703✔
2733
    return stmtGetStbColFields2(stmt, count, fields);
703✔
2734
  }
2735
  if (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt))) {
×
2736
    return stmtGetParamNum2(stmt, count);
×
2737
  }
2738

2739
  tscError("Invalid sql for stmt %s", pStmt->sql.sqlStr);
×
2740
  return TSDB_CODE_PAR_SYNTAX_ERROR;
×
2741
}
2742

2743
DLL_EXPORT void taos_stmt2_free_fields(TAOS_STMT2 *stmt, TAOS_FIELD_ALL *fields) {
703✔
2744
  (void)stmt;
2745
  if (!fields) return;
703✔
2746
  taosMemoryFree(fields);
703✔
2747
}
2748

2749
TAOS_RES *taos_stmt2_result(TAOS_STMT2 *stmt) {
242✔
2750
  if (stmt == NULL) {
242✔
2751
    tscError("NULL parameter for %s", __FUNCTION__);
×
2752
    terrno = TSDB_CODE_INVALID_PARA;
×
2753
    return NULL;
×
2754
  }
2755

2756
  return stmtUseResult2(stmt);
242✔
2757
}
2758

2759
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmtErrstr2(stmt); }
×
2760

2761
int taos_set_conn_mode(TAOS *taos, int mode, int value) {
3,454✔
2762
  if (taos == NULL) {
3,454✔
2763
    terrno = TSDB_CODE_INVALID_PARA;
×
2764
    return terrno;
×
2765
  }
2766

2767
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
3,454✔
2768
  if (NULL == pObj) {
3,454✔
2769
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2770
    tscError("invalid parameter for %s", __func__);
×
2771
    return terrno;
×
2772
  }
2773
  switch (mode) {
3,454✔
2774
    case TAOS_CONN_MODE_BI:
3,454✔
2775
      atomic_store_8(&pObj->biMode, value);
3,454✔
2776
      break;
3,454✔
2777
    default:
×
2778
      tscError("not supported mode.");
×
2779
      return TSDB_CODE_INVALID_PARA;
×
2780
  }
2781
  return 0;
3,454✔
2782
}
2783

2784
char *getBuildInfo() { return td_buildinfo; }
×
2785

2786
static int32_t buildInstanceRegisterSql(const SInstanceRegisterReq *req, char **ppSql, uint32_t *pLen) {
×
2787
  const char *action = (req->expire < 0) ? "UNREGISTER" : "REGISTER";
×
2788
  int32_t     len = 0;
×
2789

2790
  len += snprintf(NULL, 0, "%s INSTANCE '%s'", action, req->id);
×
2791
  if (req->type[0] != 0) {
×
2792
    len += snprintf(NULL, 0, " TYPE '%s'", req->type);
×
2793
  }
2794
  if (req->desc[0] != 0) {
×
2795
    len += snprintf(NULL, 0, " DESC '%s'", req->desc);
×
2796
  }
2797
  if (req->expire >= 0) {
×
2798
    len += snprintf(NULL, 0, " EXPIRE %d", req->expire);
×
2799
  }
2800

2801
  char *sql = taosMemoryMalloc((size_t)len + 1);
×
2802
  if (sql == NULL) {
×
2803
    return terrno;
×
2804
  }
2805

2806
  int32_t offset = snprintf(sql, (size_t)len + 1, "%s INSTANCE '%s'", action, req->id);
×
2807
  if (req->type[0] != 0) {
×
2808
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " TYPE '%s'", req->type);
×
2809
  }
2810
  if (req->desc[0] != 0) {
×
2811
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " DESC '%s'", req->desc);
×
2812
  }
2813
  if (req->expire >= 0) {
×
2814
    (void)snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " EXPIRE %d", req->expire);
×
2815
  }
2816

2817
  *ppSql = sql;
×
2818
  if (pLen != NULL) {
×
2819
    *pLen = (uint32_t)len;
×
2820
  }
2821
  return TSDB_CODE_SUCCESS;
×
2822
}
2823

2824
static int32_t sendInstanceRegisterReq(STscObj *pObj, const SInstanceRegisterReq *req) {
×
2825
  SRequestObj *pRequest = NULL;
×
2826
  int32_t      code = createRequest(pObj->id, TDMT_MND_REGISTER_INSTANCE, 0, &pRequest);
×
2827
  if (code != TSDB_CODE_SUCCESS) {
×
2828
    terrno = code;
×
2829
    return code;
×
2830
  }
2831

2832
  code = buildInstanceRegisterSql(req, &pRequest->sqlstr, &pRequest->sqlLen);
×
2833
  if (code != TSDB_CODE_SUCCESS) {
×
2834
    goto _cleanup;
×
2835
  }
2836

2837
  int32_t msgLen = tSerializeSInstanceRegisterReq(NULL, 0, (SInstanceRegisterReq *)req);
×
2838
  if (msgLen <= 0) {
×
2839
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
2840
    goto _cleanup;
×
2841
  }
2842

2843
  void *pMsg = taosMemoryMalloc(msgLen);
×
2844
  if (pMsg == NULL) {
×
2845
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
2846
    goto _cleanup;
×
2847
  }
2848

2849
  if (tSerializeSInstanceRegisterReq(pMsg, msgLen, (SInstanceRegisterReq *)req) < 0) {
×
2850
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
2851
    taosMemoryFree(pMsg);
×
2852
    goto _cleanup;
×
2853
  }
2854

2855
  pRequest->type = TDMT_MND_REGISTER_INSTANCE;
×
2856
  pRequest->body.requestMsg = (SDataBuf){.pData = pMsg, .len = msgLen, .handle = NULL};
×
2857

2858
  SMsgSendInfo *pSend = buildMsgInfoImpl(pRequest);
×
2859
  if (pSend == NULL) {
×
2860
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
2861
    taosMemoryFree(pMsg);
×
2862
    pRequest->body.requestMsg.pData = NULL;
×
2863
    goto _cleanup;
×
2864
  }
2865

2866
  SEpSet epSet = getEpSet_s(&pObj->pAppInfo->mgmtEp);
×
2867
  code = asyncSendMsgToServer(pObj->pAppInfo->pTransporter, &epSet, NULL, pSend);
×
2868
  if (code != TSDB_CODE_SUCCESS) {
×
2869
    destroySendMsgInfo(pSend);
×
2870
    pRequest->body.requestMsg = (SDataBuf){0};
×
2871
    goto _cleanup;
×
2872
  }
2873

2874
  code = tsem_wait(&pRequest->body.rspSem);
×
2875
  if (code != TSDB_CODE_SUCCESS) {
×
2876
    code = terrno != 0 ? terrno : code;
×
2877
    goto _cleanup;
×
2878
  }
2879

2880
  code = pRequest->code;
×
2881
  terrno = code;
×
2882

2883
_cleanup:
×
2884
  destroyRequest(pRequest);
×
2885
  return code;
×
2886
}
2887

2888
static bool instanceRegisterRpcRfp(int32_t code, tmsg_t msgType) {
×
2889
  if (NEED_REDIRECT_ERROR(code)) {
×
2890
    return true;
×
2891
  } else if (code == TSDB_CODE_UTIL_QUEUE_OUT_OF_MEMORY || code == TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE ||
×
2892
             code == TSDB_CODE_SYN_WRITE_STALL || code == TSDB_CODE_SYN_PROPOSE_NOT_READY ||
×
2893
             code == TSDB_CODE_SYN_RESTORING) {
2894
    tscDebug("client msg type %s should retry since %s", TMSG_INFO(msgType), tstrerror(code));
×
2895
    return true;
×
2896
  } else {
2897
    return false;
×
2898
  }
2899
}
2900

2901
int32_t taos_register_instance(const char *id, const char *type, const char *desc, int32_t expire) {
×
2902
  if (id == NULL || id[0] == 0) {
×
2903
    return terrno = TSDB_CODE_INVALID_PARA;
×
2904
  }
2905

2906
  // Validate string lengths
2907
  size_t idLen = strlen(id);
×
2908
  if (idLen >= TSDB_INSTANCE_ID_LEN) {
×
2909
    tscError("instance id length %zu exceeds limit %d", idLen, TSDB_INSTANCE_ID_LEN - 1);
×
2910
    return terrno = TSDB_CODE_INVALID_PARA;
×
2911
  }
2912

2913
  if (type != NULL && type[0] != 0) {
×
2914
    size_t typeLen = strlen(type);
×
2915
    if (typeLen >= TSDB_INSTANCE_TYPE_LEN) {
×
2916
      tscError("instance type length %zu exceeds limit %d", typeLen, TSDB_INSTANCE_TYPE_LEN - 1);
×
2917
      return terrno = TSDB_CODE_INVALID_PARA;
×
2918
    }
2919
  }
2920

2921
  if (desc != NULL && desc[0] != 0) {
×
2922
    size_t descLen = strlen(desc);
×
2923
    if (descLen >= TSDB_INSTANCE_DESC_LEN) {
×
2924
      tscError("instance desc length %zu exceeds limit %d", descLen, TSDB_INSTANCE_DESC_LEN - 1);
×
2925
      return terrno = TSDB_CODE_INVALID_PARA;
×
2926
    }
2927
  }
2928

2929
  int32_t code = taos_init();
×
2930
  if (code != TSDB_CODE_SUCCESS) {
×
2931
    return code;
×
2932
  }
2933

2934
  SConfig *pCfg = taosGetCfg();
×
2935
  if (pCfg == NULL) {
×
2936
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
2937
  }
2938

2939
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
×
2940
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
×
2941
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
2942
  }
2943

2944
  SEp firstEp = {0};
×
2945
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
×
2946
  if (code != TSDB_CODE_SUCCESS) {
×
2947
    return terrno = code;
×
2948
  }
2949

2950
  void    *clientRpc = NULL;
×
2951
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
×
2952
  SRpcMsg  rpcMsg = {0};
×
2953
  SRpcMsg  rpcRsp = {0};
×
2954
  SRpcInit rpcInit = {0};
×
2955

2956
  rpcInit.label = "INST";
×
2957
  rpcInit.numOfThreads = 1;
×
2958
  rpcInit.cfp = NULL;
×
2959
  rpcInit.sessions = 16;
×
2960
  rpcInit.connType = TAOS_CONN_CLIENT;
×
2961
  rpcInit.idleTime = tsShellActivityTimer * 1000;
×
2962
  rpcInit.compressSize = tsCompressMsgSize;
×
2963
  rpcInit.user = TSDB_DEFAULT_USER;
×
2964

2965
  rpcInit.rfp = instanceRegisterRpcRfp;
×
2966
  rpcInit.retryMinInterval = tsRedirectPeriod;
×
2967
  rpcInit.retryStepFactor = tsRedirectFactor;
×
2968
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
×
2969
  rpcInit.retryMaxTimeout =
×
2970
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
2971

2972
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
×
2973
  connLimitNum = TMAX(connLimitNum, 10);
×
2974
  connLimitNum = TMIN(connLimitNum, 500);
×
2975
  rpcInit.connLimitNum = connLimitNum;
×
2976
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
×
2977
  rpcInit.readTimeout = tsReadTimeout;
×
2978
  rpcInit.ipv6 = tsEnableIpv6;
×
2979
  rpcInit.enableSSL = tsEnableTLS;
×
2980

2981
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
×
2982
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
×
2983
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
×
2984
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
×
2985
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
×
2986

2987
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
×
2988
  if (code != TSDB_CODE_SUCCESS) {
×
2989
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
2990
    return code;
×
2991
  }
2992

2993
  clientRpc = rpcOpen(&rpcInit);
×
2994
  if (clientRpc == NULL) {
×
2995
    code = terrno;
×
2996
    tscError("failed to init instance register client since %s", tstrerror(code));
×
2997
    return code;
×
2998
  }
2999

3000
  // Prepare epSet
3001
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
×
3002
  epSet.eps[0].port = firstEp.port;
×
3003

3004
  // Prepare request
3005
  SInstanceRegisterReq req = {0};
×
3006
  tstrncpy(req.id, id, sizeof(req.id));
×
3007
  if (type != NULL && type[0] != 0) {
×
3008
    tstrncpy(req.type, type, sizeof(req.type));
×
3009
  }
3010
  if (desc != NULL && desc[0] != 0) {
×
3011
    tstrncpy(req.desc, desc, sizeof(req.desc));
×
3012
  }
3013
  req.expire = expire;
×
3014

3015
  int32_t contLen = tSerializeSInstanceRegisterReq(NULL, 0, &req);
×
3016
  if (contLen <= 0) {
×
3017
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3018
    rpcClose(clientRpc);
×
3019
    return code;
×
3020
  }
3021

3022
  void *pCont = rpcMallocCont(contLen);
×
3023
  if (pCont == NULL) {
×
3024
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3025
    rpcClose(clientRpc);
×
3026
    return code;
×
3027
  }
3028

3029
  if (tSerializeSInstanceRegisterReq(pCont, contLen, &req) < 0) {
×
3030
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3031
    rpcFreeCont(pCont);
×
3032
    rpcClose(clientRpc);
×
3033
    return code;
×
3034
  }
3035

3036
  rpcMsg.pCont = pCont;
×
3037
  rpcMsg.contLen = contLen;
×
3038
  rpcMsg.msgType = TDMT_MND_REGISTER_INSTANCE;
×
3039
  rpcMsg.info.ahandle = (void *)0x9528;  // Different magic number from server status
×
3040
  rpcMsg.info.notFreeAhandle = 1;
×
3041

3042
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
×
3043
  if (TSDB_CODE_SUCCESS != code) {
×
3044
    tscError("failed to send instance register req since %s", tstrerror(code));
×
3045
    // rpcSendRecv failed, pCont may not be freed, but check _RETURN1 path
3046
    // In error path, rpcSendRecv may free pCont, but we free it here to be safe
3047
    rpcClose(clientRpc);
×
3048
    return code;
×
3049
  }
3050

3051
  if (rpcRsp.code != 0) {
×
3052
    code = rpcRsp.code;
×
3053
    tscError("instance register failed, code:%s", tstrerror(code));
×
3054
  } else {
3055
    code = TSDB_CODE_SUCCESS;
×
3056
  }
3057

3058
  if (rpcRsp.pCont != NULL) {
×
3059
    rpcFreeCont(rpcRsp.pCont);
×
3060
  }
3061
  rpcClose(clientRpc);
×
3062

3063
  terrno = code;
×
3064
  return code;
×
3065
}
3066

3067
int32_t taos_list_instances(const char *filter_type, char ***pList, int32_t *pCount) {
×
3068
  if (pList == NULL || pCount == NULL) {
×
3069
    return TSDB_CODE_INVALID_PARA;
×
3070
  }
3071

3072
  int32_t code = taos_init();
×
3073
  if (code != TSDB_CODE_SUCCESS) {
×
3074
    terrno = code;
×
3075
    return code;
×
3076
  }
3077

3078
  SConfig *pCfg = taosGetCfg();
×
3079
  if (pCfg == NULL) {
×
3080
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3081
    return TSDB_CODE_CFG_NOT_FOUND;
×
3082
  }
3083

3084
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
×
3085
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
×
3086
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3087
    return TSDB_CODE_CFG_NOT_FOUND;
×
3088
  }
3089

3090
  SEp firstEp = {0};
×
3091
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
×
3092
  if (code != TSDB_CODE_SUCCESS) {
×
3093
    terrno = code;
×
3094
    return code;
×
3095
  }
3096

3097
  // Initialize RPC connection (similar to taos_register_instance)
3098
  void    *clientRpc = NULL;
×
3099
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
×
3100
  SRpcMsg  rpcMsg = {0};
×
3101
  SRpcMsg  rpcRsp = {0};
×
3102
  SRpcInit rpcInit = {0};
×
3103

3104
  rpcInit.label = "LIST";
×
3105
  rpcInit.numOfThreads = 1;
×
3106
  rpcInit.cfp = NULL;
×
3107
  rpcInit.sessions = 16;
×
3108
  rpcInit.connType = TAOS_CONN_CLIENT;
×
3109
  rpcInit.idleTime = tsShellActivityTimer * 1000;
×
3110
  rpcInit.compressSize = tsCompressMsgSize;
×
3111
  rpcInit.user = TSDB_DEFAULT_USER;
×
3112

3113
  rpcInit.rfp = instanceRegisterRpcRfp;
×
3114
  rpcInit.retryMinInterval = tsRedirectPeriod;
×
3115
  rpcInit.retryStepFactor = tsRedirectFactor;
×
3116
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
×
3117
  rpcInit.retryMaxTimeout =
×
3118
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3119

3120
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
×
3121
  connLimitNum = TMAX(connLimitNum, 10);
×
3122
  connLimitNum = TMIN(connLimitNum, 500);
×
3123
  rpcInit.connLimitNum = connLimitNum;
×
3124
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
×
3125
  rpcInit.readTimeout = tsReadTimeout;
×
3126
  rpcInit.ipv6 = tsEnableIpv6;
×
3127
  rpcInit.enableSSL = tsEnableTLS;
×
3128

3129
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
×
3130
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
×
3131
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
×
3132
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
×
3133
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
×
3134

3135
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
×
3136
  if (code != TSDB_CODE_SUCCESS) {
×
3137
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
3138
    return code;
×
3139
  }
3140

3141
  clientRpc = rpcOpen(&rpcInit);
×
3142
  if (clientRpc == NULL) {
×
3143
    code = terrno;
×
3144
    tscError("failed to init instance list client since %s", tstrerror(code));
×
3145
    terrno = code;
×
3146
    return code;
×
3147
  }
3148

3149
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
×
3150
  epSet.eps[0].port = firstEp.port;
×
3151
  SInstanceListReq req = {0};
×
3152
  if (filter_type != NULL && filter_type[0] != 0) {
×
3153
    tstrncpy(req.filter_type, filter_type, sizeof(req.filter_type));
×
3154
  }
3155

3156
  // Serialize request to get required length
3157
  int32_t contLen = tSerializeSInstanceListReq(NULL, 0, &req);
×
3158
  if (contLen <= 0) {
×
3159
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3160
    rpcClose(clientRpc);
×
3161
    terrno = code;
×
3162
    return code;
×
3163
  }
3164

3165
  // Allocate RPC message buffer (includes message header overhead)
3166
  void *pCont = rpcMallocCont(contLen);
×
3167
  if (pCont == NULL) {
×
3168
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3169
    rpcClose(clientRpc);
×
3170
    terrno = code;
×
3171
    return code;
×
3172
  }
3173

3174
  // Serialize request into the content part (after message header)
3175
  if (tSerializeSInstanceListReq(pCont, contLen, &req) < 0) {
×
3176
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3177
    rpcFreeCont(pCont);
×
3178
    rpcClose(clientRpc);
×
3179
    terrno = code;
×
3180
    return code;
×
3181
  }
3182

3183
  rpcMsg.pCont = pCont;
×
3184
  rpcMsg.contLen = contLen;
×
3185
  rpcMsg.msgType = TDMT_MND_LIST_INSTANCES;
×
3186
  rpcMsg.info.ahandle = (void *)0x9529;  // Different magic number from register
×
3187
  rpcMsg.info.notFreeAhandle = 1;
×
3188

3189
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
×
3190
  if (TSDB_CODE_SUCCESS != code) {
×
3191
    tscError("failed to send instance list req since %s", tstrerror(code));
×
3192
    rpcFreeCont(pCont);
×
3193
    rpcClose(clientRpc);
×
3194
    terrno = code;
×
3195
    return code;
×
3196
  }
3197

3198
  // Check response - rpcRsp.code contains the result code from mnode
3199
  if (rpcRsp.code != 0) {
×
3200
    code = rpcRsp.code;
×
3201
    tscError("instance list failed, code:%s", tstrerror(code));
×
3202
    if (rpcRsp.pCont != NULL) {
×
3203
      rpcFreeCont(rpcRsp.pCont);
×
3204
    }
3205
    rpcClose(clientRpc);
×
3206
    terrno = code;
×
3207
    return code;
×
3208
  }
3209

3210
  // Deserialize response
3211
  if (rpcRsp.pCont != NULL && rpcRsp.contLen > 0) {
×
3212
    SInstanceListRsp rsp = {0};
×
3213
    code = tDeserializeSInstanceListRsp(rpcRsp.pCont, rpcRsp.contLen, &rsp);
×
3214
    if (code != TSDB_CODE_SUCCESS) {
×
3215
      tscError("failed to deserialize instance list rsp, code:%s", tstrerror(code));
×
3216
      if (rsp.ids != NULL) {
×
3217
        for (int32_t i = 0; i < rsp.count; i++) {
×
3218
          if (rsp.ids[i] != NULL) {
×
3219
            taosMemoryFree(rsp.ids[i]);
×
3220
          }
3221
        }
3222
        taosMemoryFree(rsp.ids);
×
3223
        rsp.ids = NULL;
×
3224
      }
3225
      rsp.count = 0;
×
3226
      rpcFreeCont(rpcRsp.pCont);
×
3227
      rpcClose(clientRpc);
×
3228
      terrno = code;
×
3229
      return code;
×
3230
    }
3231
    *pList = rsp.ids;
×
3232
    *pCount = rsp.count;
×
3233
  } else {
3234
    *pList = NULL;
×
3235
    *pCount = 0;
×
3236
  }
3237

3238
  if (rpcRsp.pCont != NULL) {
×
3239
    rpcFreeCont(rpcRsp.pCont);
×
3240
  }
3241
  rpcClose(clientRpc);
×
3242

3243
  return TSDB_CODE_SUCCESS;
×
3244
}
3245

3246
void taos_free_instances(char ***pList, int32_t count) {
×
3247
  if (pList == NULL || *pList == NULL || count <= 0) {
×
3248
    return;
×
3249
  }
3250

3251
  // Free each string in the array
3252
  for (int32_t i = 0; i < count; i++) {
×
3253
    if ((*pList)[i] != NULL) {
×
3254
      taosMemoryFree((*pList)[i]);
×
3255
      (*pList)[i] = NULL;
×
3256
    }
3257
  }
3258

3259
  // Free the array itself
3260
  taosMemoryFree(*pList);
×
3261
  *pList = NULL;
×
3262
}
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