clientMain.c 32.1 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
    }
L
Liu Jicong 已提交
293 294
  } else if (TD_RES_TMQ_META(res)) {
    return NULL;
L
Liu Jicong 已提交
295
  } else {
296
    // assert to avoid un-initialization error
L
Liu Jicong 已提交
297 298 299
    ASSERT(0);
  }
  return NULL;
300
}
H
Haojun Liao 已提交
301

L
Liu Jicong 已提交
302
int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
H
Haojun Liao 已提交
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 359 360
  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 已提交
361
        int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
H
Haojun Liao 已提交
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
        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 已提交
382
  str[len] = 0;
H
Haojun Liao 已提交
383 384 385

  return len;
}
386

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

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

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

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

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

410
// todo intergrate with tDataTypes
411 412
const char *taos_data_type(int type) {
  switch (type) {
L
Liu Jicong 已提交
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 438 439
    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";
440 441
  }
}
442 443 444

const char *taos_get_client_info() { return version; }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return 0;
623 624
}

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

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

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

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

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

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

653 654
  resetConnectDB(pTscObj);

L
Liu Jicong 已提交
655
  releaseTscObj(*(int64_t *)taos);
656 657
}

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

L
Liu Jicong 已提交
665
  releaseTscObj(*(int64_t *)taos);
666

667 668 669
  return pTscObj->ver;
}

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

677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
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 已提交
692
  tscDebug("enter meta callback, code %s", tstrerror(code));
L
Liu Jicong 已提交
693

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

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

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

709 710
    TSWAP(pRequest->dbList, (pQuery)->pDbList);
    TSWAP(pRequest->tableList, (pQuery)->pTableList);
711

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

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

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

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

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

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

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

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

776 777
  **pCxt = (SParseContext){
      .requestId = pRequest->requestId,
X
Xiaoyu Wang 已提交
778
      .requestRid = pRequest->self,
779 780 781 782 783 784 785 786 787 788 789 790 791 792
      .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,
  };
793 794 795
  return TSDB_CODE_SUCCESS;
}

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

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

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

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

817 818
  SQuery *pQuery = NULL;

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

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

831 832 833 834 835
  pWrapper->pCtx = pCxt;
  pWrapper->pQuery = pQuery;
  pWrapper->pRequest = pRequest;
  pWrapper->catalogReq = catalogReq;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

925
  pRequest->body.resInfo.convertUcs4 = false;
926 927 928 929 930

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

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

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

  return pRequest->body.resInfo.pData;
}

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

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

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

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

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

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

  releaseTscObj(*(int64_t *)taos);
973 974

  return pStmt;
975 976
}

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

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

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

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

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

  return TSDB_CODE_SUCCESS;
1004 1005
}

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

D
stmt  
dapan1121 已提交
1013
  return stmtSetTbName(stmt, name);
1014 1015
}

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

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

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

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

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

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

D
dapan1121 已提交
1048
int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_MULTI_BIND *bind) {
D
stmt  
dapan1121 已提交
1049
  if (stmt == NULL || bind == 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 terrno;
D
stmt  
dapan1121 已提交
1053
  }
1054

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

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

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

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

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

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

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

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

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

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

D
stmt  
dapan1121 已提交
1119
  return stmtAddBatch(stmt);
1120 1121
}

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

D
stmt  
dapan1121 已提交
1129
  return stmtExec(stmt);
1130 1131
}

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

  return stmtIsInsert(stmt, insert);
1140 1141
}

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

  return stmtGetParamNum(stmt, nums);
1150 1151
}

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

D
stmt  
dapan1121 已提交
1169
  return stmtUseResult(stmt);
1170 1171
}

1172
char *taos_stmt_errstr(TAOS_STMT *stmt) { return (char *)stmtErrstr(stmt); }
1173

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

D
stmt  
dapan1121 已提交
1181
  return stmtAffectedRows(stmt);
1182 1183
}

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

D
stmt  
dapan1121 已提交
1201
  return stmtClose(stmt);
D
stmt  
dapan1121 已提交
1202
}