[td-314] [td-437] refactor C API.
This commit is contained in:
parent
82d75cbdef
commit
0944c0cd84
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue