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

taosdata / TDengine / #4988

16 Mar 2026 12:26PM UTC coverage: 75.821% (+1.9%) from 73.883%
#4988

push

travis-ci

web-flow
feat: support secure delete option. (#34591)

274 of 464 new or added lines in 29 files covered. (59.05%)

4404 existing lines in 23 files now uncovered.

337108 of 444611 relevant lines covered (75.82%)

146708292.94 hits per line

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

53.99
/source/client/src/clientMain.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#include "catalog.h"
17
#include "clientInt.h"
18
#include "clientLog.h"
19
#include "clientMonitor.h"
20
#include "clientSession.h"
21
#include "clientStmt.h"
22
#include "clientStmt2.h"
23
#include "functionMgt.h"
24
#include "os.h"
25
#include "query.h"
26
#include "scheduler.h"
27
#include "tcompare.h"
28
#include "tconv.h"
29
#include "tdatablock.h"
30
#include "tglobal.h"
31
#include "tmisce.h"
32
#include "tmsg.h"
33
#include "tref.h"
34
#include "trpc.h"
35
#include "ttime.h"
36
#include "tversion.h"
37
#include "version.h"
38

39
#define TSC_VAR_NOT_RELEASE 1
40
#define TSC_VAR_RELEASED    0
41

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

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

49
int taos_options(TSDB_OPTION option, const void *arg, ...) {
163,750,112✔
50
  if (arg == NULL) {
163,750,112✔
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();
18,826,856✔
58
    }
59
  }
60

61
  int ret = taos_options_imp(option, (const char *)arg);
1,255,072✔
62
  atomic_store_32(&lock, 0);
163,755,994✔
63
  return ret;
163,755,994✔
64
}
65

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

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

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

86
void tzCleanup() {
2,674,120✔
87
  taosHashCleanup(pTimezoneMap);
2,674,120✔
88
  taosHashCleanup(pTimezoneNameMap);
2,674,120✔
89
}
2,674,120✔
90

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

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

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

128
END:
4,374✔
129
  return tz;
7,226✔
130
}
131
#endif
132

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

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

144
  if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION) {
18,336✔
145
    return terrno = TSDB_CODE_INVALID_PARA;
380✔
146
  }
147

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

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

160
  if (option == TSDB_OPTION_CONNECTION_CLEAR) {
17,956✔
161
    val = NULL;
380✔
162
  }
163

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

200
  if (option == TSDB_OPTION_CONNECTION_USER_APP || option == TSDB_OPTION_CONNECTION_CLEAR) {
17,006✔
201
    if (val != NULL) {
2,230✔
202
      tstrncpy(pObj->optionInfo.userApp, val, sizeof(pObj->optionInfo.userApp));
1,470✔
203
    } else {
204
      pObj->optionInfo.userApp[0] = 0;
760✔
205
    }
206
  }
207

208
  if (option == TSDB_OPTION_CONNECTION_CONNECTOR_INFO || option == TSDB_OPTION_CONNECTION_CLEAR) {
17,006✔
209
    if (val != NULL) {
2,230✔
210
      tstrncpy(pObj->optionInfo.cInfo, val, sizeof(pObj->optionInfo.cInfo));
1,470✔
211
    } else {
212
      pObj->optionInfo.cInfo[0] = 0;
760✔
213
    }
214
  }
215

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

238
END:
13,396✔
239
  releaseTscObj(*(int64_t *)taos);
17,956✔
240
  return terrno = code;
17,956✔
241
}
242

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

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

254
  monitorClose();
2,674,120✔
255
  tscStopCrashReport();
2,674,120✔
256

257
  hbMgrCleanUp();
2,674,120✔
258

259
  catalogDestroy();
2,674,120✔
260
  schedulerDestroy();
2,674,120✔
261

262
  fmFuncMgtDestroy();
2,674,120✔
263
  qCleanupKeywordsTable();
2,674,120✔
264

265
#if !defined(WINDOWS) && !defined(TD_ASTRA)
266
  tzCleanup();
2,674,120✔
267
#endif
268
  tmqMgmtClose();
2,674,120✔
269

270
  int32_t id = clientReqRefPool;
2,674,120✔
271
  clientReqRefPool = -1;
2,674,120✔
272
  taosCloseRef(id);
2,674,120✔
273

274
  id = clientConnRefPool;
2,674,120✔
275
  clientConnRefPool = -1;
2,674,120✔
276
  taosCloseRef(id);
2,674,120✔
277

278
  nodesDestroyAllocatorSet();
2,674,120✔
279
  cleanupAppInfo();
2,674,120✔
280
  rpcCleanup();
2,674,120✔
281
  tscDebug("rpc cleanup");
2,674,120✔
282

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

287
  sessMgtDestroy();
2,674,120✔
288

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

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

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

314
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
167,609,982✔
315
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
167,609,982✔
316
  if (user == NULL) {
167,609,818✔
317
    user = TSDB_DEFAULT_USER;
365,010✔
318
  }
319

320
  if (pass == NULL) {
167,609,818✔
321
    pass = TSDB_DEFAULT_PASS;
365,010✔
322
  }
323

324
  STscObj *pObj = NULL;
167,609,818✔
325
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY, &pObj);
167,609,818✔
326
  if (TSDB_CODE_SUCCESS == code) {
167,580,844✔
327
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
167,565,726✔
328
    if (NULL == rid) {
167,576,262✔
329
      tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db);
×
330
      return NULL;
×
331
    }
332
    *rid = pObj->id;
167,576,262✔
333
    return (TAOS *)rid;
167,576,048✔
334
  } else {
335
    terrno = code;
23,972✔
336
  }
337

338
  return NULL;
24,264✔
339
}
340

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

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

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

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

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

379
  const char *charset = NULL;
1,140✔
380
  const char *timezone = NULL;
1,140✔
381
  const char *userIp = NULL;
1,140✔
382
  const char *userApp = NULL;
1,140✔
383
  const char *connectorInfo = NULL;
1,140✔
384

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

395
      if (strcmp(key, "ip") == 0) {
3,230✔
396
        ip = value;
760✔
397
      } else if (strcmp(key, "user") == 0) {
2,470✔
398
        user = value;
190✔
399
      } else if (strcmp(key, "pass") == 0) {
2,280✔
400
        pass = value;
190✔
401
      } else if (strcmp(key, "db") == 0) {
2,090✔
402
        db = value;
190✔
403
      } else if (strcmp(key, "port") == 0) {
1,900✔
404
        port = (uint16_t)atoi(value);
570✔
405
      } else if (strcmp(key, "charset") == 0) {
1,330✔
406
        charset = value;
380✔
407
      } else if (strcmp(key, "timezone") == 0) {
950✔
408
        timezone = value;
190✔
409
      } else if (strcmp(key, "userIp") == 0) {
760✔
410
        userIp = value;
190✔
411
      } else if (strcmp(key, "userApp") == 0) {
570✔
412
        userApp = value;
190✔
413
      } else if (strcmp(key, "connectorInfo") == 0) {
380✔
414
        connectorInfo = value;
190✔
415
      } else {
416
        tscWarn("taos_connect_with unknown option key: %s", key);
190✔
417
      }
418
    }
419
  }
420

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

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

431
  return taos;
760✔
432
}
433

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

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

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

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

496
  releaseTscObj(*(int64_t *)taos);
2,660✔
497
  return 0;
2,660✔
498
}
499

500
typedef struct SFetchWhiteListInfo {
501
  int64_t                     connId;
502
  __taos_async_whitelist_fn_t userCbFn;
503
  void                       *userParam;
504
} SFetchWhiteListInfo;
505

506
int32_t fetchWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
507
  SFetchWhiteListInfo *pInfo = (SFetchWhiteListInfo *)param;
×
508
  TAOS                *taos = &pInfo->connId;
×
509
  if (code != TSDB_CODE_SUCCESS) {
×
510
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
511
    taosMemoryFree(pMsg->pData);
×
512
    taosMemoryFree(pMsg->pEpSet);
×
513
    taosMemoryFree(pInfo);
×
514
    return code;
×
515
  }
516

517
  SGetUserIpWhiteListRsp wlRsp;
×
518
  if (TSDB_CODE_SUCCESS != tDeserializeSGetUserIpWhiteListRsp(pMsg->pData, pMsg->len, &wlRsp)) {
×
519
    taosMemoryFree(pMsg->pData);
×
520
    taosMemoryFree(pMsg->pEpSet);
×
521
    taosMemoryFree(pInfo);
×
522
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
523
    return terrno;
×
524
  }
525

526
  uint64_t *pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(uint64_t));
×
527
  if (pWhiteLists == NULL) {
×
528
    taosMemoryFree(pMsg->pData);
×
529
    taosMemoryFree(pMsg->pEpSet);
×
530
    taosMemoryFree(pInfo);
×
531
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
532
    return terrno;
×
533
  }
534

535
  for (int i = 0; i < wlRsp.numWhiteLists; ++i) {
×
536
    pWhiteLists[i] = ((uint64_t)wlRsp.pWhiteLists[i].mask << 32) | wlRsp.pWhiteLists[i].ip;
×
537
  }
538

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

541
  taosMemoryFree(pWhiteLists);
×
542
  taosMemoryFree(pMsg->pData);
×
543
  taosMemoryFree(pMsg->pEpSet);
×
544
  taosMemoryFree(pInfo);
×
545
  tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
546
  return code;
×
547
}
548

549
void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *param) {
×
550
  if (NULL == taos) {
×
551
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
552
    return;
×
553
  }
554

555
  int64_t connId = *(int64_t *)taos;
×
556

557
  STscObj *pTsc = acquireTscObj(connId);
×
558
  if (NULL == pTsc) {
×
559
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
560
    return;
×
561
  }
562

563
  SGetUserWhiteListReq req;
×
564
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
565
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
566
  if (msgLen < 0) {
×
567
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
568
    releaseTscObj(connId);
×
569
    return;
×
570
  }
571

572
  void *pReq = taosMemoryMalloc(msgLen);
×
573
  if (pReq == NULL) {
×
574
    fp(param, terrno, taos, 0, NULL);
×
575
    releaseTscObj(connId);
×
576
    return;
×
577
  }
578

579
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
580
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
581
    taosMemoryFree(pReq);
×
582
    releaseTscObj(connId);
×
583
    return;
×
584
  }
585

586
  SFetchWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchWhiteListInfo));
×
587
  if (pParam == NULL) {
×
588
    fp(param, terrno, taos, 0, NULL);
×
589
    taosMemoryFree(pReq);
×
590
    releaseTscObj(connId);
×
591
    return;
×
592
  }
593

594
  pParam->connId = connId;
×
595
  pParam->userCbFn = fp;
×
596

597
  pParam->userParam = param;
×
598
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
599
  if (pSendInfo == NULL) {
×
600
    fp(param, terrno, taos, 0, NULL);
×
601
    taosMemoryFree(pParam);
×
602
    taosMemoryFree(pReq);
×
603
    releaseTscObj(connId);
×
604
    return;
×
605
  }
606

607
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
608
  pSendInfo->requestId = generateRequestId();
×
609
  pSendInfo->requestObjRefId = 0;
×
610
  pSendInfo->param = pParam;
×
611
  pSendInfo->fp = fetchWhiteListCallbackFn;
×
612
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST;
×
613

614
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
615
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
616
    tscWarn("failed to async send msg to server");
×
617
  }
618
  releaseTscObj(connId);
×
619
  return;
×
620
}
621

622
typedef struct SFetchIpWhiteListInfo {
623
  int64_t connId;
624
  bool    supportNeg;
625
  void   *userParam;
626

627
  __taos_async_ip_whitelist_fn_t userCbFn;
628
} SFetchIpWhiteListInfo;
629

630
int32_t fetchIpWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
631
  int32_t lino = 0;
×
632
  char  **pWhiteLists = NULL;
×
633

634
  SGetUserIpWhiteListRsp wlRsp = {0};
×
635

636
  SFetchIpWhiteListInfo *pInfo = (SFetchIpWhiteListInfo *)param;
×
637
  TAOS                  *taos = &pInfo->connId;
×
638

639
  if (code != TSDB_CODE_SUCCESS) {
×
640
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
641
    TAOS_CHECK_GOTO(code, &lino, _error);
×
642
  }
643

644
  if ((code = tDeserializeSGetUserIpWhiteListDualRsp(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
645
    TAOS_CHECK_GOTO(code, &lino, _error);
×
646
  }
647

648
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
649
  if (pWhiteLists == NULL) {
×
650
    code = terrno;
×
651
    TAOS_CHECK_GOTO(code, &lino, _error);
×
652
  }
653

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

662
    code = tIpUintToStr(pIpRange, &ipAddr);
×
663
    TAOS_CHECK_GOTO(code, &lino, _error);
×
664

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

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

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

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

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

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

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

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

748
  pParam->connId = connId;
×
749
  pParam->supportNeg = supportNeg;
×
750
  pParam->userCbFn = fp;
×
751
  pParam->userParam = param;
×
752

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

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

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

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

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

785
typedef struct SFetchDateTimeWhiteListInfo {
786
  int64_t                              connId;
787
  void                                *userParam;
788
  __taos_async_datetime_whitelist_fn_t userCbFn;
789
} SFetchDateTimeWhiteListInfo;
790

791
static const char *weekdays[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
792
int32_t            fetchDateTimeWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
793
  int32_t lino = 0;
×
794
  char  **pWhiteLists = NULL;
×
795

796
  SUserDateTimeWhiteList wlRsp = {0};
×
797

798
  SFetchDateTimeWhiteListInfo *pInfo = (SFetchDateTimeWhiteListInfo *)param;
×
799
  TAOS                        *taos = &pInfo->connId;
×
800

801
  if (code != TSDB_CODE_SUCCESS) {
×
802
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
803
    TAOS_CHECK_GOTO(code, &lino, _error);
×
804
  }
805

806
  if ((code = tDeserializeSUserDateTimeWhiteList(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
807
    TAOS_CHECK_GOTO(code, &lino, _error);
×
808
  }
809

810
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
811
  if (pWhiteLists == NULL) {
×
812
    code = terrno;
×
813
    TAOS_CHECK_GOTO(code, &lino, _error);
×
814
  }
815

816
  int32_t numWhiteLists = 0;
×
817
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
818
    SDateTimeWhiteListItem *item = &wlRsp.pWhiteLists[i];
×
819

820
    char *p = taosMemCalloc(1, 128);
×
821
    if (p == NULL) {
×
822
      code = terrno;
×
823
      TAOS_CHECK_GOTO(code, &lino, _error);
×
824
    }
825

826
    int duration = item->duration / 60;
×
827

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

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

857
void taos_fetch_datetime_whitelist_a(TAOS *taos, __taos_async_datetime_whitelist_fn_t fp, void *param) {
×
858
  if (NULL == taos) {
×
859
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
860
    return;
×
861
  }
862
  int64_t connId = *(int64_t *)taos;
×
863

864
  STscObj *pTsc = acquireTscObj(connId);
×
865
  if (NULL == pTsc) {
×
866
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
867
    return;
×
868
  }
869

870
  SGetUserWhiteListReq req;
×
871
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
872
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
873
  if (msgLen < 0) {
×
874
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
875
    releaseTscObj(connId);
×
876
    return;
×
877
  }
878

879
  void *pReq = taosMemoryMalloc(msgLen);
×
880
  if (pReq == NULL) {
×
881
    fp(param, terrno, taos, 0, NULL);
×
882
    releaseTscObj(connId);
×
883
    return;
×
884
  }
885

886
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
887
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
888
    taosMemoryFree(pReq);
×
889
    releaseTscObj(connId);
×
890
    return;
×
891
  }
892

893
  SFetchDateTimeWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchDateTimeWhiteListInfo));
×
894
  if (pParam == NULL) {
×
895
    fp(param, terrno, taos, 0, NULL);
×
896
    taosMemoryFree(pReq);
×
897
    releaseTscObj(connId);
×
898
    return;
×
899
  }
900

901
  pParam->connId = connId;
×
902
  pParam->userCbFn = fp;
×
903
  pParam->userParam = param;
×
904

905
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
906
  if (pSendInfo == NULL) {
×
907
    fp(param, terrno, taos, 0, NULL);
×
908
    taosMemoryFree(pParam);
×
909
    taosMemoryFree(pReq);
×
910
    releaseTscObj(connId);
×
911
    return;
×
912
  }
913

914
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
915
  pSendInfo->requestId = generateRequestId();
×
916
  pSendInfo->requestObjRefId = 0;
×
917
  pSendInfo->param = pParam;
×
918
  pSendInfo->fp = fetchDateTimeWhiteListCallbackFn;
×
919
  pSendInfo->msgType = TDMT_MND_GET_USER_DATETIME_WHITELIST;
×
920

921
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
922
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
923
    tscWarn("failed to async send msg to server");
×
924
  }
925
  releaseTscObj(connId);
×
926
  return;
×
927
}
928

929
void taos_close_internal(void *taos) {
167,869,720✔
930
  if (taos == NULL) {
167,869,720✔
931
    return;
662✔
932
  }
933
  int32_t code = 0;
167,869,058✔
934

935
  STscObj *pTscObj = (STscObj *)taos;
167,869,058✔
936
  tscDebug("conn:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
167,869,058✔
937

938
  SSessParam para = {.type = SESSION_PER_USER, .value = -1, .noCheck = 1};
167,869,058✔
939

940
  code = tscUpdateSessMetric(pTscObj, &para);
167,869,058✔
941
  if (code != TSDB_CODE_SUCCESS) {
167,871,300✔
942
    tscWarn("conn:0x%" PRIx64 ", failed to update user:%s metric when close connection, code:%d", pTscObj->id,
×
943
            pTscObj->user, code);
944
  }
945

946
  code = tscUnrefSessMetric(pTscObj);
167,871,300✔
947
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
167,872,450✔
948
    tscError("conn:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
×
949
  }
950
}
951

952
void taos_close(TAOS *taos) {
167,593,470✔
953
  if (taos == NULL) {
167,593,470✔
954
    return;
1,094✔
955
  }
956

957
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
167,592,376✔
958
  if (NULL == pObj) {
167,593,578✔
959
    taosMemoryFree(taos);
×
960
    return;
×
961
  }
962

963
  taos_close_internal(pObj);
167,593,578✔
964
  releaseTscObj(*(int64_t *)taos);
167,592,624✔
965
  taosMemoryFree(taos);
167,588,848✔
966
}
967

968
int taos_errno(TAOS_RES *res) {
2,147,483,647✔
969
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
970
    return terrno;
1,861,662✔
971
  }
972

973
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
974
    return 0;
857,130✔
975
  }
976

977
  return ((SRequestObj *)res)->code;
2,147,483,647✔
978
}
979

980
const char *taos_errstr(TAOS_RES *res) {
200,425,044✔
981
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
200,425,044✔
982
    if (*(taosGetErrMsg()) == 0) {
1,866,762✔
983
      return (const char *)tstrerror(terrno);
1,867,312✔
984
    } else {
985
      (void)snprintf(taosGetErrMsgReturn(), ERR_MSG_LEN, "%s", taosGetErrMsg());
88✔
986
      return (const char *)taosGetErrMsgReturn();
88✔
987
    }
988
  }
989

990
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
198,558,468✔
991
    return "success";
×
992
  }
993

994
  SRequestObj *pRequest = (SRequestObj *)res;
198,558,600✔
995
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
198,558,600✔
996
    return pRequest->msgBuf;
58,598,428✔
997
  } else {
998
    return (const char *)tstrerror(pRequest->code);
139,960,172✔
999
  }
1000
}
1001

1002
void taos_free_result(TAOS_RES *res) {
1,900,012,744✔
1003
  if (NULL == res) {
1,900,012,744✔
1004
    return;
27,205,028✔
1005
  }
1006

1007
  tscTrace("res:%p, will be freed", res);
1,872,807,716✔
1008

1009
  if (TD_RES_QUERY(res)) {
1,872,816,658✔
1010
    SRequestObj *pRequest = (SRequestObj *)res;
1,849,576,402✔
1011
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query, res:%p", pRequest->requestId, res);
1,849,576,402✔
1012
    destroyRequest(pRequest);
1,849,579,634✔
1013
    return;
1,849,561,400✔
1014
  }
1015

1016
  SMqRspObj *pRsp = (SMqRspObj *)res;
23,237,142✔
1017
  if (TD_RES_TMQ(res)) {
23,237,142✔
1018
    tDeleteMqDataRsp(&pRsp->dataRsp);
23,086,610✔
1019
    doFreeReqResultInfo(&pRsp->resInfo);
23,085,818✔
1020
  } else if (TD_RES_TMQ_METADATA(res)) {
155,094✔
1021
    tDeleteSTaosxRsp(&pRsp->dataRsp);
7,074✔
1022
    doFreeReqResultInfo(&pRsp->resInfo);
7,074✔
1023
  } else if (TD_RES_TMQ_META(res)) {
148,020✔
1024
    tDeleteMqMetaRsp(&pRsp->metaRsp);
133,776✔
1025
  } else if (TD_RES_TMQ_BATCH_META(res)) {
14,244✔
1026
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
14,244✔
1027
  } else if (TD_RES_TMQ_RAW(res)) {
×
1028
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
×
1029
  }
1030
  taosMemoryFree(pRsp);
23,240,912✔
1031
}
1032

1033
void taos_kill_query(TAOS *taos) {
1,196✔
1034
  if (NULL == taos) {
1,196✔
1035
    return;
904✔
1036
  }
1037

1038
  int64_t  rid = *(int64_t *)taos;
292✔
1039
  STscObj *pTscObj = acquireTscObj(rid);
292✔
1040
  if (pTscObj) {
292✔
1041
    stopAllRequests(pTscObj->pRequests);
292✔
1042
  }
1043
  releaseTscObj(rid);
292✔
1044
}
1045

1046
int taos_field_count(TAOS_RES *res) {
2,147,483,647✔
1047
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1048
    return 0;
×
1049
  }
1050

1051
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1052
  return pResInfo->numOfCols;
2,147,483,647✔
1053
}
1054

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

1057
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
2,147,483,647✔
1058
  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✔
1059
    return NULL;
6,922,178✔
1060
  }
1061

1062
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1063
  return pResInfo->userFields;
2,147,483,647✔
1064
}
1065

1066
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
1,834,769,628✔
1067
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
462✔
1068
  return taosQueryImplWithReqid(taos, sql, false, reqid);
462✔
1069
}
1070

1071
TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res) {
268✔
1072
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
268✔
1073
    return NULL;
×
1074
  }
1075
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
268✔
1076
  return pResInfo->fields;
268✔
1077
}
1078

1079
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
2,147,483,647✔
1080
  if (res == NULL) {
2,147,483,647✔
1081
    return NULL;
×
1082
  }
1083

1084
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1085
    SRequestObj *pRequest = (SRequestObj *)res;
2,147,483,647✔
1086
    if (pRequest->killed) {
2,147,483,647✔
1087
      tscInfo("query has been killed, can not fetch more row.");
×
1088
      pRequest->code = TSDB_CODE_TSC_QUERY_KILLED;
×
1089
      return NULL;
×
1090
    }
1091

1092
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
2,147,483,647✔
1093
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
2,147,483,647✔
1094
      return NULL;
1,270✔
1095
    }
1096

1097
    if (pRequest->inCallback) {
2,147,483,647✔
1098
      tscError("can not call taos_fetch_row before query callback ends.");
380✔
1099
      terrno = TSDB_CODE_TSC_INVALID_OPERATION;
380✔
1100
      return NULL;
380✔
1101
    }
1102

1103
    return doAsyncFetchRows(pRequest, true, true);
2,147,483,647✔
1104
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
1105
    SMqRspObj      *msg = ((SMqRspObj *)res);
2,147,483,647✔
1106
    SReqResultInfo *pResultInfo = NULL;
2,147,483,647✔
1107
    if (msg->resIter == -1) {
2,147,483,647✔
1108
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
22,160,676✔
1109
        return NULL;
×
1110
      }
1111
    } else {
1112
      pResultInfo = tmqGetCurResInfo(res);
2,147,483,647✔
1113
    }
1114

1115
    if (pResultInfo->current < pResultInfo->numOfRows) {
2,147,483,647✔
1116
      doSetOneRowPtr(pResultInfo);
2,147,483,647✔
1117
      pResultInfo->current += 1;
2,147,483,647✔
1118
      return pResultInfo->row;
2,147,483,647✔
1119
    } else {
1120
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
84,680,384✔
1121
        return NULL;
22,157,726✔
1122
      }
1123

1124
      doSetOneRowPtr(pResultInfo);
62,518,466✔
1125
      pResultInfo->current += 1;
62,521,470✔
1126
      return pResultInfo->row;
62,521,470✔
1127
    }
1128
  } else if (TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1129
    return NULL;
×
1130
  } else {
1131
    tscError("invalid result passed to taos_fetch_row");
×
1132
    terrno = TSDB_CODE_TMQ_INVALID_DATA;
×
1133
    return NULL;
×
1134
  }
1135
}
1136

1137
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
2,147,483,647✔
1138
  return taos_print_row_with_size(str, INT32_MAX, row, fields, num_fields);
2,147,483,647✔
1139
}
1140
int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
2,147,483,647✔
1141
  int32_t len = 0;
2,147,483,647✔
1142
  for (int i = 0; i < num_fields; ++i) {
2,147,483,647✔
1143
    if (i > 0 && len < size - 1) {
2,147,483,647✔
1144
      str[len++] = ' ';
2,147,483,647✔
1145
    }
1146

1147
    if (row[i] == NULL) {
2,147,483,647✔
1148
      len += tsnprintf(str + len, size - len, "%s", TSDB_DATA_NULL_STR);
281,636,092✔
1149
      continue;
281,651,318✔
1150
    }
1151

1152
    switch (fields[i].type) {
2,147,483,647✔
1153
      case TSDB_DATA_TYPE_TINYINT:
20,452,548✔
1154
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
20,452,548✔
1155
        break;
20,449,104✔
1156

1157
      case TSDB_DATA_TYPE_UTINYINT:
101,078✔
1158
        len += tsnprintf(str + len, size - len, "%u", *((uint8_t *)row[i]));
101,078✔
1159
        break;
101,152✔
1160

1161
      case TSDB_DATA_TYPE_SMALLINT:
101,532✔
1162
        len += tsnprintf(str + len, size - len, "%d", *((int16_t *)row[i]));
101,532✔
1163
        break;
101,532✔
1164

1165
      case TSDB_DATA_TYPE_USMALLINT:
101,126✔
1166
        len += tsnprintf(str + len, size - len, "%u", *((uint16_t *)row[i]));
101,126✔
1167
        break;
101,134✔
1168

1169
      case TSDB_DATA_TYPE_INT:
2,147,483,647✔
1170
        len += tsnprintf(str + len, size - len, "%d", *((int32_t *)row[i]));
2,147,483,647✔
1171
        break;
2,147,483,647✔
1172

1173
      case TSDB_DATA_TYPE_UINT:
101,134✔
1174
        len += tsnprintf(str + len, size - len, "%u", *((uint32_t *)row[i]));
101,134✔
1175
        break;
101,126✔
1176

1177
      case TSDB_DATA_TYPE_BIGINT:
2,147,483,647✔
1178
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
2,147,483,647✔
1179
        break;
2,147,483,647✔
1180

1181
      case TSDB_DATA_TYPE_UBIGINT:
101,100✔
1182
        len += tsnprintf(str + len, size - len, "%" PRIu64, *((uint64_t *)row[i]));
101,100✔
1183
        break;
101,174✔
1184

1185
      case TSDB_DATA_TYPE_FLOAT: {
40,675,056✔
1186
        float fv = 0;
40,675,056✔
1187
        fv = GET_FLOAT_VAL(row[i]);
40,675,056✔
1188
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
40,728,912✔
1189
      } break;
40,858,860✔
1190

1191
      case TSDB_DATA_TYPE_DOUBLE: {
2,147,483,647✔
1192
        double dv = 0;
2,147,483,647✔
1193
        dv = GET_DOUBLE_VAL(row[i]);
2,147,483,647✔
1194
        len += snprintf(str + len, size - len, "%.*g", DBL_DIG, dv);
2,147,483,647✔
1195
      } break;
2,147,483,647✔
1196

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

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

1239
        uint32_t copyLen = TMIN(size - len - 1, tmp);
×
1240
        (void)memcpy(str + len, data, copyLen);
×
1241
        len += copyLen;
×
1242

1243
        taosMemoryFree(data);
×
1244
      } break;
×
1245

1246
      case TSDB_DATA_TYPE_TIMESTAMP:
2,147,483,647✔
1247
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
2,147,483,647✔
1248
        break;
2,147,483,647✔
1249

1250
      case TSDB_DATA_TYPE_BOOL:
101,514✔
1251
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
101,514✔
1252
        break;
101,426✔
1253
      case TSDB_DATA_TYPE_DECIMAL64:
×
1254
      case TSDB_DATA_TYPE_DECIMAL: {
1255
        uint32_t decimalLen = strlen(row[i]);
×
1256
        uint32_t copyLen = TMIN(size - len - 1, decimalLen);
×
1257
        (void)memcpy(str + len, row[i], copyLen);
×
1258
        len += copyLen;
×
1259
      } break;
×
1260
      default:
×
1261
        break;
×
1262
    }
1263

1264
    if (len >= size - 1) {
2,147,483,647✔
1265
      break;
×
1266
    }
1267
  }
1268
  if (len < size) {
2,147,483,647✔
1269
    str[len] = 0;
2,147,483,647✔
1270
  }
1271

1272
  return len;
2,147,483,647✔
1273
}
1274

1275
int *taos_fetch_lengths(TAOS_RES *res) {
2,147,483,647✔
1276
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1277
    return NULL;
×
1278
  }
1279

1280
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1281
  return pResInfo->length;
2,147,483,647✔
1282
}
1283

1284
TAOS_ROW *taos_result_block(TAOS_RES *res) {
×
1285
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1286
    terrno = TSDB_CODE_INVALID_PARA;
×
1287
    return NULL;
×
1288
  }
1289

1290
  if (taos_is_update_query(res)) {
×
1291
    return NULL;
×
1292
  }
1293

1294
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
1295
  return &pResInfo->row;
×
1296
}
1297

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

1349
const char *taos_get_client_info() { return td_version; }
1,803,134✔
1350

1351
// return int32_t
1352
int taos_affected_rows(TAOS_RES *res) {
1,229,049,574✔
1353
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,229,049,574✔
1354
      TD_RES_TMQ_BATCH_META(res)) {
1,229,054,190✔
1355
    return 0;
×
1356
  }
1357

1358
  SRequestObj    *pRequest = (SRequestObj *)res;
1,229,053,354✔
1359
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
1,229,053,354✔
1360
  return (int)pResInfo->numOfRows;
1,229,052,852✔
1361
}
1362

1363
// return int64_t
1364
int64_t taos_affected_rows64(TAOS_RES *res) {
2,716,002✔
1365
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
2,716,002✔
1366
      TD_RES_TMQ_BATCH_META(res)) {
2,716,002✔
1367
    return 0;
×
1368
  }
1369

1370
  SRequestObj    *pRequest = (SRequestObj *)res;
2,716,002✔
1371
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
2,716,002✔
1372
  return pResInfo->numOfRows;
2,716,002✔
1373
}
1374

1375
int taos_result_precision(TAOS_RES *res) {
2,147,483,647✔
1376
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1377
    return TSDB_TIME_PRECISION_MILLI;
×
1378
  }
1379

1380
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1381
    SRequestObj *pRequest = (SRequestObj *)res;
472,450,528✔
1382
    return pRequest->body.resInfo.precision;
472,450,528✔
1383
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
1384
    SReqResultInfo *info = tmqGetCurResInfo(res);
2,147,483,647✔
1385
    return info->precision;
2,147,483,647✔
1386
  }
1387
  return TSDB_TIME_PRECISION_MILLI;
×
1388
}
1389

1390
int taos_select_db(TAOS *taos, const char *db) {
79,274✔
1391
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
79,274✔
1392
  if (pObj == NULL) {
79,352✔
1393
    releaseTscObj(*(int64_t *)taos);
×
1394
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1395
    return TSDB_CODE_TSC_DISCONNECTED;
×
1396
  }
1397

1398
  if (db == NULL || strlen(db) == 0) {
79,352✔
1399
    releaseTscObj(*(int64_t *)taos);
×
1400
    tscError("invalid parameter for %s", db == NULL ? "db is NULL" : "db is empty");
×
1401
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
1402
    return terrno;
×
1403
  }
1404

1405
  char sql[256] = {0};
79,352✔
1406
  (void)snprintf(sql, tListLen(sql), "use %s", db);
79,352✔
1407

1408
  TAOS_RES *pRequest = taos_query(taos, sql);
79,352✔
1409
  int32_t   code = taos_errno(pRequest);
79,352✔
1410

1411
  taos_free_result(pRequest);
79,270✔
1412
  releaseTscObj(*(int64_t *)taos);
79,326✔
1413
  return code;
79,352✔
1414
}
1415

1416
void taos_stop_query(TAOS_RES *res) {
2,019,410,596✔
1417
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
2,019,410,596✔
1418
      TD_RES_TMQ_BATCH_META(res)) {
2,019,428,560✔
1419
    return;
×
1420
  }
1421

1422
  stopAllQueries((SRequestObj *)res);
2,019,452,408✔
1423
}
1424

1425
bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
×
1426
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1427
    return true;
×
1428
  }
1429
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
×
1430
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
×
1431
    return true;
×
1432
  }
1433

1434
  SResultColumn *pCol = &pResultInfo->pCol[col];
×
1435
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
×
1436
    return (pCol->offset[row] == -1);
×
1437
  } else {
1438
    return colDataIsNull_f(pCol, row);
×
1439
  }
1440
}
1441

1442
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
664,884✔
1443

1444
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
592,499,814✔
1445
  int32_t numOfRows = 0;
592,499,814✔
1446
  /*int32_t code = */ terrno = taos_fetch_block_s(res, &numOfRows, rows);
592,499,814✔
1447
  return numOfRows;
592,499,814✔
1448
}
1449

1450
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
592,499,814✔
1451
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
592,499,814✔
1452
    return 0;
×
1453
  }
1454

1455
  if (TD_RES_QUERY(res)) {
592,499,814✔
1456
    SRequestObj *pRequest = (SRequestObj *)res;
590,811,368✔
1457

1458
    (*rows) = NULL;
590,811,368✔
1459
    (*numOfRows) = 0;
590,811,368✔
1460

1461
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
590,811,368✔
1462
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
590,118,882✔
1463
      return pRequest->code;
2,792,052✔
1464
    }
1465

1466
    (void)doAsyncFetchRows(pRequest, false, true);
588,016,364✔
1467

1468
    // TODO refactor
1469
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
588,016,364✔
1470
    pResultInfo->current = pResultInfo->numOfRows;
588,016,364✔
1471

1472
    (*rows) = pResultInfo->row;
588,016,364✔
1473
    (*numOfRows) = pResultInfo->numOfRows;
588,015,548✔
1474
    return pRequest->code;
588,016,364✔
1475
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,688,446✔
1476
    SReqResultInfo *pResultInfo = NULL;
1,688,446✔
1477
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
1,688,446✔
1478
    if (code != 0) return code;
1,688,446✔
1479

1480
    pResultInfo->current = pResultInfo->numOfRows;
847,184✔
1481
    (*rows) = pResultInfo->row;
847,184✔
1482
    (*numOfRows) = pResultInfo->numOfRows;
847,184✔
1483
    return 0;
847,184✔
1484
  } else {
1485
    tscError("taos_fetch_block_s invalid res type");
×
1486
    return TSDB_CODE_TMQ_INVALID_DATA;
×
1487
  }
1488
}
1489

1490
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
11,716✔
1491
  *numOfRows = 0;
11,716✔
1492
  *pData = NULL;
11,716✔
1493

1494
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
11,716✔
1495
    return 0;
×
1496
  }
1497

1498
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
11,716✔
1499
    SReqResultInfo *pResultInfo = NULL;
4,540✔
1500
    int32_t         code = tmqGetNextResInfo(res, false, &pResultInfo);
4,540✔
1501
    if (code != 0) {
4,540✔
1502
      (*numOfRows) = 0;
2,270✔
1503
      return 0;
2,270✔
1504
    }
1505

1506
    pResultInfo->current = pResultInfo->numOfRows;
2,270✔
1507
    (*numOfRows) = pResultInfo->numOfRows;
2,270✔
1508
    (*pData) = (void *)pResultInfo->pData;
2,270✔
1509
    return 0;
2,270✔
1510
  }
1511

1512
  SRequestObj *pRequest = (SRequestObj *)res;
7,176✔
1513

1514
  if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
7,176✔
1515
      pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
7,176✔
1516
    return pRequest->code;
×
1517
  }
1518

1519
  (void)doAsyncFetchRows(pRequest, false, false);
7,176✔
1520

1521
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
7,176✔
1522

1523
  pResultInfo->current = pResultInfo->numOfRows;
7,176✔
1524
  (*numOfRows) = pResultInfo->numOfRows;
7,176✔
1525
  (*pData) = (void *)pResultInfo->pData;
7,176✔
1526

1527
  return pRequest->code;
7,176✔
1528
}
1529

1530
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
453,331,512✔
1531
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
453,331,512✔
1532
    return NULL;
×
1533
  }
1534

1535
  int32_t numOfFields = taos_num_fields(res);
453,331,512✔
1536
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
453,331,512✔
1537
    return NULL;
×
1538
  }
1539

1540
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
453,331,512✔
1541
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
453,331,512✔
1542
  if (!IS_VAR_DATA_TYPE(pField->type)) {
453,331,512✔
1543
    return NULL;
×
1544
  }
1545

1546
  return pResInfo->pCol[columnIndex].offset;
453,331,512✔
1547
}
1548

1549
int taos_is_null_by_column(TAOS_RES *res, int columnIndex, bool result[], int *rows) {
1,503,269,114✔
1550
  if (res == NULL || result == NULL || rows == NULL || *rows <= 0 || columnIndex < 0 || TD_RES_TMQ_META(res) ||
1,503,269,114✔
1551
      TD_RES_TMQ_RAW(res) || TD_RES_TMQ_BATCH_META(res)) {
1,503,269,114✔
1552
    return TSDB_CODE_INVALID_PARA;
×
1553
  }
1554

1555
  int32_t numOfFields = taos_num_fields(res);
1,503,269,114✔
1556
  if (columnIndex >= numOfFields || numOfFields == 0) {
1,503,269,114✔
1557
    return TSDB_CODE_INVALID_PARA;
×
1558
  }
1559

1560
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
1,503,269,114✔
1561
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
1,503,269,114✔
1562
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
1,503,269,114✔
1563

1564
  if (*rows > pResInfo->numOfRows) {
1,503,269,114✔
1565
    *rows = pResInfo->numOfRows;
×
1566
  }
1567
  if (IS_VAR_DATA_TYPE(pField->type)) {
1,503,269,114✔
1568
    for (int i = 0; i < *rows; i++) {
×
1569
      if (pCol->offset[i] == -1) {
×
1570
        result[i] = true;
×
1571
      } else {
1572
        result[i] = false;
×
1573
      }
1574
    }
1575
  } else {
1576
    for (int i = 0; i < *rows; i++) {
2,147,483,647✔
1577
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1578
        result[i] = true;
2,147,483,647✔
1579
      } else {
1580
        result[i] = false;
2,147,483,647✔
1581
      }
1582
    }
1583
  }
1584
  return 0;
1,503,269,114✔
1585
}
1586

1587
int taos_validate_sql(TAOS *taos, const char *sql) {
×
1588
  TAOS_RES *pObj = taosQueryImpl(taos, sql, true, TD_REQ_FROM_APP);
×
1589

1590
  int code = taos_errno(pObj);
×
1591

1592
  taos_free_result(pObj);
×
1593
  return code;
×
1594
}
1595

1596
void taos_reset_current_db(TAOS *taos) {
×
1597
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
1598
  if (pTscObj == NULL) {
×
1599
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1600
    return;
×
1601
  }
1602

1603
  resetConnectDB(pTscObj);
×
1604

1605
  releaseTscObj(*(int64_t *)taos);
×
1606
}
1607

1608
const char *taos_get_server_info(TAOS *taos) {
8,044✔
1609
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
8,044✔
1610
  if (pTscObj == NULL) {
8,044✔
1611
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1612
    return NULL;
×
1613
  }
1614

1615
  releaseTscObj(*(int64_t *)taos);
8,044✔
1616

1617
  return pTscObj->sDetailVer;
8,044✔
1618
}
1619

1620
int taos_get_current_db(TAOS *taos, char *database, int len, int *required) {
4,768✔
1621
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
4,768✔
1622
  if (pTscObj == NULL) {
4,768✔
1623
    return TSDB_CODE_TSC_DISCONNECTED;
×
1624
  }
1625

1626
  int code = TSDB_CODE_SUCCESS;
4,768✔
1627
  (void)taosThreadMutexLock(&pTscObj->mutex);
4,768✔
1628
  if (database == NULL || len <= 0) {
4,768✔
1629
    if (required != NULL) *required = strlen(pTscObj->db) + 1;
2,384✔
1630
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
2,384✔
1631
  } else if (len < strlen(pTscObj->db) + 1) {
2,384✔
1632
    tstrncpy(database, pTscObj->db, len);
1,192✔
1633
    if (required) *required = strlen(pTscObj->db) + 1;
1,192✔
1634
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
1,192✔
1635
  } else {
1636
    tstrncpy(database, pTscObj->db, len);
1,192✔
1637
    code = 0;
1,192✔
1638
  }
1639
_return:
4,768✔
1640
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
4,768✔
1641
  releaseTscObj(*(int64_t *)taos);
4,768✔
1642
  return code;
4,768✔
1643
}
1644

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

1653
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
380✔
1654
  if (pTscObj == NULL) {
380✔
1655
    return TSDB_CODE_TSC_DISCONNECTED;
×
1656
  }
1657

1658
  int code = TSDB_CODE_SUCCESS;
380✔
1659
  (void)taosThreadMutexLock(&pTscObj->mutex);
380✔
1660

1661
  switch (info) {
380✔
1662
    case TSDB_CONNECTION_INFO_USER: {
190✔
1663
      int userLen = strlen(pTscObj->user);
190✔
1664
      if (buffer == NULL || *len < userLen) {
190✔
1665
        *len = userLen;
×
1666
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1667
      } else {
1668
        *len = userLen;
190✔
1669
        (void)memcpy(buffer, pTscObj->user, userLen);
190✔
1670
      }
1671
      break;
190✔
1672
    }
1673

1674
    case TSDB_CONNECTION_INFO_TOKEN: {
190✔
1675
      int tokenLen = strlen(pTscObj->tokenName);
190✔
1676
      if (tokenLen == 0) {
190✔
1677
        *len = 0;
×
1678
      } else if (buffer == NULL || *len < tokenLen) {
190✔
1679
        *len = tokenLen;
×
1680
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1681
      } else {
1682
        *len = tokenLen;
190✔
1683
        (void)memcpy(buffer, pTscObj->tokenName, tokenLen);
190✔
1684
      }
1685
      break;
190✔
1686
    }
1687

1688
    default:
×
1689
      TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1690
  }
1691

1692
_return:
×
1693
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
380✔
1694
  releaseTscObj(*(int64_t *)taos);
380✔
1695
  return code;
380✔
1696
}
1697

1698
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
2,147,483,647✔
1699
  if (NULL == pWrapper) {
2,147,483,647✔
1700
    return;
2,024,014,866✔
1701
  }
1702
  destoryCatalogReq(pWrapper->pCatalogReq);
1,839,595,390✔
1703
  taosMemoryFree(pWrapper->pCatalogReq);
1,839,699,222✔
1704
  qDestroyParseContext(pWrapper->pParseCtx);
1,839,703,498✔
1705
  taosMemoryFree(pWrapper);
1,839,681,572✔
1706
}
1707

1708
void destroyCtxInRequest(SRequestObj *pRequest) {
5,381,188✔
1709
  schedulerFreeJob(&pRequest->body.queryJob, 0);
5,381,188✔
1710
  qDestroyQuery(pRequest->pQuery);
5,381,188✔
1711
  pRequest->pQuery = NULL;
5,381,188✔
1712
  destorySqlCallbackWrapper(pRequest->pWrapper);
5,381,188✔
1713
  pRequest->pWrapper = NULL;
5,381,188✔
1714
}
5,381,188✔
1715

1716
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
844,649,654✔
1717
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
844,649,654✔
1718
  SRequestObj         *pRequest = pWrapper->pRequest;
844,649,654✔
1719
  SQuery              *pQuery = pRequest->pQuery;
844,648,778✔
1720

1721
  qDebug("req:0x%" PRIx64 ", start to semantic analysis, QID:0x%" PRIx64, pRequest->self, pRequest->requestId);
844,647,848✔
1722

1723
  int64_t analyseStart = taosGetTimestampUs();
844,650,830✔
1724
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
844,650,830✔
1725
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
844,653,116✔
1726

1727
  if (TSDB_CODE_SUCCESS == code) {
844,650,360✔
1728
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
844,648,382✔
1729
  }
1730

1731
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
844,576,994✔
1732

1733
  if (pRequest->parseOnly) {
844,570,840✔
1734
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
587,618✔
1735
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
587,618✔
1736
  }
1737

1738
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
844,572,478✔
1739
}
844,553,082✔
1740

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

1768
    *ppTarget = pTarget;
×
1769
  }
1770

1771
  return code;
×
1772
}
1773

1774
void handleSubQueryFromAnalyse(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, SNode *pRoot) {
×
1775
  SRequestObj         *pNewRequest = NULL;
×
1776
  SSqlCallbackWrapper *pNewWrapper = NULL;
×
1777
  int32_t              code = buildPreviousRequest(pWrapper->pRequest, pWrapper->pRequest->sqlstr, &pNewRequest);
×
1778
  if (code) {
×
1779
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1780
    return;
×
1781
  }
1782

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

1805
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
844,492,442✔
1806
  SRequestObj *pRequest = pWrapper->pRequest;
844,492,442✔
1807
  SQuery      *pQuery = pRequest->pQuery;
844,510,288✔
1808

1809
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
844,513,182✔
1810
    SNode *prevRoot = pQuery->pPrevRoot;
×
1811
    pQuery->pPrevRoot = NULL;
×
1812
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
×
1813
    return;
×
1814
  }
1815

1816
  if (code == TSDB_CODE_SUCCESS) {
844,507,062✔
1817
    pRequest->stableQuery = pQuery->stableQuery;
698,299,340✔
1818
    if (pQuery->pRoot) {
698,288,588✔
1819
      pRequest->stmtType = pQuery->pRoot->type;
698,335,050✔
1820
      if (nodeType(pQuery->pRoot) == QUERY_NODE_DELETE_STMT) {
698,290,010✔
1821
        pRequest->secureDelete = ((SDeleteStmt*)pQuery->pRoot)->secureDelete;
3,204,036✔
1822
      }
1823
    }
1824

1825
    if (pQuery->haveResultSet) {
698,269,596✔
1826
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema,
378,661,740✔
1827
                              pRequest->stmtBindVersion > 0);
378,660,820✔
1828
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
378,655,014✔
1829
    }
1830
  }
1831

1832
  if (code == TSDB_CODE_SUCCESS) {
844,535,730✔
1833
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
698,304,268✔
1834
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
698,267,808✔
1835
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
698,249,584✔
1836

1837
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
698,255,530✔
1838
  } else {
1839
    destorySqlCallbackWrapper(pWrapper);
146,231,462✔
1840
    pRequest->pWrapper = NULL;
146,252,276✔
1841
    qDestroyQuery(pRequest->pQuery);
146,252,276✔
1842
    pRequest->pQuery = NULL;
146,248,822✔
1843

1844
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
146,248,822✔
1845
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
5,192,318✔
1846
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1847
      restartAsyncQuery(pRequest, code);
5,192,318✔
1848
      return;
5,192,318✔
1849
    }
1850

1851
    // return to app directly
1852
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self,
141,056,504✔
1853
             tstrerror(code), pRequest->requestId);
1854
    pRequest->code = code;
141,089,986✔
1855
    returnToUser(pRequest);
141,089,986✔
1856
  }
1857
}
1858

1859
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
858,396,376✔
1860
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
1,376,330,124✔
1861
                           .requestId = pWrapper->pParseCtx->requestId,
858,403,264✔
1862
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
858,393,948✔
1863
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
858,365,970✔
1864

1865
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
1,376,330,660✔
1866

1867
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
1,198,862,686✔
1868
                                &pWrapper->pRequest->body.queryJob);
858,443,044✔
1869
}
1870

1871
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1872

1873
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
1,825,044,802✔
1874
  int32_t code = TSDB_CODE_SUCCESS;
1,825,044,802✔
1875
  switch (pWrapper->pRequest->pQuery->execStage) {
1,825,044,802✔
1876
    case QUERY_EXEC_STAGE_PARSE: {
13,833,138✔
1877
      // continue parse after get metadata
1878
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
13,833,138✔
1879
      break;
13,833,160✔
1880
    }
1881
    case QUERY_EXEC_STAGE_ANALYSE: {
844,589,608✔
1882
      // analysis after get metadata
1883
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
844,589,608✔
1884
      break;
844,602,348✔
1885
    }
1886
    case QUERY_EXEC_STAGE_SCHEDULE: {
966,654,248✔
1887
      launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper);
966,654,248✔
1888
      break;
966,666,190✔
1889
    }
UNCOV
1890
    default:
×
UNCOV
1891
      break;
×
1892
  }
1893
  return code;
1,825,064,506✔
1894
}
1895

1896
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
13,833,160✔
1897
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
13,833,160✔
1898
  SRequestObj         *pRequest = pWrapper->pRequest;
13,833,160✔
1899
  SQuery              *pQuery = pRequest->pQuery;
13,833,160✔
1900

1901
  pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart;
13,833,160✔
1902
  qDebug("req:0x%" PRIx64 ", continue parse query, QID:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId,
13,833,160✔
1903
         tstrerror(code));
1904

1905
  if (code == TSDB_CODE_SUCCESS) {
13,833,160✔
1906
    // pWrapper->pCatalogReq->forceUpdate = false;
1907
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
13,772,838✔
1908
  }
1909

1910
  if (TSDB_CODE_SUCCESS == code) {
13,833,160✔
1911
    code = phaseAsyncQuery(pWrapper);
12,681,060✔
1912
  }
1913

1914
  if (TSDB_CODE_SUCCESS != code) {
13,833,160✔
1915
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
1,152,100✔
1916
             tstrerror(code), pWrapper->pRequest->requestId);
1917
    destorySqlCallbackWrapper(pWrapper);
1,152,100✔
1918
    pRequest->pWrapper = NULL;
1,152,100✔
1919
    terrno = code;
1,152,100✔
1920
    pRequest->code = code;
1,152,100✔
1921
    doRequestCallback(pRequest, code);
1,152,100✔
1922
  }
1923
}
13,833,160✔
1924

1925
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
24,038✔
1926
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
24,038✔
1927
  if (TSDB_CODE_SUCCESS == code) {
24,038✔
1928
    code = phaseAsyncQuery(pWrapper);
24,038✔
1929
  }
1930

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

1942
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
260,742✔
1943
  int64_t connId = *(int64_t *)taos;
260,742✔
1944
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
260,742✔
1945
}
260,742✔
1946

UNCOV
1947
void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) {
×
UNCOV
1948
  int64_t connId = *(int64_t *)taos;
×
UNCOV
1949
  taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid);
×
1950
}
×
1951

1952
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
1,839,709,508✔
1953
  const STscObj *pTscObj = pRequest->pTscObj;
1,839,709,508✔
1954

1955
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
1,839,727,678✔
1956
  if (*pCxt == NULL) {
1,839,691,244✔
UNCOV
1957
    return terrno;
×
1958
  }
1959

1960
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
2,147,483,647✔
1961
                           .requestRid = pRequest->self,
1,839,703,330✔
1962
                           .acctId = pTscObj->acctId,
1,839,704,800✔
1963
                           .db = pRequest->pDb,
1,839,715,670✔
1964
                           .topicQuery = false,
1965
                           .pSql = pRequest->sqlstr,
1,839,724,828✔
1966
                           .sqlLen = pRequest->sqlLen,
1,839,727,076✔
1967
                           .pMsg = pRequest->msgBuf,
1,839,719,262✔
1968
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
1969
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
1,839,718,228✔
1970
                           .pStmtCb = NULL,
1971
                           .pUser = pTscObj->user,
1,839,712,786✔
1972
                           .userId = pTscObj->userId,
1,839,710,972✔
1973
                           .pEffectiveUser = pRequest->effectiveUser,
1,839,697,142✔
1974
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
1,839,712,188✔
1975
                           .enableSysInfo = pTscObj->sysInfo,
1,839,713,804✔
1976
                           .privInfo = pWrapper->pParseCtx ? pWrapper->pParseCtx->privInfo : 0,
1,839,718,632✔
1977
                           .async = true,
1978
                           .svrVer = pTscObj->sVer,
1,839,708,004✔
1979
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
1,839,723,522✔
1980
                           .allocatorId = pRequest->allocatorRefId,
1,839,706,940✔
1981
                           .parseSqlFp = clientParseSql,
1982
                           .parseSqlParam = pWrapper,
1983
                           .setQueryFp = setQueryRequest,
1984
                           .timezone = pTscObj->optionInfo.timezone,
1,839,704,578✔
1985
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
1,839,710,452✔
1986
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
1,839,707,788✔
1987
  (*pCxt)->biMode = biMode;
1,839,695,090✔
1988
  return TSDB_CODE_SUCCESS;
1,839,697,822✔
1989
}
1990

1991
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
1,839,706,426✔
1992
  int32_t              code = TSDB_CODE_SUCCESS;
1,839,706,426✔
1993
  STscObj             *pTscObj = pRequest->pTscObj;
1,839,706,426✔
1994
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
1,839,716,904✔
1995
  if (pWrapper == NULL) {
1,839,697,806✔
UNCOV
1996
    code = terrno;
×
1997
  } else {
1998
    pWrapper->pRequest = pRequest;
1,839,697,806✔
1999
    pRequest->pWrapper = pWrapper;
1,839,707,880✔
2000
    *ppWrapper = pWrapper;
1,839,726,836✔
2001
  }
2002

2003
  if (TSDB_CODE_SUCCESS == code) {
1,839,705,118✔
2004
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
1,839,717,284✔
2005
  }
2006

2007
  if (TSDB_CODE_SUCCESS == code) {
1,839,687,994✔
2008
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
1,839,696,518✔
2009
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
1,839,742,622✔
2010
  }
2011

2012
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
1,839,731,884✔
2013
    int64_t syntaxStart = taosGetTimestampUs();
1,839,735,548✔
2014

2015
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
1,839,735,548✔
2016
    if (pWrapper->pCatalogReq == NULL) {
1,839,680,232✔
UNCOV
2017
      code = terrno;
×
2018
    } else {
2019
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
1,839,704,018✔
2020
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
1,839,708,346✔
2021
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
1,839,661,520✔
2022
    }
2023

2024
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
1,839,665,576✔
2025
  }
2026

2027
  return code;
1,839,714,820✔
2028
}
2029

2030
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
1,841,436,148✔
2031
  SSqlCallbackWrapper *pWrapper = NULL;
1,841,436,148✔
2032
  int32_t              code = TSDB_CODE_SUCCESS;
1,841,441,466✔
2033

2034
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
1,841,441,466✔
2035
    code = pRequest->prevCode;
1,732,890✔
2036
    terrno = code;
1,732,890✔
2037
    pRequest->code = code;
1,732,890✔
2038
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
1,732,890✔
2039
    doRequestCallback(pRequest, code);
1,732,890✔
2040
    return;
1,732,890✔
2041
  }
2042

2043
  if (TSDB_CODE_SUCCESS == code) {
1,839,675,604✔
2044
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
1,839,695,988✔
2045
  }
2046

2047
  if (TSDB_CODE_SUCCESS == code) {
1,839,650,994✔
2048
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
1,812,393,518✔
2049
    code = phaseAsyncQuery(pWrapper);
1,812,382,294✔
2050
  }
2051

2052
  if (TSDB_CODE_SUCCESS != code) {
1,839,659,402✔
2053
    if (NULL != pRequest->msgBuf && strlen(pRequest->msgBuf) > 0) {
27,305,010✔
2054
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, pRequest->msgBuf,
27,167,534✔
2055
               pRequest->requestId);
2056
    } else {
2057
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
137,476✔
2058
               pRequest->requestId);
2059
    }
2060

2061
    destorySqlCallbackWrapper(pWrapper);
27,305,722✔
2062
    pRequest->pWrapper = NULL;
27,305,176✔
2063
    qDestroyQuery(pRequest->pQuery);
27,305,176✔
2064
    pRequest->pQuery = NULL;
27,304,994✔
2065

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

2079
    terrno = code;
27,280,074✔
2080
    pRequest->code = code;
27,280,074✔
2081
    doRequestCallback(pRequest, code);
27,280,074✔
2082
  }
2083
}
2084

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

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

2123
static int32_t doAsyncFetch(void *pParam) {
553,832,132✔
2124
  SAsyncFetchParam *param = pParam;
553,832,132✔
2125
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
553,832,132✔
2126
  taosMemoryFree(param);
553,832,132✔
2127
  return TSDB_CODE_SUCCESS;
553,830,990✔
2128
}
2129

2130
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
553,907,112✔
2131
  if (res == NULL || fp == NULL) {
553,907,112✔
UNCOV
2132
    tscError("taos_fetch_rows_a invalid paras");
×
UNCOV
2133
    return;
×
2134
  }
2135
  if (!TD_RES_QUERY(res)) {
553,907,112✔
2136
    tscError("taos_fetch_rows_a res is NULL");
×
UNCOV
2137
    fp(param, res, TSDB_CODE_APP_ERROR);
×
UNCOV
2138
    return;
×
2139
  }
2140

2141
  SRequestObj *pRequest = res;
553,907,112✔
2142
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
553,907,112✔
2143
    fp(param, res, 0);
75,024✔
2144
    return;
75,024✔
2145
  }
2146

2147
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
553,832,068✔
2148
  if (!pParam) {
553,832,062✔
UNCOV
2149
    fp(param, res, terrno);
×
UNCOV
2150
    return;
×
2151
  }
2152
  pParam->pReq = pRequest;
553,832,062✔
2153
  pParam->fp = fp;
553,832,062✔
2154
  pParam->param = param;
553,832,062✔
2155
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
553,832,062✔
2156
  if (TSDB_CODE_SUCCESS != code) {
553,832,154✔
UNCOV
2157
    taosMemoryFree(pParam);
×
UNCOV
2158
    fp(param, res, code);
×
UNCOV
2159
    return;
×
2160
  }
2161
}
2162

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

2175
  // set the current block is all consumed
2176
  pResultInfo->convertUcs4 = false;
1,026✔
2177

2178
  // it is a local executed query, no need to do async fetch
2179
  taos_fetch_rows_a(pRequest, fp, param);
1,026✔
2180
}
2181

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

2193
  return pRequest->body.resInfo.pData;
172✔
2194
}
2195

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

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

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

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

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

2227
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2228

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

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

2237
_return:
×
2238

UNCOV
2239
  terrno = code;
×
2240

UNCOV
2241
  destroyRequest(pRequest);
×
2242
  return code;
×
2243
}
2244

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

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

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

2265
  pRequest->syncQuery = true;
×
2266

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

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

2277
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2278

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

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

2288
  *vgId = vgInfo.vgId;
×
2289

UNCOV
2290
_return:
×
2291

UNCOV
2292
  terrno = code;
×
2293

UNCOV
2294
  destroyRequest(pRequest);
×
2295
  return code;
×
2296
}
2297

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

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

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

2318
  pRequest->syncQuery = true;
×
2319

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

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

2330
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2331

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

2337
_return:
×
2338

UNCOV
2339
  terrno = code;
×
2340

UNCOV
2341
  destroyRequest(pRequest);
×
2342
  return code;
×
2343
}
2344

2345
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
2,392✔
2346
  if (NULL == taos) {
2,392✔
UNCOV
2347
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2348
    return terrno;
×
2349
  }
2350

2351
  int64_t       connId = *(int64_t *)taos;
2,392✔
2352
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
2,392✔
2353
  int32_t       code = 0;
2,392✔
2354
  SRequestObj  *pRequest = NULL;
2,392✔
2355
  SCatalogReq   catalogReq = {0};
2,392✔
2356

2357
  if (NULL == tableNameList) {
2,392✔
UNCOV
2358
    return TSDB_CODE_SUCCESS;
×
2359
  }
2360

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

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

2376
  pRequest->syncQuery = true;
2,392✔
2377

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

2384
  SCatalog *pCtg = NULL;
2,392✔
2385
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
2,392✔
2386
  if (code != TSDB_CODE_SUCCESS) {
2,392✔
UNCOV
2387
    goto _return;
×
2388
  }
2389

2390
  SRequestConnInfo conn = {
2,392✔
2391
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
2,392✔
2392

2393
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
2,392✔
2394

2395
  code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, pRequest->body.interParam, NULL);
2,392✔
2396
  if (code) {
2,392✔
UNCOV
2397
    goto _return;
×
2398
  }
2399

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

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

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

2426
  return pStmt;
43,420✔
2427
}
2428

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

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

UNCOV
2443
  return pStmt;
×
2444
}
2445

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

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

2460
  return pStmt;
24,482✔
2461
}
2462

2463
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
13,492,054✔
2464
  if (stmt == NULL || sql == NULL) {
13,492,054✔
UNCOV
2465
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2466
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2467
    return terrno;
×
2468
  }
2469

2470
  return stmtPrepare(stmt, sql, length);
13,492,070✔
2471
}
2472

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

2480
  int32_t code = stmtSetTbName(stmt, name);
13,482✔
2481
  if (code) {
13,482✔
2482
    return code;
1,196✔
2483
  }
2484

2485
  if (tags) {
12,286✔
2486
    return stmtSetTbTags(stmt, tags);
12,286✔
2487
  }
2488

UNCOV
2489
  return TSDB_CODE_SUCCESS;
×
2490
}
2491

2492
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
16,889,146✔
2493
  if (stmt == NULL || name == NULL) {
16,889,146✔
UNCOV
2494
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2495
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2496
    return terrno;
×
2497
  }
2498

2499
  return stmtSetTbName(stmt, name);
16,891,712✔
2500
}
2501

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

2509
  return stmtSetTbTags(stmt, tags);
1,078✔
2510
}
2511

2512
int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); }
384✔
2513

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

2521
  return stmtGetTagFields(stmt, fieldNum, fields);
768✔
2522
}
2523

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

2531
  return stmtGetColFields(stmt, fieldNum, fields);
1,152✔
2532
}
2533

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

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

2548
  if (bind->num > 1) {
71,624✔
2549
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
7,800✔
2550
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
7,800✔
2551
    return terrno;
7,800✔
2552
  }
2553

2554
  return stmtBindBatch(stmt, bind, -1);
63,824✔
2555
}
2556

2557
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
16,888,448✔
2558
  if (stmt == NULL || bind == NULL) {
16,888,448✔
2559
    tscError("NULL parameter for %s", __FUNCTION__);
3,456✔
2560
    terrno = TSDB_CODE_INVALID_PARA;
3,456✔
UNCOV
2561
    return terrno;
×
2562
  }
2563

2564
  if (bind->num <= 0 || bind->num > INT16_MAX) {
16,886,940✔
2565
    tscError("invalid bind num %d", bind->num);
9,840✔
2566
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
9,840✔
UNCOV
2567
    return terrno;
×
2568
  }
2569

2570
  int32_t insert = 0;
16,889,732✔
2571
  int32_t code = stmtIsInsert(stmt, &insert);
16,888,852✔
2572
  if (TSDB_CODE_SUCCESS != code) {
16,885,600✔
UNCOV
2573
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
UNCOV
2574
    return code;
×
2575
  }
2576
  if (0 == insert && bind->num > 1) {
16,885,600✔
2577
    tscError("only one row data allowed for query");
×
UNCOV
2578
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
UNCOV
2579
    return terrno;
×
2580
  }
2581

2582
  return stmtBindBatch(stmt, bind, -1);
16,885,600✔
2583
}
2584

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

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

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

2610
  return stmtBindBatch(stmt, bind, colIdx);
1,680✔
2611
}
2612

2613
int taos_stmt_add_batch(TAOS_STMT *stmt) {
14,038,874✔
2614
  if (stmt == NULL) {
14,038,874✔
UNCOV
2615
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2616
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2617
    return terrno;
×
2618
  }
2619

2620
  return stmtAddBatch(stmt);
14,038,874✔
2621
}
2622

2623
int taos_stmt_execute(TAOS_STMT *stmt) {
14,030,056✔
2624
  if (stmt == NULL) {
14,030,056✔
UNCOV
2625
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2626
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2627
    return terrno;
×
2628
  }
2629

2630
  return stmtExec(stmt);
14,030,056✔
2631
}
2632

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

2640
  return stmtIsInsert(stmt, insert);
×
2641
}
2642

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

2650
  return stmtGetParamNum(stmt, nums);
×
2651
}
2652

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

2660
  return stmtGetParam(stmt, idx, type, bytes);
768✔
2661
}
2662

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

2670
  return stmtUseResult(stmt);
19,166✔
2671
}
2672

2673
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
21,926✔
2674

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

2682
  return stmtAffectedRows(stmt);
6,262✔
2683
}
2684

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

2692
  return stmtAffectedRowsOnce(stmt);
5,536✔
2693
}
2694

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

2702
  return stmtClose(stmt);
67,902✔
2703
}
2704

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

2718
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
238,630✔
2719

2720
  releaseTscObj(*(int64_t *)taos);
238,630✔
2721

2722
  return pStmt;
238,630✔
2723
}
2724

2725
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
245,160✔
2726
  if (stmt == NULL || sql == NULL) {
245,160✔
2727
    tscError("NULL parameter for %s", __FUNCTION__);
192✔
2728
    terrno = TSDB_CODE_INVALID_PARA;
192✔
2729
    return terrno;
192✔
2730
  }
2731

2732
  return stmtPrepare2(stmt, sql, length);
244,968✔
2733
}
2734

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

2742
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
81,374,516✔
2743
  int32_t    code = TSDB_CODE_SUCCESS;
81,374,516✔
2744
  STMT2_DLOG_E("start to bind param");
81,374,516✔
2745

2746
  // check query bind number
2747
  bool isQuery = (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt)));
81,380,166✔
2748
  if (isQuery) {
81,897,022✔
2749
    if (bindv->count != 1 || bindv->bind_cols[0]->num != 1) {
7,504✔
UNCOV
2750
      terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
UNCOV
2751
      STMT2_ELOG_E("query only support one table and one row bind");
×
UNCOV
2752
      return terrno;
×
2753
    }
2754
  }
2755

2756
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 1) {
81,897,022✔
2757
    STMT2_ELOG_E("async bind param is still working, please try again later");
14,478✔
2758
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
14,478✔
UNCOV
2759
    return terrno;
×
2760
  }
2761

2762
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
81,632,354✔
2763
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
4,416✔
UNCOV
2764
      STMT2_ELOG_E("bind param wait asyncExecSem failed");
×
2765
    }
2766
    pStmt->execSemWaited = true;
4,416✔
2767
  }
2768

2769
  for (int i = 0; i < bindv->count; ++i) {
164,000,404✔
2770
    SVCreateTbReq *pCreateTbReq = NULL;
81,607,404✔
2771
    if (!isQuery) {
82,469,276✔
2772
      STMT2_TLOG("start to bind %dth table", i);
82,561,482✔
2773
      if (bindv->tbnames && bindv->tbnames[i]) {
82,499,940✔
2774
        code = stmtSetTbName2(stmt, bindv->tbnames[i]);
2,096,170✔
2775
        if (code) {
2,096,108✔
2776
          terrno = code;
2,112✔
2777
          STMT2_ELOG("set tbname failed, code:%s", stmt2Errstr(stmt));
2,112✔
2778
          return terrno;
3,456✔
2779
        }
2780
      }
2781

2782
      if (bindv->tags && bindv->tags[i]) {
82,755,832✔
2783
        code = stmtSetTbTags2(stmt, bindv->tags[i], &pCreateTbReq);
1,086,320✔
2784
      } else if (pStmt->bInfo.tbNameFlag & IS_FIXED_TAG) {
81,470,498✔
2785
        code = stmtCheckTags2(stmt, &pCreateTbReq);
213,562✔
2786
      } else if (pStmt->sql.autoCreateTbl) {
81,383,708✔
2787
        code = stmtSetTbTags2(stmt, NULL, &pCreateTbReq);
4,032✔
2788
      }
2789

2790
      if (code) {
82,685,652✔
2791
        terrno = code;
192✔
2792
        STMT2_ELOG("set tags failed, code:%s", stmt2Errstr(stmt));
192✔
2793
        if (pCreateTbReq) {
192✔
UNCOV
2794
          tdDestroySVCreateTbReq(pCreateTbReq);
×
UNCOV
2795
          taosMemoryFreeClear(pCreateTbReq);
×
2796
        }
2797
        return terrno;
192✔
2798
      }
2799
    }
2800

2801
    if (bindv->bind_cols && bindv->bind_cols[i]) {
82,593,254✔
2802
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
83,280,390✔
2803

2804
      if (bind->num <= 0 || bind->num > INT16_MAX) {
83,296,242✔
2805
        STMT2_ELOG("bind num:%d must > 0 and < INT16_MAX", bind->num);
1,092,836✔
2806
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
1,092,836✔
UNCOV
2807
        if (pCreateTbReq) {
×
UNCOV
2808
          tdDestroySVCreateTbReq(pCreateTbReq);
×
UNCOV
2809
          taosMemoryFreeClear(pCreateTbReq);
×
2810
        }
2811
        return terrno;
×
2812
      }
2813

2814
      code = stmtBindBatch2(stmt, bind, col_idx, pCreateTbReq);
82,258,792✔
2815
      if (TSDB_CODE_SUCCESS != code) {
81,660,006✔
2816
        terrno = code;
1,152✔
2817
        STMT2_ELOG("bind batch failed, code:%s", stmt2Errstr(stmt));
1,152✔
2818
        if (pCreateTbReq) {
1,152✔
2819
          tdDestroySVCreateTbReq(pCreateTbReq);
384✔
2820
          taosMemoryFreeClear(pCreateTbReq);
384✔
2821
        }
2822
        return terrno;
1,152✔
2823
      }
2824
    }
2825
  }
2826

2827
  return code;
81,998,604✔
2828
}
2829

UNCOV
2830
int taos_stmt2_bind_param_a(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx, __taos_async_fn_t fp,
×
2831
                            void *param) {
UNCOV
2832
  if (stmt == NULL || bindv == NULL || fp == NULL) {
×
2833
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2834
    return terrno;
×
2835
  }
2836

2837
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
×
2838

UNCOV
2839
  ThreadArgs *args = (ThreadArgs *)taosMemoryMalloc(sizeof(ThreadArgs));
×
2840
  args->stmt = stmt;
×
UNCOV
2841
  args->bindv = bindv;
×
2842
  args->col_idx = col_idx;
×
2843
  args->fp = fp;
×
2844
  args->param = param;
×
2845

2846
  (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2847
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 0) {
×
UNCOV
2848
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2849
    tscError("async bind param is still working, please try again later");
×
2850
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
×
2851
    return terrno;
×
2852
  }
2853
  (void)atomic_add_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2854
  (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2855

2856
  int code_s = taosStmt2AsyncBind(stmtAsyncBindThreadFunc, (void *)args);
×
2857
  if (code_s != TSDB_CODE_SUCCESS) {
×
UNCOV
2858
    terrno = code_s;
×
2859
    (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2860
    (void)taosThreadCondSignal(&(pStmt->asyncBindParam.waitCond));
×
2861
    (void)atomic_sub_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
2862
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2863
    tscError("async bind failed, code:%d , %s", code_s, tstrerror(code_s));
×
2864
  }
2865

2866
  return code_s;
×
2867
}
2868

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

2876
  return stmtExec2(stmt, affected_rows);
1,200,614✔
2877
}
2878

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

2886
  return stmtClose2(stmt);
237,596✔
2887
}
2888

2889
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
56✔
2890
  if (stmt == NULL || insert == NULL) {
56✔
UNCOV
2891
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2892
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2893
    return terrno;
×
2894
  }
2895
  *insert = stmt2IsInsert(stmt);
56✔
2896
  return TSDB_CODE_SUCCESS;
56✔
2897
}
2898

2899
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
17,704✔
2900
  if (stmt == NULL || count == NULL) {
17,704✔
2901
    tscError("NULL parameter for %s", __FUNCTION__);
192✔
2902
    terrno = TSDB_CODE_INVALID_PARA;
192✔
2903
    return terrno;
192✔
2904
  }
2905

2906
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
17,512✔
2907
  STMT2_DLOG_E("start to get fields");
17,512✔
2908

2909
  if (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type ||
17,512✔
2910
      (pStmt->sql.type == 0 && stmt2IsInsert(stmt))) {
16,168✔
2911
    return stmtGetStbColFields2(stmt, count, fields);
13,672✔
2912
  }
2913
  if (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt))) {
3,840✔
2914
    return stmtGetParamNum2(stmt, count);
3,648✔
2915
  }
2916

2917
  tscError("Invalid sql for stmt %s", pStmt->sql.sqlStr);
192✔
2918
  return TSDB_CODE_PAR_SYNTAX_ERROR;
192✔
2919
}
2920

2921
DLL_EXPORT void taos_stmt2_free_fields(TAOS_STMT2 *stmt, TAOS_FIELD_ALL *fields) {
12,904✔
2922
  (void)stmt;
2923
  if (!fields) return;
12,904✔
2924
  taosMemoryFree(fields);
9,448✔
2925
}
2926

2927
TAOS_RES *taos_stmt2_result(TAOS_STMT2 *stmt) {
6,544✔
2928
  if (stmt == NULL) {
6,544✔
UNCOV
2929
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2930
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2931
    return NULL;
×
2932
  }
2933

2934
  return stmtUseResult2(stmt);
6,544✔
2935
}
2936

2937
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmt2Errstr(stmt); }
5,952✔
2938

2939
int taos_set_conn_mode(TAOS *taos, int mode, int value) {
4,666✔
2940
  int32_t code = 0;
4,666✔
2941
  if (taos == NULL) {
4,666✔
UNCOV
2942
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2943
    return terrno;
×
2944
  }
2945

2946
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
4,666✔
2947
  if (NULL == pObj) {
4,666✔
UNCOV
2948
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2949
    tscError("invalid parameter for %s", __func__);
×
UNCOV
2950
    return terrno;
×
2951
  }
2952
  switch (mode) {
4,666✔
2953
    case TAOS_CONN_MODE_BI:
4,666✔
2954
      atomic_store_8(&pObj->biMode, value);
4,666✔
2955
      break;
4,666✔
UNCOV
2956
    default:
×
UNCOV
2957
      tscError("not supported mode.");
×
UNCOV
2958
      code = TSDB_CODE_INVALID_PARA;
×
2959
  }
2960
  releaseTscObj(*(int64_t *)taos);
4,666✔
2961
  return code;
4,666✔
2962
}
2963

UNCOV
2964
char *getBuildInfo() { return td_buildinfo; }
×
2965

UNCOV
2966
int32_t taos_connect_is_alive(TAOS *taos) {
×
2967
  int32_t code = 0, lino = 0;
×
UNCOV
2968
  if (taos == NULL) {
×
2969
    terrno = TSDB_CODE_INVALID_PARA;
×
2970
    return terrno;
×
2971
  }
2972

2973
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
UNCOV
2974
  if (NULL == pObj) {
×
UNCOV
2975
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2976
    tscError("invalid parameter for %s", __func__);
×
2977
    return terrno;
×
2978
  }
2979

2980
  code = tscCheckConnSessionMetric(pObj);
×
UNCOV
2981
  TAOS_CHECK_GOTO(code, &lino, _error);
×
2982

2983
_error:
×
2984
  releaseTscObj(*(int64_t *)taos);
×
2985

2986
  if (code != 0) {
×
2987
    tscError("taos conn failed to check alive, code:%d - %s", code, tstrerror(code));
×
2988
  }
2989

2990
  return code != 0 ? 0 : 1;
×
2991
}
UNCOV
2992
static int32_t buildInstanceRegisterSql(const SInstanceRegisterReq *req, char **ppSql, uint32_t *pLen) {
×
2993
  const char *action = (req->expire < 0) ? "UNREGISTER" : "REGISTER";
×
UNCOV
2994
  int32_t     len = 0;
×
2995

2996
  len += snprintf(NULL, 0, "%s INSTANCE '%s'", action, req->id);
×
2997
  if (req->type[0] != 0) {
×
UNCOV
2998
    len += snprintf(NULL, 0, " TYPE '%s'", req->type);
×
2999
  }
3000
  if (req->desc[0] != 0) {
×
3001
    len += snprintf(NULL, 0, " DESC '%s'", req->desc);
×
3002
  }
3003
  if (req->expire >= 0) {
×
3004
    len += snprintf(NULL, 0, " EXPIRE %d", req->expire);
×
3005
  }
3006

3007
  char *sql = taosMemoryMalloc((size_t)len + 1);
×
UNCOV
3008
  if (sql == NULL) {
×
UNCOV
3009
    return terrno;
×
3010
  }
3011

3012
  int32_t offset = snprintf(sql, (size_t)len + 1, "%s INSTANCE '%s'", action, req->id);
×
UNCOV
3013
  if (req->type[0] != 0) {
×
UNCOV
3014
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " TYPE '%s'", req->type);
×
3015
  }
3016
  if (req->desc[0] != 0) {
×
3017
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " DESC '%s'", req->desc);
×
3018
  }
3019
  if (req->expire >= 0) {
×
3020
    (void)snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " EXPIRE %d", req->expire);
×
3021
  }
3022

3023
  *ppSql = sql;
×
UNCOV
3024
  if (pLen != NULL) {
×
UNCOV
3025
    *pLen = (uint32_t)len;
×
3026
  }
3027
  return TSDB_CODE_SUCCESS;
×
3028
}
3029

3030
static int32_t sendInstanceRegisterReq(STscObj *pObj, const SInstanceRegisterReq *req) {
×
UNCOV
3031
  SRequestObj *pRequest = NULL;
×
UNCOV
3032
  int32_t      code = createRequest(pObj->id, TDMT_MND_REGISTER_INSTANCE, 0, &pRequest);
×
3033
  if (code != TSDB_CODE_SUCCESS) {
×
3034
    terrno = code;
×
3035
    return code;
×
3036
  }
3037

3038
  code = buildInstanceRegisterSql(req, &pRequest->sqlstr, (uint32_t *)&pRequest->sqlLen);
×
UNCOV
3039
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3040
    goto _cleanup;
×
3041
  }
3042

3043
  int32_t msgLen = tSerializeSInstanceRegisterReq(NULL, 0, (SInstanceRegisterReq *)req);
×
UNCOV
3044
  if (msgLen <= 0) {
×
UNCOV
3045
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3046
    goto _cleanup;
×
3047
  }
3048

3049
  void *pMsg = taosMemoryMalloc(msgLen);
×
UNCOV
3050
  if (pMsg == NULL) {
×
UNCOV
3051
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3052
    goto _cleanup;
×
3053
  }
3054

3055
  if (tSerializeSInstanceRegisterReq(pMsg, msgLen, (SInstanceRegisterReq *)req) < 0) {
×
UNCOV
3056
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3057
    taosMemoryFree(pMsg);
×
3058
    goto _cleanup;
×
3059
  }
3060

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

3064
  SMsgSendInfo *pSend = buildMsgInfoImpl(pRequest);
×
3065
  if (pSend == NULL) {
×
UNCOV
3066
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3067
    taosMemoryFree(pMsg);
×
3068
    pRequest->body.requestMsg.pData = NULL;
×
3069
    goto _cleanup;
×
3070
  }
3071

3072
  SEpSet epSet = getEpSet_s(&pObj->pAppInfo->mgmtEp);
×
UNCOV
3073
  code = asyncSendMsgToServer(pObj->pAppInfo->pTransporter, &epSet, NULL, pSend);
×
UNCOV
3074
  if (code != TSDB_CODE_SUCCESS) {
×
3075
    destroySendMsgInfo(pSend);
×
3076
    pRequest->body.requestMsg = (SDataBuf){0};
×
3077
    goto _cleanup;
×
3078
  }
3079

3080
  code = tsem_wait(&pRequest->body.rspSem);
×
UNCOV
3081
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3082
    code = terrno != 0 ? terrno : code;
×
3083
    goto _cleanup;
×
3084
  }
3085

3086
  code = pRequest->code;
×
UNCOV
3087
  terrno = code;
×
3088

3089
_cleanup:
×
3090
  destroyRequest(pRequest);
×
UNCOV
3091
  return code;
×
3092
}
3093

3094
static bool instanceRegisterRpcRfp(int32_t code, tmsg_t msgType) {
×
UNCOV
3095
  if (NEED_REDIRECT_ERROR(code)) {
×
UNCOV
3096
    return true;
×
3097
  } else if (code == TSDB_CODE_UTIL_QUEUE_OUT_OF_MEMORY || code == TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE ||
×
3098
             code == TSDB_CODE_SYN_WRITE_STALL || code == TSDB_CODE_SYN_PROPOSE_NOT_READY ||
×
3099
             code == TSDB_CODE_SYN_RESTORING) {
3100
    tscDebug("client msg type %s should retry since %s", TMSG_INFO(msgType), tstrerror(code));
×
3101
    return true;
×
3102
  } else {
3103
    return false;
×
3104
  }
3105
}
3106

3107
int32_t taos_register_instance(const char *id, const char *type, const char *desc, int32_t expire) {
5,320✔
3108
  if (id == NULL || id[0] == 0) {
5,320✔
UNCOV
3109
    return terrno = TSDB_CODE_INVALID_PARA;
×
3110
  }
3111

3112
  // Validate string lengths
3113
  size_t idLen = strlen(id);
5,320✔
3114
  if (idLen >= TSDB_INSTANCE_ID_LEN) {
5,320✔
UNCOV
3115
    tscError("instance id length %zu exceeds limit %d", idLen, TSDB_INSTANCE_ID_LEN - 1);
×
UNCOV
3116
    return terrno = TSDB_CODE_INVALID_PARA;
×
3117
  }
3118

3119
  if (type != NULL && type[0] != 0) {
5,320✔
3120
    size_t typeLen = strlen(type);
3,040✔
3121
    if (typeLen >= TSDB_INSTANCE_TYPE_LEN) {
3,040✔
UNCOV
3122
      tscError("instance type length %zu exceeds limit %d", typeLen, TSDB_INSTANCE_TYPE_LEN - 1);
×
UNCOV
3123
      return terrno = TSDB_CODE_INVALID_PARA;
×
3124
    }
3125
  }
3126

3127
  if (desc != NULL && desc[0] != 0) {
5,320✔
3128
    size_t descLen = strlen(desc);
3,040✔
3129
    if (descLen >= TSDB_INSTANCE_DESC_LEN) {
3,040✔
UNCOV
3130
      tscError("instance desc length %zu exceeds limit %d", descLen, TSDB_INSTANCE_DESC_LEN - 1);
×
UNCOV
3131
      return terrno = TSDB_CODE_INVALID_PARA;
×
3132
    }
3133
  }
3134

3135
  int32_t code = taos_init();
5,320✔
3136
  if (code != TSDB_CODE_SUCCESS) {
5,320✔
UNCOV
3137
    return code;
×
3138
  }
3139

3140
  SConfig *pCfg = taosGetCfg();
5,320✔
3141
  if (pCfg == NULL) {
5,320✔
UNCOV
3142
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3143
  }
3144

3145
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
5,320✔
3146
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
5,320✔
UNCOV
3147
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3148
  }
3149

3150
  SEp firstEp = {0};
5,320✔
3151
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
5,320✔
3152
  if (code != TSDB_CODE_SUCCESS) {
5,320✔
UNCOV
3153
    return terrno = code;
×
3154
  }
3155

3156
  void    *clientRpc = NULL;
5,320✔
3157
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
5,320✔
3158
  SRpcMsg  rpcMsg = {0};
5,320✔
3159
  SRpcMsg  rpcRsp = {0};
5,320✔
3160
  SRpcInit rpcInit = {0};
5,320✔
3161

3162
  rpcInit.label = "INST";
5,320✔
3163
  rpcInit.numOfThreads = 1;
5,320✔
3164
  rpcInit.cfp = NULL;
5,320✔
3165
  rpcInit.sessions = 16;
5,320✔
3166
  rpcInit.connType = TAOS_CONN_CLIENT;
5,320✔
3167
  rpcInit.idleTime = tsShellActivityTimer * 1000;
5,320✔
3168
  rpcInit.compressSize = tsCompressMsgSize;
5,320✔
3169
  rpcInit.user = TSDB_DEFAULT_USER;
5,320✔
3170

3171
  rpcInit.rfp = instanceRegisterRpcRfp;
5,320✔
3172
  rpcInit.retryMinInterval = tsRedirectPeriod;
5,320✔
3173
  rpcInit.retryStepFactor = tsRedirectFactor;
5,320✔
3174
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
5,320✔
3175
  rpcInit.retryMaxTimeout =
5,320✔
3176
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3177

3178
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
5,320✔
3179
  connLimitNum = TMAX(connLimitNum, 10);
5,320✔
3180
  connLimitNum = TMIN(connLimitNum, 500);
5,320✔
3181
  rpcInit.connLimitNum = connLimitNum;
5,320✔
3182
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
5,320✔
3183
  rpcInit.readTimeout = tsReadTimeout;
5,320✔
3184
  rpcInit.ipv6 = tsEnableIpv6;
5,320✔
3185
  rpcInit.enableSSL = tsEnableTLS;
5,320✔
3186

3187
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
5,320✔
3188
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
5,320✔
3189
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
5,320✔
3190
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
5,320✔
3191
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
5,320✔
3192

3193
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
5,320✔
3194
  if (code != TSDB_CODE_SUCCESS) {
5,320✔
UNCOV
3195
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
UNCOV
3196
    return code;
×
3197
  }
3198

3199
  clientRpc = rpcOpen(&rpcInit);
5,320✔
3200
  if (clientRpc == NULL) {
5,320✔
UNCOV
3201
    code = terrno;
×
UNCOV
3202
    tscError("failed to init instance register client since %s", tstrerror(code));
×
UNCOV
3203
    return code;
×
3204
  }
3205

3206
  // Prepare epSet
3207
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
5,320✔
3208
  epSet.eps[0].port = firstEp.port;
5,320✔
3209

3210
  // Prepare request
3211
  SInstanceRegisterReq req = {0};
5,320✔
3212
  tstrncpy(req.id, id, sizeof(req.id));
5,320✔
3213
  if (type != NULL && type[0] != 0) {
5,320✔
3214
    tstrncpy(req.type, type, sizeof(req.type));
3,040✔
3215
  }
3216
  if (desc != NULL && desc[0] != 0) {
5,320✔
3217
    tstrncpy(req.desc, desc, sizeof(req.desc));
3,040✔
3218
  }
3219
  req.expire = expire;
5,320✔
3220

3221
  int32_t contLen = tSerializeSInstanceRegisterReq(NULL, 0, &req);
5,320✔
3222
  if (contLen <= 0) {
5,320✔
UNCOV
3223
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3224
    rpcClose(clientRpc);
×
UNCOV
3225
    return code;
×
3226
  }
3227

3228
  void *pCont = rpcMallocCont(contLen);
5,320✔
3229
  if (pCont == NULL) {
5,320✔
UNCOV
3230
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3231
    rpcClose(clientRpc);
×
UNCOV
3232
    return code;
×
3233
  }
3234

3235
  if (tSerializeSInstanceRegisterReq(pCont, contLen, &req) < 0) {
5,320✔
UNCOV
3236
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3237
    rpcFreeCont(pCont);
×
UNCOV
3238
    rpcClose(clientRpc);
×
3239
    return code;
×
3240
  }
3241

3242
  rpcMsg.pCont = pCont;
5,320✔
3243
  rpcMsg.contLen = contLen;
5,320✔
3244
  rpcMsg.msgType = TDMT_MND_REGISTER_INSTANCE;
5,320✔
3245
  rpcMsg.info.ahandle = (void *)0x9528;  // Different magic number from server status
5,320✔
3246
  rpcMsg.info.notFreeAhandle = 1;
5,320✔
3247

3248
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
5,320✔
3249
  if (TSDB_CODE_SUCCESS != code) {
5,320✔
UNCOV
3250
    tscError("failed to send instance register req since %s", tstrerror(code));
×
3251
    // rpcSendRecv failed, pCont may not be freed, but check _RETURN1 path
3252
    // In error path, rpcSendRecv may free pCont, but we free it here to be safe
3253
    rpcClose(clientRpc);
×
UNCOV
3254
    return code;
×
3255
  }
3256

3257
  if (rpcRsp.code != 0) {
5,320✔
UNCOV
3258
    code = rpcRsp.code;
×
UNCOV
3259
    tscError("instance register failed, code:%s", tstrerror(code));
×
3260
  } else {
3261
    code = TSDB_CODE_SUCCESS;
5,320✔
3262
  }
3263

3264
  if (rpcRsp.pCont != NULL) {
5,320✔
3265
    rpcFreeCont(rpcRsp.pCont);
5,320✔
3266
  }
3267
  rpcClose(clientRpc);
5,320✔
3268

3269
  terrno = code;
5,320✔
3270
  return code;
5,320✔
3271
}
3272

3273
int32_t taos_list_instances(const char *filter_type, char ***pList, int32_t *pCount) {
4,180✔
3274
  if (pList == NULL || pCount == NULL) {
4,180✔
UNCOV
3275
    return TSDB_CODE_INVALID_PARA;
×
3276
  }
3277

3278
  int32_t code = taos_init();
4,180✔
3279
  if (code != TSDB_CODE_SUCCESS) {
4,180✔
UNCOV
3280
    terrno = code;
×
UNCOV
3281
    return code;
×
3282
  }
3283

3284
  SConfig *pCfg = taosGetCfg();
4,180✔
3285
  if (pCfg == NULL) {
4,180✔
UNCOV
3286
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
UNCOV
3287
    return TSDB_CODE_CFG_NOT_FOUND;
×
3288
  }
3289

3290
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
4,180✔
3291
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
4,180✔
UNCOV
3292
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
UNCOV
3293
    return TSDB_CODE_CFG_NOT_FOUND;
×
3294
  }
3295

3296
  SEp firstEp = {0};
4,180✔
3297
  code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
4,180✔
3298
  if (code != TSDB_CODE_SUCCESS) {
4,180✔
UNCOV
3299
    terrno = code;
×
UNCOV
3300
    return code;
×
3301
  }
3302

3303
  // Initialize RPC connection (similar to taos_register_instance)
3304
  void    *clientRpc = NULL;
4,180✔
3305
  SEpSet   epSet = {.inUse = 0, .numOfEps = 1};
4,180✔
3306
  SRpcMsg  rpcMsg = {0};
4,180✔
3307
  SRpcMsg  rpcRsp = {0};
4,180✔
3308
  SRpcInit rpcInit = {0};
4,180✔
3309

3310
  rpcInit.label = "LIST";
4,180✔
3311
  rpcInit.numOfThreads = 1;
4,180✔
3312
  rpcInit.cfp = NULL;
4,180✔
3313
  rpcInit.sessions = 16;
4,180✔
3314
  rpcInit.connType = TAOS_CONN_CLIENT;
4,180✔
3315
  rpcInit.idleTime = tsShellActivityTimer * 1000;
4,180✔
3316
  rpcInit.compressSize = tsCompressMsgSize;
4,180✔
3317
  rpcInit.user = TSDB_DEFAULT_USER;
4,180✔
3318

3319
  rpcInit.rfp = instanceRegisterRpcRfp;
4,180✔
3320
  rpcInit.retryMinInterval = tsRedirectPeriod;
4,180✔
3321
  rpcInit.retryStepFactor = tsRedirectFactor;
4,180✔
3322
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
4,180✔
3323
  rpcInit.retryMaxTimeout =
4,180✔
3324
      tsMaxRetryWaitTime;  // Use a special user for instance registration (can be configured for whitelist)
3325

3326
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
4,180✔
3327
  connLimitNum = TMAX(connLimitNum, 10);
4,180✔
3328
  connLimitNum = TMIN(connLimitNum, 500);
4,180✔
3329
  rpcInit.connLimitNum = connLimitNum;
4,180✔
3330
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
4,180✔
3331
  rpcInit.readTimeout = tsReadTimeout;
4,180✔
3332
  rpcInit.ipv6 = tsEnableIpv6;
4,180✔
3333
  rpcInit.enableSSL = tsEnableTLS;
4,180✔
3334

3335
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
4,180✔
3336
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
4,180✔
3337
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
4,180✔
3338
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
4,180✔
3339
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
4,180✔
3340

3341
  code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
4,180✔
3342
  if (code != TSDB_CODE_SUCCESS) {
4,180✔
UNCOV
3343
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
UNCOV
3344
    return code;
×
3345
  }
3346

3347
  clientRpc = rpcOpen(&rpcInit);
4,180✔
3348
  if (clientRpc == NULL) {
4,180✔
UNCOV
3349
    code = terrno;
×
UNCOV
3350
    tscError("failed to init instance list client since %s", tstrerror(code));
×
UNCOV
3351
    terrno = code;
×
3352
    return code;
×
3353
  }
3354

3355
  tstrncpy(epSet.eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
4,180✔
3356
  epSet.eps[0].port = firstEp.port;
4,180✔
3357
  SInstanceListReq req = {0};
4,180✔
3358
  if (filter_type != NULL && filter_type[0] != 0) {
4,180✔
3359
    tstrncpy(req.filter_type, filter_type, sizeof(req.filter_type));
2,660✔
3360
  }
3361

3362
  // Serialize request to get required length
3363
  int32_t contLen = tSerializeSInstanceListReq(NULL, 0, &req);
4,180✔
3364
  if (contLen <= 0) {
4,180✔
UNCOV
3365
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3366
    rpcClose(clientRpc);
×
UNCOV
3367
    terrno = code;
×
3368
    return code;
×
3369
  }
3370

3371
  // Allocate RPC message buffer (includes message header overhead)
3372
  void *pCont = rpcMallocCont(contLen);
4,180✔
3373
  if (pCont == NULL) {
4,180✔
UNCOV
3374
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3375
    rpcClose(clientRpc);
×
UNCOV
3376
    terrno = code;
×
3377
    return code;
×
3378
  }
3379

3380
  // Serialize request into the content part (after message header)
3381
  if (tSerializeSInstanceListReq(pCont, contLen, &req) < 0) {
4,180✔
UNCOV
3382
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3383
    rpcFreeCont(pCont);
×
UNCOV
3384
    rpcClose(clientRpc);
×
3385
    terrno = code;
×
3386
    return code;
×
3387
  }
3388

3389
  rpcMsg.pCont = pCont;
4,180✔
3390
  rpcMsg.contLen = contLen;
4,180✔
3391
  rpcMsg.msgType = TDMT_MND_LIST_INSTANCES;
4,180✔
3392
  rpcMsg.info.ahandle = (void *)0x9529;  // Different magic number from register
4,180✔
3393
  rpcMsg.info.notFreeAhandle = 1;
4,180✔
3394

3395
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
4,180✔
3396
  if (TSDB_CODE_SUCCESS != code) {
4,180✔
UNCOV
3397
    tscError("failed to send instance list req since %s", tstrerror(code));
×
UNCOV
3398
    rpcFreeCont(pCont);
×
UNCOV
3399
    rpcClose(clientRpc);
×
3400
    terrno = code;
×
3401
    return code;
×
3402
  }
3403

3404
  // Check response - rpcRsp.code contains the result code from mnode
3405
  if (rpcRsp.code != 0) {
4,180✔
UNCOV
3406
    code = rpcRsp.code;
×
UNCOV
3407
    tscError("instance list failed, code:%s", tstrerror(code));
×
UNCOV
3408
    if (rpcRsp.pCont != NULL) {
×
3409
      rpcFreeCont(rpcRsp.pCont);
×
3410
    }
3411
    rpcClose(clientRpc);
×
3412
    terrno = code;
×
UNCOV
3413
    return code;
×
3414
  }
3415

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

3444
  if (rpcRsp.pCont != NULL) {
4,180✔
3445
    rpcFreeCont(rpcRsp.pCont);
4,180✔
3446
  }
3447
  rpcClose(clientRpc);
4,180✔
3448

3449
  return TSDB_CODE_SUCCESS;
4,180✔
3450
}
3451

3452
void taos_free_instances(char ***pList, int32_t count) {
3,040✔
3453
  if (pList == NULL || *pList == NULL || count <= 0) {
3,040✔
UNCOV
3454
    return;
×
3455
  }
3456

3457
  // Free each string in the array
3458
  for (int32_t i = 0; i < count; i++) {
9,500✔
3459
    if ((*pList)[i] != NULL) {
6,460✔
3460
      taosMemoryFree((*pList)[i]);
6,460✔
3461
      (*pList)[i] = NULL;
6,460✔
3462
    }
3463
  }
3464

3465
  // Free the array itself
3466
  taosMemoryFree(*pList);
3,040✔
3467
  *pList = NULL;
3,040✔
3468
}
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