tscSql.c 23.3 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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/>.
 */

H
hjxilinx 已提交
16
#include "hash.h"
H
hjxilinx 已提交
17
#include "os.h"
H
hjxilinx 已提交
18
#include "qast.h"
H
hzcheng 已提交
19
#include "tcache.h"
H
hjxilinx 已提交
20
#include "tnote.h"
H
hzcheng 已提交
21
#include "trpc.h"
S
slguan 已提交
22
#include "tscLog.h"
H
hjxilinx 已提交
23
#include "tscSubquery.h"
H
hzcheng 已提交
24 25
#include "tscUtil.h"
#include "tsclient.h"
26
#include "ttokendef.h"
H
hjxilinx 已提交
27
#include "tutil.h"
H
hzcheng 已提交
28

29 30 31 32 33 34 35 36 37 38 39 40
static bool validImpl(const char* str, size_t maxsize) {
  if (str == NULL) {
    return false;
  }
  
  size_t len = strlen(str);
  if (len <= 0 || len > maxsize) {
    return false;
  }
  
  return true;
}
H
hzcheng 已提交
41

42
static bool validUserName(const char* user) {
B
Bomin Zhang 已提交
43
  return validImpl(user, TSDB_USER_LEN - 1);
44
}
S
slguan 已提交
45

46
static bool validPassword(const char* passwd) {
B
Bomin Zhang 已提交
47
  return validImpl(passwd, TSDB_PASSWORD_LEN - 1);
48
}
H
hzcheng 已提交
49

H
Haojun Liao 已提交
50
SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, const char *db, uint16_t port,
51 52 53 54
                       void (*fp)(void *, TAOS_RES *, int), void *param, void **taos) {
  taos_init();
  
  if (!validUserName(user)) {
55
    terrno = TSDB_CODE_TSC_INVALID_USER_LENGTH;
H
hzcheng 已提交
56 57 58
    return NULL;
  }

59
  if (!validPassword(pass)) {
60
    terrno = TSDB_CODE_TSC_INVALID_PASS_LENGTH;
H
hzcheng 已提交
61 62
    return NULL;
  }
63 64 65 66 67 68

  if (ip) {
    if (tscSetMgmtIpListFromCfg(ip, NULL) < 0) return NULL;
    if (port) tscMgmtIpSet.port[0] = port;
  } 
 
69 70
  void *pDnodeConn = NULL;
  if (tscInitRpc(user, pass, &pDnodeConn) != 0) {
71
    terrno = TSDB_CODE_RPC_NETWORK_UNAVAIL;
S
slguan 已提交
72 73
    return NULL;
  }
74
 
75
  STscObj *pObj = (STscObj *)calloc(1, sizeof(STscObj));
S
slguan 已提交
76
  if (NULL == pObj) {
77
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
78
    rpcClose(pDnodeConn);
S
slguan 已提交
79 80
    return NULL;
  }
H
hjxilinx 已提交
81

H
hzcheng 已提交
82 83
  pObj->signature = pObj;

B
Bomin Zhang 已提交
84
  tstrncpy(pObj->user, user, sizeof(pObj->user));
S
slguan 已提交
85
  taosEncryptPass((uint8_t *)pass, strlen(pass), pObj->pass);
H
hzcheng 已提交
86 87 88 89

  if (db) {
    int32_t len = strlen(db);
    /* db name is too long */
B
Bomin Zhang 已提交
90
    if (len >= TSDB_DB_NAME_LEN) {
91
      terrno = TSDB_CODE_TSC_INVALID_DB_LENGTH;
92 93
      rpcClose(pDnodeConn);
      free(pObj);
H
hzcheng 已提交
94 95 96
      return NULL;
    }

B
Bomin Zhang 已提交
97 98
    char tmp[TSDB_DB_NAME_LEN] = {0};
    tstrncpy(tmp, db, sizeof(tmp));
H
hzcheng 已提交
99 100

    strdequote(tmp);
S
slguan 已提交
101
    strtolower(pObj->db, tmp);
H
hzcheng 已提交
102 103 104 105
  }

  pthread_mutex_init(&pObj->mutex, NULL);

106
  SSqlObj *pSql = (SSqlObj *)calloc(1, sizeof(SSqlObj));
S
slguan 已提交
107
  if (NULL == pSql) {
108
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
109
    rpcClose(pDnodeConn);
S
slguan 已提交
110 111 112
    free(pObj);
    return NULL;
  }
H
hjxilinx 已提交
113

H
hzcheng 已提交
114 115
  pSql->pTscObj = pObj;
  pSql->signature = pSql;
S
slguan 已提交
116
  pSql->maxRetry = TSDB_MAX_REPLICA_NUM;
S
slguan 已提交
117
  tsem_init(&pSql->rspSem, 0, 0);
H
hjxilinx 已提交
118
  
119 120
  pObj->pDnodeConn = pDnodeConn;
  
H
hzcheng 已提交
121 122 123 124 125 126 127
  pSql->fp = fp;
  pSql->param = param;
  if (taos != NULL) {
    *taos = pObj;
  }

  pSql->cmd.command = TSDB_SQL_CONNECT;
128
  if (TSDB_CODE_SUCCESS != tscAllocPayload(&pSql->cmd, TSDB_DEFAULT_PAYLOAD_SIZE)) {
129
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
130
    rpcClose(pDnodeConn);
S
slguan 已提交
131 132 133 134
    free(pSql);
    free(pObj);
    return NULL;
  }
H
hzcheng 已提交
135

136
  tsInsertHeadSize = sizeof(SMsgDesc) + sizeof(SSubmitMsg);
H
Haojun Liao 已提交
137
  return pSql;
H
hzcheng 已提交
138 139
}

140
static void syncConnCallback(void *param, TAOS_RES *tres, int code) {
H
Haojun Liao 已提交
141 142
  SSqlObj *pSql = (SSqlObj *) tres;
  assert(pSql != NULL);
H
hjxilinx 已提交
143
  
H
Haojun Liao 已提交
144
  sem_post(&pSql->rspSem);
145 146
}

L
lihui 已提交
147
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
148
  tscDebug("try to create a connection to %s:%u, user:%s db:%s", ip, port, user, db);
S
Shengliang Guan 已提交
149 150
  if (user == NULL) user = TSDB_DEFAULT_USER;
  if (pass == NULL) pass = TSDB_DEFAULT_PASS;
H
hzcheng 已提交
151

H
Haojun Liao 已提交
152 153 154
  STscObj* pObj = NULL;
  SSqlObj *pSql = taosConnectImpl(ip, user, pass, db, port, syncConnCallback, NULL, (void**) &pObj);
  if (pSql != NULL) {
155
    pSql->fp = syncConnCallback;
H
Haojun Liao 已提交
156
    pSql->param = pSql;
157 158 159 160 161
    
    tscProcessSql(pSql);
    sem_wait(&pSql->rspSem);
    
    if (pSql->res.code != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
162
      terrno = pSql->res.code;
H
Haojun Liao 已提交
163
      taos_free_result(pSql);
164 165 166 167
      taos_close(pObj);
      return NULL;
    }
    
168
    tscDebug("%p DB connection is opening, dnodeConn:%p", pObj, pObj->pDnodeConn);
H
Haojun Liao 已提交
169 170
    taos_free_result(pSql);
  
S
slguan 已提交
171
    // version compare only requires the first 3 segments of the version string
172
    int code = taosCheckVersion(version, taos_get_server_info(pObj), 3);
S
slguan 已提交
173
    if (code != 0) {
H
hjxilinx 已提交
174
      terrno = code;
175
      taos_close(pObj);
S
slguan 已提交
176
      return NULL;
177 178
    } else {
      return pObj;
S
slguan 已提交
179
    }
H
hzcheng 已提交
180 181
  }

182
  return NULL;
H
hzcheng 已提交
183 184
}

L
lihui 已提交
185
TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
H
hzcheng 已提交
186
                     void *param, void **taos) {
H
Haojun Liao 已提交
187 188
  SSqlObj* pSql = taosConnectImpl(ip, user, pass, db, port, fp, param, taos);
  if (pSql == NULL) {
189 190 191 192
    return NULL;
  }
  
  pSql->res.code = tscProcessSql(pSql);
193
  tscDebug("%p DB async connection is opening", taos);
H
Haojun Liao 已提交
194
  return taos;
H
hzcheng 已提交
195 196 197 198 199
}

void taos_close(TAOS *taos) {
  STscObj *pObj = (STscObj *)taos;

H
hjxilinx 已提交
200 201 202
  if (pObj == NULL || pObj->signature != pObj)  {
    return;
  }
H
hzcheng 已提交
203 204 205 206 207 208 209 210

  if (pObj->pHb != NULL) {
    tscSetFreeHeatBeat(pObj);
  } else {
    tscCloseTscObj(pObj);
  }
}

H
Hui Li 已提交
211
void waitForQueryRsp(void *param, TAOS_RES *tres, int code) {
H
Hui Li 已提交
212
  assert(tres != NULL);
H
[td-99]  
hjxilinx 已提交
213
  
H
Haojun Liao 已提交
214
  SSqlObj *pSql = (SSqlObj *) tres;
H
[td-99]  
hjxilinx 已提交
215
  sem_post(&pSql->rspSem);
216 217
}

218 219 220 221 222
static void waitForRetrieveRsp(void *param, TAOS_RES *tres, int numOfRows) {
  SSqlObj* pSql = (SSqlObj*) tres;
  sem_post(&pSql->rspSem);
}

H
Haojun Liao 已提交
223
TAOS_RES* taos_query(TAOS *taos, const char *sqlstr) {
S
slguan 已提交
224 225
  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
226
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
Haojun Liao 已提交
227
    return NULL;
S
slguan 已提交
228
  }
229
  
H
Haojun Liao 已提交
230 231 232
  int32_t sqlLen = strlen(sqlstr);
  if (sqlLen > tsMaxSQLStringLen) {
    tscError("sql string exceeds max length:%d", tsMaxSQLStringLen);
233
    terrno = TSDB_CODE_TSC_INVALID_SQL;
H
Haojun Liao 已提交
234 235 236 237 238
    return NULL;
  }
  
  taosNotePrintTsc(sqlstr);
  
H
Haojun Liao 已提交
239 240 241
  SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
  if (pSql == NULL) {
    tscError("failed to malloc sqlObj");
242
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
H
Haojun Liao 已提交
243 244 245
    return NULL;
  }
  
H
[TD-98]  
hjxilinx 已提交
246
  doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen);
S
slguan 已提交
247

248
  // wait for the callback function to post the semaphore
H
Haojun Liao 已提交
249
  tsem_wait(&pSql->rspSem);
H
Haojun Liao 已提交
250
  return pSql;
H
hzcheng 已提交
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
}

int taos_result_precision(TAOS_RES *res) {
  SSqlObj *pSql = (SSqlObj *)res;
  if (pSql == NULL || pSql->signature != pSql) return 0;

  return pSql->res.precision;
}

int taos_num_rows(TAOS_RES *res) { return 0; }

int taos_num_fields(TAOS_RES *res) {
  SSqlObj *pSql = (SSqlObj *)res;
  if (pSql == NULL || pSql->signature != pSql) return 0;

H
hjxilinx 已提交
266
  int32_t num = 0;
267
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
268
  if (pQueryInfo == NULL) {
H
hjxilinx 已提交
269
    return num;
270
  }
271

H
hjxilinx 已提交
272 273 274 275 276 277 278 279 280
  size_t numOfCols = tscNumOfFields(pQueryInfo);
  for(int32_t i = 0; i < numOfCols; ++i) {
    SFieldSupInfo* pInfo = taosArrayGet(pQueryInfo->fieldsInfo.pSupportInfo, i);
    if (pInfo->visible) {
      num++;
    }
  }
  
  return num;
H
hzcheng 已提交
281 282
}

H
Haojun Liao 已提交
283 284 285
int taos_field_count(TAOS_RES *tres) {
  SSqlObj* pSql = (SSqlObj*) tres;
  if (pSql == NULL || pSql->signature != pSql) return 0;
H
hzcheng 已提交
286

H
Haojun Liao 已提交
287
  return taos_num_fields(pSql);
H
hzcheng 已提交
288 289
}

H
Haojun Liao 已提交
290 291 292
int taos_affected_rows(TAOS_RES *tres) {
  SSqlObj* pSql = (SSqlObj*) tres;
  if (pSql == NULL || pSql->signature != pSql) return 0;
H
hzcheng 已提交
293

H
Haojun Liao 已提交
294
  return (pSql->res.numOfRows);
H
hzcheng 已提交
295 296 297 298 299
}

TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
  SSqlObj *pSql = (SSqlObj *)res;
  if (pSql == NULL || pSql->signature != pSql) return 0;
300 301

  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
H
hjxilinx 已提交
302
  if (pQueryInfo == NULL) {
sangshuduo's avatar
sangshuduo 已提交
303
    return NULL;
H
hjxilinx 已提交
304 305 306 307 308 309 310 311
  }
  
  size_t numOfCols = tscNumOfFields(pQueryInfo);
  if (numOfCols == 0) {
    return NULL;
  }
  
  return pQueryInfo->fieldsInfo.pFields->pData;
H
hzcheng 已提交
312 313 314 315 316 317 318 319 320 321
}

int taos_retrieve(TAOS_RES *res) {
  if (res == NULL) return 0;
  SSqlObj *pSql = (SSqlObj *)res;
  SSqlCmd *pCmd = &pSql->cmd;
  SSqlRes *pRes = &pSql->res;
  if (pSql == NULL || pSql->signature != pSql) return 0;
  if (pRes->qhandle == 0) return 0;

S
slguan 已提交
322 323
  tscResetForNextRetrieve(pRes);

H
hzcheng 已提交
324 325 326 327 328 329 330 331 332 333 334 335 336
  if (pCmd->command < TSDB_SQL_LOCAL) {
    pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
  }
  tscProcessSql(pSql);

  return pRes->numOfRows;
}

int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) {
  SSqlObj *pSql = (SSqlObj *)res;
  SSqlCmd *pCmd = &pSql->cmd;
  SSqlRes *pRes = &pSql->res;

H
Haojun Liao 已提交
337
  if (pRes->qhandle == 0 || pSql->signature != pSql) {
H
hzcheng 已提交
338 339 340 341 342
    *rows = NULL;
    return 0;
  }

  // Retrieve new block
S
slguan 已提交
343
  tscResetForNextRetrieve(pRes);
H
hzcheng 已提交
344 345 346 347 348 349 350 351 352 353
  if (pCmd->command < TSDB_SQL_LOCAL) {
    pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
  }

  tscProcessSql(pSql);
  if (pRes->numOfRows == 0) {
    *rows = NULL;
    return 0;
  }

S
slguan 已提交
354
  // secondary merge has handle this situation
H
hjxilinx 已提交
355
  if (pCmd->command != TSDB_SQL_RETRIEVE_LOCALMERGE) {
H
Haojun Liao 已提交
356
    pRes->numOfClauseTotal += pRes->numOfRows;
S
slguan 已提交
357 358
  }

359
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
sangshuduo's avatar
sangshuduo 已提交
360 361 362
  if (pQueryInfo == NULL)
    return 0;

H
hjxilinx 已提交
363
  assert(0);
H
hjxilinx 已提交
364
  for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
365
    tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i);
H
hzcheng 已提交
366 367 368 369
  }

  *rows = pRes->tsrow;

370
  return (pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows;
H
hzcheng 已提交
371 372 373 374 375
}

TAOS_ROW taos_fetch_row(TAOS_RES *res) {
  SSqlObj *pSql = (SSqlObj *)res;
  if (pSql == NULL || pSql->signature != pSql) {
376
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
377 378
    return NULL;
  }
379 380 381 382
  
  SSqlCmd *pCmd = &pSql->cmd;
  SSqlRes *pRes = &pSql->res;
  
H
hjxilinx 已提交
383 384 385
  if (pRes->qhandle == 0 ||
      pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
      pCmd->command == TSDB_SQL_INSERT) {
386
    return NULL;
387
  }
388
  
389 390
  // current data set are exhausted, fetch more data from node
  if (pRes->row >= pRes->numOfRows && (pRes->completed != true || hasMoreVnodesToTry(pSql)) &&
H
hjxilinx 已提交
391
      (pCmd->command == TSDB_SQL_RETRIEVE ||
H
hjxilinx 已提交
392
       pCmd->command == TSDB_SQL_RETRIEVE_LOCALMERGE ||
393
       pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE ||
H
hjxilinx 已提交
394 395 396
       pCmd->command == TSDB_SQL_FETCH ||
       pCmd->command == TSDB_SQL_SHOW ||
       pCmd->command == TSDB_SQL_SELECT ||
H
Haojun Liao 已提交
397 398 399 400 401 402
       pCmd->command == TSDB_SQL_DESCRIBE_TABLE ||
       pCmd->command == TSDB_SQL_SERV_STATUS ||
       pCmd->command == TSDB_SQL_CURRENT_DB ||
       pCmd->command == TSDB_SQL_SERV_VERSION ||
       pCmd->command == TSDB_SQL_CLI_VERSION ||
       pCmd->command == TSDB_SQL_CURRENT_USER )) {
H
[td-99]  
hjxilinx 已提交
403
    taos_fetch_rows_a(res, waitForRetrieveRsp, pSql->pTscObj);
404
    sem_wait(&pSql->rspSem);
H
hjxilinx 已提交
405
  }
H
Haojun Liao 已提交
406

H
hjxilinx 已提交
407
  return doSetResultRowData(pSql, true);
H
hzcheng 已提交
408 409 410
}

int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
H
hjxilinx 已提交
411
#if 0
H
hzcheng 已提交
412
  SSqlObj *pSql = (SSqlObj *)res;
H
hjxilinx 已提交
413
  SSqlCmd *pCmd = &pSql->cmd;
414
  SSqlRes *pRes = &pSql->res;
415

H
hzcheng 已提交
416 417 418
  int nRows = 0;

  if (pSql == NULL || pSql->signature != pSql) {
419
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
420 421 422 423
    *rows = NULL;
    return 0;
  }

S
slguan 已提交
424
  // projection query on metric, pipeline retrieve data from vnode list,
S
slguan 已提交
425
  // instead of two-stage mergednodeProcessMsgFromShell free qhandle
H
hzcheng 已提交
426
  nRows = taos_fetch_block_impl(res, rows);
427

H
hjxilinx 已提交
428 429
  // current subclause is completed, try the next subclause
  while (rows == NULL && pCmd->clauseIndex < pCmd->numOfClause - 1) {
430 431
    SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);

432
    pSql->cmd.command = pQueryInfo->command;
H
hjxilinx 已提交
433
    pCmd->clauseIndex++;
434

H
Haojun Liao 已提交
435 436
    pRes->numOfTotal += pRes->numOfClauseTotal;
    pRes->numOfClauseTotal = 0;
437
    pRes->rspType = 0;
438

439 440
    pSql->numOfSubs = 0;
    tfree(pSql->pSubs);
441

H
hjxilinx 已提交
442
    assert(pSql->fp == NULL);
443

444
    tscDebug("%p try data in the next subclause:%d, total subclause:%d", pSql, pCmd->clauseIndex, pCmd->numOfClause);
H
hjxilinx 已提交
445
    tscProcessSql(pSql);
446

H
hjxilinx 已提交
447
    nRows = taos_fetch_block_impl(res, rows);
H
hzcheng 已提交
448
  }
449

H
hzcheng 已提交
450
  return nRows;
H
hjxilinx 已提交
451 452 453 454
#endif

  (*rows) = taos_fetch_row(res);
  return ((*rows) != NULL)? 1:0;
H
hzcheng 已提交
455 456
}

S
slguan 已提交
457
int taos_select_db(TAOS *taos, const char *db) {
458
  char sql[256] = {0};
H
hzcheng 已提交
459 460 461

  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
462 463
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
464 465
  }

466
  snprintf(sql, tListLen(sql), "use %s", db);
H
Haojun Liao 已提交
467 468 469 470 471
  SSqlObj* pSql = taos_query(taos, sql);
  int32_t code = pSql->res.code;
  taos_free_result(pSql);
  
  return code;
H
hzcheng 已提交
472 473
}

H
Haojun Liao 已提交
474
// send free message to vnode to free qhandle and corresponding resources in vnode
H
Haojun Liao 已提交
475
static bool tscFreeQhandleInVnode(SSqlObj* pSql) {
H
Haojun Liao 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489
  SSqlCmd* pCmd = &pSql->cmd;
  SSqlRes* pRes = &pSql->res;

  SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
  STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);

  if (pRes->code == TSDB_CODE_SUCCESS && pRes->completed == false && !tscIsTwoStageSTableQuery(pQueryInfo, 0) &&
      (pCmd->command == TSDB_SQL_SELECT ||
          pCmd->command == TSDB_SQL_SHOW ||
          pCmd->command == TSDB_SQL_RETRIEVE ||
          pCmd->command == TSDB_SQL_FETCH) &&
      (pCmd->command == TSDB_SQL_SELECT && pSql->pStream == NULL && pTableMetaInfo->pTableMeta != NULL)) {

    pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
490
    tscDebug("%p send msg to dnode to free qhandle ASAP, command:%s", pSql, sqlCmd[pCmd->command]);
H
Haojun Liao 已提交
491 492 493
    tscProcessSql(pSql);

    // in case of sync model query, waits for response and then goes on
494 495
//    if (pSql->fp == waitForQueryRsp || pSql->fp == waitForRetrieveRsp) {
//      sem_wait(&pSql->rspSem);
H
Haojun Liao 已提交
496

497
//      tscFreeSqlObj(pSql);
498
//      tscDebug("%p sqlObj is freed by app", pSql);
499
//    } else {
500
      tscDebug("%p sqlObj will be freed while rsp received", pSql);
501
//    }
H
Haojun Liao 已提交
502 503

    return true;
H
Haojun Liao 已提交
504
  }
H
Haojun Liao 已提交
505 506

  return false;
H
Haojun Liao 已提交
507 508
}

H
Haojun Liao 已提交
509
void taos_free_result(TAOS_RES *res) {
H
hzcheng 已提交
510
  SSqlObj *pSql = (SSqlObj *)res;
H
Haojun Liao 已提交
511

H
Haojun Liao 已提交
512
  if (pSql == NULL || pSql->signature != pSql) {
513
    tscDebug("%p sqlObj has been freed", pSql);
H
Haojun Liao 已提交
514 515
    return;
  }
H
Haojun Liao 已提交
516
  
H
Haojun Liao 已提交
517
  // The semaphore can not be changed while freeing async sub query objects.
H
Haojun Liao 已提交
518
  SSqlRes *pRes = &pSql->res;
H
Haojun Liao 已提交
519 520
  if (pRes == NULL || pRes->qhandle == 0) {
    tscFreeSqlObj(pSql);
521
    tscDebug("%p SqlObj is freed by app, qhandle is null", pSql);
H
hzcheng 已提交
522 523 524
    return;
  }

H
Haojun Liao 已提交
525
  // set freeFlag to 1 in retrieve message if there are un-retrieved results data in node
526
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
527
  if (pQueryInfo == NULL) {
H
Haojun Liao 已提交
528
    tscFreeSqlObj(pSql);
529
    tscDebug("%p SqlObj is freed by app", pSql);
530 531 532
    return;
  }

533
  pQueryInfo->type = TSDB_QUERY_TYPE_FREE_RESOURCE;
H
Haojun Liao 已提交
534 535
  if (!tscFreeQhandleInVnode(pSql)) {
    tscFreeSqlObj(pSql);
536
    tscDebug("%p sqlObj is freed by app", pSql);
H
hzcheng 已提交
537 538 539
  }
}

H
[td-99]  
hjxilinx 已提交
540
// todo should not be used in async query
H
Haojun Liao 已提交
541 542
int taos_errno(TAOS_RES *tres) {
  SSqlObj *pSql = (SSqlObj *) tres;
H
hzcheng 已提交
543

H
Haojun Liao 已提交
544
  if (pSql == NULL || pSql->signature != pSql) {
H
[td-99]  
hjxilinx 已提交
545 546
    return terrno;
  }
H
hzcheng 已提交
547

H
Haojun Liao 已提交
548
  return pSql->res.code;
H
hzcheng 已提交
549 550
}

H
hjxilinx 已提交
551 552 553 554
/*
 * In case of invalid sql error, additional information is attached to explain
 * why the sql is invalid
 */
H
hjxilinx 已提交
555
static bool hasAdditionalErrorInfo(int32_t code, SSqlCmd *pCmd) {
556
  if (code != TSDB_CODE_TSC_INVALID_SQL) {
H
hjxilinx 已提交
557 558 559 560
    return false;
  }

  size_t len = strlen(pCmd->payload);
H
hjxilinx 已提交
561 562

  char *z = NULL;
H
hjxilinx 已提交
563
  if (len > 0) {
H
hjxilinx 已提交
564
    z = strstr(pCmd->payload, "invalid SQL");
H
hjxilinx 已提交
565
  }
H
hjxilinx 已提交
566

H
hjxilinx 已提交
567 568 569
  return z != NULL;
}

H
[td-99]  
hjxilinx 已提交
570
// todo should not be used in async model
H
Haojun Liao 已提交
571 572
char *taos_errstr(TAOS_RES *tres) {
  SSqlObj *pSql = (SSqlObj *) tres;
H
hzcheng 已提交
573

H
Haojun Liao 已提交
574 575 576
  if (pSql == NULL || pSql->signature != pSql) {
    return (char*) tstrerror(terrno);
  }
H
hzcheng 已提交
577

H
[td-32]  
hjxilinx 已提交
578
  if (hasAdditionalErrorInfo(pSql->res.code, &pSql->cmd)) {
H
hjxilinx 已提交
579
    return pSql->cmd.payload;
H
hzcheng 已提交
580
  } else {
H
[td-32]  
hjxilinx 已提交
581
    return (char*)tstrerror(pSql->res.code);
H
hzcheng 已提交
582 583 584 585 586
  }
}

void taos_config(int debug, char *log_path) {
  uDebugFlag = debug;
B
Bomin Zhang 已提交
587
  tstrncpy(tsLogDir, log_path, TSDB_FILENAME_LEN);
H
hzcheng 已提交
588 589 590 591 592 593 594 595 596 597
}

char *taos_get_server_info(TAOS *taos) {
  STscObj *pObj = (STscObj *)taos;

  if (pObj == NULL) return NULL;

  return pObj->sversion;
}

598 599 600 601 602 603 604 605 606
int* taos_fetch_lengths(TAOS_RES *res) {
  SSqlObj* pSql = (SSqlObj* ) res;
  if (pSql == NULL || pSql->signature != pSql) {
    return NULL;
  }
  
  return pSql->res.length;
}

H
hzcheng 已提交
607 608 609
char *taos_get_client_info() { return version; }

void taos_stop_query(TAOS_RES *res) {
610 611 612
  if (res == NULL) {
    return;
  }
H
hzcheng 已提交
613 614

  SSqlObj *pSql = (SSqlObj *)res;
615 616
  SSqlCmd *pCmd = &pSql->cmd;

H
hzcheng 已提交
617
  if (pSql->signature != pSql) return;
618
  tscDebug("%p start to cancel query", res);
H
hzcheng 已提交
619 620


621
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
H
hjxilinx 已提交
622
  if (tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
H
hjxilinx 已提交
623
    tscKillSTableQuery(pSql);
H
hzcheng 已提交
624 625
  }

dengyihao's avatar
dengyihao 已提交
626 627
  if (pSql->cmd.command < TSDB_SQL_LOCAL) {
    rpcCancelRequest(pSql->pRpcCtx);
H
hzcheng 已提交
628
  }
dengyihao's avatar
dengyihao 已提交
629 630
  pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
  tscQueueAsyncRes(pSql);
H
hzcheng 已提交
631

632
  tscDebug("%p query is cancelled", res);
H
hzcheng 已提交
633 634 635 636 637
}

int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) {
  int len = 0;
  for (int i = 0; i < num_fields; ++i) {
638 639 640 641
    if (i > 0) {
      str[len++] = ' ';
    }

H
hzcheng 已提交
642
    if (row[i] == NULL) {
643
      len += sprintf(str + len, "%s", TSDB_DATA_NULL_STR);
H
hzcheng 已提交
644 645 646 647 648
      continue;
    }

    switch (fields[i].type) {
      case TSDB_DATA_TYPE_TINYINT:
649
        len += sprintf(str + len, "%d", *((char *)row[i]));
H
hzcheng 已提交
650 651 652
        break;

      case TSDB_DATA_TYPE_SMALLINT:
653
        len += sprintf(str + len, "%d", *((short *)row[i]));
H
hzcheng 已提交
654 655 656
        break;

      case TSDB_DATA_TYPE_INT:
657
        len += sprintf(str + len, "%d", *((int *)row[i]));
H
hzcheng 已提交
658 659 660
        break;

      case TSDB_DATA_TYPE_BIGINT:
661
        len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
H
hzcheng 已提交
662 663
        break;

L
lihui 已提交
664 665
      case TSDB_DATA_TYPE_FLOAT: {
        float fv = 0;
L
lihui 已提交
666
        fv = GET_FLOAT_VAL(row[i]);
667
        len += sprintf(str + len, "%f", fv);
668
      } break;
H
hzcheng 已提交
669

670
      case TSDB_DATA_TYPE_DOUBLE: {
L
lihui 已提交
671
        double dv = 0;
L
lihui 已提交
672
        dv = GET_DOUBLE_VAL(row[i]);
673
        len += sprintf(str + len, "%lf", dv);
674
      } break;
H
hzcheng 已提交
675 676

      case TSDB_DATA_TYPE_BINARY:
S
slguan 已提交
677
      case TSDB_DATA_TYPE_NCHAR: {
H
hjxilinx 已提交
678
        size_t xlen = 0;
679
        for (xlen = 0; xlen < fields[i].bytes - VARSTR_HEADER_SIZE; xlen++) {
H
hjxilinx 已提交
680 681 682 683 684 685
          char c = ((char *)row[i])[xlen];
          if (c == 0) break;
          str[len++] = c;
        }
        str[len] = 0;
      } break;
H
hzcheng 已提交
686 687

      case TSDB_DATA_TYPE_TIMESTAMP:
688
        len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
H
hzcheng 已提交
689 690 691
        break;

      case TSDB_DATA_TYPE_BOOL:
692
        len += sprintf(str + len, "%d", *((int8_t *)row[i]));
H
hzcheng 已提交
693 694 695 696 697 698 699 700
      default:
        break;
    }
  }

  return len;
}

S
slguan 已提交
701
int taos_validate_sql(TAOS *taos, const char *sql) {
H
hzcheng 已提交
702 703
  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
704 705
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
706 707
  }

H
Haojun Liao 已提交
708 709
  SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
  
H
hzcheng 已提交
710
  SSqlRes *pRes = &pSql->res;
711 712
  SSqlCmd *pCmd = &pSql->cmd;
  
H
hzcheng 已提交
713
  pRes->numOfTotal = 0;
H
Haojun Liao 已提交
714
  pRes->numOfClauseTotal = 0;
715

716
  tscDebug("%p Valid SQL: %s pObj:%p", pSql, sql, pObj);
H
hzcheng 已提交
717 718

  int32_t sqlLen = strlen(sql);
H
hjxilinx 已提交
719
  if (sqlLen > tsMaxSQLStringLen) {
H
hzcheng 已提交
720
    tscError("%p sql too long", pSql);
721
    pRes->code = TSDB_CODE_TSC_INVALID_SQL;
B
Bomin Zhang 已提交
722
    tfree(pSql);
H
hzcheng 已提交
723 724 725 726 727
    return pRes->code;
  }

  pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
  if (pSql->sqlstr == NULL) {
728
    pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
H
hzcheng 已提交
729
    tscError("%p failed to malloc sql string buffer", pSql);
730
    tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
B
Bomin Zhang 已提交
731
    tfree(pSql);
H
hzcheng 已提交
732 733 734
    return pRes->code;
  }

S
slguan 已提交
735
  strtolower(pSql->sqlstr, sql);
H
hzcheng 已提交
736

737 738 739 740
  pCmd->curSql = NULL;
  if (NULL != pCmd->pTableList) {
    taosHashCleanup(pCmd->pTableList);
    pCmd->pTableList = NULL;
L
lihui 已提交
741 742
  }

743
  pRes->code = (uint8_t)tsParseSql(pSql, false);
H
hzcheng 已提交
744 745
  int code = pRes->code;

746
  tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
H
hzcheng 已提交
747 748 749 750
  taos_free_result(pSql);

  return code;
}
S
slguan 已提交
751

H
hjxilinx 已提交
752
static int tscParseTblNameList(SSqlObj *pSql, const char *tblNameList, int32_t tblListLen) {
S
slguan 已提交
753
  // must before clean the sqlcmd object
754
  tscResetSqlCmdObj(&pSql->cmd);
S
slguan 已提交
755 756 757 758 759 760

  SSqlCmd *pCmd = &pSql->cmd;

  pCmd->command = TSDB_SQL_MULTI_META;
  pCmd->count = 0;

761
  int   code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
H
hjxilinx 已提交
762
  char *str = (char *)tblNameList;
S
slguan 已提交
763

764 765 766
  SQueryInfo *pQueryInfo = NULL;
  tscGetQueryInfoDetailSafely(pCmd, pCmd->clauseIndex, &pQueryInfo);

H
hjxilinx 已提交
767
  STableMetaInfo *pTableMetaInfo = tscAddEmptyMetaInfo(pQueryInfo);
S
slguan 已提交
768

H
hjxilinx 已提交
769
  if ((code = tscAllocPayload(pCmd, tblListLen + 16)) != TSDB_CODE_SUCCESS) {
S
slguan 已提交
770 771 772 773
    return code;
  }

  char *nextStr;
S
slguan 已提交
774
  char  tblName[TSDB_TABLE_ID_LEN];
S
slguan 已提交
775 776 777 778 779 780 781 782 783 784 785 786 787
  int   payloadLen = 0;
  char *pMsg = pCmd->payload;
  while (1) {
    nextStr = strchr(str, ',');
    if (nextStr == NULL) {
      break;
    }

    memcpy(tblName, str, nextStr - str);
    int32_t len = nextStr - str;
    tblName[len] = '\0';

    str = nextStr + 1;
H
Haojun Liao 已提交
788
    len = strtrim(tblName);
H
hjxilinx 已提交
789

S
slguan 已提交
790 791 792 793 794
    SSQLToken sToken = {.n = len, .type = TK_ID, .z = tblName};
    tSQLGetToken(tblName, &sToken.type);

    // Check if the table name available or not
    if (tscValidateName(&sToken) != TSDB_CODE_SUCCESS) {
795
      code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
S
slguan 已提交
796 797 798 799
      sprintf(pCmd->payload, "table name is invalid");
      return code;
    }

H
Haojun Liao 已提交
800
    if ((code = tscSetTableFullName(pTableMetaInfo, &sToken, pSql)) != TSDB_CODE_SUCCESS) {
S
slguan 已提交
801 802 803 804
      return code;
    }

    if (++pCmd->count > TSDB_MULTI_METERMETA_MAX_NUM) {
805
      code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
S
slguan 已提交
806 807 808 809
      sprintf(pCmd->payload, "tables over the max number");
      return code;
    }

H
hjxilinx 已提交
810
    if (payloadLen + strlen(pTableMetaInfo->name) + 128 >= pCmd->allocSize) {
S
slguan 已提交
811 812
      char *pNewMem = realloc(pCmd->payload, pCmd->allocSize + tblListLen);
      if (pNewMem == NULL) {
813
        code = TSDB_CODE_TSC_OUT_OF_MEMORY;
S
slguan 已提交
814 815 816 817 818 819 820 821 822
        sprintf(pCmd->payload, "failed to allocate memory");
        return code;
      }

      pCmd->payload = pNewMem;
      pCmd->allocSize = pCmd->allocSize + tblListLen;
      pMsg = pCmd->payload;
    }

H
hjxilinx 已提交
823
    payloadLen += sprintf(pMsg + payloadLen, "%s,", pTableMetaInfo->name);
S
slguan 已提交
824 825 826 827 828 829 830 831 832
  }

  *(pMsg + payloadLen) = '\0';
  pCmd->payloadLen = payloadLen + 1;

  return TSDB_CODE_SUCCESS;
}

int taos_load_table_info(TAOS *taos, const char *tableNameList) {
H
hjxilinx 已提交
833
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
S
slguan 已提交
834 835 836

  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
837 838
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
S
slguan 已提交
839 840
  }

H
Haojun Liao 已提交
841
  SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
S
slguan 已提交
842 843 844
  SSqlRes *pRes = &pSql->res;

  pRes->numOfTotal = 0;  // the number of getting table meta from server
H
Haojun Liao 已提交
845
  pRes->numOfClauseTotal = 0;
846

S
slguan 已提交
847 848 849
  pRes->code = 0;

  assert(pSql->fp == NULL);
850
  tscDebug("%p tableNameList: %s pObj:%p", pSql, tableNameList, pObj);
S
slguan 已提交
851 852 853 854

  int32_t tblListLen = strlen(tableNameList);
  if (tblListLen > MAX_TABLE_NAME_LENGTH) {
    tscError("%p tableNameList too long, length:%d, maximum allowed:%d", pSql, tblListLen, MAX_TABLE_NAME_LENGTH);
855
    pRes->code = TSDB_CODE_TSC_INVALID_SQL;
B
Bomin Zhang 已提交
856
    tfree(pSql);
S
slguan 已提交
857 858 859
    return pRes->code;
  }

H
hjxilinx 已提交
860
  char *str = calloc(1, tblListLen + 1);
S
slguan 已提交
861
  if (str == NULL) {
862
    pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
S
slguan 已提交
863
    tscError("%p failed to malloc sql string buffer", pSql);
B
Bomin Zhang 已提交
864
    tfree(pSql);
S
slguan 已提交
865 866 867 868
    return pRes->code;
  }

  strtolower(str, tableNameList);
H
hjxilinx 已提交
869
  pRes->code = (uint8_t)tscParseTblNameList(pSql, str, tblListLen);
S
slguan 已提交
870 871 872 873 874 875 876 877 878 879

  /*
   * set the qhandle to 0 before return in order to erase the qhandle value assigned in the previous successful query.
   * If qhandle is NOT set 0, the function of taos_free_result() will send message to server by calling tscProcessSql()
   * to free connection, which may cause segment fault, when the parse phrase is not even successfully executed.
   */
  pRes->qhandle = 0;
  free(str);

  if (pRes->code != TSDB_CODE_SUCCESS) {
B
Bomin Zhang 已提交
880
    tscFreeSqlObj(pSql);
S
slguan 已提交
881 882 883 884 885
    return pRes->code;
  }

  tscDoQuery(pSql);

886
  tscDebug("%p load multi metermeta result:%d %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
S
slguan 已提交
887
  if (pRes->code != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
888
    tscPartiallyFreeSqlObj(pSql);
S
slguan 已提交
889 890 891 892
  }

  return pRes->code;
}