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

taosdata / TDengine / #4996

19 Mar 2026 02:16AM UTC coverage: 72.069% (+0.07%) from 71.996%
#4996

push

travis-ci

web-flow
feat: SQL firewall black/white list (#34798)

461 of 618 new or added lines in 4 files covered. (74.6%)

380 existing lines in 128 files now uncovered.

245359 of 340448 relevant lines covered (72.07%)

135732617.17 hits per line

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

54.07
/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, ...) {
80,380,916✔
50
  if (arg == NULL) {
80,380,916✔
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();
9,582,129✔
58
    }
59
  }
60

61
  int ret = taos_options_imp(option, (const char *)arg);
1,214,917✔
62
  atomic_store_32(&lock, 0);
80,385,072✔
63
  return ret;
80,385,072✔
64
}
65

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

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

81
  pTimezoneNameMap = taosHashInit(0, taosIntHash_64, false, HASH_ENTRY_LOCK);
1,754,513✔
82
  if (pTimezoneNameMap == NULL) {
1,754,513✔
83
    return terrno;
×
84
  }
85
#endif
86
  return 0;
1,754,513✔
87
}
88

89
void tzCleanup() {
1,754,552✔
90
#if !defined(WINDOWS) && !defined(TD_ASTRA)
91
  taosHashCleanup(pTimezoneMap);
1,754,552✔
92
  taosHashCleanup(pTimezoneNameMap);
1,754,552✔
93
#endif
94
}
1,754,552✔
95

96
#if !defined(WINDOWS) && !defined(TD_ASTRA)
97
static timezone_t setConnnectionTz(const char *val) {
3,612✔
98
  timezone_t  tz = NULL;
3,612✔
99
  timezone_t *tmp = taosHashGet(pTimezoneMap, val, strlen(val));
3,612✔
100
  if (tmp != NULL && *tmp != NULL) {
3,612✔
101
    tz = *tmp;
1,426✔
102
    goto END;
1,426✔
103
  }
104

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

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

134
END:
2,186✔
135
  return tz;
3,612✔
136
}
137
#endif
138

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

144
#ifdef WINDOWS
145
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE) {
146
    return terrno = TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS;
147
  }
148
#endif
149

150
  if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION) {
9,150✔
151
    return terrno = TSDB_CODE_INVALID_PARA;
190✔
152
  }
153

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

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

166
  if (option == TSDB_OPTION_CONNECTION_CLEAR) {
8,960✔
167
    val = NULL;
190✔
168
  }
169

170
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
171
  if (option == TSDB_OPTION_CONNECTION_CHARSET || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,960✔
172
    if (val != NULL) {
1,708✔
173
      if (!taosValidateEncodec(val)) {
1,138✔
174
        code = terrno;
284✔
175
        goto END;
284✔
176
      }
177
      void *tmp = taosConvInit(val);
854✔
178
      if (tmp == NULL) {
854✔
179
        code = terrno;
190✔
180
        goto END;
190✔
181
      }
182
      pObj->optionInfo.charsetCxt = tmp;
664✔
183
    } else {
184
      pObj->optionInfo.charsetCxt = NULL;
570✔
185
    }
186
  }
187
#endif
188
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,486✔
189
#if !defined(WINDOWS) && !defined(TD_ASTRA)
190
    if (val != NULL) {
3,992✔
191
      if (val[0] == 0) {
3,612✔
192
        val = "UTC";
190✔
193
      }
194
      timezone_t tz = setConnnectionTz(val);
3,612✔
195
      if (tz == NULL) {
3,612✔
196
        code = terrno;
×
197
        goto END;
×
198
      }
199
      pObj->optionInfo.timezone = tz;
3,612✔
200
    } else {
201
      pObj->optionInfo.timezone = NULL;
380✔
202
    }
203
#endif
204
  }
205

206
  if (option == TSDB_OPTION_CONNECTION_USER_APP || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,486✔
207
    if (val != NULL) {
1,108✔
208
      tstrncpy(pObj->optionInfo.userApp, val, sizeof(pObj->optionInfo.userApp));
728✔
209
    } else {
210
      pObj->optionInfo.userApp[0] = 0;
380✔
211
    }
212
  }
213

214
  if (option == TSDB_OPTION_CONNECTION_CONNECTOR_INFO || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,486✔
215
    if (val != NULL) {
1,108✔
216
      tstrncpy(pObj->optionInfo.cInfo, val, sizeof(pObj->optionInfo.cInfo));
728✔
217
    } else {
218
      pObj->optionInfo.cInfo[0] = 0;
380✔
219
    }
220
  }
221

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

244
END:
6,682✔
245
  releaseTscObj(*(int64_t *)taos);
8,960✔
246
  return terrno = code;
8,960✔
247
}
248

249
int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...) {
9,340✔
250
  return setConnectionOption(taos, option, (const char *)arg);
9,340✔
251
}
252

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

260
  monitorClose();
1,754,552✔
261
  tscStopCrashReport();
1,754,552✔
262

263
  hbMgrCleanUp();
1,754,552✔
264

265
  catalogDestroy();
1,754,552✔
266
  schedulerDestroy();
1,754,552✔
267

268
  fmFuncMgtDestroy();
1,754,552✔
269
  qCleanupKeywordsTable();
1,754,552✔
270

271
#if !defined(WINDOWS) && !defined(TD_ASTRA)
272
  tzCleanup();
1,754,552✔
273
#endif
274
  tmqMgmtClose();
1,754,552✔
275

276
  int32_t id = clientReqRefPool;
1,754,552✔
277
  clientReqRefPool = -1;
1,754,552✔
278
  taosCloseRef(id);
1,754,552✔
279

280
  id = clientConnRefPool;
1,754,552✔
281
  clientConnRefPool = -1;
1,754,552✔
282
  taosCloseRef(id);
1,754,552✔
283

284
  nodesDestroyAllocatorSet();
1,754,552✔
285
  cleanupAppInfo();
1,754,552✔
286
  rpcCleanup();
1,754,552✔
287
  tscDebug("rpc cleanup");
1,754,552✔
288

289
  if (TSDB_CODE_SUCCESS != cleanupTaskQueue()) {
1,754,552✔
290
    tscWarn("failed to cleanup task queue");
×
291
  }
292

293
  sessMgtDestroy();
1,754,552✔
294

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

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

313
setConfRet taos_set_config(const char *config) {
13✔
314
  // TODO  pthread_mutex_lock(&setConfMutex);
315
  setConfRet ret = taos_set_config_imp(config);
13✔
316
  //  pthread_mutex_unlock(&setConfMutex);
317
  return ret;
13✔
318
}
319

320
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
82,630,390✔
321
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
82,630,390✔
322
  if (user == NULL) {
82,630,412✔
323
    user = TSDB_DEFAULT_USER;
177,794✔
324
  }
325

326
  if (pass == NULL) {
82,630,412✔
327
    pass = TSDB_DEFAULT_PASS;
177,794✔
328
  }
329

330
  STscObj *pObj = NULL;
82,630,412✔
331
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY, &pObj);
82,631,610✔
332
  if (TSDB_CODE_SUCCESS == code) {
82,615,531✔
333
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
82,610,560✔
334
    if (NULL == rid) {
82,611,165✔
335
      tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db);
×
336
      return NULL;
×
337
    }
338
    *rid = pObj->id;
82,611,165✔
339
    return (TAOS *)rid;
82,611,923✔
340
  } else {
341
    terrno = code;
11,710✔
342
  }
343

344
  return NULL;
11,856✔
345
}
346

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

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

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

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

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

385
  const char *charset = NULL;
564✔
386
  const char *timezone = NULL;
564✔
387
  const char *userIp = NULL;
564✔
388
  const char *userApp = NULL;
564✔
389
  const char *connectorInfo = NULL;
564✔
390

391
  if (options && options->count > 0) {
564✔
392
    size_t count = (size_t)options->count;
470✔
393
    for (size_t i = 0; i < count; ++i) {
2,350✔
394
      const char *key = options->keys[i];
1,880✔
395
      const char *value = options->values[i];
1,880✔
396
      if (key == NULL || value == NULL) {
1,880✔
397
        tscWarn("taos_connect_with option key or value is NULL, index: %zu", i);
282✔
398
        continue;
282✔
399
      }
400

401
      if (strcmp(key, "ip") == 0) {
1,598✔
402
        ip = value;
376✔
403
      } else if (strcmp(key, "user") == 0) {
1,222✔
404
        user = value;
94✔
405
      } else if (strcmp(key, "pass") == 0) {
1,128✔
406
        pass = value;
94✔
407
      } else if (strcmp(key, "db") == 0) {
1,034✔
408
        db = value;
94✔
409
      } else if (strcmp(key, "port") == 0) {
940✔
410
        port = (uint16_t)taosStr2Int32(value, NULL, 10);
282✔
411
      } else if (strcmp(key, "charset") == 0) {
658✔
412
        charset = value;
188✔
413
      } else if (strcmp(key, "timezone") == 0) {
470✔
414
        timezone = value;
94✔
415
      } else if (strcmp(key, "userIp") == 0) {
376✔
416
        userIp = value;
94✔
417
      } else if (strcmp(key, "userApp") == 0) {
282✔
418
        userApp = value;
94✔
419
      } else if (strcmp(key, "connectorInfo") == 0) {
188✔
420
        connectorInfo = value;
94✔
421
      } else {
422
        tscWarn("taos_connect_with unknown option key: %s", key);
94✔
423
      }
424
    }
425
  }
426

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

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

437
  return taos;
376✔
438
}
439

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

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

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

459
  switch (type) {
1,330✔
460
    case TAOS_NOTIFY_PASSVER: {
380✔
461
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
380✔
462
      pObj->passInfo.fp = fp;
380✔
463
      pObj->passInfo.param = param;
380✔
464
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
380✔
465
      break;
380✔
466
    }
467
    case TAOS_NOTIFY_WHITELIST_VER: {
×
468
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
469
      pObj->whiteListInfo.fp = fp;
×
470
      pObj->whiteListInfo.param = param;
×
471
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
472
      break;
×
473
    }
474
    case TAOS_NOTIFY_USER_DROPPED: {
950✔
475
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
950✔
476
      pObj->userDroppedInfo.fp = fp;
950✔
477
      pObj->userDroppedInfo.param = param;
950✔
478
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
950✔
479
      break;
950✔
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;
×
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;
×
497
      releaseTscObj(*(int64_t *)taos);
×
498
      return terrno;
×
499
    }
500
  }
501

502
  releaseTscObj(*(int64_t *)taos);
1,330✔
503
  return 0;
1,330✔
504
}
505

506
typedef struct SFetchWhiteListInfo {
507
  int64_t                     connId;
508
  __taos_async_whitelist_fn_t userCbFn;
509
  void                       *userParam;
510
} SFetchWhiteListInfo;
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;
×
521
  }
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;
×
530
  }
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;
×
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;
×
543
  }
544

545
  pInfo->userCbFn(pInfo->userParam, code, taos, wlRsp.numWhiteLists, pWhiteLists);
×
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;
×
559
  }
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;
×
567
  }
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;
×
576
  }
577

578
  void *pReq = taosMemoryMalloc(msgLen);
×
579
  if (pReq == NULL) {
×
580
    fp(param, terrno, taos, 0, NULL);
×
581
    releaseTscObj(connId);
×
582
    return;
×
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;
×
590
  }
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;
×
598
  }
599

600
  pParam->connId = connId;
×
601
  pParam->userCbFn = fp;
×
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;
×
611
  }
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;
×
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;
630
  bool    supportNeg;
631
  void   *userParam;
632

633
  __taos_async_ip_whitelist_fn_t userCbFn;
634
} SFetchIpWhiteListInfo;
635

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

640
  SGetUserIpWhiteListRsp wlRsp = {0};
×
641

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

645
  if (code != TSDB_CODE_SUCCESS) {
×
646
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
647
    TAOS_CHECK_GOTO(code, &lino, _error);
×
648
  }
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);
×
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;
×
665
    }
666
    SIpAddr ipAddr = {0};
×
667

668
    code = tIpUintToStr(pIpRange, &ipAddr);
×
669
    TAOS_CHECK_GOTO(code, &lino, _error);
×
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);
×
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);
×
690
      }
691
    }
692
    pWhiteLists[numWhiteLists++] = ip;
×
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]);
×
700
    }
701
    taosMemoryFree(pWhiteLists);
×
702
  }
703
  taosMemoryFree(pMsg->pData);
×
704
  taosMemoryFree(pMsg->pEpSet);
×
705
  taosMemoryFree(pInfo);
×
706
  tFreeSGetUserIpWhiteListDualRsp(&wlRsp);
×
707
  return code;
×
708
}
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;
×
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;
×
721
  }
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;
×
730
  }
731

732
  void *pReq = taosMemoryMalloc(msgLen);
×
733
  if (pReq == NULL) {
×
734
    fp(param, terrno, taos, 0, NULL);
×
735
    releaseTscObj(connId);
×
736
    return;
×
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;
×
744
  }
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
  }
753

754
  pParam->connId = connId;
×
755
  pParam->supportNeg = supportNeg;
×
756
  pParam->userCbFn = fp;
×
757
  pParam->userParam = param;
×
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;
×
766
  }
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;
×
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");
×
778
  }
779
  releaseTscObj(connId);
×
780
  return;
×
781
}
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 {
792
  int64_t                              connId;
793
  void                                *userParam;
794
  __taos_async_datetime_whitelist_fn_t userCbFn;
795
} SFetchDateTimeWhiteListInfo;
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;
×
801

802
  SUserDateTimeWhiteList wlRsp = {0};
×
803

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

807
  if (code != TSDB_CODE_SUCCESS) {
×
808
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
809
    TAOS_CHECK_GOTO(code, &lino, _error);
×
810
  }
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);
×
820
  }
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);
×
830
    }
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);
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);
×
844
    }
845
    pWhiteLists[numWhiteLists++] = p;
×
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]);
×
853
    }
854
    taosMemoryFree(pWhiteLists);
×
855
  }
856
  taosMemoryFree(pMsg->pData);
×
857
  taosMemoryFree(pMsg->pEpSet);
×
858
  taosMemoryFree(pInfo);
×
859
  tFreeSUserDateTimeWhiteList(&wlRsp);
×
860
  return code;
×
861
}
862

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

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

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

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

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

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

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

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

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

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

935
void taos_close_internal(void *taos) {
82,747,523✔
936
  if (taos == NULL) {
82,747,523✔
937
    return;
328✔
938
  }
939
  int32_t code = 0;
82,747,195✔
940

941
  STscObj *pTscObj = (STscObj *)taos;
82,747,195✔
942
  tscDebug("conn:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
82,747,195✔
943

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

946
  code = tscUpdateSessMetric(pTscObj, &para);
82,747,195✔
947
  if (code != TSDB_CODE_SUCCESS) {
82,748,229✔
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);
82,748,229✔
953
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
82,748,559✔
954
    tscError("conn:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
×
955
  }
956
}
957

958
void taos_close(TAOS *taos) {
82,621,668✔
959
  if (taos == NULL) {
82,621,668✔
960
    return;
502✔
961
  }
962

963
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
82,621,166✔
964
  if (NULL == pObj) {
82,622,692✔
965
    taosMemoryFree(taos);
×
966
    return;
×
967
  }
968

969
  taos_close_internal(pObj);
82,622,692✔
970
  releaseTscObj(*(int64_t *)taos);
82,622,040✔
971
  taosMemoryFree(taos);
82,619,433✔
972
}
973

974
int taos_errno(TAOS_RES *res) {
1,283,538,591✔
975
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,283,538,591✔
976
    return terrno;
871,750✔
977
  }
978

979
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,282,670,359✔
980
    return 0;
396,718✔
981
  }
982

983
  return ((SRequestObj *)res)->code;
1,282,272,284✔
984
}
985

986
const char *taos_errstr(TAOS_RES *res) {
98,825,686✔
987
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
98,825,686✔
988
    if (*(taosGetErrMsg()) == 0) {
882,011✔
989
      return (const char *)tstrerror(terrno);
882,506✔
990
    } else {
991
      (void)snprintf(taosGetErrMsgReturn(), ERR_MSG_LEN, "%s", taosGetErrMsg());
39✔
992
      return (const char *)taosGetErrMsgReturn();
39✔
993
    }
994
  }
995

996
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
97,943,828✔
997
    return "success";
19✔
998
  }
999

1000
  SRequestObj *pRequest = (SRequestObj *)res;
97,943,809✔
1001
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
97,943,809✔
1002
    return pRequest->msgBuf;
28,721,972✔
1003
  } else {
1004
    return (const char *)tstrerror(pRequest->code);
69,221,837✔
1005
  }
1006
}
1007

1008
void taos_free_result(TAOS_RES *res) {
946,597,561✔
1009
  if (NULL == res) {
946,597,561✔
1010
    return;
13,509,858✔
1011
  }
1012

1013
  tscTrace("res:%p, will be freed", res);
933,087,703✔
1014

1015
  if (TD_RES_QUERY(res)) {
933,093,701✔
1016
    SRequestObj *pRequest = (SRequestObj *)res;
919,698,907✔
1017
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query, res:%p", pRequest->requestId, res);
919,698,907✔
1018
    destroyRequest(pRequest);
919,698,907✔
1019
    return;
919,687,854✔
1020
  }
1021

1022
  SMqRspObj *pRsp = (SMqRspObj *)res;
13,399,025✔
1023
  if (TD_RES_TMQ(res)) {
13,399,025✔
1024
    tDeleteMqDataRsp(&pRsp->dataRsp);
13,376,534✔
1025
    doFreeReqResultInfo(&pRsp->resInfo);
13,375,830✔
1026
  } else if (TD_RES_TMQ_METADATA(res)) {
20,448✔
1027
    tDeleteSTaosxRsp(&pRsp->dataRsp);
1,678✔
1028
    doFreeReqResultInfo(&pRsp->resInfo);
1,678✔
1029
  } else if (TD_RES_TMQ_META(res)) {
18,770✔
1030
    tDeleteMqMetaRsp(&pRsp->metaRsp);
15,638✔
1031
  } else if (TD_RES_TMQ_BATCH_META(res)) {
3,132✔
1032
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
3,132✔
1033
  } else if (TD_RES_TMQ_RAW(res)) {
×
1034
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
×
1035
  }
1036
  taosMemoryFree(pRsp);
13,394,870✔
1037
}
1038

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

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

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

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

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

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

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

1072
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
912,353,836✔
1073
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
205✔
1074
  return taosQueryImplWithReqid(taos, sql, false, reqid);
205✔
1075
}
1076

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

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

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

1098
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
1,668,037,000✔
1099
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
1,668,037,737✔
1100
      return NULL;
626✔
1101
    }
1102

1103
    if (pRequest->inCallback) {
1,668,034,942✔
1104
      tscError("can not call taos_fetch_row before query callback ends.");
190✔
1105
      terrno = TSDB_CODE_TSC_INVALID_OPERATION;
190✔
1106
      return NULL;
190✔
1107
    }
1108

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

1121
    if (pResultInfo->current < pResultInfo->numOfRows) {
2,147,483,647✔
1122
      doSetOneRowPtr(pResultInfo);
2,147,483,647✔
1123
      pResultInfo->current += 1;
2,147,483,647✔
1124
      return pResultInfo->row;
2,147,483,647✔
1125
    } else {
1126
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
51,925,359✔
1127
        return NULL;
12,951,512✔
1128
      }
1129

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

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

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

1158
    switch (fields[i].type) {
2,147,483,647✔
1159
      case TSDB_DATA_TYPE_TINYINT:
8,380,038✔
1160
        len += snprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
8,380,038✔
1161
        break;
8,422,430✔
1162

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

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

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

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

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

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

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

1191
      case TSDB_DATA_TYPE_FLOAT: {
16,779,443✔
1192
        float fv = 0;
16,779,443✔
1193
        fv = GET_FLOAT_VAL(row[i]);
16,779,443✔
1194
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
16,820,883✔
1195
      } break;
16,770,427✔
1196

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1355
const char *taos_get_client_info() { return td_version; }
1,327,720✔
1356

1357
// return int32_t
1358
int taos_affected_rows(TAOS_RES *res) {
614,015,535✔
1359
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
614,015,535✔
1360
      TD_RES_TMQ_BATCH_META(res)) {
614,018,629✔
1361
    return 0;
×
1362
  }
1363

1364
  SRequestObj    *pRequest = (SRequestObj *)res;
614,016,975✔
1365
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
614,016,975✔
1366
  return (int)pResInfo->numOfRows;
614,018,810✔
1367
}
1368

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

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

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

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

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

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

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

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

1417
  taos_free_result(pRequest);
38,285✔
1418
  releaseTscObj(*(int64_t *)taos);
38,285✔
1419
  return code;
38,285✔
1420
}
1421

1422
void taos_stop_query(TAOS_RES *res) {
1,003,324,563✔
1423
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,003,324,563✔
1424
      TD_RES_TMQ_BATCH_META(res)) {
1,003,344,031✔
1425
    return;
×
1426
  }
1427

1428
  stopAllQueries((SRequestObj *)res);
1,003,336,768✔
1429
}
1430

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

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

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

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

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

1461
  if (TD_RES_QUERY(res)) {
301,838,589✔
1462
    SRequestObj *pRequest = (SRequestObj *)res;
301,058,129✔
1463

1464
    (*rows) = NULL;
301,058,129✔
1465
    (*numOfRows) = 0;
301,058,129✔
1466

1467
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
301,058,129✔
1468
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
300,713,177✔
1469
      return pRequest->code;
1,381,263✔
1470
    }
1471

1472
    (void)doAsyncFetchRows(pRequest, false, true);
299,676,866✔
1473

1474
    // TODO refactor
1475
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
299,676,866✔
1476
    pResultInfo->current = pResultInfo->numOfRows;
299,676,866✔
1477

1478
    (*rows) = pResultInfo->row;
299,676,866✔
1479
    (*numOfRows) = pResultInfo->numOfRows;
299,676,866✔
1480
    return pRequest->code;
299,676,866✔
1481
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
780,460✔
1482
    SReqResultInfo *pResultInfo = NULL;
780,460✔
1483
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
780,460✔
1484
    if (code != 0) return code;
780,460✔
1485

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

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

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

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

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

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

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

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

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

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

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

1536
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
229,258,159✔
1537
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
229,258,159✔
1538
    return NULL;
×
1539
  }
1540

1541
  int32_t numOfFields = taos_num_fields(res);
229,258,159✔
1542
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
229,258,159✔
1543
    return NULL;
×
1544
  }
1545

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

1552
  return pResInfo->pCol[columnIndex].offset;
229,258,159✔
1553
}
1554

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

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

1566
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
761,569,843✔
1567
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
761,569,843✔
1568
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
761,569,843✔
1569

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

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

1596
  int code = taos_errno(pObj);
×
1597

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

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

1609
  resetConnectDB(pTscObj);
×
1610

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

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

1621
  releaseTscObj(*(int64_t *)taos);
3,359✔
1622

1623
  return pTscObj->sDetailVer;
3,359✔
1624
}
1625

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

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

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

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

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

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

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

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

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

1704
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
1,920,340,407✔
1705
  if (NULL == pWrapper) {
1,920,340,407✔
1706
    return;
1,005,609,675✔
1707
  }
1708
  destoryCatalogReq(pWrapper->pCatalogReq);
914,730,732✔
1709
  taosMemoryFree(pWrapper->pCatalogReq);
914,786,170✔
1710
  qDestroyParseContext(pWrapper->pParseCtx);
914,786,508✔
1711
  taosMemoryFree(pWrapper);
914,783,793✔
1712
}
1713

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

1722
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
416,808,636✔
1723
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
416,808,636✔
1724
  SRequestObj         *pRequest = pWrapper->pRequest;
416,808,636✔
1725
  SQuery              *pQuery = pRequest->pQuery;
416,808,246✔
1726

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

1729
  int64_t analyseStart = taosGetTimestampUs();
416,812,067✔
1730
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
416,812,067✔
1731
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
416,811,617✔
1732

1733
  if (TSDB_CODE_SUCCESS == code) {
416,812,100✔
1734
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
416,809,382✔
1735
  }
1736

1737
  if (TSDB_CODE_SUCCESS == code) {
416,773,121✔
1738
    code = sqlSecurityCheckASTLevel(pRequest, pQuery);
344,600,356✔
1739
  }
1740

1741
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
416,760,590✔
1742

1743
  if (pRequest->parseOnly) {
416,758,398✔
1744
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
290,835✔
1745
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
290,835✔
1746
  }
1747

1748
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
416,766,222✔
1749
}
416,771,989✔
1750

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

1778
    *ppTarget = pTarget;
×
1779
  }
1780

1781
  return code;
×
1782
}
1783

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

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

1815
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
416,745,787✔
1816
  SRequestObj *pRequest = pWrapper->pRequest;
416,745,787✔
1817
  SQuery      *pQuery = pRequest->pQuery;
416,756,458✔
1818

1819
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
416,746,800✔
1820
    SNode *prevRoot = pQuery->pPrevRoot;
×
1821
    pQuery->pPrevRoot = NULL;
×
1822
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
×
1823
    return;
×
1824
  }
1825

1826
  if (code == TSDB_CODE_SUCCESS) {
416,732,580✔
1827
    pRequest->stableQuery = pQuery->stableQuery;
344,592,546✔
1828
    if (pQuery->pRoot) {
344,581,123✔
1829
      pRequest->stmtType = pQuery->pRoot->type;
344,609,765✔
1830
      if (nodeType(pQuery->pRoot) == QUERY_NODE_DELETE_STMT) {
344,584,590✔
1831
        pRequest->secureDelete = ((SDeleteStmt*)pQuery->pRoot)->secureDelete;
1,583,572✔
1832
      }
1833
    }
1834

1835
    if (pQuery->haveResultSet) {
344,582,265✔
1836
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema,
187,731,017✔
1837
                              pRequest->stmtBindVersion > 0);
187,732,223✔
1838
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
187,729,577✔
1839
    }
1840
  }
1841

1842
  if (code == TSDB_CODE_SUCCESS) {
416,753,482✔
1843
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
344,584,959✔
1844
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
344,586,193✔
1845
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
344,573,135✔
1846

1847
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
344,566,308✔
1848
  } else {
1849
    destorySqlCallbackWrapper(pWrapper);
72,168,523✔
1850
    pRequest->pWrapper = NULL;
72,176,786✔
1851
    qDestroyQuery(pRequest->pQuery);
72,176,786✔
1852
    pRequest->pQuery = NULL;
72,180,740✔
1853

1854
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
72,180,740✔
1855
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
2,568,928✔
1856
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1857
      restartAsyncQuery(pRequest, code);
2,568,928✔
1858
      return;
2,568,928✔
1859
    }
1860

1861
    // return to app directly
1862
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self,
69,611,812✔
1863
             tstrerror(code), pRequest->requestId);
1864
    pRequest->code = code;
69,627,095✔
1865
    returnToUser(pRequest);
69,627,095✔
1866
  }
1867
}
1868

1869
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
423,551,047✔
1870
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
679,708,582✔
1871
                           .requestId = pWrapper->pParseCtx->requestId,
423,557,515✔
1872
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
423,546,497✔
1873
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
423,555,055✔
1874

1875
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
679,707,020✔
1876

1877
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
590,955,598✔
1878
                                &pWrapper->pRequest->body.queryJob);
423,566,462✔
1879
}
1880

1881
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1882

1883
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
907,676,244✔
1884
  int32_t code = TSDB_CODE_SUCCESS;
907,676,244✔
1885
  switch (pWrapper->pRequest->pQuery->execStage) {
907,676,244✔
1886
    case QUERY_EXEC_STAGE_PARSE: {
6,780,050✔
1887
      // continue parse after get metadata
1888
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
6,780,050✔
1889
      break;
6,780,050✔
1890
    }
1891
    case QUERY_EXEC_STAGE_ANALYSE: {
416,778,966✔
1892
      // analysis after get metadata
1893
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
416,778,966✔
1894
      break;
416,783,272✔
1895
    }
1896
    case QUERY_EXEC_STAGE_SCHEDULE: {
484,140,346✔
1897
      launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper);
484,140,346✔
1898
      break;
484,140,440✔
1899
    }
1900
    default:
×
1901
      break;
×
1902
  }
1903
  return code;
907,675,598✔
1904
}
1905

1906
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
6,780,050✔
1907
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
6,780,050✔
1908
  SRequestObj         *pRequest = pWrapper->pRequest;
6,780,050✔
1909
  SQuery              *pQuery = pRequest->pQuery;
6,780,050✔
1910

1911
  pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart;
6,780,050✔
1912
  qDebug("req:0x%" PRIx64 ", continue parse query, QID:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId,
6,780,050✔
1913
         tstrerror(code));
1914

1915
  if (code == TSDB_CODE_SUCCESS) {
6,780,050✔
1916
    // pWrapper->pCatalogReq->forceUpdate = false;
1917
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
6,757,331✔
1918
  }
1919

1920
  if (TSDB_CODE_SUCCESS == code) {
6,780,050✔
1921
    code = phaseAsyncQuery(pWrapper);
6,214,733✔
1922
  }
1923

1924
  if (TSDB_CODE_SUCCESS != code) {
6,780,050✔
1925
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
565,317✔
1926
             tstrerror(code), pWrapper->pRequest->requestId);
1927
    destorySqlCallbackWrapper(pWrapper);
565,317✔
1928
    pRequest->pWrapper = NULL;
565,317✔
1929
    terrno = code;
565,317✔
1930
    pRequest->code = code;
565,317✔
1931
    doRequestCallback(pRequest, code);
565,317✔
1932
  }
1933
}
6,780,050✔
1934

1935
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
11,963✔
1936
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
11,963✔
1937
  if (TSDB_CODE_SUCCESS == code) {
11,963✔
1938
    code = phaseAsyncQuery(pWrapper);
11,963✔
1939
  }
1940

1941
  if (TSDB_CODE_SUCCESS != code) {
11,963✔
1942
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
×
1943
             tstrerror(code), pWrapper->pRequest->requestId);
1944
    destorySqlCallbackWrapper(pWrapper);
×
1945
    pRequest->pWrapper = NULL;
×
1946
    terrno = code;
×
1947
    pRequest->code = code;
×
1948
    doRequestCallback(pRequest, code);
×
1949
  }
1950
}
11,963✔
1951

1952
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
128,493✔
1953
  int64_t connId = *(int64_t *)taos;
128,493✔
1954
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
128,493✔
1955
}
128,493✔
1956

1957
void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) {
×
1958
  int64_t connId = *(int64_t *)taos;
×
1959
  taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid);
×
1960
}
×
1961

1962
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
914,793,692✔
1963
  const STscObj *pTscObj = pRequest->pTscObj;
914,793,692✔
1964

1965
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
914,798,034✔
1966
  if (*pCxt == NULL) {
914,773,836✔
1967
    return terrno;
×
1968
  }
1969

1970
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
2,147,483,647✔
1971
                           .requestRid = pRequest->self,
914,775,811✔
1972
                           .acctId = pTscObj->acctId,
914,782,513✔
1973
                           .db = pRequest->pDb,
914,781,442✔
1974
                           .topicQuery = false,
1975
                           .pSql = pRequest->sqlstr,
914,789,461✔
1976
                           .sqlLen = pRequest->sqlLen,
914,786,919✔
1977
                           .pMsg = pRequest->msgBuf,
914,788,472✔
1978
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
1979
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
914,782,325✔
1980
                           .pStmtCb = NULL,
1981
                           .pUser = pTscObj->user,
914,782,589✔
1982
                           .userId = pTscObj->userId,
914,782,701✔
1983
                           .pEffectiveUser = pRequest->effectiveUser,
914,789,036✔
1984
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
914,785,182✔
1985
                           .enableSysInfo = pTscObj->sysInfo,
914,785,146✔
1986
                           .privInfo = pWrapper->pParseCtx ? pWrapper->pParseCtx->privInfo : 0,
914,799,100✔
1987
                           .async = true,
1988
                           .svrVer = pTscObj->sVer,
914,783,294✔
1989
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
914,782,842✔
1990
                           .allocatorId = pRequest->allocatorRefId,
914,783,364✔
1991
                           .parseSqlFp = clientParseSql,
1992
                           .parseSqlParam = pWrapper,
1993
                           .setQueryFp = setQueryRequest,
1994
                           .timezone = pTscObj->optionInfo.timezone,
914,786,215✔
1995
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
914,785,000✔
1996
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
914,780,531✔
1997
  (*pCxt)->biMode = biMode;
914,795,143✔
1998
  return TSDB_CODE_SUCCESS;
914,797,990✔
1999
}
2000

2001
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
914,792,475✔
2002
  int32_t              code = TSDB_CODE_SUCCESS;
914,792,475✔
2003
  STscObj             *pTscObj = pRequest->pTscObj;
914,792,475✔
2004
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
914,795,989✔
2005
  if (pWrapper == NULL) {
914,794,482✔
2006
    code = terrno;
×
2007
  } else {
2008
    pWrapper->pRequest = pRequest;
914,794,482✔
2009
    pRequest->pWrapper = pWrapper;
914,793,907✔
2010
    *ppWrapper = pWrapper;
914,799,315✔
2011
  }
2012

2013
  if (TSDB_CODE_SUCCESS == code) {
914,790,968✔
2014
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
914,790,879✔
2015
  }
2016

2017
  if (TSDB_CODE_SUCCESS == code) {
914,792,727✔
2018
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
914,795,407✔
2019
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
914,807,494✔
2020
  }
2021

2022
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
914,812,663✔
2023
    int64_t syntaxStart = taosGetTimestampUs();
914,803,398✔
2024

2025
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
914,803,398✔
2026
    if (pWrapper->pCatalogReq == NULL) {
914,776,356✔
2027
      code = terrno;
×
2028
    } else {
2029
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
914,779,570✔
2030
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
914,789,001✔
2031
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
914,783,610✔
2032
    }
2033

2034
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
914,766,957✔
2035
  }
2036

2037
  return code;
914,797,772✔
2038
}
2039

2040
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
915,647,700✔
2041
  SSqlCallbackWrapper *pWrapper = NULL;
915,647,700✔
2042
  int32_t              code = TSDB_CODE_SUCCESS;
915,653,683✔
2043

2044
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
915,653,683✔
2045
    code = pRequest->prevCode;
858,265✔
2046
    terrno = code;
858,265✔
2047
    pRequest->code = code;
858,265✔
2048
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
858,265✔
2049
    doRequestCallback(pRequest, code);
858,265✔
2050
    return;
858,265✔
2051
  }
2052

2053
  if (TSDB_CODE_SUCCESS == code) {
914,787,465✔
2054
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
914,797,608✔
2055
  }
2056

2057
  if (TSDB_CODE_SUCCESS == code) {
914,758,143✔
2058
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
901,481,793✔
2059
    code = phaseAsyncQuery(pWrapper);
901,477,039✔
2060
  }
2061

2062
  if (TSDB_CODE_SUCCESS != code) {
914,757,709✔
2063
    if (NULL != pRequest->msgBuf && strlen(pRequest->msgBuf) > 0) {
13,302,149✔
2064
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, pRequest->msgBuf,
13,233,954✔
2065
               pRequest->requestId);
2066
    } else {
2067
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
68,195✔
2068
               pRequest->requestId);
2069
    }
2070

2071
    destorySqlCallbackWrapper(pWrapper);
13,302,219✔
2072
    pRequest->pWrapper = NULL;
13,302,235✔
2073
    qDestroyQuery(pRequest->pQuery);
13,302,235✔
2074
    pRequest->pQuery = NULL;
13,302,235✔
2075

2076
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
13,302,235✔
2077
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
12,392✔
2078
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
2079
      code = refreshMeta(pRequest->pTscObj, pRequest);
12,392✔
2080
      if (code != 0) {
12,392✔
2081
        tscWarn("req:0x%" PRIx64 ", refresh meta failed, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code,
12,392✔
2082
                tstrerror(code), pRequest->requestId);
2083
      }
2084
      pRequest->prevCode = code;
12,392✔
2085
      doAsyncQuery(pRequest, true);
12,392✔
2086
      return;
12,392✔
2087
    }
2088

2089
    terrno = code;
13,289,843✔
2090
    pRequest->code = code;
13,289,519✔
2091
    doRequestCallback(pRequest, code);
13,289,519✔
2092
  }
2093
}
2094

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

2127
typedef struct SAsyncFetchParam {
2128
  SRequestObj      *pReq;
2129
  __taos_async_fn_t fp;
2130
  void             *param;
2131
} SAsyncFetchParam;
2132

2133
static int32_t doAsyncFetch(void *pParam) {
283,171,861✔
2134
  SAsyncFetchParam *param = pParam;
283,171,861✔
2135
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
283,171,861✔
2136
  taosMemoryFree(param);
283,171,799✔
2137
  return TSDB_CODE_SUCCESS;
283,171,857✔
2138
}
2139

2140
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
283,209,200✔
2141
  if (res == NULL || fp == NULL) {
283,209,200✔
UNCOV
2142
    tscError("taos_fetch_rows_a invalid paras");
×
2143
    return;
×
2144
  }
2145
  if (!TD_RES_QUERY(res)) {
283,209,200✔
2146
    tscError("taos_fetch_rows_a res is NULL");
×
2147
    fp(param, res, TSDB_CODE_APP_ERROR);
×
2148
    return;
×
2149
  }
2150

2151
  SRequestObj *pRequest = res;
283,209,200✔
2152
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
283,209,200✔
2153
    fp(param, res, 0);
37,347✔
2154
    return;
37,347✔
2155
  }
2156

2157
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
283,171,853✔
2158
  if (!pParam) {
283,171,853✔
2159
    fp(param, res, terrno);
×
2160
    return;
×
2161
  }
2162
  pParam->pReq = pRequest;
283,171,853✔
2163
  pParam->fp = fp;
283,171,853✔
2164
  pParam->param = param;
283,171,853✔
2165
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
283,171,857✔
2166
  if (TSDB_CODE_SUCCESS != code) {
283,171,354✔
2167
    taosMemoryFree(pParam);
×
2168
    fp(param, res, code);
×
2169
    return;
×
2170
  }
2171
}
2172

2173
void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
513✔
2174
  if (res == NULL || fp == NULL) {
513✔
2175
    tscError("taos_fetch_raw_block_a invalid paras");
×
2176
    return;
×
2177
  }
2178
  if (!TD_RES_QUERY(res)) {
513✔
2179
    tscError("taos_fetch_raw_block_a res is NULL");
×
2180
    return;
×
2181
  }
2182
  SRequestObj    *pRequest = res;
513✔
2183
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
513✔
2184

2185
  // set the current block is all consumed
2186
  pResultInfo->convertUcs4 = false;
513✔
2187

2188
  // it is a local executed query, no need to do async fetch
2189
  taos_fetch_rows_a(pRequest, fp, param);
513✔
2190
}
2191

2192
const void *taos_get_raw_block(TAOS_RES *res) {
86✔
2193
  if (res == NULL) {
86✔
2194
    tscError("taos_get_raw_block invalid paras");
×
2195
    return NULL;
×
2196
  }
2197
  if (!TD_RES_QUERY(res)) {
86✔
2198
    tscError("taos_get_raw_block res is NULL");
×
2199
    return NULL;
×
2200
  }
2201
  SRequestObj *pRequest = res;
86✔
2202

2203
  return pRequest->body.resInfo.pData;
86✔
2204
}
2205

2206
int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInfo) {
×
2207
  if (NULL == taos) {
×
2208
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2209
    return terrno;
×
2210
  }
2211

2212
  if (NULL == db || NULL == dbInfo) {
×
2213
    tscError("invalid input param, db:%p, dbInfo:%p", db, dbInfo);
×
2214
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2215
    return terrno;
×
2216
  }
2217

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

2227
  STscObj  *pTscObj = pRequest->pTscObj;
×
2228
  SCatalog *pCtg = NULL;
×
2229
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2230
  if (code != TSDB_CODE_SUCCESS) {
×
2231
    goto _return;
×
2232
  }
2233

2234
  SRequestConnInfo conn = {
×
2235
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2236

2237
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2238

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

2242
  code = catalogGetDBVgInfo(pCtg, &conn, dbFName, dbInfo);
×
2243
  if (code) {
×
2244
    goto _return;
×
2245
  }
2246

2247
_return:
×
2248

2249
  terrno = code;
×
2250

2251
  destroyRequest(pRequest);
×
2252
  return code;
×
2253
}
2254

2255
int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId) {
×
2256
  if (NULL == taos) {
×
2257
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2258
    return terrno;
×
2259
  }
2260

2261
  if (NULL == db || NULL == table || NULL == vgId) {
×
2262
    tscError("invalid input param, db:%p, table:%p, vgId:%p", db, table, vgId);
×
2263
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2264
    return terrno;
×
2265
  }
2266

2267
  int64_t      connId = *(int64_t *)taos;
×
2268
  SRequestObj *pRequest = NULL;
×
2269
  char        *sql = "taos_get_table_vgId";
×
2270
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2271
  if (code != TSDB_CODE_SUCCESS) {
×
2272
    return terrno;
×
2273
  }
2274

2275
  pRequest->syncQuery = true;
×
2276

2277
  STscObj  *pTscObj = pRequest->pTscObj;
×
2278
  SCatalog *pCtg = NULL;
×
2279
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2280
  if (code != TSDB_CODE_SUCCESS) {
×
2281
    goto _return;
×
2282
  }
2283

2284
  SRequestConnInfo conn = {
×
2285
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2286

2287
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2288

2289
  SName tableName = {0};
×
2290
  toName(pTscObj->acctId, db, table, &tableName);
×
2291

2292
  SVgroupInfo vgInfo;
×
2293
  code = catalogGetTableHashVgroup(pCtg, &conn, &tableName, &vgInfo);
×
2294
  if (code) {
×
2295
    goto _return;
×
2296
  }
2297

2298
  *vgId = vgInfo.vgId;
×
2299

2300
_return:
×
2301

2302
  terrno = code;
×
2303

2304
  destroyRequest(pRequest);
×
2305
  return code;
×
2306
}
2307

2308
int taos_get_tables_vgId(TAOS *taos, const char *db, const char *table[], int tableNum, int *vgId) {
×
2309
  if (NULL == taos) {
×
2310
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2311
    return terrno;
×
2312
  }
2313

2314
  if (NULL == db || NULL == table || NULL == vgId || tableNum <= 0) {
×
2315
    tscError("invalid input param, db:%p, table:%p, vgId:%p, tbNum:%d", db, table, vgId, tableNum);
×
2316
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2317
    return terrno;
×
2318
  }
2319

2320
  int64_t      connId = *(int64_t *)taos;
×
2321
  SRequestObj *pRequest = NULL;
×
2322
  char        *sql = "taos_get_table_vgId";
×
2323
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
2324
  if (code != TSDB_CODE_SUCCESS) {
×
2325
    return terrno;
×
2326
  }
2327

2328
  pRequest->syncQuery = true;
×
2329

2330
  STscObj  *pTscObj = pRequest->pTscObj;
×
2331
  SCatalog *pCtg = NULL;
×
2332
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2333
  if (code != TSDB_CODE_SUCCESS) {
×
2334
    goto _return;
×
2335
  }
2336

2337
  SRequestConnInfo conn = {
×
2338
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2339

2340
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2341

2342
  code = catalogGetTablesHashVgId(pCtg, &conn, pTscObj->acctId, db, table, tableNum, vgId);
×
2343
  if (code) {
×
2344
    goto _return;
×
2345
  }
2346

2347
_return:
×
2348

2349
  terrno = code;
×
2350

2351
  destroyRequest(pRequest);
×
2352
  return code;
×
2353
}
2354

2355
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
1,184✔
2356
  if (NULL == taos) {
1,184✔
2357
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2358
    return terrno;
×
2359
  }
2360

2361
  int64_t       connId = *(int64_t *)taos;
1,184✔
2362
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
1,184✔
2363
  int32_t       code = 0;
1,184✔
2364
  SRequestObj  *pRequest = NULL;
1,184✔
2365
  SCatalogReq   catalogReq = {0};
1,184✔
2366

2367
  if (NULL == tableNameList) {
1,184✔
2368
    return TSDB_CODE_SUCCESS;
×
2369
  }
2370

2371
  int32_t length = (int32_t)strlen(tableNameList);
1,184✔
2372
  if (0 == length) {
1,184✔
2373
    return TSDB_CODE_SUCCESS;
×
2374
  } else if (length > MAX_TABLE_NAME_LENGTH) {
1,184✔
2375
    tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH);
×
2376
    return TSDB_CODE_TSC_INVALID_OPERATION;
×
2377
  }
2378

2379
  char *sql = "taos_load_table_info";
1,184✔
2380
  code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
1,184✔
2381
  if (code != TSDB_CODE_SUCCESS) {
1,184✔
2382
    terrno = code;
×
2383
    goto _return;
×
2384
  }
2385

2386
  pRequest->syncQuery = true;
1,184✔
2387

2388
  STscObj *pTscObj = pRequest->pTscObj;
1,184✔
2389
  code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
1,184✔
2390
  if (code) {
1,184✔
2391
    goto _return;
×
2392
  }
2393

2394
  SCatalog *pCtg = NULL;
1,184✔
2395
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
1,184✔
2396
  if (code != TSDB_CODE_SUCCESS) {
1,184✔
2397
    goto _return;
×
2398
  }
2399

2400
  SRequestConnInfo conn = {
1,184✔
2401
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
1,184✔
2402

2403
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
1,184✔
2404

2405
  code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, pRequest->body.interParam, NULL);
1,184✔
2406
  if (code) {
1,184✔
2407
    goto _return;
×
2408
  }
2409

2410
  SSyncQueryParam *pParam = pRequest->body.interParam;
1,184✔
2411
  code = tsem_wait(&pParam->sem);
1,184✔
2412
  if (code) {
1,184✔
2413
    tscError("tsem wait failed, code:%d - %s", code, tstrerror(code));
×
2414
    goto _return;
×
2415
  }
2416
_return:
1,184✔
2417
  destoryCatalogReq(&catalogReq);
1,184✔
2418
  destroyRequest(pRequest);
1,184✔
2419
  return code;
1,184✔
2420
}
2421

2422
TAOS_STMT *taos_stmt_init(TAOS *taos) {
21,487✔
2423
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
21,487✔
2424
  if (NULL == pObj) {
21,487✔
2425
    tscError("invalid parameter for %s", __FUNCTION__);
×
2426
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2427
    return NULL;
×
2428
  }
2429

2430
  TAOS_STMT *pStmt = stmtInit(pObj, 0, NULL);
21,487✔
2431
  if (NULL == pStmt) {
21,487✔
2432
    tscError("stmt init failed, errcode:%s", terrstr());
×
2433
  }
2434
  releaseTscObj(*(int64_t *)taos);
21,487✔
2435

2436
  return pStmt;
21,487✔
2437
}
2438

2439
TAOS_STMT *taos_stmt_init_with_reqid(TAOS *taos, int64_t reqid) {
×
2440
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
2441
  if (NULL == pObj) {
×
2442
    tscError("invalid parameter for %s", __FUNCTION__);
×
2443
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2444
    return NULL;
×
2445
  }
2446

2447
  TAOS_STMT *pStmt = stmtInit(pObj, reqid, NULL);
×
2448
  if (NULL == pStmt) {
×
2449
    tscError("stmt init failed, errcode:%s", terrstr());
×
2450
  }
2451
  releaseTscObj(*(int64_t *)taos);
×
2452

2453
  return pStmt;
×
2454
}
2455

2456
TAOS_STMT *taos_stmt_init_with_options(TAOS *taos, TAOS_STMT_OPTIONS *options) {
11,936✔
2457
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
11,936✔
2458
  if (NULL == pObj) {
11,936✔
2459
    tscError("invalid parameter for %s", __FUNCTION__);
×
2460
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2461
    return NULL;
×
2462
  }
2463

2464
  TAOS_STMT *pStmt = stmtInit(pObj, options->reqId, options);
11,936✔
2465
  if (NULL == pStmt) {
11,936✔
2466
    tscError("stmt init failed, errcode:%s", terrstr());
×
2467
  }
2468
  releaseTscObj(*(int64_t *)taos);
11,936✔
2469

2470
  return pStmt;
11,936✔
2471
}
2472

2473
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
6,701,887✔
2474
  if (stmt == NULL || sql == NULL) {
6,701,887✔
2475
    tscError("NULL parameter for %s", __FUNCTION__);
×
2476
    terrno = TSDB_CODE_INVALID_PARA;
×
2477
    return terrno;
×
2478
  }
2479

2480
  return stmtPrepare(stmt, sql, length);
6,703,229✔
2481
}
2482

2483
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
6,603✔
2484
  if (stmt == NULL || name == NULL) {
6,603✔
2485
    tscError("NULL parameter for %s", __FUNCTION__);
×
2486
    terrno = TSDB_CODE_INVALID_PARA;
×
2487
    return terrno;
×
2488
  }
2489

2490
  int32_t code = stmtSetTbName(stmt, name);
6,603✔
2491
  if (code) {
6,603✔
2492
    return code;
592✔
2493
  }
2494

2495
  if (tags) {
6,011✔
2496
    return stmtSetTbTags(stmt, tags);
6,011✔
2497
  }
2498

2499
  return TSDB_CODE_SUCCESS;
×
2500
}
2501

2502
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
8,275,581✔
2503
  if (stmt == NULL || name == NULL) {
8,275,581✔
2504
    tscError("NULL parameter for %s", __FUNCTION__);
22✔
2505
    terrno = TSDB_CODE_INVALID_PARA;
22✔
2506
    return terrno;
×
2507
  }
2508

2509
  return stmtSetTbName(stmt, name);
8,277,496✔
2510
}
2511

2512
int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) {
539✔
2513
  if (stmt == NULL || tags == NULL) {
539✔
2514
    tscError("NULL parameter for %s", __FUNCTION__);
×
2515
    terrno = TSDB_CODE_INVALID_PARA;
×
2516
    return terrno;
×
2517
  }
2518

2519
  return stmtSetTbTags(stmt, tags);
539✔
2520
}
2521

2522
int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); }
192✔
2523

2524
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
384✔
2525
  if (stmt == NULL || NULL == fieldNum) {
384✔
2526
    tscError("NULL parameter for %s", __FUNCTION__);
×
2527
    terrno = TSDB_CODE_INVALID_PARA;
×
2528
    return terrno;
×
2529
  }
2530

2531
  return stmtGetTagFields(stmt, fieldNum, fields);
384✔
2532
}
2533

2534
int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
576✔
2535
  if (stmt == NULL || NULL == fieldNum) {
576✔
2536
    tscError("NULL parameter for %s", __FUNCTION__);
×
2537
    terrno = TSDB_CODE_INVALID_PARA;
×
2538
    return terrno;
×
2539
  }
2540

2541
  return stmtGetColFields(stmt, fieldNum, fields);
576✔
2542
}
2543

2544
// let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields`
2545
void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) {
×
2546
  (void)stmt;
2547
  if (!fields) return;
×
2548
  taosMemoryFree(fields);
×
2549
}
2550

2551
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
35,460✔
2552
  if (stmt == NULL || bind == NULL) {
35,460✔
2553
    tscError("NULL parameter for %s", __FUNCTION__);
×
2554
    terrno = TSDB_CODE_INVALID_PARA;
×
2555
    return terrno;
×
2556
  }
2557

2558
  if (bind->num > 1) {
35,460✔
2559
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
3,840✔
2560
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
3,840✔
2561
    return terrno;
3,840✔
2562
  }
2563

2564
  return stmtBindBatch(stmt, bind, -1);
31,620✔
2565
}
2566

2567
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
8,272,685✔
2568
  if (stmt == NULL || bind == NULL) {
8,272,685✔
UNCOV
2569
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2570
    terrno = TSDB_CODE_INVALID_PARA;
×
2571
    return terrno;
×
2572
  }
2573

2574
  if (bind->num <= 0 || bind->num > INT16_MAX) {
8,274,377✔
2575
    tscError("invalid bind num %d", bind->num);
5,110✔
2576
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
5,110✔
2577
    return terrno;
×
2578
  }
2579

2580
  int32_t insert = 0;
8,270,644✔
2581
  int32_t code = stmtIsInsert(stmt, &insert);
8,271,647✔
2582
  if (TSDB_CODE_SUCCESS != code) {
8,270,024✔
2583
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2584
    return code;
×
2585
  }
2586
  if (0 == insert && bind->num > 1) {
8,270,024✔
2587
    tscError("only one row data allowed for query");
×
2588
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2589
    return terrno;
×
2590
  }
2591

2592
  return stmtBindBatch(stmt, bind, -1);
8,270,024✔
2593
}
2594

2595
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
700✔
2596
  if (stmt == NULL || bind == NULL) {
700✔
2597
    tscError("NULL parameter for %s", __FUNCTION__);
×
2598
    terrno = TSDB_CODE_INVALID_PARA;
×
2599
    return terrno;
×
2600
  }
2601

2602
  if (colIdx < 0) {
700✔
2603
    tscError("invalid bind column idx %d", colIdx);
×
2604
    terrno = TSDB_CODE_INVALID_PARA;
×
2605
    return terrno;
×
2606
  }
2607

2608
  int32_t insert = 0;
700✔
2609
  int32_t code = stmtIsInsert(stmt, &insert);
700✔
2610
  if (TSDB_CODE_SUCCESS != code) {
700✔
2611
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2612
    return code;
×
2613
  }
2614
  if (0 == insert && bind->num > 1) {
700✔
2615
    tscError("only one row data allowed for query");
×
2616
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2617
    return terrno;
×
2618
  }
2619

2620
  return stmtBindBatch(stmt, bind, colIdx);
700✔
2621
}
2622

2623
int taos_stmt_add_batch(TAOS_STMT *stmt) {
6,948,543✔
2624
  if (stmt == NULL) {
6,948,543✔
2625
    tscError("NULL parameter for %s", __FUNCTION__);
×
2626
    terrno = TSDB_CODE_INVALID_PARA;
×
2627
    return terrno;
×
2628
  }
2629

2630
  return stmtAddBatch(stmt);
6,948,543✔
2631
}
2632

2633
int taos_stmt_execute(TAOS_STMT *stmt) {
6,942,452✔
2634
  if (stmt == NULL) {
6,942,452✔
2635
    tscError("NULL parameter for %s", __FUNCTION__);
×
2636
    terrno = TSDB_CODE_INVALID_PARA;
×
2637
    return terrno;
×
2638
  }
2639

2640
  return stmtExec(stmt);
6,942,452✔
2641
}
2642

2643
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
×
2644
  if (stmt == NULL || insert == NULL) {
×
2645
    tscError("NULL parameter for %s", __FUNCTION__);
×
2646
    terrno = TSDB_CODE_INVALID_PARA;
×
2647
    return terrno;
×
2648
  }
2649

2650
  return stmtIsInsert(stmt, insert);
×
2651
}
2652

2653
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
×
2654
  if (stmt == NULL || nums == NULL) {
×
2655
    tscError("NULL parameter for %s", __FUNCTION__);
×
2656
    terrno = TSDB_CODE_INVALID_PARA;
×
2657
    return terrno;
×
2658
  }
2659

2660
  return stmtGetParamNum(stmt, nums);
×
2661
}
2662

2663
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
384✔
2664
  if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) {
384✔
2665
    tscError("invalid parameter for %s", __FUNCTION__);
×
2666
    terrno = TSDB_CODE_INVALID_PARA;
×
2667
    return terrno;
×
2668
  }
2669

2670
  return stmtGetParam(stmt, idx, type, bytes);
384✔
2671
}
2672

2673
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
9,487✔
2674
  if (stmt == NULL) {
9,487✔
2675
    tscError("NULL parameter for %s", __FUNCTION__);
×
2676
    terrno = TSDB_CODE_INVALID_PARA;
×
2677
    return NULL;
×
2678
  }
2679

2680
  return stmtUseResult(stmt);
9,487✔
2681
}
2682

2683
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
10,821✔
2684

2685
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
3,101✔
2686
  if (stmt == NULL) {
3,101✔
2687
    tscError("NULL parameter for %s", __FUNCTION__);
×
2688
    terrno = TSDB_CODE_INVALID_PARA;
×
2689
    return 0;
×
2690
  }
2691

2692
  return stmtAffectedRows(stmt);
3,101✔
2693
}
2694

2695
int taos_stmt_affected_rows_once(TAOS_STMT *stmt) {
2,768✔
2696
  if (stmt == NULL) {
2,768✔
2697
    tscError("NULL parameter for %s", __FUNCTION__);
×
2698
    terrno = TSDB_CODE_INVALID_PARA;
×
2699
    return 0;
×
2700
  }
2701

2702
  return stmtAffectedRowsOnce(stmt);
2,768✔
2703
}
2704

2705
int taos_stmt_close(TAOS_STMT *stmt) {
33,423✔
2706
  if (stmt == NULL) {
33,423✔
2707
    tscError("NULL parameter for %s", __FUNCTION__);
×
2708
    terrno = TSDB_CODE_INVALID_PARA;
×
2709
    return terrno;
×
2710
  }
2711

2712
  return stmtClose(stmt);
33,423✔
2713
}
2714

2715
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
115,259✔
2716
  if (NULL == taos) {
115,259✔
2717
    tscError("NULL parameter for %s", __FUNCTION__);
96✔
2718
    terrno = TSDB_CODE_INVALID_PARA;
96✔
2719
    return NULL;
96✔
2720
  }
2721
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
115,163✔
2722
  if (NULL == pObj) {
115,272✔
2723
    tscError("invalid parameter for %s", __FUNCTION__);
×
2724
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2725
    return NULL;
×
2726
  }
2727

2728
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
115,272✔
2729

2730
  releaseTscObj(*(int64_t *)taos);
115,300✔
2731

2732
  return pStmt;
115,300✔
2733
}
2734

2735
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
118,586✔
2736
  if (stmt == NULL || sql == NULL) {
118,586✔
2737
    tscError("NULL parameter for %s", __FUNCTION__);
96✔
2738
    terrno = TSDB_CODE_INVALID_PARA;
96✔
2739
    return terrno;
96✔
2740
  }
2741

2742
  return stmtPrepare2(stmt, sql, length);
118,490✔
2743
}
2744

2745
int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx) {
36,296,824✔
2746
  if (stmt == NULL) {
36,296,824✔
2747
    tscError("NULL parameter for %s", __FUNCTION__);
×
2748
    terrno = TSDB_CODE_INVALID_PARA;
×
2749
    return terrno;
×
2750
  }
2751

2752
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
36,296,824✔
2753
  int32_t    code = TSDB_CODE_SUCCESS;
36,296,824✔
2754
  STMT2_DLOG_E("start to bind param");
36,296,824✔
2755

2756
  // check query bind number
2757
  bool isQuery = (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt)));
36,265,074✔
2758
  if (isQuery) {
36,426,826✔
2759
    if (bindv->count != 1 || bindv->bind_cols[0]->num != 1) {
3,751✔
2760
      terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2761
      STMT2_ELOG_E("query only support one table and one row bind");
×
2762
      return terrno;
×
2763
    }
2764
  }
2765

2766
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 1) {
36,426,826✔
2767
    STMT2_ELOG_E("async bind param is still working, please try again later");
6,098✔
2768
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
6,098✔
2769
    return terrno;
×
2770
  }
2771

2772
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
36,405,746✔
2773
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
2,208✔
2774
      STMT2_ELOG_E("bind param wait asyncExecSem failed");
×
2775
    }
2776
    pStmt->execSemWaited = true;
2,208✔
2777
  }
2778

2779
  for (int i = 0; i < bindv->count; ++i) {
73,103,052✔
2780
    SVCreateTbReq *pCreateTbReq = NULL;
36,462,101✔
2781
    if (!isQuery) {
36,838,592✔
2782
      STMT2_TLOG("start to bind %dth table", i);
36,838,780✔
2783
      if (bindv->tbnames && bindv->tbnames[i]) {
36,837,526✔
2784
        code = stmtSetTbName2(stmt, bindv->tbnames[i]);
898,141✔
2785
        if (code) {
897,898✔
2786
          terrno = code;
1,056✔
2787
          STMT2_ELOG("set tbname failed, code:%s", stmt2Errstr(stmt));
1,056✔
2788
          return terrno;
1,728✔
2789
        }
2790
      }
2791

2792
      if (bindv->tags && bindv->tags[i]) {
36,983,599✔
2793
        code = stmtSetTbTags2(stmt, bindv->tags[i], &pCreateTbReq);
462,732✔
2794
      } else if (pStmt->bInfo.tbNameFlag & IS_FIXED_TAG) {
36,468,632✔
2795
        code = stmtCheckTags2(stmt, &pCreateTbReq);
90,843✔
2796
      } else if (pStmt->sql.autoCreateTbl) {
36,188,570✔
2797
        code = stmtSetTbTags2(stmt, NULL, &pCreateTbReq);
2,016✔
2798
      }
2799

2800
      if (code) {
37,014,973✔
2801
        terrno = code;
96✔
2802
        STMT2_ELOG("set tags failed, code:%s", stmt2Errstr(stmt));
96✔
2803
        if (pCreateTbReq) {
96✔
2804
          tdDestroySVCreateTbReq(pCreateTbReq);
×
2805
          taosMemoryFreeClear(pCreateTbReq);
×
2806
        }
2807
        return terrno;
96✔
2808
      }
2809
    }
2810

2811
    if (bindv->bind_cols && bindv->bind_cols[i]) {
37,014,689✔
2812
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
37,202,267✔
2813

2814
      if (bind->num <= 0 || bind->num > INT16_MAX) {
37,172,094✔
2815
        STMT2_ELOG("bind num:%d must > 0 and < INT16_MAX", bind->num);
78,866✔
2816
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
78,866✔
2817
        if (pCreateTbReq) {
×
2818
          tdDestroySVCreateTbReq(pCreateTbReq);
×
2819
          taosMemoryFreeClear(pCreateTbReq);
×
2820
        }
2821
        return terrno;
×
2822
      }
2823

2824
      code = stmtBindBatch2(stmt, bind, col_idx, pCreateTbReq);
36,946,438✔
2825
      if (TSDB_CODE_SUCCESS != code) {
35,486,327✔
2826
        terrno = code;
576✔
2827
        STMT2_ELOG("bind batch failed, code:%s", stmt2Errstr(stmt));
576✔
2828
        if (pCreateTbReq) {
576✔
2829
          tdDestroySVCreateTbReq(pCreateTbReq);
192✔
2830
          taosMemoryFreeClear(pCreateTbReq);
192✔
2831
        }
2832
        return terrno;
576✔
2833
      }
2834
    }
2835
  }
2836

2837
  return code;
36,464,122✔
2838
}
2839

2840
int taos_stmt2_bind_param_a(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx, __taos_async_fn_t fp,
×
2841
                            void *param) {
2842
  if (stmt == NULL || bindv == NULL || fp == NULL) {
×
2843
    terrno = TSDB_CODE_INVALID_PARA;
×
2844
    return terrno;
×
2845
  }
2846

2847
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
×
2848

2849
  ThreadArgs *args = (ThreadArgs *)taosMemoryMalloc(sizeof(ThreadArgs));
×
2850
  args->stmt = stmt;
×
2851
  args->bindv = bindv;
×
2852
  args->col_idx = col_idx;
×
2853
  args->fp = fp;
×
2854
  args->param = param;
×
2855

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

2866
  int code_s = taosStmt2AsyncBind(stmtAsyncBindThreadFunc, (void *)args);
×
2867
  if (code_s != TSDB_CODE_SUCCESS) {
×
2868
    terrno = code_s;
×
2869
    (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2870
    (void)taosThreadCondSignal(&(pStmt->asyncBindParam.waitCond));
×
2871
    (void)atomic_sub_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2872
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2873
    tscError("async bind failed, code:%d , %s", code_s, tstrerror(code_s));
×
2874
  }
2875

2876
  return code_s;
×
2877
}
2878

2879
int taos_stmt2_exec(TAOS_STMT2 *stmt, int *affected_rows) {
522,918✔
2880
  if (stmt == NULL) {
522,918✔
2881
    tscError("NULL parameter for %s", __FUNCTION__);
×
2882
    terrno = TSDB_CODE_INVALID_PARA;
×
2883
    return terrno;
×
2884
  }
2885

2886
  return stmtExec2(stmt, affected_rows);
522,918✔
2887
}
2888

2889
int taos_stmt2_close(TAOS_STMT2 *stmt) {
114,820✔
2890
  if (stmt == NULL) {
114,820✔
2891
    tscError("NULL parameter for %s", __FUNCTION__);
×
2892
    terrno = TSDB_CODE_INVALID_PARA;
×
2893
    return terrno;
×
2894
  }
2895

2896
  return stmtClose2(stmt);
114,820✔
2897
}
2898

2899
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
23✔
2900
  if (stmt == NULL || insert == NULL) {
23✔
2901
    tscError("NULL parameter for %s", __FUNCTION__);
×
2902
    terrno = TSDB_CODE_INVALID_PARA;
×
2903
    return terrno;
×
2904
  }
2905
  *insert = stmt2IsInsert(stmt);
23✔
2906
  return TSDB_CODE_SUCCESS;
23✔
2907
}
2908

2909
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
8,848✔
2910
  if (stmt == NULL || count == NULL) {
8,848✔
2911
    tscError("NULL parameter for %s", __FUNCTION__);
96✔
2912
    terrno = TSDB_CODE_INVALID_PARA;
96✔
2913
    return terrno;
96✔
2914
  }
2915

2916
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
8,752✔
2917
  STMT2_DLOG_E("start to get fields");
8,752✔
2918

2919
  if (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type ||
8,752✔
2920
      (pStmt->sql.type == 0 && stmt2IsInsert(stmt))) {
8,080✔
2921
    return stmtGetStbColFields2(stmt, count, fields);
6,832✔
2922
  }
2923
  if (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt))) {
1,920✔
2924
    return stmtGetParamNum2(stmt, count);
1,824✔
2925
  }
2926

2927
  tscError("Invalid sql for stmt %s", pStmt->sql.sqlStr);
96✔
2928
  return TSDB_CODE_PAR_SYNTAX_ERROR;
96✔
2929
}
2930

2931
DLL_EXPORT void taos_stmt2_free_fields(TAOS_STMT2 *stmt, TAOS_FIELD_ALL *fields) {
6,448✔
2932
  (void)stmt;
2933
  if (!fields) return;
6,448✔
2934
  taosMemoryFree(fields);
4,720✔
2935
}
2936

2937
TAOS_RES *taos_stmt2_result(TAOS_STMT2 *stmt) {
3,271✔
2938
  if (stmt == NULL) {
3,271✔
2939
    tscError("NULL parameter for %s", __FUNCTION__);
×
2940
    terrno = TSDB_CODE_INVALID_PARA;
×
2941
    return NULL;
×
2942
  }
2943

2944
  return stmtUseResult2(stmt);
3,271✔
2945
}
2946

2947
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmt2Errstr(stmt); }
2,976✔
2948

2949
int taos_set_conn_mode(TAOS *taos, int mode, int value) {
2,304✔
2950
  int32_t code = 0;
2,304✔
2951
  if (taos == NULL) {
2,304✔
2952
    terrno = TSDB_CODE_INVALID_PARA;
×
2953
    return terrno;
×
2954
  }
2955

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

2974
char *getBuildInfo() { return td_buildinfo; }
×
2975

2976
int32_t taos_connect_is_alive(TAOS *taos) {
×
2977
  int32_t code = 0, lino = 0;
×
2978
  if (taos == NULL) {
×
2979
    terrno = TSDB_CODE_INVALID_PARA;
×
2980
    return terrno;
×
2981
  }
2982

2983
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
2984
  if (NULL == pObj) {
×
2985
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2986
    tscError("invalid parameter for %s", __func__);
×
2987
    return terrno;
×
2988
  }
2989

2990
  code = tscCheckConnSessionMetric(pObj);
×
2991
  TAOS_CHECK_GOTO(code, &lino, _error);
×
2992

2993
_error:
×
2994
  releaseTscObj(*(int64_t *)taos);
×
2995

2996
  if (code != 0) {
×
2997
    tscError("taos conn failed to check alive, code:%d - %s", code, tstrerror(code));
×
2998
  }
2999

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

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

3017
  char *sql = taosMemoryMalloc((size_t)len + 1);
×
3018
  if (sql == NULL) {
×
3019
    return terrno;
×
3020
  }
3021

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

3033
  *ppSql = sql;
×
3034
  if (pLen != NULL) {
×
3035
    *pLen = (uint32_t)len;
×
3036
  }
3037
  return TSDB_CODE_SUCCESS;
×
3038
}
3039

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

3048
  code = buildInstanceRegisterSql(req, &pRequest->sqlstr, (uint32_t *)&pRequest->sqlLen);
×
3049
  if (code != TSDB_CODE_SUCCESS) {
×
3050
    goto _cleanup;
×
3051
  }
3052

3053
  int32_t msgLen = tSerializeSInstanceRegisterReq(NULL, 0, (SInstanceRegisterReq *)req);
×
3054
  if (msgLen <= 0) {
×
3055
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3056
    goto _cleanup;
×
3057
  }
3058

3059
  void *pMsg = taosMemoryMalloc(msgLen);
×
3060
  if (pMsg == NULL) {
×
3061
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3062
    goto _cleanup;
×
3063
  }
3064

3065
  if (tSerializeSInstanceRegisterReq(pMsg, msgLen, (SInstanceRegisterReq *)req) < 0) {
×
3066
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3067
    taosMemoryFree(pMsg);
×
3068
    goto _cleanup;
×
3069
  }
3070

3071
  pRequest->type = TDMT_MND_REGISTER_INSTANCE;
×
3072
  pRequest->body.requestMsg = (SDataBuf){.pData = pMsg, .len = msgLen, .handle = NULL};
×
3073

3074
  SMsgSendInfo *pSend = buildMsgInfoImpl(pRequest);
×
3075
  if (pSend == NULL) {
×
3076
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3077
    taosMemoryFree(pMsg);
×
3078
    pRequest->body.requestMsg.pData = NULL;
×
3079
    goto _cleanup;
×
3080
  }
3081

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

3090
  code = tsem_wait(&pRequest->body.rspSem);
×
3091
  if (code != TSDB_CODE_SUCCESS) {
×
3092
    code = terrno != 0 ? terrno : code;
×
3093
    goto _cleanup;
×
3094
  }
3095

3096
  code = pRequest->code;
×
3097
  terrno = code;
×
3098

3099
_cleanup:
×
3100
  destroyRequest(pRequest);
×
3101
  return code;
×
3102
}
3103

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

3117
int32_t taos_register_instance(const char *id, const char *type, const char *desc, int32_t expire) {
2,660✔
3118
  if (id == NULL || id[0] == 0) {
2,660✔
3119
    return terrno = TSDB_CODE_INVALID_PARA;
×
3120
  }
3121

3122
  // Validate string lengths
3123
  size_t idLen = strlen(id);
2,660✔
3124
  if (idLen >= TSDB_INSTANCE_ID_LEN) {
2,660✔
3125
    tscError("instance id length %zu exceeds limit %d", idLen, TSDB_INSTANCE_ID_LEN - 1);
×
3126
    return terrno = TSDB_CODE_INVALID_PARA;
×
3127
  }
3128

3129
  if (type != NULL && type[0] != 0) {
2,660✔
3130
    size_t typeLen = strlen(type);
1,520✔
3131
    if (typeLen >= TSDB_INSTANCE_TYPE_LEN) {
1,520✔
3132
      tscError("instance type length %zu exceeds limit %d", typeLen, TSDB_INSTANCE_TYPE_LEN - 1);
×
3133
      return terrno = TSDB_CODE_INVALID_PARA;
×
3134
    }
3135
  }
3136

3137
  if (desc != NULL && desc[0] != 0) {
2,660✔
3138
    size_t descLen = strlen(desc);
1,520✔
3139
    if (descLen >= TSDB_INSTANCE_DESC_LEN) {
1,520✔
3140
      tscError("instance desc length %zu exceeds limit %d", descLen, TSDB_INSTANCE_DESC_LEN - 1);
×
3141
      return terrno = TSDB_CODE_INVALID_PARA;
×
3142
    }
3143
  }
3144

3145
  int32_t code = taos_init();
2,660✔
3146
  if (code != TSDB_CODE_SUCCESS) {
2,660✔
3147
    return code;
×
3148
  }
3149

3150
  SConfig *pCfg = taosGetCfg();
2,660✔
3151
  if (pCfg == NULL) {
2,660✔
3152
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3153
  }
3154

3155
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
2,660✔
3156
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
2,660✔
3157
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3158
  }
3159

3160
  SEp firstEp = {0};
2,660✔
3161
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
2,660✔
3162
  if (code != TSDB_CODE_SUCCESS) {
2,660✔
3163
    return terrno = code;
×
3164
  }
3165

3166
  void    *clientRpc = NULL;
2,660✔
3167
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
2,660✔
3168
  SRpcMsg  rpcMsg = {0};
2,660✔
3169
  SRpcMsg  rpcRsp = {0};
2,660✔
3170
  SRpcInit rpcInit = {0};
2,660✔
3171

3172
  rpcInit.label = "INST";
2,660✔
3173
  rpcInit.numOfThreads = 1;
2,660✔
3174
  rpcInit.cfp = NULL;
2,660✔
3175
  rpcInit.sessions = 16;
2,660✔
3176
  rpcInit.connType = TAOS_CONN_CLIENT;
2,660✔
3177
  rpcInit.idleTime = tsShellActivityTimer * 1000;
2,660✔
3178
  rpcInit.compressSize = tsCompressMsgSize;
2,660✔
3179
  rpcInit.user = TSDB_DEFAULT_USER;
2,660✔
3180

3181
  rpcInit.rfp = instanceRegisterRpcRfp;
2,660✔
3182
  rpcInit.retryMinInterval = tsRedirectPeriod;
2,660✔
3183
  rpcInit.retryStepFactor = tsRedirectFactor;
2,660✔
3184
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
2,660✔
3185
  rpcInit.retryMaxTimeout =
2,660✔
3186
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3187

3188
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
2,660✔
3189
  connLimitNum = TMAX(connLimitNum, 10);
2,660✔
3190
  connLimitNum = TMIN(connLimitNum, 500);
2,660✔
3191
  rpcInit.connLimitNum = connLimitNum;
2,660✔
3192
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
2,660✔
3193
  rpcInit.readTimeout = tsReadTimeout;
2,660✔
3194
  rpcInit.ipv6 = tsEnableIpv6;
2,660✔
3195
  rpcInit.enableSSL = tsEnableTLS;
2,660✔
3196

3197
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
2,660✔
3198
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
2,660✔
3199
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
2,660✔
3200
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
2,660✔
3201
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
2,660✔
3202

3203
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
2,660✔
3204
  if (code != TSDB_CODE_SUCCESS) {
2,660✔
3205
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
3206
    return code;
×
3207
  }
3208

3209
  clientRpc = rpcOpen(&rpcInit);
2,660✔
3210
  if (clientRpc == NULL) {
2,660✔
3211
    code = terrno;
×
3212
    tscError("failed to init instance register client since %s", tstrerror(code));
×
3213
    return code;
×
3214
  }
3215

3216
  // Prepare epSet
3217
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
2,660✔
3218
  epSet.eps[0].port = firstEp.port;
2,660✔
3219

3220
  // Prepare request
3221
  SInstanceRegisterReq req = {0};
2,660✔
3222
  tstrncpy(req.id, id, sizeof(req.id));
2,660✔
3223
  if (type != NULL && type[0] != 0) {
2,660✔
3224
    tstrncpy(req.type, type, sizeof(req.type));
1,520✔
3225
  }
3226
  if (desc != NULL && desc[0] != 0) {
2,660✔
3227
    tstrncpy(req.desc, desc, sizeof(req.desc));
1,520✔
3228
  }
3229
  req.expire = expire;
2,660✔
3230

3231
  int32_t contLen = tSerializeSInstanceRegisterReq(NULL, 0, &req);
2,660✔
3232
  if (contLen <= 0) {
2,660✔
3233
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3234
    rpcClose(clientRpc);
×
3235
    return code;
×
3236
  }
3237

3238
  void *pCont = rpcMallocCont(contLen);
2,660✔
3239
  if (pCont == NULL) {
2,660✔
3240
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3241
    rpcClose(clientRpc);
×
3242
    return code;
×
3243
  }
3244

3245
  if (tSerializeSInstanceRegisterReq(pCont, contLen, &req) < 0) {
2,660✔
3246
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3247
    rpcFreeCont(pCont);
×
3248
    rpcClose(clientRpc);
×
3249
    return code;
×
3250
  }
3251

3252
  rpcMsg.pCont = pCont;
2,660✔
3253
  rpcMsg.contLen = contLen;
2,660✔
3254
  rpcMsg.msgType = TDMT_MND_REGISTER_INSTANCE;
2,660✔
3255
  rpcMsg.info.ahandle = (void *)0x9528;  // Different magic number from server status
2,660✔
3256
  rpcMsg.info.notFreeAhandle = 1;
2,660✔
3257

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

3267
  if (rpcRsp.code != 0) {
2,660✔
3268
    code = rpcRsp.code;
×
3269
    tscError("instance register failed, code:%s", tstrerror(code));
×
3270
  } else {
3271
    code = TSDB_CODE_SUCCESS;
2,660✔
3272
  }
3273

3274
  if (rpcRsp.pCont != NULL) {
2,660✔
3275
    rpcFreeCont(rpcRsp.pCont);
2,660✔
3276
  }
3277
  rpcClose(clientRpc);
2,660✔
3278

3279
  terrno = code;
2,660✔
3280
  return code;
2,660✔
3281
}
3282

3283
int32_t taos_list_instances(const char *filter_type, char ***pList, int32_t *pCount) {
2,090✔
3284
  if (pList == NULL || pCount == NULL) {
2,090✔
3285
    return TSDB_CODE_INVALID_PARA;
×
3286
  }
3287

3288
  int32_t code = taos_init();
2,090✔
3289
  if (code != TSDB_CODE_SUCCESS) {
2,090✔
3290
    terrno = code;
×
3291
    return code;
×
3292
  }
3293

3294
  SConfig *pCfg = taosGetCfg();
2,090✔
3295
  if (pCfg == NULL) {
2,090✔
3296
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3297
    return TSDB_CODE_CFG_NOT_FOUND;
×
3298
  }
3299

3300
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
2,090✔
3301
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
2,090✔
3302
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3303
    return TSDB_CODE_CFG_NOT_FOUND;
×
3304
  }
3305

3306
  SEp firstEp = {0};
2,090✔
3307
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
2,090✔
3308
  if (code != TSDB_CODE_SUCCESS) {
2,090✔
3309
    terrno = code;
×
3310
    return code;
×
3311
  }
3312

3313
  // Initialize RPC connection (similar to taos_register_instance)
3314
  void    *clientRpc = NULL;
2,090✔
3315
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
2,090✔
3316
  SRpcMsg  rpcMsg = {0};
2,090✔
3317
  SRpcMsg  rpcRsp = {0};
2,090✔
3318
  SRpcInit rpcInit = {0};
2,090✔
3319

3320
  rpcInit.label = "LIST";
2,090✔
3321
  rpcInit.numOfThreads = 1;
2,090✔
3322
  rpcInit.cfp = NULL;
2,090✔
3323
  rpcInit.sessions = 16;
2,090✔
3324
  rpcInit.connType = TAOS_CONN_CLIENT;
2,090✔
3325
  rpcInit.idleTime = tsShellActivityTimer * 1000;
2,090✔
3326
  rpcInit.compressSize = tsCompressMsgSize;
2,090✔
3327
  rpcInit.user = TSDB_DEFAULT_USER;
2,090✔
3328

3329
  rpcInit.rfp = instanceRegisterRpcRfp;
2,090✔
3330
  rpcInit.retryMinInterval = tsRedirectPeriod;
2,090✔
3331
  rpcInit.retryStepFactor = tsRedirectFactor;
2,090✔
3332
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
2,090✔
3333
  rpcInit.retryMaxTimeout =
2,090✔
3334
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3335

3336
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
2,090✔
3337
  connLimitNum = TMAX(connLimitNum, 10);
2,090✔
3338
  connLimitNum = TMIN(connLimitNum, 500);
2,090✔
3339
  rpcInit.connLimitNum = connLimitNum;
2,090✔
3340
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
2,090✔
3341
  rpcInit.readTimeout = tsReadTimeout;
2,090✔
3342
  rpcInit.ipv6 = tsEnableIpv6;
2,090✔
3343
  rpcInit.enableSSL = tsEnableTLS;
2,090✔
3344

3345
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
2,090✔
3346
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
2,090✔
3347
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
2,090✔
3348
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
2,090✔
3349
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
2,090✔
3350

3351
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
2,090✔
3352
  if (code != TSDB_CODE_SUCCESS) {
2,090✔
3353
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
3354
    return code;
×
3355
  }
3356

3357
  clientRpc = rpcOpen(&rpcInit);
2,090✔
3358
  if (clientRpc == NULL) {
2,090✔
3359
    code = terrno;
×
3360
    tscError("failed to init instance list client since %s", tstrerror(code));
×
3361
    terrno = code;
×
3362
    return code;
×
3363
  }
3364

3365
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
2,090✔
3366
  epSet.eps[0].port = firstEp.port;
2,090✔
3367
  SInstanceListReq req = {0};
2,090✔
3368
  if (filter_type != NULL && filter_type[0] != 0) {
2,090✔
3369
    tstrncpy(req.filter_type, filter_type, sizeof(req.filter_type));
1,330✔
3370
  }
3371

3372
  // Serialize request to get required length
3373
  int32_t contLen = tSerializeSInstanceListReq(NULL, 0, &req);
2,090✔
3374
  if (contLen <= 0) {
2,090✔
3375
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3376
    rpcClose(clientRpc);
×
3377
    terrno = code;
×
3378
    return code;
×
3379
  }
3380

3381
  // Allocate RPC message buffer (includes message header overhead)
3382
  void *pCont = rpcMallocCont(contLen);
2,090✔
3383
  if (pCont == NULL) {
2,090✔
3384
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3385
    rpcClose(clientRpc);
×
3386
    terrno = code;
×
3387
    return code;
×
3388
  }
3389

3390
  // Serialize request into the content part (after message header)
3391
  if (tSerializeSInstanceListReq(pCont, contLen, &req) < 0) {
2,090✔
3392
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3393
    rpcFreeCont(pCont);
×
3394
    rpcClose(clientRpc);
×
3395
    terrno = code;
×
3396
    return code;
×
3397
  }
3398

3399
  rpcMsg.pCont = pCont;
2,090✔
3400
  rpcMsg.contLen = contLen;
2,090✔
3401
  rpcMsg.msgType = TDMT_MND_LIST_INSTANCES;
2,090✔
3402
  rpcMsg.info.ahandle = (void *)0x9529;  // Different magic number from register
2,090✔
3403
  rpcMsg.info.notFreeAhandle = 1;
2,090✔
3404

3405
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
2,090✔
3406
  if (TSDB_CODE_SUCCESS != code) {
2,090✔
3407
    tscError("failed to send instance list req since %s", tstrerror(code));
×
3408
    rpcFreeCont(pCont);
×
3409
    rpcClose(clientRpc);
×
3410
    terrno = code;
×
3411
    return code;
×
3412
  }
3413

3414
  // Check response - rpcRsp.code contains the result code from mnode
3415
  if (rpcRsp.code != 0) {
2,090✔
3416
    code = rpcRsp.code;
×
3417
    tscError("instance list failed, code:%s", tstrerror(code));
×
3418
    if (rpcRsp.pCont != NULL) {
×
3419
      rpcFreeCont(rpcRsp.pCont);
×
3420
    }
3421
    rpcClose(clientRpc);
×
3422
    terrno = code;
×
3423
    return code;
×
3424
  }
3425

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

3454
  if (rpcRsp.pCont != NULL) {
2,090✔
3455
    rpcFreeCont(rpcRsp.pCont);
2,090✔
3456
  }
3457
  rpcClose(clientRpc);
2,090✔
3458

3459
  return TSDB_CODE_SUCCESS;
2,090✔
3460
}
3461

3462
void taos_free_instances(char ***pList, int32_t count) {
1,520✔
3463
  if (pList == NULL || *pList == NULL || count <= 0) {
1,520✔
3464
    return;
×
3465
  }
3466

3467
  // Free each string in the array
3468
  for (int32_t i = 0; i < count; i++) {
4,750✔
3469
    if ((*pList)[i] != NULL) {
3,230✔
3470
      taosMemoryFree((*pList)[i]);
3,230✔
3471
      (*pList)[i] = NULL;
3,230✔
3472
    }
3473
  }
3474

3475
  // Free the array itself
3476
  taosMemoryFree(*pList);
1,520✔
3477
  *pList = NULL;
1,520✔
3478
}
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