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

taosdata / TDengine / #4905

29 Dec 2025 02:08PM UTC coverage: 65.423% (-0.3%) from 65.734%
#4905

push

travis-ci

web-flow
enh: sign connect request (#34067)

23 of 29 new or added lines in 4 files covered. (79.31%)

11614 existing lines in 186 files now uncovered.

193476 of 295730 relevant lines covered (65.42%)

115752566.53 hits per line

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

37.13
/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, ...) {
437,500✔
50
  if (arg == NULL) {
437,500✔
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) {
105,509,404✔
56
    if (i % 1000 == 0) {
105,060,564✔
57
      (void)sched_yield();
106,596✔
58
    }
59
  }
60

61
  int ret = taos_options_imp(option, (const char *)arg);
399,322✔
62
  atomic_store_32(&lock, 0);
437,500✔
63
  return ret;
437,500✔
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,159,155✔
73
  pTimezoneMap = taosHashInit(0, MurmurHash3_32, false, HASH_ENTRY_LOCK);
1,159,155✔
74
  if (pTimezoneMap == NULL) {
1,159,155✔
75
    return terrno;
×
76
  }
77
  taosHashSetFreeFp(pTimezoneMap, freeTz);
1,159,155✔
78

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

86
void tzCleanup() {
1,159,170✔
87
  taosHashCleanup(pTimezoneMap);
1,159,170✔
88
  taosHashCleanup(pTimezoneNameMap);
1,159,170✔
89
}
1,159,170✔
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,159,657✔
249
  tscInfo("start to cleanup client environment");
1,159,657✔
250
  if (atomic_val_compare_exchange_32(&sentinel, TSC_VAR_NOT_RELEASE, TSC_VAR_RELEASED) != TSC_VAR_NOT_RELEASE) {
1,159,657✔
251
    return;
487✔
252
  }
253

254
  monitorClose();
1,159,170✔
255
  tscStopCrashReport();
1,159,170✔
256

257
  hbMgrCleanUp();
1,159,170✔
258

259
  catalogDestroy();
1,159,170✔
260
  schedulerDestroy();
1,159,170✔
261

262
  fmFuncMgtDestroy();
1,159,170✔
263
  qCleanupKeywordsTable();
1,159,170✔
264

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

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

274
  id = clientConnRefPool;
1,159,170✔
275
  clientConnRefPool = -1;
1,159,170✔
276
  taosCloseRef(id);
1,159,170✔
277

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

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

287
  sessMgtDestroy();
1,159,170✔
288

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

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

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

314
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
1,947,440✔
315
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
1,947,440✔
316
  if (user == NULL) {
1,947,624✔
317
    user = TSDB_DEFAULT_USER;
149,354✔
318
  }
319

320
  if (pass == NULL) {
1,947,624✔
321
    pass = TSDB_DEFAULT_PASS;
149,353✔
322
  }
323

324
  STscObj *pObj = NULL;
1,947,624✔
325
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY, &pObj);
1,947,676✔
326
  if (TSDB_CODE_SUCCESS == code) {
1,947,740✔
327
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
1,939,358✔
328
    if (NULL == rid) {
1,939,358✔
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;
1,939,358✔
333
    return (TAOS *)rid;
1,939,358✔
334
  } else {
335
    terrno = code;
8,382✔
336
  }
337

338
  return NULL;
8,382✔
339
}
340

341
void taos_set_option(OPTIONS *options, const char *key, const char *value) {
×
342
  if (options == NULL || key == NULL || value == NULL) {
×
343
    terrno = TSDB_CODE_INVALID_PARA;
×
344
    tscError("taos_set_option invalid parameter, options: %p, key: %p, value: %p", options, key, value);
×
345
    return;
×
346
  }
347

348
  size_t count = (size_t)options->count;
×
349
  size_t len = sizeof(options->keys) / sizeof(options->keys[0]);
×
350
  if (count >= len) {
×
351
    terrno = TSDB_CODE_INVALID_PARA;
×
352
    tscError("taos_set_option overflow, count: %zu, reached capacity: %zu", count, len);
×
353
    return;
×
354
  }
355

356
  options->keys[count] = key;
×
357
  options->values[count] = value;
×
358
  options->count = (uint16_t)(count + 1);
×
359
}
360

361
static int set_connection_option_or_close(TAOS *taos, TSDB_OPTION_CONNECTION option, const char *value) {
×
362
  if (value == NULL) return TSDB_CODE_SUCCESS;
×
363
  int code = taos_options_connection(taos, option, value);
×
364
  if (code != TSDB_CODE_SUCCESS) {
×
365
    tscError("failed to set option(%d): %s", (int)option, value);
×
366
    taos_close(taos);
×
367
    return code;
×
368
  }
369
  return TSDB_CODE_SUCCESS;
×
370
}
371

372
TAOS *taos_connect_with(const OPTIONS *options) {
×
373
  const char *ip = NULL;
×
374
  const char *user = NULL;
×
375
  const char *pass = NULL;
×
376
  const char *db = NULL;
×
377
  uint16_t port = 0;
×
378

379
  const char *charset = NULL;
×
380
  const char *timezone = NULL;
×
381
  const char *userIp = NULL;
×
382
  const char *userApp = NULL;
×
383
  const char *connectorInfo = NULL;
×
384

385
  if (options && options->count > 0) {
×
386
    size_t count = (size_t)options->count;
×
387
    for (size_t i = 0; i < count; ++i) {
×
388
      const char *key = options->keys[i];
×
389
      const char *value = options->values[i];
×
390
      if (key == NULL || value == NULL) {
×
391
        tscWarn("taos_connect_with option key or value is NULL, index: %zu", i);
×
392
        continue;
×
393
      }
394

395
      if (strcmp(key, "ip") == 0) {
×
396
        ip = value;
×
397
      } else if (strcmp(key, "user") == 0) {
×
398
        user = value;
×
399
      } else if (strcmp(key, "pass") == 0) {
×
400
        pass = value;
×
401
      } else if (strcmp(key, "db") == 0) {
×
402
        db = value;
×
403
      } else if (strcmp(key, "port") == 0) {
×
404
        port = (uint16_t)atoi(value);
×
405
      } else if (strcmp(key, "charset") == 0) {
×
406
        charset = value;
×
407
      } else if (strcmp(key, "timezone") == 0) {
×
408
        timezone = value;
×
409
      } else if (strcmp(key, "userIp") == 0) {
×
410
        userIp = value;
×
411
      } else if (strcmp(key, "userApp") == 0) {
×
412
        userApp = value;
×
413
      } else if (strcmp(key, "connectorInfo") == 0) {
×
414
        connectorInfo = value;
×
415
      } else {
416
        tscWarn("taos_connect_with unknown option key: %s", key);
×
417
      }
418
    }
419
  }
420

421
  TAOS* taos = taos_connect(ip, user, pass, db, port);
×
422
  if (taos == NULL) return NULL;
×
423

424
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_CHARSET, charset) != TSDB_CODE_SUCCESS) return NULL;
×
425
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_TIMEZONE, timezone) != TSDB_CODE_SUCCESS) return NULL;
×
426
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_USER_IP, userIp) != TSDB_CODE_SUCCESS) return NULL;
×
427
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_USER_APP, userApp) != TSDB_CODE_SUCCESS) return NULL;
×
428
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_CONNECTOR_INFO, connectorInfo) != TSDB_CODE_SUCCESS) return NULL;
×
429

430
  return taos;
×
431
}
432

433
TAOS *taos_connect_with_dsn(const char *dsn) {
×
434
  terrno = TSDB_CODE_OPS_NOT_SUPPORT;
×
435
  tscError("taos_connect_with_dsn not supported");
×
436
  return NULL;
×
437
}
438

439
int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type) {
1,540✔
440
  if (taos == NULL) {
1,540✔
441
    terrno = TSDB_CODE_INVALID_PARA;
×
442
    return terrno;
×
443
  }
444

445
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
1,540✔
446
  if (NULL == pObj) {
1,540✔
447
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
448
    tscError("invalid parameter for %s", __func__);
×
449
    return terrno;
×
450
  }
451

452
  switch (type) {
1,540✔
453
    case TAOS_NOTIFY_PASSVER: {
440✔
454
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
440✔
455
      pObj->passInfo.fp = fp;
440✔
456
      pObj->passInfo.param = param;
440✔
457
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
440✔
458
      break;
440✔
459
    }
460
    case TAOS_NOTIFY_WHITELIST_VER: {
×
461
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
462
      pObj->whiteListInfo.fp = fp;
×
463
      pObj->whiteListInfo.param = param;
×
464
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
465
      break;
×
466
    }
467
    case TAOS_NOTIFY_USER_DROPPED: {
1,100✔
468
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
1,100✔
469
      pObj->userDroppedInfo.fp = fp;
1,100✔
470
      pObj->userDroppedInfo.param = param;
1,100✔
471
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
1,100✔
472
      break;
1,100✔
473
    }
474
    case TAOS_NOTIFY_DATETIME_WHITELIST_VER: {
×
475
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
476
      pObj->dateTimeWhiteListInfo.fp = fp;
×
477
      pObj->dateTimeWhiteListInfo.param = param;
×
478
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
479
      break;
×
480
    }
481
    default: {
×
482
      terrno = TSDB_CODE_INVALID_PARA;
×
483
      releaseTscObj(*(int64_t *)taos);
×
484
      return terrno;
×
485
    }
486
  }
487

488
  releaseTscObj(*(int64_t *)taos);
1,540✔
489
  return 0;
1,540✔
490
}
491

492
typedef struct SFetchWhiteListInfo {
493
  int64_t                     connId;
494
  __taos_async_whitelist_fn_t userCbFn;
495
  void                       *userParam;
496
} SFetchWhiteListInfo;
497

498
int32_t fetchWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
499
  SFetchWhiteListInfo *pInfo = (SFetchWhiteListInfo *)param;
×
500
  TAOS                *taos = &pInfo->connId;
×
501
  if (code != TSDB_CODE_SUCCESS) {
×
502
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
503
    taosMemoryFree(pMsg->pData);
×
504
    taosMemoryFree(pMsg->pEpSet);
×
505
    taosMemoryFree(pInfo);
×
506
    return code;
×
507
  }
508

509
  SGetUserIpWhiteListRsp wlRsp;
×
510
  if (TSDB_CODE_SUCCESS != tDeserializeSGetUserIpWhiteListRsp(pMsg->pData, pMsg->len, &wlRsp)) {
×
511
    taosMemoryFree(pMsg->pData);
×
512
    taosMemoryFree(pMsg->pEpSet);
×
513
    taosMemoryFree(pInfo);
×
514
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
515
    return terrno;
×
516
  }
517

518
  uint64_t *pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(uint64_t));
×
519
  if (pWhiteLists == NULL) {
×
520
    taosMemoryFree(pMsg->pData);
×
521
    taosMemoryFree(pMsg->pEpSet);
×
522
    taosMemoryFree(pInfo);
×
523
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
524
    return terrno;
×
525
  }
526

527
  for (int i = 0; i < wlRsp.numWhiteLists; ++i) {
×
528
    pWhiteLists[i] = ((uint64_t)wlRsp.pWhiteLists[i].mask << 32) | wlRsp.pWhiteLists[i].ip;
×
529
  }
530

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

533
  taosMemoryFree(pWhiteLists);
×
534
  taosMemoryFree(pMsg->pData);
×
535
  taosMemoryFree(pMsg->pEpSet);
×
536
  taosMemoryFree(pInfo);
×
537
  tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
538
  return code;
×
539
}
540

541
void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *param) {
×
542
  if (NULL == taos) {
×
543
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
544
    return;
×
545
  }
546

547
  int64_t connId = *(int64_t *)taos;
×
548

549
  STscObj *pTsc = acquireTscObj(connId);
×
550
  if (NULL == pTsc) {
×
551
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
552
    return;
×
553
  }
554

555
  SGetUserWhiteListReq req;
×
556
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
557
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
558
  if (msgLen < 0) {
×
559
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
560
    releaseTscObj(connId);
×
561
    return;
×
562
  }
563

564
  void *pReq = taosMemoryMalloc(msgLen);
×
565
  if (pReq == NULL) {
×
566
    fp(param, terrno, taos, 0, NULL);
×
567
    releaseTscObj(connId);
×
568
    return;
×
569
  }
570

571
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
572
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
573
    taosMemoryFree(pReq);
×
574
    releaseTscObj(connId);
×
575
    return;
×
576
  }
577

578
  SFetchWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchWhiteListInfo));
×
579
  if (pParam == NULL) {
×
580
    fp(param, terrno, taos, 0, NULL);
×
581
    taosMemoryFree(pReq);
×
582
    releaseTscObj(connId);
×
583
    return;
×
584
  }
585

586
  pParam->connId = connId;
×
587
  pParam->userCbFn = fp;
×
588

589
  pParam->userParam = param;
×
590
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
591
  if (pSendInfo == NULL) {
×
592
    fp(param, terrno, taos, 0, NULL);
×
593
    taosMemoryFree(pParam);
×
594
    taosMemoryFree(pReq);
×
595
    releaseTscObj(connId);
×
596
    return;
×
597
  }
598

599
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
600
  pSendInfo->requestId = generateRequestId();
×
601
  pSendInfo->requestObjRefId = 0;
×
602
  pSendInfo->param = pParam;
×
603
  pSendInfo->fp = fetchWhiteListCallbackFn;
×
604
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST;
×
605

606
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
607
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
608
    tscWarn("failed to async send msg to server");
×
609
  }
610
  releaseTscObj(connId);
×
611
  return;
×
612
}
613

614

615

616
typedef struct SFetchIpWhiteListInfo {
617
  int64_t connId;
618
  bool supportNeg;
619
  void   *userParam;
620

621
  __taos_async_ip_whitelist_fn_t userCbFn;
622
} SFetchIpWhiteListInfo;
623

624

625

626
int32_t fetchIpWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
627
  int32_t lino = 0;
×
628
  char  **pWhiteLists = NULL;
×
629

630
  SGetUserIpWhiteListRsp wlRsp = {0};
×
631

632
  SFetchIpWhiteListInfo *pInfo = (SFetchIpWhiteListInfo *)param;
×
633
  TAOS *taos = &pInfo->connId;
×
634

635
  if (code != TSDB_CODE_SUCCESS) {
×
636
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
637
    TAOS_CHECK_GOTO(code, &lino, _error);
×
638
  }
639

640
  if ((code = tDeserializeSGetUserIpWhiteListDualRsp(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
641
    TAOS_CHECK_GOTO(code, &lino, _error);
×
642
  }
643

644
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
645
  if (pWhiteLists == NULL) {
×
646
    code = terrno;
×
647
    TAOS_CHECK_GOTO(code, &lino, _error);
×
648
  }
649

650
  int32_t numWhiteLists =0;
×
651
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
652
    SIpRange *pIpRange = &wlRsp.pWhiteListsDual[i];
×
653
    if (!pInfo->supportNeg && pIpRange->neg) {
×
654
      continue;
×
655
    }
656
    SIpAddr   ipAddr = {0};
×
657

658
    code = tIpUintToStr(pIpRange, &ipAddr);
×
659
    TAOS_CHECK_GOTO(code, &lino, _error);
×
660

661
    char *ip = taosMemCalloc(1, IP_RESERVE_CAP);
×
662
    if (ip == NULL) {
×
663
      code = terrno;
×
664
      TAOS_CHECK_GOTO(code, &lino, _error);
×
665
    }
666
    if (ipAddr.type == 0) {
×
667
      if (pInfo->supportNeg) {
×
668
        snprintf(ip, IP_RESERVE_CAP, "%c %s/%d", pIpRange->neg ? '-' : '+', ipAddr.ipv4, ipAddr.mask);
×
669
      } else {
670
        snprintf(ip, IP_RESERVE_CAP, "%s/%d", ipAddr.ipv4, ipAddr.mask);
×
671
      }
672
    } else {
673
      if (ipAddr.ipv6[0] == 0) {
×
674
        memcpy(ipAddr.ipv6, "::", 2);
×
675
      }
676
      if (pInfo->supportNeg) {
×
677
        snprintf(ip, IP_RESERVE_CAP, "%c %s/%d", pIpRange->neg ? '-' : '+', ipAddr.ipv6, ipAddr.mask);
×
678
      } else {
679
        snprintf(ip, IP_RESERVE_CAP, "%s/%d", ipAddr.ipv6, ipAddr.mask);
×
680
      }
681
    }
682
    pWhiteLists[numWhiteLists++] = ip;
×
683
  }
684

685
  pInfo->userCbFn(pInfo->userParam, code, taos, numWhiteLists, pWhiteLists);
×
686
_error:
×
687
  if (pWhiteLists != NULL) {
×
688
    for (int32_t i = 0; i < numWhiteLists; i++) {
×
689
      taosMemFree(pWhiteLists[i]);
×
690
    }
691
    taosMemoryFree(pWhiteLists);
×
692
  }
693
  taosMemoryFree(pMsg->pData);
×
694
  taosMemoryFree(pMsg->pEpSet);
×
695
  taosMemoryFree(pInfo);
×
696
  tFreeSGetUserIpWhiteListDualRsp(&wlRsp);
×
697
  return code;
×
698
}
699

700

701

702
static void taosFetchIpWhiteList(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param, bool supportNeg) {
×
703
  if (NULL == taos) {
×
704
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
705
    return;
×
706
  }
707
  int64_t connId = *(int64_t *)taos;
×
708

709
  STscObj *pTsc = acquireTscObj(connId);
×
710
  if (NULL == pTsc) {
×
711
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
712
    return;
×
713
  }
714

715
  SGetUserWhiteListReq req;
×
716
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
717
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
718
  if (msgLen < 0) {
×
719
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
720
    releaseTscObj(connId);
×
721
    return;
×
722
  }
723

724
  void *pReq = taosMemoryMalloc(msgLen);
×
725
  if (pReq == NULL) {
×
726
    fp(param, terrno, taos, 0, NULL);
×
727
    releaseTscObj(connId);
×
728
    return;
×
729
  }
730

731
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
732
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
733
    taosMemoryFree(pReq);
×
734
    releaseTscObj(connId);
×
735
    return;
×
736
  }
737

738
  SFetchIpWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchIpWhiteListInfo));
×
739
  if (pParam == NULL) {
×
740
    fp(param, terrno, taos, 0, NULL);
×
741
    taosMemoryFree(pReq);
×
742
    releaseTscObj(connId);
×
743
    return;
×
744
  }
745

746
  pParam->connId = connId;
×
747
  pParam->supportNeg = supportNeg;
×
748
  pParam->userCbFn = fp;
×
749
  pParam->userParam = param;
×
750

751
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
752
  if (pSendInfo == NULL) {
×
753
    fp(param, terrno, taos, 0, NULL);
×
754
    taosMemoryFree(pParam);
×
755
    taosMemoryFree(pReq);
×
756
    releaseTscObj(connId);
×
757
    return;
×
758
  }
759

760
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
761
  pSendInfo->requestId = generateRequestId();
×
762
  pSendInfo->requestObjRefId = 0;
×
763
  pSendInfo->param = pParam;
×
764
  pSendInfo->fp = fetchIpWhiteListCallbackFn;
×
765
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST_DUAL;
×
766

767
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
768
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
769
    tscWarn("failed to async send msg to server");
×
770
  }
771
  releaseTscObj(connId);
×
772
  return;
×
773
}
774

775

776

777
void taos_fetch_whitelist_dual_stack_a(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param) {
×
778
  taosFetchIpWhiteList(taos, fp, param, false);
×
779
}
×
780

781

782

783
void taos_fetch_ip_whitelist_a(TAOS *taos, __taos_async_ip_whitelist_fn_t fp, void *param) {
×
784
  taosFetchIpWhiteList(taos, fp, param, true);
×
785
}
×
786

787

788
typedef struct SFetchDateTimeWhiteListInfo {
789
  int64_t                              connId;
790
  void                                *userParam;
791
  __taos_async_datetime_whitelist_fn_t userCbFn;
792
} SFetchDateTimeWhiteListInfo;
793

794

795

796
static const char* weekdays[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
797
int32_t fetchDateTimeWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
798
  int32_t lino = 0;
×
799
  char  **pWhiteLists = NULL;
×
800

801
  SUserDateTimeWhiteList wlRsp = {0};
×
802

803
  SFetchDateTimeWhiteListInfo *pInfo = (SFetchDateTimeWhiteListInfo *)param;
×
804
  TAOS *taos = &pInfo->connId;
×
805

806
  if (code != TSDB_CODE_SUCCESS) {
×
807
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
808
    TAOS_CHECK_GOTO(code, &lino, _error);
×
809
  }
810

811
  if ((code = tDeserializeSUserDateTimeWhiteList(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
812
    TAOS_CHECK_GOTO(code, &lino, _error);
×
813
  }
814

815
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
816
  if (pWhiteLists == NULL) {
×
817
    code = terrno;
×
818
    TAOS_CHECK_GOTO(code, &lino, _error);
×
819
  }
820

821
  int32_t numWhiteLists =0;
×
822
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
823
    SDateTimeWhiteListItem *item = &wlRsp.pWhiteLists[i];
×
824

825
    char *p = taosMemCalloc(1, 128);
×
826
    if (p == NULL) {
×
827
      code = terrno;
×
828
      TAOS_CHECK_GOTO(code, &lino, _error);
×
829
    }
830

831
    int duration = item->duration / 60;
×
832

833
    if (item->absolute) {
×
834
      struct STm tm;
×
835
      (void)taosTs2Tm(item->start, TSDB_TIME_PRECISION_SECONDS, &tm, NULL);
×
836
      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);
×
837
    } else {
838
      int day = item->start / 86400;
×
839
      int hour = (item->start % 86400) / 3600;
×
840
      int minute = (item->start % 3600) / 60;
×
841
      snprintf(p, 128, "%c %s %02d:%02d %d", item->neg ? '-' : '+', weekdays[day], hour, minute, duration);
×
842
    }
843
    pWhiteLists[numWhiteLists++] = p;
×
844
  }
845

846
  pInfo->userCbFn(pInfo->userParam, code, taos, numWhiteLists, pWhiteLists);
×
847
_error:
×
848
  if (pWhiteLists != NULL) {
×
849
    for (int32_t i = 0; i < numWhiteLists; i++) {
×
850
      taosMemFree(pWhiteLists[i]);
×
851
    }
852
    taosMemoryFree(pWhiteLists);
×
853
  }
854
  taosMemoryFree(pMsg->pData);
×
855
  taosMemoryFree(pMsg->pEpSet);
×
856
  taosMemoryFree(pInfo);
×
857
  tFreeSUserDateTimeWhiteList(&wlRsp);
×
858
  return code;
×
859
}
860

861

862

863
void taos_fetch_datetime_whitelist_a(TAOS *taos, __taos_async_datetime_whitelist_fn_t fp, void *param) {
×
864
  if (NULL == taos) {
×
865
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
866
    return;
×
867
  }
868
  int64_t connId = *(int64_t *)taos;
×
869

870
  STscObj *pTsc = acquireTscObj(connId);
×
871
  if (NULL == pTsc) {
×
872
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
873
    return;
×
874
  }
875

876
  SGetUserWhiteListReq req;
×
877
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
878
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
879
  if (msgLen < 0) {
×
880
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
881
    releaseTscObj(connId);
×
882
    return;
×
883
  }
884

885
  void *pReq = taosMemoryMalloc(msgLen);
×
886
  if (pReq == NULL) {
×
887
    fp(param, terrno, taos, 0, NULL);
×
888
    releaseTscObj(connId);
×
889
    return;
×
890
  }
891

892
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
893
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
894
    taosMemoryFree(pReq);
×
895
    releaseTscObj(connId);
×
896
    return;
×
897
  }
898

899
  SFetchDateTimeWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchDateTimeWhiteListInfo));
×
900
  if (pParam == NULL) {
×
901
    fp(param, terrno, taos, 0, NULL);
×
902
    taosMemoryFree(pReq);
×
903
    releaseTscObj(connId);
×
904
    return;
×
905
  }
906

907
  pParam->connId = connId;
×
908
  pParam->userCbFn = fp;
×
909
  pParam->userParam = param;
×
910

911
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
912
  if (pSendInfo == NULL) {
×
913
    fp(param, terrno, taos, 0, NULL);
×
914
    taosMemoryFree(pParam);
×
915
    taosMemoryFree(pReq);
×
916
    releaseTscObj(connId);
×
917
    return;
×
918
  }
919

920
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
921
  pSendInfo->requestId = generateRequestId();
×
922
  pSendInfo->requestObjRefId = 0;
×
923
  pSendInfo->param = pParam;
×
924
  pSendInfo->fp = fetchDateTimeWhiteListCallbackFn;
×
925
  pSendInfo->msgType = TDMT_MND_GET_USER_DATETIME_WHITELIST;
×
926

927
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
928
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
929
    tscWarn("failed to async send msg to server");
×
930
  }
931
  releaseTscObj(connId);
×
932
  return;
×
933
}
934

935

936

937
void taos_close_internal(void *taos) {
2,059,873✔
938
  if (taos == NULL) {
2,059,873✔
939
    return;
×
940
  }
941
  int32_t code = 0;
2,059,873✔
942

943
  STscObj *pTscObj = (STscObj *)taos;
2,059,873✔
944
  tscDebug("conn:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
2,059,873✔
945

946
  SSessParam para = {.type = SESSION_PER_USER, .value = -1};
2,059,873✔
947
  code = sessMgtUpdateUserMetric((char *)pTscObj->user, &para);
2,059,873✔
948
  if (code != TSDB_CODE_SUCCESS) {
2,059,873✔
949
    tscWarn("conn:0x%" PRIx64 ", failed to update user:%s metric when close connection, code:%d", pTscObj->id,
×
950
            pTscObj->user, code);
951
  } 
952

953
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
2,059,873✔
954
    tscError("conn:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
×
955
  }
956
}
957

958
void taos_close(TAOS *taos) {
1,939,230✔
959
  if (taos == NULL) {
1,939,230✔
960
    return;
180✔
961
  }
962

963
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
1,939,050✔
964
  if (NULL == pObj) {
1,939,050✔
965
    taosMemoryFree(taos);
×
966
    return;
×
967
  }
968

969
  taos_close_internal(pObj);
1,939,050✔
970
  releaseTscObj(*(int64_t *)taos);
1,939,050✔
971
  taosMemoryFree(taos);
1,939,091✔
972
}
973

974
int taos_errno(TAOS_RES *res) {
1,006,596,554✔
975
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,006,596,554✔
976
    return terrno;
13,548✔
977
  }
978

979
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,006,582,942✔
980
    return 0;
265,303✔
981
  }
982

983
  return ((SRequestObj *)res)->code;
1,006,311,467✔
984
}
985

986
const char *taos_errstr(TAOS_RES *res) {
71,003,328✔
987
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
71,003,328✔
988
    if (*(taosGetErrMsg()) == 0) {
12,669✔
989
      return (const char *)tstrerror(terrno);
12,654✔
990
    } else {
991
      (void)snprintf(taosGetErrMsgReturn(), ERR_MSG_LEN, "%s", taosGetErrMsg());
15✔
992
      return (const char*)taosGetErrMsgReturn();
15✔
993
    }
994
  }
995

996
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
70,990,659✔
997
    return "success";
×
998
  }
999

1000
  SRequestObj *pRequest = (SRequestObj *)res;
70,990,659✔
1001
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
70,990,659✔
1002
    return pRequest->msgBuf;
20,828,378✔
1003
  } else {
1004
    return (const char *)tstrerror(pRequest->code);
50,162,281✔
1005
  }
1006
}
1007

1008
void taos_free_result(TAOS_RES *res) {
765,560,511✔
1009
  if (NULL == res) {
765,560,511✔
1010
    return;
6,540,858✔
1011
  }
1012

1013
  tscTrace("res:%p, will be freed", res);
759,019,653✔
1014

1015
  if (TD_RES_QUERY(res)) {
759,019,653✔
1016
    SRequestObj *pRequest = (SRequestObj *)res;
747,731,967✔
1017
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query, res:%p", pRequest->requestId, res);
747,731,967✔
1018
    destroyRequest(pRequest);
747,731,967✔
1019
    return;
747,729,515✔
1020
  }
1021

1022
  SMqRspObj *pRsp = (SMqRspObj *)res;
11,286,417✔
1023
  if (TD_RES_TMQ(res)) {
11,286,417✔
1024
    tDeleteMqDataRsp(&pRsp->dataRsp);
11,227,645✔
1025
    doFreeReqResultInfo(&pRsp->resInfo);
11,226,987✔
1026
  } else if (TD_RES_TMQ_METADATA(res)) {
63,102✔
1027
    tDeleteSTaosxRsp(&pRsp->dataRsp);
3,222✔
1028
    doFreeReqResultInfo(&pRsp->resInfo);
3,222✔
1029
  } else if (TD_RES_TMQ_META(res)) {
59,880✔
1030
    tDeleteMqMetaRsp(&pRsp->metaRsp);
54,074✔
1031
  } else if (TD_RES_TMQ_BATCH_META(res)) {
5,806✔
1032
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
5,806✔
1033
  } else if (TD_RES_TMQ_RAW(res)) {
×
1034
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
×
1035
  }
1036
  taosMemoryFree(pRsp);
11,289,760✔
1037
}
1038

1039
void taos_kill_query(TAOS *taos) {
360✔
1040
  if (NULL == taos) {
360✔
1041
    return;
180✔
1042
  }
1043

1044
  int64_t  rid = *(int64_t *)taos;
180✔
1045
  STscObj *pTscObj = acquireTscObj(rid);
180✔
1046
  if (pTscObj) {
180✔
1047
    stopAllRequests(pTscObj->pRequests);
180✔
1048
  }
1049
  releaseTscObj(rid);
180✔
1050
}
1051

1052
int taos_field_count(TAOS_RES *res) {
2,147,483,647✔
1053
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1054
    return 0;
×
1055
  }
1056

1057
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1058
  return pResInfo->numOfCols;
2,147,483,647✔
1059
}
1060

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

1063
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
2,147,483,647✔
1064
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1065
    return NULL;
3,182,272✔
1066
  }
1067

1068
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1069
  return pResInfo->userFields;
2,147,483,647✔
1070
}
1071

1072
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
743,950,189✔
1073
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
247✔
1074
  return taosQueryImplWithReqid(taos, sql, false, reqid);
247✔
1075
}
1076

1077
TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res) {
154✔
1078
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
154✔
1079
    return NULL;
×
1080
  }
1081
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
154✔
1082
  return pResInfo->fields;
154✔
1083
}
1084

1085
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
2,147,483,647✔
1086
  if (res == NULL) {
2,147,483,647✔
1087
    return NULL;
×
1088
  }
1089

1090
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1091
    SRequestObj *pRequest = (SRequestObj *)res;
836,723,945✔
1092
    if (pRequest->killed) {
836,723,945✔
1093
      tscInfo("query has been killed, can not fetch more row.");
×
1094
      pRequest->code = TSDB_CODE_TSC_QUERY_KILLED;
×
1095
      return NULL;
×
1096
    }
1097

1098
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
836,723,650✔
1099
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
836,724,893✔
1100
      return NULL;
329✔
1101
    }
1102

1103
    if (pRequest->inCallback) {
836,726,642✔
1104
      tscError("can not call taos_fetch_row before query callback ends.");
×
1105
      terrno = TSDB_CODE_TSC_INVALID_OPERATION;
×
1106
      return NULL;
×
1107
    }
1108

1109
    return doAsyncFetchRows(pRequest, true, true);
836,724,997✔
1110
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
1111
    SMqRspObj      *msg = ((SMqRspObj *)res);
2,147,483,647✔
1112
    SReqResultInfo *pResultInfo = NULL;
2,147,483,647✔
1113
    if (msg->resIter == -1) {
2,147,483,647✔
1114
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
10,945,045✔
1115
        return NULL;
×
1116
      }
1117
    } else {
1118
      pResultInfo = tmqGetCurResInfo(res);
2,147,483,647✔
1119
    }
1120

1121
    if (pResultInfo->current < pResultInfo->numOfRows) {
2,147,483,647✔
1122
      doSetOneRowPtr(pResultInfo);
2,147,483,647✔
1123
      pResultInfo->current += 1;
2,147,483,647✔
1124
      return pResultInfo->row;
2,147,483,647✔
1125
    } else {
1126
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
96,295,539✔
1127
        return NULL;
10,944,059✔
1128
      }
1129

1130
      doSetOneRowPtr(pResultInfo);
85,348,519✔
1131
      pResultInfo->current += 1;
85,350,822✔
1132
      return pResultInfo->row;
85,350,822✔
1133
    }
1134
  } else if (TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1135
    return NULL;
×
1136
  } else {
1137
    tscError("invalid result passed to taos_fetch_row");
×
1138
    terrno = TSDB_CODE_TMQ_INVALID_DATA;
×
1139
    return NULL;
×
1140
  }
1141
}
1142

1143
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
2,147,483,647✔
1144
  return taos_print_row_with_size(str, INT32_MAX, row, fields, num_fields);
2,147,483,647✔
1145
}
1146
int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
2,147,483,647✔
1147
  int32_t len = 0;
2,147,483,647✔
1148
  for (int i = 0; i < num_fields; ++i) {
2,147,483,647✔
1149
    if (i > 0 && len < size - 1) {
2,147,483,647✔
1150
      str[len++] = ' ';
2,147,483,647✔
1151
    }
1152

1153
    if (row[i] == NULL) {
2,147,483,647✔
1154
      len += tsnprintf(str + len, size - len, "%s", TSDB_DATA_NULL_STR);
126,317,215✔
1155
      continue;
126,317,215✔
1156
    }
1157

1158
    switch (fields[i].type) {
2,147,483,647✔
1159
      case TSDB_DATA_TYPE_TINYINT:
12,589,978✔
1160
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
12,589,978✔
1161
        break;
12,613,737✔
1162

1163
      case TSDB_DATA_TYPE_UTINYINT:
56,787✔
1164
        len += tsnprintf(str + len, size - len, "%u", *((uint8_t *)row[i]));
56,787✔
1165
        break;
56,787✔
1166

1167
      case TSDB_DATA_TYPE_SMALLINT:
56,787✔
1168
        len += tsnprintf(str + len, size - len, "%d", *((int16_t *)row[i]));
56,787✔
1169
        break;
56,787✔
1170

1171
      case TSDB_DATA_TYPE_USMALLINT:
56,787✔
1172
        len += tsnprintf(str + len, size - len, "%u", *((uint16_t *)row[i]));
56,787✔
1173
        break;
56,800✔
1174

1175
      case TSDB_DATA_TYPE_INT:
2,147,483,647✔
1176
        len += tsnprintf(str + len, size - len, "%d", *((int32_t *)row[i]));
2,147,483,647✔
1177
        break;
2,147,483,647✔
1178

1179
      case TSDB_DATA_TYPE_UINT:
56,800✔
1180
        len += tsnprintf(str + len, size - len, "%u", *((uint32_t *)row[i]));
56,800✔
1181
        break;
56,800✔
1182

1183
      case TSDB_DATA_TYPE_BIGINT:
2,147,483,647✔
1184
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
2,147,483,647✔
1185
        break;
2,147,483,647✔
1186

1187
      case TSDB_DATA_TYPE_UBIGINT:
56,800✔
1188
        len += tsnprintf(str + len, size - len, "%" PRIu64, *((uint64_t *)row[i]));
56,800✔
1189
        break;
56,800✔
1190

1191
      case TSDB_DATA_TYPE_FLOAT: {
25,129,245✔
1192
        float fv = 0;
25,129,245✔
1193
        fv = GET_FLOAT_VAL(row[i]);
25,129,245✔
1194
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
25,149,489✔
1195
      } break;
25,168,641✔
1196

1197
      case TSDB_DATA_TYPE_DOUBLE: {
2,147,483,647✔
1198
        double dv = 0;
2,147,483,647✔
1199
        dv = GET_DOUBLE_VAL(row[i]);
2,147,483,647✔
1200
        len += snprintf(str + len, size - len, "%.*g", DBL_DIG, dv);
2,147,483,647✔
1201
      } break;
2,147,483,647✔
1202

1203
      case TSDB_DATA_TYPE_VARBINARY: {
56,800✔
1204
        void    *data = NULL;
56,800✔
1205
        uint32_t tmp = 0;
56,800✔
1206
        int32_t  charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
56,800✔
1207
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
56,800✔
1208
          break;
×
1209
        }
1210
        uint32_t copyLen = TMIN(size - len - 1, tmp);
56,774✔
1211
        (void)memcpy(str + len, data, copyLen);
56,774✔
1212
        len += copyLen;
56,774✔
1213
        taosMemoryFree(data);
56,774✔
1214
      } break;
56,787✔
1215
      case TSDB_DATA_TYPE_BINARY:
2,147,483,647✔
1216
      case TSDB_DATA_TYPE_NCHAR:
1217
      case TSDB_DATA_TYPE_GEOMETRY: {
1218
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
2,147,483,647✔
1219
        if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_VARBINARY ||
2,147,483,647✔
1220
            fields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
1,710,046,199✔
1221
          if (charLen > fields[i].bytes || charLen < 0) {
2,147,483,647✔
1222
            tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
11,190✔
1223
            break;
×
1224
          }
1225
        } else {
1226
          if (charLen > fields[i].bytes * TSDB_NCHAR_SIZE || charLen < 0) {
1,709,990,418✔
1227
            tscError("taos_print_row error. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
156✔
1228
            break;
×
1229
          }
1230
        }
1231

1232
        uint32_t copyLen = TMIN(size - len - 1, charLen);
2,147,483,647✔
1233
        (void)memcpy(str + len, row[i], copyLen);
2,147,483,647✔
1234
        len += copyLen;
2,147,483,647✔
1235
      } break;
2,147,483,647✔
1236
      case TSDB_DATA_TYPE_BLOB:
×
1237
      case TSDB_DATA_TYPE_MEDIUMBLOB: {
1238
        void    *data = NULL;
×
1239
        uint32_t tmp = 0;
×
1240
        int32_t  charLen = blobDataLen((char *)row[i] - BLOBSTR_HEADER_SIZE);
×
1241
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
×
1242
          break;
×
1243
        }
1244

1245
        uint32_t copyLen = TMIN(size - len - 1, tmp);
×
1246
        (void)memcpy(str + len, data, copyLen);
×
1247
        len += copyLen;
×
1248

1249
        taosMemoryFree(data);
×
1250
      } break;
×
1251

1252
      case TSDB_DATA_TYPE_TIMESTAMP:
2,147,483,647✔
1253
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
2,147,483,647✔
1254
        break;
2,147,483,647✔
1255

1256
      case TSDB_DATA_TYPE_BOOL:
56,761✔
1257
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
56,761✔
1258
        break;
56,787✔
1259
      case TSDB_DATA_TYPE_DECIMAL64:
×
1260
      case TSDB_DATA_TYPE_DECIMAL: {
1261
        uint32_t decimalLen = strlen(row[i]);
×
1262
        uint32_t copyLen = TMIN(size - len - 1, decimalLen);
×
1263
        (void)memcpy(str + len, row[i], copyLen);
×
1264
        len += copyLen;
×
1265
      } break;
×
1266
      default:
×
1267
        break;
×
1268
    }
1269

1270
    if (len >= size - 1) {
2,147,483,647✔
1271
      break;
×
1272
    }
1273
  }
1274
  if (len < size) {
2,147,483,647✔
1275
    str[len] = 0;
2,147,483,647✔
1276
  }
1277

1278
  return len;
2,147,483,647✔
1279
}
1280

1281
int *taos_fetch_lengths(TAOS_RES *res) {
2,147,483,647✔
1282
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1283
    return NULL;
×
1284
  }
1285

1286
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1287
  return pResInfo->length;
2,147,483,647✔
1288
}
1289

1290
TAOS_ROW *taos_result_block(TAOS_RES *res) {
×
1291
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1292
    terrno = TSDB_CODE_INVALID_PARA;
×
1293
    return NULL;
×
1294
  }
1295

1296
  if (taos_is_update_query(res)) {
×
1297
    return NULL;
×
1298
  }
1299

1300
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
1301
  return &pResInfo->row;
×
1302
}
1303

1304
// todo intergrate with tDataTypes
1305
const char *taos_data_type(int type) {
×
1306
  switch (type) {
×
1307
    case TSDB_DATA_TYPE_NULL:
×
1308
      return "TSDB_DATA_TYPE_NULL";
×
1309
    case TSDB_DATA_TYPE_BOOL:
×
1310
      return "TSDB_DATA_TYPE_BOOL";
×
1311
    case TSDB_DATA_TYPE_TINYINT:
×
1312
      return "TSDB_DATA_TYPE_TINYINT";
×
1313
    case TSDB_DATA_TYPE_SMALLINT:
×
1314
      return "TSDB_DATA_TYPE_SMALLINT";
×
1315
    case TSDB_DATA_TYPE_INT:
×
1316
      return "TSDB_DATA_TYPE_INT";
×
1317
    case TSDB_DATA_TYPE_BIGINT:
×
1318
      return "TSDB_DATA_TYPE_BIGINT";
×
1319
    case TSDB_DATA_TYPE_FLOAT:
×
1320
      return "TSDB_DATA_TYPE_FLOAT";
×
1321
    case TSDB_DATA_TYPE_DOUBLE:
×
1322
      return "TSDB_DATA_TYPE_DOUBLE";
×
1323
    case TSDB_DATA_TYPE_VARCHAR:
×
1324
      return "TSDB_DATA_TYPE_VARCHAR";
×
1325
      //    case TSDB_DATA_TYPE_BINARY:          return "TSDB_DATA_TYPE_VARCHAR";
1326
    case TSDB_DATA_TYPE_TIMESTAMP:
×
1327
      return "TSDB_DATA_TYPE_TIMESTAMP";
×
1328
    case TSDB_DATA_TYPE_NCHAR:
×
1329
      return "TSDB_DATA_TYPE_NCHAR";
×
1330
    case TSDB_DATA_TYPE_JSON:
×
1331
      return "TSDB_DATA_TYPE_JSON";
×
1332
    case TSDB_DATA_TYPE_GEOMETRY:
×
1333
      return "TSDB_DATA_TYPE_GEOMETRY";
×
1334
    case TSDB_DATA_TYPE_UTINYINT:
×
1335
      return "TSDB_DATA_TYPE_UTINYINT";
×
1336
    case TSDB_DATA_TYPE_USMALLINT:
×
1337
      return "TSDB_DATA_TYPE_USMALLINT";
×
1338
    case TSDB_DATA_TYPE_UINT:
×
1339
      return "TSDB_DATA_TYPE_UINT";
×
1340
    case TSDB_DATA_TYPE_UBIGINT:
×
1341
      return "TSDB_DATA_TYPE_UBIGINT";
×
1342
    case TSDB_DATA_TYPE_VARBINARY:
×
1343
      return "TSDB_DATA_TYPE_VARBINARY";
×
1344
    case TSDB_DATA_TYPE_DECIMAL:
×
1345
      return "TSDB_DATA_TYPE_DECIMAL";
×
1346
    case TSDB_DATA_TYPE_BLOB:
×
1347
      return "TSDB_DATA_TYPE_BLOB";
×
1348
    case TSDB_DATA_TYPE_MEDIUMBLOB:
×
1349
      return "TSDB_DATA_TYPE_MEDIUMBLOB";
×
1350
    default:
×
1351
      return "UNKNOWN";
×
1352
  }
1353
}
1354

1355
const char *taos_get_client_info() { return td_version; }
770,424✔
1356

1357
// return int32_t
1358
int taos_affected_rows(TAOS_RES *res) {
532,859,235✔
1359
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
532,859,235✔
1360
      TD_RES_TMQ_BATCH_META(res)) {
532,860,512✔
1361
    return 0;
×
1362
  }
1363

1364
  SRequestObj    *pRequest = (SRequestObj *)res;
532,859,291✔
1365
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
532,859,291✔
1366
  return (int)pResInfo->numOfRows;
532,860,188✔
1367
}
1368

1369
// return int64_t
1370
int64_t taos_affected_rows64(TAOS_RES *res) {
1,253,472✔
1371
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,253,472✔
1372
      TD_RES_TMQ_BATCH_META(res)) {
1,253,472✔
1373
    return 0;
×
1374
  }
1375

1376
  SRequestObj    *pRequest = (SRequestObj *)res;
1,253,472✔
1377
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
1,253,472✔
1378
  return pResInfo->numOfRows;
1,253,472✔
1379
}
1380

1381
int taos_result_precision(TAOS_RES *res) {
2,147,483,647✔
1382
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1383
    return TSDB_TIME_PRECISION_MILLI;
×
1384
  }
1385

1386
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1387
    SRequestObj *pRequest = (SRequestObj *)res;
114,962,898✔
1388
    return pRequest->body.resInfo.precision;
114,962,898✔
1389
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
1390
    SReqResultInfo *info = tmqGetCurResInfo(res);
2,147,483,647✔
1391
    return info->precision;
2,147,483,647✔
1392
  }
1393
  return TSDB_TIME_PRECISION_MILLI;
×
1394
}
1395

1396
int taos_select_db(TAOS *taos, const char *db) {
36,642✔
1397
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
36,642✔
1398
  if (pObj == NULL) {
36,642✔
1399
    releaseTscObj(*(int64_t *)taos);
×
1400
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1401
    return TSDB_CODE_TSC_DISCONNECTED;
×
1402
  }
1403

1404
  if (db == NULL || strlen(db) == 0) {
36,642✔
1405
    releaseTscObj(*(int64_t *)taos);
45✔
1406
    tscError("invalid parameter for %s", db == NULL ? "db is NULL" : "db is empty");
×
1407
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
1408
    return terrno;
×
1409
  }
1410

1411
  char sql[256] = {0};
36,642✔
1412
  (void)snprintf(sql, tListLen(sql), "use %s", db);
36,642✔
1413

1414
  TAOS_RES *pRequest = taos_query(taos, sql);
36,642✔
1415
  int32_t   code = taos_errno(pRequest);
36,684✔
1416

1417
  taos_free_result(pRequest);
36,627✔
1418
  releaseTscObj(*(int64_t *)taos);
36,684✔
1419
  return code;
36,687✔
1420
}
1421

1422
void taos_stop_query(TAOS_RES *res) {
750,257,784✔
1423
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
750,257,784✔
1424
      TD_RES_TMQ_BATCH_META(res)) {
750,260,523✔
UNCOV
1425
    return;
×
1426
  }
1427

1428
  stopAllQueries((SRequestObj *)res);
750,259,205✔
1429
}
1430

1431
bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
×
1432
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1433
    return true;
×
1434
  }
1435
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
×
1436
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
×
1437
    return true;
×
1438
  }
1439

1440
  SResultColumn *pCol = &pResultInfo->pCol[col];
×
1441
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
×
1442
    return (pCol->offset[row] == -1);
×
1443
  } else {
1444
    return colDataIsNull_f(pCol, row);
×
1445
  }
1446
}
1447

1448
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
282,729✔
1449

1450
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
198,431,675✔
1451
  int32_t numOfRows = 0;
198,431,675✔
1452
  /*int32_t code = */ terrno = taos_fetch_block_s(res, &numOfRows, rows);
198,431,675✔
1453
  return numOfRows;
198,431,675✔
1454
}
1455

1456
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
198,431,675✔
1457
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
198,431,675✔
1458
    return 0;
×
1459
  }
1460

1461
  if (TD_RES_QUERY(res)) {
198,431,675✔
1462
    SRequestObj *pRequest = (SRequestObj *)res;
190,898,383✔
1463

1464
    (*rows) = NULL;
190,898,383✔
1465
    (*numOfRows) = 0;
190,898,383✔
1466

1467
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
190,898,383✔
1468
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
190,597,240✔
1469
      return pRequest->code;
1,265,543✔
1470
    }
1471

1472
    (void)doAsyncFetchRows(pRequest, false, true);
189,632,840✔
1473

1474
    // TODO refactor
1475
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
189,632,840✔
1476
    pResultInfo->current = pResultInfo->numOfRows;
189,632,840✔
1477

1478
    (*rows) = pResultInfo->row;
189,632,840✔
1479
    (*numOfRows) = pResultInfo->numOfRows;
189,632,840✔
1480
    return pRequest->code;
189,632,358✔
1481
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
7,533,292✔
1482
    SReqResultInfo *pResultInfo = NULL;
7,533,292✔
1483
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
7,533,292✔
1484
    if (code != 0) return code;
7,533,292✔
1485

1486
    pResultInfo->current = pResultInfo->numOfRows;
7,276,230✔
1487
    (*rows) = pResultInfo->row;
7,276,230✔
1488
    (*numOfRows) = pResultInfo->numOfRows;
7,276,230✔
1489
    return 0;
7,275,882✔
1490
  } else {
1491
    tscError("taos_fetch_block_s invalid res type");
×
1492
    return TSDB_CODE_TMQ_INVALID_DATA;
×
1493
  }
1494
}
1495

1496
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
55,644✔
1497
  *numOfRows = 0;
55,644✔
1498
  *pData = NULL;
55,644✔
1499

1500
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
55,644✔
1501
    return 0;
×
1502
  }
1503

1504
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
55,644✔
1505
    SReqResultInfo *pResultInfo = NULL;
52,539✔
1506
    int32_t         code = tmqGetNextResInfo(res, false, &pResultInfo);
52,539✔
1507
    if (code != 0) {
52,539✔
1508
      (*numOfRows) = 0;
800✔
1509
      return 0;
800✔
1510
    }
1511

1512
    pResultInfo->current = pResultInfo->numOfRows;
51,739✔
1513
    (*numOfRows) = pResultInfo->numOfRows;
51,739✔
1514
    (*pData) = (void *)pResultInfo->pData;
51,739✔
1515
    return 0;
51,739✔
1516
  }
1517

1518
  SRequestObj *pRequest = (SRequestObj *)res;
3,105✔
1519

1520
  if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
3,105✔
1521
      pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
3,105✔
1522
    return pRequest->code;
×
1523
  }
1524

1525
  (void)doAsyncFetchRows(pRequest, false, false);
3,105✔
1526

1527
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
3,105✔
1528

1529
  pResultInfo->current = pResultInfo->numOfRows;
3,105✔
1530
  (*numOfRows) = pResultInfo->numOfRows;
3,105✔
1531
  (*pData) = (void *)pResultInfo->pData;
3,105✔
1532

1533
  return pRequest->code;
3,105✔
1534
}
1535

1536
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
118,635,874✔
1537
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
118,635,874✔
1538
    return 0;
×
1539
  }
1540

1541
  int32_t numOfFields = taos_num_fields(res);
118,635,874✔
1542
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
118,635,874✔
1543
    return 0;
×
1544
  }
1545

1546
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
118,635,874✔
1547
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
118,635,874✔
1548
  if (!IS_VAR_DATA_TYPE(pField->type)) {
118,635,874✔
1549
    return 0;
×
1550
  }
1551

1552
  return pResInfo->pCol[columnIndex].offset;
118,635,874✔
1553
}
1554

1555
int taos_is_null_by_column(TAOS_RES *res, int columnIndex, bool result[], int *rows) {
336,554,563✔
1556
  if (res == NULL || result == NULL || rows == NULL || *rows <= 0 || columnIndex < 0 || TD_RES_TMQ_META(res) ||
336,554,563✔
1557
      TD_RES_TMQ_RAW(res) || TD_RES_TMQ_BATCH_META(res)) {
336,554,563✔
1558
    return TSDB_CODE_INVALID_PARA;
×
1559
  }
1560

1561
  int32_t numOfFields = taos_num_fields(res);
336,554,563✔
1562
  if (columnIndex >= numOfFields || numOfFields == 0) {
336,554,563✔
1563
    return TSDB_CODE_INVALID_PARA;
×
1564
  }
1565

1566
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
336,554,563✔
1567
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
336,554,563✔
1568
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
336,553,587✔
1569

1570
  if (*rows > pResInfo->numOfRows) {
336,554,563✔
1571
    *rows = pResInfo->numOfRows;
×
1572
  }
1573
  if (IS_VAR_DATA_TYPE(pField->type)) {
336,554,563✔
1574
    for (int i = 0; i < *rows; i++) {
×
1575
      if (pCol->offset[i] == -1) {
×
1576
        result[i] = true;
×
1577
      } else {
1578
        result[i] = false;
×
1579
      }
1580
    }
1581
  } else {
1582
    for (int i = 0; i < *rows; i++) {
2,147,483,647✔
1583
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1584
        result[i] = true;
2,147,483,647✔
1585
      } else {
1586
        result[i] = false;
2,147,483,647✔
1587
      }
1588
    }
1589
  }
1590
  return 0;
336,554,563✔
1591
}
1592

1593
int taos_validate_sql(TAOS *taos, const char *sql) {
×
1594
  TAOS_RES *pObj = taosQueryImpl(taos, sql, true, TD_REQ_FROM_APP);
×
1595

1596
  int code = taos_errno(pObj);
×
1597

1598
  taos_free_result(pObj);
×
1599
  return code;
×
1600
}
1601

1602
void taos_reset_current_db(TAOS *taos) {
×
1603
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
1604
  if (pTscObj == NULL) {
×
1605
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1606
    return;
×
1607
  }
1608

1609
  resetConnectDB(pTscObj);
×
1610

1611
  releaseTscObj(*(int64_t *)taos);
×
1612
}
1613

1614
const char *taos_get_server_info(TAOS *taos) {
4,890✔
1615
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
4,890✔
1616
  if (pTscObj == NULL) {
4,890✔
1617
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1618
    return NULL;
×
1619
  }
1620

1621
  releaseTscObj(*(int64_t *)taos);
4,890✔
1622

1623
  return pTscObj->sDetailVer;
4,890✔
1624
}
1625

1626
int taos_get_current_db(TAOS *taos, char *database, int len, int *required) {
2,216✔
1627
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
2,216✔
1628
  if (pTscObj == NULL) {
2,216✔
1629
    return TSDB_CODE_TSC_DISCONNECTED;
×
1630
  }
1631

1632
  int code = TSDB_CODE_SUCCESS;
2,216✔
1633
  (void)taosThreadMutexLock(&pTscObj->mutex);
2,216✔
1634
  if (database == NULL || len <= 0) {
2,216✔
1635
    if (required != NULL) *required = strlen(pTscObj->db) + 1;
1,108✔
1636
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
1,108✔
1637
  } else if (len < strlen(pTscObj->db) + 1) {
1,108✔
1638
    tstrncpy(database, pTscObj->db, len);
554✔
1639
    if (required) *required = strlen(pTscObj->db) + 1;
554✔
1640
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
554✔
1641
  } else {
1642
    tstrncpy(database, pTscObj->db, len);
554✔
1643
    code = 0;
554✔
1644
  }
1645
_return:
2,216✔
1646
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
2,216✔
1647
  releaseTscObj(*(int64_t *)taos);
2,216✔
1648
  return code;
2,216✔
1649
}
1650

1651
// buffer is allocated by caller, len is in/out parameter, input is buffer length, output is actual length.
1652
// because this is a general purpose api, buffer is not null-terminated string even for string info, and
1653
// the return length is the actual length of the info, not including null-terminator.
1654
int taos_get_connection_info(TAOS *taos, TSDB_CONNECTION_INFO info, char* buffer, int* len) {
×
1655
  if (len == NULL) {
×
1656
    return TSDB_CODE_INVALID_PARA;
×
1657
  }
1658

1659
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
1660
  if (pTscObj == NULL) {
×
1661
    return TSDB_CODE_TSC_DISCONNECTED;
×
1662
  }
1663

1664
  int code = TSDB_CODE_SUCCESS;
×
1665
  (void)taosThreadMutexLock(&pTscObj->mutex);
×
1666

1667
  switch (info) {
×
1668
    case TSDB_CONNECTION_INFO_USER: {
×
1669
      int userLen = strlen(pTscObj->user);
×
1670
      if (buffer == NULL || *len < userLen) {
×
1671
        *len = userLen;
×
1672
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1673
      } else {
1674
        *len = userLen;
×
1675
        (void)memcpy(buffer, pTscObj->user, userLen);
×
1676
      }
1677
      break;
×
1678
    }
1679

1680
    case TSDB_CONNECTION_INFO_TOKEN: {
×
1681
      int tokenLen = strlen(pTscObj->tokenName);
×
1682
      if (tokenLen == 0) {
×
1683
        *len = 0;
×
1684
      } else if (buffer == NULL || *len < tokenLen) {
×
1685
        *len = tokenLen;
×
1686
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1687
      } else {
1688
        *len = tokenLen;
×
1689
        (void)memcpy(buffer, pTscObj->tokenName, tokenLen);
×
1690
      }
1691
      break;
×
1692
    }
1693

1694
    default:
×
1695
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1696
  }
1697

1698
_return:
×
1699
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
×
1700
  releaseTscObj(*(int64_t *)taos);
×
1701
  return code;
×
1702
}
1703

1704
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
1,497,960,438✔
1705
  if (NULL == pWrapper) {
1,497,960,438✔
1706
    return;
752,372,251✔
1707
  }
1708
  destoryCatalogReq(pWrapper->pCatalogReq);
745,588,187✔
1709
  taosMemoryFree(pWrapper->pCatalogReq);
745,579,770✔
1710
  qDestroyParseContext(pWrapper->pParseCtx);
745,581,766✔
1711
  taosMemoryFree(pWrapper);
745,571,219✔
1712
}
1713

1714
void destroyCtxInRequest(SRequestObj *pRequest) {
2,192,236✔
1715
  schedulerFreeJob(&pRequest->body.queryJob, 0);
2,192,236✔
1716
  qDestroyQuery(pRequest->pQuery);
2,192,277✔
1717
  pRequest->pQuery = NULL;
2,192,277✔
1718
  destorySqlCallbackWrapper(pRequest->pWrapper);
2,192,236✔
1719
  pRequest->pWrapper = NULL;
2,192,236✔
1720
}
2,192,236✔
1721

1722
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
250,958,021✔
1723
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
250,958,021✔
1724
  SRequestObj         *pRequest = pWrapper->pRequest;
250,958,021✔
1725
  SQuery              *pQuery = pRequest->pQuery;
250,958,087✔
1726

1727
  qDebug("req:0x%" PRIx64 ", start to semantic analysis, QID:0x%" PRIx64, pRequest->self, pRequest->requestId);
250,958,154✔
1728

1729
  int64_t analyseStart = taosGetTimestampUs();
250,958,227✔
1730
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
250,958,227✔
1731
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
250,958,480✔
1732

1733
  if (TSDB_CODE_SUCCESS == code) {
250,958,522✔
1734
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
250,957,495✔
1735
  }
1736

1737
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
250,948,986✔
1738

1739
  if (pRequest->parseOnly) {
250,955,548✔
1740
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
7,326✔
1741
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
7,326✔
1742
  }
1743

1744
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
250,954,679✔
1745
}
250,949,188✔
1746

1747
int32_t cloneCatalogReq(SCatalogReq **ppTarget, SCatalogReq *pSrc) {
×
1748
  int32_t      code = TSDB_CODE_SUCCESS;
×
1749
  SCatalogReq *pTarget = taosMemoryCalloc(1, sizeof(SCatalogReq));
×
1750
  if (pTarget == NULL) {
×
1751
    code = terrno;
×
1752
  } else {
1753
    pTarget->pDbVgroup = taosArrayDup(pSrc->pDbVgroup, NULL);
×
1754
    pTarget->pDbCfg = taosArrayDup(pSrc->pDbCfg, NULL);
×
1755
    pTarget->pDbInfo = taosArrayDup(pSrc->pDbInfo, NULL);
×
1756
    pTarget->pTableMeta = taosArrayDup(pSrc->pTableMeta, NULL);
×
1757
    pTarget->pTableHash = taosArrayDup(pSrc->pTableHash, NULL);
×
1758
    pTarget->pUdf = taosArrayDup(pSrc->pUdf, NULL);
×
1759
    pTarget->pIndex = taosArrayDup(pSrc->pIndex, NULL);
×
1760
    pTarget->pUser = taosArrayDup(pSrc->pUser, NULL);
×
1761
    pTarget->pTableIndex = taosArrayDup(pSrc->pTableIndex, NULL);
×
1762
    pTarget->pTableCfg = taosArrayDup(pSrc->pTableCfg, NULL);
×
1763
    pTarget->pTableTag = taosArrayDup(pSrc->pTableTag, NULL);
×
1764
    pTarget->pView = taosArrayDup(pSrc->pView, NULL);
×
1765
    pTarget->pTableTSMAs = taosArrayDup(pSrc->pTableTSMAs, NULL);
×
1766
    pTarget->pTSMAs = taosArrayDup(pSrc->pTSMAs, NULL);
×
1767
    pTarget->pVStbRefDbs = taosArrayDup(pSrc->pVStbRefDbs, NULL);
×
1768
    pTarget->qNodeRequired = pSrc->qNodeRequired;
×
1769
    pTarget->dNodeRequired = pSrc->dNodeRequired;
×
1770
    pTarget->svrVerRequired = pSrc->svrVerRequired;
×
1771
    pTarget->forceUpdate = pSrc->forceUpdate;
×
1772
    pTarget->cloned = true;
×
1773

1774
    *ppTarget = pTarget;
×
1775
  }
1776

1777
  return code;
×
1778
}
1779

1780
void handleSubQueryFromAnalyse(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, SNode *pRoot) {
×
1781
  SRequestObj         *pNewRequest = NULL;
×
1782
  SSqlCallbackWrapper *pNewWrapper = NULL;
×
1783
  int32_t              code = buildPreviousRequest(pWrapper->pRequest, pWrapper->pRequest->sqlstr, &pNewRequest);
×
1784
  if (code) {
×
1785
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1786
    return;
×
1787
  }
1788

1789
  pNewRequest->pQuery = NULL;
×
1790
  code = nodesMakeNode(QUERY_NODE_QUERY, (SNode **)&pNewRequest->pQuery);
×
1791
  if (pNewRequest->pQuery) {
×
1792
    pNewRequest->pQuery->pRoot = pRoot;
×
1793
    pRoot = NULL;
×
1794
    pNewRequest->pQuery->execStage = QUERY_EXEC_STAGE_ANALYSE;
×
1795
  }
1796
  if (TSDB_CODE_SUCCESS == code) {
×
1797
    code = prepareAndParseSqlSyntax(&pNewWrapper, pNewRequest, false);
×
1798
  }
1799
  if (TSDB_CODE_SUCCESS == code) {
×
1800
    code = cloneCatalogReq(&pNewWrapper->pCatalogReq, pWrapper->pCatalogReq);
×
1801
  }
1802
  if (TSDB_CODE_SUCCESS == code) {
×
1803
    doAsyncQueryFromAnalyse(pResultMeta, pNewWrapper, code);
×
1804
    nodesDestroyNode(pRoot);
×
1805
  } else {
1806
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1807
    return;
×
1808
  }
1809
}
1810

1811
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
250,945,413✔
1812
  SRequestObj *pRequest = pWrapper->pRequest;
250,945,413✔
1813
  SQuery      *pQuery = pRequest->pQuery;
250,954,366✔
1814

1815
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
250,948,875✔
1816
    SNode *prevRoot = pQuery->pPrevRoot;
×
1817
    pQuery->pPrevRoot = NULL;
×
1818
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
×
1819
    return;
×
1820
  }
1821

1822
  if (code == TSDB_CODE_SUCCESS) {
250,951,526✔
1823
    pRequest->stableQuery = pQuery->stableQuery;
200,231,168✔
1824
    if (pQuery->pRoot) {
200,227,508✔
1825
      pRequest->stmtType = pQuery->pRoot->type;
200,224,405✔
1826
    }
1827

1828
    if (pQuery->haveResultSet) {
200,224,559✔
1829
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema,
125,748,924✔
1830
                              pRequest->stmtBindVersion > 0);
125,748,444✔
1831
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
125,748,930✔
1832
    }
1833
  }
1834

1835
  if (code == TSDB_CODE_SUCCESS) {
250,944,453✔
1836
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
200,226,056✔
1837
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
200,222,742✔
1838
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
200,231,544✔
1839

1840
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
200,223,269✔
1841
  } else {
1842
    destorySqlCallbackWrapper(pWrapper);
50,718,397✔
1843
    pRequest->pWrapper = NULL;
50,718,397✔
1844
    qDestroyQuery(pRequest->pQuery);
50,718,438✔
1845
    pRequest->pQuery = NULL;
50,718,438✔
1846

1847
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
50,718,397✔
1848
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
2,121,709✔
1849
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1850
      restartAsyncQuery(pRequest, code);
2,121,709✔
1851
      return;
2,121,709✔
1852
    }
1853

1854
    // return to app directly
1855
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self,
48,596,688✔
1856
             tstrerror(code), pRequest->requestId);
1857
    pRequest->code = code;
48,596,688✔
1858
    returnToUser(pRequest);
48,596,729✔
1859
  }
1860
}
1861

1862
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
257,412,678✔
1863
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
514,389,391✔
1864
                           .requestId = pWrapper->pParseCtx->requestId,
257,416,156✔
1865
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
257,421,943✔
1866
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
257,416,752✔
1867

1868
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
514,388,696✔
1869

1870
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
257,859,059✔
1871
                                &pWrapper->pRequest->body.queryJob);
257,414,450✔
1872
}
1873

1874
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1875

1876
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
742,715,649✔
1877
  int32_t code = TSDB_CODE_SUCCESS;
742,715,649✔
1878
  switch (pWrapper->pRequest->pQuery->execStage) {
742,715,649✔
1879
    case QUERY_EXEC_STAGE_PARSE: {
6,472,138✔
1880
      // continue parse after get metadata
1881
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
6,472,138✔
1882
      break;
6,472,249✔
1883
    }
1884
    case QUERY_EXEC_STAGE_ANALYSE: {
250,949,481✔
1885
      // analysis after get metadata
1886
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
250,949,481✔
1887
      break;
250,951,199✔
1888
    }
1889
    case QUERY_EXEC_STAGE_SCHEDULE: {
485,308,498✔
1890
      launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper);
485,308,498✔
1891
      break;
485,306,901✔
1892
    }
1893
    default:
×
1894
      break;
×
1895
  }
1896
  return code;
742,730,335✔
1897
}
1898

1899
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
6,472,249✔
1900
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
6,472,249✔
1901
  SRequestObj         *pRequest = pWrapper->pRequest;
6,472,249✔
1902
  SQuery              *pQuery = pRequest->pQuery;
6,472,249✔
1903

1904
  pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart;
6,472,249✔
1905
  qDebug("req:0x%" PRIx64 ", continue parse query, QID:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId,
6,472,249✔
1906
         tstrerror(code));
1907

1908
  if (code == TSDB_CODE_SUCCESS) {
6,472,249✔
1909
    // pWrapper->pCatalogReq->forceUpdate = false;
1910
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
6,434,665✔
1911
  }
1912

1913
  if (TSDB_CODE_SUCCESS == code) {
6,472,249✔
1914
    code = phaseAsyncQuery(pWrapper);
5,937,429✔
1915
  }
1916

1917
  if (TSDB_CODE_SUCCESS != code) {
6,472,249✔
1918
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
534,820✔
1919
             tstrerror(code), pWrapper->pRequest->requestId);
1920
    destorySqlCallbackWrapper(pWrapper);
534,820✔
1921
    pRequest->pWrapper = NULL;
534,820✔
1922
    terrno = code;
534,820✔
1923
    pRequest->code = code;
534,820✔
1924
    doRequestCallback(pRequest, code);
534,820✔
1925
  }
1926
}
6,472,249✔
1927

1928
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
10,941✔
1929
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
10,941✔
1930
  if (TSDB_CODE_SUCCESS == code) {
10,941✔
1931
    code = phaseAsyncQuery(pWrapper);
10,941✔
1932
  }
1933

1934
  if (TSDB_CODE_SUCCESS != code) {
10,941✔
1935
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
×
1936
             tstrerror(code), pWrapper->pRequest->requestId);
1937
    destorySqlCallbackWrapper(pWrapper);
×
1938
    pRequest->pWrapper = NULL;
×
1939
    terrno = code;
×
1940
    pRequest->code = code;
×
1941
    doRequestCallback(pRequest, code);
×
1942
  }
1943
}
10,941✔
1944

1945
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
120,106✔
1946
  int64_t connId = *(int64_t *)taos;
120,106✔
1947
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
120,106✔
1948
}
120,106✔
1949

1950
void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) {
×
1951
  int64_t connId = *(int64_t *)taos;
×
1952
  taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid);
×
1953
}
×
1954

1955
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
745,589,833✔
1956
  const STscObj *pTscObj = pRequest->pTscObj;
745,589,833✔
1957

1958
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
745,592,082✔
1959
  if (*pCxt == NULL) {
745,587,498✔
1960
    return terrno;
×
1961
  }
1962

1963
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
1,488,531,218✔
1964
                           .requestRid = pRequest->self,
745,589,544✔
1965
                           .acctId = pTscObj->acctId,
745,590,380✔
1966
                           .db = pRequest->pDb,
745,591,573✔
1967
                           .topicQuery = false,
1968
                           .pSql = pRequest->sqlstr,
745,591,763✔
1969
                           .sqlLen = pRequest->sqlLen,
745,591,460✔
1970
                           .pMsg = pRequest->msgBuf,
745,589,981✔
1971
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
1972
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
745,592,719✔
1973
                           .pStmtCb = NULL,
1974
                           .pUser = pTscObj->user,
745,591,234✔
1975
                           .userId = pTscObj->userId,
745,591,884✔
1976
                           .pEffectiveUser = pRequest->effectiveUser,
745,590,030✔
1977
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
745,591,615✔
1978
                           .enableSysInfo = pTscObj->sysInfo,
745,591,151✔
1979
                           .async = true,
1980
                           .svrVer = pTscObj->sVer,
745,593,349✔
1981
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
745,591,050✔
1982
                           .allocatorId = pRequest->allocatorRefId,
745,592,845✔
1983
                           .parseSqlFp = clientParseSql,
1984
                           .parseSqlParam = pWrapper,
1985
                           .setQueryFp = setQueryRequest,
1986
                           .timezone = pTscObj->optionInfo.timezone,
745,589,341✔
1987
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
745,589,000✔
1988
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
745,589,853✔
1989
  (*pCxt)->biMode = biMode;
745,587,205✔
1990
  return TSDB_CODE_SUCCESS;
745,590,623✔
1991
}
1992

1993
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
745,588,563✔
1994
  int32_t              code = TSDB_CODE_SUCCESS;
745,588,563✔
1995
  STscObj             *pTscObj = pRequest->pTscObj;
745,588,563✔
1996
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
745,592,278✔
1997
  if (pWrapper == NULL) {
745,588,314✔
UNCOV
1998
    code = terrno;
×
1999
  } else {
2000
    pWrapper->pRequest = pRequest;
745,588,314✔
2001
    pRequest->pWrapper = pWrapper;
745,587,054✔
2002
    *ppWrapper = pWrapper;
745,591,123✔
2003
  }
2004

2005
  if (TSDB_CODE_SUCCESS == code) {
745,587,510✔
2006
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
745,588,798✔
2007
  }
2008

2009
  if (TSDB_CODE_SUCCESS == code) {
745,590,567✔
2010
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
745,590,567✔
2011
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
745,592,475✔
2012
  }
2013

2014
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
745,591,071✔
2015
    int64_t syntaxStart = taosGetTimestampUs();
745,592,507✔
2016

2017
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
745,592,507✔
2018
    if (pWrapper->pCatalogReq == NULL) {
745,583,408✔
UNCOV
2019
      code = terrno;
×
2020
    } else {
2021
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
745,585,817✔
2022
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
745,588,503✔
2023
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
745,586,176✔
2024
    }
2025

2026
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
745,588,517✔
2027
  }
2028

2029
  return code;
745,593,372✔
2030
}
2031

2032
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
746,296,287✔
2033
  SSqlCallbackWrapper *pWrapper = NULL;
746,296,287✔
2034
  int32_t              code = TSDB_CODE_SUCCESS;
746,299,648✔
2035

2036
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
746,299,648✔
2037
    code = pRequest->prevCode;
707,414✔
2038
    terrno = code;
707,414✔
2039
    pRequest->code = code;
707,414✔
2040
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
707,414✔
2041
    doRequestCallback(pRequest, code);
707,414✔
2042
    return;
707,414✔
2043
  }
2044

2045
  if (TSDB_CODE_SUCCESS == code) {
745,590,271✔
2046
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
745,588,635✔
2047
  }
2048

2049
  if (TSDB_CODE_SUCCESS == code) {
745,584,508✔
2050
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
736,783,580✔
2051
    code = phaseAsyncQuery(pWrapper);
736,771,419✔
2052
  }
2053

2054
  if (TSDB_CODE_SUCCESS != code) {
745,582,168✔
2055
    if (NULL != pRequest->msgBuf && strlen(pRequest->msgBuf) > 0) {
8,801,416✔
2056
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, pRequest->msgBuf,
8,736,432✔
2057
               pRequest->requestId);
2058
    } else {
2059
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
64,984✔
2060
               pRequest->requestId);
2061
    }
2062

2063
    destorySqlCallbackWrapper(pWrapper);
8,801,416✔
2064
    pRequest->pWrapper = NULL;
8,801,416✔
2065
    qDestroyQuery(pRequest->pQuery);
8,801,416✔
2066
    pRequest->pQuery = NULL;
8,801,416✔
2067

2068
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
8,801,416✔
2069
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
10,119✔
2070
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
2071
      code = refreshMeta(pRequest->pTscObj, pRequest);
10,119✔
2072
      if (code != 0) {
10,119✔
2073
        tscWarn("req:0x%" PRIx64 ", refresh meta failed, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code,
10,119✔
2074
                tstrerror(code), pRequest->requestId);
2075
      }
2076
      pRequest->prevCode = code;
10,119✔
2077
      doAsyncQuery(pRequest, true);
10,119✔
2078
      return;
10,119✔
2079
    }
2080

2081
    terrno = code;
8,791,297✔
2082
    pRequest->code = code;
8,791,297✔
2083
    doRequestCallback(pRequest, code);
8,791,297✔
2084
  }
2085
}
2086

2087
void restartAsyncQuery(SRequestObj *pRequest, int32_t code) {
2,192,236✔
2088
  tscInfo("restart request:%s p:%p", pRequest->sqlstr, pRequest);
2,192,236✔
2089
  SRequestObj *pUserReq = pRequest;
2,192,236✔
2090
  (void)acquireRequest(pRequest->self);
2,192,236✔
2091
  while (pUserReq) {
2,192,195✔
2092
    if (pUserReq->self == pUserReq->relation.userRefId || pUserReq->relation.userRefId == 0) {
2,192,236✔
2093
      break;
2094
    } else {
2095
      int64_t nextRefId = pUserReq->relation.nextRefId;
×
2096
      (void)releaseRequest(pUserReq->self);
×
2097
      if (nextRefId) {
×
UNCOV
2098
        pUserReq = acquireRequest(nextRefId);
×
2099
      }
2100
    }
2101
  }
2102
  bool hasSubRequest = pUserReq != pRequest || pRequest->relation.prevRefId != 0;
2,192,277✔
2103
  if (pUserReq) {
2,192,277✔
2104
    destroyCtxInRequest(pUserReq);
2,192,236✔
2105
    pUserReq->prevCode = code;
2,192,236✔
2106
    (void)memset(&pUserReq->relation, 0, sizeof(pUserReq->relation));
2,192,236✔
2107
  } else {
2108
    tscError("User req is missing");
41✔
2109
    (void)removeFromMostPrevReq(pRequest);
41✔
UNCOV
2110
    return;
×
2111
  }
2112
  if (hasSubRequest)
2,192,236✔
UNCOV
2113
    (void)removeFromMostPrevReq(pRequest);
×
2114
  else
2115
    (void)releaseRequest(pUserReq->self);
2,192,236✔
2116
  doAsyncQuery(pUserReq, true);
2,192,277✔
2117
}
2118

2119
typedef struct SAsyncFetchParam {
2120
  SRequestObj      *pReq;
2121
  __taos_async_fn_t fp;
2122
  void             *param;
2123
} SAsyncFetchParam;
2124

2125
static int32_t doAsyncFetch(void *pParam) {
132,896,358✔
2126
  SAsyncFetchParam *param = pParam;
132,896,358✔
2127
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
132,896,358✔
2128
  taosMemoryFree(param);
132,895,870✔
2129
  return TSDB_CODE_SUCCESS;
132,895,259✔
2130
}
2131

2132
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
132,898,742✔
2133
  if (res == NULL || fp == NULL) {
132,898,742✔
2134
    tscError("taos_fetch_rows_a invalid paras");
15✔
UNCOV
2135
    return;
×
2136
  }
2137
  if (!TD_RES_QUERY(res)) {
132,898,727✔
2138
    tscError("taos_fetch_rows_a res is NULL");
×
2139
    fp(param, res, TSDB_CODE_APP_ERROR);
×
UNCOV
2140
    return;
×
2141
  }
2142

2143
  SRequestObj *pRequest = res;
132,898,742✔
2144
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
132,898,742✔
2145
    fp(param, res, 0);
2,520✔
2146
    return;
2,520✔
2147
  }
2148

2149
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
132,896,222✔
2150
  if (!pParam) {
132,896,164✔
2151
    fp(param, res, terrno);
×
UNCOV
2152
    return;
×
2153
  }
2154
  pParam->pReq = pRequest;
132,896,164✔
2155
  pParam->fp = fp;
132,895,839✔
2156
  pParam->param = param;
132,896,302✔
2157
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
132,896,222✔
2158
  if (TSDB_CODE_SUCCESS != code) {
132,896,358✔
2159
    taosMemoryFree(pParam);
×
2160
    fp(param, res, code);
×
UNCOV
2161
    return;
×
2162
  }
2163
}
2164

2165
void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
106✔
2166
  if (res == NULL || fp == NULL) {
106✔
2167
    tscError("taos_fetch_raw_block_a invalid paras");
×
UNCOV
2168
    return;
×
2169
  }
2170
  if (!TD_RES_QUERY(res)) {
106✔
2171
    tscError("taos_fetch_raw_block_a res is NULL");
×
UNCOV
2172
    return;
×
2173
  }
2174
  SRequestObj    *pRequest = res;
106✔
2175
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
106✔
2176

2177
  // set the current block is all consumed
2178
  pResultInfo->convertUcs4 = false;
106✔
2179

2180
  // it is a local executed query, no need to do async fetch
2181
  taos_fetch_rows_a(pRequest, fp, param);
106✔
2182
}
2183

2184
const void *taos_get_raw_block(TAOS_RES *res) {
62✔
2185
  if (res == NULL) {
62✔
2186
    tscError("taos_get_raw_block invalid paras");
×
UNCOV
2187
    return NULL;
×
2188
  }
2189
  if (!TD_RES_QUERY(res)) {
62✔
2190
    tscError("taos_get_raw_block res is NULL");
×
UNCOV
2191
    return NULL;
×
2192
  }
2193
  SRequestObj *pRequest = res;
62✔
2194

2195
  return pRequest->body.resInfo.pData;
62✔
2196
}
2197

2198
int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInfo) {
×
2199
  if (NULL == taos) {
×
2200
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2201
    return terrno;
×
2202
  }
2203

2204
  if (NULL == db || NULL == dbInfo) {
×
2205
    tscError("invalid input param, db:%p, dbInfo:%p", db, dbInfo);
×
2206
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
UNCOV
2207
    return terrno;
×
2208
  }
2209

2210
  int64_t      connId = *(int64_t *)taos;
×
2211
  SRequestObj *pRequest = NULL;
×
2212
  char        *sql = "taos_get_db_route_info";
×
2213
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2214
  if (code != TSDB_CODE_SUCCESS) {
×
2215
    terrno = code;
×
UNCOV
2216
    return terrno;
×
2217
  }
2218

2219
  STscObj  *pTscObj = pRequest->pTscObj;
×
2220
  SCatalog *pCtg = NULL;
×
2221
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2222
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2223
    goto _return;
×
2224
  }
2225

2226
  SRequestConnInfo conn = {
×
UNCOV
2227
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2228

UNCOV
2229
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2230

2231
  char dbFName[TSDB_DB_FNAME_LEN] = {0};
×
UNCOV
2232
  (void)snprintf(dbFName, sizeof(dbFName), "%d.%s", pTscObj->acctId, db);
×
2233

2234
  code = catalogGetDBVgInfo(pCtg, &conn, dbFName, dbInfo);
×
2235
  if (code) {
×
UNCOV
2236
    goto _return;
×
2237
  }
2238

UNCOV
2239
_return:
×
2240

UNCOV
2241
  terrno = code;
×
2242

2243
  destroyRequest(pRequest);
×
UNCOV
2244
  return code;
×
2245
}
2246

2247
int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId) {
×
2248
  if (NULL == taos) {
×
2249
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2250
    return terrno;
×
2251
  }
2252

2253
  if (NULL == db || NULL == table || NULL == vgId) {
×
2254
    tscError("invalid input param, db:%p, table:%p, vgId:%p", db, table, vgId);
×
2255
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
UNCOV
2256
    return terrno;
×
2257
  }
2258

2259
  int64_t      connId = *(int64_t *)taos;
×
2260
  SRequestObj *pRequest = NULL;
×
2261
  char        *sql = "taos_get_table_vgId";
×
2262
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2263
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2264
    return terrno;
×
2265
  }
2266

UNCOV
2267
  pRequest->syncQuery = true;
×
2268

2269
  STscObj  *pTscObj = pRequest->pTscObj;
×
2270
  SCatalog *pCtg = NULL;
×
2271
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2272
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2273
    goto _return;
×
2274
  }
2275

2276
  SRequestConnInfo conn = {
×
UNCOV
2277
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2278

UNCOV
2279
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2280

2281
  SName tableName = {0};
×
UNCOV
2282
  toName(pTscObj->acctId, db, table, &tableName);
×
2283

2284
  SVgroupInfo vgInfo;
×
2285
  code = catalogGetTableHashVgroup(pCtg, &conn, &tableName, &vgInfo);
×
2286
  if (code) {
×
UNCOV
2287
    goto _return;
×
2288
  }
2289

UNCOV
2290
  *vgId = vgInfo.vgId;
×
2291

UNCOV
2292
_return:
×
2293

UNCOV
2294
  terrno = code;
×
2295

2296
  destroyRequest(pRequest);
×
UNCOV
2297
  return code;
×
2298
}
2299

2300
int taos_get_tables_vgId(TAOS *taos, const char *db, const char *table[], int tableNum, int *vgId) {
×
2301
  if (NULL == taos) {
×
2302
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2303
    return terrno;
×
2304
  }
2305

2306
  if (NULL == db || NULL == table || NULL == vgId || tableNum <= 0) {
×
2307
    tscError("invalid input param, db:%p, table:%p, vgId:%p, tbNum:%d", db, table, vgId, tableNum);
×
2308
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
UNCOV
2309
    return terrno;
×
2310
  }
2311

2312
  int64_t      connId = *(int64_t *)taos;
×
2313
  SRequestObj *pRequest = NULL;
×
2314
  char        *sql = "taos_get_table_vgId";
×
2315
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2316
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2317
    return terrno;
×
2318
  }
2319

UNCOV
2320
  pRequest->syncQuery = true;
×
2321

2322
  STscObj  *pTscObj = pRequest->pTscObj;
×
2323
  SCatalog *pCtg = NULL;
×
2324
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2325
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2326
    goto _return;
×
2327
  }
2328

2329
  SRequestConnInfo conn = {
×
UNCOV
2330
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2331

UNCOV
2332
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2333

2334
  code = catalogGetTablesHashVgId(pCtg, &conn, pTscObj->acctId, db, table, tableNum, vgId);
×
2335
  if (code) {
×
UNCOV
2336
    goto _return;
×
2337
  }
2338

UNCOV
2339
_return:
×
2340

UNCOV
2341
  terrno = code;
×
2342

2343
  destroyRequest(pRequest);
×
UNCOV
2344
  return code;
×
2345
}
2346

2347
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
1,112✔
2348
  if (NULL == taos) {
1,112✔
2349
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2350
    return terrno;
×
2351
  }
2352

2353
  int64_t       connId = *(int64_t *)taos;
1,112✔
2354
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
1,112✔
2355
  int32_t       code = 0;
1,112✔
2356
  SRequestObj  *pRequest = NULL;
1,112✔
2357
  SCatalogReq   catalogReq = {0};
1,112✔
2358

2359
  if (NULL == tableNameList) {
1,112✔
UNCOV
2360
    return TSDB_CODE_SUCCESS;
×
2361
  }
2362

2363
  int32_t length = (int32_t)strlen(tableNameList);
1,112✔
2364
  if (0 == length) {
1,112✔
UNCOV
2365
    return TSDB_CODE_SUCCESS;
×
2366
  } else if (length > MAX_TABLE_NAME_LENGTH) {
1,112✔
2367
    tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH);
×
UNCOV
2368
    return TSDB_CODE_TSC_INVALID_OPERATION;
×
2369
  }
2370

2371
  char *sql = "taos_load_table_info";
1,112✔
2372
  code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
1,112✔
2373
  if (code != TSDB_CODE_SUCCESS) {
1,112✔
2374
    terrno = code;
×
UNCOV
2375
    goto _return;
×
2376
  }
2377

2378
  pRequest->syncQuery = true;
1,112✔
2379

2380
  STscObj *pTscObj = pRequest->pTscObj;
1,112✔
2381
  code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
1,112✔
2382
  if (code) {
1,112✔
UNCOV
2383
    goto _return;
×
2384
  }
2385

2386
  SCatalog *pCtg = NULL;
1,112✔
2387
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
1,112✔
2388
  if (code != TSDB_CODE_SUCCESS) {
1,112✔
UNCOV
2389
    goto _return;
×
2390
  }
2391

2392
  SRequestConnInfo conn = {
1,112✔
2393
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
1,112✔
2394

2395
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
1,112✔
2396

2397
  code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, pRequest->body.interParam, NULL);
1,112✔
2398
  if (code) {
1,112✔
UNCOV
2399
    goto _return;
×
2400
  }
2401

2402
  SSyncQueryParam *pParam = pRequest->body.interParam;
1,112✔
2403
  code = tsem_wait(&pParam->sem);
1,112✔
2404
  if (code) {
1,112✔
2405
    tscError("tsem wait failed, code:%d - %s", code, tstrerror(code));
×
UNCOV
2406
    goto _return;
×
2407
  }
2408
_return:
1,112✔
2409
  destoryCatalogReq(&catalogReq);
1,112✔
2410
  destroyRequest(pRequest);
1,112✔
2411
  return code;
1,112✔
2412
}
2413

2414
TAOS_STMT *taos_stmt_init(TAOS *taos) {
126,668✔
2415
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
126,668✔
2416
  if (NULL == pObj) {
126,793✔
2417
    tscError("invalid parameter for %s", __FUNCTION__);
×
2418
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2419
    return NULL;
×
2420
  }
2421

2422
  TAOS_STMT *pStmt = stmtInit(pObj, 0, NULL);
126,793✔
2423
  if (NULL == pStmt) {
126,793✔
UNCOV
2424
    tscError("stmt init failed, errcode:%s", terrstr());
×
2425
  }
2426
  releaseTscObj(*(int64_t *)taos);
126,793✔
2427

2428
  return pStmt;
126,793✔
2429
}
2430

2431
TAOS_STMT *taos_stmt_init_with_reqid(TAOS *taos, int64_t reqid) {
×
2432
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
2433
  if (NULL == pObj) {
×
2434
    tscError("invalid parameter for %s", __FUNCTION__);
×
2435
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2436
    return NULL;
×
2437
  }
2438

2439
  TAOS_STMT *pStmt = stmtInit(pObj, reqid, NULL);
×
2440
  if (NULL == pStmt) {
×
UNCOV
2441
    tscError("stmt init failed, errcode:%s", terrstr());
×
2442
  }
UNCOV
2443
  releaseTscObj(*(int64_t *)taos);
×
2444

UNCOV
2445
  return pStmt;
×
2446
}
2447

2448
TAOS_STMT *taos_stmt_init_with_options(TAOS *taos, TAOS_STMT_OPTIONS *options) {
8,857✔
2449
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
8,857✔
2450
  if (NULL == pObj) {
8,857✔
2451
    tscError("invalid parameter for %s", __FUNCTION__);
×
2452
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2453
    return NULL;
×
2454
  }
2455

2456
  TAOS_STMT *pStmt = stmtInit(pObj, options->reqId, options);
8,857✔
2457
  if (NULL == pStmt) {
8,857✔
UNCOV
2458
    tscError("stmt init failed, errcode:%s", terrstr());
×
2459
  }
2460
  releaseTscObj(*(int64_t *)taos);
8,857✔
2461

2462
  return pStmt;
8,857✔
2463
}
2464

2465
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
3,281,037✔
2466
  if (stmt == NULL || sql == NULL) {
3,281,037✔
2467
    tscError("NULL parameter for %s", __FUNCTION__);
×
2468
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2469
    return terrno;
×
2470
  }
2471

2472
  return stmtPrepare(stmt, sql, length);
3,281,292✔
2473
}
2474

2475
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
5,709✔
2476
  if (stmt == NULL || name == NULL) {
5,709✔
2477
    tscError("NULL parameter for %s", __FUNCTION__);
×
2478
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2479
    return terrno;
×
2480
  }
2481

2482
  int32_t code = stmtSetTbName(stmt, name);
5,709✔
2483
  if (code) {
5,709✔
2484
    return code;
556✔
2485
  }
2486

2487
  if (tags) {
5,153✔
2488
    return stmtSetTbTags(stmt, tags);
5,153✔
2489
  }
2490

UNCOV
2491
  return TSDB_CODE_SUCCESS;
×
2492
}
2493

2494
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
5,336,235✔
2495
  if (stmt == NULL || name == NULL) {
5,336,235✔
2496
    tscError("NULL parameter for %s", __FUNCTION__);
242✔
2497
    terrno = TSDB_CODE_INVALID_PARA;
242✔
UNCOV
2498
    return terrno;
×
2499
  }
2500

2501
  return stmtSetTbName(stmt, name);
5,336,987✔
2502
}
2503

2504
int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) {
133✔
2505
  if (stmt == NULL || tags == NULL) {
133✔
2506
    tscError("NULL parameter for %s", __FUNCTION__);
×
2507
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2508
    return terrno;
×
2509
  }
2510

2511
  return stmtSetTbTags(stmt, tags);
133✔
2512
}
2513

UNCOV
2514
int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); }
×
2515

2516
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
×
2517
  if (stmt == NULL || NULL == fieldNum) {
×
2518
    tscError("NULL parameter for %s", __FUNCTION__);
×
2519
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2520
    return terrno;
×
2521
  }
2522

UNCOV
2523
  return stmtGetTagFields(stmt, fieldNum, fields);
×
2524
}
2525

2526
int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
×
2527
  if (stmt == NULL || NULL == fieldNum) {
×
2528
    tscError("NULL parameter for %s", __FUNCTION__);
×
2529
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2530
    return terrno;
×
2531
  }
2532

UNCOV
2533
  return stmtGetColFields(stmt, fieldNum, fields);
×
2534
}
2535

2536
// let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields`
UNCOV
2537
void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) {
×
2538
  (void)stmt;
2539
  if (!fields) return;
×
UNCOV
2540
  taosMemoryFree(fields);
×
2541
}
2542

2543
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
26,251✔
2544
  if (stmt == NULL || bind == NULL) {
26,251✔
2545
    tscError("NULL parameter for %s", __FUNCTION__);
×
2546
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2547
    return terrno;
×
2548
  }
2549

2550
  if (bind->num > 1) {
26,251✔
2551
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
3,654✔
2552
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
3,654✔
2553
    return terrno;
3,654✔
2554
  }
2555

2556
  return stmtBindBatch(stmt, bind, -1);
22,597✔
2557
}
2558

2559
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
63,679,890✔
2560
  if (stmt == NULL || bind == NULL) {
63,679,890✔
2561
    tscError("NULL parameter for %s", __FUNCTION__);
×
2562
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2563
    return terrno;
×
2564
  }
2565

2566
  if (bind->num <= 0 || bind->num > INT16_MAX) {
64,371,497✔
2567
    tscError("invalid bind num %d", bind->num);
2,081✔
2568
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
2,081✔
UNCOV
2569
    return terrno;
×
2570
  }
2571

2572
  int32_t insert = 0;
64,712,172✔
2573
  int32_t code = stmtIsInsert(stmt, &insert);
64,196,158✔
2574
  if (TSDB_CODE_SUCCESS != code) {
63,856,806✔
2575
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
UNCOV
2576
    return code;
×
2577
  }
2578
  if (0 == insert && bind->num > 1) {
63,856,806✔
2579
    tscError("only one row data allowed for query");
×
2580
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
UNCOV
2581
    return terrno;
×
2582
  }
2583

2584
  return stmtBindBatch(stmt, bind, -1);
63,856,806✔
2585
}
2586

2587
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
700✔
2588
  if (stmt == NULL || bind == NULL) {
700✔
2589
    tscError("NULL parameter for %s", __FUNCTION__);
×
2590
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2591
    return terrno;
×
2592
  }
2593

2594
  if (colIdx < 0) {
700✔
2595
    tscError("invalid bind column idx %d", colIdx);
×
2596
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2597
    return terrno;
×
2598
  }
2599

2600
  int32_t insert = 0;
700✔
2601
  int32_t code = stmtIsInsert(stmt, &insert);
700✔
2602
  if (TSDB_CODE_SUCCESS != code) {
700✔
2603
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
UNCOV
2604
    return code;
×
2605
  }
2606
  if (0 == insert && bind->num > 1) {
700✔
2607
    tscError("only one row data allowed for query");
×
2608
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
UNCOV
2609
    return terrno;
×
2610
  }
2611

2612
  return stmtBindBatch(stmt, bind, colIdx);
700✔
2613
}
2614

2615
int taos_stmt_add_batch(TAOS_STMT *stmt) {
61,117,568✔
2616
  if (stmt == NULL) {
61,117,568✔
2617
    tscError("NULL parameter for %s", __FUNCTION__);
×
2618
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2619
    return terrno;
×
2620
  }
2621

2622
  return stmtAddBatch(stmt);
61,117,568✔
2623
}
2624

2625
int taos_stmt_execute(TAOS_STMT *stmt) {
3,600,383✔
2626
  if (stmt == NULL) {
3,600,383✔
2627
    tscError("NULL parameter for %s", __FUNCTION__);
×
2628
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2629
    return terrno;
×
2630
  }
2631

2632
  return stmtExec(stmt);
3,600,383✔
2633
}
2634

2635
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
×
2636
  if (stmt == NULL || insert == NULL) {
×
2637
    tscError("NULL parameter for %s", __FUNCTION__);
×
2638
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2639
    return terrno;
×
2640
  }
2641

UNCOV
2642
  return stmtIsInsert(stmt, insert);
×
2643
}
2644

2645
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
×
2646
  if (stmt == NULL || nums == NULL) {
×
2647
    tscError("NULL parameter for %s", __FUNCTION__);
×
2648
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2649
    return terrno;
×
2650
  }
2651

UNCOV
2652
  return stmtGetParamNum(stmt, nums);
×
2653
}
2654

2655
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
×
2656
  if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) {
×
2657
    tscError("invalid parameter for %s", __FUNCTION__);
×
2658
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2659
    return terrno;
×
2660
  }
2661

UNCOV
2662
  return stmtGetParam(stmt, idx, type, bytes);
×
2663
}
2664

2665
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
8,881✔
2666
  if (stmt == NULL) {
8,881✔
2667
    tscError("NULL parameter for %s", __FUNCTION__);
×
2668
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2669
    return NULL;
×
2670
  }
2671

2672
  return stmtUseResult(stmt);
8,881✔
2673
}
2674

2675
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
9,546✔
2676

2677
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
2,889✔
2678
  if (stmt == NULL) {
2,889✔
2679
    tscError("NULL parameter for %s", __FUNCTION__);
×
2680
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2681
    return 0;
×
2682
  }
2683

2684
  return stmtAffectedRows(stmt);
2,889✔
2685
}
2686

2687
int taos_stmt_affected_rows_once(TAOS_STMT *stmt) {
100✔
2688
  if (stmt == NULL) {
100✔
2689
    tscError("NULL parameter for %s", __FUNCTION__);
×
2690
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2691
    return 0;
×
2692
  }
2693

2694
  return stmtAffectedRowsOnce(stmt);
100✔
2695
}
2696

2697
int taos_stmt_close(TAOS_STMT *stmt) {
135,448✔
2698
  if (stmt == NULL) {
135,448✔
2699
    tscError("NULL parameter for %s", __FUNCTION__);
×
2700
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2701
    return terrno;
×
2702
  }
2703

2704
  return stmtClose(stmt);
135,448✔
2705
}
2706

2707
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
2,935✔
2708
  if (NULL == taos) {
2,935✔
2709
    tscError("NULL parameter for %s", __FUNCTION__);
×
2710
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2711
    return NULL;
×
2712
  }
2713
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2,935✔
2714
  if (NULL == pObj) {
2,935✔
2715
    tscError("invalid parameter for %s", __FUNCTION__);
×
2716
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2717
    return NULL;
×
2718
  }
2719

2720
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
2,935✔
2721

2722
  releaseTscObj(*(int64_t *)taos);
2,935✔
2723

2724
  return pStmt;
2,893✔
2725
}
2726

2727
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
3,047✔
2728
  if (stmt == NULL || sql == NULL) {
3,047✔
2729
    tscError("NULL parameter for %s", __FUNCTION__);
×
2730
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2731
    return terrno;
×
2732
  }
2733

2734
  return stmtPrepare2(stmt, sql, length);
3,047✔
2735
}
2736

2737
int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx) {
535,717✔
2738
  if (stmt == NULL) {
535,717✔
2739
    tscError("NULL parameter for %s", __FUNCTION__);
×
2740
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2741
    return terrno;
×
2742
  }
2743

2744
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
535,717✔
2745
  int32_t    code = TSDB_CODE_SUCCESS;
535,717✔
2746
  STMT2_DLOG_E("start to bind param");
535,717✔
2747

2748
  // check query bind number
2749
  bool isQuery = (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt)));
535,787✔
2750
  if (isQuery) {
535,875✔
2751
    if (bindv->count != 1 || bindv->bind_cols[0]->num != 1) {
8✔
2752
      terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2753
      STMT2_ELOG_E("query only support one table and one row bind");
×
UNCOV
2754
      return terrno;
×
2755
    }
2756
  }
2757

2758
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 1) {
535,875✔
2759
    STMT2_ELOG_E("async bind param is still working, please try again later");
112✔
2760
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
112✔
UNCOV
2761
    return terrno;
×
2762
  }
2763

2764
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
535,693✔
2765
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
×
UNCOV
2766
      STMT2_ELOG_E("bind param wait asyncExecSem failed");
×
2767
    }
UNCOV
2768
    pStmt->execSemWaited = true;
×
2769
  }
2770

2771
  for (int i = 0; i < bindv->count; ++i) {
1,655,026✔
2772
    SVCreateTbReq *pCreateTbReq = NULL;
1,118,642✔
2773
    if (!isQuery) {
1,118,603✔
2774
      STMT2_TLOG("start to bind %dth table", i);
1,118,332✔
2775
      if (bindv->tbnames && bindv->tbnames[i]) {
1,118,276✔
2776
        code = stmtSetTbName2(stmt, bindv->tbnames[i]);
1,118,215✔
2777
        if (code) {
1,118,236✔
2778
          terrno = code;
×
2779
          STMT2_ELOG("set tbname failed, code:%s", tstrerror(code));
×
UNCOV
2780
          return terrno;
×
2781
        }
2782
      }
2783

2784
      if (bindv->tags && bindv->tags[i]) {
1,117,919✔
2785
        code = stmtSetTbTags2(stmt, bindv->tags[i], &pCreateTbReq);
565,720✔
2786
      } else if (pStmt->bInfo.tbNameFlag & IS_FIXED_TAG) {
552,446✔
2787
        code = stmtCheckTags2(stmt, &pCreateTbReq);
111,832✔
2788
      } else if (pStmt->sql.autoCreateTbl) {
440,738✔
UNCOV
2789
        code = stmtSetTbTags2(stmt, NULL, &pCreateTbReq);
×
2790
      }
2791

2792
      if (code) {
1,118,062✔
2793
        terrno = code;
×
2794
        STMT2_ELOG("set tags failed, code:%s", tstrerror(code));
×
UNCOV
2795
        return terrno;
×
2796
      }
2797
    }
2798

2799
    if (bindv->bind_cols && bindv->bind_cols[i]) {
1,118,333✔
2800
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
1,118,558✔
2801

2802
      if (bind->num <= 0 || bind->num > INT16_MAX) {
1,118,558✔
2803
        STMT2_ELOG("bind num:%d must > 0 and < INT16_MAX", bind->num);
842✔
2804
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
842✔
UNCOV
2805
        return terrno;
×
2806
      }
2807

2808
      code = stmtBindBatch2(stmt, bind, col_idx, pCreateTbReq);
1,118,267✔
2809
      if (TSDB_CODE_SUCCESS != code) {
1,118,863✔
2810
        terrno = code;
×
2811
        STMT2_ELOG("bind batch failed, code:%s", tstrerror(code));
×
UNCOV
2812
        return terrno;
×
2813
      }
2814
    }
2815
  }
2816

2817
  return code;
536,381✔
2818
}
2819

UNCOV
2820
int taos_stmt2_bind_param_a(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx, __taos_async_fn_t fp,
×
2821
                            void *param) {
2822
  if (stmt == NULL || bindv == NULL || fp == NULL) {
×
2823
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2824
    return terrno;
×
2825
  }
2826

UNCOV
2827
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
×
2828

2829
  ThreadArgs *args = (ThreadArgs *)taosMemoryMalloc(sizeof(ThreadArgs));
×
2830
  args->stmt = stmt;
×
2831
  args->bindv = bindv;
×
2832
  args->col_idx = col_idx;
×
2833
  args->fp = fp;
×
UNCOV
2834
  args->param = param;
×
2835

2836
  (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2837
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 0) {
×
2838
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2839
    tscError("async bind param is still working, please try again later");
×
2840
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
×
UNCOV
2841
    return terrno;
×
2842
  }
2843
  (void)atomic_add_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
UNCOV
2844
  (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2845

2846
  int code_s = taosStmt2AsyncBind(stmtAsyncBindThreadFunc, (void *)args);
×
2847
  if (code_s != TSDB_CODE_SUCCESS) {
×
2848
    terrno = code_s;
×
2849
    (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2850
    (void)taosThreadCondSignal(&(pStmt->asyncBindParam.waitCond));
×
2851
    (void)atomic_sub_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2852
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
UNCOV
2853
    tscError("async bind failed, code:%d , %s", code_s, tstrerror(code_s));
×
2854
  }
2855

UNCOV
2856
  return code_s;
×
2857
}
2858

2859
int taos_stmt2_exec(TAOS_STMT2 *stmt, int *affected_rows) {
536,322✔
2860
  if (stmt == NULL) {
536,322✔
2861
    tscError("NULL parameter for %s", __FUNCTION__);
×
2862
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2863
    return terrno;
×
2864
  }
2865

2866
  return stmtExec2(stmt, affected_rows);
536,322✔
2867
}
2868

2869
int taos_stmt2_close(TAOS_STMT2 *stmt) {
2,935✔
2870
  if (stmt == NULL) {
2,935✔
2871
    tscError("NULL parameter for %s", __FUNCTION__);
×
2872
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2873
    return terrno;
×
2874
  }
2875

2876
  return stmtClose2(stmt);
2,935✔
2877
}
2878

2879
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
31✔
2880
  if (stmt == NULL || insert == NULL) {
31✔
2881
    tscError("NULL parameter for %s", __FUNCTION__);
×
2882
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2883
    return terrno;
×
2884
  }
2885
  *insert = stmt2IsInsert(stmt);
31✔
2886
  return TSDB_CODE_SUCCESS;
31✔
2887
}
2888

2889
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
23✔
2890
  if (stmt == NULL || count == NULL) {
23✔
2891
    tscError("NULL parameter for %s", __FUNCTION__);
×
2892
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2893
    return terrno;
×
2894
  }
2895

2896
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
23✔
2897
  STMT2_DLOG_E("start to get fields");
23✔
2898

2899
  if (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type ||
23✔
2900
      (pStmt->sql.type == 0 && stmt2IsInsert(stmt))) {
23✔
2901
    return stmtGetStbColFields2(stmt, count, fields);
23✔
2902
  }
2903
  if (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt))) {
×
UNCOV
2904
    return stmtGetParamNum2(stmt, count);
×
2905
  }
2906

2907
  tscError("Invalid sql for stmt %s", pStmt->sql.sqlStr);
×
UNCOV
2908
  return TSDB_CODE_PAR_SYNTAX_ERROR;
×
2909
}
2910

2911
DLL_EXPORT void taos_stmt2_free_fields(TAOS_STMT2 *stmt, TAOS_FIELD_ALL *fields) {
23✔
2912
  (void)stmt;
2913
  if (!fields) return;
23✔
2914
  taosMemoryFree(fields);
23✔
2915
}
2916

2917
TAOS_RES *taos_stmt2_result(TAOS_STMT2 *stmt) {
8✔
2918
  if (stmt == NULL) {
8✔
2919
    tscError("NULL parameter for %s", __FUNCTION__);
×
2920
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2921
    return NULL;
×
2922
  }
2923

2924
  return stmtUseResult2(stmt);
8✔
2925
}
2926

UNCOV
2927
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmtErrstr2(stmt); }
×
2928

2929
int taos_set_conn_mode(TAOS *taos, int mode, int value) {
2,024✔
2930
  int32_t code = 0;
2,024✔
2931
  if (taos == NULL) {
2,024✔
2932
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2933
    return terrno;
×
2934
  }
2935

2936
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2,024✔
2937
  if (NULL == pObj) {
2,024✔
2938
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2939
    tscError("invalid parameter for %s", __func__);
×
UNCOV
2940
    return terrno;
×
2941
  }
2942
  switch (mode) {
2,024✔
2943
    case TAOS_CONN_MODE_BI:
2,024✔
2944
      atomic_store_8(&pObj->biMode, value);
2,024✔
2945
      break;
2,024✔
2946
    default:
×
2947
      tscError("not supported mode.");
×
UNCOV
2948
      code = TSDB_CODE_INVALID_PARA;
×
2949
  }
2950
  releaseTscObj(*(int64_t *)taos);
2,024✔
2951
  return code;
2,024✔
2952
}
2953

UNCOV
2954
char *getBuildInfo() { return td_buildinfo; }
×
2955

2956
int32_t taos_connect_is_alive(TAOS *taos) {
×
2957
  int32_t code = 0, lino = 0;
×
2958
  if (taos == NULL) {
×
2959
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2960
    return terrno;
×
2961
  }
2962

2963
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
2964
  if (NULL == pObj) {
×
2965
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2966
    tscError("invalid parameter for %s", __func__);
×
UNCOV
2967
    return terrno;
×
2968
  }
2969

2970
  code = sessMgtCheckConnStatus(pObj->user, &pObj->sessInfo);
×
UNCOV
2971
  TAOS_CHECK_GOTO(code, &lino, _error);
×
2972

2973
_error:
×
UNCOV
2974
  releaseTscObj(*(int64_t *)taos);
×
2975

2976
  if (code != 0) {
×
UNCOV
2977
    tscError("taos conn failed to check alive, code:%d - %s", code, tstrerror(code));
×
2978
  }
2979

UNCOV
2980
  return code != 0 ? 0 : 1;
×
2981
}
2982
static int32_t buildInstanceRegisterSql(const SInstanceRegisterReq *req, char **ppSql, uint32_t *pLen) {
×
2983
  const char *action = (req->expire < 0) ? "UNREGISTER" : "REGISTER";
×
UNCOV
2984
  int32_t     len = 0;
×
2985

2986
  len += snprintf(NULL, 0, "%s INSTANCE '%s'", action, req->id);
×
2987
  if (req->type[0] != 0) {
×
UNCOV
2988
    len += snprintf(NULL, 0, " TYPE '%s'", req->type);
×
2989
  }
2990
  if (req->desc[0] != 0) {
×
UNCOV
2991
    len += snprintf(NULL, 0, " DESC '%s'", req->desc);
×
2992
  }
2993
  if (req->expire >= 0) {
×
UNCOV
2994
    len += snprintf(NULL, 0, " EXPIRE %d", req->expire);
×
2995
  }
2996

2997
  char *sql = taosMemoryMalloc((size_t)len + 1);
×
2998
  if (sql == NULL) {
×
UNCOV
2999
    return terrno;
×
3000
  }
3001

3002
  int32_t offset = snprintf(sql, (size_t)len + 1, "%s INSTANCE '%s'", action, req->id);
×
3003
  if (req->type[0] != 0) {
×
UNCOV
3004
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " TYPE '%s'", req->type);
×
3005
  }
3006
  if (req->desc[0] != 0) {
×
UNCOV
3007
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " DESC '%s'", req->desc);
×
3008
  }
3009
  if (req->expire >= 0) {
×
UNCOV
3010
    (void)snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " EXPIRE %d", req->expire);
×
3011
  }
3012

3013
  *ppSql = sql;
×
3014
  if (pLen != NULL) {
×
UNCOV
3015
    *pLen = (uint32_t)len;
×
3016
  }
UNCOV
3017
  return TSDB_CODE_SUCCESS;
×
3018
}
3019

3020
static int32_t sendInstanceRegisterReq(STscObj *pObj, const SInstanceRegisterReq *req) {
×
3021
  SRequestObj *pRequest = NULL;
×
3022
  int32_t      code = createRequest(pObj->id, TDMT_MND_REGISTER_INSTANCE, 0, &pRequest);
×
3023
  if (code != TSDB_CODE_SUCCESS) {
×
3024
    terrno = code;
×
UNCOV
3025
    return code;
×
3026
  }
3027

3028
  code = buildInstanceRegisterSql(req, &pRequest->sqlstr, (uint32_t *)&pRequest->sqlLen);
×
3029
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3030
    goto _cleanup;
×
3031
  }
3032

3033
  int32_t msgLen = tSerializeSInstanceRegisterReq(NULL, 0, (SInstanceRegisterReq *)req);
×
3034
  if (msgLen <= 0) {
×
3035
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3036
    goto _cleanup;
×
3037
  }
3038

3039
  void *pMsg = taosMemoryMalloc(msgLen);
×
3040
  if (pMsg == NULL) {
×
3041
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3042
    goto _cleanup;
×
3043
  }
3044

3045
  if (tSerializeSInstanceRegisterReq(pMsg, msgLen, (SInstanceRegisterReq *)req) < 0) {
×
3046
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3047
    taosMemoryFree(pMsg);
×
UNCOV
3048
    goto _cleanup;
×
3049
  }
3050

3051
  pRequest->type = TDMT_MND_REGISTER_INSTANCE;
×
UNCOV
3052
  pRequest->body.requestMsg = (SDataBuf){.pData = pMsg, .len = msgLen, .handle = NULL};
×
3053

3054
  SMsgSendInfo *pSend = buildMsgInfoImpl(pRequest);
×
3055
  if (pSend == NULL) {
×
3056
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3057
    taosMemoryFree(pMsg);
×
3058
    pRequest->body.requestMsg.pData = NULL;
×
UNCOV
3059
    goto _cleanup;
×
3060
  }
3061

3062
  SEpSet epSet = getEpSet_s(&pObj->pAppInfo->mgmtEp);
×
3063
  code = asyncSendMsgToServer(pObj->pAppInfo->pTransporter, &epSet, NULL, pSend);
×
3064
  if (code != TSDB_CODE_SUCCESS) {
×
3065
    destroySendMsgInfo(pSend);
×
3066
    pRequest->body.requestMsg = (SDataBuf){0};
×
UNCOV
3067
    goto _cleanup;
×
3068
  }
3069

3070
  code = tsem_wait(&pRequest->body.rspSem);
×
3071
  if (code != TSDB_CODE_SUCCESS) {
×
3072
    code = terrno != 0 ? terrno : code;
×
UNCOV
3073
    goto _cleanup;
×
3074
  }
3075

3076
  code = pRequest->code;
×
UNCOV
3077
  terrno = code;
×
3078

3079
_cleanup:
×
3080
  destroyRequest(pRequest);
×
UNCOV
3081
  return code;
×
3082
}
3083

3084
static bool instanceRegisterRpcRfp(int32_t code, tmsg_t msgType) {
×
3085
  if (NEED_REDIRECT_ERROR(code)) {
×
3086
    return true;
×
3087
  } else if (code == TSDB_CODE_UTIL_QUEUE_OUT_OF_MEMORY || code == TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE ||
×
UNCOV
3088
             code == TSDB_CODE_SYN_WRITE_STALL || code == TSDB_CODE_SYN_PROPOSE_NOT_READY ||
×
3089
             code == TSDB_CODE_SYN_RESTORING) {
3090
    tscDebug("client msg type %s should retry since %s", TMSG_INFO(msgType), tstrerror(code));
×
UNCOV
3091
    return true;
×
3092
  } else {
UNCOV
3093
    return false;
×
3094
  }
3095
}
3096

3097
int32_t taos_register_instance(const char *id, const char *type, const char *desc, int32_t expire) {
×
3098
  if (id == NULL || id[0] == 0) {
×
UNCOV
3099
    return terrno = TSDB_CODE_INVALID_PARA;
×
3100
  }
3101

3102
  // Validate string lengths
3103
  size_t idLen = strlen(id);
×
3104
  if (idLen >= TSDB_INSTANCE_ID_LEN) {
×
3105
    tscError("instance id length %zu exceeds limit %d", idLen, TSDB_INSTANCE_ID_LEN - 1);
×
UNCOV
3106
    return terrno = TSDB_CODE_INVALID_PARA;
×
3107
  }
3108

3109
  if (type != NULL && type[0] != 0) {
×
3110
    size_t typeLen = strlen(type);
×
3111
    if (typeLen >= TSDB_INSTANCE_TYPE_LEN) {
×
3112
      tscError("instance type length %zu exceeds limit %d", typeLen, TSDB_INSTANCE_TYPE_LEN - 1);
×
UNCOV
3113
      return terrno = TSDB_CODE_INVALID_PARA;
×
3114
    }
3115
  }
3116

3117
  if (desc != NULL && desc[0] != 0) {
×
3118
    size_t descLen = strlen(desc);
×
3119
    if (descLen >= TSDB_INSTANCE_DESC_LEN) {
×
3120
      tscError("instance desc length %zu exceeds limit %d", descLen, TSDB_INSTANCE_DESC_LEN - 1);
×
UNCOV
3121
      return terrno = TSDB_CODE_INVALID_PARA;
×
3122
    }
3123
  }
3124

3125
  int32_t code = taos_init();
×
3126
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3127
    return code;
×
3128
  }
3129

3130
  SConfig *pCfg = taosGetCfg();
×
3131
  if (pCfg == NULL) {
×
UNCOV
3132
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3133
  }
3134

3135
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
×
3136
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
×
UNCOV
3137
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3138
  }
3139

3140
  SEp firstEp = {0};
×
3141
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
×
3142
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3143
    return terrno = code;
×
3144
  }
3145

3146
  void    *clientRpc = NULL;
×
3147
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
×
3148
  SRpcMsg  rpcMsg = {0};
×
3149
  SRpcMsg  rpcRsp = {0};
×
UNCOV
3150
  SRpcInit rpcInit = {0};
×
3151

3152
  rpcInit.label = "INST";
×
3153
  rpcInit.numOfThreads = 1;
×
3154
  rpcInit.cfp = NULL;
×
3155
  rpcInit.sessions = 16;
×
3156
  rpcInit.connType = TAOS_CONN_CLIENT;
×
3157
  rpcInit.idleTime = tsShellActivityTimer * 1000;
×
3158
  rpcInit.compressSize = tsCompressMsgSize;
×
UNCOV
3159
  rpcInit.user = TSDB_DEFAULT_USER;
×
3160

3161
  rpcInit.rfp = instanceRegisterRpcRfp;
×
3162
  rpcInit.retryMinInterval = tsRedirectPeriod;
×
3163
  rpcInit.retryStepFactor = tsRedirectFactor;
×
3164
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
×
UNCOV
3165
  rpcInit.retryMaxTimeout =
×
3166
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3167

3168
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
×
3169
  connLimitNum = TMAX(connLimitNum, 10);
×
3170
  connLimitNum = TMIN(connLimitNum, 500);
×
3171
  rpcInit.connLimitNum = connLimitNum;
×
3172
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
×
3173
  rpcInit.readTimeout = tsReadTimeout;
×
3174
  rpcInit.ipv6 = tsEnableIpv6;
×
UNCOV
3175
  rpcInit.enableSSL = tsEnableTLS;
×
3176

3177
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
×
3178
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
×
3179
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
×
3180
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
×
UNCOV
3181
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
×
3182

3183
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
×
3184
  if (code != TSDB_CODE_SUCCESS) {
×
3185
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
UNCOV
3186
    return code;
×
3187
  }
3188

3189
  clientRpc = rpcOpen(&rpcInit);
×
3190
  if (clientRpc == NULL) {
×
3191
    code = terrno;
×
3192
    tscError("failed to init instance register client since %s", tstrerror(code));
×
UNCOV
3193
    return code;
×
3194
  }
3195

3196
  // Prepare epSet
3197
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
×
UNCOV
3198
  epSet.eps[0].port = firstEp.port;
×
3199

3200
  // Prepare request
3201
  SInstanceRegisterReq req = {0};
×
3202
  tstrncpy(req.id, id, sizeof(req.id));
×
3203
  if (type != NULL && type[0] != 0) {
×
UNCOV
3204
    tstrncpy(req.type, type, sizeof(req.type));
×
3205
  }
3206
  if (desc != NULL && desc[0] != 0) {
×
UNCOV
3207
    tstrncpy(req.desc, desc, sizeof(req.desc));
×
3208
  }
UNCOV
3209
  req.expire = expire;
×
3210

3211
  int32_t contLen = tSerializeSInstanceRegisterReq(NULL, 0, &req);
×
3212
  if (contLen <= 0) {
×
3213
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3214
    rpcClose(clientRpc);
×
UNCOV
3215
    return code;
×
3216
  }
3217

3218
  void *pCont = rpcMallocCont(contLen);
×
3219
  if (pCont == NULL) {
×
3220
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3221
    rpcClose(clientRpc);
×
UNCOV
3222
    return code;
×
3223
  }
3224

3225
  if (tSerializeSInstanceRegisterReq(pCont, contLen, &req) < 0) {
×
3226
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3227
    rpcFreeCont(pCont);
×
3228
    rpcClose(clientRpc);
×
UNCOV
3229
    return code;
×
3230
  }
3231

3232
  rpcMsg.pCont = pCont;
×
3233
  rpcMsg.contLen = contLen;
×
3234
  rpcMsg.msgType = TDMT_MND_REGISTER_INSTANCE;
×
3235
  rpcMsg.info.ahandle = (void *)0x9528;  // Different magic number from server status
×
UNCOV
3236
  rpcMsg.info.notFreeAhandle = 1;
×
3237

3238
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
×
3239
  if (TSDB_CODE_SUCCESS != code) {
×
UNCOV
3240
    tscError("failed to send instance register req since %s", tstrerror(code));
×
3241
    // rpcSendRecv failed, pCont may not be freed, but check _RETURN1 path
3242
    // In error path, rpcSendRecv may free pCont, but we free it here to be safe
3243
    rpcClose(clientRpc);
×
UNCOV
3244
    return code;
×
3245
  }
3246

3247
  if (rpcRsp.code != 0) {
×
3248
    code = rpcRsp.code;
×
UNCOV
3249
    tscError("instance register failed, code:%s", tstrerror(code));
×
3250
  } else {
UNCOV
3251
    code = TSDB_CODE_SUCCESS;
×
3252
  }
3253

3254
  if (rpcRsp.pCont != NULL) {
×
UNCOV
3255
    rpcFreeCont(rpcRsp.pCont);
×
3256
  }
UNCOV
3257
  rpcClose(clientRpc);
×
3258

3259
  terrno = code;
×
UNCOV
3260
  return code;
×
3261
}
3262

3263
int32_t taos_list_instances(const char *filter_type, char ***pList, int32_t *pCount) {
×
3264
  if (pList == NULL || pCount == NULL) {
×
UNCOV
3265
    return TSDB_CODE_INVALID_PARA;
×
3266
  }
3267

3268
  int32_t code = taos_init();
×
3269
  if (code != TSDB_CODE_SUCCESS) {
×
3270
    terrno = code;
×
UNCOV
3271
    return code;
×
3272
  }
3273

3274
  SConfig *pCfg = taosGetCfg();
×
3275
  if (pCfg == NULL) {
×
3276
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
UNCOV
3277
    return TSDB_CODE_CFG_NOT_FOUND;
×
3278
  }
3279

3280
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
×
3281
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
×
3282
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
UNCOV
3283
    return TSDB_CODE_CFG_NOT_FOUND;
×
3284
  }
3285

3286
  SEp firstEp = {0};
×
3287
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
×
3288
  if (code != TSDB_CODE_SUCCESS) {
×
3289
    terrno = code;
×
UNCOV
3290
    return code;
×
3291
  }
3292

3293
  // Initialize RPC connection (similar to taos_register_instance)
3294
  void    *clientRpc = NULL;
×
3295
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
×
3296
  SRpcMsg  rpcMsg = {0};
×
3297
  SRpcMsg  rpcRsp = {0};
×
UNCOV
3298
  SRpcInit rpcInit = {0};
×
3299

3300
  rpcInit.label = "LIST";
×
3301
  rpcInit.numOfThreads = 1;
×
3302
  rpcInit.cfp = NULL;
×
3303
  rpcInit.sessions = 16;
×
3304
  rpcInit.connType = TAOS_CONN_CLIENT;
×
3305
  rpcInit.idleTime = tsShellActivityTimer * 1000;
×
3306
  rpcInit.compressSize = tsCompressMsgSize;
×
UNCOV
3307
  rpcInit.user = TSDB_DEFAULT_USER;
×
3308

3309
  rpcInit.rfp = instanceRegisterRpcRfp;
×
3310
  rpcInit.retryMinInterval = tsRedirectPeriod;
×
3311
  rpcInit.retryStepFactor = tsRedirectFactor;
×
3312
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
×
UNCOV
3313
  rpcInit.retryMaxTimeout =
×
3314
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3315

3316
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
×
3317
  connLimitNum = TMAX(connLimitNum, 10);
×
3318
  connLimitNum = TMIN(connLimitNum, 500);
×
3319
  rpcInit.connLimitNum = connLimitNum;
×
3320
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
×
3321
  rpcInit.readTimeout = tsReadTimeout;
×
3322
  rpcInit.ipv6 = tsEnableIpv6;
×
UNCOV
3323
  rpcInit.enableSSL = tsEnableTLS;
×
3324

3325
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
×
3326
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
×
3327
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
×
3328
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
×
UNCOV
3329
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
×
3330

3331
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
×
3332
  if (code != TSDB_CODE_SUCCESS) {
×
3333
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
UNCOV
3334
    return code;
×
3335
  }
3336

3337
  clientRpc = rpcOpen(&rpcInit);
×
3338
  if (clientRpc == NULL) {
×
3339
    code = terrno;
×
3340
    tscError("failed to init instance list client since %s", tstrerror(code));
×
3341
    terrno = code;
×
UNCOV
3342
    return code;
×
3343
  }
3344

3345
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
×
3346
  epSet.eps[0].port = firstEp.port;
×
3347
  SInstanceListReq req = {0};
×
3348
  if (filter_type != NULL && filter_type[0] != 0) {
×
UNCOV
3349
    tstrncpy(req.filter_type, filter_type, sizeof(req.filter_type));
×
3350
  }
3351

3352
  // Serialize request to get required length
3353
  int32_t contLen = tSerializeSInstanceListReq(NULL, 0, &req);
×
3354
  if (contLen <= 0) {
×
3355
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3356
    rpcClose(clientRpc);
×
3357
    terrno = code;
×
UNCOV
3358
    return code;
×
3359
  }
3360

3361
  // Allocate RPC message buffer (includes message header overhead)
3362
  void *pCont = rpcMallocCont(contLen);
×
3363
  if (pCont == NULL) {
×
3364
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3365
    rpcClose(clientRpc);
×
3366
    terrno = code;
×
UNCOV
3367
    return code;
×
3368
  }
3369

3370
  // Serialize request into the content part (after message header)
3371
  if (tSerializeSInstanceListReq(pCont, contLen, &req) < 0) {
×
3372
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3373
    rpcFreeCont(pCont);
×
3374
    rpcClose(clientRpc);
×
3375
    terrno = code;
×
UNCOV
3376
    return code;
×
3377
  }
3378

3379
  rpcMsg.pCont = pCont;
×
3380
  rpcMsg.contLen = contLen;
×
3381
  rpcMsg.msgType = TDMT_MND_LIST_INSTANCES;
×
3382
  rpcMsg.info.ahandle = (void *)0x9529;  // Different magic number from register
×
UNCOV
3383
  rpcMsg.info.notFreeAhandle = 1;
×
3384

3385
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
×
3386
  if (TSDB_CODE_SUCCESS != code) {
×
3387
    tscError("failed to send instance list req since %s", tstrerror(code));
×
3388
    rpcFreeCont(pCont);
×
3389
    rpcClose(clientRpc);
×
3390
    terrno = code;
×
UNCOV
3391
    return code;
×
3392
  }
3393

3394
  // Check response - rpcRsp.code contains the result code from mnode
3395
  if (rpcRsp.code != 0) {
×
3396
    code = rpcRsp.code;
×
3397
    tscError("instance list failed, code:%s", tstrerror(code));
×
3398
    if (rpcRsp.pCont != NULL) {
×
UNCOV
3399
      rpcFreeCont(rpcRsp.pCont);
×
3400
    }
3401
    rpcClose(clientRpc);
×
3402
    terrno = code;
×
UNCOV
3403
    return code;
×
3404
  }
3405

3406
  // Deserialize response
3407
  if (rpcRsp.pCont != NULL && rpcRsp.contLen > 0) {
×
3408
    SInstanceListRsp rsp = {0};
×
3409
    code = tDeserializeSInstanceListRsp(rpcRsp.pCont, rpcRsp.contLen, &rsp);
×
3410
    if (code != TSDB_CODE_SUCCESS) {
×
3411
      tscError("failed to deserialize instance list rsp, code:%s", tstrerror(code));
×
3412
      if (rsp.ids != NULL) {
×
3413
        for (int32_t i = 0; i < rsp.count; i++) {
×
3414
          if (rsp.ids[i] != NULL) {
×
UNCOV
3415
            taosMemoryFree(rsp.ids[i]);
×
3416
          }
3417
        }
3418
        taosMemoryFree(rsp.ids);
×
UNCOV
3419
        rsp.ids = NULL;
×
3420
      }
3421
      rsp.count = 0;
×
3422
      rpcFreeCont(rpcRsp.pCont);
×
3423
      rpcClose(clientRpc);
×
3424
      terrno = code;
×
UNCOV
3425
      return code;
×
3426
    }
3427
    *pList = rsp.ids;
×
UNCOV
3428
    *pCount = rsp.count;
×
3429
  } else {
3430
    *pList = NULL;
×
UNCOV
3431
    *pCount = 0;
×
3432
  }
3433

3434
  if (rpcRsp.pCont != NULL) {
×
UNCOV
3435
    rpcFreeCont(rpcRsp.pCont);
×
3436
  }
UNCOV
3437
  rpcClose(clientRpc);
×
3438

UNCOV
3439
  return TSDB_CODE_SUCCESS;
×
3440
}
3441

3442
void taos_free_instances(char ***pList, int32_t count) {
×
3443
  if (pList == NULL || *pList == NULL || count <= 0) {
×
UNCOV
3444
    return;
×
3445
  }
3446

3447
  // Free each string in the array
3448
  for (int32_t i = 0; i < count; i++) {
×
3449
    if ((*pList)[i] != NULL) {
×
3450
      taosMemoryFree((*pList)[i]);
×
UNCOV
3451
      (*pList)[i] = NULL;
×
3452
    }
3453
  }
3454

3455
  // Free the array itself
3456
  taosMemoryFree(*pList);
×
UNCOV
3457
  *pList = NULL;
×
3458
}
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