clientMain.c 32.0 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 "functionMgt.h"
L
Liu Jicong 已提交
21
#include "os.h"
H
Haojun Liao 已提交
22
#include "query.h"
L
Liu Jicong 已提交
23
#include "scheduler.h"
24
#include "tglobal.h"
L
Liu Jicong 已提交
25 26 27
#include "tmsg.h"
#include "tref.h"
#include "trpc.h"
S
version  
Shengliang Guan 已提交
28
#include "version.h"
29 30 31 32 33

#define TSC_VAR_NOT_RELEASE 1
#define TSC_VAR_RELEASED    0

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

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 已提交
46
  int ret = taos_options_imp(option, (const char *)arg);
47 48 49 50 51 52
  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 已提交
53
  tscInfo("start to cleanup client environment");
54 55 56 57 58

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

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

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

X
Xiaoyu Wang 已提交
65 66 67
  fmFuncMgtDestroy();
  qCleanupKeywordsTable();

68 69
  id = clientConnRefPool;
  clientConnRefPool = -1;
70 71
  taosCloseRef(id);

72 73
  hbMgrCleanUp();

D
dapan1121 已提交
74
  catalogDestroy();
D
dapan1121 已提交
75
  schedulerDestroy();
H
Haojun Liao 已提交
76

D
dapan1121 已提交
77 78
  rpcCleanup();

H
Haojun Liao 已提交
79
  tscInfo("all local resources released");
80
  taosCleanupCfg();
81
  taosCloseLog();
82 83
}

L
Liu Jicong 已提交
84
setConfRet taos_set_config(const char *config) {
85 86 87 88 89
  // TODO
  setConfRet ret = {SET_CONF_RET_SUCC, {0}};
  return ret;
}

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

H
Haojun Liao 已提交
96 97 98
  if (pass == NULL) {
    pass = TSDB_DEFAULT_PASS;
  }
99

L
Liu Jicong 已提交
100
  STscObj *pObj = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY);
101
  if (pObj) {
D
dapan1121 已提交
102
    return pObj->id;
103
  }
L
Liu Jicong 已提交
104

D
dapan1121 已提交
105
  return NULL;
106 107
}

108
void taos_close_internal(void *taos) {
109 110 111 112
  if (taos == NULL) {
    return;
  }

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

L
Liu Jicong 已提交
116
  taosRemoveRef(clientConnRefPool, *(int64_t *)pTscObj->id);
117 118
}

119
void taos_close(TAOS *taos) {
D
dapan1121 已提交
120 121 122
  if (taos == NULL) {
    return;
  }
L
Liu Jicong 已提交
123 124

  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
125 126 127
  if (NULL == pObj) {
    return;
  }
L
Liu Jicong 已提交
128

129
  taos_close_internal(pObj);
L
Liu Jicong 已提交
130
  releaseTscObj(*(int64_t *)taos);
D
dapan1121 已提交
131
  taosMemoryFree(taos);
132 133
}

L
Liu Jicong 已提交
134 135
int taos_errno(TAOS_RES *res) {
  if (res == NULL || TD_RES_TMQ_META(res)) {
136 137 138
    return terrno;
  }

L
Liu Jicong 已提交
139
  if (TD_RES_TMQ(res)) {
140 141 142
    return 0;
  }

L
Liu Jicong 已提交
143
  return ((SRequestObj *)res)->code;
144 145
}

146
const char *taos_errstr(TAOS_RES *res) {
L
Liu Jicong 已提交
147
  if (res == NULL || TD_RES_TMQ_META(res)) {
L
Liu Jicong 已提交
148
    return (const char *)tstrerror(terrno);
149 150
  }

151 152 153 154 155
  if (TD_RES_TMQ(res)) {
    return "success";
  }

  SRequestObj *pRequest = (SRequestObj *)res;
156
  if (NULL != pRequest->msgBuf && (strlen(pRequest->msgBuf) > 0 || pRequest->code == TSDB_CODE_RPC_FQDN_ERROR)) {
157 158
    return pRequest->msgBuf;
  } else {
L
Liu Jicong 已提交
159
    return (const char *)tstrerror(pRequest->code);
160
  }
161 162 163
}

void taos_free_result(TAOS_RES *res) {
D
stmt  
dapan1121 已提交
164 165 166
  if (NULL == res) {
    return;
  }
167

L
Liu Jicong 已提交
168 169 170
  if (TD_RES_QUERY(res)) {
    SRequestObj *pRequest = (SRequestObj *)res;
    destroyRequest(pRequest);
L
Liu Jicong 已提交
171 172 173 174 175 176
  } 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 已提交
177 178
    if (pRsp->rsp.withTbName) taosArrayDestroyP(pRsp->rsp.blockTbName, taosMemoryFree);
    if (pRsp->rsp.withSchema) taosArrayDestroyP(pRsp->rsp.blockSchema, (FDelete)tDeleteSSchemaWrapper);
L
Liu Jicong 已提交
179 180
    pRsp->resInfo.pRspMsg = NULL;
    doFreeReqResultInfo(&pRsp->resInfo);
L
Liu Jicong 已提交
181 182 183 184
  } else if (TD_RES_TMQ_META(res)) {
    SMqMetaRspObj *pRspObj = (SMqMetaRspObj *)res;
    taosMemoryFree(pRspObj->metaRsp.metaRsp);
    taosMemoryFree(pRspObj);
L
Liu Jicong 已提交
185
  }
186 187
}

L
Liu Jicong 已提交
188
int taos_field_count(TAOS_RES *res) {
L
Liu Jicong 已提交
189
  if (res == NULL || TD_RES_TMQ_META(res)) {
H
Haojun Liao 已提交
190 191 192
    return 0;
  }

L
Liu Jicong 已提交
193
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
H
Haojun Liao 已提交
194 195 196
  return pResInfo->numOfCols;
}

L
Liu Jicong 已提交
197
int taos_num_fields(TAOS_RES *res) { return taos_field_count(res); }
H
Haojun Liao 已提交
198 199

TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
L
Liu Jicong 已提交
200
  if (taos_num_fields(res) == 0 || TD_RES_TMQ_META(res)) {
H
Haojun Liao 已提交
201 202 203
    return NULL;
  }

L
Liu Jicong 已提交
204
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
205
  return pResInfo->userFields;
H
Haojun Liao 已提交
206 207
}

208 209
static void syncQueryFn(void *param, void *res, int32_t code) {
  SSyncQueryParam *pParam = param;
210 211 212 213 214 215
  pParam->pRequest = res;
  pParam->pRequest->code = code;

  tsem_post(&pParam->sem);
}

216
TAOS_RES *taos_query(TAOS *taos, const char *sql) {
D
dapan1121 已提交
217 218 219 220
  if (NULL == taos) {
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return NULL;
  }
L
Liu Jicong 已提交
221 222

  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
223 224
  if (pTscObj == NULL || sql == NULL) {
    terrno = TSDB_CODE_TSC_DISCONNECTED;
225 226 227
    return NULL;
  }

228
#if SYNC_ON_TOP_OF_ASYNC
229
  SSyncQueryParam *param = taosMemoryCalloc(1, sizeof(SSyncQueryParam));
230 231
  tsem_init(&param->sem, 0, 0);

232
  taos_query_a(taos, sql, syncQueryFn, param);
233 234
  tsem_wait(&param->sem);

L
Liu Jicong 已提交
235
  releaseTscObj(*(int64_t *)taos);
236

237 238
  return param->pRequest;
#else
239 240
  size_t sqlLen = strlen(sql);
  if (sqlLen > (size_t)TSDB_MAX_ALLOWED_SQL_LEN) {
L
Liu Jicong 已提交
241
    releaseTscObj(*(int64_t *)taos);
242 243 244 245 246
    tscError("sql string exceeds max length:%d", TSDB_MAX_ALLOWED_SQL_LEN);
    terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
    return NULL;
  }

L
Liu Jicong 已提交
247
  TAOS_RES *pRes = execQuery(pTscObj, sql, sqlLen);
248

L
Liu Jicong 已提交
249
  releaseTscObj(*(int64_t *)taos);
250 251

  return pRes;
252
#endif
253
}
254

255 256
TAOS_ROW taos_fetch_row(TAOS_RES *res) {
  if (res == NULL) {
257 258 259
    return NULL;
  }

L
Liu Jicong 已提交
260 261 262
  if (TD_RES_QUERY(res)) {
    SRequestObj *pRequest = (SRequestObj *)res;
    if (pRequest->type == TSDB_SQL_RETRIEVE_EMPTY_RESULT || pRequest->type == TSDB_SQL_INSERT ||
D
dapan1121 已提交
263
        pRequest->code != TSDB_CODE_SUCCESS || taos_num_fields(res) == 0 || pRequest->killed) {
L
Liu Jicong 已提交
264 265
      return NULL;
    }
D
dapan1121 已提交
266 267 268 269

#if SYNC_ON_TOP_OF_ASYNC
    return doAsyncFetchRows(pRequest, true, true);
#else
270
    return doFetchRows(pRequest, true, true);
271
#endif
L
Liu Jicong 已提交
272 273

  } else if (TD_RES_TMQ(res)) {
L
Liu Jicong 已提交
274 275 276 277 278 279 280
    SMqRspObj      *msg = ((SMqRspObj *)res);
    SReqResultInfo *pResultInfo;
    if (msg->resIter == -1) {
      pResultInfo = tmqGetNextResInfo(res, true);
    } else {
      pResultInfo = tmqGetCurResInfo(res);
    }
281

L
Liu Jicong 已提交
282
    if (pResultInfo->current < pResultInfo->numOfRows) {
L
Liu Jicong 已提交
283 284
      doSetOneRowPtr(pResultInfo);
      pResultInfo->current += 1;
L
Liu Jicong 已提交
285 286
      return pResultInfo->row;
    } else {
L
Liu Jicong 已提交
287 288 289 290 291
      pResultInfo = tmqGetNextResInfo(res, true);
      if (pResultInfo == NULL) return NULL;
      doSetOneRowPtr(pResultInfo);
      pResultInfo->current += 1;
      return pResultInfo->row;
L
Liu Jicong 已提交
292 293
    }
  } else {
294
    // assert to avoid un-initialization error
L
Liu Jicong 已提交
295 296 297
    ASSERT(0);
  }
  return NULL;
298
}
H
Haojun Liao 已提交
299

L
Liu Jicong 已提交
300
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
H
Haojun Liao 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
  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 已提交
359
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
H
Haojun Liao 已提交
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
        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 已提交
380
  str[len] = 0;
H
Haojun Liao 已提交
381 382 383

  return len;
}
384

L
Liu Jicong 已提交
385
int *taos_fetch_lengths(TAOS_RES *res) {
L
Liu Jicong 已提交
386
  if (res == NULL || TD_RES_TMQ_META(res)) {
387 388 389
    return NULL;
  }

L
Liu Jicong 已提交
390 391
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
  return pResInfo->length;
392 393
}

394
TAOS_ROW *taos_result_block(TAOS_RES *res) {
L
Liu Jicong 已提交
395
  if (res == NULL || TD_RES_TMQ_META(res)) {
396 397 398 399 400 401 402 403
    terrno = TSDB_CODE_INVALID_PARA;
    return NULL;
  }

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

L
Liu Jicong 已提交
404 405
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
  return &pResInfo->row;
406 407
}

408
// todo intergrate with tDataTypes
409 410
const char *taos_data_type(int type) {
  switch (type) {
L
Liu Jicong 已提交
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
    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";
438 439
  }
}
440 441 442

const char *taos_get_client_info() { return version; }

X
Xiaoyu Wang 已提交
443
int taos_affected_rows(TAOS_RES *res) {
L
Liu Jicong 已提交
444
  if (res == NULL || TD_RES_TMQ(res) || TD_RES_TMQ_META(res)) {
H
Haojun Liao 已提交
445 446 447
    return 0;
  }

L
Liu Jicong 已提交
448 449
  SRequestObj    *pRequest = (SRequestObj *)res;
  SReqResultInfo *pResInfo = &pRequest->body.resInfo;
H
Haojun Liao 已提交
450
  return pResInfo->numOfRows;
X
Xiaoyu Wang 已提交
451
}
452

453
int taos_result_precision(TAOS_RES *res) {
L
Liu Jicong 已提交
454
  if (res == NULL || TD_RES_TMQ_META(res)) {
H
Haojun Liao 已提交
455 456
    return TSDB_TIME_PRECISION_MILLI;
  }
457

L
Liu Jicong 已提交
458 459 460 461 462 463 464 465
  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;
466
}
467 468

int taos_select_db(TAOS *taos, const char *db) {
L
Liu Jicong 已提交
469
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
470
  if (pObj == NULL) {
L
Liu Jicong 已提交
471
    releaseTscObj(*(int64_t *)taos);
472 473 474 475 476
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
  }

  if (db == NULL || strlen(db) == 0) {
L
Liu Jicong 已提交
477
    releaseTscObj(*(int64_t *)taos);
478 479 480 481 482 483 484
    terrno = TSDB_CODE_TSC_INVALID_INPUT;
    return terrno;
  }

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

L
Liu Jicong 已提交
485 486
  TAOS_RES *pRequest = taos_query(taos, sql);
  int32_t   code = taos_errno(pRequest);
487 488

  taos_free_result(pRequest);
L
Liu Jicong 已提交
489
  releaseTscObj(*(int64_t *)taos);
490 491 492 493
  return code;
}

void taos_stop_query(TAOS_RES *res) {
L
Liu Jicong 已提交
494
  if (res == NULL || TD_RES_TMQ(res) || TD_RES_TMQ_META(res)) {
495 496 497
    return;
  }

L
Liu Jicong 已提交
498
  SRequestObj *pRequest = (SRequestObj *)res;
D
dapan1121 已提交
499
  pRequest->killed = true;
L
Liu Jicong 已提交
500 501

  int32_t numOfFields = taos_num_fields(pRequest);
502 503
  // It is not a query, no need to stop.
  if (numOfFields == 0) {
D
dapan1121 已提交
504
    tscDebug("request %" PRIx64 " no need to be killed since not query", pRequest->requestId);
505 506 507
    return;
  }

D
dapan1121 已提交
508 509 510 511 512
  if (pRequest->body.queryJob) {
    schedulerFreeJob(pRequest->body.queryJob, TSDB_CODE_TSC_QUERY_KILLED);
  }

  tscDebug("request %" PRIx64 " killed", pRequest->requestId);
513 514 515
}

bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) {
L
Liu Jicong 已提交
516 517 518
  if (res == NULL || TD_RES_TMQ_META(res)) {
    return true;
  }
L
Liu Jicong 已提交
519
  SReqResultInfo *pResultInfo = tscGetCurResInfo(res);
520 521 522 523
  if (col >= pResultInfo->numOfCols || col < 0 || row >= pResultInfo->numOfRows || row < 0) {
    return true;
  }

L
Liu Jicong 已提交
524
  SResultColumn *pCol = &pResultInfo->pCol[col];
525 526 527 528 529
  if (IS_VAR_DATA_TYPE(pResultInfo->fields[col].type)) {
    return (pCol->offset[row] == -1);
  } else {
    return colDataIsNull_f(pCol->nullbitmap, row);
  }
530 531
}

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

L
Liu Jicong 已提交
534
int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
H
Haojun Liao 已提交
535
  int32_t numOfRows = 0;
L
Liu Jicong 已提交
536
  /*int32_t code = */ taos_fetch_block_s(res, &numOfRows, rows);
H
Haojun Liao 已提交
537 538 539
  return numOfRows;
}

L
Liu Jicong 已提交
540
int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) {
L
Liu Jicong 已提交
541
  if (res == NULL || TD_RES_TMQ_META(res)) {
542 543
    return 0;
  }
544

L
Liu Jicong 已提交
545 546
  if (TD_RES_QUERY(res)) {
    SRequestObj *pRequest = (SRequestObj *)res;
547

L
Liu Jicong 已提交
548 549
    (*rows) = NULL;
    (*numOfRows) = 0;
H
Haojun Liao 已提交
550

L
Liu Jicong 已提交
551 552 553 554
    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;
    }
555

556
#if SYNC_ON_TOP_OF_ASYNC
557
    doAsyncFetchRows(pRequest, false, true);
558 559 560
#else
    doFetchRows(pRequest, true, true);
#endif
561

L
Liu Jicong 已提交
562 563 564
    // TODO refactor
    SReqResultInfo *pResultInfo = &pRequest->body.resInfo;
    pResultInfo->current = pResultInfo->numOfRows;
565

L
Liu Jicong 已提交
566 567 568 569
    (*rows) = pResultInfo->row;
    (*numOfRows) = pResultInfo->numOfRows;
    return pRequest->code;
  } else if (TD_RES_TMQ(res)) {
L
Liu Jicong 已提交
570
    SReqResultInfo *pResultInfo = tmqGetNextResInfo(res, true);
L
Liu Jicong 已提交
571
    if (pResultInfo == NULL) return -1;
H
Haojun Liao 已提交
572

L
Liu Jicong 已提交
573 574 575
    pResultInfo->current = pResultInfo->numOfRows;
    (*rows) = pResultInfo->row;
    (*numOfRows) = pResultInfo->numOfRows;
H
Haojun Liao 已提交
576
    return 0;
L
Liu Jicong 已提交
577 578 579
  } else {
    ASSERT(0);
    return -1;
H
Haojun Liao 已提交
580
  }
L
Liu Jicong 已提交
581
}
H
Haojun Liao 已提交
582

L
Liu Jicong 已提交
583
int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) {
L
Liu Jicong 已提交
584
  if (res == NULL || TD_RES_TMQ_META(res)) {
H
Haojun Liao 已提交
585 586
    return 0;
  }
587

588
  if (TD_RES_TMQ(res)) {
L
Liu Jicong 已提交
589
    SReqResultInfo *pResultInfo = tmqGetNextResInfo(res, false);
L
Liu Jicong 已提交
590 591 592 593
    if (pResultInfo == NULL) {
      (*numOfRows) = 0;
      return 0;
    }
H
Haojun Liao 已提交
594

L
Liu Jicong 已提交
595 596 597 598
    pResultInfo->current = pResultInfo->numOfRows;
    (*numOfRows) = pResultInfo->numOfRows;
    (*pData) = (void *)pResultInfo->pData;
    return 0;
599
  }
L
Liu Jicong 已提交
600

601 602 603 604 605
  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 已提交
606
  }
607

608 609 610
#if SYNC_ON_TOP_OF_ASYNC
  doAsyncFetchRows(pRequest, false, false);
#else
611
  doFetchRows(pRequest, false, false);
612
#endif
613 614 615 616 617 618 619 620

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

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

  return 0;
621 622
}

H
Haojun Liao 已提交
623
int *taos_get_column_data_offset(TAOS_RES *res, int columnIndex) {
L
Liu Jicong 已提交
624
  if (res == NULL || TD_RES_TMQ_META(res)) {
H
Haojun Liao 已提交
625 626 627
    return 0;
  }

L
Liu Jicong 已提交
628
  int32_t numOfFields = taos_num_fields(res);
H
Haojun Liao 已提交
629 630 631 632
  if (columnIndex < 0 || columnIndex >= numOfFields || numOfFields == 0) {
    return 0;
  }

L
Liu Jicong 已提交
633 634
  SReqResultInfo *pResInfo = tscGetCurResInfo(res);
  TAOS_FIELD     *pField = &pResInfo->userFields[columnIndex];
H
Haojun Liao 已提交
635 636 637 638
  if (!IS_VAR_DATA_TYPE(pField->type)) {
    return 0;
  }

L
Liu Jicong 已提交
639
  return pResInfo->pCol[columnIndex].offset;
H
Haojun Liao 已提交
640 641
}

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

644
void taos_reset_current_db(TAOS *taos) {
L
Liu Jicong 已提交
645
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
646 647
  if (pTscObj == NULL) {
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
Haojun Liao 已提交
648 649 650
    return;
  }

651 652
  resetConnectDB(pTscObj);

L
Liu Jicong 已提交
653
  releaseTscObj(*(int64_t *)taos);
654 655
}

656
const char *taos_get_server_info(TAOS *taos) {
L
Liu Jicong 已提交
657
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
658 659
  if (pTscObj == NULL) {
    terrno = TSDB_CODE_TSC_DISCONNECTED;
660 661 662
    return NULL;
  }

L
Liu Jicong 已提交
663
  releaseTscObj(*(int64_t *)taos);
664

665 666 667
  return pTscObj->ver;
}

668
typedef struct SqlParseWrapper {
669
  SParseContext *pCtx;
670
  SCatalogReq    catalogReq;
671 672
  SRequestObj   *pRequest;
  SQuery        *pQuery;
673 674
} SqlParseWrapper;

675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
static void destorySqlParseWrapper(SqlParseWrapper *pWrapper) {
  taosArrayDestroy(pWrapper->catalogReq.pDbVgroup);
  taosArrayDestroy(pWrapper->catalogReq.pDbCfg);
  taosArrayDestroy(pWrapper->catalogReq.pDbInfo);
  taosArrayDestroy(pWrapper->catalogReq.pTableMeta);
  taosArrayDestroy(pWrapper->catalogReq.pTableHash);
  taosArrayDestroy(pWrapper->catalogReq.pUdf);
  taosArrayDestroy(pWrapper->catalogReq.pIndex);
  taosArrayDestroy(pWrapper->catalogReq.pUser);
  taosArrayDestroy(pWrapper->catalogReq.pTableIndex);
  taosMemoryFree(pWrapper->pCtx);
  taosMemoryFree(pWrapper);
}

void retrieveMetaCallback(SMetaData *pResultMeta, void *param, int32_t code) {
D
dapan1121 已提交
690
  tscDebug("enter meta callback, code %s", tstrerror(code));
L
Liu Jicong 已提交
691

692 693 694
  SqlParseWrapper *pWrapper = (SqlParseWrapper *)param;
  SQuery          *pQuery = pWrapper->pQuery;
  SRequestObj     *pRequest = pWrapper->pRequest;
695

696 697
  if (code == TSDB_CODE_SUCCESS) {
    code = qAnalyseSqlSemantic(pWrapper->pCtx, &pWrapper->catalogReq, pResultMeta, pQuery);
698
    pRequest->stableQuery = pQuery->stableQuery;
699 700
  }

701 702 703 704 705
  if (code == TSDB_CODE_SUCCESS) {
    if (pQuery->haveResultSet) {
      setResSchemaInfo(&pRequest->body.resInfo, pQuery->pResSchema, pQuery->numOfResCols);
      setResPrecision(&pRequest->body.resInfo, pQuery->precision);
    }
706

707 708
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
709

710
    destorySqlParseWrapper(pWrapper);
D
dapan1121 已提交
711
    launchAsyncQuery(pRequest, pQuery, pResultMeta);
712
  } else {
713
    destorySqlParseWrapper(pWrapper);
714
    tscDebug("error happens, code:%d", code);
715
    if (NEED_CLIENT_HANDLE_ERROR(code)) {
716 717
      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);
718 719 720 721
      pRequest->prevCode = code;
      doAsyncQuery(pRequest, true);
      return;
    }
722

723
    // return to app directly
724 725
    tscError("0x%" PRIx64 " error occurs, code:%s, return to user app, reqId:0x%" PRIx64, pRequest->self,
             tstrerror(code), pRequest->requestId);
726 727 728
    pRequest->code = code;
    pRequest->body.queryFp(pRequest->body.param, pRequest, code);
  }
729 730
}

731
void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) {
L
Liu Jicong 已提交
732
  STscObj *pTscObj = acquireTscObj(*(int64_t *)taos);
733
  if (pTscObj == NULL || sql == NULL || NULL == fp) {
734
    terrno = TSDB_CODE_INVALID_PARA;
735
    if (pTscObj) {
L
Liu Jicong 已提交
736
      releaseTscObj(*(int64_t *)taos);
737 738 739
    } else {
      terrno = TSDB_CODE_TSC_DISCONNECTED;
    }
740
    fp(param, NULL, terrno);
741 742 743
    return;
  }

744 745 746 747 748 749
  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);
750 751 752
    return;
  }

753
  SRequestObj *pRequest = NULL;
L
Liu Jicong 已提交
754
  int32_t      code = buildRequest(pTscObj, sql, sqlLen, &pRequest);
755 756
  if (code != TSDB_CODE_SUCCESS) {
    terrno = code;
757
    fp(param, NULL, terrno);
758 759
    return;
  }
760

761
  pRequest->body.queryFp = fp;
762
  pRequest->body.param = param;
763 764
  doAsyncQuery(pRequest, false);
}
765

766
int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt) {
767 768 769 770 771 772 773
  const STscObj *pTscObj = pRequest->pTscObj;

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

774 775
  **pCxt = (SParseContext){
      .requestId = pRequest->requestId,
X
Xiaoyu Wang 已提交
776
      .requestRid = pRequest->self,
777 778 779 780 781 782 783 784 785 786 787 788 789 790
      .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,
      .schemalessType = pTscObj->schemalessType,
      .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)),
      .async = true,
  };
791 792 793
  return TSDB_CODE_SUCCESS;
}

794 795 796 797
void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
  SParseContext *pCxt = NULL;
  STscObj       *pTscObj = pRequest->pTscObj;
  int32_t        code = 0;
798 799

  if (pRequest->retry++ > REQUEST_TOTAL_EXEC_TIMES) {
800
    code = pRequest->prevCode;
801 802 803
    goto _error;
  }

804
  code = createParseContext(pRequest, &pCxt);
805 806 807
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
808 809 810 811 812

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

815 816
  SQuery *pQuery = NULL;

D
dapan1121 已提交
817
  SCatalogReq catalogReq = {.forceUpdate = updateMetaForce, .qNodeRequired = qnodeRequired(pRequest)};
818 819 820 821 822 823
  code = qParseSqlSyntax(pCxt, &pQuery, &catalogReq);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  SqlParseWrapper *pWrapper = taosMemoryCalloc(1, sizeof(SqlParseWrapper));
824
  if (pWrapper == NULL) {
825
    code = TSDB_CODE_OUT_OF_MEMORY;
826 827 828
    goto _error;
  }

829 830 831 832 833
  pWrapper->pCtx = pCxt;
  pWrapper->pQuery = pQuery;
  pWrapper->pRequest = pRequest;
  pWrapper->catalogReq = catalogReq;

X
Xiaoyu Wang 已提交
834
  SRequestConnInfo conn = {.pTrans = pCxt->pTransporter,
D
dapan1121 已提交
835 836 837 838
                           .requestId = pCxt->requestId,
                           .requestObjRefId = pCxt->requestRid,
                           .mgmtEps = pCxt->mgmtEpSet};

X
Xiaoyu Wang 已提交
839 840
  code = catalogAsyncGetAllMeta(pCxt->pCatalog, &conn, pRequest->requestId, &catalogReq, retrieveMetaCallback, pWrapper,
                                &pRequest->body.queryJob);
841 842
  if (code == TSDB_CODE_SUCCESS) {
    return;
843 844
  }

845 846 847
_error:
  tscError("0x%" PRIx64 " error happens, code:%d - %s, reqId:0x%" PRIx64, pRequest->self, code, tstrerror(code),
           pRequest->requestId);
848 849
  terrno = code;
  pRequest->code = code;
850
  pRequest->body.queryFp(pRequest->body.param, pRequest, code);
851 852
}

853 854
static void fetchCallback(void *pResult, void *param, int32_t code) {
  SRequestObj *pRequest = (SRequestObj *)param;
855

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

L
Liu Jicong 已提交
858 859
  tscDebug("0x%" PRIx64 " enter scheduler fetch cb, code:%d - %s, reqId:0x%" PRIx64, pRequest->self, code,
           tstrerror(code), pRequest->requestId);
D
dapan1121 已提交
860

861 862 863 864 865 866 867 868 869 870 871
  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);
872
    return;
873 874
  }

875 876
  pRequest->code =
      setQueryResultFromRsp(pResultInfo, (SRetrieveTableRsp *)pResultInfo->pData, pResultInfo->convertUcs4, false);
877 878 879
  if (pRequest->code != TSDB_CODE_SUCCESS) {
    pResultInfo->numOfRows = 0;
    pRequest->code = code;
880 881 882 883 884 885
    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);
886 887 888 889 890
  }

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

891
void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
892
  ASSERT(res != NULL && fp != NULL);
L
Liu Jicong 已提交
893
  ASSERT(TD_RES_QUERY(res));
894 895 896

  SRequestObj *pRequest = res;
  pRequest->body.fetchFp = fp;
897
  pRequest->body.param = param;
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914

  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;
    }
  }

915
  schedulerAsyncFetchRows(pRequest->body.queryJob, fetchCallback, pRequest);
L
Liu Jicong 已提交
916
}
917

918
void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) {
919
  ASSERT(res != NULL && fp != NULL);
L
Liu Jicong 已提交
920
  ASSERT(TD_RES_QUERY(res));
921
  SRequestObj *pRequest = res;
H
Haojun Liao 已提交
922

923
  pRequest->body.resInfo.convertUcs4 = false;
924 925 926 927 928

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

  // set the current block is all consumed
  pResultInfo->current = pResultInfo->numOfRows;
929 930 931
  taos_fetch_rows_a(res, fp, param);
}

932
const void *taos_get_raw_block(TAOS_RES *res) {
H
Haojun Liao 已提交
933
  ASSERT(res != NULL);
L
Liu Jicong 已提交
934
  ASSERT(TD_RES_QUERY(res));
935
  SRequestObj *pRequest = res;
H
Haojun Liao 已提交
936 937 938 939

  return pRequest->body.resInfo.pData;
}

L
Liu Jicong 已提交
940 941 942 943
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;
944 945 946
}

TAOS_RES *taos_consume(TAOS_SUB *tsub) {
L
Liu Jicong 已提交
947 948
  // TODO
  return NULL;
949 950 951
}

void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress) {
L
Liu Jicong 已提交
952
  // TODO
953 954
}

955 956 957 958 959
int taos_load_table_info(TAOS *taos, const char *tableNameList) {
  // TODO
  return -1;
}

L
Liu Jicong 已提交
960
TAOS_STMT *taos_stmt_init(TAOS *taos) {
L
Liu Jicong 已提交
961
  STscObj *pObj = acquireTscObj(*(int64_t *)taos);
962 963 964
  if (NULL == pObj) {
    tscError("invalid parameter for %s", __FUNCTION__);
    terrno = TSDB_CODE_TSC_DISCONNECTED;
D
stmt  
dapan1121 已提交
965 966 967
    return NULL;
  }

L
Liu Jicong 已提交
968 969 970
  TAOS_STMT *pStmt = stmtInit(pObj);

  releaseTscObj(*(int64_t *)taos);
971 972

  return pStmt;
973 974
}

D
stmt  
dapan1121 已提交
975 976
int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) {
  if (stmt == NULL || sql == NULL) {
D
stmt  
dapan1121 已提交
977
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
978 979 980 981
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
982
  return stmtPrepare(stmt, sql, length);
983 984
}

D
dapan1121 已提交
985
int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *name, TAOS_MULTI_BIND *tags) {
D
stmt  
dapan1121 已提交
986
  if (stmt == NULL || name == NULL) {
D
stmt  
dapan1121 已提交
987
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
988 989 990 991
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
992 993 994 995 996 997 998 999 1000 1001
  int32_t code = stmtSetTbName(stmt, name);
  if (code) {
    return code;
  }

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

  return TSDB_CODE_SUCCESS;
1002 1003
}

D
stmt  
dapan1121 已提交
1004 1005
int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name) {
  if (stmt == NULL || name == NULL) {
D
stmt  
dapan1121 已提交
1006
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1007
    terrno = TSDB_CODE_INVALID_PARA;
D
stmt  
dapan1121 已提交
1008
    return terrno;
D
stmt  
dapan1121 已提交
1009 1010
  }

D
stmt  
dapan1121 已提交
1011
  return stmtSetTbName(stmt, name);
1012 1013
}

D
dapan1121 已提交
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
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);
}

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

1026
int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
D
dapan1121 已提交
1027 1028 1029 1030 1031
  if (stmt == NULL || NULL == fieldNum) {
    tscError("NULL parameter for %s", __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
1032

D
dapan1121 已提交
1033 1034 1035
  return stmtGetTagFields(stmt, fieldNum, fields);
}

1036
int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields) {
D
dapan1121 已提交
1037 1038 1039 1040 1041
  if (stmt == NULL || NULL == fieldNum) {
    tscError("NULL parameter for %s", __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
1042

D
dapan1121 已提交
1043 1044 1045
  return stmtGetColFields(stmt, fieldNum, fields);
}

D
dapan1121 已提交
1046
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
D
stmt  
dapan1121 已提交
1047
  if (stmt == NULL || bind == NULL) {
D
stmt  
dapan1121 已提交
1048
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1049
    terrno = TSDB_CODE_INVALID_PARA;
D
stmt  
dapan1121 已提交
1050
    return terrno;
D
stmt  
dapan1121 已提交
1051
  }
1052

D
stmt  
dapan1121 已提交
1053 1054 1055 1056 1057
  if (bind->num > 1) {
    tscError("invalid bind number %d for %s", bind->num, __FUNCTION__);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
1058

D
stmt  
dapan1121 已提交
1059
  return stmtBindBatch(stmt, bind, -1);
1060 1061
}

D
dapan1121 已提交
1062
int taos_stmt_bind_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
D
stmt  
dapan1121 已提交
1063
  if (stmt == NULL || bind == NULL) {
D
stmt  
dapan1121 已提交
1064
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1065 1066 1067 1068
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
1069 1070
  if (bind->num <= 0 || bind->num > INT16_MAX) {
    tscError("invalid bind num %d", bind->num);
D
stmt  
dapan1121 已提交
1071 1072 1073 1074
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
dapan1121 已提交
1075 1076 1077 1078 1079 1080 1081 1082
  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 已提交
1083
  return stmtBindBatch(stmt, bind, -1);
1084 1085
}

D
dapan1121 已提交
1086
int taos_stmt_bind_single_param_batch(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind, int colIdx) {
D
stmt  
dapan1121 已提交
1087
  if (stmt == NULL || bind == NULL) {
D
stmt  
dapan1121 已提交
1088
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1089 1090 1091 1092
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
1093
  if (colIdx < 0) {
D
stmt  
dapan1121 已提交
1094 1095 1096 1097
    tscError("invalid bind column idx %d", colIdx);
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }
D
dapan1121 已提交
1098 1099 1100 1101 1102 1103 1104 1105

  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;
  }
1106

D
stmt  
dapan1121 已提交
1107
  return stmtBindBatch(stmt, bind, colIdx);
1108 1109
}

D
stmt  
dapan1121 已提交
1110 1111
int taos_stmt_add_batch(TAOS_STMT *stmt) {
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1112
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1113 1114 1115 1116
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
1117
  return stmtAddBatch(stmt);
1118 1119
}

D
stmt  
dapan1121 已提交
1120 1121
int taos_stmt_execute(TAOS_STMT *stmt) {
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1122
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1123 1124 1125 1126
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
1127
  return stmtExec(stmt);
1128 1129
}

1130
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
D
stmt  
dapan1121 已提交
1131
  if (stmt == NULL || insert == NULL) {
D
stmt  
dapan1121 已提交
1132
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1133 1134 1135 1136 1137
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

  return stmtIsInsert(stmt, insert);
1138 1139
}

1140
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
D
stmt  
dapan1121 已提交
1141
  if (stmt == NULL || nums == NULL) {
D
stmt  
dapan1121 已提交
1142
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1143 1144 1145 1146 1147
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

  return stmtGetParamNum(stmt, nums);
1148 1149
}

D
dapan1121 已提交
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
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 已提交
1160
TAOS_RES *taos_stmt_use_result(TAOS_STMT *stmt) {
D
stmt  
dapan1121 已提交
1161
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1162
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1163
    terrno = TSDB_CODE_INVALID_PARA;
D
stmt  
dapan1121 已提交
1164
    return NULL;
D
stmt  
dapan1121 已提交
1165 1166
  }

D
stmt  
dapan1121 已提交
1167
  return stmtUseResult(stmt);
1168 1169
}

1170
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
1171

D
stmt  
dapan1121 已提交
1172
int taos_stmt_affected_rows(TAOS_STMT *stmt) {
D
stmt  
dapan1121 已提交
1173
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1174
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1175
    terrno = TSDB_CODE_INVALID_PARA;
D
stmt  
dapan1121 已提交
1176
    return 0;
D
stmt  
dapan1121 已提交
1177 1178
  }

D
stmt  
dapan1121 已提交
1179
  return stmtAffectedRows(stmt);
1180 1181
}

D
dapan1121 已提交
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191
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 已提交
1192 1193
int taos_stmt_close(TAOS_STMT *stmt) {
  if (stmt == NULL) {
D
stmt  
dapan1121 已提交
1194
    tscError("NULL parameter for %s", __FUNCTION__);
D
stmt  
dapan1121 已提交
1195 1196 1197 1198
    terrno = TSDB_CODE_INVALID_PARA;
    return terrno;
  }

D
stmt  
dapan1121 已提交
1199
  return stmtClose(stmt);
D
stmt  
dapan1121 已提交
1200
}