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

#include "catalog.h"
17
#include "clientInt.h"
18
#include "clientLog.h"
L
Liu Jicong 已提交
19
#include "clientStmt.h"
L
Liu Jicong 已提交
20
#include "os.h"
H
Haojun Liao 已提交
21
#include "query.h"
L
Liu Jicong 已提交
22
#include "scheduler.h"
23
#include "tglobal.h"
L
Liu Jicong 已提交
24 25 26
#include "tmsg.h"
#include "tref.h"
#include "trpc.h"
S
version  
Shengliang Guan 已提交
27
#include "version.h"
28 29 30 31 32

#define TSC_VAR_NOT_RELEASE 1
#define TSC_VAR_RELEASED    0

static int32_t sentinel = TSC_VAR_NOT_RELEASE;
33
static int32_t createParseContext(const SRequestObj *pRequest, SParseContext** pCxt);
34 35 36 37 38 39 40 41 42 43 44

int taos_options(TSDB_OPTION option, const void *arg, ...) {
  static int32_t lock = 0;

  for (int i = 1; atomic_val_compare_exchange_32(&lock, 0, 1) != 0; ++i) {
    if (i % 1000 == 0) {
      tscInfo("haven't acquire lock after spin %d times.", i);
      sched_yield();
    }
  }

L
Liu Jicong 已提交
45
  int ret = taos_options_imp(option, (const char *)arg);
46 47 48 49 50 51
  atomic_store_32(&lock, 0);
  return ret;
}

// this function may be called by user or system, or by both simultaneously.
void taos_cleanup(void) {
H
Haojun Liao 已提交
52
  tscInfo("start to cleanup client environment");
53 54 55 56 57

  if (atomic_val_compare_exchange_32(&sentinel, TSC_VAR_NOT_RELEASE, TSC_VAR_RELEASED) != TSC_VAR_NOT_RELEASE) {
    return;
  }

H
Haojun Liao 已提交
58 59
  int32_t id = clientReqRefPool;
  clientReqRefPool = -1;
60 61
  taosCloseRef(id);

H
Haojun Liao 已提交
62
  cleanupTaskQueue();
63

64 65
  id = clientConnRefPool;
  clientConnRefPool = -1;
66 67
  taosCloseRef(id);

68 69
  hbMgrCleanUp();

D
dapan1121 已提交
70
  catalogDestroy();
D
dapan1121 已提交
71
  schedulerDestroy();
H
Haojun Liao 已提交
72

D
dapan1121 已提交
73 74
  rpcCleanup();

H
Haojun Liao 已提交
75
  tscInfo("all local resources released");
76
  taosCleanupCfg();
77
  taosCloseLog();
78 79
}

L
Liu Jicong 已提交
80
setConfRet taos_set_config(const char *config) {
81 82 83 84 85
  // TODO
  setConfRet ret = {SET_CONF_RET_SUCC, {0}};
  return ret;
}

86
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
S
Shengliang Guan 已提交
87
  tscDebug("try to connect to %s:%u, user:%s db:%s", ip, port, user, db);
H
Haojun Liao 已提交
88 89 90
  if (user == NULL) {
    user = TSDB_DEFAULT_USER;
  }
91

H
Haojun Liao 已提交
92 93 94
  if (pass == NULL) {
    pass = TSDB_DEFAULT_PASS;
  }
95

L
Liu Jicong 已提交
96
  return taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY);
97 98
}

L
Liu Jicong 已提交
99
void taos_close(TAOS *taos) {
100 101 102 103
  if (taos == NULL) {
    return;
  }

H
Haojun Liao 已提交
104
  STscObj *pTscObj = (STscObj *)taos;
L
Liu Jicong 已提交
105
  tscDebug("0x%" PRIx64 " try to close connection, numOfReq:%d", pTscObj->id, pTscObj->numOfReqs);
106

D
dapan1121 已提交
107
  taosRemoveRef(clientConnRefPool, pTscObj->id);
108 109
}

110 111 112 113 114
int taos_errno(TAOS_RES *tres) {
  if (tres == NULL) {
    return terrno;
  }

115 116 117 118
  if (TD_RES_TMQ(tres)) {
    return 0;
  }

L
Liu Jicong 已提交
119
  return ((SRequestObj *)tres)->code;
120 121
}

122
const char *taos_errstr(TAOS_RES *res) {
123
  if (res == NULL) {
L
Liu Jicong 已提交
124
    return (const char *)tstrerror(terrno);
125 126
  }

127 128 129 130 131
  if (TD_RES_TMQ(res)) {
    return "success";
  }

  SRequestObj *pRequest = (SRequestObj *)res;
132
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
133 134
    return pRequest->msgBuf;
  } else {
L
Liu Jicong 已提交
135
    return (const char *)tstrerror(pRequest->code);
136
  }
137 138 139
}

void taos_free_result(TAOS_RES *res) {
D
stmt  
dapan1121 已提交
140 141 142
  if (NULL == res) {
    return;
  }
143

L
Liu Jicong 已提交
144 145 146
  if (TD_RES_QUERY(res)) {
    SRequestObj *pRequest = (SRequestObj *)res;
    destroyRequest(pRequest);
L
Liu Jicong 已提交
147 148 149 150 151 152
  } else if (TD_RES_TMQ(res)) {
    SMqRspObj *pRsp = (SMqRspObj *)res;
    if (pRsp->rsp.blockData) taosArrayDestroyP(pRsp->rsp.blockData, taosMemoryFree);
    if (pRsp->rsp.blockDataLen) taosArrayDestroy(pRsp->rsp.blockDataLen);
    if (pRsp->rsp.blockTags) taosArrayDestroy(pRsp->rsp.blockTags);
    if (pRsp->rsp.blockTagSchema) taosArrayDestroy(pRsp->rsp.blockTagSchema);
L
Liu Jicong 已提交
153 154
    if (pRsp->rsp.withTbName) taosArrayDestroyP(pRsp->rsp.blockTbName, taosMemoryFree);
    if (pRsp->rsp.withSchema) taosArrayDestroyP(pRsp->rsp.blockSchema, (FDelete)tDeleteSSchemaWrapper);
L
Liu Jicong 已提交
155 156
    pRsp->resInfo.pRspMsg = NULL;
    doFreeReqResultInfo(&pRsp->resInfo);
L
Liu Jicong 已提交
157
  }
158 159
}

L
Liu Jicong 已提交
160
int taos_field_count(TAOS_RES *res) {
H
Haojun Liao 已提交
161 162 163 164
  if (res == NULL) {
    return 0;
  }

L
Liu Jicong 已提交
165
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
H
Haojun Liao 已提交
166 167 168
  return pResInfo->numOfCols;
}

L
Liu Jicong 已提交
169
int taos_num_fields(TAOS_RES *res) { return taos_field_count(res); }
H
Haojun Liao 已提交
170 171 172 173 174 175

TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
  if (taos_num_fields(res) == 0) {
    return NULL;
  }

L
Liu Jicong 已提交
176
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
177
  return pResInfo->userFields;
H
Haojun Liao 已提交
178 179
}

180 181 182 183 184 185 186 187
static void syncQueryFn(void* param, void* res, int32_t code) {
  SSyncQueryParam* pParam = param;
  pParam->pRequest = res;
  pParam->pRequest->code = code;

  tsem_post(&pParam->sem);
}

188 189 190 191 192
TAOS_RES *taos_query(TAOS *taos, const char *sql) {
  if (taos == NULL || sql == NULL) {
    return NULL;
  }

193
  STscObj* pTscObj = (STscObj*)taos;
194 195

#if SYNC_ON_TOP_OF_ASYNC
196
  SSyncQueryParam* param = taosMemoryCalloc(1, sizeof(SSyncQueryParam));
197 198 199 200 201
  tsem_init(&param->sem, 0, 0);

  taos_query_a(pTscObj, sql, syncQueryFn, param);
  tsem_wait(&param->sem);

wmmhello's avatar
wmmhello 已提交
202 203 204 205
  TAOS_RES *request = param->pRequest;
  tsem_destroy(&param->sem);
  taosMemoryFree(param);
  return request;
206
#else
207 208 209 210 211 212 213 214 215
  size_t sqlLen = strlen(sql);
  if (sqlLen > (size_t)TSDB_MAX_ALLOWED_SQL_LEN) {
    tscError("sql string exceeds max length:%d", TSDB_MAX_ALLOWED_SQL_LEN);
    terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
    return NULL;
  }

  return execQuery(pTscObj, sql, sqlLen);
#endif
216
}
217

218 219
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
  if (res == NULL) {
220 221 222
    return NULL;
  }

L
Liu Jicong 已提交
223 224
  if (TD_RES_QUERY(res)) {
    SRequestObj *pRequest = (SRequestObj *)res;
225 226 227
#if SYNC_ON_TOP_OF_ASYNC
    return doAsyncFetchRows(pRequest, true, true);
#else
L
Liu Jicong 已提交
228 229 230 231
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
      return NULL;
    }
232
    return doFetchRows(pRequest, true, true);
233
#endif
L
Liu Jicong 已提交
234 235

  } else if (TD_RES_TMQ(res)) {
L
Liu Jicong 已提交
236 237 238 239 240 241 242
    SMqRspObj      *msg = ((SMqRspObj *)res);
    SReqResultInfo *pResultInfo;
    if (msg->resIter == -1) {
      pResultInfo = tmqGetNextResInfo(res, true);
    } else {
      pResultInfo = tmqGetCurResInfo(res);
    }
243

L
Liu Jicong 已提交
244
    if (pResultInfo->current < pResultInfo->numOfRows) {
L
Liu Jicong 已提交
245 246
      doSetOneRowPtr(pResultInfo);
      pResultInfo->current += 1;
L
Liu Jicong 已提交
247 248
      return pResultInfo->row;
    } else {
L
Liu Jicong 已提交
249 250 251 252 253
      pResultInfo = tmqGetNextResInfo(res, true);
      if (pResultInfo == NULL) return NULL;
      doSetOneRowPtr(pResultInfo);
      pResultInfo->current += 1;
      return pResultInfo->row;
L
Liu Jicong 已提交
254 255
    }
  } else {
256
    // assert to avoid un-initialization error
L
Liu Jicong 已提交
257 258 259
    ASSERT(0);
  }
  return NULL;
260
}
H
Haojun Liao 已提交
261

L
Liu Jicong 已提交
262
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
H
Haojun Liao 已提交
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
  int32_t len = 0;
  for (int i = 0; i < num_fields; ++i) {
    if (i > 0) {
      str[len++] = ' ';
    }

    if (row[i] == NULL) {
      len += sprintf(str + len, "%s", TSDB_DATA_NULL_STR);
      continue;
    }

    switch (fields[i].type) {
      case TSDB_DATA_TYPE_TINYINT:
        len += sprintf(str + len, "%d", *((int8_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_UTINYINT:
        len += sprintf(str + len, "%u", *((uint8_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_SMALLINT:
        len += sprintf(str + len, "%d", *((int16_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_USMALLINT:
        len += sprintf(str + len, "%u", *((uint16_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_INT:
        len += sprintf(str + len, "%d", *((int32_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_UINT:
        len += sprintf(str + len, "%u", *((uint32_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_BIGINT:
        len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_UBIGINT:
        len += sprintf(str + len, "%" PRIu64, *((uint64_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_FLOAT: {
        float fv = 0;
        fv = GET_FLOAT_VAL(row[i]);
        len += sprintf(str + len, "%f", fv);
      } break;

      case TSDB_DATA_TYPE_DOUBLE: {
        double dv = 0;
        dv = GET_DOUBLE_VAL(row[i]);
        len += sprintf(str + len, "%lf", dv);
      } break;

      case TSDB_DATA_TYPE_BINARY:
      case TSDB_DATA_TYPE_NCHAR: {
L
Liu Jicong 已提交
321
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
H
Haojun Liao 已提交
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
        if (fields[i].type == TSDB_DATA_TYPE_BINARY) {
          assert(charLen <= fields[i].bytes && charLen >= 0);
        } else {
          assert(charLen <= fields[i].bytes * TSDB_NCHAR_SIZE && charLen >= 0);
        }

        memcpy(str + len, row[i], charLen);
        len += charLen;
      } break;

      case TSDB_DATA_TYPE_TIMESTAMP:
        len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
        break;

      case TSDB_DATA_TYPE_BOOL:
        len += sprintf(str + len, "%d", *((int8_t *)row[i]));
      default:
        break;
    }
  }
L
Liu Jicong 已提交
342
  str[len] = 0;
H
Haojun Liao 已提交
343 344 345

  return len;
}
346

L
Liu Jicong 已提交
347
int *taos_fetch_lengths(TAOS_RES *res) {
348 349 350 351
  if (res == NULL) {
    return NULL;
  }

L
Liu Jicong 已提交
352 353
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
  return pResInfo->length;
354 355
}

356
TAOS_ROW *taos_result_block(TAOS_RES *res) {
L
Liu Jicong 已提交
357
  if (res == NULL) {
358 359 360 361 362 363 364 365
    terrno = TSDB_CODE_INVALID_PARA;
    return NULL;
  }

  if (taos_is_update_query(res)) {
    return NULL;
  }

L
Liu Jicong 已提交
366 367
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
  return &pResInfo->row;
368 369
}

370
// todo intergrate with tDataTypes
371 372
const char *taos_data_type(int type) {
  switch (type) {
L
Liu Jicong 已提交
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
    case TSDB_DATA_TYPE_NULL:
      return "TSDB_DATA_TYPE_NULL";
    case TSDB_DATA_TYPE_BOOL:
      return "TSDB_DATA_TYPE_BOOL";
    case TSDB_DATA_TYPE_TINYINT:
      return "TSDB_DATA_TYPE_TINYINT";
    case TSDB_DATA_TYPE_SMALLINT:
      return "TSDB_DATA_TYPE_SMALLINT";
    case TSDB_DATA_TYPE_INT:
      return "TSDB_DATA_TYPE_INT";
    case TSDB_DATA_TYPE_BIGINT:
      return "TSDB_DATA_TYPE_BIGINT";
    case TSDB_DATA_TYPE_FLOAT:
      return "TSDB_DATA_TYPE_FLOAT";
    case TSDB_DATA_TYPE_DOUBLE:
      return "TSDB_DATA_TYPE_DOUBLE";
    case TSDB_DATA_TYPE_VARCHAR:
      return "TSDB_DATA_TYPE_VARCHAR";
      //    case TSDB_DATA_TYPE_BINARY:          return "TSDB_DATA_TYPE_VARCHAR";
    case TSDB_DATA_TYPE_TIMESTAMP:
      return "TSDB_DATA_TYPE_TIMESTAMP";
    case TSDB_DATA_TYPE_NCHAR:
      return "TSDB_DATA_TYPE_NCHAR";
    case TSDB_DATA_TYPE_JSON:
      return "TSDB_DATA_TYPE_JSON";
    default:
      return "UNKNOWN";
400 401
  }
}
402 403 404

const char *taos_get_client_info() { return version; }

X
Xiaoyu Wang 已提交
405
int taos_affected_rows(TAOS_RES *res) {
L
Liu Jicong 已提交
406
  if (res == NULL || TD_RES_TMQ(res)) {
H
Haojun Liao 已提交
407 408 409
    return 0;
  }

L
Liu Jicong 已提交
410 411
  SRequestObj    *pRequest = (SRequestObj *)res;
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
H
Haojun Liao 已提交
412
  return pResInfo->numOfRows;
X
Xiaoyu Wang 已提交
413
}
414

415
int taos_result_precision(TAOS_RES *res) {
L
Liu Jicong 已提交
416
  if (res == NULL) {
H
Haojun Liao 已提交
417 418
    return TSDB_TIME_PRECISION_MILLI;
  }
419

L
Liu Jicong 已提交
420 421 422 423 424 425 426 427
  if (TD_RES_QUERY(res)) {
    SRequestObj *pRequest = (SRequestObj *)res;
    return pRequest->body.resInfo.precision;
  } else if (TD_RES_TMQ(res)) {
    SReqResultInfo *info = tmqGetCurResInfo(res);
    return info->precision;
  }
  return TSDB_TIME_PRECISION_MILLI;
428
}
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444

int taos_select_db(TAOS *taos, const char *db) {
  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL) {
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
  }

  if (db == NULL || strlen(db) == 0) {
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
    return terrno;
  }

  char sql[256] = {0};
  snprintf(sql, tListLen(sql), "use %s", db);

L
Liu Jicong 已提交
445 446
  TAOS_RES *pRequest = taos_query(taos, sql);
  int32_t   code = taos_errno(pRequest);
447 448 449 450 451 452 453 454 455 456

  taos_free_result(pRequest);
  return code;
}

void taos_stop_query(TAOS_RES *res) {
  if (res == NULL) {
    return;
  }

L
Liu Jicong 已提交
457 458
  SRequestObj *pRequest = (SRequestObj *)res;
  int32_t      numOfFields = taos_num_fields(pRequest);
459 460 461 462 463 464

  // It is not a query, no need to stop.
  if (numOfFields == 0) {
    return;
  }

D
dapan1121 已提交
465
  schedulerFreeJob(pRequest->body.queryJob);
466 467 468
}

bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
L
Liu Jicong 已提交
469
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
470 471 472 473
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
    return true;
  }

L
Liu Jicong 已提交
474
  SResultColumn *pCol = &pResultInfo->pCol[col];
475 476 477 478 479
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
    return (pCol->offset[row] == -1);
  } else {
    return colDataIsNull_f(pCol->nullbitmap, row);
  }
480 481
}

L
Liu Jicong 已提交
482
bool taos_is_update_query(TAOS_RES *res) { return taos_num_fields(res) == 0; }
483

L
Liu Jicong 已提交
484
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
H
Haojun Liao 已提交
485
  int32_t numOfRows = 0;
L
Liu Jicong 已提交
486
  /*int32_t code = */ taos_fetch_block_s(res, &numOfRows, rows);
H
Haojun Liao 已提交
487 488 489
  return numOfRows;
}

L
Liu Jicong 已提交
490 491
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
  if (res == NULL) {
492 493
    return 0;
  }
494

L
Liu Jicong 已提交
495 496
  if (TD_RES_QUERY(res)) {
    SRequestObj *pRequest = (SRequestObj *)res;
497

L
Liu Jicong 已提交
498 499
    (*rows) = NULL;
    (*numOfRows) = 0;
H
Haojun Liao 已提交
500

L
Liu Jicong 已提交
501 502 503 504
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
      return 0;
    }
505

506
#if SYNC_ON_TOP_OF_ASYNC
507
    doAsyncFetchRows(pRequest, false, true);
508 509 510
#else
    doFetchRows(pRequest, true, true);
#endif
511

L
Liu Jicong 已提交
512 513 514
    // TODO refactor
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
    pResultInfo->current = pResultInfo->numOfRows;
515

L
Liu Jicong 已提交
516 517 518 519
    (*rows) = pResultInfo->row;
    (*numOfRows) = pResultInfo->numOfRows;
    return pRequest->code;
  } else if (TD_RES_TMQ(res)) {
L
Liu Jicong 已提交
520
    SReqResultInfo *pResultInfo = tmqGetNextResInfo(res, true);
L
Liu Jicong 已提交
521
    if (pResultInfo == NULL) return -1;
H
Haojun Liao 已提交
522

L
Liu Jicong 已提交
523 524 525
    pResultInfo->current = pResultInfo->numOfRows;
    (*rows) = pResultInfo->row;
    (*numOfRows) = pResultInfo->numOfRows;
H
Haojun Liao 已提交
526
    return 0;
L
Liu Jicong 已提交
527 528 529
  } else {
    ASSERT(0);
    return -1;
H
Haojun Liao 已提交
530
  }
L
Liu Jicong 已提交
531
}
H
Haojun Liao 已提交
532

L
Liu Jicong 已提交
533 534
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
  if (res == NULL) {
H
Haojun Liao 已提交
535 536
    return 0;
  }
537

538
  if (TD_RES_TMQ(res)) {
L
Liu Jicong 已提交
539
    SReqResultInfo *pResultInfo = tmqGetNextResInfo(res, false);
L
Liu Jicong 已提交
540 541 542 543
    if (pResultInfo == NULL) {
      (*numOfRows) = 0;
      return 0;
    }
H
Haojun Liao 已提交
544

L
Liu Jicong 已提交
545 546 547 548
    pResultInfo->current = pResultInfo->numOfRows;
    (*numOfRows) = pResultInfo->numOfRows;
    (*pData) = (void *)pResultInfo->pData;
    return 0;
549
  }
L
Liu Jicong 已提交
550

551 552 553 554 555
  SRequestObj *pRequest = (SRequestObj *)res;

  if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
      pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0) {
    return 0;
L
Liu Jicong 已提交
556
  }
557

558 559 560
#if SYNC_ON_TOP_OF_ASYNC
  doAsyncFetchRows(pRequest, false, false);
#else
561
  doFetchRows(pRequest, false, false);
562
#endif
563 564 565 566 567 568 569 570

  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;

  pResultInfo->current = pResultInfo->numOfRows;
  (*numOfRows) = pResultInfo->numOfRows;
  (*pData) = (void *)pResultInfo->pData;

  return 0;
571 572
}

H
Haojun Liao 已提交
573
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
L
Liu Jicong 已提交
574
  if (res == NULL) {
H
Haojun Liao 已提交
575 576 577
    return 0;
  }

L
Liu Jicong 已提交
578
  int32_t numOfFields = taos_num_fields(res);
H
Haojun Liao 已提交
579 580 581 582
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
    return 0;
  }

L
Liu Jicong 已提交
583 584
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
H
Haojun Liao 已提交
585 586 587 588
  if (!IS_VAR_DATA_TYPE(pField->type)) {
    return 0;
  }

L
Liu Jicong 已提交
589
  return pResInfo->pCol[columnIndex].offset;
H
Haojun Liao 已提交
590 591
}

L
Liu Jicong 已提交
592
int taos_validate_sql(TAOS *taos, const char *sql) { return true; }
593

594
void taos_reset_current_db(TAOS *taos) {
H
Haojun Liao 已提交
595 596 597 598 599
  if (taos == NULL) {
    return;
  }

  resetConnectDB(taos);
600 601
}

602 603 604 605 606
const char *taos_get_server_info(TAOS *taos) {
  if (taos == NULL) {
    return NULL;
  }

L
Liu Jicong 已提交
607
  STscObj *pTscObj = (STscObj *)taos;
608 609 610
  return pTscObj->ver;
}

611 612 613 614 615 616 617 618 619 620 621 622
typedef struct SqlParseWrapper {
  SParseContext* pCtx;
  SCatalogReq    catalogReq;
  SRequestObj*   pRequest;
  SQuery*        pQuery;
} SqlParseWrapper;

void retrieveMetaCallback(SMetaData* pResultMeta, void* param, int32_t code) {
  SqlParseWrapper *pWrapper = (SqlParseWrapper*) param;
  SQuery* pQuery = pWrapper->pQuery;
  SRequestObj* pRequest = pWrapper->pRequest;

623 624
  if (code == TSDB_CODE_SUCCESS) {
    code = qAnalyseSqlSemantic(pWrapper->pCtx, &pWrapper->catalogReq, pResultMeta, pQuery);
625 626
  }

627 628 629 630 631
  if (code == TSDB_CODE_SUCCESS) {
    if (pQuery->haveResultSet) {
      setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols);
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
    }
632

633 634
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
635

636 637 638
    taosMemoryFree(pWrapper);
    launchAsyncQuery(pRequest, pQuery);
  } else {
639
    tscDebug("error happens, code:%d", code);
640
    if (NEED_CLIENT_HANDLE_ERROR(code)) {
641 642
      tscDebug("0x%"PRIx64" client retry to handle the error, code:%d - %s, tryCount:%d, reqId:0x%"PRIx64, pRequest->self, code, tstrerror(code),
               pRequest->retry, pRequest->requestId);
643 644 645 646
      pRequest->prevCode = code;
      doAsyncQuery(pRequest, true);
      return;
    }
647

648 649
    // return to app directly
    taosMemoryFree(pWrapper);
H
Haojun Liao 已提交
650
    tscError("0x%" PRIx64 " error occurs, code:%s, return to user app, reqId:0x%" PRIx64, pRequest->self, tstrerror(code),
651 652 653 654
             pRequest->requestId);
    pRequest->code = code;
    pRequest->body.queryFp(pRequest->body.param, pRequest, code);
  }
655 656
}

657
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
658 659
  ASSERT(fp != NULL);

660
  if (taos == NULL || sql == NULL) {
661 662
    terrno = TSDB_CODE_INVALID_PARA;
    fp(param, NULL, terrno);
663 664 665
    return;
  }

666 667 668 669 670 671
  size_t sqlLen = strlen(sql);
  if (sqlLen > (size_t)TSDB_MAX_ALLOWED_SQL_LEN) {
    tscError("sql string exceeds max length:%d", TSDB_MAX_ALLOWED_SQL_LEN);
    terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;

    fp(param, NULL, terrno);
672 673 674
    return;
  }

675
  SRequestObj *pRequest = NULL;
676
  int32_t code = buildRequest(taos, sql, sqlLen, &pRequest);
677 678
  if (code != TSDB_CODE_SUCCESS) {
    terrno = code;
679
    fp(param, NULL, terrno);
680 681
    return;
  }
682

683 684
  pRequest->body.queryFp = fp;
  pRequest->body.param   = param;
685 686
  doAsyncQuery(pRequest, false);
}
687

688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
int32_t createParseContext(const SRequestObj *pRequest, SParseContext** pCxt) {
  const STscObj *pTscObj = pRequest->pTscObj;

  *pCxt = taosMemoryCalloc(1, sizeof(SParseContext));
  if (*pCxt == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  **pCxt = (SParseContext){.requestId = pRequest->requestId,
                       .acctId = pTscObj->acctId,
                       .db = pRequest->pDb,
                       .topicQuery = false,
                       .pSql = pRequest->sqlstr,
                       .sqlLen = pRequest->sqlLen,
                       .pMsg = pRequest->msgBuf,
                       .msgLen = ERROR_MSG_BUF_DEFAULT_SIZE,
                       .pTransporter = pTscObj->pAppInfo->pTransporter,
                       .pStmtCb = NULL,
                       .pUser = pTscObj->user,
707
                       .schemalessType = pTscObj->schemalessType,
708 709 710 711 712 713
                       .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
                       .async = true,};
  return TSDB_CODE_SUCCESS;
}

void doAsyncQuery(SRequestObj* pRequest, bool updateMetaForce) {
714
  SParseContext* pCxt = NULL;
715
  STscObj *pTscObj = pRequest->pTscObj;
716
  int32_t code = 0;
717 718

  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
719
    code = pRequest->prevCode;
720 721 722
    goto _error;
  }

723
  code = createParseContext(pRequest, &pCxt);
724 725 726
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
727 728 729 730 731

  pCxt->mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
  code = catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCxt->pCatalog);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
732 733
  }

734 735
  SQuery *pQuery = NULL;

736
  SCatalogReq catalogReq = {.forceUpdate = updateMetaForce};
737 738 739 740 741 742
  code = qParseSqlSyntax(pCxt, &pQuery, &catalogReq);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  SqlParseWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SqlParseWrapper));
743
  if (pWrapper == NULL) {
744
    code = TSDB_CODE_OUT_OF_MEMORY;
745 746 747
    goto _error;
  }

748 749 750 751 752
  pWrapper->pCtx = pCxt;
  pWrapper->pQuery = pQuery;
  pWrapper->pRequest = pRequest;
  pWrapper->catalogReq = catalogReq;

753
  code = catalogAsyncGetAllMeta(pCxt->pCatalog, pCxt->pTransporter, &pCxt->mgmtEpSet, pRequest->requestId,
754 755 756
                                &catalogReq, retrieveMetaCallback, pWrapper, &pRequest->body.queryJob);
  if (code == TSDB_CODE_SUCCESS) {
    return;
757 758
  }

759
  _error:
760
  tscError("0x%"PRIx64" error happens, code:%d - %s, reqId:0x%"PRIx64, pRequest->self, code, tstrerror(code), pRequest->requestId);
761 762
  terrno = code;
  pRequest->code = code;
763
  pRequest->body.queryFp(pRequest->body.param, pRequest, code);
764 765
}

766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
static void fetchCallback(void* pResult, void* param, int32_t code) {
  SRequestObj* pRequest = (SRequestObj*) param;

  SReqResultInfo* pResultInfo = &pRequest->body.resInfo;

  pResultInfo->pData = pResult;
  pResultInfo->numOfRows = 0;

  if (code != TSDB_CODE_SUCCESS) {
    pRequest->code = code;
    pRequest->body.fetchFp(pRequest->body.param, pRequest, 0);
    return;
  }

  if (pRequest->code != TSDB_CODE_SUCCESS) {
    pRequest->body.fetchFp(pRequest->body.param, pRequest, 0);
782
    return;
783 784
  }

785
  pRequest->code = setQueryResultFromRsp(pResultInfo, (SRetrieveTableRsp*)pResultInfo->pData, pResultInfo->convertUcs4, false);
786 787 788
  if (pRequest->code != TSDB_CODE_SUCCESS) {
    pResultInfo->numOfRows = 0;
    pRequest->code = code;
789 790 791 792 793 794
    tscError("0x%" PRIx64 " fetch results failed, code:%s, reqId:0x%" PRIx64, pRequest->self, tstrerror(code),
             pRequest->requestId);
  } else {
    tscDebug("0x%" PRIx64 " fetch results, numOfRows:%d total Rows:%" PRId64 ", complete:%d, reqId:0x%" PRIx64,
             pRequest->self, pResultInfo->numOfRows, pResultInfo->totalRows, pResultInfo->completed,
             pRequest->requestId);
795 796 797 798 799
  }

  pRequest->body.fetchFp(pRequest->body.param, pRequest, pResultInfo->numOfRows);
}

800
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
  ASSERT (res != NULL && fp != NULL);

  SRequestObj *pRequest = res;
  pRequest->body.fetchFp = fp;

  SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
  if (taos_num_fields(pRequest) == 0) {
    pResultInfo->numOfRows = 0;
    pRequest->body.fetchFp(param, pRequest, pResultInfo->numOfRows);
    return;
  }

  if (pResultInfo->pData == NULL || pResultInfo->current >= pResultInfo->numOfRows) {
    // All data has returned to App already, no need to try again
    if (pResultInfo->completed) {
      pResultInfo->numOfRows = 0;
      pRequest->body.fetchFp(param, pRequest, pResultInfo->numOfRows);
      return;
    }
  }

822
  schedulerAsyncFetchRows(pRequest->body.queryJob, fetchCallback, pRequest);
L
Liu Jicong 已提交
823
}
824

825 826 827 828 829 830 831
void taos_fetch_raw_block_a(TAOS_RES* res, __taos_async_fn_t fp, void* param) {
  ASSERT(res != NULL && fp != NULL);
  SRequestObj *pRequest = res;
  pRequest->body.resInfo.convertUcs4 = false;
  taos_fetch_rows_a(res, fp, param);
}

L
Liu Jicong 已提交
832 833 834 835
TAOS_SUB *taos_subscribe(TAOS *taos, int restart, const char *topic, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp,
                         void *param, int interval) {
  // TODO
  return NULL;
836 837 838
}

TAOS_RES *taos_consume(TAOS_SUB *tsub) {
L
Liu Jicong 已提交
839 840
  // TODO
  return NULL;
841 842 843
}

void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress) {
L
Liu Jicong 已提交
844
  // TODO
845 846
}

847 848 849 850 851
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
  // TODO
  return -1;
}

L
Liu Jicong 已提交
852
TAOS_STMT *taos_stmt_init(TAOS *taos) {
D
stmt  
dapan1121 已提交
853
  if (taos == NULL) {
D
stmt  
dapan1121 已提交
854
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
855 856 857 858 859
    terrno = TSDB_CODE_INVALID_PARA;
    return NULL;
  }

  return stmtInit(taos);
860 861
}

D
stmt  
dapan1121 已提交
862 863
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
  if (stmt == NULL || sql == NULL) {
D
stmt  
dapan1121 已提交
864
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
865 866 867 868
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
869
  return stmtPrepare(stmt, sql, length);
870 871
}

D
dapan1121 已提交
872
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
D
stmt  
dapan1121 已提交
873
  if (stmt == NULL || name == NULL) {
D
stmt  
dapan1121 已提交
874
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
875 876 877 878
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
879 880 881 882 883 884 885 886 887 888
  int32_t code = stmtSetTbName(stmt, name);
  if (code) {
    return code;
  }

  if (tags) {
    return stmtSetTbTags(stmt, tags);
  }

  return TSDB_CODE_SUCCESS;
889 890
}

D
stmt  
dapan1121 已提交
891 892
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
  if (stmt == NULL || name == NULL) {
D
stmt  
dapan1121 已提交
893
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
894
    terrno = TSDB_CODE_INVALID_PARA;
D
stmt  
dapan1121 已提交
895
    return terrno;
D
stmt  
dapan1121 已提交
896 897
  }

D
stmt  
dapan1121 已提交
898
  return stmtSetTbName(stmt, name);
899 900
}

D
dapan1121 已提交
901 902 903 904 905 906 907 908 909 910 911
int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) {
  if (stmt == NULL || tags == NULL) {
    tscError("NULL parameter for %s", __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

  return stmtSetTbTags(stmt, tags);
}


912
int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name) { return taos_stmt_set_tbname(stmt, name); }
D
dapan1121 已提交
913

D
dapan1121 已提交
914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields) {
  if (stmt == NULL || NULL == fieldNum) {
    tscError("NULL parameter for %s", __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
  
  return stmtGetTagFields(stmt, fieldNum, fields);
}

int taos_stmt_get_col_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields) {
  if (stmt == NULL || NULL == fieldNum) {
    tscError("NULL parameter for %s", __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
  
  return stmtGetColFields(stmt, fieldNum, fields);
}

D
dapan1121 已提交
934
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
D
stmt  
dapan1121 已提交
935
  if (stmt == NULL || bind == NULL) {
D
stmt  
dapan1121 已提交
936
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
937
    terrno = TSDB_CODE_INVALID_PARA;
D
stmt  
dapan1121 已提交
938
    return terrno;
D
stmt  
dapan1121 已提交
939
  }
940

D
stmt  
dapan1121 已提交
941 942 943 944 945
  if (bind->num > 1) {
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
946

D
stmt  
dapan1121 已提交
947
  return stmtBindBatch(stmt, bind, -1);
948 949
}

D
dapan1121 已提交
950
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
D
stmt  
dapan1121 已提交
951
  if (stmt == NULL || bind == NULL) {
D
stmt  
dapan1121 已提交
952
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
953 954 955 956
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
957 958
  if (bind->num <= 0 || bind->num > INT16_MAX) {
    tscError("invalid bind num %d", bind->num);
D
stmt  
dapan1121 已提交
959 960 961 962
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
dapan1121 已提交
963 964 965 966 967 968 969 970
  int32_t insert = 0;
  stmtIsInsert(stmt, &insert);
  if (0 == insert && bind->num > 1) {
    tscError("only one row data allowed for query");
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
971
  return stmtBindBatch(stmt, bind, -1);
972 973
}

D
dapan1121 已提交
974
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
D
stmt  
dapan1121 已提交
975
  if (stmt == NULL || bind == NULL) {
D
stmt  
dapan1121 已提交
976
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
977 978 979 980
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
981
  if (colIdx < 0) {
D
stmt  
dapan1121 已提交
982 983 984 985
    tscError("invalid bind column idx %d", colIdx);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
D
dapan1121 已提交
986 987 988 989 990 991 992 993

  int32_t insert = 0;
  stmtIsInsert(stmt, &insert);
  if (0 == insert && bind->num > 1) {
    tscError("only one row data allowed for query");
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
994

D
stmt  
dapan1121 已提交
995
  return stmtBindBatch(stmt, bind, colIdx);
996 997
}

D
stmt  
dapan1121 已提交
998 999
int taos_stmt_add_batch(TAOS_STMT *stmt) {
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1000
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1001 1002 1003 1004
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
1005
  return stmtAddBatch(stmt);
1006 1007
}

D
stmt  
dapan1121 已提交
1008 1009
int taos_stmt_execute(TAOS_STMT *stmt) {
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1010
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1011 1012 1013 1014
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
1015
  return stmtExec(stmt);
1016 1017
}

1018
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
D
stmt  
dapan1121 已提交
1019
  if (stmt == NULL || insert == NULL) {
D
stmt  
dapan1121 已提交
1020
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1021 1022 1023 1024 1025
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

  return stmtIsInsert(stmt, insert);
1026 1027
}

1028
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
D
stmt  
dapan1121 已提交
1029
  if (stmt == NULL || nums == NULL) {
D
stmt  
dapan1121 已提交
1030
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1031 1032 1033 1034 1035
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

  return stmtGetParamNum(stmt, nums);
1036 1037
}

D
dapan1121 已提交
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
  if (stmt == NULL || type == NULL || NULL == bytes || idx < 0) {
    tscError("invalid parameter for %s", __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

  return stmtGetParam(stmt, idx, type, bytes);
}

D
stmt  
dapan1121 已提交
1048
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
D
stmt  
dapan1121 已提交
1049
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1050
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1051
    terrno = TSDB_CODE_INVALID_PARA;
D
stmt  
dapan1121 已提交
1052
    return NULL;
D
stmt  
dapan1121 已提交
1053 1054
  }

D
stmt  
dapan1121 已提交
1055
  return stmtUseResult(stmt);
1056 1057
}

1058
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
1059

D
stmt  
dapan1121 已提交
1060
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
D
stmt  
dapan1121 已提交
1061
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1062
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1063
    terrno = TSDB_CODE_INVALID_PARA;
D
stmt  
dapan1121 已提交
1064
    return 0;
D
stmt  
dapan1121 已提交
1065 1066
  }

D
stmt  
dapan1121 已提交
1067
  return stmtAffectedRows(stmt);
1068 1069
}

D
dapan1121 已提交
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
int taos_stmt_affected_rows_once(TAOS_STMT *stmt) {
  if (stmt == NULL) {
    tscError("NULL parameter for %s", __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return 0;
  }

  return stmtAffectedRowsOnce(stmt);
}

D
stmt  
dapan1121 已提交
1080 1081
int taos_stmt_close(TAOS_STMT *stmt) {
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1082
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1083 1084 1085 1086
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
1087
  return stmtClose(stmt);
D
stmt  
dapan1121 已提交
1088 1089
}