tscSql.c 28.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
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 "ttimer.h"
H
Haojun Liao 已提交
30
#include "tscProfile.h"
31
#include "ttimer.h"
H
hzcheng 已提交
32

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

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

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

54 55
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) {
56
  taos_init();
57

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

63 64 65 66 67 68 69 70 71 72
  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;
73
    int   len = (int)strlen(auth);
74 75 76 77 78 79 80 81 82 83 84
    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 已提交
85
  }
86 87

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

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

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

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

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

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

  pthread_mutex_init(&pObj->mutex, NULL);

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

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

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

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

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

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

H
Haojun Liao 已提交
164
  return pSql;
H
hzcheng 已提交
165 166
}

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

174 175 176 177
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 已提交
178
  if (pSql != NULL) {
179
    pSql->fp = syncConnCallback;
H
Haojun Liao 已提交
180
    pSql->param = pSql;
181

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

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

206
  return NULL;
H
hzcheng 已提交
207
}
H
Haojun Liao 已提交
208

209
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
S
Shengliang Guan 已提交
210
  tscDebug("try to create a connection to %s:%u, user:%s db:%s", ip, port != 0 ? port : tsServerPort , user, db);
211 212 213 214 215 216 217 218 219 220 221 222
  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 已提交
223 224
}

225 226 227 228 229 230 231 232 233 234 235 236
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 已提交
237

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

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

H
Haojun Liao 已提交
261 262
  if (pObj == NULL) {
    tscDebug("(null) try to free tscObj and close dnodeConn");
H
hjxilinx 已提交
263 264
    return;
  }
H
hzcheng 已提交
265

H
Haojun Liao 已提交
266 267 268 269 270 271 272 273 274 275
  tscDebug("%p try to free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn);
  if (pObj->signature != pObj) {
    tscDebug("%p already closed or invalid tscObj", pObj);
    return;
  }

  // make sure that the close connection can only be executed once.
  pObj->signature = NULL;
  taosTmrStopA(&(pObj->pTimer));

276
  SSqlObj* pHb = pObj->pHb;
277
  if (pHb != NULL && atomic_val_compare_exchange_ptr(&pObj->pHb, pHb, 0) == pHb) {
278 279
    if (pHb->pRpcCtx != NULL) {  // wait for rsp from dnode
      rpcCancelRequest(pHb->pRpcCtx);
280
      pHb->pRpcCtx = NULL;
281 282
    }

283
    tscDebug("%p HB is freed", pHb);
284
    taos_free_result(pHb);
H
hzcheng 已提交
285
  }
286

H
Haojun Liao 已提交
287 288 289 290
  int32_t ref = T_REF_DEC(pObj);
  assert(ref >= 0);

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

H
Haojun Liao 已提交
295
  tscDebug("%p all sqlObj are freed, free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn);
296
  tscCloseTscObj(pObj);
H
hzcheng 已提交
297 298
}

H
Hui Li 已提交
299
void waitForQueryRsp(void *param, TAOS_RES *tres, int code) {
H
Hui Li 已提交
300
  assert(tres != NULL);
H
[td-99]  
hjxilinx 已提交
301
  
H
Haojun Liao 已提交
302
  SSqlObj *pSql = (SSqlObj *) tres;
S
TD-1057  
Shengliang Guan 已提交
303
  tsem_post(&pSql->rspSem);
304 305
}

306 307
static void waitForRetrieveRsp(void *param, TAOS_RES *tres, int numOfRows) {
  SSqlObj* pSql = (SSqlObj*) tres;
S
TD-1057  
Shengliang Guan 已提交
308
  tsem_post(&pSql->rspSem);
309 310
}

H
Haojun Liao 已提交
311
TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen, TAOS_RES** res) {
S
slguan 已提交
312 313
  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
314
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
Haojun Liao 已提交
315
    return NULL;
S
slguan 已提交
316
  }
317
  
S
TD-1057  
Shengliang Guan 已提交
318
  if (sqlLen > (uint32_t)tsMaxSQLStringLen) {
H
Haojun Liao 已提交
319
    tscError("sql string exceeds max length:%d", tsMaxSQLStringLen);
320
    terrno = TSDB_CODE_TSC_INVALID_SQL;
H
Haojun Liao 已提交
321 322
    return NULL;
  }
323

H
Haojun Liao 已提交
324
  taosNotePrintTsc(sqlstr);
S
slguan 已提交
325

H
Haojun Liao 已提交
326 327 328
  SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
  if (pSql == NULL) {
    tscError("failed to malloc sqlObj");
329
    terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
H
Haojun Liao 已提交
330 331 332
    return NULL;
  }
  
S
TD-1057  
Shengliang Guan 已提交
333
  tsem_init(&pSql->rspSem, 0, 0);
H
[TD-98]  
hjxilinx 已提交
334
  doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen);
S
slguan 已提交
335

H
Haojun Liao 已提交
336 337 338 339
  if (res != NULL) {
    *res = pSql;
  }

H
Haojun Liao 已提交
340
  tsem_wait(&pSql->rspSem);
341
  return pSql; 
H
hzcheng 已提交
342
}
343

344
TAOS_RES* taos_query(TAOS *taos, const char *sqlstr) {
H
Haojun Liao 已提交
345 346 347 348 349
  return taos_query_c(taos, sqlstr, (uint32_t)strlen(sqlstr), NULL);
}

TAOS_RES* taos_query_h(TAOS* taos, const char *sqlstr, TAOS_RES** res) {
  return taos_query_c(taos, sqlstr, (uint32_t) strlen(sqlstr), res);
dengyihao's avatar
dengyihao 已提交
350
}
351

H
hzcheng 已提交
352 353 354 355 356 357 358 359 360 361 362 363 364
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 已提交
365
  int32_t num = 0;
366
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
367
  if (pQueryInfo == NULL) {
H
hjxilinx 已提交
368
    return num;
369
  }
370

H
hjxilinx 已提交
371 372 373 374 375 376 377 378 379
  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 已提交
380 381
}

H
Haojun Liao 已提交
382 383 384
int taos_field_count(TAOS_RES *tres) {
  SSqlObj* pSql = (SSqlObj*) tres;
  if (pSql == NULL || pSql->signature != pSql) return 0;
H
hzcheng 已提交
385

H
Haojun Liao 已提交
386
  return taos_num_fields(pSql);
H
hzcheng 已提交
387 388
}

H
Haojun Liao 已提交
389 390 391
int taos_affected_rows(TAOS_RES *tres) {
  SSqlObj* pSql = (SSqlObj*) tres;
  if (pSql == NULL || pSql->signature != pSql) return 0;
H
hzcheng 已提交
392

S
TD-1057  
Shengliang Guan 已提交
393
  return (int)(pSql->res.numOfRows);
H
hzcheng 已提交
394 395 396 397 398
}

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

  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
H
hjxilinx 已提交
401
  if (pQueryInfo == NULL) {
sangshuduo's avatar
sangshuduo 已提交
402
    return NULL;
H
hjxilinx 已提交
403 404 405 406 407 408 409 410
  }
  
  size_t numOfCols = tscNumOfFields(pQueryInfo);
  if (numOfCols == 0) {
    return NULL;
  }
  
  return pQueryInfo->fieldsInfo.pFields->pData;
H
hzcheng 已提交
411 412 413 414 415 416 417 418 419 420
}

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

H
hzcheng 已提交
423 424 425 426 427
  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 已提交
428
  return (int)pRes->numOfRows;
H
hzcheng 已提交
429 430 431 432 433 434 435
}

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 已提交
436
  if (pRes->qhandle == 0 || pSql->signature != pSql) {
H
hzcheng 已提交
437 438 439 440 441
    *rows = NULL;
    return 0;
  }

  // Retrieve new block
S
slguan 已提交
442
  tscResetForNextRetrieve(pRes);
H
hzcheng 已提交
443 444 445 446 447 448 449 450 451 452
  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 已提交
453
  // secondary merge has handle this situation
H
hjxilinx 已提交
454
  if (pCmd->command != TSDB_SQL_RETRIEVE_LOCALMERGE) {
H
Haojun Liao 已提交
455
    pRes->numOfClauseTotal += pRes->numOfRows;
S
slguan 已提交
456 457
  }

458
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
sangshuduo's avatar
sangshuduo 已提交
459 460 461
  if (pQueryInfo == NULL)
    return 0;

H
hjxilinx 已提交
462
  assert(0);
H
hjxilinx 已提交
463
  for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
464
    tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i);
H
hzcheng 已提交
465 466 467 468
  }

  *rows = pRes->tsrow;

S
TD-1057  
Shengliang Guan 已提交
469
  return (int)((pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows);
H
hzcheng 已提交
470 471 472 473 474
}

TAOS_ROW taos_fetch_row(TAOS_RES *res) {
  SSqlObj *pSql = (SSqlObj *)res;
  if (pSql == NULL || pSql->signature != pSql) {
475
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
476 477
    return NULL;
  }
478 479 480 481
  
  SSqlCmd *pCmd = &pSql->cmd;
  SSqlRes *pRes = &pSql->res;
  
482 483
  if (pRes->qhandle == 0 ||
      pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED ||
H
hjxilinx 已提交
484 485
      pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
      pCmd->command == TSDB_SQL_INSERT) {
486
    return NULL;
487
  }
488 489 490 491

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

492
  // current data set are exhausted, fetch more data from node
H
Haojun Liao 已提交
493
  if (pRes->row >= pRes->numOfRows && (pRes->completed != true || hasMoreVnodesToTry(pSql) || hasMoreClauseToTry(pSql)) &&
H
hjxilinx 已提交
494
      (pCmd->command == TSDB_SQL_RETRIEVE ||
H
hjxilinx 已提交
495
       pCmd->command == TSDB_SQL_RETRIEVE_LOCALMERGE ||
496
       pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE ||
H
hjxilinx 已提交
497 498
       pCmd->command == TSDB_SQL_FETCH ||
       pCmd->command == TSDB_SQL_SHOW ||
499 500
       pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE ||
       pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE ||
H
hjxilinx 已提交
501
       pCmd->command == TSDB_SQL_SELECT ||
H
Haojun Liao 已提交
502 503 504 505 506 507
       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 已提交
508
    taos_fetch_rows_a(res, waitForRetrieveRsp, pSql->pTscObj);
S
TD-1057  
Shengliang Guan 已提交
509
    tsem_wait(&pSql->rspSem);
H
hjxilinx 已提交
510
  }
H
Haojun Liao 已提交
511

512 513 514 515
  void* data = doSetResultRowData(pSql, true);

  tscClearSqlOwner(pSql);
  return data;
H
hzcheng 已提交
516 517 518
}

int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
H
hjxilinx 已提交
519
#if 0
H
hzcheng 已提交
520
  SSqlObj *pSql = (SSqlObj *)res;
H
hjxilinx 已提交
521
  SSqlCmd *pCmd = &pSql->cmd;
522
  SSqlRes *pRes = &pSql->res;
523

H
hzcheng 已提交
524 525 526
  int nRows = 0;

  if (pSql == NULL || pSql->signature != pSql) {
527
    terrno = TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
528 529 530 531
    *rows = NULL;
    return 0;
  }

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

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

540
    pSql->cmd.command = pQueryInfo->command;
H
hjxilinx 已提交
541
    pCmd->clauseIndex++;
542

H
Haojun Liao 已提交
543 544
    pRes->numOfTotal += pRes->numOfClauseTotal;
    pRes->numOfClauseTotal = 0;
545
    pRes->rspType = 0;
546

H
Haojun Liao 已提交
547
    pSql->subState.numOfSub = 0;
S
Shengliang Guan 已提交
548
    taosTFree(pSql->pSubs);
549

H
hjxilinx 已提交
550
    assert(pSql->fp == NULL);
551

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

H
hjxilinx 已提交
555
    nRows = taos_fetch_block_impl(res, rows);
H
hzcheng 已提交
556
  }
557

H
hzcheng 已提交
558
  return nRows;
H
hjxilinx 已提交
559 560 561 562
#endif

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

S
slguan 已提交
565
int taos_select_db(TAOS *taos, const char *db) {
566
  char sql[256] = {0};
H
hzcheng 已提交
567 568 569

  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
570 571
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
572 573
  }

574
  snprintf(sql, tListLen(sql), "use %s", db);
H
Haojun Liao 已提交
575 576 577 578 579
  SSqlObj* pSql = taos_query(taos, sql);
  int32_t code = pSql->res.code;
  taos_free_result(pSql);
  
  return code;
H
hzcheng 已提交
580 581
}

H
Haojun Liao 已提交
582
// send free message to vnode to free qhandle and corresponding resources in vnode
H
Haojun Liao 已提交
583
static UNUSED_FUNC bool tscKillQueryInDnode(SSqlObj* pSql) {
H
Haojun Liao 已提交
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
  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 已提交
607
    tscDebug("%p send msg to dnode to free qhandle ASAP before free sqlObj, command:%s", pSql, sqlCmd[pCmd->command]);
H
Haojun Liao 已提交
608 609 610 611 612 613 614

    tscProcessSql(pSql);
    return false;
  }

  return true;
}
H
Haojun Liao 已提交
615

H
Haojun Liao 已提交
616
void taos_free_result(TAOS_RES *res) {
H
Haojun Liao 已提交
617 618 619
  SSqlObj* pSql = (SSqlObj*) res;
  if (pSql == NULL || pSql->signature != pSql) {
    tscError("%p already released sqlObj", res);
H
hzcheng 已提交
620 621 622
    return;
  }

H
Haojun Liao 已提交
623 624 625
  bool freeNow = tscKillQueryInDnode(pSql);
  if (freeNow) {
    tscDebug("%p free sqlObj in cache", pSql);
H
Haojun Liao 已提交
626 627
    SSqlObj** p = pSql->self;
    taosCacheRelease(tscObjCache, (void**) &p, true);
H
Haojun Liao 已提交
628
  }
H
hzcheng 已提交
629 630
}

H
Haojun Liao 已提交
631 632 633
int taos_errno(TAOS_RES *tres) {
  SSqlObj *pSql = (SSqlObj *) tres;
  if (pSql == NULL || pSql->signature != pSql) {
H
[td-99]  
hjxilinx 已提交
634 635
    return terrno;
  }
H
hzcheng 已提交
636

H
Haojun Liao 已提交
637
  return pSql->res.code;
H
hzcheng 已提交
638 639
}

H
hjxilinx 已提交
640
/*
Y
TD-934  
yihaoDeng 已提交
641
 * In case of invalid sql/sql syntax error, additional information is attached to explain
H
hjxilinx 已提交
642 643
 * why the sql is invalid
 */
H
hjxilinx 已提交
644
static bool hasAdditionalErrorInfo(int32_t code, SSqlCmd *pCmd) {
Y
TD-934  
yihaoDeng 已提交
645 646
  if (code != TSDB_CODE_TSC_INVALID_SQL
      && code != TSDB_CODE_TSC_SQL_SYNTAX_ERROR) {
H
hjxilinx 已提交
647 648 649 650
    return false;
  }

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

  char *z = NULL;
H
hjxilinx 已提交
653
  if (len > 0) {
Y
TD-934  
yihaoDeng 已提交
654 655 656 657
      z = strstr(pCmd->payload, "invalid SQL");
      if (z == NULL) {
        z = strstr(pCmd->payload, "syntax error");
      }
H
hjxilinx 已提交
658 659 660 661
  }
  return z != NULL;
}

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

H
Haojun Liao 已提交
666 667 668
  if (pSql == NULL || pSql->signature != pSql) {
    return (char*) tstrerror(terrno);
  }
H
hzcheng 已提交
669

H
[td-32]  
hjxilinx 已提交
670
  if (hasAdditionalErrorInfo(pSql->res.code, &pSql->cmd)) {
H
hjxilinx 已提交
671
    return pSql->cmd.payload;
H
hzcheng 已提交
672
  } else {
H
[td-32]  
hjxilinx 已提交
673
    return (char*)tstrerror(pSql->res.code);
H
hzcheng 已提交
674 675 676 677 678
  }
}

void taos_config(int debug, char *log_path) {
  uDebugFlag = debug;
B
Bomin Zhang 已提交
679
  tstrncpy(tsLogDir, log_path, TSDB_FILENAME_LEN);
H
hzcheng 已提交
680 681 682 683 684 685 686 687 688 689
}

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

  if (pObj == NULL) return NULL;

  return pObj->sversion;
}

690 691 692 693 694 695 696 697 698
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 已提交
699 700
char *taos_get_client_info() { return version; }

H
Haojun Liao 已提交
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
static void tscKillSTableQuery(SSqlObj *pSql) {
  SSqlCmd* pCmd = &pSql->cmd;

  SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
  if (!tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
    return;
  }

  // set the master sqlObj flag to cancel query
  pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;

  for (int i = 0; i < pSql->subState.numOfSub; ++i) {
    // NOTE: pSub may have been released already here
    SSqlObj *pSub = pSql->pSubs[i];
    if (pSub == NULL) {
      continue;
    }

    void** p = taosCacheAcquireByKey(tscObjCache, &pSub, sizeof(TSDB_CACHE_PTR_TYPE));
    if (p == NULL) {
      continue;
    }

    SSqlObj* pSubObj = (SSqlObj*) (*p);
    assert(pSubObj->self == (SSqlObj**) p);

    pSubObj->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
    if (pSubObj->pRpcCtx != NULL) {
      rpcCancelRequest(pSubObj->pRpcCtx);
      pSubObj->pRpcCtx = NULL;
    }

    tscQueueAsyncRes(pSubObj);
    taosCacheRelease(tscObjCache, (void**) &p, false);
  }

  tscDebug("%p super table query cancelled", pSql);
}

H
hzcheng 已提交
740
void taos_stop_query(TAOS_RES *res) {
H
Haojun Liao 已提交
741 742
  SSqlObj *pSql = (SSqlObj *)res;
  if (pSql == NULL || pSql->signature != pSql) {
743 744
    return;
  }
H
hzcheng 已提交
745

746
  tscDebug("%p start to cancel query", res);
747 748
  SSqlCmd *pCmd = &pSql->cmd;

749 750
  // set the error code for master pSqlObj firstly
  pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
H
hzcheng 已提交
751

H
Haojun Liao 已提交
752
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
H
hjxilinx 已提交
753
  if (tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
754
    assert(pSql->pRpcCtx == NULL);
H
hjxilinx 已提交
755
    tscKillSTableQuery(pSql);
756 757
  } else {
    if (pSql->cmd.command < TSDB_SQL_LOCAL) {
H
Haojun Liao 已提交
758 759 760 761 762
      /*
       * There is multi-thread problem here, since pSql->pRpcCtx may have been
       * reset and freed in the processMsgFromServer function, and causes the invalid
       * write problem for rpcCancelRequest.
       */
H
Haojun Liao 已提交
763 764 765 766
      if (pSql->pRpcCtx != NULL) {
        rpcCancelRequest(pSql->pRpcCtx);
        pSql->pRpcCtx = NULL;
      }
H
Haojun Liao 已提交
767 768

      tscQueueAsyncRes(pSql);
769
    }
H
hzcheng 已提交
770 771
  }

772
  tscDebug("%p query is cancelled", res);
H
hzcheng 已提交
773 774 775 776 777
}

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) {
778 779 780 781
    if (i > 0) {
      str[len++] = ' ';
    }

H
hzcheng 已提交
782
    if (row[i] == NULL) {
783
      len += sprintf(str + len, "%s", TSDB_DATA_NULL_STR);
H
hzcheng 已提交
784 785 786 787 788
      continue;
    }

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

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

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

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

L
lihui 已提交
804 805
      case TSDB_DATA_TYPE_FLOAT: {
        float fv = 0;
L
lihui 已提交
806
        fv = GET_FLOAT_VAL(row[i]);
807
        len += sprintf(str + len, "%f", fv);
808
      } break;
H
hzcheng 已提交
809

810
      case TSDB_DATA_TYPE_DOUBLE: {
L
lihui 已提交
811
        double dv = 0;
L
lihui 已提交
812
        dv = GET_DOUBLE_VAL(row[i]);
813
        len += sprintf(str + len, "%lf", dv);
814
      } break;
H
hzcheng 已提交
815 816

      case TSDB_DATA_TYPE_BINARY:
S
slguan 已提交
817
      case TSDB_DATA_TYPE_NCHAR: {
H
hjxilinx 已提交
818
        size_t xlen = 0;
819
        for (xlen = 0; xlen < fields[i].bytes - VARSTR_HEADER_SIZE; xlen++) {
H
hjxilinx 已提交
820 821 822 823 824 825
          char c = ((char *)row[i])[xlen];
          if (c == 0) break;
          str[len++] = c;
        }
        str[len] = 0;
      } break;
H
hzcheng 已提交
826 827

      case TSDB_DATA_TYPE_TIMESTAMP:
828
        len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
H
hzcheng 已提交
829 830 831
        break;

      case TSDB_DATA_TYPE_BOOL:
832
        len += sprintf(str + len, "%d", *((int8_t *)row[i]));
H
hzcheng 已提交
833 834 835 836 837 838 839 840
      default:
        break;
    }
  }

  return len;
}

841 842 843 844
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 已提交
845
  tsem_post(&pSql->rspSem);
846 847
}

S
slguan 已提交
848
int taos_validate_sql(TAOS *taos, const char *sql) {
H
hzcheng 已提交
849 850
  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
851 852
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
H
hzcheng 已提交
853 854
  }

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

857 858
  pSql->pTscObj = taos;
  pSql->signature = pSql;
H
Haojun Liao 已提交
859

H
hzcheng 已提交
860
  SSqlRes *pRes = &pSql->res;
861 862
  SSqlCmd *pCmd = &pSql->cmd;
  
H
hzcheng 已提交
863
  pRes->numOfTotal = 0;
H
Haojun Liao 已提交
864
  pRes->numOfClauseTotal = 0;
865

H
Haojun Liao 已提交
866

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

S
TD-1057  
Shengliang Guan 已提交
869
  int32_t sqlLen = (int32_t)strlen(sql);
H
hjxilinx 已提交
870
  if (sqlLen > tsMaxSQLStringLen) {
H
hzcheng 已提交
871
    tscError("%p sql too long", pSql);
872
    pRes->code = TSDB_CODE_TSC_INVALID_SQL;
S
Shengliang Guan 已提交
873
    taosTFree(pSql);
H
hzcheng 已提交
874 875 876 877 878
    return pRes->code;
  }

  pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
  if (pSql->sqlstr == NULL) {
879
    pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
H
hzcheng 已提交
880
    tscError("%p failed to malloc sql string buffer", pSql);
881
    tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
S
Shengliang Guan 已提交
882
    taosTFree(pSql);
H
hzcheng 已提交
883 884 885
    return pRes->code;
  }

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

888 889 890 891
  pCmd->curSql = NULL;
  if (NULL != pCmd->pTableList) {
    taosHashCleanup(pCmd->pTableList);
    pCmd->pTableList = NULL;
L
lihui 已提交
892 893
  }

894 895 896
  pSql->fp = asyncCallback;
  pSql->fetchFp = asyncCallback;
  pSql->param = pSql;
Y
TD-1711  
yihaoDeng 已提交
897 898

  registerSqlObj(pSql);
899 900
  int code = tsParseSql(pSql, true);
  if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
S
TD-1057  
Shengliang Guan 已提交
901
    tsem_wait(&pSql->rspSem);
902 903
    code = pSql->res.code;
  }
H
Haojun Liao 已提交
904

905 906 907
  if (code != TSDB_CODE_SUCCESS) {
    tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, code, taos_errstr(taos), pObj);
  }
H
hzcheng 已提交
908

H
Haojun Liao 已提交
909
  taos_free_result(pSql);
H
hzcheng 已提交
910 911
  return code;
}
S
slguan 已提交
912

H
hjxilinx 已提交
913
static int tscParseTblNameList(SSqlObj *pSql, const char *tblNameList, int32_t tblListLen) {
S
slguan 已提交
914
  // must before clean the sqlcmd object
B
Bomin Zhang 已提交
915
  tscResetSqlCmdObj(&pSql->cmd, false);
S
slguan 已提交
916 917 918 919 920 921

  SSqlCmd *pCmd = &pSql->cmd;

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

922
  int   code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
H
hjxilinx 已提交
923
  char *str = (char *)tblNameList;
S
slguan 已提交
924

925 926 927 928 929
  SQueryInfo *pQueryInfo = tscGetQueryInfoDetailSafely(pCmd, pCmd->clauseIndex);
  if (pQueryInfo == NULL) {
    pSql->res.code = terrno;
    return terrno;
  }
930

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

H
hjxilinx 已提交
933
  if ((code = tscAllocPayload(pCmd, tblListLen + 16)) != TSDB_CODE_SUCCESS) {
S
slguan 已提交
934 935 936 937
    return code;
  }

  char *nextStr;
H
Haojun Liao 已提交
938
  char  tblName[TSDB_TABLE_FNAME_LEN];
S
slguan 已提交
939 940 941 942 943 944 945 946 947
  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 已提交
948
    int32_t len = (int32_t)(nextStr - str);
S
slguan 已提交
949 950 951
    tblName[len] = '\0';

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

H
Haojun Liao 已提交
954
    SStrToken sToken = {.n = len, .type = TK_ID, .z = tblName};
S
slguan 已提交
955 956 957 958
    tSQLGetToken(tblName, &sToken.type);

    // Check if the table name available or not
    if (tscValidateName(&sToken) != TSDB_CODE_SUCCESS) {
959
      code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
S
slguan 已提交
960 961 962 963
      sprintf(pCmd->payload, "table name is invalid");
      return code;
    }

H
Haojun Liao 已提交
964
    if ((code = tscSetTableFullName(pTableMetaInfo, &sToken, pSql)) != TSDB_CODE_SUCCESS) {
S
slguan 已提交
965 966 967 968
      return code;
    }

    if (++pCmd->count > TSDB_MULTI_METERMETA_MAX_NUM) {
969
      code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
S
slguan 已提交
970 971 972 973
      sprintf(pCmd->payload, "tables over the max number");
      return code;
    }

H
hjxilinx 已提交
974
    if (payloadLen + strlen(pTableMetaInfo->name) + 128 >= pCmd->allocSize) {
S
slguan 已提交
975 976
      char *pNewMem = realloc(pCmd->payload, pCmd->allocSize + tblListLen);
      if (pNewMem == NULL) {
977
        code = TSDB_CODE_TSC_OUT_OF_MEMORY;
S
slguan 已提交
978 979 980 981 982 983 984 985 986
        sprintf(pCmd->payload, "failed to allocate memory");
        return code;
      }

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

H
hjxilinx 已提交
987
    payloadLen += sprintf(pMsg + payloadLen, "%s,", pTableMetaInfo->name);
S
slguan 已提交
988 989 990 991 992 993 994 995 996
  }

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

  return TSDB_CODE_SUCCESS;
}

int taos_load_table_info(TAOS *taos, const char *tableNameList) {
H
hjxilinx 已提交
997
  const int32_t MAX_TABLE_NAME_LENGTH = 12 * 1024 * 1024;  // 12MB list
S
slguan 已提交
998 999 1000

  STscObj *pObj = (STscObj *)taos;
  if (pObj == NULL || pObj->signature != pObj) {
1001 1002
    terrno = TSDB_CODE_TSC_DISCONNECTED;
    return TSDB_CODE_TSC_DISCONNECTED;
S
slguan 已提交
1003 1004
  }

H
Haojun Liao 已提交
1005
  SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
1006 1007
  pSql->pTscObj = taos;
  pSql->signature = pSql;
H
Haojun Liao 已提交
1008

S
slguan 已提交
1009 1010
  SSqlRes *pRes = &pSql->res;

H
Haojun Liao 已提交
1011
  pRes->code = 0;
S
slguan 已提交
1012
  pRes->numOfTotal = 0;  // the number of getting table meta from server
H
Haojun Liao 已提交
1013
  pRes->numOfClauseTotal = 0;
1014

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

S
TD-1057  
Shengliang Guan 已提交
1018
  int32_t tblListLen = (int32_t)strlen(tableNameList);
S
slguan 已提交
1019 1020
  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 已提交
1021 1022
    tscFreeSqlObj(pSql);
    return TSDB_CODE_TSC_INVALID_SQL;
S
slguan 已提交
1023 1024
  }

H
hjxilinx 已提交
1025
  char *str = calloc(1, tblListLen + 1);
S
slguan 已提交
1026 1027
  if (str == NULL) {
    tscError("%p failed to malloc sql string buffer", pSql);
H
Haojun Liao 已提交
1028 1029
    tscFreeSqlObj(pSql);
    return TSDB_CODE_TSC_OUT_OF_MEMORY;
S
slguan 已提交
1030 1031 1032
  }

  strtolower(str, tableNameList);
H
Haojun Liao 已提交
1033
  int32_t code = (uint8_t) tscParseTblNameList(pSql, str, tblListLen);
S
slguan 已提交
1034 1035 1036 1037 1038 1039 1040 1041 1042

  /*
   * 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 已提交
1043
  if (code != TSDB_CODE_SUCCESS) {
B
Bomin Zhang 已提交
1044
    tscFreeSqlObj(pSql);
H
Haojun Liao 已提交
1045
    return code;
S
slguan 已提交
1046 1047 1048 1049
  }

  tscDoQuery(pSql);

H
Haojun Liao 已提交
1050 1051 1052
  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 已提交
1053 1054
  }

H
Haojun Liao 已提交
1055
  return code;
S
slguan 已提交
1056
}