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

taosdata / TDengine / #4890

19 Dec 2025 11:37AM UTC coverage: 62.824% (-2.7%) from 65.487%
#4890

push

travis-ci

web-flow
feat: support TOTP code login and password expired tip (#33969)

22 of 26 new or added lines in 3 files covered. (84.62%)

1989 existing lines in 120 files now uncovered.

63068 of 100389 relevant lines covered (62.82%)

286770988.88 hits per line

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

38.71
/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 "clientSession.h"
37
#include "ttime.h"
38

39
#define TSC_VAR_NOT_RELEASE 1
40
#define TSC_VAR_RELEASED    0
41

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

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

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

55
  for (int i = 1; atomic_val_compare_exchange_32(&lock, 0, 1) != 0; ++i) {
524,604✔
UNCOV
56
    if (i % 1000 == 0) {
×
UNCOV
57
      (void)sched_yield();
×
58
    }
59
  }
60

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

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

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

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

86
void tzCleanup() {
1,177,318✔
87
  taosHashCleanup(pTimezoneMap);
1,177,318✔
88
  taosHashCleanup(pTimezoneNameMap);
1,177,318✔
89
}
1,177,318✔
90

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

254
  monitorClose();
1,177,318✔
255
  tscStopCrashReport();
1,177,318✔
256

257
  hbMgrCleanUp();
1,177,318✔
258

259
  catalogDestroy();
1,177,318✔
260
  schedulerDestroy();
1,177,318✔
261

262
  fmFuncMgtDestroy();
1,177,318✔
263
  qCleanupKeywordsTable();
1,177,318✔
264

265
#if !defined(WINDOWS) && !defined(TD_ASTRA)
266
  tzCleanup();
1,177,318✔
267
#endif
268
  tmqMgmtClose();
1,177,318✔
269

270
  int32_t id = clientReqRefPool;
1,177,318✔
271
  clientReqRefPool = -1;
1,177,318✔
272
  taosCloseRef(id);
1,177,318✔
273

274
  id = clientConnRefPool;
1,177,318✔
275
  clientConnRefPool = -1;
1,177,318✔
276
  taosCloseRef(id);
1,177,318✔
277

278
  nodesDestroyAllocatorSet();
1,177,318✔
279
  cleanupAppInfo();
1,177,318✔
280
  rpcCleanup();
1,177,318✔
281
  tscDebug("rpc cleanup");
1,177,318✔
282

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

287
  sessMgtDestroy();
1,177,318✔
288

289
  taosConvDestroy();
1,177,318✔
290
  DestroyRegexCache();
1,177,318✔
291
#ifdef TAOSD_INTEGRATED
292
  shellStopDaemon();
293
#endif
294
  tscInfo("all local resources released");
1,177,318✔
295
  taosCleanupCfg();
1,177,318✔
296
#ifndef TAOSD_INTEGRATED
297
  taosCloseLog();
1,177,318✔
298
#endif
299
}
300

301
static setConfRet taos_set_config_imp(const char *config) {
51✔
302
  setConfRet ret = {SET_CONF_RET_SUCC, {0}};
51✔
303
  // TODO: need re-implementation
304
  return ret;
51✔
305
}
306

307
setConfRet taos_set_config(const char *config) {
51✔
308
  // TODO  pthread_mutex_lock(&setConfMutex);
309
  setConfRet ret = taos_set_config_imp(config);
51✔
310
  //  pthread_mutex_unlock(&setConfMutex);
311
  return ret;
51✔
312
}
313

314
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
2,639,087✔
315
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
2,639,087✔
316
  if (user == NULL) {
2,639,857✔
317
    user = TSDB_DEFAULT_USER;
259,856✔
318
  }
319

320
  if (pass == NULL) {
2,639,857✔
321
    pass = TSDB_DEFAULT_PASS;
259,856✔
322
  }
323

324
  STscObj *pObj = NULL;
2,639,857✔
325
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, NULL, db, port, CONN_TYPE__QUERY, &pObj);
2,639,810✔
326
  if (TSDB_CODE_SUCCESS == code) {
2,639,810✔
327
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
2,626,295✔
328
    if (NULL == rid) {
2,626,295✔
329
      tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db);
×
330
      return NULL;
×
331
    }
332
    *rid = pObj->id;
2,626,295✔
333
    return (TAOS *)rid;
2,626,295✔
334
  } else {
335
    terrno = code;
13,515✔
336
  }
337

338
  return NULL;
13,515✔
339
}
340

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

347
int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type) {
2,660✔
348
  if (taos == NULL) {
2,660✔
349
    terrno = TSDB_CODE_INVALID_PARA;
×
350
    return terrno;
×
351
  }
352

353
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2,660✔
354
  if (NULL == pObj) {
2,660✔
355
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
356
    tscError("invalid parameter for %s", __func__);
×
357
    return terrno;
×
358
  }
359

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

396
  releaseTscObj(*(int64_t *)taos);
2,660✔
397
  return 0;
2,660✔
398
}
399

400
typedef struct SFetchWhiteListInfo {
401
  int64_t                     connId;
402
  __taos_async_whitelist_fn_t userCbFn;
403
  void                       *userParam;
404
} SFetchWhiteListInfo;
405

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

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

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

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

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

441
  taosMemoryFree(pWhiteLists);
×
442
  taosMemoryFree(pMsg->pData);
×
443
  taosMemoryFree(pMsg->pEpSet);
×
444
  taosMemoryFree(pInfo);
×
445
  tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
446
  return code;
×
447
}
448

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

455
  int64_t connId = *(int64_t *)taos;
×
456

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

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

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

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

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

494
  pParam->connId = connId;
×
495
  pParam->userCbFn = fp;
×
496

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

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

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

522

523

524
typedef struct SFetchIpWhiteListInfo {
525
  int64_t connId;
526
  bool supportNeg;
527
  void   *userParam;
528

529
  __taos_async_ip_whitelist_fn_t userCbFn;
530
} SFetchIpWhiteListInfo;
531

532

533

534
int32_t fetchIpWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
535
  int32_t lino = 0;
×
536
  char  **pWhiteLists = NULL;
×
537

538
  SGetUserIpWhiteListRsp wlRsp = {0};
×
539

540
  SFetchIpWhiteListInfo *pInfo = (SFetchIpWhiteListInfo *)param;
×
541
  TAOS *taos = &pInfo->connId;
×
542

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

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

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

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

566
    code = tIpUintToStr(pIpRange, &ipAddr);
×
567
    TAOS_CHECK_GOTO(code, &lino, _error);
×
568

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

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

608

609

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

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

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

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

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

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

654
  pParam->connId = connId;
×
655
  pParam->supportNeg = supportNeg;
×
656
  pParam->userCbFn = fp;
×
657
  pParam->userParam = param;
×
658

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

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

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

683

684

685
void taos_fetch_whitelist_dual_stack_a(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param) {
×
686
  taosFetchIpWhiteList(taos, fp, param, false);
×
687
}
×
688

689

690

691
void taos_fetch_ip_whitelist_a(TAOS *taos, __taos_async_ip_whitelist_fn_t fp, void *param) {
×
692
  taosFetchIpWhiteList(taos, fp, param, true);
×
693
}
×
694

695

696
typedef struct SFetchDateTimeWhiteListInfo {
697
  int64_t                              connId;
698
  void                                *userParam;
699
  __taos_async_datetime_whitelist_fn_t userCbFn;
700
} SFetchDateTimeWhiteListInfo;
701

702

703

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

709
  SUserDateTimeWhiteList wlRsp = {0};
×
710

711
  SFetchDateTimeWhiteListInfo *pInfo = (SFetchDateTimeWhiteListInfo *)param;
×
712
  TAOS *taos = &pInfo->connId;
×
713

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

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

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

729
  int32_t numWhiteLists =0;
×
730
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
731
    SDateTimeWhiteListItem *item = &wlRsp.pWhiteLists[i];
×
732

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

739
    int duration = item->duration / 60;
×
740

741
    if (item->absolute) {
×
742
      struct STm tm;
×
743
      (void)taosTs2Tm(item->start, TSDB_TIME_PRECISION_SECONDS, &tm, NULL);
×
744
      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);
×
745
    } else {
746
      int day = item->start / 86400;
×
747
      int hour = (item->start % 86400) / 3600;
×
748
      int minute = (item->start % 3600) / 60;
×
749
      snprintf(p, 128, "%c %s %02d:%02d %d", item->neg ? '-' : '+', weekdays[day], hour, minute, duration);
×
750
    }
751
    pWhiteLists[numWhiteLists++] = p;
×
752
  }
753

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

769

770

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

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

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

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

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

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

815
  pParam->connId = connId;
×
816
  pParam->userCbFn = fp;
×
817
  pParam->userParam = param;
×
818

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

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

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

843

844

845
void taos_close_internal(void *taos) {
2,690,474✔
846
  if (taos == NULL) {
2,690,474✔
847
    return;
×
848
  }
849
  int32_t code = 0;
2,690,474✔
850

851
  STscObj *pTscObj = (STscObj *)taos;
2,690,474✔
852
  tscDebug("conn:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
2,690,474✔
853

854
  SSessParam para = {.type = SESSION_PER_USER, .value = -1};
2,690,474✔
855
  code = sessMgtUpdateUserMetric((char *)pTscObj->user, &para);
2,690,226✔
856
  if (code != TSDB_CODE_SUCCESS) {
2,690,474✔
857
    tscWarn("conn:0x%" PRIx64 ", failed to update user:%s metric when close connection, code:%d", pTscObj->id,
×
858
            pTscObj->user, code);
859
  } 
860

861
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
2,690,474✔
862
    tscError("conn:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
×
863
  }
864
}
865

866
void taos_close(TAOS *taos) {
2,626,678✔
867
  if (taos == NULL) {
2,626,678✔
868
    return;
402✔
869
  }
870

871
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2,626,276✔
872
  if (NULL == pObj) {
2,626,220✔
873
    taosMemoryFree(taos);
×
874
    return;
×
875
  }
876

877
  taos_close_internal(pObj);
2,626,220✔
878
  releaseTscObj(*(int64_t *)taos);
2,626,276✔
879
  taosMemoryFree(taos);
2,626,276✔
880
}
881

882
int taos_errno(TAOS_RES *res) {
795,870,286✔
883
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
795,870,286✔
884
    return terrno;
34,332✔
885
  }
886

887
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
795,836,044✔
888
    return 0;
275,920✔
889
  }
890

891
  return ((SRequestObj *)res)->code;
795,563,782✔
892
}
893

894
const char *taos_errstr(TAOS_RES *res) {
21,320,083✔
895
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
21,320,083✔
896
    if (*(taosGetErrMsg()) == 0) {
33,790✔
897
      return (const char *)tstrerror(terrno);
33,756✔
898
    } else {
899
      (void)snprintf(taosGetErrMsgReturn(), ERR_MSG_LEN, "%s", taosGetErrMsg());
34✔
900
      return (const char*)taosGetErrMsgReturn();
34✔
901
    }
902
  }
903

904
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
21,286,293✔
905
    return "success";
×
906
  }
907

908
  SRequestObj *pRequest = (SRequestObj *)res;
21,286,293✔
909
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
21,286,293✔
910
    return pRequest->msgBuf;
17,464,692✔
911
  } else {
912
    return (const char *)tstrerror(pRequest->code);
3,821,601✔
913
  }
914
}
915

916
void taos_free_result(TAOS_RES *res) {
640,875,235✔
917
  if (NULL == res) {
640,875,235✔
918
    return;
1,315,685✔
919
  }
920

921
  tscTrace("res:%p, will be freed", res);
639,559,550✔
922

923
  if (TD_RES_QUERY(res)) {
639,559,548✔
924
    SRequestObj *pRequest = (SRequestObj *)res;
637,141,462✔
925
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query, res:%p", pRequest->requestId, res);
637,141,462✔
926
    destroyRequest(pRequest);
637,142,462✔
927
    return;
637,138,606✔
928
  }
929

930
  SMqRspObj *pRsp = (SMqRspObj *)res;
2,418,094✔
931
  if (TD_RES_TMQ(res)) {
2,418,094✔
932
    tDeleteMqDataRsp(&pRsp->dataRsp);
2,409,503✔
933
    doFreeReqResultInfo(&pRsp->resInfo);
2,409,410✔
934
  } else if (TD_RES_TMQ_METADATA(res)) {
8,838✔
935
    tDeleteSTaosxRsp(&pRsp->dataRsp);
323✔
936
    doFreeReqResultInfo(&pRsp->resInfo);
323✔
937
  } else if (TD_RES_TMQ_META(res)) {
8,608✔
938
    tDeleteMqMetaRsp(&pRsp->metaRsp);
7,308✔
939
  } else if (TD_RES_TMQ_BATCH_META(res)) {
1,300✔
940
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
1,300✔
941
  } else if (TD_RES_TMQ_RAW(res)) {
×
942
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
×
943
  }
944
  taosMemoryFree(pRsp);
2,418,062✔
945
}
946

947
void taos_kill_query(TAOS *taos) {
670✔
948
  if (NULL == taos) {
670✔
949
    return;
402✔
950
  }
951

952
  int64_t  rid = *(int64_t *)taos;
268✔
953
  STscObj *pTscObj = acquireTscObj(rid);
268✔
954
  if (pTscObj) {
268✔
955
    stopAllRequests(pTscObj->pRequests);
268✔
956
  }
957
  releaseTscObj(rid);
268✔
958
}
959

960
int taos_field_count(TAOS_RES *res) {
2,147,483,647✔
961
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
962
    return 0;
×
963
  }
964

965
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
966
  return pResInfo->numOfCols;
2,147,483,647✔
967
}
968

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

971
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
1,231,454,288✔
972
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,231,454,288✔
973
    return NULL;
2,341,903✔
974
  }
975

976
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
1,229,164,176✔
977
  return pResInfo->userFields;
1,229,164,176✔
978
}
979

980
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
635,901,877✔
981
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
813✔
982
  return taosQueryImplWithReqid(taos, sql, false, reqid);
813✔
983
}
984

985
TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res) {
855✔
986
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
855✔
987
    return NULL;
×
988
  }
989
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
855✔
990
  return pResInfo->fields;
855✔
991
}
992

993
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
2,036,657,758✔
994
  if (res == NULL) {
2,036,657,758✔
995
    return NULL;
×
996
  }
997

998
  if (TD_RES_QUERY(res)) {
2,036,657,758✔
999
    SRequestObj *pRequest = (SRequestObj *)res;
898,003,969✔
1000
    if (pRequest->killed) {
898,003,969✔
1001
      tscInfo("query has been killed, can not fetch more row.");
×
1002
      pRequest->code = TSDB_CODE_TSC_QUERY_KILLED;
×
1003
      return NULL;
×
1004
    }
1005

1006
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
898,013,118✔
1007
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
898,051,495✔
1008
      return NULL;
×
1009
    }
1010

1011
    if (pRequest->inCallback) {
897,994,539✔
UNCOV
1012
      tscError("can not call taos_fetch_row before query callback ends.");
×
UNCOV
1013
      terrno = TSDB_CODE_TSC_INVALID_OPERATION;
×
UNCOV
1014
      return NULL;
×
1015
    }
1016

1017
    return doAsyncFetchRows(pRequest, true, true);
898,063,155✔
1018
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,138,683,321✔
1019
    SMqRspObj      *msg = ((SMqRspObj *)res);
1,138,697,289✔
1020
    SReqResultInfo *pResultInfo = NULL;
1,138,697,289✔
1021
    if (msg->resIter == -1) {
1,138,724,971✔
1022
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
2,128,804✔
1023
        return NULL;
×
1024
      }
1025
    } else {
1026
      pResultInfo = tmqGetCurResInfo(res);
1,136,622,602✔
1027
    }
1028

1029
    if (pResultInfo->current < pResultInfo->numOfRows) {
1,138,751,406✔
1030
      doSetOneRowPtr(pResultInfo);
1,116,672,998✔
1031
      pResultInfo->current += 1;
1,116,753,816✔
1032
      return pResultInfo->row;
1,116,824,444✔
1033
    } else {
1034
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
22,073,628✔
1035
        return NULL;
2,128,757✔
1036
      }
1037

1038
      doSetOneRowPtr(pResultInfo);
19,944,034✔
1039
      pResultInfo->current += 1;
19,944,685✔
1040
      return pResultInfo->row;
19,944,592✔
1041
    }
1042
  } else if (TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1043
    return NULL;
×
1044
  } else {
1045
    tscError("invalid result passed to taos_fetch_row");
×
1046
    terrno = TSDB_CODE_TMQ_INVALID_DATA;
×
1047
    return NULL;
×
1048
  }
1049
}
1050

1051
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
1,139,478,783✔
1052
  return taos_print_row_with_size(str, INT32_MAX, row, fields, num_fields);
1,139,478,783✔
1053
}
1054
int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
1,139,672,183✔
1055
  int32_t len = 0;
1,139,672,183✔
1056
  for (int i = 0; i < num_fields; ++i) {
2,147,483,647✔
1057
    if (i > 0 && len < size - 1) {
2,147,483,647✔
1058
      str[len++] = ' ';
2,147,483,647✔
1059
    }
1060

1061
    if (row[i] == NULL) {
2,147,483,647✔
1062
      len += tsnprintf(str + len, size - len, "%s", TSDB_DATA_NULL_STR);
27,838,440✔
1063
      continue;
27,838,511✔
1064
    }
1065

1066
    switch (fields[i].type) {
2,147,483,647✔
1067
      case TSDB_DATA_TYPE_TINYINT:
74,573,235✔
1068
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
74,573,235✔
1069
        break;
74,592,159✔
1070

1071
      case TSDB_DATA_TYPE_UTINYINT:
125,940✔
1072
        len += tsnprintf(str + len, size - len, "%u", *((uint8_t *)row[i]));
125,940✔
1073
        break;
126,000✔
1074

1075
      case TSDB_DATA_TYPE_SMALLINT:
125,970✔
1076
        len += tsnprintf(str + len, size - len, "%d", *((int16_t *)row[i]));
125,970✔
1077
        break;
125,850✔
1078

1079
      case TSDB_DATA_TYPE_USMALLINT:
126,000✔
1080
        len += tsnprintf(str + len, size - len, "%u", *((uint16_t *)row[i]));
126,000✔
1081
        break;
125,970✔
1082

1083
      case TSDB_DATA_TYPE_INT:
1,070,572,993✔
1084
        len += tsnprintf(str + len, size - len, "%d", *((int32_t *)row[i]));
1,070,572,993✔
1085
        break;
1,070,657,260✔
1086

1087
      case TSDB_DATA_TYPE_UINT:
125,970✔
1088
        len += tsnprintf(str + len, size - len, "%u", *((uint32_t *)row[i]));
125,970✔
1089
        break;
126,000✔
1090

1091
      case TSDB_DATA_TYPE_BIGINT:
974,223,835✔
1092
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
974,223,835✔
1093
        break;
974,238,562✔
1094

1095
      case TSDB_DATA_TYPE_UBIGINT:
126,000✔
1096
        len += tsnprintf(str + len, size - len, "%" PRIu64, *((uint64_t *)row[i]));
126,000✔
1097
        break;
125,940✔
1098

1099
      case TSDB_DATA_TYPE_FLOAT: {
148,292,486✔
1100
        float fv = 0;
148,292,486✔
1101
        fv = GET_FLOAT_VAL(row[i]);
148,292,486✔
1102
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
148,329,587✔
1103
      } break;
147,928,448✔
1104

1105
      case TSDB_DATA_TYPE_DOUBLE: {
449,995,487✔
1106
        double dv = 0;
449,995,487✔
1107
        dv = GET_DOUBLE_VAL(row[i]);
449,995,487✔
1108
        len += snprintf(str + len, size - len, "%.*g", DBL_DIG, dv);
449,995,393✔
1109
      } break;
449,997,352✔
1110

1111
      case TSDB_DATA_TYPE_VARBINARY: {
126,296✔
1112
        void    *data = NULL;
126,296✔
1113
        uint32_t tmp = 0;
126,296✔
1114
        int32_t  charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
126,296✔
1115
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
126,296✔
1116
          break;
×
1117
        }
1118
        uint32_t copyLen = TMIN(size - len - 1, tmp);
126,236✔
1119
        (void)memcpy(str + len, data, copyLen);
126,236✔
1120
        len += copyLen;
126,236✔
1121
        taosMemoryFree(data);
126,236✔
1122
      } break;
126,326✔
1123
      case TSDB_DATA_TYPE_BINARY:
1,327,533,921✔
1124
      case TSDB_DATA_TYPE_NCHAR:
1125
      case TSDB_DATA_TYPE_GEOMETRY: {
1126
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
1,327,533,921✔
1127
        if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_VARBINARY ||
1,327,536,990✔
1128
            fields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
354,507,874✔
1129
          if (charLen > fields[i].bytes || charLen < 0) {
973,182,758✔
UNCOV
1130
            tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
×
1131
            break;
×
1132
          }
1133
        } else {
1134
          if (charLen > fields[i].bytes * TSDB_NCHAR_SIZE || charLen < 0) {
354,389,602✔
1135
            tscError("taos_print_row error. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
150✔
1136
            break;
×
1137
          }
1138
        }
1139

1140
        uint32_t copyLen = TMIN(size - len - 1, charLen);
1,327,594,000✔
1141
        (void)memcpy(str + len, row[i], copyLen);
1,327,594,000✔
1142
        len += copyLen;
1,327,540,767✔
1143
      } break;
1,327,540,767✔
1144
      case TSDB_DATA_TYPE_BLOB:
×
1145
      case TSDB_DATA_TYPE_MEDIUMBLOB: {
1146
        void    *data = NULL;
×
1147
        uint32_t tmp = 0;
×
1148
        int32_t  charLen = blobDataLen((char *)row[i] - BLOBSTR_HEADER_SIZE);
×
1149
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
×
1150
          break;
×
1151
        }
1152

1153
        uint32_t copyLen = TMIN(size - len - 1, tmp);
×
1154
        (void)memcpy(str + len, data, copyLen);
×
1155
        len += copyLen;
×
1156

1157
        taosMemoryFree(data);
×
1158
      } break;
×
1159

1160
      case TSDB_DATA_TYPE_TIMESTAMP:
1,519,031,414✔
1161
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
1,519,031,414✔
1162
        break;
1,519,002,439✔
1163

1164
      case TSDB_DATA_TYPE_BOOL:
126,000✔
1165
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
126,000✔
1166
        break;
125,970✔
1167
      case TSDB_DATA_TYPE_DECIMAL64:
×
1168
      case TSDB_DATA_TYPE_DECIMAL: {
1169
        uint32_t decimalLen = strlen(row[i]);
×
1170
        uint32_t copyLen = TMIN(size - len - 1, decimalLen);
×
1171
        (void)memcpy(str + len, row[i], copyLen);
×
1172
        len += copyLen;
×
1173
      } break;
×
1174
      default:
×
1175
        break;
×
1176
    }
1177

1178
    if (len >= size - 1) {
2,147,483,647✔
1179
      break;
×
1180
    }
1181
  }
1182
  if (len < size) {
1,138,219,700✔
1183
    str[len] = 0;
1,139,640,539✔
1184
  }
1185

1186
  return len;
1,139,548,194✔
1187
}
1188

1189
int *taos_fetch_lengths(TAOS_RES *res) {
1,950,618,933✔
1190
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,950,618,933✔
1191
    return NULL;
×
1192
  }
1193

1194
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
1,950,724,244✔
1195
  return pResInfo->length;
1,950,724,244✔
1196
}
1197

1198
TAOS_ROW *taos_result_block(TAOS_RES *res) {
×
1199
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1200
    terrno = TSDB_CODE_INVALID_PARA;
×
1201
    return NULL;
×
1202
  }
1203

1204
  if (taos_is_update_query(res)) {
×
1205
    return NULL;
×
1206
  }
1207

1208
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
1209
  return &pResInfo->row;
×
1210
}
1211

1212
// todo intergrate with tDataTypes
1213
const char *taos_data_type(int type) {
×
1214
  switch (type) {
×
1215
    case TSDB_DATA_TYPE_NULL:
×
1216
      return "TSDB_DATA_TYPE_NULL";
×
1217
    case TSDB_DATA_TYPE_BOOL:
×
1218
      return "TSDB_DATA_TYPE_BOOL";
×
1219
    case TSDB_DATA_TYPE_TINYINT:
×
1220
      return "TSDB_DATA_TYPE_TINYINT";
×
1221
    case TSDB_DATA_TYPE_SMALLINT:
×
1222
      return "TSDB_DATA_TYPE_SMALLINT";
×
1223
    case TSDB_DATA_TYPE_INT:
×
1224
      return "TSDB_DATA_TYPE_INT";
×
1225
    case TSDB_DATA_TYPE_BIGINT:
×
1226
      return "TSDB_DATA_TYPE_BIGINT";
×
1227
    case TSDB_DATA_TYPE_FLOAT:
×
1228
      return "TSDB_DATA_TYPE_FLOAT";
×
1229
    case TSDB_DATA_TYPE_DOUBLE:
×
1230
      return "TSDB_DATA_TYPE_DOUBLE";
×
1231
    case TSDB_DATA_TYPE_VARCHAR:
×
1232
      return "TSDB_DATA_TYPE_VARCHAR";
×
1233
      //    case TSDB_DATA_TYPE_BINARY:          return "TSDB_DATA_TYPE_VARCHAR";
1234
    case TSDB_DATA_TYPE_TIMESTAMP:
×
1235
      return "TSDB_DATA_TYPE_TIMESTAMP";
×
1236
    case TSDB_DATA_TYPE_NCHAR:
×
1237
      return "TSDB_DATA_TYPE_NCHAR";
×
1238
    case TSDB_DATA_TYPE_JSON:
×
1239
      return "TSDB_DATA_TYPE_JSON";
×
1240
    case TSDB_DATA_TYPE_GEOMETRY:
×
1241
      return "TSDB_DATA_TYPE_GEOMETRY";
×
1242
    case TSDB_DATA_TYPE_UTINYINT:
×
1243
      return "TSDB_DATA_TYPE_UTINYINT";
×
1244
    case TSDB_DATA_TYPE_USMALLINT:
×
1245
      return "TSDB_DATA_TYPE_USMALLINT";
×
1246
    case TSDB_DATA_TYPE_UINT:
×
1247
      return "TSDB_DATA_TYPE_UINT";
×
1248
    case TSDB_DATA_TYPE_UBIGINT:
×
1249
      return "TSDB_DATA_TYPE_UBIGINT";
×
1250
    case TSDB_DATA_TYPE_VARBINARY:
×
1251
      return "TSDB_DATA_TYPE_VARBINARY";
×
1252
    case TSDB_DATA_TYPE_DECIMAL:
×
1253
      return "TSDB_DATA_TYPE_DECIMAL";
×
1254
    case TSDB_DATA_TYPE_BLOB:
×
1255
      return "TSDB_DATA_TYPE_BLOB";
×
1256
    case TSDB_DATA_TYPE_MEDIUMBLOB:
×
1257
      return "TSDB_DATA_TYPE_MEDIUMBLOB";
×
1258
    default:
×
1259
      return "UNKNOWN";
×
1260
  }
1261
}
1262

1263
const char *taos_get_client_info() { return td_version; }
727,595✔
1264

1265
// return int32_t
1266
int taos_affected_rows(TAOS_RES *res) {
499,484,912✔
1267
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
499,484,912✔
1268
      TD_RES_TMQ_BATCH_META(res)) {
499,487,449✔
1269
    return 0;
×
1270
  }
1271

1272
  SRequestObj    *pRequest = (SRequestObj *)res;
499,485,866✔
1273
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
499,485,866✔
1274
  return (int)pResInfo->numOfRows;
499,486,154✔
1275
}
1276

1277
// return int64_t
1278
int64_t taos_affected_rows64(TAOS_RES *res) {
1,308,795✔
1279
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,308,795✔
1280
      TD_RES_TMQ_BATCH_META(res)) {
1,308,795✔
1281
    return 0;
×
1282
  }
1283

1284
  SRequestObj    *pRequest = (SRequestObj *)res;
1,308,795✔
1285
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
1,308,795✔
1286
  return pResInfo->numOfRows;
1,308,795✔
1287
}
1288

1289
int taos_result_precision(TAOS_RES *res) {
1,154,467,655✔
1290
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,154,467,655✔
1291
    return TSDB_TIME_PRECISION_MILLI;
×
1292
  }
1293

1294
  if (TD_RES_QUERY(res)) {
1,154,470,607✔
1295
    SRequestObj *pRequest = (SRequestObj *)res;
83,409,292✔
1296
    return pRequest->body.resInfo.precision;
83,409,292✔
1297
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,071,064,198✔
1298
    SReqResultInfo *info = tmqGetCurResInfo(res);
1,071,060,000✔
1299
    return info->precision;
1,071,060,000✔
1300
  }
1301
  return TSDB_TIME_PRECISION_MILLI;
×
1302
}
1303

1304
int taos_select_db(TAOS *taos, const char *db) {
92,269✔
1305
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
92,269✔
1306
  if (pObj == NULL) {
92,269✔
1307
    releaseTscObj(*(int64_t *)taos);
×
1308
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1309
    return TSDB_CODE_TSC_DISCONNECTED;
×
1310
  }
1311

1312
  if (db == NULL || strlen(db) == 0) {
92,269✔
1313
    releaseTscObj(*(int64_t *)taos);
×
1314
    tscError("invalid parameter for %s", db == NULL ? "db is NULL" : "db is empty");
×
1315
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
1316
    return terrno;
×
1317
  }
1318

1319
  char sql[256] = {0};
92,269✔
1320
  (void)snprintf(sql, tListLen(sql), "use %s", db);
92,269✔
1321

1322
  TAOS_RES *pRequest = taos_query(taos, sql);
92,269✔
1323
  int32_t   code = taos_errno(pRequest);
92,269✔
1324

1325
  taos_free_result(pRequest);
92,269✔
1326
  releaseTscObj(*(int64_t *)taos);
92,269✔
1327
  return code;
92,269✔
1328
}
1329

1330
void taos_stop_query(TAOS_RES *res) {
640,736,337✔
1331
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
640,736,337✔
1332
      TD_RES_TMQ_BATCH_META(res)) {
640,737,292✔
1333
    return;
50✔
1334
  }
1335

1336
  stopAllQueries((SRequestObj *)res);
640,736,878✔
1337
}
1338

1339
bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
×
1340
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1341
    return true;
×
1342
  }
1343
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
×
1344
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
×
1345
    return true;
×
1346
  }
1347

1348
  SResultColumn *pCol = &pResultInfo->pCol[col];
×
1349
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
×
1350
    return (pCol->offset[row] == -1);
×
1351
  } else {
1352
    return colDataIsNull_f(pCol, row);
×
1353
  }
1354
}
1355

1356
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
793,998✔
1357

1358
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
163,454,725✔
1359
  int32_t numOfRows = 0;
163,454,725✔
1360
  /*int32_t code = */ terrno = taos_fetch_block_s(res, &numOfRows, rows);
163,454,725✔
1361
  return numOfRows;
163,454,725✔
1362
}
1363

1364
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
163,454,725✔
1365
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
163,454,725✔
1366
    return 0;
×
1367
  }
1368

1369
  if (TD_RES_QUERY(res)) {
163,454,725✔
1370
    SRequestObj *pRequest = (SRequestObj *)res;
154,111,860✔
1371

1372
    (*rows) = NULL;
154,111,860✔
1373
    (*numOfRows) = 0;
154,111,860✔
1374

1375
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
154,111,860✔
1376
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
153,960,857✔
1377
      return pRequest->code;
667,350✔
1378
    }
1379

1380
    (void)doAsyncFetchRows(pRequest, false, true);
153,444,303✔
1381

1382
    // TODO refactor
1383
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
153,443,712✔
1384
    pResultInfo->current = pResultInfo->numOfRows;
153,444,106✔
1385

1386
    (*rows) = pResultInfo->row;
153,444,303✔
1387
    (*numOfRows) = pResultInfo->numOfRows;
153,444,106✔
1388
    return pRequest->code;
153,444,303✔
1389
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
9,342,865✔
1390
    SReqResultInfo *pResultInfo = NULL;
9,342,865✔
1391
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
9,342,865✔
1392
    if (code != 0) return code;
9,342,865✔
1393

1394
    pResultInfo->current = pResultInfo->numOfRows;
9,071,021✔
1395
    (*rows) = pResultInfo->row;
9,071,021✔
1396
    (*numOfRows) = pResultInfo->numOfRows;
9,071,021✔
1397
    return 0;
9,071,021✔
1398
  } else {
1399
    tscError("taos_fetch_block_s invalid res type");
×
1400
    return TSDB_CODE_TMQ_INVALID_DATA;
×
1401
  }
1402
}
1403

1404
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
148,028✔
1405
  *numOfRows = 0;
148,028✔
1406
  *pData = NULL;
148,028✔
1407

1408
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
148,028✔
1409
    return 0;
×
1410
  }
1411

1412
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
148,028✔
1413
    SReqResultInfo *pResultInfo = NULL;
143,465✔
1414
    int32_t         code = tmqGetNextResInfo(res, false, &pResultInfo);
143,465✔
1415
    if (code != 0) {
143,465✔
1416
      (*numOfRows) = 0;
2,513✔
1417
      return 0;
2,513✔
1418
    }
1419

1420
    pResultInfo->current = pResultInfo->numOfRows;
140,952✔
1421
    (*numOfRows) = pResultInfo->numOfRows;
140,952✔
1422
    (*pData) = (void *)pResultInfo->pData;
140,952✔
1423
    return 0;
140,952✔
1424
  }
1425

1426
  SRequestObj *pRequest = (SRequestObj *)res;
4,563✔
1427

1428
  if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
4,563✔
1429
      pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
4,563✔
1430
    return pRequest->code;
×
1431
  }
1432

1433
  (void)doAsyncFetchRows(pRequest, false, false);
4,563✔
1434

1435
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
4,563✔
1436

1437
  pResultInfo->current = pResultInfo->numOfRows;
4,563✔
1438
  (*numOfRows) = pResultInfo->numOfRows;
4,563✔
1439
  (*pData) = (void *)pResultInfo->pData;
4,563✔
1440

1441
  return pRequest->code;
4,563✔
1442
}
1443

1444
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
114,219,322✔
1445
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
114,219,322✔
1446
    return 0;
×
1447
  }
1448

1449
  int32_t numOfFields = taos_num_fields(res);
114,219,322✔
1450
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
114,219,322✔
1451
    return 0;
×
1452
  }
1453

1454
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
114,219,322✔
1455
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
114,219,322✔
1456
  if (!IS_VAR_DATA_TYPE(pField->type)) {
114,219,322✔
1457
    return 0;
×
1458
  }
1459

1460
  return pResInfo->pCol[columnIndex].offset;
114,219,322✔
1461
}
1462

1463
int taos_is_null_by_column(TAOS_RES *res, int columnIndex, bool result[], int *rows) {
326,632,983✔
1464
  if (res == NULL || result == NULL || rows == NULL || *rows <= 0 || columnIndex < 0 || TD_RES_TMQ_META(res) ||
326,632,983✔
1465
      TD_RES_TMQ_RAW(res) || TD_RES_TMQ_BATCH_META(res)) {
326,633,462✔
1466
    return TSDB_CODE_INVALID_PARA;
×
1467
  }
1468

1469
  int32_t numOfFields = taos_num_fields(res);
326,632,983✔
1470
  if (columnIndex >= numOfFields || numOfFields == 0) {
326,633,462✔
1471
    return TSDB_CODE_INVALID_PARA;
×
1472
  }
1473

1474
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
326,632,983✔
1475
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
326,632,983✔
1476
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
326,632,983✔
1477

1478
  if (*rows > pResInfo->numOfRows) {
326,633,462✔
1479
    *rows = pResInfo->numOfRows;
×
1480
  }
1481
  if (IS_VAR_DATA_TYPE(pField->type)) {
326,632,983✔
1482
    for (int i = 0; i < *rows; i++) {
×
1483
      if (pCol->offset[i] == -1) {
×
1484
        result[i] = true;
×
1485
      } else {
1486
        result[i] = false;
×
1487
      }
1488
    }
1489
  } else {
1490
    for (int i = 0; i < *rows; i++) {
2,147,483,647✔
1491
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1492
        result[i] = true;
2,147,483,647✔
1493
      } else {
1494
        result[i] = false;
2,147,483,647✔
1495
      }
1496
    }
1497
  }
1498
  return 0;
326,633,462✔
1499
}
1500

1501
int taos_validate_sql(TAOS *taos, const char *sql) {
×
1502
  TAOS_RES *pObj = taosQueryImpl(taos, sql, true, TD_REQ_FROM_APP);
×
1503

1504
  int code = taos_errno(pObj);
×
1505

1506
  taos_free_result(pObj);
×
1507
  return code;
×
1508
}
1509

1510
void taos_reset_current_db(TAOS *taos) {
×
1511
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
1512
  if (pTscObj == NULL) {
×
1513
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1514
    return;
×
1515
  }
1516

1517
  resetConnectDB(pTscObj);
×
1518

1519
  releaseTscObj(*(int64_t *)taos);
×
1520
}
1521

1522
const char *taos_get_server_info(TAOS *taos) {
36,914✔
1523
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
36,914✔
1524
  if (pTscObj == NULL) {
36,914✔
1525
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1526
    return NULL;
×
1527
  }
1528

1529
  releaseTscObj(*(int64_t *)taos);
36,914✔
1530

1531
  return pTscObj->sDetailVer;
36,914✔
1532
}
1533

1534
int taos_get_current_db(TAOS *taos, char *database, int len, int *required) {
556✔
1535
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
556✔
1536
  if (pTscObj == NULL) {
556✔
1537
    return TSDB_CODE_TSC_DISCONNECTED;
×
1538
  }
1539

1540
  int code = TSDB_CODE_SUCCESS;
556✔
1541
  (void)taosThreadMutexLock(&pTscObj->mutex);
556✔
1542
  if (database == NULL || len <= 0) {
556✔
1543
    if (required != NULL) *required = strlen(pTscObj->db) + 1;
278✔
1544
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
278✔
1545
  } else if (len < strlen(pTscObj->db) + 1) {
278✔
1546
    tstrncpy(database, pTscObj->db, len);
139✔
1547
    if (required) *required = strlen(pTscObj->db) + 1;
139✔
1548
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
139✔
1549
  } else {
1550
    tstrncpy(database, pTscObj->db, len);
139✔
1551
    code = 0;
139✔
1552
  }
1553
_return:
556✔
1554
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
556✔
1555
  releaseTscObj(*(int64_t *)taos);
556✔
1556
  return code;
556✔
1557
}
1558

1559
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
1,281,220,693✔
1560
  if (NULL == pWrapper) {
1,281,220,693✔
1561
    return;
642,984,248✔
1562
  }
1563
  destoryCatalogReq(pWrapper->pCatalogReq);
638,236,445✔
1564
  taosMemoryFree(pWrapper->pCatalogReq);
638,225,223✔
1565
  qDestroyParseContext(pWrapper->pParseCtx);
638,216,679✔
1566
  taosMemoryFree(pWrapper);
638,212,765✔
1567
}
1568

1569
void destroyCtxInRequest(SRequestObj *pRequest) {
2,578,105✔
1570
  schedulerFreeJob(&pRequest->body.queryJob, 0);
2,578,105✔
1571
  qDestroyQuery(pRequest->pQuery);
2,578,105✔
1572
  pRequest->pQuery = NULL;
2,578,105✔
1573
  destorySqlCallbackWrapper(pRequest->pWrapper);
2,578,105✔
1574
  pRequest->pWrapper = NULL;
2,578,105✔
1575
}
2,578,105✔
1576

1577
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
184,215,251✔
1578
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
184,215,251✔
1579
  SRequestObj         *pRequest = pWrapper->pRequest;
184,215,251✔
1580
  SQuery              *pQuery = pRequest->pQuery;
184,215,023✔
1581

1582
  qDebug("req:0x%" PRIx64 ", start to semantic analysis, QID:0x%" PRIx64, pRequest->self, pRequest->requestId);
184,218,935✔
1583

1584
  int64_t analyseStart = taosGetTimestampUs();
184,216,712✔
1585
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
184,216,712✔
1586
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
184,218,079✔
1587

1588
  if (TSDB_CODE_SUCCESS == code) {
184,214,918✔
1589
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
184,209,552✔
1590
  }
1591

1592
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
184,196,188✔
1593

1594
  if (pRequest->parseOnly) {
184,202,608✔
1595
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
291,780✔
1596
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
291,780✔
1597
  }
1598

1599
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
184,195,908✔
1600
}
184,193,804✔
1601

1602
int32_t cloneCatalogReq(SCatalogReq **ppTarget, SCatalogReq *pSrc) {
×
1603
  int32_t      code = TSDB_CODE_SUCCESS;
×
1604
  SCatalogReq *pTarget = taosMemoryCalloc(1, sizeof(SCatalogReq));
×
1605
  if (pTarget == NULL) {
×
1606
    code = terrno;
×
1607
  } else {
1608
    pTarget->pDbVgroup = taosArrayDup(pSrc->pDbVgroup, NULL);
×
1609
    pTarget->pDbCfg = taosArrayDup(pSrc->pDbCfg, NULL);
×
1610
    pTarget->pDbInfo = taosArrayDup(pSrc->pDbInfo, NULL);
×
1611
    pTarget->pTableMeta = taosArrayDup(pSrc->pTableMeta, NULL);
×
1612
    pTarget->pTableHash = taosArrayDup(pSrc->pTableHash, NULL);
×
1613
    pTarget->pUdf = taosArrayDup(pSrc->pUdf, NULL);
×
1614
    pTarget->pIndex = taosArrayDup(pSrc->pIndex, NULL);
×
1615
    pTarget->pUser = taosArrayDup(pSrc->pUser, NULL);
×
1616
    pTarget->pTableIndex = taosArrayDup(pSrc->pTableIndex, NULL);
×
1617
    pTarget->pTableCfg = taosArrayDup(pSrc->pTableCfg, NULL);
×
1618
    pTarget->pTableTag = taosArrayDup(pSrc->pTableTag, NULL);
×
1619
    pTarget->pView = taosArrayDup(pSrc->pView, NULL);
×
1620
    pTarget->pTableTSMAs = taosArrayDup(pSrc->pTableTSMAs, NULL);
×
1621
    pTarget->pTSMAs = taosArrayDup(pSrc->pTSMAs, NULL);
×
1622
    pTarget->pVStbRefDbs = taosArrayDup(pSrc->pVStbRefDbs, NULL);
×
1623
    pTarget->qNodeRequired = pSrc->qNodeRequired;
×
1624
    pTarget->dNodeRequired = pSrc->dNodeRequired;
×
1625
    pTarget->svrVerRequired = pSrc->svrVerRequired;
×
1626
    pTarget->forceUpdate = pSrc->forceUpdate;
×
1627
    pTarget->cloned = true;
×
1628

1629
    *ppTarget = pTarget;
×
1630
  }
1631

1632
  return code;
×
1633
}
1634

1635
void handleSubQueryFromAnalyse(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, SNode *pRoot) {
×
1636
  SRequestObj         *pNewRequest = NULL;
×
1637
  SSqlCallbackWrapper *pNewWrapper = NULL;
×
1638
  int32_t              code = buildPreviousRequest(pWrapper->pRequest, pWrapper->pRequest->sqlstr, &pNewRequest);
×
1639
  if (code) {
×
1640
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1641
    return;
×
1642
  }
1643

1644
  pNewRequest->pQuery = NULL;
×
1645
  code = nodesMakeNode(QUERY_NODE_QUERY, (SNode **)&pNewRequest->pQuery);
×
1646
  if (pNewRequest->pQuery) {
×
1647
    pNewRequest->pQuery->pRoot = pRoot;
×
1648
    pRoot = NULL;
×
1649
    pNewRequest->pQuery->execStage = QUERY_EXEC_STAGE_ANALYSE;
×
1650
  }
1651
  if (TSDB_CODE_SUCCESS == code) {
×
1652
    code = prepareAndParseSqlSyntax(&pNewWrapper, pNewRequest, false);
×
1653
  }
1654
  if (TSDB_CODE_SUCCESS == code) {
×
1655
    code = cloneCatalogReq(&pNewWrapper->pCatalogReq, pWrapper->pCatalogReq);
×
1656
  }
1657
  if (TSDB_CODE_SUCCESS == code) {
×
1658
    doAsyncQueryFromAnalyse(pResultMeta, pNewWrapper, code);
×
1659
    nodesDestroyNode(pRoot);
×
1660
  } else {
1661
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1662
    return;
×
1663
  }
1664
}
1665

1666
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
184,176,049✔
1667
  SRequestObj *pRequest = pWrapper->pRequest;
184,176,049✔
1668
  SQuery      *pQuery = pRequest->pQuery;
184,184,342✔
1669

1670
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
184,185,988✔
1671
    SNode *prevRoot = pQuery->pPrevRoot;
×
1672
    pQuery->pPrevRoot = NULL;
×
1673
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
×
1674
    return;
×
1675
  }
1676

1677
  if (code == TSDB_CODE_SUCCESS) {
184,185,823✔
1678
    pRequest->stableQuery = pQuery->stableQuery;
169,181,875✔
1679
    if (pQuery->pRoot) {
169,230,491✔
1680
      pRequest->stmtType = pQuery->pRoot->type;
169,176,339✔
1681
    }
1682

1683
    if (pQuery->haveResultSet) {
169,244,228✔
1684
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema,
82,083,056✔
1685
                              pRequest->stmtBindVersion > 0);
82,083,466✔
1686
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
82,084,972✔
1687
    }
1688
  }
1689

1690
  if (code == TSDB_CODE_SUCCESS) {
184,167,356✔
1691
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
169,200,905✔
1692
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
169,152,826✔
1693
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
169,181,175✔
1694

1695
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
169,149,432✔
1696
  } else {
1697
    destorySqlCallbackWrapper(pWrapper);
14,966,451✔
1698
    pRequest->pWrapper = NULL;
14,966,205✔
1699
    qDestroyQuery(pRequest->pQuery);
14,966,205✔
1700
    pRequest->pQuery = NULL;
14,966,451✔
1701

1702
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
14,966,451✔
1703
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
2,534,653✔
1704
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1705
      restartAsyncQuery(pRequest, code);
2,534,653✔
1706
      return;
2,534,653✔
1707
    }
1708

1709
    // return to app directly
1710
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self,
12,431,798✔
1711
             tstrerror(code), pRequest->requestId);
1712
    pRequest->code = code;
12,431,798✔
1713
    returnToUser(pRequest);
12,431,798✔
1714
  }
1715
}
1716

1717
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
193,939,648✔
1718
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
386,805,138✔
1719
                           .requestId = pWrapper->pParseCtx->requestId,
193,935,089✔
1720
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
193,932,327✔
1721
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
193,924,610✔
1722

1723
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
386,791,158✔
1724

1725
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
194,982,054✔
1726
                                &pWrapper->pRequest->body.queryJob);
193,914,836✔
1727
}
1728

1729
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1730

1731
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
642,574,201✔
1732
  int32_t code = TSDB_CODE_SUCCESS;
642,574,201✔
1733
  switch (pWrapper->pRequest->pQuery->execStage) {
642,574,201✔
1734
    case QUERY_EXEC_STAGE_PARSE: {
9,738,752✔
1735
      // continue parse after get metadata
1736
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
9,738,752✔
1737
      break;
9,738,752✔
1738
    }
1739
    case QUERY_EXEC_STAGE_ANALYSE: {
184,195,594✔
1740
      // analysis after get metadata
1741
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
184,195,594✔
1742
      break;
184,209,709✔
1743
    }
1744
    case QUERY_EXEC_STAGE_SCHEDULE: {
448,639,588✔
1745
      launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper);
448,639,588✔
1746
      break;
448,637,630✔
1747
    }
1748
    default:
2✔
1749
      break;
2✔
1750
  }
1751
  return code;
642,586,020✔
1752
}
1753

1754
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
9,738,752✔
1755
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
9,738,752✔
1756
  SRequestObj         *pRequest = pWrapper->pRequest;
9,738,752✔
1757
  SQuery              *pQuery = pRequest->pQuery;
9,738,752✔
1758

1759
  pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart;
9,738,752✔
1760
  qDebug("req:0x%" PRIx64 ", continue parse query, QID:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId,
9,738,752✔
1761
         tstrerror(code));
1762

1763
  if (code == TSDB_CODE_SUCCESS) {
9,738,752✔
1764
    // pWrapper->pCatalogReq->forceUpdate = false;
1765
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
9,720,564✔
1766
  }
1767

1768
  if (TSDB_CODE_SUCCESS == code) {
9,738,752✔
1769
    code = phaseAsyncQuery(pWrapper);
9,251,229✔
1770
  }
1771

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

1783
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
11,694✔
1784
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
11,694✔
1785
  if (TSDB_CODE_SUCCESS == code) {
11,694✔
1786
    code = phaseAsyncQuery(pWrapper);
11,694✔
1787
  }
1788

1789
  if (TSDB_CODE_SUCCESS != code) {
11,694✔
1790
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
×
1791
             tstrerror(code), pWrapper->pRequest->requestId);
1792
    destorySqlCallbackWrapper(pWrapper);
×
1793
    pRequest->pWrapper = NULL;
×
1794
    terrno = code;
×
1795
    pRequest->code = code;
×
1796
    doRequestCallback(pRequest, code);
×
1797
  }
1798
}
11,694✔
1799

1800
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
38,594✔
1801
  int64_t connId = *(int64_t *)taos;
38,594✔
1802
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
38,594✔
1803
}
38,594✔
1804

1805
void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) {
×
1806
  int64_t connId = *(int64_t *)taos;
×
1807
  taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid);
×
1808
}
×
1809

1810
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
638,238,812✔
1811
  const STscObj *pTscObj = pRequest->pTscObj;
638,238,812✔
1812

1813
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
638,241,277✔
1814
  if (*pCxt == NULL) {
638,241,029✔
1815
    return terrno;
×
1816
  }
1817

1818
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
1,273,307,298✔
1819
                           .requestRid = pRequest->self,
638,242,129✔
1820
                           .acctId = pTscObj->acctId,
638,242,506✔
1821
                           .db = pRequest->pDb,
638,242,505✔
1822
                           .topicQuery = false,
1823
                           .pSql = pRequest->sqlstr,
638,242,765✔
1824
                           .sqlLen = pRequest->sqlLen,
638,242,765✔
1825
                           .pMsg = pRequest->msgBuf,
638,241,119✔
1826
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
1827
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
638,242,679✔
1828
                           .pStmtCb = NULL,
1829
                           .pUser = pTscObj->user,
638,241,780✔
1830
                           .pEffectiveUser = pRequest->effectiveUser,
638,240,369✔
1831
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
638,239,941✔
1832
                           .enableSysInfo = pTscObj->sysInfo,
638,239,659✔
1833
                           .async = true,
1834
                           .svrVer = pTscObj->sVer,
638,240,095✔
1835
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
638,241,521✔
1836
                           .allocatorId = pRequest->allocatorRefId,
638,240,664✔
1837
                           .parseSqlFp = clientParseSql,
1838
                           .parseSqlParam = pWrapper,
1839
                           .setQueryFp = setQueryRequest,
1840
                           .timezone = pTscObj->optionInfo.timezone,
638,237,929✔
1841
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
638,236,649✔
1842
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
638,239,705✔
1843
  (*pCxt)->biMode = biMode;
638,236,825✔
1844
  return TSDB_CODE_SUCCESS;
638,239,879✔
1845
}
1846

1847
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
638,242,915✔
1848
  int32_t              code = TSDB_CODE_SUCCESS;
638,242,915✔
1849
  STscObj             *pTscObj = pRequest->pTscObj;
638,242,915✔
1850
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
638,243,396✔
1851
  if (pWrapper == NULL) {
638,242,123✔
1852
    code = terrno;
×
1853
  } else {
1854
    pWrapper->pRequest = pRequest;
638,242,123✔
1855
    pRequest->pWrapper = pWrapper;
638,241,864✔
1856
    *ppWrapper = pWrapper;
638,240,879✔
1857
  }
1858

1859
  if (TSDB_CODE_SUCCESS == code) {
638,239,936✔
1860
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
638,239,710✔
1861
  }
1862

1863
  if (TSDB_CODE_SUCCESS == code) {
638,238,491✔
1864
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
638,238,491✔
1865
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
638,239,506✔
1866
  }
1867

1868
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
638,233,758✔
1869
    int64_t syntaxStart = taosGetTimestampUs();
638,238,798✔
1870

1871
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
638,238,798✔
1872
    if (pWrapper->pCatalogReq == NULL) {
638,222,571✔
1873
      code = terrno;
×
1874
    } else {
1875
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
638,222,747✔
1876
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
638,228,877✔
1877
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
638,228,412✔
1878
    }
1879

1880
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
638,222,660✔
1881
  }
1882

1883
  return code;
638,233,186✔
1884
}
1885

1886
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
639,088,254✔
1887
  SSqlCallbackWrapper *pWrapper = NULL;
639,088,254✔
1888
  int32_t              code = TSDB_CODE_SUCCESS;
639,088,254✔
1889

1890
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
639,088,254✔
1891
    code = pRequest->prevCode;
844,858✔
1892
    terrno = code;
844,858✔
1893
    pRequest->code = code;
844,858✔
1894
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
844,858✔
1895
    doRequestCallback(pRequest, code);
844,858✔
1896
    return;
844,858✔
1897
  }
1898

1899
  if (TSDB_CODE_SUCCESS == code) {
638,243,396✔
1900
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
638,243,396✔
1901
  }
1902

1903
  if (TSDB_CODE_SUCCESS == code) {
638,221,739✔
1904
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
633,320,437✔
1905
    code = phaseAsyncQuery(pWrapper);
633,322,406✔
1906
  }
1907

1908
  if (TSDB_CODE_SUCCESS != code) {
638,231,238✔
1909
    if (NULL != pRequest->msgBuf && strlen(pRequest->msgBuf) > 0) {
4,905,863✔
1910
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, pRequest->msgBuf,
4,783,315✔
1911
               pRequest->requestId);
1912
    } else {
1913
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
122,548✔
1914
               pRequest->requestId);
1915
    }
1916

1917
    destorySqlCallbackWrapper(pWrapper);
4,905,863✔
1918
    pRequest->pWrapper = NULL;
4,905,863✔
1919
    qDestroyQuery(pRequest->pQuery);
4,905,863✔
1920
    pRequest->pQuery = NULL;
4,905,863✔
1921

1922
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
4,905,863✔
1923
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
11,143✔
1924
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1925
      code = refreshMeta(pRequest->pTscObj, pRequest);
11,143✔
1926
      if (code != 0) {
11,143✔
1927
        tscWarn("req:0x%" PRIx64 ", refresh meta failed, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code,
11,143✔
1928
                tstrerror(code), pRequest->requestId);
1929
      }
1930
      pRequest->prevCode = code;
11,143✔
1931
      doAsyncQuery(pRequest, true);
11,143✔
1932
      return;
11,143✔
1933
    }
1934

1935
    terrno = code;
4,894,720✔
1936
    pRequest->code = code;
4,894,720✔
1937
    doRequestCallback(pRequest, code);
4,894,720✔
1938
  }
1939
}
1940

1941
void restartAsyncQuery(SRequestObj *pRequest, int32_t code) {
2,578,105✔
1942
  tscInfo("restart request:%s p:%p", pRequest->sqlstr, pRequest);
2,578,105✔
1943
  SRequestObj *pUserReq = pRequest;
2,578,105✔
1944
  (void)acquireRequest(pRequest->self);
2,578,105✔
1945
  while (pUserReq) {
2,578,105✔
1946
    if (pUserReq->self == pUserReq->relation.userRefId || pUserReq->relation.userRefId == 0) {
2,578,105✔
1947
      break;
1948
    } else {
1949
      int64_t nextRefId = pUserReq->relation.nextRefId;
×
1950
      (void)releaseRequest(pUserReq->self);
×
1951
      if (nextRefId) {
×
1952
        pUserReq = acquireRequest(nextRefId);
×
1953
      }
1954
    }
1955
  }
1956
  bool hasSubRequest = pUserReq != pRequest || pRequest->relation.prevRefId != 0;
2,578,105✔
1957
  if (pUserReq) {
2,578,105✔
1958
    destroyCtxInRequest(pUserReq);
2,578,105✔
1959
    pUserReq->prevCode = code;
2,578,105✔
1960
    (void)memset(&pUserReq->relation, 0, sizeof(pUserReq->relation));
2,578,105✔
1961
  } else {
1962
    tscError("User req is missing");
×
1963
    (void)removeFromMostPrevReq(pRequest);
×
1964
    return;
×
1965
  }
1966
  if (hasSubRequest)
2,578,105✔
1967
    (void)removeFromMostPrevReq(pRequest);
×
1968
  else
1969
    (void)releaseRequest(pUserReq->self);
2,578,105✔
1970
  doAsyncQuery(pUserReq, true);
2,578,105✔
1971
}
1972

1973
typedef struct SAsyncFetchParam {
1974
  SRequestObj      *pReq;
1975
  __taos_async_fn_t fp;
1976
  void             *param;
1977
} SAsyncFetchParam;
1978

1979
static int32_t doAsyncFetch(void *pParam) {
93,087,767✔
1980
  SAsyncFetchParam *param = pParam;
93,087,767✔
1981
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
93,087,767✔
1982
  taosMemoryFree(param);
93,087,767✔
1983
  return TSDB_CODE_SUCCESS;
93,087,061✔
1984
}
1985

1986
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
93,089,908✔
1987
  if (res == NULL || fp == NULL) {
93,089,908✔
1988
    tscError("taos_fetch_rows_a invalid paras");
×
1989
    return;
×
1990
  }
1991
  if (!TD_RES_QUERY(res)) {
93,090,357✔
1992
    tscError("taos_fetch_rows_a res is NULL");
×
1993
    fp(param, res, TSDB_CODE_APP_ERROR);
×
1994
    return;
×
1995
  }
1996

1997
  SRequestObj *pRequest = res;
93,090,296✔
1998
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
93,090,296✔
1999
    fp(param, res, 0);
2,980✔
2000
    return;
2,980✔
2001
  }
2002

2003
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
93,087,121✔
2004
  if (!pParam) {
93,086,960✔
2005
    fp(param, res, terrno);
×
2006
    return;
×
2007
  }
2008
  pParam->pReq = pRequest;
93,086,960✔
2009
  pParam->fp = fp;
93,086,926✔
2010
  pParam->param = param;
93,087,182✔
2011
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
93,086,987✔
2012
  if (TSDB_CODE_SUCCESS != code) {
93,087,519✔
2013
    taosMemoryFree(pParam);
×
2014
    fp(param, res, code);
×
2015
    return;
×
2016
  }
2017
}
2018

2019
void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
442✔
2020
  if (res == NULL || fp == NULL) {
442✔
2021
    tscError("taos_fetch_raw_block_a invalid paras");
×
2022
    return;
×
2023
  }
2024
  if (!TD_RES_QUERY(res)) {
442✔
2025
    tscError("taos_fetch_raw_block_a res is NULL");
×
2026
    return;
×
2027
  }
2028
  SRequestObj    *pRequest = res;
442✔
2029
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
442✔
2030

2031
  // set the current block is all consumed
2032
  pResultInfo->convertUcs4 = false;
442✔
2033

2034
  // it is a local executed query, no need to do async fetch
2035
  taos_fetch_rows_a(pRequest, fp, param);
442✔
2036
}
2037

2038
const void *taos_get_raw_block(TAOS_RES *res) {
260✔
2039
  if (res == NULL) {
260✔
2040
    tscError("taos_get_raw_block invalid paras");
×
2041
    return NULL;
×
2042
  }
2043
  if (!TD_RES_QUERY(res)) {
260✔
2044
    tscError("taos_get_raw_block res is NULL");
×
2045
    return NULL;
×
2046
  }
2047
  SRequestObj *pRequest = res;
260✔
2048

2049
  return pRequest->body.resInfo.pData;
260✔
2050
}
2051

2052
int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInfo) {
×
2053
  if (NULL == taos) {
×
2054
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2055
    return terrno;
×
2056
  }
2057

2058
  if (NULL == db || NULL == dbInfo) {
×
2059
    tscError("invalid input param, db:%p, dbInfo:%p", db, dbInfo);
×
2060
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2061
    return terrno;
×
2062
  }
2063

2064
  int64_t      connId = *(int64_t *)taos;
×
2065
  SRequestObj *pRequest = NULL;
×
2066
  char        *sql = "taos_get_db_route_info";
×
2067
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2068
  if (code != TSDB_CODE_SUCCESS) {
×
2069
    terrno = code;
×
2070
    return terrno;
×
2071
  }
2072

2073
  STscObj  *pTscObj = pRequest->pTscObj;
×
2074
  SCatalog *pCtg = NULL;
×
2075
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2076
  if (code != TSDB_CODE_SUCCESS) {
×
2077
    goto _return;
×
2078
  }
2079

2080
  SRequestConnInfo conn = {
×
2081
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2082

2083
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2084

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

2088
  code = catalogGetDBVgInfo(pCtg, &conn, dbFName, dbInfo);
×
2089
  if (code) {
×
2090
    goto _return;
×
2091
  }
2092

2093
_return:
×
2094

2095
  terrno = code;
×
2096

2097
  destroyRequest(pRequest);
×
2098
  return code;
×
2099
}
2100

2101
int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId) {
×
2102
  if (NULL == taos) {
×
2103
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2104
    return terrno;
×
2105
  }
2106

2107
  if (NULL == db || NULL == table || NULL == vgId) {
×
2108
    tscError("invalid input param, db:%p, table:%p, vgId:%p", db, table, vgId);
×
2109
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2110
    return terrno;
×
2111
  }
2112

2113
  int64_t      connId = *(int64_t *)taos;
×
2114
  SRequestObj *pRequest = NULL;
×
2115
  char        *sql = "taos_get_table_vgId";
×
2116
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2117
  if (code != TSDB_CODE_SUCCESS) {
×
2118
    return terrno;
×
2119
  }
2120

2121
  pRequest->syncQuery = true;
×
2122

2123
  STscObj  *pTscObj = pRequest->pTscObj;
×
2124
  SCatalog *pCtg = NULL;
×
2125
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2126
  if (code != TSDB_CODE_SUCCESS) {
×
2127
    goto _return;
×
2128
  }
2129

2130
  SRequestConnInfo conn = {
×
2131
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2132

2133
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2134

2135
  SName tableName = {0};
×
2136
  toName(pTscObj->acctId, db, table, &tableName);
×
2137

2138
  SVgroupInfo vgInfo;
×
2139
  code = catalogGetTableHashVgroup(pCtg, &conn, &tableName, &vgInfo);
×
2140
  if (code) {
×
2141
    goto _return;
×
2142
  }
2143

2144
  *vgId = vgInfo.vgId;
×
2145

2146
_return:
×
2147

2148
  terrno = code;
×
2149

2150
  destroyRequest(pRequest);
×
2151
  return code;
×
2152
}
2153

2154
int taos_get_tables_vgId(TAOS *taos, const char *db, const char *table[], int tableNum, int *vgId) {
×
2155
  if (NULL == taos) {
×
2156
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2157
    return terrno;
×
2158
  }
2159

2160
  if (NULL == db || NULL == table || NULL == vgId || tableNum <= 0) {
×
2161
    tscError("invalid input param, db:%p, table:%p, vgId:%p, tbNum:%d", db, table, vgId, tableNum);
×
2162
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2163
    return terrno;
×
2164
  }
2165

2166
  int64_t      connId = *(int64_t *)taos;
×
2167
  SRequestObj *pRequest = NULL;
×
2168
  char        *sql = "taos_get_table_vgId";
×
2169
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2170
  if (code != TSDB_CODE_SUCCESS) {
×
2171
    return terrno;
×
2172
  }
2173

2174
  pRequest->syncQuery = true;
×
2175

2176
  STscObj  *pTscObj = pRequest->pTscObj;
×
2177
  SCatalog *pCtg = NULL;
×
2178
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2179
  if (code != TSDB_CODE_SUCCESS) {
×
2180
    goto _return;
×
2181
  }
2182

2183
  SRequestConnInfo conn = {
×
2184
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2185

2186
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2187

2188
  code = catalogGetTablesHashVgId(pCtg, &conn, pTscObj->acctId, db, table, tableNum, vgId);
×
2189
  if (code) {
×
2190
    goto _return;
×
2191
  }
2192

2193
_return:
×
2194

2195
  terrno = code;
×
2196

2197
  destroyRequest(pRequest);
×
2198
  return code;
×
2199
}
2200

2201
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
1,252✔
2202
  if (NULL == taos) {
1,252✔
2203
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2204
    return terrno;
×
2205
  }
2206

2207
  int64_t       connId = *(int64_t *)taos;
1,252✔
2208
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
1,252✔
2209
  int32_t       code = 0;
1,252✔
2210
  SRequestObj  *pRequest = NULL;
1,252✔
2211
  SCatalogReq   catalogReq = {0};
1,252✔
2212

2213
  if (NULL == tableNameList) {
1,252✔
2214
    return TSDB_CODE_SUCCESS;
×
2215
  }
2216

2217
  int32_t length = (int32_t)strlen(tableNameList);
1,252✔
2218
  if (0 == length) {
1,252✔
2219
    return TSDB_CODE_SUCCESS;
×
2220
  } else if (length > MAX_TABLE_NAME_LENGTH) {
1,252✔
2221
    tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH);
×
2222
    return TSDB_CODE_TSC_INVALID_OPERATION;
×
2223
  }
2224

2225
  char *sql = "taos_load_table_info";
1,252✔
2226
  code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
1,252✔
2227
  if (code != TSDB_CODE_SUCCESS) {
1,252✔
2228
    terrno = code;
×
2229
    goto _return;
×
2230
  }
2231

2232
  pRequest->syncQuery = true;
1,252✔
2233

2234
  STscObj *pTscObj = pRequest->pTscObj;
1,252✔
2235
  code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
1,252✔
2236
  if (code) {
1,252✔
2237
    goto _return;
×
2238
  }
2239

2240
  SCatalog *pCtg = NULL;
1,252✔
2241
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
1,252✔
2242
  if (code != TSDB_CODE_SUCCESS) {
1,252✔
2243
    goto _return;
×
2244
  }
2245

2246
  SRequestConnInfo conn = {
1,252✔
2247
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
1,252✔
2248

2249
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
1,252✔
2250

2251
  code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, pRequest->body.interParam, NULL);
1,252✔
2252
  if (code) {
1,252✔
2253
    goto _return;
×
2254
  }
2255

2256
  SSyncQueryParam *pParam = pRequest->body.interParam;
1,252✔
2257
  code = tsem_wait(&pParam->sem);
1,252✔
2258
  if (code) {
1,252✔
2259
    tscError("tsem wait failed, code:%d - %s", code, tstrerror(code));
×
2260
    goto _return;
×
2261
  }
2262
_return:
1,252✔
2263
  destoryCatalogReq(&catalogReq);
1,252✔
2264
  destroyRequest(pRequest);
1,252✔
2265
  return code;
1,252✔
2266
}
2267

2268
TAOS_STMT *taos_stmt_init(TAOS *taos) {
321,983✔
2269
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
321,983✔
2270
  if (NULL == pObj) {
322,440✔
2271
    tscError("invalid parameter for %s", __FUNCTION__);
×
2272
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2273
    return NULL;
×
2274
  }
2275

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

2282
  return pStmt;
322,440✔
2283
}
2284

2285
TAOS_STMT *taos_stmt_init_with_reqid(TAOS *taos, int64_t reqid) {
×
2286
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
2287
  if (NULL == pObj) {
×
2288
    tscError("invalid parameter for %s", __FUNCTION__);
×
2289
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2290
    return NULL;
×
2291
  }
2292

2293
  TAOS_STMT *pStmt = stmtInit(pObj, reqid, NULL);
×
2294
  if (NULL == pStmt) {
×
2295
    tscError("stmt init failed, errcode:%s", terrstr());
×
2296
  }
2297
  releaseTscObj(*(int64_t *)taos);
×
2298

2299
  return pStmt;
×
2300
}
2301

2302
TAOS_STMT *taos_stmt_init_with_options(TAOS *taos, TAOS_STMT_OPTIONS *options) {
18,705✔
2303
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
18,705✔
2304
  if (NULL == pObj) {
18,705✔
2305
    tscError("invalid parameter for %s", __FUNCTION__);
×
2306
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2307
    return NULL;
×
2308
  }
2309

2310
  TAOS_STMT *pStmt = stmtInit(pObj, options->reqId, options);
18,705✔
2311
  if (NULL == pStmt) {
18,705✔
2312
    tscError("stmt init failed, errcode:%s", terrstr());
×
2313
  }
2314
  releaseTscObj(*(int64_t *)taos);
18,705✔
2315

2316
  return pStmt;
18,705✔
2317
}
2318

2319
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
680,437✔
2320
  if (stmt == NULL || sql == NULL) {
680,437✔
2321
    tscError("NULL parameter for %s", __FUNCTION__);
×
2322
    terrno = TSDB_CODE_INVALID_PARA;
×
2323
    return terrno;
×
2324
  }
2325

2326
  return stmtPrepare(stmt, sql, length);
680,716✔
2327
}
2328

2329
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
7,334✔
2330
  if (stmt == NULL || name == NULL) {
7,334✔
2331
    tscError("NULL parameter for %s", __FUNCTION__);
×
2332
    terrno = TSDB_CODE_INVALID_PARA;
×
2333
    return terrno;
×
2334
  }
2335

2336
  int32_t code = stmtSetTbName(stmt, name);
7,334✔
2337
  if (code) {
7,334✔
2338
    return code;
626✔
2339
  }
2340

2341
  if (tags) {
6,708✔
2342
    return stmtSetTbTags(stmt, tags);
6,708✔
2343
  }
2344

2345
  return TSDB_CODE_SUCCESS;
×
2346
}
2347

2348
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
12,663,706✔
2349
  if (stmt == NULL || name == NULL) {
12,663,706✔
2350
    tscError("NULL parameter for %s", __FUNCTION__);
230✔
2351
    terrno = TSDB_CODE_INVALID_PARA;
230✔
2352
    return terrno;
×
2353
  }
2354

2355
  return stmtSetTbName(stmt, name);
12,663,720✔
2356
}
2357

2358
int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) {
572✔
2359
  if (stmt == NULL || tags == NULL) {
572✔
2360
    tscError("NULL parameter for %s", __FUNCTION__);
×
2361
    terrno = TSDB_CODE_INVALID_PARA;
×
2362
    return terrno;
×
2363
  }
2364

2365
  return stmtSetTbTags(stmt, tags);
572✔
2366
}
2367

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

2370
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
×
2371
  if (stmt == NULL || NULL == fieldNum) {
×
2372
    tscError("NULL parameter for %s", __FUNCTION__);
×
2373
    terrno = TSDB_CODE_INVALID_PARA;
×
2374
    return terrno;
×
2375
  }
2376

2377
  return stmtGetTagFields(stmt, fieldNum, fields);
×
2378
}
2379

2380
int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
×
2381
  if (stmt == NULL || NULL == fieldNum) {
×
2382
    tscError("NULL parameter for %s", __FUNCTION__);
×
2383
    terrno = TSDB_CODE_INVALID_PARA;
×
2384
    return terrno;
×
2385
  }
2386

2387
  return stmtGetColFields(stmt, fieldNum, fields);
×
2388
}
2389

2390
// let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields`
2391
void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) {
×
2392
  (void)stmt;
2393
  if (!fields) return;
×
2394
  taosMemoryFree(fields);
×
2395
}
2396

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

2404
  if (bind->num > 1) {
33,008✔
2405
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
4,032✔
2406
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
4,032✔
2407
    return terrno;
4,032✔
2408
  }
2409

2410
  return stmtBindBatch(stmt, bind, -1);
28,976✔
2411
}
2412

2413
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
476,337,007✔
2414
  if (stmt == NULL || bind == NULL) {
476,337,007✔
2415
    tscError("NULL parameter for %s", __FUNCTION__);
×
2416
    terrno = TSDB_CODE_INVALID_PARA;
×
2417
    return terrno;
×
2418
  }
2419

2420
  if (bind->num <= 0 || bind->num > INT16_MAX) {
485,977,596✔
UNCOV
2421
    tscError("invalid bind num %d", bind->num);
×
UNCOV
2422
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2423
    return terrno;
×
2424
  }
2425

2426
  int32_t insert = 0;
488,754,308✔
2427
  int32_t code = stmtIsInsert(stmt, &insert);
486,702,381✔
2428
  if (TSDB_CODE_SUCCESS != code) {
484,995,979✔
2429
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2430
    return code;
×
2431
  }
2432
  if (0 == insert && bind->num > 1) {
484,995,979✔
2433
    tscError("only one row data allowed for query");
×
2434
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2435
    return terrno;
×
2436
  }
2437

2438
  return stmtBindBatch(stmt, bind, -1);
484,995,979✔
2439
}
2440

2441
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
3,220✔
2442
  if (stmt == NULL || bind == NULL) {
3,220✔
2443
    tscError("NULL parameter for %s", __FUNCTION__);
×
2444
    terrno = TSDB_CODE_INVALID_PARA;
×
2445
    return terrno;
×
2446
  }
2447

2448
  if (colIdx < 0) {
3,220✔
2449
    tscError("invalid bind column idx %d", colIdx);
×
2450
    terrno = TSDB_CODE_INVALID_PARA;
×
2451
    return terrno;
×
2452
  }
2453

2454
  int32_t insert = 0;
3,220✔
2455
  int32_t code = stmtIsInsert(stmt, &insert);
3,220✔
2456
  if (TSDB_CODE_SUCCESS != code) {
3,220✔
2457
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2458
    return code;
×
2459
  }
2460
  if (0 == insert && bind->num > 1) {
3,220✔
2461
    tscError("only one row data allowed for query");
×
2462
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2463
    return terrno;
×
2464
  }
2465

2466
  return stmtBindBatch(stmt, bind, colIdx);
3,220✔
2467
}
2468

2469
int taos_stmt_add_batch(TAOS_STMT *stmt) {
463,971,788✔
2470
  if (stmt == NULL) {
463,971,788✔
2471
    tscError("NULL parameter for %s", __FUNCTION__);
×
2472
    terrno = TSDB_CODE_INVALID_PARA;
×
2473
    return terrno;
×
2474
  }
2475

2476
  return stmtAddBatch(stmt);
463,971,788✔
2477
}
2478

2479
int taos_stmt_execute(TAOS_STMT *stmt) {
3,986,520✔
2480
  if (stmt == NULL) {
3,986,520✔
2481
    tscError("NULL parameter for %s", __FUNCTION__);
×
2482
    terrno = TSDB_CODE_INVALID_PARA;
×
2483
    return terrno;
×
2484
  }
2485

2486
  return stmtExec(stmt);
3,986,520✔
2487
}
2488

2489
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
×
2490
  if (stmt == NULL || insert == NULL) {
×
2491
    tscError("NULL parameter for %s", __FUNCTION__);
×
2492
    terrno = TSDB_CODE_INVALID_PARA;
×
2493
    return terrno;
×
2494
  }
2495

2496
  return stmtIsInsert(stmt, insert);
×
2497
}
2498

2499
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
×
2500
  if (stmt == NULL || nums == NULL) {
×
2501
    tscError("NULL parameter for %s", __FUNCTION__);
×
2502
    terrno = TSDB_CODE_INVALID_PARA;
×
2503
    return terrno;
×
2504
  }
2505

2506
  return stmtGetParamNum(stmt, nums);
×
2507
}
2508

2509
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
×
2510
  if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) {
×
2511
    tscError("invalid parameter for %s", __FUNCTION__);
×
2512
    terrno = TSDB_CODE_INVALID_PARA;
×
2513
    return terrno;
×
2514
  }
2515

2516
  return stmtGetParam(stmt, idx, type, bytes);
×
2517
}
2518

2519
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
10,342✔
2520
  if (stmt == NULL) {
10,342✔
2521
    tscError("NULL parameter for %s", __FUNCTION__);
×
2522
    terrno = TSDB_CODE_INVALID_PARA;
×
2523
    return NULL;
×
2524
  }
2525

2526
  return stmtUseResult(stmt);
10,342✔
2527
}
2528

2529
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
10,574✔
2530

2531
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
2,840✔
2532
  if (stmt == NULL) {
2,840✔
2533
    tscError("NULL parameter for %s", __FUNCTION__);
×
2534
    terrno = TSDB_CODE_INVALID_PARA;
×
2535
    return 0;
×
2536
  }
2537

2538
  return stmtAffectedRows(stmt);
2,840✔
2539
}
2540

2541
int taos_stmt_affected_rows_once(TAOS_STMT *stmt) {
280✔
2542
  if (stmt == NULL) {
280✔
2543
    tscError("NULL parameter for %s", __FUNCTION__);
×
2544
    terrno = TSDB_CODE_INVALID_PARA;
×
2545
    return 0;
×
2546
  }
2547

2548
  return stmtAffectedRowsOnce(stmt);
280✔
2549
}
2550

2551
int taos_stmt_close(TAOS_STMT *stmt) {
339,637✔
2552
  if (stmt == NULL) {
339,637✔
2553
    tscError("NULL parameter for %s", __FUNCTION__);
×
2554
    terrno = TSDB_CODE_INVALID_PARA;
×
2555
    return terrno;
×
2556
  }
2557

2558
  return stmtClose(stmt);
339,637✔
2559
}
2560

2561
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
15,566✔
2562
  if (NULL == taos) {
15,566✔
2563
    tscError("NULL parameter for %s", __FUNCTION__);
×
2564
    terrno = TSDB_CODE_INVALID_PARA;
×
2565
    return NULL;
×
2566
  }
2567
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
15,566✔
2568
  if (NULL == pObj) {
15,566✔
2569
    tscError("invalid parameter for %s", __FUNCTION__);
×
2570
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2571
    return NULL;
×
2572
  }
2573

2574
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
15,566✔
2575

2576
  releaseTscObj(*(int64_t *)taos);
15,566✔
2577

2578
  return pStmt;
15,566✔
2579
}
2580

2581
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
15,559✔
2582
  if (stmt == NULL || sql == NULL) {
15,559✔
2583
    tscError("NULL parameter for %s", __FUNCTION__);
×
2584
    terrno = TSDB_CODE_INVALID_PARA;
×
2585
    return terrno;
×
2586
  }
2587

2588
  return stmtPrepare2(stmt, sql, length);
15,559✔
2589
}
2590

2591
int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx) {
1,876,164✔
2592
  if (stmt == NULL) {
1,876,164✔
2593
    tscError("NULL parameter for %s", __FUNCTION__);
×
2594
    terrno = TSDB_CODE_INVALID_PARA;
×
2595
    return terrno;
×
2596
  }
2597

2598
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
1,876,164✔
2599
  int32_t    code = TSDB_CODE_SUCCESS;
1,876,164✔
2600
  STMT2_DLOG_E("start to bind param");
1,876,164✔
2601

2602
  // check query bind number
2603
  bool isQuery = (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt)));
1,876,282✔
2604
  if (isQuery) {
1,876,536✔
2605
    if (bindv->count != 1 || bindv->bind_cols[0]->num != 1) {
28✔
2606
      terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2607
      STMT2_ELOG_E("query only support one table and one row bind");
×
2608
      return terrno;
×
2609
    }
2610
  }
2611

2612
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 1) {
1,876,536✔
2613
    STMT2_ELOG_E("async bind param is still working, please try again later");
120✔
2614
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
120✔
2615
    return terrno;
×
2616
  }
2617

2618
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
1,877,047✔
2619
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
×
2620
      STMT2_ELOG_E("bind param wait asyncExecSem failed");
×
2621
    }
2622
    pStmt->execSemWaited = true;
×
2623
  }
2624

2625
  for (int i = 0; i < bindv->count; ++i) {
5,473,339✔
2626
    SVCreateTbReq *pCreateTbReq = NULL;
3,594,236✔
2627
    if (!isQuery) {
3,594,744✔
2628
      STMT2_TLOG("start to bind %dth table", i);
3,594,729✔
2629
      if (bindv->tbnames && bindv->tbnames[i]) {
3,595,086✔
2630
        code = stmtSetTbName2(stmt, bindv->tbnames[i]);
3,594,984✔
2631
        if (code) {
3,594,598✔
2632
          terrno = code;
×
2633
          STMT2_ELOG("set tbname failed, code:%s", tstrerror(code));
×
2634
          return terrno;
×
2635
        }
2636
      }
2637

2638
      if (bindv->tags && bindv->tags[i]) {
3,593,938✔
2639
        code = stmtSetTbTags2(stmt, bindv->tags[i], &pCreateTbReq);
1,212,484✔
2640
      } else if (pStmt->bInfo.tbNameFlag & IS_FIXED_TAG) {
2,382,725✔
2641
        code = stmtCheckTags2(stmt, &pCreateTbReq);
247,721✔
2642
      } else if (pStmt->sql.autoCreateTbl) {
2,134,496✔
2643
        code = stmtSetTbTags2(stmt, NULL, &pCreateTbReq);
×
2644
      }
2645

2646
      if (code) {
3,594,988✔
2647
        terrno = code;
×
2648
        STMT2_ELOG("set tags failed, code:%s", tstrerror(code));
×
2649
        return terrno;
×
2650
      }
2651
    }
2652

2653
    if (bindv->bind_cols && bindv->bind_cols[i]) {
3,595,003✔
2654
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
3,595,765✔
2655

2656
      if (bind->num <= 0 || bind->num > INT16_MAX) {
3,595,511✔
2657
        STMT2_ELOG("bind num:%d must > 0 and < INT16_MAX", bind->num);
547✔
2658
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
547✔
2659
        return terrno;
×
2660
      }
2661

2662
      code = stmtBindBatch2(stmt, bind, col_idx, pCreateTbReq);
3,594,456✔
2663
      if (TSDB_CODE_SUCCESS != code) {
3,595,784✔
2664
        terrno = code;
×
2665
        STMT2_ELOG("bind batch failed, code:%s", tstrerror(code));
×
2666
        return terrno;
×
2667
      }
2668
    }
2669
  }
2670

2671
  return code;
1,879,103✔
2672
}
2673

2674
int taos_stmt2_bind_param_a(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx, __taos_async_fn_t fp,
×
2675
                            void *param) {
2676
  if (stmt == NULL || bindv == NULL || fp == NULL) {
×
2677
    terrno = TSDB_CODE_INVALID_PARA;
×
2678
    return terrno;
×
2679
  }
2680

2681
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
×
2682

2683
  ThreadArgs *args = (ThreadArgs *)taosMemoryMalloc(sizeof(ThreadArgs));
×
2684
  args->stmt = stmt;
×
2685
  args->bindv = bindv;
×
2686
  args->col_idx = col_idx;
×
2687
  args->fp = fp;
×
2688
  args->param = param;
×
2689

2690
  (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2691
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 0) {
×
2692
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2693
    tscError("async bind param is still working, please try again later");
×
2694
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
×
2695
    return terrno;
×
2696
  }
2697
  (void)atomic_add_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2698
  (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2699

2700
  int code_s = taosStmt2AsyncBind(stmtAsyncBindThreadFunc, (void *)args);
×
2701
  if (code_s != TSDB_CODE_SUCCESS) {
×
2702
    terrno = code_s;
×
2703
    (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2704
    (void)taosThreadCondSignal(&(pStmt->asyncBindParam.waitCond));
×
2705
    (void)atomic_sub_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2706
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2707
    tscError("async bind failed, code:%d , %s", code_s, tstrerror(code_s));
×
2708
  }
2709

2710
  return code_s;
×
2711
}
2712

2713
int taos_stmt2_exec(TAOS_STMT2 *stmt, int *affected_rows) {
1,878,719✔
2714
  if (stmt == NULL) {
1,878,719✔
2715
    tscError("NULL parameter for %s", __FUNCTION__);
×
2716
    terrno = TSDB_CODE_INVALID_PARA;
×
2717
    return terrno;
×
2718
  }
2719

2720
  return stmtExec2(stmt, affected_rows);
1,878,719✔
2721
}
2722

2723
int taos_stmt2_close(TAOS_STMT2 *stmt) {
15,566✔
2724
  if (stmt == NULL) {
15,566✔
2725
    tscError("NULL parameter for %s", __FUNCTION__);
×
2726
    terrno = TSDB_CODE_INVALID_PARA;
×
2727
    return terrno;
×
2728
  }
2729

2730
  return stmtClose2(stmt);
15,566✔
2731
}
2732

2733
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
104✔
2734
  if (stmt == NULL || insert == NULL) {
104✔
2735
    tscError("NULL parameter for %s", __FUNCTION__);
×
2736
    terrno = TSDB_CODE_INVALID_PARA;
×
2737
    return terrno;
×
2738
  }
2739
  *insert = stmt2IsInsert(stmt);
104✔
2740
  return TSDB_CODE_SUCCESS;
104✔
2741
}
2742

2743
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
76✔
2744
  if (stmt == NULL || count == NULL) {
76✔
2745
    tscError("NULL parameter for %s", __FUNCTION__);
×
2746
    terrno = TSDB_CODE_INVALID_PARA;
×
2747
    return terrno;
×
2748
  }
2749

2750
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
76✔
2751
  STMT2_DLOG_E("start to get fields");
76✔
2752

2753
  if (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type ||
76✔
2754
      (pStmt->sql.type == 0 && stmt2IsInsert(stmt))) {
76✔
2755
    return stmtGetStbColFields2(stmt, count, fields);
76✔
2756
  }
2757
  if (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt))) {
×
2758
    return stmtGetParamNum2(stmt, count);
×
2759
  }
2760

2761
  tscError("Invalid sql for stmt %s", pStmt->sql.sqlStr);
×
2762
  return TSDB_CODE_PAR_SYNTAX_ERROR;
×
2763
}
2764

2765
DLL_EXPORT void taos_stmt2_free_fields(TAOS_STMT2 *stmt, TAOS_FIELD_ALL *fields) {
76✔
2766
  (void)stmt;
2767
  if (!fields) return;
76✔
2768
  taosMemoryFree(fields);
76✔
2769
}
2770

2771
TAOS_RES *taos_stmt2_result(TAOS_STMT2 *stmt) {
28✔
2772
  if (stmt == NULL) {
28✔
2773
    tscError("NULL parameter for %s", __FUNCTION__);
×
2774
    terrno = TSDB_CODE_INVALID_PARA;
×
2775
    return NULL;
×
2776
  }
2777

2778
  return stmtUseResult2(stmt);
28✔
2779
}
2780

2781
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmtErrstr2(stmt); }
×
2782

2783
int taos_set_conn_mode(TAOS *taos, int mode, int value) {
2,460✔
2784
  if (taos == NULL) {
2,460✔
2785
    terrno = TSDB_CODE_INVALID_PARA;
×
2786
    return terrno;
×
2787
  }
2788

2789
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2,460✔
2790
  if (NULL == pObj) {
2,460✔
2791
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2792
    tscError("invalid parameter for %s", __func__);
×
2793
    return terrno;
×
2794
  }
2795
  switch (mode) {
2,460✔
2796
    case TAOS_CONN_MODE_BI:
2,460✔
2797
      atomic_store_8(&pObj->biMode, value);
2,460✔
2798
      break;
2,460✔
2799
    default:
×
2800
      tscError("not supported mode.");
×
2801
      return TSDB_CODE_INVALID_PARA;
×
2802
  }
2803
  return 0;
2,460✔
2804
}
2805

2806
char *getBuildInfo() { return td_buildinfo; }
×
2807

2808
int32_t taos_connect_is_alive(TAOS *taos) {
×
2809
  int32_t code = 0;
×
2810
  code = TSDB_CODE_TSC_SESS_CONN_TIMEOUT;
×
2811

2812
  if (code != TSDB_CODE_SUCCESS) {
×
2813
    return 0; 
×
2814
  } else {
2815
    return 1;
×
2816
  }
2817
}
2818
static int32_t buildInstanceRegisterSql(const SInstanceRegisterReq *req, char **ppSql, uint32_t *pLen) {
×
2819
  const char *action = (req->expire < 0) ? "UNREGISTER" : "REGISTER";
×
2820
  int32_t     len = 0;
×
2821

2822
  len += snprintf(NULL, 0, "%s INSTANCE '%s'", action, req->id);
×
2823
  if (req->type[0] != 0) {
×
2824
    len += snprintf(NULL, 0, " TYPE '%s'", req->type);
×
2825
  }
2826
  if (req->desc[0] != 0) {
×
2827
    len += snprintf(NULL, 0, " DESC '%s'", req->desc);
×
2828
  }
2829
  if (req->expire >= 0) {
×
2830
    len += snprintf(NULL, 0, " EXPIRE %d", req->expire);
×
2831
  }
2832

2833
  char *sql = taosMemoryMalloc((size_t)len + 1);
×
2834
  if (sql == NULL) {
×
2835
    return terrno;
×
2836
  }
2837

2838
  int32_t offset = snprintf(sql, (size_t)len + 1, "%s INSTANCE '%s'", action, req->id);
×
2839
  if (req->type[0] != 0) {
×
2840
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " TYPE '%s'", req->type);
×
2841
  }
2842
  if (req->desc[0] != 0) {
×
2843
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " DESC '%s'", req->desc);
×
2844
  }
2845
  if (req->expire >= 0) {
×
2846
    (void)snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " EXPIRE %d", req->expire);
×
2847
  }
2848

2849
  *ppSql = sql;
×
2850
  if (pLen != NULL) {
×
2851
    *pLen = (uint32_t)len;
×
2852
  }
2853
  return TSDB_CODE_SUCCESS;
×
2854
}
2855

2856
static int32_t sendInstanceRegisterReq(STscObj *pObj, const SInstanceRegisterReq *req) {
×
2857
  SRequestObj *pRequest = NULL;
×
2858
  int32_t      code = createRequest(pObj->id, TDMT_MND_REGISTER_INSTANCE, 0, &pRequest);
×
2859
  if (code != TSDB_CODE_SUCCESS) {
×
2860
    terrno = code;
×
2861
    return code;
×
2862
  }
2863

2864
  code = buildInstanceRegisterSql(req, &pRequest->sqlstr, &pRequest->sqlLen);
×
2865
  if (code != TSDB_CODE_SUCCESS) {
×
2866
    goto _cleanup;
×
2867
  }
2868

2869
  int32_t msgLen = tSerializeSInstanceRegisterReq(NULL, 0, (SInstanceRegisterReq *)req);
×
2870
  if (msgLen <= 0) {
×
2871
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
2872
    goto _cleanup;
×
2873
  }
2874

2875
  void *pMsg = taosMemoryMalloc(msgLen);
×
2876
  if (pMsg == NULL) {
×
2877
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
2878
    goto _cleanup;
×
2879
  }
2880

2881
  if (tSerializeSInstanceRegisterReq(pMsg, msgLen, (SInstanceRegisterReq *)req) < 0) {
×
2882
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
2883
    taosMemoryFree(pMsg);
×
2884
    goto _cleanup;
×
2885
  }
2886

2887
  pRequest->type = TDMT_MND_REGISTER_INSTANCE;
×
2888
  pRequest->body.requestMsg = (SDataBuf){.pData = pMsg, .len = msgLen, .handle = NULL};
×
2889

2890
  SMsgSendInfo *pSend = buildMsgInfoImpl(pRequest);
×
2891
  if (pSend == NULL) {
×
2892
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
2893
    taosMemoryFree(pMsg);
×
2894
    pRequest->body.requestMsg.pData = NULL;
×
2895
    goto _cleanup;
×
2896
  }
2897

2898
  SEpSet epSet = getEpSet_s(&pObj->pAppInfo->mgmtEp);
×
2899
  code = asyncSendMsgToServer(pObj->pAppInfo->pTransporter, &epSet, NULL, pSend);
×
2900
  if (code != TSDB_CODE_SUCCESS) {
×
2901
    destroySendMsgInfo(pSend);
×
2902
    pRequest->body.requestMsg = (SDataBuf){0};
×
2903
    goto _cleanup;
×
2904
  }
2905

2906
  code = tsem_wait(&pRequest->body.rspSem);
×
2907
  if (code != TSDB_CODE_SUCCESS) {
×
2908
    code = terrno != 0 ? terrno : code;
×
2909
    goto _cleanup;
×
2910
  }
2911

2912
  code = pRequest->code;
×
2913
  terrno = code;
×
2914

2915
_cleanup:
×
2916
  destroyRequest(pRequest);
×
2917
  return code;
×
2918
}
2919

2920
static bool instanceRegisterRpcRfp(int32_t code, tmsg_t msgType) {
×
2921
  if (NEED_REDIRECT_ERROR(code)) {
×
2922
    return true;
×
2923
  } else if (code == TSDB_CODE_UTIL_QUEUE_OUT_OF_MEMORY || code == TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE ||
×
2924
             code == TSDB_CODE_SYN_WRITE_STALL || code == TSDB_CODE_SYN_PROPOSE_NOT_READY ||
×
2925
             code == TSDB_CODE_SYN_RESTORING) {
2926
    tscDebug("client msg type %s should retry since %s", TMSG_INFO(msgType), tstrerror(code));
×
2927
    return true;
×
2928
  } else {
2929
    return false;
×
2930
  }
2931
}
2932

2933
int32_t taos_register_instance(const char *id, const char *type, const char *desc, int32_t expire) {
×
2934
  if (id == NULL || id[0] == 0) {
×
2935
    return terrno = TSDB_CODE_INVALID_PARA;
×
2936
  }
2937

2938
  // Validate string lengths
2939
  size_t idLen = strlen(id);
×
2940
  if (idLen >= TSDB_INSTANCE_ID_LEN) {
×
2941
    tscError("instance id length %zu exceeds limit %d", idLen, TSDB_INSTANCE_ID_LEN - 1);
×
2942
    return terrno = TSDB_CODE_INVALID_PARA;
×
2943
  }
2944

2945
  if (type != NULL && type[0] != 0) {
×
2946
    size_t typeLen = strlen(type);
×
2947
    if (typeLen >= TSDB_INSTANCE_TYPE_LEN) {
×
2948
      tscError("instance type length %zu exceeds limit %d", typeLen, TSDB_INSTANCE_TYPE_LEN - 1);
×
2949
      return terrno = TSDB_CODE_INVALID_PARA;
×
2950
    }
2951
  }
2952

2953
  if (desc != NULL && desc[0] != 0) {
×
2954
    size_t descLen = strlen(desc);
×
2955
    if (descLen >= TSDB_INSTANCE_DESC_LEN) {
×
2956
      tscError("instance desc length %zu exceeds limit %d", descLen, TSDB_INSTANCE_DESC_LEN - 1);
×
2957
      return terrno = TSDB_CODE_INVALID_PARA;
×
2958
    }
2959
  }
2960

2961
  int32_t code = taos_init();
×
2962
  if (code != TSDB_CODE_SUCCESS) {
×
2963
    return code;
×
2964
  }
2965

2966
  SConfig *pCfg = taosGetCfg();
×
2967
  if (pCfg == NULL) {
×
2968
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
2969
  }
2970

2971
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
×
2972
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
×
2973
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
2974
  }
2975

2976
  SEp firstEp = {0};
×
2977
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
×
2978
  if (code != TSDB_CODE_SUCCESS) {
×
2979
    return terrno = code;
×
2980
  }
2981

2982
  void    *clientRpc = NULL;
×
2983
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
×
2984
  SRpcMsg  rpcMsg = {0};
×
2985
  SRpcMsg  rpcRsp = {0};
×
2986
  SRpcInit rpcInit = {0};
×
2987

2988
  rpcInit.label = "INST";
×
2989
  rpcInit.numOfThreads = 1;
×
2990
  rpcInit.cfp = NULL;
×
2991
  rpcInit.sessions = 16;
×
2992
  rpcInit.connType = TAOS_CONN_CLIENT;
×
2993
  rpcInit.idleTime = tsShellActivityTimer * 1000;
×
2994
  rpcInit.compressSize = tsCompressMsgSize;
×
2995
  rpcInit.user = TSDB_DEFAULT_USER;
×
2996

2997
  rpcInit.rfp = instanceRegisterRpcRfp;
×
2998
  rpcInit.retryMinInterval = tsRedirectPeriod;
×
2999
  rpcInit.retryStepFactor = tsRedirectFactor;
×
3000
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
×
3001
  rpcInit.retryMaxTimeout =
×
3002
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3003

3004
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
×
3005
  connLimitNum = TMAX(connLimitNum, 10);
×
3006
  connLimitNum = TMIN(connLimitNum, 500);
×
3007
  rpcInit.connLimitNum = connLimitNum;
×
3008
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
×
3009
  rpcInit.readTimeout = tsReadTimeout;
×
3010
  rpcInit.ipv6 = tsEnableIpv6;
×
3011
  rpcInit.enableSSL = tsEnableTLS;
×
3012

3013
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
×
3014
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
×
3015
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
×
3016
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
×
3017
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
×
3018

3019
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
×
3020
  if (code != TSDB_CODE_SUCCESS) {
×
3021
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
3022
    return code;
×
3023
  }
3024

3025
  clientRpc = rpcOpen(&rpcInit);
×
3026
  if (clientRpc == NULL) {
×
3027
    code = terrno;
×
3028
    tscError("failed to init instance register client since %s", tstrerror(code));
×
3029
    return code;
×
3030
  }
3031

3032
  // Prepare epSet
3033
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
×
3034
  epSet.eps[0].port = firstEp.port;
×
3035

3036
  // Prepare request
3037
  SInstanceRegisterReq req = {0};
×
3038
  tstrncpy(req.id, id, sizeof(req.id));
×
3039
  if (type != NULL && type[0] != 0) {
×
3040
    tstrncpy(req.type, type, sizeof(req.type));
×
3041
  }
3042
  if (desc != NULL && desc[0] != 0) {
×
3043
    tstrncpy(req.desc, desc, sizeof(req.desc));
×
3044
  }
3045
  req.expire = expire;
×
3046

3047
  int32_t contLen = tSerializeSInstanceRegisterReq(NULL, 0, &req);
×
3048
  if (contLen <= 0) {
×
3049
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3050
    rpcClose(clientRpc);
×
3051
    return code;
×
3052
  }
3053

3054
  void *pCont = rpcMallocCont(contLen);
×
3055
  if (pCont == NULL) {
×
3056
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3057
    rpcClose(clientRpc);
×
3058
    return code;
×
3059
  }
3060

3061
  if (tSerializeSInstanceRegisterReq(pCont, contLen, &req) < 0) {
×
3062
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3063
    rpcFreeCont(pCont);
×
3064
    rpcClose(clientRpc);
×
3065
    return code;
×
3066
  }
3067

3068
  rpcMsg.pCont = pCont;
×
3069
  rpcMsg.contLen = contLen;
×
3070
  rpcMsg.msgType = TDMT_MND_REGISTER_INSTANCE;
×
3071
  rpcMsg.info.ahandle = (void *)0x9528;  // Different magic number from server status
×
3072
  rpcMsg.info.notFreeAhandle = 1;
×
3073

3074
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
×
3075
  if (TSDB_CODE_SUCCESS != code) {
×
3076
    tscError("failed to send instance register req since %s", tstrerror(code));
×
3077
    // rpcSendRecv failed, pCont may not be freed, but check _RETURN1 path
3078
    // In error path, rpcSendRecv may free pCont, but we free it here to be safe
3079
    rpcClose(clientRpc);
×
3080
    return code;
×
3081
  }
3082

3083
  if (rpcRsp.code != 0) {
×
3084
    code = rpcRsp.code;
×
3085
    tscError("instance register failed, code:%s", tstrerror(code));
×
3086
  } else {
3087
    code = TSDB_CODE_SUCCESS;
×
3088
  }
3089

3090
  if (rpcRsp.pCont != NULL) {
×
3091
    rpcFreeCont(rpcRsp.pCont);
×
3092
  }
3093
  rpcClose(clientRpc);
×
3094

3095
  terrno = code;
×
3096
  return code;
×
3097
}
3098

3099
int32_t taos_list_instances(const char *filter_type, char ***pList, int32_t *pCount) {
×
3100
  if (pList == NULL || pCount == NULL) {
×
3101
    return TSDB_CODE_INVALID_PARA;
×
3102
  }
3103

3104
  int32_t code = taos_init();
×
3105
  if (code != TSDB_CODE_SUCCESS) {
×
3106
    terrno = code;
×
3107
    return code;
×
3108
  }
3109

3110
  SConfig *pCfg = taosGetCfg();
×
3111
  if (pCfg == NULL) {
×
3112
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3113
    return TSDB_CODE_CFG_NOT_FOUND;
×
3114
  }
3115

3116
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
×
3117
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
×
3118
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3119
    return TSDB_CODE_CFG_NOT_FOUND;
×
3120
  }
3121

3122
  SEp firstEp = {0};
×
3123
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
×
3124
  if (code != TSDB_CODE_SUCCESS) {
×
3125
    terrno = code;
×
3126
    return code;
×
3127
  }
3128

3129
  // Initialize RPC connection (similar to taos_register_instance)
3130
  void    *clientRpc = NULL;
×
3131
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
×
3132
  SRpcMsg  rpcMsg = {0};
×
3133
  SRpcMsg  rpcRsp = {0};
×
3134
  SRpcInit rpcInit = {0};
×
3135

3136
  rpcInit.label = "LIST";
×
3137
  rpcInit.numOfThreads = 1;
×
3138
  rpcInit.cfp = NULL;
×
3139
  rpcInit.sessions = 16;
×
3140
  rpcInit.connType = TAOS_CONN_CLIENT;
×
3141
  rpcInit.idleTime = tsShellActivityTimer * 1000;
×
3142
  rpcInit.compressSize = tsCompressMsgSize;
×
3143
  rpcInit.user = TSDB_DEFAULT_USER;
×
3144

3145
  rpcInit.rfp = instanceRegisterRpcRfp;
×
3146
  rpcInit.retryMinInterval = tsRedirectPeriod;
×
3147
  rpcInit.retryStepFactor = tsRedirectFactor;
×
3148
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
×
3149
  rpcInit.retryMaxTimeout =
×
3150
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3151

3152
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
×
3153
  connLimitNum = TMAX(connLimitNum, 10);
×
3154
  connLimitNum = TMIN(connLimitNum, 500);
×
3155
  rpcInit.connLimitNum = connLimitNum;
×
3156
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
×
3157
  rpcInit.readTimeout = tsReadTimeout;
×
3158
  rpcInit.ipv6 = tsEnableIpv6;
×
3159
  rpcInit.enableSSL = tsEnableTLS;
×
3160

3161
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
×
3162
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
×
3163
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
×
3164
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
×
3165
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
×
3166

3167
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
×
3168
  if (code != TSDB_CODE_SUCCESS) {
×
3169
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
3170
    return code;
×
3171
  }
3172

3173
  clientRpc = rpcOpen(&rpcInit);
×
3174
  if (clientRpc == NULL) {
×
3175
    code = terrno;
×
3176
    tscError("failed to init instance list client since %s", tstrerror(code));
×
3177
    terrno = code;
×
3178
    return code;
×
3179
  }
3180

3181
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
×
3182
  epSet.eps[0].port = firstEp.port;
×
3183
  SInstanceListReq req = {0};
×
3184
  if (filter_type != NULL && filter_type[0] != 0) {
×
3185
    tstrncpy(req.filter_type, filter_type, sizeof(req.filter_type));
×
3186
  }
3187

3188
  // Serialize request to get required length
3189
  int32_t contLen = tSerializeSInstanceListReq(NULL, 0, &req);
×
3190
  if (contLen <= 0) {
×
3191
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3192
    rpcClose(clientRpc);
×
3193
    terrno = code;
×
3194
    return code;
×
3195
  }
3196

3197
  // Allocate RPC message buffer (includes message header overhead)
3198
  void *pCont = rpcMallocCont(contLen);
×
3199
  if (pCont == NULL) {
×
3200
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3201
    rpcClose(clientRpc);
×
3202
    terrno = code;
×
3203
    return code;
×
3204
  }
3205

3206
  // Serialize request into the content part (after message header)
3207
  if (tSerializeSInstanceListReq(pCont, contLen, &req) < 0) {
×
3208
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3209
    rpcFreeCont(pCont);
×
3210
    rpcClose(clientRpc);
×
3211
    terrno = code;
×
3212
    return code;
×
3213
  }
3214

3215
  rpcMsg.pCont = pCont;
×
3216
  rpcMsg.contLen = contLen;
×
3217
  rpcMsg.msgType = TDMT_MND_LIST_INSTANCES;
×
3218
  rpcMsg.info.ahandle = (void *)0x9529;  // Different magic number from register
×
3219
  rpcMsg.info.notFreeAhandle = 1;
×
3220

3221
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
×
3222
  if (TSDB_CODE_SUCCESS != code) {
×
3223
    tscError("failed to send instance list req since %s", tstrerror(code));
×
3224
    rpcFreeCont(pCont);
×
3225
    rpcClose(clientRpc);
×
3226
    terrno = code;
×
3227
    return code;
×
3228
  }
3229

3230
  // Check response - rpcRsp.code contains the result code from mnode
3231
  if (rpcRsp.code != 0) {
×
3232
    code = rpcRsp.code;
×
3233
    tscError("instance list failed, code:%s", tstrerror(code));
×
3234
    if (rpcRsp.pCont != NULL) {
×
3235
      rpcFreeCont(rpcRsp.pCont);
×
3236
    }
3237
    rpcClose(clientRpc);
×
3238
    terrno = code;
×
3239
    return code;
×
3240
  }
3241

3242
  // Deserialize response
3243
  if (rpcRsp.pCont != NULL && rpcRsp.contLen > 0) {
×
3244
    SInstanceListRsp rsp = {0};
×
3245
    code = tDeserializeSInstanceListRsp(rpcRsp.pCont, rpcRsp.contLen, &rsp);
×
3246
    if (code != TSDB_CODE_SUCCESS) {
×
3247
      tscError("failed to deserialize instance list rsp, code:%s", tstrerror(code));
×
3248
      if (rsp.ids != NULL) {
×
3249
        for (int32_t i = 0; i < rsp.count; i++) {
×
3250
          if (rsp.ids[i] != NULL) {
×
3251
            taosMemoryFree(rsp.ids[i]);
×
3252
          }
3253
        }
3254
        taosMemoryFree(rsp.ids);
×
3255
        rsp.ids = NULL;
×
3256
      }
3257
      rsp.count = 0;
×
3258
      rpcFreeCont(rpcRsp.pCont);
×
3259
      rpcClose(clientRpc);
×
3260
      terrno = code;
×
3261
      return code;
×
3262
    }
3263
    *pList = rsp.ids;
×
3264
    *pCount = rsp.count;
×
3265
  } else {
3266
    *pList = NULL;
×
3267
    *pCount = 0;
×
3268
  }
3269

3270
  if (rpcRsp.pCont != NULL) {
×
3271
    rpcFreeCont(rpcRsp.pCont);
×
3272
  }
3273
  rpcClose(clientRpc);
×
3274

3275
  return TSDB_CODE_SUCCESS;
×
3276
}
3277

3278
void taos_free_instances(char ***pList, int32_t count) {
×
3279
  if (pList == NULL || *pList == NULL || count <= 0) {
×
3280
    return;
×
3281
  }
3282

3283
  // Free each string in the array
3284
  for (int32_t i = 0; i < count; i++) {
×
3285
    if ((*pList)[i] != NULL) {
×
3286
      taosMemoryFree((*pList)[i]);
×
3287
      (*pList)[i] = NULL;
×
3288
    }
3289
  }
3290

3291
  // Free the array itself
3292
  taosMemoryFree(*pList);
×
3293
  *pList = NULL;
×
3294
}
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