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

taosdata / TDengine / #5034

24 Apr 2026 11:25AM UTC coverage: 73.058%. Remained the same
#5034

push

travis-ci

web-flow
merge: from main to 3.0 branch #35224

merge: from main to 3.0 branch[manual-only]

1336 of 1975 new or added lines in 48 files covered. (67.65%)

14149 existing lines in 164 files now uncovered.

275896 of 377640 relevant lines covered (73.06%)

132944440.29 hits per line

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

52.27
/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 CLIENT_CLEANUP_WAIT_TIMEOUT_MS 10000
40

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

45
static int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper);
46

47
static int32_t waitRefSetToBaseCount(int32_t rsetId, const char *name, int64_t startMs, int64_t timeoutMs) {
3,115,806✔
48
  if (rsetId < 0) {
3,115,806✔
49
    return TSDB_CODE_SUCCESS;
86✔
50
  }
51

52
  while (true) {
927,556,701✔
53
    int32_t count = 0;
930,672,421✔
54
    int32_t code = taosGetRefSetCount(rsetId, &count);
930,672,421✔
55
    if (code != TSDB_CODE_SUCCESS) {
930,672,421✔
NEW
56
      tscWarn("failed to inspect %s ref pool:%d before cleanup, code:%s", name, rsetId, tstrerror(code));
×
57
      return code;
32,050✔
58
    }
59

60
    if (count <= 1) {
930,672,421✔
61
      return TSDB_CODE_SUCCESS;
2,898,444✔
62
    }
63

64
    if (timeoutMs >= 0 && taosGetTimestampMs() - startMs >= timeoutMs) {
1,855,547,954✔
65
      tscWarn("timeout waiting for %s ref pool:%d to drain, count:%d", name, rsetId, count);
217,276✔
66
      return TSDB_CODE_TIMEOUT_ERROR;
217,276✔
67
    }
68

69
    taosMsleep(1);
927,556,701✔
70
  }
71
}
72

73
int taos_options(TSDB_OPTION option, const void *arg, ...) {
92,238,192✔
74
  if (arg == NULL) {
92,238,192✔
UNCOV
75
    return TSDB_CODE_INVALID_PARA;
×
76
  }
77
  static int32_t lock = 0;
78

79
  for (int i = 1; atomic_val_compare_exchange_32(&lock, 0, 1) != 0; ++i) {
2,147,483,647✔
80
    if (i % 1000 == 0) {
2,147,483,647✔
81
      (void)sched_yield();
11,368,271✔
82
    }
83
  }
84

85
  int ret = taos_options_imp(option, (const char *)arg);
16,418,355✔
86
  atomic_store_32(&lock, 0);
92,243,179✔
87
  return ret;
92,243,179✔
88
}
89

90
#if !defined(WINDOWS) && !defined(TD_ASTRA)
91
static void freeTz(void *p) {
2,352✔
92
  timezone_t tz = *(timezone_t *)p;
2,352✔
93
  tzfree(tz);
2,352✔
94
}
2,352✔
95
#endif
96

97
int32_t tzInit() {
1,557,860✔
98
#if !defined(WINDOWS) && !defined(TD_ASTRA)
99
  pTimezoneMap = taosHashInit(0, MurmurHash3_32, false, HASH_ENTRY_LOCK);
1,557,860✔
100
  if (pTimezoneMap == NULL) {
1,557,860✔
UNCOV
101
    return terrno;
×
102
  }
103
  taosHashSetFreeFp(pTimezoneMap, freeTz);
1,557,860✔
104

105
  pTimezoneNameMap = taosHashInit(0, taosIntHash_64, false, HASH_ENTRY_LOCK);
1,557,860✔
106
  if (pTimezoneNameMap == NULL) {
1,557,860✔
UNCOV
107
    return terrno;
×
108
  }
109
#endif
110
  return 0;
1,557,860✔
111
}
112

113
void tzCleanup() {
1,557,903✔
114
#if !defined(WINDOWS) && !defined(TD_ASTRA)
115
  taosHashCleanup(pTimezoneMap);
1,557,903✔
116
  taosHashCleanup(pTimezoneNameMap);
1,557,903✔
117
#endif
118
}
1,557,903✔
119

120
#if !defined(WINDOWS) && !defined(TD_ASTRA)
121
static timezone_t setConnnectionTz(const char *val) {
3,920✔
122
  timezone_t  tz = NULL;
3,920✔
123
  timezone_t *tmp = taosHashGet(pTimezoneMap, val, strlen(val));
3,920✔
124
  if (tmp != NULL && *tmp != NULL) {
3,920✔
125
    tz = *tmp;
1,568✔
126
    goto END;
1,568✔
127
  }
128

129
  tscDebug("set timezone to %s", val);
2,352✔
130
  tz = tzalloc(val);
2,352✔
131
  if (tz == NULL) {
2,352✔
132
    tscWarn("%s unknown timezone %s change to UTC", __func__, val);
196✔
133
    tz = tzalloc("UTC");
196✔
134
    if (tz == NULL) {
196✔
UNCOV
135
      tscError("%s set timezone UTC error", __func__);
×
UNCOV
136
      terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
UNCOV
137
      goto END;
×
138
    }
139
  }
140
  int32_t code = taosHashPut(pTimezoneMap, val, strlen(val), &tz, sizeof(timezone_t));
2,352✔
141
  if (code != 0) {
2,352✔
UNCOV
142
    tscError("%s put timezone to tz map error:%d", __func__, code);
×
UNCOV
143
    tzfree(tz);
×
UNCOV
144
    tz = NULL;
×
UNCOV
145
    goto END;
×
146
  }
147

148
  time_t tx1 = taosGetTimestampSec();
2,352✔
149
  char   output[TD_TIMEZONE_LEN] = {0};
2,352✔
150
  code = taosFormatTimezoneStr(tx1, val, tz, output);
2,352✔
151
  if (code == 0) {
2,352✔
152
    code = taosHashPut(pTimezoneNameMap, &tz, sizeof(timezone_t), output, strlen(output) + 1);
2,352✔
153
  }
154
  if (code != 0) {
2,352✔
UNCOV
155
    tscError("failed to put timezone %s to map", val);
×
156
  }
157

158
END:
2,352✔
159
  return tz;
3,920✔
160
}
161
#endif
162

163
static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, const char *val) {
9,370✔
164
  if (taos == NULL) {
9,370✔
165
    return terrno = TSDB_CODE_INVALID_PARA;
196✔
166
  }
167

168
#ifdef WINDOWS
169
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE) {
170
    return terrno = TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS;
171
  }
172
#endif
173

174
  if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION) {
9,174✔
175
    return terrno = TSDB_CODE_INVALID_PARA;
196✔
176
  }
177

178
  int32_t code = taos_init();
8,978✔
179
  // initialize global config
180
  if (code != 0) {
8,978✔
UNCOV
181
    return terrno = code;
×
182
  }
183

184
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
8,978✔
185
  if (NULL == pObj) {
8,978✔
UNCOV
186
    tscError("invalid parameter for %s", __func__);
×
UNCOV
187
    return terrno;
×
188
  }
189

190
  if (option == TSDB_OPTION_CONNECTION_CLEAR) {
8,978✔
191
    val = NULL;
196✔
192
  }
193

194
#ifndef DISALLOW_NCHAR_WITHOUT_ICONV
195
  if (option == TSDB_OPTION_CONNECTION_CHARSET || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,978✔
196
    if (val != NULL) {
1,568✔
197
      if (!taosValidateEncodec(val)) {
980✔
198
        code = terrno;
196✔
199
        goto END;
196✔
200
      }
201
      void *tmp = taosConvInit(val);
784✔
202
      if (tmp == NULL) {
784✔
203
        code = terrno;
196✔
204
        goto END;
196✔
205
      }
206
      pObj->optionInfo.charsetCxt = tmp;
588✔
207
    } else {
208
      pObj->optionInfo.charsetCxt = NULL;
588✔
209
    }
210
  }
211
#endif
212
  if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,586✔
213
#if !defined(WINDOWS) && !defined(TD_ASTRA)
214
    if (val != NULL) {
4,312✔
215
      if (val[0] == 0) {
3,920✔
216
        val = "UTC";
196✔
217
      }
218
      timezone_t tz = setConnnectionTz(val);
3,920✔
219
      if (tz == NULL) {
3,920✔
UNCOV
220
        code = terrno;
×
UNCOV
221
        goto END;
×
222
      }
223
      pObj->optionInfo.timezone = tz;
3,920✔
224
    } else {
225
      pObj->optionInfo.timezone = NULL;
392✔
226
    }
227
#endif
228
  }
229

230
  if (option == TSDB_OPTION_CONNECTION_USER_APP || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,586✔
231
    if (val != NULL) {
1,059✔
232
      tstrncpy(pObj->optionInfo.userApp, val, sizeof(pObj->optionInfo.userApp));
667✔
233
    } else {
234
      pObj->optionInfo.userApp[0] = 0;
392✔
235
    }
236
  }
237

238
  if (option == TSDB_OPTION_CONNECTION_CONNECTOR_INFO || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,586✔
239
    if (val != NULL) {
1,059✔
240
      tstrncpy(pObj->optionInfo.cInfo, val, sizeof(pObj->optionInfo.cInfo));
667✔
241
    } else {
242
      pObj->optionInfo.cInfo[0] = 0;
392✔
243
    }
244
  }
245

246
  if (option == TSDB_OPTION_CONNECTION_USER_IP || option == TSDB_OPTION_CONNECTION_CLEAR) {
8,586✔
247
    SIpRange dualIp = {0};
1,764✔
248
    if (val != NULL) {
1,764✔
249
      pObj->optionInfo.userIp = taosInetAddr(val);
1,176✔
250
      SIpAddr addr = {0};
1,176✔
251
      code = taosGetIpFromFqdn(tsEnableIpv6, val, &addr);
1,176✔
252
      if (code == 0) {
1,176✔
253
        code = tIpStrToUint(&addr, &pObj->optionInfo.userDualIp);
588✔
254
      }
255
      if (code != 0) {
1,176✔
256
        tscError("ipv6 flag %d failed to convert user ip %s to dual ip since %s", tsEnableIpv6 ? 1 : 0, val,
588✔
257
                 tstrerror(code));
258
        pObj->optionInfo.userIp = INADDR_NONE;
588✔
259
        pObj->optionInfo.userDualIp = dualIp;
588✔
260
        code = 0;
588✔
261
      }
262
    } else {
263
      pObj->optionInfo.userIp = INADDR_NONE;
588✔
264
      pObj->optionInfo.userDualIp = dualIp;
588✔
265
    }
266
  }
267

268
END:
6,822✔
269
  releaseTscObj(*(int64_t *)taos);
8,978✔
270
  return terrno = code;
8,978✔
271
}
272

273
int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...) {
9,370✔
274
  return setConnectionOption(taos, option, (const char *)arg);
9,370✔
275
}
276

277
// this function may be called by user or system, or by both simultaneously.
278
void taos_cleanup(void) {
1,558,779✔
279
  tscInfo("start to cleanup client environment");
1,558,779✔
280
  if (!beginAsyncWorkShutdown()) {
1,558,779✔
281
    return;
876✔
282
  }
283

284
  int64_t cleanupStartMs = taosGetTimestampMs();
1,557,903✔
285

286
  if (TSDB_CODE_SUCCESS != waitRefSetToBaseCount(clientReqRefPool, "request", cleanupStartMs, CLIENT_CLEANUP_WAIT_TIMEOUT_MS)) {
1,557,903✔
287
    tscWarn("request ref pool did not drain cleanly before cleanup continues");
104,127✔
288
  }
289

290
  monitorClose();
1,557,903✔
291
  tscStopCrashReport();
1,557,903✔
292

293
  hbMgrCleanUp();
1,557,903✔
294

295
  catalogDestroy();
1,557,903✔
296
  schedulerDestroy();
1,557,903✔
297

298
  fmFuncMgtDestroy();
1,557,903✔
299
  qCleanupKeywordsTable();
1,557,903✔
300

301
#if !defined(WINDOWS) && !defined(TD_ASTRA)
302
  tzCleanup();
1,557,903✔
303
#endif
304
  tmqMgmtClose();
1,557,903✔
305

306
  int32_t id = clientReqRefPool;
1,557,903✔
307
  clientReqRefPool = -1;
1,557,903✔
308
  taosCloseRef(id);
1,557,903✔
309

310
  if (TSDB_CODE_SUCCESS != waitRefSetToBaseCount(clientConnRefPool, "connection", cleanupStartMs, CLIENT_CLEANUP_WAIT_TIMEOUT_MS)) {
1,557,903✔
311
    tscWarn("connection ref pool did not drain cleanly before cleanup continues");
113,149✔
312
  }
313

314
  id = clientConnRefPool;
1,557,903✔
315
  clientConnRefPool = -1;
1,557,903✔
316
  taosCloseRef(id);
1,557,903✔
317

318
  nodesDestroyAllocatorSet();
1,557,903✔
319
  cleanupAppInfo();
1,557,903✔
320
  rpcCleanup();
1,557,903✔
321
  tscDebug("rpc cleanup");
1,557,903✔
322

323
  if (TSDB_CODE_SUCCESS != cleanupTaskQueue()) {
1,557,903✔
UNCOV
324
    tscWarn("failed to cleanup task queue");
×
325
  }
326

327
  sessMgtDestroy();
1,557,903✔
328

329
  taosConvDestroy();
1,557,903✔
330
  DestroyRegexCache();
1,557,903✔
331
#ifdef TAOSD_INTEGRATED
332
  shellStopDaemon();
333
#endif
334
  tscInfo("all local resources released");
1,557,903✔
335
  taosCleanupCfg();
1,557,903✔
336
#ifndef TAOSD_INTEGRATED
337
  taosCloseLog();
1,557,903✔
338
#endif
339
}
340

341
static setConfRet taos_set_config_imp(const char *config) {
17✔
342
  setConfRet ret = {SET_CONF_RET_SUCC, {0}};
17✔
343
  // TODO: need re-implementation
344
  return ret;
17✔
345
}
346

347
setConfRet taos_set_config(const char *config) {
17✔
348
  // TODO  pthread_mutex_lock(&setConfMutex);
349
  setConfRet ret = taos_set_config_imp(config);
17✔
350
  //  pthread_mutex_unlock(&setConfMutex);
351
  return ret;
17✔
352
}
353

354
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
94,506,821✔
355
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
94,506,821✔
356
  if (user == NULL) {
94,506,566✔
357
    user = TSDB_DEFAULT_USER;
186,712✔
358
  }
359

360
  if (pass == NULL) {
94,506,566✔
361
    pass = TSDB_DEFAULT_PASS;
186,712✔
362
  }
363

364
  STscObj *pObj = NULL;
94,506,566✔
365
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY, &pObj);
94,506,566✔
366
  if (TSDB_CODE_SUCCESS == code) {
94,490,777✔
367
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
94,484,402✔
368
    if (NULL == rid) {
94,487,773✔
UNCOV
369
      tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db);
×
UNCOV
370
      return NULL;
×
371
    }
372
    *rid = pObj->id;
94,487,773✔
373
    return (TAOS *)rid;
94,487,837✔
374
  } else {
375
    terrno = code;
14,293✔
376
  }
377

378
  return NULL;
14,477✔
379
}
380

381
void taos_set_option(OPTIONS *options, const char *key, const char *value) {
1,176✔
382
  if (options == NULL || key == NULL || value == NULL) {
1,176✔
UNCOV
383
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
384
    tscError("taos_set_option invalid parameter, options: %p, key: %p, value: %p", options, key, value);
×
UNCOV
385
    return;
×
386
  }
387

388
  size_t count = (size_t)options->count;
1,176✔
389
  size_t len = sizeof(options->keys) / sizeof(options->keys[0]);
1,176✔
390
  if (count >= len) {
1,176✔
UNCOV
391
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
392
    tscError("taos_set_option overflow, count: %zu, reached capacity: %zu", count, len);
×
UNCOV
393
    return;
×
394
  }
395

396
  options->keys[count] = key;
1,176✔
397
  options->values[count] = value;
1,176✔
398
  options->count = (uint16_t)(count + 1);
1,176✔
399
}
400

401
static int set_connection_option_or_close(TAOS *taos, TSDB_OPTION_CONNECTION option, const char *value) {
980✔
402
  if (value == NULL) return TSDB_CODE_SUCCESS;
980✔
403
  int code = taos_options_connection(taos, option, value);
×
404
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
405
    tscError("failed to set option(%d): %s", (int)option, value);
×
UNCOV
406
    taos_close(taos);
×
UNCOV
407
    return code;
×
408
  }
UNCOV
409
  return TSDB_CODE_SUCCESS;
×
410
}
411

412
TAOS *taos_connect_with(const OPTIONS *options) {
196✔
413
  const char *ip = NULL;
196✔
414
  const char *user = NULL;
196✔
415
  const char *pass = NULL;
196✔
416
  const char *db = NULL;
196✔
417
  uint16_t    port = 0;
196✔
418

419
  const char *charset = NULL;
196✔
420
  const char *timezone = NULL;
196✔
421
  const char *userIp = NULL;
196✔
422
  const char *userApp = NULL;
196✔
423
  const char *connectorInfo = NULL;
196✔
424

425
  if (options && options->count > 0) {
196✔
426
    size_t count = (size_t)options->count;
196✔
427
    for (size_t i = 0; i < count; ++i) {
1,372✔
428
      const char *key = options->keys[i];
1,176✔
429
      const char *value = options->values[i];
1,176✔
430
      if (key == NULL || value == NULL) {
1,176✔
UNCOV
431
        tscWarn("taos_connect_with option key or value is NULL, index: %zu", i);
×
UNCOV
432
        continue;
×
433
      }
434

435
      if (strcmp(key, "ip") == 0) {
1,176✔
436
        ip = value;
196✔
437
      } else if (strcmp(key, "user") == 0) {
980✔
438
        user = value;
196✔
439
      } else if (strcmp(key, "pass") == 0) {
784✔
440
        pass = value;
196✔
441
      } else if (strcmp(key, "db") == 0) {
588✔
UNCOV
442
        db = value;
×
443
      } else if (strcmp(key, "port") == 0) {
588✔
444
        port = (uint16_t)taosStr2Int32(value, NULL, 10);
196✔
445
      } else if (strcmp(key, "charset") == 0) {
392✔
UNCOV
446
        charset = value;
×
447
      } else if (strcmp(key, "timezone") == 0) {
392✔
UNCOV
448
        timezone = value;
×
449
      } else if (strcmp(key, "userIp") == 0) {
392✔
UNCOV
450
        userIp = value;
×
451
      } else if (strcmp(key, "userApp") == 0) {
392✔
UNCOV
452
        userApp = value;
×
453
      } else if (strcmp(key, "connectorInfo") == 0) {
392✔
UNCOV
454
        connectorInfo = value;
×
455
      } else {
456
        tscWarn("taos_connect_with unknown option key: %s", key);
392✔
457
      }
458
    }
459
  }
460

461
  TAOS *taos = taos_connect(ip, user, pass, db, port);
196✔
462
  if (taos == NULL) return NULL;
196✔
463

464
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_CHARSET, charset) != TSDB_CODE_SUCCESS) return NULL;
196✔
465
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_TIMEZONE, timezone) != TSDB_CODE_SUCCESS) return NULL;
196✔
466
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_USER_IP, userIp) != TSDB_CODE_SUCCESS) return NULL;
196✔
467
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_USER_APP, userApp) != TSDB_CODE_SUCCESS) return NULL;
196✔
468
  if (set_connection_option_or_close(taos, TSDB_OPTION_CONNECTION_CONNECTOR_INFO, connectorInfo) != TSDB_CODE_SUCCESS)
196✔
UNCOV
469
    return NULL;
×
470

471
  return taos;
196✔
472
}
473

UNCOV
474
TAOS *taos_connect_with_dsn(const char *dsn) {
×
UNCOV
475
  terrno = TSDB_CODE_OPS_NOT_SUPPORT;
×
UNCOV
476
  tscError("taos_connect_with_dsn not supported");
×
UNCOV
477
  return NULL;
×
478
}
479

480
int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type) {
1,400✔
481
  if (taos == NULL) {
1,400✔
UNCOV
482
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
483
    return terrno;
×
484
  }
485

486
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
1,400✔
487
  if (NULL == pObj) {
1,400✔
UNCOV
488
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
489
    tscError("invalid parameter for %s", __func__);
×
UNCOV
490
    return terrno;
×
491
  }
492

493
  switch (type) {
1,400✔
494
    case TAOS_NOTIFY_PASSVER: {
400✔
495
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
400✔
496
      pObj->passInfo.fp = fp;
400✔
497
      pObj->passInfo.param = param;
400✔
498
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
400✔
499
      break;
400✔
500
    }
UNCOV
501
    case TAOS_NOTIFY_WHITELIST_VER: {
×
UNCOV
502
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
503
      pObj->whiteListInfo.fp = fp;
×
UNCOV
504
      pObj->whiteListInfo.param = param;
×
UNCOV
505
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
UNCOV
506
      break;
×
507
    }
508
    case TAOS_NOTIFY_USER_DROPPED: {
1,000✔
509
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
1,000✔
510
      pObj->userDroppedInfo.fp = fp;
1,000✔
511
      pObj->userDroppedInfo.param = param;
1,000✔
512
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
1,000✔
513
      break;
1,000✔
514
    }
UNCOV
515
    case TAOS_NOTIFY_DATETIME_WHITELIST_VER: {
×
516
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
517
      pObj->dateTimeWhiteListInfo.fp = fp;
×
UNCOV
518
      pObj->dateTimeWhiteListInfo.param = param;
×
UNCOV
519
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
UNCOV
520
      break;
×
521
    }
522
    case TAOS_NOTIFY_TOKEN: {
×
523
      TSC_ERR_RET(taosThreadMutexLock(&pObj->mutex));
×
524
      pObj->tokenNotifyInfo.fp = fp;
×
UNCOV
525
      pObj->tokenNotifyInfo.param = param;
×
UNCOV
526
      TSC_ERR_RET(taosThreadMutexUnlock(&pObj->mutex));
×
UNCOV
527
      break;
×
528
    }
UNCOV
529
    default: {
×
UNCOV
530
      terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
531
      releaseTscObj(*(int64_t *)taos);
×
UNCOV
532
      return terrno;
×
533
    }
534
  }
535

536
  releaseTscObj(*(int64_t *)taos);
1,400✔
537
  return 0;
1,400✔
538
}
539

540
typedef struct SFetchWhiteListInfo {
541
  int64_t                     connId;
542
  __taos_async_whitelist_fn_t userCbFn;
543
  void                       *userParam;
544
} SFetchWhiteListInfo;
545

UNCOV
546
int32_t fetchWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
UNCOV
547
  SFetchWhiteListInfo *pInfo = (SFetchWhiteListInfo *)param;
×
UNCOV
548
  TAOS                *taos = &pInfo->connId;
×
549
  if (code != TSDB_CODE_SUCCESS) {
×
550
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
551
    taosMemoryFree(pMsg->pData);
×
552
    taosMemoryFree(pMsg->pEpSet);
×
553
    taosMemoryFree(pInfo);
×
554
    return code;
×
555
  }
556

557
  SGetUserIpWhiteListRsp wlRsp;
×
558
  if (TSDB_CODE_SUCCESS != tDeserializeSGetUserIpWhiteListRsp(pMsg->pData, pMsg->len, &wlRsp)) {
×
559
    taosMemoryFree(pMsg->pData);
×
560
    taosMemoryFree(pMsg->pEpSet);
×
561
    taosMemoryFree(pInfo);
×
UNCOV
562
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
563
    return terrno;
×
564
  }
565

566
  uint64_t *pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(uint64_t));
×
UNCOV
567
  if (pWhiteLists == NULL) {
×
UNCOV
568
    taosMemoryFree(pMsg->pData);
×
UNCOV
569
    taosMemoryFree(pMsg->pEpSet);
×
UNCOV
570
    taosMemoryFree(pInfo);
×
UNCOV
571
    tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
UNCOV
572
    return terrno;
×
573
  }
574

UNCOV
575
  for (int i = 0; i < wlRsp.numWhiteLists; ++i) {
×
UNCOV
576
    pWhiteLists[i] = ((uint64_t)wlRsp.pWhiteLists[i].mask << 32) | wlRsp.pWhiteLists[i].ip;
×
577
  }
578

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

581
  taosMemoryFree(pWhiteLists);
×
582
  taosMemoryFree(pMsg->pData);
×
583
  taosMemoryFree(pMsg->pEpSet);
×
584
  taosMemoryFree(pInfo);
×
585
  tFreeSGetUserIpWhiteListRsp(&wlRsp);
×
586
  return code;
×
587
}
588

UNCOV
589
void taos_fetch_whitelist_a(TAOS *taos, __taos_async_whitelist_fn_t fp, void *param) {
×
UNCOV
590
  if (NULL == taos) {
×
591
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
592
    return;
×
593
  }
594

595
  int64_t connId = *(int64_t *)taos;
×
596

597
  STscObj *pTsc = acquireTscObj(connId);
×
UNCOV
598
  if (NULL == pTsc) {
×
UNCOV
599
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
600
    return;
×
601
  }
602

603
  SGetUserWhiteListReq req;
×
604
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
605
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
606
  if (msgLen < 0) {
×
UNCOV
607
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
UNCOV
608
    releaseTscObj(connId);
×
609
    return;
×
610
  }
611

UNCOV
612
  void *pReq = taosMemoryMalloc(msgLen);
×
613
  if (pReq == NULL) {
×
UNCOV
614
    fp(param, terrno, taos, 0, NULL);
×
615
    releaseTscObj(connId);
×
616
    return;
×
617
  }
618

619
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
620
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
UNCOV
621
    taosMemoryFree(pReq);
×
UNCOV
622
    releaseTscObj(connId);
×
623
    return;
×
624
  }
625

626
  SFetchWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchWhiteListInfo));
×
UNCOV
627
  if (pParam == NULL) {
×
UNCOV
628
    fp(param, terrno, taos, 0, NULL);
×
629
    taosMemoryFree(pReq);
×
UNCOV
630
    releaseTscObj(connId);
×
631
    return;
×
632
  }
633

634
  pParam->connId = connId;
×
UNCOV
635
  pParam->userCbFn = fp;
×
636

637
  pParam->userParam = param;
×
638
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
639
  if (pSendInfo == NULL) {
×
640
    fp(param, terrno, taos, 0, NULL);
×
641
    taosMemoryFree(pParam);
×
642
    taosMemoryFree(pReq);
×
643
    releaseTscObj(connId);
×
UNCOV
644
    return;
×
645
  }
646

647
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
648
  pSendInfo->requestId = generateRequestId();
×
649
  pSendInfo->requestObjRefId = 0;
×
650
  pSendInfo->param = pParam;
×
UNCOV
651
  pSendInfo->fp = fetchWhiteListCallbackFn;
×
UNCOV
652
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST;
×
653

654
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
655
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
656
    tscWarn("failed to async send msg to server");
×
657
  }
UNCOV
658
  releaseTscObj(connId);
×
UNCOV
659
  return;
×
660
}
661

662
typedef struct SFetchIpWhiteListInfo {
663
  int64_t connId;
664
  bool    supportNeg;
665
  void   *userParam;
666

667
  __taos_async_ip_whitelist_fn_t userCbFn;
668
} SFetchIpWhiteListInfo;
669

UNCOV
670
int32_t fetchIpWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
671
  int32_t lino = 0;
×
672
  char  **pWhiteLists = NULL;
×
673

674
  SGetUserIpWhiteListRsp wlRsp = {0};
×
675

676
  SFetchIpWhiteListInfo *pInfo = (SFetchIpWhiteListInfo *)param;
×
677
  TAOS                  *taos = &pInfo->connId;
×
678

UNCOV
679
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
680
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
681
    TAOS_CHECK_GOTO(code, &lino, _error);
×
682
  }
683

684
  if ((code = tDeserializeSGetUserIpWhiteListDualRsp(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
685
    TAOS_CHECK_GOTO(code, &lino, _error);
×
686
  }
687

688
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
689
  if (pWhiteLists == NULL) {
×
690
    code = terrno;
×
UNCOV
691
    TAOS_CHECK_GOTO(code, &lino, _error);
×
692
  }
693

UNCOV
694
  int32_t numWhiteLists = 0;
×
UNCOV
695
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
UNCOV
696
    SIpRange *pIpRange = &wlRsp.pWhiteListsDual[i];
×
UNCOV
697
    if (!pInfo->supportNeg && pIpRange->neg) {
×
UNCOV
698
      continue;
×
699
    }
UNCOV
700
    SIpAddr ipAddr = {0};
×
701

UNCOV
702
    code = tIpUintToStr(pIpRange, &ipAddr);
×
UNCOV
703
    TAOS_CHECK_GOTO(code, &lino, _error);
×
704

705
    char *ip = taosMemCalloc(1, IP_RESERVE_CAP);
×
706
    if (ip == NULL) {
×
UNCOV
707
      code = terrno;
×
708
      TAOS_CHECK_GOTO(code, &lino, _error);
×
709
    }
710
    if (ipAddr.type == 0) {
×
711
      if (pInfo->supportNeg) {
×
UNCOV
712
        snprintf(ip, IP_RESERVE_CAP, "%c %s/%d", pIpRange->neg ? '-' : '+', ipAddr.ipv4, ipAddr.mask);
×
713
      } else {
714
        snprintf(ip, IP_RESERVE_CAP, "%s/%d", ipAddr.ipv4, ipAddr.mask);
×
715
      }
716
    } else {
UNCOV
717
      if (ipAddr.ipv6[0] == 0) {
×
718
        memcpy(ipAddr.ipv6, "::", 2);
×
719
      }
UNCOV
720
      if (pInfo->supportNeg) {
×
UNCOV
721
        snprintf(ip, IP_RESERVE_CAP, "%c %s/%d", pIpRange->neg ? '-' : '+', ipAddr.ipv6, ipAddr.mask);
×
722
      } else {
723
        snprintf(ip, IP_RESERVE_CAP, "%s/%d", ipAddr.ipv6, ipAddr.mask);
×
724
      }
725
    }
UNCOV
726
    pWhiteLists[numWhiteLists++] = ip;
×
727
  }
728

729
  pInfo->userCbFn(pInfo->userParam, code, taos, numWhiteLists, pWhiteLists);
×
730
_error:
×
731
  if (pWhiteLists != NULL) {
×
732
    for (int32_t i = 0; i < numWhiteLists; i++) {
×
UNCOV
733
      taosMemFree(pWhiteLists[i]);
×
734
    }
UNCOV
735
    taosMemoryFree(pWhiteLists);
×
736
  }
737
  taosMemoryFree(pMsg->pData);
×
UNCOV
738
  taosMemoryFree(pMsg->pEpSet);
×
739
  taosMemoryFree(pInfo);
×
740
  tFreeSGetUserIpWhiteListDualRsp(&wlRsp);
×
741
  return code;
×
742
}
743

744
static void taosFetchIpWhiteList(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param, bool supportNeg) {
×
745
  if (NULL == taos) {
×
746
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
UNCOV
747
    return;
×
748
  }
UNCOV
749
  int64_t connId = *(int64_t *)taos;
×
750

751
  STscObj *pTsc = acquireTscObj(connId);
×
752
  if (NULL == pTsc) {
×
UNCOV
753
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
754
    return;
×
755
  }
756

757
  SGetUserWhiteListReq req;
×
UNCOV
758
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
UNCOV
759
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
760
  if (msgLen < 0) {
×
UNCOV
761
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
UNCOV
762
    releaseTscObj(connId);
×
763
    return;
×
764
  }
765

766
  void *pReq = taosMemoryMalloc(msgLen);
×
767
  if (pReq == NULL) {
×
UNCOV
768
    fp(param, terrno, taos, 0, NULL);
×
769
    releaseTscObj(connId);
×
UNCOV
770
    return;
×
771
  }
772

773
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
774
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
775
    taosMemoryFree(pReq);
×
UNCOV
776
    releaseTscObj(connId);
×
UNCOV
777
    return;
×
778
  }
779

780
  SFetchIpWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchIpWhiteListInfo));
×
781
  if (pParam == NULL) {
×
UNCOV
782
    fp(param, terrno, taos, 0, NULL);
×
783
    taosMemoryFree(pReq);
×
UNCOV
784
    releaseTscObj(connId);
×
785
    return;
×
786
  }
787

788
  pParam->connId = connId;
×
UNCOV
789
  pParam->supportNeg = supportNeg;
×
UNCOV
790
  pParam->userCbFn = fp;
×
791
  pParam->userParam = param;
×
792

793
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
794
  if (pSendInfo == NULL) {
×
795
    fp(param, terrno, taos, 0, NULL);
×
796
    taosMemoryFree(pParam);
×
797
    taosMemoryFree(pReq);
×
UNCOV
798
    releaseTscObj(connId);
×
UNCOV
799
    return;
×
800
  }
801

802
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
803
  pSendInfo->requestId = generateRequestId();
×
804
  pSendInfo->requestObjRefId = 0;
×
UNCOV
805
  pSendInfo->param = pParam;
×
UNCOV
806
  pSendInfo->fp = fetchIpWhiteListCallbackFn;
×
807
  pSendInfo->msgType = TDMT_MND_GET_USER_IP_WHITELIST_DUAL;
×
808

809
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
810
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
811
    tscWarn("failed to async send msg to server");
×
812
  }
UNCOV
813
  releaseTscObj(connId);
×
814
  return;
×
815
}
816

817
void taos_fetch_whitelist_dual_stack_a(TAOS *taos, __taos_async_whitelist_dual_stack_fn_t fp, void *param) {
×
818
  taosFetchIpWhiteList(taos, fp, param, false);
×
819
}
×
820

UNCOV
821
void taos_fetch_ip_whitelist_a(TAOS *taos, __taos_async_ip_whitelist_fn_t fp, void *param) {
×
822
  taosFetchIpWhiteList(taos, fp, param, true);
×
823
}
×
824

825
typedef struct SFetchDateTimeWhiteListInfo {
826
  int64_t                              connId;
827
  void                                *userParam;
828
  __taos_async_datetime_whitelist_fn_t userCbFn;
829
} SFetchDateTimeWhiteListInfo;
830

831
static const char *weekdays[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
832
int32_t            fetchDateTimeWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
833
  int32_t lino = 0;
×
UNCOV
834
  char  **pWhiteLists = NULL;
×
835

836
  SUserDateTimeWhiteList wlRsp = {0};
×
837

838
  SFetchDateTimeWhiteListInfo *pInfo = (SFetchDateTimeWhiteListInfo *)param;
×
839
  TAOS                        *taos = &pInfo->connId;
×
840

841
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
842
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
843
    TAOS_CHECK_GOTO(code, &lino, _error);
×
844
  }
845

UNCOV
846
  if ((code = tDeserializeSUserDateTimeWhiteList(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
847
    TAOS_CHECK_GOTO(code, &lino, _error);
×
848
  }
849

UNCOV
850
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
851
  if (pWhiteLists == NULL) {
×
852
    code = terrno;
×
853
    TAOS_CHECK_GOTO(code, &lino, _error);
×
854
  }
855

856
  int32_t numWhiteLists = 0;
×
857
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
UNCOV
858
    SDateTimeWhiteListItem *item = &wlRsp.pWhiteLists[i];
×
859

UNCOV
860
    char *p = taosMemCalloc(1, 128);
×
UNCOV
861
    if (p == NULL) {
×
UNCOV
862
      code = terrno;
×
UNCOV
863
      TAOS_CHECK_GOTO(code, &lino, _error);
×
864
    }
865

866
    int duration = item->duration / 60;
×
867

868
    if (item->absolute) {
×
UNCOV
869
      struct STm tm;
×
870
      (void)taosTs2Tm(item->start, TSDB_TIME_PRECISION_SECONDS, &tm, NULL);
×
UNCOV
871
      snprintf(p, 128, "%c %04d-%02d-%02d %02d:%02d %d", item->neg ? '-' : '+', tm.tm.tm_year + 1900, tm.tm.tm_mon + 1,
×
872
                          tm.tm.tm_mday, tm.tm.tm_hour, tm.tm.tm_min, duration);
873
    } else {
UNCOV
874
      int day = item->start / 86400;
×
875
      int hour = (item->start % 86400) / 3600;
×
876
      int minute = (item->start % 3600) / 60;
×
877
      snprintf(p, 128, "%c %s %02d:%02d %d", item->neg ? '-' : '+', weekdays[day], hour, minute, duration);
×
878
    }
UNCOV
879
    pWhiteLists[numWhiteLists++] = p;
×
880
  }
881

UNCOV
882
  pInfo->userCbFn(pInfo->userParam, code, taos, numWhiteLists, pWhiteLists);
×
UNCOV
883
_error:
×
884
  if (pWhiteLists != NULL) {
×
885
    for (int32_t i = 0; i < numWhiteLists; i++) {
×
886
      taosMemFree(pWhiteLists[i]);
×
887
    }
UNCOV
888
    taosMemoryFree(pWhiteLists);
×
889
  }
890
  taosMemoryFree(pMsg->pData);
×
891
  taosMemoryFree(pMsg->pEpSet);
×
892
  taosMemoryFree(pInfo);
×
UNCOV
893
  tFreeSUserDateTimeWhiteList(&wlRsp);
×
894
  return code;
×
895
}
896

897
void taos_fetch_datetime_whitelist_a(TAOS *taos, __taos_async_datetime_whitelist_fn_t fp, void *param) {
×
UNCOV
898
  if (NULL == taos) {
×
UNCOV
899
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
900
    return;
×
901
  }
902
  int64_t connId = *(int64_t *)taos;
×
903

904
  STscObj *pTsc = acquireTscObj(connId);
×
905
  if (NULL == pTsc) {
×
UNCOV
906
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
UNCOV
907
    return;
×
908
  }
909

910
  SGetUserWhiteListReq req;
×
911
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
UNCOV
912
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
913
  if (msgLen < 0) {
×
UNCOV
914
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
UNCOV
915
    releaseTscObj(connId);
×
916
    return;
×
917
  }
918

919
  void *pReq = taosMemoryMalloc(msgLen);
×
920
  if (pReq == NULL) {
×
UNCOV
921
    fp(param, terrno, taos, 0, NULL);
×
922
    releaseTscObj(connId);
×
UNCOV
923
    return;
×
924
  }
925

926
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
927
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
928
    taosMemoryFree(pReq);
×
UNCOV
929
    releaseTscObj(connId);
×
UNCOV
930
    return;
×
931
  }
932

933
  SFetchDateTimeWhiteListInfo *pParam = taosMemoryMalloc(sizeof(SFetchDateTimeWhiteListInfo));
×
934
  if (pParam == NULL) {
×
UNCOV
935
    fp(param, terrno, taos, 0, NULL);
×
936
    taosMemoryFree(pReq);
×
UNCOV
937
    releaseTscObj(connId);
×
938
    return;
×
939
  }
940

941
  pParam->connId = connId;
×
UNCOV
942
  pParam->userCbFn = fp;
×
UNCOV
943
  pParam->userParam = param;
×
944

945
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
946
  if (pSendInfo == NULL) {
×
947
    fp(param, terrno, taos, 0, NULL);
×
948
    taosMemoryFree(pParam);
×
949
    taosMemoryFree(pReq);
×
950
    releaseTscObj(connId);
×
UNCOV
951
    return;
×
952
  }
953

954
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
955
  pSendInfo->requestId = generateRequestId();
×
956
  pSendInfo->requestObjRefId = 0;
×
957
  pSendInfo->param = pParam;
×
UNCOV
958
  pSendInfo->fp = fetchDateTimeWhiteListCallbackFn;
×
UNCOV
959
  pSendInfo->msgType = TDMT_MND_GET_USER_DATETIME_WHITELIST;
×
960

961
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
962
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
963
    tscWarn("failed to async send msg to server");
×
964
  }
UNCOV
965
  releaseTscObj(connId);
×
UNCOV
966
  return;
×
967
}
968

969
void taos_close_internal(void *taos) {
94,648,342✔
970
  if (taos == NULL) {
94,648,342✔
971
    return;
348✔
972
  }
973
  int32_t code = 0;
94,647,994✔
974

975
  STscObj *pTscObj = (STscObj *)taos;
94,647,994✔
976
  tscDebug("conn:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
94,647,994✔
977

978
  SSessParam para = {.type = SESSION_PER_USER, .value = -1, .noCheck = 1};
94,647,994✔
979

980
  code = tscUpdateSessMetric(pTscObj, &para);
94,647,994✔
981
  if (code != TSDB_CODE_SUCCESS) {
94,649,269✔
982
    tscWarn("conn:0x%" PRIx64 ", failed to update user:%s metric when close connection, code:%d", pTscObj->id,
×
983
            pTscObj->user, code);
984
  }
985

986
  code = tscUnrefSessMetric(pTscObj);
94,649,269✔
987
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
94,648,929✔
988
    tscError("conn:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
×
989
  }
990
}
991

992
void taos_close(TAOS *taos) {
94,494,751✔
993
  if (taos == NULL) {
94,494,751✔
994
    return;
379✔
995
  }
996

997
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
94,494,372✔
998
  if (NULL == pObj) {
94,496,326✔
999
    taosMemoryFree(taos);
×
1000
    return;
×
1001
  }
1002

1003
  taos_close_internal(pObj);
94,496,326✔
1004
  releaseTscObj(*(int64_t *)taos);
94,494,565✔
1005
  taosMemoryFree(taos);
94,493,551✔
1006
}
1007

1008
int taos_errno(TAOS_RES *res) {
1,527,397,236✔
1009
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,527,397,236✔
1010
    return terrno;
10,052,430✔
1011
  }
1012

1013
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,517,352,489✔
1014
    return 0;
19,669,609✔
1015
  }
1016

1017
  return ((SRequestObj *)res)->code;
1,497,675,465✔
1018
}
1019

1020
const char *taos_errstr(TAOS_RES *res) {
120,148,930✔
1021
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
120,148,930✔
1022
    if (*(taosGetErrMsg()) == 0) {
10,084,849✔
1023
      return (const char *)tstrerror(terrno);
10,085,342✔
1024
    } else {
1025
      (void)snprintf(taosGetErrMsgReturn(), ERR_MSG_LEN, "%s", taosGetErrMsg());
43✔
1026
      return (const char *)taosGetErrMsgReturn();
43✔
1027
    }
1028
  }
1029

1030
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
110,064,339✔
UNCOV
1031
    return "success";
×
1032
  }
1033

1034
  SRequestObj *pRequest = (SRequestObj *)res;
110,064,921✔
1035
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
110,064,921✔
1036
    return pRequest->msgBuf;
31,292,303✔
1037
  } else {
1038
    return (const char *)tstrerror(pRequest->code);
78,772,618✔
1039
  }
1040
}
1041

1042
void taos_free_result(TAOS_RES *res) {
1,162,154,724✔
1043
  if (NULL == res) {
1,162,154,724✔
1044
    return;
14,401,217✔
1045
  }
1046

1047
  tscTrace("res:%p, will be freed", res);
1,147,753,507✔
1048

1049
  if (TD_RES_QUERY(res)) {
1,147,759,125✔
1050
    SRequestObj *pRequest = (SRequestObj *)res;
1,092,750,873✔
1051
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query, res:%p", pRequest->requestId, res);
1,092,750,873✔
1052
    destroyRequest(pRequest);
1,092,750,873✔
1053
    return;
1,092,732,224✔
1054
  }
1055

1056
  SMqRspObj *pRsp = (SMqRspObj *)res;
55,015,194✔
1057
  if (TD_RES_TMQ(res)) {
55,015,194✔
1058
    tDeleteMqDataRsp(&pRsp->dataRsp);
54,929,341✔
1059
    doFreeReqResultInfo(&pRsp->resInfo);
54,928,966✔
1060
  } else if (TD_RES_TMQ_METADATA(res)) {
99,005✔
1061
    tDeleteSTaosxRsp(&pRsp->dataRsp);
5,033✔
1062
    doFreeReqResultInfo(&pRsp->resInfo);
5,033✔
1063
  } else if (TD_RES_TMQ_META(res)) {
93,597✔
1064
    tDeleteMqMetaRsp(&pRsp->metaRsp);
85,098✔
1065
  } else if (TD_RES_TMQ_BATCH_META(res)) {
8,499✔
1066
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
8,499✔
UNCOV
1067
  } else if (TD_RES_TMQ_RAW(res)) {
×
UNCOV
1068
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
×
1069
  }
1070
  taosMemoryFree(pRsp);
55,026,471✔
1071
}
1072

1073
void taos_kill_query(TAOS *taos) {
430✔
1074
  if (NULL == taos) {
430✔
1075
    return;
379✔
1076
  }
1077

1078
  int64_t  rid = *(int64_t *)taos;
51✔
1079
  STscObj *pTscObj = acquireTscObj(rid);
51✔
1080
  if (pTscObj) {
51✔
1081
    stopAllRequests(pTscObj->pRequests);
51✔
1082
  }
1083
  releaseTscObj(rid);
51✔
1084
}
1085

1086
int taos_field_count(TAOS_RES *res) {
2,147,483,647✔
1087
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
UNCOV
1088
    return 0;
×
1089
  }
1090

1091
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1092
  return pResInfo->numOfCols;
2,147,483,647✔
1093
}
1094

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

1097
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
2,147,483,647✔
1098
  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✔
1099
    return NULL;
3,660,378✔
1100
  }
1101

1102
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1103
  return pResInfo->userFields;
2,147,483,647✔
1104
}
1105

1106
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
1,084,873,190✔
1107
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
252✔
1108
  return taosQueryImplWithReqid(taos, sql, false, reqid);
252✔
1109
}
1110

1111
TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res) {
105✔
1112
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
105✔
1113
    return NULL;
×
1114
  }
1115
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
105✔
1116
  return pResInfo->fields;
105✔
1117
}
1118

1119
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
2,147,483,647✔
1120
  if (res == NULL) {
2,147,483,647✔
UNCOV
1121
    return NULL;
×
1122
  }
1123

1124
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1125
    SRequestObj *pRequest = (SRequestObj *)res;
1,404,422,061✔
1126
    if (pRequest->killed) {
1,404,422,061✔
UNCOV
1127
      tscInfo("query has been killed, can not fetch more row.");
×
UNCOV
1128
      pRequest->code = TSDB_CODE_TSC_QUERY_KILLED;
×
UNCOV
1129
      CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_FETCH_RETURNED);
×
UNCOV
1130
      return NULL;
×
1131
    }
1132

1133
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
1,404,422,412✔
1134
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
1,404,423,932✔
1135
      if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT) {
429✔
UNCOV
1136
        CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_FETCH_RETURNED);
×
1137
      }
1138
      return NULL;
372✔
1139
    }
1140

1141
    if (pRequest->inCallback) {
1,404,413,088✔
1142
      tscError("can not call taos_fetch_row before query callback ends.");
196✔
1143
      terrno = TSDB_CODE_TSC_INVALID_OPERATION;
196✔
1144
      return NULL;
196✔
1145
    }
1146

1147
    return doAsyncFetchRows(pRequest, true, true);
1,404,411,338✔
1148
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
1149
    SMqRspObj      *msg = ((SMqRspObj *)res);
2,147,483,647✔
1150
    SReqResultInfo *pResultInfo = NULL;
2,147,483,647✔
1151
    if (msg->resIter == -1) {
2,147,483,647✔
1152
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
35,205,279✔
UNCOV
1153
        return NULL;
×
1154
      }
1155
    } else {
1156
      pResultInfo = tmqGetCurResInfo(res);
2,147,483,647✔
1157
    }
1158

1159
    if (pResultInfo->current < pResultInfo->numOfRows) {
2,147,483,647✔
1160
      doSetOneRowPtr(pResultInfo);
2,147,483,647✔
1161
      pResultInfo->current += 1;
2,147,483,647✔
1162
      return pResultInfo->row;
2,147,483,647✔
1163
    } else {
1164
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
62,533,686✔
1165
        return NULL;
35,204,134✔
1166
      }
1167

1168
      doSetOneRowPtr(pResultInfo);
27,327,302✔
1169
      pResultInfo->current += 1;
27,329,552✔
1170
      return pResultInfo->row;
27,329,552✔
1171
    }
UNCOV
1172
  } else if (TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
UNCOV
1173
    return NULL;
×
1174
  } else {
UNCOV
1175
    tscError("invalid result passed to taos_fetch_row");
×
UNCOV
1176
    terrno = TSDB_CODE_TMQ_INVALID_DATA;
×
UNCOV
1177
    return NULL;
×
1178
  }
1179
}
1180

1181
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
2,147,483,647✔
1182
  return taos_print_row_with_size(str, INT32_MAX, row, fields, num_fields);
2,147,483,647✔
1183
}
1184
int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
2,147,483,647✔
1185
  int32_t len = 0;
2,147,483,647✔
1186
  for (int i = 0; i < num_fields; ++i) {
2,147,483,647✔
1187
    if (i > 0 && len < size - 1) {
2,147,483,647✔
1188
      str[len++] = ' ';
2,147,483,647✔
1189
    }
1190

1191
    if (row[i] == NULL) {
2,147,483,647✔
1192
      len += snprintf(str + len, size - len, "%s", TSDB_DATA_NULL_STR);
146,527,158✔
1193
      continue;
146,527,158✔
1194
    }
1195

1196
    switch (fields[i].type) {
2,147,483,647✔
1197
      case TSDB_DATA_TYPE_TINYINT:
11,080,685✔
1198
        len += snprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
11,080,685✔
1199
        break;
11,123,198✔
1200

1201
      case TSDB_DATA_TYPE_UTINYINT:
54,548✔
1202
        len += snprintf(str + len, size - len, "%u", *((uint8_t *)row[i]));
54,548✔
1203
        break;
54,548✔
1204

1205
      case TSDB_DATA_TYPE_SMALLINT:
54,574✔
1206
        len += snprintf(str + len, size - len, "%d", *((int16_t *)row[i]));
54,574✔
1207
        break;
54,574✔
1208

1209
      case TSDB_DATA_TYPE_USMALLINT:
54,587✔
1210
        len += snprintf(str + len, size - len, "%u", *((uint16_t *)row[i]));
54,587✔
1211
        break;
54,587✔
1212

1213
      case TSDB_DATA_TYPE_INT:
2,147,483,647✔
1214
        len += snprintf(str + len, size - len, "%d", *((int32_t *)row[i]));
2,147,483,647✔
1215
        break;
2,147,483,647✔
1216

1217
      case TSDB_DATA_TYPE_UINT:
54,600✔
1218
        len += snprintf(str + len, size - len, "%u", *((uint32_t *)row[i]));
54,600✔
1219
        break;
54,600✔
1220

1221
      case TSDB_DATA_TYPE_BIGINT:
2,147,483,647✔
1222
        len += snprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
2,147,483,647✔
1223
        break;
2,147,483,647✔
1224

1225
      case TSDB_DATA_TYPE_UBIGINT:
54,535✔
1226
        len += snprintf(str + len, size - len, "%" PRIu64, *((uint64_t *)row[i]));
54,535✔
1227
        break;
54,535✔
1228

1229
      case TSDB_DATA_TYPE_FLOAT: {
22,154,372✔
1230
        float fv = 0;
22,154,372✔
1231
        fv = GET_FLOAT_VAL(row[i]);
22,154,372✔
1232
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
22,125,142✔
1233
      } break;
22,168,543✔
1234

1235
      case TSDB_DATA_TYPE_DOUBLE: {
2,147,483,647✔
1236
        double dv = 0;
2,147,483,647✔
1237
        dv = GET_DOUBLE_VAL(row[i]);
2,147,483,647✔
1238
        len += snprintf(str + len, size - len, "%.*g", DBL_DIG, dv);
2,147,483,647✔
1239
      } break;
2,147,483,647✔
1240

1241
      case TSDB_DATA_TYPE_VARBINARY: {
54,548✔
1242
        void    *data = NULL;
54,548✔
1243
        uint32_t tmp = 0;
54,548✔
1244
        int32_t  charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
54,548✔
1245
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
54,548✔
UNCOV
1246
          break;
×
1247
        }
1248
        uint32_t copyLen = TMIN(size - len - 1, tmp);
54,535✔
1249
        (void)memcpy(str + len, data, copyLen);
54,535✔
1250
        len += copyLen;
54,535✔
1251
        taosMemoryFree(data);
54,535✔
1252
      } break;
54,600✔
1253
      case TSDB_DATA_TYPE_BINARY:
2,147,483,647✔
1254
      case TSDB_DATA_TYPE_NCHAR:
1255
      case TSDB_DATA_TYPE_GEOMETRY: {
1256
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
2,147,483,647✔
1257
        if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_VARBINARY ||
2,147,483,647✔
1258
            fields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
1,982,058,066✔
1259
          if (charLen > fields[i].bytes || charLen < 0) {
2,147,483,647✔
1260
            tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
2,259✔
UNCOV
1261
            break;
×
1262
          }
1263
        } else {
1264
          if (charLen > fields[i].bytes * TSDB_NCHAR_SIZE || charLen < 0) {
1,982,012,385✔
1265
            tscError("taos_print_row error. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
403✔
UNCOV
1266
            break;
×
1267
          }
1268
        }
1269

1270
        uint32_t copyLen = TMIN(size - len - 1, charLen);
2,147,483,647✔
1271
        (void)memcpy(str + len, row[i], copyLen);
2,147,483,647✔
1272
        len += copyLen;
2,147,483,647✔
1273
      } break;
2,147,483,647✔
UNCOV
1274
      case TSDB_DATA_TYPE_BLOB:
×
1275
      case TSDB_DATA_TYPE_MEDIUMBLOB: {
UNCOV
1276
        void    *data = NULL;
×
UNCOV
1277
        uint32_t tmp = 0;
×
UNCOV
1278
        int32_t  charLen = blobDataLen((char *)row[i] - BLOBSTR_HEADER_SIZE);
×
UNCOV
1279
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
×
1280
          break;
×
1281
        }
1282

UNCOV
1283
        uint32_t copyLen = TMIN(size - len - 1, tmp);
×
UNCOV
1284
        (void)memcpy(str + len, data, copyLen);
×
UNCOV
1285
        len += copyLen;
×
1286

UNCOV
1287
        taosMemoryFree(data);
×
UNCOV
1288
      } break;
×
1289

1290
      case TSDB_DATA_TYPE_TIMESTAMP:
2,147,483,647✔
1291
        len += snprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
2,147,483,647✔
1292
        break;
2,147,483,647✔
1293

1294
      case TSDB_DATA_TYPE_BOOL:
54,587✔
1295
        len += snprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
54,587✔
1296
        break;
56,327✔
UNCOV
1297
      case TSDB_DATA_TYPE_DECIMAL64:
×
1298
      case TSDB_DATA_TYPE_DECIMAL: {
UNCOV
1299
        uint32_t decimalLen = strlen(row[i]);
×
1300
        uint32_t copyLen = TMIN(size - len - 1, decimalLen);
×
UNCOV
1301
        (void)memcpy(str + len, row[i], copyLen);
×
UNCOV
1302
        len += copyLen;
×
UNCOV
1303
      } break;
×
UNCOV
1304
      default:
×
UNCOV
1305
        break;
×
1306
    }
1307

1308
    if (len >= size - 1) {
2,147,483,647✔
UNCOV
1309
      break;
×
1310
    }
1311
  }
1312
  if (len < size) {
2,147,483,647✔
1313
    str[len] = 0;
2,147,483,647✔
1314
  }
1315

1316
  return len;
2,147,483,647✔
1317
}
1318

1319
int *taos_fetch_lengths(TAOS_RES *res) {
2,147,483,647✔
1320
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1321
    return NULL;
×
1322
  }
1323

1324
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1325
  return pResInfo->length;
2,147,483,647✔
1326
}
1327

UNCOV
1328
TAOS_ROW *taos_result_block(TAOS_RES *res) {
×
UNCOV
1329
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
UNCOV
1330
    terrno = TSDB_CODE_INVALID_PARA;
×
1331
    return NULL;
×
1332
  }
1333

1334
  if (taos_is_update_query(res)) {
×
1335
    return NULL;
×
1336
  }
1337

1338
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
1339
  return &pResInfo->row;
×
1340
}
1341

1342
// todo intergrate with tDataTypes
1343
const char *taos_data_type(int type) {
×
UNCOV
1344
  switch (type) {
×
UNCOV
1345
    case TSDB_DATA_TYPE_NULL:
×
UNCOV
1346
      return "TSDB_DATA_TYPE_NULL";
×
UNCOV
1347
    case TSDB_DATA_TYPE_BOOL:
×
UNCOV
1348
      return "TSDB_DATA_TYPE_BOOL";
×
UNCOV
1349
    case TSDB_DATA_TYPE_TINYINT:
×
UNCOV
1350
      return "TSDB_DATA_TYPE_TINYINT";
×
UNCOV
1351
    case TSDB_DATA_TYPE_SMALLINT:
×
UNCOV
1352
      return "TSDB_DATA_TYPE_SMALLINT";
×
UNCOV
1353
    case TSDB_DATA_TYPE_INT:
×
UNCOV
1354
      return "TSDB_DATA_TYPE_INT";
×
1355
    case TSDB_DATA_TYPE_BIGINT:
×
UNCOV
1356
      return "TSDB_DATA_TYPE_BIGINT";
×
UNCOV
1357
    case TSDB_DATA_TYPE_FLOAT:
×
UNCOV
1358
      return "TSDB_DATA_TYPE_FLOAT";
×
UNCOV
1359
    case TSDB_DATA_TYPE_DOUBLE:
×
UNCOV
1360
      return "TSDB_DATA_TYPE_DOUBLE";
×
UNCOV
1361
    case TSDB_DATA_TYPE_VARCHAR:
×
1362
      return "TSDB_DATA_TYPE_VARCHAR";
×
1363
      //    case TSDB_DATA_TYPE_BINARY:          return "TSDB_DATA_TYPE_VARCHAR";
1364
    case TSDB_DATA_TYPE_TIMESTAMP:
×
1365
      return "TSDB_DATA_TYPE_TIMESTAMP";
×
UNCOV
1366
    case TSDB_DATA_TYPE_NCHAR:
×
UNCOV
1367
      return "TSDB_DATA_TYPE_NCHAR";
×
1368
    case TSDB_DATA_TYPE_JSON:
×
1369
      return "TSDB_DATA_TYPE_JSON";
×
UNCOV
1370
    case TSDB_DATA_TYPE_GEOMETRY:
×
UNCOV
1371
      return "TSDB_DATA_TYPE_GEOMETRY";
×
1372
    case TSDB_DATA_TYPE_UTINYINT:
×
1373
      return "TSDB_DATA_TYPE_UTINYINT";
×
UNCOV
1374
    case TSDB_DATA_TYPE_USMALLINT:
×
UNCOV
1375
      return "TSDB_DATA_TYPE_USMALLINT";
×
UNCOV
1376
    case TSDB_DATA_TYPE_UINT:
×
1377
      return "TSDB_DATA_TYPE_UINT";
×
1378
    case TSDB_DATA_TYPE_UBIGINT:
×
1379
      return "TSDB_DATA_TYPE_UBIGINT";
×
1380
    case TSDB_DATA_TYPE_VARBINARY:
×
1381
      return "TSDB_DATA_TYPE_VARBINARY";
×
1382
    case TSDB_DATA_TYPE_DECIMAL:
×
1383
      return "TSDB_DATA_TYPE_DECIMAL";
×
1384
    case TSDB_DATA_TYPE_BLOB:
×
1385
      return "TSDB_DATA_TYPE_BLOB";
×
1386
    case TSDB_DATA_TYPE_MEDIUMBLOB:
×
1387
      return "TSDB_DATA_TYPE_MEDIUMBLOB";
×
1388
    default:
×
1389
      return "UNKNOWN";
×
1390
  }
1391
}
1392

1393
const char *taos_get_client_info() { return td_version; }
1,079,974✔
1394

1395
// return int32_t
1396
int taos_affected_rows(TAOS_RES *res) {
634,953,021✔
1397
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
634,953,021✔
1398
      TD_RES_TMQ_BATCH_META(res)) {
634,957,094✔
1399
    return 0;
×
1400
  }
1401

1402
  SRequestObj    *pRequest = (SRequestObj *)res;
634,956,342✔
1403
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
634,956,342✔
1404
  return (int)pResInfo->numOfRows;
634,956,229✔
1405
}
1406

1407
// return int64_t
1408
int64_t taos_affected_rows64(TAOS_RES *res) {
1,427,589✔
1409
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,427,589✔
1410
      TD_RES_TMQ_BATCH_META(res)) {
1,427,589✔
1411
    return 0;
×
1412
  }
1413

1414
  SRequestObj    *pRequest = (SRequestObj *)res;
1,427,589✔
1415
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
1,427,589✔
1416
  return pResInfo->numOfRows;
1,427,589✔
1417
}
1418

1419
int taos_result_precision(TAOS_RES *res) {
2,147,483,647✔
1420
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1421
    return TSDB_TIME_PRECISION_MILLI;
×
1422
  }
1423

1424
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1425
    SRequestObj *pRequest = (SRequestObj *)res;
275,447,241✔
1426
    return pRequest->body.resInfo.precision;
275,447,241✔
1427
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
1428
    SReqResultInfo *info = tmqGetCurResInfo(res);
2,147,483,647✔
1429
    return info->precision;
2,147,483,647✔
1430
  }
UNCOV
1431
  return TSDB_TIME_PRECISION_MILLI;
×
1432
}
1433

1434
int taos_select_db(TAOS *taos, const char *db) {
41,254✔
1435
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
41,254✔
1436
  if (pObj == NULL) {
41,254✔
UNCOV
1437
    releaseTscObj(*(int64_t *)taos);
×
UNCOV
1438
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
1439
    return TSDB_CODE_TSC_DISCONNECTED;
×
1440
  }
1441

1442
  if (db == NULL || strlen(db) == 0) {
41,254✔
UNCOV
1443
    releaseTscObj(*(int64_t *)taos);
×
UNCOV
1444
    tscError("invalid parameter for %s", db == NULL ? "db is NULL" : "db is empty");
×
1445
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
UNCOV
1446
    return terrno;
×
1447
  }
1448

1449
  char sql[256] = {0};
41,254✔
1450
  (void)snprintf(sql, tListLen(sql), "use %s", db);
41,254✔
1451

1452
  TAOS_RES *pRequest = taos_query(taos, sql);
41,254✔
1453
  int32_t   code = taos_errno(pRequest);
41,254✔
1454

1455
  taos_free_result(pRequest);
41,214✔
1456
  releaseTscObj(*(int64_t *)taos);
41,254✔
1457
  return code;
41,254✔
1458
}
1459

1460
void taos_stop_query(TAOS_RES *res) {
1,188,441,071✔
1461
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,188,441,071✔
1462
      TD_RES_TMQ_BATCH_META(res)) {
1,188,479,009✔
UNCOV
1463
    return;
×
1464
  }
1465

1466
  stopAllQueries((SRequestObj *)res);
1,188,458,592✔
1467
}
1468

UNCOV
1469
bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
×
UNCOV
1470
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1471
    return true;
×
1472
  }
1473
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
×
UNCOV
1474
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
×
UNCOV
1475
    return true;
×
1476
  }
1477

1478
  SResultColumn *pCol = &pResultInfo->pCol[col];
×
1479
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
×
1480
    return (pCol->offset[row] == -1);
×
1481
  } else {
UNCOV
1482
    return colDataIsNull_f(pCol, row);
×
1483
  }
1484
}
1485

1486
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
428,226✔
1487

1488
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
375,081,194✔
1489
  int32_t numOfRows = 0;
375,081,194✔
1490
  /*int32_t code = */ terrno = taos_fetch_block_s(res, &numOfRows, rows);
375,081,194✔
1491
  return numOfRows;
375,080,666✔
1492
}
1493

1494
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
375,081,194✔
1495
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
375,081,194✔
UNCOV
1496
    return 0;
×
1497
  }
1498

1499
  if (TD_RES_QUERY(res)) {
375,081,194✔
1500
    SRequestObj *pRequest = (SRequestObj *)res;
335,757,633✔
1501
    (*rows) = NULL;
335,757,633✔
1502
    (*numOfRows) = 0;
335,757,633✔
1503

1504
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
335,757,633✔
1505
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
335,385,756✔
1506
      CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_FETCH_RETURNED);
2,975,924✔
1507
      return pRequest->code;
1,488,226✔
1508
    }
1509

1510
    (void)doAsyncFetchRows(pRequest, false, true);
334,269,407✔
1511

1512
    // TODO refactor
1513
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
334,268,877✔
1514
    pResultInfo->current = pResultInfo->numOfRows;
334,269,407✔
1515

1516
    (*rows) = pResultInfo->row;
334,269,407✔
1517
    (*numOfRows) = pResultInfo->numOfRows;
334,269,407✔
1518
    return pRequest->code;
334,269,407✔
1519
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
39,323,561✔
1520
    SReqResultInfo *pResultInfo = NULL;
39,323,561✔
1521
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
39,323,561✔
1522
    if (code != 0) return code;
39,323,561✔
1523

1524
    pResultInfo->current = pResultInfo->numOfRows;
19,663,461✔
1525
    (*rows) = pResultInfo->row;
19,663,461✔
1526
    (*numOfRows) = pResultInfo->numOfRows;
19,663,461✔
1527
    return 0;
19,663,461✔
1528
  } else {
UNCOV
1529
    tscError("taos_fetch_block_s invalid res type");
×
1530
    return TSDB_CODE_TMQ_INVALID_DATA;
×
1531
  }
1532
}
1533

1534
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
7,100✔
1535
  *numOfRows = 0;
7,100✔
1536
  *pData = NULL;
7,100✔
1537

1538
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
7,100✔
UNCOV
1539
    return 0;
×
1540
  }
1541

1542
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
7,100✔
1543
    SReqResultInfo *pResultInfo = NULL;
3,024✔
1544
    int32_t         code = tmqGetNextResInfo(res, false, &pResultInfo);
3,024✔
1545
    if (code != 0) {
3,024✔
1546
      (*numOfRows) = 0;
1,512✔
1547
      return 0;
1,512✔
1548
    }
1549

1550
    pResultInfo->current = pResultInfo->numOfRows;
1,512✔
1551
    (*numOfRows) = pResultInfo->numOfRows;
1,512✔
1552
    (*pData) = (void *)pResultInfo->pData;
1,512✔
1553
    return 0;
1,512✔
1554
  }
1555

1556
  SRequestObj *pRequest = (SRequestObj *)res;
4,076✔
1557

1558
  if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
4,076✔
1559
      pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
4,076✔
UNCOV
1560
    if (pRequest->code == TSDB_SQL_RETRIEVE_EMPTY_RESULT) {
×
UNCOV
1561
      CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_FETCH_RETURNED);
×
1562
    }
1563
    return pRequest->code;
×
1564
  }
1565

1566
  (void)doAsyncFetchRows(pRequest, false, false);
4,076✔
1567

1568
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
4,076✔
1569

1570
  pResultInfo->current = pResultInfo->numOfRows;
4,076✔
1571
  (*numOfRows) = pResultInfo->numOfRows;
4,076✔
1572
  (*pData) = (void *)pResultInfo->pData;
4,076✔
1573

1574
  return pRequest->code;
4,076✔
1575
}
1576

1577
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
268,982,936✔
1578
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
268,982,936✔
UNCOV
1579
    return NULL;
×
1580
  }
1581

1582
  int32_t numOfFields = taos_num_fields(res);
268,982,936✔
1583
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
268,983,480✔
UNCOV
1584
    return NULL;
×
1585
  }
1586

1587
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
268,983,480✔
1588
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
268,983,480✔
1589
  if (!IS_VAR_DATA_TYPE(pField->type)) {
268,983,480✔
UNCOV
1590
    return NULL;
×
1591
  }
1592

1593
  return pResInfo->pCol[columnIndex].offset;
268,983,480✔
1594
}
1595

1596
int taos_is_null_by_column(TAOS_RES *res, int columnIndex, bool result[], int *rows) {
931,934,630✔
1597
  if (res == NULL || result == NULL || rows == NULL || *rows <= 0 || columnIndex < 0 || TD_RES_TMQ_META(res) ||
931,934,630✔
1598
      TD_RES_TMQ_RAW(res) || TD_RES_TMQ_BATCH_META(res)) {
931,935,024✔
UNCOV
1599
    return TSDB_CODE_INVALID_PARA;
×
1600
  }
1601

1602
  int32_t numOfFields = taos_num_fields(res);
931,934,630✔
1603
  if (columnIndex >= numOfFields || numOfFields == 0) {
931,935,024✔
UNCOV
1604
    return TSDB_CODE_INVALID_PARA;
×
1605
  }
1606

1607
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
931,935,024✔
1608
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
931,935,024✔
1609
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
931,935,024✔
1610

1611
  if (*rows > pResInfo->numOfRows) {
931,935,024✔
UNCOV
1612
    *rows = pResInfo->numOfRows;
×
1613
  }
1614
  if (IS_VAR_DATA_TYPE(pField->type)) {
931,935,024✔
UNCOV
1615
    for (int i = 0; i < *rows; i++) {
×
UNCOV
1616
      if (pCol->offset[i] == -1) {
×
UNCOV
1617
        result[i] = true;
×
1618
      } else {
UNCOV
1619
        result[i] = false;
×
1620
      }
1621
    }
1622
  } else {
1623
    for (int i = 0; i < *rows; i++) {
2,147,483,647✔
1624
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1625
        result[i] = true;
2,147,483,647✔
1626
      } else {
1627
        result[i] = false;
2,147,483,647✔
1628
      }
1629
    }
1630
  }
1631
  return 0;
931,935,024✔
1632
}
1633

UNCOV
1634
int taos_validate_sql(TAOS *taos, const char *sql) {
×
UNCOV
1635
  TAOS_RES *pObj = taosQueryImpl(taos, sql, true, TD_REQ_FROM_APP);
×
1636

UNCOV
1637
  int code = taos_errno(pObj);
×
1638

UNCOV
1639
  taos_free_result(pObj);
×
UNCOV
1640
  return code;
×
1641
}
1642

UNCOV
1643
void taos_reset_current_db(TAOS *taos) {
×
UNCOV
1644
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
UNCOV
1645
  if (pTscObj == NULL) {
×
1646
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
1647
    return;
×
1648
  }
1649

1650
  resetConnectDB(pTscObj);
×
1651

UNCOV
1652
  releaseTscObj(*(int64_t *)taos);
×
1653
}
1654

1655
const char *taos_get_server_info(TAOS *taos) {
3,975✔
1656
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
3,975✔
1657
  if (pTscObj == NULL) {
3,975✔
UNCOV
1658
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
1659
    return NULL;
×
1660
  }
1661

1662
  releaseTscObj(*(int64_t *)taos);
3,975✔
1663

1664
  return pTscObj->sDetailVer;
3,975✔
1665
}
1666

1667
int taos_get_current_db(TAOS *taos, char *database, int len, int *required) {
2,484✔
1668
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
2,484✔
1669
  if (pTscObj == NULL) {
2,484✔
UNCOV
1670
    return TSDB_CODE_TSC_DISCONNECTED;
×
1671
  }
1672

1673
  int code = TSDB_CODE_SUCCESS;
2,484✔
1674
  (void)taosThreadMutexLock(&pTscObj->mutex);
2,484✔
1675
  if (database == NULL || len <= 0) {
2,484✔
1676
    if (required != NULL) *required = strlen(pTscObj->db) + 1;
1,242✔
1677
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
1,242✔
1678
  } else if (len < strlen(pTscObj->db) + 1) {
1,242✔
1679
    tstrncpy(database, pTscObj->db, len);
621✔
1680
    if (required) *required = strlen(pTscObj->db) + 1;
621✔
1681
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
621✔
1682
  } else {
1683
    tstrncpy(database, pTscObj->db, len);
621✔
1684
    code = 0;
621✔
1685
  }
1686
_return:
2,484✔
1687
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
2,484✔
1688
  releaseTscObj(*(int64_t *)taos);
2,484✔
1689
  return code;
2,484✔
1690
}
1691

1692
// buffer is allocated by caller, len is in/out parameter, input is buffer length, output is actual length.
1693
// because this is a general purpose api, buffer is not null-terminated string even for string info, and
1694
// the return length is the actual length of the info, not including null-terminator.
UNCOV
1695
int taos_get_connection_info(TAOS *taos, TSDB_CONNECTION_INFO info, char *buffer, int *len) {
×
UNCOV
1696
  if (len == NULL) {
×
UNCOV
1697
    return TSDB_CODE_INVALID_PARA;
×
1698
  }
1699

UNCOV
1700
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
UNCOV
1701
  if (pTscObj == NULL) {
×
UNCOV
1702
    return TSDB_CODE_TSC_DISCONNECTED;
×
1703
  }
1704

UNCOV
1705
  int code = TSDB_CODE_SUCCESS;
×
UNCOV
1706
  (void)taosThreadMutexLock(&pTscObj->mutex);
×
1707

UNCOV
1708
  switch (info) {
×
UNCOV
1709
    case TSDB_CONNECTION_INFO_USER: {
×
UNCOV
1710
      int userLen = strlen(pTscObj->user);
×
UNCOV
1711
      if (buffer == NULL || *len < userLen) {
×
UNCOV
1712
        *len = userLen;
×
UNCOV
1713
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1714
      } else {
UNCOV
1715
        *len = userLen;
×
UNCOV
1716
        (void)memcpy(buffer, pTscObj->user, userLen);
×
1717
      }
UNCOV
1718
      break;
×
1719
    }
1720

UNCOV
1721
    case TSDB_CONNECTION_INFO_TOKEN: {
×
UNCOV
1722
      int tokenLen = strlen(pTscObj->tokenName);
×
UNCOV
1723
      if (tokenLen == 0) {
×
UNCOV
1724
        *len = 0;
×
UNCOV
1725
      } else if (buffer == NULL || *len < tokenLen) {
×
UNCOV
1726
        *len = tokenLen;
×
UNCOV
1727
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1728
      } else {
UNCOV
1729
        *len = tokenLen;
×
UNCOV
1730
        (void)memcpy(buffer, pTscObj->tokenName, tokenLen);
×
1731
      }
UNCOV
1732
      break;
×
1733
    }
1734

UNCOV
1735
    default:
×
1736
      TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1737
  }
1738

UNCOV
1739
_return:
×
UNCOV
1740
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
×
UNCOV
1741
  releaseTscObj(*(int64_t *)taos);
×
UNCOV
1742
  return code;
×
1743
}
1744

1745
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
2,147,483,647✔
1746
  if (NULL == pWrapper) {
2,147,483,647✔
1747
    return;
1,190,841,994✔
1748
  }
1749
  destoryCatalogReq(pWrapper->pCatalogReq);
1,087,376,315✔
1750
  taosMemoryFree(pWrapper->pCatalogReq);
1,087,451,149✔
1751
  qDestroyParseContext(pWrapper->pParseCtx);
1,087,450,302✔
1752
  taosMemoryFree(pWrapper);
1,087,423,574✔
1753
}
1754

1755
void destroyCtxInRequest(SRequestObj *pRequest) {
2,788,693✔
1756
  schedulerFreeJob(&pRequest->body.queryJob, 0);
2,788,693✔
1757
  qDestroyQuery(pRequest->pQuery);
2,788,693✔
1758
  pRequest->pQuery = NULL;
2,788,693✔
1759
  destorySqlCallbackWrapper(pRequest->pWrapper);
2,788,693✔
1760
  pRequest->pWrapper = NULL;
2,788,693✔
1761
}
2,788,693✔
1762

1763
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
468,393,346✔
1764
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
468,393,346✔
1765
  SRequestObj         *pRequest = pWrapper->pRequest;
468,393,346✔
1766
  SQuery              *pQuery = pRequest->pQuery;
468,393,346✔
1767

1768
  qDebug("req:0x%" PRIx64 ", start to semantic analysis, QID:0x%" PRIx64, pRequest->self, pRequest->requestId);
468,392,912✔
1769

1770
  int64_t analyseStart = taosGetTimestampUs();
468,393,828✔
1771
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
468,393,828✔
1772
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
468,393,828✔
1773

1774
  if (TSDB_CODE_SUCCESS == code) {
468,392,866✔
1775
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
468,392,514✔
1776
  }
1777

1778
  if (TSDB_CODE_SUCCESS == code) {
468,355,209✔
1779
    code = sqlSecurityCheckASTLevel(pRequest, pQuery);
386,638,157✔
1780
  }
1781

1782
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
468,346,816✔
1783

1784
  if (pRequest->parseOnly) {
468,342,810✔
1785
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
308,854✔
1786
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
308,854✔
1787
  }
1788

1789
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
468,341,283✔
1790
}
468,357,554✔
1791

UNCOV
1792
int32_t cloneCatalogReq(SCatalogReq **ppTarget, SCatalogReq *pSrc) {
×
UNCOV
1793
  int32_t      code = TSDB_CODE_SUCCESS;
×
UNCOV
1794
  SCatalogReq *pTarget = taosMemoryCalloc(1, sizeof(SCatalogReq));
×
UNCOV
1795
  if (pTarget == NULL) {
×
UNCOV
1796
    code = terrno;
×
1797
  } else {
UNCOV
1798
    pTarget->pDbVgroup = taosArrayDup(pSrc->pDbVgroup, NULL);
×
UNCOV
1799
    pTarget->pDbCfg = taosArrayDup(pSrc->pDbCfg, NULL);
×
UNCOV
1800
    pTarget->pDbInfo = taosArrayDup(pSrc->pDbInfo, NULL);
×
UNCOV
1801
    pTarget->pTableMeta = taosArrayDup(pSrc->pTableMeta, NULL);
×
UNCOV
1802
    pTarget->pTableHash = taosArrayDup(pSrc->pTableHash, NULL);
×
UNCOV
1803
    pTarget->pUdf = taosArrayDup(pSrc->pUdf, NULL);
×
UNCOV
1804
    pTarget->pIndex = taosArrayDup(pSrc->pIndex, NULL);
×
UNCOV
1805
    pTarget->pUser = taosArrayDup(pSrc->pUser, NULL);
×
UNCOV
1806
    pTarget->pTableIndex = taosArrayDup(pSrc->pTableIndex, NULL);
×
UNCOV
1807
    pTarget->pTableCfg = taosArrayDup(pSrc->pTableCfg, NULL);
×
UNCOV
1808
    pTarget->pTableTag = taosArrayDup(pSrc->pTableTag, NULL);
×
UNCOV
1809
    pTarget->pView = taosArrayDup(pSrc->pView, NULL);
×
UNCOV
1810
    pTarget->pTableTSMAs = taosArrayDup(pSrc->pTableTSMAs, NULL);
×
UNCOV
1811
    pTarget->pTSMAs = taosArrayDup(pSrc->pTSMAs, NULL);
×
UNCOV
1812
    pTarget->pVStbRefDbs = taosArrayDup(pSrc->pVStbRefDbs, NULL);
×
UNCOV
1813
    pTarget->qNodeRequired = pSrc->qNodeRequired;
×
UNCOV
1814
    pTarget->dNodeRequired = pSrc->dNodeRequired;
×
UNCOV
1815
    pTarget->svrVerRequired = pSrc->svrVerRequired;
×
UNCOV
1816
    pTarget->forceUpdate = pSrc->forceUpdate;
×
UNCOV
1817
    pTarget->cloned = true;
×
1818

UNCOV
1819
    *ppTarget = pTarget;
×
1820
  }
1821

UNCOV
1822
  return code;
×
1823
}
1824

UNCOV
1825
void handleSubQueryFromAnalyse(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, SNode *pRoot) {
×
1826
  SRequestObj         *pNewRequest = NULL;
×
1827
  SSqlCallbackWrapper *pNewWrapper = NULL;
×
1828
  int32_t              code = buildPreviousRequest(pWrapper->pRequest, pWrapper->pRequest->sqlstr, &pNewRequest);
×
1829
  if (code) {
×
1830
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
UNCOV
1831
    return;
×
1832
  }
1833

1834
  pNewRequest->pQuery = NULL;
×
1835
  code = nodesMakeNode(QUERY_NODE_QUERY, (SNode **)&pNewRequest->pQuery);
×
1836
  if (pNewRequest->pQuery) {
×
1837
    pNewRequest->pQuery->pRoot = pRoot;
×
1838
    pRoot = NULL;
×
1839
    pNewRequest->pQuery->execStage = QUERY_EXEC_STAGE_ANALYSE;
×
1840
  }
1841
  if (TSDB_CODE_SUCCESS == code) {
×
1842
    code = prepareAndParseSqlSyntax(&pNewWrapper, pNewRequest, false);
×
1843
  }
1844
  if (TSDB_CODE_SUCCESS == code) {
×
1845
    code = cloneCatalogReq(&pNewWrapper->pCatalogReq, pWrapper->pCatalogReq);
×
1846
  }
1847
  if (TSDB_CODE_SUCCESS == code) {
×
1848
    doAsyncQueryFromAnalyse(pResultMeta, pNewWrapper, code);
×
1849
    nodesDestroyNode(pRoot);
×
1850
  } else {
1851
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
UNCOV
1852
    return;
×
1853
  }
1854
}
1855

1856
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
468,333,471✔
1857
  SRequestObj *pRequest = pWrapper->pRequest;
468,333,471✔
1858
  SQuery      *pQuery = pRequest->pQuery;
468,342,319✔
1859

1860
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
468,337,962✔
1861
    SNode *prevRoot = pQuery->pPrevRoot;
×
1862
    pQuery->pPrevRoot = NULL;
×
1863
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
×
1864
    return;
×
1865
  }
1866

1867
  if (code == TSDB_CODE_SUCCESS) {
468,321,484✔
1868
    pRequest->stableQuery = pQuery->stableQuery;
386,632,218✔
1869
    if (pQuery->pRoot) {
386,634,896✔
1870
      pRequest->stmtType = pQuery->pRoot->type;
386,638,673✔
1871
      if (nodeType(pQuery->pRoot) == QUERY_NODE_DELETE_STMT) {
386,645,328✔
1872
        pRequest->secureDelete = ((SDeleteStmt*)pQuery->pRoot)->secureDelete;
1,713,715✔
1873
      }
1874
    }
1875

1876
    if (pQuery->haveResultSet) {
386,630,687✔
1877
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema,
206,744,996✔
1878
                              pRequest->stmtBindVersion > 0);
206,745,753✔
1879
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
206,745,825✔
1880
    }
1881
  }
1882

1883
  if (code == TSDB_CODE_SUCCESS) {
468,350,184✔
1884
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
386,631,692✔
1885
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
386,595,881✔
1886
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
386,600,024✔
1887

1888
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
386,624,000✔
1889
  } else {
1890
    destorySqlCallbackWrapper(pWrapper);
81,718,492✔
1891
    pRequest->pWrapper = NULL;
81,720,927✔
1892
    qDestroyQuery(pRequest->pQuery);
81,720,927✔
1893
    pRequest->pQuery = NULL;
81,725,123✔
1894

1895
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
81,725,123✔
1896
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
2,696,820✔
1897
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1898
      restartAsyncQuery(pRequest, code);
2,696,820✔
1899
      return;
2,696,847✔
1900
    }
1901

1902
    // return to app directly
1903
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self,
79,028,303✔
1904
             tstrerror(code), pRequest->requestId);
1905
    pRequest->code = code;
79,040,720✔
1906
    returnToUser(pRequest);
79,040,720✔
1907
  }
1908
}
1909

1910
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
476,036,192✔
1911
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
759,812,981✔
1912
                           .requestId = pWrapper->pParseCtx->requestId,
476,037,362✔
1913
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
476,042,750✔
1914
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
476,033,963✔
1915

1916
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
759,817,392✔
1917

1918
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
668,291,952✔
1919
                                &pWrapper->pRequest->body.queryJob);
476,036,588✔
1920
}
1921

1922
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1923

1924
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
1,080,047,707✔
1925
  int32_t      code = TSDB_CODE_SUCCESS;
1,080,047,707✔
1926
  SRequestObj *pRequest = pWrapper->pRequest;
1,080,047,707✔
1927

1928
  switch (pRequest->pQuery->execStage) {
1,080,109,911✔
1929
    case QUERY_EXEC_STAGE_PARSE: {
7,671,725✔
1930
      CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_CATALOG);
15,208,726✔
1931
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
7,671,862✔
1932
      break;
7,671,862✔
1933
    }
1934
    case QUERY_EXEC_STAGE_ANALYSE: {
468,341,105✔
1935
      CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_CATALOG);
936,717,267✔
1936
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
468,381,616✔
1937
      break;
468,357,373✔
1938
    }
1939
    case QUERY_EXEC_STAGE_SCHEDULE: {
604,050,879✔
1940
      CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_SCHEDULE);
1,208,149,235✔
1941
      launchAsyncQuery(pRequest, pRequest->pQuery, NULL, pWrapper);
604,121,412✔
1942
      break;
604,080,207✔
1943
    }
UNCOV
1944
    default:
×
UNCOV
1945
      break;
×
1946
  }
1947
  return code;
1,080,103,768✔
1948
}
1949

1950
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
7,671,886✔
1951
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
7,671,886✔
1952
  SRequestObj         *pRequest = pWrapper->pRequest;
7,671,886✔
1953
  SQuery              *pQuery = pRequest->pQuery;
7,671,886✔
1954

1955
  pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart;
7,671,886✔
1956
  qDebug("req:0x%" PRIx64 ", continue parse query, QID:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId,
7,671,886✔
1957
         tstrerror(code));
1958

1959
  if (code == TSDB_CODE_SUCCESS) {
7,671,886✔
1960
    // pWrapper->pCatalogReq->forceUpdate = false;
1961
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
7,637,460✔
1962
  }
1963

1964
  if (TSDB_CODE_SUCCESS == code) {
7,671,886✔
1965
    code = phaseAsyncQuery(pWrapper);
7,061,933✔
1966
  }
1967

1968
  if (TSDB_CODE_SUCCESS != code) {
7,671,886✔
1969
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
609,953✔
1970
             tstrerror(code), pWrapper->pRequest->requestId);
1971
    destorySqlCallbackWrapper(pWrapper);
609,953✔
1972
    pRequest->pWrapper = NULL;
609,953✔
1973
    terrno = code;
609,953✔
1974
    pRequest->code = code;
609,953✔
1975
    doRequestCallback(pRequest, code);
609,953✔
1976
  }
1977
}
7,671,886✔
1978

1979
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
12,787✔
1980
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
12,787✔
1981
  if (TSDB_CODE_SUCCESS == code) {
12,787✔
1982
    code = phaseAsyncQuery(pWrapper);
12,787✔
1983
  }
1984

1985
  if (TSDB_CODE_SUCCESS != code) {
12,787✔
UNCOV
1986
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
×
1987
             tstrerror(code), pWrapper->pRequest->requestId);
UNCOV
1988
    destorySqlCallbackWrapper(pWrapper);
×
UNCOV
1989
    pRequest->pWrapper = NULL;
×
UNCOV
1990
    terrno = code;
×
UNCOV
1991
    pRequest->code = code;
×
UNCOV
1992
    doRequestCallback(pRequest, code);
×
1993
  }
1994
}
12,787✔
1995

1996
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
137,730✔
1997
  int64_t connId = *(int64_t *)taos;
137,730✔
1998
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
137,730✔
1999
}
137,730✔
2000

UNCOV
2001
void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) {
×
UNCOV
2002
  int64_t connId = *(int64_t *)taos;
×
UNCOV
2003
  taosAsyncQueryImplWithReqid(connId, sql, fp, param, false, reqid);
×
UNCOV
2004
}
×
2005

2006
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
1,087,399,945✔
2007
  const STscObj *pTscObj = pRequest->pTscObj;
1,087,399,945✔
2008

2009
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
1,087,450,359✔
2010
  if (*pCxt == NULL) {
1,087,368,733✔
UNCOV
2011
    return terrno;
×
2012
  }
2013

2014
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
2,147,483,647✔
2015
                           .requestRid = pRequest->self,
1,087,387,398✔
2016
                           .acctId = pTscObj->acctId,
1,087,411,956✔
2017
                           .db = pRequest->pDb,
1,087,414,251✔
2018
                           .topicQuery = false,
2019
                           .pSql = pRequest->sqlstr,
1,087,444,853✔
2020
                           .sqlLen = pRequest->sqlLen,
1,087,444,170✔
2021
                           .pMsg = pRequest->msgBuf,
1,087,424,226✔
2022
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
2023
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
1,087,418,312✔
2024
                           .pStmtCb = NULL,
2025
                           .pUser = pTscObj->user,
1,087,438,727✔
2026
                           .userId = pTscObj->userId,
1,087,432,899✔
2027
                           .pEffectiveUser = pRequest->effectiveUser,
1,087,436,734✔
2028
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
1,087,439,066✔
2029
                           .enableSysInfo = pTscObj->sysInfo,
1,087,427,530✔
2030
                           .privInfo = pWrapper->pParseCtx ? pWrapper->pParseCtx->privInfo : 0,
1,087,423,131✔
2031
                           .sodInitial = pTscObj->pAppInfo->serverCfg.sodInitial,
1,087,437,575✔
2032
                           .async = true,
2033
                           .svrVer = pTscObj->sVer,
1,087,391,130✔
2034
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes), .allocatorId = pRequest->allocatorRefId,
1,971,453,377✔
2035
                           .parseSqlFp = clientParseSql,
2036
                           .parseSqlParam = pWrapper,
2037
                           .setQueryFp = setQueryRequest,
2038
                           .timezone = pTscObj->optionInfo.timezone,
1,087,428,503✔
2039
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
1,087,415,048✔
2040
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
1,087,421,710✔
2041
  (*pCxt)->biMode = biMode;
1,087,400,755✔
2042
  (*pCxt)->minSecLevel = pTscObj->minSecLevel;
1,087,422,043✔
2043
  (*pCxt)->maxSecLevel = pTscObj->maxSecLevel;
1,087,435,041✔
2044
  (*pCxt)->macMode = pTscObj->pAppInfo->serverCfg.macActive;
1,087,448,741✔
2045
  return TSDB_CODE_SUCCESS;
1,087,446,517✔
2046
}
2047

2048
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
1,087,393,377✔
2049
  int32_t              code = TSDB_CODE_SUCCESS;
1,087,393,377✔
2050
  STscObj             *pTscObj = pRequest->pTscObj;
1,087,393,377✔
2051
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
1,087,440,170✔
2052
  if (pWrapper == NULL) {
1,087,405,750✔
UNCOV
2053
    code = terrno;
×
2054
  } else {
2055
    pWrapper->pRequest = pRequest;
1,087,405,750✔
2056
    pRequest->pWrapper = pWrapper;
1,087,390,918✔
2057
    *ppWrapper = pWrapper;
1,087,431,133✔
2058
  }
2059

2060
  if (TSDB_CODE_SUCCESS == code) {
1,087,423,562✔
2061
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
1,087,427,652✔
2062
  }
2063

2064
  if (TSDB_CODE_SUCCESS == code) {
1,087,418,956✔
2065
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
1,087,421,591✔
2066
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
1,087,477,311✔
2067
  }
2068

2069
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
1,087,419,883✔
2070
    int64_t syntaxStart = taosGetTimestampUs();
1,087,455,267✔
2071

2072
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
1,087,455,267✔
2073
    if (pWrapper->pCatalogReq == NULL) {
1,087,345,589✔
UNCOV
2074
      code = terrno;
×
2075
    } else {
2076
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
1,087,365,778✔
2077
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
1,087,385,751✔
2078
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
1,087,404,751✔
2079
    }
2080

2081
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
1,087,389,317✔
2082
  }
2083

2084
  return code;
1,087,460,180✔
2085
}
2086

2087
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
1,088,289,274✔
2088
  SSqlCallbackWrapper *pWrapper = NULL;
1,088,289,274✔
2089
  int32_t              code = TSDB_CODE_SUCCESS;
1,088,326,815✔
2090

2091
  CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_PARSE);
2,147,483,647✔
2092

2093
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
1,088,378,910✔
2094
    code = pRequest->prevCode;
900,880✔
2095
    terrno = code;
900,880✔
2096
    pRequest->code = code;
900,880✔
2097
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
900,880✔
2098
    doRequestCallback(pRequest, code);
900,880✔
2099
    return;
900,880✔
2100
  }
2101

2102
  if (TSDB_CODE_SUCCESS == code) {
1,087,405,064✔
2103
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
1,087,391,444✔
2104
  }
2105

2106
  if (TSDB_CODE_SUCCESS == code) {
1,087,398,644✔
2107
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
1,073,034,974✔
2108
    code = phaseAsyncQuery(pWrapper);
1,073,043,491✔
2109
  }
2110

2111
  if (TSDB_CODE_SUCCESS != code) {
1,087,393,582✔
2112
    if (NULL != pRequest->msgBuf && strlen(pRequest->msgBuf) > 0) {
14,377,503✔
2113
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, pRequest->msgBuf,
14,298,606✔
2114
               pRequest->requestId);
2115
    } else {
2116
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
78,897✔
2117
               pRequest->requestId);
2118
    }
2119

2120
    destorySqlCallbackWrapper(pWrapper);
14,377,519✔
2121
    pRequest->pWrapper = NULL;
14,377,503✔
2122
    qDestroyQuery(pRequest->pQuery);
14,377,503✔
2123
    pRequest->pQuery = NULL;
14,377,503✔
2124

2125
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
14,377,503✔
2126
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
13,202✔
2127
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
2128
      code = refreshMeta(pRequest->pTscObj, pRequest);
13,202✔
2129
      if (code != 0) {
13,202✔
2130
        tscWarn("req:0x%" PRIx64 ", refresh meta failed, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code,
13,202✔
2131
                tstrerror(code), pRequest->requestId);
2132
      }
2133
      pRequest->prevCode = code;
13,202✔
2134
      doAsyncQuery(pRequest, true);
13,202✔
2135
      return;
13,202✔
2136
    }
2137

2138
    terrno = code;
14,364,301✔
2139
    pRequest->code = code;
14,364,207✔
2140
    doRequestCallback(pRequest, code);
14,364,207✔
2141
  }
2142
}
2143

2144
void restartAsyncQuery(SRequestObj *pRequest, int32_t code) {
2,788,693✔
2145
  tscInfo("restart request:%s p:%p", pRequest->sqlstr, pRequest);
2,788,693✔
2146
  SRequestObj *pUserReq = pRequest;
2,788,693✔
2147
  (void)acquireRequest(pRequest->self);
2,788,693✔
2148
  while (pUserReq) {
2,788,693✔
2149
    if (pUserReq->self == pUserReq->relation.userRefId || pUserReq->relation.userRefId == 0) {
2,788,693✔
2150
      break;
2151
    } else {
UNCOV
2152
      int64_t nextRefId = pUserReq->relation.nextRefId;
×
UNCOV
2153
      (void)releaseRequest(pUserReq->self);
×
UNCOV
2154
      if (nextRefId) {
×
UNCOV
2155
        pUserReq = acquireRequest(nextRefId);
×
2156
      }
2157
    }
2158
  }
2159
  bool hasSubRequest = pUserReq != pRequest || pRequest->relation.prevRefId != 0;
2,788,693✔
2160
  if (pUserReq) {
2,788,693✔
2161
    destroyCtxInRequest(pUserReq);
2,788,693✔
2162
    pUserReq->prevCode = code;
2,788,693✔
2163
    (void)memset(&pUserReq->relation, 0, sizeof(pUserReq->relation));
2,788,693✔
2164
  } else {
UNCOV
2165
    tscError("User req is missing");
×
UNCOV
2166
    (void)removeFromMostPrevReq(pRequest);
×
UNCOV
2167
    return;
×
2168
  }
2169
  if (hasSubRequest)
2,788,693✔
UNCOV
2170
    (void)removeFromMostPrevReq(pRequest);
×
2171
  else
2172
    (void)releaseRequest(pUserReq->self);
2,788,693✔
2173
  doAsyncQuery(pUserReq, true);
2,788,693✔
2174
}
2175

2176
typedef struct SAsyncFetchParam {
2177
  SRequestObj      *pReq;
2178
  __taos_async_fn_t fp;
2179
  void             *param;
2180
} SAsyncFetchParam;
2181

2182
static int32_t doAsyncFetch(void *pParam) {
320,572,082✔
2183
  SAsyncFetchParam *param = pParam;
320,572,082✔
2184
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
320,572,082✔
2185
  taosMemoryFree(param);
320,571,338✔
2186
  return TSDB_CODE_SUCCESS;
320,571,380✔
2187
}
2188

2189
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
320,611,381✔
2190
  if (res == NULL || fp == NULL) {
320,611,381✔
2191
    tscError("taos_fetch_rows_a invalid paras");
×
2192
    return;
×
2193
  }
2194
  if (!TD_RES_QUERY(res)) {
320,611,411✔
UNCOV
2195
    tscError("taos_fetch_rows_a res is NULL");
×
UNCOV
2196
    fp(param, res, TSDB_CODE_APP_ERROR);
×
UNCOV
2197
    return;
×
2198
  }
2199

2200
  SRequestObj *pRequest = res;
320,611,373✔
2201

2202
  // Each fetch call sets phase to IN_PROGRESS
2203

2204
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
320,611,373✔
2205
    CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_FETCH_RETURNED);
78,670✔
2206
    fp(param, res, 0);
39,335✔
2207
    return;
39,335✔
2208
  }
2209

2210
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
320,572,038✔
2211
  if (!pParam) {
320,572,082✔
UNCOV
2212
    CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_FETCH_RETURNED);
×
UNCOV
2213
    fp(param, res, terrno);
×
UNCOV
2214
    return;
×
2215
  }
2216

2217
  CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_FETCH_IN_PROGRESS);
475,599,467✔
2218
  pParam->pReq = pRequest;
320,572,085✔
2219
  pParam->fp = fp;
320,572,085✔
2220
  pParam->param = param;
320,572,082✔
2221
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
320,572,082✔
2222
  if (TSDB_CODE_SUCCESS != code) {
320,572,085✔
UNCOV
2223
    taosMemoryFree(pParam);
×
UNCOV
2224
    fp(param, res, code);
×
UNCOV
2225
    return;
×
2226
  }
2227
}
2228

2229
void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
171✔
2230
  if (res == NULL || fp == NULL) {
171✔
UNCOV
2231
    tscError("taos_fetch_raw_block_a invalid paras");
×
UNCOV
2232
    return;
×
2233
  }
2234
  if (!TD_RES_QUERY(res)) {
171✔
2235
    tscError("taos_fetch_raw_block_a res is NULL");
×
UNCOV
2236
    return;
×
2237
  }
2238
  SRequestObj    *pRequest = res;
171✔
2239
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
171✔
2240

2241
  CLIENT_UPDATE_REQUEST_PHASE_IF_CHANGED(pRequest, QUERY_PHASE_FETCH_IN_PROGRESS);
243✔
2242
  // set the current block is all consumed
2243
  pResultInfo->convertUcs4 = false;
171✔
2244

2245
  // it is a local executed query, no need to do async fetch
2246
  taos_fetch_rows_a(pRequest, fp, param);
171✔
2247
}
2248

2249
const void *taos_get_raw_block(TAOS_RES *res) {
108✔
2250
  if (res == NULL) {
108✔
2251
    tscError("taos_get_raw_block invalid paras");
×
2252
    return NULL;
×
2253
  }
2254
  if (!TD_RES_QUERY(res)) {
108✔
UNCOV
2255
    tscError("taos_get_raw_block res is NULL");
×
UNCOV
2256
    return NULL;
×
2257
  }
2258
  SRequestObj *pRequest = res;
108✔
2259

2260
  return pRequest->body.resInfo.pData;
108✔
2261
}
2262

2263
int taos_get_db_route_info(TAOS *taos, const char *db, TAOS_DB_ROUTE_INFO *dbInfo) {
×
UNCOV
2264
  if (NULL == taos) {
×
UNCOV
2265
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2266
    return terrno;
×
2267
  }
2268

2269
  if (NULL == db || NULL == dbInfo) {
×
2270
    tscError("invalid input param, db:%p, dbInfo:%p", db, dbInfo);
×
UNCOV
2271
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
UNCOV
2272
    return terrno;
×
2273
  }
2274

UNCOV
2275
  int64_t      connId = *(int64_t *)taos;
×
UNCOV
2276
  SRequestObj *pRequest = NULL;
×
UNCOV
2277
  char        *sql = "taos_get_db_route_info";
×
UNCOV
2278
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
UNCOV
2279
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2280
    terrno = code;
×
UNCOV
2281
    return terrno;
×
2282
  }
2283

UNCOV
2284
  STscObj  *pTscObj = pRequest->pTscObj;
×
UNCOV
2285
  SCatalog *pCtg = NULL;
×
UNCOV
2286
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
UNCOV
2287
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2288
    goto _return;
×
2289
  }
2290

UNCOV
2291
  SRequestConnInfo conn = {
×
UNCOV
2292
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2293

2294
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2295

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

UNCOV
2299
  code = catalogGetDBVgInfo(pCtg, &conn, dbFName, dbInfo);
×
UNCOV
2300
  if (code) {
×
2301
    goto _return;
×
2302
  }
2303

2304
_return:
×
2305

UNCOV
2306
  terrno = code;
×
2307

2308
  destroyRequest(pRequest);
×
2309
  return code;
×
2310
}
2311

UNCOV
2312
int taos_get_table_vgId(TAOS *taos, const char *db, const char *table, int *vgId) {
×
2313
  if (NULL == taos) {
×
2314
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2315
    return terrno;
×
2316
  }
2317

2318
  if (NULL == db || NULL == table || NULL == vgId) {
×
2319
    tscError("invalid input param, db:%p, table:%p, vgId:%p", db, table, vgId);
×
UNCOV
2320
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
UNCOV
2321
    return terrno;
×
2322
  }
2323

2324
  int64_t      connId = *(int64_t *)taos;
×
2325
  SRequestObj *pRequest = NULL;
×
2326
  char        *sql = "taos_get_table_vgId";
×
UNCOV
2327
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
UNCOV
2328
  if (code != TSDB_CODE_SUCCESS) {
×
2329
    return terrno;
×
2330
  }
2331

2332
  pRequest->syncQuery = true;
×
2333

2334
  STscObj  *pTscObj = pRequest->pTscObj;
×
2335
  SCatalog *pCtg = NULL;
×
UNCOV
2336
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2337
  if (code != TSDB_CODE_SUCCESS) {
×
2338
    goto _return;
×
2339
  }
2340

UNCOV
2341
  SRequestConnInfo conn = {
×
2342
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2343

2344
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2345

2346
  SName tableName = {0};
×
2347
  toName(pTscObj->acctId, db, table, &tableName);
×
2348

UNCOV
2349
  SVgroupInfo vgInfo;
×
2350
  code = catalogGetTableHashVgroup(pCtg, &conn, &tableName, &vgInfo);
×
2351
  if (code) {
×
2352
    goto _return;
×
2353
  }
2354

UNCOV
2355
  *vgId = vgInfo.vgId;
×
2356

2357
_return:
×
2358

2359
  terrno = code;
×
2360

UNCOV
2361
  destroyRequest(pRequest);
×
2362
  return code;
×
2363
}
2364

2365
int taos_get_tables_vgId(TAOS *taos, const char *db, const char *table[], int tableNum, int *vgId) {
×
2366
  if (NULL == taos) {
×
2367
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2368
    return terrno;
×
2369
  }
2370

UNCOV
2371
  if (NULL == db || NULL == table || NULL == vgId || tableNum <= 0) {
×
2372
    tscError("invalid input param, db:%p, table:%p, vgId:%p, tbNum:%d", db, table, vgId, tableNum);
×
2373
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
2374
    return terrno;
×
2375
  }
2376

UNCOV
2377
  int64_t      connId = *(int64_t *)taos;
×
UNCOV
2378
  SRequestObj *pRequest = NULL;
×
2379
  char        *sql = "taos_get_table_vgId";
×
2380
  int32_t      code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
×
UNCOV
2381
  if (code != TSDB_CODE_SUCCESS) {
×
2382
    return terrno;
×
2383
  }
2384

2385
  pRequest->syncQuery = true;
×
2386

2387
  STscObj  *pTscObj = pRequest->pTscObj;
×
2388
  SCatalog *pCtg = NULL;
×
2389
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
×
2390
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2391
    goto _return;
×
2392
  }
2393

UNCOV
2394
  SRequestConnInfo conn = {
×
2395
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
×
2396

2397
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2398

2399
  code = catalogGetTablesHashVgId(pCtg, &conn, pTscObj->acctId, db, table, tableNum, vgId);
×
2400
  if (code) {
×
UNCOV
2401
    goto _return;
×
2402
  }
2403

2404
_return:
×
2405

2406
  terrno = code;
×
2407

UNCOV
2408
  destroyRequest(pRequest);
×
2409
  return code;
×
2410
}
2411

2412
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
1,252✔
2413
  if (NULL == taos) {
1,252✔
UNCOV
2414
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2415
    return terrno;
×
2416
  }
2417

2418
  int64_t       connId = *(int64_t *)taos;
1,252✔
2419
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
1,252✔
2420
  int32_t       code = 0;
1,252✔
2421
  SRequestObj  *pRequest = NULL;
1,252✔
2422
  SCatalogReq   catalogReq = {0};
1,252✔
2423

2424
  if (NULL == tableNameList) {
1,252✔
2425
    return TSDB_CODE_SUCCESS;
×
2426
  }
2427

2428
  int32_t length = (int32_t)strlen(tableNameList);
1,252✔
2429
  if (0 == length) {
1,252✔
UNCOV
2430
    return TSDB_CODE_SUCCESS;
×
2431
  } else if (length > MAX_TABLE_NAME_LENGTH) {
1,252✔
2432
    tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH);
×
2433
    return TSDB_CODE_TSC_INVALID_OPERATION;
×
2434
  }
2435

2436
  char *sql = "taos_load_table_info";
1,252✔
2437
  code = buildRequest(connId, sql, strlen(sql), NULL, false, &pRequest, 0);
1,252✔
2438
  if (code != TSDB_CODE_SUCCESS) {
1,252✔
2439
    terrno = code;
×
UNCOV
2440
    goto _return;
×
2441
  }
2442

2443
  pRequest->syncQuery = true;
1,252✔
2444

2445
  STscObj *pTscObj = pRequest->pTscObj;
1,252✔
2446
  code = transferTableNameList(tableNameList, pTscObj->acctId, pTscObj->db, &catalogReq.pTableMeta);
1,252✔
2447
  if (code) {
1,252✔
UNCOV
2448
    goto _return;
×
2449
  }
2450

2451
  SCatalog *pCtg = NULL;
1,252✔
2452
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCtg);
1,252✔
2453
  if (code != TSDB_CODE_SUCCESS) {
1,252✔
UNCOV
2454
    goto _return;
×
2455
  }
2456

2457
  SRequestConnInfo conn = {
1,252✔
2458
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
1,252✔
2459

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

2462
  code = catalogAsyncGetAllMeta(pCtg, &conn, &catalogReq, syncCatalogFn, pRequest->body.interParam, NULL);
1,252✔
2463
  if (code) {
1,252✔
UNCOV
2464
    goto _return;
×
2465
  }
2466

2467
  SSyncQueryParam *pParam = pRequest->body.interParam;
1,252✔
2468
  code = tsem_wait(&pParam->sem);
1,252✔
2469
  if (code) {
1,252✔
2470
    tscError("tsem wait failed, code:%d - %s", code, tstrerror(code));
×
2471
    goto _return;
×
2472
  }
2473
_return:
1,252✔
2474
  destoryCatalogReq(&catalogReq);
1,252✔
2475
  destroyRequest(pRequest);
1,252✔
2476
  return code;
1,252✔
2477
}
2478

2479
TAOS_STMT *taos_stmt_init(TAOS *taos) {
27,383✔
2480
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
27,383✔
2481
  if (NULL == pObj) {
27,383✔
UNCOV
2482
    tscError("invalid parameter for %s", __FUNCTION__);
×
UNCOV
2483
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2484
    return NULL;
×
2485
  }
2486

2487
  TAOS_STMT *pStmt = stmtInit(pObj, 0, NULL);
27,383✔
2488
  if (NULL == pStmt) {
27,383✔
UNCOV
2489
    tscError("stmt init failed, errcode:%s", terrstr());
×
2490
  }
2491
  releaseTscObj(*(int64_t *)taos);
27,383✔
2492

2493
  return pStmt;
27,383✔
2494
}
2495

UNCOV
2496
TAOS_STMT *taos_stmt_init_with_reqid(TAOS *taos, int64_t reqid) {
×
UNCOV
2497
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
UNCOV
2498
  if (NULL == pObj) {
×
UNCOV
2499
    tscError("invalid parameter for %s", __FUNCTION__);
×
UNCOV
2500
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2501
    return NULL;
×
2502
  }
2503

UNCOV
2504
  TAOS_STMT *pStmt = stmtInit(pObj, reqid, NULL);
×
UNCOV
2505
  if (NULL == pStmt) {
×
UNCOV
2506
    tscError("stmt init failed, errcode:%s", terrstr());
×
2507
  }
2508
  releaseTscObj(*(int64_t *)taos);
×
2509

UNCOV
2510
  return pStmt;
×
2511
}
2512

2513
TAOS_STMT *taos_stmt_init_with_options(TAOS *taos, TAOS_STMT_OPTIONS *options) {
12,550✔
2514
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
12,550✔
2515
  if (NULL == pObj) {
12,589✔
UNCOV
2516
    tscError("invalid parameter for %s", __FUNCTION__);
×
UNCOV
2517
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
2518
    return NULL;
×
2519
  }
2520

2521
  TAOS_STMT *pStmt = stmtInit(pObj, options->reqId, options);
12,589✔
2522
  if (NULL == pStmt) {
12,589✔
UNCOV
2523
    tscError("stmt init failed, errcode:%s", terrstr());
×
2524
  }
2525
  releaseTscObj(*(int64_t *)taos);
12,589✔
2526

2527
  return pStmt;
12,589✔
2528
}
2529

2530
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
7,131,628✔
2531
  if (stmt == NULL || sql == NULL) {
7,131,628✔
UNCOV
2532
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2533
    terrno = TSDB_CODE_INVALID_PARA;
×
2534
    return terrno;
×
2535
  }
2536

2537
  return stmtPrepare(stmt, sql, length);
7,132,328✔
2538
}
2539

2540
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
7,846✔
2541
  if (stmt == NULL || name == NULL) {
7,846✔
2542
    tscError("NULL parameter for %s", __FUNCTION__);
×
2543
    terrno = TSDB_CODE_INVALID_PARA;
×
2544
    return terrno;
×
2545
  }
2546

2547
  int32_t code = stmtSetTbName(stmt, name);
7,846✔
2548
  if (code) {
7,846✔
2549
    return code;
626✔
2550
  }
2551

2552
  if (tags) {
7,220✔
2553
    return stmtSetTbTags(stmt, tags);
7,220✔
2554
  }
2555

2556
  return TSDB_CODE_SUCCESS;
×
2557
}
2558

2559
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
8,739,159✔
2560
  if (stmt == NULL || name == NULL) {
8,739,159✔
2561
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2562
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2563
    return terrno;
×
2564
  }
2565

2566
  return stmtSetTbName(stmt, name);
8,745,105✔
2567
}
2568

2569
int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) {
971✔
2570
  if (stmt == NULL || tags == NULL) {
971✔
UNCOV
2571
    tscError("NULL parameter for %s", __FUNCTION__);
×
2572
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2573
    return terrno;
×
2574
  }
2575

2576
  return stmtSetTbTags(stmt, tags);
971✔
2577
}
2578

2579
int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); }
392✔
2580

2581
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
784✔
2582
  if (stmt == NULL || NULL == fieldNum) {
784✔
UNCOV
2583
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2584
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2585
    return terrno;
×
2586
  }
2587

2588
  return stmtGetTagFields(stmt, fieldNum, fields);
784✔
2589
}
2590

2591
int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
1,176✔
2592
  if (stmt == NULL || NULL == fieldNum) {
1,176✔
UNCOV
2593
    tscError("NULL parameter for %s", __FUNCTION__);
×
2594
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2595
    return terrno;
×
2596
  }
2597

2598
  return stmtGetColFields(stmt, fieldNum, fields);
1,176✔
2599
}
2600

2601
// let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields`
UNCOV
2602
void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) {
×
2603
  (void)stmt;
UNCOV
2604
  if (!fields) return;
×
UNCOV
2605
  taosMemoryFree(fields);
×
2606
}
2607

2608
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
48,206✔
2609
  if (stmt == NULL || bind == NULL) {
48,206✔
2610
    tscError("NULL parameter for %s", __FUNCTION__);
×
2611
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2612
    return terrno;
×
2613
  }
2614

2615
  if (bind->num > 1) {
48,206✔
2616
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
4,146✔
2617
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
4,146✔
2618
    return terrno;
4,146✔
2619
  }
2620

2621
  return stmtBindBatch(stmt, bind, -1);
44,060✔
2622
}
2623

2624
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
8,744,244✔
2625
  if (stmt == NULL || bind == NULL) {
8,744,244✔
2626
    tscError("NULL parameter for %s", __FUNCTION__);
1,540✔
2627
    terrno = TSDB_CODE_INVALID_PARA;
1,540✔
UNCOV
2628
    return terrno;
×
2629
  }
2630

2631
  if (bind->num <= 0 || bind->num > INT16_MAX) {
8,745,909✔
2632
    tscError("invalid bind num %d", bind->num);
14,753✔
2633
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
14,753✔
UNCOV
2634
    return terrno;
×
2635
  }
2636

2637
  int32_t insert = 0;
8,738,440✔
2638
  int32_t code = stmtIsInsert(stmt, &insert);
8,743,069✔
2639
  if (TSDB_CODE_SUCCESS != code) {
8,746,239✔
2640
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
UNCOV
2641
    return code;
×
2642
  }
2643
  if (0 == insert && bind->num > 1) {
8,746,239✔
UNCOV
2644
    tscError("only one row data allowed for query");
×
UNCOV
2645
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
UNCOV
2646
    return terrno;
×
2647
  }
2648

2649
  return stmtBindBatch(stmt, bind, -1);
8,746,239✔
2650
}
2651

2652
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
1,120✔
2653
  if (stmt == NULL || bind == NULL) {
1,120✔
UNCOV
2654
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2655
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2656
    return terrno;
×
2657
  }
2658

2659
  if (colIdx < 0) {
1,120✔
UNCOV
2660
    tscError("invalid bind column idx %d", colIdx);
×
UNCOV
2661
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2662
    return terrno;
×
2663
  }
2664

2665
  int32_t insert = 0;
1,120✔
2666
  int32_t code = stmtIsInsert(stmt, &insert);
1,120✔
2667
  if (TSDB_CODE_SUCCESS != code) {
1,120✔
UNCOV
2668
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
UNCOV
2669
    return code;
×
2670
  }
2671
  if (0 == insert && bind->num > 1) {
1,120✔
2672
    tscError("only one row data allowed for query");
×
UNCOV
2673
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
UNCOV
2674
    return terrno;
×
2675
  }
2676

2677
  return stmtBindBatch(stmt, bind, colIdx);
1,120✔
2678
}
2679

2680
int taos_stmt_add_batch(TAOS_STMT *stmt) {
7,391,971✔
2681
  if (stmt == NULL) {
7,391,971✔
2682
    tscError("NULL parameter for %s", __FUNCTION__);
×
2683
    terrno = TSDB_CODE_INVALID_PARA;
×
2684
    return terrno;
×
2685
  }
2686

2687
  return stmtAddBatch(stmt);
7,391,971✔
2688
}
2689

2690
int taos_stmt_execute(TAOS_STMT *stmt) {
7,387,411✔
2691
  if (stmt == NULL) {
7,387,411✔
2692
    tscError("NULL parameter for %s", __FUNCTION__);
×
2693
    terrno = TSDB_CODE_INVALID_PARA;
×
2694
    return terrno;
×
2695
  }
2696

2697
  return stmtExec(stmt);
7,387,411✔
2698
}
2699

2700
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
×
UNCOV
2701
  if (stmt == NULL || insert == NULL) {
×
UNCOV
2702
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2703
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2704
    return terrno;
×
2705
  }
2706

2707
  return stmtIsInsert(stmt, insert);
×
2708
}
2709

2710
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
×
2711
  if (stmt == NULL || nums == NULL) {
×
2712
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2713
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2714
    return terrno;
×
2715
  }
2716

UNCOV
2717
  return stmtGetParamNum(stmt, nums);
×
2718
}
2719

2720
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
784✔
2721
  if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) {
784✔
2722
    tscError("invalid parameter for %s", __FUNCTION__);
×
UNCOV
2723
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2724
    return terrno;
×
2725
  }
2726

2727
  return stmtGetParam(stmt, idx, type, bytes);
784✔
2728
}
2729

2730
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
10,016✔
2731
  if (stmt == NULL) {
10,016✔
2732
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2733
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2734
    return NULL;
×
2735
  }
2736

2737
  return stmtUseResult(stmt);
10,016✔
2738
}
2739

2740
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
14,989✔
2741

2742
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
3,286✔
2743
  if (stmt == NULL) {
3,286✔
UNCOV
2744
    tscError("NULL parameter for %s", __FUNCTION__);
×
2745
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2746
    return 0;
×
2747
  }
2748

2749
  return stmtAffectedRows(stmt);
3,286✔
2750
}
2751

2752
int taos_stmt_affected_rows_once(TAOS_STMT *stmt) {
5,588✔
2753
  if (stmt == NULL) {
5,588✔
UNCOV
2754
    tscError("NULL parameter for %s", __FUNCTION__);
×
2755
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2756
    return 0;
×
2757
  }
2758

2759
  return stmtAffectedRowsOnce(stmt);
5,588✔
2760
}
2761

2762
int taos_stmt_close(TAOS_STMT *stmt) {
39,972✔
2763
  if (stmt == NULL) {
39,972✔
UNCOV
2764
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2765
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2766
    return terrno;
×
2767
  }
2768

2769
  return stmtClose(stmt);
39,972✔
2770
}
2771

2772
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
154,918✔
2773
  if (NULL == taos) {
154,918✔
2774
    tscError("NULL parameter for %s", __FUNCTION__);
196✔
2775
    terrno = TSDB_CODE_INVALID_PARA;
196✔
2776
    return NULL;
196✔
2777
  }
2778
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
154,722✔
2779
  if (NULL == pObj) {
154,749✔
UNCOV
2780
    tscError("invalid parameter for %s", __FUNCTION__);
×
UNCOV
2781
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2782
    return NULL;
×
2783
  }
2784

2785
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
154,749✔
2786

2787
  releaseTscObj(*(int64_t *)taos);
154,749✔
2788

2789
  return pStmt;
154,749✔
2790
}
2791

2792
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
161,386✔
2793
  if (stmt == NULL || sql == NULL) {
161,386✔
2794
    tscError("NULL parameter for %s", __FUNCTION__);
196✔
2795
    terrno = TSDB_CODE_INVALID_PARA;
196✔
2796
    return terrno;
196✔
2797
  }
2798

2799
  return stmtPrepare2(stmt, sql, length);
161,190✔
2800
}
2801

2802
int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx) {
82,033,549✔
2803
  if (stmt == NULL) {
82,033,549✔
2804
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2805
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2806
    return terrno;
×
2807
  }
2808

2809
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
82,033,549✔
2810
  int32_t    code = TSDB_CODE_SUCCESS;
82,033,549✔
2811
  STMT2_DLOG_E("start to bind param");
82,033,549✔
2812

2813
  // check query bind number
2814
  bool isQuery = (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt)));
82,051,106✔
2815
  if (isQuery) {
82,899,385✔
2816
    if (bindv->count != 1 || bindv->bind_cols[0]->num != 1) {
7,653✔
UNCOV
2817
      terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2818
      STMT2_ELOG_E("query only support one table and one row bind");
×
2819
      return terrno;
×
2820
    }
2821
  }
2822

2823
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 1) {
82,899,385✔
2824
    STMT2_ELOG_E("async bind param is still working, please try again later");
1,939✔
2825
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
1,939✔
UNCOV
2826
    return terrno;
×
2827
  }
2828

2829
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
82,385,158✔
2830
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
4,900✔
UNCOV
2831
      STMT2_ELOG_E("bind param wait asyncExecSem failed");
×
2832
    }
2833
    pStmt->execSemWaited = true;
4,900✔
2834
  }
2835

2836
  for (int i = 0; i < bindv->count; ++i) {
164,337,288✔
2837
    SVCreateTbReq *pCreateTbReq = NULL;
82,214,789✔
2838
    if (!isQuery) {
82,717,390✔
2839
      STMT2_TLOG("start to bind %dth table", i);
82,739,457✔
2840
      if (bindv->tbnames && bindv->tbnames[i]) {
82,705,249✔
2841
        code = stmtSetTbName2(stmt, bindv->tbnames[i]);
1,078,294✔
2842
        if (code) {
1,078,237✔
2843
          terrno = code;
2,156✔
2844
          STMT2_ELOG("set tbname failed, code:%s", stmt2Errstr(stmt));
2,156✔
2845
          return terrno;
3,528✔
2846
        }
2847
      }
2848

2849
      if (bindv->tags && bindv->tags[i]) {
83,274,042✔
2850
        code = stmtSetTbTags2(stmt, bindv->tags[i], &pCreateTbReq);
562,405✔
2851
      } else if (pStmt->bInfo.tbNameFlag & IS_FIXED_TAG) {
82,460,401✔
2852
        code = stmtCheckTags2(stmt, &pCreateTbReq);
109,902✔
2853
      } else if (pStmt->sql.autoCreateTbl) {
82,040,440✔
2854
        code = stmtSetTbTags2(stmt, NULL, &pCreateTbReq);
4,116✔
2855
      }
2856

2857
      if (code) {
83,221,919✔
2858
        terrno = code;
196✔
2859
        STMT2_ELOG("set tags failed, code:%s", stmt2Errstr(stmt));
196✔
2860
        if (pCreateTbReq) {
196✔
UNCOV
2861
          tdDestroySVCreateTbReq(pCreateTbReq);
×
UNCOV
2862
          taosMemoryFreeClear(pCreateTbReq);
×
2863
        }
2864
        return terrno;
196✔
2865
      }
2866
    }
2867

2868
    if (bindv->bind_cols && bindv->bind_cols[i]) {
83,199,656✔
2869
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
84,125,589✔
2870

2871
      if (bind->num <= 0 || bind->num > INT16_MAX) {
83,860,185✔
2872
        STMT2_ELOG("bind num:%d must > 0 and < INT16_MAX", bind->num);
74,357✔
2873
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
74,357✔
UNCOV
2874
        if (pCreateTbReq) {
×
UNCOV
2875
          tdDestroySVCreateTbReq(pCreateTbReq);
×
UNCOV
2876
          taosMemoryFreeClear(pCreateTbReq);
×
2877
        }
UNCOV
2878
        return terrno;
×
2879
      }
2880

2881
      code = stmtBindBatch2(stmt, bind, col_idx, pCreateTbReq);
84,316,026✔
2882
      if (TSDB_CODE_SUCCESS != code) {
81,962,778✔
2883
        terrno = code;
1,176✔
2884
        STMT2_ELOG("bind batch failed, code:%s", stmt2Errstr(stmt));
1,176✔
2885
        if (pCreateTbReq) {
1,176✔
2886
          tdDestroySVCreateTbReq(pCreateTbReq);
392✔
2887
          taosMemoryFreeClear(pCreateTbReq);
392✔
2888
        }
2889
        return terrno;
1,176✔
2890
      }
2891
    }
2892
  }
2893

2894
  return code;
82,353,725✔
2895
}
2896

UNCOV
2897
int taos_stmt2_bind_param_a(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx, __taos_async_fn_t fp,
×
2898
                            void *param) {
2899
  if (stmt == NULL || bindv == NULL || fp == NULL) {
×
2900
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2901
    return terrno;
×
2902
  }
2903

UNCOV
2904
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
×
2905

UNCOV
2906
  ThreadArgs *args = (ThreadArgs *)taosMemoryMalloc(sizeof(ThreadArgs));
×
UNCOV
2907
  args->stmt = stmt;
×
UNCOV
2908
  args->bindv = bindv;
×
UNCOV
2909
  args->col_idx = col_idx;
×
UNCOV
2910
  args->fp = fp;
×
UNCOV
2911
  args->param = param;
×
2912

2913
  (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
2914
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 0) {
×
UNCOV
2915
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2916
    tscError("async bind param is still working, please try again later");
×
UNCOV
2917
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
×
UNCOV
2918
    return terrno;
×
2919
  }
UNCOV
2920
  (void)atomic_add_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
UNCOV
2921
  (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
2922

UNCOV
2923
  int code_s = taosStmt2AsyncBind(stmtAsyncBindThreadFunc, (void *)args);
×
UNCOV
2924
  if (code_s != TSDB_CODE_SUCCESS) {
×
UNCOV
2925
    terrno = code_s;
×
UNCOV
2926
    (void)taosThreadMutexLock(&(pStmt->asyncBindParam.mutex));
×
UNCOV
2927
    (void)taosThreadCondSignal(&(pStmt->asyncBindParam.waitCond));
×
UNCOV
2928
    (void)atomic_sub_fetch_8(&pStmt->asyncBindParam.asyncBindNum, 1);
×
UNCOV
2929
    (void)taosThreadMutexUnlock(&(pStmt->asyncBindParam.mutex));
×
UNCOV
2930
    tscError("async bind failed, code:%d , %s", code_s, tstrerror(code_s));
×
2931
  }
2932

UNCOV
2933
  return code_s;
×
2934
}
2935

2936
int taos_stmt2_exec(TAOS_STMT2 *stmt, int *affected_rows) {
640,202✔
2937
  if (stmt == NULL) {
640,202✔
2938
    tscError("NULL parameter for %s", __FUNCTION__);
×
2939
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2940
    return terrno;
×
2941
  }
2942

2943
  return stmtExec2(stmt, affected_rows);
640,202✔
2944
}
2945

2946
int taos_stmt2_close(TAOS_STMT2 *stmt) {
153,994✔
2947
  if (stmt == NULL) {
153,994✔
2948
    tscError("NULL parameter for %s", __FUNCTION__);
×
2949
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2950
    return terrno;
×
2951
  }
2952

2953
  return stmtClose2(stmt);
153,994✔
2954
}
2955

2956
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
194✔
2957
  if (stmt == NULL || insert == NULL) {
194✔
2958
    tscError("NULL parameter for %s", __FUNCTION__);
×
2959
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
2960
    return terrno;
×
2961
  }
2962
  *insert = stmt2IsInsert(stmt);
194✔
2963
  return TSDB_CODE_SUCCESS;
194✔
2964
}
2965

2966
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
18,217✔
2967
  if (stmt == NULL || count == NULL) {
18,217✔
2968
    tscError("NULL parameter for %s", __FUNCTION__);
196✔
2969
    terrno = TSDB_CODE_INVALID_PARA;
196✔
2970
    return terrno;
196✔
2971
  }
2972

2973
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
18,021✔
2974
  STMT2_DLOG_E("start to get fields");
18,021✔
2975

2976
  if (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type ||
18,021✔
2977
      (pStmt->sql.type == 0 && stmt2IsInsert(stmt))) {
16,649✔
2978
    return stmtGetStbColFields2(stmt, count, fields);
14,101✔
2979
  }
2980
  if (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt))) {
3,920✔
2981
    return stmtGetParamNum2(stmt, count);
3,724✔
2982
  }
2983

2984
  tscError("Invalid sql for stmt %s", pStmt->sql.sqlStr);
196✔
2985
  return TSDB_CODE_PAR_SYNTAX_ERROR;
196✔
2986
}
2987

2988
DLL_EXPORT void taos_stmt2_free_fields(TAOS_STMT2 *stmt, TAOS_FIELD_ALL *fields) {
13,153✔
2989
  (void)stmt;
2990
  if (!fields) return;
13,153✔
2991
  taosMemoryFree(fields);
9,625✔
2992
}
2993

2994
TAOS_RES *taos_stmt2_result(TAOS_STMT2 *stmt) {
6,673✔
2995
  if (stmt == NULL) {
6,673✔
2996
    tscError("NULL parameter for %s", __FUNCTION__);
×
2997
    terrno = TSDB_CODE_INVALID_PARA;
×
2998
    return NULL;
×
2999
  }
3000

3001
  return stmtUseResult2(stmt);
6,673✔
3002
}
3003

3004
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmt2Errstr(stmt); }
6,240✔
3005

3006
int taos_set_conn_mode(TAOS *taos, int mode, int value) {
2,557✔
3007
  int32_t code = 0;
2,557✔
3008
  if (taos == NULL) {
2,557✔
UNCOV
3009
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
3010
    return terrno;
×
3011
  }
3012

3013
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2,557✔
3014
  if (NULL == pObj) {
2,557✔
UNCOV
3015
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
3016
    tscError("invalid parameter for %s", __func__);
×
UNCOV
3017
    return terrno;
×
3018
  }
3019
  switch (mode) {
2,557✔
3020
    case TAOS_CONN_MODE_BI:
2,557✔
3021
      atomic_store_8(&pObj->biMode, value);
2,557✔
3022
      break;
2,557✔
UNCOV
3023
    default:
×
UNCOV
3024
      tscError("not supported mode.");
×
UNCOV
3025
      code = TSDB_CODE_INVALID_PARA;
×
3026
  }
3027
  releaseTscObj(*(int64_t *)taos);
2,557✔
3028
  return code;
2,557✔
3029
}
3030

UNCOV
3031
char *getBuildInfo() { return td_buildinfo; }
×
3032

UNCOV
3033
int32_t taos_connect_is_alive(TAOS *taos) {
×
3034
  int32_t code = 0, lino = 0;
×
3035
  if (taos == NULL) {
×
3036
    terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
3037
    return terrno;
×
3038
  }
3039

UNCOV
3040
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
×
UNCOV
3041
  if (NULL == pObj) {
×
UNCOV
3042
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
UNCOV
3043
    tscError("invalid parameter for %s", __func__);
×
UNCOV
3044
    return terrno;
×
3045
  }
3046

3047
  code = tscCheckConnSessionMetric(pObj);
×
3048
  TAOS_CHECK_GOTO(code, &lino, _error);
×
3049

UNCOV
3050
_error:
×
UNCOV
3051
  releaseTscObj(*(int64_t *)taos);
×
3052

3053
  if (code != 0) {
×
3054
    tscError("taos conn failed to check alive, code:%d - %s", code, tstrerror(code));
×
3055
  }
3056

UNCOV
3057
  return code != 0 ? 0 : 1;
×
3058
}
UNCOV
3059
static int32_t buildInstanceRegisterSql(const SInstanceRegisterReq *req, char **ppSql, uint32_t *pLen) {
×
UNCOV
3060
  const char *action = (req->expire < 0) ? "UNREGISTER" : "REGISTER";
×
3061
  int32_t     len = 0;
×
3062

3063
  len += snprintf(NULL, 0, "%s INSTANCE '%s'", action, req->id);
×
UNCOV
3064
  if (req->type[0] != 0) {
×
UNCOV
3065
    len += snprintf(NULL, 0, " TYPE '%s'", req->type);
×
3066
  }
UNCOV
3067
  if (req->desc[0] != 0) {
×
UNCOV
3068
    len += snprintf(NULL, 0, " DESC '%s'", req->desc);
×
3069
  }
UNCOV
3070
  if (req->expire >= 0) {
×
3071
    len += snprintf(NULL, 0, " EXPIRE %d", req->expire);
×
3072
  }
3073

3074
  char *sql = taosMemoryMalloc((size_t)len + 1);
×
3075
  if (sql == NULL) {
×
UNCOV
3076
    return terrno;
×
3077
  }
3078

3079
  int32_t offset = snprintf(sql, (size_t)len + 1, "%s INSTANCE '%s'", action, req->id);
×
3080
  if (req->type[0] != 0) {
×
3081
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " TYPE '%s'", req->type);
×
3082
  }
UNCOV
3083
  if (req->desc[0] != 0) {
×
UNCOV
3084
    offset += snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " DESC '%s'", req->desc);
×
3085
  }
3086
  if (req->expire >= 0) {
×
UNCOV
3087
    (void)snprintf(sql + offset, (size_t)len + 1 - (size_t)offset, " EXPIRE %d", req->expire);
×
3088
  }
3089

UNCOV
3090
  *ppSql = sql;
×
3091
  if (pLen != NULL) {
×
3092
    *pLen = (uint32_t)len;
×
3093
  }
UNCOV
3094
  return TSDB_CODE_SUCCESS;
×
3095
}
3096

3097
static int32_t sendInstanceRegisterReq(STscObj *pObj, const SInstanceRegisterReq *req) {
×
3098
  SRequestObj *pRequest = NULL;
×
3099
  int32_t      code = createRequest(pObj->id, TDMT_MND_REGISTER_INSTANCE, 0, &pRequest);
×
UNCOV
3100
  if (code != TSDB_CODE_SUCCESS) {
×
3101
    terrno = code;
×
3102
    return code;
×
3103
  }
3104

3105
  code = buildInstanceRegisterSql(req, &pRequest->sqlstr, (uint32_t *)&pRequest->sqlLen);
×
3106
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3107
    goto _cleanup;
×
3108
  }
3109

UNCOV
3110
  int32_t msgLen = tSerializeSInstanceRegisterReq(NULL, 0, (SInstanceRegisterReq *)req);
×
UNCOV
3111
  if (msgLen <= 0) {
×
3112
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3113
    goto _cleanup;
×
3114
  }
3115

UNCOV
3116
  void *pMsg = taosMemoryMalloc(msgLen);
×
3117
  if (pMsg == NULL) {
×
3118
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3119
    goto _cleanup;
×
3120
  }
3121

3122
  if (tSerializeSInstanceRegisterReq(pMsg, msgLen, (SInstanceRegisterReq *)req) < 0) {
×
UNCOV
3123
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3124
    taosMemoryFree(pMsg);
×
3125
    goto _cleanup;
×
3126
  }
3127

3128
  pRequest->type = TDMT_MND_REGISTER_INSTANCE;
×
3129
  pRequest->body.requestMsg = (SDataBuf){.pData = pMsg, .len = msgLen, .handle = NULL};
×
3130

UNCOV
3131
  SMsgSendInfo *pSend = buildMsgInfoImpl(pRequest);
×
3132
  if (pSend == NULL) {
×
UNCOV
3133
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3134
    taosMemoryFree(pMsg);
×
3135
    pRequest->body.requestMsg.pData = NULL;
×
3136
    goto _cleanup;
×
3137
  }
3138

3139
  SEpSet epSet = getEpSet_s(&pObj->pAppInfo->mgmtEp);
×
3140
  code = asyncSendMsgToServer(pObj->pAppInfo->pTransporter, &epSet, NULL, pSend);
×
UNCOV
3141
  if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
3142
    destroySendMsgInfo(pSend);
×
3143
    pRequest->body.requestMsg = (SDataBuf){0};
×
3144
    goto _cleanup;
×
3145
  }
3146

UNCOV
3147
  code = tsem_wait(&pRequest->body.rspSem);
×
3148
  if (code != TSDB_CODE_SUCCESS) {
×
3149
    code = terrno != 0 ? terrno : code;
×
3150
    goto _cleanup;
×
3151
  }
3152

UNCOV
3153
  code = pRequest->code;
×
3154
  terrno = code;
×
3155

3156
_cleanup:
×
3157
  destroyRequest(pRequest);
×
UNCOV
3158
  return code;
×
3159
}
3160

3161
static bool instanceRegisterRpcRfp(int32_t code, tmsg_t msgType) {
×
3162
  if (NEED_REDIRECT_ERROR(code)) {
×
3163
    return true;
×
UNCOV
3164
  } else if (code == TSDB_CODE_UTIL_QUEUE_OUT_OF_MEMORY || code == TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE ||
×
UNCOV
3165
             code == TSDB_CODE_SYN_WRITE_STALL || code == TSDB_CODE_SYN_PROPOSE_NOT_READY ||
×
3166
             code == TSDB_CODE_SYN_RESTORING) {
3167
    tscDebug("client msg type %s should retry since %s", TMSG_INFO(msgType), tstrerror(code));
×
UNCOV
3168
    return true;
×
3169
  } else {
3170
    return false;
×
3171
  }
3172
}
3173

3174
/** Build epSet from firstEp and secondEp in config. pCfg must have valid firstEp. */
3175
static int32_t instanceBuildEpSetFromCfg(SConfig *pCfg, SEpSet *pEpSet) {
5,684✔
3176
  SConfigItem *pFirstEpItem = cfgGetItem(pCfg, "firstEp");
5,684✔
3177
  if (pFirstEpItem == NULL || pFirstEpItem->str == NULL || pFirstEpItem->str[0] == 0) {
5,684✔
3178
    return TSDB_CODE_CFG_NOT_FOUND;
×
3179
  }
3180
  SEp firstEp = {0};
5,684✔
3181
  int32_t code = taosGetFqdnPortFromEp(pFirstEpItem->str, &firstEp);
5,684✔
3182
  if (code != TSDB_CODE_SUCCESS) {
5,684✔
UNCOV
3183
    return code;
×
3184
  }
3185
  pEpSet->inUse = 0;
5,684✔
3186
  pEpSet->numOfEps = 1;
5,684✔
3187
  tstrncpy(pEpSet->eps[0].fqdn, firstEp.fqdn, TSDB_FQDN_LEN);
5,684✔
3188
  pEpSet->eps[0].port = firstEp.port;
5,684✔
3189

3190
  SConfigItem *pSecondEpItem = cfgGetItem(pCfg, "secondEp");
5,684✔
3191
  if (pSecondEpItem != NULL && pSecondEpItem->str != NULL && pSecondEpItem->str[0] != 0) {
5,684✔
3192
    SEp secondEp = {0};
5,684✔
3193
    if (taosGetFqdnPortFromEp(pSecondEpItem->str, &secondEp) == TSDB_CODE_SUCCESS) {
5,684✔
3194
      tstrncpy(pEpSet->eps[1].fqdn, secondEp.fqdn, TSDB_FQDN_LEN);
5,684✔
3195
      pEpSet->eps[1].port = secondEp.port;
5,684✔
3196
      pEpSet->numOfEps = 2;
5,684✔
3197
    }
3198
  }
3199
  return TSDB_CODE_SUCCESS;
5,684✔
3200
}
3201

3202
/** Init and open instance RPC client. label e.g. "INST" or "LIST". Returns handle or NULL. */
3203
static void *instanceOpenRpcClient(const char *label) {
5,684✔
3204
  SRpcInit rpcInit = {0};
5,684✔
3205
  rpcInit.label = (char *)label;
5,684✔
3206
  rpcInit.numOfThreads = 1;
5,684✔
3207
  rpcInit.cfp = NULL;
5,684✔
3208
  rpcInit.sessions = 16;
5,684✔
3209
  rpcInit.connType = TAOS_CONN_CLIENT;
5,684✔
3210
  rpcInit.idleTime = tsShellActivityTimer * 1000;
5,684✔
3211
  rpcInit.compressSize = tsCompressMsgSize;
5,684✔
3212
  rpcInit.user = TSDB_DEFAULT_USER;
5,684✔
3213
  rpcInit.rfp = instanceRegisterRpcRfp;
5,684✔
3214
  rpcInit.retryMinInterval = tsRedirectPeriod;
5,684✔
3215
  rpcInit.retryStepFactor = tsRedirectFactor;
5,684✔
3216
  rpcInit.retryMaxInterval = tsRedirectMaxPeriod;
5,684✔
3217
  rpcInit.retryMaxTimeout = tsMaxRetryWaitTime;
5,684✔
3218

3219
  int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3);
5,684✔
3220
  connLimitNum = TMAX(connLimitNum, 10);
5,684✔
3221
  connLimitNum = TMIN(connLimitNum, 500);
5,684✔
3222
  rpcInit.connLimitNum = connLimitNum;
5,684✔
3223
  rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
5,684✔
3224
  rpcInit.readTimeout = tsReadTimeout;
5,684✔
3225
  rpcInit.ipv6 = tsEnableIpv6;
5,684✔
3226
  rpcInit.enableSSL = tsEnableTLS;
5,684✔
3227

3228
  memcpy(rpcInit.caPath, tsTLSCaPath, strlen(tsTLSCaPath));
5,684✔
3229
  memcpy(rpcInit.certPath, tsTLSSvrCertPath, strlen(tsTLSSvrCertPath));
5,684✔
3230
  memcpy(rpcInit.keyPath, tsTLSSvrKeyPath, strlen(tsTLSSvrKeyPath));
5,684✔
3231
  memcpy(rpcInit.cliCertPath, tsTLSCliCertPath, strlen(tsTLSCliCertPath));
5,684✔
3232
  memcpy(rpcInit.cliKeyPath, tsTLSCliKeyPath, strlen(tsTLSCliKeyPath));
5,684✔
3233

3234
  int32_t code = taosVersionStrToInt(td_version, &rpcInit.compatibilityVer);
5,684✔
3235
  if (code != TSDB_CODE_SUCCESS) {
5,684✔
UNCOV
3236
    tscError("failed to convert taos version from str to int, errcode:%s", terrstr(code));
×
UNCOV
3237
    terrno = code;
×
UNCOV
3238
    return NULL;
×
3239
  }
3240

3241
  void *clientRpc = rpcOpen(&rpcInit);
5,684✔
3242
  if (clientRpc == NULL) {
5,684✔
UNCOV
3243
    tscError("failed to init instance rpc client since %s", tstrerror(terrno));
×
3244
  }
3245
  return clientRpc;
5,684✔
3246
}
3247

3248
int32_t taos_register_instance(const char *id, const char *type, const char *desc, int32_t expire) {
3,136✔
3249
  if (id == NULL || id[0] == 0) {
3,136✔
UNCOV
3250
    return terrno = TSDB_CODE_INVALID_PARA;
×
3251
  }
3252

3253
  // Validate string lengths
3254
  size_t idLen = strlen(id);
3,136✔
3255
  if (idLen >= TSDB_INSTANCE_ID_LEN) {
3,136✔
UNCOV
3256
    tscError("instance id length %zu exceeds limit %d", idLen, TSDB_INSTANCE_ID_LEN - 1);
×
UNCOV
3257
    return terrno = TSDB_CODE_INVALID_PARA;
×
3258
  }
3259

3260
  if (type != NULL && type[0] != 0) {
3,136✔
3261
    size_t typeLen = strlen(type);
1,960✔
3262
    if (typeLen >= TSDB_INSTANCE_TYPE_LEN) {
1,960✔
UNCOV
3263
      tscError("instance type length %zu exceeds limit %d", typeLen, TSDB_INSTANCE_TYPE_LEN - 1);
×
UNCOV
3264
      return terrno = TSDB_CODE_INVALID_PARA;
×
3265
    }
3266
  }
3267

3268
  if (desc != NULL && desc[0] != 0) {
3,136✔
3269
    size_t descLen = strlen(desc);
1,960✔
3270
    if (descLen >= TSDB_INSTANCE_DESC_LEN) {
1,960✔
UNCOV
3271
      tscError("instance desc length %zu exceeds limit %d", descLen, TSDB_INSTANCE_DESC_LEN - 1);
×
UNCOV
3272
      return terrno = TSDB_CODE_INVALID_PARA;
×
3273
    }
3274
  }
3275

3276
  int32_t code = taos_init();
3,136✔
3277
  if (code != TSDB_CODE_SUCCESS) {
3,136✔
UNCOV
3278
    return code;
×
3279
  }
3280

3281
  SConfig *pCfg = taosGetCfg();
3,136✔
3282
  if (pCfg == NULL) {
3,136✔
UNCOV
3283
    return terrno = TSDB_CODE_CFG_NOT_FOUND;
×
3284
  }
3285

3286
  SEpSet epSet = {0};
3,136✔
3287
  code = instanceBuildEpSetFromCfg(pCfg, &epSet);
3,136✔
3288
  if (code != TSDB_CODE_SUCCESS) {
3,136✔
UNCOV
3289
    return terrno = code;
×
3290
  }
3291

3292
  void *clientRpc = instanceOpenRpcClient("INST");
3,136✔
3293
  if (clientRpc == NULL) {
3,136✔
3294
    return terrno;
×
3295
  }
3296

3297
  SRpcMsg rpcMsg = {0};
3,136✔
3298
  SRpcMsg rpcRsp = {0};
3,136✔
3299

3300
  // Prepare request
3301
  SInstanceRegisterReq req = {0};
3,136✔
3302
  tstrncpy(req.id, id, sizeof(req.id));
3,136✔
3303
  if (type != NULL && type[0] != 0) {
3,136✔
3304
    tstrncpy(req.type, type, sizeof(req.type));
1,960✔
3305
  }
3306
  if (desc != NULL && desc[0] != 0) {
3,136✔
3307
    tstrncpy(req.desc, desc, sizeof(req.desc));
1,960✔
3308
  }
3309
  req.expire = expire;
3,136✔
3310

3311
  int32_t contLen = tSerializeSInstanceRegisterReq(NULL, 0, &req);
3,136✔
3312
  if (contLen <= 0) {
3,136✔
UNCOV
3313
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3314
    rpcClose(clientRpc);
×
UNCOV
3315
    return code;
×
3316
  }
3317

3318
  void *pCont = rpcMallocCont(contLen);
3,136✔
3319
  if (pCont == NULL) {
3,136✔
UNCOV
3320
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
3321
    rpcClose(clientRpc);
×
UNCOV
3322
    return code;
×
3323
  }
3324

3325
  if (tSerializeSInstanceRegisterReq(pCont, contLen, &req) < 0) {
3,136✔
UNCOV
3326
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3327
    rpcFreeCont(pCont);
×
UNCOV
3328
    rpcClose(clientRpc);
×
UNCOV
3329
    return code;
×
3330
  }
3331

3332
  rpcMsg.pCont = pCont;
3,136✔
3333
  rpcMsg.contLen = contLen;
3,136✔
3334
  rpcMsg.msgType = TDMT_MND_REGISTER_INSTANCE;
3,136✔
3335
  rpcMsg.info.ahandle = (void *)0x9528;  // Different magic number from server status
3,136✔
3336
  rpcMsg.info.notFreeAhandle = 1;
3,136✔
3337

3338
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
3,136✔
3339
  if (TSDB_CODE_SUCCESS != code) {
3,136✔
UNCOV
3340
    tscError("failed to send instance register req since %s", tstrerror(code));
×
3341
    // rpcSendRecv failed, pCont may not be freed, but check _RETURN1 path
3342
    // In error path, rpcSendRecv may free pCont, but we free it here to be safe
UNCOV
3343
    rpcClose(clientRpc);
×
UNCOV
3344
    return code;
×
3345
  }
3346

3347
  if (rpcRsp.code != 0) {
3,136✔
UNCOV
3348
    code = rpcRsp.code;
×
UNCOV
3349
    tscError("instance register failed, code:%s", tstrerror(code));
×
3350
  } else {
3351
    code = TSDB_CODE_SUCCESS;
3,136✔
3352
  }
3353

3354
  if (rpcRsp.pCont != NULL) {
3,136✔
3355
    rpcFreeCont(rpcRsp.pCont);
3,136✔
3356
  }
3357
  rpcClose(clientRpc);
3,136✔
3358

3359
  terrno = code;
3,136✔
3360
  return code;
3,136✔
3361
}
3362

3363
int32_t taos_list_instances(const char *filter_type, char ***pList, int32_t *pCount) {
2,548✔
3364
  if (pList == NULL || pCount == NULL) {
2,548✔
3365
    return TSDB_CODE_INVALID_PARA;
×
3366
  }
3367

3368
  int32_t code = taos_init();
2,548✔
3369
  if (code != TSDB_CODE_SUCCESS) {
2,548✔
UNCOV
3370
    terrno = code;
×
UNCOV
3371
    return code;
×
3372
  }
3373

3374
  SConfig *pCfg = taosGetCfg();
2,548✔
3375
  if (pCfg == NULL) {
2,548✔
UNCOV
3376
    terrno = TSDB_CODE_CFG_NOT_FOUND;
×
UNCOV
3377
    return TSDB_CODE_CFG_NOT_FOUND;
×
3378
  }
3379

3380
  SEpSet epSet = {0};
2,548✔
3381
  code = instanceBuildEpSetFromCfg(pCfg, &epSet);
2,548✔
3382
  if (code != TSDB_CODE_SUCCESS) {
2,548✔
UNCOV
3383
    terrno = code;
×
UNCOV
3384
    return code;
×
3385
  }
3386

3387
  void *clientRpc = instanceOpenRpcClient("LIST");
2,548✔
3388
  if (clientRpc == NULL) {
2,548✔
UNCOV
3389
    return terrno;
×
3390
  }
3391

3392
  SRpcMsg rpcMsg = {0};
2,548✔
3393
  SRpcMsg rpcRsp = {0};
2,548✔
3394

3395
  SInstanceListReq req = {0};
2,548✔
3396
  if (filter_type != NULL && filter_type[0] != 0) {
2,548✔
3397
    tstrncpy(req.filter_type, filter_type, sizeof(req.filter_type));
1,568✔
3398
  }
3399

3400
  // Serialize request to get required length
3401
  int32_t contLen = tSerializeSInstanceListReq(NULL, 0, &req);
2,548✔
3402
  if (contLen <= 0) {
2,548✔
3403
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
UNCOV
3404
    rpcClose(clientRpc);
×
UNCOV
3405
    terrno = code;
×
UNCOV
3406
    return code;
×
3407
  }
3408

3409
  // Allocate RPC message buffer (includes message header overhead)
3410
  void *pCont = rpcMallocCont(contLen);
2,548✔
3411
  if (pCont == NULL) {
2,548✔
UNCOV
3412
    code = terrno != 0 ? terrno : TSDB_CODE_OUT_OF_MEMORY;
×
UNCOV
3413
    rpcClose(clientRpc);
×
3414
    terrno = code;
×
3415
    return code;
×
3416
  }
3417

3418
  // Serialize request into the content part (after message header)
3419
  if (tSerializeSInstanceListReq(pCont, contLen, &req) < 0) {
2,548✔
UNCOV
3420
    code = terrno != 0 ? terrno : TSDB_CODE_TSC_INTERNAL_ERROR;
×
3421
    rpcFreeCont(pCont);
×
3422
    rpcClose(clientRpc);
×
UNCOV
3423
    terrno = code;
×
UNCOV
3424
    return code;
×
3425
  }
3426

3427
  rpcMsg.pCont = pCont;
2,548✔
3428
  rpcMsg.contLen = contLen;
2,548✔
3429
  rpcMsg.msgType = TDMT_MND_LIST_INSTANCES;
2,548✔
3430
  rpcMsg.info.ahandle = (void *)0x9529;  // Different magic number from register
2,548✔
3431
  rpcMsg.info.notFreeAhandle = 1;
2,548✔
3432

3433
  code = rpcSendRecv(clientRpc, &epSet, &rpcMsg, &rpcRsp);
2,548✔
3434
  if (TSDB_CODE_SUCCESS != code) {
2,548✔
UNCOV
3435
    tscError("failed to send instance list req since %s", tstrerror(code));
×
UNCOV
3436
    rpcFreeCont(pCont);
×
UNCOV
3437
    rpcClose(clientRpc);
×
UNCOV
3438
    terrno = code;
×
UNCOV
3439
    return code;
×
3440
  }
3441

3442
  // Check response - rpcRsp.code contains the result code from mnode
3443
  if (rpcRsp.code != 0) {
2,548✔
3444
    code = rpcRsp.code;
×
UNCOV
3445
    tscError("instance list failed, code:%s", tstrerror(code));
×
UNCOV
3446
    if (rpcRsp.pCont != NULL) {
×
UNCOV
3447
      rpcFreeCont(rpcRsp.pCont);
×
3448
    }
UNCOV
3449
    rpcClose(clientRpc);
×
3450
    terrno = code;
×
3451
    return code;
×
3452
  }
3453

3454
  // Deserialize response
3455
  if (rpcRsp.pCont != NULL && rpcRsp.contLen > 0) {
2,548✔
3456
    SInstanceListRsp rsp = {0};
2,548✔
3457
    code = tDeserializeSInstanceListRsp(rpcRsp.pCont, rpcRsp.contLen, &rsp);
2,548✔
3458
    if (code != TSDB_CODE_SUCCESS) {
2,548✔
3459
      tscError("failed to deserialize instance list rsp, code:%s", tstrerror(code));
×
3460
      if (rsp.ids != NULL) {
×
3461
        for (int32_t i = 0; i < rsp.count; i++) {
×
3462
          if (rsp.ids[i] != NULL) {
×
UNCOV
3463
            taosMemoryFree(rsp.ids[i]);
×
3464
          }
3465
        }
UNCOV
3466
        taosMemoryFree(rsp.ids);
×
UNCOV
3467
        rsp.ids = NULL;
×
3468
      }
UNCOV
3469
      rsp.count = 0;
×
UNCOV
3470
      rpcFreeCont(rpcRsp.pCont);
×
UNCOV
3471
      rpcClose(clientRpc);
×
UNCOV
3472
      terrno = code;
×
3473
      return code;
×
3474
    }
3475
    *pList = rsp.ids;
2,548✔
3476
    *pCount = rsp.count;
2,548✔
3477
  } else {
UNCOV
3478
    *pList = NULL;
×
UNCOV
3479
    *pCount = 0;
×
3480
  }
3481

3482
  if (rpcRsp.pCont != NULL) {
2,548✔
3483
    rpcFreeCont(rpcRsp.pCont);
2,548✔
3484
  }
3485
  rpcClose(clientRpc);
2,548✔
3486

3487
  return TSDB_CODE_SUCCESS;
2,548✔
3488
}
3489

3490
void taos_free_instances(char ***pList, int32_t count) {
1,764✔
3491
  if (pList == NULL || *pList == NULL || count <= 0) {
1,764✔
UNCOV
3492
    return;
×
3493
  }
3494

3495
  // Free each string in the array
3496
  for (int32_t i = 0; i < count; i++) {
5,488✔
3497
    if ((*pList)[i] != NULL) {
3,724✔
3498
      taosMemoryFree((*pList)[i]);
3,724✔
3499
      (*pList)[i] = NULL;
3,724✔
3500
    }
3501
  }
3502

3503
  // Free the array itself
3504
  taosMemoryFree(*pList);
1,764✔
3505
  *pList = NULL;
1,764✔
3506
}
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