tscSql.c 26.5 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
Haojun Liao 已提交
18
#include "qAst.h"
19
#include "tkey.h"
H
hzcheng 已提交
20
#include "tcache.h"
H
hjxilinx 已提交
21
#include "tnote.h"
H
hzcheng 已提交
22
#include "trpc.h"
S
slguan 已提交
23
#include "tscLog.h"
H
hjxilinx 已提交
24
#include "tscSubquery.h"
H
hzcheng 已提交
25 26
#include "tscUtil.h"
#include "tsclient.h"
27
#include "ttokendef.h"
H
hjxilinx 已提交
28
#include "tutil.h"
H
Haojun Liao 已提交
29
#include "tscProfile.h"
H
hzcheng 已提交
30

31 32 33 34 35 36 37 38 39 40 41 42
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 已提交
43

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

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

52 53
SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, const char *auth, const char *db,
                         uint16_t port, void (*fp)(void *, TAOS_RES *, int), void *param, void **taos) {
54
  taos_init();
55

56
  if (!validUserName(user)) {
57
    terrno = TSDB_CODE_TSC_INVALID_USER_LENGTH;
H
hzcheng 已提交
58 59 60
    return NULL;
  }

61 62 63 64 65 66 67 68 69 70
  char secretEncrypt[32] = {0};
  int  secretEncryptLen = 0;
  if (auth == NULL) {
    if (!validPassword(pass)) {
      terrno = TSDB_CODE_TSC_INVALID_PASS_LENGTH;
      return NULL;
    }
    taosEncryptPass((uint8_t *)pass, strlen(pass), secretEncrypt);
  } else {
    int   outlen = 0;
71
    int   len = (int)strlen(auth);
72 73 74 75 76 77 78 79 80 81 82
    char *base64 = (char *)base64_decode(auth, len, &outlen);
    if (base64 == NULL || outlen == 0) {
      tscError("invalid auth info:%s", auth);
      free(base64);
      terrno = TSDB_CODE_TSC_INVALID_PASS_LENGTH;
      return NULL;
    } else {
      memcpy(secretEncrypt, base64, outlen);
      free(base64);
    }
    secretEncryptLen = outlen;
H
hzcheng 已提交
83
  }
84 85

  if (ip) {
86
    if (tscSetMgmtEpSetFromCfg(ip, NULL) < 0) return NULL;
87
    if (port) tscMgmtEpSet.epSet.port[0] = port;
88 89
  } 
 
90
  void *pDnodeConn = NULL;
91
  if (tscInitRpc(user, secretEncrypt, &pDnodeConn) != 0) {
92
    terrno = TSDB_CODE_RPC_NETWORK_UNAVAIL;
S
slguan 已提交
93 94
    return NULL;
  }
95
 
96
  STscObj *pObj = (STscObj *)calloc(1, sizeof(STscObj));
S
slguan 已提交
97
  if (NULL == pObj) {
98
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
99
    rpcClose(pDnodeConn);
S
slguan 已提交
100 101
    return NULL;
  }
H
hjxilinx 已提交
102

H
hzcheng 已提交
103
  pObj->signature = pObj;
H
Haojun Liao 已提交
104
  pObj->pDnodeConn = pDnodeConn;
H
Haojun Liao 已提交
105
  T_REF_INIT_VAL(pObj, 1);
H
hzcheng 已提交
106

B
Bomin Zhang 已提交
107
  tstrncpy(pObj->user, user, sizeof(pObj->user));
108 109
  secretEncryptLen = MIN(secretEncryptLen, sizeof(pObj->pass));
  memcpy(pObj->pass, secretEncrypt, secretEncryptLen);
H
hzcheng 已提交
110 111

  if (db) {
S
TD-1057  
Shengliang Guan 已提交
112
    int32_t len = (int32_t)strlen(db);
H
hzcheng 已提交
113
    /* db name is too long */
B
Bomin Zhang 已提交
114
    if (len >= TSDB_DB_NAME_LEN) {
115
      terrno = TSDB_CODE_TSC_INVALID_DB_LENGTH;
116 117
      rpcClose(pDnodeConn);
      free(pObj);
H
hzcheng 已提交
118 119 120
      return NULL;
    }

B
Bomin Zhang 已提交
121 122
    char tmp[TSDB_DB_NAME_LEN] = {0};
    tstrncpy(tmp, db, sizeof(tmp));
H
hzcheng 已提交
123 124

    strdequote(tmp);
S
slguan 已提交
125
    strtolower(pObj->db, tmp);
H
hzcheng 已提交
126 127 128 129
  }

  pthread_mutex_init(&pObj->mutex, NULL);

130
  SSqlObj *pSql = (SSqlObj *)calloc(1, sizeof(SSqlObj));
S
slguan 已提交
131
  if (NULL == pSql) {
132
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
133
    rpcClose(pDnodeConn);
S
slguan 已提交
134 135 136
    free(pObj);
    return NULL;
  }
H
hjxilinx 已提交
137

H
Haojun Liao 已提交
138
  pSql->pTscObj   = pObj;
H
hzcheng 已提交
139
  pSql->signature = pSql;
H
Haojun Liao 已提交
140 141 142 143 144
  pSql->maxRetry  = TSDB_MAX_REPLICA;
  pSql->fp        = fp;
  pSql->param     = param;
  pSql->cmd.command = TSDB_SQL_CONNECT;

S
slguan 已提交
145
  tsem_init(&pSql->rspSem, 0, 0);
H
hzcheng 已提交
146

147
  if (TSDB_CODE_SUCCESS != tscAllocPayload(&pSql->cmd, TSDB_DEFAULT_PAYLOAD_SIZE)) {
148
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
149
    rpcClose(pDnodeConn);
S
slguan 已提交
150 151 152 153
    free(pSql);
    free(pObj);
    return NULL;
  }
H
hzcheng 已提交
154

H
Haojun Liao 已提交
155 156 157 158
  if (taos != NULL) {
    *taos = pObj;
  }

159
  registerSqlObj(pSql);
160
  tsInsertHeadSize = sizeof(SMsgDesc) + sizeof(SSubmitMsg);
H
Haojun Liao 已提交
161

H
Haojun Liao 已提交
162
  return pSql;
H
hzcheng 已提交
163 164
}

165
static void syncConnCallback(void *param, TAOS_RES *tres, int code) {
H
Haojun Liao 已提交
166 167
  SSqlObj *pSql = (SSqlObj *) tres;
  assert(pSql != NULL);
H
hjxilinx 已提交
168
  
S
TD-1057  
Shengliang Guan 已提交
169
  tsem_post(&pSql->rspSem);
170 171
}

172 173 174 175
TAOS *taos_connect_internal(const char *ip, const char *user, const char *pass, const char *auth, const char *db,
                            uint16_t port) {
  STscObj *pObj = NULL;
  SSqlObj *pSql = taosConnectImpl(ip, user, pass, auth, db, port, syncConnCallback, NULL, (void **)&pObj);
H
Haojun Liao 已提交
176
  if (pSql != NULL) {
177
    pSql->fp = syncConnCallback;
H
Haojun Liao 已提交
178
    pSql->param = pSql;
179

180
    tscProcessSql(pSql);
S
TD-1057  
Shengliang Guan 已提交
181
    tsem_wait(&pSql->rspSem);
182

183
    if (pSql->res.code != TSDB_CODE_SUCCESS) {
H
hjxilinx 已提交
184
      terrno = pSql->res.code;
H
Haojun Liao 已提交
185
      taos_free_result(pSql);
186 187 188 189
      taos_close(pObj);
      return NULL;
    }
    
190
    tscDebug("%p DB connection is opening, dnodeConn:%p", pObj, pObj->pDnodeConn);
H
Haojun Liao 已提交
191 192
    taos_free_result(pSql);
  
S
slguan 已提交
193
    // version compare only requires the first 3 segments of the version string
194
    int code = taosCheckVersion(version, taos_get_server_info(pObj), 3);
S
slguan 已提交
195
    if (code != 0) {
H
hjxilinx 已提交
196
      terrno = code;
197
      taos_close(pObj);
S
slguan 已提交
198
      return NULL;
199 200
    } else {
      return pObj;
S
slguan 已提交
201
    }
H
hzcheng 已提交
202 203
  }

204
  return NULL;
H
hzcheng 已提交
205
}
H
Haojun Liao 已提交
206

207
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
S
Shengliang Guan 已提交
208
  tscDebug("try to create a connection to %s:%u, user:%s db:%s", ip, port != 0 ? port : tsServerPort , user, db);
209 210 211 212 213 214 215 216 217 218 219 220
  if (user == NULL) user = TSDB_DEFAULT_USER;
  if (pass == NULL) pass = TSDB_DEFAULT_PASS;

  return taos_connect_internal(ip, user, pass, NULL, db, port);
}

TAOS *taos_connect_auth(const char *ip, const char *user, const char *auth, const char *db, uint16_t port) {
  tscDebug("try to create a connection to %s:%u by auth, user:%s db:%s", ip, port, user, db);
  if (user == NULL) user = TSDB_DEFAULT_USER;
  if (auth == NULL) return NULL;

  return taos_connect_internal(ip, user, NULL, auth, db, port);
dengyihao's avatar
dengyihao 已提交
221 222
}

223 224 225 226 227 228 229 230 231 232 233 234
TAOS *taos_connect_c(const char *ip, uint8_t ipLen, const char *user, uint8_t userLen, const char *pass,
                     uint8_t passLen, const char *db, uint8_t dbLen, uint16_t port) {
  char ipBuf[TSDB_EP_LEN] = {0};
  char userBuf[TSDB_USER_LEN] = {0};
  char passBuf[TSDB_PASSWORD_LEN] = {0};
  char dbBuf[TSDB_DB_NAME_LEN] = {0};
  strncpy(ipBuf, ip, MIN(TSDB_EP_LEN - 1, ipLen));
  strncpy(userBuf, user, MIN(TSDB_USER_LEN - 1, userLen));
  strncpy(passBuf, pass, MIN(TSDB_PASSWORD_LEN - 1, passLen));
  strncpy(dbBuf, db, MIN(TSDB_DB_NAME_LEN - 1, dbLen));
  return taos_connect(ipBuf, userBuf, passBuf, dbBuf, port);
}
H
hzcheng 已提交
235

236 237 238 239 240 241 242
static void asyncConnCallback(void *param, TAOS_RES *tres, int code) {
  SSqlObj *pSql = (SSqlObj *) tres;
  assert(pSql != NULL);
  
  pSql->fetchFp(pSql->param, tres, code);
}

L
lihui 已提交
243
TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
H
hzcheng 已提交
244
                     void *param, void **taos) {
245
  SSqlObj* pSql = taosConnectImpl(ip, user, pass, NULL, db, port, asyncConnCallback, param, taos);
H
Haojun Liao 已提交
246
  if (pSql == NULL) {
247 248 249
    return NULL;
  }
  
250
  pSql->fetchFp = fp;
251
  pSql->res.code = tscProcessSql(pSql);
252
  tscDebug("%p DB async connection is opening", taos);
H
Haojun Liao 已提交
253
  return taos;
H
hzcheng 已提交
254 255 256 257 258
}

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

H
hjxilinx 已提交
259 260 261
  if (pObj == NULL || pObj->signature != pObj)  {
    return;
  }
H
hzcheng 已提交
262

263
  SSqlObj* pHb = pObj->pHb;
264
  if (pHb != NULL && atomic_val_compare_exchange_ptr(&pObj->pHb, pHb, 0) == pHb) {
265 266
    if (pHb->pRpcCtx != NULL) {  // wait for rsp from dnode
      rpcCancelRequest(pHb->pRpcCtx);
267
      pHb->pRpcCtx = NULL;
268 269
    }

270
    tscDebug("%p HB is freed", pHb);
271
    taos_free_result(pHb);
H
hzcheng 已提交
272
  }
273

H
Haojun Liao 已提交
274 275 276 277
  int32_t ref = T_REF_DEC(pObj);
  assert(ref >= 0);

  if (ref > 0) {
H
Haojun Liao 已提交
278
    tscDebug("%p %d remain sqlObjs, not free tscObj and dnodeConn:%p", pObj, ref, pObj->pDnodeConn);
H
Haojun Liao 已提交
279 280 281
    return;
  }

H
Haojun Liao 已提交
282
  tscDebug("%p all sqlObj are freed, free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn);
283
  tscCloseTscObj(pObj);
H
hzcheng 已提交
284 285
}

H
Hui Li 已提交
286
void waitForQueryRsp(void *param, TAOS_RES *tres, int code) {
H
Hui Li 已提交
287
  assert(tres != NULL);
H
[td-99]  
hjxilinx 已提交
288
  
H
Haojun Liao 已提交
289
  SSqlObj *pSql = (SSqlObj *) tres;
S
TD-1057  
Shengliang Guan 已提交
290
  tsem_post(&pSql->rspSem);
291 292
}

293 294
static void waitForRetrieveRsp(void *param, TAOS_RES *tres, int numOfRows) {
  SSqlObj* pSql = (SSqlObj*) tres;
S
TD-1057  
Shengliang Guan 已提交
295
  tsem_post(&pSql->rspSem);
296 297
}

298
TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen) {
S
slguan 已提交
299 300
  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
301
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
Haojun Liao 已提交
302
    return NULL;
S
slguan 已提交
303
  }
304
  
S
TD-1057  
Shengliang Guan 已提交
305
  if (sqlLen > (uint32_t)tsMaxSQLStringLen) {
H
Haojun Liao 已提交
306
    tscError("sql string exceeds max length:%d", tsMaxSQLStringLen);
307
    terrno = TSDB_CODE_TSC_INVALID_SQL;
H
Haojun Liao 已提交
308 309
    return NULL;
  }
310

H
Haojun Liao 已提交
311
  taosNotePrintTsc(sqlstr);
S
slguan 已提交
312

H
Haojun Liao 已提交
313 314 315
  SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
  if (pSql == NULL) {
    tscError("failed to malloc sqlObj");
316
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
H
Haojun Liao 已提交
317 318 319
    return NULL;
  }
  
S
TD-1057  
Shengliang Guan 已提交
320
  tsem_init(&pSql->rspSem, 0, 0);
H
[TD-98]  
hjxilinx 已提交
321
  doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen);
S
slguan 已提交
322

H
Haojun Liao 已提交
323
  tsem_wait(&pSql->rspSem);
324
  return pSql; 
H
hzcheng 已提交
325
}
326

327
TAOS_RES* taos_query(TAOS *taos, const char *sqlstr) {
S
Shengliang Guan 已提交
328
  return taos_query_c(taos, sqlstr, (uint32_t)strlen(sqlstr));
dengyihao's avatar
dengyihao 已提交
329
}
330

H
hzcheng 已提交
331 332 333 334 335 336 337 338 339 340 341 342 343
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 已提交
344
  int32_t num = 0;
345
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
346
  if (pQueryInfo == NULL) {
H
hjxilinx 已提交
347
    return num;
348
  }
349

H
hjxilinx 已提交
350 351 352 353 354 355 356 357 358
  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 已提交
359 360
}

H
Haojun Liao 已提交
361 362 363
int taos_field_count(TAOS_RES *tres) {
  SSqlObj* pSql = (SSqlObj*) tres;
  if (pSql == NULL || pSql->signature != pSql) return 0;
H
hzcheng 已提交
364

H
Haojun Liao 已提交
365
  return taos_num_fields(pSql);
H
hzcheng 已提交
366 367
}

H
Haojun Liao 已提交
368 369 370
int taos_affected_rows(TAOS_RES *tres) {
  SSqlObj* pSql = (SSqlObj*) tres;
  if (pSql == NULL || pSql->signature != pSql) return 0;
H
hzcheng 已提交
371

S
TD-1057  
Shengliang Guan 已提交
372
  return (int)(pSql->res.numOfRows);
H
hzcheng 已提交
373 374 375 376 377
}

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

  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
H
hjxilinx 已提交
380
  if (pQueryInfo == NULL) {
sangshuduo's avatar
sangshuduo 已提交
381
    return NULL;
H
hjxilinx 已提交
382 383 384 385 386 387 388 389
  }
  
  size_t numOfCols = tscNumOfFields(pQueryInfo);
  if (numOfCols == 0) {
    return NULL;
  }
  
  return pQueryInfo->fieldsInfo.pFields->pData;
H
hzcheng 已提交
390 391 392 393 394 395 396 397 398 399
}

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 已提交
400 401
  tscResetForNextRetrieve(pRes);

H
hzcheng 已提交
402 403 404 405 406
  if (pCmd->command < TSDB_SQL_LOCAL) {
    pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
  }
  tscProcessSql(pSql);

S
TD-1057  
Shengliang Guan 已提交
407
  return (int)pRes->numOfRows;
H
hzcheng 已提交
408 409 410 411 412 413 414
}

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 已提交
415
  if (pRes->qhandle == 0 || pSql->signature != pSql) {
H
hzcheng 已提交
416 417 418 419 420
    *rows = NULL;
    return 0;
  }

  // Retrieve new block
S
slguan 已提交
421
  tscResetForNextRetrieve(pRes);
H
hzcheng 已提交
422 423 424 425 426 427 428 429 430 431
  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 已提交
432
  // secondary merge has handle this situation
H
hjxilinx 已提交
433
  if (pCmd->command != TSDB_SQL_RETRIEVE_LOCALMERGE) {
H
Haojun Liao 已提交
434
    pRes->numOfClauseTotal += pRes->numOfRows;
S
slguan 已提交
435 436
  }

437
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
sangshuduo's avatar
sangshuduo 已提交
438 439 440
  if (pQueryInfo == NULL)
    return 0;

H
hjxilinx 已提交
441
  assert(0);
H
hjxilinx 已提交
442
  for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
443
    tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i);
H
hzcheng 已提交
444 445 446 447
  }

  *rows = pRes->tsrow;

S
TD-1057  
Shengliang Guan 已提交
448
  return (int)((pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows);
H
hzcheng 已提交
449 450 451 452 453
}

TAOS_ROW taos_fetch_row(TAOS_RES *res) {
  SSqlObj *pSql = (SSqlObj *)res;
  if (pSql == NULL || pSql->signature != pSql) {
454
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
455 456
    return NULL;
  }
457 458 459 460
  
  SSqlCmd *pCmd = &pSql->cmd;
  SSqlRes *pRes = &pSql->res;
  
H
hjxilinx 已提交
461 462 463
  if (pRes->qhandle == 0 ||
      pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
      pCmd->command == TSDB_SQL_INSERT) {
464
    return NULL;
465
  }
466 467 468 469

  // set the sql object owner
  tscSetSqlOwner(pSql);

470
  // current data set are exhausted, fetch more data from node
H
Haojun Liao 已提交
471
  if (pRes->row >= pRes->numOfRows && (pRes->completed != true || hasMoreVnodesToTry(pSql) || hasMoreClauseToTry(pSql)) &&
H
hjxilinx 已提交
472
      (pCmd->command == TSDB_SQL_RETRIEVE ||
H
hjxilinx 已提交
473
       pCmd->command == TSDB_SQL_RETRIEVE_LOCALMERGE ||
474
       pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE ||
H
hjxilinx 已提交
475 476
       pCmd->command == TSDB_SQL_FETCH ||
       pCmd->command == TSDB_SQL_SHOW ||
477 478
       pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE ||
       pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE ||
H
hjxilinx 已提交
479
       pCmd->command == TSDB_SQL_SELECT ||
H
Haojun Liao 已提交
480 481 482 483 484 485
       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 已提交
486
    taos_fetch_rows_a(res, waitForRetrieveRsp, pSql->pTscObj);
S
TD-1057  
Shengliang Guan 已提交
487
    tsem_wait(&pSql->rspSem);
H
hjxilinx 已提交
488
  }
H
Haojun Liao 已提交
489

490 491 492 493
  void* data = doSetResultRowData(pSql, true);

  tscClearSqlOwner(pSql);
  return data;
H
hzcheng 已提交
494 495 496
}

int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
H
hjxilinx 已提交
497
#if 0
H
hzcheng 已提交
498
  SSqlObj *pSql = (SSqlObj *)res;
H
hjxilinx 已提交
499
  SSqlCmd *pCmd = &pSql->cmd;
500
  SSqlRes *pRes = &pSql->res;
501

H
hzcheng 已提交
502 503 504
  int nRows = 0;

  if (pSql == NULL || pSql->signature != pSql) {
505
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
506 507 508 509
    *rows = NULL;
    return 0;
  }

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

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

518
    pSql->cmd.command = pQueryInfo->command;
H
hjxilinx 已提交
519
    pCmd->clauseIndex++;
520

H
Haojun Liao 已提交
521 522
    pRes->numOfTotal += pRes->numOfClauseTotal;
    pRes->numOfClauseTotal = 0;
523
    pRes->rspType = 0;
524

525
    pSql->numOfSubs = 0;
S
Shengliang Guan 已提交
526
    taosTFree(pSql->pSubs);
527

H
hjxilinx 已提交
528
    assert(pSql->fp == NULL);
529

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

H
hjxilinx 已提交
533
    nRows = taos_fetch_block_impl(res, rows);
H
hzcheng 已提交
534
  }
535

H
hzcheng 已提交
536
  return nRows;
H
hjxilinx 已提交
537 538 539 540
#endif

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

S
slguan 已提交
543
int taos_select_db(TAOS *taos, const char *db) {
544
  char sql[256] = {0};
H
hzcheng 已提交
545 546 547

  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
548 549
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
550 551
  }

552
  snprintf(sql, tListLen(sql), "use %s", db);
H
Haojun Liao 已提交
553 554 555 556 557
  SSqlObj* pSql = taos_query(taos, sql);
  int32_t code = pSql->res.code;
  taos_free_result(pSql);
  
  return code;
H
hzcheng 已提交
558 559
}

H
Haojun Liao 已提交
560
// send free message to vnode to free qhandle and corresponding resources in vnode
H
Haojun Liao 已提交
561
static UNUSED_FUNC bool tscKillQueryInDnode(SSqlObj* pSql) {
H
Haojun Liao 已提交
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
  SSqlCmd* pCmd = &pSql->cmd;
  SSqlRes* pRes = &pSql->res;

  if (pRes == NULL || pRes->qhandle == 0) {
    return true;
  }

  SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
  if ((pQueryInfo == NULL) || tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
    return true;
  }

  STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
  tscRemoveFromSqlList(pSql);

  int32_t cmd = pCmd->command;
  if (pRes->code == TSDB_CODE_SUCCESS && pRes->completed == false && pSql->pStream == NULL && (pTableMetaInfo->pTableMeta != NULL) &&
      (cmd == TSDB_SQL_SELECT ||
       cmd == TSDB_SQL_SHOW ||
       cmd == TSDB_SQL_RETRIEVE ||
       cmd == TSDB_SQL_FETCH)) {
    pQueryInfo->type = TSDB_QUERY_TYPE_FREE_RESOURCE;
    pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
H
Haojun Liao 已提交
585
    tscDebug("%p send msg to dnode to free qhandle ASAP before free sqlObj, command:%s", pSql, sqlCmd[pCmd->command]);
H
Haojun Liao 已提交
586 587 588 589 590 591 592

    tscProcessSql(pSql);
    return false;
  }

  return true;
}
H
Haojun Liao 已提交
593

H
Haojun Liao 已提交
594
void taos_free_result(TAOS_RES *res) {
H
Haojun Liao 已提交
595 596 597
  SSqlObj* pSql = (SSqlObj*) res;
  if (pSql == NULL || pSql->signature != pSql) {
    tscError("%p already released sqlObj", res);
H
hzcheng 已提交
598 599 600
    return;
  }

H
Haojun Liao 已提交
601 602 603
  bool freeNow = tscKillQueryInDnode(pSql);
  if (freeNow) {
    tscDebug("%p free sqlObj in cache", pSql);
H
Haojun Liao 已提交
604 605
    SSqlObj** p = pSql->self;
    taosCacheRelease(tscObjCache, (void**) &p, true);
H
Haojun Liao 已提交
606
  }
H
hzcheng 已提交
607 608
}

H
Haojun Liao 已提交
609 610 611
int taos_errno(TAOS_RES *tres) {
  SSqlObj *pSql = (SSqlObj *) tres;
  if (pSql == NULL || pSql->signature != pSql) {
H
[td-99]  
hjxilinx 已提交
612 613
    return terrno;
  }
H
hzcheng 已提交
614

H
Haojun Liao 已提交
615
  return pSql->res.code;
H
hzcheng 已提交
616 617
}

H
hjxilinx 已提交
618
/*
Y
TD-934  
yihaoDeng 已提交
619
 * In case of invalid sql/sql syntax error, additional information is attached to explain
H
hjxilinx 已提交
620 621
 * why the sql is invalid
 */
H
hjxilinx 已提交
622
static bool hasAdditionalErrorInfo(int32_t code, SSqlCmd *pCmd) {
Y
TD-934  
yihaoDeng 已提交
623 624
  if (code != TSDB_CODE_TSC_INVALID_SQL
      && code != TSDB_CODE_TSC_SQL_SYNTAX_ERROR) {
H
hjxilinx 已提交
625 626 627 628
    return false;
  }

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

  char *z = NULL;
H
hjxilinx 已提交
631
  if (len > 0) {
Y
TD-934  
yihaoDeng 已提交
632 633 634 635
      z = strstr(pCmd->payload, "invalid SQL");
      if (z == NULL) {
        z = strstr(pCmd->payload, "syntax error");
      }
H
hjxilinx 已提交
636 637 638 639
  }
  return z != NULL;
}

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

H
Haojun Liao 已提交
644 645 646
  if (pSql == NULL || pSql->signature != pSql) {
    return (char*) tstrerror(terrno);
  }
H
hzcheng 已提交
647

H
[td-32]  
hjxilinx 已提交
648
  if (hasAdditionalErrorInfo(pSql->res.code, &pSql->cmd)) {
H
hjxilinx 已提交
649
    return pSql->cmd.payload;
H
hzcheng 已提交
650
  } else {
H
[td-32]  
hjxilinx 已提交
651
    return (char*)tstrerror(pSql->res.code);
H
hzcheng 已提交
652 653 654 655 656
  }
}

void taos_config(int debug, char *log_path) {
  uDebugFlag = debug;
B
Bomin Zhang 已提交
657
  tstrncpy(tsLogDir, log_path, TSDB_FILENAME_LEN);
H
hzcheng 已提交
658 659 660 661 662 663 664 665 666 667
}

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

  if (pObj == NULL) return NULL;

  return pObj->sversion;
}

668 669 670 671 672 673 674 675 676
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 已提交
677 678 679
char *taos_get_client_info() { return version; }

void taos_stop_query(TAOS_RES *res) {
H
Haojun Liao 已提交
680 681
  SSqlObj *pSql = (SSqlObj *)res;
  if (pSql == NULL || pSql->signature != pSql) {
682 683
    return;
  }
H
hzcheng 已提交
684

685
  tscDebug("%p start to cancel query", res);
686 687
  SSqlCmd *pCmd = &pSql->cmd;

H
Haojun Liao 已提交
688 689
  // TODO there are multi-thread problem.
  // It may have been released by the other thread already.
H
Haojun Liao 已提交
690
  // The ref count may fix this problem.
691
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
H
hzcheng 已提交
692

693 694
  // set the error code for master pSqlObj firstly
  pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
H
hzcheng 已提交
695

H
hjxilinx 已提交
696
  if (tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
697
    assert(pSql->pRpcCtx == NULL);
H
hjxilinx 已提交
698
    tscKillSTableQuery(pSql);
699 700
  } else {
    if (pSql->cmd.command < TSDB_SQL_LOCAL) {
H
Haojun Liao 已提交
701 702 703 704
      if (pSql->pRpcCtx != NULL) {
        rpcCancelRequest(pSql->pRpcCtx);
        pSql->pRpcCtx = NULL;
      }
705
    }
H
hzcheng 已提交
706 707
  }

708
  tscDebug("%p query is cancelled", res);
H
hzcheng 已提交
709 710 711 712 713
}

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) {
714 715 716 717
    if (i > 0) {
      str[len++] = ' ';
    }

H
hzcheng 已提交
718
    if (row[i] == NULL) {
719
      len += sprintf(str + len, "%s", TSDB_DATA_NULL_STR);
H
hzcheng 已提交
720 721 722 723 724
      continue;
    }

    switch (fields[i].type) {
      case TSDB_DATA_TYPE_TINYINT:
S
TD-1530  
Shengliang Guan 已提交
725
        len += sprintf(str + len, "%d", *((int8_t *)row[i]));
H
hzcheng 已提交
726 727 728
        break;

      case TSDB_DATA_TYPE_SMALLINT:
S
TD-1530  
Shengliang Guan 已提交
729
        len += sprintf(str + len, "%d", *((int16_t *)row[i]));
H
hzcheng 已提交
730 731 732
        break;

      case TSDB_DATA_TYPE_INT:
S
TD-1530  
Shengliang Guan 已提交
733
        len += sprintf(str + len, "%d", *((int32_t *)row[i]));
H
hzcheng 已提交
734 735 736
        break;

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

L
lihui 已提交
740 741
      case TSDB_DATA_TYPE_FLOAT: {
        float fv = 0;
L
lihui 已提交
742
        fv = GET_FLOAT_VAL(row[i]);
743
        len += sprintf(str + len, "%f", fv);
744
      } break;
H
hzcheng 已提交
745

746
      case TSDB_DATA_TYPE_DOUBLE: {
L
lihui 已提交
747
        double dv = 0;
L
lihui 已提交
748
        dv = GET_DOUBLE_VAL(row[i]);
749
        len += sprintf(str + len, "%lf", dv);
750
      } break;
H
hzcheng 已提交
751 752

      case TSDB_DATA_TYPE_BINARY:
S
slguan 已提交
753
      case TSDB_DATA_TYPE_NCHAR: {
H
hjxilinx 已提交
754
        size_t xlen = 0;
755
        for (xlen = 0; xlen < fields[i].bytes - VARSTR_HEADER_SIZE; xlen++) {
H
hjxilinx 已提交
756 757 758 759 760 761
          char c = ((char *)row[i])[xlen];
          if (c == 0) break;
          str[len++] = c;
        }
        str[len] = 0;
      } break;
H
hzcheng 已提交
762 763

      case TSDB_DATA_TYPE_TIMESTAMP:
764
        len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
H
hzcheng 已提交
765 766 767
        break;

      case TSDB_DATA_TYPE_BOOL:
768
        len += sprintf(str + len, "%d", *((int8_t *)row[i]));
H
hzcheng 已提交
769 770 771 772 773 774 775 776
      default:
        break;
    }
  }

  return len;
}

777 778 779 780
static void asyncCallback(void *param, TAOS_RES *tres, int code) {
  assert(param != NULL);
  SSqlObj *pSql = ((SSqlObj *)param);
  pSql->res.code = code;
S
TD-1057  
Shengliang Guan 已提交
781
  tsem_post(&pSql->rspSem);
782 783
}

S
slguan 已提交
784
int taos_validate_sql(TAOS *taos, const char *sql) {
H
hzcheng 已提交
785 786
  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
787 788
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
789 790
  }

H
Haojun Liao 已提交
791
  SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
H
Haojun Liao 已提交
792

793 794
  pSql->pTscObj = taos;
  pSql->signature = pSql;
H
Haojun Liao 已提交
795

H
hzcheng 已提交
796
  SSqlRes *pRes = &pSql->res;
797 798
  SSqlCmd *pCmd = &pSql->cmd;
  
H
hzcheng 已提交
799
  pRes->numOfTotal = 0;
H
Haojun Liao 已提交
800
  pRes->numOfClauseTotal = 0;
801

H
Haojun Liao 已提交
802

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

S
TD-1057  
Shengliang Guan 已提交
805
  int32_t sqlLen = (int32_t)strlen(sql);
H
hjxilinx 已提交
806
  if (sqlLen > tsMaxSQLStringLen) {
H
hzcheng 已提交
807
    tscError("%p sql too long", pSql);
808
    pRes->code = TSDB_CODE_TSC_INVALID_SQL;
S
Shengliang Guan 已提交
809
    taosTFree(pSql);
H
hzcheng 已提交
810 811 812 813 814
    return pRes->code;
  }

  pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
  if (pSql->sqlstr == NULL) {
815
    pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
H
hzcheng 已提交
816
    tscError("%p failed to malloc sql string buffer", pSql);
817
    tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
S
Shengliang Guan 已提交
818
    taosTFree(pSql);
H
hzcheng 已提交
819 820 821
    return pRes->code;
  }

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

824 825 826 827
  pCmd->curSql = NULL;
  if (NULL != pCmd->pTableList) {
    taosHashCleanup(pCmd->pTableList);
    pCmd->pTableList = NULL;
L
lihui 已提交
828 829
  }

830 831 832 833 834
  pSql->fp = asyncCallback;
  pSql->fetchFp = asyncCallback;
  pSql->param = pSql;
  int code = tsParseSql(pSql, true);
  if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
S
TD-1057  
Shengliang Guan 已提交
835
    tsem_wait(&pSql->rspSem);
836 837
    code = pSql->res.code;
  }
H
Haojun Liao 已提交
838

839 840 841
  if (code != TSDB_CODE_SUCCESS) {
    tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, code, taos_errstr(taos), pObj);
  }
H
hzcheng 已提交
842

H
Haojun Liao 已提交
843
  taos_free_result(pSql);
H
hzcheng 已提交
844 845
  return code;
}
S
slguan 已提交
846

H
hjxilinx 已提交
847
static int tscParseTblNameList(SSqlObj *pSql, const char *tblNameList, int32_t tblListLen) {
S
slguan 已提交
848
  // must before clean the sqlcmd object
B
Bomin Zhang 已提交
849
  tscResetSqlCmdObj(&pSql->cmd, false);
S
slguan 已提交
850 851 852 853 854 855

  SSqlCmd *pCmd = &pSql->cmd;

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

856
  int   code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
H
hjxilinx 已提交
857
  char *str = (char *)tblNameList;
S
slguan 已提交
858

859 860 861 862 863
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetailSafely(pCmd, pCmd->clauseIndex);
  if (pQueryInfo == NULL) {
    pSql->res.code = terrno;
    return terrno;
  }
864

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

H
hjxilinx 已提交
867
  if ((code = tscAllocPayload(pCmd, tblListLen + 16)) != TSDB_CODE_SUCCESS) {
S
slguan 已提交
868 869 870 871
    return code;
  }

  char *nextStr;
H
Haojun Liao 已提交
872
  char  tblName[TSDB_TABLE_FNAME_LEN];
S
slguan 已提交
873 874 875 876 877 878 879 880 881
  int   payloadLen = 0;
  char *pMsg = pCmd->payload;
  while (1) {
    nextStr = strchr(str, ',');
    if (nextStr == NULL) {
      break;
    }

    memcpy(tblName, str, nextStr - str);
S
TD-1057  
Shengliang Guan 已提交
882
    int32_t len = (int32_t)(nextStr - str);
S
slguan 已提交
883 884 885
    tblName[len] = '\0';

    str = nextStr + 1;
S
TD-1057  
Shengliang Guan 已提交
886
    len = (int32_t)strtrim(tblName);
H
hjxilinx 已提交
887

H
Haojun Liao 已提交
888
    SStrToken sToken = {.n = len, .type = TK_ID, .z = tblName};
S
slguan 已提交
889 890 891 892
    tSQLGetToken(tblName, &sToken.type);

    // Check if the table name available or not
    if (tscValidateName(&sToken) != TSDB_CODE_SUCCESS) {
893
      code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
S
slguan 已提交
894 895 896 897
      sprintf(pCmd->payload, "table name is invalid");
      return code;
    }

H
Haojun Liao 已提交
898
    if ((code = tscSetTableFullName(pTableMetaInfo, &sToken, pSql)) != TSDB_CODE_SUCCESS) {
S
slguan 已提交
899 900 901 902
      return code;
    }

    if (++pCmd->count > TSDB_MULTI_METERMETA_MAX_NUM) {
903
      code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
S
slguan 已提交
904 905 906 907
      sprintf(pCmd->payload, "tables over the max number");
      return code;
    }

H
hjxilinx 已提交
908
    if (payloadLen + strlen(pTableMetaInfo->name) + 128 >= pCmd->allocSize) {
S
slguan 已提交
909 910
      char *pNewMem = realloc(pCmd->payload, pCmd->allocSize + tblListLen);
      if (pNewMem == NULL) {
911
        code = TSDB_CODE_TSC_OUT_OF_MEMORY;
S
slguan 已提交
912 913 914 915 916 917 918 919 920
        sprintf(pCmd->payload, "failed to allocate memory");
        return code;
      }

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

H
hjxilinx 已提交
921
    payloadLen += sprintf(pMsg + payloadLen, "%s,", pTableMetaInfo->name);
S
slguan 已提交
922 923 924 925 926 927 928 929 930
  }

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

  return TSDB_CODE_SUCCESS;
}

int taos_load_table_info(TAOS *taos, const char *tableNameList) {
H
hjxilinx 已提交
931
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
S
slguan 已提交
932 933 934

  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
935 936
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
S
slguan 已提交
937 938
  }

H
Haojun Liao 已提交
939
  SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
940 941
  pSql->pTscObj = taos;
  pSql->signature = pSql;
H
Haojun Liao 已提交
942

S
slguan 已提交
943 944
  SSqlRes *pRes = &pSql->res;

H
Haojun Liao 已提交
945
  pRes->code = 0;
S
slguan 已提交
946
  pRes->numOfTotal = 0;  // the number of getting table meta from server
H
Haojun Liao 已提交
947
  pRes->numOfClauseTotal = 0;
948

S
slguan 已提交
949
  assert(pSql->fp == NULL);
950
  tscDebug("%p tableNameList: %s pObj:%p", pSql, tableNameList, pObj);
S
slguan 已提交
951

S
TD-1057  
Shengliang Guan 已提交
952
  int32_t tblListLen = (int32_t)strlen(tableNameList);
S
slguan 已提交
953 954
  if (tblListLen > MAX_TABLE_NAME_LENGTH) {
    tscError("%p tableNameList too long, length:%d, maximum allowed:%d", pSql, tblListLen, MAX_TABLE_NAME_LENGTH);
H
Haojun Liao 已提交
955 956
    tscFreeSqlObj(pSql);
    return TSDB_CODE_TSC_INVALID_SQL;
S
slguan 已提交
957 958
  }

H
hjxilinx 已提交
959
  char *str = calloc(1, tblListLen + 1);
S
slguan 已提交
960 961
  if (str == NULL) {
    tscError("%p failed to malloc sql string buffer", pSql);
H
Haojun Liao 已提交
962 963
    tscFreeSqlObj(pSql);
    return TSDB_CODE_TSC_OUT_OF_MEMORY;
S
slguan 已提交
964 965 966
  }

  strtolower(str, tableNameList);
H
Haojun Liao 已提交
967
  int32_t code = (uint8_t) tscParseTblNameList(pSql, str, tblListLen);
S
slguan 已提交
968 969 970 971 972 973 974 975 976

  /*
   * 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);

H
Haojun Liao 已提交
977
  if (code != TSDB_CODE_SUCCESS) {
B
Bomin Zhang 已提交
978
    tscFreeSqlObj(pSql);
H
Haojun Liao 已提交
979
    return code;
S
slguan 已提交
980 981 982 983
  }

  tscDoQuery(pSql);

H
Haojun Liao 已提交
984 985 986
  tscDebug("%p load multi table meta result:%d %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
  if ((code = pRes->code) != TSDB_CODE_SUCCESS) {
    tscFreeSqlObj(pSql);
S
slguan 已提交
987 988
  }

H
Haojun Liao 已提交
989
  return code;
S
slguan 已提交
990
}