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

taosdata / TDengine / #4990

17 Mar 2026 03:40AM UTC coverage: 69.348% (+0.5%) from 68.862%
#4990

push

travis-ci

web-flow
Merge c54c3d8de into e29fadda2

31 of 44 new or added lines in 2 files covered. (70.45%)

527 existing lines in 3 files now uncovered.

184525 of 266084 relevant lines covered (69.35%)

303865407.08 hits per line

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

53.99
/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 "clientSession.h"
21
#include "clientStmt.h"
22
#include "clientStmt2.h"
23
#include "functionMgt.h"
24
#include "os.h"
25
#include "query.h"
26
#include "scheduler.h"
27
#include "tcompare.h"
28
#include "tconv.h"
29
#include "tdatablock.h"
30
#include "tglobal.h"
31
#include "tmisce.h"
32
#include "tmsg.h"
33
#include "tref.h"
34
#include "trpc.h"
35
#include "ttime.h"
36
#include "tversion.h"
37
#include "version.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, ...) {
1,064,375,728✔
50
  if (arg == NULL) {
1,064,375,728✔
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) {
2,147,483,647✔
56
    if (i % 1000 == 0) {
2,147,483,647✔
57
      (void)sched_yield();
122,374,564✔
58
    }
59
  }
60

61
  int ret = taos_options_imp(option, (const char *)arg);
8,157,968✔
62
  atomic_store_32(&lock, 0);
1,064,413,961✔
63
  return ret;
1,064,413,961✔
64
}
65

66
#if !defined(WINDOWS) && !defined(TD_ASTRA)
67
static void freeTz(void *p) {
28,431✔
68
  timezone_t tz = *(timezone_t *)p;
28,431✔
69
  tzfree(tz);
28,431✔
70
}
28,431✔
71
#endif
72

17,381,208✔
73
int32_t tzInit() {
17,381,208✔
74
#if !defined(WINDOWS) && !defined(TD_ASTRA)
17,381,208✔
UNCOV
75
  pTimezoneMap = taosHashInit(0, MurmurHash3_32, false, HASH_ENTRY_LOCK);
×
76
  if (pTimezoneMap == NULL) {
77
    return terrno;
17,381,208✔
78
  }
79
  taosHashSetFreeFp(pTimezoneMap, freeTz);
17,381,208✔
80

17,381,208✔
UNCOV
81
  pTimezoneNameMap = taosHashInit(0, taosIntHash_64, false, HASH_ENTRY_LOCK);
×
82
  if (pTimezoneNameMap == NULL) {
83
    return terrno;
17,381,208✔
84
  }
85
#endif
86
  return 0;
17,381,780✔
87
}
17,381,780✔
88

17,381,780✔
89
void tzCleanup() {
17,381,780✔
90
#if !defined(WINDOWS) && !defined(TD_ASTRA)
91
  taosHashCleanup(pTimezoneMap);
46,969✔
92
  taosHashCleanup(pTimezoneNameMap);
46,969✔
93
#endif
46,969✔
94
}
46,969✔
95

18,538✔
96
#if !defined(WINDOWS) && !defined(TD_ASTRA)
18,538✔
97
static timezone_t setConnnectionTz(const char *val) {
98
  timezone_t  tz = NULL;
99
  timezone_t *tmp = taosHashGet(pTimezoneMap, val, strlen(val));
28,431✔
100
  if (tmp != NULL && *tmp != NULL) {
28,431✔
101
    tz = *tmp;
28,431✔
102
    goto END;
2,470✔
103
  }
2,470✔
104

2,470✔
UNCOV
105
  tscDebug("set timezone to %s", val);
×
UNCOV
106
  tz = tzalloc(val);
×
UNCOV
107
  if (tz == NULL) {
×
108
    tscWarn("%s unknown timezone %s change to UTC", __func__, val);
109
    tz = tzalloc("UTC");
110
    if (tz == NULL) {
28,431✔
111
      tscError("%s set timezone UTC error", __func__);
28,431✔
112
      terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
113
      goto END;
×
UNCOV
114
    }
×
UNCOV
115
  }
×
116
  int32_t code = taosHashPut(pTimezoneMap, val, strlen(val), &tz, sizeof(timezone_t));
117
  if (code != 0) {
118
    tscError("%s put timezone to tz map error:%d", __func__, code);
28,431✔
119
    tzfree(tz);
28,431✔
120
    tz = NULL;
28,431✔
121
    goto END;
28,431✔
122
  }
28,431✔
123

124
  time_t tx1 = taosGetTimestampSec();
28,431✔
UNCOV
125
  char   output[TD_TIMEZONE_LEN] = {0};
×
126
  code = taosFormatTimezoneStr(tx1, val, tz, output);
127
  if (code == 0) {
128
    code = taosHashPut(pTimezoneNameMap, &tz, sizeof(timezone_t), output, strlen(output) + 1);
28,431✔
129
  }
46,969✔
130
  if (code != 0) {
131
    tscError("failed to put timezone %s to map", val);
132
  }
133

121,654✔
134
END:
121,654✔
135
  return tz;
2,470✔
136
}
137
#endif
138

139
static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, const char *val) {
140
  if (taos == NULL) {
141
    return terrno = TSDB_CODE_INVALID_PARA;
142
  }
143

144
#ifdef WINDOWS
119,184✔
145
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE) {
2,470✔
146
    return terrno = TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS;
147
  }
148
#endif
116,714✔
149

150
  if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION) {
116,714✔
UNCOV
151
    return terrno = TSDB_CODE_INVALID_PARA;
×
152
  }
153

154
  int32_t code = taos_init();
116,714✔
155
  // initialize global config
116,714✔
UNCOV
156
  if (code != 0) {
×
157
    return terrno = code;
×
158
  }
159

160
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
116,714✔
161
  if (NULL == pObj) {
2,470✔
162
    tscError("invalid parameter for %s", __func__);
163
    return terrno;
164
  }
165

116,714✔
166
  if (option == TSDB_OPTION_CONNECTION_CLEAR) {
22,230✔
167
    val = NULL;
14,820✔
168
  }
3,705✔
169

3,705✔
170
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
171
  if (option == TSDB_OPTION_CONNECTION_CHARSET || option == TSDB_OPTION_CONNECTION_CLEAR) {
11,115✔
172
    if (val != NULL) {
11,115✔
173
      if (!taosValidateEncodec(val)) {
2,470✔
174
        code = terrno;
2,470✔
175
        goto END;
176
      }
8,645✔
177
      void *tmp = taosConvInit(val);
178
      if (tmp == NULL) {
7,410✔
179
        code = terrno;
180
        goto END;
181
      }
182
      pObj->optionInfo.charsetCxt = tmp;
110,539✔
183
    } else {
184
      pObj->optionInfo.charsetCxt = NULL;
51,909✔
185
    }
46,969✔
186
  }
2,470✔
187
#endif
188
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) {
46,969✔
189
#if !defined(WINDOWS) && !defined(TD_ASTRA)
46,969✔
UNCOV
190
    if (val != NULL) {
×
UNCOV
191
      if (val[0] == 0) {
×
192
        val = "UTC";
193
      }
46,969✔
194
      timezone_t tz = setConnnectionTz(val);
195
      if (tz == NULL) {
4,940✔
196
        code = terrno;
197
        goto END;
198
      }
199
      pObj->optionInfo.timezone = tz;
200
    } else {
110,539✔
201
      pObj->optionInfo.timezone = NULL;
14,495✔
202
    }
9,555✔
203
#endif
204
  }
4,940✔
205

206
  if (option == TSDB_OPTION_CONNECTION_USER_APP || option == TSDB_OPTION_CONNECTION_CLEAR) {
207
    if (val != NULL) {
208
      tstrncpy(pObj->optionInfo.userApp, val, sizeof(pObj->optionInfo.userApp));
110,539✔
209
    } else {
14,495✔
210
      pObj->optionInfo.userApp[0] = 0;
9,555✔
211
    }
212
  }
4,940✔
213

214
  if (option == TSDB_OPTION_CONNECTION_CONNECTOR_INFO || option == TSDB_OPTION_CONNECTION_CLEAR) {
215
    if (val != NULL) {
216
      tstrncpy(pObj->optionInfo.cInfo, val, sizeof(pObj->optionInfo.cInfo));
110,539✔
217
    } else {
23,465✔
218
      pObj->optionInfo.cInfo[0] = 0;
23,465✔
219
    }
16,055✔
220
  }
16,055✔
221

16,055✔
222
  if (option == TSDB_OPTION_CONNECTION_USER_IP || option == TSDB_OPTION_CONNECTION_CLEAR) {
16,055✔
223
    SIpRange dualIp = {0};
8,645✔
224
    if (val != NULL) {
225
      pObj->optionInfo.userIp = taosInetAddr(val);
16,055✔
226
      SIpAddr addr = {0};
7,410✔
227
      code = taosGetIpFromFqdn(tsEnableIpv6, val, &addr);
228
      if (code == 0) {
7,410✔
229
        code = tIpStrToUint(&addr, &pObj->optionInfo.userDualIp);
7,410✔
230
      }
7,410✔
231
      if (code != 0) {
232
        tscError("ipv6 flag %d failed to convert user ip %s to dual ip since %s", tsEnableIpv6 ? 1 : 0, val,
233
                 tstrerror(code));
7,410✔
234
        pObj->optionInfo.userIp = INADDR_NONE;
7,410✔
235
        pObj->optionInfo.userDualIp = dualIp;
236
        code = 0;
237
      }
238
    } else {
87,074✔
239
      pObj->optionInfo.userIp = INADDR_NONE;
116,714✔
240
      pObj->optionInfo.userDualIp = dualIp;
116,714✔
241
    }
242
  }
243

121,654✔
244
END:
121,654✔
245
  releaseTscObj(*(int64_t *)taos);
246
  return terrno = code;
247
}
248

17,392,531✔
249
int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...) {
17,392,531✔
250
  return setConnectionOption(taos, option, (const char *)arg);
17,392,531✔
251
}
10,751✔
252

253
// this function may be called by user or system, or by both simultaneously.
254
void taos_cleanup(void) {
17,381,780✔
255
  tscInfo("start to cleanup client environment");
17,381,780✔
256
  if (atomic_val_compare_exchange_32(&sentinel, TSC_VAR_NOT_RELEASE, TSC_VAR_RELEASED) != TSC_VAR_NOT_RELEASE) {
257
    return;
17,381,780✔
258
  }
259

17,381,780✔
260
  monitorClose();
17,381,780✔
261
  tscStopCrashReport();
262

17,381,780✔
263
  hbMgrCleanUp();
17,381,780✔
264

265
  catalogDestroy();
266
  schedulerDestroy();
17,381,780✔
267

268
  fmFuncMgtDestroy();
17,381,780✔
269
  qCleanupKeywordsTable();
270

17,381,780✔
271
#if !defined(WINDOWS) && !defined(TD_ASTRA)
17,381,780✔
272
  tzCleanup();
17,381,780✔
273
#endif
274
  tmqMgmtClose();
17,381,780✔
275

17,381,780✔
276
  int32_t id = clientReqRefPool;
17,381,780✔
277
  clientReqRefPool = -1;
278
  taosCloseRef(id);
17,381,780✔
279

17,381,780✔
280
  id = clientConnRefPool;
17,381,780✔
281
  clientConnRefPool = -1;
17,381,780✔
282
  taosCloseRef(id);
283

17,381,780✔
UNCOV
284
  nodesDestroyAllocatorSet();
×
285
  cleanupAppInfo();
286
  rpcCleanup();
287
  tscDebug("rpc cleanup");
17,381,780✔
288

289
  if (TSDB_CODE_SUCCESS != cleanupTaskQueue()) {
17,381,780✔
290
    tscWarn("failed to cleanup task queue");
17,381,780✔
291
  }
292

293
  sessMgtDestroy();
294

17,381,780✔
295
  taosConvDestroy();
17,381,780✔
296
  DestroyRegexCache();
297
#ifdef TAOSD_INTEGRATED
17,381,780✔
298
  shellStopDaemon();
299
#endif
300
  tscInfo("all local resources released");
301
  taosCleanupCfg();
182✔
302
#ifndef TAOSD_INTEGRATED
182✔
303
  taosCloseLog();
304
#endif
182✔
305
}
306

307
static setConfRet taos_set_config_imp(const char *config) {
182✔
308
  setConfRet ret = {SET_CONF_RET_SUCC, {0}};
309
  // TODO: need re-implementation
182✔
310
  return ret;
311
}
182✔
312

313
setConfRet taos_set_config(const char *config) {
314
  // TODO  pthread_mutex_lock(&setConfMutex);
1,089,464,883✔
315
  setConfRet ret = taos_set_config_imp(config);
1,089,464,883✔
316
  //  pthread_mutex_unlock(&setConfMutex);
1,089,463,817✔
317
  return ret;
2,372,565✔
318
}
319

320
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
1,089,463,817✔
321
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
2,372,565✔
322
  if (user == NULL) {
323
    user = TSDB_DEFAULT_USER;
324
  }
1,089,463,817✔
325

1,089,463,817✔
326
  if (pass == NULL) {
1,089,275,486✔
327
    pass = TSDB_DEFAULT_PASS;
1,089,177,219✔
328
  }
1,089,245,703✔
UNCOV
329

×
UNCOV
330
  STscObj *pObj = NULL;
×
331
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY, &pObj);
332
  if (TSDB_CODE_SUCCESS == code) {
1,089,245,703✔
333
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
1,089,244,312✔
334
    if (NULL == rid) {
335
      tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db);
155,818✔
336
      return NULL;
337
    }
338
    *rid = pObj->id;
157,716✔
339
    return (TAOS *)rid;
340
  } else {
341
    terrno = code;
28,405✔
342
  }
28,405✔
343

3,705✔
344
  return NULL;
3,705✔
345
}
3,705✔
346

347
void taos_set_option(OPTIONS *options, const char *key, const char *value) {
348
  if (options == NULL || key == NULL || value == NULL) {
24,700✔
349
    terrno = TSDB_CODE_INVALID_PARA;
24,700✔
350
    tscError("taos_set_option invalid parameter, options: %p, key: %p, value: %p", options, key, value);
24,700✔
351
    return;
1,235✔
352
  }
1,235✔
353

1,235✔
354
  size_t count = (size_t)options->count;
355
  size_t len = sizeof(options->keys) / sizeof(options->keys[0]);
356
  if (count >= len) {
23,465✔
357
    terrno = TSDB_CODE_INVALID_PARA;
23,465✔
358
    tscError("taos_set_option overflow, count: %zu, reached capacity: %zu", count, len);
23,465✔
359
    return;
360
  }
361

25,935✔
362
  options->keys[count] = key;
25,935✔
363
  options->values[count] = value;
7,410✔
364
  options->count = (uint16_t)(count + 1);
7,410✔
365
}
1,235✔
366

1,235✔
367
static int set_connection_option_or_close(TAOS *taos, TSDB_OPTION_CONNECTION option, const char *value) {
1,235✔
368
  if (value == NULL) return TSDB_CODE_SUCCESS;
369
  int code = taos_options_connection(taos, option, value);
6,175✔
370
  if (code != TSDB_CODE_SUCCESS) {
371
    tscError("failed to set option(%d): %s", (int)option, value);
372
    taos_close(taos);
7,410✔
373
    return code;
7,410✔
374
  }
7,410✔
375
  return TSDB_CODE_SUCCESS;
7,410✔
376
}
7,410✔
377

7,410✔
378
TAOS *taos_connect_with(const OPTIONS *options) {
379
  const char *ip = NULL;
7,410✔
380
  const char *user = NULL;
7,410✔
381
  const char *pass = NULL;
7,410✔
382
  const char *db = NULL;
7,410✔
383
  uint16_t    port = 0;
7,410✔
384

385
  const char *charset = NULL;
7,410✔
386
  const char *timezone = NULL;
6,175✔
387
  const char *userIp = NULL;
30,875✔
388
  const char *userApp = NULL;
24,700✔
389
  const char *connectorInfo = NULL;
24,700✔
390

24,700✔
391
  if (options && options->count > 0) {
3,705✔
392
    size_t count = (size_t)options->count;
3,705✔
393
    for (size_t i = 0; i < count; ++i) {
394
      const char *key = options->keys[i];
395
      const char *value = options->values[i];
20,995✔
396
      if (key == NULL || value == NULL) {
4,940✔
397
        tscWarn("taos_connect_with option key or value is NULL, index: %zu", i);
16,055✔
398
        continue;
1,235✔
399
      }
14,820✔
400

1,235✔
401
      if (strcmp(key, "ip") == 0) {
13,585✔
402
        ip = value;
1,235✔
403
      } else if (strcmp(key, "user") == 0) {
12,350✔
404
        user = value;
3,705✔
405
      } else if (strcmp(key, "pass") == 0) {
8,645✔
406
        pass = value;
2,470✔
407
      } else if (strcmp(key, "db") == 0) {
6,175✔
408
        db = value;
1,235✔
409
      } else if (strcmp(key, "port") == 0) {
4,940✔
410
        port = (uint16_t)atoi(value);
1,235✔
411
      } else if (strcmp(key, "charset") == 0) {
3,705✔
412
        charset = value;
1,235✔
413
      } else if (strcmp(key, "timezone") == 0) {
2,470✔
414
        timezone = value;
1,235✔
415
      } else if (strcmp(key, "userIp") == 0) {
416
        userIp = value;
1,235✔
417
      } else if (strcmp(key, "userApp") == 0) {
418
        userApp = value;
419
      } else if (strcmp(key, "connectorInfo") == 0) {
420
        connectorInfo = value;
421
      } else {
7,410✔
422
        tscWarn("taos_connect_with unknown option key: %s", key);
7,410✔
423
      }
424
    }
6,175✔
425
  }
4,940✔
426

4,940✔
427
  TAOS *taos = taos_connect(ip, user, pass, db, port);
4,940✔
428
  if (taos == NULL) return NULL;
4,940✔
UNCOV
429

×
430
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_CHARSET, charset) != TSDB_CODE_SUCCESS) return NULL;
431
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_TIMEZONE, timezone) != TSDB_CODE_SUCCESS) return NULL;
4,940✔
432
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_USER_IP, userIp) != TSDB_CODE_SUCCESS) return NULL;
433
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_USER_APP, userApp) != TSDB_CODE_SUCCESS) return NULL;
434
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_CONNECTOR_INFO, connectorInfo) != TSDB_CODE_SUCCESS)
1,235✔
435
    return NULL;
1,235✔
436

1,235✔
437
  return taos;
1,235✔
438
}
439

440
TAOS *taos_connect_with_dsn(const char *dsn) {
17,290✔
441
  terrno = TSDB_CODE_OPS_NOT_SUPPORT;
17,290✔
UNCOV
442
  tscError("taos_connect_with_dsn not supported");
×
UNCOV
443
  return NULL;
×
444
}
445

446
int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type) {
17,290✔
447
  if (taos == NULL) {
17,290✔
448
    terrno = TSDB_CODE_INVALID_PARA;
×
449
    return terrno;
×
UNCOV
450
  }
×
451

452
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
453
  if (NULL == pObj) {
17,290✔
454
    terrno = TSDB_CODE_TSC_DISCONNECTED;
4,940✔
455
    tscError("invalid parameter for %s", __func__);
4,940✔
456
    return terrno;
4,940✔
457
  }
4,940✔
458

4,940✔
459
  switch (type) {
4,940✔
460
    case TAOS_NOTIFY_PASSVER: {
UNCOV
461
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
UNCOV
462
      pObj->passInfo.fp = fp;
×
UNCOV
463
      pObj->passInfo.param = param;
×
UNCOV
464
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
UNCOV
465
      break;
×
UNCOV
466
    }
×
467
    case TAOS_NOTIFY_WHITELIST_VER: {
468
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
12,350✔
469
      pObj->whiteListInfo.fp = fp;
12,350✔
470
      pObj->whiteListInfo.param = param;
12,350✔
471
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
12,350✔
472
      break;
12,350✔
473
    }
12,350✔
474
    case TAOS_NOTIFY_USER_DROPPED: {
UNCOV
475
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
UNCOV
476
      pObj->userDroppedInfo.fp = fp;
×
UNCOV
477
      pObj->userDroppedInfo.param = param;
×
UNCOV
478
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
UNCOV
479
      break;
×
UNCOV
480
    }
×
481
    case TAOS_NOTIFY_DATETIME_WHITELIST_VER: {
482
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
483
      pObj->dateTimeWhiteListInfo.fp = fp;
×
484
      pObj->dateTimeWhiteListInfo.param = param;
×
485
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
486
      break;
×
UNCOV
487
    }
×
488
    case TAOS_NOTIFY_TOKEN: {
489
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
490
      pObj->tokenNotifyInfo.fp = fp;
×
491
      pObj->tokenNotifyInfo.param = param;
×
492
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
493
      break;
494
    }
495
    default: {
496
      terrno = TSDB_CODE_INVALID_PARA;
17,290✔
497
      releaseTscObj(*(int64_t *)taos);
17,290✔
498
      return terrno;
499
    }
500
  }
501

502
  releaseTscObj(*(int64_t *)taos);
503
  return 0;
504
}
505

UNCOV
506
typedef struct SFetchWhiteListInfo {
×
UNCOV
507
  int64_t                     connId;
×
UNCOV
508
  __taos_async_whitelist_fn_t userCbFn;
×
UNCOV
509
  void                       *userParam;
×
UNCOV
510
} SFetchWhiteListInfo;
×
UNCOV
511

×
512
int32_t fetchWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
513
  SFetchWhiteListInfo *pInfo = (SFetchWhiteListInfo *)param;
×
514
  TAOS                *taos = &pInfo->connId;
×
515
  if (code != TSDB_CODE_SUCCESS) {
516
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
517
    taosMemoryFree(pMsg->pData);
×
518
    taosMemoryFree(pMsg->pEpSet);
×
519
    taosMemoryFree(pInfo);
×
520
    return code;
×
UNCOV
521
  }
×
UNCOV
522

×
523
  SGetUserIpWhiteListRsp wlRsp;
×
524
  if (TSDB_CODE_SUCCESS != tDeserializeSGetUserIpWhiteListRsp(pMsg->pData, pMsg->len, &wlRsp)) {
525
    taosMemoryFree(pMsg->pData);
526
    taosMemoryFree(pMsg->pEpSet);
×
527
    taosMemoryFree(pInfo);
×
528
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
529
    return terrno;
×
UNCOV
530
  }
×
UNCOV
531

×
532
  uint64_t *pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(uint64_t));
×
533
  if (pWhiteLists == NULL) {
534
    taosMemoryFree(pMsg->pData);
535
    taosMemoryFree(pMsg->pEpSet);
×
536
    taosMemoryFree(pInfo);
×
537
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
538
    return terrno;
UNCOV
539
  }
×
540

541
  for (int i = 0; i < wlRsp.numWhiteLists; ++i) {
×
542
    pWhiteLists[i] = ((uint64_t)wlRsp.pWhiteLists[i].mask << 32) | wlRsp.pWhiteLists[i].ip;
×
UNCOV
543
  }
×
UNCOV
544

×
545
  pInfo->userCbFn(pInfo->userParam, code, taos, wlRsp.numWhiteLists, pWhiteLists);
×
UNCOV
546

×
547
  taosMemoryFree(pWhiteLists);
548
  taosMemoryFree(pMsg->pData);
549
  taosMemoryFree(pMsg->pEpSet);
×
550
  taosMemoryFree(pInfo);
×
551
  tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
552
  return code;
×
553
}
554

555
void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *param) {
×
556
  if (NULL == taos) {
557
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
558
    return;
×
UNCOV
559
  }
×
UNCOV
560

×
561
  int64_t connId = *(int64_t *)taos;
562

563
  STscObj *pTsc = acquireTscObj(connId);
×
564
  if (NULL == pTsc) {
×
565
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
566
    return;
×
UNCOV
567
  }
×
UNCOV
568

×
569
  SGetUserWhiteListReq req;
×
570
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
571
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
572
  if (msgLen < 0) {
×
573
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
574
    releaseTscObj(connId);
×
575
    return;
×
UNCOV
576
  }
×
577

578
  void *pReq = taosMemoryMalloc(msgLen);
579
  if (pReq == NULL) {
×
580
    fp(param, terrno, taos, 0, NULL);
×
581
    releaseTscObj(connId);
×
582
    return;
×
UNCOV
583
  }
×
584

585
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
586
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
587
    taosMemoryFree(pReq);
×
588
    releaseTscObj(connId);
×
589
    return;
×
UNCOV
590
  }
×
UNCOV
591

×
592
  SFetchWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchWhiteListInfo));
593
  if (pParam == NULL) {
594
    fp(param, terrno, taos, 0, NULL);
×
595
    taosMemoryFree(pReq);
×
596
    releaseTscObj(connId);
597
    return;
×
UNCOV
598
  }
×
UNCOV
599

×
600
  pParam->connId = connId;
×
601
  pParam->userCbFn = fp;
×
UNCOV
602

×
603
  pParam->userParam = param;
×
604
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
605
  if (pSendInfo == NULL) {
606
    fp(param, terrno, taos, 0, NULL);
607
    taosMemoryFree(pParam);
×
608
    taosMemoryFree(pReq);
×
609
    releaseTscObj(connId);
×
610
    return;
×
UNCOV
611
  }
×
UNCOV
612

×
613
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
614
  pSendInfo->requestId = generateRequestId();
×
615
  pSendInfo->requestObjRefId = 0;
×
616
  pSendInfo->param = pParam;
×
617
  pSendInfo->fp = fetchWhiteListCallbackFn;
618
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST;
×
UNCOV
619

×
620
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
621
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
622
    tscWarn("failed to async send msg to server");
623
  }
624
  releaseTscObj(connId);
625
  return;
626
}
627

628
typedef struct SFetchIpWhiteListInfo {
629
  int64_t connId;
UNCOV
630
  bool    supportNeg;
×
UNCOV
631
  void   *userParam;
×
UNCOV
632

×
633
  __taos_async_ip_whitelist_fn_t userCbFn;
UNCOV
634
} SFetchIpWhiteListInfo;
×
635

636
int32_t fetchIpWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
637
  int32_t lino = 0;
×
638
  char  **pWhiteLists = NULL;
UNCOV
639

×
640
  SGetUserIpWhiteListRsp wlRsp = {0};
×
UNCOV
641

×
642
  SFetchIpWhiteListInfo *pInfo = (SFetchIpWhiteListInfo *)param;
643
  TAOS                  *taos = &pInfo->connId;
UNCOV
644

×
645
  if (code != TSDB_CODE_SUCCESS) {
×
646
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
647
    TAOS_CHECK_GOTO(code, &lino, _error);
UNCOV
648
  }
×
UNCOV
649

×
650
  if ((code = tDeserializeSGetUserIpWhiteListDualRsp(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
651
    TAOS_CHECK_GOTO(code, &lino, _error);
×
652
  }
653

654
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
655
  if (pWhiteLists == NULL) {
×
656
    code = terrno;
×
657
    TAOS_CHECK_GOTO(code, &lino, _error);
×
UNCOV
658
  }
×
659

660
  int32_t numWhiteLists = 0;
×
661
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
662
    SIpRange *pIpRange = &wlRsp.pWhiteListsDual[i];
×
663
    if (!pInfo->supportNeg && pIpRange->neg) {
×
664
      continue;
UNCOV
665
    }
×
666
    SIpAddr ipAddr = {0};
×
UNCOV
667

×
668
    code = tIpUintToStr(pIpRange, &ipAddr);
×
669
    TAOS_CHECK_GOTO(code, &lino, _error);
UNCOV
670

×
671
    char *ip = taosMemCalloc(1, IP_RESERVE_CAP);
×
672
    if (ip == NULL) {
×
673
      code = terrno;
674
      TAOS_CHECK_GOTO(code, &lino, _error);
×
675
    }
676
    if (ipAddr.type == 0) {
677
      if (pInfo->supportNeg) {
×
678
        snprintf(ip, IP_RESERVE_CAP, "%c %s/%d", pIpRange->neg ? '-' : '+', ipAddr.ipv4, ipAddr.mask);
×
679
      } else {
680
        snprintf(ip, IP_RESERVE_CAP, "%s/%d", ipAddr.ipv4, ipAddr.mask);
×
UNCOV
681
      }
×
682
    } else {
683
      if (ipAddr.ipv6[0] == 0) {
×
684
        memcpy(ipAddr.ipv6, "::", 2);
685
      }
686
      if (pInfo->supportNeg) {
×
687
        snprintf(ip, IP_RESERVE_CAP, "%c %s/%d", pIpRange->neg ? '-' : '+', ipAddr.ipv6, ipAddr.mask);
688
      } else {
689
        snprintf(ip, IP_RESERVE_CAP, "%s/%d", ipAddr.ipv6, ipAddr.mask);
×
UNCOV
690
      }
×
UNCOV
691
    }
×
692
    pWhiteLists[numWhiteLists++] = ip;
×
UNCOV
693
  }
×
694

695
  pInfo->userCbFn(pInfo->userParam, code, taos, numWhiteLists, pWhiteLists);
×
696
_error:
697
  if (pWhiteLists != NULL) {
×
698
    for (int32_t i = 0; i < numWhiteLists; i++) {
×
699
      taosMemFree(pWhiteLists[i]);
×
UNCOV
700
    }
×
701
    taosMemoryFree(pWhiteLists);
×
702
  }
703
  taosMemoryFree(pMsg->pData);
704
  taosMemoryFree(pMsg->pEpSet);
×
705
  taosMemoryFree(pInfo);
×
706
  tFreeSGetUserIpWhiteListDualRsp(&wlRsp);
×
707
  return code;
×
708
}
UNCOV
709

×
710
static void taosFetchIpWhiteList(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param, bool supportNeg) {
711
  if (NULL == taos) {
×
712
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
713
    return;
×
UNCOV
714
  }
×
715
  int64_t connId = *(int64_t *)taos;
716

717
  STscObj *pTsc = acquireTscObj(connId);
×
718
  if (NULL == pTsc) {
×
719
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
720
    return;
×
UNCOV
721
  }
×
UNCOV
722

×
723
  SGetUserWhiteListReq req;
×
724
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
725
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
726
  if (msgLen < 0) {
×
727
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
728
    releaseTscObj(connId);
×
729
    return;
×
UNCOV
730
  }
×
731

732
  void *pReq = taosMemoryMalloc(msgLen);
733
  if (pReq == NULL) {
×
734
    fp(param, terrno, taos, 0, NULL);
×
735
    releaseTscObj(connId);
×
736
    return;
×
UNCOV
737
  }
×
738

739
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
740
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
741
    taosMemoryFree(pReq);
×
742
    releaseTscObj(connId);
×
743
    return;
×
UNCOV
744
  }
×
UNCOV
745

×
746
  SFetchIpWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchIpWhiteListInfo));
747
  if (pParam == NULL) {
748
    fp(param, terrno, taos, 0, NULL);
×
749
    taosMemoryFree(pReq);
×
750
    releaseTscObj(connId);
×
751
    return;
×
752
  }
UNCOV
753

×
754
  pParam->connId = connId;
×
755
  pParam->supportNeg = supportNeg;
×
756
  pParam->userCbFn = fp;
×
757
  pParam->userParam = param;
×
UNCOV
758

×
759
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
760
  if (pSendInfo == NULL) {
761
    fp(param, terrno, taos, 0, NULL);
762
    taosMemoryFree(pParam);
×
763
    taosMemoryFree(pReq);
×
764
    releaseTscObj(connId);
×
765
    return;
×
UNCOV
766
  }
×
UNCOV
767

×
768
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
769
  pSendInfo->requestId = generateRequestId();
×
770
  pSendInfo->requestObjRefId = 0;
×
771
  pSendInfo->param = pParam;
×
772
  pSendInfo->fp = fetchIpWhiteListCallbackFn;
773
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST_DUAL;
×
UNCOV
774

×
775
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
776
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
777
    tscWarn("failed to async send msg to server");
×
UNCOV
778
  }
×
779
  releaseTscObj(connId);
×
780
  return;
UNCOV
781
}
×
UNCOV
782

×
783
void taos_fetch_whitelist_dual_stack_a(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param) {
×
784
  taosFetchIpWhiteList(taos, fp, param, false);
785
}
786

787
void taos_fetch_ip_whitelist_a(TAOS *taos, __taos_async_ip_whitelist_fn_t fp, void *param) {
788
  taosFetchIpWhiteList(taos, fp, param, true);
789
}
790

791
typedef struct SFetchDateTimeWhiteListInfo {
UNCOV
792
  int64_t                              connId;
×
UNCOV
793
  void                                *userParam;
×
UNCOV
794
  __taos_async_datetime_whitelist_fn_t userCbFn;
×
795
} SFetchDateTimeWhiteListInfo;
UNCOV
796

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

×
802
  SUserDateTimeWhiteList wlRsp = {0};
×
UNCOV
803

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

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

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

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

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

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

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

834
    if (item->absolute) {
×
835
      struct STm tm;
×
836
      (void)taosTs2Tm(item->start, TSDB_TIME_PRECISION_SECONDS, &tm, NULL);
×
837
      snprintf(p, 128, "%c %04d-%02d-%02d %02d:%02d %d", item->neg ? '-' : '+', tm.tm.tm_year + 1900, tm.tm.tm_mon + 1,
×
838
                          tm.tm.tm_mday, tm.tm.tm_hour, tm.tm.tm_min, duration);
UNCOV
839
    } else {
×
840
      int day = item->start / 86400;
841
      int hour = (item->start % 86400) / 3600;
842
      int minute = (item->start % 3600) / 60;
×
843
      snprintf(p, 128, "%c %s %02d:%02d %d", item->neg ? '-' : '+', weekdays[day], hour, minute, duration);
×
UNCOV
844
    }
×
845
    pWhiteLists[numWhiteLists++] = p;
×
UNCOV
846
  }
×
847

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

885
  void *pReq = taosMemoryMalloc(msgLen);
886
  if (pReq == NULL) {
×
887
    fp(param, terrno, taos, 0, NULL);
×
888
    releaseTscObj(connId);
×
889
    return;
×
UNCOV
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;
×
UNCOV
897
  }
×
UNCOV
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;
UNCOV
905
  }
×
UNCOV
906

×
907
  pParam->connId = connId;
×
908
  pParam->userCbFn = fp;
×
909
  pParam->userParam = param;
×
UNCOV
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;
×
UNCOV
918
  }
×
UNCOV
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;
×
UNCOV
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");
1,091,153,180✔
930
  }
1,091,153,180✔
931
  releaseTscObj(connId);
4,303✔
932
  return;
933
}
1,091,148,877✔
934

935
void taos_close_internal(void *taos) {
1,091,148,877✔
936
  if (taos == NULL) {
1,091,148,877✔
937
    return;
938
  }
1,091,148,877✔
939
  int32_t code = 0;
940

1,091,148,877✔
941
  STscObj *pTscObj = (STscObj *)taos;
1,091,163,450✔
UNCOV
942
  tscDebug("conn:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
×
943

944
  SSessParam para = {.type = SESSION_PER_USER, .value = -1, .noCheck = 1};
945

946
  code = tscUpdateSessMetric(pTscObj, &para);
1,091,163,450✔
947
  if (code != TSDB_CODE_SUCCESS) {
1,091,170,925✔
948
    tscWarn("conn:0x%" PRIx64 ", failed to update user:%s metric when close connection, code:%d", pTscObj->id,
×
949
            pTscObj->user, code);
950
  }
951

952
  code = tscUnrefSessMetric(pTscObj);
1,089,357,555✔
953
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
1,089,357,555✔
954
    tscError("conn:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
7,111✔
955
  }
956
}
957

1,089,350,444✔
958
void taos_close(TAOS *taos) {
1,089,358,257✔
UNCOV
959
  if (taos == NULL) {
×
UNCOV
960
    return;
×
961
  }
962

963
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
1,089,358,257✔
964
  if (NULL == pObj) {
1,089,352,056✔
965
    taosMemoryFree(taos);
1,089,327,512✔
966
    return;
967
  }
968

2,147,483,647✔
969
  taos_close_internal(pObj);
2,147,483,647✔
970
  releaseTscObj(*(int64_t *)taos);
12,100,803✔
971
  taosMemoryFree(taos);
972
}
973

2,147,483,647✔
974
int taos_errno(TAOS_RES *res) {
5,571,345✔
975
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
976
    return terrno;
977
  }
2,147,483,647✔
978

979
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
980
    return 0;
1,302,762,786✔
981
  }
1,302,762,786✔
982

12,133,953✔
983
  return ((SRequestObj *)res)->code;
12,137,528✔
984
}
985

572✔
986
const char *taos_errstr(TAOS_RES *res) {
572✔
987
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
988
    if (*(taosGetErrMsg()) == 0) {
989
      return (const char *)tstrerror(terrno);
990
    } else {
1,290,630,042✔
UNCOV
991
      (void)snprintf(taosGetErrMsgReturn(), ERR_MSG_LEN, "%s", taosGetErrMsg());
×
992
      return (const char *)taosGetErrMsgReturn();
993
    }
994
  }
1,290,630,900✔
995

1,290,630,900✔
996
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
380,889,782✔
997
    return "success";
998
  }
909,741,118✔
999

1000
  SRequestObj *pRequest = (SRequestObj *)res;
1001
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
1002
    return pRequest->msgBuf;
2,147,483,647✔
1003
  } else {
2,147,483,647✔
1004
    return (const char *)tstrerror(pRequest->code);
176,832,682✔
1005
  }
1006
}
1007

2,147,483,647✔
1008
void taos_free_result(TAOS_RES *res) {
1009
  if (NULL == res) {
2,147,483,647✔
1010
    return;
2,147,483,647✔
1011
  }
2,147,483,647✔
1012

2,147,483,647✔
1013
  tscTrace("res:%p, will be freed", res);
2,147,483,647✔
1014

1015
  if (TD_RES_QUERY(res)) {
1016
    SRequestObj *pRequest = (SRequestObj *)res;
151,041,423✔
1017
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query, res:%p", pRequest->requestId, res);
151,041,423✔
1018
    destroyRequest(pRequest);
150,062,965✔
1019
    return;
150,057,817✔
1020
  }
1,008,111✔
1021

45,981✔
1022
  SMqRspObj *pRsp = (SMqRspObj *)res;
45,981✔
1023
  if (TD_RES_TMQ(res)) {
962,130✔
1024
    tDeleteMqDataRsp(&pRsp->dataRsp);
869,544✔
1025
    doFreeReqResultInfo(&pRsp->resInfo);
92,586✔
1026
  } else if (TD_RES_TMQ_METADATA(res)) {
92,586✔
UNCOV
1027
    tDeleteSTaosxRsp(&pRsp->dataRsp);
×
UNCOV
1028
    doFreeReqResultInfo(&pRsp->resInfo);
×
1029
  } else if (TD_RES_TMQ_META(res)) {
1030
    tDeleteMqMetaRsp(&pRsp->metaRsp);
151,065,928✔
1031
  } else if (TD_RES_TMQ_BATCH_META(res)) {
1032
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
1033
  } else if (TD_RES_TMQ_RAW(res)) {
7,774✔
1034
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
7,774✔
1035
  }
5,876✔
1036
  taosMemoryFree(pRsp);
1037
}
1038

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

1,898✔
1044
  int64_t  rid = *(int64_t *)taos;
1045
  STscObj *pTscObj = acquireTscObj(rid);
1046
  if (pTscObj) {
2,147,483,647✔
1047
    stopAllRequests(pTscObj->pRequests);
2,147,483,647✔
UNCOV
1048
  }
×
1049
  releaseTscObj(rid);
1050
}
1051

2,147,483,647✔
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)) {
1054
    return 0;
1055
  }
2,147,483,647✔
1056

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

1061
int taos_num_fields(TAOS_RES *res) { return taos_field_count(res); }
1062

2,147,483,647✔
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)) {
1065
    return NULL;
1066
  }
2,147,483,647✔
1067

3,003✔
1068
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
3,003✔
1069
  return pResInfo->userFields;
1070
}
1071

1,742✔
1072
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
1,742✔
UNCOV
1073
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
×
1074
  return taosQueryImplWithReqid(taos, sql, false, reqid);
1075
}
1,742✔
1076

1,742✔
1077
TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res) {
1078
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1079
    return NULL;
2,147,483,647✔
1080
  }
2,147,483,647✔
UNCOV
1081
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
1082
  return pResInfo->fields;
1083
}
1084

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

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

2,147,483,647✔
1098
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
2,470✔
1099
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
2,470✔
1100
      return NULL;
2,470✔
1101
    }
1102

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

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

550,422,496✔
1121
    if (pResultInfo->current < pResultInfo->numOfRows) {
144,025,219✔
1122
      doSetOneRowPtr(pResultInfo);
1123
      pResultInfo->current += 1;
1124
      return pResultInfo->row;
406,370,029✔
1125
    } else {
406,389,555✔
1126
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
406,389,555✔
1127
        return NULL;
UNCOV
1128
      }
×
UNCOV
1129

×
1130
      doSetOneRowPtr(pResultInfo);
UNCOV
1131
      pResultInfo->current += 1;
×
UNCOV
1132
      return pResultInfo->row;
×
UNCOV
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");
2,147,483,647✔
1138
    terrno = TSDB_CODE_TMQ_INVALID_DATA;
2,147,483,647✔
1139
    return NULL;
1140
  }
2,147,483,647✔
1141
}
2,147,483,647✔
1142

2,147,483,647✔
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) {
1147
  int32_t len = 0;
2,147,483,647✔
1148
  for (int i = 0; i < num_fields; ++i) {
1,830,634,598✔
1149
    if (i > 0 && len < size - 1) {
1,830,733,567✔
1150
      str[len++] = ' ';
1151
    }
1152

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

657,007✔
1158
    switch (fields[i].type) {
657,007✔
1159
      case TSDB_DATA_TYPE_TINYINT:
657,488✔
1160
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
1161
        break;
659,958✔
1162

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

657,319✔
1167
      case TSDB_DATA_TYPE_SMALLINT:
657,371✔
1168
        len += tsnprintf(str + len, size - len, "%d", *((int16_t *)row[i]));
1169
        break;
2,147,483,647✔
1170

2,147,483,647✔
1171
      case TSDB_DATA_TYPE_USMALLINT:
2,147,483,647✔
1172
        len += tsnprintf(str + len, size - len, "%u", *((uint16_t *)row[i]));
1173
        break;
657,371✔
1174

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

2,147,483,647✔
1179
      case TSDB_DATA_TYPE_UINT:
2,147,483,647✔
1180
        len += tsnprintf(str + len, size - len, "%u", *((uint32_t *)row[i]));
1181
        break;
657,150✔
1182

657,150✔
1183
      case TSDB_DATA_TYPE_BIGINT:
657,631✔
1184
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
1185
        break;
264,387,864✔
1186

264,387,864✔
1187
      case TSDB_DATA_TYPE_UBIGINT:
264,387,864✔
1188
        len += tsnprintf(str + len, size - len, "%" PRIu64, *((uint64_t *)row[i]));
264,737,928✔
1189
        break;
265,582,590✔
1190

1191
      case TSDB_DATA_TYPE_FLOAT: {
2,147,483,647✔
1192
        float fv = 0;
2,147,483,647✔
1193
        fv = GET_FLOAT_VAL(row[i]);
2,147,483,647✔
1194
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
2,147,483,647✔
1195
      } break;
2,147,483,647✔
1196

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

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

UNCOV
1232
        uint32_t copyLen = TMIN(size - len - 1, charLen);
×
UNCOV
1233
        (void)memcpy(str + len, row[i], copyLen);
×
UNCOV
1234
        len += copyLen;
×
UNCOV
1235
      } break;
×
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;
UNCOV
1243
        }
×
UNCOV
1244

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

2,147,483,647✔
1249
        taosMemoryFree(data);
1250
      } break;
659,841✔
1251

659,841✔
1252
      case TSDB_DATA_TYPE_TIMESTAMP:
659,269✔
UNCOV
1253
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
×
1254
        break;
UNCOV
1255

×
UNCOV
1256
      case TSDB_DATA_TYPE_BOOL:
×
UNCOV
1257
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
×
UNCOV
1258
        break;
×
1259
      case TSDB_DATA_TYPE_DECIMAL64:
×
UNCOV
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;
2,147,483,647✔
1265
      } break;
×
1266
      default:
1267
        break;
1268
    }
2,147,483,647✔
1269

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

×
1278
  return len;
1279
}
1280

2,147,483,647✔
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)) {
1283
    return NULL;
UNCOV
1284
  }
×
UNCOV
1285

×
UNCOV
1286
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
UNCOV
1287
  return pResInfo->length;
×
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;
UNCOV
1294
  }
×
UNCOV
1295

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

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

×
UNCOV
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";
×
UNCOV
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";
11,720,371✔
1350
    default:
1351
      return "UNKNOWN";
1352
  }
2,147,483,647✔
1353
}
2,147,483,647✔
1354

2,147,483,647✔
UNCOV
1355
const char *taos_get_client_info() { return td_version; }
×
1356

1357
// return int32_t
1358
int taos_affected_rows(TAOS_RES *res) {
2,147,483,647✔
1359
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
2,147,483,647✔
1360
      TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1361
    return 0;
1362
  }
1363

1364
  SRequestObj    *pRequest = (SRequestObj *)res;
17,654,013✔
1365
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
17,654,013✔
1366
  return (int)pResInfo->numOfRows;
17,654,013✔
UNCOV
1367
}
×
1368

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

2,147,483,647✔
1376
  SRequestObj    *pRequest = (SRequestObj *)res;
2,147,483,647✔
UNCOV
1377
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
×
1378
  return pResInfo->numOfRows;
1379
}
1380

2,147,483,647✔
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;
2,147,483,647✔
1384
  }
2,147,483,647✔
1385

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

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

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

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

515,788✔
1414
  TAOS_RES *pRequest = taos_query(taos, sql);
1415
  int32_t   code = taos_errno(pRequest);
1416

2,147,483,647✔
1417
  taos_free_result(pRequest);
2,147,483,647✔
1418
  releaseTscObj(*(int64_t *)taos);
2,147,483,647✔
UNCOV
1419
  return code;
×
1420
}
1421

1422
void taos_stop_query(TAOS_RES *res) {
2,147,483,647✔
1423
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1424
      TD_RES_TMQ_BATCH_META(res)) {
1425
    return;
×
UNCOV
1426
  }
×
UNCOV
1427

×
1428
  stopAllQueries((SRequestObj *)res);
UNCOV
1429
}
×
UNCOV
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;
UNCOV
1434
  }
×
1435
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
×
1436
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
×
1437
    return true;
UNCOV
1438
  }
×
1439

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

2,147,483,647✔
1448
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
1449

1450
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
2,147,483,647✔
1451
  int32_t numOfRows = 0;
2,147,483,647✔
UNCOV
1452
  /*int32_t code = */ terrno = taos_fetch_block_s(res, &numOfRows, rows);
×
1453
  return numOfRows;
1454
}
1455

2,147,483,647✔
1456
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
2,147,483,647✔
1457
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1458
    return 0;
2,147,483,647✔
1459
  }
2,147,483,647✔
1460

1461
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1462
    SRequestObj *pRequest = (SRequestObj *)res;
2,147,483,647✔
1463

18,148,338✔
1464
    (*rows) = NULL;
1465
    (*numOfRows) = 0;
1466

2,147,483,647✔
1467
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
1468
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
1469
      return pRequest->code;
2,147,483,647✔
1470
    }
2,147,483,647✔
1471

1472
    (void)doAsyncFetchRows(pRequest, false, true);
2,147,483,647✔
1473

2,147,483,647✔
1474
    // TODO refactor
2,147,483,647✔
1475
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
10,974,899✔
1476
    pResultInfo->current = pResultInfo->numOfRows;
10,974,899✔
1477

10,974,899✔
1478
    (*rows) = pResultInfo->row;
10,974,899✔
1479
    (*numOfRows) = pResultInfo->numOfRows;
1480
    return pRequest->code;
5,506,696✔
1481
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
5,506,696✔
1482
    SReqResultInfo *pResultInfo = NULL;
5,506,696✔
1483
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
5,506,696✔
1484
    if (code != 0) return code;
UNCOV
1485

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

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

29,510✔
1500
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
29,510✔
1501
    return 0;
29,510✔
1502
  }
14,755✔
1503

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

1512
    pResultInfo->current = pResultInfo->numOfRows;
46,644✔
1513
    (*numOfRows) = pResultInfo->numOfRows;
1514
    (*pData) = (void *)pResultInfo->pData;
46,644✔
1515
    return 0;
46,644✔
UNCOV
1516
  }
×
1517

1518
  SRequestObj *pRequest = (SRequestObj *)res;
1519

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

46,644✔
1525
  (void)doAsyncFetchRows(pRequest, false, false);
46,644✔
1526

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

1529
  pResultInfo->current = pResultInfo->numOfRows;
1530
  (*numOfRows) = pResultInfo->numOfRows;
2,147,483,647✔
1531
  (*pData) = (void *)pResultInfo->pData;
2,147,483,647✔
UNCOV
1532

×
1533
  return pRequest->code;
1534
}
1535

2,147,483,647✔
1536
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
2,147,483,647✔
UNCOV
1537
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1538
    return NULL;
1539
  }
1540

2,147,483,647✔
1541
  int32_t numOfFields = taos_num_fields(res);
2,147,483,647✔
1542
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
2,147,483,647✔
1543
    return NULL;
×
1544
  }
1545

1546
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1547
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
1548
  if (!IS_VAR_DATA_TYPE(pField->type)) {
1549
    return NULL;
2,147,483,647✔
1550
  }
2,147,483,647✔
1551

2,147,483,647✔
UNCOV
1552
  return pResInfo->pCol[columnIndex].offset;
×
1553
}
1554

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

2,147,483,647✔
1561
  int32_t numOfFields = taos_num_fields(res);
2,147,483,647✔
1562
  if (columnIndex >= numOfFields || numOfFields == 0) {
2,147,483,647✔
1563
    return TSDB_CODE_INVALID_PARA;
1564
  }
2,147,483,647✔
UNCOV
1565

×
1566
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
1567
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
2,147,483,647✔
UNCOV
1568
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
×
UNCOV
1569

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

×
1598
  taos_free_result(pObj);
×
1599
  return code;
×
UNCOV
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

52,286✔
1609
  resetConnectDB(pTscObj);
52,286✔
1610

52,286✔
1611
  releaseTscObj(*(int64_t *)taos);
×
UNCOV
1612
}
×
1613

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

30,992✔
1621
  releaseTscObj(*(int64_t *)taos);
30,992✔
1622

30,992✔
UNCOV
1623
  return pTscObj->sDetailVer;
×
1624
}
1625

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

15,496✔
1632
  int code = TSDB_CODE_SUCCESS;
7,748✔
1633
  (void)taosThreadMutexLock(&pTscObj->mutex);
7,748✔
1634
  if (database == NULL || len <= 0) {
7,748✔
1635
    if (required != NULL) *required = strlen(pTscObj->db) + 1;
1636
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
7,748✔
1637
  } else if (len < strlen(pTscObj->db) + 1) {
7,748✔
1638
    tstrncpy(database, pTscObj->db, len);
1639
    if (required) *required = strlen(pTscObj->db) + 1;
30,992✔
1640
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
30,992✔
1641
  } else {
30,992✔
1642
    tstrncpy(database, pTscObj->db, len);
30,992✔
1643
    code = 0;
1644
  }
1645
_return:
1646
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
1647
  releaseTscObj(*(int64_t *)taos);
1648
  return code;
2,470✔
1649
}
2,470✔
UNCOV
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.
2,470✔
1654
int taos_get_connection_info(TAOS *taos, TSDB_CONNECTION_INFO info, char *buffer, int *len) {
2,470✔
UNCOV
1655
  if (len == NULL) {
×
1656
    return TSDB_CODE_INVALID_PARA;
1657
  }
1658

2,470✔
1659
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
2,470✔
1660
  if (pTscObj == NULL) {
1661
    return TSDB_CODE_TSC_DISCONNECTED;
2,470✔
1662
  }
1,235✔
1663

1,235✔
1664
  int code = TSDB_CODE_SUCCESS;
1,235✔
UNCOV
1665
  (void)taosThreadMutexLock(&pTscObj->mutex);
×
UNCOV
1666

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

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

2,470✔
1694
    default:
2,470✔
1695
      TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
2,470✔
1696
  }
1697

1698
_return:
2,147,483,647✔
1699
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
2,147,483,647✔
1700
  releaseTscObj(*(int64_t *)taos);
2,147,483,647✔
1701
  return code;
1702
}
2,147,483,647✔
1703

2,147,483,647✔
1704
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
2,147,483,647✔
1705
  if (NULL == pWrapper) {
2,147,483,647✔
1706
    return;
1707
  }
1708
  destoryCatalogReq(pWrapper->pCatalogReq);
34,977,722✔
1709
  taosMemoryFree(pWrapper->pCatalogReq);
34,977,722✔
1710
  qDestroyParseContext(pWrapper->pParseCtx);
34,977,722✔
1711
  taosMemoryFree(pWrapper);
34,977,722✔
1712
}
34,977,722✔
1713

34,977,722✔
1714
void destroyCtxInRequest(SRequestObj *pRequest) {
34,977,722✔
1715
  schedulerFreeJob(&pRequest->body.queryJob, 0);
1716
  qDestroyQuery(pRequest->pQuery);
2,147,483,647✔
1717
  pRequest->pQuery = NULL;
2,147,483,647✔
1718
  destorySqlCallbackWrapper(pRequest->pWrapper);
2,147,483,647✔
1719
  pRequest->pWrapper = NULL;
2,147,483,647✔
1720
}
1721

2,147,483,647✔
1722
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
1723
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
2,147,483,647✔
1724
  SRequestObj         *pRequest = pWrapper->pRequest;
2,147,483,647✔
1725
  SQuery              *pQuery = pRequest->pQuery;
2,147,483,647✔
1726

1727
  qDebug("req:0x%" PRIx64 ", start to semantic analysis, QID:0x%" PRIx64, pRequest->self, pRequest->requestId);
2,147,483,647✔
1728

2,147,483,647✔
1729
  int64_t analyseStart = taosGetTimestampUs();
1730
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
1731
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
2,147,483,647✔
1732

1733
  if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
1734
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
3,819,517✔
1735
  }
3,819,517✔
1736

1737
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
1738

2,147,483,647✔
1739
  if (pRequest->parseOnly) {
2,147,483,647✔
1740
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
UNCOV
1741
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
×
UNCOV
1742
  }
×
UNCOV
1743

×
UNCOV
1744
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
UNCOV
1745
}
×
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;
×
UNCOV
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;
×
UNCOV
1775
  }
×
UNCOV
1776

×
1777
  return code;
×
UNCOV
1778
}
×
UNCOV
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;
×
UNCOV
1787
  }
×
UNCOV
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);
×
UNCOV
1798
  }
×
1799
  if (TSDB_CODE_SUCCESS == code) {
1800
    code = cloneCatalogReq(&pNewWrapper->pCatalogReq, pWrapper->pCatalogReq);
×
UNCOV
1801
  }
×
1802
  if (TSDB_CODE_SUCCESS == code) {
1803
    doAsyncQueryFromAnalyse(pResultMeta, pNewWrapper, code);
1804
    nodesDestroyNode(pRoot);
1805
  } else {
2,147,483,647✔
1806
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
2,147,483,647✔
1807
    return;
2,147,483,647✔
1808
  }
1809
}
2,147,483,647✔
UNCOV
1810

×
UNCOV
1811
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
×
UNCOV
1812
  SRequestObj *pRequest = pWrapper->pRequest;
×
UNCOV
1813
  SQuery      *pQuery = pRequest->pQuery;
×
1814

1815
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
1816
    SNode *prevRoot = pQuery->pPrevRoot;
2,147,483,647✔
1817
    pQuery->pPrevRoot = NULL;
2,147,483,647✔
1818
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
2,147,483,647✔
1819
    return;
2,147,483,647✔
1820
  }
2,147,483,647✔
1821

20,826,234✔
1822
  if (code == TSDB_CODE_SUCCESS) {
1823
    pRequest->stableQuery = pQuery->stableQuery;
1824
    if (pQuery->pRoot) {
1825
      pRequest->stmtType = pQuery->pRoot->type;
2,147,483,647✔
1826
      if (nodeType(pQuery->pRoot) == QUERY_NODE_DELETE_STMT) {
2,147,483,647✔
1827
        pRequest->secureDelete = ((SDeleteStmt*)pQuery->pRoot)->secureDelete;
2,147,483,647✔
1828
      }
2,147,483,647✔
1829
    }
1830

1831
    if (pQuery->haveResultSet) {
1832
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema,
2,147,483,647✔
1833
                              pRequest->stmtBindVersion > 0);
2,147,483,647✔
1834
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
2,147,483,647✔
1835
    }
2,147,483,647✔
1836
  }
1837

2,147,483,647✔
1838
  if (code == TSDB_CODE_SUCCESS) {
1839
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
950,504,503✔
1840
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
950,639,794✔
1841
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
950,639,794✔
1842

950,617,343✔
1843
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
1844
  } else {
950,617,343✔
1845
    destorySqlCallbackWrapper(pWrapper);
33,750,067✔
1846
    pRequest->pWrapper = NULL;
1847
    qDestroyQuery(pRequest->pQuery);
33,750,067✔
1848
    pRequest->pQuery = NULL;
33,750,067✔
1849

1850
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
1851
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
1852
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
916,867,276✔
1853
      restartAsyncQuery(pRequest, code);
1854
      return;
917,084,909✔
1855
    }
917,084,909✔
1856

1857
    // return to app directly
1858
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self,
1859
             tstrerror(code), pRequest->requestId);
2,147,483,647✔
1860
    pRequest->code = code;
2,147,483,647✔
1861
    returnToUser(pRequest);
2,147,483,647✔
1862
  }
2,147,483,647✔
1863
}
2,147,483,647✔
1864

1865
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
2,147,483,647✔
1866
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
1867
                           .requestId = pWrapper->pParseCtx->requestId,
2,147,483,647✔
1868
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
2,147,483,647✔
1869
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
1870

1871
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
1872

1873
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
2,147,483,647✔
1874
                                &pWrapper->pRequest->body.queryJob);
2,147,483,647✔
1875
}
2,147,483,647✔
1876

89,915,397✔
1877
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1878

89,915,397✔
1879
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
89,915,540✔
1880
  int32_t code = TSDB_CODE_SUCCESS;
1881
  switch (pWrapper->pRequest->pQuery->execStage) {
2,147,483,647✔
1882
    case QUERY_EXEC_STAGE_PARSE: {
1883
      // continue parse after get metadata
2,147,483,647✔
1884
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
2,147,483,647✔
1885
      break;
1886
    }
2,147,483,647✔
1887
    case QUERY_EXEC_STAGE_ANALYSE: {
2,147,483,647✔
1888
      // analysis after get metadata
2,147,483,647✔
1889
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
UNCOV
1890
      break;
×
UNCOV
1891
    }
×
1892
    case QUERY_EXEC_STAGE_SCHEDULE: {
1893
      launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper);
2,147,483,647✔
1894
      break;
1895
    }
1896
    default:
89,915,540✔
1897
      break;
89,915,540✔
1898
  }
89,915,540✔
1899
  return code;
89,915,540✔
1900
}
1901

89,915,540✔
1902
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
89,915,540✔
1903
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
1904
  SRequestObj         *pRequest = pWrapper->pRequest;
1905
  SQuery              *pQuery = pRequest->pQuery;
89,915,540✔
1906

1907
  pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart;
89,523,447✔
1908
  qDebug("req:0x%" PRIx64 ", continue parse query, QID:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId,
1909
         tstrerror(code));
1910

89,915,540✔
1911
  if (code == TSDB_CODE_SUCCESS) {
82,426,890✔
1912
    // pWrapper->pCatalogReq->forceUpdate = false;
1913
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
1914
  }
89,915,540✔
1915

7,488,650✔
1916
  if (TSDB_CODE_SUCCESS == code) {
1917
    code = phaseAsyncQuery(pWrapper);
7,488,650✔
1918
  }
7,488,650✔
1919

7,488,650✔
1920
  if (TSDB_CODE_SUCCESS != code) {
7,488,650✔
1921
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
7,488,650✔
1922
             tstrerror(code), pWrapper->pRequest->requestId);
1923
    destorySqlCallbackWrapper(pWrapper);
89,915,540✔
1924
    pRequest->pWrapper = NULL;
1925
    terrno = code;
156,247✔
1926
    pRequest->code = code;
156,247✔
1927
    doRequestCallback(pRequest, code);
156,247✔
1928
  }
156,247✔
1929
}
1930

1931
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
156,247✔
UNCOV
1932
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
×
1933
  if (TSDB_CODE_SUCCESS == code) {
UNCOV
1934
    code = phaseAsyncQuery(pWrapper);
×
UNCOV
1935
  }
×
UNCOV
1936

×
UNCOV
1937
  if (TSDB_CODE_SUCCESS != code) {
×
1938
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
×
1939
             tstrerror(code), pWrapper->pRequest->requestId);
1940
    destorySqlCallbackWrapper(pWrapper);
156,247✔
1941
    pRequest->pWrapper = NULL;
1942
    terrno = code;
1,694,823✔
1943
    pRequest->code = code;
1,694,823✔
1944
    doRequestCallback(pRequest, code);
1,694,823✔
1945
  }
1,694,823✔
1946
}
UNCOV
1947

×
UNCOV
1948
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
×
UNCOV
1949
  int64_t connId = *(int64_t *)taos;
×
UNCOV
1950
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
×
1951
}
1952

2,147,483,647✔
1953
void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) {
2,147,483,647✔
1954
  int64_t connId = *(int64_t *)taos;
1955
  taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid);
2,147,483,647✔
1956
}
2,147,483,647✔
UNCOV
1957

×
1958
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
1959
  const STscObj *pTscObj = pRequest->pTscObj;
1960

2,147,483,647✔
1961
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
2,147,483,647✔
1962
  if (*pCxt == NULL) {
2,147,483,647✔
1963
    return terrno;
2,147,483,647✔
1964
  }
1965

2,147,483,647✔
1966
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
2,147,483,647✔
1967
                           .requestRid = pRequest->self,
2,147,483,647✔
1968
                           .acctId = pTscObj->acctId,
1969
                           .db = pRequest->pDb,
2,147,483,647✔
1970
                           .topicQuery = false,
1971
                           .pSql = pRequest->sqlstr,
2,147,483,647✔
1972
                           .sqlLen = pRequest->sqlLen,
2,147,483,647✔
1973
                           .pMsg = pRequest->msgBuf,
2,147,483,647✔
1974
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
2,147,483,647✔
1975
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
2,147,483,647✔
1976
                           .pStmtCb = NULL,
2,147,483,647✔
1977
                           .pUser = pTscObj->user,
1978
                           .userId = pTscObj->userId,
2,147,483,647✔
1979
                           .pEffectiveUser = pRequest->effectiveUser,
2,147,483,647✔
1980
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
2,147,483,647✔
1981
                           .enableSysInfo = pTscObj->sysInfo,
1982
                           .privInfo = pWrapper->pParseCtx ? pWrapper->pParseCtx->privInfo : 0,
1983
                           .async = true,
1984
                           .svrVer = pTscObj->sVer,
2,147,483,647✔
1985
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
2,147,483,647✔
1986
                           .allocatorId = pRequest->allocatorRefId,
2,147,483,647✔
1987
                           .parseSqlFp = clientParseSql,
2,147,483,647✔
1988
                           .parseSqlParam = pWrapper,
2,147,483,647✔
1989
                           .setQueryFp = setQueryRequest,
1990
                           .timezone = pTscObj->optionInfo.timezone,
1991
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
2,147,483,647✔
1992
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
2,147,483,647✔
1993
  (*pCxt)->biMode = biMode;
2,147,483,647✔
1994
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
1995
}
2,147,483,647✔
UNCOV
1996

×
1997
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
1998
  int32_t              code = TSDB_CODE_SUCCESS;
2,147,483,647✔
1999
  STscObj             *pTscObj = pRequest->pTscObj;
2,147,483,647✔
2000
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
2,147,483,647✔
2001
  if (pWrapper == NULL) {
2002
    code = terrno;
2003
  } else {
2,147,483,647✔
2004
    pWrapper->pRequest = pRequest;
2,147,483,647✔
2005
    pRequest->pWrapper = pWrapper;
2006
    *ppWrapper = pWrapper;
2007
  }
2,147,483,647✔
2008

2,147,483,647✔
2009
  if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
2010
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
2011
  }
2012

2,147,483,647✔
2013
  if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
2014
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
2015
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
2,147,483,647✔
2016
  }
2,147,483,647✔
UNCOV
2017

×
2018
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
2019
    int64_t syntaxStart = taosGetTimestampUs();
2,147,483,647✔
2020

2,147,483,647✔
2021
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
2,147,483,647✔
2022
    if (pWrapper->pCatalogReq == NULL) {
2023
      code = terrno;
2024
    } else {
2,147,483,647✔
2025
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
2026
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
2027
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
2,147,483,647✔
2028
    }
2029

2030
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
2,147,483,647✔
2031
  }
2,147,483,647✔
2032

2,147,483,647✔
2033
  return code;
2034
}
2,147,483,647✔
2035

11,263,785✔
2036
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
11,263,785✔
2037
  SSqlCallbackWrapper *pWrapper = NULL;
11,263,785✔
2038
  int32_t              code = TSDB_CODE_SUCCESS;
11,263,785✔
2039

11,263,785✔
2040
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
11,263,785✔
2041
    code = pRequest->prevCode;
2042
    terrno = code;
2043
    pRequest->code = code;
2,147,483,647✔
2044
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
2,147,483,647✔
2045
    doRequestCallback(pRequest, code);
2046
    return;
2047
  }
2,147,483,647✔
2048

2,147,483,647✔
2049
  if (TSDB_CODE_SUCCESS == code) {
2,147,483,647✔
2050
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
2051
  }
2052

2,147,483,647✔
2053
  if (TSDB_CODE_SUCCESS == code) {
177,482,565✔
2054
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
176,588,971✔
2055
    code = phaseAsyncQuery(pWrapper);
2056
  }
2057

893,594✔
2058
  if (TSDB_CODE_SUCCESS != code) {
2059
    if (NULL != pRequest->msgBuf && strlen(pRequest->msgBuf) > 0) {
2060
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, pRequest->msgBuf,
2061
               pRequest->requestId);
177,487,193✔
2062
    } else {
177,483,644✔
2063
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
177,483,644✔
2064
               pRequest->requestId);
177,482,461✔
2065
    }
2066

177,482,461✔
2067
    destorySqlCallbackWrapper(pWrapper);
161,980✔
2068
    pRequest->pWrapper = NULL;
2069
    qDestroyQuery(pRequest->pQuery);
161,980✔
2070
    pRequest->pQuery = NULL;
161,980✔
2071

161,980✔
2072
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
2073
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
2074
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
161,980✔
2075
      code = refreshMeta(pRequest->pTscObj, pRequest);
161,980✔
2076
      if (code != 0) {
161,980✔
2077
        tscWarn("req:0x%" PRIx64 ", refresh meta failed, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code,
2078
                tstrerror(code), pRequest->requestId);
2079
      }
177,320,481✔
2080
      pRequest->prevCode = code;
177,320,481✔
2081
      doAsyncQuery(pRequest, true);
177,320,481✔
2082
      return;
2083
    }
2084

2085
    terrno = code;
34,977,722✔
2086
    pRequest->code = code;
34,977,722✔
2087
    doRequestCallback(pRequest, code);
34,977,722✔
2088
  }
34,977,722✔
2089
}
34,977,722✔
2090

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

2123
typedef struct SAsyncFetchParam {
2,147,483,647✔
2124
  SRequestObj      *pReq;
2,147,483,647✔
2125
  __taos_async_fn_t fp;
2,147,483,647✔
2126
  void             *param;
2,147,483,647✔
2127
} SAsyncFetchParam;
2,147,483,647✔
2128

2129
static int32_t doAsyncFetch(void *pParam) {
2130
  SAsyncFetchParam *param = pParam;
2,147,483,647✔
2131
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
2,147,483,647✔
UNCOV
2132
  taosMemoryFree(param);
×
UNCOV
2133
  return TSDB_CODE_SUCCESS;
×
2134
}
2135

2,147,483,647✔
UNCOV
2136
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
×
UNCOV
2137
  if (res == NULL || fp == NULL) {
×
2138
    tscError("taos_fetch_rows_a invalid paras");
×
2139
    return;
2140
  }
2141
  if (!TD_RES_QUERY(res)) {
2,147,483,647✔
2142
    tscError("taos_fetch_rows_a res is NULL");
2,147,483,647✔
2143
    fp(param, res, TSDB_CODE_APP_ERROR);
487,656✔
2144
    return;
487,656✔
2145
  }
2146

2147
  SRequestObj *pRequest = res;
2,147,483,647✔
2148
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
2,147,483,647✔
UNCOV
2149
    fp(param, res, 0);
×
UNCOV
2150
    return;
×
2151
  }
2152

2,147,483,647✔
2153
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
2,147,483,647✔
2154
  if (!pParam) {
2,147,483,647✔
2155
    fp(param, res, terrno);
2,147,483,647✔
2156
    return;
2,147,483,647✔
UNCOV
2157
  }
×
UNCOV
2158
  pParam->pReq = pRequest;
×
UNCOV
2159
  pParam->fp = fp;
×
2160
  pParam->param = param;
2161
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
2162
  if (TSDB_CODE_SUCCESS != code) {
2163
    taosMemoryFree(pParam);
6,669✔
2164
    fp(param, res, code);
6,669✔
2165
    return;
×
UNCOV
2166
  }
×
2167
}
2168

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

2181
  // set the current block is all consumed
2182
  pResultInfo->convertUcs4 = false;
1,118✔
2183

1,118✔
UNCOV
2184
  // it is a local executed query, no need to do async fetch
×
UNCOV
2185
  taos_fetch_rows_a(pRequest, fp, param);
×
2186
}
2187

1,118✔
UNCOV
2188
const void *taos_get_raw_block(TAOS_RES *res) {
×
UNCOV
2189
  if (res == NULL) {
×
2190
    tscError("taos_get_raw_block invalid paras");
2191
    return NULL;
1,118✔
2192
  }
2193
  if (!TD_RES_QUERY(res)) {
1,118✔
2194
    tscError("taos_get_raw_block res is NULL");
2195
    return NULL;
UNCOV
2196
  }
×
UNCOV
2197
  SRequestObj *pRequest = res;
×
UNCOV
2198

×
UNCOV
2199
  return pRequest->body.resInfo.pData;
×
2200
}
2201

2202
int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInfo) {
×
2203
  if (NULL == taos) {
×
2204
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2205
    return terrno;
×
2206
  }
2207

2208
  if (NULL == db || NULL == dbInfo) {
×
2209
    tscError("invalid input param, db:%p, dbInfo:%p", db, dbInfo);
×
2210
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2211
    return terrno;
×
UNCOV
2212
  }
×
UNCOV
2213

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

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

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

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

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

×
2238
  code = catalogGetDBVgInfo(pCtg, &conn, dbFName, dbInfo);
2239
  if (code) {
×
2240
    goto _return;
UNCOV
2241
  }
×
UNCOV
2242

×
2243
_return:
2244

2245
  terrno = code;
×
UNCOV
2246

×
2247
  destroyRequest(pRequest);
×
2248
  return code;
×
2249
}
2250

2251
int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId) {
×
2252
  if (NULL == taos) {
×
2253
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2254
    return terrno;
×
2255
  }
2256

2257
  if (NULL == db || NULL == table || NULL == vgId) {
×
2258
    tscError("invalid input param, db:%p, table:%p, vgId:%p", db, table, vgId);
×
2259
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2260
    return terrno;
×
UNCOV
2261
  }
×
UNCOV
2262

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

×
2271
  pRequest->syncQuery = true;
×
2272

2273
  STscObj  *pTscObj = pRequest->pTscObj;
2274
  SCatalog *pCtg = NULL;
×
2275
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2276
  if (code != TSDB_CODE_SUCCESS) {
2277
    goto _return;
×
2278
  }
UNCOV
2279

×
2280
  SRequestConnInfo conn = {
×
2281
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
UNCOV
2282

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

×
2285
  SName tableName = {0};
×
2286
  toName(pTscObj->acctId, db, table, &tableName);
2287

2288
  SVgroupInfo vgInfo;
×
2289
  code = catalogGetTableHashVgroup(pCtg, &conn, &tableName, &vgInfo);
2290
  if (code) {
×
2291
    goto _return;
UNCOV
2292
  }
×
2293

2294
  *vgId = vgInfo.vgId;
×
UNCOV
2295

×
2296
_return:
2297

2298
  terrno = code;
×
UNCOV
2299

×
2300
  destroyRequest(pRequest);
×
2301
  return code;
×
2302
}
2303

2304
int taos_get_tables_vgId(TAOS *taos, const char *db, const char *table[], int tableNum, int *vgId) {
×
2305
  if (NULL == taos) {
×
2306
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2307
    return terrno;
×
2308
  }
2309

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

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

×
2324
  pRequest->syncQuery = true;
×
2325

2326
  STscObj  *pTscObj = pRequest->pTscObj;
2327
  SCatalog *pCtg = NULL;
×
2328
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2329
  if (code != TSDB_CODE_SUCCESS) {
2330
    goto _return;
×
2331
  }
UNCOV
2332

×
2333
  SRequestConnInfo conn = {
×
2334
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2335

2336
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
UNCOV
2337

×
2338
  code = catalogGetTablesHashVgId(pCtg, &conn, pTscObj->acctId, db, table, tableNum, vgId);
2339
  if (code) {
×
2340
    goto _return;
UNCOV
2341
  }
×
UNCOV
2342

×
2343
_return:
2344

2345
  terrno = code;
15,548✔
2346

15,548✔
2347
  destroyRequest(pRequest);
×
2348
  return code;
×
2349
}
2350

2351
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
15,548✔
2352
  if (NULL == taos) {
15,548✔
2353
    terrno = TSDB_CODE_TSC_DISCONNECTED;
15,548✔
2354
    return terrno;
15,548✔
2355
  }
15,548✔
2356

2357
  int64_t       connId = *(int64_t *)taos;
15,548✔
UNCOV
2358
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
×
2359
  int32_t       code = 0;
2360
  SRequestObj  *pRequest = NULL;
2361
  SCatalogReq   catalogReq = {0};
15,548✔
2362

15,548✔
UNCOV
2363
  if (NULL == tableNameList) {
×
2364
    return TSDB_CODE_SUCCESS;
15,548✔
UNCOV
2365
  }
×
UNCOV
2366

×
2367
  int32_t length = (int32_t)strlen(tableNameList);
2368
  if (0 == length) {
2369
    return TSDB_CODE_SUCCESS;
15,548✔
2370
  } else if (length > MAX_TABLE_NAME_LENGTH) {
15,548✔
2371
    tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH);
15,548✔
2372
    return TSDB_CODE_TSC_INVALID_OPERATION;
×
UNCOV
2373
  }
×
2374

2375
  char *sql = "taos_load_table_info";
2376
  code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
15,548✔
2377
  if (code != TSDB_CODE_SUCCESS) {
2378
    terrno = code;
15,548✔
2379
    goto _return;
15,548✔
2380
  }
15,548✔
UNCOV
2381

×
2382
  pRequest->syncQuery = true;
2383

2384
  STscObj *pTscObj = pRequest->pTscObj;
15,548✔
2385
  code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
15,548✔
2386
  if (code) {
15,548✔
2387
    goto _return;
×
2388
  }
2389

2390
  SCatalog *pCtg = NULL;
15,548✔
2391
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
15,548✔
2392
  if (code != TSDB_CODE_SUCCESS) {
2393
    goto _return;
15,548✔
2394
  }
2395

15,548✔
2396
  SRequestConnInfo conn = {
15,548✔
UNCOV
2397
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2398

2399
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
2400

15,548✔
2401
  code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, pRequest->body.interParam, NULL);
15,548✔
2402
  if (code) {
15,548✔
2403
    goto _return;
×
UNCOV
2404
  }
×
2405

2406
  SSyncQueryParam *pParam = pRequest->body.interParam;
15,548✔
2407
  code = tsem_wait(&pParam->sem);
15,548✔
2408
  if (code) {
15,548✔
2409
    tscError("tsem wait failed, code:%d - %s", code, tstrerror(code));
15,548✔
2410
    goto _return;
2411
  }
2412
_return:
282,230✔
2413
  destoryCatalogReq(&catalogReq);
282,230✔
2414
  destroyRequest(pRequest);
282,230✔
UNCOV
2415
  return code;
×
UNCOV
2416
}
×
UNCOV
2417

×
2418
TAOS_STMT *taos_stmt_init(TAOS *taos) {
2419
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2420
  if (NULL == pObj) {
282,230✔
2421
    tscError("invalid parameter for %s", __FUNCTION__);
282,230✔
2422
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2423
    return NULL;
2424
  }
282,230✔
2425

2426
  TAOS_STMT *pStmt = stmtInit(pObj, 0, NULL);
282,230✔
2427
  if (NULL == pStmt) {
2428
    tscError("stmt init failed, errcode:%s", terrstr());
UNCOV
2429
  }
×
UNCOV
2430
  releaseTscObj(*(int64_t *)taos);
×
UNCOV
2431

×
UNCOV
2432
  return pStmt;
×
UNCOV
2433
}
×
UNCOV
2434

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

2443
  TAOS_STMT *pStmt = stmtInit(pObj, reqid, NULL);
×
2444
  if (NULL == pStmt) {
2445
    tscError("stmt init failed, errcode:%s", terrstr());
2446
  }
159,133✔
2447
  releaseTscObj(*(int64_t *)taos);
159,133✔
2448

159,133✔
2449
  return pStmt;
×
UNCOV
2450
}
×
UNCOV
2451

×
2452
TAOS_STMT *taos_stmt_init_with_options(TAOS *taos, TAOS_STMT_OPTIONS *options) {
2453
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2454
  if (NULL == pObj) {
159,133✔
2455
    tscError("invalid parameter for %s", __FUNCTION__);
159,133✔
2456
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2457
    return NULL;
2458
  }
159,133✔
2459

2460
  TAOS_STMT *pStmt = stmtInit(pObj, options->reqId, options);
159,133✔
2461
  if (NULL == pStmt) {
2462
    tscError("stmt init failed, errcode:%s", terrstr());
2463
  }
87,698,351✔
2464
  releaseTscObj(*(int64_t *)taos);
87,698,351✔
UNCOV
2465

×
UNCOV
2466
  return pStmt;
×
UNCOV
2467
}
×
2468

2469
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
2470
  if (stmt == NULL || sql == NULL) {
87,698,455✔
2471
    tscError("NULL parameter for %s", __FUNCTION__);
2472
    terrno = TSDB_CODE_INVALID_PARA;
2473
    return terrno;
87,633✔
2474
  }
87,633✔
UNCOV
2475

×
UNCOV
2476
  return stmtPrepare(stmt, sql, length);
×
UNCOV
2477
}
×
2478

2479
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
2480
  if (stmt == NULL || name == NULL) {
87,633✔
2481
    tscError("NULL parameter for %s", __FUNCTION__);
87,633✔
2482
    terrno = TSDB_CODE_INVALID_PARA;
7,774✔
2483
    return terrno;
2484
  }
2485

79,859✔
2486
  int32_t code = stmtSetTbName(stmt, name);
79,859✔
2487
  if (code) {
2488
    return code;
UNCOV
2489
  }
×
2490

2491
  if (tags) {
2492
    return stmtSetTbTags(stmt, tags);
109,779,449✔
2493
  }
109,779,449✔
UNCOV
2494

×
2495
  return TSDB_CODE_SUCCESS;
×
UNCOV
2496
}
×
2497

2498
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
2499
  if (stmt == NULL || name == NULL) {
109,796,128✔
2500
    tscError("NULL parameter for %s", __FUNCTION__);
2501
    terrno = TSDB_CODE_INVALID_PARA;
2502
    return terrno;
7,007✔
2503
  }
7,007✔
UNCOV
2504

×
UNCOV
2505
  return stmtSetTbName(stmt, name);
×
UNCOV
2506
}
×
2507

2508
int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) {
2509
  if (stmt == NULL || tags == NULL) {
7,007✔
2510
    tscError("NULL parameter for %s", __FUNCTION__);
2511
    terrno = TSDB_CODE_INVALID_PARA;
2512
    return terrno;
2,496✔
2513
  }
2514

4,992✔
2515
  return stmtSetTbTags(stmt, tags);
4,992✔
UNCOV
2516
}
×
UNCOV
2517

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

2520
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
2521
  if (stmt == NULL || NULL == fieldNum) {
4,992✔
2522
    tscError("NULL parameter for %s", __FUNCTION__);
2523
    terrno = TSDB_CODE_INVALID_PARA;
2524
    return terrno;
7,488✔
2525
  }
7,488✔
UNCOV
2526

×
UNCOV
2527
  return stmtGetTagFields(stmt, fieldNum, fields);
×
UNCOV
2528
}
×
2529

2530
int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
2531
  if (stmt == NULL || NULL == fieldNum) {
7,488✔
2532
    tscError("NULL parameter for %s", __FUNCTION__);
2533
    terrno = TSDB_CODE_INVALID_PARA;
2534
    return terrno;
UNCOV
2535
  }
×
2536

UNCOV
2537
  return stmtGetColFields(stmt, fieldNum, fields);
×
UNCOV
2538
}
×
2539

2540
// let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields`
2541
void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) {
465,556✔
2542
  (void)stmt;
465,556✔
2543
  if (!fields) return;
×
2544
  taosMemoryFree(fields);
×
UNCOV
2545
}
×
2546

2547
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
2548
  if (stmt == NULL || bind == NULL) {
465,556✔
2549
    tscError("NULL parameter for %s", __FUNCTION__);
50,700✔
2550
    terrno = TSDB_CODE_INVALID_PARA;
50,700✔
2551
    return terrno;
50,700✔
2552
  }
2553

2554
  if (bind->num > 1) {
414,856✔
2555
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
2556
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
2557
    return terrno;
109,774,912✔
2558
  }
109,774,912✔
2559

22,464✔
2560
  return stmtBindBatch(stmt, bind, -1);
22,464✔
UNCOV
2561
}
×
2562

2563
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
2564
  if (stmt == NULL || bind == NULL) {
109,765,110✔
2565
    tscError("NULL parameter for %s", __FUNCTION__);
63,960✔
2566
    terrno = TSDB_CODE_INVALID_PARA;
63,960✔
2567
    return terrno;
×
2568
  }
2569

2570
  if (bind->num <= 0 || bind->num > INT16_MAX) {
109,783,258✔
2571
    tscError("invalid bind num %d", bind->num);
109,777,538✔
2572
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
109,756,400✔
2573
    return terrno;
×
UNCOV
2574
  }
×
2575

2576
  int32_t insert = 0;
109,756,400✔
UNCOV
2577
  int32_t code = stmtIsInsert(stmt, &insert);
×
UNCOV
2578
  if (TSDB_CODE_SUCCESS != code) {
×
2579
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2580
    return code;
2581
  }
2582
  if (0 == insert && bind->num > 1) {
109,756,400✔
2583
    tscError("only one row data allowed for query");
2584
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
2585
    return terrno;
10,920✔
2586
  }
10,920✔
UNCOV
2587

×
UNCOV
2588
  return stmtBindBatch(stmt, bind, -1);
×
UNCOV
2589
}
×
2590

2591
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
2592
  if (stmt == NULL || bind == NULL) {
10,920✔
2593
    tscError("NULL parameter for %s", __FUNCTION__);
×
2594
    terrno = TSDB_CODE_INVALID_PARA;
×
2595
    return terrno;
×
2596
  }
2597

2598
  if (colIdx < 0) {
10,920✔
2599
    tscError("invalid bind column idx %d", colIdx);
10,920✔
2600
    terrno = TSDB_CODE_INVALID_PARA;
10,920✔
2601
    return terrno;
×
UNCOV
2602
  }
×
2603

2604
  int32_t insert = 0;
10,920✔
UNCOV
2605
  int32_t code = stmtIsInsert(stmt, &insert);
×
UNCOV
2606
  if (TSDB_CODE_SUCCESS != code) {
×
2607
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2608
    return code;
2609
  }
2610
  if (0 == insert && bind->num > 1) {
10,920✔
2611
    tscError("only one row data allowed for query");
2612
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
2613
    return terrno;
91,252,681✔
2614
  }
91,252,681✔
UNCOV
2615

×
UNCOV
2616
  return stmtBindBatch(stmt, bind, colIdx);
×
UNCOV
2617
}
×
2618

2619
int taos_stmt_add_batch(TAOS_STMT *stmt) {
2620
  if (stmt == NULL) {
91,252,681✔
2621
    tscError("NULL parameter for %s", __FUNCTION__);
2622
    terrno = TSDB_CODE_INVALID_PARA;
2623
    return terrno;
91,195,364✔
2624
  }
91,195,364✔
UNCOV
2625

×
UNCOV
2626
  return stmtAddBatch(stmt);
×
UNCOV
2627
}
×
2628

2629
int taos_stmt_execute(TAOS_STMT *stmt) {
2630
  if (stmt == NULL) {
91,195,364✔
2631
    tscError("NULL parameter for %s", __FUNCTION__);
2632
    terrno = TSDB_CODE_INVALID_PARA;
2633
    return terrno;
×
UNCOV
2634
  }
×
UNCOV
2635

×
UNCOV
2636
  return stmtExec(stmt);
×
UNCOV
2637
}
×
2638

2639
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
2640
  if (stmt == NULL || insert == NULL) {
×
2641
    tscError("NULL parameter for %s", __FUNCTION__);
2642
    terrno = TSDB_CODE_INVALID_PARA;
2643
    return terrno;
×
UNCOV
2644
  }
×
UNCOV
2645

×
2646
  return stmtIsInsert(stmt, insert);
×
UNCOV
2647
}
×
2648

2649
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
2650
  if (stmt == NULL || nums == NULL) {
×
2651
    tscError("NULL parameter for %s", __FUNCTION__);
2652
    terrno = TSDB_CODE_INVALID_PARA;
2653
    return terrno;
4,992✔
2654
  }
4,992✔
UNCOV
2655

×
2656
  return stmtGetParamNum(stmt, nums);
×
UNCOV
2657
}
×
2658

2659
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
2660
  if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) {
4,992✔
2661
    tscError("invalid parameter for %s", __FUNCTION__);
2662
    terrno = TSDB_CODE_INVALID_PARA;
2663
    return terrno;
124,579✔
2664
  }
124,579✔
UNCOV
2665

×
UNCOV
2666
  return stmtGetParam(stmt, idx, type, bytes);
×
UNCOV
2667
}
×
2668

2669
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
2670
  if (stmt == NULL) {
124,579✔
2671
    tscError("NULL parameter for %s", __FUNCTION__);
2672
    terrno = TSDB_CODE_INVALID_PARA;
2673
    return NULL;
142,519✔
2674
  }
2675

40,703✔
2676
  return stmtUseResult(stmt);
40,703✔
UNCOV
2677
}
×
UNCOV
2678

×
UNCOV
2679
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
×
2680

2681
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
2682
  if (stmt == NULL) {
40,703✔
2683
    tscError("NULL parameter for %s", __FUNCTION__);
2684
    terrno = TSDB_CODE_INVALID_PARA;
2685
    return 0;
35,984✔
2686
  }
35,984✔
UNCOV
2687

×
UNCOV
2688
  return stmtAffectedRows(stmt);
×
UNCOV
2689
}
×
2690

2691
int taos_stmt_affected_rows_once(TAOS_STMT *stmt) {
2692
  if (stmt == NULL) {
35,984✔
2693
    tscError("NULL parameter for %s", __FUNCTION__);
2694
    terrno = TSDB_CODE_INVALID_PARA;
2695
    return 0;
441,363✔
2696
  }
441,363✔
UNCOV
2697

×
UNCOV
2698
  return stmtAffectedRowsOnce(stmt);
×
UNCOV
2699
}
×
2700

2701
int taos_stmt_close(TAOS_STMT *stmt) {
2702
  if (stmt == NULL) {
441,363✔
2703
    tscError("NULL parameter for %s", __FUNCTION__);
2704
    terrno = TSDB_CODE_INVALID_PARA;
2705
    return terrno;
1,551,927✔
2706
  }
1,551,927✔
2707

1,248✔
2708
  return stmtClose(stmt);
1,248✔
2709
}
1,248✔
2710

2711
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
1,550,679✔
2712
  if (NULL == taos) {
1,551,095✔
UNCOV
2713
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2714
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2715
    return NULL;
×
2716
  }
2717
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2718
  if (NULL == pObj) {
1,551,095✔
2719
    tscError("invalid parameter for %s", __FUNCTION__);
2720
    terrno = TSDB_CODE_TSC_DISCONNECTED;
1,551,095✔
2721
    return NULL;
2722
  }
1,551,095✔
2723

2724
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
2725

1,593,540✔
2726
  releaseTscObj(*(int64_t *)taos);
1,593,540✔
2727

1,248✔
2728
  return pStmt;
1,248✔
2729
}
1,248✔
2730

2731
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
2732
  if (stmt == NULL || sql == NULL) {
1,592,292✔
2733
    tscError("NULL parameter for %s", __FUNCTION__);
2734
    terrno = TSDB_CODE_INVALID_PARA;
2735
    return terrno;
528,934,354✔
2736
  }
528,934,354✔
UNCOV
2737

×
UNCOV
2738
  return stmtPrepare2(stmt, sql, length);
×
UNCOV
2739
}
×
2740

2741
int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx) {
2742
  if (stmt == NULL) {
528,934,354✔
2743
    tscError("NULL parameter for %s", __FUNCTION__);
528,934,354✔
2744
    terrno = TSDB_CODE_INVALID_PARA;
528,934,354✔
2745
    return terrno;
2746
  }
2747

528,971,079✔
2748
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
532,330,643✔
2749
  int32_t    code = TSDB_CODE_SUCCESS;
48,776✔
UNCOV
2750
  STMT2_DLOG_E("start to bind param");
×
UNCOV
2751

×
UNCOV
2752
  // check query bind number
×
2753
  bool isQuery = (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt)));
2754
  if (isQuery) {
2755
    if (bindv->count != 1 || bindv->bind_cols[0]->num != 1) {
2756
      terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
532,330,643✔
2757
      STMT2_ELOG_E("query only support one table and one row bind");
94,107✔
2758
      return terrno;
94,107✔
UNCOV
2759
    }
×
2760
  }
2761

2762
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 1) {
530,610,301✔
2763
    STMT2_ELOG_E("async bind param is still working, please try again later");
28,704✔
UNCOV
2764
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
×
2765
    return terrno;
2766
  }
28,704✔
2767

2768
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
2769
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
1,066,002,626✔
2770
      STMT2_ELOG_E("bind param wait asyncExecSem failed");
530,448,126✔
2771
    }
536,050,294✔
2772
    pStmt->execSemWaited = true;
536,649,633✔
2773
  }
536,249,610✔
2774

13,625,105✔
2775
  for (int i = 0; i < bindv->count; ++i) {
13,624,702✔
2776
    SVCreateTbReq *pCreateTbReq = NULL;
13,728✔
2777
    if (!isQuery) {
13,728✔
2778
      STMT2_TLOG("start to bind %dth table", i);
22,464✔
2779
      if (bindv->tbnames && bindv->tbnames[i]) {
2780
        code = stmtSetTbName2(stmt, bindv->tbnames[i]);
2781
        if (code) {
2782
          terrno = code;
537,912,908✔
2783
          STMT2_ELOG("set tbname failed, code:%s", stmt2Errstr(stmt));
7,061,080✔
2784
          return terrno;
529,558,237✔
2785
        }
1,388,153✔
2786
      }
528,994,102✔
2787

26,208✔
2788
      if (bindv->tags && bindv->tags[i]) {
2789
        code = stmtSetTbTags2(stmt, bindv->tags[i], &pCreateTbReq);
2790
      } else if (pStmt->bInfo.tbNameFlag & IS_FIXED_TAG) {
537,456,738✔
2791
        code = stmtCheckTags2(stmt, &pCreateTbReq);
1,248✔
2792
      } else if (pStmt->sql.autoCreateTbl) {
1,248✔
2793
        code = stmtSetTbTags2(stmt, NULL, &pCreateTbReq);
1,248✔
UNCOV
2794
      }
×
UNCOV
2795

×
2796
      if (code) {
2797
        terrno = code;
1,248✔
2798
        STMT2_ELOG("set tags failed, code:%s", stmt2Errstr(stmt));
2799
        if (pCreateTbReq) {
2800
          tdDestroySVCreateTbReq(pCreateTbReq);
2801
          taosMemoryFreeClear(pCreateTbReq);
536,856,151✔
2802
        }
541,322,535✔
2803
        return terrno;
2804
      }
541,425,573✔
2805
    }
7,103,434✔
2806

7,103,434✔
UNCOV
2807
    if (bindv->bind_cols && bindv->bind_cols[i]) {
×
UNCOV
2808
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
×
UNCOV
2809

×
2810
      if (bind->num <= 0 || bind->num > INT16_MAX) {
UNCOV
2811
        STMT2_ELOG("bind num:%d must > 0 and < INT16_MAX", bind->num);
×
2812
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
2813
        if (pCreateTbReq) {
2814
          tdDestroySVCreateTbReq(pCreateTbReq);
534,682,148✔
2815
          taosMemoryFreeClear(pCreateTbReq);
530,790,039✔
2816
        }
7,488✔
2817
        return terrno;
7,488✔
2818
      }
7,488✔
2819

2,496✔
2820
      code = stmtBindBatch2(stmt, bind, col_idx, pCreateTbReq);
2,496✔
2821
      if (TSDB_CODE_SUCCESS != code) {
2822
        terrno = code;
7,488✔
2823
        STMT2_ELOG("bind batch failed, code:%s", stmt2Errstr(stmt));
2824
        if (pCreateTbReq) {
2825
          tdDestroySVCreateTbReq(pCreateTbReq);
2826
          taosMemoryFreeClear(pCreateTbReq);
2827
        }
532,990,926✔
2828
        return terrno;
2829
      }
UNCOV
2830
    }
×
2831
  }
UNCOV
2832

×
UNCOV
2833
  return code;
×
UNCOV
2834
}
×
2835

2836
int taos_stmt2_bind_param_a(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx, __taos_async_fn_t fp,
UNCOV
2837
                            void *param) {
×
2838
  if (stmt == NULL || bindv == NULL || fp == NULL) {
2839
    terrno = TSDB_CODE_INVALID_PARA;
×
2840
    return terrno;
×
UNCOV
2841
  }
×
UNCOV
2842

×
2843
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
×
UNCOV
2844

×
2845
  ThreadArgs *args = (ThreadArgs *)taosMemoryMalloc(sizeof(ThreadArgs));
2846
  args->stmt = stmt;
×
2847
  args->bindv = bindv;
×
2848
  args->col_idx = col_idx;
×
2849
  args->fp = fp;
×
2850
  args->param = param;
×
UNCOV
2851

×
2852
  (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
2853
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 0) {
×
2854
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2855
    tscError("async bind param is still working, please try again later");
2856
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
×
2857
    return terrno;
×
UNCOV
2858
  }
×
2859
  (void)atomic_add_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2860
  (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
UNCOV
2861

×
2862
  int code_s = taosStmt2AsyncBind(stmtAsyncBindThreadFunc, (void *)args);
×
2863
  if (code_s != TSDB_CODE_SUCCESS) {
×
2864
    terrno = code_s;
2865
    (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
2866
    (void)taosThreadCondSignal(&(pStmt->asyncBindParam.waitCond));
×
2867
    (void)atomic_sub_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
2868
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
2869
    tscError("async bind failed, code:%d , %s", code_s, tstrerror(code_s));
7,803,991✔
2870
  }
7,803,991✔
UNCOV
2871

×
2872
  return code_s;
×
UNCOV
2873
}
×
2874

2875
int taos_stmt2_exec(TAOS_STMT2 *stmt, int *affected_rows) {
2876
  if (stmt == NULL) {
7,803,991✔
2877
    tscError("NULL parameter for %s", __FUNCTION__);
2878
    terrno = TSDB_CODE_INVALID_PARA;
2879
    return terrno;
1,544,374✔
2880
  }
1,544,374✔
UNCOV
2881

×
UNCOV
2882
  return stmtExec2(stmt, affected_rows);
×
UNCOV
2883
}
×
2884

2885
int taos_stmt2_close(TAOS_STMT2 *stmt) {
2886
  if (stmt == NULL) {
1,544,374✔
2887
    tscError("NULL parameter for %s", __FUNCTION__);
2888
    terrno = TSDB_CODE_INVALID_PARA;
2889
    return terrno;
364✔
2890
  }
364✔
UNCOV
2891

×
UNCOV
2892
  return stmtClose2(stmt);
×
UNCOV
2893
}
×
2894

2895
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
364✔
2896
  if (stmt == NULL || insert == NULL) {
364✔
2897
    tscError("NULL parameter for %s", __FUNCTION__);
2898
    terrno = TSDB_CODE_INVALID_PARA;
2899
    return terrno;
115,076✔
2900
  }
115,076✔
2901
  *insert = stmt2IsInsert(stmt);
1,248✔
2902
  return TSDB_CODE_SUCCESS;
1,248✔
2903
}
1,248✔
2904

2905
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
2906
  if (stmt == NULL || count == NULL) {
113,828✔
2907
    tscError("NULL parameter for %s", __FUNCTION__);
113,828✔
2908
    terrno = TSDB_CODE_INVALID_PARA;
2909
    return terrno;
113,828✔
2910
  }
105,092✔
2911

88,868✔
2912
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
2913
  STMT2_DLOG_E("start to get fields");
24,960✔
2914

23,712✔
2915
  if (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type ||
2916
      (pStmt->sql.type == 0 && stmt2IsInsert(stmt))) {
2917
    return stmtGetStbColFields2(stmt, count, fields);
1,248✔
2918
  }
1,248✔
2919
  if (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt))) {
2920
    return stmtGetParamNum2(stmt, count);
2921
  }
83,876✔
2922

2923
  tscError("Invalid sql for stmt %s", pStmt->sql.sqlStr);
83,876✔
2924
  return TSDB_CODE_PAR_SYNTAX_ERROR;
61,412✔
2925
}
2926

2927
DLL_EXPORT void taos_stmt2_free_fields(TAOS_STMT2 *stmt, TAOS_FIELD_ALL *fields) {
42,536✔
2928
  (void)stmt;
42,536✔
UNCOV
2929
  if (!fields) return;
×
UNCOV
2930
  taosMemoryFree(fields);
×
UNCOV
2931
}
×
2932

2933
TAOS_RES *taos_stmt2_result(TAOS_STMT2 *stmt) {
2934
  if (stmt == NULL) {
42,536✔
2935
    tscError("NULL parameter for %s", __FUNCTION__);
2936
    terrno = TSDB_CODE_INVALID_PARA;
2937
    return NULL;
38,688✔
2938
  }
2939

30,329✔
2940
  return stmtUseResult2(stmt);
30,329✔
2941
}
30,329✔
UNCOV
2942

×
UNCOV
2943
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmt2Errstr(stmt); }
×
2944

2945
int taos_set_conn_mode(TAOS *taos, int mode, int value) {
2946
  int32_t code = 0;
30,329✔
2947
  if (taos == NULL) {
30,329✔
2948
    terrno = TSDB_CODE_INVALID_PARA;
×
2949
    return terrno;
×
UNCOV
2950
  }
×
2951

2952
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
30,329✔
2953
  if (NULL == pObj) {
30,329✔
2954
    terrno = TSDB_CODE_TSC_DISCONNECTED;
30,329✔
2955
    tscError("invalid parameter for %s", __func__);
30,329✔
2956
    return terrno;
×
UNCOV
2957
  }
×
UNCOV
2958
  switch (mode) {
×
2959
    case TAOS_CONN_MODE_BI:
2960
      atomic_store_8(&pObj->biMode, value);
30,329✔
2961
      break;
30,329✔
2962
    default:
2963
      tscError("not supported mode.");
2964
      code = TSDB_CODE_INVALID_PARA;
×
2965
  }
UNCOV
2966
  releaseTscObj(*(int64_t *)taos);
×
UNCOV
2967
  return code;
×
UNCOV
2968
}
×
UNCOV
2969

×
2970
char *getBuildInfo() { return td_buildinfo; }
×
2971

2972
int32_t taos_connect_is_alive(TAOS *taos) {
2973
  int32_t code = 0, lino = 0;
×
2974
  if (taos == NULL) {
×
2975
    terrno = TSDB_CODE_INVALID_PARA;
×
2976
    return terrno;
×
UNCOV
2977
  }
×
2978

2979
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2980
  if (NULL == pObj) {
×
2981
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2982
    tscError("invalid parameter for %s", __func__);
2983
    return terrno;
×
UNCOV
2984
  }
×
2985

2986
  code = tscCheckConnSessionMetric(pObj);
×
2987
  TAOS_CHECK_GOTO(code, &lino, _error);
×
2988

2989
_error:
2990
  releaseTscObj(*(int64_t *)taos);
×
2991

2992
  if (code != 0) {
×
2993
    tscError("taos conn failed to check alive, code:%d - %s", code, tstrerror(code));
×
UNCOV
2994
  }
×
2995

2996
  return code != 0 ? 0 : 1;
×
UNCOV
2997
}
×
2998
static int32_t buildInstanceRegisterSql(const SInstanceRegisterReq *req, char **ppSql, uint32_t *pLen) {
×
2999
  const char *action = (req->expire < 0) ? "UNREGISTER" : "REGISTER";
3000
  int32_t     len = 0;
×
UNCOV
3001

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

×
3013
  char *sql = taosMemoryMalloc((size_t)len + 1);
×
3014
  if (sql == NULL) {
×
3015
    return terrno;
UNCOV
3016
  }
×
UNCOV
3017

×
3018
  int32_t offset = snprintf(sql, (size_t)len + 1, "%s INSTANCE '%s'", action, req->id);
3019
  if (req->type[0] != 0) {
×
3020
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " TYPE '%s'", req->type);
×
3021
  }
3022
  if (req->desc[0] != 0) {
3023
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " DESC '%s'", req->desc);
×
UNCOV
3024
  }
×
3025
  if (req->expire >= 0) {
×
3026
    (void)snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " EXPIRE %d", req->expire);
UNCOV
3027
  }
×
3028

3029
  *ppSql = sql;
3030
  if (pLen != NULL) {
×
3031
    *pLen = (uint32_t)len;
×
UNCOV
3032
  }
×
3033
  return TSDB_CODE_SUCCESS;
×
UNCOV
3034
}
×
UNCOV
3035

×
3036
static int32_t sendInstanceRegisterReq(STscObj *pObj, const SInstanceRegisterReq *req) {
3037
  SRequestObj *pRequest = NULL;
3038
  int32_t      code = createRequest(pObj->id, TDMT_MND_REGISTER_INSTANCE, 0, &pRequest);
×
3039
  if (code != TSDB_CODE_SUCCESS) {
×
3040
    terrno = code;
×
3041
    return code;
3042
  }
UNCOV
3043

×
3044
  code = buildInstanceRegisterSql(req, &pRequest->sqlstr, (uint32_t *)&pRequest->sqlLen);
×
3045
  if (code != TSDB_CODE_SUCCESS) {
×
3046
    goto _cleanup;
×
3047
  }
3048

3049
  int32_t msgLen = tSerializeSInstanceRegisterReq(NULL, 0, (SInstanceRegisterReq *)req);
×
3050
  if (msgLen <= 0) {
×
3051
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3052
    goto _cleanup;
×
3053
  }
3054

3055
  void *pMsg = taosMemoryMalloc(msgLen);
×
3056
  if (pMsg == NULL) {
×
3057
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3058
    goto _cleanup;
×
3059
  }
3060

3061
  if (tSerializeSInstanceRegisterReq(pMsg, msgLen, (SInstanceRegisterReq *)req) < 0) {
×
3062
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3063
    taosMemoryFree(pMsg);
3064
    goto _cleanup;
×
UNCOV
3065
  }
×
UNCOV
3066

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

×
3070
  SMsgSendInfo *pSend = buildMsgInfoImpl(pRequest);
3071
  if (pSend == NULL) {
3072
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3073
    taosMemoryFree(pMsg);
×
3074
    pRequest->body.requestMsg.pData = NULL;
×
3075
    goto _cleanup;
×
UNCOV
3076
  }
×
UNCOV
3077

×
3078
  SEpSet epSet = getEpSet_s(&pObj->pAppInfo->mgmtEp);
3079
  code = asyncSendMsgToServer(pObj->pAppInfo->pTransporter, &epSet, NULL, pSend);
3080
  if (code != TSDB_CODE_SUCCESS) {
×
3081
    destroySendMsgInfo(pSend);
×
3082
    pRequest->body.requestMsg = (SDataBuf){0};
×
3083
    goto _cleanup;
×
3084
  }
3085

3086
  code = tsem_wait(&pRequest->body.rspSem);
×
3087
  if (code != TSDB_CODE_SUCCESS) {
×
3088
    code = terrno != 0 ? terrno : code;
3089
    goto _cleanup;
×
UNCOV
3090
  }
×
UNCOV
3091

×
3092
  code = pRequest->code;
3093
  terrno = code;
UNCOV
3094

×
3095
_cleanup:
×
3096
  destroyRequest(pRequest);
×
3097
  return code;
×
UNCOV
3098
}
×
3099

3100
static bool instanceRegisterRpcRfp(int32_t code, tmsg_t msgType) {
×
3101
  if (NEED_REDIRECT_ERROR(code)) {
×
3102
    return true;
3103
  } else if (code == TSDB_CODE_UTIL_QUEUE_OUT_OF_MEMORY || code == TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE ||
×
3104
             code == TSDB_CODE_SYN_WRITE_STALL || code == TSDB_CODE_SYN_PROPOSE_NOT_READY ||
3105
             code == TSDB_CODE_SYN_RESTORING) {
3106
    tscDebug("client msg type %s should retry since %s", TMSG_INFO(msgType), tstrerror(code));
3107
    return true;
34,580✔
3108
  } else {
34,580✔
3109
    return false;
×
3110
  }
3111
}
3112

3113
int32_t taos_register_instance(const char *id, const char *type, const char *desc, int32_t expire) {
34,580✔
3114
  if (id == NULL || id[0] == 0) {
34,580✔
3115
    return terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
3116
  }
×
3117

3118
  // Validate string lengths
3119
  size_t idLen = strlen(id);
34,580✔
3120
  if (idLen >= TSDB_INSTANCE_ID_LEN) {
19,760✔
3121
    tscError("instance id length %zu exceeds limit %d", idLen, TSDB_INSTANCE_ID_LEN - 1);
19,760✔
3122
    return terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
3123
  }
×
3124

3125
  if (type != NULL && type[0] != 0) {
3126
    size_t typeLen = strlen(type);
3127
    if (typeLen >= TSDB_INSTANCE_TYPE_LEN) {
34,580✔
3128
      tscError("instance type length %zu exceeds limit %d", typeLen, TSDB_INSTANCE_TYPE_LEN - 1);
19,760✔
3129
      return terrno = TSDB_CODE_INVALID_PARA;
19,760✔
UNCOV
3130
    }
×
UNCOV
3131
  }
×
3132

3133
  if (desc != NULL && desc[0] != 0) {
3134
    size_t descLen = strlen(desc);
3135
    if (descLen >= TSDB_INSTANCE_DESC_LEN) {
34,580✔
3136
      tscError("instance desc length %zu exceeds limit %d", descLen, TSDB_INSTANCE_DESC_LEN - 1);
34,580✔
3137
      return terrno = TSDB_CODE_INVALID_PARA;
×
3138
    }
3139
  }
3140

34,580✔
3141
  int32_t code = taos_init();
34,580✔
UNCOV
3142
  if (code != TSDB_CODE_SUCCESS) {
×
3143
    return code;
3144
  }
3145

34,580✔
3146
  SConfig *pCfg = taosGetCfg();
34,580✔
UNCOV
3147
  if (pCfg == NULL) {
×
3148
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
3149
  }
3150

34,580✔
3151
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
34,580✔
3152
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
34,580✔
3153
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3154
  }
3155

3156
  SEp firstEp = {0};
34,580✔
3157
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
34,580✔
3158
  if (code != TSDB_CODE_SUCCESS) {
34,580✔
3159
    return terrno = code;
34,580✔
3160
  }
34,580✔
3161

3162
  void    *clientRpc = NULL;
34,580✔
3163
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
34,580✔
3164
  SRpcMsg  rpcMsg = {0};
34,580✔
3165
  SRpcMsg  rpcRsp = {0};
34,580✔
3166
  SRpcInit rpcInit = {0};
34,580✔
3167

34,580✔
3168
  rpcInit.label = "INST";
34,580✔
3169
  rpcInit.numOfThreads = 1;
34,580✔
3170
  rpcInit.cfp = NULL;
3171
  rpcInit.sessions = 16;
34,580✔
3172
  rpcInit.connType = TAOS_CONN_CLIENT;
34,580✔
3173
  rpcInit.idleTime = tsShellActivityTimer * 1000;
34,580✔
3174
  rpcInit.compressSize = tsCompressMsgSize;
34,580✔
3175
  rpcInit.user = TSDB_DEFAULT_USER;
34,580✔
3176

3177
  rpcInit.rfp = instanceRegisterRpcRfp;
3178
  rpcInit.retryMinInterval = tsRedirectPeriod;
34,580✔
3179
  rpcInit.retryStepFactor = tsRedirectFactor;
34,580✔
3180
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
34,580✔
3181
  rpcInit.retryMaxTimeout =
34,580✔
3182
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
34,580✔
3183

34,580✔
3184
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
34,580✔
3185
  connLimitNum = TMAX(connLimitNum, 10);
34,580✔
3186
  connLimitNum = TMIN(connLimitNum, 500);
3187
  rpcInit.connLimitNum = connLimitNum;
34,580✔
3188
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
34,580✔
3189
  rpcInit.readTimeout = tsReadTimeout;
34,580✔
3190
  rpcInit.ipv6 = tsEnableIpv6;
34,580✔
3191
  rpcInit.enableSSL = tsEnableTLS;
34,580✔
3192

3193
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
34,580✔
3194
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
34,580✔
UNCOV
3195
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
×
UNCOV
3196
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
×
3197
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
3198

3199
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
34,580✔
3200
  if (code != TSDB_CODE_SUCCESS) {
34,580✔
3201
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
3202
    return code;
×
UNCOV
3203
  }
×
3204

3205
  clientRpc = rpcOpen(&rpcInit);
3206
  if (clientRpc == NULL) {
3207
    code = terrno;
34,580✔
3208
    tscError("failed to init instance register client since %s", tstrerror(code));
34,580✔
3209
    return code;
3210
  }
3211

34,580✔
3212
  // Prepare epSet
34,580✔
3213
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
34,580✔
3214
  epSet.eps[0].port = firstEp.port;
19,760✔
3215

3216
  // Prepare request
34,580✔
3217
  SInstanceRegisterReq req = {0};
19,760✔
3218
  tstrncpy(req.id, id, sizeof(req.id));
3219
  if (type != NULL && type[0] != 0) {
34,580✔
3220
    tstrncpy(req.type, type, sizeof(req.type));
3221
  }
34,580✔
3222
  if (desc != NULL && desc[0] != 0) {
34,580✔
UNCOV
3223
    tstrncpy(req.desc, desc, sizeof(req.desc));
×
UNCOV
3224
  }
×
UNCOV
3225
  req.expire = expire;
×
3226

3227
  int32_t contLen = tSerializeSInstanceRegisterReq(NULL, 0, &req);
3228
  if (contLen <= 0) {
34,580✔
3229
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
34,580✔
3230
    rpcClose(clientRpc);
×
3231
    return code;
×
UNCOV
3232
  }
×
3233

3234
  void *pCont = rpcMallocCont(contLen);
3235
  if (pCont == NULL) {
34,580✔
3236
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3237
    rpcClose(clientRpc);
×
3238
    return code;
×
UNCOV
3239
  }
×
3240

3241
  if (tSerializeSInstanceRegisterReq(pCont, contLen, &req) < 0) {
3242
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
34,580✔
3243
    rpcFreeCont(pCont);
34,580✔
3244
    rpcClose(clientRpc);
34,580✔
3245
    return code;
34,580✔
3246
  }
34,580✔
3247

3248
  rpcMsg.pCont = pCont;
34,580✔
3249
  rpcMsg.contLen = contLen;
34,580✔
UNCOV
3250
  rpcMsg.msgType = TDMT_MND_REGISTER_INSTANCE;
×
3251
  rpcMsg.info.ahandle = (void *)0x9528;  // Different magic number from server status
3252
  rpcMsg.info.notFreeAhandle = 1;
UNCOV
3253

×
UNCOV
3254
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
×
3255
  if (TSDB_CODE_SUCCESS != code) {
3256
    tscError("failed to send instance register req since %s", tstrerror(code));
3257
    // rpcSendRecv failed, pCont may not be freed, but check _RETURN1 path
34,580✔
UNCOV
3258
    // In error path, rpcSendRecv may free pCont, but we free it here to be safe
×
3259
    rpcClose(clientRpc);
×
3260
    return code;
3261
  }
34,580✔
3262

3263
  if (rpcRsp.code != 0) {
3264
    code = rpcRsp.code;
34,580✔
3265
    tscError("instance register failed, code:%s", tstrerror(code));
34,580✔
3266
  } else {
3267
    code = TSDB_CODE_SUCCESS;
34,580✔
3268
  }
3269

34,580✔
3270
  if (rpcRsp.pCont != NULL) {
34,580✔
3271
    rpcFreeCont(rpcRsp.pCont);
3272
  }
3273
  rpcClose(clientRpc);
27,170✔
3274

27,170✔
UNCOV
3275
  terrno = code;
×
3276
  return code;
3277
}
3278

27,170✔
3279
int32_t taos_list_instances(const char *filter_type, char ***pList, int32_t *pCount) {
27,170✔
UNCOV
3280
  if (pList == NULL || pCount == NULL) {
×
3281
    return TSDB_CODE_INVALID_PARA;
×
3282
  }
3283

3284
  int32_t code = taos_init();
27,170✔
3285
  if (code != TSDB_CODE_SUCCESS) {
27,170✔
3286
    terrno = code;
×
3287
    return code;
×
3288
  }
3289

3290
  SConfig *pCfg = taosGetCfg();
27,170✔
3291
  if (pCfg == NULL) {
27,170✔
3292
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3293
    return TSDB_CODE_CFG_NOT_FOUND;
×
3294
  }
3295

3296
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
27,170✔
3297
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
27,170✔
3298
    terrno = TSDB_CODE_CFG_NOT_FOUND;
27,170✔
3299
    return TSDB_CODE_CFG_NOT_FOUND;
×
UNCOV
3300
  }
×
3301

3302
  SEp firstEp = {0};
3303
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
3304
  if (code != TSDB_CODE_SUCCESS) {
27,170✔
3305
    terrno = code;
27,170✔
3306
    return code;
27,170✔
3307
  }
27,170✔
3308

27,170✔
3309
  // Initialize RPC connection (similar to taos_register_instance)
3310
  void    *clientRpc = NULL;
27,170✔
3311
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
27,170✔
3312
  SRpcMsg  rpcMsg = {0};
27,170✔
3313
  SRpcMsg  rpcRsp = {0};
27,170✔
3314
  SRpcInit rpcInit = {0};
27,170✔
3315

27,170✔
3316
  rpcInit.label = "LIST";
27,170✔
3317
  rpcInit.numOfThreads = 1;
27,170✔
3318
  rpcInit.cfp = NULL;
3319
  rpcInit.sessions = 16;
27,170✔
3320
  rpcInit.connType = TAOS_CONN_CLIENT;
27,170✔
3321
  rpcInit.idleTime = tsShellActivityTimer * 1000;
27,170✔
3322
  rpcInit.compressSize = tsCompressMsgSize;
27,170✔
3323
  rpcInit.user = TSDB_DEFAULT_USER;
27,170✔
3324

3325
  rpcInit.rfp = instanceRegisterRpcRfp;
3326
  rpcInit.retryMinInterval = tsRedirectPeriod;
27,170✔
3327
  rpcInit.retryStepFactor = tsRedirectFactor;
27,170✔
3328
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
27,170✔
3329
  rpcInit.retryMaxTimeout =
27,170✔
3330
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
27,170✔
3331

27,170✔
3332
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
27,170✔
3333
  connLimitNum = TMAX(connLimitNum, 10);
27,170✔
3334
  connLimitNum = TMIN(connLimitNum, 500);
3335
  rpcInit.connLimitNum = connLimitNum;
27,170✔
3336
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
27,170✔
3337
  rpcInit.readTimeout = tsReadTimeout;
27,170✔
3338
  rpcInit.ipv6 = tsEnableIpv6;
27,170✔
3339
  rpcInit.enableSSL = tsEnableTLS;
27,170✔
3340

3341
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
27,170✔
3342
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
27,170✔
UNCOV
3343
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
×
UNCOV
3344
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
×
3345
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
3346

3347
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
27,170✔
3348
  if (code != TSDB_CODE_SUCCESS) {
27,170✔
3349
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
3350
    return code;
×
UNCOV
3351
  }
×
UNCOV
3352

×
3353
  clientRpc = rpcOpen(&rpcInit);
3354
  if (clientRpc == NULL) {
3355
    code = terrno;
27,170✔
3356
    tscError("failed to init instance list client since %s", tstrerror(code));
27,170✔
3357
    terrno = code;
27,170✔
3358
    return code;
27,170✔
3359
  }
17,290✔
3360

3361
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
3362
  epSet.eps[0].port = firstEp.port;
3363
  SInstanceListReq req = {0};
27,170✔
3364
  if (filter_type != NULL && filter_type[0] != 0) {
27,170✔
UNCOV
3365
    tstrncpy(req.filter_type, filter_type, sizeof(req.filter_type));
×
UNCOV
3366
  }
×
UNCOV
3367

×
UNCOV
3368
  // Serialize request to get required length
×
3369
  int32_t contLen = tSerializeSInstanceListReq(NULL, 0, &req);
3370
  if (contLen <= 0) {
3371
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
3372
    rpcClose(clientRpc);
27,170✔
3373
    terrno = code;
27,170✔
3374
    return code;
×
UNCOV
3375
  }
×
UNCOV
3376

×
UNCOV
3377
  // Allocate RPC message buffer (includes message header overhead)
×
3378
  void *pCont = rpcMallocCont(contLen);
3379
  if (pCont == NULL) {
3380
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
3381
    rpcClose(clientRpc);
27,170✔
3382
    terrno = code;
×
3383
    return code;
×
UNCOV
3384
  }
×
UNCOV
3385

×
UNCOV
3386
  // Serialize request into the content part (after message header)
×
3387
  if (tSerializeSInstanceListReq(pCont, contLen, &req) < 0) {
3388
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
3389
    rpcFreeCont(pCont);
27,170✔
3390
    rpcClose(clientRpc);
27,170✔
3391
    terrno = code;
27,170✔
3392
    return code;
27,170✔
3393
  }
27,170✔
3394

3395
  rpcMsg.pCont = pCont;
27,170✔
3396
  rpcMsg.contLen = contLen;
27,170✔
UNCOV
3397
  rpcMsg.msgType = TDMT_MND_LIST_INSTANCES;
×
UNCOV
3398
  rpcMsg.info.ahandle = (void *)0x9529;  // Different magic number from register
×
UNCOV
3399
  rpcMsg.info.notFreeAhandle = 1;
×
UNCOV
3400

×
UNCOV
3401
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
×
3402
  if (TSDB_CODE_SUCCESS != code) {
3403
    tscError("failed to send instance list req since %s", tstrerror(code));
3404
    rpcFreeCont(pCont);
3405
    rpcClose(clientRpc);
27,170✔
3406
    terrno = code;
×
3407
    return code;
×
UNCOV
3408
  }
×
UNCOV
3409

×
3410
  // Check response - rpcRsp.code contains the result code from mnode
UNCOV
3411
  if (rpcRsp.code != 0) {
×
3412
    code = rpcRsp.code;
×
3413
    tscError("instance list failed, code:%s", tstrerror(code));
×
3414
    if (rpcRsp.pCont != NULL) {
3415
      rpcFreeCont(rpcRsp.pCont);
3416
    }
3417
    rpcClose(clientRpc);
27,170✔
3418
    terrno = code;
27,170✔
3419
    return code;
27,170✔
3420
  }
27,170✔
UNCOV
3421

×
UNCOV
3422
  // Deserialize response
×
UNCOV
3423
  if (rpcRsp.pCont != NULL && rpcRsp.contLen > 0) {
×
UNCOV
3424
    SInstanceListRsp rsp = {0};
×
UNCOV
3425
    code = tDeserializeSInstanceListRsp(rpcRsp.pCont, rpcRsp.contLen, &rsp);
×
3426
    if (code != TSDB_CODE_SUCCESS) {
3427
      tscError("failed to deserialize instance list rsp, code:%s", tstrerror(code));
3428
      if (rsp.ids != NULL) {
×
3429
        for (int32_t i = 0; i < rsp.count; i++) {
×
3430
          if (rsp.ids[i] != NULL) {
3431
            taosMemoryFree(rsp.ids[i]);
×
UNCOV
3432
          }
×
UNCOV
3433
        }
×
3434
        taosMemoryFree(rsp.ids);
×
3435
        rsp.ids = NULL;
×
3436
      }
3437
      rsp.count = 0;
27,170✔
3438
      rpcFreeCont(rpcRsp.pCont);
27,170✔
3439
      rpcClose(clientRpc);
3440
      terrno = code;
×
3441
      return code;
×
3442
    }
3443
    *pList = rsp.ids;
3444
    *pCount = rsp.count;
27,170✔
3445
  } else {
27,170✔
3446
    *pList = NULL;
3447
    *pCount = 0;
27,170✔
3448
  }
3449

27,170✔
3450
  if (rpcRsp.pCont != NULL) {
3451
    rpcFreeCont(rpcRsp.pCont);
3452
  }
19,760✔
3453
  rpcClose(clientRpc);
19,760✔
UNCOV
3454

×
3455
  return TSDB_CODE_SUCCESS;
3456
}
3457

3458
void taos_free_instances(char ***pList, int32_t count) {
61,750✔
3459
  if (pList == NULL || *pList == NULL || count <= 0) {
41,990✔
3460
    return;
41,990✔
3461
  }
41,990✔
3462

3463
  // Free each string in the array
3464
  for (int32_t i = 0; i < count; i++) {
3465
    if ((*pList)[i] != NULL) {
3466
      taosMemoryFree((*pList)[i]);
19,760✔
3467
      (*pList)[i] = NULL;
19,760✔
3468
    }
3469
  }
3470

3471
  // Free the array itself
3472
  taosMemoryFree(*pList);
3473
  *pList = NULL;
3474
}
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