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

taosdata / TDengine / #4943

30 Jan 2026 06:19AM UTC coverage: 66.718% (-0.07%) from 66.788%
#4943

push

travis-ci

web-flow
merge: from main to 3.0 #34453

1122 of 2018 new or added lines in 72 files covered. (55.6%)

823 existing lines in 156 files now uncovered.

204811 of 306978 relevant lines covered (66.72%)

123993567.34 hits per line

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

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

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

39
#define TSC_VAR_NOT_RELEASE 1
40
#define TSC_VAR_RELEASED    0
41

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

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

49
int taos_options(TSDB_OPTION option, const void *arg, ...) {
628,707✔
50
  if (arg == NULL) {
628,707✔
51
    return TSDB_CODE_INVALID_PARA;
×
52
  }
53
  static int32_t lock = 0;
54

55
  for (int i = 1; atomic_val_compare_exchange_32(&lock, 0, 1) != 0; ++i) {
628,707✔
UNCOV
56
    if (i % 1000 == 0) {
×
UNCOV
57
      (void)sched_yield();
×
58
    }
59
  }
60

61
  int ret = taos_options_imp(option, (const char *)arg);
628,707✔
62
  atomic_store_32(&lock, 0);
628,707✔
63
  return ret;
628,707✔
64
}
65

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

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

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

86
void tzCleanup() {
1,296,862✔
87
  taosHashCleanup(pTimezoneMap);
1,296,862✔
88
  taosHashCleanup(pTimezoneNameMap);
1,296,862✔
89
}
1,296,862✔
90

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

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

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

128
END:
×
129
  return tz;
×
130
}
131
#endif
132

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

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

144
  if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION) {
×
145
    return terrno = TSDB_CODE_INVALID_PARA;
×
146
  }
147

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

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

160
  if (option == TSDB_OPTION_CONNECTION_CLEAR) {
×
161
    val = NULL;
×
162
  }
163

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

200
  if (option == TSDB_OPTION_CONNECTION_USER_APP || option == TSDB_OPTION_CONNECTION_CLEAR) {
×
201
    if (val != NULL) {
×
202
      tstrncpy(pObj->optionInfo.userApp, val, sizeof(pObj->optionInfo.userApp));
×
203
    } else {
204
      pObj->optionInfo.userApp[0] = 0;
×
205
    }
206
  }
207

208
  if (option == TSDB_OPTION_CONNECTION_CONNECTOR_INFO || option == TSDB_OPTION_CONNECTION_CLEAR) {
×
209
    if (val != NULL) {
×
210
      tstrncpy(pObj->optionInfo.cInfo, val, sizeof(pObj->optionInfo.cInfo));
×
211
    } else {
212
      pObj->optionInfo.cInfo[0] = 0;
×
213
    }
214
  }
215

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

238
END:
×
239
  releaseTscObj(*(int64_t *)taos);
×
240
  return terrno = code;
×
241
}
242

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

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

254
  monitorClose();
1,296,862✔
255
  tscStopCrashReport();
1,296,862✔
256

257
  hbMgrCleanUp();
1,296,862✔
258

259
  catalogDestroy();
1,296,862✔
260
  schedulerDestroy();
1,296,862✔
261

262
  fmFuncMgtDestroy();
1,296,862✔
263
  qCleanupKeywordsTable();
1,296,862✔
264

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

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

274
  id = clientConnRefPool;
1,296,862✔
275
  clientConnRefPool = -1;
1,296,862✔
276
  taosCloseRef(id);
1,296,862✔
277

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

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

287
  sessMgtDestroy();
1,296,862✔
288

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

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

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

314
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
2,438,374✔
315
  tscInfo("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
2,438,374✔
316
  if (user == NULL) {
2,439,881✔
317
    user = TSDB_DEFAULT_USER;
163,858✔
318
  }
319

320
  if (pass == NULL) {
2,439,881✔
321
    pass = TSDB_DEFAULT_PASS;
163,858✔
322
  }
323

324
  STscObj *pObj = NULL;
2,439,881✔
325
  int32_t  code = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY, &pObj);
2,438,853✔
326
  if (TSDB_CODE_SUCCESS == code) {
2,438,772✔
327
    int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t));
2,426,277✔
328
    if (NULL == rid) {
2,426,324✔
329
      tscError("out of memory when taos connect to %s:%u, user:%s db:%s", ip, port, user, db);
×
330
      return NULL;
×
331
    }
332
    *rid = pObj->id;
2,426,324✔
333
    return (TAOS *)rid;
2,426,324✔
334
  } else {
335
    terrno = code;
12,495✔
336
  }
337

338
  return NULL;
12,495✔
339
}
340

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

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

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

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

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

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

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

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

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

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

430
  return taos;
×
431
}
432

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

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

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

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

495
  releaseTscObj(*(int64_t *)taos);
1,190✔
496
  return 0;
1,190✔
497
}
498

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

621

622

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

628
  __taos_async_ip_whitelist_fn_t userCbFn;
629
} SFetchIpWhiteListInfo;
630

631

632

633
int32_t fetchIpWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
634
  int32_t lino = 0;
×
635
  char  **pWhiteLists = NULL;
×
636

637
  SGetUserIpWhiteListRsp wlRsp = {0};
×
638

639
  SFetchIpWhiteListInfo *pInfo = (SFetchIpWhiteListInfo *)param;
×
640
  TAOS *taos = &pInfo->connId;
×
641

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

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

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

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

665
    code = tIpUintToStr(pIpRange, &ipAddr);
×
666
    TAOS_CHECK_GOTO(code, &lino, _error);
×
667

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

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

707

708

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

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

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

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

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

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

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

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

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

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

782

783

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

788

789

790
void taos_fetch_ip_whitelist_a(TAOS *taos, __taos_async_ip_whitelist_fn_t fp, void *param) {
×
791
  taosFetchIpWhiteList(taos, fp, param, true);
×
792
}
×
793

794

795
typedef struct SFetchDateTimeWhiteListInfo {
796
  int64_t                              connId;
797
  void                                *userParam;
798
  __taos_async_datetime_whitelist_fn_t userCbFn;
799
} SFetchDateTimeWhiteListInfo;
800

801

802

803
static const char* weekdays[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
804
int32_t fetchDateTimeWhiteListCallbackFn(void *param, SDataBuf *pMsg, int32_t code) {
×
805
  int32_t lino = 0;
×
806
  char  **pWhiteLists = NULL;
×
807

808
  SUserDateTimeWhiteList wlRsp = {0};
×
809

810
  SFetchDateTimeWhiteListInfo *pInfo = (SFetchDateTimeWhiteListInfo *)param;
×
811
  TAOS *taos = &pInfo->connId;
×
812

813
  if (code != TSDB_CODE_SUCCESS) {
×
814
    pInfo->userCbFn(pInfo->userParam, code, taos, 0, NULL);
×
815
    TAOS_CHECK_GOTO(code, &lino, _error);
×
816
  }
817

818
  if ((code = tDeserializeSUserDateTimeWhiteList(pMsg->pData, pMsg->len, &wlRsp)) != TSDB_CODE_SUCCESS) {
×
819
    TAOS_CHECK_GOTO(code, &lino, _error);
×
820
  }
821

822
  pWhiteLists = taosMemoryMalloc(wlRsp.numWhiteLists * sizeof(char *));
×
823
  if (pWhiteLists == NULL) {
×
824
    code = terrno;
×
825
    TAOS_CHECK_GOTO(code, &lino, _error);
×
826
  }
827

828
  int32_t numWhiteLists =0;
×
829
  for (int32_t i = 0; i < wlRsp.numWhiteLists; i++) {
×
830
    SDateTimeWhiteListItem *item = &wlRsp.pWhiteLists[i];
×
831

832
    char *p = taosMemCalloc(1, 128);
×
833
    if (p == NULL) {
×
834
      code = terrno;
×
835
      TAOS_CHECK_GOTO(code, &lino, _error);
×
836
    }
837

838
    int duration = item->duration / 60;
×
839

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

853
  pInfo->userCbFn(pInfo->userParam, code, taos, numWhiteLists, pWhiteLists);
×
854
_error:
×
855
  if (pWhiteLists != NULL) {
×
856
    for (int32_t i = 0; i < numWhiteLists; i++) {
×
857
      taosMemFree(pWhiteLists[i]);
×
858
    }
859
    taosMemoryFree(pWhiteLists);
×
860
  }
861
  taosMemoryFree(pMsg->pData);
×
862
  taosMemoryFree(pMsg->pEpSet);
×
863
  taosMemoryFree(pInfo);
×
864
  tFreeSUserDateTimeWhiteList(&wlRsp);
×
865
  return code;
×
866
}
867

868

869

870
void taos_fetch_datetime_whitelist_a(TAOS *taos, __taos_async_datetime_whitelist_fn_t fp, void *param) {
×
871
  if (NULL == taos) {
×
872
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
873
    return;
×
874
  }
875
  int64_t connId = *(int64_t *)taos;
×
876

877
  STscObj *pTsc = acquireTscObj(connId);
×
878
  if (NULL == pTsc) {
×
879
    fp(param, TSDB_CODE_TSC_DISCONNECTED, taos, 0, NULL);
×
880
    return;
×
881
  }
882

883
  SGetUserWhiteListReq req;
×
884
  (void)memcpy(req.user, pTsc->user, TSDB_USER_LEN);
×
885
  int32_t msgLen = tSerializeSGetUserWhiteListReq(NULL, 0, &req);
×
886
  if (msgLen < 0) {
×
887
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
888
    releaseTscObj(connId);
×
889
    return;
×
890
  }
891

892
  void *pReq = taosMemoryMalloc(msgLen);
×
893
  if (pReq == NULL) {
×
894
    fp(param, terrno, taos, 0, NULL);
×
895
    releaseTscObj(connId);
×
896
    return;
×
897
  }
898

899
  if (tSerializeSGetUserWhiteListReq(pReq, msgLen, &req) < 0) {
×
900
    fp(param, TSDB_CODE_INVALID_PARA, taos, 0, NULL);
×
901
    taosMemoryFree(pReq);
×
902
    releaseTscObj(connId);
×
903
    return;
×
904
  }
905

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

914
  pParam->connId = connId;
×
915
  pParam->userCbFn = fp;
×
916
  pParam->userParam = param;
×
917

918
  SMsgSendInfo *pSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
×
919
  if (pSendInfo == NULL) {
×
920
    fp(param, terrno, taos, 0, NULL);
×
921
    taosMemoryFree(pParam);
×
922
    taosMemoryFree(pReq);
×
923
    releaseTscObj(connId);
×
924
    return;
×
925
  }
926

927
  pSendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = msgLen, .handle = NULL};
×
928
  pSendInfo->requestId = generateRequestId();
×
929
  pSendInfo->requestObjRefId = 0;
×
930
  pSendInfo->param = pParam;
×
931
  pSendInfo->fp = fetchDateTimeWhiteListCallbackFn;
×
932
  pSendInfo->msgType = TDMT_MND_GET_USER_DATETIME_WHITELIST;
×
933

934
  SEpSet epSet = getEpSet_s(&pTsc->pAppInfo->mgmtEp);
×
935
  if (TSDB_CODE_SUCCESS != asyncSendMsgToServer(pTsc->pAppInfo->pTransporter, &epSet, NULL, pSendInfo)) {
×
936
    tscWarn("failed to async send msg to server");
×
937
  }
938
  releaseTscObj(connId);
×
939
  return;
×
940
}
941

942

943

944
void taos_close_internal(void *taos) {
2,554,593✔
945
  if (taos == NULL) {
2,554,593✔
946
    return;
323✔
947
  }
948
  int32_t code = 0;
2,554,270✔
949

950
  STscObj *pTscObj = (STscObj *)taos;
2,554,270✔
951
  tscDebug("conn:0x%" PRIx64 ", try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
2,554,270✔
952

953
  SSessParam para = {.type = SESSION_PER_USER, .value = -1, .noCheck = 1};
2,554,270✔
954

955
  code = tscUpdateSessMetric(pTscObj, &para);
2,554,235✔
956
  if (code != TSDB_CODE_SUCCESS) {
2,554,270✔
957
    tscWarn("conn:0x%" PRIx64 ", failed to update user:%s metric when close connection, code:%d", pTscObj->id,
×
958
            pTscObj->user, code);
959
  }
960

961
  code = tscUnrefSessMetric(pTscObj);
2,554,270✔
962
  if (TSDB_CODE_SUCCESS != taosRemoveRef(clientConnRefPool, pTscObj->id)) {
2,554,201✔
963
    tscError("conn:0x%" PRIx64 ", failed to remove ref from conn pool", pTscObj->id);
×
964
  }
965
}
966

967
void taos_close(TAOS *taos) {
2,428,525✔
968
  if (taos == NULL) {
2,428,525✔
UNCOV
969
    return;
×
970
  }
971

972
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
2,428,525✔
973
  if (NULL == pObj) {
2,428,525✔
974
    taosMemoryFree(taos);
×
975
    return;
×
976
  }
977

978
  taos_close_internal(pObj);
2,428,525✔
979
  releaseTscObj(*(int64_t *)taos);
2,428,525✔
980
  taosMemoryFree(taos);
2,428,525✔
981
}
982

983
int taos_errno(TAOS_RES *res) {
1,167,750,105✔
984
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
1,167,750,105✔
985
    return terrno;
30,977✔
986
  }
987

988
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
1,167,720,965✔
989
    return 0;
331,367✔
990
  }
991

992
  return ((SRequestObj *)res)->code;
1,167,387,677✔
993
}
994

995
const char *taos_errstr(TAOS_RES *res) {
73,118,206✔
996
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
73,118,206✔
997
    if (*(taosGetErrMsg()) == 0) {
42,603✔
998
      return (const char *)tstrerror(terrno);
42,549✔
999
    } else {
1000
      (void)snprintf(taosGetErrMsgReturn(), ERR_MSG_LEN, "%s", taosGetErrMsg());
54✔
1001
      return (const char*)taosGetErrMsgReturn();
54✔
1002
    }
1003
  }
1004

1005
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
73,075,603✔
1006
    return "success";
×
1007
  }
1008

1009
  SRequestObj *pRequest = (SRequestObj *)res;
73,075,603✔
1010
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
73,075,603✔
1011
    return pRequest->msgBuf;
22,973,526✔
1012
  } else {
1013
    return (const char *)tstrerror(pRequest->code);
50,102,077✔
1014
  }
1015
}
1016

1017
void taos_free_result(TAOS_RES *res) {
904,596,449✔
1018
  if (NULL == res) {
904,596,449✔
1019
    return;
13,408,593✔
1020
  }
1021

1022
  tscTrace("res:%p, will be freed", res);
891,187,856✔
1023

1024
  if (TD_RES_QUERY(res)) {
891,187,843✔
1025
    SRequestObj *pRequest = (SRequestObj *)res;
874,942,382✔
1026
    tscDebug("QID:0x%" PRIx64 ", call taos_free_result to free query, res:%p", pRequest->requestId, res);
874,942,382✔
1027
    destroyRequest(pRequest);
874,942,382✔
1028
    return;
874,941,262✔
1029
  }
1030

1031
  SMqRspObj *pRsp = (SMqRspObj *)res;
16,247,741✔
1032
  if (TD_RES_TMQ(res)) {
16,247,741✔
1033
    tDeleteMqDataRsp(&pRsp->dataRsp);
16,184,075✔
1034
    doFreeReqResultInfo(&pRsp->resInfo);
16,184,075✔
1035
  } else if (TD_RES_TMQ_METADATA(res)) {
65,574✔
1036
    tDeleteSTaosxRsp(&pRsp->dataRsp);
2,723✔
1037
    doFreeReqResultInfo(&pRsp->resInfo);
2,723✔
1038
  } else if (TD_RES_TMQ_META(res)) {
62,851✔
1039
    tDeleteMqMetaRsp(&pRsp->metaRsp);
56,700✔
1040
  } else if (TD_RES_TMQ_BATCH_META(res)) {
6,151✔
1041
    tDeleteMqBatchMetaRsp(&pRsp->batchMetaRsp);
6,151✔
1042
  } else if (TD_RES_TMQ_RAW(res)) {
×
1043
    tDeleteMqRawDataRsp(&pRsp->dataRsp);
×
1044
  }
1045
  taosMemoryFree(pRsp);
16,248,608✔
1046
}
1047

UNCOV
1048
void taos_kill_query(TAOS *taos) {
×
UNCOV
1049
  if (NULL == taos) {
×
UNCOV
1050
    return;
×
1051
  }
1052

UNCOV
1053
  int64_t  rid = *(int64_t *)taos;
×
UNCOV
1054
  STscObj *pTscObj = acquireTscObj(rid);
×
UNCOV
1055
  if (pTscObj) {
×
UNCOV
1056
    stopAllRequests(pTscObj->pRequests);
×
1057
  }
UNCOV
1058
  releaseTscObj(rid);
×
1059
}
1060

1061
int taos_field_count(TAOS_RES *res) {
2,147,483,647✔
1062
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1063
    return 0;
8✔
1064
  }
1065

1066
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1067
  return pResInfo->numOfCols;
2,147,483,647✔
1068
}
1069

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

1072
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
2,147,483,647✔
1073
  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✔
1074
    return NULL;
3,376,319✔
1075
  }
1076

1077
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1078
  return pResInfo->userFields;
2,147,483,647✔
1079
}
1080

1081
TAOS_RES *taos_query(TAOS *taos, const char *sql) { return taosQueryImpl(taos, sql, false, TD_REQ_FROM_APP); }
867,722,287✔
1082
TAOS_RES *taos_query_with_reqid(TAOS *taos, const char *sql, int64_t reqid) {
248✔
1083
  return taosQueryImplWithReqid(taos, sql, false, reqid);
248✔
1084
}
1085

1086
TAOS_FIELD_E *taos_fetch_fields_e(TAOS_RES *res) {
169✔
1087
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
169✔
1088
    return NULL;
×
1089
  }
1090
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
169✔
1091
  return pResInfo->fields;
169✔
1092
}
1093

1094
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
2,147,483,647✔
1095
  if (res == NULL) {
2,147,483,647✔
1096
    return NULL;
×
1097
  }
1098

1099
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1100
    SRequestObj *pRequest = (SRequestObj *)res;
1,898,421,193✔
1101
    if (pRequest->killed) {
1,898,421,193✔
1102
      tscInfo("query has been killed, can not fetch more row.");
×
1103
      pRequest->code = TSDB_CODE_TSC_QUERY_KILLED;
×
1104
      return NULL;
×
1105
    }
1106

1107
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
1,898,421,905✔
1108
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
1,898,421,641✔
1109
      return NULL;
343✔
1110
    }
1111

1112
    if (pRequest->inCallback) {
1,898,420,211✔
1113
      tscError("can not call taos_fetch_row before query callback ends.");
×
1114
      terrno = TSDB_CODE_TSC_INVALID_OPERATION;
×
1115
      return NULL;
×
1116
    }
1117

1118
    return doAsyncFetchRows(pRequest, true, true);
1,898,420,574✔
1119
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
1120
    SMqRspObj      *msg = ((SMqRspObj *)res);
2,147,483,647✔
1121
    SReqResultInfo *pResultInfo = NULL;
2,147,483,647✔
1122
    if (msg->resIter == -1) {
2,147,483,647✔
1123
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
15,814,367✔
1124
        return NULL;
×
1125
      }
1126
    } else {
1127
      pResultInfo = tmqGetCurResInfo(res);
2,147,483,647✔
1128
    }
1129

1130
    if (pResultInfo->current < pResultInfo->numOfRows) {
2,147,483,647✔
1131
      doSetOneRowPtr(pResultInfo);
2,147,483,647✔
1132
      pResultInfo->current += 1;
2,147,483,647✔
1133
      return pResultInfo->row;
2,147,483,647✔
1134
    } else {
1135
      if (tmqGetNextResInfo(res, true, &pResultInfo) != 0) {
99,046,115✔
1136
        return NULL;
15,812,992✔
1137
      }
1138

1139
      doSetOneRowPtr(pResultInfo);
83,225,836✔
1140
      pResultInfo->current += 1;
83,230,000✔
1141
      return pResultInfo->row;
83,230,347✔
1142
    }
1143
  } else if (TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1144
    return NULL;
×
1145
  } else {
1146
    tscError("invalid result passed to taos_fetch_row");
×
1147
    terrno = TSDB_CODE_TMQ_INVALID_DATA;
×
1148
    return NULL;
×
1149
  }
1150
}
1151

1152
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
2,147,483,647✔
1153
  return taos_print_row_with_size(str, INT32_MAX, row, fields, num_fields);
2,147,483,647✔
1154
}
1155
int taos_print_row_with_size(char *str, uint32_t size, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
2,147,483,647✔
1156
  int32_t len = 0;
2,147,483,647✔
1157
  for (int i = 0; i < num_fields; ++i) {
2,147,483,647✔
1158
    if (i > 0 && len < size - 1) {
2,147,483,647✔
1159
      str[len++] = ' ';
2,147,483,647✔
1160
    }
1161

1162
    if (row[i] == NULL) {
2,147,483,647✔
1163
      len += tsnprintf(str + len, size - len, "%s", TSDB_DATA_NULL_STR);
138,137,619✔
1164
      continue;
138,139,515✔
1165
    }
1166

1167
    switch (fields[i].type) {
2,147,483,647✔
1168
      case TSDB_DATA_TYPE_TINYINT:
11,680,395✔
1169
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
11,680,395✔
1170
        break;
11,701,767✔
1171

1172
      case TSDB_DATA_TYPE_UTINYINT:
50,400✔
1173
        len += tsnprintf(str + len, size - len, "%u", *((uint8_t *)row[i]));
50,400✔
1174
        break;
50,400✔
1175

1176
      case TSDB_DATA_TYPE_SMALLINT:
50,400✔
1177
        len += tsnprintf(str + len, size - len, "%d", *((int16_t *)row[i]));
50,400✔
1178
        break;
50,400✔
1179

1180
      case TSDB_DATA_TYPE_USMALLINT:
50,400✔
1181
        len += tsnprintf(str + len, size - len, "%u", *((uint16_t *)row[i]));
50,400✔
1182
        break;
50,400✔
1183

1184
      case TSDB_DATA_TYPE_INT:
2,147,483,647✔
1185
        len += tsnprintf(str + len, size - len, "%d", *((int32_t *)row[i]));
2,147,483,647✔
1186
        break;
2,147,483,647✔
1187

1188
      case TSDB_DATA_TYPE_UINT:
50,400✔
1189
        len += tsnprintf(str + len, size - len, "%u", *((uint32_t *)row[i]));
50,400✔
1190
        break;
50,400✔
1191

1192
      case TSDB_DATA_TYPE_BIGINT:
2,147,483,647✔
1193
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
2,147,483,647✔
1194
        break;
2,147,483,647✔
1195

1196
      case TSDB_DATA_TYPE_UBIGINT:
50,400✔
1197
        len += tsnprintf(str + len, size - len, "%" PRIu64, *((uint64_t *)row[i]));
50,400✔
1198
        break;
50,400✔
1199

1200
      case TSDB_DATA_TYPE_FLOAT: {
23,103,364✔
1201
        float fv = 0;
23,103,364✔
1202
        fv = GET_FLOAT_VAL(row[i]);
23,103,364✔
1203
        len += snprintf(str + len, size - len, "%.*g", FLT_DIG, fv);
23,139,673✔
1204
      } break;
23,274,535✔
1205

1206
      case TSDB_DATA_TYPE_DOUBLE: {
2,147,483,647✔
1207
        double dv = 0;
2,147,483,647✔
1208
        dv = GET_DOUBLE_VAL(row[i]);
2,147,483,647✔
1209
        len += snprintf(str + len, size - len, "%.*g", DBL_DIG, dv);
2,147,483,647✔
1210
      } break;
2,147,483,647✔
1211

1212
      case TSDB_DATA_TYPE_VARBINARY: {
50,400✔
1213
        void    *data = NULL;
50,400✔
1214
        uint32_t tmp = 0;
50,400✔
1215
        int32_t  charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
50,400✔
1216
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
50,400✔
1217
          break;
×
1218
        }
1219
        uint32_t copyLen = TMIN(size - len - 1, tmp);
50,400✔
1220
        (void)memcpy(str + len, data, copyLen);
50,400✔
1221
        len += copyLen;
50,400✔
1222
        taosMemoryFree(data);
50,400✔
1223
      } break;
50,400✔
1224
      case TSDB_DATA_TYPE_BINARY:
2,147,483,647✔
1225
      case TSDB_DATA_TYPE_NCHAR:
1226
      case TSDB_DATA_TYPE_GEOMETRY: {
1227
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
2,147,483,647✔
1228
        if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_VARBINARY ||
2,147,483,647✔
1229
            fields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
1,806,438,323✔
1230
          if (charLen > fields[i].bytes || charLen < 0) {
2,147,483,647✔
1231
            tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
93,310✔
1232
            break;
×
1233
          }
1234
        } else {
1235
          if (charLen > fields[i].bytes * TSDB_NCHAR_SIZE || charLen < 0) {
1,806,392,096✔
1236
            tscError("taos_print_row error. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
12✔
1237
            break;
×
1238
          }
1239
        }
1240

1241
        uint32_t copyLen = TMIN(size - len - 1, charLen);
2,147,483,647✔
1242
        (void)memcpy(str + len, row[i], copyLen);
2,147,483,647✔
1243
        len += copyLen;
2,147,483,647✔
1244
      } break;
2,147,483,647✔
1245
      case TSDB_DATA_TYPE_BLOB:
×
1246
      case TSDB_DATA_TYPE_MEDIUMBLOB: {
1247
        void    *data = NULL;
×
1248
        uint32_t tmp = 0;
×
1249
        int32_t  charLen = blobDataLen((char *)row[i] - BLOBSTR_HEADER_SIZE);
×
1250
        if (taosAscii2Hex(row[i], charLen, &data, &tmp) < 0) {
×
1251
          break;
×
1252
        }
1253

1254
        uint32_t copyLen = TMIN(size - len - 1, tmp);
×
1255
        (void)memcpy(str + len, data, copyLen);
×
1256
        len += copyLen;
×
1257

1258
        taosMemoryFree(data);
×
1259
      } break;
×
1260

1261
      case TSDB_DATA_TYPE_TIMESTAMP:
2,147,483,647✔
1262
        len += tsnprintf(str + len, size - len, "%" PRId64, *((int64_t *)row[i]));
2,147,483,647✔
1263
        break;
2,147,483,647✔
1264

1265
      case TSDB_DATA_TYPE_BOOL:
50,400✔
1266
        len += tsnprintf(str + len, size - len, "%d", *((int8_t *)row[i]));
50,400✔
1267
        break;
50,400✔
1268
      case TSDB_DATA_TYPE_DECIMAL64:
×
1269
      case TSDB_DATA_TYPE_DECIMAL: {
1270
        uint32_t decimalLen = strlen(row[i]);
×
1271
        uint32_t copyLen = TMIN(size - len - 1, decimalLen);
×
1272
        (void)memcpy(str + len, row[i], copyLen);
×
1273
        len += copyLen;
×
1274
      } break;
×
1275
      default:
×
1276
        break;
×
1277
    }
1278

1279
    if (len >= size - 1) {
2,147,483,647✔
1280
      break;
×
1281
    }
1282
  }
1283
  if (len < size) {
2,147,483,647✔
1284
    str[len] = 0;
2,147,483,647✔
1285
  }
1286

1287
  return len;
2,147,483,647✔
1288
}
1289

1290
int *taos_fetch_lengths(TAOS_RES *res) {
2,147,483,647✔
1291
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1292
    return NULL;
×
1293
  }
1294

1295
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
2,147,483,647✔
1296
  return pResInfo->length;
2,147,483,647✔
1297
}
1298

1299
TAOS_ROW *taos_result_block(TAOS_RES *res) {
×
1300
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1301
    terrno = TSDB_CODE_INVALID_PARA;
×
1302
    return NULL;
×
1303
  }
1304

1305
  if (taos_is_update_query(res)) {
×
1306
    return NULL;
×
1307
  }
1308

1309
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
×
1310
  return &pResInfo->row;
×
1311
}
1312

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

1364
const char *taos_get_client_info() { return td_version; }
885,239✔
1365

1366
// return int32_t
1367
int taos_affected_rows(TAOS_RES *res) {
632,835,740✔
1368
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
632,835,740✔
1369
      TD_RES_TMQ_BATCH_META(res)) {
632,836,133✔
UNCOV
1370
    return 0;
×
1371
  }
1372

1373
  SRequestObj    *pRequest = (SRequestObj *)res;
632,836,121✔
1374
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
632,836,121✔
1375
  return (int)pResInfo->numOfRows;
632,836,558✔
1376
}
1377

1378
// return int64_t
1379
int64_t taos_affected_rows64(TAOS_RES *res) {
1,311,683✔
1380
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
1,311,683✔
1381
      TD_RES_TMQ_BATCH_META(res)) {
1,311,683✔
1382
    return 0;
×
1383
  }
1384

1385
  SRequestObj    *pRequest = (SRequestObj *)res;
1,311,683✔
1386
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
1,311,683✔
1387
  return pResInfo->numOfRows;
1,311,683✔
1388
}
1389

1390
int taos_result_precision(TAOS_RES *res) {
2,147,483,647✔
1391
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
2,147,483,647✔
1392
    return TSDB_TIME_PRECISION_MILLI;
×
1393
  }
1394

1395
  if (TD_RES_QUERY(res)) {
2,147,483,647✔
1396
    SRequestObj *pRequest = (SRequestObj *)res;
144,284,898✔
1397
    return pRequest->body.resInfo.precision;
144,284,898✔
1398
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
2,147,483,647✔
1399
    SReqResultInfo *info = tmqGetCurResInfo(res);
2,147,483,647✔
1400
    return info->precision;
2,147,483,647✔
1401
  }
1402
  return TSDB_TIME_PRECISION_MILLI;
×
1403
}
1404

1405
int taos_select_db(TAOS *taos, const char *db) {
43,705✔
1406
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
43,705✔
1407
  if (pObj == NULL) {
43,705✔
1408
    releaseTscObj(*(int64_t *)taos);
×
1409
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1410
    return TSDB_CODE_TSC_DISCONNECTED;
×
1411
  }
1412

1413
  if (db == NULL || strlen(db) == 0) {
43,705✔
1414
    releaseTscObj(*(int64_t *)taos);
×
1415
    tscError("invalid parameter for %s", db == NULL ? "db is NULL" : "db is empty");
×
1416
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
×
1417
    return terrno;
×
1418
  }
1419

1420
  char sql[256] = {0};
43,705✔
1421
  (void)snprintf(sql, tListLen(sql), "use %s", db);
43,705✔
1422

1423
  TAOS_RES *pRequest = taos_query(taos, sql);
43,705✔
1424
  int32_t   code = taos_errno(pRequest);
43,705✔
1425

1426
  taos_free_result(pRequest);
43,705✔
1427
  releaseTscObj(*(int64_t *)taos);
43,127✔
1428
  return code;
43,705✔
1429
}
1430

1431
void taos_stop_query(TAOS_RES *res) {
878,426,368✔
1432
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_METADATA(res) ||
878,426,368✔
1433
      TD_RES_TMQ_BATCH_META(res)) {
878,428,665✔
1434
    return;
×
1435
  }
1436

1437
  stopAllQueries((SRequestObj *)res);
878,427,359✔
1438
}
1439

1440
bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
×
1441
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
×
1442
    return true;
×
1443
  }
1444
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
×
1445
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
×
1446
    return true;
×
1447
  }
1448

1449
  SResultColumn *pCol = &pResultInfo->pCol[col];
×
1450
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
×
1451
    return (pCol->offset[row] == -1);
×
1452
  } else {
1453
    return colDataIsNull_f(pCol, row);
×
1454
  }
1455
}
1456

1457
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
330,360✔
1458

1459
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
214,765,894✔
1460
  int32_t numOfRows = 0;
214,765,894✔
1461
  /*int32_t code = */ terrno = taos_fetch_block_s(res, &numOfRows, rows);
214,766,389✔
1462
  return numOfRows;
214,766,389✔
1463
}
1464

1465
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
214,766,389✔
1466
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
214,766,389✔
1467
    return 0;
×
1468
  }
1469

1470
  if (TD_RES_QUERY(res)) {
214,766,389✔
1471
    SRequestObj *pRequest = (SRequestObj *)res;
210,659,607✔
1472

1473
    (*rows) = NULL;
210,659,607✔
1474
    (*numOfRows) = 0;
210,659,607✔
1475

1476
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
210,659,607✔
1477
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
210,338,863✔
1478
      return pRequest->code;
1,353,062✔
1479
    }
1480

1481
    (void)doAsyncFetchRows(pRequest, false, true);
209,306,545✔
1482

1483
    // TODO refactor
1484
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
209,306,545✔
1485
    pResultInfo->current = pResultInfo->numOfRows;
209,306,545✔
1486

1487
    (*rows) = pResultInfo->row;
209,306,545✔
1488
    (*numOfRows) = pResultInfo->numOfRows;
209,306,545✔
1489
    return pRequest->code;
209,306,545✔
1490
  } else if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
4,106,782✔
1491
    SReqResultInfo *pResultInfo = NULL;
4,106,782✔
1492
    int32_t         code = tmqGetNextResInfo(res, true, &pResultInfo);
4,106,782✔
1493
    if (code != 0) return code;
4,106,782✔
1494

1495
    pResultInfo->current = pResultInfo->numOfRows;
3,784,734✔
1496
    (*rows) = pResultInfo->row;
3,784,734✔
1497
    (*numOfRows) = pResultInfo->numOfRows;
3,784,734✔
1498
    return 0;
3,784,734✔
1499
  } else {
1500
    tscError("taos_fetch_block_s invalid res type");
×
1501
    return TSDB_CODE_TMQ_INVALID_DATA;
×
1502
  }
1503
}
1504

1505
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
61,543✔
1506
  *numOfRows = 0;
61,543✔
1507
  *pData = NULL;
61,543✔
1508

1509
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
61,543✔
1510
    return 0;
×
1511
  }
1512

1513
  if (TD_RES_TMQ(res) || TD_RES_TMQ_METADATA(res)) {
61,543✔
1514
    SReqResultInfo *pResultInfo = NULL;
57,855✔
1515
    int32_t         code = tmqGetNextResInfo(res, false, &pResultInfo);
57,855✔
1516
    if (code != 0) {
57,855✔
1517
      (*numOfRows) = 0;
1,057✔
1518
      return 0;
1,057✔
1519
    }
1520

1521
    pResultInfo->current = pResultInfo->numOfRows;
56,798✔
1522
    (*numOfRows) = pResultInfo->numOfRows;
56,798✔
1523
    (*pData) = (void *)pResultInfo->pData;
56,798✔
1524
    return 0;
56,798✔
1525
  }
1526

1527
  SRequestObj *pRequest = (SRequestObj *)res;
3,688✔
1528

1529
  if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
3,688✔
1530
      pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
3,688✔
1531
    return pRequest->code;
×
1532
  }
1533

1534
  (void)doAsyncFetchRows(pRequest, false, false);
3,688✔
1535

1536
  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
3,688✔
1537

1538
  pResultInfo->current = pResultInfo->numOfRows;
3,688✔
1539
  (*numOfRows) = pResultInfo->numOfRows;
3,688✔
1540
  (*pData) = (void *)pResultInfo->pData;
3,688✔
1541

1542
  return pRequest->code;
3,688✔
1543
}
1544

1545
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
143,278,145✔
1546
  if (res == NULL || TD_RES_TMQ_RAW(res) || TD_RES_TMQ_META(res) || TD_RES_TMQ_BATCH_META(res)) {
143,278,145✔
1547
    return 0;
×
1548
  }
1549

1550
  int32_t numOfFields = taos_num_fields(res);
143,278,145✔
1551
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
143,278,145✔
1552
    return 0;
×
1553
  }
1554

1555
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
143,278,145✔
1556
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
143,278,145✔
1557
  if (!IS_VAR_DATA_TYPE(pField->type)) {
143,278,145✔
1558
    return 0;
×
1559
  }
1560

1561
  return pResInfo->pCol[columnIndex].offset;
143,278,145✔
1562
}
1563

1564
int taos_is_null_by_column(TAOS_RES *res, int columnIndex, bool result[], int *rows) {
407,698,858✔
1565
  if (res == NULL || result == NULL || rows == NULL || *rows <= 0 || columnIndex < 0 || TD_RES_TMQ_META(res) ||
407,698,858✔
1566
      TD_RES_TMQ_RAW(res) || TD_RES_TMQ_BATCH_META(res)) {
407,698,858✔
1567
    return TSDB_CODE_INVALID_PARA;
×
1568
  }
1569

1570
  int32_t numOfFields = taos_num_fields(res);
407,698,858✔
1571
  if (columnIndex >= numOfFields || numOfFields == 0) {
407,698,858✔
1572
    return TSDB_CODE_INVALID_PARA;
×
1573
  }
1574

1575
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
407,698,858✔
1576
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
407,698,858✔
1577
  SResultColumn  *pCol = &pResInfo->pCol[columnIndex];
407,698,858✔
1578

1579
  if (*rows > pResInfo->numOfRows) {
407,698,858✔
1580
    *rows = pResInfo->numOfRows;
×
1581
  }
1582
  if (IS_VAR_DATA_TYPE(pField->type)) {
407,698,858✔
1583
    for (int i = 0; i < *rows; i++) {
×
1584
      if (pCol->offset[i] == -1) {
×
1585
        result[i] = true;
×
1586
      } else {
1587
        result[i] = false;
×
1588
      }
1589
    }
1590
  } else {
1591
    for (int i = 0; i < *rows; i++) {
2,147,483,647✔
1592
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1593
        result[i] = true;
2,147,483,647✔
1594
      } else {
1595
        result[i] = false;
2,147,483,647✔
1596
      }
1597
    }
1598
  }
1599
  return 0;
407,698,363✔
1600
}
1601

1602
int taos_validate_sql(TAOS *taos, const char *sql) {
×
1603
  TAOS_RES *pObj = taosQueryImpl(taos, sql, true, TD_REQ_FROM_APP);
×
1604

1605
  int code = taos_errno(pObj);
×
1606

1607
  taos_free_result(pObj);
×
1608
  return code;
×
1609
}
1610

1611
void taos_reset_current_db(TAOS *taos) {
×
1612
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
1613
  if (pTscObj == NULL) {
×
1614
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1615
    return;
×
1616
  }
1617

1618
  resetConnectDB(pTscObj);
×
1619

1620
  releaseTscObj(*(int64_t *)taos);
×
1621
}
1622

1623
const char *taos_get_server_info(TAOS *taos) {
4,174✔
1624
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
4,174✔
1625
  if (pTscObj == NULL) {
4,174✔
1626
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
1627
    return NULL;
×
1628
  }
1629

1630
  releaseTscObj(*(int64_t *)taos);
4,174✔
1631

1632
  return pTscObj->sDetailVer;
4,174✔
1633
}
1634

1635
int taos_get_current_db(TAOS *taos, char *database, int len, int *required) {
2,264✔
1636
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
2,264✔
1637
  if (pTscObj == NULL) {
2,264✔
1638
    return TSDB_CODE_TSC_DISCONNECTED;
×
1639
  }
1640

1641
  int code = TSDB_CODE_SUCCESS;
2,264✔
1642
  (void)taosThreadMutexLock(&pTscObj->mutex);
2,264✔
1643
  if (database == NULL || len <= 0) {
2,264✔
1644
    if (required != NULL) *required = strlen(pTscObj->db) + 1;
1,132✔
1645
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
1,132✔
1646
  } else if (len < strlen(pTscObj->db) + 1) {
1,132✔
1647
    tstrncpy(database, pTscObj->db, len);
566✔
1648
    if (required) *required = strlen(pTscObj->db) + 1;
566✔
1649
    TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
566✔
1650
  } else {
1651
    tstrncpy(database, pTscObj->db, len);
566✔
1652
    code = 0;
566✔
1653
  }
1654
_return:
2,264✔
1655
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
2,264✔
1656
  releaseTscObj(*(int64_t *)taos);
2,264✔
1657
  return code;
2,264✔
1658
}
1659

1660
// buffer is allocated by caller, len is in/out parameter, input is buffer length, output is actual length.
1661
// because this is a general purpose api, buffer is not null-terminated string even for string info, and
1662
// the return length is the actual length of the info, not including null-terminator.
1663
int taos_get_connection_info(TAOS *taos, TSDB_CONNECTION_INFO info, char* buffer, int* len) {
×
1664
  if (len == NULL) {
×
1665
    return TSDB_CODE_INVALID_PARA;
×
1666
  }
1667

1668
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
×
1669
  if (pTscObj == NULL) {
×
1670
    return TSDB_CODE_TSC_DISCONNECTED;
×
1671
  }
1672

1673
  int code = TSDB_CODE_SUCCESS;
×
1674
  (void)taosThreadMutexLock(&pTscObj->mutex);
×
1675

1676
  switch (info) {
×
1677
    case TSDB_CONNECTION_INFO_USER: {
×
1678
      int userLen = strlen(pTscObj->user);
×
1679
      if (buffer == NULL || *len < userLen) {
×
1680
        *len = userLen;
×
1681
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1682
      } else {
1683
        *len = userLen;
×
1684
        (void)memcpy(buffer, pTscObj->user, userLen);
×
1685
      }
1686
      break;
×
1687
    }
1688

1689
    case TSDB_CONNECTION_INFO_TOKEN: {
×
1690
      int tokenLen = strlen(pTscObj->tokenName);
×
1691
      if (tokenLen == 0) {
×
1692
        *len = 0;
×
1693
      } else if (buffer == NULL || *len < tokenLen) {
×
1694
        *len = tokenLen;
×
1695
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1696
      } else {
1697
        *len = tokenLen;
×
1698
        (void)memcpy(buffer, pTscObj->tokenName, tokenLen);
×
1699
      }
1700
      break;
×
1701
    }
1702

1703
    default:
×
1704
        TSC_ERR_JRET(TSDB_CODE_INVALID_PARA);
×
1705
  }
1706

1707
_return:
×
1708
  (void)taosThreadMutexUnlock(&pTscObj->mutex);
×
1709
  releaseTscObj(*(int64_t *)taos);
×
1710
  return code;
×
1711
}
1712

1713
void destorySqlCallbackWrapper(SSqlCallbackWrapper *pWrapper) {
1,751,078,784✔
1714
  if (NULL == pWrapper) {
1,751,078,784✔
1715
    return;
880,855,837✔
1716
  }
1717
  destoryCatalogReq(pWrapper->pCatalogReq);
870,222,947✔
1718
  taosMemoryFree(pWrapper->pCatalogReq);
870,221,437✔
1719
  qDestroyParseContext(pWrapper->pParseCtx);
870,219,533✔
1720
  taosMemoryFree(pWrapper);
870,215,392✔
1721
}
1722

1723
void destroyCtxInRequest(SRequestObj *pRequest) {
2,790,741✔
1724
  schedulerFreeJob(&pRequest->body.queryJob, 0);
2,790,741✔
1725
  qDestroyQuery(pRequest->pQuery);
2,790,741✔
1726
  pRequest->pQuery = NULL;
2,790,741✔
1727
  destorySqlCallbackWrapper(pRequest->pWrapper);
2,790,741✔
1728
  pRequest->pWrapper = NULL;
2,790,741✔
1729
}
2,790,741✔
1730

1731
static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t code) {
271,979,678✔
1732
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
271,979,678✔
1733
  SRequestObj         *pRequest = pWrapper->pRequest;
271,979,678✔
1734
  SQuery              *pQuery = pRequest->pQuery;
271,979,679✔
1735

1736
  qDebug("req:0x%" PRIx64 ", start to semantic analysis, QID:0x%" PRIx64, pRequest->self, pRequest->requestId);
271,980,906✔
1737

1738
  int64_t analyseStart = taosGetTimestampUs();
271,980,522✔
1739
  pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart;
271,980,522✔
1740
  pWrapper->pParseCtx->parseOnly = pRequest->parseOnly;
271,980,521✔
1741

1742
  if (TSDB_CODE_SUCCESS == code) {
271,979,678✔
1743
    code = qAnalyseSqlSemantic(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
271,979,515✔
1744
  }
1745

1746
  pRequest->metric.analyseCostUs += taosGetTimestampUs() - analyseStart;
271,974,454✔
1747

1748
  if (pRequest->parseOnly) {
271,975,545✔
1749
    (void)memcpy(&pRequest->parseMeta, pResultMeta, sizeof(*pResultMeta));
268,818✔
1750
    (void)memset(pResultMeta, 0, sizeof(*pResultMeta));
268,818✔
1751
  }
1752

1753
  handleQueryAnslyseRes(pWrapper, pResultMeta, code);
271,976,278✔
1754
}
271,971,767✔
1755

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

1783
    *ppTarget = pTarget;
×
1784
  }
1785

1786
  return code;
×
1787
}
1788

1789
void handleSubQueryFromAnalyse(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, SNode *pRoot) {
×
1790
  SRequestObj         *pNewRequest = NULL;
×
1791
  SSqlCallbackWrapper *pNewWrapper = NULL;
×
1792
  int32_t              code = buildPreviousRequest(pWrapper->pRequest, pWrapper->pRequest->sqlstr, &pNewRequest);
×
1793
  if (code) {
×
1794
    handleQueryAnslyseRes(pWrapper, pResultMeta, code);
×
1795
    return;
×
1796
  }
1797

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

1820
void handleQueryAnslyseRes(SSqlCallbackWrapper *pWrapper, SMetaData *pResultMeta, int32_t code) {
271,960,640✔
1821
  SRequestObj *pRequest = pWrapper->pRequest;
271,960,640✔
1822
  SQuery      *pQuery = pRequest->pQuery;
271,968,828✔
1823

1824
  if (code == TSDB_CODE_SUCCESS && pQuery->pPrevRoot) {
271,975,445✔
1825
    SNode *prevRoot = pQuery->pPrevRoot;
×
1826
    pQuery->pPrevRoot = NULL;
×
1827
    handleSubQueryFromAnalyse(pWrapper, pResultMeta, prevRoot);
×
1828
    return;
×
1829
  }
1830

1831
  if (code == TSDB_CODE_SUCCESS) {
271,976,404✔
1832
    pRequest->stableQuery = pQuery->stableQuery;
216,622,576✔
1833
    if (pQuery->pRoot) {
216,627,908✔
1834
      pRequest->stmtType = pQuery->pRoot->type;
216,628,072✔
1835
    }
1836

1837
    if (pQuery->haveResultSet) {
216,628,869✔
1838
      code = setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols, pQuery->pResExtSchema,
146,815,821✔
1839
                              pRequest->stmtBindVersion > 0);
146,816,939✔
1840
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
146,818,443✔
1841
    }
1842
  }
1843

1844
  if (code == TSDB_CODE_SUCCESS) {
271,958,809✔
1845
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
216,617,267✔
1846
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
216,611,579✔
1847
    TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList);
216,607,402✔
1848

1849
    launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper);
216,606,314✔
1850
  } else {
1851
    destorySqlCallbackWrapper(pWrapper);
55,341,542✔
1852
    pRequest->pWrapper = NULL;
55,341,542✔
1853
    qDestroyQuery(pRequest->pQuery);
55,341,542✔
1854
    pRequest->pQuery = NULL;
55,341,542✔
1855

1856
    if (NEED_CLIENT_HANDLE_ERROR(code) && pRequest->stmtBindVersion == 0) {
55,341,542✔
1857
      tscDebug("req:0x%" PRIx64 ", client retry to handle the error, code:%d - %s, tryCount:%d, QID:0x%" PRIx64,
2,697,197✔
1858
               pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
1859
      restartAsyncQuery(pRequest, code);
2,697,197✔
1860
      return;
2,697,197✔
1861
    }
1862

1863
    // return to app directly
1864
    tscError("req:0x%" PRIx64 ", error occurs, code:%s, return to user app, QID:0x%" PRIx64, pRequest->self,
52,644,345✔
1865
             tstrerror(code), pRequest->requestId);
1866
    pRequest->code = code;
52,644,345✔
1867
    returnToUser(pRequest);
52,644,345✔
1868
  }
1869
}
1870

1871
static int32_t getAllMetaAsync(SSqlCallbackWrapper *pWrapper, catalogCallback fp) {
278,883,135✔
1872
  SRequestConnInfo conn = {.pTrans = pWrapper->pParseCtx->pTransporter,
485,165,621✔
1873
                           .requestId = pWrapper->pParseCtx->requestId,
278,887,472✔
1874
                           .requestObjRefId = pWrapper->pParseCtx->requestRid,
278,887,223✔
1875
                           .mgmtEps = pWrapper->pParseCtx->mgmtEpSet};
278,884,549✔
1876

1877
  pWrapper->pRequest->metric.ctgStart = taosGetTimestampUs();
485,166,011✔
1878

1879
  return catalogAsyncGetAllMeta(pWrapper->pParseCtx->pCatalog, &conn, pWrapper->pCatalogReq, fp, pWrapper,
351,485,354✔
1880
                                &pWrapper->pRequest->body.queryJob);
278,882,161✔
1881
}
1882

1883
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code);
1884

1885
static int32_t phaseAsyncQuery(SSqlCallbackWrapper *pWrapper) {
867,002,288✔
1886
  int32_t code = TSDB_CODE_SUCCESS;
867,002,288✔
1887
  switch (pWrapper->pRequest->pQuery->execStage) {
867,002,288✔
1888
    case QUERY_EXEC_STAGE_PARSE: {
6,913,367✔
1889
      // continue parse after get metadata
1890
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromParse);
6,913,367✔
1891
      break;
6,913,367✔
1892
    }
1893
    case QUERY_EXEC_STAGE_ANALYSE: {
271,976,853✔
1894
      // analysis after get metadata
1895
      code = getAllMetaAsync(pWrapper, doAsyncQueryFromAnalyse);
271,976,853✔
1896
      break;
271,972,799✔
1897
    }
1898
    case QUERY_EXEC_STAGE_SCHEDULE: {
588,123,177✔
1899
      launchAsyncQuery(pWrapper->pRequest, pWrapper->pRequest->pQuery, NULL, pWrapper);
588,123,177✔
1900
      break;
588,117,718✔
1901
    }
1902
    default:
12✔
1903
      break;
12✔
1904
  }
1905
  return code;
867,003,874✔
1906
}
1907

1908
static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t code) {
6,913,367✔
1909
  SSqlCallbackWrapper *pWrapper = (SSqlCallbackWrapper *)param;
6,913,367✔
1910
  SRequestObj         *pRequest = pWrapper->pRequest;
6,913,367✔
1911
  SQuery              *pQuery = pRequest->pQuery;
6,913,367✔
1912

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

1917
  if (code == TSDB_CODE_SUCCESS) {
6,913,367✔
1918
    // pWrapper->pCatalogReq->forceUpdate = false;
1919
    code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery);
6,866,986✔
1920
  }
1921

1922
  if (TSDB_CODE_SUCCESS == code) {
6,913,367✔
1923
    code = phaseAsyncQuery(pWrapper);
6,326,907✔
1924
  }
1925

1926
  if (TSDB_CODE_SUCCESS != code) {
6,913,367✔
1927
    tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pWrapper->pRequest->self, code,
586,460✔
1928
             tstrerror(code), pWrapper->pRequest->requestId);
1929
    destorySqlCallbackWrapper(pWrapper);
586,460✔
1930
    pRequest->pWrapper = NULL;
586,460✔
1931
    terrno = code;
586,460✔
1932
    pRequest->code = code;
586,460✔
1933
    doRequestCallback(pRequest, code);
586,460✔
1934
  }
1935
}
6,913,367✔
1936

1937
void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) {
21,520✔
1938
  int32_t code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
21,520✔
1939
  if (TSDB_CODE_SUCCESS == code) {
21,520✔
1940
    code = phaseAsyncQuery(pWrapper);
21,520✔
1941
  }
1942

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

1954
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
126,221✔
1955
  int64_t connId = *(int64_t *)taos;
126,221✔
1956
  taosAsyncQueryImpl(connId, sql, fp, param, false, TD_REQ_FROM_APP);
126,221✔
1957
}
126,221✔
1958

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

1964
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt, SSqlCallbackWrapper *pWrapper) {
870,215,205✔
1965
  const STscObj *pTscObj = pRequest->pTscObj;
870,215,205✔
1966

1967
  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
870,219,985✔
1968
  if (*pCxt == NULL) {
870,212,972✔
1969
    return terrno;
×
1970
  }
1971

1972
  **pCxt = (SParseContext){.requestId = pRequest->requestId,
2,147,483,647✔
1973
                           .requestRid = pRequest->self,
870,220,172✔
1974
                           .acctId = pTscObj->acctId,
870,220,664✔
1975
                           .db = pRequest->pDb,
870,221,469✔
1976
                           .topicQuery = false,
1977
                           .pSql = pRequest->sqlstr,
870,222,282✔
1978
                           .sqlLen = pRequest->sqlLen,
870,223,716✔
1979
                           .pMsg = pRequest->msgBuf,
870,221,763✔
1980
                           .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
1981
                           .pTransporter = pTscObj->pAppInfo->pTransporter,
870,219,237✔
1982
                           .pStmtCb = NULL,
1983
                           .pUser = pTscObj->user,
870,222,752✔
1984
                           .userId = pTscObj->userId,
870,219,448✔
1985
                           .pEffectiveUser = pRequest->effectiveUser,
870,221,101✔
1986
                           .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
870,215,356✔
1987
                           .enableSysInfo = pTscObj->sysInfo,
870,219,968✔
1988
                           .privInfo = pWrapper->pParseCtx ? pWrapper->pParseCtx->privInfo : 0,
870,219,439✔
1989
                           .async = true,
1990
                           .svrVer = pTscObj->sVer,
870,216,807✔
1991
                           .nodeOffline = (pTscObj->pAppInfo->onlineDnodes < pTscObj->pAppInfo->totalDnodes),
870,223,833✔
1992
                           .allocatorId = pRequest->allocatorRefId,
870,223,752✔
1993
                           .parseSqlFp = clientParseSql,
1994
                           .parseSqlParam = pWrapper,
1995
                           .setQueryFp = setQueryRequest,
1996
                           .timezone = pTscObj->optionInfo.timezone,
870,222,063✔
1997
                           .charsetCxt = pTscObj->optionInfo.charsetCxt};
870,220,675✔
1998
  int8_t biMode = atomic_load_8(&((STscObj *)pTscObj)->biMode);
870,215,533✔
1999
  (*pCxt)->biMode = biMode;
870,213,159✔
2000
  return TSDB_CODE_SUCCESS;
870,221,484✔
2001
}
2002

2003
int32_t prepareAndParseSqlSyntax(SSqlCallbackWrapper **ppWrapper, SRequestObj *pRequest, bool updateMetaForce) {
870,215,991✔
2004
  int32_t              code = TSDB_CODE_SUCCESS;
870,215,991✔
2005
  STscObj             *pTscObj = pRequest->pTscObj;
870,215,991✔
2006
  SSqlCallbackWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SSqlCallbackWrapper));
870,222,847✔
2007
  if (pWrapper == NULL) {
870,220,204✔
2008
    code = terrno;
×
2009
  } else {
2010
    pWrapper->pRequest = pRequest;
870,220,204✔
2011
    pRequest->pWrapper = pWrapper;
870,217,133✔
2012
    *ppWrapper = pWrapper;
870,220,572✔
2013
  }
2014

2015
  if (TSDB_CODE_SUCCESS == code) {
870,219,941✔
2016
    code = createParseContext(pRequest, &pWrapper->pParseCtx, pWrapper);
870,213,890✔
2017
  }
2018

2019
  if (TSDB_CODE_SUCCESS == code) {
870,217,323✔
2020
    pWrapper->pParseCtx->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
870,217,357✔
2021
    code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pWrapper->pParseCtx->pCatalog);
870,226,630✔
2022
  }
2023

2024
  if (TSDB_CODE_SUCCESS == code && NULL == pRequest->pQuery) {
870,213,146✔
2025
    int64_t syntaxStart = taosGetTimestampUs();
870,223,324✔
2026

2027
    pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq));
870,223,324✔
2028
    if (pWrapper->pCatalogReq == NULL) {
870,208,928✔
2029
      code = terrno;
×
2030
    } else {
2031
      pWrapper->pCatalogReq->forceUpdate = updateMetaForce;
870,211,645✔
2032
      TSC_ERR_RET(qnodeRequired(pRequest, &pWrapper->pCatalogReq->qNodeRequired));
870,212,988✔
2033
      code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq);
870,217,103✔
2034
    }
2035

2036
    pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart;
870,216,064✔
2037
  }
2038

2039
  return code;
870,226,313✔
2040
}
2041

2042
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
871,116,271✔
2043
  SSqlCallbackWrapper *pWrapper = NULL;
871,116,271✔
2044
  int32_t              code = TSDB_CODE_SUCCESS;
871,121,728✔
2045

2046
  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
871,121,728✔
2047
    code = pRequest->prevCode;
900,743✔
2048
    terrno = code;
900,743✔
2049
    pRequest->code = code;
900,743✔
2050
    tscDebug("req:0x%" PRIx64 ", call sync query cb with code:%s", pRequest->self, tstrerror(code));
900,743✔
2051
    doRequestCallback(pRequest, code);
900,743✔
2052
    return;
900,743✔
2053
  }
2054

2055
  if (TSDB_CODE_SUCCESS == code) {
870,218,187✔
2056
    code = prepareAndParseSqlSyntax(&pWrapper, pRequest, updateMetaForce);
870,215,609✔
2057
  }
2058

2059
  if (TSDB_CODE_SUCCESS == code) {
870,221,483✔
2060
    pRequest->stmtType = pRequest->pQuery->pRoot->type;
860,664,049✔
2061
    code = phaseAsyncQuery(pWrapper);
860,668,628✔
2062
  }
2063

2064
  if (TSDB_CODE_SUCCESS != code) {
870,216,241✔
2065
    if (NULL != pRequest->msgBuf && strlen(pRequest->msgBuf) > 0) {
9,556,481✔
2066
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, pRequest->msgBuf,
9,488,525✔
2067
               pRequest->requestId);
2068
    } else {
2069
      tscError("req:0x%" PRIx64 ", error happens, code:%d - %s, QID:0x%" PRIx64, pRequest->self, code, tstrerror(code),
67,956✔
2070
               pRequest->requestId);
2071
    }
2072

2073
    destorySqlCallbackWrapper(pWrapper);
9,556,481✔
2074
    pRequest->pWrapper = NULL;
9,556,481✔
2075
    qDestroyQuery(pRequest->pQuery);
9,556,481✔
2076
    pRequest->pQuery = NULL;
9,556,481✔
2077

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

2091
    terrno = code;
9,546,124✔
2092
    pRequest->code = code;
9,546,124✔
2093
    doRequestCallback(pRequest, code);
9,546,124✔
2094
  }
2095
}
2096

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

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

2135
static int32_t doAsyncFetch(void *pParam) {
184,175,870✔
2136
  SAsyncFetchParam *param = pParam;
184,175,870✔
2137
  taosAsyncFetchImpl(param->pReq, param->fp, param->param);
184,175,870✔
2138
  taosMemoryFree(param);
184,173,675✔
2139
  return TSDB_CODE_SUCCESS;
184,172,661✔
2140
}
2141

2142
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
184,196,105✔
2143
  if (res == NULL || fp == NULL) {
184,196,105✔
2144
    tscError("taos_fetch_rows_a invalid paras");
×
2145
    return;
×
2146
  }
2147
  if (!TD_RES_QUERY(res)) {
184,196,846✔
2148
    tscError("taos_fetch_rows_a res is NULL");
×
2149
    fp(param, res, TSDB_CODE_APP_ERROR);
×
2150
    return;
×
2151
  }
2152

2153
  SRequestObj *pRequest = res;
184,196,846✔
2154
  if (TSDB_SQL_RETRIEVE_EMPTY_RESULT == pRequest->type) {
184,196,846✔
2155
    fp(param, res, 0);
20,976✔
2156
    return;
20,976✔
2157
  }
2158

2159
  SAsyncFetchParam *pParam = taosMemoryCalloc(1, sizeof(SAsyncFetchParam));
184,175,129✔
2160
  if (!pParam) {
184,175,870✔
2161
    fp(param, res, terrno);
×
2162
    return;
×
2163
  }
2164
  pParam->pReq = pRequest;
184,175,870✔
2165
  pParam->fp = fp;
184,175,870✔
2166
  pParam->param = param;
184,175,129✔
2167
  int32_t code = taosAsyncExec(doAsyncFetch, pParam, NULL);
184,175,848✔
2168
  if (TSDB_CODE_SUCCESS != code) {
184,175,848✔
2169
    taosMemoryFree(pParam);
×
2170
    fp(param, res, code);
×
2171
    return;
×
2172
  }
2173
}
2174

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

2187
  // set the current block is all consumed
2188
  pResultInfo->convertUcs4 = false;
136✔
2189

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

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

2205
  return pRequest->body.resInfo.pData;
80✔
2206
}
2207

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

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

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

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

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

2239
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2240

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

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

2249
_return:
×
2250

2251
  terrno = code;
×
2252

2253
  destroyRequest(pRequest);
×
2254
  return code;
×
2255
}
2256

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

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

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

2277
  pRequest->syncQuery = true;
×
2278

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

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

2289
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2290

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

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

2300
  *vgId = vgInfo.vgId;
×
2301

2302
_return:
×
2303

2304
  terrno = code;
×
2305

2306
  destroyRequest(pRequest);
×
2307
  return code;
×
2308
}
2309

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

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

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

2330
  pRequest->syncQuery = true;
×
2331

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

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

2342
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
×
2343

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

2349
_return:
×
2350

2351
  terrno = code;
×
2352

2353
  destroyRequest(pRequest);
×
2354
  return code;
×
2355
}
2356

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

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

2369
  if (NULL == tableNameList) {
1,140✔
2370
    return TSDB_CODE_SUCCESS;
×
2371
  }
2372

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

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

2388
  pRequest->syncQuery = true;
1,140✔
2389

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

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

2402
  SRequestConnInfo conn = {
1,140✔
2403
      .pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self};
1,140✔
2404

2405
  conn.mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
1,140✔
2406

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

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

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

2432
  TAOS_STMT *pStmt = stmtInit(pObj, 0, NULL);
124,653✔
2433
  if (NULL == pStmt) {
124,687✔
2434
    tscError("stmt init failed, errcode:%s", terrstr());
×
2435
  }
2436
  releaseTscObj(*(int64_t *)taos);
124,687✔
2437

2438
  return pStmt;
124,687✔
2439
}
2440

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

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

2455
  return pStmt;
×
2456
}
2457

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

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

2472
  return pStmt;
12,551✔
2473
}
2474

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

2482
  return stmtPrepare(stmt, sql, length);
6,709,436✔
2483
}
2484

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

2492
  int32_t code = stmtSetTbName(stmt, name);
5,972✔
2493
  if (code) {
5,972✔
2494
    return code;
570✔
2495
  }
2496

2497
  if (tags) {
5,402✔
2498
    return stmtSetTbTags(stmt, tags);
5,402✔
2499
  }
2500

2501
  return TSDB_CODE_SUCCESS;
×
2502
}
2503

2504
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
8,749,934✔
2505
  if (stmt == NULL || name == NULL) {
8,749,934✔
UNCOV
2506
    tscError("NULL parameter for %s", __FUNCTION__);
×
UNCOV
2507
    terrno = TSDB_CODE_INVALID_PARA;
×
2508
    return terrno;
×
2509
  }
2510

2511
  return stmtSetTbName(stmt, name);
8,754,018✔
2512
}
2513

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

2521
  return stmtSetTbTags(stmt, tags);
176✔
2522
}
2523

2524
int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); }
×
2525

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

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

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

2543
  return stmtGetColFields(stmt, fieldNum, fields);
×
2544
}
2545

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

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

2560
  if (bind->num > 1) {
26,891✔
2561
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
3,798✔
2562
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
3,798✔
2563
    return terrno;
3,798✔
2564
  }
2565

2566
  return stmtBindBatch(stmt, bind, -1);
23,093✔
2567
}
2568

2569
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
68,714,582✔
2570
  if (stmt == NULL || bind == NULL) {
68,714,582✔
2571
    tscError("NULL parameter for %s", __FUNCTION__);
×
2572
    terrno = TSDB_CODE_INVALID_PARA;
×
2573
    return terrno;
×
2574
  }
2575

2576
  if (bind->num <= 0 || bind->num > INT16_MAX) {
69,730,140✔
2577
    tscError("invalid bind num %d", bind->num);
1,578✔
2578
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
1,578✔
2579
    return terrno;
×
2580
  }
2581

2582
  int32_t insert = 0;
70,243,150✔
2583
  int32_t code = stmtIsInsert(stmt, &insert);
70,076,045✔
2584
  if (TSDB_CODE_SUCCESS != code) {
70,052,957✔
2585
    tscError("stmt insert failed, errcode:%s", tstrerror(code));
×
2586
    return code;
×
2587
  }
2588
  if (0 == insert && bind->num > 1) {
70,052,957✔
2589
    tscError("only one row data allowed for query");
×
2590
    terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2591
    return terrno;
×
2592
  }
2593

2594
  return stmtBindBatch(stmt, bind, -1);
70,052,957✔
2595
}
2596

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

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

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

2622
  return stmtBindBatch(stmt, bind, colIdx);
1,120✔
2623
}
2624

2625
int taos_stmt_add_batch(TAOS_STMT *stmt) {
66,359,167✔
2626
  if (stmt == NULL) {
66,359,167✔
2627
    tscError("NULL parameter for %s", __FUNCTION__);
×
2628
    terrno = TSDB_CODE_INVALID_PARA;
×
2629
    return terrno;
×
2630
  }
2631

2632
  return stmtAddBatch(stmt);
66,359,167✔
2633
}
2634

2635
int taos_stmt_execute(TAOS_STMT *stmt) {
7,064,797✔
2636
  if (stmt == NULL) {
7,064,797✔
2637
    tscError("NULL parameter for %s", __FUNCTION__);
×
2638
    terrno = TSDB_CODE_INVALID_PARA;
×
2639
    return terrno;
×
2640
  }
2641

2642
  return stmtExec(stmt);
7,064,797✔
2643
}
2644

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

2652
  return stmtIsInsert(stmt, insert);
×
2653
}
2654

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

2662
  return stmtGetParamNum(stmt, nums);
×
2663
}
2664

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

2672
  return stmtGetParam(stmt, idx, type, bytes);
×
2673
}
2674

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

2682
  return stmtUseResult(stmt);
9,120✔
2683
}
2684

2685
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
9,881✔
2686

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

2694
  return stmtAffectedRows(stmt);
3,006✔
2695
}
2696

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

2704
  return stmtAffectedRowsOnce(stmt);
80✔
2705
}
2706

2707
int taos_stmt_close(TAOS_STMT *stmt) {
137,064✔
2708
  if (stmt == NULL) {
137,064✔
2709
    tscError("NULL parameter for %s", __FUNCTION__);
×
2710
    terrno = TSDB_CODE_INVALID_PARA;
×
2711
    return terrno;
×
2712
  }
2713

2714
  return stmtClose(stmt);
137,064✔
2715
}
2716

2717
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
3,271✔
2718
  if (NULL == taos) {
3,271✔
2719
    tscError("NULL parameter for %s", __FUNCTION__);
×
2720
    terrno = TSDB_CODE_INVALID_PARA;
×
2721
    return NULL;
×
2722
  }
2723
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
3,271✔
2724
  if (NULL == pObj) {
3,314✔
2725
    tscError("invalid parameter for %s", __FUNCTION__);
×
2726
    terrno = TSDB_CODE_TSC_DISCONNECTED;
×
2727
    return NULL;
×
2728
  }
2729

2730
  TAOS_STMT2 *pStmt = stmtInit2(pObj, option);
3,314✔
2731

2732
  releaseTscObj(*(int64_t *)taos);
3,314✔
2733

2734
  return pStmt;
3,314✔
2735
}
2736

2737
int taos_stmt2_prepare(TAOS_STMT2 *stmt, const char *sql, unsigned long length) {
3,418✔
2738
  if (stmt == NULL || sql == NULL) {
3,418✔
2739
    tscError("NULL parameter for %s", __FUNCTION__);
×
2740
    terrno = TSDB_CODE_INVALID_PARA;
×
2741
    return terrno;
×
2742
  }
2743

2744
  return stmtPrepare2(stmt, sql, length);
3,418✔
2745
}
2746

2747
int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col_idx) {
557,555✔
2748
  if (stmt == NULL) {
557,555✔
2749
    tscError("NULL parameter for %s", __FUNCTION__);
×
2750
    terrno = TSDB_CODE_INVALID_PARA;
×
2751
    return terrno;
×
2752
  }
2753

2754
  STscStmt2 *pStmt = (STscStmt2 *)stmt;
557,555✔
2755
  int32_t    code = TSDB_CODE_SUCCESS;
557,555✔
2756
  STMT2_DLOG_E("start to bind param");
557,555✔
2757

2758
  // check query bind number
2759
  bool isQuery = (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt)));
557,581✔
2760
  if (isQuery) {
557,634✔
2761
    if (bindv->count != 1 || bindv->bind_cols[0]->num != 1) {
8✔
2762
      terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
×
2763
      STMT2_ELOG_E("query only support one table and one row bind");
×
2764
      return terrno;
×
2765
    }
2766
  }
2767

2768
  if (atomic_load_8((int8_t *)&pStmt->asyncBindParam.asyncBindNum) > 1) {
557,634✔
2769
    STMT2_ELOG_E("async bind param is still working, please try again later");
52✔
2770
    terrno = TSDB_CODE_TSC_STMT_API_ERROR;
52✔
2771
    return terrno;
×
2772
  }
2773

2774
  if (pStmt->options.asyncExecFn && !pStmt->execSemWaited) {
557,488✔
2775
    if (tsem_wait(&pStmt->asyncExecSem) != 0) {
×
2776
      STMT2_ELOG_E("bind param wait asyncExecSem failed");
×
2777
    }
2778
    pStmt->execSemWaited = true;
×
2779
  }
2780

2781
  for (int i = 0; i < bindv->count; ++i) {
1,676,228✔
2782
    SVCreateTbReq *pCreateTbReq = NULL;
1,118,626✔
2783
    if (!isQuery) {
1,118,475✔
2784
      STMT2_TLOG("start to bind %dth table", i);
1,118,482✔
2785
      if (bindv->tbnames && bindv->tbnames[i]) {
1,118,443✔
2786
        code = stmtSetTbName2(stmt, bindv->tbnames[i]);
1,118,663✔
2787
        if (code) {
1,118,412✔
2788
          terrno = code;
×
2789
          STMT2_ELOG("set tbname failed, code:%s", tstrerror(code));
×
2790
          return terrno;
×
2791
        }
2792
      }
2793

2794
      if (bindv->tags && bindv->tags[i]) {
1,118,282✔
2795
        code = stmtSetTbTags2(stmt, bindv->tags[i], &pCreateTbReq);
525,334✔
2796
      } else if (pStmt->bInfo.tbNameFlag & IS_FIXED_TAG) {
593,062✔
2797
        code = stmtCheckTags2(stmt, &pCreateTbReq);
103,831✔
2798
      } else if (pStmt->sql.autoCreateTbl) {
488,884✔
2799
        code = stmtSetTbTags2(stmt, NULL, &pCreateTbReq);
×
2800
      }
2801

2802
      if (code) {
1,118,222✔
2803
        terrno = code;
×
2804
        STMT2_ELOG("set tags failed, code:%s", tstrerror(code));
×
2805
        return terrno;
×
2806
      }
2807
    }
2808

2809
    if (bindv->bind_cols && bindv->bind_cols[i]) {
1,118,215✔
2810
      TAOS_STMT2_BIND *bind = bindv->bind_cols[i];
1,118,622✔
2811

2812
      if (bind->num <= 0 || bind->num > INT16_MAX) {
1,118,657✔
2813
        STMT2_ELOG("bind num:%d must > 0 and < INT16_MAX", bind->num);
108✔
2814
        code = terrno = TSDB_CODE_TSC_STMT_BIND_NUMBER_ERROR;
108✔
2815
        return terrno;
×
2816
      }
2817

2818
      code = stmtBindBatch2(stmt, bind, col_idx, pCreateTbReq);
1,118,549✔
2819
      if (TSDB_CODE_SUCCESS != code) {
1,118,557✔
2820
        terrno = code;
×
2821
        STMT2_ELOG("bind batch failed, code:%s", tstrerror(code));
×
2822
        return terrno;
×
2823
      }
2824
    }
2825
  }
2826

2827
  return code;
557,647✔
2828
}
2829

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

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

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

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

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

2866
  return code_s;
×
2867
}
2868

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

2876
  return stmtExec2(stmt, affected_rows);
557,594✔
2877
}
2878

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

2886
  return stmtClose2(stmt);
3,314✔
2887
}
2888

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

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

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

2909
  if (STMT_TYPE_INSERT == pStmt->sql.type || STMT_TYPE_MULTI_INSERT == pStmt->sql.type ||
24✔
2910
      (pStmt->sql.type == 0 && stmt2IsInsert(stmt))) {
24✔
2911
    return stmtGetStbColFields2(stmt, count, fields);
24✔
2912
  }
2913
  if (STMT_TYPE_QUERY == pStmt->sql.type || (pStmt->sql.type == 0 && stmt2IsSelect(stmt))) {
×
2914
    return stmtGetParamNum2(stmt, count);
×
2915
  }
2916

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

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

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

2934
  return stmtUseResult2(stmt);
8✔
2935
}
2936

2937
char *taos_stmt2_error(TAOS_STMT2 *stmt) { return (char *)stmtErrstr2(stmt); }
×
2938

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3135
  int32_t code = taos_init();
×
3136
  if (code != TSDB_CODE_SUCCESS) {
×
3137
    return code;
×
3138
  }
3139

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3269
  terrno = code;
×
3270
  return code;
×
3271
}
3272

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3449
  return TSDB_CODE_SUCCESS;
×
3450
}
3451

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

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

3465
  // Free the array itself
3466
  taosMemoryFree(*pList);
×
3467
  *pList = NULL;
×
3468
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc