[td-314] [td-437] refactor C API.

This commit is contained in:
Haojun Liao 2020-06-01 23:30:10 +08:00
parent 82d75cbdef
commit 0944c0cd84
12 changed files with 213 additions and 246 deletions

View File

@ -293,7 +293,6 @@ typedef struct STscObj {
char sversion[TSDB_VERSION_LEN]; char sversion[TSDB_VERSION_LEN];
char writeAuth : 1; char writeAuth : 1;
char superAuth : 1; char superAuth : 1;
struct SSqlObj * pSql;
struct SSqlObj * pHb; struct SSqlObj * pHb;
struct SSqlObj * sqlList; struct SSqlObj * sqlList;
struct SSqlStream *streamList; struct SSqlStream *streamList;
@ -408,7 +407,7 @@ void doAsyncQuery(STscObj *pObj, SSqlObj *pSql, void (*fp)(), void *param, const
void tscProcessMultiVnodesInsertFromFile(SSqlObj *pSql); void tscProcessMultiVnodesInsertFromFile(SSqlObj *pSql);
void tscKillSTableQuery(SSqlObj *pSql); void tscKillSTableQuery(SSqlObj *pSql);
void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen); void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen);
bool tscIsUpdateQuery(STscObj *pObj); bool tscIsUpdateQuery(SSqlObj* pSql);
bool tscHasReachLimitation(SQueryInfo *pQueryInfo, SSqlRes *pRes); bool tscHasReachLimitation(SQueryInfo *pQueryInfo, SSqlRes *pRes);
char *tscGetErrorMsgPayload(SSqlCmd *pCmd); char *tscGetErrorMsgPayload(SSqlCmd *pCmd);

View File

@ -268,18 +268,18 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(J
} }
jniTrace("jobj:%p, conn:%p, sql:%s", jobj, tscon, dst); jniTrace("jobj:%p, conn:%p, sql:%s", jobj, tscon, dst);
int code = taos_query(tscon, dst); SSqlObj *pSql = taos_query(tscon, dst);
if (code != 0) { if (pSql == NULL || pSql->res.code != TSDB_CODE_SUCCESS) {
jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, tscon, tstrerror(code), taos_errstr(tscon)); jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, tscon, tstrerror(pSql->res.code), taos_errstr(tscon));
free(dst); free(dst);
return JNI_TDENGINE_ERROR; return JNI_TDENGINE_ERROR;
} else { } else {
int32_t affectRows = 0; int32_t affectRows = 0;
SSqlObj *pSql = ((STscObj *)tscon)->pSql; int32_t code = pSql->res.code;
if (pSql->cmd.command == TSDB_SQL_INSERT) { if (pSql->cmd.command == TSDB_SQL_INSERT) {
affectRows = taos_affected_rows(tscon); affectRows = taos_affected_rows(pSql);
jniTrace("jobj:%p, conn:%p, code:%s, affect rows:%d", jobj, tscon, tstrerror(code), affectRows); jniTrace("jobj:%p, conn:%p, code:%s, affect rows:%d", jobj, tscon, tstrerror(code), affectRows);
} else { } else {
jniTrace("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); jniTrace("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code));
@ -306,20 +306,20 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(J
} }
JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con) { JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con) {
TAOS *tscon = (TAOS *)con; SSqlObj *pSql = (TAOS_RES *) con;
if (tscon == NULL) { if (pSql == NULL) {
jniError("jobj:%p, connection is closed", jobj); jniError("jobj:%p, connection is closed", jobj);
return JNI_CONNECTION_NULL; return JNI_CONNECTION_NULL;
} }
jlong ret = 0; jlong ret = 0;
STscObj* pObj = pSql->pTscObj;
if (tscIsUpdateQuery(tscon)) {
if (tscIsUpdateQuery(pSql)) {
ret = 0; // for update query, no result pointer ret = 0; // for update query, no result pointer
jniTrace("jobj:%p, conn:%p, no resultset", jobj, tscon); jniTrace("jobj:%p, conn:%p, no resultset", jobj, pObj);
} else { } else {
ret = (jlong) taos_use_result(tscon); jniTrace("jobj:%p, conn:%p, get resultset:%p", jobj, pObj, (void *) ret);
jniTrace("jobj:%p, conn:%p, get resultset:%p", jobj, tscon, (void *) ret);
} }
return ret; return ret;

View File

@ -220,9 +220,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcIpSet *pIpSet) {
if (pObj->signature != pObj) { if (pObj->signature != pObj) {
tscTrace("%p sql is already released or DB connection is closed, freed:%d pObj:%p signature:%p", pSql, pSql->freed, tscTrace("%p sql is already released or DB connection is closed, freed:%d pObj:%p signature:%p", pSql, pSql->freed,
pObj, pObj->signature); pObj, pObj->signature);
if (pSql != pObj->pSql) { tscFreeSqlObj(pSql);
tscFreeSqlObj(pSql);
}
rpcFreeCont(rpcMsg->pCont); rpcFreeCont(rpcMsg->pCont);
return; return;
} }
@ -257,6 +255,9 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcIpSet *pIpSet) {
rpcMsg->code = TSDB_CODE_NOT_READY; rpcMsg->code = TSDB_CODE_NOT_READY;
rpcFreeCont(rpcMsg->pCont); rpcFreeCont(rpcMsg->pCont);
return; return;
} else if (pCmd->command == TSDB_SQL_META) {
// rpcFreeCont(rpcMsg->pCont);
// return;
} else { } else {
tscWarn("%p it shall renew table meta, code:%s, retry:%d", pSql, tstrerror(rpcMsg->code), ++pSql->retry); tscWarn("%p it shall renew table meta, code:%s, retry:%d", pSql, tstrerror(rpcMsg->code), ++pSql->retry);
@ -331,7 +332,6 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcIpSet *pIpSet) {
rpcMsg->code = (*tscProcessMsgRsp[pCmd->command])(pSql); rpcMsg->code = (*tscProcessMsgRsp[pCmd->command])(pSql);
if (rpcMsg->code != TSDB_CODE_ACTION_IN_PROGRESS) { if (rpcMsg->code != TSDB_CODE_ACTION_IN_PROGRESS) {
void *taosres = tscKeepConn[pCmd->command] ? pSql : NULL;
rpcMsg->code = pRes->code ? pRes->code : pRes->numOfRows; rpcMsg->code = pRes->code ? pRes->code : pRes->numOfRows;
tscTrace("%p SQL result:%s res:%p", pSql, tstrerror(pRes->code), pSql); tscTrace("%p SQL result:%s res:%p", pSql, tstrerror(pRes->code), pSql);
@ -345,7 +345,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcIpSet *pIpSet) {
* the tscShouldBeFreed will success and tscFreeSqlObj free it immediately. * the tscShouldBeFreed will success and tscFreeSqlObj free it immediately.
*/ */
bool shouldFree = tscShouldBeFreed(pSql); bool shouldFree = tscShouldBeFreed(pSql);
(*pSql->fp)(pSql->param, taosres, rpcMsg->code); (*pSql->fp)(pSql->param, pSql, rpcMsg->code);
if (shouldFree) { if (shouldFree) {
tscTrace("%p sqlObj is automatically freed", pSql); tscTrace("%p sqlObj is automatically freed", pSql);

View File

@ -52,7 +52,7 @@ static bool validPassword(const char* passwd) {
return validImpl(passwd, TSDB_PASSWORD_LEN); return validImpl(passwd, TSDB_PASSWORD_LEN);
} }
STscObj *taosConnectImpl(const char *ip, const char *user, const char *pass, const char *db, uint16_t port, SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, const char *db, uint16_t port,
void (*fp)(void *, TAOS_RES *, int), void *param, void **taos) { void (*fp)(void *, TAOS_RES *, int), void *param, void **taos) {
taos_init(); taos_init();
@ -120,10 +120,8 @@ STscObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con
pSql->pTscObj = pObj; pSql->pTscObj = pObj;
pSql->signature = pSql; pSql->signature = pSql;
pSql->maxRetry = TSDB_MAX_REPLICA_NUM; pSql->maxRetry = TSDB_MAX_REPLICA_NUM;
tsem_init(&pSql->rspSem, 0, 0); tsem_init(&pSql->rspSem, 0, 0);
pObj->pSql = pSql;
pObj->pDnodeConn = pDnodeConn; pObj->pDnodeConn = pDnodeConn;
pSql->fp = fp; pSql->fp = fp;
@ -143,42 +141,38 @@ STscObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con
// tsRpcHeaderSize will be updated during RPC initialization, so only after it initialization, this value is valid // tsRpcHeaderSize will be updated during RPC initialization, so only after it initialization, this value is valid
tsInsertHeadSize = tsRpcHeadSize + sizeof(SMsgDesc) + sizeof(SSubmitMsg); tsInsertHeadSize = tsRpcHeadSize + sizeof(SMsgDesc) + sizeof(SSubmitMsg);
return pObj; return pSql;
} }
static void syncConnCallback(void *param, TAOS_RES *tres, int code) { static void syncConnCallback(void *param, TAOS_RES *tres, int code) {
STscObj *pObj = (STscObj *)param; SSqlObj *pSql = (SSqlObj *) tres;
assert(pObj != NULL && pObj->pSql != NULL); assert(pSql != NULL);
if (code < 0) { sem_post(&pSql->rspSem);
pObj->pSql->res.code = code;
}
sem_post(&pObj->pSql->rspSem);
} }
TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) { TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port) {
tscTrace("try to create a connection to %s:%u, user:%s db:%s", ip, port, user, db); tscTrace("try to create a connection to %s:%u, user:%s db:%s", ip, port, user, db);
STscObj *pObj = taosConnectImpl(ip, user, pass, db, port, NULL, NULL, NULL); STscObj* pObj = NULL;
if (pObj != NULL) { SSqlObj *pSql = taosConnectImpl(ip, user, pass, db, port, syncConnCallback, NULL, (void**) &pObj);
SSqlObj* pSql = pObj->pSql; if (pSql != NULL) {
assert(pSql != NULL);
pSql->fp = syncConnCallback; pSql->fp = syncConnCallback;
pSql->param = pObj; pSql->param = pSql;
tscProcessSql(pSql); tscProcessSql(pSql);
sem_wait(&pSql->rspSem); sem_wait(&pSql->rspSem);
if (pSql->res.code != TSDB_CODE_SUCCESS) { if (pSql->res.code != TSDB_CODE_SUCCESS) {
terrno = pSql->res.code; terrno = pSql->res.code;
taos_free_result(pSql);
taos_close(pObj); taos_close(pObj);
return NULL; return NULL;
} }
tscTrace("%p DB connection is opening, dnodeConn:%p", pObj, pObj->pDnodeConn); tscTrace("%p DB connection is opening, dnodeConn:%p", pObj, pObj->pDnodeConn);
taos_free_result(pSql);
// version compare only requires the first 3 segments of the version string // version compare only requires the first 3 segments of the version string
int code = taosCheckVersion(version, taos_get_server_info(pObj), 3); int code = taosCheckVersion(version, taos_get_server_info(pObj), 3);
if (code != 0) { if (code != 0) {
@ -195,17 +189,14 @@ TAOS *taos_connect(const char *ip, const char *user, const char *pass, const cha
TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int), TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
void *param, void **taos) { void *param, void **taos) {
STscObj* pObj = taosConnectImpl(ip, user, pass, db, port, fp, param, taos); SSqlObj* pSql = taosConnectImpl(ip, user, pass, db, port, fp, param, taos);
if (pObj == NULL) { if (pSql == NULL) {
return NULL; return NULL;
} }
SSqlObj* pSql = pObj->pSql;
pSql->res.code = tscProcessSql(pSql); pSql->res.code = tscProcessSql(pSql);
tscTrace("%p DB async connection is opening", pObj); tscTrace("%p DB async connection is opening", taos);
return taos;
return pObj;
} }
void taos_close(TAOS *taos) { void taos_close(TAOS *taos) {
@ -265,41 +256,32 @@ int taos_query_imp(STscObj *pObj, SSqlObj *pSql) {
} }
static void waitForQueryRsp(void *param, TAOS_RES *tres, int code) { static void waitForQueryRsp(void *param, TAOS_RES *tres, int code) {
assert(param != NULL); assert(tres != NULL);
SSqlObj *pSql = ((STscObj *)param)->pSql;
// valid error code is less than 0
if (code < 0) {
pSql->res.code = code;
}
SSqlObj *pSql = (SSqlObj *) tres;
sem_post(&pSql->rspSem); sem_post(&pSql->rspSem);
} }
int taos_query(TAOS *taos, const char *sqlstr) { TAOS_RES* taos_query(TAOS *taos, const char *sqlstr) {
STscObj *pObj = (STscObj *)taos;
if (pObj == NULL || pObj->signature != pObj) {
terrno = TSDB_CODE_DISCONNECTED;
return TSDB_CODE_DISCONNECTED;
}
SSqlObj* pSql = pObj->pSql;
size_t sqlLen = strlen(sqlstr);
doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen);
// wait for the callback function to post the semaphore
tsem_wait(&pSql->rspSem);
return pSql->res.code;
}
TAOS_RES *taos_use_result(TAOS *taos) {
STscObj *pObj = (STscObj *)taos; STscObj *pObj = (STscObj *)taos;
if (pObj == NULL || pObj->signature != pObj) { if (pObj == NULL || pObj->signature != pObj) {
terrno = TSDB_CODE_DISCONNECTED; terrno = TSDB_CODE_DISCONNECTED;
return NULL; return NULL;
} }
SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
if (pSql == NULL) {
tscError("failed to malloc sqlObj");
terrno = TSDB_CODE_CLI_OUT_OF_MEMORY;
return NULL;
}
size_t sqlLen = strlen(sqlstr);
doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen);
return pObj->pSql; // wait for the callback function to post the semaphore
tsem_wait(&pSql->rspSem);
return pSql;
} }
int taos_result_precision(TAOS_RES *res) { int taos_result_precision(TAOS_RES *res) {
@ -332,18 +314,18 @@ int taos_num_fields(TAOS_RES *res) {
return num; return num;
} }
int taos_field_count(TAOS *taos) { int taos_field_count(TAOS_RES *tres) {
STscObj *pObj = (STscObj *)taos; SSqlObj* pSql = (SSqlObj*) tres;
if (pObj == NULL || pObj->signature != pObj) return 0; if (pSql == NULL || pSql->signature != pSql) return 0;
return taos_num_fields(pObj->pSql); return taos_num_fields(pSql);
} }
int taos_affected_rows(TAOS *taos) { int taos_affected_rows(TAOS_RES *tres) {
STscObj *pObj = (STscObj *)taos; SSqlObj* pSql = (SSqlObj*) tres;
if (pObj == NULL || pObj->signature != pObj) return 0; if (pSql == NULL || pSql->signature != pSql) return 0;
return (pObj->pSql->res.numOfRows); return (pSql->res.numOfRows);
} }
TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) { TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
@ -385,9 +367,8 @@ int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) {
SSqlObj *pSql = (SSqlObj *)res; SSqlObj *pSql = (SSqlObj *)res;
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
STscObj *pObj = pSql->pTscObj;
if (pRes->qhandle == 0 || pObj->pSql != pSql) { if (pRes->qhandle == 0 || pSql->signature != pSql) {
*rows = NULL; *rows = NULL;
return 0; return 0;
} }
@ -521,7 +502,11 @@ int taos_select_db(TAOS *taos, const char *db) {
} }
snprintf(sql, tListLen(sql), "use %s", db); snprintf(sql, tListLen(sql), "use %s", db);
return taos_query(taos, sql); SSqlObj* pSql = taos_query(taos, sql);
int32_t code = pSql->res.code;
taos_free_result(pSql);
return code;
} }
void taos_free_result(TAOS_RES *res) { void taos_free_result(TAOS_RES *res) {
@ -533,83 +518,62 @@ void taos_free_result(TAOS_RES *res) {
tscTrace("%p start to free result", pSql); tscTrace("%p start to free result", pSql);
if (pSql->signature != pSql) return; if (pSql->signature != pSql) {
tscTrace("%p result has been freed", pSql);
STscObj* pObj = pSql->pTscObj; return;
if (pRes == NULL || pRes->qhandle == 0) { }
/* Query rsp is not received from vnode, so the qhandle is NULL */
tscTrace("%p qhandle is null, abort free, fp:%p", pSql, pSql->fp);
// The semaphore can not be changed while freeing async sub query objects.
if (pObj->pSql != pSql) {
tscTrace("%p SqlObj is freed by app", pSql);
tscFreeSqlObj(pSql);
} else {
tscPartiallyFreeSqlObj(pSql);
}
// The semaphore can not be changed while freeing async sub query objects.
if (pRes == NULL || pRes->qhandle == 0) {
tscTrace("%p SqlObj is freed by app, phandle is null", pSql);
tscFreeSqlObj(pSql);
return; return;
} }
// set freeFlag to 1 in retrieve message if there are un-retrieved results data in node // set freeFlag to 1 in retrieve message if there are un-retrieved results data in node
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0); SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
if (pQueryInfo == NULL) { if (pQueryInfo == NULL) {
tscPartiallyFreeSqlObj(pSql); tscFreeSqlObj(pSql);
return; return;
} }
pQueryInfo->type = TSDB_QUERY_TYPE_FREE_RESOURCE; pQueryInfo->type = TSDB_QUERY_TYPE_FREE_RESOURCE;
STscObj* pTscObj = pSql->pTscObj;
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
/* /*
* case 1. Partial data have been retrieved from vnodes, but not all data has been retrieved yet. * If the query process is cancelled by user in stable query, tscProcessSql should not be called
* We need to recycle the connection by noticing the vnode return 0 results. * for each subquery. Because the failure of execution tsProcessSql may trigger the callback function
* case 2. When the query response is received from vnodes and the numOfRows is set to 0, the user calls * be executed, and the retry efforts may result in double free the resources, e.g.,SRetrieveSupport
* taos_free_result before the taos_fetch_row is called in non-stream computing,
* we need to recycle the connection.
* case 3. If the query process is cancelled by user in stable query, tscProcessSql should not be called
* for each subquery. Because the failure of execution tsProcessSql may trigger the callback function
* be executed, and the retry efforts may result in double free the resources, e.g.,SRetrieveSupport
*/ */
if ((pCmd->command == TSDB_SQL_SELECT || if (pRes->code == TSDB_CODE_SUCCESS && pRes->completed == false &&
pCmd->command == TSDB_SQL_SHOW || (pCmd->command == TSDB_SQL_SELECT || pCmd->command == TSDB_SQL_SHOW ||
pCmd->command == TSDB_SQL_RETRIEVE || pCmd->command == TSDB_SQL_RETRIEVE || pCmd->command == TSDB_SQL_FETCH) &&
pCmd->command == TSDB_SQL_FETCH) && pRes->code == TSDB_CODE_SUCCESS && pRes->completed == false &&
(pCmd->command == TSDB_SQL_SELECT && pSql->pStream == NULL && pTableMetaInfo->pTableMeta != NULL)) { (pCmd->command == TSDB_SQL_SELECT && pSql->pStream == NULL && pTableMetaInfo->pTableMeta != NULL)) {
pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH; pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
tscTrace("%p send msg to free qhandle in vnode, code:%d, numOfRows:%d, command:%s", pSql, pRes->code, pRes->numOfRows, tscTrace("%p send msg to free qhandle in node, code:%d, command:%s", pSql, pRes->code, sqlCmd[pCmd->command]);
sqlCmd[pCmd->command]);
pSql->freed = 1; pSql->freed = 1;
tscProcessSql(pSql); tscProcessSql(pSql);
// waits for response and then goes on // in case of sync model query, waits for response and then goes on
if (pTscObj->pSql == pSql) { if (pSql->fp == waitForQueryRsp || pSql->fp == waitForRetrieveRsp) {
sem_wait(&pSql->rspSem); sem_wait(&pSql->rspSem);
} }
} else { // if no free resource msg is sent to vnode, we free this object immediately.
if (pTscObj->pSql != pSql) {
tscFreeSqlObj(pSql);
tscTrace("%p sql result is freed by app", pSql);
} else {
tscPartiallyFreeSqlObj(pSql);
tscTrace("%p sql result is freed by app", pSql);
}
} }
tscFreeSqlObj(pSql);
tscTrace("%p sql result is freed by app", pSql);
} }
// todo should not be used in async query // todo should not be used in async query
int taos_errno(TAOS *taos) { int taos_errno(TAOS_RES *tres) {
STscObj *pObj = (STscObj *)taos; SSqlObj *pSql = (SSqlObj *) tres;
if (pObj == NULL || pObj->signature != pObj) { if (pSql == NULL || pSql->signature != pSql) {
return terrno; return terrno;
} }
return pObj->pSql->res.code; return pSql->res.code;
} }
/* /*
@ -632,14 +596,13 @@ static bool hasAdditionalErrorInfo(int32_t code, SSqlCmd *pCmd) {
} }
// todo should not be used in async model // todo should not be used in async model
char *taos_errstr(TAOS *taos) { char *taos_errstr(TAOS_RES *tres) {
STscObj *pObj = (STscObj *)taos; SSqlObj *pSql = (SSqlObj *) tres;
if (pObj == NULL || pObj->signature != pObj) if (pSql == NULL || pSql->signature != pSql) {
return (char*)tstrerror(terrno); return (char*) tstrerror(terrno);
}
SSqlObj* pSql = pObj->pSql;
if (hasAdditionalErrorInfo(pSql->res.code, &pSql->cmd)) { if (hasAdditionalErrorInfo(pSql->res.code, &pSql->cmd)) {
return pSql->cmd.payload; return pSql->cmd.payload;
} else { } else {
@ -769,7 +732,8 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
return TSDB_CODE_DISCONNECTED; return TSDB_CODE_DISCONNECTED;
} }
SSqlObj *pSql = pObj->pSql; SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
SSqlCmd *pCmd = &pSql->cmd; SSqlCmd *pCmd = &pSql->cmd;
@ -902,7 +866,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
return TSDB_CODE_DISCONNECTED; return TSDB_CODE_DISCONNECTED;
} }
SSqlObj *pSql = pObj->pSql; SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
pRes->numOfTotal = 0; // the number of getting table meta from server pRes->numOfTotal = 0; // the number of getting table meta from server

View File

@ -459,14 +459,14 @@ static int64_t tscGetLaunchTimestamp(const SSqlStream *pStream) {
return (pStream->precision == TSDB_TIME_PRECISION_MICRO) ? timer / 1000L : timer; return (pStream->precision == TSDB_TIME_PRECISION_MICRO) ? timer / 1000L : timer;
} }
static void setErrorInfo(STscObj* pObj, int32_t code, char* info) { static void setErrorInfo(SSqlObj* pSql, int32_t code, char* info) {
if (pObj == NULL) { if (pSql == NULL) {
return; return;
} }
SSqlCmd* pCmd = &pObj->pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
pObj->pSql->res.code = code; pSql->res.code = code;
if (info != NULL) { if (info != NULL) {
strncpy(pCmd->payload, info, pCmd->payloadLen); strncpy(pCmd->payload, info, pCmd->payloadLen);
@ -480,7 +480,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
SSqlObj *pSql = (SSqlObj *)calloc(1, sizeof(SSqlObj)); SSqlObj *pSql = (SSqlObj *)calloc(1, sizeof(SSqlObj));
if (pSql == NULL) { if (pSql == NULL) {
setErrorInfo(pObj, TSDB_CODE_CLI_OUT_OF_MEMORY, NULL); setErrorInfo(pSql, TSDB_CODE_CLI_OUT_OF_MEMORY, NULL);
return NULL; return NULL;
} }
@ -490,14 +490,14 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
SSqlRes *pRes = &pSql->res; SSqlRes *pRes = &pSql->res;
int ret = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE); int ret = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE);
if (TSDB_CODE_SUCCESS != ret) { if (TSDB_CODE_SUCCESS != ret) {
setErrorInfo(pObj, ret, NULL); setErrorInfo(pSql, ret, NULL);
free(pSql); free(pSql);
return NULL; return NULL;
} }
pSql->sqlstr = strdup(sqlstr); pSql->sqlstr = strdup(sqlstr);
if (pSql->sqlstr == NULL) { if (pSql->sqlstr == NULL) {
setErrorInfo(pObj, TSDB_CODE_CLI_OUT_OF_MEMORY, NULL); setErrorInfo(pSql, TSDB_CODE_CLI_OUT_OF_MEMORY, NULL);
tfree(pSql); tfree(pSql);
return NULL; return NULL;
@ -511,7 +511,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
tscResetSqlCmdObj(&pSql->cmd); tscResetSqlCmdObj(&pSql->cmd);
ret = tscAllocPayload(&pSql->cmd, TSDB_DEFAULT_PAYLOAD_SIZE); ret = tscAllocPayload(&pSql->cmd, TSDB_DEFAULT_PAYLOAD_SIZE);
if (TSDB_CODE_SUCCESS != ret) { if (TSDB_CODE_SUCCESS != ret) {
setErrorInfo(pObj, ret, NULL); setErrorInfo(pSql, ret, NULL);
tscError("%p open stream failed, sql:%s, code:%d", pSql, sqlstr, TSDB_CODE_CLI_OUT_OF_MEMORY); tscError("%p open stream failed, sql:%s, code:%d", pSql, sqlstr, TSDB_CODE_CLI_OUT_OF_MEMORY);
tscFreeSqlObj(pSql); tscFreeSqlObj(pSql);
return NULL; return NULL;
@ -521,7 +521,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
SQLInfoDestroy(&SQLInfo); SQLInfoDestroy(&SQLInfo);
if (pRes->code != TSDB_CODE_SUCCESS) { if (pRes->code != TSDB_CODE_SUCCESS) {
setErrorInfo(pObj, pRes->code, pCmd->payload); setErrorInfo(pSql, pRes->code, pCmd->payload);
tscError("%p open stream failed, sql:%s, reason:%s, code:%d", pSql, sqlstr, pCmd->payload, pRes->code); tscError("%p open stream failed, sql:%s, reason:%s, code:%d", pSql, sqlstr, pCmd->payload, pRes->code);
tscFreeSqlObj(pSql); tscFreeSqlObj(pSql);
@ -530,7 +530,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
SSqlStream *pStream = (SSqlStream *)calloc(1, sizeof(SSqlStream)); SSqlStream *pStream = (SSqlStream *)calloc(1, sizeof(SSqlStream));
if (pStream == NULL) { if (pStream == NULL) {
setErrorInfo(pObj, TSDB_CODE_CLI_OUT_OF_MEMORY, NULL); setErrorInfo(pSql, TSDB_CODE_CLI_OUT_OF_MEMORY, NULL);
tscError("%p open stream failed, sql:%s, reason:%s, code:%d", pSql, sqlstr, pCmd->payload, pRes->code); tscError("%p open stream failed, sql:%s, reason:%s, code:%d", pSql, sqlstr, pCmd->payload, pRes->code);
tscFreeSqlObj(pSql); tscFreeSqlObj(pSql);

View File

@ -181,21 +181,23 @@ static SArray* getTableList( SSqlObj* pSql ) {
const char* p = strstr( pSql->sqlstr, " from " ); const char* p = strstr( pSql->sqlstr, " from " );
char* sql = alloca(strlen(p) + 32); char* sql = alloca(strlen(p) + 32);
sprintf(sql, "select tbid(tbname)%s", p); sprintf(sql, "select tbid(tbname)%s", p);
int code = taos_query( pSql->pTscObj, sql );
if (code != TSDB_CODE_SUCCESS) { SSqlObj* pSql1 = taos_query(pSql->pTscObj, sql);
tscError("failed to retrieve table id: %s", tstrerror(code)); if (terrno != TSDB_CODE_SUCCESS) {
tscError("failed to retrieve table id: %s", tstrerror(terrno));
return NULL; return NULL;
} }
TAOS_RES* res = taos_use_result( pSql->pTscObj );
TAOS_ROW row; TAOS_ROW row;
SArray* result = taosArrayInit( 128, sizeof(STidTags) ); SArray* result = taosArrayInit( 128, sizeof(STidTags) );
while ((row = taos_fetch_row(res))) { while ((row = taos_fetch_row(pSql1))) {
STidTags tags; STidTags tags;
memcpy(&tags, row[0], sizeof(tags)); memcpy(&tags, row[0], sizeof(tags));
taosArrayPush(result, &tags); taosArrayPush(result, &tags);
} }
taos_free_result(pSql1);
return result; return result;
} }

View File

@ -409,8 +409,10 @@ void tscPartiallyFreeSqlObj(SSqlObj* pSql) {
} }
void tscFreeSqlObj(SSqlObj* pSql) { void tscFreeSqlObj(SSqlObj* pSql) {
if (pSql == NULL || pSql->signature != pSql) return; if (pSql == NULL || pSql->signature != pSql) {
return;
}
tscTrace("%p start to free sql object", pSql); tscTrace("%p start to free sql object", pSql);
tscPartiallyFreeSqlObj(pSql); tscPartiallyFreeSqlObj(pSql);
@ -749,20 +751,7 @@ void tscCloseTscObj(STscObj* pObj) {
assert(pObj != NULL); assert(pObj != NULL);
pObj->signature = NULL; pObj->signature = NULL;
SSqlObj* pSql = pObj->pSql;
if (pSql) {
terrno = pSql->res.code;
sem_destroy(&pSql->rspSem);
}
taosTmrStopA(&(pObj->pTimer)); taosTmrStopA(&(pObj->pTimer));
tscFreeSqlObj(pSql);
if (pSql) {
sem_destroy(&pSql->rspSem);
}
pthread_mutex_destroy(&pObj->mutex); pthread_mutex_destroy(&pObj->mutex);
if (pObj->pDnodeConn != NULL) { if (pObj->pDnodeConn != NULL) {
@ -1474,22 +1463,27 @@ bool tscShouldFreeHeatBeat(SSqlObj* pHb) {
* If connection need to be recycled, the SqlObj also should be freed. * If connection need to be recycled, the SqlObj also should be freed.
*/ */
bool tscShouldBeFreed(SSqlObj* pSql) { bool tscShouldBeFreed(SSqlObj* pSql) {
if (pSql == NULL || pSql->signature != pSql || pSql->fp == NULL) { if (pSql == NULL || pSql->signature != pSql) {
return false; return false;
} }
assert(pSql->fp != NULL);
STscObj* pTscObj = pSql->pTscObj; STscObj* pTscObj = pSql->pTscObj;
if (pSql->pStream != NULL || pTscObj->pHb == pSql || pTscObj->pSql == pSql || pSql->pSubscription != NULL) { if (pSql->pStream != NULL || pTscObj->pHb == pSql || pSql->pSubscription != NULL) {
return false; return false;
} }
int32_t command = pSql->cmd.command; int32_t command = pSql->cmd.command;
if (command == TSDB_SQL_CONNECT || command == TSDB_SQL_INSERT) { if (command == TSDB_SQL_META || command == TSDB_SQL_STABLEVGROUP) {//TODO subquery should be freed here
return true; return true;
} else {
return tscKeepConn[command] == 0 ||
(pSql->res.code != TSDB_CODE_ACTION_IN_PROGRESS && pSql->res.code != TSDB_CODE_SUCCESS);
} }
// all subqueries should be automatically freed
// if (pSql->cmd.pQueryInfo != NULL && pSql->cmd.pQueryInfo[0]->type & TSDB_QUERY_TYPE_SUBQUERY) {
// return true;
// }
return false;
} }
/** /**
@ -1952,15 +1946,14 @@ int16_t tscGetJoinTagColIndexByUid(STagCond* pTagCond, uint64_t uid) {
} }
} }
bool tscIsUpdateQuery(STscObj* pObj) { bool tscIsUpdateQuery(SSqlObj* pSql) {
if (pObj == NULL || pObj->signature != pObj) { if (pSql == NULL || pSql->signature != pSql) {
terrno = TSDB_CODE_DISCONNECTED; terrno = TSDB_CODE_DISCONNECTED;
return TSDB_CODE_DISCONNECTED; return TSDB_CODE_DISCONNECTED;
} }
SSqlCmd* pCmd = &pObj->pSql->cmd; SSqlCmd* pCmd = &pSql->cmd;
return ((pCmd->command >= TSDB_SQL_INSERT && pCmd->command <= TSDB_SQL_DROP_DNODE) || return ((pCmd->command >= TSDB_SQL_INSERT && pCmd->command <= TSDB_SQL_DROP_DNODE) || TSDB_SQL_USE_DB == pCmd->command);
TSDB_SQL_USE_DB == pCmd->command);
} }
int32_t tscInvalidSQLErrMsg(char* msg, const char* additionalInfo, const char* sql) { int32_t tscInvalidSQLErrMsg(char* msg, const char* additionalInfo, const char* sql) {

View File

@ -88,14 +88,13 @@ int taos_stmt_execute(TAOS_STMT *stmt);
TAOS_RES * taos_stmt_use_result(TAOS_STMT *stmt); TAOS_RES * taos_stmt_use_result(TAOS_STMT *stmt);
int taos_stmt_close(TAOS_STMT *stmt); int taos_stmt_close(TAOS_STMT *stmt);
DLL_EXPORT int taos_query(TAOS *taos, const char *sql); DLL_EXPORT TAOS_RES *taos_query(TAOS *taos, const char *sql);
DLL_EXPORT TAOS_RES *taos_use_result(TAOS *taos);
DLL_EXPORT TAOS_ROW taos_fetch_row(TAOS_RES *res); DLL_EXPORT TAOS_ROW taos_fetch_row(TAOS_RES *res);
DLL_EXPORT int taos_result_precision(TAOS_RES *res); // get the time precision of result DLL_EXPORT int taos_result_precision(TAOS_RES *res); // get the time precision of result
DLL_EXPORT void taos_free_result(TAOS_RES *res); DLL_EXPORT void taos_free_result(TAOS_RES *res);
DLL_EXPORT int taos_field_count(TAOS *taos); DLL_EXPORT int taos_field_count(TAOS_RES *tres);
DLL_EXPORT int taos_num_fields(TAOS_RES *res); DLL_EXPORT int taos_num_fields(TAOS_RES *res);
DLL_EXPORT int taos_affected_rows(TAOS *taos); DLL_EXPORT int taos_affected_rows(TAOS_RES *taos);
DLL_EXPORT TAOS_FIELD *taos_fetch_fields(TAOS_RES *res); DLL_EXPORT TAOS_FIELD *taos_fetch_fields(TAOS_RES *res);
DLL_EXPORT int taos_select_db(TAOS *taos, const char *db); DLL_EXPORT int taos_select_db(TAOS *taos, const char *db);
DLL_EXPORT int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields); DLL_EXPORT int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields);
@ -112,9 +111,9 @@ int* taos_fetch_lengths(TAOS_RES *res);
// TODO: the return value should be `const` // TODO: the return value should be `const`
DLL_EXPORT char *taos_get_server_info(TAOS *taos); DLL_EXPORT char *taos_get_server_info(TAOS *taos);
DLL_EXPORT char *taos_get_client_info(); DLL_EXPORT char *taos_get_client_info();
DLL_EXPORT char *taos_errstr(TAOS *taos); DLL_EXPORT char *taos_errstr(TAOS_RES *tres);
DLL_EXPORT int taos_errno(TAOS *taos); DLL_EXPORT int taos_errno(TAOS_RES *tres);
DLL_EXPORT void taos_query_a(TAOS *taos, const char *sql, void (*fp)(void *param, TAOS_RES *, int code), void *param); DLL_EXPORT void taos_query_a(TAOS *taos, const char *sql, void (*fp)(void *param, TAOS_RES *, int code), void *param);
DLL_EXPORT void taos_fetch_rows_a(TAOS_RES *res, void (*fp)(void *param, TAOS_RES *, int numOfRows), void *param); DLL_EXPORT void taos_fetch_rows_a(TAOS_RES *res, void (*fp)(void *param, TAOS_RES *, int numOfRows), void *param);

View File

@ -275,22 +275,28 @@ void shellRunCommandOnServer(TAOS *con, char command[]) {
st = taosGetTimestampUs(); st = taosGetTimestampUs();
if (taos_query(con, command)) { TAOS_RES* pSql = taos_query(con, command);
taos_error(con); if (taos_errno(pSql)) {
taos_error(pSql);
return; return;
} }
if (regex_match(command, "^\\s*use\\s+[a-zA-Z0-9_]+\\s*;\\s*$", REG_EXTENDED | REG_ICASE)) { if (regex_match(command, "^\\s*use\\s+[a-zA-Z0-9_]+\\s*;\\s*$", REG_EXTENDED | REG_ICASE)) {
fprintf(stdout, "Database changed.\n\n"); fprintf(stdout, "Database changed.\n\n");
fflush(stdout); fflush(stdout);
taos_free_result(pSql);
return; return;
} }
int num_fields = taos_field_count(con); int num_fields = taos_field_count(pSql);
if (num_fields != 0) { // select and show kinds of commands if (num_fields != 0) { // select and show kinds of commands
int error_no = 0; int error_no = 0;
int numOfRows = shellDumpResult(con, fname, &error_no, printMode); int numOfRows = shellDumpResult(pSql, fname, &error_no, printMode);
if (numOfRows < 0) return; if (numOfRows < 0) {
taos_free_result(pSql);
return;
}
et = taosGetTimestampUs(); et = taosGetTimestampUs();
if (error_no == 0) { if (error_no == 0) {
@ -299,7 +305,7 @@ void shellRunCommandOnServer(TAOS *con, char command[]) {
printf("Query interrupted (%s), %d row(s) in set (%.6fs)\n", taos_errstr(con), numOfRows, (et - st) / 1E6); printf("Query interrupted (%s), %d row(s) in set (%.6fs)\n", taos_errstr(con), numOfRows, (et - st) / 1E6);
} }
} else { } else {
int num_rows_affacted = taos_affected_rows(con); int num_rows_affacted = taos_affected_rows(pSql);
et = taosGetTimestampUs(); et = taosGetTimestampUs();
printf("Query OK, %d row(s) affected (%.6fs)\n", num_rows_affacted, (et - st) / 1E6); printf("Query OK, %d row(s) affected (%.6fs)\n", num_rows_affacted, (et - st) / 1E6);
} }
@ -309,6 +315,8 @@ void shellRunCommandOnServer(TAOS *con, char command[]) {
if (fname != NULL) { if (fname != NULL) {
wordfree(&full_path); wordfree(&full_path);
} }
taos_free_result(pSql);
} }
/* Function to do regular expression check */ /* Function to do regular expression check */
@ -461,6 +469,7 @@ static int dumpResultToFile(const char* fname, TAOS_RES* result) {
} while( row != NULL); } while( row != NULL);
fclose(fp); fclose(fp);
taos_free_result(result);
return numOfRows; return numOfRows;
} }
@ -548,15 +557,15 @@ static void printField(const char* val, TAOS_FIELD* field, int width, int32_t le
} }
static int verticalPrintResult(TAOS_RES* result) { static int verticalPrintResult(TAOS_RES* tres) {
TAOS_ROW row = taos_fetch_row(result); TAOS_ROW row = taos_fetch_row(tres);
if (row == NULL) { if (row == NULL) {
return 0; return 0;
} }
int num_fields = taos_num_fields(result); int num_fields = taos_num_fields(tres);
TAOS_FIELD *fields = taos_fetch_fields(result); TAOS_FIELD *fields = taos_fetch_fields(tres);
int precision = taos_result_precision(result); int precision = taos_result_precision(tres);
int maxColNameLen = 0; int maxColNameLen = 0;
for (int col = 0; col < num_fields; col++) { for (int col = 0; col < num_fields; col++) {
@ -569,7 +578,7 @@ static int verticalPrintResult(TAOS_RES* result) {
int numOfRows = 0; int numOfRows = 0;
do { do {
printf("*************************** %d.row ***************************\n", numOfRows + 1); printf("*************************** %d.row ***************************\n", numOfRows + 1);
int32_t* length = taos_fetch_lengths(result); int32_t* length = taos_fetch_lengths(tres);
for (int i = 0; i < num_fields; i++) { for (int i = 0; i < num_fields; i++) {
TAOS_FIELD* field = fields + i; TAOS_FIELD* field = fields + i;
@ -581,7 +590,7 @@ static int verticalPrintResult(TAOS_RES* result) {
} }
numOfRows++; numOfRows++;
row = taos_fetch_row(result); row = taos_fetch_row(tres);
} while(row != NULL); } while(row != NULL);
return numOfRows; return numOfRows;
@ -656,15 +665,15 @@ static void printHeader(TAOS_FIELD* fields, int* width, int num_fields) {
} }
static int horizontalPrintResult(TAOS_RES* result) { static int horizontalPrintResult(TAOS_RES* tres) {
TAOS_ROW row = taos_fetch_row(result); TAOS_ROW row = taos_fetch_row(tres);
if (row == NULL) { if (row == NULL) {
return 0; return 0;
} }
int num_fields = taos_num_fields(result); int num_fields = taos_num_fields(tres);
TAOS_FIELD *fields = taos_fetch_fields(result); TAOS_FIELD *fields = taos_fetch_fields(tres);
int precision = taos_result_precision(result); int precision = taos_result_precision(tres);
int width[TSDB_MAX_COLUMNS]; int width[TSDB_MAX_COLUMNS];
for (int col = 0; col < num_fields; col++) { for (int col = 0; col < num_fields; col++) {
@ -675,7 +684,7 @@ static int horizontalPrintResult(TAOS_RES* result) {
int numOfRows = 0; int numOfRows = 0;
do { do {
int32_t* length = taos_fetch_lengths(result); int32_t* length = taos_fetch_lengths(tres);
for (int i = 0; i < num_fields; i++) { for (int i = 0; i < num_fields; i++) {
putchar(' '); putchar(' ');
printField(row[i], fields + i, width[i], length[i], precision); printField(row[i], fields + i, width[i], length[i], precision);
@ -684,32 +693,24 @@ static int horizontalPrintResult(TAOS_RES* result) {
} }
putchar('\n'); putchar('\n');
numOfRows++; numOfRows++;
row = taos_fetch_row(result); row = taos_fetch_row(tres);
} while(row != NULL); } while(row != NULL);
return numOfRows; return numOfRows;
} }
int shellDumpResult(TAOS *con, char *fname, int *error_no, bool vertical) { int shellDumpResult(TAOS_RES *tres, char *fname, int *error_no, bool vertical) {
int numOfRows = 0; int numOfRows = 0;
TAOS_RES* result = taos_use_result(con);
if (result == NULL) {
taos_error(con);
return -1;
}
if (fname != NULL) { if (fname != NULL) {
numOfRows = dumpResultToFile(fname, result); numOfRows = dumpResultToFile(fname, tres);
} else if(vertical) { } else if(vertical) {
numOfRows = verticalPrintResult(result); numOfRows = verticalPrintResult(tres);
} else { } else {
numOfRows = horizontalPrintResult(result); numOfRows = horizontalPrintResult(tres);
} }
*error_no = taos_errno(con); *error_no = taos_errno(tres);
taos_free_result(result);
return numOfRows; return numOfRows;
} }
@ -771,12 +772,11 @@ void write_history() {
fclose(f); fclose(f);
} }
void taos_error(TAOS *con) { void taos_error(TAOS_RES *tres) {
fprintf(stderr, "\nDB error: %s\n", taos_errstr(con)); fprintf(stderr, "\nDB error: %s\n", taos_errstr(tres));
/* free local resouce: allocated memory/metric-meta refcnt */ /* free local resouce: allocated memory/metric-meta refcnt */
TAOS_RES *pRes = taos_use_result(con); taos_free_result(tres);
taos_free_result(pRes);
} }
int isCommentLine(char *line) { int isCommentLine(char *line) {
@ -858,8 +858,9 @@ void shellGetGrantInfo(void *con) {
char sql[] = "show grants"; char sql[] = "show grants";
int code = taos_query(con, sql); TAOS_RES* pSql = taos_query(con, sql);
int code = taos_errno(pSql);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
if (code == TSDB_CODE_OPS_NOT_SUPPORT) { if (code == TSDB_CODE_OPS_NOT_SUPPORT) {
fprintf(stdout, "Server is Community Edition, version is %s\n\n", taos_get_server_info(con)); fprintf(stdout, "Server is Community Edition, version is %s\n\n", taos_get_server_info(con));
@ -869,12 +870,11 @@ void shellGetGrantInfo(void *con) {
return; return;
} }
int num_fields = taos_field_count(con); int num_fields = taos_field_count(result);
if (num_fields == 0) { if (num_fields == 0) {
fprintf(stderr, "\nInvalid grant information.\n"); fprintf(stderr, "\nInvalid grant information.\n");
exit(0); exit(0);
} else { } else {
result = taos_use_result(con);
if (result == NULL) { if (result == NULL) {
fprintf(stderr, "\nGrant information is null.\n"); fprintf(stderr, "\nGrant information is null.\n");
exit(0); exit(0);

View File

@ -192,11 +192,14 @@ static void shellSourceFile(TAOS *con, char *fptr) {
} }
memcpy(cmd + cmd_len, line, read_len); memcpy(cmd + cmd_len, line, read_len);
if (taos_query(con, cmd)) {
TAOS_RES* pSql = taos_query(con, cmd);
int32_t code = taos_errno(pSql);
if (code != 0) {
fprintf(stderr, "DB error: %s: %s (%d)\n", taos_errstr(con), fname, lineNo); fprintf(stderr, "DB error: %s: %s (%d)\n", taos_errstr(con), fname, lineNo);
/* free local resouce: allocated memory/metric-meta refcnt */ /* free local resouce: allocated memory/metric-meta refcnt */
TAOS_RES *pRes = taos_use_result(con); taos_free_result(pSql);
taos_free_result(pRes);
} }
memset(cmd, 0, MAX_COMMAND_SIZE); memset(cmd, 0, MAX_COMMAND_SIZE);

View File

@ -18,21 +18,21 @@
#include "tsclient.h" #include "tsclient.h"
#include "tutil.h" #include "tutil.h"
TAOS* con; TAOS_RES* con;
pthread_t pid; pthread_t pid;
// TODO: IMPLEMENT INTERRUPT HANDLER. // TODO: IMPLEMENT INTERRUPT HANDLER.
void interruptHandler(int signum) { void interruptHandler(int signum) {
#ifdef LINUX #ifdef LINUX
TAOS_RES* res = taos_use_result(con); taos_stop_query(con);
taos_stop_query(res); if (con != NULL) {
if (res != NULL) {
/* /*
* we need to free result in async model, in order to avoid free * we need to free result in async model, in order to avoid free
* results while the master thread is waiting for server response. * results while the master thread is waiting for server response.
*/ */
tscQueueAsyncFreeResult(res); tscQueueAsyncFreeResult(con);
} }
result = NULL; result = NULL;
#else #else
printf("\nReceive ctrl+c or other signal, quit shell.\n"); printf("\nReceive ctrl+c or other signal, quit shell.\n");
@ -90,7 +90,6 @@ int main(int argc, char* argv[]) {
/* Initialize the shell */ /* Initialize the shell */
con = shellInit(&args); con = shellInit(&args);
if (con == NULL) { if (con == NULL) {
taos_error(con);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -635,9 +635,13 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) {
SCmdLine *line = &script->lines[script->linePos]; SCmdLine *line = &script->lines[script->linePos];
int ret = -1; int ret = -1;
TAOS_RES* pSql = NULL;
for (int attempt = 0; attempt < 3; ++attempt) { for (int attempt = 0; attempt < 3; ++attempt) {
simLogSql(rest); simLogSql(rest);
ret = taos_query(script->taos, rest); pSql = taos_query(script->taos, rest);
ret = terrno;
if (ret == TSDB_CODE_TABLE_ALREADY_EXIST || if (ret == TSDB_CODE_TABLE_ALREADY_EXIST ||
ret == TSDB_CODE_DB_ALREADY_EXIST) { ret == TSDB_CODE_DB_ALREADY_EXIST) {
simTrace("script:%s, taos:%p, %s success, ret:%d:%s", script->fileName, script->taos, rest, ret, tstrerror(ret)); simTrace("script:%s, taos:%p, %s success, ret:%d:%s", script->fileName, script->taos, rest, ret, tstrerror(ret));
@ -663,10 +667,9 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) {
} }
int numOfRows = 0; int numOfRows = 0;
int num_fields = taos_field_count(script->taos); int num_fields = taos_field_count(pSql);
if (num_fields != 0) { if (num_fields != 0) {
TAOS_RES *result = taos_use_result(script->taos); if (pSql == NULL) {
if (result == NULL) {
simTrace("script:%s, taos:%p, %s failed, result is null", script->fileName, script->taos, rest); simTrace("script:%s, taos:%p, %s failed, result is null", script->fileName, script->taos, rest);
if (line->errorJump == SQL_JUMP_TRUE) { if (line->errorJump == SQL_JUMP_TRUE) {
script->linePos = line->jump; script->linePos = line->jump;
@ -679,10 +682,10 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) {
TAOS_ROW row; TAOS_ROW row;
while ((row = taos_fetch_row(result))) { while ((row = taos_fetch_row(pSql))) {
if (numOfRows < MAX_QUERY_ROW_NUM) { if (numOfRows < MAX_QUERY_ROW_NUM) {
TAOS_FIELD *fields = taos_fetch_fields(result); TAOS_FIELD *fields = taos_fetch_fields(pSql);
int* length = taos_fetch_lengths(result); int* length = taos_fetch_lengths(pSql);
for (int i = 0; i < num_fields; i++) { for (int i = 0; i < num_fields; i++) {
char *value = NULL; char *value = NULL;
@ -768,9 +771,9 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) {
} }
} }
taos_free_result(result); taos_free_result(pSql);
} else { } else {
numOfRows = taos_affected_rows(script->taos); numOfRows = taos_affected_rows(pSql);
} }
sprintf(script->rows, "%d", numOfRows); sprintf(script->rows, "%d", numOfRows);
@ -911,13 +914,17 @@ bool simExecuteSqlErrorCmd(SScript *script, char *rest) {
} }
int ret; int ret;
TAOS_RES* pSql = NULL;
if (simAsyncQuery) { if (simAsyncQuery) {
char command[4096]; char command[4096];
sprintf(command, "curl -H 'Authorization: Taosd %s' -d '%s' 127.0.0.1:6020/rest/sql", script->auth, rest); sprintf(command, "curl -H 'Authorization: Taosd %s' -d '%s' 127.0.0.1:6020/rest/sql", script->auth, rest);
ret = simExecuteRestFulCommand(script, command); ret = simExecuteRestFulCommand(script, command);
} }
else { else {
ret = taos_query(script->taos, rest); pSql = taos_query(script->taos, rest);
ret = terrno;
taos_free_result(pSql);
} }
if (ret != TSDB_CODE_SUCCESS) { if (ret != TSDB_CODE_SUCCESS) {
@ -926,6 +933,7 @@ bool simExecuteSqlErrorCmd(SScript *script, char *rest) {
script->linePos++; script->linePos++;
return true; return true;
} }
sprintf(script->error, "lineNum:%d. sql:%s expect failed, but success, ret:%d:%s", line->lineNum, rest, ret, tstrerror(ret)); sprintf(script->error, "lineNum:%d. sql:%s expect failed, but success, ret:%d:%s", line->lineNum, rest, ret, tstrerror(ret));
return false; return false;