diff --git a/alert/README.md b/alert/README.md index 547f3a0381..b8b8c92a27 100644 --- a/alert/README.md +++ b/alert/README.md @@ -61,7 +61,7 @@ The use of each configuration item is: * **port**: This is the `http` service port which enables other application to manage rules by `restful API`. * **database**: rules are stored in a `sqlite` database, this is the path of the database file (if the file does not exist, the alert application creates it automatically). -* **tdengine**: connection string of `TDEngine` server, note the database name should be put in the `sql` field of a rule in most cases, thus it should NOT be included in the string. +* **tdengine**: connection string of `TDEngine` server (please refer the documentation of GO connector for the detailed format of this string), note the database name should be put in the `sql` field of a rule in most cases, thus it should NOT be included in the string. * **log > level**: log level, could be `production` or `debug`. * **log > path**: log output file path. * **receivers > alertManager**: the alert application pushes alerts to `AlertManager` at this URL. diff --git a/alert/README_cn.md b/alert/README_cn.md index 938b23a584..f659e997e3 100644 --- a/alert/README_cn.md +++ b/alert/README_cn.md @@ -58,7 +58,7 @@ $ go build * **port**:报警监测程序支持使用 `restful API` 对规则进行管理,这个参数用于配置 `http` 服务的侦听端口。 * **database**:报警监测程序将规则保存到了一个 `sqlite` 数据库中,这个参数用于指定数据库文件的路径(不需要提前创建这个文件,如果它不存在,程序会自动创建它)。 -* **tdengine**:`TDEngine` 的连接字符串,一般来说,数据库名应该在报警规则的 `sql` 语句中指定,所以这个字符串中 **不** 应包含数据库名。 +* **tdengine**:`TDEngine` 的连接字符串(这个字符串的详细格式说明请见 GO 连接器的文档),一般来说,数据库名应该在报警规则的 `sql` 语句中指定,所以这个字符串中 **不** 应包含数据库名。 * **log > level**:日志的记录级别,可选 `production` 或 `debug`。 * **log > path**:日志文件的路径。 * **receivers > alertManager**:报警监测程序会将报警推送到 `AlertManager`,在这里指定 `AlertManager` 的接收地址。 diff --git a/alert/app/rule.go b/alert/app/rule.go index 44596ca26d..236e5bd755 100644 --- a/alert/app/rule.go +++ b/alert/app/rule.go @@ -84,6 +84,7 @@ func (alert *Alert) doRefresh(firing bool, rule *Rule) bool { case firing && (alert.State == AlertStateWaiting): alert.StartsAt = time.Now() + alert.EndsAt = time.Time{} if rule.For.Nanoseconds() > 0 { alert.State = AlertStatePending return false @@ -95,6 +96,7 @@ func (alert *Alert) doRefresh(firing bool, rule *Rule) bool { return false } alert.StartsAt = alert.StartsAt.Add(rule.For.Duration) + alert.EndsAt = time.Time{} alert.State = AlertStateFiring case firing && (alert.State == AlertStateFiring): diff --git a/cmake/install.inc b/cmake/install.inc index 9bbcc2cf40..746e493a17 100755 --- a/cmake/install.inc +++ b/cmake/install.inc @@ -9,7 +9,7 @@ ELSEIF (TD_WINDOWS) ELSE () SET(CMAKE_INSTALL_PREFIX C:/TDengine) ENDIF () - + INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/go DESTINATION connector) INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/nodejs DESTINATION connector) INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/python DESTINATION connector) @@ -20,12 +20,12 @@ ELSEIF (TD_WINDOWS) INSTALL(FILES ${TD_COMMUNITY_DIR}/src/inc/taoserror.h DESTINATION include) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.lib DESTINATION driver) INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.exp DESTINATION driver) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver) - + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver) + IF (TD_POWER) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/power.exe DESTINATION .) - ELSE () - INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .) + ELSE () + INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .) INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taosdemo.exe DESTINATION .) ENDIF () diff --git a/packaging/tools/install.sh b/packaging/tools/install.sh index aedfb0a683..ddf7114f08 100755 --- a/packaging/tools/install.sh +++ b/packaging/tools/install.sh @@ -312,7 +312,7 @@ function install_data() { } function install_connector() { - ${csudo} cp -rf ${script_dir}/connector/* ${install_main_dir}/connector + ${csudo} cp -rf ${script_dir}/connector/ ${install_main_dir}/ } function install_examples() { diff --git a/packaging/tools/install_client.sh b/packaging/tools/install_client.sh index 24586d3390..34a9bfaecb 100755 --- a/packaging/tools/install_client.sh +++ b/packaging/tools/install_client.sh @@ -163,7 +163,7 @@ function install_log() { } function install_connector() { - ${csudo} cp -rf ${script_dir}/connector/* ${install_main_dir}/connector + ${csudo} cp -rf ${script_dir}/connector/ ${install_main_dir}/ } function install_examples() { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f619edd221..a2600785c3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,6 @@ ADD_SUBDIRECTORY(tsdb) ADD_SUBDIRECTORY(wal) ADD_SUBDIRECTORY(cq) ADD_SUBDIRECTORY(dnode) -ADD_SUBDIRECTORY(connector/odbc) +#ADD_SUBDIRECTORY(connector/odbc) ADD_SUBDIRECTORY(connector/jdbc) diff --git a/src/client/inc/tscLocalMerge.h b/src/client/inc/tscLocalMerge.h index ce67344b03..2c7c2f51d0 100644 --- a/src/client/inc/tscLocalMerge.h +++ b/src/client/inc/tscLocalMerge.h @@ -84,9 +84,9 @@ typedef struct SRetrieveSupport { } SRetrieveSupport; int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOrderDescriptor **pDesc, - SColumnModel **pFinalModel, uint32_t nBufferSize); + SColumnModel **pFinalModel, SColumnModel** pFFModel, uint32_t nBufferSize); -void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDesc, SColumnModel *pFinalModel, +void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDesc, SColumnModel *pFinalModel, SColumnModel* pFFModel, int32_t numOfVnodes); int32_t saveToBuffer(tExtMemBuffer *pMemoryBuf, tOrderDescriptor *pDesc, tFilePage *pPage, void *data, diff --git a/src/client/inc/tscSubquery.h b/src/client/inc/tscSubquery.h index 3226f70528..f7832c9818 100644 --- a/src/client/inc/tscSubquery.h +++ b/src/client/inc/tscSubquery.h @@ -39,9 +39,9 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql); int32_t tscHandleInsertRetry(SSqlObj* pSql); void tscBuildResFromSubqueries(SSqlObj *pSql); -TAOS_ROW doSetResultRowData(SSqlObj *pSql, bool finalResult); +TAOS_ROW doSetResultRowData(SSqlObj *pSql); -char *getArithemicInputSrc(void *param, const char *name, int32_t colId); +char *getArithmeticInputSrc(void *param, const char *name, int32_t colId); #ifdef __cplusplus } diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index 223fb5d226..bde27d2932 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -282,6 +282,7 @@ int tscSetMgmtEpSetFromCfg(const char *first, const char *second); bool tscSetSqlOwner(SSqlObj* pSql); void tscClearSqlOwner(SSqlObj* pSql); +int32_t doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize); void* malloc_throw(size_t size); void* calloc_throw(size_t nmemb, size_t size); diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index 6b3d97d6f9..ff36cf0f5a 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -293,32 +293,32 @@ typedef struct SResRec { } SResRec; typedef struct { - int64_t numOfRows; // num of results in current retrieved - int64_t numOfRowsGroup; // num of results of current group - int64_t numOfTotal; // num of total results - int64_t numOfClauseTotal; // num of total result in current subclause - char * pRsp; - int32_t rspType; - int32_t rspLen; - uint64_t qhandle; - int64_t uid; - int64_t useconds; - int64_t offset; // offset value from vnode during projection query of stable - int32_t row; - int16_t numOfCols; - int16_t precision; - bool completed; - int32_t code; - int32_t numOfGroups; - SResRec * pGroupRec; - char * data; - TAOS_ROW tsrow; - int32_t* length; // length for each field for current row - char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t) - SColumnIndex * pColumnIndex; + int32_t numOfRows; // num of results in current retrieval + int64_t numOfRowsGroup; // num of results of current group + int64_t numOfTotal; // num of total results + int64_t numOfClauseTotal; // num of total result in current subclause + char * pRsp; + int32_t rspType; + int32_t rspLen; + uint64_t qhandle; + int64_t useconds; + int64_t offset; // offset value from vnode during projection query of stable + int32_t row; + int16_t numOfCols; + int16_t precision; + bool completed; + int32_t code; + int32_t numOfGroups; + SResRec * pGroupRec; + char * data; + TAOS_ROW tsrow; + TAOS_ROW urow; + int32_t* length; // length for each field for current row + char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t) + SColumnIndex* pColumnIndex; + SArithmeticSupport* pArithSup; // support the arithmetic expression calculation on agg functions - - struct SLocalReducer *pLocalReducer; + struct SLocalReducer* pLocalReducer; } SSqlRes; typedef struct STscObj { @@ -425,6 +425,7 @@ int32_t tscTansformSQLFuncForSTableQuery(SQueryInfo *pQueryInfo); void tscRestoreSQLFuncForSTableQuery(SQueryInfo *pQueryInfo); int32_t tscCreateResPointerInfo(SSqlRes *pRes, SQueryInfo *pQueryInfo); +void tscSetResRawPtr(SSqlRes* pRes, SQueryInfo* pQueryInfo); void tscResetSqlCmdObj(SSqlCmd *pCmd, bool removeFromCache); @@ -471,8 +472,9 @@ static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pField int32_t bytes = pInfo->field.bytes; char* pData = pRes->data + (int32_t)(offset * pRes->numOfRows + bytes * pRes->row); + UNUSED(pData); - // user defined constant value output columns +// user defined constant value output columns if (pInfo->pSqlExpr != NULL && TSDB_COL_IS_UD_COL(pInfo->pSqlExpr->colInfo.flag)) { if (type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_BINARY) { pData = pInfo->pSqlExpr->param[1].pz; diff --git a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h index eaea91d1bf..582bd6bac0 100644 --- a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h +++ b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h @@ -129,6 +129,14 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp (JNIEnv *, jobject, jlong, jlong, jobject); +/* + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: fetchBlockImp + * Signature: (JJLcom/taosdata/jdbc/TSDBResultSetBlockData;)I + */ +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp + (JNIEnv *, jobject, jlong, jlong, jobject); + /* * Class: com_taosdata_jdbc_TSDBJNIConnector * Method: closeConnectionImp diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index 4e2272eb05..a8829499a3 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -17,7 +17,6 @@ #include "taos.h" #include "tlog.h" #include "tscUtil.h" -#include "tsclient.h" #include "com_taosdata_jdbc_TSDBJNIConnector.h" @@ -57,6 +56,10 @@ jmethodID g_rowdataSetStringFp; jmethodID g_rowdataSetTimestampFp; jmethodID g_rowdataSetByteArrayFp; +jmethodID g_blockdataSetByteArrayFp; +jmethodID g_blockdataSetNumOfRowsFp; +jmethodID g_blockdataSetNumOfColsFp; + #define JNI_SUCCESS 0 #define JNI_TDENGINE_ERROR -1 #define JNI_CONNECTION_NULL -2 @@ -66,7 +69,7 @@ jmethodID g_rowdataSetByteArrayFp; #define JNI_FETCH_END -6 #define JNI_OUT_OF_MEMORY -7 -void jniGetGlobalMethod(JNIEnv *env) { +static void jniGetGlobalMethod(JNIEnv *env) { // make sure init function executed once switch (atomic_val_compare_exchange_32(&__init, 0, 1)) { case 0: @@ -114,10 +117,31 @@ void jniGetGlobalMethod(JNIEnv *env) { g_rowdataSetByteArrayFp = (*env)->GetMethodID(env, g_rowdataClass, "setByteArray", "(I[B)V"); (*env)->DeleteLocalRef(env, rowdataClass); + jclass blockdataClass = (*env)->FindClass(env, "com/taosdata/jdbc/TSDBResultSetBlockData"); + jclass g_blockdataClass = (*env)->NewGlobalRef(env, blockdataClass); + g_blockdataSetByteArrayFp = (*env)->GetMethodID(env, g_blockdataClass, "setByteArray", "(II[B)V"); + g_blockdataSetNumOfRowsFp = (*env)->GetMethodID(env, g_blockdataClass, "setNumOfRows", "(I)V"); + g_blockdataSetNumOfColsFp = (*env)->GetMethodID(env, g_blockdataClass, "setNumOfCols", "(I)V"); + (*env)->DeleteLocalRef(env, blockdataClass); + atomic_store_32(&__init, 2); jniDebug("native method register finished"); } +static int32_t check_for_params(jobject jobj, jlong conn, jlong res) { + if ((TAOS*) conn == NULL) { + jniError("jobj:%p, connection is closed", jobj); + return JNI_CONNECTION_NULL; + } + + if ((TAOS_RES *) res == NULL) { + jniError("jobj:%p, conn:%p, res is null", jobj, (TAOS*) conn); + return JNI_RESULT_SET_NULL; + } + + return JNI_SUCCESS; +} + JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp(JNIEnv *env, jobject jobj, jint jMode, jstring jPath, jboolean jAutoDump) { if (jPath != NULL) { @@ -192,39 +216,37 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEnv *env, jobject jobj, jstring jhost, jint jport, jstring jdbName, jstring juser, jstring jpass) { - jlong ret = 0; + jlong ret = 0; const char *host = NULL; - const char *dbname = NULL; const char *user = NULL; const char *pass = NULL; + const char *dbname = NULL; if (jhost != NULL) { host = (*env)->GetStringUTFChars(env, jhost, NULL); } + if (jdbName != NULL) { dbname = (*env)->GetStringUTFChars(env, jdbName, NULL); } + if (juser != NULL) { user = (*env)->GetStringUTFChars(env, juser, NULL); } + if (jpass != NULL) { pass = (*env)->GetStringUTFChars(env, jpass, NULL); } if (user == NULL) { - jniDebug("jobj:%p, user is null, use default user %s", jobj, TSDB_DEFAULT_USER); + jniDebug("jobj:%p, user not specified, use default user %s", jobj, TSDB_DEFAULT_USER); } + if (pass == NULL) { - jniDebug("jobj:%p, pass is null, use default password", jobj); + jniDebug("jobj:%p, pass not specified, use default password", jobj); } - /* - * set numOfThreadsPerCore = 0 - * means only one thread for client side scheduler - */ - tsNumOfThreadsPerCore = 0.0; - - ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport); + ret = (jlong) taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport); if (ret == 0) { jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret, (char *)host, (char *)user, (char *)dbname, (int32_t)jport); @@ -233,10 +255,21 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn (char *)host, (char *)user, (char *)dbname, (int32_t)jport); } - if (host != NULL) (*env)->ReleaseStringUTFChars(env, jhost, host); - if (dbname != NULL) (*env)->ReleaseStringUTFChars(env, jdbName, dbname); - if (user != NULL) (*env)->ReleaseStringUTFChars(env, juser, user); - if (pass != NULL) (*env)->ReleaseStringUTFChars(env, jpass, pass); + if (host != NULL) { + (*env)->ReleaseStringUTFChars(env, jhost, host); + } + + if (dbname != NULL) { + (*env)->ReleaseStringUTFChars(env, jdbName, dbname); + } + + if (user != NULL) { + (*env)->ReleaseStringUTFChars(env, juser, user); + } + + if (pass != NULL) { + (*env)->ReleaseStringUTFChars(env, jpass, pass); + } return ret; } @@ -245,64 +278,53 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp( jbyteArray jsql, jlong con) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { - jniError("jobj:%p, connection is already closed", jobj); + jniError("jobj:%p, connection already closed", jobj); return JNI_CONNECTION_NULL; } if (jsql == NULL) { - jniError("jobj:%p, conn:%p, sql is null", jobj, tscon); + jniError("jobj:%p, conn:%p, empty sql string", jobj, tscon); return JNI_SQL_NULL; } jsize len = (*env)->GetArrayLength(env, jsql); - char *dst = (char *)calloc(1, sizeof(char) * (len + 1)); - if (dst == NULL) { - jniError("jobj:%p, conn:%p, can not alloc memory", jobj, tscon); + char *str = (char *) calloc(1, sizeof(char) * (len + 1)); + if (str == NULL) { + jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon); return JNI_OUT_OF_MEMORY; } - (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)dst); + (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str); if ((*env)->ExceptionCheck(env)) { // todo handle error } - jniDebug("jobj:%p, conn:%p, sql:%s", jobj, tscon, dst); - - SSqlObj *pSql = taos_query(tscon, dst); + SSqlObj *pSql = taos_query(tscon, str); int32_t code = taos_errno(pSql); if (code != TSDB_CODE_SUCCESS) { jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, tscon, tstrerror(code), taos_errstr(pSql)); } else { - int32_t affectRows = 0; if (pSql->cmd.command == TSDB_SQL_INSERT) { - affectRows = taos_affected_rows(pSql); + int32_t affectRows = taos_affected_rows(pSql); jniDebug("jobj:%p, conn:%p, code:%s, affect rows:%d", jobj, tscon, tstrerror(code), affectRows); } else { jniDebug("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); } } - free(dst); - return (jlong)pSql; + free(str); + return (jlong) pSql; } JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) { - TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return (jint)TSDB_CODE_TSC_INVALID_CONNECTION; + int32_t code = check_for_params(jobj, con, tres); + if (code != JNI_SUCCESS) { + return code; } - if ((void *)tres == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; - } - - TAOS_RES *pSql = (TAOS_RES *)tres; - - return (jint)taos_errno(pSql); + return (jint)taos_errno((TAOS_RES*) tres); } JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(JNIEnv *env, jobject jobj, jlong tres) { @@ -313,23 +335,16 @@ 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, jlong tres) { TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; - } - - if ((void *)tres == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; + int32_t code = check_for_params(jobj, con, tres); + if (code != JNI_SUCCESS) { + return code; } SSqlObj *pSql = (TAOS_RES *)tres; - STscObj *pObj = pSql->pTscObj; - if (tscIsUpdateQuery(pSql)) { - jniDebug("jobj:%p, conn:%p, update query, no resultset, %p", jobj, pObj, (void *)tres); + jniDebug("jobj:%p, conn:%p, update query, no resultset, %p", jobj, tscon, (void *)tres); } else { - jniDebug("jobj:%p, conn:%p, get resultset, %p", jobj, pObj, (void *)tres); + jniDebug("jobj:%p, conn:%p, get resultset, %p", jobj, tscon, (void *)tres); } return tres; @@ -337,15 +352,9 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp( JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) { - TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; - } - - if ((void *)tres == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; + int32_t code = check_for_params(jobj, con, tres); + if (code != JNI_SUCCESS) { + return code; } SSqlObj *pSql = (TAOS_RES *)tres; @@ -355,37 +364,27 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp( JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *env, jobject jobj, jlong con, jlong res) { - TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; - } - - if ((void *)res == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; + int32_t code = check_for_params(jobj, con, res); + if (code != JNI_SUCCESS) { + return code; } taos_free_result((void *)res); - jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, tscon, (void *)res); + jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, (TAOS*) con, (void *)res); + return JNI_SUCCESS; } JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp(JNIEnv *env, jobject jobj, jlong con, jlong res) { TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; - } - - if ((void *)res == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; + int32_t code = check_for_params(jobj, con, res); + if (code != JNI_SUCCESS) { + return code; } jint ret = taos_affected_rows((SSqlObj *)res); - jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (void *)con, (void *)res, (int32_t)ret); + jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (TAOS *)con, (TAOS_RES *)res, (int32_t)ret); return ret; } @@ -394,27 +393,20 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData jlong con, jlong res, jobject arrayListObj) { TAOS *tscon = (TAOS *)con; - if (tscon == NULL) { - jniError("jobj:%p, connection is closed", jobj); - return JNI_CONNECTION_NULL; + int32_t code = check_for_params(jobj, con, res); + if (code != JNI_SUCCESS) { + return code; } - TAOS_RES *result = (TAOS_RES *)res; - if (result == NULL) { - jniError("jobj:%p, conn:%p, resultset is null", jobj, tscon); - return JNI_RESULT_SET_NULL; - } - - TAOS_FIELD *fields = taos_fetch_fields(result); - int num_fields = taos_num_fields(result); - - // jobject arrayListObj = (*env)->NewObject(env, g_arrayListClass, g_arrayListConstructFp, ""); + TAOS_RES* tres = (TAOS_RES*) res; + TAOS_FIELD *fields = taos_fetch_fields(tres); + int32_t num_fields = taos_num_fields(tres); if (num_fields == 0) { - jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void *)res, num_fields); + jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, num_fields); return JNI_NUM_OF_FIELDS_0; } else { - jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void *)res, num_fields); + jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, tres, num_fields); for (int i = 0; i < num_fields; ++i) { jobject metadataObj = (*env)->NewObject(env, g_metadataClass, g_metadataConstructFp); (*env)->SetIntField(env, metadataObj, g_metadataColtypeField, fields[i].type); @@ -457,21 +449,21 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn } TAOS_FIELD *fields = taos_fetch_fields(result); - int num_fields = taos_num_fields(result); - if (num_fields == 0) { - jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void*)res, num_fields); + int32_t numOfFields = taos_num_fields(result); + if (numOfFields == 0) { + jniError("jobj:%p, conn:%p, resultset:%p, fields size %d", jobj, tscon, (void*)res, numOfFields); return JNI_NUM_OF_FIELDS_0; } TAOS_ROW row = taos_fetch_row(result); if (row == NULL) { - int tserrno = taos_errno(result); - if (tserrno == 0) { - jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void*)res, num_fields); + int code = taos_errno(result); + if (code == TSDB_CODE_SUCCESS) { + jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void*)res, numOfFields); return JNI_FETCH_END; } else { - jniDebug("jobj:%p, conn:%p, interruptted query", jobj, tscon); + jniDebug("jobj:%p, conn:%p, interrupted query", jobj, tscon); return JNI_RESULT_SET_NULL; } } @@ -480,7 +472,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn char tmp[TSDB_MAX_BYTES_PER_ROW] = {0}; - for (int i = 0; i < num_fields; i++) { + for (int i = 0; i < numOfFields; i++) { if (row[i] == NULL) { continue; } @@ -534,6 +526,45 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn return JNI_SUCCESS; } +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNIEnv *env, jobject jobj, jlong con, + jlong res, jobject rowobj) { + TAOS * tscon = (TAOS *)con; + int32_t code = check_for_params(jobj, con, res); + if (code != JNI_SUCCESS) { + return code; + } + + TAOS_RES * tres = (TAOS_RES *)res; + TAOS_FIELD *fields = taos_fetch_fields(tres); + + int32_t numOfFields = taos_num_fields(tres); + assert(numOfFields > 0); + + TAOS_ROW row = NULL; + int32_t numOfRows = taos_fetch_block(tres, &row); + if (numOfRows == 0) { + code = taos_errno(tres); + if (code == JNI_SUCCESS) { + jniDebug("jobj:%p, conn:%p, resultset:%p, numOfFields:%d, no data to retrieve", jobj, tscon, (void *)res, + numOfFields); + return JNI_FETCH_END; + } else { + jniDebug("jobj:%p, conn:%p, query interrupted", jobj, tscon); + return JNI_RESULT_SET_NULL; + } + } + + (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfRowsFp, (jint)numOfRows); + (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfColsFp, (jint)numOfFields); + + for (int i = 0; i < numOfFields; i++) { + (*env)->CallVoidMethod(env, rowobj, g_blockdataSetByteArrayFp, i, fields[i].bytes * numOfRows, + jniFromNCharToByteArray(env, (char *)row[i], fields[i].bytes * numOfRows)); + } + + return JNI_SUCCESS; +} + JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionImp(JNIEnv *env, jobject jobj, jlong con) { TAOS *tscon = (TAOS *)con; @@ -589,7 +620,6 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_consumeImp(JNIEn jniGetGlobalMethod(env); TAOS_SUB *tsub = (TAOS_SUB *)sub; - TAOS_RES *res = taos_consume(tsub); if (res == NULL) { @@ -621,16 +651,16 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTab jsize len = (*env)->GetArrayLength(env, jsql); - char *dst = (char *)calloc(1, sizeof(char) * (len + 1)); - (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)dst); + char *str = (char *)calloc(1, sizeof(char) * (len + 1)); + (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str); if ((*env)->ExceptionCheck(env)) { // todo handle error } - int code = taos_validate_sql(tscon, dst); + int code = taos_validate_sql(tscon, str); jniDebug("jobj:%p, conn:%p, code is %d", jobj, tscon, code); - free(dst); + free(str); return code; } diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c index e9e8214c4c..3ff8a68d8f 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -91,8 +91,8 @@ void taos_query_a(TAOS *taos, const char *sqlstr, __async_cb_func_t fp, void *pa int32_t sqlLen = (int32_t)strlen(sqlstr); if (sqlLen > tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); - terrno = TSDB_CODE_TSC_INVALID_SQL; - tscQueueAsyncError(fp, param, TSDB_CODE_TSC_INVALID_SQL); + terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT; + tscQueueAsyncError(fp, param, terrno); return; } diff --git a/src/client/src/tscFunctionImpl.c b/src/client/src/tscFunctionImpl.c index 35dc94f37b..d39b833374 100644 --- a/src/client/src/tscFunctionImpl.c +++ b/src/client/src/tscFunctionImpl.c @@ -130,11 +130,11 @@ typedef struct STopBotInfo { } STopBotInfo; // leastsquares do not apply to super table -typedef struct SLeastsquareInfo { +typedef struct SLeastsquaresInfo { double mat[2][3]; double startVal; int64_t num; -} SLeastsquareInfo; +} SLeastsquaresInfo; typedef struct SAPercentileInfo { SHistogramInfo *pHisto; @@ -316,7 +316,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI *interBytes = (int16_t)sizeof(SPercentileInfo); } else if (functionId == TSDB_FUNC_LEASTSQR) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = TSDB_AVG_FUNCTION_INTER_BUFFER_SIZE; // string + *bytes = MAX(TSDB_AVG_FUNCTION_INTER_BUFFER_SIZE, sizeof(SLeastsquaresInfo)); // string *interBytes = *bytes; } else if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_LAST_DST) { *type = TSDB_DATA_TYPE_BINARY; @@ -681,7 +681,7 @@ static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, i } // no result for first query, data block is required - if (GET_RES_INFO(pCtx)->numOfRes <= 0) { + if (GET_RES_INFO(pCtx) == NULL || GET_RES_INFO(pCtx)->numOfRes <= 0) { return BLK_DATA_ALL_NEEDED; } else { return BLK_DATA_NO_NEEDED; @@ -693,7 +693,7 @@ static int32_t lastFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, in return BLK_DATA_NO_NEEDED; } - if (GET_RES_INFO(pCtx)->numOfRes <= 0) { + if (GET_RES_INFO(pCtx) == NULL || GET_RES_INFO(pCtx)->numOfRes <= 0) { return BLK_DATA_ALL_NEEDED; } else { return BLK_DATA_NO_NEEDED; @@ -2756,7 +2756,7 @@ static bool leastsquares_function_setup(SQLFunctionCtx *pCtx) { } SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx); - SLeastsquareInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); + SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); // 2*3 matrix pInfo->startVal = pCtx->param[0].dKey; @@ -2783,7 +2783,7 @@ static bool leastsquares_function_setup(SQLFunctionCtx *pCtx) { static void leastsquares_function(SQLFunctionCtx *pCtx) { SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx); - SLeastsquareInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); + SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); double(*param)[3] = pInfo->mat; double x = pInfo->startVal; @@ -2853,40 +2853,40 @@ static void leastsquares_function_f(SQLFunctionCtx *pCtx, int32_t index) { return; } - SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx); - SLeastsquareInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); double(*param)[3] = pInfo->mat; switch (pCtx->inputType) { case TSDB_DATA_TYPE_INT: { int32_t *p = pData; - LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey); + LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey); break; }; case TSDB_DATA_TYPE_TINYINT: { int8_t *p = pData; - LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey); + LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey); break; } case TSDB_DATA_TYPE_SMALLINT: { int16_t *p = pData; - LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey); + LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey); break; } case TSDB_DATA_TYPE_BIGINT: { int64_t *p = pData; - LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey); + LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey); break; } case TSDB_DATA_TYPE_FLOAT: { float *p = pData; - LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey); + LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey); break; } case TSDB_DATA_TYPE_DOUBLE: { double *p = pData; - LEASTSQR_CAL(param, pInfo->startVal, p, index, pCtx->param[1].dKey); + LEASTSQR_CAL(param, pInfo->startVal, p, 0, pCtx->param[1].dKey); break; } default: @@ -2904,15 +2904,10 @@ static void leastsquares_function_f(SQLFunctionCtx *pCtx, int32_t index) { static void leastsquares_finalizer(SQLFunctionCtx *pCtx) { // no data in query SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx); - SLeastsquareInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); + SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); if (pInfo->num == 0) { - if (pCtx->outputType == TSDB_DATA_TYPE_BINARY || pCtx->outputType == TSDB_DATA_TYPE_NCHAR) { - setVardataNull(pCtx->aOutputBuf, pCtx->outputType); - } else { - setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes); - } - + setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes); return; } diff --git a/src/client/src/tscLocal.c b/src/client/src/tscLocal.c index 310c4c6657..538e652f3c 100644 --- a/src/client/src/tscLocal.c +++ b/src/client/src/tscLocal.c @@ -341,7 +341,7 @@ TAOS_ROW tscFetchRow(void *param) { return NULL; } - void* data = doSetResultRowData(pSql, true); + void* data = doSetResultRowData(pSql); tscClearSqlOwner(pSql); return data; diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index b07c7ca66d..3c7d46f914 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -30,8 +30,6 @@ typedef struct SCompareParam { int32_t groupOrderType; } SCompareParam; -static void doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize); - int32_t treeComparator(const void *pLeft, const void *pRight, void *param) { int32_t pLeftIdx = *(int32_t *)pLeft; int32_t pRightIdx = *(int32_t *)pRight; @@ -174,14 +172,14 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd SSqlRes* pRes = &pSql->res; if (pMemBuffer == NULL) { - tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer); + tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer); tscError("%p pMemBuffer is NULL", pMemBuffer); pRes->code = TSDB_CODE_TSC_APP_ERROR; return; } if (pDesc->pColumnModel == NULL) { - tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer); + tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer); tscError("%p no local buffer or intermediate result format model", pSql); pRes->code = TSDB_CODE_TSC_APP_ERROR; return; @@ -199,7 +197,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd } if (numOfFlush == 0 || numOfBuffer == 0) { - tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer); + tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer); tscDebug("%p retrieved no data", pSql); return; } @@ -208,7 +206,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd tscError("%p Invalid value of buffer capacity %d and page size %d ", pSql, pDesc->pColumnModel->capacity, pMemBuffer[0]->pageSize); - tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer); + tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer); pRes->code = TSDB_CODE_TSC_APP_ERROR; return; } @@ -219,7 +217,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd if (pReducer == NULL) { tscError("%p failed to create local merge structure, out of memory", pSql); - tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, numOfBuffer); + tscLocalReducerEnvDestroy(pMemBuffer, pDesc, finalmodel, pFFModel, numOfBuffer); pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; return; } @@ -336,6 +334,8 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd pReducer->resColModel = finalmodel; pReducer->resColModel->capacity = pReducer->nResultBufSize; + pReducer->finalModel = pFFModel; + assert(pReducer->finalRowSize > 0); if (pReducer->finalRowSize > 0) { pReducer->resColModel->capacity /= pReducer->finalRowSize; @@ -533,7 +533,7 @@ void tscDestroyLocalReducer(SSqlObj *pSql) { tfree(pLocalReducer->pFinalRes); tfree(pLocalReducer->discardData); - tscLocalReducerEnvDestroy(pLocalReducer->pExtMemBuffer, pLocalReducer->pDesc, pLocalReducer->resColModel, + tscLocalReducerEnvDestroy(pLocalReducer->pExtMemBuffer, pLocalReducer->pDesc, pLocalReducer->resColModel, pLocalReducer->finalModel, pLocalReducer->numOfVnode); for (int32_t i = 0; i < pLocalReducer->numOfBuffer; ++i) { tfree(pLocalReducer->pLocalDataSrc[i]); @@ -657,7 +657,7 @@ bool isSameGroup(SSqlCmd *pCmd, SLocalReducer *pReducer, char *pPrev, tFilePage } int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOrderDescriptor **pOrderDesc, - SColumnModel **pFinalModel, uint32_t nBufferSizes) { + SColumnModel **pFinalModel, SColumnModel** pFFModel, uint32_t nBufferSizes) { SSqlCmd *pCmd = &pSql->cmd; SSqlRes *pRes = &pSql->res; @@ -755,6 +755,18 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr *pFinalModel = createColumnModel(pSchema, (int32_t)size, capacity); + memset(pSchema, 0, sizeof(SSchema) * size); + size = tscNumOfFields(pQueryInfo); + + for(int32_t i = 0; i < size; ++i) { + SInternalField* pField = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i); + pSchema[i].bytes = pField->field.bytes; + pSchema[i].type = pField->field.type; + tstrncpy(pSchema[i].name, pField->field.name, tListLen(pSchema[i].name)); + } + + *pFFModel = createColumnModel(pSchema, (int32_t) size, capacity); + tfree(pSchema); return TSDB_CODE_SUCCESS; } @@ -765,9 +777,11 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr * @param pFinalModel * @param numOfVnodes */ -void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDesc, SColumnModel *pFinalModel, +void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDesc, SColumnModel *pFinalModel, SColumnModel *pFFModel, int32_t numOfVnodes) { destroyColumnModel(pFinalModel); + destroyColumnModel(pFFModel); + tOrderDescDestroy(pDesc); for (int32_t i = 0; i < numOfVnodes; ++i) { @@ -870,17 +884,17 @@ static void genFinalResWithoutFill(SSqlRes* pRes, SLocalReducer *pLocalReducer, tFilePage * pBeforeFillData = pLocalReducer->pResultBuf; pRes->data = pLocalReducer->pFinalRes; - pRes->numOfRows = pBeforeFillData->num; + pRes->numOfRows = (int32_t) pBeforeFillData->num; if (pQueryInfo->limit.offset > 0) { if (pQueryInfo->limit.offset < pRes->numOfRows) { - int32_t prevSize = (int32_t)pBeforeFillData->num; - tColModelErase(pLocalReducer->resColModel, pBeforeFillData, prevSize, 0, (int32_t)pQueryInfo->limit.offset - 1); + int32_t prevSize = (int32_t) pBeforeFillData->num; + tColModelErase(pLocalReducer->finalModel, pBeforeFillData, prevSize, 0, (int32_t)pQueryInfo->limit.offset - 1); /* remove the hole in column model */ - tColModelCompact(pLocalReducer->resColModel, pBeforeFillData, prevSize); + tColModelCompact(pLocalReducer->finalModel, pBeforeFillData, prevSize); - pRes->numOfRows -= pQueryInfo->limit.offset; + pRes->numOfRows -= (int32_t) pQueryInfo->limit.offset; pQueryInfo->limit.offset = 0; } else { pQueryInfo->limit.offset -= pRes->numOfRows; @@ -900,7 +914,7 @@ static void genFinalResWithoutFill(SSqlRes* pRes, SLocalReducer *pLocalReducer, pRes->numOfRows -= overflow; pBeforeFillData->num -= overflow; - tColModelCompact(pLocalReducer->resColModel, pBeforeFillData, prevSize); + tColModelCompact(pLocalReducer->finalModel, pBeforeFillData, prevSize); // set remain data to be discarded, and reset the interpolation information savePrevRecordAndSetupFillInfo(pLocalReducer, pQueryInfo, pLocalReducer->pFillInfo); @@ -948,7 +962,7 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO } pRes->data = pLocalReducer->pFinalRes; - pRes->numOfRows = newRows; + pRes->numOfRows = (int32_t) newRows; pQueryInfo->limit.offset = 0; break; @@ -1242,7 +1256,7 @@ bool genFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool noMoreCur tColModelCompact(pModel, pResBuf, pModel->capacity); if (tscIsSecondStageQuery(pQueryInfo)) { - doArithmeticCalculate(pQueryInfo, pResBuf, pModel->rowSize, pLocalReducer->finalRowSize); + pLocalReducer->finalRowSize = doArithmeticCalculate(pQueryInfo, pResBuf, pModel->rowSize, pLocalReducer->finalRowSize); } #ifdef _DEBUG_VIEW @@ -1612,7 +1626,7 @@ void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen) pRes->data = pRes->pLocalReducer->pResultBuf->data; } -void doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize) { +int32_t doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t rowSize, int32_t finalRowSize) { char* pbuf = calloc(1, pOutput->num * rowSize); size_t size = tscNumOfFields(pQueryInfo); @@ -1637,7 +1651,7 @@ void doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t r // calculate the result from several other columns if (pSup->pArithExprInfo != NULL) { arithSup.pArithExpr = pSup->pArithExprInfo; - tExprTreeCalcTraverse(arithSup.pArithExpr->pExpr, (int32_t) pOutput->num, pbuf + pOutput->num*offset, &arithSup, TSDB_ORDER_ASC, getArithemicInputSrc); + tExprTreeCalcTraverse(arithSup.pArithExpr->pExpr, (int32_t) pOutput->num, pbuf + pOutput->num*offset, &arithSup, TSDB_ORDER_ASC, getArithmeticInputSrc); } else { SSqlExpr* pExpr = pSup->pSqlExpr; memcpy(pbuf + pOutput->num * offset, pExpr->offset * pOutput->num + pOutput->data, pExpr->resBytes * pOutput->num); @@ -1647,8 +1661,10 @@ void doArithmeticCalculate(SQueryInfo* pQueryInfo, tFilePage* pOutput, int32_t r } assert(finalRowSize <= rowSize); - memcpy(pOutput->data, pbuf, pOutput->num * finalRowSize); + memcpy(pOutput->data, pbuf, pOutput->num * offset); tfree(pbuf); tfree(arithSup.data); + + return offset; } \ No newline at end of file diff --git a/src/client/src/tscPrepare.c b/src/client/src/tscPrepare.c index 1739e4348c..68f2ecbf0e 100644 --- a/src/client/src/tscPrepare.c +++ b/src/client/src/tscPrepare.c @@ -268,7 +268,6 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) { if (1) { // allow user bind param data with different type - short size = 0; union { int8_t v1; int16_t v2; @@ -600,7 +599,7 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) { if ((*bind->length) > (uintptr_t)param->bytes) { return TSDB_CODE_TSC_INVALID_VALUE; } - size = (short)*bind->length; + short size = (short)*bind->length; STR_WITH_SIZE_TO_VARSTR(data + param->offset, bind->buffer, size); return TSDB_CODE_SUCCESS; } break; diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index b55326bbd3..15d2647c51 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -1454,13 +1454,13 @@ static void addPrimaryTsColIntoResult(SQueryInfo* pQueryInfo) { } } - SColumnIndex index = {0}; // set the constant column value always attached to first table. STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, PRIMARYKEY_TIMESTAMP_COL_INDEX); // add the timestamp column into the output columns + SColumnIndex index = {0}; // primary timestamp column info int32_t numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); tscAddSpecialColumnForSelect(pQueryInfo, numOfCols, TSDB_FUNC_PRJ, &index, pSchema, TSDB_COL_NORMAL); @@ -2432,6 +2432,8 @@ int32_t getTableIndexImpl(SStrToken* pTableToken, SQueryInfo* pQueryInfo, SColum if (pTableToken->n == 0) { // only one table and no table name prefix in column name if (pQueryInfo->numOfTables == 1) { pIndex->tableIndex = 0; + } else { + pIndex->tableIndex = COLUMN_INDEX_INITIAL_VAL; } return TSDB_CODE_SUCCESS; @@ -3950,9 +3952,6 @@ static void doExtractExprForSTable(SSqlCmd* pCmd, tSQLExpr** pExpr, SQueryInfo* return; } - SStrToken t = {0}; - extractTableNameFromToken(&pLeft->colInfo, &t); - *pOut = *pExpr; (*pExpr) = NULL; @@ -4187,7 +4186,7 @@ static void cleanQueryExpr(SCondExpr* pCondExpr) { static void doAddJoinTagsColumnsIntoTagList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); if (QUERY_IS_JOIN_QUERY(pQueryInfo->type) && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { - SColumnIndex index = {0}; + SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (getColumnIndexByName(pCmd, &pCondExpr->pJoinExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { tscError("%p: invalid column name (left)", pQueryInfo); @@ -4604,7 +4603,7 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu } SStrToken columnName = {pVar->nLen, pVar->nType, pVar->pz}; - SColumnIndex index = {0}; + SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // super table query if (getColumnIndexByName(pCmd, &columnName, pQueryInfo, &index) != TSDB_CODE_SUCCESS) { @@ -5509,7 +5508,9 @@ void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex) { tscAddSpecialColumnForSelect(pQueryInfo, (int32_t)size, TSDB_FUNC_PRJ, &colIndex, pSchema, TSDB_COL_NORMAL); - SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, (int32_t)size); + int32_t numOfFields = tscNumOfFields(pQueryInfo); + SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, numOfFields - 1); + doLimitOutputNormalColOfGroupby(pInfo->pSqlExpr); pInfo->visible = false; } @@ -6412,7 +6413,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { return code; } - tVariantListItem* p1 = taosArrayGet(pQuerySql->from, i); + tVariantListItem* p1 = taosArrayGet(pQuerySql->from, i + 1); if (p1->pVar.nType != TSDB_DATA_TYPE_BINARY) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg11); } @@ -6620,7 +6621,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS } } } else if (pSqlExpr->nSQLOptr == TK_ID) { // column name, normal column arithmetic expression - SColumnIndex index = {0}; + SColumnIndex index = COLUMN_INDEX_INITIALIZER; int32_t ret = getColumnIndexByName(pCmd, &pSqlExpr->colInfo, pQueryInfo, &index); if (ret != TSDB_CODE_SUCCESS) { return ret; diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index e8b6cb284e..cbc5604a27 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -547,7 +547,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlCmd *pCmd, int32_t clauseIndex) { int32_t srcColListSize = (int32_t)(taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo)); size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); - int32_t exprSize = (int32_t)(sizeof(SSqlFuncMsg) * numOfExprs); + int32_t exprSize = (int32_t)(sizeof(SSqlFuncMsg) * numOfExprs * 2); int32_t tsBufSize = (pQueryInfo->tsBuf != NULL) ? pQueryInfo->tsBuf->fileSize : 0; @@ -787,8 +787,9 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pSqlFuncExpr = (SSqlFuncMsg *)pMsg; } - if(tscIsSecondStageQuery(pQueryInfo)) { - size_t output = tscNumOfFields(pQueryInfo); + size_t output = tscNumOfFields(pQueryInfo); + + if (tscIsSecondStageQuery(pQueryInfo)) { pQueryMsg->secondStageOutput = htonl((int32_t) output); SSqlFuncMsg *pSqlFuncExpr1 = (SSqlFuncMsg *)pMsg; @@ -1437,19 +1438,6 @@ int tscBuildRetrieveFromMgmtMsg(SSqlObj *pSql, SSqlInfo *pInfo) { return TSDB_CODE_SUCCESS; } -static int tscSetResultPointer(SQueryInfo *pQueryInfo, SSqlRes *pRes) { - if (tscCreateResPointerInfo(pRes, pQueryInfo) != TSDB_CODE_SUCCESS) { - return pRes->code; - } - - for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { - int16_t offset = tscFieldInfoGetOffset(pQueryInfo, i); - pRes->tsrow[i] = (unsigned char*)((char*) pRes->data + offset * pRes->numOfRows); - } - - return 0; -} - /* * this function can only be called once. * by using pRes->rspType to denote its status @@ -1460,15 +1448,18 @@ static int tscLocalResultCommonBuilder(SSqlObj *pSql, int32_t numOfRes) { SSqlRes *pRes = &pSql->res; SSqlCmd *pCmd = &pSql->cmd; - SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex); - pRes->code = TSDB_CODE_SUCCESS; if (pRes->rspType == 0) { pRes->numOfRows = numOfRes; pRes->row = 0; pRes->rspType = 1; - tscSetResultPointer(pQueryInfo, pRes); + SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex); + if (tscCreateResPointerInfo(pRes, pQueryInfo) != TSDB_CODE_SUCCESS) { + return pRes->code; + } + + tscSetResRawPtr(pRes, pQueryInfo); } else { tscResetForNextRetrieve(pRes); } @@ -1512,10 +1503,11 @@ int tscProcessRetrieveLocalMergeRsp(SSqlObj *pSql) { } pRes->code = tscDoLocalMerge(pSql); - SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex); if (pRes->code == TSDB_CODE_SUCCESS && pRes->numOfRows > 0) { + SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex); tscCreateResPointerInfo(pRes, pQueryInfo); + tscSetResRawPtr(pRes, pQueryInfo); } pRes->row = 0; @@ -2195,7 +2187,16 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) { if (tscCreateResPointerInfo(pRes, pQueryInfo) != TSDB_CODE_SUCCESS) { return pRes->code; } - + + STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); + if (pCmd->command == TSDB_SQL_RETRIEVE) { + tscSetResRawPtr(pRes, pQueryInfo); + } else if ((UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_SUBQUERY)) { + tscSetResRawPtr(pRes, pQueryInfo); + } else if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_QUERY) && !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) { + tscSetResRawPtr(pRes, pQueryInfo); + } + if (pSql->pSubscription != NULL) { int32_t numOfCols = pQueryInfo->fieldsInfo.numOfOutput; @@ -2217,7 +2218,7 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) { } pRes->row = 0; - tscDebug("%p numOfRows:%" PRId64 ", offset:%" PRId64 ", complete:%d", pSql, pRes->numOfRows, pRes->offset, pRes->completed); + tscDebug("%p numOfRows:%d, offset:%" PRId64 ", complete:%d", pSql, pRes->numOfRows, pRes->offset, pRes->completed); return 0; } diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index a7b859b294..020305a0a8 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -321,7 +321,7 @@ TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen, TAOS_RES if (sqlLen > (uint32_t)tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); - terrno = TSDB_CODE_TSC_INVALID_SQL; + terrno = TSDB_CODE_TSC_EXCEED_SQL_LIMIT; return NULL; } @@ -394,7 +394,7 @@ int taos_affected_rows(TAOS_RES *tres) { SSqlObj* pSql = (SSqlObj*) tres; if (pSql == NULL || pSql->signature != pSql) return 0; - return (int)(pSql->res.numOfRows); + return pSql->res.numOfRows; } TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) { @@ -443,50 +443,30 @@ int taos_retrieve(TAOS_RES *res) { if (pCmd->command < TSDB_SQL_LOCAL) { pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH; } - tscProcessSql(pSql); - return (int)pRes->numOfRows; + tscProcessSql(pSql); + return pRes->numOfRows; } -int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) { - SSqlObj *pSql = (SSqlObj *)res; - SSqlCmd *pCmd = &pSql->cmd; +static bool needToFetchNewBlock(SSqlObj* pSql) { SSqlRes *pRes = &pSql->res; + SSqlCmd *pCmd = &pSql->cmd; - if (pRes->qhandle == 0 || pSql->signature != pSql) { - *rows = NULL; - return 0; - } - - // Retrieve new block - tscResetForNextRetrieve(pRes); - if (pCmd->command < TSDB_SQL_LOCAL) { - pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH; - } - - tscProcessSql(pSql); - if (pRes->numOfRows == 0) { - *rows = NULL; - return 0; - } - - // secondary merge has handle this situation - if (pCmd->command != TSDB_SQL_RETRIEVE_LOCALMERGE) { - pRes->numOfClauseTotal += pRes->numOfRows; - } - - SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0); - if (pQueryInfo == NULL) - return 0; - - assert(0); - for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { - tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i, 0); - } - - *rows = pRes->tsrow; - - return (int)((pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows); + return (pRes->completed != true || hasMoreVnodesToTry(pSql) || hasMoreClauseToTry(pSql)) && + (pCmd->command == TSDB_SQL_RETRIEVE || + pCmd->command == TSDB_SQL_RETRIEVE_LOCALMERGE || + pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE || + pCmd->command == TSDB_SQL_FETCH || + pCmd->command == TSDB_SQL_SHOW || + pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE || + pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE || + pCmd->command == TSDB_SQL_SELECT || + pCmd->command == TSDB_SQL_DESCRIBE_TABLE || + pCmd->command == TSDB_SQL_SERV_STATUS || + pCmd->command == TSDB_SQL_CURRENT_DB || + pCmd->command == TSDB_SQL_SERV_VERSION || + pCmd->command == TSDB_SQL_CLI_VERSION || + pCmd->command == TSDB_SQL_CURRENT_USER); } TAOS_ROW taos_fetch_row(TAOS_RES *res) { @@ -509,77 +489,50 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) { // set the sql object owner tscSetSqlOwner(pSql); - // current data set are exhausted, fetch more data from node - if (pRes->row >= pRes->numOfRows && (pRes->completed != true || hasMoreVnodesToTry(pSql) || hasMoreClauseToTry(pSql)) && - (pCmd->command == TSDB_SQL_RETRIEVE || - pCmd->command == TSDB_SQL_RETRIEVE_LOCALMERGE || - pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE || - pCmd->command == TSDB_SQL_FETCH || - pCmd->command == TSDB_SQL_SHOW || - pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE || - pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE || - pCmd->command == TSDB_SQL_SELECT || - pCmd->command == TSDB_SQL_DESCRIBE_TABLE || - pCmd->command == TSDB_SQL_SERV_STATUS || - pCmd->command == TSDB_SQL_CURRENT_DB || - pCmd->command == TSDB_SQL_SERV_VERSION || - pCmd->command == TSDB_SQL_CLI_VERSION || - pCmd->command == TSDB_SQL_CURRENT_USER )) { + // current data set are exhausted, fetch more result from node + if (pRes->row >= pRes->numOfRows && needToFetchNewBlock(pSql)) { taos_fetch_rows_a(res, waitForRetrieveRsp, pSql->pTscObj); tsem_wait(&pSql->rspSem); } - void* data = doSetResultRowData(pSql, true); + void* data = doSetResultRowData(pSql); tscClearSqlOwner(pSql); return data; } int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) { -#if 0 SSqlObj *pSql = (SSqlObj *)res; - SSqlCmd *pCmd = &pSql->cmd; - SSqlRes *pRes = &pSql->res; - - int nRows = 0; - if (pSql == NULL || pSql->signature != pSql) { terrno = TSDB_CODE_TSC_DISCONNECTED; - *rows = NULL; return 0; } - // projection query on metric, pipeline retrieve data from vnode list, - // instead of two-stage mergednodeProcessMsgFromShell free qhandle - nRows = taos_fetch_block_impl(res, rows); + SSqlCmd *pCmd = &pSql->cmd; + SSqlRes *pRes = &pSql->res; - // current subclause is completed, try the next subclause - while (rows == NULL && pCmd->clauseIndex < pCmd->numOfClause - 1) { - SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex); - - pSql->cmd.command = pQueryInfo->command; - pCmd->clauseIndex++; - - pRes->numOfTotal += pRes->numOfClauseTotal; - pRes->numOfClauseTotal = 0; - pRes->rspType = 0; - - pSql->subState.numOfSub = 0; - tfree(pSql->pSubs); - - assert(pSql->fp == NULL); - - tscDebug("%p try data in the next subclause:%d, total subclause:%d", pSql, pCmd->clauseIndex, pCmd->numOfClause); - tscProcessSql(pSql); - - nRows = taos_fetch_block_impl(res, rows); + if (pRes->qhandle == 0 || + pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED || + pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT || + pCmd->command == TSDB_SQL_INSERT) { + return 0; } - return nRows; -#endif + tscResetForNextRetrieve(pRes); - (*rows) = taos_fetch_row(res); - return ((*rows) != NULL)? 1:0; + // set the sql object owner + tscSetSqlOwner(pSql); + + // current data set are exhausted, fetch more data from node + if (needToFetchNewBlock(pSql)) { + taos_fetch_rows_a(res, waitForRetrieveRsp, pSql->pTscObj); + tsem_wait(&pSql->rspSem); + } + + *rows = pRes->urow; + + tscClearSqlOwner(pSql); + return pRes->numOfRows; } int taos_select_db(TAOS *taos, const char *db) { @@ -600,7 +553,7 @@ int taos_select_db(TAOS *taos, const char *db) { } // send free message to vnode to free qhandle and corresponding resources in vnode -static UNUSED_FUNC bool tscKillQueryInDnode(SSqlObj* pSql) { +static bool tscKillQueryInDnode(SSqlObj* pSql) { SSqlCmd* pCmd = &pSql->cmd; SSqlRes* pRes = &pSql->res; @@ -795,6 +748,25 @@ void taos_stop_query(TAOS_RES *res) { tscDebug("%p query is cancelled", res); } +bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col) { + SSqlObj *pSql = (SSqlObj *)res; + if (pSql == NULL || pSql->signature != pSql) { + return true; + } + + SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0); + if (pQueryInfo == NULL) { + return true; + } + + SInternalField* pInfo = (SInternalField*)TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, col); + if (col < 0 || col >= tscNumOfFields(pQueryInfo) || row < 0 || row > pSql->res.numOfRows) { + return true; + } + + return isNull(((char*) pSql->res.urow[col]) + row * pInfo->field.bytes, pInfo->field.type); +} + int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) { int len = 0; for (int i = 0; i < num_fields; ++i) { @@ -892,18 +864,16 @@ int taos_validate_sql(TAOS *taos, const char *sql) { int32_t sqlLen = (int32_t)strlen(sql); if (sqlLen > tsMaxSQLStringLen) { tscError("%p sql too long", pSql); - pRes->code = TSDB_CODE_TSC_INVALID_SQL; tfree(pSql); - return pRes->code; + return TSDB_CODE_TSC_EXCEED_SQL_LIMIT; } pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1); if (pSql->sqlstr == NULL) { - pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; tscError("%p failed to malloc sql string buffer", pSql); tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(pSql), pObj); tfree(pSql); - return pRes->code; + return TSDB_CODE_TSC_OUT_OF_MEMORY; } strtolower(pSql->sqlstr, sql); diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index bc522d4007..6ebbeeef41 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -594,7 +594,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr if (taosArrayGetSize(result) > 0) { SVgroupTableInfo* prevGroup = taosArrayGet(result, taosArrayGetSize(result) - 1); - tscDebug("%p vgId:%d, tables:%"PRId64, pSql, prevGroup->vgInfo.vgId, taosArrayGetSize(prevGroup->itemList)); + tscDebug("%p vgId:%d, tables:%"PRIzu, pSql, prevGroup->vgInfo.vgId, taosArrayGetSize(prevGroup->itemList)); } taosArrayPush(result, &info); @@ -612,7 +612,7 @@ void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArr if (taosArrayGetSize(result) > 0) { SVgroupTableInfo* g = taosArrayGet(result, taosArrayGetSize(result) - 1); - tscDebug("%p vgId:%d, tables:%"PRId64, pSql, g->vgInfo.vgId, taosArrayGetSize(g->itemList)); + tscDebug("%p vgId:%d, tables:%"PRIzu, pSql, g->vgInfo.vgId, taosArrayGetSize(g->itemList)); } } @@ -753,7 +753,7 @@ static int32_t getIntersectionOfTableTuple(SQueryInfo* pQueryInfo, SSqlObj* pPar } #endif - tscDebug("%p tags match complete, result: %"PRId64", %"PRId64, pParentSql, t1, t2); + tscDebug("%p tags match complete, result: %"PRIzu", %"PRIzu, pParentSql, t1, t2); return TSDB_CODE_SUCCESS; } @@ -948,7 +948,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow if (!pRes->completed) { taosGetTmpfilePath("ts-join", pSupporter->path); pSupporter->f = fopen(pSupporter->path, "w"); - pRes->row = (int32_t)pRes->numOfRows; + pRes->row = pRes->numOfRows; taos_fetch_rows_a(tres, tsCompRetrieveCallback, param); return; @@ -974,7 +974,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow // TODO check for failure pSupporter->f = fopen(pSupporter->path, "w"); - pRes->row = (int32_t)pRes->numOfRows; + pRes->row = pRes->numOfRows; // set the callback function pSql->fp = tscJoinQueryCallback; @@ -1085,7 +1085,7 @@ static void joinRetrieveFinalResCallback(void* param, TAOS_RES* tres, int numOfR SSqlRes* pRes1 = &pParentSql->pSubs[i]->res; if (pRes1->row > 0 && pRes1->numOfRows > 0) { - tscDebug("%p sub:%p index:%d numOfRows:%"PRId64" total:%"PRId64 " (not retrieve)", pParentSql, pParentSql->pSubs[i], i, + tscDebug("%p sub:%p index:%d numOfRows:%d total:%"PRId64 " (not retrieve)", pParentSql, pParentSql->pSubs[i], i, pRes1->numOfRows, pRes1->numOfTotal); assert(pRes1->row < pRes1->numOfRows); } else { @@ -1093,7 +1093,7 @@ static void joinRetrieveFinalResCallback(void* param, TAOS_RES* tres, int numOfR pRes1->numOfClauseTotal += pRes1->numOfRows; } - tscDebug("%p sub:%p index:%d numOfRows:%"PRId64" total:%"PRId64, pParentSql, pParentSql->pSubs[i], i, + tscDebug("%p sub:%p index:%d numOfRows:%d total:%"PRId64, pParentSql, pParentSql->pSubs[i], i, pRes1->numOfRows, pRes1->numOfTotal); } } @@ -1644,6 +1644,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { tExtMemBuffer ** pMemoryBuf = NULL; tOrderDescriptor *pDesc = NULL; SColumnModel *pModel = NULL; + SColumnModel *pFinalModel = NULL; pRes->qhandle = 0x1; // hack the qhandle check @@ -1662,7 +1663,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { assert(pState->numOfSub > 0); - int32_t ret = tscLocalReducerEnvCreate(pSql, &pMemoryBuf, &pDesc, &pModel, nBufferSize); + int32_t ret = tscLocalReducerEnvCreate(pSql, &pMemoryBuf, &pDesc, &pModel, &pFinalModel, nBufferSize); if (ret != 0) { pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; tscQueueAsyncRes(pSql); @@ -1677,7 +1678,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { if (pSql->pSubs == NULL) { tfree(pSql->pSubs); pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; - tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pState->numOfSub); + tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pFinalModel,pState->numOfSub); tscQueueAsyncRes(pSql); return ret; @@ -1707,6 +1708,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { trs->subqueryIndex = i; trs->pParentSql = pSql; trs->pFinalColModel = pModel; + trs->pFFColModel = pFinalModel; SSqlObj *pNew = tscCreateSTableSubquery(pSql, trs, NULL); if (pNew == NULL) { @@ -1730,13 +1732,13 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { tscError("%p failed to prepare subquery structure and launch subqueries", pSql); pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; - tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pState->numOfSub); + tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pFinalModel, pState->numOfSub); doCleanupSubqueries(pSql, i); return pRes->code; // free all allocated resource } if (pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED) { - tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pState->numOfSub); + tscLocalReducerEnvDestroy(pMemoryBuf, pDesc, pModel, pFinalModel, pState->numOfSub); doCleanupSubqueries(pSql, i); return pRes->code; } @@ -1876,7 +1878,7 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO tstrerror(pParentSql->res.code)); // release allocated resource - tscLocalReducerEnvDestroy(trsupport->pExtMemBuffer, trsupport->pOrderDescriptor, trsupport->pFinalColModel, + tscLocalReducerEnvDestroy(trsupport->pExtMemBuffer, trsupport->pOrderDescriptor, trsupport->pFinalColModel, trsupport->pFFColModel, pState->numOfSub); tscFreeRetrieveSup(pSql); @@ -2030,7 +2032,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR assert(pRes->numOfRows == numOfRows); int64_t num = atomic_add_fetch_64(&pState->numOfRetrievedRows, numOfRows); - tscDebug("%p sub:%p retrieve numOfRows:%" PRId64 " totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d", pParentSql, pSql, + tscDebug("%p sub:%p retrieve numOfRows:%d totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d", pParentSql, pSql, pRes->numOfRows, pState->numOfRetrievedRows, pSql->epSet.fqdn[pSql->epSet.inUse], idx); if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0)) { @@ -2057,7 +2059,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR } int32_t ret = saveToBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pRes->data, - (int32_t)pRes->numOfRows, pQueryInfo->groupbyExpr.orderType); + pRes->numOfRows, pQueryInfo->groupbyExpr.orderType); if (ret != 0) { // set no disk space error info, and abort retry tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE); } else if (pRes->completed) { @@ -2169,7 +2171,7 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows) return; } - tscDebug("%p Async insertion completed, total inserted:%" PRId64, pParentObj, pParentObj->res.numOfRows); + tscDebug("%p Async insertion completed, total inserted:%d", pParentObj, pParentObj->res.numOfRows); // restore user defined fp pParentObj->fp = pParentObj->fetchFp; @@ -2312,10 +2314,10 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) { return; } - int32_t totalSize = tscGetResRowLength(pQueryInfo->exprList); + int32_t rowSize = tscGetResRowLength(pQueryInfo->exprList); - assert(numOfRes * totalSize > 0); - char* tmp = realloc(pRes->pRsp, numOfRes * totalSize); + assert(numOfRes * rowSize > 0); + char* tmp = realloc(pRes->pRsp, numOfRes * rowSize + sizeof(tFilePage)); if (tmp == NULL) { pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; return; @@ -2323,9 +2325,12 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) { pRes->pRsp = tmp; } - pRes->data = pRes->pRsp; + tFilePage* pFilePage = (tFilePage*) pRes->pRsp; + pFilePage->num = numOfRes; + pRes->data = pFilePage->data; char* data = pRes->data; + int16_t bytes = 0; size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); @@ -2352,6 +2357,17 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) { pRes->numOfRows = numOfRes; pRes->numOfClauseTotal += numOfRes; + + int32_t finalRowSize = 0; + for(int32_t i = 0; i < tscNumOfFields(pQueryInfo); ++i) { + TAOS_FIELD* pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i); + finalRowSize += pField->bytes; + } + + doArithmeticCalculate(pQueryInfo, pFilePage, rowSize, finalRowSize); + + pRes->data = pFilePage->data; + tscSetResRawPtr(pRes, pQueryInfo); } void tscBuildResFromSubqueries(SSqlObj *pSql) { @@ -2364,13 +2380,12 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) { if (pRes->tsrow == NULL) { SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex); + pRes->numOfCols = (int16_t) tscSqlExprNumOfExprs(pQueryInfo); - size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); - pRes->numOfCols = (int16_t)numOfExprs; - - pRes->tsrow = calloc(numOfExprs, POINTER_BYTES); - pRes->buffer = calloc(numOfExprs, POINTER_BYTES); - pRes->length = calloc(numOfExprs, sizeof(int32_t)); + pRes->tsrow = calloc(pRes->numOfCols, POINTER_BYTES); + pRes->urow = calloc(pRes->numOfCols, POINTER_BYTES); + pRes->buffer = calloc(pRes->numOfCols, POINTER_BYTES); + pRes->length = calloc(pRes->numOfCols, sizeof(int32_t)); if (pRes->tsrow == NULL || pRes->buffer == NULL || pRes->length == NULL) { pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; @@ -2390,7 +2405,7 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) { } } -static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) { +static UNUSED_FUNC void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) { SSqlRes *pRes = &pSql->res; if (pRes->tsrow[columnIndex] != NULL && pField->type == TSDB_DATA_TYPE_NCHAR) { @@ -2414,7 +2429,7 @@ static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pF } } -char *getArithemicInputSrc(void *param, const char *name, int32_t colId) { +char *getArithmeticInputSrc(void *param, const char *name, int32_t colId) { SArithmeticSupport *pSupport = (SArithmeticSupport *) param; int32_t index = -1; @@ -2432,7 +2447,7 @@ char *getArithemicInputSrc(void *param, const char *name, int32_t colId) { return pSupport->data[index] + pSupport->offset * pExpr->resBytes; } -TAOS_ROW doSetResultRowData(SSqlObj *pSql, bool finalResult) { +TAOS_ROW doSetResultRowData(SSqlObj *pSql) { SSqlCmd *pCmd = &pSql->cmd; SSqlRes *pRes = &pSql->res; @@ -2445,22 +2460,20 @@ TAOS_ROW doSetResultRowData(SSqlObj *pSql, bool finalResult) { SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex); size_t size = tscNumOfFields(pQueryInfo); - int32_t offset = 0; - for (int i = 0; i < size; ++i) { - tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i, offset); - TAOS_FIELD *pField = TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i); + SInternalField* pInfo = (SInternalField*)TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i); - offset += pField->bytes; + int32_t type = pInfo->field.type; + int32_t bytes = pInfo->field.bytes; - // primary key column cannot be null in interval query, no need to check - if (i == 0 && pQueryInfo->interval.interval > 0) { - continue; + if (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR) { + pRes->tsrow[i] = isNull(pRes->urow[i], type) ? NULL : pRes->urow[i]; + } else { + pRes->tsrow[i] = isNull(pRes->urow[i], type) ? NULL : varDataVal(pRes->urow[i]); + pRes->length[i] = varDataLen(pRes->urow[i]); } - if (pRes->tsrow[i] != NULL && pField->type == TSDB_DATA_TYPE_NCHAR) { - transferNcharData(pSql, i, pField); - } + ((char**) pRes->urow)[i] += bytes; } pRes->row++; // index increase one-step diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 27824fc1ff..7a82bcaaab 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -220,13 +220,11 @@ bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo) { } bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo) { - size_t numOfOutput = tscNumOfFields(pQueryInfo); - size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); - - if (numOfOutput == numOfExprs) { + if (tscIsProjectionQuery(pQueryInfo)) { return false; } + size_t numOfOutput = tscNumOfFields(pQueryInfo); for(int32_t i = 0; i < numOfOutput; ++i) { SExprInfo* pExprInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, i)->pArithExprInfo; if (pExprInfo != NULL) { @@ -265,16 +263,20 @@ void tscClearInterpInfo(SQueryInfo* pQueryInfo) { int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) { if (pRes->tsrow == NULL) { - int32_t numOfOutput = pQueryInfo->fieldsInfo.numOfOutput; - pRes->numOfCols = numOfOutput; + pRes->numOfCols = pQueryInfo->fieldsInfo.numOfOutput; - pRes->tsrow = calloc(numOfOutput, POINTER_BYTES); - pRes->length = calloc(numOfOutput, sizeof(int32_t)); - pRes->buffer = calloc(numOfOutput, POINTER_BYTES); + pRes->tsrow = calloc(pRes->numOfCols, POINTER_BYTES); + pRes->urow = calloc(pRes->numOfCols, POINTER_BYTES); + pRes->length = calloc(pRes->numOfCols, sizeof(int32_t)); + pRes->buffer = calloc(pRes->numOfCols, POINTER_BYTES); // not enough memory - if (pRes->tsrow == NULL || (pRes->buffer == NULL && pRes->numOfCols > 0)) { + if (pRes->tsrow == NULL || pRes->urow == NULL || pRes->length == NULL || (pRes->buffer == NULL && pRes->numOfCols > 0)) { tfree(pRes->tsrow); + tfree(pRes->urow); + tfree(pRes->length); + tfree(pRes->buffer); + pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; return pRes->code; } @@ -283,6 +285,71 @@ int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) { return TSDB_CODE_SUCCESS; } +void tscSetResRawPtr(SSqlRes* pRes, SQueryInfo* pQueryInfo) { + assert(pRes->numOfCols > 0); + + int32_t offset = 0; + + for (int32_t i = 0; i < pRes->numOfCols; ++i) { + SInternalField* pInfo = (SInternalField*)TARRAY_GET_ELEM(pQueryInfo->fieldsInfo.internalField, i); + + pRes->urow[i] = pRes->data + offset * pRes->numOfRows; + pRes->length[i] = pInfo->field.bytes; + + offset += pInfo->field.bytes; + + // generated the user-defined column result + if (pInfo->pSqlExpr != NULL && TSDB_COL_IS_UD_COL(pInfo->pSqlExpr->colInfo.flag)) { + if (pInfo->pSqlExpr->param[1].nType == TSDB_DATA_TYPE_NULL) { + setNullN(pRes->urow[i], pInfo->field.type, pInfo->field.bytes, (int32_t) pRes->numOfRows); + } else { + if (pInfo->field.type == TSDB_DATA_TYPE_NCHAR || pInfo->field.type == TSDB_DATA_TYPE_BINARY) { + assert(pInfo->pSqlExpr->param[1].nLen <= pInfo->field.bytes); + + for (int32_t k = 0; k < pRes->numOfRows; ++k) { + char* p = ((char**)pRes->urow)[i] + k * pInfo->field.bytes; + + memcpy(varDataVal(p), pInfo->pSqlExpr->param[1].pz, pInfo->pSqlExpr->param[1].nLen); + varDataSetLen(p, pInfo->pSqlExpr->param[1].nLen); + } + } else { + for (int32_t k = 0; k < pRes->numOfRows; ++k) { + char* p = ((char**)pRes->urow)[i] + k * pInfo->field.bytes; + memcpy(p, &pInfo->pSqlExpr->param[1].i64Key, pInfo->field.bytes); + } + } + } + + } else if (pInfo->field.type == TSDB_DATA_TYPE_NCHAR) { + // convert unicode to native code in a temporary buffer extra one byte for terminated symbol + pRes->buffer[i] = realloc(pRes->buffer[i], pInfo->field.bytes * pRes->numOfRows); + + // string terminated char for binary data + memset(pRes->buffer[i], 0, pInfo->field.bytes * pRes->numOfRows); + + char* p = pRes->urow[i]; + for (int32_t k = 0; k < pRes->numOfRows; ++k) { + char* dst = pRes->buffer[i] + k * pInfo->field.bytes; + + if (isNull(p, TSDB_DATA_TYPE_NCHAR)) { + memcpy(dst, p, varDataTLen(p)); + } else { + int32_t length = taosUcs4ToMbs(varDataVal(p), varDataLen(p), varDataVal(dst)); + varDataSetLen(dst, length); + + if (length == 0) { + tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p); + } + } + + p += pInfo->field.bytes; + } + + memcpy(pRes->urow[i], pRes->buffer[i], pInfo->field.bytes * pRes->numOfRows); + } + } +} + static void tscDestroyResPointerInfo(SSqlRes* pRes) { if (pRes->buffer != NULL) { // free all buffers containing the multibyte string for (int i = 0; i < pRes->numOfCols; i++) { @@ -297,6 +364,7 @@ static void tscDestroyResPointerInfo(SSqlRes* pRes) { tfree(pRes->tsrow); tfree(pRes->length); tfree(pRes->buffer); + tfree(pRes->urow); tfree(pRes->pGroupRec); tfree(pRes->pColumnIndex); diff --git a/src/connector/grafanaplugin b/src/connector/grafanaplugin index d598db167e..ec77d9049a 160000 --- a/src/connector/grafanaplugin +++ b/src/connector/grafanaplugin @@ -1 +1 @@ -Subproject commit d598db167eb256fe67409b7bb3d0eb7fffc3ff8c +Subproject commit ec77d9049a719dabfd1a7c1122a209e201861944 diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml index 3b62f66d2e..e7124a0599 100755 --- a/src/connector/jdbc/pom.xml +++ b/src/connector/jdbc/pom.xml @@ -56,6 +56,23 @@ test + + + org.apache.httpcomponents + httpclient + 4.5.8 + + + org.apache.commons + commons-lang3 + 3.9 + + + com.alibaba + fastjson + 1.2.58 + + diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractTaosDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractTaosDriver.java new file mode 100644 index 0000000000..f864788bff --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/AbstractTaosDriver.java @@ -0,0 +1,161 @@ +package com.taosdata.jdbc; + +import java.io.*; +import java.sql.Driver; +import java.sql.DriverPropertyInfo; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.StringTokenizer; + +public abstract class AbstractTaosDriver implements Driver { + + private static final String TAOS_CFG_FILENAME = "taos.cfg"; + + /** + * @param cfgDirPath + * @return return the config dir + **/ + protected File loadConfigDir(String cfgDirPath) { + if (cfgDirPath == null) + return loadDefaultConfigDir(); + File cfgDir = new File(cfgDirPath); + if (!cfgDir.exists()) + return loadDefaultConfigDir(); + return cfgDir; + } + + /** + * @return search the default config dir, if the config dir is not exist will return null + */ + protected File loadDefaultConfigDir() { + File cfgDir; + File cfgDir_linux = new File("/etc/taos"); + cfgDir = cfgDir_linux.exists() ? cfgDir_linux : null; + File cfgDir_windows = new File("C:\\TDengine\\cfg"); + cfgDir = (cfgDir == null && cfgDir_windows.exists()) ? cfgDir_windows : cfgDir; + return cfgDir; + } + + protected List loadConfigEndpoints(File cfgFile) { + List endpoints = new ArrayList<>(); + try (BufferedReader reader = new BufferedReader(new FileReader(cfgFile))) { + String line = null; + while ((line = reader.readLine()) != null) { + if (line.trim().startsWith("firstEp") || line.trim().startsWith("secondEp")) { + endpoints.add(line.substring(line.indexOf('p') + 1).trim()); + } + if (endpoints.size() > 1) + break; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return endpoints; + } + + protected void loadTaosConfig(Properties info) { + if ((info.getProperty(TSDBDriver.PROPERTY_KEY_HOST) == null || + info.getProperty(TSDBDriver.PROPERTY_KEY_HOST).isEmpty()) && ( + info.getProperty(TSDBDriver.PROPERTY_KEY_PORT) == null || + info.getProperty(TSDBDriver.PROPERTY_KEY_PORT).isEmpty())) { + File cfgDir = loadConfigDir(info.getProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR)); + File cfgFile = cfgDir.listFiles((dir, name) -> TAOS_CFG_FILENAME.equalsIgnoreCase(name))[0]; + List endpoints = loadConfigEndpoints(cfgFile); + if (!endpoints.isEmpty()) { + info.setProperty(TSDBDriver.PROPERTY_KEY_HOST, endpoints.get(0).split(":")[0]); + info.setProperty(TSDBDriver.PROPERTY_KEY_PORT, endpoints.get(0).split(":")[1]); + } + } + } + + protected DriverPropertyInfo[] getPropertyInfo(Properties info) { + DriverPropertyInfo hostProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_HOST, info.getProperty(TSDBDriver.PROPERTY_KEY_HOST)); + hostProp.required = false; + hostProp.description = "Hostname"; + + DriverPropertyInfo portProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_PORT, info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT)); + portProp.required = false; + portProp.description = "Port"; + + DriverPropertyInfo dbProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_DBNAME, info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME)); + dbProp.required = false; + dbProp.description = "Database name"; + + DriverPropertyInfo userProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_USER, info.getProperty(TSDBDriver.PROPERTY_KEY_USER)); + userProp.required = true; + userProp.description = "User"; + + DriverPropertyInfo passwordProp = new DriverPropertyInfo(TSDBDriver.PROPERTY_KEY_PASSWORD, info.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD)); + passwordProp.required = true; + passwordProp.description = "Password"; + + DriverPropertyInfo[] propertyInfo = new DriverPropertyInfo[5]; + propertyInfo[0] = hostProp; + propertyInfo[1] = portProp; + propertyInfo[2] = dbProp; + propertyInfo[3] = userProp; + propertyInfo[4] = passwordProp; + return propertyInfo; + } + + protected Properties parseURL(String url, Properties defaults) { + Properties urlProps = (defaults != null) ? defaults : new Properties(); + + // parse properties + int beginningOfSlashes = url.indexOf("//"); + int index = url.indexOf("?"); + if (index != -1) { + String paramString = url.substring(index + 1, url.length()); + url = url.substring(0, index); + StringTokenizer queryParams = new StringTokenizer(paramString, "&"); + while (queryParams.hasMoreElements()) { + String parameterValuePair = queryParams.nextToken(); + int indexOfEqual = parameterValuePair.indexOf("="); + String parameter = null; + String value = null; + if (indexOfEqual != -1) { + parameter = parameterValuePair.substring(0, indexOfEqual); + if (indexOfEqual + 1 < parameterValuePair.length()) { + value = parameterValuePair.substring(indexOfEqual + 1); + } + } + if ((value != null && value.length() > 0) && (parameter != null && parameter.length() > 0)) { + urlProps.setProperty(parameter, value); + } + } + } + + // parse Product Name + String dbProductName = url.substring(0, beginningOfSlashes); + dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1); + dbProductName = dbProductName.substring(0, dbProductName.indexOf(":")); + // parse dbname + url = url.substring(beginningOfSlashes + 2); + int indexOfSlash = url.indexOf("/"); + if (indexOfSlash != -1) { + if (indexOfSlash + 1 < url.length()) { + urlProps.setProperty(TSDBDriver.PROPERTY_KEY_DBNAME, url.substring(indexOfSlash + 1)); + } + url = url.substring(0, indexOfSlash); + } + // parse port + int indexOfColon = url.indexOf(":"); + if (indexOfColon != -1) { + if (indexOfColon + 1 < url.length()) { + urlProps.setProperty(TSDBDriver.PROPERTY_KEY_PORT, url.substring(indexOfColon + 1)); + } + url = url.substring(0, indexOfColon); + } + // parse host + if (url != null && url.length() > 0 && url.trim().length() > 0) { + urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url); + } + return urlProps; + } + + + +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java index 5c7f80c715..633fdcd5ab 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/ColumnMetaData.java @@ -16,10 +16,10 @@ package com.taosdata.jdbc; public class ColumnMetaData { - int colType = 0; - String colName = null; - int colSize = -1; - int colIndex = 0; + private int colType = 0; + private String colName = null; + private int colSize = -1; + private int colIndex = 0; public int getColSize() { return colSize; diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java index f93412ffec..94abe39655 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBConnection.java @@ -14,7 +14,6 @@ *****************************************************************************/ package com.taosdata.jdbc; -import java.io.*; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; @@ -35,11 +34,10 @@ import java.util.*; import java.util.concurrent.Executor; public class TSDBConnection implements Connection { + protected Properties props = null; private TSDBJNIConnector connector = null; - protected Properties props = null; - private String catalog = null; private TSDBDatabaseMetaData dbMetaData = null; @@ -47,15 +45,21 @@ public class TSDBConnection implements Connection { private Properties clientInfoProps = new Properties(); private int timeoutMilliseconds = 0; - - private String tsCharSet = ""; + + private boolean batchFetch = false; public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException { this.dbMetaData = meta; connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST), Integer.parseInt(info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "0")), - info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME), info.getProperty(TSDBDriver.PROPERTY_KEY_USER), + info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME), + info.getProperty(TSDBDriver.PROPERTY_KEY_USER), info.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD)); + + String batchLoad = info.getProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD); + if (batchLoad != null) { + this.batchFetch = Boolean.parseBoolean(batchLoad); + } } private void connect(String host, int port, String dbName, String user, String password) throws SQLException { @@ -223,6 +227,14 @@ public class TSDBConnection implements Connection { return this.prepareStatement(sql); } + + public Boolean getBatchFetch() { + return this.batchFetch; + } + + public void setBatchFetch(Boolean batchFetch) { + this.batchFetch = batchFetch; + } public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java index 63c42ca399..06f88cebfa 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java @@ -14,7 +14,6 @@ *****************************************************************************/ package com.taosdata.jdbc; -import java.io.*; import java.sql.*; import java.util.*; import java.util.logging.Logger; @@ -38,7 +37,7 @@ import java.util.logging.Logger; * register it with the DriverManager. This means that a user can load and * register a driver by doing Class.forName("foo.bah.Driver") */ -public class TSDBDriver implements java.sql.Driver { +public class TSDBDriver extends AbstractTaosDriver { @Deprecated private static final String URL_PREFIX1 = "jdbc:TSDB://"; @@ -87,6 +86,11 @@ public class TSDBDriver implements java.sql.Driver { */ public static final String PROPERTY_KEY_CHARSET = "charset"; + /** + * fetch data from native function in a batch model + */ + public static final String PROPERTY_KEY_BATCH_LOAD = "batchfetch"; + private TSDBDatabaseMetaData dbMetaData = null; static { @@ -97,50 +101,6 @@ public class TSDBDriver implements java.sql.Driver { } } - private List loadConfigEndpoints(File cfgFile) { - List endpoints = new ArrayList<>(); - try (BufferedReader reader = new BufferedReader(new FileReader(cfgFile))) { - String line = null; - while ((line = reader.readLine()) != null) { - if (line.trim().startsWith("firstEp") || line.trim().startsWith("secondEp")) { - endpoints.add(line.substring(line.indexOf('p') + 1).trim()); - } - if (endpoints.size() > 1) - break; - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return endpoints; - } - - /** - * @param cfgDirPath - * @return return the config dir - **/ - private File loadConfigDir(String cfgDirPath) { - if (cfgDirPath == null) - return loadDefaultConfigDir(); - File cfgDir = new File(cfgDirPath); - if (!cfgDir.exists()) - return loadDefaultConfigDir(); - return cfgDir; - } - - /** - * @return search the default config dir, if the config dir is not exist will return null - */ - private File loadDefaultConfigDir() { - File cfgDir; - File cfgDir_linux = new File("/etc/taos"); - cfgDir = cfgDir_linux.exists() ? cfgDir_linux : null; - File cfgDir_windows = new File("C:\\TDengine\\cfg"); - cfgDir = (cfgDir == null && cfgDir_windows.exists()) ? cfgDir_windows : cfgDir; - return cfgDir; - } - public Connection connect(String url, Properties info) throws SQLException { if (url == null) throw new SQLException(TSDBConstants.WrapErrMsg("url is not set!")); @@ -152,26 +112,12 @@ public class TSDBDriver implements java.sql.Driver { if ((props = parseURL(url, info)) == null) { return null; } - //load taos.cfg start - if ((info.getProperty(TSDBDriver.PROPERTY_KEY_HOST) == null || - info.getProperty(TSDBDriver.PROPERTY_KEY_HOST).isEmpty()) && ( - info.getProperty(TSDBDriver.PROPERTY_KEY_PORT) == null || - info.getProperty(TSDBDriver.PROPERTY_KEY_PORT).isEmpty())) { - File cfgDir = loadConfigDir(info.getProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR)); - File cfgFile = cfgDir.listFiles((dir, name) -> "taos.cfg".equalsIgnoreCase(name))[0]; - List endpoints = loadConfigEndpoints(cfgFile); - if (!endpoints.isEmpty()) { - info.setProperty(TSDBDriver.PROPERTY_KEY_HOST, endpoints.get(0).split(":")[0]); - info.setProperty(TSDBDriver.PROPERTY_KEY_PORT, endpoints.get(0).split(":")[1]); - } - } + loadTaosConfig(info); try { - TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), - (String) props.get(PROPERTY_KEY_LOCALE), - (String) props.get(PROPERTY_KEY_CHARSET), - (String) props.get(PROPERTY_KEY_TIME_ZONE)); + TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE), + (String) props.get(PROPERTY_KEY_CHARSET), (String) props.get(PROPERTY_KEY_TIME_ZONE)); Connection newConn = new TSDBConnection(props, this.dbMetaData); return newConn; } catch (SQLWarning sqlWarning) { @@ -208,39 +154,13 @@ public class TSDBDriver implements java.sql.Driver { info = parseURL(url, info); } - DriverPropertyInfo hostProp = new DriverPropertyInfo(PROPERTY_KEY_HOST, info.getProperty(PROPERTY_KEY_HOST)); - hostProp.required = false; - hostProp.description = "Hostname"; - - DriverPropertyInfo portProp = new DriverPropertyInfo(PROPERTY_KEY_PORT, info.getProperty(PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT)); - portProp.required = false; - portProp.description = "Port"; - - DriverPropertyInfo dbProp = new DriverPropertyInfo(PROPERTY_KEY_DBNAME, info.getProperty(PROPERTY_KEY_DBNAME)); - dbProp.required = false; - dbProp.description = "Database name"; - - DriverPropertyInfo userProp = new DriverPropertyInfo(PROPERTY_KEY_USER, info.getProperty(PROPERTY_KEY_USER)); - userProp.required = true; - userProp.description = "User"; - - DriverPropertyInfo passwordProp = new DriverPropertyInfo(PROPERTY_KEY_PASSWORD, info.getProperty(PROPERTY_KEY_PASSWORD)); - passwordProp.required = true; - passwordProp.description = "Password"; - - DriverPropertyInfo[] propertyInfo = new DriverPropertyInfo[5]; - propertyInfo[0] = hostProp; - propertyInfo[1] = portProp; - propertyInfo[2] = dbProp; - propertyInfo[3] = userProp; - propertyInfo[4] = passwordProp; - - return propertyInfo; + return getPropertyInfo(info); } /** * example: jdbc:TAOS://127.0.0.1:0/db?user=root&password=your_password */ + @Override public Properties parseURL(String url, Properties defaults) { Properties urlProps = (defaults != null) ? defaults : new Properties(); if (url == null || url.length() <= 0 || url.trim().length() <= 0) @@ -257,26 +177,21 @@ public class TSDBDriver implements java.sql.Driver { url = url.substring(0, index); StringTokenizer queryParams = new StringTokenizer(paramString, "&"); while (queryParams.hasMoreElements()) { - String parameterValuePair = queryParams.nextToken(); - int indexOfEqual = parameterValuePair.indexOf("="); - String parameter = null; - String value = null; - if (indexOfEqual != -1) { - parameter = parameterValuePair.substring(0, indexOfEqual); - if (indexOfEqual + 1 < parameterValuePair.length()) { - value = parameterValuePair.substring(indexOfEqual + 1); - } - } - if ((value != null && value.length() > 0) && (parameter != null && parameter.length() > 0)) { - urlProps.setProperty(parameter, value); + String oneToken = queryParams.nextToken(); + String[] pair = oneToken.split("="); + + if ((pair[0] != null && pair[0].trim().length() > 0) && (pair[1] != null && pair[1].trim().length() > 0)) { + urlProps.setProperty(pair[0].trim(), pair[1].trim()); } } } + // parse Product Name String dbProductName = url.substring(0, beginningOfSlashes); dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1); dbProductName = dbProductName.substring(0, dbProductName.indexOf(":")); - // parse dbname + + // parse database name url = url.substring(beginningOfSlashes + 2); int indexOfSlash = url.indexOf("/"); if (indexOfSlash != -1) { @@ -285,6 +200,7 @@ public class TSDBDriver implements java.sql.Driver { } url = url.substring(0, indexOfSlash); } + // parse port int indexOfColon = url.indexOf(":"); if (indexOfColon != -1) { @@ -293,89 +209,15 @@ public class TSDBDriver implements java.sql.Driver { } url = url.substring(0, indexOfColon); } + if (url != null && url.length() > 0 && url.trim().length() > 0) { urlProps.setProperty(TSDBDriver.PROPERTY_KEY_HOST, url); } - + this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, urlProps.getProperty(TSDBDriver.PROPERTY_KEY_USER)); - - /* - String urlForMeta = url; - String dbProductName = url.substring(url.indexOf(":") + 1); - dbProductName = dbProductName.substring(0, dbProductName.indexOf(":")); - int beginningOfSlashes = url.indexOf("//"); - url = url.substring(beginningOfSlashes + 2); - - String host = url.substring(0, url.indexOf(":")); - url = url.substring(url.indexOf(":") + 1); - urlProps.setProperty(PROPERTY_KEY_HOST, host); - - String port = url.substring(0, url.indexOf("/")); - urlProps.setProperty(PROPERTY_KEY_PORT, port); - url = url.substring(url.indexOf("/") + 1); - - if (url.indexOf("?") != -1) { - String dbName = url.substring(0, url.indexOf("?")); - urlProps.setProperty(PROPERTY_KEY_DBNAME, dbName); - url = url.trim().substring(url.indexOf("?") + 1); - } else { - // without user & password so return - if (!url.trim().isEmpty()) { - String dbName = url.trim(); - urlProps.setProperty(PROPERTY_KEY_DBNAME, dbName); - } - this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, urlProps.getProperty("user")); - return urlProps; - } - - String user = ""; - - if (url.indexOf("&") == -1) { - String[] kvPair = url.trim().split("="); - if (kvPair.length == 2) { - setPropertyValue(urlProps, kvPair); - return urlProps; - } - } - - String[] queryStrings = url.trim().split("&"); - for (String queryStr : queryStrings) { - String[] kvPair = queryStr.trim().split("="); - if (kvPair.length < 2) { - continue; - } - setPropertyValue(urlProps, kvPair); - } - - user = urlProps.getProperty(PROPERTY_KEY_USER).toString(); - this.dbMetaData = new TSDBDatabaseMetaData(dbProductName, urlForMeta, user); -*/ return urlProps; } - private void setPropertyValue(Properties property, String[] keyValuePair) { - switch (keyValuePair[0].toLowerCase()) { - case PROPERTY_KEY_USER: - property.setProperty(PROPERTY_KEY_USER, keyValuePair[1]); - break; - case PROPERTY_KEY_PASSWORD: - property.setProperty(PROPERTY_KEY_PASSWORD, keyValuePair[1]); - break; - case PROPERTY_KEY_TIME_ZONE: - property.setProperty(PROPERTY_KEY_TIME_ZONE, keyValuePair[1]); - break; - case PROPERTY_KEY_LOCALE: - property.setProperty(PROPERTY_KEY_LOCALE, keyValuePair[1]); - break; - case PROPERTY_KEY_CHARSET: - property.setProperty(PROPERTY_KEY_CHARSET, keyValuePair[1]); - break; - case PROPERTY_KEY_CONFIG_DIR: - property.setProperty(PROPERTY_KEY_CONFIG_DIR, keyValuePair[1]); - break; - } - } - public int getMajorVersion() { return 2; } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java index edc160e323..f918463439 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java @@ -243,6 +243,11 @@ public class TSDBJNIConnector { private native int fetchRowImp(long connection, long resultSet, TSDBResultSetRowData rowData); + public int fetchBlock(long resultSet, TSDBResultSetBlockData blockData) { + return this.fetchBlockImp(this.taos, resultSet, blockData); + } + + private native int fetchBlockImp(long connection, long resultSet, TSDBResultSetBlockData blockData); /** * Execute close operation from C to release connection pointer by JNI * diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java index 961633b8ae..84a3f58f46 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java @@ -47,10 +47,14 @@ public class TSDBResultSet implements ResultSet { private List columnMetaDataList = new ArrayList(); private TSDBResultSetRowData rowData; + private TSDBResultSetBlockData blockData; + private boolean batchFetch = false; private boolean lastWasNull = false; private final int COLUMN_INDEX_START_VALUE = 1; + private int rowIndex = 0; + public TSDBJNIConnector getJniConnector() { return jniConnector; } @@ -67,6 +71,14 @@ public class TSDBResultSet implements ResultSet { this.resultSetPointer = resultSetPointer; } + public void setBatchFetch(boolean batchFetch) { + this.batchFetch = batchFetch; + } + + public Boolean getBatchFetch() { + return this.batchFetch; + } + public List getColumnMetaDataList() { return columnMetaDataList; } @@ -94,8 +106,8 @@ public class TSDBResultSet implements ResultSet { public TSDBResultSet() { } - public TSDBResultSet(TSDBJNIConnector connecter, long resultSetPointer) throws SQLException { - this.jniConnector = connecter; + public TSDBResultSet(TSDBJNIConnector connector, long resultSetPointer) throws SQLException { + this.jniConnector = connector; this.resultSetPointer = resultSetPointer; int code = this.jniConnector.getSchemaMetaData(this.resultSetPointer, this.columnMetaDataList); if (code == TSDBConstants.JNI_CONNECTION_NULL) { @@ -107,6 +119,7 @@ public class TSDBResultSet implements ResultSet { } this.rowData = new TSDBResultSetRowData(this.columnMetaDataList.size()); + this.blockData = new TSDBResultSetBlockData(this.columnMetaDataList, this.columnMetaDataList.size()); } public T unwrap(Class iface) throws SQLException { @@ -118,21 +131,42 @@ public class TSDBResultSet implements ResultSet { } public boolean next() throws SQLException { - if (rowData != null) { - this.rowData.clear(); - } + if (this.getBatchFetch()) { + if (this.blockData.forward()) { + return true; + } + + int code = this.jniConnector.fetchBlock(this.resultSetPointer, this.blockData); + this.blockData.reset(); + + if (code == TSDBConstants.JNI_CONNECTION_NULL) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); + } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL)); + } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0)); + } else if (code == TSDBConstants.JNI_FETCH_END) { + return false; + } - int code = this.jniConnector.fetchRow(this.resultSetPointer, this.rowData); - if (code == TSDBConstants.JNI_CONNECTION_NULL) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); - } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL)); - } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { - throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0)); - } else if (code == TSDBConstants.JNI_FETCH_END) { - return false; - } else { return true; + } else { + if (rowData != null) { + this.rowData.clear(); + } + + int code = this.jniConnector.fetchRow(this.resultSetPointer, this.rowData); + if (code == TSDBConstants.JNI_CONNECTION_NULL) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); + } else if (code == TSDBConstants.JNI_RESULT_SET_NULL) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_RESULT_SET_NULL)); + } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { + throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_NUM_OF_FIELDS_0)); + } else if (code == TSDBConstants.JNI_FETCH_END) { + return false; + } else { + return true; + } } } @@ -155,21 +189,30 @@ public class TSDBResultSet implements ResultSet { String res = null; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return this.blockData.getString(colIndex); } - return res; } public boolean getBoolean(int columnIndex) throws SQLException { boolean res = false; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getBoolean(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + } else { + return this.blockData.getBoolean(colIndex); } + return res; } @@ -177,66 +220,91 @@ public class TSDBResultSet implements ResultSet { byte res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = (byte) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return (byte) this.blockData.getInt(colIndex); } - return res; } public short getShort(int columnIndex) throws SQLException { short res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = (short) this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return (short) this.blockData.getInt(colIndex); } - return res; } public int getInt(int columnIndex) throws SQLException { int res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getInt(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return this.blockData.getInt(colIndex); } - return res; + } public long getLong(int columnIndex) throws SQLException { long res = 0l; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return this.blockData.getLong(colIndex); } - return res; } public float getFloat(int columnIndex) throws SQLException { float res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getFloat(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return (float) this.blockData.getDouble(colIndex); } - return res; } public double getDouble(int columnIndex) throws SQLException { double res = 0; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getDouble(colIndex, this.columnMetaDataList.get(colIndex).getColType()); + } + return res; + } else { + return this.blockData.getDouble(colIndex); } - return res; } /* @@ -249,25 +317,11 @@ public class TSDBResultSet implements ResultSet { */ @Deprecated public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - BigDecimal res = null; - int colIndex = getTrueColumnIndex(columnIndex); - - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); - } - return res; + return new BigDecimal(getLong(columnIndex)); } public byte[] getBytes(int columnIndex) throws SQLException { - byte[] res = null; - int colIndex = getTrueColumnIndex(columnIndex); - - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getString(colIndex, this.columnMetaDataList.get(colIndex).getColType()).getBytes(); - } - return res; + return getString(columnIndex).getBytes(); } public Date getDate(int columnIndex) throws SQLException { @@ -284,11 +338,15 @@ public class TSDBResultSet implements ResultSet { Timestamp res = null; int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - if (!lastWasNull) { - res = this.rowData.getTimestamp(colIndex); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + if (!lastWasNull) { + res = this.rowData.getTimestamp(colIndex); + } + return res; + } else { + return this.blockData.getTimestamp(columnIndex); } - return res; } public InputStream getAsciiStream(int columnIndex) throws SQLException { @@ -400,8 +458,12 @@ public class TSDBResultSet implements ResultSet { public Object getObject(int columnIndex) throws SQLException { int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - return this.rowData.get(colIndex); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + return this.rowData.get(colIndex); + } else { + return this.blockData.get(colIndex); + } } public Object getObject(String columnLabel) throws SQLException { @@ -433,8 +495,12 @@ public class TSDBResultSet implements ResultSet { public BigDecimal getBigDecimal(int columnIndex) throws SQLException { int colIndex = getTrueColumnIndex(columnIndex); - this.lastWasNull = this.rowData.wasNull(colIndex); - return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); + if (!this.getBatchFetch()) { + this.lastWasNull = this.rowData.wasNull(colIndex); + return new BigDecimal(this.rowData.getLong(colIndex, this.columnMetaDataList.get(colIndex).getColType())); + } else { + return new BigDecimal(this.blockData.getLong(colIndex)); + } } public BigDecimal getBigDecimal(String columnLabel) throws SQLException { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java new file mode 100644 index 0000000000..9352cf5253 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java @@ -0,0 +1,497 @@ +/*************************************************************************** + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + *****************************************************************************/ +package com.taosdata.jdbc; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.nio.ShortBuffer; +import java.sql.SQLDataException; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class TSDBResultSetBlockData { + private int numOfRows = 0; + private int rowIndex = 0; + + private List columnMetaDataList; + private ArrayList colData = null; + + public TSDBResultSetBlockData(List colMeta, int numOfCols) { + this.columnMetaDataList = colMeta; + this.colData = new ArrayList(numOfCols); + } + + public TSDBResultSetBlockData() { + this.colData = new ArrayList(); + } + + public void clear() { + int size = this.colData.size(); + if (this.colData != null) { + this.colData.clear(); + } + + setNumOfCols(size); + } + + public int getNumOfRows() { + return this.numOfRows; + } + + public void setNumOfRows(int numOfRows) { + this.numOfRows = numOfRows; + } + + public int getNumOfCols() { + return this.colData.size(); + } + + public void setNumOfCols(int numOfCols) { + this.colData = new ArrayList(numOfCols); + this.colData.addAll(Collections.nCopies(numOfCols, null)); + } + + public boolean hasMore() { + return this.rowIndex < this.numOfRows; + } + + public boolean forward() { + if (this.rowIndex > this.numOfRows) { + return false; + } + + return ((++this.rowIndex) < this.numOfRows); + } + + public void reset() { + this.rowIndex = 0; + } + + public void setBoolean(int col, boolean value) { + colData.set(col, value); + } + + public void setByteArray(int col, int length, byte[] value) { + try { + switch (this.columnMetaDataList.get(col).getColType()) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + ShortBuffer sb = buf.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); + this.colData.set(col, sb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_INT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + IntBuffer ib = buf.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); + this.colData.set(col, ib); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); + this.colData.set(col, lb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + FloatBuffer fb = buf.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer(); + this.colData.set(col, fb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + DoubleBuffer db = buf.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer(); + this.colData.set(col, db); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + LongBuffer lb = buf.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer(); + this.colData.set(col, lb); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { + ByteBuffer buf = ByteBuffer.wrap(value, 0, length); + buf.order(ByteOrder.LITTLE_ENDIAN); + this.colData.set(col, buf); + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static class NullType { + private static final byte NULL_BOOL_VAL = 0x2; + private static final String NULL_STR = "null"; + + public String toString() { + return NullType.NULL_STR; + } + + public static boolean isBooleanNull(byte val) { + return val == NullType.NULL_BOOL_VAL; + } + + private static boolean isTinyIntNull(byte val) { + return val == Byte.MIN_VALUE; + } + + private static boolean isSmallIntNull(short val) { + return val == Short.MIN_VALUE; + } + + private static boolean isIntNull(int val) { + return val == Integer.MIN_VALUE; + } + + private static boolean isBigIntNull(long val) { + return val == Long.MIN_VALUE; + } + + private static boolean isFloatNull(float val) { + return Float.isNaN(val); + } + + private static boolean isDoubleNull(double val) { + return Double.isNaN(val); + } + + private static boolean isBinaryNull(byte[] val, int length) { + if (length != Byte.BYTES) { + return false; + } + + return val[0] == 0xFF; + } + + private static boolean isNcharNull(byte[] val, int length) { + if (length != Integer.BYTES) { + return false; + } + + return (val[0] & val[1] & val[2] & val[3]) == 0xFF; + } + + } + + /** + * The original type may not be a string type, but will be converted to by + * calling this method + * + * @param col column index + * @return + * @throws SQLException + */ + public String getString(int col) throws SQLException { + Object obj = get(col); + if (obj == null) { + return new NullType().toString(); + } + + return obj.toString(); + } + + public int getInt(int col) { + Object obj = get(col); + if (obj == null) { + return 0; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return ((Long) obj).intValue(); + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return ((Double) obj).intValue(); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + return Integer.parseInt((String) obj); + } + } + + return 0; + } + + public boolean getBoolean(int col) throws SQLException { + Object obj = get(col); + if (obj == null) { + return Boolean.FALSE; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return ((int) obj == 0L) ? Boolean.FALSE : Boolean.TRUE; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (((Long) obj) == 0L) ? Boolean.FALSE : Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return (((Double) obj) == 0) ? Boolean.FALSE : Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + if ("TRUE".compareToIgnoreCase((String) obj) == 0) { + return Boolean.TRUE; + } else if ("FALSE".compareToIgnoreCase((String) obj) == 0) { + return Boolean.TRUE; + } else { + throw new SQLDataException(); + } + } + } + + return Boolean.FALSE; + } + + public long getLong(int col) throws SQLException { + Object obj = get(col); + if (obj == null) { + return 0; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (long) obj; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return ((Double) obj).longValue(); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + return Long.parseLong((String) obj); + } + } + + return 0; + } + + public Timestamp getTimestamp(int col) { + try { + return new Timestamp(getLong(col)); + } catch (SQLException e) { + e.printStackTrace(); + } + + return null; + } + + public double getDouble(int col) { + Object obj = get(col); + if (obj == null) { + return 0; + } + + int type = this.columnMetaDataList.get(col).getColType(); + switch (type) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_INT: { + return (int) obj; + } + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: { + return (long) obj; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + return (double) obj; + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + return Double.parseDouble((String) obj); + } + } + + return 0; + } + + public Object get(int col) { + int fieldSize = this.columnMetaDataList.get(col).getColSize(); + + switch (this.columnMetaDataList.get(col).getColType()) { + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + + byte val = bb.get(this.rowIndex); + if (NullType.isBooleanNull(val)) { + return null; + } + + return (val == 0x0) ? Boolean.FALSE : Boolean.TRUE; + } + + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + + byte val = bb.get(this.rowIndex); + if (NullType.isTinyIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + ShortBuffer sb = (ShortBuffer) this.colData.get(col); + short val = sb.get(this.rowIndex); + if (NullType.isSmallIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_INT: { + IntBuffer ib = (IntBuffer) this.colData.get(col); + int val = ib.get(this.rowIndex); + if (NullType.isIntNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + LongBuffer lb = (LongBuffer) this.colData.get(col); + long val = lb.get(this.rowIndex); + if (NullType.isBigIntNull(val)) { + return null; + } + + return (long) val; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + FloatBuffer fb = (FloatBuffer) this.colData.get(col); + float val = fb.get(this.rowIndex); + if (NullType.isFloatNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + DoubleBuffer lb = (DoubleBuffer) this.colData.get(col); + double val = lb.get(this.rowIndex); + if (NullType.isDoubleNull(val)) { + return null; + } + + return val; + } + + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (NullType.isBinaryNull(dest, length)) { + return null; + } + + return new String(dest); + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { + ByteBuffer bb = (ByteBuffer) this.colData.get(col); + bb.position(fieldSize * this.rowIndex); + + int length = bb.getShort(); + + byte[] dest = new byte[length]; + bb.get(dest, 0, length); + if (NullType.isNcharNull(dest, length)) { + return null; + } + + try { + String ss = TaosGlobalConfig.getCharset(); + return new String(dest, ss); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + + return 0; + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java index 8efcac9000..c57f19550d 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java @@ -218,5 +218,4 @@ public class TSDBResultSetRowData { public void setData(ArrayList data) { this.data = (ArrayList) data.clone(); } - } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java index 5c6b0545e9..cdd88b825e 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBStatement.java @@ -19,7 +19,7 @@ import java.util.ArrayList; import java.util.List; public class TSDBStatement implements Statement { - private TSDBJNIConnector connecter = null; + private TSDBJNIConnector connector = null; /** * To store batched commands @@ -45,9 +45,9 @@ public class TSDBStatement implements Statement { this.connection = connection; } - TSDBStatement(TSDBConnection connection, TSDBJNIConnector connecter) { + TSDBStatement(TSDBConnection connection, TSDBJNIConnector connector) { this.connection = connection; - this.connecter = connecter; + this.connector = connector; this.isClosed = false; } @@ -65,25 +65,27 @@ public class TSDBStatement implements Statement { } // TODO make sure it is not a update query - pSql = this.connecter.executeQuery(sql); + pSql = this.connector.executeQuery(sql); - long resultSetPointer = this.connecter.getResultSet(); + long resultSetPointer = this.connector.getResultSet(); if (resultSetPointer == TSDBConstants.JNI_CONNECTION_NULL) { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); } // create/insert/update/delete/alter if (resultSetPointer == TSDBConstants.JNI_NULL_POINTER) { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); return null; } - if (!this.connecter.isUpdateQuery(pSql)) { - return new TSDBResultSet(this.connecter, resultSetPointer); + if (!this.connector.isUpdateQuery(pSql)) { + TSDBResultSet res = new TSDBResultSet(this.connector, resultSetPointer); + res.setBatchFetch(this.connection.getBatchFetch()); + return res; } else { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); return null; } @@ -95,28 +97,28 @@ public class TSDBStatement implements Statement { } // TODO check if current query is update query - pSql = this.connecter.executeQuery(sql); - long resultSetPointer = this.connecter.getResultSet(); + pSql = this.connector.executeQuery(sql); + long resultSetPointer = this.connector.getResultSet(); if (resultSetPointer == TSDBConstants.JNI_CONNECTION_NULL) { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); } - this.affectedRows = this.connecter.getAffectedRows(pSql); - this.connecter.freeResultSet(pSql); + this.affectedRows = this.connector.getAffectedRows(pSql); + this.connector.freeResultSet(pSql); return this.affectedRows; } public String getErrorMsg(long pSql) { - return this.connecter.getErrMsg(pSql); + return this.connector.getErrMsg(pSql); } public void close() throws SQLException { if (!isClosed) { - if (!this.connecter.isResultsetClosed()) { - this.connecter.freeResultSet(); + if (!this.connector.isResultsetClosed()) { + this.connector.freeResultSet(); } isClosed = true; } @@ -136,7 +138,7 @@ public class TSDBStatement implements Statement { } public void setMaxRows(int max) throws SQLException { - // always set maxRows to zero, meaning unlimitted rows in a resultSet + // always set maxRows to zero, meaning unlimited rows in a resultSet } public void setEscapeProcessing(boolean enable) throws SQLException { @@ -172,15 +174,15 @@ public class TSDBStatement implements Statement { throw new SQLException("Invalid method call on a closed statement."); } boolean res = true; - pSql = this.connecter.executeQuery(sql); - long resultSetPointer = this.connecter.getResultSet(); + pSql = this.connector.executeQuery(sql); + long resultSetPointer = this.connector.getResultSet(); if (resultSetPointer == TSDBConstants.JNI_CONNECTION_NULL) { - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL)); } else if (resultSetPointer == TSDBConstants.JNI_NULL_POINTER) { // no result set is retrieved - this.connecter.freeResultSet(pSql); + this.connector.freeResultSet(pSql); res = false; } @@ -191,10 +193,10 @@ public class TSDBStatement implements Statement { if (isClosed) { throw new SQLException("Invalid method call on a closed statement."); } - long resultSetPointer = connecter.getResultSet(); + long resultSetPointer = connector.getResultSet(); TSDBResultSet resSet = null; if (resultSetPointer != TSDBConstants.JNI_NULL_POINTER) { - resSet = new TSDBResultSet(connecter, resultSetPointer); + resSet = new TSDBResultSet(connector, resultSetPointer); } return resSet; } @@ -267,7 +269,7 @@ public class TSDBStatement implements Statement { } public Connection getConnection() throws SQLException { - if (this.connecter != null) + if (this.connector != null) return this.connection; throw new SQLException(TSDBConstants.UNSUPPORT_METHOD_EXCEPTIONZ_MSG); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java new file mode 100644 index 0000000000..b82efca3ef --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java @@ -0,0 +1,319 @@ +package com.taosdata.jdbc.rs; + +import com.taosdata.jdbc.TSDBConstants; + +import java.sql.*; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +public class RestfulConnection implements Connection { + + private final String host; + private final int port; + private final Properties props; + private final String database; + private final String url; + + + public RestfulConnection(String host, String port, Properties props, String database, String url) { + this.host = host; + this.port = Integer.parseInt(port); + this.props = props; + this.database = database; + this.url = url; + } + + @Override + public Statement createStatement() throws SQLException { + if (isClosed()) + throw new SQLException(TSDBConstants.WrapErrMsg("restful TDengine connection is closed.")); + return new RestfulStatement(this, this.database); + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + return null; + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + return null; + } + + @Override + public String nativeSQL(String sql) throws SQLException { + return null; + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + + } + + @Override + public boolean getAutoCommit() throws SQLException { + return false; + } + + @Override + public void commit() throws SQLException { + + } + + @Override + public void rollback() throws SQLException { + + } + + @Override + public void close() throws SQLException { + + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + //TODO: RestfulDatabaseMetaData is not implemented + return new RestfulDatabaseMetaData(); + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + + } + + @Override + public boolean isReadOnly() throws SQLException { + return false; + } + + @Override + public void setCatalog(String catalog) throws SQLException { + + } + + @Override + public String getCatalog() throws SQLException { + return null; + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + + } + + @Override + public int getTransactionIsolation() throws SQLException { + return 0; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException { + + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return null; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return null; + } + + @Override + public Map> getTypeMap() throws SQLException { + return null; + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + + } + + @Override + public void setHoldability(int holdability) throws SQLException { + + } + + @Override + public int getHoldability() throws SQLException { + return 0; + } + + @Override + public Savepoint setSavepoint() throws SQLException { + return null; + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + return null; + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + return null; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + return null; + } + + @Override + public Clob createClob() throws SQLException { + return null; + } + + @Override + public Blob createBlob() throws SQLException { + return null; + } + + @Override + public NClob createNClob() throws SQLException { + return null; + } + + @Override + public SQLXML createSQLXML() throws SQLException { + return null; + } + + @Override + public boolean isValid(int timeout) throws SQLException { + return false; + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + + } + + @Override + public String getClientInfo(String name) throws SQLException { + return null; + } + + @Override + public Properties getClientInfo() throws SQLException { + return null; + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return null; + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return null; + } + + @Override + public void setSchema(String schema) throws SQLException { + + } + + @Override + public String getSchema() throws SQLException { + return null; + } + + @Override + public void abort(Executor executor) throws SQLException { + + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + + } + + @Override + public int getNetworkTimeout() throws SQLException { + return 0; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public Properties getProps() { + return props; + } + + public String getDatabase() { + return database; + } + + public String getUrl() { + return url; + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDatabaseMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDatabaseMetaData.java new file mode 100644 index 0000000000..2b4d7899fa --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDatabaseMetaData.java @@ -0,0 +1,886 @@ +package com.taosdata.jdbc.rs; + +import java.sql.*; + +public class RestfulDatabaseMetaData implements DatabaseMetaData { + + @Override + public boolean allProceduresAreCallable() throws SQLException { + return false; + } + + @Override + public boolean allTablesAreSelectable() throws SQLException { + return false; + } + + @Override + public String getURL() throws SQLException { + return null; + } + + @Override + public String getUserName() throws SQLException { + return null; + } + + @Override + public boolean isReadOnly() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedHigh() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedLow() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedAtStart() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedAtEnd() throws SQLException { + return false; + } + + @Override + public String getDatabaseProductName() throws SQLException { + return null; + } + + @Override + public String getDatabaseProductVersion() throws SQLException { + return null; + } + + @Override + public String getDriverName() throws SQLException { + return null; + } + + @Override + public String getDriverVersion() throws SQLException { + return null; + } + + @Override + public int getDriverMajorVersion() { + return 0; + } + + @Override + public int getDriverMinorVersion() { + return 0; + } + + @Override + public boolean usesLocalFiles() throws SQLException { + return false; + } + + @Override + public boolean usesLocalFilePerTable() throws SQLException { + return false; + } + + @Override + public boolean supportsMixedCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesUpperCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesLowerCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesMixedCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public String getIdentifierQuoteString() throws SQLException { + return null; + } + + @Override + public String getSQLKeywords() throws SQLException { + return null; + } + + @Override + public String getNumericFunctions() throws SQLException { + return null; + } + + @Override + public String getStringFunctions() throws SQLException { + return null; + } + + @Override + public String getSystemFunctions() throws SQLException { + return null; + } + + @Override + public String getTimeDateFunctions() throws SQLException { + return null; + } + + @Override + public String getSearchStringEscape() throws SQLException { + return null; + } + + @Override + public String getExtraNameCharacters() throws SQLException { + return null; + } + + @Override + public boolean supportsAlterTableWithAddColumn() throws SQLException { + return false; + } + + @Override + public boolean supportsAlterTableWithDropColumn() throws SQLException { + return false; + } + + @Override + public boolean supportsColumnAliasing() throws SQLException { + return false; + } + + @Override + public boolean nullPlusNonNullIsNull() throws SQLException { + return false; + } + + @Override + public boolean supportsConvert() throws SQLException { + return false; + } + + @Override + public boolean supportsConvert(int fromType, int toType) throws SQLException { + return false; + } + + @Override + public boolean supportsTableCorrelationNames() throws SQLException { + return false; + } + + @Override + public boolean supportsDifferentTableCorrelationNames() throws SQLException { + return false; + } + + @Override + public boolean supportsExpressionsInOrderBy() throws SQLException { + return false; + } + + @Override + public boolean supportsOrderByUnrelated() throws SQLException { + return false; + } + + @Override + public boolean supportsGroupBy() throws SQLException { + return false; + } + + @Override + public boolean supportsGroupByUnrelated() throws SQLException { + return false; + } + + @Override + public boolean supportsGroupByBeyondSelect() throws SQLException { + return false; + } + + @Override + public boolean supportsLikeEscapeClause() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleResultSets() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsNonNullableColumns() throws SQLException { + return false; + } + + @Override + public boolean supportsMinimumSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsCoreSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsExtendedSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92EntryLevelSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92IntermediateSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92FullSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsIntegrityEnhancementFacility() throws SQLException { + return false; + } + + @Override + public boolean supportsOuterJoins() throws SQLException { + return false; + } + + @Override + public boolean supportsFullOuterJoins() throws SQLException { + return false; + } + + @Override + public boolean supportsLimitedOuterJoins() throws SQLException { + return false; + } + + @Override + public String getSchemaTerm() throws SQLException { + return null; + } + + @Override + public String getProcedureTerm() throws SQLException { + return null; + } + + @Override + public String getCatalogTerm() throws SQLException { + return null; + } + + @Override + public boolean isCatalogAtStart() throws SQLException { + return false; + } + + @Override + public String getCatalogSeparator() throws SQLException { + return null; + } + + @Override + public boolean supportsSchemasInDataManipulation() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInProcedureCalls() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInTableDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInIndexDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInDataManipulation() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInProcedureCalls() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInTableDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInIndexDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsPositionedDelete() throws SQLException { + return false; + } + + @Override + public boolean supportsPositionedUpdate() throws SQLException { + return false; + } + + @Override + public boolean supportsSelectForUpdate() throws SQLException { + return false; + } + + @Override + public boolean supportsStoredProcedures() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInComparisons() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInExists() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInIns() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInQuantifieds() throws SQLException { + return false; + } + + @Override + public boolean supportsCorrelatedSubqueries() throws SQLException { + return false; + } + + @Override + public boolean supportsUnion() throws SQLException { + return false; + } + + @Override + public boolean supportsUnionAll() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenCursorsAcrossCommit() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenCursorsAcrossRollback() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenStatementsAcrossCommit() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenStatementsAcrossRollback() throws SQLException { + return false; + } + + @Override + public int getMaxBinaryLiteralLength() throws SQLException { + return 0; + } + + @Override + public int getMaxCharLiteralLength() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInGroupBy() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInIndex() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInOrderBy() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInSelect() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInTable() throws SQLException { + return 0; + } + + @Override + public int getMaxConnections() throws SQLException { + return 0; + } + + @Override + public int getMaxCursorNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxIndexLength() throws SQLException { + return 0; + } + + @Override + public int getMaxSchemaNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxProcedureNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxCatalogNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxRowSize() throws SQLException { + return 0; + } + + @Override + public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { + return false; + } + + @Override + public int getMaxStatementLength() throws SQLException { + return 0; + } + + @Override + public int getMaxStatements() throws SQLException { + return 0; + } + + @Override + public int getMaxTableNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxTablesInSelect() throws SQLException { + return 0; + } + + @Override + public int getMaxUserNameLength() throws SQLException { + return 0; + } + + @Override + public int getDefaultTransactionIsolation() throws SQLException { + return 0; + } + + @Override + public boolean supportsTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsTransactionIsolationLevel(int level) throws SQLException { + return false; + } + + @Override + public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsDataManipulationTransactionsOnly() throws SQLException { + return false; + } + + @Override + public boolean dataDefinitionCausesTransactionCommit() throws SQLException { + return false; + } + + @Override + public boolean dataDefinitionIgnoredInTransactions() throws SQLException { + return false; + } + + @Override + public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { + return null; + } + + @Override + public ResultSet getSchemas() throws SQLException { + return null; + } + + @Override + public ResultSet getCatalogs() throws SQLException { + return null; + } + + @Override + public ResultSet getTableTypes() throws SQLException { + return null; + } + + @Override + public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { + return null; + } + + @Override + public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { + return null; + } + + @Override + public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { + return null; + } + + @Override + public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { + return null; + } + + @Override + public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { + return null; + } + + @Override + public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { + return null; + } + + @Override + public ResultSet getTypeInfo() throws SQLException { + return null; + } + + @Override + public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { + return null; + } + + @Override + public boolean supportsResultSetType(int type) throws SQLException { + return false; + } + + @Override + public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { + return false; + } + + @Override + public boolean ownUpdatesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean ownDeletesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean ownInsertsAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersUpdatesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersDeletesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersInsertsAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean updatesAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean deletesAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean insertsAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean supportsBatchUpdates() throws SQLException { + return false; + } + + @Override + public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { + return null; + } + + @Override + public Connection getConnection() throws SQLException { + return null; + } + + @Override + public boolean supportsSavepoints() throws SQLException { + return false; + } + + @Override + public boolean supportsNamedParameters() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleOpenResults() throws SQLException { + return false; + } + + @Override + public boolean supportsGetGeneratedKeys() throws SQLException { + return false; + } + + @Override + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { + return null; + } + + @Override + public boolean supportsResultSetHoldability(int holdability) throws SQLException { + return false; + } + + @Override + public int getResultSetHoldability() throws SQLException { + return 0; + } + + @Override + public int getDatabaseMajorVersion() throws SQLException { + return 0; + } + + @Override + public int getDatabaseMinorVersion() throws SQLException { + return 0; + } + + @Override + public int getJDBCMajorVersion() throws SQLException { + return 0; + } + + @Override + public int getJDBCMinorVersion() throws SQLException { + return 0; + } + + @Override + public int getSQLStateType() throws SQLException { + return 0; + } + + @Override + public boolean locatorsUpdateCopy() throws SQLException { + return false; + } + + @Override + public boolean supportsStatementPooling() throws SQLException { + return false; + } + + @Override + public RowIdLifetime getRowIdLifetime() throws SQLException { + return null; + } + + @Override + public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { + return null; + } + + @Override + public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { + return false; + } + + @Override + public boolean autoCommitFailureClosesAllResultSets() throws SQLException { + return false; + } + + @Override + public ResultSet getClientInfoProperties() throws SQLException { + return null; + } + + @Override + public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { + return null; + } + + @Override + public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { + return null; + } + + @Override + public boolean generatedKeyAlwaysReturned() throws SQLException { + return false; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java new file mode 100644 index 0000000000..c267f660de --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java @@ -0,0 +1,91 @@ +package com.taosdata.jdbc.rs; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.taosdata.jdbc.AbstractTaosDriver; +import com.taosdata.jdbc.TSDBConstants; +import com.taosdata.jdbc.TSDBDriver; +import com.taosdata.jdbc.rs.util.HttpClientPoolUtil; + +import java.sql.*; +import java.util.Properties; +import java.util.logging.Logger; + +public class RestfulDriver extends AbstractTaosDriver { + + private static final String URL_PREFIX = "jdbc:TAOS-RS://"; + + static { + try { + DriverManager.registerDriver(new RestfulDriver()); + } catch (SQLException e) { + throw new RuntimeException(TSDBConstants.WrapErrMsg("can not register Restful JDBC driver"), e); + } + } + + @Override + public Connection connect(String url, Properties info) throws SQLException { + // throw SQLException if url is null + if (url == null) + throw new SQLException(TSDBConstants.WrapErrMsg("url is not set!")); + // return null if url is not be accepted + if (!acceptsURL(url)) + return null; + + Properties props = parseURL(url, info); + String host = props.getProperty(TSDBDriver.PROPERTY_KEY_HOST, "localhost"); + String port = props.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "6041"); + String database = props.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME); + + String loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + + props.getProperty(TSDBDriver.PROPERTY_KEY_USER) + "/" + + props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD) + ""; + String result = HttpClientPoolUtil.execute(loginUrl); + JSONObject jsonResult = JSON.parseObject(result); + String status = jsonResult.getString("status"); + if (!status.equals("succ")) { + throw new SQLException(jsonResult.getString("desc")); + } + + return new RestfulConnection(host, port, props, database, url); + } + + @Override + public boolean acceptsURL(String url) throws SQLException { + if (url == null) + throw new SQLException(TSDBConstants.WrapErrMsg("url is null")); + return (url != null && url.length() > 0 && url.trim().length() > 0) && url.startsWith(URL_PREFIX); + } + + @Override + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { + if (info == null) { + info = new Properties(); + } + if (acceptsURL(url)) { + info = parseURL(url, info); + } + return getPropertyInfo(info); + } + + @Override + public int getMajorVersion() { + return 2; + } + + @Override + public int getMinorVersion() { + return 0; + } + + @Override + public boolean jdbcCompliant() { + return false; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + return null; + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java new file mode 100644 index 0000000000..c536ae4a89 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSet.java @@ -0,0 +1,1180 @@ +package com.taosdata.jdbc.rs; + +import com.taosdata.jdbc.TSDBConstants; +import org.apache.commons.lang3.StringUtils; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Map; + +public class RestfulResultSet implements ResultSet { + private boolean isClosed = false; + private int pos = -1; + private ArrayList> data; + private ArrayList fields; + + public RestfulResultSet(String str, String fieldData) { + data = new ArrayList<>(); + str = str.substring(2, str.length() - 2); + ArrayList strTemp = new ArrayList<>(Arrays.asList(str.split("],\\["))); + for (String s : strTemp) { + ArrayList curr = new ArrayList<>(Arrays.asList(s.split(","))); + data.add(curr); + } + if (!StringUtils.isBlank(fieldData)) { + fields = new ArrayList<>(); + fieldData = fieldData.substring(2, fieldData.length() - 2); + ArrayList fieldTemp = new ArrayList<>(Arrays.asList(fieldData.split("],\\["))); + for (String s : fieldTemp) { + String curr = Arrays.asList(s.split(",")).get(0); + fields.add(curr.substring(1, curr.length() - 1)); // 去掉双引号 + } + } + } + + @Override + public boolean next() throws SQLException { + if (isClosed) throw new SQLException(TSDBConstants.WrapErrMsg("Result is Closed!!!")); + if (pos < data.size() - 1) { + pos++; + return true; + } + return false; + } + + @Override + public void close() throws SQLException { + this.isClosed = true; + } + + @Override + public boolean wasNull() throws SQLException { + return data.isEmpty(); + } + + @Override + public String getString(int columnIndex) throws SQLException { + if (columnIndex > data.get(pos).size()) { + throw new SQLException(TSDBConstants.WrapErrMsg("Column Index out of range, " + columnIndex + " > " + data.get(pos).size())); + } + return data.get(pos).get(columnIndex - 1); + } + + @Override + public boolean getBoolean(int columnIndex) throws SQLException { + String result = getString(columnIndex); + if (!(result.equals("true") || result.equals("false"))) { + throw new SQLException("not boolean value"); + } + return result.equals("true"); + } + + @Override + public byte getByte(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public short getShort(int columnIndex) throws SQLException { + return Short.parseShort(getString(columnIndex)); + } + + @Override + public int getInt(int columnIndex) throws SQLException { + String result = getString(columnIndex); + return Integer.parseInt(result); + } + + @Override + public long getLong(int columnIndex) throws SQLException { + String result = getString(columnIndex); + return Long.parseLong(result); + } + + @Override + public float getFloat(int columnIndex) throws SQLException { + String result = getString(columnIndex); + return Float.parseFloat(result); + } + + @Override + public double getDouble(int columnIndex) throws SQLException { + String result = getString(columnIndex); + return Double.parseDouble(result); + } + + @Override + public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public byte[] getBytes(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Date getDate(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Time getTime(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Timestamp getTimestamp(int columnIndex) throws SQLException { + String strDate = getString(columnIndex); + strDate = strDate.substring(1, strDate.length() - 1); + return Timestamp.valueOf(strDate); + } + + @Override + public InputStream getAsciiStream(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public InputStream getUnicodeStream(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public InputStream getBinaryStream(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public String getString(String columnLabel) throws SQLException { + return getString(findColumn(columnLabel) + 1); + } + + @Override + public boolean getBoolean(String columnLabel) throws SQLException { + return Boolean.parseBoolean(getString(columnLabel)); + } + + @Override + public byte getByte(String columnLabel) throws SQLException { + return 0; + } + + @Override + public short getShort(String columnLabel) throws SQLException { + return Short.parseShort(getString(columnLabel)); + } + + @Override + public int getInt(String columnLabel) throws SQLException { + return Integer.parseInt(getString(columnLabel)); + } + + @Override + public long getLong(String columnLabel) throws SQLException { + return Long.parseLong(getString(columnLabel)); + } + + @Override + public float getFloat(String columnLabel) throws SQLException { + String result = getString(columnLabel); + return Float.parseFloat(result); + } + + @Override + public double getDouble(String columnLabel) throws SQLException { + return Double.parseDouble(getString(columnLabel)); + } + + @Override + public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { + return null; + } + + @Override + public byte[] getBytes(String columnLabel) throws SQLException { + return new byte[0]; + } + + @Override + public Date getDate(String columnLabel) throws SQLException { + return null; + } + + @Override + public Time getTime(String columnLabel) throws SQLException { + return null; + } + + @Override + public Timestamp getTimestamp(String columnLabel) throws SQLException { + return Timestamp.valueOf(getString(columnLabel)); + } + + @Override + public InputStream getAsciiStream(String columnLabel) throws SQLException { + return null; + } + + @Override + public InputStream getUnicodeStream(String columnLabel) throws SQLException { + return null; + } + + @Override + public InputStream getBinaryStream(String columnLabel) throws SQLException { + return null; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + //TODO: SQLFeature Not Supported +// throw new SQLFeatureNotSupportedException(); + } + + @Override + public void clearWarnings() throws SQLException { + return; + //TODO: SQLFeature Not Supported +// throw new SQLFeatureNotSupportedException(); + } + + @Override + public String getCursorName() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return new RestfulResultSetMetaData(fields); + } + + @Override + public Object getObject(int columnIndex) throws SQLException { +// return null; + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Object getObject(String columnLabel) throws SQLException { +// return null; + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public int findColumn(String columnLabel) throws SQLException { + return fields.indexOf(columnLabel); + } + + @Override + public Reader getCharacterStream(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Reader getCharacterStream(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public BigDecimal getBigDecimal(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public BigDecimal getBigDecimal(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean isBeforeFirst() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean isAfterLast() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean isFirst() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean isLast() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void beforeFirst() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void afterLast() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean first() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean last() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public int getRow() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean absolute(int row) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean relative(int rows) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean previous() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public int getFetchDirection() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void setFetchSize(int rows) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public int getFetchSize() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public int getType() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public int getConcurrency() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean rowUpdated() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean rowInserted() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean rowDeleted() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNull(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBoolean(int columnIndex, boolean x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateByte(int columnIndex, byte x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateShort(int columnIndex, short x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateInt(int columnIndex, int x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateLong(int columnIndex, long x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateFloat(int columnIndex, float x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateDouble(int columnIndex, double x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateString(int columnIndex, String x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBytes(int columnIndex, byte[] x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateDate(int columnIndex, Date x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateTime(int columnIndex, Time x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(int columnIndex, Object x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNull(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBoolean(String columnLabel, boolean x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateByte(String columnLabel, byte x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateShort(String columnLabel, short x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateInt(String columnLabel, int x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateLong(String columnLabel, long x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateFloat(String columnLabel, float x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateDouble(String columnLabel, double x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateString(String columnLabel, String x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBytes(String columnLabel, byte[] x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateDate(String columnLabel, Date x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateTime(String columnLabel, Time x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(String columnLabel, Object x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void insertRow() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRow() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void deleteRow() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void refreshRow() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void cancelRowUpdates() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void moveToInsertRow() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void moveToCurrentRow() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Statement getStatement() throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Object getObject(int columnIndex, Map> map) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Ref getRef(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Blob getBlob(int columnIndex) throws SQLException { + return null; + } + + @Override + public Clob getClob(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Array getArray(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Object getObject(String columnLabel, Map> map) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Ref getRef(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Blob getBlob(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Clob getClob(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Array getArray(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Date getDate(int columnIndex, Calendar cal) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Date getDate(String columnLabel, Calendar cal) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Time getTime(int columnIndex, Calendar cal) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Time getTime(String columnLabel, Calendar cal) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public URL getURL(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public URL getURL(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRef(int columnIndex, Ref x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRef(String columnLabel, Ref x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(int columnIndex, Blob x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(String columnLabel, Blob x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(int columnIndex, Clob x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(String columnLabel, Clob x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateArray(int columnIndex, Array x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateArray(String columnLabel, Array x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public RowId getRowId(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public RowId getRowId(String columnLabel) throws SQLException { + return null; + } + + @Override + public void updateRowId(int columnIndex, RowId x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRowId(String columnLabel, RowId x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public int getHoldability() throws SQLException { +// return 0; + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean isClosed() throws SQLException { + return false; + //TODO: SQLFeature Not Supported +// throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNString(int columnIndex, String nString) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNString(String columnLabel, String nString) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(int columnIndex, NClob nClob) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(String columnLabel, NClob nClob) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public NClob getNClob(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public NClob getNClob(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public SQLXML getSQLXML(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public SQLXML getSQLXML(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public String getNString(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public String getNString(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Reader getNCharacterStream(int columnIndex) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Reader getNCharacterStream(String columnLabel) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(int columnIndex, Reader reader) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(String columnLabel, Reader reader) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(int columnIndex, Reader reader) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(String columnLabel, Reader reader) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public T getObject(int columnIndex, Class type) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public T getObject(String columnLabel, Class type) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + //TODO: SQLFeature Not Supported + throw new SQLFeatureNotSupportedException(); + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java new file mode 100644 index 0000000000..5dd61391bc --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulResultSetMetaData.java @@ -0,0 +1,129 @@ +package com.taosdata.jdbc.rs; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.List; + +public class RestfulResultSetMetaData implements ResultSetMetaData { + + private List fields; + + public RestfulResultSetMetaData(List fields) { + this.fields = fields; + } + + @Override + public int getColumnCount() throws SQLException { + return fields.size(); + } + + @Override + public boolean isAutoIncrement(int column) throws SQLException { + return false; + } + + @Override + public boolean isCaseSensitive(int column) throws SQLException { + return false; + } + + @Override + public boolean isSearchable(int column) throws SQLException { + return false; + } + + @Override + public boolean isCurrency(int column) throws SQLException { + return false; + } + + @Override + public int isNullable(int column) throws SQLException { + return 0; + } + + @Override + public boolean isSigned(int column) throws SQLException { + return false; + } + + @Override + public int getColumnDisplaySize(int column) throws SQLException { + return 0; + } + + @Override + public String getColumnLabel(int column) throws SQLException { + return fields.get(column - 1); + } + + @Override + public String getColumnName(int column) throws SQLException { + return null; + } + + @Override + public String getSchemaName(int column) throws SQLException { + return null; + } + + @Override + public int getPrecision(int column) throws SQLException { + return 0; + } + + @Override + public int getScale(int column) throws SQLException { + return 0; + } + + @Override + public String getTableName(int column) throws SQLException { + return null; + } + + @Override + public String getCatalogName(int column) throws SQLException { + return null; + } + + @Override + public int getColumnType(int column) throws SQLException { + return 0; + } + + @Override + public String getColumnTypeName(int column) throws SQLException { + return null; + } + + @Override + public boolean isReadOnly(int column) throws SQLException { + return false; + } + + @Override + public boolean isWritable(int column) throws SQLException { + return false; + } + + @Override + public boolean isDefinitelyWritable(int column) throws SQLException { + return false; + } + + @Override + public String getColumnClassName(int column) throws SQLException { + return null; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java new file mode 100644 index 0000000000..20510f0135 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulStatement.java @@ -0,0 +1,280 @@ +package com.taosdata.jdbc.rs; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.taosdata.jdbc.TSDBConstants; +import com.taosdata.jdbc.rs.util.HttpClientPoolUtil; + +import java.sql.*; +import java.util.Arrays; +import java.util.List; + +public class RestfulStatement implements Statement { + + private final String catalog; + private final RestfulConnection conn; + + public RestfulStatement(RestfulConnection c, String catalog) { + this.conn = c; + this.catalog = catalog; + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + + final String url = "http://" + conn.getHost() + ":"+conn.getPort()+"/rest/sql"; + + String result = HttpClientPoolUtil.execute(url, sql); + String fields = ""; + List words = Arrays.asList(sql.split(" ")); + if (words.get(0).equalsIgnoreCase("select")) { + int index = 0; + if (words.contains("from")) { + index = words.indexOf("from"); + } + if (words.contains("FROM")) { + index = words.indexOf("FROM"); + } + fields = HttpClientPoolUtil.execute(url, "DESCRIBE " + words.get(index + 1)); + } + + JSONObject jsonObject = JSON.parseObject(result); + if (jsonObject.getString("status").equals("error")) { + throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + + jsonObject.getString("desc") + "\n" + + "error code: " + jsonObject.getString("code"))); + } + String dataStr = jsonObject.getString("data"); + if ("use".equalsIgnoreCase(fields.split(" ")[0])) { + return new RestfulResultSet(dataStr, ""); + } + + JSONObject jsonField = JSON.parseObject(fields); + if (jsonField == null) { + return new RestfulResultSet(dataStr, ""); + } + if (jsonField.getString("status").equals("error")) { + throw new SQLException(TSDBConstants.WrapErrMsg("SQL execution error: " + + jsonField.getString("desc") + "\n" + + "error code: " + jsonField.getString("code"))); + } + String fieldData = jsonField.getString("data"); + + return new RestfulResultSet(dataStr, fieldData); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + return 0; + } + + @Override + public void close() throws SQLException { + + } + + @Override + public int getMaxFieldSize() throws SQLException { + return 0; + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + + } + + @Override + public int getMaxRows() throws SQLException { + return 0; + } + + @Override + public void setMaxRows(int max) throws SQLException { + + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + + } + + @Override + public int getQueryTimeout() throws SQLException { + return 0; + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + + } + + @Override + public void cancel() throws SQLException { + + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException { + + } + + @Override + public void setCursorName(String name) throws SQLException { + + } + + @Override + public boolean execute(String sql) throws SQLException { + return false; + } + + @Override + public ResultSet getResultSet() throws SQLException { + return null; + } + + @Override + public int getUpdateCount() throws SQLException { + return 0; + } + + @Override + public boolean getMoreResults() throws SQLException { + return false; + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + + } + + @Override + public int getFetchDirection() throws SQLException { + return 0; + } + + @Override + public void setFetchSize(int rows) throws SQLException { + + } + + @Override + public int getFetchSize() throws SQLException { + return 0; + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return 0; + } + + @Override + public int getResultSetType() throws SQLException { + return 0; + } + + @Override + public void addBatch(String sql) throws SQLException { + + } + + @Override + public void clearBatch() throws SQLException { + + } + + @Override + public int[] executeBatch() throws SQLException { + return new int[0]; + } + + @Override + public Connection getConnection() throws SQLException { + return null; + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return false; + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return null; + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + return 0; + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + return 0; + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + return 0; + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + return false; + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + return false; + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + return false; + } + + @Override + public int getResultSetHoldability() throws SQLException { + return 0; + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + + } + + @Override + public boolean isPoolable() throws SQLException { + return false; + } + + @Override + public void closeOnCompletion() throws SQLException { + + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + return false; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/util/HttpClientPoolUtil.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/util/HttpClientPoolUtil.java new file mode 100644 index 0000000000..65399b122d --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/util/HttpClientPoolUtil.java @@ -0,0 +1,222 @@ +package com.taosdata.jdbc.rs.util; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HeaderElement; +import org.apache.http.HeaderElementIterator; +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.*; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.ConnectionKeepAliveStrategy; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicHeaderElementIterator; +import org.apache.http.protocol.HTTP; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; + + +public class HttpClientPoolUtil { + public static PoolingHttpClientConnectionManager cm = null; + public static CloseableHttpClient httpClient = null; + /** + * 默认content 类型 + */ + private static final String DEFAULT_CONTENT_TYPE = "application/json"; + /** + * 默认请求超时时间30s + */ + private static final int DEFAULT_TIME_OUT = 15000; + private static final int count = 32; + private static final int totalCount = 1000; + private static final int Http_Default_Keep_Time = 15000; + + /** + * 初始化连接池 + */ + public static synchronized void initPools() { + if (httpClient == null) { + cm = new PoolingHttpClientConnectionManager(); + cm.setDefaultMaxPerRoute(count); + cm.setMaxTotal(totalCount); + httpClient = HttpClients.custom().setKeepAliveStrategy(defaultStrategy).setConnectionManager(cm).build(); + } + } + + /** + * Http connection keepAlive 设置 + */ + public static ConnectionKeepAliveStrategy defaultStrategy = (response, context) -> { + HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); + int keepTime = Http_Default_Keep_Time * 1000; + while (it.hasNext()) { + HeaderElement headerElement = it.nextElement(); + String param = headerElement.getName(); + String value = headerElement.getValue(); + if (value != null && param.equalsIgnoreCase("timeout")) { + try { + return Long.parseLong(value) * 1000; + } catch (Exception e) { + new Exception( + "format KeepAlive timeout exception, exception:" + e.toString()) + .printStackTrace(); + } + } + } + return keepTime; + }; + + public static CloseableHttpClient getHttpClient() { + return httpClient; + } + + public static PoolingHttpClientConnectionManager getHttpConnectionManager() { + return cm; + } + + /** + * 执行http post请求 + * 默认采用Content-Type:application/json,Accept:application/json + * + * @param uri 请求地址 + * @param data 请求数据 + * @return responseBody + */ + public static String execute(String uri, String data) { + long startTime = System.currentTimeMillis(); + HttpEntity httpEntity = null; + HttpEntityEnclosingRequestBase method = null; + String responseBody = ""; + try { + if (httpClient == null) { + initPools(); + } + method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0); + method.setEntity(new StringEntity(data)); + HttpContext context = HttpClientContext.create(); + CloseableHttpResponse httpResponse = httpClient.execute(method, context); + httpEntity = httpResponse.getEntity(); + if (httpEntity != null) { + responseBody = EntityUtils.toString(httpEntity, "UTF-8"); + } + } catch (Exception e) { + if (method != null) { + method.abort(); + } +// e.printStackTrace(); +// logger.error("execute post request exception, url:" + uri + ", exception:" + e.toString() +// + ", cost time(ms):" + (System.currentTimeMillis() - startTime)); + new Exception("execute post request exception, url:" + + uri + ", exception:" + e.toString() + + ", cost time(ms):" + (System.currentTimeMillis() - startTime)) + .printStackTrace(); + } finally { + if (httpEntity != null) { + try { + EntityUtils.consumeQuietly(httpEntity); + } catch (Exception e) { +// e.printStackTrace(); +// logger.error("close response exception, url:" + uri + ", exception:" + e.toString() +// + ", cost time(ms):" + (System.currentTimeMillis() - startTime)); + new Exception( + "close response exception, url:" + uri + + ", exception:" + e.toString() + + ", cost time(ms):" + (System.currentTimeMillis() - startTime)) + .printStackTrace(); + } + } + } + return responseBody; + } + + /** + * * 创建请求 + * + * @param uri 请求url + * @param methodName 请求的方法类型 + * @param contentType contentType类型 + * @param timeout 超时时间 + * @return HttpRequestBase 返回类型 + * @author lisc + */ + public static HttpRequestBase getRequest(String uri, String methodName, String contentType, int timeout) { + if (httpClient == null) { + initPools(); + } + HttpRequestBase method; + if (timeout <= 0) { + timeout = DEFAULT_TIME_OUT; + } + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout * 1000) + .setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000) + .setExpectContinueEnabled(false).build(); + if (HttpPut.METHOD_NAME.equalsIgnoreCase(methodName)) { + method = new HttpPut(uri); + } else if (HttpPost.METHOD_NAME.equalsIgnoreCase(methodName)) { + method = new HttpPost(uri); + } else if (HttpGet.METHOD_NAME.equalsIgnoreCase(methodName)) { + method = new HttpGet(uri); + } else { + method = new HttpPost(uri); + } + + if (StringUtils.isBlank(contentType)) { + contentType = DEFAULT_CONTENT_TYPE; + } + method.addHeader("Content-Type", contentType); + method.addHeader("Accept", contentType); + method.setConfig(requestConfig); + return method; + } + + /** + * 执行GET 请求 + * + * @param uri 网址 + * @return responseBody + */ + public static String execute(String uri) { + long startTime = System.currentTimeMillis(); + HttpEntity httpEntity = null; + HttpRequestBase method = null; + String responseBody = ""; + try { + if (httpClient == null) { + initPools(); + } + method = getRequest(uri, HttpGet.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0); + HttpContext context = HttpClientContext.create(); + CloseableHttpResponse httpResponse = httpClient.execute(method, context); + httpEntity = httpResponse.getEntity(); + if (httpEntity != null) { + responseBody = EntityUtils.toString(httpEntity, "UTF-8"); +// logger.info("请求URL: " + uri + "+ 返回状态码:" + httpResponse.getStatusLine().getStatusCode()); + } + } catch (Exception e) { + if (method != null) { + method.abort(); + } + e.printStackTrace(); +// logger.error("execute get request exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):" +// + (System.currentTimeMillis() - startTime)); + System.out.println("log:调用 HttpClientPoolUtil execute get request exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):" + + (System.currentTimeMillis() - startTime)); + } finally { + if (httpEntity != null) { + try { + EntityUtils.consumeQuietly(httpEntity); + } catch (Exception e) { +// e.printStackTrace(); +// logger.error("close response exception, url:" + uri + ", exception:" + e.toString() +// + ",cost time(ms):" + (System.currentTimeMillis() - startTime)); + new Exception("close response exception, url:" + uri + ", exception:" + e.toString() + + ",cost time(ms):" + (System.currentTimeMillis() - startTime)) + .printStackTrace(); + } + } + } + return responseBody; + } +} \ No newline at end of file diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/BaseTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/BaseTest.java index b793a47c99..ce3735c128 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/BaseTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/BaseTest.java @@ -5,24 +5,24 @@ import com.taosdata.jdbc.utils.TDNodes; import org.junit.AfterClass; import org.junit.BeforeClass; -public class BaseTest { +public abstract class BaseTest { - private static boolean testCluster = false; + private static boolean testCluster = false; private static TDNodes nodes = new TDNodes(); - + @BeforeClass public static void setupEnv() { - try{ + try { if (nodes.getTDNode(1).getTaosdPid() != null) { System.out.println("Kill taosd before running JDBC test"); nodes.getTDNode(1).setRunning(1); nodes.stop(1); } - nodes.setTestCluster(testCluster); + nodes.setTestCluster(testCluster); nodes.deploy(1); nodes.start(1); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(); } } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java new file mode 100644 index 0000000000..83295df527 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/FailOverTest.java @@ -0,0 +1,36 @@ +package com.taosdata.jdbc.cases; + +import org.junit.Test; + +import java.sql.*; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +public class FailOverTest { + + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + + @Test + public void testFailOver() throws ClassNotFoundException { + Class.forName("com.taosdata.jdbc.TSDBDriver"); + final String url = "jdbc:TAOS://:/?user=root&password=taosdata"; + + long end = System.currentTimeMillis() + 1000 * 60 * 5; + while (System.currentTimeMillis() < end) { + try (Connection conn = DriverManager.getConnection(url)) { + Statement stmt = conn.createStatement(); + ResultSet resultSet = stmt.executeQuery("select server_status()"); + resultSet.next(); + int status = resultSet.getInt("server_status()"); + System.out.println(">>>>>>>>>" + sdf.format(new Date()) + " status : " + status); + stmt.close(); + TimeUnit.SECONDS.sleep(5); + } catch (SQLException | InterruptedException e) { + e.printStackTrace(); + } + } + + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDriverTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDriverTest.java new file mode 100644 index 0000000000..a91d1c2d6b --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulDriverTest.java @@ -0,0 +1,40 @@ +package com.taosdata.jdbc.rs; + +import org.junit.Assert; +import org.junit.Test; + +import java.sql.*; + +public class RestfulDriverTest { + + @Test + public void testCase001() { + try { + Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); + Connection connection = DriverManager.getConnection("jdbc:TAOS-RS://master:6041/?user=root&password=taosdata"); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("select * from log.log"); + ResultSetMetaData metaData = resultSet.getMetaData(); + while (resultSet.next()) { + for (int i = 1; i <= metaData.getColumnCount(); i++) { + String column = metaData.getColumnLabel(i); + String value = resultSet.getString(i); + System.out.print(column + ":" + value + "\t"); + } + System.out.println(); + } + statement.close(); + connection.close(); + } catch (SQLException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + + @Test + public void testAcceptUrl() throws SQLException { + Driver driver = new RestfulDriver(); + boolean isAccept = driver.acceptsURL("jdbc:TAOS-RS://master:6041"); + Assert.assertTrue(isAccept); + } + +} diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index 58e7b6acf1..0d8c07041a 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -3,7 +3,6 @@ PROJECT(TDengine) IF (TD_LINUX_64) find_program(HAVE_ODBCINST NAMES odbcinst) - IF (HAVE_ODBCINST) include(CheckSymbolExists) # shall we revert CMAKE_REQUIRED_LIBRARIES and how? @@ -14,20 +13,43 @@ IF (TD_LINUX_64) message(WARNING "unixodbc-dev is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc-dev") else () message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built") - AUX_SOURCE_DIRECTORY(src SRC) - - # generate dynamic library (*.so) - ADD_LIBRARY(todbc SHARED ${SRC}) - SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) - SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) - TARGET_LINK_LIBRARIES(todbc taos) - - install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/install.sh ${CMAKE_BINARY_DIR})") - - ADD_SUBDIRECTORY(tests) + find_package(FLEX) + if(NOT FLEX_FOUND) + message(FATAL_ERROR "you need to install flex first") + else () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0.0) + message(WARNING "gcc 4.8.0 will complain too much about flex-generated code, we just bypass building ODBC driver in such case") + else () + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wconversion") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") + ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tools) + ADD_SUBDIRECTORY(tests) + endif () + endif() endif() ELSE () message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc") ENDIF () ENDIF () +IF (TD_WINDOWS_64) + find_package(ODBC) + if (NOT ODBC_FOUND) + message(FATAL_ERROR "you need to install ODBC first") + else () + message(STATUS "ODBC_INCLUDE_DIRS: ${ODBC_INCLUDE_DIRS}") + message(STATUS "ODBC_LIBRARIES: ${ODBC_LIBRARIES}") + message(STATUS "ODBC_CONFIG: ${ODBC_CONFIG}") + endif () + find_package(FLEX) + if(NOT FLEX_FOUND) + message(WARNING "you need to install flex first\n" + "you may go to: https://github.com/lexxmark/winflexbison\n" + "or download from: https://github.com/lexxmark/winflexbison/releases") + else () + ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tools) + ADD_SUBDIRECTORY(tests) + endif() +ENDIF () diff --git a/src/connector/odbc/README.md b/src/connector/odbc/README.md new file mode 100644 index 0000000000..e026884a07 --- /dev/null +++ b/src/connector/odbc/README.md @@ -0,0 +1,88 @@ + +# ODBC Driver # + +- **very initial implementation of ODBC driver for TAOS + +- **currently partially supported ODBC functions are: ` +SQLAllocEnv +SQLFreeEnv +SQLAllocConnect +SQLFreeConnect +SQLConnect +SQLDisconnect +SQLAllocStmt +SQLAllocHandle +SQLFreeStmt +SQLExecDirect +SQLExecDirectW +SQLNumResultCols +SQLRowCount +SQLColAttribute +SQLGetData +SQLFetch +SQLPrepare +SQLExecute +SQLGetDiagField +SQLGetDiagRec +SQLBindParameter +SQLDriverConnect +SQLSetConnectAttr +SQLDescribeCol +SQLNumParams +SQLSetStmtAttr +ConfigDSN +` + +- **internationalized, you can specify different charset/code page for easy going. eg.: insert `utf-8.zh_cn` characters into database located in linux machine, while query them out in `gb2312/gb18030/...` code page in your chinese windows machine, or vice-versa. and much fun, insert `gb2312/gb18030/...` characters into database located in linux box from +your japanese windows box, and query them out in your local chinese windows machine. + +- **enable ODBC-aware software to communicate with TAOS. + +- **enable any language with ODBC-bindings/ODBC-plugings to communicate with TAOS + +- **still going on... + +# Building and Testing +**Note**: all `work` is done in TDengine's project directory + + +# Building under Linux, use Ubuntu as example +``` +sudo apt install unixodbc unixodbc-dev flex +rm -rf debug && cmake -B debug && cmake --build debug && cmake --install debug && echo yes +``` +# Building under Windows, use Windows 10 as example +- install windows `flex` port. We use [https://github.com/lexxmark/winflexbison](url) at the moment. Please be noted to append `` to your `PATH`. +- install Microsoft Visual Studio, take VS2015 as example here +- `"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64` +- `rmdir /s /q debug` +- `cmake -G "NMake Makefiles" -B debug` +- `cmake --build debug` +- `cmake --install debug` +- open your `Command Prompt` with Administrator's priviledge +- remove previously installed TAOS ODBC driver: run `C:\TDengine\todbcinst -u -f -n TAOS` +- install TAOS ODBC driver that was just built: run `C:\TDengine\todbcinst -i -n TAOS -p C:\TDengine\driver` +- add a new user dsn: run `odbcconf CONFIGDSN TAOS "DSN=TAOS_DSN|Server=:` + +# Test +we highly suggest that you build both in linux(ubuntu) and windows(windows 10) platform, because currently TAOS only has it's server-side port on linux platform. +**Note1**: content within <> shall be modified to match your environment +**Note2**: `.stmts` source files are all encoded in `UTF-8` +## start taosd in linux, suppose charset is `UTF-8` as default +``` +taosd -c ./debug/test/cfg +``` +## create data in linux +``` +./debug/build/bin/tcodbc --dsn TAOS_DSN --uid --pwd --sts ./src/connector/odbc/tests/create_data.stmts +-- +./debug/build/bin/tcodbc --dcs 'Driver=TAOS;UID=;PWD=;Server=:;client_enc=UTF-8' ./src/connector/odbc/tests/create_data.stmts +``` +## query data in windows +``` +.\debug\build\bin\tcodbc --dsn TAOS_DSN --uid --pwd --sts .\src\connector\odbc\tests\query_data.stmts +-- +.\debug\build\bin\tcodbc --dcs "Driver=TAOS;UID=;PWD=;Server=:;client_enc=UTF-8" .\src\connector\odbc\tests\query_data.stmts +``` + + diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt new file mode 100644 index 0000000000..2699e1bc90 --- /dev/null +++ b/src/connector/odbc/src/CMakeLists.txt @@ -0,0 +1,54 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF (TD_LINUX_64) + FLEX_TARGET(todbcFlexScanner + todbc_scanner.l + ${CMAKE_CURRENT_BINARY_DIR}/todbc_scanner.c + ) + set(todbc_flex_scanner_src + ${FLEX_todbcFlexScanner_OUTPUTS} + ) + AUX_SOURCE_DIRECTORY(. SRC) + + # generate dynamic library (*.so) + ADD_LIBRARY(todbc SHARED ${SRC} ${todbc_flex_scanner_src}) + SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) + TARGET_LINK_LIBRARIES(todbc taos odbcinst) + target_include_directories(todbc PUBLIC .) + + install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") +ENDIF () + +IF (TD_WINDOWS_64) + FLEX_TARGET(todbcFlexScanner + todbc_scanner.l + ${CMAKE_CURRENT_BINARY_DIR}/todbc_scanner.c + ) + set(todbc_flex_scanner_src + ${FLEX_todbcFlexScanner_OUTPUTS} + ) + AUX_SOURCE_DIRECTORY(. SRC) + + # generate dynamic library (*.dll) + ADD_LIBRARY(todbc SHARED + ${SRC} + ${todbc_flex_scanner_src} + ${CMAKE_CURRENT_BINARY_DIR}/todbc.rc + todbc.def) + TARGET_LINK_LIBRARIES(todbc taos_static odbccp32 legacy_stdio_definitions) + target_include_directories(todbc PUBLIC .) + target_compile_definitions(todbc PRIVATE "todbc_EXPORT") + + CONFIGURE_FILE("todbc.rc.in" + "${CMAKE_CURRENT_BINARY_DIR}/todbc.rc") + SET_TARGET_PROPERTIES(todbc PROPERTIES LINK_FLAGS + /DEF:todbc.def) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /GL") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") + + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.lib DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.exp DESTINATION driver) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/todbc.dll DESTINATION driver) +ENDIF () diff --git a/src/connector/odbc/src/install.sh b/src/connector/odbc/src/install.sh index b8c04677c7..02f31de70e 100755 --- a/src/connector/odbc/src/install.sh +++ b/src/connector/odbc/src/install.sh @@ -9,16 +9,18 @@ rm -f "${BLD_DIR}/template.dsn" cat > "${BLD_DIR}/template.ini" < "${BLD_DIR}/template.dsn" < +#include "os.h" + +#include #include -#include +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#define UTF8_ENC "UTF-8" +#define UTF16_ENC "UCS-2LE" +#define UNICODE_ENC "UCS-4LE" +#define GB18030_ENC "GB18030" #define GET_REF(obj) atomic_load_64(&obj->refcount) #define INC_REF(obj) atomic_add_fetch_64(&obj->refcount, 1) @@ -41,15 +58,22 @@ do { obj->err.err_no = eno; \ const char* estr = tstrerror(eno); \ if (!estr) estr = "Unknown error"; \ - int n = snprintf(NULL, 0, "%s: @[%d][TSDB:%x]" err_fmt "", estr, __LINE__, eno, ##__VA_ARGS__); \ + int n = snprintf(NULL, 0, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \ + eno, estr, \ + basename((char*)__FILE__), __LINE__, \ + ##__VA_ARGS__); \ if (n<0) break; \ - char *err_str = (char*)realloc(obj->err.err_str, n+1); \ + char *err_str = (char*)realloc(obj->err.err_str, (size_t)n+1); \ if (!err_str) break; \ obj->err.err_str = err_str; \ - snprintf(obj->err.err_str, n+1, "%s: @[%d][TSDB:%x]" err_fmt "", estr, __LINE__, eno, ##__VA_ARGS__); \ + snprintf(obj->err.err_str, (size_t)n+1, "[TSDB:%x]%s: @%s[%d]" err_fmt "", \ + eno, estr, \ + basename((char*)__FILE__), __LINE__, \ + ##__VA_ARGS__); \ snprintf((char*)obj->err.sql_state, sizeof(obj->err.sql_state), "%s", sqlstate); \ } while (0) + #define CLR_ERROR(obj) \ do { \ obj->err.err_no = TSDB_CODE_SUCCESS; \ @@ -57,14 +81,13 @@ do { obj->err.sql_state[0] = '\0'; \ } while (0) -#define FILL_ERROR(obj) \ -do { \ - size_t n = sizeof(obj->err.sql_state); \ - if (Sqlstate) strncpy((char*)Sqlstate, (char*)obj->err.sql_state, n); \ - if (NativeError) *NativeError = obj->err.err_no; \ - snprintf((char*)MessageText, BufferLength, "%s", obj->err.err_str); \ - if (TextLength && obj->err.err_str) *TextLength = strlen(obj->err.err_str); \ - if (TextLength && obj->err.err_str) *TextLength = utf8_chars(obj->err.err_str); \ +#define FILL_ERROR(obj) \ +do { \ + size_t n = sizeof(obj->err.sql_state); \ + if (Sqlstate) strncpy((char*)Sqlstate, (char*)obj->err.sql_state, n); \ + if (NativeError) *NativeError = obj->err.err_no; \ + snprintf((char*)MessageText, (size_t)BufferLength, "%s", obj->err.err_str); \ + if (TextLength && obj->err.err_str) *TextLength = (SQLSMALLINT)utf8_chars(obj->err.err_str); \ } while (0) #define FREE_ERROR(obj) \ @@ -87,7 +110,7 @@ do { SET_ERROR(obj, sqlstate, TSDB_CODE_QRY_INVALID_QHANDLE, err_fmt, ##__VA_ARGS__); \ } while (0); -#define SDUP(s,n) (s ? (s[n] ? (const char*)strndup((const char*)s,n) : (const char*)s) : strdup("")) +#define SDUP(s,n) (s ? (s[(size_t)n] ? (const char*)strndup((const char*)s,(size_t)n) : (const char*)s) : strdup("")) #define SFRE(x,s,n) \ do { \ if (x==(const char*)s) break; \ @@ -124,6 +147,15 @@ do { \ r_091c = SQL_SUCCESS; \ } while (0) +#define NORM_STR_LENGTH(obj, ptr, len) \ +do { \ + if ((len) < 0 && (len)!=SQL_NTS) { \ + SET_ERROR((obj), "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); \ + return SQL_ERROR; \ + } \ + if (len==SQL_NTS) len = (ptr) ? (SQLSMALLINT)strlen((const char*)(ptr)) : 0; \ +} while (0) + #define PROFILING 0 #define PROFILE(statement) \ @@ -138,22 +170,67 @@ do { \ gettimeofday(&tv1, NULL); \ double delta = difftime(tv1.tv_sec, tv0.tv_sec); \ delta *= 1000000; \ - delta += (tv1.tv_usec-tv0.tv_usec); \ + delta += (double)(tv1.tv_usec-tv0.tv_usec); \ delta /= 1000000; \ D("%s: elapsed: [%.6f]s", #statement, delta); \ } while (0) - -#define CHK_CONV(statement) \ -do { \ - const char *sqlstate = statement; \ - if (sqlstate) { \ - SET_ERROR(sql, sqlstate, TSDB_CODE_ODBC_OUT_OF_RANGE, \ - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", \ - sql_c_type(valueType), valueType, valueType, \ - taos_data_type(type), type, type, idx+1); \ - return SQL_ERROR; \ - } \ +#define CHK_CONV(todb, statement) \ +do { \ + TSDB_CONV_CODE code_0c80 = (statement); \ + switch (code_0c80) { \ + case TSDB_CONV_OK: return SQL_SUCCESS; \ + case TSDB_CONV_OOM: \ + case TSDB_CONV_NOT_AVAIL: { \ + SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_OOR: { \ + SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_OOR, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_CHAR_NOT_NUM: \ + case TSDB_CONV_CHAR_NOT_TS: { \ + SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_NOT_VALID_TS: { \ + SET_ERROR(sql, "22007", TSDB_CODE_ODBC_CONV_NOT_VALID_TS, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_TRUNC_FRACTION: { \ + SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC_FRAC, ""); \ + return todb ? SQL_ERROR : SQL_SUCCESS_WITH_INFO; \ + } break; \ + case TSDB_CONV_TRUNC: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_SRC_TOO_LARGE: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_TOO_LARGE, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_SRC_BAD_SEQ: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_BAD_SEQ, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_SRC_INCOMPLETE: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_INCOMPLETE, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_SRC_GENERAL: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_SRC_GENERAL, ""); \ + return SQL_ERROR; \ + } break; \ + case TSDB_CONV_BAD_CHAR: { \ + SET_ERROR(sql, "22001", TSDB_CODE_ODBC_CONV_TRUNC, ""); \ + return SQL_ERROR; \ + } break; \ + default: { \ + DASSERTX(0, "internal logic error: %d", code_0c80); \ + return SQL_ERROR; /* never reached here */ \ + } break; \ + } \ } while (0) typedef struct env_s env_t; @@ -185,6 +262,9 @@ struct env_s { uint64_t refcount; unsigned int destroying:1; + char env_locale[64]; + char env_charset[64]; + taos_error_t err; }; @@ -192,6 +272,16 @@ struct conn_s { uint64_t refcount; env_t *env; + char client_enc[64]; // ODBC client that communicates with this driver + char server_enc[64]; // taos dynamic library that's loaded by this driver + + tsdb_conv_t *client_to_server; + tsdb_conv_t *server_to_client; + tsdb_conv_t *utf8_to_client; + tsdb_conv_t *utf16_to_utf8; + tsdb_conv_t *utf16_to_server; + tsdb_conv_t *client_to_utf8; + TAOS *taos; taos_error_t err; @@ -229,50 +319,98 @@ struct c_target_s { static pthread_once_t init_once = PTHREAD_ONCE_INIT; static void init_routine(void); -// conversions +static size_t do_field_display_size(TAOS_FIELD *field); -const char* tsdb_int64_to_bit(int64_t src, int8_t *dst); -const char* tsdb_int64_to_tinyint(int64_t src, int8_t *dst); -const char* tsdb_int64_to_smallint(int64_t src, int16_t *dst); -const char* tsdb_int64_to_int(int64_t src, int32_t *dst); -const char* tsdb_int64_to_bigint(int64_t src, int64_t *dst); -const char* tsdb_int64_to_ts(int64_t src, int64_t *dst); -const char* tsdb_int64_to_float(int64_t src, float *dst); -const char* tsdb_int64_to_double(int64_t src, double *dst); -const char* tsdb_int64_to_char(int64_t src, char *dst, size_t dlen); +static tsdb_conv_t* tsdb_conn_client_to_server(conn_t *conn) { + if (!conn->client_to_server) { + conn->client_to_server = tsdb_conv_open(conn->client_enc, conn->server_enc); + } + return conn->client_to_server; +} -const char* tsdb_double_to_bit(double src, int precision, int8_t *dst); -const char* tsdb_double_to_tinyint(double src, int precision, int8_t *dst); -const char* tsdb_double_to_smallint(double src, int precision, int16_t *dst); -const char* tsdb_double_to_int(double src, int precision, int32_t *dst); -const char* tsdb_double_to_bigint(double src, int precision, int64_t *dst); -const char* tsdb_double_to_ts(double src, int precision, int64_t *dst); -const char* tsdb_double_to_float(double src, int precision, float *dst); -const char* tsdb_double_to_double(double src, int precision, double *dst); -const char* tsdb_double_to_char(double src, int precision, char *dst, size_t dlen); +static tsdb_conv_t* tsdb_conn_server_to_client(conn_t *conn) { + if (!conn->server_to_client) { + conn->server_to_client = tsdb_conv_open(conn->server_enc, conn->client_enc); + } + return conn->server_to_client; +} -const char* tsdb_chars_to_bit(const char *src, int8_t *dst); -const char* tsdb_chars_to_tinyint(const char *src, int8_t *dst); -const char* tsdb_chars_to_smallint(const char *src, int16_t *dst); -const char* tsdb_chars_to_int(const char *src, int32_t *dst); -const char* tsdb_chars_to_bigint(const char *src, int64_t *dst); -const char* tsdb_chars_to_ts(const char *src, int64_t *dst); -const char* tsdb_chars_to_float(const char *src, float *dst); -const char* tsdb_chars_to_double(const char *src, double *dst); -const char* tsdb_chars_to_char(const char *src, char *dst, size_t dlen); +static tsdb_conv_t* tsdb_conn_utf8_to_client(conn_t *conn) { + if (!conn->utf8_to_client) { + conn->utf8_to_client = tsdb_conv_open(UTF8_ENC, conn->client_enc); + } + return conn->utf8_to_client; +} +static tsdb_conv_t* tsdb_conn_utf16_to_utf8(conn_t *conn) { + if (!conn->utf16_to_utf8) { + conn->utf16_to_utf8 = tsdb_conv_open(UTF16_ENC, UTF8_ENC); + } + return conn->utf16_to_utf8; +} -static int do_field_display_size(TAOS_FIELD *field); +static tsdb_conv_t* tsdb_conn_utf16_to_server(conn_t *conn) { + if (!conn->utf16_to_server) { + conn->utf16_to_server = tsdb_conv_open(UTF16_ENC, conn->server_enc); + } + return conn->utf16_to_server; +} + +static tsdb_conv_t* tsdb_conn_client_to_utf8(conn_t *conn) { + if (!conn->client_to_utf8) { + conn->client_to_utf8 = tsdb_conv_open(conn->client_enc, UTF8_ENC); + } + return conn->client_to_utf8; +} + +static void tsdb_conn_close_convs(conn_t *conn) { + if (conn->client_to_server) { + tsdb_conv_close(conn->client_to_server); + conn->client_to_server = NULL; + } + if (conn->server_to_client) { + tsdb_conv_close(conn->server_to_client); + conn->server_to_client = NULL; + } + if (conn->utf8_to_client) { + tsdb_conv_close(conn->utf8_to_client); + conn->utf8_to_client = NULL; + } + if (conn->utf16_to_utf8) { + tsdb_conv_close(conn->utf16_to_utf8); + conn->utf16_to_utf8 = NULL; + } + if (conn->utf16_to_server) { + tsdb_conv_close(conn->utf16_to_server); + conn->utf16_to_server = NULL; + } + if (conn->client_to_utf8) { + tsdb_conv_close(conn->client_to_utf8); + conn->client_to_utf8 = NULL; + } +} + +#define SFREE(buffer, v, src) \ +do { \ + const char *v_096a = (const char*)(v); \ + const char *src_6a = (const char*)(src); \ + if (v_096a && v_096a!=src_6a && !is_owned_by_stack_buffer((buffer), v_096a)) { \ + free((char*)v_096a); \ + } \ +} while (0) static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle) { pthread_once(&init_once, init_routine); env_t *env = (env_t*)calloc(1, sizeof(*env)); - if (!env) return SQL_ERROR; + if (!env) return SQL_INVALID_HANDLE; DASSERT(INC_REF(env)>0); + snprintf(env->env_locale, sizeof(env->env_locale), "%s", tsLocale); + snprintf(env->env_charset, sizeof(env->env_charset), "%s", tsCharset); + *EnvironmentHandle = env; CLR_ERROR(env); @@ -289,7 +427,7 @@ SQLRETURN SQL_API SQLAllocEnv(SQLHENV *EnvironmentHandle) static SQLRETURN doSQLFreeEnv(SQLHENV EnvironmentHandle) { env_t *env = (env_t*)EnvironmentHandle; - if (!env) return SQL_ERROR; + if (!env) return SQL_INVALID_HANDLE; DASSERT(GET_REF(env)==1); @@ -317,7 +455,12 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, SQLHDBC *ConnectionHandle) { env_t *env = (env_t*)EnvironmentHandle; - if (!env) return SQL_ERROR; + if (!env) return SQL_INVALID_HANDLE; + + if (!ConnectionHandle) { + SET_ERROR(env, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ConnectionHandle [%p] not valid", ConnectionHandle); + return SQL_ERROR; + } DASSERT(INC_REF(env)>1); @@ -330,6 +473,10 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle, } conn->env = env; + + snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", conn->env->env_charset); + snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", conn->env->env_charset); + *ConnectionHandle = conn; DASSERT(INC_REF(conn)>0); @@ -353,7 +500,7 @@ SQLRETURN SQL_API SQLAllocConnect(SQLHENV EnvironmentHandle, static SQLRETURN doSQLFreeConnect(SQLHDBC ConnectionHandle) { conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; DASSERT(GET_REF(conn)==1); @@ -370,6 +517,7 @@ static SQLRETURN doSQLFreeConnect(SQLHDBC ConnectionHandle) conn->env = NULL; FREE_ERROR(conn); + tsdb_conn_close_convs(conn); free(conn); } while (0); @@ -388,6 +536,8 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, SQLCHAR *UserName, SQLSMALLINT NameLength2, SQLCHAR *Authentication, SQLSMALLINT NameLength3) { + stack_buffer_t buffer; buffer.next = 0; + conn_t *conn = (conn_t*)ConnectionHandle; if (!conn) return SQL_ERROR; @@ -396,28 +546,58 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, return SQL_ERROR; } - const char *serverName = SDUP(ServerName, NameLength1); - const char *userName = SDUP(UserName, NameLength2); - const char *auth = SDUP(Authentication, NameLength3); + NORM_STR_LENGTH(conn, ServerName, NameLength1); + NORM_STR_LENGTH(conn, UserName, NameLength2); + NORM_STR_LENGTH(conn, Authentication, NameLength3); + + if (NameLength1>SQL_MAX_DSN_LENGTH) { + SET_ERROR(conn, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + const char *dsn = NULL; + const char *uid = NULL; + const char *pwd = NULL; + const char *svr = NULL; + char server[4096]; server[0] = '\0'; do { - if ((ServerName && !serverName) || (UserName && !userName) || (Authentication && !auth)) { + tsdb_conv(client_to_server, &buffer, (const char*)ServerName, (size_t)NameLength1, &dsn, NULL); + tsdb_conv(client_to_server, &buffer, (const char*)UserName, (size_t)NameLength2, &uid, NULL); + tsdb_conv(client_to_server, &buffer, (const char*)Authentication, (size_t)NameLength3, &pwd, NULL); + int n = SQLGetPrivateProfileString(dsn, "Server", "", server, sizeof(server)-1, "Odbc.ini"); + if (n<=0) { + snprintf(server, sizeof(server), "localhost:6030"); // all 7-bit ascii + } + tsdb_conv(client_to_server, &buffer, (const char*)server, (size_t)strlen(server), &svr, NULL); + + if ((!dsn) || (!uid) || (!pwd) || (!svr)) { SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, ""); break; } + char *ip = NULL; + int port = 0; + char *p = strchr(svr, ':'); + if (p) { + ip = strndup(svr, (size_t)(p-svr)); + port = atoi(p+1); + } + // TODO: data-race // TODO: shall receive ip/port from odbc.ini - conn->taos = taos_connect("localhost", userName, auth, NULL, 0); + conn->taos = taos_connect(ip, uid, pwd, NULL, (uint16_t)port); if (!conn->taos) { - SET_ERROR(conn, "08001", terrno, "failed to connect to data source"); + SET_ERROR(conn, "08001", terrno, "failed to connect to data source for DSN[%s] @[%s:%d]", dsn, ip, port); break; } } while (0); - SFRE(serverName, ServerName, NameLength1); - SFRE(userName, UserName, NameLength2); - SFRE(auth, Authentication, NameLength3); + tsdb_conv_free(client_to_server, dsn, &buffer, (const char*)ServerName); + tsdb_conv_free(client_to_server, uid, &buffer, (const char*)UserName); + tsdb_conv_free(client_to_server, pwd, &buffer, (const char*)Authentication); + tsdb_conv_free(client_to_server, svr, &buffer, (const char*)server); return conn->taos ? SQL_SUCCESS : SQL_ERROR; } @@ -437,7 +617,7 @@ SQLRETURN SQL_API SQLConnect(SQLHDBC ConnectionHandle, static SQLRETURN doSQLDisconnect(SQLHDBC ConnectionHandle) { conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; if (conn->taos) { taos_close(conn->taos); @@ -455,10 +635,15 @@ SQLRETURN SQL_API SQLDisconnect(SQLHDBC ConnectionHandle) } static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle, - SQLHSTMT *StatementHandle) + SQLHSTMT *StatementHandle) { conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; + + if (!StatementHandle) { + SET_ERROR(conn, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StatementHandle [%p] not valid", StatementHandle); + return SQL_ERROR; + } DASSERT(INC_REF(conn)>1); @@ -495,20 +680,17 @@ static SQLRETURN doSQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, switch (HandleType) { case SQL_HANDLE_ENV: { SQLHENV env = {0}; + if (!OutputHandle) return SQL_ERROR; SQLRETURN r = doSQLAllocEnv(&env); - if (r==SQL_SUCCESS && OutputHandle) *OutputHandle = env; + if (r==SQL_SUCCESS) *OutputHandle = env; return r; } break; case SQL_HANDLE_DBC: { - SQLHDBC dbc = {0}; - SQLRETURN r = doSQLAllocConnect(InputHandle, &dbc); - if (r==SQL_SUCCESS && OutputHandle) *OutputHandle = dbc; + SQLRETURN r = doSQLAllocConnect(InputHandle, OutputHandle); return r; } break; case SQL_HANDLE_STMT: { - SQLHSTMT stmt = {0}; - SQLRETURN r = doSQLAllocStmt(InputHandle, &stmt); - if (r==SQL_SUCCESS && OutputHandle) *OutputHandle = stmt; + SQLRETURN r = doSQLAllocStmt(InputHandle, OutputHandle); return r; } break; default: { @@ -528,12 +710,20 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; - if (Option == SQL_CLOSE) return SQL_SUCCESS; - if (Option != SQL_DROP) { - SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "free statement with Option[%x] not supported yet", Option); - return SQL_ERROR; + switch (Option) { + case SQL_CLOSE: return SQL_SUCCESS; + case SQL_DROP: break; + case SQL_UNBIND: + case SQL_RESET_PARAMS: { + SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "free statement with Option[%x] not supported yet", Option); + return SQL_ERROR; + } break; + default: { + SET_ERROR(sql, "HY092", TSDB_CODE_ODBC_OUT_OF_RANGE, "free statement with Option[%x] not supported yet", Option); + return SQL_ERROR; + } break; } DASSERT(GET_REF(sql)==1); @@ -560,6 +750,7 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle, sql->conn = NULL; FREE_ERROR(sql); + free(sql); return SQL_SUCCESS; @@ -573,15 +764,32 @@ SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle, return r; } +static SQLRETURN do_exec_direct(sql_t *sql, TSDB_CONV_CODE code, const char *statement) { + if (code) CHK_CONV(1, code); + DASSERT(code==TSDB_CONV_OK); + + SQLRETURN r = SQL_ERROR; + do { + sql->rs = taos_query(sql->conn->taos, statement); + CHK_RS(r, sql, "failed to execute"); + } while (0); + + return r; +} + static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); + conn_t *conn = sql->conn; + + NORM_STR_LENGTH(sql, StatementText, TextLength); + if (sql->rs) { taos_free_result(sql->rs); sql->rs = NULL; @@ -599,19 +807,15 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle, } sql->n_params = 0; - const char *stxt = SDUP(StatementText, TextLength); - - SQLRETURN r = SQL_ERROR; + SQLRETURN r = SQL_SUCCESS; + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + const char *stxt = NULL; do { - if (!stxt) { - SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); - break; - } - sql->rs = taos_query(sql->conn->taos, stxt); - CHK_RS(r, sql, "failed to execute"); + TSDB_CONV_CODE code = tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); + r = do_exec_direct(sql, code, stxt); } while (0); - - SFRE(stxt, StatementText, TextLength); + tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); return r; } @@ -624,18 +828,50 @@ SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle, return r; } +static SQLRETURN doSQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER cbSqlStr) +{ + sql_t *sql = (sql_t*)hstmt; + if (!sql) return SQL_INVALID_HANDLE; + + CHK_CONN(sql); + CHK_CONN_TAOS(sql); + + conn_t *conn = sql->conn; + + if (!szSqlStr) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "szSqlStr [%p] not allowed", szSqlStr); + return SQL_ERROR; + } + if (cbSqlStr < 0) { + SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } + + SQLRETURN r = SQL_SUCCESS; + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); + const char *stxt = NULL; + do { + size_t slen = (size_t)cbSqlStr * sizeof(*szSqlStr); + TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, &buffer, (const char*)szSqlStr, slen, &stxt, NULL); + r = do_exec_direct(sql, code, stxt); + } while (0); + tsdb_conv_free(utf16_to_server, stxt, &buffer, (const char*)szSqlStr); + + return r; +} + SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT hstmt, SQLWCHAR *szSqlStr, SQLINTEGER cbSqlStr) { - size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(szSqlStr, cbSqlStr, &bytes); - return SQLExecDirect(hstmt, utf8, bytes); + SQLRETURN r = doSQLExecDirectW(hstmt, szSqlStr, cbSqlStr); + return r; } static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCount) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -654,7 +890,7 @@ static SQLRETURN doSQLNumResultCols(SQLHSTMT StatementHandle, int fields = taos_field_count(sql->rs); if (ColumnCount) { - *ColumnCount = fields; + *ColumnCount = (SQLSMALLINT)fields; } return SQL_SUCCESS; @@ -677,7 +913,22 @@ static SQLRETURN doSQLRowCount(SQLHSTMT StatementHandle, CHK_CONN(sql); CHK_CONN_TAOS(sql); - if (sql->is_insert) { + // ref: https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlrowcount-function?view=sql-server-ver15 + // Summary + // SQLRowCount returns the number of rows affected by an UPDATE, INSERT, or DELETE statement; + // an SQL_ADD, SQL_UPDATE_BY_BOOKMARK, or SQL_DELETE_BY_BOOKMARK operation in SQLBulkOperations; + // or an SQL_UPDATE or SQL_DELETE operation in SQLSetPos. + + // how to fetch affected rows from taos? + // taos_affected_rows? + + if (1) { + SET_ERROR(sql, "IM001", TSDB_CODE_ODBC_NOT_SUPPORT, ""); + // if (RowCount) *RowCount = 0; + return SQL_SUCCESS_WITH_INFO; + } + + if (!sql->is_insert) { if (RowCount) *RowCount = 0; return SQL_SUCCESS; } @@ -735,11 +986,12 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle, switch (FieldIdentifier) { case SQL_COLUMN_DISPLAY_SIZE: { - *NumericAttribute = do_field_display_size(field); + *NumericAttribute = (SQLLEN)do_field_display_size(field); } break; case SQL_COLUMN_LABEL: { + // todo: check BufferLength size_t n = sizeof(field->name); - strncpy(CharacterAttribute, field->name, (n>BufferLength ? BufferLength : n)); + strncpy(CharacterAttribute, field->name, (n>BufferLength ? (size_t)BufferLength : n)); } break; case SQL_COLUMN_UNSIGNED: { *NumericAttribute = SQL_FALSE; @@ -766,75 +1018,19 @@ SQLRETURN SQL_API SQLColAttribute(SQLHSTMT StatementHandle, return r; } -static SQLRETURN conv_tsdb_bool_to_c_bit(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_tinyint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_bool_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b); -static SQLRETURN conv_tsdb_v1_to_c_tinyint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v1_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1); -static SQLRETURN conv_tsdb_v2_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v2_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2); -static SQLRETURN conv_tsdb_v4_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v4_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4); -static SQLRETURN conv_tsdb_v8_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_v8_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_v8_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_v8_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_v8_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8); -static SQLRETURN conv_tsdb_f4_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4); -static SQLRETURN conv_tsdb_f4_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4); -static SQLRETURN conv_tsdb_f4_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4); -static SQLRETURN conv_tsdb_f4_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4); -static SQLRETURN conv_tsdb_f8_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8); -static SQLRETURN conv_tsdb_f8_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8); -static SQLRETURN conv_tsdb_f8_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8); -static SQLRETURN conv_tsdb_ts_to_c_v8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts); -static SQLRETURN conv_tsdb_ts_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts); -static SQLRETURN conv_tsdb_ts_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts); -static SQLRETURN conv_tsdb_ts_to_c_ts(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts); -static SQLRETURN conv_tsdb_bin_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const unsigned char *bin); -static SQLRETURN conv_tsdb_bin_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const unsigned char *bin); -static SQLRETURN conv_tsdb_str_to_c_bit(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_v1(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_v2(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_v4(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_v8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_f4(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_f8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); -static SQLRETURN conv_tsdb_str_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str); - static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValue, SQLLEN BufferLength, SQLLEN *StrLen_or_Ind) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); + conn_t *conn = sql->conn; + if (!sql->rs) { SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, ""); return SQL_ERROR; @@ -845,8 +1041,6 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, return SQL_ERROR; } - DASSERT(TargetValue); - int nfields = taos_field_count(sql->rs); TAOS_FIELD *fields = taos_fetch_fields(sql->rs); @@ -859,14 +1053,20 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "NULL TargetValue not allowed for col [%d]", ColumnNumber); return SQL_ERROR; } + if (BufferLength<0) { + SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } TAOS_FIELD *field = fields + ColumnNumber-1; void *row = sql->row[ColumnNumber-1]; if (!row) { - if (StrLen_or_Ind) { - *StrLen_or_Ind = SQL_NULL_DATA; + if (!StrLen_or_Ind) { + SET_ERROR(sql, "22002", TSDB_CODE_ODBC_BAD_ARG, "NULL StrLen_or_Ind not allowed for col [%d]", ColumnNumber); + return SQL_ERROR; } + *StrLen_or_Ind = SQL_NULL_DATA; return SQL_SUCCESS; } @@ -878,89 +1078,49 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, target.soi = StrLen_or_Ind; switch (field->type) { - case TSDB_DATA_TYPE_BOOL: { - int8_t v = *(int8_t*)row; - if (v) v = 1; - switch (target.ct) { - case SQL_C_BIT: return conv_tsdb_bool_to_c_bit(sql, &target, field, v); - case SQL_C_TINYINT: return conv_tsdb_bool_to_c_tinyint(sql, &target, field, v); - case SQL_C_SHORT: return conv_tsdb_bool_to_c_short(sql, &target, field, v); - case SQL_C_LONG: return conv_tsdb_bool_to_c_long(sql, &target, field, v); - case SQL_C_SBIGINT: return conv_tsdb_bool_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_bool_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_bool_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_bool_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_bool_to_c_binary(sql, &target, field, v); - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_TINYINT: { - int8_t v = *(int8_t*)row; - switch (target.ct) { - case SQL_C_TINYINT: return conv_tsdb_v1_to_c_tinyint(sql, &target, field, v); - case SQL_C_SHORT: return conv_tsdb_v1_to_c_short(sql, &target, field, v); - case SQL_C_LONG: return conv_tsdb_v1_to_c_long(sql, &target, field, v); - case SQL_C_SBIGINT: return conv_tsdb_v1_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_v1_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_v1_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_v1_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_v1_to_c_binary(sql, &target, field, v); - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_SMALLINT: { - int16_t v = *(int16_t*)row; - switch (target.ct) { - case SQL_C_SHORT: return conv_tsdb_v2_to_c_short(sql, &target, field, v); - case SQL_C_LONG: return conv_tsdb_v2_to_c_long(sql, &target, field, v); - case SQL_C_SBIGINT: return conv_tsdb_v2_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_v2_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_v2_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_v2_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_v2_to_c_binary(sql, &target, field, v); - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; - case TSDB_DATA_TYPE_INT: { - int32_t v = *(int32_t*)row; - switch (target.ct) { - case SQL_C_LONG: return conv_tsdb_v4_to_c_long(sql, &target, field, v); - case SQL_C_SBIGINT: return conv_tsdb_v4_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_v4_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_v4_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_v4_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_v4_to_c_binary(sql, &target, field, v); - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, - "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", - taos_data_type(field->type), sql_c_type(target.ct), target.ct, target.ct, ColumnNumber); - return SQL_ERROR; - } - } - } break; + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_INT: case TSDB_DATA_TYPE_BIGINT: { - int64_t v = *(int64_t*)row; + int64_t v; + switch (field->type) { + case TSDB_DATA_TYPE_BOOL: v = *(int8_t*)row; if (v) v = 1; break; + case TSDB_DATA_TYPE_TINYINT: v = *(int8_t*)row; break; + case TSDB_DATA_TYPE_SMALLINT: v = *(int16_t*)row; break; + case TSDB_DATA_TYPE_INT: v = *(int32_t*)row; break; + case TSDB_DATA_TYPE_BIGINT: // fall through + default: v = *(int64_t*)row; break; + } switch (target.ct) { - case SQL_C_SBIGINT: return conv_tsdb_v8_to_c_sbigint(sql, &target, field, v); - case SQL_C_FLOAT: return conv_tsdb_v8_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_v8_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_v8_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_v8_to_c_binary(sql, &target, field, v); + case SQL_C_BIT: { + CHK_CONV(0, tsdb_int64_to_bit(v, TargetValue)); + } break; + case SQL_C_TINYINT: { + CHK_CONV(0, tsdb_int64_to_tinyint(v, TargetValue)); + } break; + case SQL_C_SHORT: { + CHK_CONV(0, tsdb_int64_to_smallint(v, TargetValue)); + } break; + case SQL_C_LONG: { + CHK_CONV(0, tsdb_int64_to_int(v, TargetValue)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(0, tsdb_int64_to_bigint(v, TargetValue)); + } break; + case SQL_C_FLOAT: { + CHK_CONV(0, tsdb_int64_to_float(v, TargetValue)); + } break; + case SQL_C_DOUBLE: { + CHK_CONV(0, tsdb_int64_to_double(v, TargetValue)); + } break; + case SQL_C_CHAR: { + tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write_int64(utf8_to_client, v, (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; + CHK_CONV(0, code); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -972,10 +1132,21 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, case TSDB_DATA_TYPE_FLOAT: { float v = *(float*)row; switch (target.ct) { - case SQL_C_FLOAT: return conv_tsdb_f4_to_c_float(sql, &target, field, v); - case SQL_C_DOUBLE: return conv_tsdb_f4_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_f4_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_f4_to_c_binary(sql, &target, field, v); + case SQL_C_FLOAT: { + *(float*)TargetValue = v; + return SQL_SUCCESS; + } break; + case SQL_C_DOUBLE: { + *(double*)TargetValue = v; + return SQL_SUCCESS; + } break; + case SQL_C_CHAR: { + tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write_double(utf8_to_client, v, (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; + CHK_CONV(0, code); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -987,9 +1158,17 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, case TSDB_DATA_TYPE_DOUBLE: { double v = *(double*)row; switch (target.ct) { - case SQL_C_DOUBLE: return conv_tsdb_f8_to_c_double(sql, &target, field, v); - case SQL_C_CHAR: return conv_tsdb_f8_to_c_char(sql, &target, field, v); - case SQL_C_BINARY: return conv_tsdb_f8_to_c_binary(sql, &target, field, v); + case SQL_C_DOUBLE: { + *(double*)TargetValue = v; + return SQL_SUCCESS; + } break; + case SQL_C_CHAR: { + tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write_double(utf8_to_client, v, (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; + CHK_CONV(0, code); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -1002,21 +1181,31 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, SQL_TIMESTAMP_STRUCT ts = {0}; int64_t v = *(int64_t*)row; time_t t = v/1000; - struct tm tm = {0}; - localtime_r(&t, &tm); - ts.year = tm.tm_year + 1900; - ts.month = tm.tm_mon + 1; - ts.day = tm.tm_mday; - ts.hour = tm.tm_hour; - ts.minute = tm.tm_min; - ts.second = tm.tm_sec; - ts.fraction = v%1000 * 1000000; + struct tm vtm = {0}; + localtime_r(&t, &vtm); + ts.year = (SQLSMALLINT)(vtm.tm_year + 1900); + ts.month = (SQLUSMALLINT)(vtm.tm_mon + 1); + ts.day = (SQLUSMALLINT)(vtm.tm_mday); + ts.hour = (SQLUSMALLINT)(vtm.tm_hour); + ts.minute = (SQLUSMALLINT)(vtm.tm_min); + ts.second = (SQLUSMALLINT)(vtm.tm_sec); + ts.fraction = (SQLUINTEGER)(v%1000 * 1000000); switch (target.ct) { - case SQL_C_SBIGINT: return conv_tsdb_ts_to_c_v8(sql, &target, field, &ts); - case SQL_C_CHAR: return conv_tsdb_ts_to_c_str(sql, &target, field, &ts); - case SQL_C_BINARY: return conv_tsdb_ts_to_c_bin(sql, &target, field, &ts); - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_TIMESTAMP: return conv_tsdb_ts_to_c_ts(sql, &target, field, &ts); + case SQL_C_SBIGINT: { + *(int64_t*)TargetValue = v; + return SQL_SUCCESS; + } break; + case SQL_C_CHAR: { + tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write_timestamp(utf8_to_client, ts, (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len; + CHK_CONV(0, code); + } break; + case SQL_C_TYPE_TIMESTAMP: { + *(SQL_TIMESTAMP_STRUCT*)TargetValue = ts; + return SQL_SUCCESS; + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -1026,10 +1215,34 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, } } break; case TSDB_DATA_TYPE_BINARY: { - const unsigned char *bin = (const unsigned char *)row; + size_t field_bytes = (size_t)field->bytes; + field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { - case SQL_C_CHAR: return conv_tsdb_bin_to_c_str(sql, &target, field, bin); - case SQL_C_BINARY: return conv_tsdb_bin_to_c_bin(sql, &target, field, bin); + case SQL_C_CHAR: { + // taos cares nothing about what would be stored in 'binary' as most sql implementations do + // but the client requires to fetch it as a SQL_C_CHAR + // thus, we first try to decode binary to client charset + // if failed, we then do hex-serialization + + tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); + size_t slen = strnlen((const char*)row, field_bytes); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, + (const char*)row, &slen, + (char*)TargetValue, &len); + if (code==TSDB_CONV_OK) { + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); + CHK_CONV(0, code); + // code never reached here + } + + // todo: hex-serialization + const char *bad = ""; + int n = snprintf((char*)TargetValue, (size_t)BufferLength, "%s", bad); + // what if n < 0 ? + if (StrLen_or_Ind) *StrLen_or_Ind = n; + CHK_CONV(0, n>=BufferLength ? TSDB_CONV_TRUNC : TSDB_CONV_OK); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -1039,17 +1252,19 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle, } } break; case TSDB_DATA_TYPE_NCHAR: { - const char *str = (const char *)row; + size_t field_bytes = (size_t)field->bytes; + field_bytes -= VARSTR_HEADER_SIZE; switch (target.ct) { - case SQL_C_BIT: return conv_tsdb_str_to_c_bit(sql, &target, field, str); - case SQL_C_TINYINT: return conv_tsdb_str_to_c_v1(sql, &target, field, str); - case SQL_C_SHORT: return conv_tsdb_str_to_c_v2(sql, &target, field, str); - case SQL_C_LONG: return conv_tsdb_str_to_c_v4(sql, &target, field, str); - case SQL_C_SBIGINT: return conv_tsdb_str_to_c_v8(sql, &target, field, str); - case SQL_C_FLOAT: return conv_tsdb_str_to_c_f4(sql, &target, field, str); - case SQL_C_DOUBLE: return conv_tsdb_str_to_c_f8(sql, &target, field, str); - case SQL_C_CHAR: return conv_tsdb_str_to_c_str(sql, &target, field, str); - case SQL_C_BINARY: return conv_tsdb_str_to_c_bin(sql, &target, field, str); + case SQL_C_CHAR: { + tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn); + size_t slen = strnlen((const char*)row, field_bytes); + size_t len = (size_t)BufferLength; + TSDB_CONV_CODE code = tsdb_conv_write(server_to_client, + (const char*)row, &slen, + (char*)TargetValue, &len); + if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len); + CHK_CONV(0, code); + } break; default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "no convertion from [%s] to [%s[%d][0x%x]] for col [%d]", @@ -1083,7 +1298,7 @@ SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle, static SQLRETURN doSQLFetch(SQLHSTMT StatementHandle) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -1107,12 +1322,18 @@ SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle) static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength) { + stack_buffer_t buffer; buffer.next = 0; + sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); + conn_t *conn = sql->conn; + + NORM_STR_LENGTH(sql, StatementText, TextLength); + if (sql->rs) { taos_free_result(sql->rs); sql->rs = NULL; @@ -1138,9 +1359,17 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, break; } + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + const char *stxt = NULL; int ok = 0; do { - int r = taos_stmt_prepare(sql->stmt, (const char *)StatementText, TextLength); + tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL); + if ((!stxt)) { + SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); + break; + } + + int r = taos_stmt_prepare(sql->stmt, stxt, (unsigned long)strlen(stxt)); if (r) { SET_ERROR(sql, "HY000", r, "failed to prepare a TAOS statement"); break; @@ -1164,7 +1393,7 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, DASSERT(params>=0); if (params>0) { - param_bind_t *ar = (param_bind_t*)calloc(1, params * sizeof(*ar)); + param_bind_t *ar = (param_bind_t*)calloc(1, ((size_t)params) * sizeof(*ar)); if (!ar) { SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); break; @@ -1177,6 +1406,8 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle, ok = 1; } while (0); + tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText); + if (!ok) { taos_stmt_close(sql->stmt); sql->stmt = NULL; @@ -1206,57 +1437,86 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "parameter [@%d] not bound yet", idx+1); return SQL_ERROR; } + if (param->ParameterValue==NULL) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ParameterValue [@%p] not allowed", param->ParameterValue); + return SQL_ERROR; + } + if (param->StrLen_or_Ind==NULL) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StrLen_or_Ind [@%p] not allowed", param->StrLen_or_Ind); + return SQL_ERROR; + } - SQLPOINTER paramValue = param->ParameterValue; - SQLSMALLINT valueType = param->ValueType; - SQLLEN *soi = param->StrLen_or_Ind; + conn_t *conn = sql->conn; - size_t offset = idx_row * sql->rowlen + sql->ptr_offset; + unsigned char *paramValue = param->ParameterValue; + SQLSMALLINT valueType = param->ValueType; + SQLLEN *soi = param->StrLen_or_Ind; - if (paramValue) paramValue += offset; - if (soi) soi = (SQLLEN*)((char*)soi + offset); + size_t offset = ((size_t)idx_row) * sql->rowlen + sql->ptr_offset; + + paramValue += offset; + soi = (SQLLEN*)((char*)soi + offset); - if (soi && *soi == SQL_NULL_DATA) { + if (*soi == SQL_NULL_DATA) { bind->is_null = (int*)&yes; return SQL_SUCCESS; } bind->is_null = (int*)&no; - int type = 0; - int bytes = 0; + int tsdb_type = 0; // taos internal data tsdb_type to be bound to + int tsdb_bytes = 0; // we don't rely much on 'tsdb_bytes' here, we delay until taos to check it internally if (sql->is_insert) { - int r = taos_stmt_get_param(sql->stmt, idx, &type, &bytes); + int r = taos_stmt_get_param(sql->stmt, idx, &tsdb_type, &tsdb_bytes); if (r) { SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_OUT_OF_RANGE, "parameter [@%d] not valid", idx+1); return SQL_ERROR; } } else { + // we don't have correspondent data type from taos api + // we have to give a good guess here switch (valueType) { + case SQL_C_BIT: { + tsdb_type = TSDB_DATA_TYPE_BOOL; + } break; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + tsdb_type = TSDB_DATA_TYPE_TINYINT; + } break; + case SQL_C_SSHORT: + case SQL_C_SHORT: { + tsdb_type = TSDB_DATA_TYPE_SMALLINT; + } break; + case SQL_C_SLONG: case SQL_C_LONG: { - type = TSDB_DATA_TYPE_INT; + tsdb_type = TSDB_DATA_TYPE_INT; + } break; + case SQL_C_SBIGINT: { + tsdb_type = TSDB_DATA_TYPE_BIGINT; + } break; + case SQL_C_FLOAT: { + tsdb_type = TSDB_DATA_TYPE_FLOAT; + } break; + case SQL_C_DOUBLE: { + tsdb_type = TSDB_DATA_TYPE_DOUBLE; + } break; + case SQL_C_TIMESTAMP: { + tsdb_type = TSDB_DATA_TYPE_TIMESTAMP; + } break; + case SQL_C_CHAR: { + tsdb_type = TSDB_DATA_TYPE_BINARY; + tsdb_bytes = SQL_NTS; } break; case SQL_C_WCHAR: { - type = TSDB_DATA_TYPE_NCHAR; - bytes = SQL_NTS; + tsdb_type = TSDB_DATA_TYPE_NCHAR; + tsdb_bytes = SQL_NTS; } break; - case SQL_C_CHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: case SQL_C_USHORT: - case SQL_C_SLONG: case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: case SQL_C_TIME: - case SQL_C_TIMESTAMP: case SQL_C_TYPE_DATE: case SQL_C_TYPE_TIME: case SQL_C_TYPE_TIMESTAMP: @@ -1273,32 +1533,54 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin } // ref: https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/converting-data-from-c-to-sql-data-types?view=sql-server-ver15 - switch (type) { + switch (tsdb_type) { case TSDB_DATA_TYPE_BOOL: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.b); bind->buffer = &bind->u.b; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_bit(*(int32_t*)paramValue, &bind->u.b)); - } break; case SQL_C_BIT: { - CHK_CONV(tsdb_int64_to_bit(*(int8_t*)paramValue, &bind->u.b)); + CHK_CONV(1, tsdb_int64_to_bit(*(int8_t*)paramValue, &bind->u.b)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: - case SQL_C_USHORT: - case SQL_C_SLONG: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: case SQL_C_TINYINT: - case SQL_C_STINYINT: + case SQL_C_STINYINT: { + CHK_CONV(1, tsdb_int64_to_bit(*(int8_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_SHORT: + case SQL_C_SSHORT: { + CHK_CONV(1, tsdb_int64_to_bit(*(int16_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_LONG: + case SQL_C_SLONG: { + CHK_CONV(1, tsdb_int64_to_bit(*(int32_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(1, tsdb_int64_to_bit(*(int64_t*)paramValue, &bind->u.b)); + } break; + case SQL_C_FLOAT: { + CHK_CONV(1, tsdb_double_to_bit(*(float*)paramValue, &bind->u.b)); + } break; + case SQL_C_DOUBLE: { + CHK_CONV(1, tsdb_double_to_bit(*(double*)paramValue, &bind->u.b)); + } break; + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_bit(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b)); + } break; + case SQL_C_WCHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_bit(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b)); + } break; + case SQL_C_USHORT: + case SQL_C_ULONG: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1313,39 +1595,54 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_TINYINT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v1); bind->buffer = &bind->u.v1; bind->length = &bind->buffer_length; switch (valueType) { + case SQL_C_BIT: { + CHK_CONV(1, tsdb_int64_to_tinyint(*(int8_t*)paramValue, &bind->u.v1)); + } break; + case SQL_C_STINYINT: case SQL_C_TINYINT: { - CHK_CONV(tsdb_int64_to_tinyint(*(int8_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int8_t*)paramValue, &bind->u.v1)); } break; + case SQL_C_SSHORT: case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_tinyint(*(int16_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int16_t*)paramValue, &bind->u.v1)); } break; + case SQL_C_SLONG: case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_tinyint(*(int32_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int32_t*)paramValue, &bind->u.v1)); } break; case SQL_C_SBIGINT: { - CHK_CONV(tsdb_int64_to_tinyint(*(int64_t*)paramValue, &bind->u.v1)); + CHK_CONV(1, tsdb_int64_to_tinyint(*(int64_t*)paramValue, &bind->u.v1)); + } break; + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_tinyint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v1)); + // CHK_CONV(1, tsdb_chars_to_tinyint((const char *)paramValue, (size_t)*soi, &bind->u.v1)); + } break; + case SQL_C_WCHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_tinyint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v1)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SSHORT: case SQL_C_USHORT: - case SQL_C_SLONG: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: case SQL_C_UBIGINT: case SQL_C_BINARY: @@ -1361,36 +1658,55 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_SMALLINT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v2); bind->buffer = &bind->u.v2; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_smallint(*(int32_t*)paramValue, &bind->u.v2)); + case SQL_C_BIT: { + CHK_CONV(1, tsdb_int64_to_smallint(*(int8_t*)paramValue, &bind->u.v2)); } break; - case SQL_C_SHORT: { - CHK_CONV(tsdb_int64_to_smallint(*(int16_t*)paramValue, &bind->u.v2)); + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(1, tsdb_int64_to_smallint(*(int8_t*)paramValue, &bind->u.v2)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: case SQL_C_SSHORT: - case SQL_C_USHORT: + case SQL_C_SHORT: { + CHK_CONV(1, tsdb_int64_to_smallint(*(int16_t*)paramValue, &bind->u.v2)); + } break; case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(1, tsdb_int64_to_smallint(*(int32_t*)paramValue, &bind->u.v2)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(1, tsdb_int64_to_smallint(*(int64_t*)paramValue, &bind->u.v2)); + } break; + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_smallint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v2)); + // CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, (size_t)*soi, &bind->u.v2)); + } break; + case SQL_C_WCHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_smallint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v2)); + } break; + case SQL_C_USHORT: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1405,34 +1721,55 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_INT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v4); bind->buffer = &bind->u.v4; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_LONG: { - CHK_CONV(tsdb_int64_to_int(*(int32_t*)paramValue, &bind->u.v4)); + case SQL_C_BIT: { + CHK_CONV(1, tsdb_int64_to_int(*(int8_t*)paramValue, &bind->u.v4)); + } break; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(1, tsdb_int64_to_int(*(int8_t*)paramValue, &bind->u.v4)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: case SQL_C_SSHORT: - case SQL_C_USHORT: + case SQL_C_SHORT: { + CHK_CONV(1, tsdb_int64_to_int(*(int16_t*)paramValue, &bind->u.v4)); + } break; case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(1, tsdb_int64_to_int(*(int32_t*)paramValue, &bind->u.v4)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(1, tsdb_int64_to_int(*(int64_t*)paramValue, &bind->u.v4)); + } break; + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_int(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v4)); + // CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, (size_t)*soi, &bind->u.v4)); + } break; + case SQL_C_WCHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_int(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v4)); + } break; + case SQL_C_USHORT: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1447,35 +1784,54 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_BIGINT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v8); bind->buffer = &bind->u.v8; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_SBIGINT: { - bind->u.v8 = *(int64_t*)paramValue; + case SQL_C_BIT: { + CHK_CONV(1, tsdb_int64_to_bigint(*(int8_t*)paramValue, &bind->u.v8)); } break; - case SQL_C_LONG: { - bind->u.v8 = *(int32_t*)paramValue; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(1, tsdb_int64_to_bigint(*(int8_t*)paramValue, &bind->u.v8)); } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: case SQL_C_SSHORT: - case SQL_C_USHORT: + case SQL_C_SHORT: { + CHK_CONV(1, tsdb_int64_to_bigint(*(int16_t*)paramValue, &bind->u.v8)); + } break; case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(1, tsdb_int64_to_bigint(*(int32_t*)paramValue, &bind->u.v8)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(1, tsdb_int64_to_bigint(*(int64_t*)paramValue, &bind->u.v8)); + } break; + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_bigint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); + // CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, (size_t)*soi, &bind->u.v8)); + } break; + case SQL_C_WCHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_bigint(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); + } break; + case SQL_C_USHORT: case SQL_C_ULONG: case SQL_C_FLOAT: case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: case SQL_C_UBIGINT: case SQL_C_BINARY: @@ -1491,36 +1847,58 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_FLOAT: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.f4); bind->buffer = &bind->u.f4; bind->length = &bind->buffer_length; switch (valueType) { - case SQL_C_DOUBLE: { - bind->u.f4 = *(double*)paramValue; + case SQL_C_BIT: { + CHK_CONV(1, tsdb_int64_to_float(*(int8_t*)paramValue, &bind->u.f4)); + } break; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(1, tsdb_int64_to_float(*(int8_t*)paramValue, &bind->u.f4)); + } break; + case SQL_C_SSHORT: + case SQL_C_SHORT: { + CHK_CONV(1, tsdb_int64_to_float(*(int16_t*)paramValue, &bind->u.f4)); + } break; + case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(1, tsdb_int64_to_float(*(int32_t*)paramValue, &bind->u.f4)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(1, tsdb_int64_to_float(*(int64_t*)paramValue, &bind->u.f4)); } break; case SQL_C_FLOAT: { bind->u.f4 = *(float*)paramValue; } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: + case SQL_C_DOUBLE: { + bind->u.f4 = (float)*(double*)paramValue; + } break; + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_float(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4)); + } break; + case SQL_C_WCHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_float(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4)); + } break; case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: case SQL_C_ULONG: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1535,34 +1913,59 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_DOUBLE: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.f8); bind->buffer = &bind->u.f8; bind->length = &bind->buffer_length; switch (valueType) { + case SQL_C_BIT: { + CHK_CONV(1, tsdb_int64_to_double(*(int8_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_STINYINT: + case SQL_C_TINYINT: { + CHK_CONV(1, tsdb_int64_to_double(*(int8_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_SSHORT: + case SQL_C_SHORT: { + CHK_CONV(1, tsdb_int64_to_double(*(int16_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_SLONG: + case SQL_C_LONG: { + CHK_CONV(1, tsdb_int64_to_double(*(int32_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_SBIGINT: { + CHK_CONV(1, tsdb_int64_to_double(*(int64_t*)paramValue, &bind->u.f8)); + } break; + case SQL_C_FLOAT: { + bind->u.f8 = *(float*)paramValue; + } break; case SQL_C_DOUBLE: { bind->u.f8 = *(double*)paramValue; } break; - case SQL_C_CHAR: - case SQL_C_WCHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + CHK_CONV(1, tsdb_conv_chars_to_double(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8)); + // CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, (size_t)*soi, &bind->u.f8)); + } break; + case SQL_C_WCHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_double(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8)); + } break; case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: case SQL_C_UTINYINT: - case SQL_C_SBIGINT: case SQL_C_UBIGINT: case SQL_C_BINARY: case SQL_C_DATE: @@ -1577,95 +1980,51 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); - return SQL_ERROR; - } break; - } - } break; - case TSDB_DATA_TYPE_BINARY: { - bind->buffer_type = type; - bind->length = &bind->buffer_length; - switch (valueType) { - case SQL_C_WCHAR: { - DASSERT(soi); - DASSERT(*soi != SQL_NTS); - size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, *soi/2, &bytes); - bind->allocated = 1; - bind->u.bin = utf8; - bind->buffer_length = bytes; - bind->buffer = bind->u.bin; - } break; - case SQL_C_BINARY: { - bind->u.bin = (unsigned char*)paramValue; - if (*soi == SQL_NTS) { - bind->buffer_length = strlen((const char*)paramValue); - } else { - bind->buffer_length = *soi; - } - bind->buffer = bind->u.bin; - } break; - case SQL_C_CHAR: - case SQL_C_SHORT: - case SQL_C_SSHORT: - case SQL_C_USHORT: - case SQL_C_LONG: - case SQL_C_SLONG: - case SQL_C_ULONG: - case SQL_C_FLOAT: - case SQL_C_DOUBLE: - case SQL_C_BIT: - case SQL_C_TINYINT: - case SQL_C_STINYINT: - case SQL_C_UTINYINT: - case SQL_C_SBIGINT: - case SQL_C_UBIGINT: - case SQL_C_DATE: - case SQL_C_TIME: - case SQL_C_TIMESTAMP: - case SQL_C_TYPE_DATE: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_NUMERIC: - case SQL_C_GUID: - default: { - SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, - "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", - sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; case TSDB_DATA_TYPE_TIMESTAMP: { - bind->buffer_type = type; + bind->buffer_type = tsdb_type; bind->buffer_length = sizeof(bind->u.v8); bind->buffer = &bind->u.v8; bind->length = &bind->buffer_length; switch (valueType) { + case SQL_C_CHAR: { + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_timestamp_ts(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); + } break; case SQL_C_WCHAR: { - DASSERT(soi); - DASSERT(*soi != SQL_NTS); - size_t bytes = 0; - int r = 0; - int64_t t = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, *soi/2, &bytes); - // why cast utf8 to 'char*' ? - r = taosParseTime((char*)utf8, &t, strlen((const char*)utf8), TSDB_TIME_PRECISION_MILLI, 0); - bind->u.v8 = t; - free(utf8); - if (r) { - SET_ERROR(sql, "22007", TSDB_CODE_ODBC_OUT_OF_RANGE, - "convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d] failed", - sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); - return SQL_ERROR; - } + stack_buffer_t buffer; buffer.next = 0; + tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn); + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + CHK_CONV(1, tsdb_conv_chars_to_timestamp_ts(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8)); } break; case SQL_C_SBIGINT: { int64_t t = *(int64_t*)paramValue; bind->u.v8 = t; } break; + case SQL_C_TYPE_TIMESTAMP: { + SQL_TIMESTAMP_STRUCT ts = *(SQL_TIMESTAMP_STRUCT*)paramValue; + struct tm vtm = {0}; + vtm.tm_year = ts.year - 1900; + vtm.tm_mon = ts.month - 1; + vtm.tm_mday = ts.day; + vtm.tm_hour = ts.hour; + vtm.tm_min = ts.minute; + vtm.tm_sec = ts.second; + int64_t t = (int64_t) mktime(&vtm); + if (t==-1) { + CHK_CONV(1, TSDB_CONV_NOT_VALID_TS); + // code never reached here + } + bind->u.ts = t * 1000 + ts.fraction / 1000000; + } break; case SQL_C_SHORT: case SQL_C_SSHORT: case SQL_C_USHORT: @@ -1685,40 +2044,100 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin case SQL_C_TIMESTAMP: case SQL_C_TYPE_DATE: case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: case SQL_C_NUMERIC: case SQL_C_GUID: default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } } break; - case TSDB_DATA_TYPE_NCHAR: { - bind->buffer_type = type; + case TSDB_DATA_TYPE_BINARY: { + bind->buffer_type = tsdb_type; bind->length = &bind->buffer_length; switch (valueType) { case SQL_C_WCHAR: { - DASSERT(soi); - DASSERT(*soi != SQL_NTS); - size_t bytes = 0; - SQLCHAR *utf8 = wchars_to_chars(paramValue, *soi/2, &bytes); - bind->allocated = 1; - bind->u.nchar = (char*)utf8; - bind->buffer_length = bytes; - bind->buffer = bind->u.nchar; + // taos cares nothing about what would be stored in 'binary' as most sql implementations do + // thus, we just copy it as is + // it's caller's responsibility to maintain data-consistency + // if he/she is going to use 'binary' to store characters + // taos might extend it's sql syntax to let user specify + // what charset is to be used for specific 'binary' field when + // table is to be created + // in such way, 'binary' would be 'internationalized' + // but actually speaking, normally, 'char' field is a better + // one for this purpose + size_t slen = (size_t)*soi; + DASSERT(slen != SQL_NTS); + bind->u.bin = (unsigned char*)malloc(slen + 1); // add null-terminator, just for case of use + if (!bind->u.bin) { + CHK_CONV(1, TSDB_CONV_OOM); + // code never reached here + } + memcpy(bind->u.bin, paramValue, slen); + bind->buffer_length = slen; + bind->buffer = bind->u.bin; + CHK_CONV(1, TSDB_CONV_OK); + + // tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); + // size_t slen = (size_t)*soi; + // DASSERT(slen != SQL_NTS); + // const char *buf = NULL; + // size_t blen = 0; + // TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + // if (code==TSDB_CONV_OK) { + // if (buf!=(const char*)paramValue) { + // bind->allocated = 1; + // } + // bind->u.bin = (unsigned char*)buf; + // bind->buffer_length = blen; + // bind->buffer = bind->u.bin; + // } + // CHK_CONV(1, code); } break; case SQL_C_CHAR: { - bind->u.nchar = (char*)paramValue; - if (*soi == SQL_NTS) { - bind->buffer_length = strlen((const char*)paramValue); - } else { - bind->buffer_length = *soi; + // taos cares nothing about what would be stored in 'binary' as most sql implementations do + // thus, we just copy it as is + // it's caller's responsibility to maintain data-consistency + // if he/she is going to use 'binary' to store characters + // taos might extend it's sql syntax to let user specify + // what charset is to be used for specific 'binary' field when + // table is to be created + // in such way, 'binary' would be 'internationalized' + // but actually speaking, normally, 'char' field is a better + // one for this purpose + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + // we can not use strndup, because ODBC client might pass in a buffer without null-terminated + bind->u.bin = (unsigned char*)malloc(slen + 1); // add null-terminator, just for case of use + if (!bind->u.bin) { + CHK_CONV(1, TSDB_CONV_OOM); + // code never reached here } - bind->buffer = bind->u.nchar; + memcpy(bind->u.bin, paramValue, slen); + bind->buffer_length = slen; + bind->buffer = bind->u.bin; + CHK_CONV(1, TSDB_CONV_OK); + // code never reached here + + // tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + // size_t slen = (size_t)*soi; + // if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + // const char *buf = NULL; + // size_t blen = 0; + // TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + // if (code==TSDB_CONV_OK) { + // if (buf!=(const char*)paramValue) { + // bind->allocated = 1; + // } + // bind->u.bin = (unsigned char*)buf; + // bind->buffer_length = blen; + // bind->buffer = bind->u.bin; + // } + // CHK_CONV(1, code); } break; case SQL_C_SHORT: case SQL_C_SSHORT: @@ -1740,14 +2159,84 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin case SQL_C_TIMESTAMP: case SQL_C_TYPE_DATE: case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: + case SQL_C_TYPE_TIMESTAMP: // we don't provide auto-converstion case SQL_C_NUMERIC: case SQL_C_GUID: default: { SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); + return SQL_ERROR; + } break; + } + } break; + case TSDB_DATA_TYPE_NCHAR: { + bind->buffer_type = tsdb_type; + bind->length = &bind->buffer_length; + switch (valueType) { + case SQL_C_WCHAR: { + tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + const char *buf = NULL; + size_t blen = 0; + TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + if (code==TSDB_CONV_OK) { + if (buf!=(const char*)paramValue) { + bind->allocated = 1; + } + bind->u.nchar = (char*)buf; + bind->buffer_length = blen; + bind->buffer = bind->u.nchar; + } + CHK_CONV(1, code); + } break; + case SQL_C_CHAR: { + tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn); + size_t slen = (size_t)*soi; + if (slen==SQL_NTS) slen = strlen((const char*)paramValue); + const char *buf = NULL; + size_t blen = 0; + TSDB_CONV_CODE code = tsdb_conv(client_to_server, NULL, (const char *)paramValue, slen, &buf, &blen); + if (code==TSDB_CONV_OK) { + if (buf!=(const char*)paramValue) { + bind->allocated = 1; + } + bind->u.bin = (unsigned char*)buf; + bind->buffer_length = blen; + bind->buffer = bind->u.bin; + } + CHK_CONV(1, code); + } break; + case SQL_C_SHORT: + case SQL_C_SSHORT: + case SQL_C_USHORT: + case SQL_C_LONG: + case SQL_C_SLONG: + case SQL_C_ULONG: + case SQL_C_FLOAT: + case SQL_C_DOUBLE: + case SQL_C_BIT: + case SQL_C_TINYINT: + case SQL_C_STINYINT: + case SQL_C_UTINYINT: + case SQL_C_SBIGINT: + case SQL_C_UBIGINT: + case SQL_C_BINARY: + case SQL_C_DATE: + case SQL_C_TIME: + case SQL_C_TIMESTAMP: + case SQL_C_TYPE_DATE: + case SQL_C_TYPE_TIME: + case SQL_C_TYPE_TIMESTAMP: // we don't provide auto-converstion + case SQL_C_NUMERIC: + case SQL_C_GUID: + default: { + SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, + "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", + sql_c_type(valueType), valueType, valueType, + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } @@ -1756,7 +2245,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE, "no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]", sql_c_type(valueType), valueType, valueType, - taos_data_type(type), type, type, idx+1); + taos_data_type(tsdb_type), tsdb_type, tsdb_type, idx+1); return SQL_ERROR; } break; } @@ -1797,7 +2286,7 @@ static SQLRETURN do_execute(sql_t *sql) for (int i=0; in_rows; ++i) { TAOS_BIND *binds = NULL; if (sql->n_params>0) { - binds = (TAOS_BIND*)calloc(sql->n_params, sizeof(*binds)); + binds = (TAOS_BIND*)calloc((size_t)sql->n_params, sizeof(*binds)); if (!binds) { SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); return SQL_ERROR; @@ -1827,7 +2316,7 @@ static SQLRETURN do_execute(sql_t *sql) } sql->is_executed = 1; - if (sql->is_insert) return SQL_SUCCESS; + // if (sql->is_insert) return SQL_SUCCESS; SQLRETURN r = SQL_SUCCESS; PROFILE(sql->rs = taos_stmt_use_result(sql->stmt)); @@ -1872,8 +2361,12 @@ static SQLRETURN doSQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLPOINTER DiagInfo, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) { - // if this function is not exported, isql will never call SQLGetDiagRec - return SQL_ERROR; + switch (DiagIdentifier) { + case SQL_DIAG_CLASS_ORIGIN: { + *StringLength = 0; + } break; + } + return SQL_SUCCESS; } SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, @@ -1949,7 +2442,7 @@ static SQLRETURN doSQLBindParameter( SQLLEN *StrLen_or_Ind) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -1989,6 +2482,16 @@ static SQLRETURN doSQLBindParameter( return SQL_ERROR; } + if (ParameterValue==NULL) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ParameterValue [@%p] not allowed", ParameterValue); + return SQL_ERROR; + } + + if (StrLen_or_Ind==NULL) { + SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StrLen_or_Ind [@%p] not allowed", StrLen_or_Ind); + return SQL_ERROR; + } + param_bind_t *pb = sql->params + ParameterNumber - 1; pb->ParameterNumber = ParameterNumber; @@ -2032,26 +2535,25 @@ static SQLRETURN doSQLDriverConnect( SQLUSMALLINT fDriverCompletion) { conn_t *conn = (conn_t*)hdbc; - if (!conn) return SQL_ERROR; - - if (fDriverCompletion!=SQL_DRIVER_NOPROMPT) { - SET_ERROR(conn, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "option[%d] other than SQL_DRIVER_NOPROMPT not supported yet", fDriverCompletion); - return SQL_ERROR; - } + if (!conn) return SQL_INVALID_HANDLE; if (conn->taos) { SET_ERROR(conn, "08002", TSDB_CODE_ODBC_CONNECTION_BUSY, "connection still in use"); return SQL_ERROR; } + if (fDriverCompletion!=SQL_DRIVER_NOPROMPT) { + SET_ERROR(conn, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "option[%d] other than SQL_DRIVER_NOPROMPT not supported yet", fDriverCompletion); + return SQL_ERROR; + } + + NORM_STR_LENGTH(conn, szConnStrIn, cbConnStrIn); + // DSN=; UID=; PWD= const char *connStr = SDUP(szConnStrIn, cbConnStrIn); - char *serverName = NULL; - char *userName = NULL; - char *auth = NULL; - int bytes = 0; + conn_val_t val = {0}; do { if (szConnStrIn && !connStr) { @@ -2059,32 +2561,52 @@ static SQLRETURN doSQLDriverConnect( break; } - int n = sscanf((const char*)connStr, "DSN=%m[^;]; UID=%m[^;]; PWD=%m[^;] %n", &serverName, &userName, &auth, &bytes); - if (n<1) { + int n = todbc_parse_conn_string((const char *)connStr, &val); + if (n) { SET_ERROR(conn, "HY000", TSDB_CODE_ODBC_BAD_CONNSTR, "unrecognized connection string: [%s]", (const char*)szConnStrIn); break; } + char *ip = NULL; + int port = 0; + if (val.server) { + char *p = strchr(val.server, ':'); + if (p) { + ip = strndup(val.server, (size_t)(p-val.server)); + port = atoi(p+1); + } + } + + if ((val.cli_enc && strcmp(val.cli_enc, conn->client_enc)) || + (val.svr_enc && strcmp(val.svr_enc, conn->server_enc)) ) + { + tsdb_conn_close_convs(conn); + if (val.cli_enc) { + snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", val.cli_enc); + } + if (val.svr_enc) { + snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", val.svr_enc); + } + } // TODO: data-race // TODO: shall receive ip/port from odbc.ini - conn->taos = taos_connect("localhost", userName, auth, NULL, 0); + // shall we support non-ansi uid/pwd/db etc? + conn->taos = taos_connect(ip ? ip : "localhost", val.uid, val.pwd, val.db, (uint16_t)port); + free(ip); ip = NULL; if (!conn->taos) { SET_ERROR(conn, "HY000", terrno, "failed to connect to data source"); break; } if (szConnStrOut) { - snprintf((char*)szConnStrOut, cbConnStrOutMax, "%s", connStr); + snprintf((char*)szConnStrOut, (size_t)cbConnStrOutMax, "%s", connStr); } if (pcbConnStrOut) { *pcbConnStrOut = cbConnStrIn; } - } while (0); - if (serverName) free(serverName); - if (userName) free(userName); - if (auth) free(auth); + conn_val_reset(&val); SFRE(connStr, szConnStrIn, cbConnStrIn); @@ -2111,7 +2633,7 @@ static SQLRETURN doSQLSetConnectAttr(SQLHDBC ConnectionHandle, SQLINTEGER StringLength) { conn_t *conn = (conn_t*)ConnectionHandle; - if (!conn) return SQL_ERROR; + if (!conn) return SQL_INVALID_HANDLE; if (Attribute != SQL_ATTR_AUTOCOMMIT) { SET_ERROR(conn, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT, "Attribute other than SQL_ATTR_AUTOCOMMIT not supported yet"); @@ -2141,7 +2663,7 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -2158,19 +2680,21 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, SET_ERROR(sql, "07009", TSDB_CODE_ODBC_OUT_OF_RANGE, "invalid column number [%d]", ColumnNumber); return SQL_ERROR; } + if (BufferLength<0) { + SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); + return SQL_ERROR; + } TAOS_FIELD *field = fields + ColumnNumber - 1; if (ColumnName) { size_t n = sizeof(field->name); - if (n>BufferLength) n = BufferLength; + if (n>BufferLength) n = (size_t)BufferLength; strncpy((char*)ColumnName, field->name, n); } if (NameLength) { - *NameLength = strnlen(field->name, sizeof(field->name)); - } - if (ColumnSize) { - *ColumnSize = field->bytes; + *NameLength = (SQLSMALLINT)strnlen(field->name, sizeof(field->name)); } + if (ColumnSize) *ColumnSize = (SQLULEN)field->bytes; if (DecimalDigits) *DecimalDigits = 0; if (DataType) { @@ -2204,12 +2728,9 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, } break; case TSDB_DATA_TYPE_TIMESTAMP: { - // *DataType = SQL_TIMESTAMP; - // *ColumnSize = 30; - // *DecimalDigits = 3; *DataType = SQL_TIMESTAMP; - *ColumnSize = sizeof(SQL_TIMESTAMP_STRUCT); - *DecimalDigits = 0; + if (ColumnSize) *ColumnSize = sizeof(SQL_TIMESTAMP_STRUCT); + if (DecimalDigits) *DecimalDigits = 0; } break; case TSDB_DATA_TYPE_NCHAR: { @@ -2218,7 +2739,7 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle, } break; case TSDB_DATA_TYPE_BINARY: { - *DataType = SQL_BINARY; + *DataType = SQL_CHAR; if (ColumnSize) *ColumnSize -= VARSTR_HEADER_SIZE; } break; @@ -2253,7 +2774,7 @@ SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle, static SQLRETURN doSQLNumParams(SQLHSTMT hstmt, SQLSMALLINT *pcpar) { sql_t *sql = (sql_t*)hstmt; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -2281,7 +2802,7 @@ static SQLRETURN doSQLNumParams(SQLHSTMT hstmt, SQLSMALLINT *pcpar) return SQL_ERROR; } - if (pcpar) *pcpar = params; + if (pcpar) *pcpar = (SQLSMALLINT)params; return SQL_SUCCESS; } @@ -2298,7 +2819,7 @@ static SQLRETURN doSQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER StringLength) { sql_t *sql = (sql_t*)StatementHandle; - if (!sql) return SQL_ERROR; + if (!sql) return SQL_INVALID_HANDLE; CHK_CONN(sql); CHK_CONN_TAOS(sql); @@ -2355,19 +2876,254 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, return r; } +#ifdef _MSC_VER +#define POST_INSTALLER_ERROR(hwndParent, code, fmt, ...) \ +do { \ + char buf[4096]; \ + snprintf(buf, sizeof(buf), "%s[%d]%s():" fmt "", \ + basename((char*)__FILE__), __LINE__, __func__, \ + ##__VA_ARGS__); \ + SQLPostInstallerError(code, buf); \ + if (hwndParent) { \ + MessageBox(hwndParent, buf, "Error", MB_OK|MB_ICONEXCLAMATION); \ + } \ +} while (0) + +typedef struct kv_s kv_t; +struct kv_s { + char *line; + size_t val; +}; + +static BOOL get_driver_dll_path(HWND hwndParent, char *buf, size_t len) +{ + HMODULE hm = NULL; + + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCSTR) &ConfigDSN, &hm) == 0) + { + int ret = GetLastError(); + POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "GetModuleHandle failed, error = %d\n", ret); + return FALSE; + } + if (GetModuleFileName(hm, buf, (DWORD)len) == 0) + { + int ret = GetLastError(); + POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "GetModuleFileName failed, error = %d\n", ret); + return FALSE; + } + return TRUE; +} + +static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) +{ + BOOL r = TRUE; + + kv_t *kvs = NULL; + + kv_t dsn = {0}; + char *line = NULL; + + do { + char driver_dll[MAX_PATH + 1]; + r = get_driver_dll_path(hwndParent, driver_dll, sizeof(driver_dll)); + if (!r) break; + + dsn.line = strdup("DSN=TAOS_DEMO"); + if (!dsn.line) { r = FALSE; break; } + + const char *p = lpszAttributes; + int ikvs = 0; + while (p && *p) { + line = strdup(p); + if (!line) { r = FALSE; break; } + char *v = strchr(line, '='); + if (!v) { r = FALSE; break; } + + if (strstr(line, "DSN")==line) { + if (dsn.line) { + free(dsn.line); + dsn.line = NULL; + dsn.val = 0; + } + dsn.line = line; + line = NULL; + } else { + kv_t *t = (kv_t*)realloc(kvs, (ikvs+1)*sizeof(*t)); + if (!t) { r = FALSE; free(line); break; } + t[ikvs].line = line; + *v = '\0'; + if (v) t[ikvs].val = v - line + 1; + line = NULL; + + kvs = t; + ++ikvs; + } + + p += strlen(p) + 1; + } + + if (hwndParent) { + MessageBox(hwndParent, "Please use odbcconf to add DSN for TAOS ODBC Driver", "Warning!", MB_OK|MB_ICONEXCLAMATION); + } + if (!r) break; + + char *v = NULL; + v = strchr(dsn.line, '='); + if (!v) { r = FALSE; break; } + *v = '\0'; + dsn.val = v - dsn.line + 1; + + if ((!dsn.line)) { + if (!r) POST_INSTALLER_ERROR(hwndParent, ODBC_ERROR_REQUEST_FAILED, "lack of either DSN or Driver"); + } else { + if (r) r = SQLWritePrivateProfileString("ODBC Data Sources", dsn.line+dsn.val, lpszDriver, "Odbc.ini"); + if (r) r = SQLWritePrivateProfileString(dsn.line+dsn.val, "Driver", driver_dll, "Odbc.ini"); + } + + for (int i=0; r && itype) { case TSDB_DATA_TYPE_TINYINT: return 5; @@ -2395,7 +3151,7 @@ static int do_field_display_size(TAOS_FIELD *field) { case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: { - return 3*(field->bytes - VARSTR_HEADER_SIZE) + 2; + return 3*((size_t)field->bytes - VARSTR_HEADER_SIZE) + 2; } break; case TSDB_DATA_TYPE_TIMESTAMP: @@ -2411,1070 +3167,5 @@ static int do_field_display_size(TAOS_FIELD *field) { return 10; } -// convertion from TSDB_DATA_TYPE_XXX to SQL_C_XXX -static SQLRETURN conv_tsdb_bool_to_c_bit(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int8_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} -static SQLRETURN conv_tsdb_bool_to_c_tinyint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int8_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int16_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int32_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - int64_t v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - float v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - double v = b; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - DASSERT(target->len>0); - *target->soi = 1; - target->ptr[0] = '0' + b; - if (target->len>1) { - target->ptr[1] = '\0'; - } - - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bool_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t b) -{ - DASSERT(target->len>0); - *target->soi = 1; - target->ptr[0] = '0' + b; - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_tinyint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - int8_t v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - int16_t v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - int32_t v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - int64_t v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - float v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - double v = v1; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v1_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v1); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_TINYINT -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v1_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int8_t v1) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v1); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_TINYINT -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v2_to_c_short(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - int16_t v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - int32_t v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - int64_t v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - float v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - double v = v2; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v2_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v2); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_SMALLINT -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v2_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int16_t v2) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v2); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_SMALLINT -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_v4_to_c_long(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - int32_t v = v4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v4_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - int64_t v = v4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v4_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - float v = v4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v4_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - double v = v4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v4_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v4); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_INTEGER -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v4_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int32_t v4) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%d", v4); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_INTEGER -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_v8_to_c_sbigint(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - int64_t v = v8; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v8_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - float v = v8; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v8_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - double v = v8; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_v8_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%" PRId64 "", v8); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_BIGINT -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_v8_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, int64_t v8) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%" PRId64 "", v8); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_BIGINT -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_f4_to_c_float(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4) -{ - float v = f4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_f4_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4) -{ - double v = f4; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_f4_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%g", f4); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_FLOAT -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_f4_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, float f4) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%g", f4); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_FLOAT -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_f8_to_c_double(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8) -{ - double v = f8; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_f8_to_c_char(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%.6f", f8); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>=target->len ? target->len : n+1)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_DOUBLE -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_f8_to_c_binary(sql_t *sql, c_target_t *target, TAOS_FIELD *field, double f8) -{ - char buf[64]; - int n = snprintf(buf, sizeof(buf), "%g", f8); - DASSERT(nsoi = n; - strncpy(target->ptr, buf, (n>target->len ? target->len : n)); - if (n<=target->len) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_DOUBLE -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - - -static SQLRETURN conv_tsdb_ts_to_c_v8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts) -{ - struct tm tm = {0}; - tm.tm_sec = ts->second; - tm.tm_min = ts->minute; - tm.tm_hour = ts->hour; - tm.tm_mday = ts->day; - tm.tm_mon = ts->month - 1; - tm.tm_year = ts->year - 1900; - time_t t = mktime(&tm); - DASSERT(sizeof(t) == sizeof(int64_t)); - int64_t v = (int64_t)t; - v *= 1000; - v += ts->fraction / 1000000; - memcpy(target->ptr, &v, sizeof(v)); - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_ts_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts) -{ - struct tm tm = {0}; - tm.tm_sec = ts->second; - tm.tm_min = ts->minute; - tm.tm_hour = ts->hour; - tm.tm_mday = ts->day; - tm.tm_mon = ts->month - 1; - tm.tm_year = ts->year - 1900; - - char buf[64]; - int n = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); - DASSERT(n < sizeof(buf)); - - *target->soi = n; - - unsigned int fraction = ts->fraction; - fraction /= 1000000; - snprintf(target->ptr, target->len, "%s.%03d", buf, fraction); - if (target->soi) *target->soi = strlen((const char*)target->ptr); - - if (n <= target->len) { - return SQL_SUCCESS; - } - - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_TIMESTAMP -> SQL_C_CHAR"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_ts_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts) -{ - struct tm tm = {0}; - tm.tm_sec = ts->second; - tm.tm_min = ts->minute; - tm.tm_hour = ts->hour; - tm.tm_mday = ts->day; - tm.tm_mon = ts->month - 1; - tm.tm_year = ts->year - 1900; - - char buf[64]; - int n = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); - DASSERT(n < sizeof(buf)); - - unsigned int fraction = ts->fraction; - fraction /= 1000000; - snprintf(target->ptr, target->len, "%s.%03d", buf, fraction); - if (target->soi) *target->soi = strlen((const char*)target->ptr); - - if (n <= target->len) { - return SQL_SUCCESS; - } - - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_TIMESTAMP -> SQL_C_BINARY"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_ts_to_c_ts(sql_t *sql, c_target_t *target, TAOS_FIELD *field, SQL_TIMESTAMP_STRUCT *ts) -{ - DASSERT(target->len == sizeof(*ts)); - memcpy(target->ptr, ts, sizeof(*ts)); - *target->soi = target->len; - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_bin_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const unsigned char *bin) -{ - if (target->len<1) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - size_t field_bytes = field->bytes - VARSTR_HEADER_SIZE; - size_t n = strnlen((const char*)bin, field_bytes); - - if (n < target->len) { - memcpy(target->ptr, bin, n); - target->ptr[n] = '\0'; - *target->soi = n; - return SQL_SUCCESS; - } - n = target->len - 1; - *target->soi = n; - if (n > 0) { - memcpy(target->ptr, bin, n-1); - target->ptr[n-1] = '\0'; - } - SET_ERROR(sql, "01004", TSDB_CODE_ODBC_CONV_TRUNC, ""); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_bin_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const unsigned char *bin) -{ - if (target->len<1) { - SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, ""); - return SQL_ERROR; - } - size_t field_bytes = field->bytes - VARSTR_HEADER_SIZE; - size_t n = strnlen((const char*)bin, field_bytes); - - if (n <= target->len) { - memcpy(target->ptr, bin, n); - if (nlen) target->ptr[n] = '\0'; - *target->soi = n; - return SQL_SUCCESS; - } - - n = target->len; - memcpy(target->ptr, bin, n); - *target->soi = n; - SET_ERROR(sql, "01004", TSDB_CODE_ODBC_CONV_TRUNC, ""); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_bit(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int8_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 1; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - - if (strcmp(buf, str)==0) { - if (v==0 || v==1) return SQL_SUCCESS; - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; - } - - if (f8>0 || f8<2) { - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; - } - - if (f8<0 || f8>2) { - SET_ERROR(sql, "22003", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_BIT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_v1(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int8_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 1; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_TINYINT"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - - if (strcmp(buf, str)==0) return SQL_SUCCESS; - - if (f8>INT8_MAX || f8 SQL_C_TINYINT"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_TINYINT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_v2(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int16_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 2; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_SHORT"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - - if (strcmp(buf, str)==0) return SQL_SUCCESS; - - if (f8>INT16_MAX || f8 SQL_C_SHORT"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_SHORT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_v4(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int32_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 4; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_LONG"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - - if (strcmp(buf, str)==0) return SQL_SUCCESS; - - if (f8>INT32_MAX || f8 SQL_C_LONG"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_LONG"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_v8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - int64_t v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 8; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_SBIGINT"); - return SQL_SUCCESS_WITH_INFO; - } - - char buf[64]; - snprintf(buf, sizeof(buf), "%" PRId64 "", v); - - if (strcmp(buf, str)==0) return SQL_SUCCESS; - - if (f8>INT64_MAX || f8 SQL_C_SBIGINT"); - return SQL_SUCCESS_WITH_INFO; - } - - SET_ERROR(sql, "01S07", TSDB_CODE_ODBC_CONV_TRUNC, "TSDB_DATA_TYPE_NCHAR -> SQL_C_SBIGINT"); - return SQL_SUCCESS_WITH_INFO; -} - -static SQLRETURN conv_tsdb_str_to_c_f4(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - float v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 4; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_FLOAT"); - return SQL_SUCCESS_WITH_INFO; - } - - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_str_to_c_f8(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - int bytes = 0; - double f8 = 0; - int n = sscanf(str, "%lf%n", &f8, &bytes); - - float v = f8; - memcpy(target->ptr, &v, sizeof(v)); - - *target->soi = 8; - - if (n!=1 || bytes!=strlen(str)) { - SET_ERROR(sql, "22018", TSDB_CODE_ODBC_CONV_UNDEF, "TSDB_DATA_TYPE_NCHAR -> SQL_C_DOUBLE"); - return SQL_SUCCESS_WITH_INFO; - } - - return SQL_SUCCESS; -} - -static SQLRETURN conv_tsdb_str_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - return conv_tsdb_bin_to_c_str(sql, target, field, (const unsigned char*)str); -} - -static SQLRETURN conv_tsdb_str_to_c_bin(sql_t *sql, c_target_t *target, TAOS_FIELD *field, const char *str) -{ - return conv_tsdb_bin_to_c_bin(sql, target, field, (const unsigned char*)str); -} - - - - -const char* tsdb_int64_to_bit(int64_t src, int8_t *dst) -{ - *dst = src; - if (src==0 || src==1) return NULL; - return "22003"; -} - -const char* tsdb_int64_to_tinyint(int64_t src, int8_t *dst) -{ - *dst = src; - if (src>=SCHAR_MIN && src<=SCHAR_MAX) return NULL; - return "22003"; -} - -const char* tsdb_int64_to_smallint(int64_t src, int16_t *dst) -{ - *dst = src; - if (src>=SHRT_MIN && src<=SHRT_MAX) return NULL; - return "22003"; -} - -const char* tsdb_int64_to_int(int64_t src, int32_t *dst) -{ - *dst = src; - if (src>=LONG_MIN && src<=LONG_MAX) return NULL; - return "22003"; -} - -const char* tsdb_int64_to_bigint(int64_t src, int64_t *dst) -{ - *dst = src; - return NULL; -} - -const char* tsdb_int64_to_ts(int64_t src, int64_t *dst) -{ - *dst = src; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%" PRId64 "", src); - DASSERT(n>=0); - DASSERT(n=2) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(nSCHAR_MAX) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(nSHRT_MAX) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(nLONG_MAX) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(nLLONG_MAX) return "22003"; - - char buf[4096]; - int n = snprintf(buf, sizeof(buf), "%.*g", precision, src); - DASSERT(n>=0); - DASSERT(n=0); - DASSERT(n=0); - DASSERT(n2>=0); - DASSERT(n1=0); - if (n>=dlen) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_bit(const char *src, int8_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (v==0 || v==1) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (v==0 || v==1) return NULL; - - return "22003"; -} - -const char* tsdb_chars_to_tinyint(const char *src, int8_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vSCHAR_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vSCHAR_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_smallint(const char *src, int16_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vSHRT_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vSHRT_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_int(const char *src, int32_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vLONG_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vLONG_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_bigint(const char *src, int64_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vLLONG_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vLLONG_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_ts(const char *src, int64_t *dst) -{ - int bytes = 0; - int64_t v = 0; - int n = sscanf(src, "%" PRId64 "%n", &v, &bytes); - if (n!=1) return "22018"; - - - if (bytes!=strlen(src)) { - if (src[bytes-1]=='.') { - if (vLLONG_MAX) return "22001"; - - return "22003"; - } - return "22018"; - } - - if (vLLONG_MAX) return "22001"; - - return NULL; -} - -const char* tsdb_chars_to_float(const char *src, float *dst) -{ - int bytes = 0; - int n = sscanf(src, "%f%n", dst, &bytes); - if (n!=1) return "22018"; - - if (bytes!=strlen(src)) return "22018"; - - return NULL; -} - -const char* tsdb_chars_to_double(const char *src, double *dst) -{ - int bytes = 0; - int n = sscanf(src, "%lf%n", dst, &bytes); - if (n!=1) return "22018"; - - if (bytes!=strlen(src)) return "22018"; - - return NULL; -} - -const char* tsdb_chars_to_char(const char *src, char *dst, size_t dlen) -{ - int n = snprintf(dst, dlen, "%s", src); - if (n>=dlen) return "22001"; - - return NULL; -} diff --git a/src/connector/odbc/src/todbc.def b/src/connector/odbc/src/todbc.def new file mode 100644 index 0000000000..1e080f0198 --- /dev/null +++ b/src/connector/odbc/src/todbc.def @@ -0,0 +1,31 @@ +EXPORTS +SQLAllocEnv +SQLFreeEnv +SQLAllocConnect +SQLFreeConnect +SQLConnect +SQLDisconnect +SQLAllocStmt +SQLAllocHandle +SQLFreeStmt +SQLExecDirect +SQLExecDirectW +SQLNumResultCols +SQLRowCount +SQLColAttribute +SQLGetData +SQLFetch +SQLPrepare +SQLExecute +SQLGetDiagField +SQLGetDiagRec +SQLBindParameter +SQLDriverConnect +SQLSetConnectAttr +SQLDescribeCol +SQLNumParams +SQLSetStmtAttr +ConfigDSN +ConfigTranslator +ConfigDriver + diff --git a/src/connector/odbc/src/todbc.rc.in b/src/connector/odbc/src/todbc.rc.in new file mode 100644 index 0000000000..cf0b211454 --- /dev/null +++ b/src/connector/odbc/src/todbc.rc.in @@ -0,0 +1,31 @@ +1 VERSIONINFO + FILEVERSION ${TD_VER_NUMBER} + PRODUCTVERSION ${TD_VER_NUMBER} + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "ODBC Driver for TDengine" + VALUE "FileVersion", "${TD_VER_NUMBER}" + VALUE "InternalName", "todbc.dll(${TD_VER_CPUTYPE})" + VALUE "LegalCopyright", "Copyright (C) 2020 TAOS Data" + VALUE "OriginalFilename", "" + VALUE "ProductName", "todbc.dll(${TD_VER_CPUTYPE})" + VALUE "ProductVersion", "${TD_VER_NUMBER}" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file diff --git a/src/connector/odbc/src/todbc.rsp b/src/connector/odbc/src/todbc.rsp new file mode 100644 index 0000000000..f5e5115658 --- /dev/null +++ b/src/connector/odbc/src/todbc.rsp @@ -0,0 +1,5 @@ +INSTALLDRIVER "TAOS ODBC|Driver=todbc.dll|FileUsage=0|ConnectFunctions=YYN" + + + + diff --git a/src/connector/odbc/src/todbc_conv.c b/src/connector/odbc/src/todbc_conv.c new file mode 100644 index 0000000000..9c0f19764c --- /dev/null +++ b/src/connector/odbc/src/todbc_conv.c @@ -0,0 +1,660 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "todbc_conv.h" + +#include "todbc_log.h" + +#include +#include +#include +#include +#include + +const char* tsdb_conv_code_str(TSDB_CONV_CODE code) { + switch (code) { + case TSDB_CONV_OK: return "TSDB_CONV_OK"; + case TSDB_CONV_NOT_AVAIL: return "TSDB_CONV_NOT_AVAIL"; + case TSDB_CONV_OOM: return "TSDB_CONV_OOM"; + case TSDB_CONV_OOR: return "TSDB_CONV_OOR"; + case TSDB_CONV_TRUNC_FRACTION: return "TSDB_CONV_TRUNC_FRACTION"; + case TSDB_CONV_TRUNC: return "TSDB_CONV_TRUNC"; + case TSDB_CONV_CHAR_NOT_NUM: return "TSDB_CONV_CHAR_NOT_NUM"; + case TSDB_CONV_CHAR_NOT_TS: return "TSDB_CONV_CHAR_NOT_TS"; + case TSDB_CONV_NOT_VALID_TS: return "TSDB_CONV_NOT_VALID_TS"; + case TSDB_CONV_GENERAL: return "TSDB_CONV_GENERAL"; + case TSDB_CONV_SRC_TOO_LARGE: return "TSDB_CONV_SRC_TOO_LARGE"; + case TSDB_CONV_SRC_BAD_SEQ: return "TSDB_CONV_SRC_BAD_SEQ"; + case TSDB_CONV_SRC_INCOMPLETE: return "TSDB_CONV_SRC_INCOMPLETE"; + case TSDB_CONV_SRC_GENERAL: return "TSDB_CONV_SRC_GENERAL"; + case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR"; + default: return "UNKNOWN"; + }; +} + +// src: int +TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst) { + *dst = (int8_t)src; + if (src==0 || src==1) return TSDB_CONV_OK; + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst) { + *dst = (int8_t)src; + if (src == *dst) return TSDB_CONV_OK; + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst) { + *dst = (int16_t)src; + if (src == *dst) return TSDB_CONV_OK; + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_int(int64_t src, int32_t *dst) { + *dst = (int32_t)src; + if (src == *dst) return TSDB_CONV_OK; + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_bigint(int64_t src, int64_t *dst) { + *dst = src; + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_int64_to_ts(int64_t src, int64_t *dst) { + *dst = src; + + time_t t = (time_t)(src / 1000); + struct tm tm = {0}; + if (localtime_r(&t, &tm)) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_float(int64_t src, float *dst) { + *dst = (float)src; + + int64_t v = (int64_t)*dst; + if (v==src) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst) { + *dst = (double)src; + + int64_t v = (int64_t)*dst; + if (v==src) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen) { + int n = snprintf(dst, dlen, "%" PRId64 "", src); + DASSERT(n>=0); + + if (n=2) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_tinyint(double src, int8_t *dst) { + *dst = (int8_t)src; + + if (srcSCHAR_MAX) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_smallint(double src, int16_t *dst) { + *dst = (int16_t)src; + + if (srcSHRT_MAX) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_int(double src, int32_t *dst) { + *dst = (int32_t)src; + + if (srcLONG_MAX) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_bigint(double src, int64_t *dst) { + *dst = (int64_t)src; + + if (srcLLONG_MAX) return TSDB_CONV_OOR; + if (src == *dst) return TSDB_CONV_OK; + + int64_t v = (int64_t)src; + if (v == *dst) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst) { + TSDB_CONV_CODE code = tsdb_double_to_bigint(src, dst); + + if (code==TSDB_CONV_OK || code==TSDB_CONV_TRUNC_FRACTION) { + int64_t v = (int64_t)src; + time_t t = (time_t)(v / 1000); + struct tm tm = {0}; + if (localtime_r(&t, &tm)) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; + } + + return code; +} + +TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen) { + int n = snprintf(dst, dlen, "%lg", src); + DASSERT(n>=0); + + if (n=0); + if (n=19) return TSDB_CONV_TRUNC_FRACTION; + + return TSDB_CONV_TRUNC; +} + +// src: chars +TSDB_CONV_CODE tsdb_chars_to_bit(const char *src, size_t smax, int8_t *dst) { + if (strcmp(src, "0")==0) { + *dst = 0; + return TSDB_CONV_OK; + } + + if (strcmp(src, "1")==0) { + *dst = 1; + return TSDB_CONV_OK; + } + + double v; + int bytes; + int n = sscanf(src, "%lg%n", &v, &bytes); + + if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; + if (bytes!=strlen(src)) return TSDB_CONV_CHAR_NOT_NUM; + + if (v<0 || v>=2) return TSDB_CONV_OOR; + + return TSDB_CONV_TRUNC_FRACTION; +} + +TSDB_CONV_CODE tsdb_chars_to_tinyint(const char *src, size_t smax, int8_t *dst) { + int64_t v; + TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); + if (code!=TSDB_CONV_OK) return code; + + *dst = (int8_t)v; + + if (v==*dst) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_chars_to_smallint(const char *src, size_t smax, int16_t *dst) { + int64_t v; + TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); + if (code!=TSDB_CONV_OK) return code; + + *dst = (int16_t)v; + + if (v==*dst) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_chars_to_int(const char *src, size_t smax, int32_t *dst) { + int64_t v; + TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); + if (code!=TSDB_CONV_OK) return code; + + *dst = (int32_t)v; + + if (v==*dst) return TSDB_CONV_OK; + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst) { + int bytes; + int n = sscanf(src, "%" PRId64 "%n", dst, &bytes); + + if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; + if (bytes==strlen(src)) { + return TSDB_CONV_OK; + } + + double v; + n = sscanf(src, "%lg%n", &v, &bytes); + if (n!=1) return TSDB_CONV_CHAR_NOT_NUM; + if (bytes==strlen(src)) { + return TSDB_CONV_TRUNC_FRACTION; + } + + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst) { + int64_t v; + TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v); + if (code!=TSDB_CONV_OK) return code; + + *dst = v; + + if (v==*dst) { + time_t t = (time_t)(v / 1000); + struct tm tm = {0}; + if (localtime_r(&t, &tm)) return TSDB_CONV_OK; + } + + return TSDB_CONV_OOR; +} + +TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst) { + int bytes; + int n = sscanf(src, "%g%n", dst, &bytes); + + if (n==1 && bytes==strlen(src)) { + return TSDB_CONV_OK; + } + + return TSDB_CONV_CHAR_NOT_NUM; +} + +TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst) { + int bytes; + int n = sscanf(src, "%lg%n", dst, &bytes); + + if (n==1 && bytes==strlen(src)) { + return TSDB_CONV_OK; + } + + return TSDB_CONV_CHAR_NOT_NUM; +} + +TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst) { + int64_t v = 0; + // why cast to 'char*' ? + int r = taosParseTime((char*)src, &v, (int32_t)smax, TSDB_TIME_PRECISION_MILLI, 0); + + if (r) { + return TSDB_CONV_CHAR_NOT_TS; + } + + time_t t = v/1000; + struct tm vtm = {0}; + localtime_r(&t, &vtm); + dst->year = (SQLSMALLINT)(vtm.tm_year + 1900); + dst->month = (SQLUSMALLINT)(vtm.tm_mon + 1); + dst->day = (SQLUSMALLINT)(vtm.tm_mday); + dst->hour = (SQLUSMALLINT)(vtm.tm_hour); + dst->minute = (SQLUSMALLINT)(vtm.tm_min); + dst->second = (SQLUSMALLINT)(vtm.tm_sec); + dst->fraction = (SQLUINTEGER)(v%1000 * 1000000); + + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_chars_to_timestamp_ts(const char *src, size_t smax, int64_t *dst) { + // why cast to 'char*' ? + int r = taosParseTime((char*)src, dst, (int32_t)smax, TSDB_TIME_PRECISION_MILLI, 0); + + if (r) { + return TSDB_CONV_CHAR_NOT_TS; + } + + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax) { + int n = snprintf(dst, dmax, "%s", src); + DASSERT(n>=0); + if (nnext + bytes; + if (next>sizeof(buffer->buf)) return NULL; + + char *p = buffer->buf + buffer->next; + buffer->next = next; + return p; +} + +int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr) { + if (!buffer) return 0; + if (ptr>=buffer->buf && ptrbuf+buffer->next) return 1; + return 0; +} + + +struct tsdb_conv_s { + iconv_t cnv; + unsigned int direct:1; +}; + +static tsdb_conv_t no_conversion = {0}; +static pthread_once_t once = PTHREAD_ONCE_INIT; +static void once_init(void) { + no_conversion.cnv = (iconv_t)-1; + no_conversion.direct = 1; +} + +tsdb_conv_t* tsdb_conv_direct() { // get a non-conversion-converter + pthread_once(&once, once_init); + return &no_conversion; +} + +tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc) { + pthread_once(&once, once_init); + tsdb_conv_t *cnv = (tsdb_conv_t*)calloc(1, sizeof(*cnv)); + if (!cnv) return NULL; + if (strcmp(from_enc, to_enc)==0 && 0) { + cnv->cnv = (iconv_t)-1; + cnv->direct = 1; + return cnv; + } + cnv->cnv = iconv_open(to_enc, from_enc); + if (cnv->cnv == (iconv_t)-1) { + free(cnv); + return NULL; + } + cnv->direct = 0; + return cnv; +} + +void tsdb_conv_close(tsdb_conv_t *cnv) { + if (!cnv) return; + if (cnv == &no_conversion) return; + if (!cnv->direct) { + if (cnv->cnv != (iconv_t)-1) { + iconv_close(cnv->cnv); + } + } + cnv->cnv = (iconv_t)-1; + cnv->direct = 0; + free(cnv); +} + +TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen) { + if (!cnv) return TSDB_CONV_NOT_AVAIL; + if (cnv->direct) { + size_t n = (*slen > *dlen) ? *dlen : *slen; + memcpy(dst, src, n); + *slen -= n; + *dlen -= n; + if (*dlen) dst[n] = '\0'; + return TSDB_CONV_OK; + } + if (!cnv->cnv) return TSDB_CONV_NOT_AVAIL; + size_t r = iconv(cnv->cnv, (char**)&src, slen, &dst, dlen); + if (r==(size_t)-1) return TSDB_CONV_BAD_CHAR; + if (*slen) return TSDB_CONV_TRUNC; + if (*dlen) *dst = '\0'; + return TSDB_CONV_OK; +} + +TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen) { + char utf8[64]; + int n = snprintf(utf8, sizeof(utf8), "%" PRId64 "", val); + DASSERT(n>=0); + DASSERT(n=0); + DASSERT(n=0); + DASSERT(ndirect) { + if (src[slen]=='\0') { // access violation? + *dst = src; + if (dlen) *dlen = slen; + return TSDB_CONV_OK; + } + blen = slen + 1; + } else { + blen = (slen + 1) * 4; + } + + buf = stack_buffer_alloc(buffer, blen); + if (!buf) { + buf = (char*)malloc(blen); + if (!buf) return TSDB_CONV_OOM; + } + + if (cnv->direct) { + size_t n = slen; + DASSERT(blen > n); + memcpy(buf, src, n); + buf[n] = '\0'; + *dst = buf; + if (dlen) *dlen = n; + return TSDB_CONV_OK; + } + + const char *orig_s = src; + char *orig_d = buf; + size_t orig_blen = blen; + + TSDB_CONV_CODE code; + size_t r = iconv(cnv->cnv, (char**)&src, &slen, &buf, &blen); + do { + if (r==(size_t)-1) { + switch(errno) { + case E2BIG: { + code = TSDB_CONV_SRC_TOO_LARGE; + } break; + case EILSEQ: { + code = TSDB_CONV_SRC_BAD_SEQ; + } break; + case EINVAL: { + code = TSDB_CONV_SRC_INCOMPLETE; + } break; + default: { + code = TSDB_CONV_SRC_GENERAL; + } break; + } + break; + } + if (slen) { + code = TSDB_CONV_TRUNC; + break; + } + DASSERT(blen); + *buf = '\0'; + *dst = orig_d; + if (dlen) *dlen = orig_blen - blen; + return TSDB_CONV_OK; + } while (0); + + if (orig_d!=(char*)orig_s && !is_owned_by_stack_buffer(buffer, orig_d)) free(orig_d); + return code; +} + +void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src) { + if (ptr!=src && !is_owned_by_stack_buffer(buffer, ptr)) free((char*)ptr); +} + diff --git a/src/connector/odbc/src/todbc_conv.h b/src/connector/odbc/src/todbc_conv.h new file mode 100644 index 0000000000..2941f3e496 --- /dev/null +++ b/src/connector/odbc/src/todbc_conv.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _todbc_conv_h_ +#define _todbc_conv_h_ + +#include "os.h" +#include +#include + + +typedef enum { + TSDB_CONV_OK = 0, + TSDB_CONV_NOT_AVAIL, + TSDB_CONV_OOM, + TSDB_CONV_OOR, + TSDB_CONV_TRUNC_FRACTION, + TSDB_CONV_TRUNC, + TSDB_CONV_CHAR_NOT_NUM, + TSDB_CONV_CHAR_NOT_TS, + TSDB_CONV_NOT_VALID_TS, + TSDB_CONV_GENERAL, + TSDB_CONV_BAD_CHAR, + TSDB_CONV_SRC_TOO_LARGE, + TSDB_CONV_SRC_BAD_SEQ, + TSDB_CONV_SRC_INCOMPLETE, + TSDB_CONV_SRC_GENERAL, +} TSDB_CONV_CODE; + +const char* tsdb_conv_code_str(TSDB_CONV_CODE code); + +typedef struct stack_buffer_s stack_buffer_t; +struct stack_buffer_s { + char buf[1024*16]; + size_t next; +}; + +char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes); +int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr); + +typedef struct tsdb_conv_s tsdb_conv_t; +tsdb_conv_t* tsdb_conv_direct(); // get a non-conversion-converter +tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc); +void tsdb_conv_close(tsdb_conv_t *cnv); + +TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen); +TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen); +TSDB_CONV_CODE tsdb_conv_write_double(tsdb_conv_t *cnv, double val, char *dst, size_t *dlen); +TSDB_CONV_CODE tsdb_conv_write_timestamp(tsdb_conv_t *cnv, SQL_TIMESTAMP_STRUCT val, char *dst, size_t *dlen); + +TSDB_CONV_CODE tsdb_conv_chars_to_bit(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_tinyint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_smallint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int16_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_int(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int32_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_bigint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_float(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, float *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_double(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, double *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_timestamp(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, SQL_TIMESTAMP_STRUCT *dst); +TSDB_CONV_CODE tsdb_conv_chars_to_timestamp_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst); +TSDB_CONV_CODE tsdb_conv(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, const char **dst, size_t *dlen); +void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src); + + +TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst); +TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst); +TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst); +TSDB_CONV_CODE tsdb_int64_to_int(int64_t src, int32_t *dst); +TSDB_CONV_CODE tsdb_int64_to_bigint(int64_t src, int64_t *dst); +TSDB_CONV_CODE tsdb_int64_to_ts(int64_t src, int64_t *dst); +TSDB_CONV_CODE tsdb_int64_to_float(int64_t src, float *dst); +TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst); +TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen); + +TSDB_CONV_CODE tsdb_double_to_bit(double src, int8_t *dst); +TSDB_CONV_CODE tsdb_double_to_tinyint(double src, int8_t *dst); +TSDB_CONV_CODE tsdb_double_to_smallint(double src, int16_t *dst); +TSDB_CONV_CODE tsdb_double_to_int(double src, int32_t *dst); +TSDB_CONV_CODE tsdb_double_to_bigint(double src, int64_t *dst); +TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst); +TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen); + +TSDB_CONV_CODE tsdb_timestamp_to_char(SQL_TIMESTAMP_STRUCT src, char *dst, size_t dlen); + +TSDB_CONV_CODE tsdb_chars_to_bit(const char *src, size_t smax, int8_t *dst); +TSDB_CONV_CODE tsdb_chars_to_tinyint(const char *src, size_t smax, int8_t *dst); +TSDB_CONV_CODE tsdb_chars_to_smallint(const char *src, size_t smax, int16_t *dst); +TSDB_CONV_CODE tsdb_chars_to_int(const char *src, size_t smax, int32_t *dst); +TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst); +TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst); +TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst); +TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst); +TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst); +TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax); + +#endif // _todbc_conv_h_ + diff --git a/src/connector/odbc/src/todbc_flex.h b/src/connector/odbc/src/todbc_flex.h new file mode 100644 index 0000000000..a13f1f4d2e --- /dev/null +++ b/src/connector/odbc/src/todbc_flex.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _TODBC_FLEX_H_ +#define _TODBC_FLEX_H_ + +typedef struct conn_val_s conn_val_t; +struct conn_val_s { + char *key; + char *dsn; + char *uid; + char *pwd; + char *db; + char *server; + char *svr_enc; + char *cli_enc; +}; + + +void conn_val_reset(conn_val_t *val); +int todbc_parse_conn_string(const char *conn, conn_val_t *val); + +#endif // _TODBC_FLEX_H_ + diff --git a/src/connector/odbc/src/todbc_log.h b/src/connector/odbc/src/todbc_log.h new file mode 100644 index 0000000000..391a690ccc --- /dev/null +++ b/src/connector/odbc/src/todbc_log.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _todbc_log_h_ +#define _todbc_log_h_ + +#include "os.h" + +#define D(fmt, ...) \ + fprintf(stderr, \ + "%s[%d]:%s() " fmt "\n", \ + basename((char*)__FILE__), __LINE__, __func__, \ + ##__VA_ARGS__) + +#define DASSERT(statement) \ +do { \ + if (statement) break; \ + D("Assertion failure: %s", #statement); \ + abort(); \ +} while (0) + +#define DASSERTX(statement, fmt, ...) \ +do { \ + if (statement) break; \ + D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \ + abort(); \ +} while (0) + +#endif // _todbc_log_h_ + diff --git a/src/connector/odbc/src/todbc_scanner.l b/src/connector/odbc/src/todbc_scanner.l new file mode 100644 index 0000000000..f8c6a15d92 --- /dev/null +++ b/src/connector/odbc/src/todbc_scanner.l @@ -0,0 +1,165 @@ +%{ +#include "todbc_flex.h" +#include + +#ifdef _MSC_VER +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + +#define PUSH_STATE(state) yy_push_state(state, yyscanner) +#define POP_STATE() yy_pop_state(yyscanner) + +#define CHG_STATE(state) \ +do { \ + yy_pop_state(yyscanner); \ + yy_push_state(state, yyscanner); \ +} while (0) + +#define TOP_STATE(top) \ +do { \ + yy_push_state(INITIAL, yyscanner); \ + top = yy_top_state(yyscanner); \ + yy_pop_state(yyscanner); \ +} while (0) + +#define UNPUT() \ +do { \ + while (yyleng) unput(yytext[yyleng-1]); \ +} while (0) + +#define set_key() \ +do { \ + free(yyextra->key); \ + yyextra->key = strdup(yytext); \ +} while (0) + +#define set_val() \ +do { \ + if (!yyextra->key) break; \ + if (strcasecmp(yyextra->key, "DSN")==0) { \ + free(yyextra->dsn); \ + yyextra->dsn = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "UID")==0) { \ + free(yyextra->uid); \ + yyextra->uid = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "PWD")==0) { \ + free(yyextra->pwd); \ + yyextra->pwd = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "DB")==0) { \ + free(yyextra->db); \ + yyextra->pwd = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "Server")==0) { \ + free(yyextra->server); \ + yyextra->server = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "SERVER_ENC")==0) { \ + free(yyextra->svr_enc); \ + yyextra->svr_enc = strdup(yytext); \ + break; \ + } \ + if (strcasecmp(yyextra->key, "CLIENT_ENC")==0) { \ + free(yyextra->cli_enc); \ + yyextra->cli_enc = strdup(yytext); \ + break; \ + } \ +} while (0) + +%} + +%option prefix="todbc_yy" +%option extra-type="conn_val_t *" +%option nounistd +%option never-interactive +%option reentrant +%option noyywrap +%option noinput nounput +%option debug verbose +%option stack +%option nodefault +%option warn +%option perf-report +%option 8bit + +%x KEY EQ BRACE1 BRACE2 VAL + +%% +<> { int state; TOP_STATE(state); + if (state == INITIAL) yyterminate(); + if (state == VAL) yyterminate(); + return -1; } +[[:space:]]+ { } +[[:alnum:]_]+ { set_key(); PUSH_STATE(KEY); } +.|\n { return -1; } + +[[:space:]]+ { } +[=] { CHG_STATE(EQ); } +.|\n { return -1; } + +[[:space:]]+ { } +[^][{}(),;?*=!@/\\\n[:space:]]+ { set_val(); CHG_STATE(VAL); } +[{] { CHG_STATE(BRACE1); } +.|\n { return -1; } + +[^{}\n]+ { set_val(); CHG_STATE(BRACE2); } +.|\n { return -1; } + +[[:space:]]+ { } +[}] { CHG_STATE(VAL); } +.|\n { return -1; } + +[;] { POP_STATE(); } +.|\n { return -1; } +%% + +int todbc_parse_conn_string(const char *conn, conn_val_t *val) { + yyscan_t arg = {0}; + yylex_init(&arg); + yyset_debug(0, arg); + yyset_extra(val, arg); + yy_scan_string(conn, arg); + int ret =yylex(arg); + yylex_destroy(arg); + if (val->key) free(val->key); val->key = NULL; + if (ret) { + conn_val_reset(val); + } + return ret ? -1 : 0; +} + +void conn_val_reset(conn_val_t *val) { + if (val->key) { + free(val->key); val->key = NULL; + } + if (val->dsn) { + free(val->dsn); val->dsn = NULL; + } + if (val->uid) { + free(val->uid); val->uid = NULL; + } + if (val->pwd) { + free(val->pwd); val->pwd = NULL; + } + if (val->db) { + free(val->db); val->db = NULL; + } + if (val->server) { + free(val->server); val->server = NULL; + } + if (val->svr_enc) { + free(val->svr_enc); val->svr_enc = NULL; + } + if (val->cli_enc) { + free(val->cli_enc); val->cli_enc = NULL; + } +} + diff --git a/src/connector/odbc/src/todbc_util.c b/src/connector/odbc/src/todbc_util.c index b6b45d8120..9c130b4f2f 100644 --- a/src/connector/odbc/src/todbc_util.c +++ b/src/connector/odbc/src/todbc_util.c @@ -14,14 +14,10 @@ */ #include "todbc_util.h" - -#include "iconv.h" - -#include -#include +#include "todbc_log.h" +#include #include -#include -#include + const char* sql_sql_type(int type) { switch (type) { @@ -111,39 +107,6 @@ int is_valid_sql_sql_type(int type) { return 1; } -int string_conv(const char *fromcode, const char *tocode, - const unsigned char *src, size_t sbytes, - unsigned char *dst, size_t dbytes, - size_t *consumed, size_t *generated) -{ - if (consumed) *consumed = 0; - if (generated) *generated = 0; - - if (dbytes <= 0) return -1; - dst[0] = '\0'; - - iconv_t conv = iconv_open(tocode, fromcode); - if (!conv) return -1; - - int r = 0; - do { - char *s = (char*)src; - char *d = (char*)dst; - size_t sl = sbytes; - size_t dl = dbytes; - - r = iconv(conv, &s, &sl, &d, &dl); - *d = '\0'; - - if (consumed) *consumed = sbytes - sl; - if (generated) *generated = dbytes - dl; - - } while (0); - - iconv_close(conv); - return r; -} - int utf8_chars(const char *src) { const char *fromcode = "UTF-8"; @@ -161,78 +124,6 @@ int utf8_chars(const char *src) size_t chars = (sizeof(buf) - dlen) / 2; iconv_close(conv); - return chars; -} - -unsigned char* utf8_to_ucs4le(const char *utf8, size_t *chars) -{ - const char *tocode = "UCS-4LE"; - const char *fromcode = "UTF-8"; - - iconv_t conv = iconv_open(tocode, fromcode); - if (!conv) return NULL; - - unsigned char *ucs4le = NULL; - - do { - size_t slen = strlen(utf8); - size_t dlen = slen * 4; - - ucs4le = (unsigned char*)malloc(dlen+1); - if (!ucs4le) break; - - char *src = (char*)utf8; - char *dst = (char*)ucs4le; - size_t s = slen; - size_t d = dlen; - iconv(conv, &src, &s, &dst, &d); - dst[0] = '\0'; - - if (chars) *chars = (dlen - d) / 4; - } while (0); - - iconv_close(conv); - return ucs4le; -} - -char* ucs4le_to_utf8(const unsigned char *ucs4le, size_t slen, size_t *chars) -{ - const char *fromcode = "UCS-4LE"; - const char *tocode = "UTF-8"; - - iconv_t conv = iconv_open(tocode, fromcode); - if (!conv) return NULL; - - char *utf8 = NULL; - - do { - size_t dlen = slen; - - utf8 = (char*)malloc(dlen+1); - if (!utf8) break; - - char *dst = utf8; - char *src = (char*)ucs4le; - size_t s = slen; - size_t d = dlen; - iconv(conv, &src, &s, &dst, &d); - dst[0] = '\0'; - - if (chars) *chars = (slen - s) / 4; - } while (0); - - iconv_close(conv); - return utf8; -} - -SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes) -{ - size_t dlen = chs * 4; - SQLCHAR *dst = (SQLCHAR*)malloc(dlen + 1); - if (!dst) return NULL; - - string_conv("UCS-2LE", "UTF-8", (const unsigned char*)wchars, chs * sizeof(*wchars), dst, dlen + 1, NULL, bytes); - - return dst; + return (int)chars; } diff --git a/src/connector/odbc/src/todbc_util.h b/src/connector/odbc/src/todbc_util.h index 43264975b4..ead0d73489 100644 --- a/src/connector/odbc/src/todbc_util.h +++ b/src/connector/odbc/src/todbc_util.h @@ -16,33 +16,10 @@ #ifndef _TODBC_UTIL_H_ #define _TODBC_UTIL_H_ -#include -#include -#include -#include +#include "os.h" + #include - -#define D(fmt, ...) \ - fprintf(stderr, \ - "%s[%d]:%s() " fmt "\n", \ - basename((char*)__FILE__), __LINE__, __func__, \ - ##__VA_ARGS__) - -#define DASSERT(statement) \ -do { \ - if (statement) break; \ - D("Assertion failure: %s", #statement); \ - abort(); \ -} while (0) - -#define DASSERTX(statement, fmt, ...) \ -do { \ - if (statement) break; \ - D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \ - abort(); \ -} while (0) - - +#include const char* sql_sql_type(int type); const char* sql_c_type(int type); @@ -50,14 +27,7 @@ const char* sql_c_type(int type); int is_valid_sql_c_type(int type); int is_valid_sql_sql_type(int type); -int string_conv(const char *fromcode, const char *tocode, - const unsigned char *src, size_t sbytes, - unsigned char *dst, size_t dbytes, - size_t *consumed, size_t *generated); int utf8_chars(const char *src); -unsigned char* utf8_to_ucs4le(const char *utf8, size_t *chars); -char* ucs4le_to_utf8(const unsigned char *ucs4le, size_t slen, size_t *chars); -SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes); - #endif // _TODBC_UTIL_H_ + diff --git a/src/connector/odbc/tests/CMakeLists.txt b/src/connector/odbc/tests/CMakeLists.txt index ac57a5647f..1cc6acaf4b 100644 --- a/src/connector/odbc/tests/CMakeLists.txt +++ b/src/connector/odbc/tests/CMakeLists.txt @@ -1,7 +1,18 @@ PROJECT(TDengine) IF (TD_LINUX) - AUX_SOURCE_DIRECTORY(. SRC) + # AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(tcodbc main.c) TARGET_LINK_LIBRARIES(tcodbc odbc) + ADD_EXECUTABLE(tconv tconv.c) +ENDIF () + +IF (TD_WINDOWS_64) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /GL") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") + # AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(tcodbc main.c) + TARGET_LINK_LIBRARIES(tcodbc odbc32 odbccp32 user32 legacy_stdio_definitions os) + ADD_EXECUTABLE(tconv tconv.c) + TARGET_LINK_LIBRARIES(tconv tutil) ENDIF () diff --git a/src/connector/odbc/tests/create_data.stmts b/src/connector/odbc/tests/create_data.stmts new file mode 100644 index 0000000000..549cb583d8 --- /dev/null +++ b/src/connector/odbc/tests/create_data.stmts @@ -0,0 +1,12 @@ +P:drop database if exists m; +P:create database m; +P:use m; + +P:drop table if exists t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1)); +P:insert into t (ts, blob, name) values('2020-10-10 00:00:00', 0, 1); +P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.001', 1, 2); +P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.002', '你', '好'); +P:insert into t (ts, blob, name) values('2020-10-10 00:00:00.003', 'abc', 'd'); +P:select * from t; + diff --git a/src/connector/odbc/tests/main.c b/src/connector/odbc/tests/main.c index 1ac9b71369..417de00d55 100644 --- a/src/connector/odbc/tests/main.c +++ b/src/connector/odbc/tests/main.c @@ -1,14 +1,38 @@ +#include "../src/todbc_log.h" + +#ifdef _MSC_VER +#include +#include +#include "os.h" +#endif #include #include +#include #include #include -#include "os.h" +#define CHK_TEST(statement) \ +do { \ + D("testing: %s", #statement); \ + int r = (statement); \ + if (r) { \ + D("testing failed: %s", #statement); \ + return 1; \ + } \ +} while (0); -// static const char *dsn = "TAOS_DSN"; -// static const char *uid = "root"; -// static const char *pwd = "taosdata"; +typedef struct db_column_s db_column_t; +struct db_column_s { + SQLSMALLINT nameLength; + char name[4096]; // seems enough + SQLSMALLINT dataType; + SQLULEN columnSize; + SQLSMALLINT decimalDigits; + SQLSMALLINT nullable; +}; + +static db_column_t *columns = NULL; typedef struct data_s data_t; struct data_s { @@ -37,7 +61,7 @@ static const char *pro_stmts[] = { // "drop database db" }; -#define CHK_RESULT(r, ht, h) \ +#define CHK_RESULT(r, ht, h, fmt, ...) \ do { \ if (r==0) break; \ SQLCHAR ss[10]; \ @@ -48,23 +72,149 @@ do { es[0] = '\0'; \ SQLRETURN ret = SQLGetDiagRec(ht, h, 1, ss, &ne, es, sizeof(es), &n); \ if (ret) break; \ - fprintf(stderr, "%s%s\n", ss, es); \ + D("[%s]%s: " fmt "", ss, es, ##__VA_ARGS__); \ } while (0) +static int open_connect(const char *dsn, const char *uid, const char *pwd, SQLHENV *pEnv, SQLHDBC *pConn) { + SQLRETURN r; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + r = SQLAllocEnv(&env); + if (r!=SQL_SUCCESS) return 1; + do { + r = SQLAllocConnect(env, &conn); + CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); + if (r!=SQL_SUCCESS) break; + do { + r = SQLConnect(conn, (SQLCHAR*)dsn, (SQLSMALLINT)(dsn ? strlen(dsn) : 0), + (SQLCHAR*)uid, (SQLSMALLINT)(uid ? strlen(uid) : 0), + (SQLCHAR*)pwd, (SQLSMALLINT)(pwd ? strlen(pwd) : 0)); + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r==SQL_SUCCESS) { + *pEnv = env; + *pConn = conn; + return 0; + } + } while (0); + SQLFreeConnect(conn); + } while (0); + SQLFreeEnv(env); + + return 1; +} + +static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pConn) { + SQLRETURN r; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + r = SQLAllocEnv(&env); + if (r!=SQL_SUCCESS) return 1; + do { + r = SQLAllocConnect(env, &conn); + CHK_RESULT(r, SQL_HANDLE_ENV, env, ""); + if (r!=SQL_SUCCESS) break; + do { + SQLCHAR buf[4096]; + SQLSMALLINT blen = 0; + SQLHDBC ConnectionHandle = conn; + SQLHWND WindowHandle = NULL; + SQLCHAR * InConnectionString = (SQLCHAR*)connstr; + SQLSMALLINT StringLength1 = (SQLSMALLINT)(connstr ? strlen(connstr) : 0); + SQLCHAR * OutConnectionString = buf; + SQLSMALLINT BufferLength = sizeof(buf); + SQLSMALLINT * StringLength2Ptr = &blen; + SQLUSMALLINT DriverCompletion = SQL_DRIVER_NOPROMPT; + r = SQLDriverConnect(ConnectionHandle, WindowHandle, InConnectionString, + StringLength1, OutConnectionString, BufferLength, + StringLength2Ptr, DriverCompletion); + CHK_RESULT(r, SQL_HANDLE_DBC, conn, ""); + if (r==SQL_SUCCESS) { + *pEnv = env; + *pConn = conn; + return 0; + } + } while (0); + SQLFreeConnect(conn); + } while (0); + SQLFreeEnv(env); + + return 1; +} + +static SQLRETURN traverse_cols(SQLHSTMT stmt, SQLSMALLINT cols) { + SQLRETURN r = SQL_ERROR; + for (SQLSMALLINT i=0; i0) fprintf(stdout, "\n"); + return r; + } + } + if (soi==SQL_NULL_DATA) { + fprintf(stdout, "%snull", i==0?"":","); + } else { + fprintf(stdout, "%s\"%s\"", i==0?"":",", buf); + } + } + fprintf(stdout, "\n"); + } + + // r = SQLFetch(stmt); + // if (r==SQL_NO_DATA) { + // D(".........."); + // r = SQL_SUCCESS; + // break; + // } + // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + // if (r) break; + // r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement)); + // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, ""); + // if (r) break; + // r = SQLExecute(stmt); + // CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); + // if (r) break; } while (0); - fprintf(stderr, "r: [%x][%d]\n", r, r); return r; } @@ -74,158 +224,450 @@ static int do_insert(SQLHSTMT stmt, data_t data) { SQLLEN lblob; const char *statement = "insert into t values (?, ?, ?, ?, ?, ?, ?, ?, ?,?)"; - int ignored = 0; + #define ignored 0 do { - fprintf(stderr, "prepare [%s]\n", statement); - r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement)); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + r = SQLPrepare(stmt, (SQLCHAR*)statement, (SQLINTEGER)strlen(statement)); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 1 [%s]\n", statement); r = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_TIMESTAMP, ignored, ignored, &data.ts, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 2 [%s]\n", statement); r = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, ignored, ignored, &data.b, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 3 [%s]\n", statement); r = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_TINYINT, ignored, ignored, &data.v1, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 4 [%s]\n", statement); r = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, ignored, ignored, &data.v2, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 5 [%s]\n", statement); r = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, ignored, ignored, &data.v4, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 6 [%s]\n", statement); r = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, ignored, ignored, &data.v8, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 7 [%s]\n", statement); r = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, ignored, ignored, &data.f4, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 8 [%s]\n", statement); r = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, ignored, ignored, &data.f8, ignored, NULL); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 9 [%s]\n", statement); lbin = SQL_NTS; r = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sizeof(data.bin)-1, ignored, &data.bin, ignored, &lbin); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "bind 10 [%s]\n", statement); lblob = SQL_NTS; r = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(data.blob)-1, ignored, &data.blob, ignored, &lblob); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; - fprintf(stderr, "execute [%s]\n", statement); r = SQLExecute(stmt); - CHK_RESULT(r, SQL_HANDLE_STMT, stmt); + CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement); if (r) break; // ts += 1; // v = 2; - // fprintf(stderr, "execute [%s]\n", statement); // r = SQLExecute(stmt); // if (r) break; - - fprintf(stderr, "done\n"); } while (0); - fprintf(stderr, "r: [%x][%d]\n", r, r); + + #undef ignored return r; } -int main(int argc, char *argv[]) { - if (argc < 4) return 1; - const char *dsn = argv[1]; - const char *uid = argv[2]; - const char *pwd = argv[3]; - SQLRETURN r; +static int test1(const char *dsn, const char *uid, const char *pwd) { SQLHENV env = {0}; SQLHDBC conn = {0}; - r = SQLAllocEnv(&env); - if (r!=SQL_SUCCESS) return 1; + int n = open_connect(dsn, uid, pwd, &env, &conn); + if (n) return 1; + + int ok = 0; do { - r = SQLAllocConnect(env, &conn); - CHK_RESULT(r, SQL_HANDLE_ENV, env); + SQLRETURN r = SQL_SUCCESS; + SQLHSTMT stmt = {0}; + r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt); if (r!=SQL_SUCCESS) break; do { - r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn), - (SQLCHAR*)uid, strlen(uid), - (SQLCHAR*)pwd, strlen(pwd)); - CHK_RESULT(r, SQL_HANDLE_DBC, conn); - if (r!=SQL_SUCCESS) break; + if (do_statement(stmt, "drop database if exists db")) { + break; + } + for (size_t i=0; i0 && line[n-1] == '\n') line[n-1]='\0'; + if (n>0 && line[n-1] == '\r') line[n-1]='\0'; + if (n>1 && line[n-2] == '\r') line[n-2]='\0'; + p = line; + while (isspace(*p)) ++p; + + if (*p==0) break; + + int positive = 1; + if (strncmp(p, "N:", 2)==0) { + positive = 0; + p += 2; + } else if (strncmp(p, "P:", 2)==0) { + p += 2; + } + + D("statement: [%s]", p); + r = do_statement(stmt, p); + + if (positive && r==0) break; + if (!positive && r) { r = 0; break; } + if (positive) return r; + D("expecting negative result, but got positive"); + return -1; + } while (0); + + free(line); + + if (r) break; + } + + fclose(f); + return r ? 1 : 0; +} + +int test_sqls_in_conn(SQLHENV env, SQLHDBC conn, const char *sqls) { + SQLHSTMT stmt = {0}; + CHK_TEST(create_statement(env, conn, &stmt)); + int r = test_sqls_in_stmt(env, conn, stmt, sqls); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + return r ? 1 : 0; +} + +int test_sqls(const char *dsn, const char *uid, const char *pwd, const char *connstr, const char *sqls) { + int r = 0; + SQLHENV env = {0}; + SQLHDBC conn = {0}; + if (dsn) { + CHK_TEST(open_connect(dsn, uid, pwd, &env, &conn)); + } else { + CHK_TEST(open_driver_connect(connstr, &env, &conn)); + } + if (sqls) { + r = test_sqls_in_conn(env, conn, sqls); + } + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + return r ? 1 : 0; +} + +void usage(const char *arg0) { + fprintf(stdout, "%s usage:\n", arg0); + fprintf(stdout, "%s [--dsn ] [--uid ] [--pwd ] [--dcs ] [--sts ]\n", arg0); + fprintf(stdout, " --dsn : DSN\n"); + fprintf(stdout, " --uid : UID\n"); + fprintf(stdout, " --pwd : PWD\n"); + fprintf(stdout, " --dcs : driver connection string\n"); + fprintf(stdout, " --sts : file where statements store\n"); +} + +int main(int argc, char *argv[]) { + // if (argc==1) { + // CHK_TEST(test_env()); + // CHK_TEST(test1("TAOS_DSN", "root", "taoxsdata")); + // D("Done!"); + // return 0; + // } + + const char *dsn = NULL; + const char *uid = NULL; + const char *pwd = NULL; + const char *dcs = NULL; // driver connection string + const char *sts = NULL; // statements file + for (size_t i=1; i=argc) { + D(" expected but got nothing"); + return 1; + } + if (dcs) { + D("--dcs has already been specified"); + return 1; + } + dsn = argv[i]; + continue; + } + if (strcmp(arg, "--uid")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + uid = argv[i]; + continue; + } + if (strcmp(arg, "--pwd")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + pwd = argv[i]; + continue; + } + if (strcmp(arg, "--dcs")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + if (dsn || uid || pwd) { + D("either of --dsn/--uid/--pwd has already been specified"); + return 1; + } + dcs = argv[i]; + continue; + } + if (strcmp(arg, "--sts")==0) { + ++i; + if (i>=argc) { + D(" expected but got nothing"); + return 1; + } + sts = argv[i]; + continue; + } + } + CHK_TEST(test_sqls(dsn, uid, pwd, dcs, sts)); + D("Done!"); + return 0; + + if (0) { + const char *dsn = (argc>1) ? argv[1] : NULL; + const char *uid = (argc>2) ? argv[2] : NULL; + const char *pwd = (argc>3) ? argv[3] : NULL; + const char *connstr = (argc>4) ? argv[4] : NULL; + const char *sqls = (argc>5) ? argv[5] : NULL; + + dsn = NULL; + uid = NULL; + pwd = NULL; + connstr = argv[1]; + sqls = argv[2]; + if (0) { + CHK_TEST(test_env()); + + CHK_TEST(test1(dsn, uid, pwd)); + + const char *statements[] = { + "drop database if exists m", + "create database m", + "use m", + "drop database m", + NULL + }; + CHK_TEST(test_statements(dsn, uid, pwd, statements)); + + if (connstr) + CHK_TEST(test_driver_connect(connstr)); + + if (connstr) { + SQLHENV env = {0}; + SQLHDBC conn = {0}; + CHK_TEST(open_driver_connect(connstr, &env, &conn)); + int r = tests(env, conn); + SQLDisconnect(conn); + SQLFreeConnect(conn); + SQLFreeEnv(env); + if (r) return 1; + } + } + + if ((dsn || connstr) && 1) { + CHK_TEST(test_sqls(dsn, uid, pwd, connstr, sqls)); + } + + D("Done!"); + return 0; + } +} + diff --git a/src/connector/odbc/tests/odbc.py b/src/connector/odbc/tests/odbc.py index d2de8f39c6..c137905775 100644 --- a/src/connector/odbc/tests/odbc.py +++ b/src/connector/odbc/tests/odbc.py @@ -1,16 +1,17 @@ import pyodbc -cnxn = pyodbc.connect('DSN=TAOS_DSN;UID=root;PWD=taosdata', autocommit=True) +# cnxn = pyodbc.connect('DSN={TAOS_DSN};UID={ root };PWD={ taosdata };HOST={ localhost:6030 }', autocommit=True) +cnxn = pyodbc.connect('DSN={TAOS_DSN}; UID=root;PWD=taosdata; HOST=localhost:6030', autocommit=True) cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8') #cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8') #cnxn.setencoding(encoding='utf-8') -cursor = cnxn.cursor() -cursor.execute("SELECT * from db.t") -row = cursor.fetchone() -while row: - print(row) - row = cursor.fetchone() -cursor.close() +#cursor = cnxn.cursor() +#cursor.execute("SELECT * from db.t") +#row = cursor.fetchone() +#while row: +# print(row) +# row = cursor.fetchone() +#cursor.close() #cursor = cnxn.cursor() #cursor.execute(""" @@ -36,32 +37,32 @@ cursor.execute("create database db"); cursor.close() cursor = cnxn.cursor() -cursor.execute("create table db.t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))"); +cursor.execute("create table db.mt (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))"); cursor.close() cursor = cnxn.cursor() -cursor.execute("insert into db.t values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hello', 'world')") +cursor.execute("insert into db.mt values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hello', 'world')") cursor.close() cursor = cnxn.cursor() -cursor.execute("insert into db.t values(?,?,?,?,?,?,?,?,?,?)", "2020-10-13 07:06:00", 0, 127, 32767, 32768, 32769, 123.456, 789.987, "hel后lo", "wo哈rld"); +cursor.execute("insert into db.mt values(?,?,?,?,?,?,?,?,?,?)", "2020-10-13 07:06:00", 0, 127, 32767, 32768, 32769, 123.456, 789.987, "hel后lo", "wo哈rld"); cursor.close() cursor = cnxn.cursor() -cursor.execute("SELECT * from db.t") +cursor.execute("SELECT * from db.mt") row = cursor.fetchone() while row: print(row) row = cursor.fetchone() cursor.close() -cursor = cnxn.cursor() -cursor.execute("drop database if exists db"); -cursor.close() - -cursor = cnxn.cursor() -cursor.execute("create database db"); -cursor.close() +#cursor = cnxn.cursor() +#cursor.execute("drop database if exists db"); +#cursor.close() +# +#cursor = cnxn.cursor() +#cursor.execute("create database db"); +#cursor.close() cursor = cnxn.cursor() cursor.execute("create table db.t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(4), blob nchar(4))"); @@ -118,3 +119,13 @@ while row: row = cursor.fetchone() cursor.close() +cursor = cnxn.cursor() +cursor.execute("create table db.f (ts timestamp, v1 float)") +cursor.close() + +params = [ ('2020-10-20 00:00:10', '123.3') ] +cursor = cnxn.cursor() +cursor.fast_executemany = True +cursor.executemany("insert into db.f values (?, ?)", params) +cursor.close() + diff --git a/src/connector/odbc/tests/query_data.stmts b/src/connector/odbc/tests/query_data.stmts new file mode 100644 index 0000000000..b0e9ea27ea --- /dev/null +++ b/src/connector/odbc/tests/query_data.stmts @@ -0,0 +1 @@ +P:select * from m.t; diff --git a/src/connector/odbc/tests/select.stmts b/src/connector/odbc/tests/select.stmts new file mode 100644 index 0000000000..f7152ba6cf --- /dev/null +++ b/src/connector/odbc/tests/select.stmts @@ -0,0 +1,4 @@ +P: select * from db.t; +P: select * from db.f; +P: select * from db.v; +P: select * from db.mt; \ No newline at end of file diff --git a/src/connector/odbc/tests/simples.stmts b/src/connector/odbc/tests/simples.stmts new file mode 100644 index 0000000000..0db58a8807 --- /dev/null +++ b/src/connector/odbc/tests/simples.stmts @@ -0,0 +1,44 @@ +P:drop database if exists m; +P:create database m; +P:use m; + +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1)); +P:insert into t (ts, b) values('2020-10-10 00:00:00', 0); +P:insert into t (ts, b) values('2020-10-10 00:00:00.001', 1); +P:insert into t (ts, b) values('2020-10-10 00:00:00.002', 10); +P:select * from t; + +P:drop table t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1)); +P:insert into t (ts, v1) values('2020-10-10 00:00:00', 0); +P:insert into t (ts, v1) values('2020-10-10 00:00:00.001', 1); +P:insert into t (ts, v1) values('2020-10-10 00:00:00.002', 10); +P:select * from t; + +P:drop table t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1)); +P:insert into t (ts, name) values('2020-10-10 00:00:00', 0); +P:insert into t (ts, name) values('2020-10-10 00:00:00.001', 1); +P:insert into t (ts, name) values('2020-10-10 00:00:00.002', '人'); +P:insert into t (ts, name) values('2020-10-10 00:00:00.003', 'a'); +P:select * from t; + +P:drop table t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1)); +P:insert into t (ts, blob) values('2020-10-10 00:00:00', 0); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.001', 1); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.002', 'a'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.003', 'b'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.004', '人'); +P:select * from t; + +P:drop table t; +P:create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(3), name nchar(1)); +N:insert into t (ts, blob) values('2020-10-10 00:00:00', '1234'); +N:insert into t (ts, blob) values('2020-10-10 00:00:00.001', '0000'); +N:insert into t (ts, blob) values('2020-10-10 00:00:00.002', '人a'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.003', 'a'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.004', 'b'); +P:insert into t (ts, blob) values('2020-10-10 00:00:00.005', '人'); +P:select * from t; + diff --git a/src/connector/odbc/tests/tconv.c b/src/connector/odbc/tests/tconv.c new file mode 100644 index 0000000000..acae6421bb --- /dev/null +++ b/src/connector/odbc/tests/tconv.c @@ -0,0 +1,156 @@ +#include "../src/todbc_log.h" + +#ifdef _MSC_VER +#include +#include +#endif + +#include + + +#include +#include + +static void usage(const char *arg0); +static int do_conv(iconv_t cnv, FILE *fin, FILE *fout); + +int main(int argc, char *argv[]) { + const char *from_enc = "UTF-8"; + const char *to_enc = "UTF-8"; + const char *dst_file = NULL; + const char *src = NULL; +#ifdef _MSC_VER + from_enc = "CP936"; + to_enc = "CP936"; +#endif + for (int i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (strcmp(arg, "-h") == 0) { + usage(argv[0]); + return 0; + } else if (strcmp(arg, "-f") == 0 ) { + i += 1; + if (i>=argc) { + fprintf(stderr, "expecing , but got nothing\n"); + return 1; + } + from_enc = argv[i]; + continue; + } else if (strcmp(arg, "-t") == 0 ) { + i += 1; + if (i>=argc) { + fprintf(stderr, "expecing , but got nothing\n"); + return 1; + } + to_enc = argv[i]; + continue; + } else if (strcmp(arg, "-o") == 0 ) { + i += 1; + if (i>=argc) { + fprintf(stderr, "expecing , but got nothing\n"); + return 1; + } + dst_file = argv[i]; + continue; + } else if (arg[0]=='-') { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return 1; + } else { + if (src) { + fprintf(stderr, "does not allow multiple files\n"); + return 1; + } + src = arg; + continue; + } + } + int r = -1; + FILE *fin = src ? fopen(src, "rb") : stdin; + FILE *fout = dst_file ? fopen(dst_file, "wb") : stdout; + iconv_t cnv = iconv_open(to_enc, from_enc); + do { + if (!fin) { + fprintf(stderr, "failed to open file [%s]\n", src); + break; + } + if (!fout) { + fprintf(stderr, "failed to open file [%s]\n", dst_file); + break; + } +#ifdef _MSC_VER + if (fout == stdout) { + r = _setmode(_fileno(fout), _O_BINARY); + if (r == -1) { + fprintf(stderr, "Cannot set binary mode for output stream: %d[%s]\n", errno, strerror(errno)); + } + } +#endif + + if (cnv == (iconv_t)-1) { + fprintf(stderr, "failed to open conv from [%s] to [%s]: [%s]\n", from_enc, to_enc, strerror(errno)); + break; + } + r = do_conv(cnv, fin, fout); + iconv_close(cnv); + cnv = (iconv_t)-1; + } while (0); + if (fin && fin != stdin) fclose(fin); + if (fout && fout != stdout) fclose(fout); + return r ? 1 : 0; +} + +static void usage(const char *arg0) { + fprintf(stderr, "%s -h | [-f ] [-t ] [-o ] [file]\n", arg0); + return; +} + +#define IN_SIZE (64*1024) +#define OUT_SIZE (8*IN_SIZE) +static int do_conv(iconv_t cnv, FILE *fin, FILE *fout) { + int r = 0; + char src[IN_SIZE]; + size_t slen = sizeof(src); + char dst[OUT_SIZE]; + size_t dlen = sizeof(dst); + char *start = src; + while (!feof(fin)) { + slen = (size_t)(src + sizeof(src) - start); + size_t n = fread(start, 1, slen, fin); + if (n>0) { + char *ss = src; + size_t sl = n; + while (sl) { + char *dd = dst; + size_t dn = dlen; + size_t v = iconv(cnv, &ss, &sl, &dd, &dn); + if (v==(size_t)-1) { + int err = errno; + if (err == EILSEQ) { + fprintf(stderr, "failed to convert: [%s]\n", strerror(err)); + r = -1; + break; + } + if (err == EINVAL) { + fprintf(stderr, "[%s]\n", strerror(errno)); + size_t ava = (size_t)(src + sizeof(src) - ss); + memcpy(src, ss, ava); + start = ss; + } else { + fprintf(stderr, "internal logic error: [%s]\n", strerror(errno)); + r = -1; + break; + } + } + n = fwrite(dst, 1, (size_t)(dd-dst), fout); + if (n +#include +#include "os.h" +#endif +#include + +#include +#include +#include + +static void usage(const char *arg0); +static int do_install(int i, int argc, char *argv[]); +static int do_uninstall(int i, int argc, char *argv[]); + +int main(int argc, char *argv[]) { + for (int i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (strcmp(arg, "-h") == 0) { + usage(argv[0]); + return 0; + } else if (strcmp(arg, "-i") == 0 ) { + i = do_install(i + 1, argc, argv); + if (i > 0) continue; + return i == 0 ? 0 : 1; + } else if (strcmp(arg, "-u") == 0 ) { + i = do_uninstall(i + 1, argc, argv); + if (i > 0) continue; + return i == 0 ? 0 : 1; + } else { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return 1; + } + } +} + +static void usage(const char *arg0) { + fprintf(stderr, "%s -h | -i -n [TaosDriverName] -p [TaosDriverPath] | -u [-f] -n [TaosDriverName]\n", arg0); + return; +} + +static int do_install(int i, int argc, char *argv[]) { + const char* driverName = NULL; +#ifdef _MSC_VER + const char* driverFile = "todbc.dll"; +#else + const char* driverFile = "libtodbc.so"; +#endif + const char* driverPath = NULL; + for (; i < argc; ++i) { + const char *arg = argv[i]; + if (strcmp(arg, "-n") == 0) { + i += 1; + if (i >= argc) { + fprintf(stderr, "expecting TaosDriverName, but got nothing\n"); + return -1; + } + arg = argv[i]; + if (strstr(arg, "TAOS") != arg) { + fprintf(stderr, "TaosDriverName shall begin with 'TAOS': [%s]\n", arg); + return -1; + } + driverName = arg; + } else if (strcmp(arg, "-p") == 0) { + i += 1; + if (i >= argc) { + fprintf(stderr, "expecting TaosDriverPath, but got nothing\n"); + return -1; + } + driverPath = argv[i]; + } else { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return -1; + } + } + if (!driverName) { + fprintf(stderr, "TaosDriverName not specified\n"); + return -1; + } + if (!driverPath) { + fprintf(stderr, "TaosDriverPath not specified\n"); + return -1; + } + char buf[8192]; + snprintf(buf, sizeof(buf), "%s%cDriver=%s%cFileUage=0%cConnectFunctions=YYN%c", + driverName, 0, driverFile, 0, 0, 0); + BOOL ok = 1; + DWORD usageCount = 1; + char installed[PATH_MAX + 1]; + WORD len = 0; + ok = SQLInstallDriverEx(buf, driverPath, installed, sizeof(installed), &len, ODBC_INSTALL_INQUIRY, &usageCount); + if (!ok) { + fprintf(stderr, "failed to query TaosDriverName: [%s]\n", driverName); + return -1; + } + int r = 0; +#ifdef _MSC_VER + r = stricmp(driverPath, installed); +#else + r = strcasecmp(driverPath, installed); +#endif + if (r) { + fprintf(stderr, "previously installed TaosDriver [%s] has different target path [%s]\n" + "it shall be uninstalled before you can install it to different path [%s]\n", + driverName, installed, driverPath); + return -1; + } + ok = SQLInstallDriverEx(buf, driverPath, installed, sizeof(installed), &len, ODBC_INSTALL_COMPLETE, &usageCount); + if (!ok) { + fprintf(stderr, "failed to install TaosDriverName: [%s][%s]\n", driverName, driverPath); + return -1; + } + + fprintf(stderr, "ODBC driver [%s] has been installed in [%s], and UsageCount is now [%d]\n", + driverName, driverPath, usageCount); + return argc; +} + +static int do_uninstall(int i, int argc, char *argv[]) { + int forceful = 0; + const char* driverName = NULL; + for (; i < argc; ++i) { + const char *arg = argv[i]; + if (strcmp(arg, "-f") == 0) { + forceful = 1; + } else if (strcmp(arg, "-n") == 0) { + i += 1; + if (i >= argc) { + fprintf(stderr, "expecting TaosDriverName, but got nothing\n"); + return -1; + } + arg = argv[i]; + if (strstr(arg, "TAOS") != arg) { + fprintf(stderr, "TaosDriverName shall begin with 'TAOS': [%s]\n", arg); + return -1; + } + driverName = arg; + } else { + fprintf(stderr, "unknown argument: [%s]\n", arg); + return -1; + } + } + if (!driverName) { + fprintf(stderr, "TaosDriverName not specified\n"); + return -1; + } + BOOL ok = 1; + DWORD usageCount = 1; + do { + ok = SQLRemoveDriver(driverName, 0, &usageCount); + if (!ok) { + fprintf(stderr, "failed to remove driver [%s]\n", driverName); + return -1; + } + if (!forceful) { + fprintf(stderr, "UsageCount for ODBC driver [%s] is now: [%d]\n", driverName, usageCount); + return argc; + } + } while (usageCount > 0); + fprintf(stderr, "ODBC driver [%s] is now fully uninstalled\n", driverName); + return argc; +} + diff --git a/src/connector/python/linux/python2/taos/cinterface.py b/src/connector/python/linux/python2/taos/cinterface.py index 32859f6b34..269326535c 100644 --- a/src/connector/python/linux/python2/taos/cinterface.py +++ b/src/connector/python/linux/python2/taos/cinterface.py @@ -18,7 +18,7 @@ def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): _timestamp_converter = _convert_microsecond_to_datetime if num_of_rows > 0: - return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::-1])) + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::1])) else: return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)])) @@ -26,7 +26,7 @@ def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bool row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] @@ -34,7 +34,7 @@ def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C tinyint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] @@ -42,7 +42,7 @@ def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C smallint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::1]] else: return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] @@ -50,7 +50,7 @@ def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C int row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] @@ -58,7 +58,7 @@ def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bigint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)] ] @@ -66,7 +66,7 @@ def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C float row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] @@ -74,7 +74,7 @@ def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C double row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] @@ -82,7 +82,7 @@ def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C binary row to python row """ if num_of_rows > 0: - return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::1]] else: return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] @@ -311,29 +311,24 @@ class CTaosInterface(object): @staticmethod def fetchBlock(result, fields): pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - - if num_of_rows == 0: + pblock = CTaosInterface.libtaos.taos_fetch_row(result) + if pblock : + num_of_rows = 1 + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + else: return None, 0 - - isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if data == None: - blocks[i] = [None] * num_of_rows - continue - - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError("Invalid data type returned from database") - - blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) - return blocks, abs(num_of_rows) - @staticmethod def freeResult(result): CTaosInterface.libtaos.taos_free_result(result) diff --git a/src/connector/python/linux/python2/taos/cursor.py b/src/connector/python/linux/python2/taos/cursor.py index 37c02d330e..bc6670ca77 100644 --- a/src/connector/python/linux/python2/taos/cursor.py +++ b/src/connector/python/linux/python2/taos/cursor.py @@ -1,6 +1,7 @@ from .cinterface import CTaosInterface from .error import * from .constants import FieldType +import threading class TDengineCursor(object): @@ -35,6 +36,7 @@ class TDengineCursor(object): self._block_iter = 0 self._affected_rows = 0 self._logfile = "" + self._threadId = threading.get_ident() if connection is not None: self._connection = connection @@ -42,7 +44,7 @@ class TDengineCursor(object): def __iter__(self): return self - def next(self): + def __next__(self): if self._result is None or self._fields is None: raise OperationalError("Invalid use of fetch iterator") @@ -137,7 +139,7 @@ class TDengineCursor(object): else: raise ProgrammingError( CTaosInterface.errStr( - self._result ), errno) + self._result), errno) def executemany(self, operation, seq_of_parameters): """Prepare a database operation (query or command) and then execute it against all parameter sequences or mappings found in the sequence seq_of_parameters. @@ -148,6 +150,8 @@ class TDengineCursor(object): """Fetch the next row of a query result set, returning a single sequence, or None when no more data is available. """ pass + def fetchmany(self): + pass def istype(self, col, dataType): if (dataType.upper() == "BOOL"): @@ -180,9 +184,6 @@ class TDengineCursor(object): return False - def fetchmany(self): - pass - def fetchall(self): """Fetch all (remaining) rows of a query result, returning them as a sequence of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute can affect the performance of this operation. """ @@ -201,8 +202,6 @@ class TDengineCursor(object): self._rowcount += num_of_fields for i in range(len(self._fields)): buffer[i].extend(block[i]) - - return list(map(tuple, zip(*buffer))) def nextset(self): diff --git a/src/connector/python/linux/python3/taos/cinterface.py b/src/connector/python/linux/python3/taos/cinterface.py index 609154a3a4..be5b99d8c1 100644 --- a/src/connector/python/linux/python3/taos/cinterface.py +++ b/src/connector/python/linux/python3/taos/cinterface.py @@ -18,7 +18,7 @@ def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): _timestamp_converter = _convert_microsecond_to_datetime if num_of_rows > 0: - return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::-1])) + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::1])) else: return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)])) @@ -26,7 +26,7 @@ def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bool row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] @@ -34,7 +34,7 @@ def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C tinyint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] @@ -42,7 +42,7 @@ def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C smallint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::1]] else: return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] @@ -50,7 +50,7 @@ def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C int row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] @@ -58,7 +58,7 @@ def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bigint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_long))[:abs(num_of_rows)] ] @@ -66,7 +66,7 @@ def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C float row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] @@ -74,7 +74,7 @@ def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C double row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] @@ -82,7 +82,7 @@ def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C binary row to python row """ if num_of_rows > 0: - return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::1]] else: return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] @@ -111,7 +111,7 @@ def _crow_nchar_to_python(data, num_of_rows, nbytes=None, micro=False): # except ValueError: # res.append(None) # return res - # # return [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[:abs(num_of_rows)][::-1]] + # # return [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[:abs(num_of_rows)][::1]] # else: # return [ele.value for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_wchar * (nbytes//4))))[:abs(num_of_rows)]] @@ -308,32 +308,48 @@ class CTaosInterface(object): return fields + # @staticmethod + # def fetchBlock(result, fields): + # pblock = ctypes.c_void_p(0) + # num_of_rows = CTaosInterface.libtaos.taos_fetch_block( + # result, ctypes.byref(pblock)) + # if num_of_rows == 0: + # return None, 0 + + # isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + # blocks = [None] * len(fields) + # fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + # fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + # for i in range(len(fields)): + # data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + + # if fields[i]['type'] not in _CONVERT_FUNC: + # raise DatabaseError("Invalid data type returned from database") + # print('====================',fieldLen[i]) + # blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + + # return blocks, abs(num_of_rows) @staticmethod def fetchBlock(result, fields): pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - - if num_of_rows == 0: + pblock = CTaosInterface.libtaos.taos_fetch_row(result) + if pblock : + num_of_rows = 1 + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + else: return None, 0 - - isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if data == None: - blocks[i] = [None] * num_of_rows - continue - - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError("Invalid data type returned from database") - - blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) - return blocks, abs(num_of_rows) - @staticmethod def freeResult(result): CTaosInterface.libtaos.taos_free_result(result) diff --git a/src/connector/python/linux/python3/taos/cursor.py b/src/connector/python/linux/python3/taos/cursor.py index ec7a85ee1a..eb10bed485 100644 --- a/src/connector/python/linux/python3/taos/cursor.py +++ b/src/connector/python/linux/python3/taos/cursor.py @@ -216,7 +216,6 @@ class TDengineCursor(object): self._rowcount += num_of_fields for i in range(len(self._fields)): buffer[i].extend(block[i]) - return list(map(tuple, zip(*buffer))) def nextset(self): diff --git a/src/connector/python/windows/python2/taos/cinterface.py b/src/connector/python/windows/python2/taos/cinterface.py index 6a9c5bfcef..084d38e41c 100644 --- a/src/connector/python/windows/python2/taos/cinterface.py +++ b/src/connector/python/windows/python2/taos/cinterface.py @@ -18,7 +18,7 @@ def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): _timestamp_converter = _convert_microsecond_to_datetime if num_of_rows > 0: - return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1])) + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::1])) else: return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)])) @@ -26,7 +26,7 @@ def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bool row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] @@ -34,7 +34,7 @@ def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C tinyint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] @@ -42,7 +42,7 @@ def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C smallint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::1]] else: return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] @@ -50,7 +50,7 @@ def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C int row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] @@ -58,7 +58,7 @@ def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bigint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)] ] @@ -66,7 +66,7 @@ def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C float row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] @@ -74,7 +74,7 @@ def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C double row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] @@ -82,7 +82,7 @@ def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C binary row to python row """ if num_of_rows > 0: - return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::1]] else: return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] @@ -310,27 +310,23 @@ class CTaosInterface(object): @staticmethod def fetchBlock(result, fields): pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - - if num_of_rows == 0: + pblock = CTaosInterface.libtaos.taos_fetch_row(result) + if pblock : + num_of_rows = 1 + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + else: return None, 0 - - isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if data == None: - blocks[i] = [None] * num_of_rows - continue - - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError("Invalid data type returned from database") - - blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) - return blocks, abs(num_of_rows) @staticmethod diff --git a/src/connector/python/windows/python2/taos/cursor.py b/src/connector/python/windows/python2/taos/cursor.py index 8714fe77cb..35846cbe11 100644 --- a/src/connector/python/windows/python2/taos/cursor.py +++ b/src/connector/python/windows/python2/taos/cursor.py @@ -1,5 +1,9 @@ from .cinterface import CTaosInterface from .error import * +from .constants import FieldType +import threading + +# querySeqNum = 0 class TDengineCursor(object): """Database cursor which is used to manage the context of a fetch operation. @@ -32,6 +36,8 @@ class TDengineCursor(object): self._block_rows = -1 self._block_iter = 0 self._affected_rows = 0 + self._logfile = "" + self._threadId = threading.get_ident() if connection is not None: self._connection = connection @@ -39,7 +45,7 @@ class TDengineCursor(object): def __iter__(self): return self - def next(self): + def __next__(self): if self._result is None or self._fields is None: raise OperationalError("Invalid use of fetch iterator") diff --git a/src/connector/python/windows/python3/taos/cinterface.py b/src/connector/python/windows/python3/taos/cinterface.py index fa7124431c..68adf191c9 100644 --- a/src/connector/python/windows/python3/taos/cinterface.py +++ b/src/connector/python/windows/python3/taos/cinterface.py @@ -18,7 +18,7 @@ def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, micro=False): _timestamp_converter = _convert_microsecond_to_datetime if num_of_rows > 0: - return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1])) + return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::1])) else: return list(map(_timestamp_converter, ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)])) @@ -26,7 +26,7 @@ def _crow_bool_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bool row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BOOL_NULL else bool(ele) for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_bool))[:abs(num_of_rows)] ] @@ -34,7 +34,7 @@ def _crow_tinyint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C tinyint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_TINYINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_byte))[:abs(num_of_rows)] ] @@ -42,7 +42,7 @@ def _crow_smallint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C smallint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::-1]] + return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)][::1]] else: return [ None if ele == FieldType.C_SMALLINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_short))[:abs(num_of_rows)] ] @@ -50,7 +50,7 @@ def _crow_int_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C int row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_INT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_int))[:abs(num_of_rows)] ] @@ -58,7 +58,7 @@ def _crow_bigint_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C bigint row to python row """ if num_of_rows > 0: - return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::-1] ] + return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)][::1] ] else: return [ None if ele == FieldType.C_BIGINT_NULL else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_longlong))[:abs(num_of_rows)] ] @@ -66,7 +66,7 @@ def _crow_float_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C float row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_float))[:abs(num_of_rows)] ] @@ -74,7 +74,7 @@ def _crow_double_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C double row to python row """ if num_of_rows > 0: - return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::-1] ] + return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)][::1] ] else: return [ None if math.isnan(ele) else ele for ele in ctypes.cast(data, ctypes.POINTER(ctypes.c_double))[:abs(num_of_rows)] ] @@ -82,7 +82,7 @@ def _crow_binary_to_python(data, num_of_rows, nbytes=None, micro=False): """Function to convert C binary row to python row """ if num_of_rows > 0: - return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::-1]] + return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)][::1]] else: return [ None if ele.value[0:1] == FieldType.C_BINARY_NULL else ele.value.decode('utf-8') for ele in (ctypes.cast(data, ctypes.POINTER(ctypes.c_char * nbytes)))[:abs(num_of_rows)]] @@ -225,6 +225,7 @@ class CTaosInterface(object): if connection.value == None: print('connect to TDengine failed') + raise ConnectionError("connect to TDengine failed") # sys.exit(1) else: print('connect to TDengine success') @@ -310,27 +311,23 @@ class CTaosInterface(object): @staticmethod def fetchBlock(result, fields): pblock = ctypes.c_void_p(0) - num_of_rows = CTaosInterface.libtaos.taos_fetch_block( - result, ctypes.byref(pblock)) - - if num_of_rows == 0: + pblock = CTaosInterface.libtaos.taos_fetch_row(result) + if pblock : + num_of_rows = 1 + isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) + blocks = [None] * len(fields) + fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) + fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] + for i in range(len(fields)): + data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] + if fields[i]['type'] not in _CONVERT_FUNC: + raise DatabaseError("Invalid data type returned from database") + if data is None: + blocks[i] = [None] + else: + blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) + else: return None, 0 - - isMicro = (CTaosInterface.libtaos.taos_result_precision(result) == FieldType.C_TIMESTAMP_MICRO) - blocks = [None] * len(fields) - fieldL = CTaosInterface.libtaos.taos_fetch_lengths(result) - fieldLen = [ele for ele in ctypes.cast(fieldL, ctypes.POINTER(ctypes.c_int))[:len(fields)]] - for i in range(len(fields)): - data = ctypes.cast(pblock, ctypes.POINTER(ctypes.c_void_p))[i] - if data == None: - blocks[i] = [None] * num_of_rows - continue - - if fields[i]['type'] not in _CONVERT_FUNC: - raise DatabaseError("Invalid data type returned from database") - - blocks[i] = _CONVERT_FUNC[fields[i]['type']](data, num_of_rows, fieldLen[i], isMicro) - return blocks, abs(num_of_rows) @staticmethod diff --git a/src/connector/python/windows/python3/taos/cursor.py b/src/connector/python/windows/python3/taos/cursor.py index c2c442b06e..b58b494cad 100644 --- a/src/connector/python/windows/python3/taos/cursor.py +++ b/src/connector/python/windows/python3/taos/cursor.py @@ -1,5 +1,10 @@ from .cinterface import CTaosInterface from .error import * +from .constants import FieldType +import threading + +# querySeqNum = 0 + class TDengineCursor(object): """Database cursor which is used to manage the context of a fetch operation. @@ -32,6 +37,8 @@ class TDengineCursor(object): self._block_rows = -1 self._block_iter = 0 self._affected_rows = 0 + self._logfile = "" + self._threadId = threading.get_ident() if connection is not None: self._connection = connection diff --git a/src/dnode/inc/dnodeVRead.h b/src/dnode/inc/dnodeVRead.h index b3c3df80b2..5b17693146 100644 --- a/src/dnode/inc/dnodeVRead.h +++ b/src/dnode/inc/dnodeVRead.h @@ -24,7 +24,7 @@ int32_t dnodeInitVRead(); void dnodeCleanupVRead(); void dnodeDispatchToVReadQueue(SRpcMsg *pMsg); void * dnodeAllocVReadQueue(void *pVnode); -void dnodeFreeVReadQueue(void *rqueue); +void dnodeFreeVReadQueue(void *pRqueue); #ifdef __cplusplus } diff --git a/src/dnode/src/dnodeMRead.c b/src/dnode/src/dnodeMRead.c index c14c7a8158..ee9da72e4d 100644 --- a/src/dnode/src/dnodeMRead.c +++ b/src/dnode/src/dnodeMRead.c @@ -168,7 +168,8 @@ static void *dnodeProcessMReadQueue(void *param) { break; } - dDebug("%p, msg:%s will be processed in mread queue", pRead->rpcMsg.ahandle, taosMsg[pRead->rpcMsg.msgType]); + dDebug("msg:%p, app:%p type:%s will be processed in mread queue", pRead->rpcMsg.ahandle, pRead, + taosMsg[pRead->rpcMsg.msgType]); int32_t code = mnodeProcessRead(pRead); dnodeSendRpcMReadRsp(pRead, code); } diff --git a/src/dnode/src/dnodeMWrite.c b/src/dnode/src/dnodeMWrite.c index bde4b95bc6..65c0d53819 100644 --- a/src/dnode/src/dnodeMWrite.c +++ b/src/dnode/src/dnodeMWrite.c @@ -127,7 +127,7 @@ void dnodeDispatchToMWriteQueue(SRpcMsg *pMsg) { dnodeSendRedirectMsg(pMsg, true); } else { SMnodeMsg *pWrite = mnodeCreateMsg(pMsg); - dDebug("app:%p:%p, msg:%s is put into mwrite queue:%p", pWrite->rpcMsg.ahandle, pWrite, + dDebug("msg:%p, app:%p type:%s is put into mwrite queue:%p", pWrite, pWrite->rpcMsg.ahandle, taosMsg[pWrite->rpcMsg.msgType], tsMWriteQueue); taosWriteQitem(tsMWriteQueue, TAOS_QTYPE_RPC, pWrite); } @@ -136,7 +136,7 @@ void dnodeDispatchToMWriteQueue(SRpcMsg *pMsg) { } static void dnodeFreeMWriteMsg(SMnodeMsg *pWrite) { - dDebug("app:%p:%p, msg:%s is freed from mwrite queue:%p", pWrite->rpcMsg.ahandle, pWrite, + dDebug("msg:%p, app:%p type:%s is freed from mwrite queue:%p", pWrite, pWrite->rpcMsg.ahandle, taosMsg[pWrite->rpcMsg.msgType], tsMWriteQueue); mnodeCleanupMsg(pWrite); @@ -174,7 +174,7 @@ static void *dnodeProcessMWriteQueue(void *param) { break; } - dDebug("app:%p:%p, msg:%s will be processed in mwrite queue", pWrite->rpcMsg.ahandle, pWrite, + dDebug("msg:%p, app:%p type:%s will be processed in mwrite queue", pWrite, pWrite->rpcMsg.ahandle, taosMsg[pWrite->rpcMsg.msgType]); int32_t code = mnodeProcessWrite(pWrite); @@ -188,13 +188,13 @@ void dnodeReprocessMWriteMsg(void *pMsg) { SMnodeMsg *pWrite = pMsg; if (!mnodeIsRunning() || tsMWriteQueue == NULL) { - dDebug("app:%p:%p, msg:%s is redirected for mnode not running, retry times:%d", pWrite->rpcMsg.ahandle, pWrite, + dDebug("msg:%p, app:%p type:%s is redirected for mnode not running, retry times:%d", pWrite, pWrite->rpcMsg.ahandle, taosMsg[pWrite->rpcMsg.msgType], pWrite->retry); dnodeSendRedirectMsg(pMsg, true); dnodeFreeMWriteMsg(pWrite); } else { - dDebug("app:%p:%p, msg:%s is reput into mwrite queue:%p, retry times:%d", pWrite->rpcMsg.ahandle, pWrite, + dDebug("msg:%p, app:%p type:%s is reput into mwrite queue:%p, retry times:%d", pWrite, pWrite->rpcMsg.ahandle, taosMsg[pWrite->rpcMsg.msgType], tsMWriteQueue, pWrite->retry); taosWriteQitem(tsMWriteQueue, TAOS_QTYPE_RPC, pWrite); diff --git a/src/dnode/src/dnodeMgmt.c b/src/dnode/src/dnodeMgmt.c index dcb48f7833..da1852e05e 100644 --- a/src/dnode/src/dnodeMgmt.c +++ b/src/dnode/src/dnodeMgmt.c @@ -216,7 +216,7 @@ static void *dnodeProcessMgmtQueue(void *param) { } pMsg = &pMgmt->rpcMsg; - dDebug("%p, msg:%p:%s will be processed", pMsg->ahandle, pMgmt, taosMsg[pMsg->msgType]); + dDebug("msg:%p, ahandle:%p type:%s will be processed", pMgmt, pMsg->ahandle, taosMsg[pMsg->msgType]); if (dnodeProcessMgmtMsgFp[pMsg->msgType]) { rsp.code = (*dnodeProcessMgmtMsgFp[pMsg->msgType])(pMsg); } else { diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index 34df11adcc..4cce54bf59 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -35,7 +35,7 @@ typedef struct { pthread_mutex_t mutex; } SVReadWorkerPool; -static void *dnodeProcessReadQueue(void *param); +static void *dnodeProcessReadQueue(void *pWorker); // module global variable static SVReadWorkerPool tsVReadWP; @@ -47,7 +47,7 @@ int32_t dnodeInitVRead() { tsVReadWP.min = tsNumOfCores; tsVReadWP.max = tsNumOfCores * tsNumOfThreadsPerCore; if (tsVReadWP.max <= tsVReadWP.min * 2) tsVReadWP.max = 2 * tsVReadWP.min; - tsVReadWP.worker = (SVReadWorker *)calloc(sizeof(SVReadWorker), tsVReadWP.max); + tsVReadWP.worker = calloc(sizeof(SVReadWorker), tsVReadWP.max); pthread_mutex_init(&tsVReadWP.mutex, NULL); if (tsVReadWP.worker == NULL) return -1; @@ -85,7 +85,7 @@ void dnodeCleanupVRead() { void dnodeDispatchToVReadQueue(SRpcMsg *pMsg) { int32_t queuedMsgNum = 0; int32_t leftLen = pMsg->contLen; - char * pCont = (char *)pMsg->pCont; + char * pCont = pMsg->pCont; while (leftLen > 0) { SMsgHead *pHead = (SMsgHead *)pCont; @@ -146,8 +146,8 @@ void *dnodeAllocVReadQueue(void *pVnode) { return queue; } -void dnodeFreeVReadQueue(void *rqueue) { - taosCloseQueue(rqueue); +void dnodeFreeVReadQueue(void *pRqueue) { + taosCloseQueue(pRqueue); } void dnodeSendRpcVReadRsp(void *pVnode, SVReadMsg *pRead, int32_t code) { @@ -159,14 +159,12 @@ void dnodeSendRpcVReadRsp(void *pVnode, SVReadMsg *pRead, int32_t code) { }; rpcSendResponse(&rpcRsp); - vnodeRelease(pVnode); } void dnodeDispatchNonRspMsg(void *pVnode, SVReadMsg *pRead, int32_t code) { - vnodeRelease(pVnode); } -static void *dnodeProcessReadQueue(void *param) { +static void *dnodeProcessReadQueue(void *pWorker) { SVReadMsg *pRead; int32_t qtype; void * pVnode; @@ -177,7 +175,7 @@ static void *dnodeProcessReadQueue(void *param) { break; } - dDebug("%p, msg:%p:%s will be processed in vread queue, qtype:%d", pRead->rpcAhandle, pRead, + dDebug("msg:%p, app:%p type:%s will be processed in vread queue, qtype:%d", pRead, pRead->rpcAhandle, taosMsg[pRead->msgType], qtype); int32_t code = vnodeProcessRead(pVnode, pRead); @@ -193,7 +191,7 @@ static void *dnodeProcessReadQueue(void *param) { } } - taosFreeQitem(pRead); + vnodeFreeFromRQueue(pVnode, pRead); } return NULL; diff --git a/src/dnode/src/dnodeVWrite.c b/src/dnode/src/dnodeVWrite.c index da1a902fb3..959eb3c9c5 100644 --- a/src/dnode/src/dnodeVWrite.c +++ b/src/dnode/src/dnodeVWrite.c @@ -205,8 +205,8 @@ static void *dnodeProcessVWriteQueue(void *wparam) { bool forceFsync = false; for (int32_t i = 0; i < numOfMsgs; ++i) { taosGetQitem(pWorker->qall, &qtype, (void **)&pWrite); - dTrace("%p, msg:%p:%s will be processed in vwrite queue, qtype:%s hver:%" PRIu64, pWrite->rpcAhandle, pWrite, - taosMsg[pWrite->pHead->msgType], qtypeStr[qtype], pWrite->pHead->version); + dTrace("msg:%p, app:%p type:%s will be processed in vwrite queue, qtype:%s hver:%" PRIu64, pWrite, + pWrite->rpcAhandle, taosMsg[pWrite->pHead->msgType], qtypeStr[qtype], pWrite->pHead->version); pWrite->code = vnodeProcessWrite(pVnode, pWrite->pHead, qtype, &pWrite->rspRet); if (pWrite->code <= 0) pWrite->processedCount = 1; diff --git a/src/inc/dnode.h b/src/inc/dnode.h index d71fdd5e0a..eef4490800 100644 --- a/src/inc/dnode.h +++ b/src/inc/dnode.h @@ -57,7 +57,7 @@ void *dnodeAllocVWriteQueue(void *pVnode); void dnodeFreeVWriteQueue(void *pWqueue); void dnodeSendRpcVWriteRsp(void *pVnode, void *pWrite, int32_t code); void *dnodeAllocVReadQueue(void *pVnode); -void dnodeFreeVReadQueue(void *rqueue); +void dnodeFreeVReadQueue(void *pRqueue); int32_t dnodeAllocateMPeerQueue(); void dnodeFreeMPeerQueue(); diff --git a/src/inc/taos.h b/src/inc/taos.h index 2c6454ced1..cd863587a6 100644 --- a/src/inc/taos.h +++ b/src/inc/taos.h @@ -17,6 +17,7 @@ #define TDENGINE_TAOS_H #include +#include #ifdef __cplusplus extern "C" { @@ -109,13 +110,14 @@ DLL_EXPORT TAOS_RES *taos_query(TAOS *taos, const char *sql); 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 void taos_free_result(TAOS_RES *res); -DLL_EXPORT int taos_field_count(TAOS_RES *tres); +DLL_EXPORT int taos_field_count(TAOS_RES *res); DLL_EXPORT int taos_num_fields(TAOS_RES *res); DLL_EXPORT int taos_affected_rows(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_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields); DLL_EXPORT void taos_stop_query(TAOS_RES *res); +DLL_EXPORT bool taos_is_null(TAOS_RES *res, int32_t row, int32_t col); int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows); int taos_validate_sql(TAOS *taos, const char *sql); diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 1aa9095b30..ff91989e5f 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -24,9 +24,9 @@ extern "C" { #include #ifdef TAOS_ERROR_C -#define TAOS_DEFINE_ERROR(name, mod, code, msg) {.val = (0x80000000 | ((mod)<<16) | (code)), .str=(msg)}, +#define TAOS_DEFINE_ERROR(name, mod, code, msg) {.val = (int32_t)((0x80000000 | ((mod)<<16) | (code))), .str=(msg)}, #else -#define TAOS_DEFINE_ERROR(name, mod, code, msg) static const int32_t name = (0x80000000 | ((mod)<<16) | (code)); +#define TAOS_DEFINE_ERROR(name, mod, code, msg) static const int32_t name = (int32_t)((0x80000000 | ((mod)<<16) | (code))); #endif #define TAOS_SYSTEM_ERROR(code) (0x80ff0000 | (code)) @@ -107,6 +107,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_CONN_KILLED, 0, 0x0215, "Connection TAOS_DEFINE_ERROR(TSDB_CODE_TSC_SQL_SYNTAX_ERROR, 0, 0x0216, "Syntax error in SQL") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DB_NOT_SELECTED, 0, 0x0217, "Database not specified or available") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TABLE_NAME, 0, 0x0218, "Table does not exist") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_EXCEED_SQL_LIMIT, 0, 0x0219, "SQL statement too long, check maxSQLLength config") // mnode TAOS_DEFINE_ERROR(TSDB_CODE_MND_MSG_NOT_PROCESSED, 0, 0x0300, "Message not processed") @@ -365,20 +366,28 @@ TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_NULL, 0, 0x11A5, "value not TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_TYPE, 0, 0x11A6, "value type should be boolean, number or string") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, 0, 0x2101, "out of memory") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, 0, 0x2100, "out of memory") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, 0, 0x2101, "convertion not a valid literal input") TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_UNDEF, 0, 0x2102, "convertion undefined") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC, 0, 0x2103, "convertion truncated") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_SUPPORT, 0, 0x2104, "convertion not supported") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OUT_OF_RANGE, 0, 0x2105, "out of range") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NOT_SUPPORT, 0, 0x2106, "not supported yet") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_HANDLE, 0, 0x2107, "invalid handle") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_RESULT, 0, 0x2108, "no result set") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_FIELDS, 0, 0x2109, "no fields returned") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_CURSOR, 0, 0x2110, "invalid cursor") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_STATEMENT_NOT_READY, 0, 0x2111, "statement not ready") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONNECTION_BUSY, 0, 0x2112, "connection still busy") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_CONNSTR, 0, 0x2113, "bad connection string") -TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_ARG, 0, 0x2114, "bad argument") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC_FRAC, 0, 0x2103, "convertion fractional truncated") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC, 0, 0x2104, "convertion truncated") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_SUPPORT, 0, 0x2105, "convertion not supported") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_OOR, 0, 0x2106, "convertion numeric value out of range") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OUT_OF_RANGE, 0, 0x2107, "out of range") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NOT_SUPPORT, 0, 0x2108, "not supported yet") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_HANDLE, 0, 0x2109, "invalid handle") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_RESULT, 0, 0x210a, "no result set") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_FIELDS, 0, 0x210b, "no fields returned") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_CURSOR, 0, 0x210c, "invalid cursor") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_STATEMENT_NOT_READY, 0, 0x210d, "statement not ready") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONNECTION_BUSY, 0, 0x210e, "connection still busy") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_CONNSTR, 0, 0x210f, "bad connection string") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_ARG, 0, 0x2110, "bad argument") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_VALID_TS, 0, 0x2111, "not a valid timestamp") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_SRC_TOO_LARGE, 0, 0x2112, "src too large") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_SRC_BAD_SEQ, 0, 0x2113, "src bad sequence") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_SRC_INCOMPLETE, 0, 0x2114, "src incomplete") +TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_SRC_GENERAL, 0, 0x2115, "src general") #ifdef TAOS_ERROR_C diff --git a/src/inc/tsync.h b/src/inc/tsync.h index d57433eba9..967b254992 100644 --- a/src/inc/tsync.h +++ b/src/inc/tsync.h @@ -24,18 +24,18 @@ extern "C" { #define TAOS_SYNC_MAX_INDEX 0x7FFFFFFF typedef enum _TAOS_SYNC_ROLE { - TAOS_SYNC_ROLE_OFFLINE, - TAOS_SYNC_ROLE_UNSYNCED, - TAOS_SYNC_ROLE_SYNCING, - TAOS_SYNC_ROLE_SLAVE, - TAOS_SYNC_ROLE_MASTER, + TAOS_SYNC_ROLE_OFFLINE = 0, + TAOS_SYNC_ROLE_UNSYNCED = 1, + TAOS_SYNC_ROLE_SYNCING = 2, + TAOS_SYNC_ROLE_SLAVE = 3, + TAOS_SYNC_ROLE_MASTER = 4 } ESyncRole; typedef enum _TAOS_SYNC_STATUS { - TAOS_SYNC_STATUS_INIT, - TAOS_SYNC_STATUS_START, - TAOS_SYNC_STATUS_FILE, - TAOS_SYNC_STATUS_CACHE, + TAOS_SYNC_STATUS_INIT = 0, + TAOS_SYNC_STATUS_START = 1, + TAOS_SYNC_STATUS_FILE = 2, + TAOS_SYNC_STATUS_CACHE = 3 } ESyncStatus; typedef struct { diff --git a/src/inc/vnode.h b/src/inc/vnode.h index 563d035898..4e8389498b 100644 --- a/src/inc/vnode.h +++ b/src/inc/vnode.h @@ -23,12 +23,12 @@ extern "C" { #include "twal.h" typedef enum _VN_STATUS { - TAOS_VN_STATUS_INIT, - TAOS_VN_STATUS_READY, - TAOS_VN_STATUS_CLOSING, - TAOS_VN_STATUS_UPDATING, - TAOS_VN_STATUS_RESET, -} EVnStatus; + TAOS_VN_STATUS_INIT = 0, + TAOS_VN_STATUS_READY = 1, + TAOS_VN_STATUS_CLOSING = 2, + TAOS_VN_STATUS_UPDATING = 3, + TAOS_VN_STATUS_RESET = 4, +} EVnodeStatus; typedef struct { int32_t len; @@ -81,7 +81,8 @@ void vnodeSetAccess(SVgroupAccess *pAccess, int32_t numOfVnodes); int32_t vnodeInitResources(); void vnodeCleanupResources(); -int32_t vnodeWriteToRQueue(void *vparam, void *pCont, int32_t contLen, int8_t qtype, void *rparam); +int32_t vnodeWriteToRQueue(void *pVnode, void *pCont, int32_t contLen, int8_t qtype, void *rparam); +void vnodeFreeFromRQueue(void *pVnode, SVReadMsg *pRead); int32_t vnodeProcessRead(void *pVnode, SVReadMsg *pRead); #ifdef __cplusplus diff --git a/src/mnode/inc/mnodeSdb.h b/src/mnode/inc/mnodeSdb.h index f4854f69a0..29d8cf1207 100644 --- a/src/mnode/inc/mnodeSdb.h +++ b/src/mnode/inc/mnodeSdb.h @@ -20,7 +20,8 @@ extern "C" { #endif -struct SMnodeMsg; +#include "mnode.h" +#include "twal.h" typedef enum { SDB_TABLE_CLUSTER = 0, @@ -36,44 +37,46 @@ typedef enum { } ESdbTable; typedef enum { - SDB_KEY_STRING, - SDB_KEY_INT, - SDB_KEY_AUTO, - SDB_KEY_VAR_STRING, + SDB_KEY_STRING = 0, + SDB_KEY_INT = 1, + SDB_KEY_AUTO = 2, + SDB_KEY_VAR_STRING = 3, } ESdbKey; typedef enum { - SDB_OPER_GLOBAL, - SDB_OPER_LOCAL + SDB_OPER_GLOBAL = 0, + SDB_OPER_LOCAL = 1 } ESdbOper; -typedef struct SSdbOper { - ESdbOper type; - int32_t rowSize; - int32_t retCode; // for callback in sdb queue - int32_t processedCount; // for sync fwd callback - int32_t (*reqFp)(struct SMnodeMsg *pMsg); - int32_t (*writeCb)(struct SMnodeMsg *pMsg, int32_t code); - void * table; - void * pObj; - void * rowData; - struct SMnodeMsg *pMsg; -} SSdbOper; +typedef struct SSdbRow { + ESdbOper type; + int32_t processedCount; // for sync fwd callback + int32_t code; // for callback in sdb queue + int32_t rowSize; + void * rowData; + void * pObj; + void * pTable; + SMnodeMsg *pMsg; + int32_t (*fpReq)(SMnodeMsg *pMsg); + int32_t (*fpRsp)(SMnodeMsg *pMsg, int32_t code); + char reserveForSync[16]; + SWalHead pHead[]; +} SSdbRow; typedef struct { - char *tableName; - int32_t hashSessions; - int32_t maxRowSize; - int32_t refCountPos; - ESdbTable tableId; + char * name; + int32_t hashSessions; + int32_t maxRowSize; + int32_t refCountPos; + ESdbTable id; ESdbKey keyType; - int32_t (*insertFp)(SSdbOper *pOper); - int32_t (*deleteFp)(SSdbOper *pOper); - int32_t (*updateFp)(SSdbOper *pOper); - int32_t (*encodeFp)(SSdbOper *pOper); - int32_t (*decodeFp)(SSdbOper *pDesc); - int32_t (*destroyFp)(SSdbOper *pDesc); - int32_t (*restoredFp)(); + int32_t (*fpInsert)(SSdbRow *pRow); + int32_t (*fpDelete)(SSdbRow *pRow); + int32_t (*fpUpdate)(SSdbRow *pRow); + int32_t (*fpEncode)(SSdbRow *pRow); + int32_t (*fpDecode)(SSdbRow *pRow); + int32_t (*fpDestroy)(SSdbRow *pRow); + int32_t (*fpRestored)(); } SSdbTableDesc; int32_t sdbInit(); @@ -84,20 +87,20 @@ bool sdbIsMaster(); bool sdbIsServing(); void sdbUpdateMnodeRoles(); -int32_t sdbInsertRow(SSdbOper *pOper); -int32_t sdbDeleteRow(SSdbOper *pOper); -int32_t sdbUpdateRow(SSdbOper *pOper); -int32_t sdbInsertRowImp(SSdbOper *pOper); +int32_t sdbInsertRow(SSdbRow *pRow); +int32_t sdbDeleteRow(SSdbRow *pRow); +int32_t sdbUpdateRow(SSdbRow *pRow); +int32_t sdbInsertRowToQueue(SSdbRow *pRow); -void *sdbGetRow(void *handle, void *key); -void *sdbFetchRow(void *handle, void *pIter, void **ppRow); +void *sdbGetRow(void *pTable, void *key); +void *sdbFetchRow(void *pTable, void *pIter, void **ppRow); void sdbFreeIter(void *pIter); -void sdbIncRef(void *thandle, void *pRow); -void sdbDecRef(void *thandle, void *pRow); -int64_t sdbGetNumOfRows(void *handle); -int32_t sdbGetId(void *handle); +void sdbIncRef(void *pTable, void *pRow); +void sdbDecRef(void *pTable, void *pRow); +int64_t sdbGetNumOfRows(void *pTable); +int32_t sdbGetId(void *pTable); uint64_t sdbGetVersion(); -bool sdbCheckRowDeleted(void *thandle, void *pRow); +bool sdbCheckRowDeleted(void *pTable, void *pRow); #ifdef __cplusplus } diff --git a/src/mnode/src/mnodeAcct.c b/src/mnode/src/mnodeAcct.c index 365cf656de..9fff2f0229 100644 --- a/src/mnode/src/mnodeAcct.c +++ b/src/mnode/src/mnodeAcct.c @@ -16,6 +16,7 @@ #define _DEFAULT_SOURCE #include "os.h" #include "taoserror.h" +#include "tglobal.h" #include "dnode.h" #include "mnodeDef.h" #include "mnodeInt.h" @@ -25,36 +26,34 @@ #include "mnodeUser.h" #include "mnodeVgroup.h" -#include "tglobal.h" - void * tsAcctSdb = NULL; static int32_t tsAcctUpdateSize; static int32_t mnodeCreateRootAcct(); -static int32_t mnodeAcctActionDestroy(SSdbOper *pOper) { - SAcctObj *pAcct = pOper->pObj; +static int32_t mnodeAcctActionDestroy(SSdbRow *pRow) { + SAcctObj *pAcct = pRow->pObj; pthread_mutex_destroy(&pAcct->mutex); - tfree(pOper->pObj); + tfree(pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t mnodeAcctActionInsert(SSdbOper *pOper) { - SAcctObj *pAcct = pOper->pObj; +static int32_t mnodeAcctActionInsert(SSdbRow *pRow) { + SAcctObj *pAcct = pRow->pObj; memset(&pAcct->acctInfo, 0, sizeof(SAcctInfo)); pAcct->acctInfo.accessState = TSDB_VN_ALL_ACCCESS; pthread_mutex_init(&pAcct->mutex, NULL); return TSDB_CODE_SUCCESS; } -static int32_t mnodeAcctActionDelete(SSdbOper *pOper) { - SAcctObj *pAcct = pOper->pObj; +static int32_t mnodeAcctActionDelete(SSdbRow *pRow) { + SAcctObj *pAcct = pRow->pObj; mnodeDropAllUsers(pAcct); mnodeDropAllDbs(pAcct); return TSDB_CODE_SUCCESS; } -static int32_t mnodeAcctActionUpdate(SSdbOper *pOper) { - SAcctObj *pAcct = pOper->pObj; +static int32_t mnodeAcctActionUpdate(SSdbRow *pRow) { + SAcctObj *pAcct = pRow->pObj; SAcctObj *pSaved = mnodeGetAcct(pAcct->user); if (pAcct != pSaved) { memcpy(pSaved, pAcct, tsAcctUpdateSize); @@ -64,19 +63,19 @@ static int32_t mnodeAcctActionUpdate(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeAcctActionEncode(SSdbOper *pOper) { - SAcctObj *pAcct = pOper->pObj; - memcpy(pOper->rowData, pAcct, tsAcctUpdateSize); - pOper->rowSize = tsAcctUpdateSize; +static int32_t mnodeAcctActionEncode(SSdbRow *pRow) { + SAcctObj *pAcct = pRow->pObj; + memcpy(pRow->rowData, pAcct, tsAcctUpdateSize); + pRow->rowSize = tsAcctUpdateSize; return TSDB_CODE_SUCCESS; } -static int32_t mnodeAcctActionDecode(SSdbOper *pOper) { +static int32_t mnodeAcctActionDecode(SSdbRow *pRow) { SAcctObj *pAcct = (SAcctObj *) calloc(1, sizeof(SAcctObj)); if (pAcct == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - memcpy(pAcct, pOper->rowData, tsAcctUpdateSize); - pOper->pObj = pAcct; + memcpy(pAcct, pRow->rowData, tsAcctUpdateSize); + pRow->pObj = pAcct; return TSDB_CODE_SUCCESS; } @@ -99,29 +98,29 @@ int32_t mnodeInitAccts() { SAcctObj tObj; tsAcctUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; - SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_ACCOUNT, - .tableName = "accounts", + SSdbTableDesc desc = { + .id = SDB_TABLE_ACCOUNT, + .name = "accounts", .hashSessions = TSDB_DEFAULT_ACCOUNTS_HASH_SIZE, .maxRowSize = tsAcctUpdateSize, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_STRING, - .insertFp = mnodeAcctActionInsert, - .deleteFp = mnodeAcctActionDelete, - .updateFp = mnodeAcctActionUpdate, - .encodeFp = mnodeAcctActionEncode, - .decodeFp = mnodeAcctActionDecode, - .destroyFp = mnodeAcctActionDestroy, - .restoredFp = mnodeAcctActionRestored + .fpInsert = mnodeAcctActionInsert, + .fpDelete = mnodeAcctActionDelete, + .fpUpdate = mnodeAcctActionUpdate, + .fpEncode = mnodeAcctActionEncode, + .fpDecode = mnodeAcctActionDecode, + .fpDestroy = mnodeAcctActionDestroy, + .fpRestored = mnodeAcctActionRestored }; - tsAcctSdb = sdbOpenTable(&tableDesc); + tsAcctSdb = sdbOpenTable(&desc); if (tsAcctSdb == NULL) { - mError("table:%s, failed to create hash", tableDesc.tableName); + mError("table:%s, failed to create hash", desc.name); return -1; } - mDebug("table:%s, hash is created", tableDesc.tableName); + mDebug("table:%s, hash is created", desc.name); return TSDB_CODE_SUCCESS; } @@ -226,13 +225,13 @@ static int32_t mnodeCreateRootAcct() { pAcct->acctId = sdbGetId(tsAcctSdb); pAcct->createdTime = taosGetTimestampMs(); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsAcctSdb, - .pObj = pAcct, + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsAcctSdb, + .pObj = pAcct, }; - return sdbInsertRow(&oper); + return sdbInsertRow(&row); } #ifndef _ACCT diff --git a/src/mnode/src/mnodeCluster.c b/src/mnode/src/mnodeCluster.c index 98587cf53d..5be67e4ad9 100644 --- a/src/mnode/src/mnodeCluster.c +++ b/src/mnode/src/mnodeCluster.c @@ -32,36 +32,36 @@ static int32_t mnodeCreateCluster(); static int32_t mnodeGetClusterMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn); static int32_t mnodeRetrieveClusters(SShowObj *pShow, char *data, int32_t rows, void *pConn); -static int32_t mnodeClusterActionDestroy(SSdbOper *pOper) { - tfree(pOper->pObj); +static int32_t mnodeClusterActionDestroy(SSdbRow *pRow) { + tfree(pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t mnodeClusterActionInsert(SSdbOper *pOper) { +static int32_t mnodeClusterActionInsert(SSdbRow *pRow) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeClusterActionDelete(SSdbOper *pOper) { +static int32_t mnodeClusterActionDelete(SSdbRow *pRow) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeClusterActionUpdate(SSdbOper *pOper) { +static int32_t mnodeClusterActionUpdate(SSdbRow *pRow) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeClusterActionEncode(SSdbOper *pOper) { - SClusterObj *pCluster = pOper->pObj; - memcpy(pOper->rowData, pCluster, tsClusterUpdateSize); - pOper->rowSize = tsClusterUpdateSize; +static int32_t mnodeClusterActionEncode(SSdbRow *pRow) { + SClusterObj *pCluster = pRow->pObj; + memcpy(pRow->rowData, pCluster, tsClusterUpdateSize); + pRow->rowSize = tsClusterUpdateSize; return TSDB_CODE_SUCCESS; } -static int32_t mnodeClusterActionDecode(SSdbOper *pOper) { +static int32_t mnodeClusterActionDecode(SSdbRow *pRow) { SClusterObj *pCluster = (SClusterObj *) calloc(1, sizeof(SClusterObj)); if (pCluster == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - memcpy(pCluster, pOper->rowData, tsClusterUpdateSize); - pOper->pObj = pCluster; + memcpy(pCluster, pRow->rowData, tsClusterUpdateSize); + pRow->pObj = pCluster; return TSDB_CODE_SUCCESS; } @@ -84,32 +84,32 @@ int32_t mnodeInitCluster() { SClusterObj tObj; tsClusterUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; - SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_CLUSTER, - .tableName = "cluster", + SSdbTableDesc desc = { + .id = SDB_TABLE_CLUSTER, + .name = "cluster", .hashSessions = TSDB_DEFAULT_CLUSTER_HASH_SIZE, .maxRowSize = tsClusterUpdateSize, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_STRING, - .insertFp = mnodeClusterActionInsert, - .deleteFp = mnodeClusterActionDelete, - .updateFp = mnodeClusterActionUpdate, - .encodeFp = mnodeClusterActionEncode, - .decodeFp = mnodeClusterActionDecode, - .destroyFp = mnodeClusterActionDestroy, - .restoredFp = mnodeClusterActionRestored + .fpInsert = mnodeClusterActionInsert, + .fpDelete = mnodeClusterActionDelete, + .fpUpdate = mnodeClusterActionUpdate, + .fpEncode = mnodeClusterActionEncode, + .fpDecode = mnodeClusterActionDecode, + .fpDestroy = mnodeClusterActionDestroy, + .fpRestored = mnodeClusterActionRestored }; - tsClusterSdb = sdbOpenTable(&tableDesc); + tsClusterSdb = sdbOpenTable(&desc); if (tsClusterSdb == NULL) { - mError("table:%s, failed to create hash", tableDesc.tableName); + mError("table:%s, failed to create hash", desc.name); return -1; } mnodeAddShowMetaHandle(TSDB_MGMT_TABLE_CLUSTER, mnodeGetClusterMeta); mnodeAddShowRetrieveHandle(TSDB_MGMT_TABLE_CLUSTER, mnodeRetrieveClusters); - mDebug("table:%s, hash is created", tableDesc.tableName); + mDebug("table:%s, hash is created", desc.name); return TSDB_CODE_SUCCESS; } @@ -145,13 +145,13 @@ static int32_t mnodeCreateCluster() { mDebug("uid is %s", pCluster->uid); } - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsClusterSdb, - .pObj = pCluster, + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsClusterSdb, + .pObj = pCluster, }; - return sdbInsertRow(&oper); + return sdbInsertRow(&row); } const char* mnodeGetClusterId() { diff --git a/src/mnode/src/mnodeDb.c b/src/mnode/src/mnodeDb.c index 3b3a21aeb1..d121208447 100644 --- a/src/mnode/src/mnodeDb.c +++ b/src/mnode/src/mnodeDb.c @@ -56,8 +56,8 @@ static void mnodeDestroyDb(SDbObj *pDb) { tfree(pDb); } -static int32_t mnodeDbActionDestroy(SSdbOper *pOper) { - mnodeDestroyDb(pOper->pObj); +static int32_t mnodeDbActionDestroy(SSdbRow *pRow) { + mnodeDestroyDb(pRow->pObj); return TSDB_CODE_SUCCESS; } @@ -65,8 +65,8 @@ int64_t mnodeGetDbNum() { return sdbGetNumOfRows(tsDbSdb); } -static int32_t mnodeDbActionInsert(SSdbOper *pOper) { - SDbObj *pDb = pOper->pObj; +static int32_t mnodeDbActionInsert(SSdbRow *pRow) { + SDbObj *pDb = pRow->pObj; SAcctObj *pAcct = mnodeGetAcct(pDb->acct); pthread_mutex_init(&pDb->mutex, NULL); @@ -91,8 +91,8 @@ static int32_t mnodeDbActionInsert(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeDbActionDelete(SSdbOper *pOper) { - SDbObj *pDb = pOper->pObj; +static int32_t mnodeDbActionDelete(SSdbRow *pRow) { + SDbObj *pDb = pRow->pObj; SAcctObj *pAcct = mnodeGetAcct(pDb->acct); mnodeDropAllChildTables(pDb); @@ -107,11 +107,11 @@ static int32_t mnodeDbActionDelete(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeDbActionUpdate(SSdbOper *pOper) { - SDbObj *pNew = pOper->pObj; +static int32_t mnodeDbActionUpdate(SSdbRow *pRow) { + SDbObj *pNew = pRow->pObj; SDbObj *pDb = mnodeGetDb(pNew->name); if (pDb != NULL && pNew != pDb) { - memcpy(pDb, pNew, pOper->rowSize); + memcpy(pDb, pNew, pRow->rowSize); free(pNew->vgList); free(pNew); } @@ -120,19 +120,19 @@ static int32_t mnodeDbActionUpdate(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeDbActionEncode(SSdbOper *pOper) { - SDbObj *pDb = pOper->pObj; - memcpy(pOper->rowData, pDb, tsDbUpdateSize); - pOper->rowSize = tsDbUpdateSize; +static int32_t mnodeDbActionEncode(SSdbRow *pRow) { + SDbObj *pDb = pRow->pObj; + memcpy(pRow->rowData, pDb, tsDbUpdateSize); + pRow->rowSize = tsDbUpdateSize; return TSDB_CODE_SUCCESS; } -static int32_t mnodeDbActionDecode(SSdbOper *pOper) { +static int32_t mnodeDbActionDecode(SSdbRow *pRow) { SDbObj *pDb = (SDbObj *) calloc(1, sizeof(SDbObj)); if (pDb == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - memcpy(pDb, pOper->rowData, tsDbUpdateSize); - pOper->pObj = pDb; + memcpy(pDb, pRow->rowData, tsDbUpdateSize); + pRow->pObj = pDb; return TSDB_CODE_SUCCESS; } @@ -144,23 +144,23 @@ int32_t mnodeInitDbs() { SDbObj tObj; tsDbUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; - SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_DB, - .tableName = "dbs", + SSdbTableDesc desc = { + .id = SDB_TABLE_DB, + .name = "dbs", .hashSessions = TSDB_DEFAULT_DBS_HASH_SIZE, .maxRowSize = tsDbUpdateSize, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_STRING, - .insertFp = mnodeDbActionInsert, - .deleteFp = mnodeDbActionDelete, - .updateFp = mnodeDbActionUpdate, - .encodeFp = mnodeDbActionEncode, - .decodeFp = mnodeDbActionDecode, - .destroyFp = mnodeDbActionDestroy, - .restoredFp = mnodeDbActionRestored + .fpInsert = mnodeDbActionInsert, + .fpDelete = mnodeDbActionDelete, + .fpUpdate = mnodeDbActionUpdate, + .fpEncode = mnodeDbActionEncode, + .fpDecode = mnodeDbActionDecode, + .fpDestroy = mnodeDbActionDestroy, + .fpRestored = mnodeDbActionRestored }; - tsDbSdb = sdbOpenTable(&tableDesc); + tsDbSdb = sdbOpenTable(&desc); if (tsDbSdb == NULL) { mError("failed to init db data"); return -1; @@ -412,16 +412,16 @@ static int32_t mnodeCreateDb(SAcctObj *pAcct, SCreateDbMsg *pCreate, SMnodeMsg * pMsg->pDb = pDb; mnodeIncDbRef(pDb); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsDbSdb, - .pObj = pDb, - .rowSize = sizeof(SDbObj), - .pMsg = pMsg, - .writeCb = mnodeCreateDbCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsDbSdb, + .pObj = pDb, + .rowSize = sizeof(SDbObj), + .pMsg = pMsg, + .fpRsp = mnodeCreateDbCb }; - code = sdbInsertRow(&oper); + code = sdbInsertRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("db:%s, failed to create, reason:%s", pDb->name, tstrerror(code)); pMsg->pDb = NULL; @@ -440,8 +440,8 @@ bool mnodeCheckIsMonitorDB(char *db, char *monitordb) { } #if 0 -void mnodePrintVgroups(SDbObj *pDb, char *oper) { - mInfo("db:%s, vgroup link from head, oper:%s", pDb->name, oper); +void mnodePrintVgroups(SDbObj *pDb, char *row) { + mInfo("db:%s, vgroup link from head, row:%s", pDb->name, row); SVgObj *pVgroup = pDb->pHead; while (pVgroup != NULL) { mInfo("vgId:%d", pVgroup->vgId); @@ -807,13 +807,13 @@ static int32_t mnodeSetDbDropping(SDbObj *pDb) { if (pDb->status) return TSDB_CODE_SUCCESS; pDb->status = true; - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsDbSdb, - .pObj = pDb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsDbSdb, + .pObj = pDb }; - int32_t code = sdbUpdateRow(&oper); + int32_t code = sdbUpdateRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("db:%s, failed to set dropping state, reason:%s", pDb->name, tstrerror(code)); } @@ -1019,15 +1019,15 @@ static int32_t mnodeAlterDb(SDbObj *pDb, SAlterDbMsg *pAlter, void *pMsg) { if (memcmp(&newCfg, &pDb->cfg, sizeof(SDbCfg)) != 0) { pDb->cfg = newCfg; pDb->cfgVersion++; - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsDbSdb, - .pObj = pDb, - .pMsg = pMsg, - .writeCb = mnodeAlterDbCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsDbSdb, + .pObj = pDb, + .pMsg = pMsg, + .fpRsp = mnodeAlterDbCb }; - code = sdbUpdateRow(&oper); + code = sdbUpdateRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("db:%s, failed to alter, reason:%s", pDb->name, tstrerror(code)); } @@ -1071,15 +1071,15 @@ static int32_t mnodeDropDb(SMnodeMsg *pMsg) { SDbObj *pDb = pMsg->pDb; mInfo("db:%s, drop db from sdb", pDb->name); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsDbSdb, - .pObj = pDb, - .pMsg = pMsg, - .writeCb = mnodeDropDbCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsDbSdb, + .pObj = pDb, + .pMsg = pMsg, + .fpRsp = mnodeDropDbCb }; - int32_t code = sdbDeleteRow(&oper); + int32_t code = sdbDeleteRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("db:%s, failed to drop, reason:%s", pDb->name, tstrerror(code)); } @@ -1134,13 +1134,13 @@ void mnodeDropAllDbs(SAcctObj *pAcct) { if (pDb->pAcct == pAcct) { mInfo("db:%s, drop db from sdb for acct:%s is dropped", pDb->name, pAcct->user); - SSdbOper oper = { - .type = SDB_OPER_LOCAL, - .table = tsDbSdb, - .pObj = pDb + SSdbRow row = { + .type = SDB_OPER_LOCAL, + .pTable = tsDbSdb, + .pObj = pDb }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); numOfDbs++; } mnodeDecDbRef(pDb); diff --git a/src/mnode/src/mnodeDnode.c b/src/mnode/src/mnodeDnode.c index 7e34e08373..f76533c760 100644 --- a/src/mnode/src/mnodeDnode.c +++ b/src/mnode/src/mnodeDnode.c @@ -87,13 +87,13 @@ static char* offlineReason[] = { "unknown", }; -static int32_t mnodeDnodeActionDestroy(SSdbOper *pOper) { - tfree(pOper->pObj); +static int32_t mnodeDnodeActionDestroy(SSdbRow *pRow) { + tfree(pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t mnodeDnodeActionInsert(SSdbOper *pOper) { - SDnodeObj *pDnode = pOper->pObj; +static int32_t mnodeDnodeActionInsert(SSdbRow *pRow) { + SDnodeObj *pDnode = pRow->pObj; if (pDnode->status != TAOS_DN_STATUS_DROPPING) { pDnode->status = TAOS_DN_STATUS_OFFLINE; pDnode->lastAccess = tsAccessSquence; @@ -107,8 +107,8 @@ static int32_t mnodeDnodeActionInsert(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeDnodeActionDelete(SSdbOper *pOper) { - SDnodeObj *pDnode = pOper->pObj; +static int32_t mnodeDnodeActionDelete(SSdbRow *pRow) { + SDnodeObj *pDnode = pRow->pObj; #ifndef _SYNC mnodeDropAllDnodeVgroups(pDnode); @@ -121,11 +121,11 @@ static int32_t mnodeDnodeActionDelete(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeDnodeActionUpdate(SSdbOper *pOper) { - SDnodeObj *pNew = pOper->pObj; +static int32_t mnodeDnodeActionUpdate(SSdbRow *pRow) { + SDnodeObj *pNew = pRow->pObj; SDnodeObj *pDnode = mnodeGetDnode(pNew->dnodeId); if (pDnode != NULL && pNew != pDnode) { - memcpy(pDnode, pNew, pOper->rowSize); + memcpy(pDnode, pNew, pRow->rowSize); free(pNew); } mnodeDecDnodeRef(pDnode); @@ -134,19 +134,19 @@ static int32_t mnodeDnodeActionUpdate(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeDnodeActionEncode(SSdbOper *pOper) { - SDnodeObj *pDnode = pOper->pObj; - memcpy(pOper->rowData, pDnode, tsDnodeUpdateSize); - pOper->rowSize = tsDnodeUpdateSize; +static int32_t mnodeDnodeActionEncode(SSdbRow *pRow) { + SDnodeObj *pDnode = pRow->pObj; + memcpy(pRow->rowData, pDnode, tsDnodeUpdateSize); + pRow->rowSize = tsDnodeUpdateSize; return TSDB_CODE_SUCCESS; } -static int32_t mnodeDnodeActionDecode(SSdbOper *pOper) { +static int32_t mnodeDnodeActionDecode(SSdbRow *pRow) { SDnodeObj *pDnode = (SDnodeObj *) calloc(1, sizeof(SDnodeObj)); if (pDnode == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - memcpy(pDnode, pOper->rowData, tsDnodeUpdateSize); - pOper->pObj = pDnode; + memcpy(pDnode, pRow->rowData, tsDnodeUpdateSize); + pRow->pObj = pDnode; return TSDB_CODE_SUCCESS; } @@ -171,23 +171,23 @@ int32_t mnodeInitDnodes() { tsDnodeUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; pthread_mutex_init(&tsDnodeEpsMutex, NULL); - SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_DNODE, - .tableName = "dnodes", + SSdbTableDesc desc = { + .id = SDB_TABLE_DNODE, + .name = "dnodes", .hashSessions = TSDB_DEFAULT_DNODES_HASH_SIZE, .maxRowSize = tsDnodeUpdateSize, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_AUTO, - .insertFp = mnodeDnodeActionInsert, - .deleteFp = mnodeDnodeActionDelete, - .updateFp = mnodeDnodeActionUpdate, - .encodeFp = mnodeDnodeActionEncode, - .decodeFp = mnodeDnodeActionDecode, - .destroyFp = mnodeDnodeActionDestroy, - .restoredFp = mnodeDnodeActionRestored + .fpInsert = mnodeDnodeActionInsert, + .fpDelete = mnodeDnodeActionDelete, + .fpUpdate = mnodeDnodeActionUpdate, + .fpEncode = mnodeDnodeActionEncode, + .fpDecode = mnodeDnodeActionDecode, + .fpDestroy = mnodeDnodeActionDestroy, + .fpRestored = mnodeDnodeActionRestored }; - tsDnodeSdb = sdbOpenTable(&tableDesc); + tsDnodeSdb = sdbOpenTable(&desc); if (tsDnodeSdb == NULL) { mError("failed to init dnodes data"); return -1; @@ -296,13 +296,13 @@ void mnodeDecDnodeRef(SDnodeObj *pDnode) { } void mnodeUpdateDnode(SDnodeObj *pDnode) { - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsDnodeSdb, - .pObj = pDnode + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsDnodeSdb, + .pObj = pDnode }; - int32_t code = sdbUpdateRow(&oper); + int32_t code = sdbUpdateRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("dnodeId:%d, failed update", pDnode->dnodeId); } @@ -644,15 +644,15 @@ static int32_t mnodeCreateDnode(char *ep, SMnodeMsg *pMsg) { tstrncpy(pDnode->dnodeEp, ep, TSDB_EP_LEN); taosGetFqdnPortFromEp(ep, pDnode->dnodeFqdn, &pDnode->dnodePort); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsDnodeSdb, - .pObj = pDnode, + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsDnodeSdb, + .pObj = pDnode, .rowSize = sizeof(SDnodeObj), - .pMsg = pMsg + .pMsg = pMsg }; - int32_t code = sdbInsertRow(&oper); + int32_t code = sdbInsertRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { int dnodeId = pDnode->dnodeId; tfree(pDnode); @@ -665,14 +665,14 @@ static int32_t mnodeCreateDnode(char *ep, SMnodeMsg *pMsg) { } int32_t mnodeDropDnode(SDnodeObj *pDnode, void *pMsg) { - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsDnodeSdb, - .pObj = pDnode, - .pMsg = pMsg + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsDnodeSdb, + .pObj = pDnode, + .pMsg = pMsg }; - int32_t code = sdbDeleteRow(&oper); + int32_t code = sdbDeleteRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("dnode:%d, failed to drop from cluster, result:%s", pDnode->dnodeId, tstrerror(code)); } else { @@ -1141,7 +1141,7 @@ static int32_t mnodeRetrieveVnodes(SShowObj *pShow, char *data, int32_t rows, vo cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - strcpy(pWrite, mnodeGetMnodeRoleStr(pVgid->role)); + strcpy(pWrite, syncRole[pVgid->role]); cols++; } } diff --git a/src/mnode/src/mnodeInt.c b/src/mnode/src/mnodeInt.c index 8431baf4f4..534deec09a 100644 --- a/src/mnode/src/mnodeInt.c +++ b/src/mnode/src/mnodeInt.c @@ -48,7 +48,7 @@ void *mnodeCreateMsg(SRpcMsg *pRpcMsg) { int32_t mnodeInitMsg(SMnodeMsg *pMsg) { if (pMsg->pUser != NULL) { - mDebug("app:%p:%p, user info already inited", pMsg->rpcMsg.ahandle, pMsg); + mTrace("msg:%p, app:%p user info already inited", pMsg, pMsg->rpcMsg.ahandle); return TSDB_CODE_SUCCESS; } diff --git a/src/mnode/src/mnodeMnode.c b/src/mnode/src/mnodeMnode.c index 092f246c13..205bfda4b9 100644 --- a/src/mnode/src/mnodeMnode.c +++ b/src/mnode/src/mnodeMnode.c @@ -58,13 +58,13 @@ static int32_t mnodeRetrieveMnodes(SShowObj *pShow, char *data, int32_t rows, vo #define mnodeMnodeDestroyLock() pthread_mutex_destroy(&tsMnodeLock) #endif -static int32_t mnodeMnodeActionDestroy(SSdbOper *pOper) { - tfree(pOper->pObj); +static int32_t mnodeMnodeActionDestroy(SSdbRow *pRow) { + tfree(pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t mnodeMnodeActionInsert(SSdbOper *pOper) { - SMnodeObj *pMnode = pOper->pObj; +static int32_t mnodeMnodeActionInsert(SSdbRow *pRow) { + SMnodeObj *pMnode = pRow->pObj; SDnodeObj *pDnode = mnodeGetDnode(pMnode->mnodeId); if (pDnode == NULL) return TSDB_CODE_MND_DNODE_NOT_EXIST; @@ -76,8 +76,8 @@ static int32_t mnodeMnodeActionInsert(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeMnodeActionDelete(SSdbOper *pOper) { - SMnodeObj *pMnode = pOper->pObj; +static int32_t mnodeMnodeActionDelete(SSdbRow *pRow) { + SMnodeObj *pMnode = pRow->pObj; SDnodeObj *pDnode = mnodeGetDnode(pMnode->mnodeId); if (pDnode == NULL) return TSDB_CODE_MND_DNODE_NOT_EXIST; @@ -88,30 +88,30 @@ static int32_t mnodeMnodeActionDelete(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeMnodeActionUpdate(SSdbOper *pOper) { - SMnodeObj *pMnode = pOper->pObj; +static int32_t mnodeMnodeActionUpdate(SSdbRow *pRow) { + SMnodeObj *pMnode = pRow->pObj; SMnodeObj *pSaved = mnodeGetMnode(pMnode->mnodeId); if (pMnode != pSaved) { - memcpy(pSaved, pMnode, pOper->rowSize); + memcpy(pSaved, pMnode, pRow->rowSize); free(pMnode); } mnodeDecMnodeRef(pSaved); return TSDB_CODE_SUCCESS; } -static int32_t mnodeMnodeActionEncode(SSdbOper *pOper) { - SMnodeObj *pMnode = pOper->pObj; - memcpy(pOper->rowData, pMnode, tsMnodeUpdateSize); - pOper->rowSize = tsMnodeUpdateSize; +static int32_t mnodeMnodeActionEncode(SSdbRow *pRow) { + SMnodeObj *pMnode = pRow->pObj; + memcpy(pRow->rowData, pMnode, tsMnodeUpdateSize); + pRow->rowSize = tsMnodeUpdateSize; return TSDB_CODE_SUCCESS; } -static int32_t mnodeMnodeActionDecode(SSdbOper *pOper) { +static int32_t mnodeMnodeActionDecode(SSdbRow *pRow) { SMnodeObj *pMnode = calloc(1, sizeof(SMnodeObj)); if (pMnode == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - memcpy(pMnode, pOper->rowData, tsMnodeUpdateSize); - pOper->pObj = pMnode; + memcpy(pMnode, pRow->rowData, tsMnodeUpdateSize); + pRow->pObj = pMnode; return TSDB_CODE_SUCCESS; } @@ -137,23 +137,23 @@ int32_t mnodeInitMnodes() { SMnodeObj tObj; tsMnodeUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; - SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_MNODE, - .tableName = "mnodes", + SSdbTableDesc desc = { + .id = SDB_TABLE_MNODE, + .name = "mnodes", .hashSessions = TSDB_DEFAULT_MNODES_HASH_SIZE, .maxRowSize = tsMnodeUpdateSize, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_INT, - .insertFp = mnodeMnodeActionInsert, - .deleteFp = mnodeMnodeActionDelete, - .updateFp = mnodeMnodeActionUpdate, - .encodeFp = mnodeMnodeActionEncode, - .decodeFp = mnodeMnodeActionDecode, - .destroyFp = mnodeMnodeActionDestroy, - .restoredFp = mnodeMnodeActionRestored + .fpInsert = mnodeMnodeActionInsert, + .fpDelete = mnodeMnodeActionDelete, + .fpUpdate = mnodeMnodeActionUpdate, + .fpEncode = mnodeMnodeActionEncode, + .fpDecode = mnodeMnodeActionDecode, + .fpDestroy = mnodeMnodeActionDestroy, + .fpRestored = mnodeMnodeActionRestored }; - tsMnodeSdb = sdbOpenTable(&tableDesc); + tsMnodeSdb = sdbOpenTable(&desc); if (tsMnodeSdb == NULL) { mError("failed to init mnodes data"); return -1; @@ -192,10 +192,6 @@ void *mnodeGetNextMnode(void *pIter, SMnodeObj **pMnode) { return sdbFetchRow(tsMnodeSdb, pIter, (void **)pMnode); } -char *mnodeGetMnodeRoleStr(int32_t role) { - return syncRole[role]; -} - void mnodeUpdateMnodeEpSet() { mInfo("update mnodes epSet, numOfEps:%d ", mnodeGetMnodesNum()); @@ -329,11 +325,11 @@ void mnodeCreateMnode(int32_t dnodeId, char *dnodeEp, bool needConfirm) { pMnode->mnodeId = dnodeId; pMnode->createdTime = taosGetTimestampMs(); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsMnodeSdb, - .pObj = pMnode, - .writeCb = mnodeCreateMnodeCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsMnodeSdb, + .pObj = pMnode, + .fpRsp = mnodeCreateMnodeCb }; int32_t code = TSDB_CODE_SUCCESS; @@ -346,7 +342,7 @@ void mnodeCreateMnode(int32_t dnodeId, char *dnodeEp, bool needConfirm) { return; } - code = sdbInsertRow(&oper); + code = sdbInsertRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("dnode:%d, failed to create mnode, ep:%s reason:%s", dnodeId, dnodeEp, tstrerror(code)); tfree(pMnode); @@ -356,8 +352,8 @@ void mnodeCreateMnode(int32_t dnodeId, char *dnodeEp, bool needConfirm) { void mnodeDropMnodeLocal(int32_t dnodeId) { SMnodeObj *pMnode = mnodeGetMnode(dnodeId); if (pMnode != NULL) { - SSdbOper oper = {.type = SDB_OPER_LOCAL, .table = tsMnodeSdb, .pObj = pMnode}; - sdbDeleteRow(&oper); + SSdbRow row = {.type = SDB_OPER_LOCAL, .pTable = tsMnodeSdb, .pObj = pMnode}; + sdbDeleteRow(&row); mnodeDecMnodeRef(pMnode); } @@ -371,13 +367,13 @@ int32_t mnodeDropMnode(int32_t dnodeId) { return TSDB_CODE_MND_DNODE_NOT_EXIST; } - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsMnodeSdb, - .pObj = pMnode + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsMnodeSdb, + .pObj = pMnode }; - int32_t code = sdbDeleteRow(&oper); + int32_t code = sdbDeleteRow(&row); sdbDecRef(tsMnodeSdb, pMnode); @@ -469,7 +465,7 @@ static int32_t mnodeRetrieveMnodes(SShowObj *pShow, char *data, int32_t rows, vo cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - char* roles = mnodeGetMnodeRoleStr(pMnode->role); + char* roles = syncRole[pMnode->role]; STR_WITH_MAXSIZE_TO_VARSTR(pWrite, roles, pShow->bytes[cols]); cols++; diff --git a/src/mnode/src/mnodePeer.c b/src/mnode/src/mnodePeer.c index e43f8c1b78..f13ef75398 100644 --- a/src/mnode/src/mnodePeer.c +++ b/src/mnode/src/mnodePeer.c @@ -47,7 +47,7 @@ void mnodeAddPeerRspHandle(uint8_t msgType, void (*fp)(SRpcMsg *rpcMsg)) { int32_t mnodeProcessPeerReq(SMnodeMsg *pMsg) { if (pMsg->rpcMsg.pCont == NULL) { - mError("%p, msg:%s in mpeer queue, content is null", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); + mError("msg:%p, ahandle:%p type:%s in mpeer queue, content is null", pMsg, pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); return TSDB_CODE_MND_INVALID_MSG_LEN; } @@ -58,8 +58,8 @@ int32_t mnodeProcessPeerReq(SMnodeMsg *pMsg) { rpcRsp->rsp = epSet; rpcRsp->len = sizeof(SRpcEpSet); - mDebug("%p, msg:%s in mpeer queue will be redirected, numOfEps:%d inUse:%d", pMsg->rpcMsg.ahandle, - taosMsg[pMsg->rpcMsg.msgType], epSet->numOfEps, epSet->inUse); + mDebug("msg:%p, ahandle:%p type:%s in mpeer queue will be redirected, numOfEps:%d inUse:%d", pMsg, + pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType], epSet->numOfEps, epSet->inUse); for (int32_t i = 0; i < epSet->numOfEps; ++i) { if (strcmp(epSet->fqdn[i], tsLocalFqdn) == 0 && htons(epSet->port[i]) == tsServerPort + TSDB_PORT_DNODEDNODE) { epSet->inUse = (i + 1) % epSet->numOfEps; @@ -73,7 +73,8 @@ int32_t mnodeProcessPeerReq(SMnodeMsg *pMsg) { } if (tsMnodeProcessPeerMsgFp[pMsg->rpcMsg.msgType] == NULL) { - mError("%p, msg:%s in mpeer queue, not processed", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); + mError("msg:%p, ahandle:%p type:%s in mpeer queue, not processed", pMsg, pMsg->rpcMsg.ahandle, + taosMsg[pMsg->rpcMsg.msgType]); return TSDB_CODE_MND_MSG_NOT_PROCESSED; } @@ -82,13 +83,14 @@ int32_t mnodeProcessPeerReq(SMnodeMsg *pMsg) { void mnodeProcessPeerRsp(SRpcMsg *pMsg) { if (!sdbIsMaster()) { - mError("%p, msg:%s is not processed for it is not master", pMsg->ahandle, taosMsg[pMsg->msgType]); + mError("msg:%p, ahandle:%p type:%s is not processed for it is not master", pMsg, pMsg->ahandle, + taosMsg[pMsg->msgType]); return; } if (tsMnodeProcessPeerRspFp[pMsg->msgType]) { (*tsMnodeProcessPeerRspFp[pMsg->msgType])(pMsg); } else { - mError("%p, msg:%s is not processed", pMsg->ahandle, taosMsg[pMsg->msgType]); + mError("msg:%p, ahandle:%p type:%s is not processed", pMsg, pMsg->ahandle, taosMsg[pMsg->msgType]); } } diff --git a/src/mnode/src/mnodeRead.c b/src/mnode/src/mnodeRead.c index 93b944febb..ea7ce783e8 100644 --- a/src/mnode/src/mnodeRead.c +++ b/src/mnode/src/mnodeRead.c @@ -43,7 +43,7 @@ void mnodeAddReadMsgHandle(uint8_t msgType, int32_t (*fp)(SMnodeMsg *pMsg)) { int32_t mnodeProcessRead(SMnodeMsg *pMsg) { if (pMsg->rpcMsg.pCont == NULL) { - mError("%p, msg:%s in mread queue, content is null", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); + mError("msg:%p, app:%p type:%s in mread queue, content is null", pMsg, pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); return TSDB_CODE_MND_INVALID_MSG_LEN; } @@ -52,7 +52,7 @@ int32_t mnodeProcessRead(SMnodeMsg *pMsg) { SRpcEpSet *epSet = rpcMallocCont(sizeof(SRpcEpSet)); mnodeGetMnodeEpSetForShell(epSet); - mDebug("%p, msg:%s in mread queue will be redirected, numOfEps:%d inUse:%d", pMsg->rpcMsg.ahandle, + mDebug("msg:%p, app:%p type:%s in mread queue will be redirected, numOfEps:%d inUse:%d", pMsg, pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType], epSet->numOfEps, epSet->inUse); for (int32_t i = 0; i < epSet->numOfEps; ++i) { if (strcmp(epSet->fqdn[i], tsLocalFqdn) == 0 && htons(epSet->port[i]) == tsServerPort) { @@ -70,13 +70,15 @@ int32_t mnodeProcessRead(SMnodeMsg *pMsg) { } if (tsMnodeProcessReadMsgFp[pMsg->rpcMsg.msgType] == NULL) { - mError("%p, msg:%s in mread queue, not processed", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); + mError("msg:%p, app:%p type:%s in mread queue, not processed", pMsg, pMsg->rpcMsg.ahandle, + taosMsg[pMsg->rpcMsg.msgType]); return TSDB_CODE_MND_MSG_NOT_PROCESSED; } int32_t code = mnodeInitMsg(pMsg); if (code != TSDB_CODE_SUCCESS) { - mError("%p, msg:%s in mread queue, not processed reason:%s", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType], tstrerror(code)); + mError("msg:%p, app:%p type:%s in mread queue, not processed reason:%s", pMsg, pMsg->rpcMsg.ahandle, + taosMsg[pMsg->rpcMsg.msgType], tstrerror(code)); return code; } diff --git a/src/mnode/src/mnodeSdb.c b/src/mnode/src/mnodeSdb.c index 003ecd0d24..1728bb7e3b 100644 --- a/src/mnode/src/mnodeSdb.c +++ b/src/mnode/src/mnodeSdb.c @@ -34,23 +34,30 @@ #include "mnodeSdb.h" #define SDB_TABLE_LEN 12 -#define SDB_SYNC_HACK 16 +#define MAX_QUEUED_MSG_NUM 10000 typedef enum { - SDB_ACTION_INSERT, - SDB_ACTION_DELETE, - SDB_ACTION_UPDATE + SDB_ACTION_INSERT = 0, + SDB_ACTION_DELETE = 1, + SDB_ACTION_UPDATE = 2 } ESdbAction; typedef enum { - SDB_STATUS_OFFLINE, - SDB_STATUS_SERVING, - SDB_STATUS_CLOSING + SDB_STATUS_OFFLINE = 0, + SDB_STATUS_SERVING = 1, + SDB_STATUS_CLOSING = 2 } ESdbStatus; -typedef struct _SSdbTable { - char tableName[SDB_TABLE_LEN]; - ESdbTable tableId; +char *actStr[] = { + "insert", + "delete", + "update", + "invalid" +}; + +typedef struct SSdbTable { + char name[SDB_TABLE_LEN]; + ESdbTable id; ESdbKey keyType; int32_t hashSessions; int32_t maxRowSize; @@ -58,13 +65,13 @@ typedef struct _SSdbTable { int32_t autoIndex; int64_t numOfRows; void * iHandle; - int32_t (*insertFp)(SSdbOper *pDesc); - int32_t (*deleteFp)(SSdbOper *pOper); - int32_t (*updateFp)(SSdbOper *pOper); - int32_t (*decodeFp)(SSdbOper *pOper); - int32_t (*encodeFp)(SSdbOper *pOper); - int32_t (*destroyFp)(SSdbOper *pOper); - int32_t (*restoredFp)(); + int32_t (*fpInsert)(SSdbRow *pRow); + int32_t (*fpDelete)(SSdbRow *pRow); + int32_t (*fpUpdate)(SSdbRow *pRow); + int32_t (*fpDecode)(SSdbRow *pRow); + int32_t (*fpEncode)(SSdbRow *pRow); + int32_t (*fpDestroy)(SSdbRow *pRow); + int32_t (*fpRestored)(); pthread_mutex_t mutex; } SSdbTable; @@ -75,60 +82,61 @@ typedef struct { int64_t sync; void * wal; SSyncCfg cfg; + int32_t queuedMsg; int32_t numOfTables; SSdbTable *tableList[SDB_TABLE_MAX]; pthread_mutex_t mutex; -} SSdbObject; +} SSdbMgmt; typedef struct { pthread_t thread; int32_t workerId; -} SSdbWriteWorker; +} SSdbWorker; typedef struct { int32_t num; - SSdbWriteWorker *writeWorker; -} SSdbWriteWorkerPool; + SSdbWorker *worker; +} SSdbWorkerPool; extern void * tsMnodeTmr; -static void * tsUpdateSyncTmr; -static SSdbObject tsSdbObj = {0}; -static taos_qset tsSdbWriteQset; -static taos_qall tsSdbWriteQall; -static taos_queue tsSdbWriteQueue; -static SSdbWriteWorkerPool tsSdbPool; +static void * tsSdbTmr; +static SSdbMgmt tsSdbMgmt = {0}; +static taos_qset tsSdbWQset; +static taos_qall tsSdbWQall; +static taos_queue tsSdbWQueue; +static SSdbWorkerPool tsSdbPool; -static int32_t sdbWrite(void *param, void *data, int32_t type, void *pMsg); -static int32_t sdbWriteToQueue(void *param, void *data, int32_t type, void *pMsg); -static void * sdbWorkerFp(void *param); -static int32_t sdbInitWriteWorker(); -static void sdbCleanupWriteWorker(); -static int32_t sdbAllocWriteQueue(); -static void sdbFreeWritequeue(); -static int32_t sdbUpdateRowImp(SSdbOper *pOper); -static int32_t sdbDeleteRowImp(SSdbOper *pOper); -static int32_t sdbInsertHash(SSdbTable *pTable, SSdbOper *pOper); -static int32_t sdbUpdateHash(SSdbTable *pTable, SSdbOper *pOper); -static int32_t sdbDeleteHash(SSdbTable *pTable, SSdbOper *pOper); +static int32_t sdbProcessWrite(void *pRow, void *pHead, int32_t qtype, void *unused); +static int32_t sdbWriteWalToQueue(void *vparam, void *pHead, int32_t qtype, void *rparam); +static int32_t sdbWriteRowToQueue(SSdbRow *pRow, int32_t action); +static void sdbFreeFromQueue(SSdbRow *pRow); +static void * sdbWorkerFp(void *pWorker); +static int32_t sdbInitWorker(); +static void sdbCleanupWorker(); +static int32_t sdbAllocQueue(); +static void sdbFreeQueue(); +static int32_t sdbInsertHash(SSdbTable *pTable, SSdbRow *pRow); +static int32_t sdbUpdateHash(SSdbTable *pTable, SSdbRow *pRow); +static int32_t sdbDeleteHash(SSdbTable *pTable, SSdbRow *pRow); -int32_t sdbGetId(void *handle) { - return ((SSdbTable *)handle)->autoIndex; +int32_t sdbGetId(void *pTable) { + return ((SSdbTable *)pTable)->autoIndex; } -int64_t sdbGetNumOfRows(void *handle) { - return ((SSdbTable *)handle)->numOfRows; +int64_t sdbGetNumOfRows(void *pTable) { + return ((SSdbTable *)pTable)->numOfRows; } uint64_t sdbGetVersion() { - return tsSdbObj.version; + return tsSdbMgmt.version; } bool sdbIsMaster() { - return tsSdbObj.role == TAOS_SYNC_ROLE_MASTER; + return tsSdbMgmt.role == TAOS_SYNC_ROLE_MASTER; } bool sdbIsServing() { - return tsSdbObj.status == SDB_STATUS_SERVING; + return tsSdbMgmt.status == SDB_STATUS_SERVING; } static void *sdbGetObjKey(SSdbTable *pTable, void *key) { @@ -139,18 +147,6 @@ static void *sdbGetObjKey(SSdbTable *pTable, void *key) { return key; } -static char *sdbGetActionStr(int32_t action) { - switch (action) { - case SDB_ACTION_INSERT: - return "insert"; - case SDB_ACTION_DELETE: - return "delete"; - case SDB_ACTION_UPDATE: - return "update"; - } - return "invalid"; -} - static char *sdbGetKeyStr(SSdbTable *pTable, void *key) { static char str[16]; switch (pTable->keyType) { @@ -166,28 +162,28 @@ static char *sdbGetKeyStr(SSdbTable *pTable, void *key) { } } -static char *sdbGetKeyStrFromObj(SSdbTable *pTable, void *key) { +static char *sdbGetRowStr(SSdbTable *pTable, void *key) { return sdbGetKeyStr(pTable, sdbGetObjKey(pTable, key)); } static void *sdbGetTableFromId(int32_t tableId) { - return tsSdbObj.tableList[tableId]; + return tsSdbMgmt.tableList[tableId]; } static int32_t sdbInitWal() { SWalCfg walCfg = {.vgId = 1, .walLevel = TAOS_WAL_FSYNC, .keep = TAOS_WAL_KEEP, .fsyncPeriod = 0}; - char temp[TSDB_FILENAME_LEN]; + char temp[TSDB_FILENAME_LEN] = {0}; sprintf(temp, "%s/wal", tsMnodeDir); - tsSdbObj.wal = walOpen(temp, &walCfg); - if (tsSdbObj.wal == NULL) { - sdbError("failed to open sdb wal in %s", tsMnodeDir); + tsSdbMgmt.wal = walOpen(temp, &walCfg); + if (tsSdbMgmt.wal == NULL) { + sdbError("vgId:1, failed to open wal in %s", tsMnodeDir); return -1; } - sdbInfo("open sdb wal for restore"); - int code = walRestore(tsSdbObj.wal, NULL, sdbWrite); + sdbInfo("vgId:1, open wal for restore"); + int32_t code = walRestore(tsSdbMgmt.wal, NULL, sdbProcessWrite); if (code != TSDB_CODE_SUCCESS) { - sdbError("failed to open wal for restore, reason:%s", tstrerror(code)); + sdbError("vgId:1, failed to open wal for restore since %s", tstrerror(code)); return -1; } return 0; @@ -199,31 +195,31 @@ static void sdbRestoreTables() { for (int32_t tableId = 0; tableId < SDB_TABLE_MAX; ++tableId) { SSdbTable *pTable = sdbGetTableFromId(tableId); if (pTable == NULL) continue; - if (pTable->restoredFp) { - (*pTable->restoredFp)(); + if (pTable->fpRestored) { + (*pTable->fpRestored)(); } totalRows += pTable->numOfRows; numOfTables++; - sdbDebug("table:%s, is restored, numOfRows:%" PRId64, pTable->tableName, pTable->numOfRows); + sdbDebug("vgId:1, sdb:%s is restored, rows:%" PRId64, pTable->name, pTable->numOfRows); } - sdbInfo("sdb is restored, ver:%" PRId64 " totalRows:%d numOfTables:%d", tsSdbObj.version, totalRows, numOfTables); + sdbInfo("vgId:1, sdb is restored, mver:%" PRIu64 " rows:%d tables:%d", tsSdbMgmt.version, totalRows, numOfTables); } void sdbUpdateMnodeRoles() { - if (tsSdbObj.sync <= 0) return; + if (tsSdbMgmt.sync <= 0) return; SNodesRole roles = {0}; - syncGetNodesRole(tsSdbObj.sync, &roles); + syncGetNodesRole(tsSdbMgmt.sync, &roles); - sdbInfo("update mnodes sync roles, total:%d", tsSdbObj.cfg.replica); - for (int32_t i = 0; i < tsSdbObj.cfg.replica; ++i) { + sdbInfo("vgId:1, update mnodes role, replica:%d", tsSdbMgmt.cfg.replica); + for (int32_t i = 0; i < tsSdbMgmt.cfg.replica; ++i) { SMnodeObj *pMnode = mnodeGetMnode(roles.nodeId[i]); if (pMnode != NULL) { pMnode->role = roles.role[i]; - sdbInfo("mnode:%d, role:%s", pMnode->mnodeId, mnodeGetMnodeRoleStr(pMnode->role)); - if (pMnode->mnodeId == dnodeGetDnodeId()) tsSdbObj.role = pMnode->role; + sdbInfo("vgId:1, mnode:%d, role:%s", pMnode->mnodeId, syncRole[pMnode->role]); + if (pMnode->mnodeId == dnodeGetDnodeId()) tsSdbMgmt.role = pMnode->role; mnodeDecMnodeRef(pMnode); } } @@ -238,87 +234,74 @@ static uint32_t sdbGetFileInfo(void *ahandle, char *name, uint32_t *index, uint3 } static int32_t sdbGetWalInfo(void *ahandle, char *fileName, int64_t *fileId) { - return walGetWalFile(tsSdbObj.wal, fileName, fileId); + return walGetWalFile(tsSdbMgmt.wal, fileName, fileId); } static void sdbNotifyRole(void *ahandle, int8_t role) { - sdbInfo("mnode role changed from %s to %s", mnodeGetMnodeRoleStr(tsSdbObj.role), mnodeGetMnodeRoleStr(role)); + sdbInfo("vgId:1, mnode role changed from %s to %s", syncRole[tsSdbMgmt.role], syncRole[role]); - if (role == TAOS_SYNC_ROLE_MASTER && tsSdbObj.role != TAOS_SYNC_ROLE_MASTER) { + if (role == TAOS_SYNC_ROLE_MASTER && tsSdbMgmt.role != TAOS_SYNC_ROLE_MASTER) { balanceReset(); } - tsSdbObj.role = role; + tsSdbMgmt.role = role; sdbUpdateMnodeRoles(); } +// failed to forward, need revert insert +static void sdbHandleFailedConfirm(SSdbRow *pRow) { + SWalHead *pHead = pRow->pHead; + int32_t action = pHead->msgType % 10; + + sdbError("vgId:1, row:%p:%s hver:%" PRIu64 " action:%s, failed to foward since %s", pRow->pObj, + sdbGetKeyStr(pRow->pTable, pHead->cont), pHead->version, actStr[action], tstrerror(pRow->code)); + + // It's better to create a table in two stages, create it first and then set it success + if (action == SDB_ACTION_INSERT) { + SSdbRow row = {.type = SDB_OPER_GLOBAL, .pTable = pRow->pTable, .pObj = pRow->pObj}; + sdbDeleteRow(&row); + } +} + FORCE_INLINE -static void sdbConfirmForward(void *ahandle, void *param, int32_t code) { - assert(param); - SSdbOper * pOper = param; - SMnodeMsg *pMsg = pOper->pMsg; - if (code <= 0) pOper->retCode = code; +static void sdbConfirmForward(void *ahandle, void *wparam, int32_t code) { + if (wparam == NULL) return; + SSdbRow *pRow = wparam; + SMnodeMsg * pMsg = pRow->pMsg; - int32_t processedCount = atomic_add_fetch_32(&pOper->processedCount, 1); - if (processedCount <= 1) { - if (pMsg != NULL) { - sdbDebug("app:%p:%p, waiting for confirm this operation, count:%d result:%s", pMsg->rpcMsg.ahandle, pMsg, - processedCount, tstrerror(code)); - } + if (code <= 0) pRow->code = code; + int32_t count = atomic_add_fetch_32(&pRow->processedCount, 1); + if (count <= 1) { + if (pMsg != NULL) sdbTrace("vgId:1, msg:%p waiting for confirm, count:%d code:%x", pMsg, count, code); return; + } else { + if (pMsg != NULL) sdbTrace("vgId:1, msg:%p is confirmed, code:%x", pMsg, code); } - if (pMsg != NULL) { - sdbDebug("app:%p:%p, is confirmed and will do callback func, result:%s", pMsg->rpcMsg.ahandle, pMsg, - tstrerror(code)); + if (pRow->code != TSDB_CODE_SUCCESS) sdbHandleFailedConfirm(pRow); + + if (pRow->fpRsp != NULL) { + pRow->code = (*pRow->fpRsp)(pMsg, pRow->code); } - // failed to forward, need revert insert - if (pOper->retCode != TSDB_CODE_SUCCESS) { - SWalHead *pHead = (void *)pOper + sizeof(SSdbOper) + SDB_SYNC_HACK; - int32_t action = pHead->msgType % 10; - sdbError("table:%s record:%p:%s ver:%" PRIu64 ", action:%d failed to foward reason:%s", - ((SSdbTable *)pOper->table)->tableName, pOper->pObj, sdbGetKeyStr(pOper->table, pHead->cont), - pHead->version, action, tstrerror(pOper->retCode)); - if (action == SDB_ACTION_INSERT) { - // It's better to create a table in two stages, create it first and then set it success - //sdbDeleteHash(pOper->table, pOper); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = pOper->table, - .pObj = pOper->pObj - }; - sdbDeleteRow(&oper); - } - } - - if (pOper->writeCb != NULL) { - pOper->retCode = (*pOper->writeCb)(pMsg, pOper->retCode); - } - dnodeSendRpcMWriteRsp(pMsg, pOper->retCode); - - // if ahandle, means this func is called by sdb write - if (ahandle == NULL) { - sdbDecRef(pOper->table, pOper->pObj); - } - - taosFreeQitem(pOper); + dnodeSendRpcMWriteRsp(pMsg, pRow->code); + sdbFreeFromQueue(pRow); } static void sdbUpdateSyncTmrFp(void *param, void *tmrId) { sdbUpdateSync(NULL); } void sdbUpdateAsync() { - taosTmrReset(sdbUpdateSyncTmrFp, 200, NULL, tsMnodeTmr, &tsUpdateSyncTmr); + taosTmrReset(sdbUpdateSyncTmrFp, 200, NULL, tsMnodeTmr, &tsSdbTmr); } void sdbUpdateSync(void *pMnodes) { SMnodeInfos *mnodes = pMnodes; if (!mnodeIsRunning()) { - mDebug("mnode not start yet, update sync config later"); + mDebug("vgId:1, mnode not start yet, update sync config later"); return; } - mDebug("update sync config in sync module, mnodes:%p", pMnodes); + mDebug("vgId:1, update sync config in sync module, mnodes:%p", pMnodes); SSyncCfg syncCfg = {0}; int32_t index = 0; @@ -344,7 +327,7 @@ void sdbUpdateSync(void *pMnodes) { } sdbFreeIter(pIter); syncCfg.replica = index; - mDebug("mnodes info not input, use infos in sdb, numOfMnodes:%d", syncCfg.replica); + mDebug("vgId:1, mnodes info not input, use infos in sdb, numOfMnodes:%d", syncCfg.replica); } else { for (index = 0; index < mnodes->mnodeNum; ++index) { SMnodeInfo *node = &mnodes->mnodeInfos[index]; @@ -353,7 +336,7 @@ void sdbUpdateSync(void *pMnodes) { syncCfg.nodeInfo[index].nodePort += TSDB_PORT_SYNC; } syncCfg.replica = index; - mDebug("mnodes info input, numOfMnodes:%d", syncCfg.replica); + mDebug("vgId:1, mnodes info input, numOfMnodes:%d", syncCfg.replica); } syncCfg.quorum = (syncCfg.replica == 1) ? 1 : 2; @@ -367,18 +350,19 @@ void sdbUpdateSync(void *pMnodes) { } if (!hasThisDnode) { - sdbDebug("update sync config, this dnode not exist"); + sdbDebug("vgId:1, update sync config, this dnode not exist"); return; } - if (memcmp(&syncCfg, &tsSdbObj.cfg, sizeof(SSyncCfg)) == 0) { - sdbDebug("update sync config, info not changed"); + if (memcmp(&syncCfg, &tsSdbMgmt.cfg, sizeof(SSyncCfg)) == 0) { + sdbDebug("vgId:1, update sync config, info not changed"); return; } - sdbInfo("work as mnode, replica:%d", syncCfg.replica); + sdbInfo("vgId:1, work as mnode, replica:%d", syncCfg.replica); for (int32_t i = 0; i < syncCfg.replica; ++i) { - sdbInfo("mnode:%d, %s:%d", syncCfg.nodeInfo[i].nodeId, syncCfg.nodeInfo[i].nodeFqdn, syncCfg.nodeInfo[i].nodePort); + sdbInfo("vgId:1, mnode:%d, %s:%d", syncCfg.nodeInfo[i].nodeId, syncCfg.nodeInfo[i].nodeFqdn, + syncCfg.nodeInfo[i].nodePort); } SSyncInfo syncInfo = {0}; @@ -389,23 +373,24 @@ void sdbUpdateSync(void *pMnodes) { syncInfo.ahandle = NULL; syncInfo.getWalInfo = sdbGetWalInfo; syncInfo.getFileInfo = sdbGetFileInfo; - syncInfo.writeToCache = sdbWriteToQueue; + syncInfo.writeToCache = sdbWriteWalToQueue; syncInfo.confirmForward = sdbConfirmForward; syncInfo.notifyRole = sdbNotifyRole; - tsSdbObj.cfg = syncCfg; + tsSdbMgmt.cfg = syncCfg; - if (tsSdbObj.sync) { - syncReconfig(tsSdbObj.sync, &syncCfg); + if (tsSdbMgmt.sync) { + syncReconfig(tsSdbMgmt.sync, &syncCfg); } else { - tsSdbObj.sync = syncStart(&syncInfo); + tsSdbMgmt.sync = syncStart(&syncInfo); } + sdbUpdateMnodeRoles(); } int32_t sdbInit() { - pthread_mutex_init(&tsSdbObj.mutex, NULL); + pthread_mutex_init(&tsSdbMgmt.mutex, NULL); - if (sdbInitWriteWorker() != 0) { + if (sdbInitWorker() != 0) { return -1; } @@ -416,56 +401,56 @@ int32_t sdbInit() { sdbRestoreTables(); if (mnodeGetMnodesNum() == 1) { - tsSdbObj.role = TAOS_SYNC_ROLE_MASTER; + tsSdbMgmt.role = TAOS_SYNC_ROLE_MASTER; } - tsSdbObj.status = SDB_STATUS_SERVING; + tsSdbMgmt.status = SDB_STATUS_SERVING; return TSDB_CODE_SUCCESS; } void sdbCleanUp() { - if (tsSdbObj.status != SDB_STATUS_SERVING) return; + if (tsSdbMgmt.status != SDB_STATUS_SERVING) return; - tsSdbObj.status = SDB_STATUS_CLOSING; - - sdbCleanupWriteWorker(); - sdbDebug("sdb will be closed, ver:%" PRId64, tsSdbObj.version); + tsSdbMgmt.status = SDB_STATUS_CLOSING; - if (tsSdbObj.sync) { - syncStop(tsSdbObj.sync); - tsSdbObj.sync = -1; + sdbCleanupWorker(); + sdbDebug("vgId:1, sdb will be closed, mver:%" PRIu64, tsSdbMgmt.version); + + if (tsSdbMgmt.sync) { + syncStop(tsSdbMgmt.sync); + tsSdbMgmt.sync = -1; } - if (tsSdbObj.wal) { - walClose(tsSdbObj.wal); - tsSdbObj.wal = NULL; + if (tsSdbMgmt.wal) { + walClose(tsSdbMgmt.wal); + tsSdbMgmt.wal = NULL; } - pthread_mutex_destroy(&tsSdbObj.mutex); + pthread_mutex_destroy(&tsSdbMgmt.mutex); } -void sdbIncRef(void *handle, void *pObj) { - if (pObj == NULL || handle == NULL) return; +void sdbIncRef(void *tparam, void *pRow) { + if (pRow == NULL || tparam == NULL) return; - SSdbTable *pTable = handle; - int32_t * pRefCount = (int32_t *)(pObj + pTable->refCountPos); + SSdbTable *pTable = tparam; + int32_t * pRefCount = (int32_t *)(pRow + pTable->refCountPos); int32_t refCount = atomic_add_fetch_32(pRefCount, 1); - sdbTrace("add ref to table:%s record:%p:%s:%d", pTable->tableName, pObj, sdbGetKeyStrFromObj(pTable, pObj), refCount); + sdbTrace("vgId:1, sdb:%s, inc ref to row:%p:%s:%d", pTable->name, pRow, sdbGetRowStr(pTable, pRow), refCount); } -void sdbDecRef(void *handle, void *pObj) { - if (pObj == NULL || handle == NULL) return; +void sdbDecRef(void *tparam, void *pRow) { + if (pRow == NULL || tparam == NULL) return; - SSdbTable *pTable = handle; - int32_t * pRefCount = (int32_t *)(pObj + pTable->refCountPos); + SSdbTable *pTable = tparam; + int32_t * pRefCount = (int32_t *)(pRow + pTable->refCountPos); int32_t refCount = atomic_sub_fetch_32(pRefCount, 1); - sdbTrace("def ref of table:%s record:%p:%s:%d", pTable->tableName, pObj, sdbGetKeyStrFromObj(pTable, pObj), refCount); + sdbTrace("vgId:1, sdb:%s, dec ref to row:%p:%s:%d", pTable->name, pRow, sdbGetRowStr(pTable, pRow), refCount); - int32_t *updateEnd = pObj + pTable->refCountPos - 4; + int32_t *updateEnd = pRow + pTable->refCountPos - 4; if (refCount <= 0 && *updateEnd) { - sdbTrace("table:%s, record:%p:%s:%d is destroyed", pTable->tableName, pObj, sdbGetKeyStrFromObj(pTable, pObj), refCount); - SSdbOper oper = {.pObj = pObj}; - (*pTable->destroyFp)(&oper); + sdbTrace("vgId:1, sdb:%s, row:%p:%s:%d destroyed", pTable->name, pRow, sdbGetRowStr(pTable, pRow), refCount); + SSdbRow row = {.pObj = pRow}; + (*pTable->fpDestroy)(&row); } } @@ -487,12 +472,12 @@ static void *sdbGetRowMetaFromObj(SSdbTable *pTable, void *key) { return sdbGetRowMeta(pTable, sdbGetObjKey(pTable, key)); } -void *sdbGetRow(void *handle, void *key) { - SSdbTable *pTable = handle; +void *sdbGetRow(void *tparam, void *key) { + SSdbTable *pTable = tparam; pthread_mutex_lock(&pTable->mutex); - void *pRow = sdbGetRowMeta(handle, key); - if (pRow) sdbIncRef(handle, pRow); + void *pRow = sdbGetRowMeta(pTable, key); + if (pRow) sdbIncRef(pTable, pRow); pthread_mutex_unlock(&pTable->mutex); return pRow; @@ -502,8 +487,8 @@ static void *sdbGetRowFromObj(SSdbTable *pTable, void *key) { return sdbGetRow(pTable, sdbGetObjKey(pTable, key)); } -static int32_t sdbInsertHash(SSdbTable *pTable, SSdbOper *pOper) { - void * key = sdbGetObjKey(pTable, pOper->pObj); +static int32_t sdbInsertHash(SSdbTable *pTable, SSdbRow *pRow) { + void * key = sdbGetObjKey(pTable, pRow->pObj); int32_t keySize = sizeof(int32_t); if (pTable->keyType == SDB_KEY_STRING || pTable->keyType == SDB_KEY_VAR_STRING) { @@ -511,43 +496,43 @@ static int32_t sdbInsertHash(SSdbTable *pTable, SSdbOper *pOper) { } pthread_mutex_lock(&pTable->mutex); - taosHashPut(pTable->iHandle, key, keySize, &pOper->pObj, sizeof(int64_t)); + taosHashPut(pTable->iHandle, key, keySize, &pRow->pObj, sizeof(int64_t)); pthread_mutex_unlock(&pTable->mutex); - sdbIncRef(pTable, pOper->pObj); + sdbIncRef(pTable, pRow->pObj); atomic_add_fetch_32(&pTable->numOfRows, 1); if (pTable->keyType == SDB_KEY_AUTO) { - pTable->autoIndex = MAX(pTable->autoIndex, *((uint32_t *)pOper->pObj)); + pTable->autoIndex = MAX(pTable->autoIndex, *((uint32_t *)pRow->pObj)); } else { atomic_add_fetch_32(&pTable->autoIndex, 1); } - sdbDebug("table:%s, insert record:%s to hash, rowSize:%d numOfRows:%" PRId64 ", msg:%p", pTable->tableName, - sdbGetKeyStrFromObj(pTable, pOper->pObj), pOper->rowSize, pTable->numOfRows, pOper->pMsg); + sdbDebug("vgId:1, sdb:%s, insert key:%s to hash, rowSize:%d rows:%" PRId64 ", msg:%p", pTable->name, + sdbGetRowStr(pTable, pRow->pObj), pRow->rowSize, pTable->numOfRows, pRow->pMsg); - int32_t code = (*pTable->insertFp)(pOper); + int32_t code = (*pTable->fpInsert)(pRow); if (code != TSDB_CODE_SUCCESS) { - sdbError("table:%s, failed to insert record:%s to hash, remove it", pTable->tableName, - sdbGetKeyStrFromObj(pTable, pOper->pObj)); - sdbDeleteHash(pTable, pOper); + sdbError("vgId:1, sdb:%s, failed to insert key:%s to hash, remove it", pTable->name, + sdbGetRowStr(pTable, pRow->pObj)); + sdbDeleteHash(pTable, pRow); } return TSDB_CODE_SUCCESS; } -static int32_t sdbDeleteHash(SSdbTable *pTable, SSdbOper *pOper) { - int32_t *updateEnd = pOper->pObj + pTable->refCountPos - 4; +static int32_t sdbDeleteHash(SSdbTable *pTable, SSdbRow *pRow) { + int32_t *updateEnd = pRow->pObj + pTable->refCountPos - 4; bool set = atomic_val_compare_exchange_32(updateEnd, 0, 1) == 0; if (!set) { - sdbError("table:%s, failed to delete record:%s from hash, for it already removed", pTable->tableName, - sdbGetKeyStrFromObj(pTable, pOper->pObj)); + sdbError("vgId:1, sdb:%s, failed to delete key:%s from hash, for it already removed", pTable->name, + sdbGetRowStr(pTable, pRow->pObj)); return TSDB_CODE_MND_SDB_OBJ_NOT_THERE; } - (*pTable->deleteFp)(pOper); + (*pTable->fpDelete)(pRow); - void * key = sdbGetObjKey(pTable, pOper->pObj); + void * key = sdbGetObjKey(pTable, pRow->pObj); int32_t keySize = sizeof(int32_t); if (pTable->keyType == SDB_KEY_STRING || pTable->keyType == SDB_KEY_VAR_STRING) { keySize = strlen((char *)key); @@ -558,310 +543,221 @@ static int32_t sdbDeleteHash(SSdbTable *pTable, SSdbOper *pOper) { pthread_mutex_unlock(&pTable->mutex); atomic_sub_fetch_32(&pTable->numOfRows, 1); - - sdbDebug("table:%s, delete record:%s from hash, numOfRows:%" PRId64 ", msg:%p", pTable->tableName, - sdbGetKeyStrFromObj(pTable, pOper->pObj), pTable->numOfRows, pOper->pMsg); - sdbDecRef(pTable, pOper->pObj); + sdbDebug("vgId:1, sdb:%s, delete key:%s from hash, numOfRows:%" PRId64 ", msg:%p", pTable->name, + sdbGetRowStr(pTable, pRow->pObj), pTable->numOfRows, pRow->pMsg); + + sdbDecRef(pTable, pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t sdbUpdateHash(SSdbTable *pTable, SSdbOper *pOper) { - sdbDebug("table:%s, update record:%s in hash, numOfRows:%" PRId64 ", msg:%p", pTable->tableName, - sdbGetKeyStrFromObj(pTable, pOper->pObj), pTable->numOfRows, pOper->pMsg); +static int32_t sdbUpdateHash(SSdbTable *pTable, SSdbRow *pRow) { + sdbDebug("vgId:1, sdb:%s, update key:%s in hash, numOfRows:%" PRId64 ", msg:%p", pTable->name, + sdbGetRowStr(pTable, pRow->pObj), pTable->numOfRows, pRow->pMsg); - (*pTable->updateFp)(pOper); + (*pTable->fpUpdate)(pRow); return TSDB_CODE_SUCCESS; } -static int sdbWrite(void *param, void *data, int32_t type, void *pMsg) { - SSdbOper *pOper = param; - SWalHead *pHead = data; +static int sdbProcessWrite(void *wparam, void *hparam, int32_t qtype, void *unused) { + SSdbRow *pRow = wparam; + SWalHead *pHead = hparam; int32_t tableId = pHead->msgType / 10; int32_t action = pHead->msgType % 10; SSdbTable *pTable = sdbGetTableFromId(tableId); assert(pTable != NULL); - pthread_mutex_lock(&tsSdbObj.mutex); + pthread_mutex_lock(&tsSdbMgmt.mutex); if (pHead->version == 0) { // assign version - tsSdbObj.version++; - pHead->version = tsSdbObj.version; + tsSdbMgmt.version++; + pHead->version = tsSdbMgmt.version; } else { // for data from WAL or forward, version may be smaller - if (pHead->version <= tsSdbObj.version) { - pthread_mutex_unlock(&tsSdbObj.mutex); - sdbDebug("table:%s, failed to restore %s record:%s from source(%d), ver:%" PRId64 " too large, sdb ver:%" PRId64, - pTable->tableName, sdbGetActionStr(action), sdbGetKeyStr(pTable, pHead->cont), type, pHead->version, tsSdbObj.version); + if (pHead->version <= tsSdbMgmt.version) { + pthread_mutex_unlock(&tsSdbMgmt.mutex); + sdbDebug("vgId:1, sdb:%s, failed to restore %s key:%s from source(%d), hver:%" PRIu64 " too large, mver:%" PRIu64, + pTable->name, actStr[action], sdbGetKeyStr(pTable, pHead->cont), qtype, pHead->version, tsSdbMgmt.version); return TSDB_CODE_SUCCESS; - } else if (pHead->version != tsSdbObj.version + 1) { - pthread_mutex_unlock(&tsSdbObj.mutex); - sdbError("table:%s, failed to restore %s record:%s from source(%d), ver:%" PRId64 " too large, sdb ver:%" PRId64, - pTable->tableName, sdbGetActionStr(action), sdbGetKeyStr(pTable, pHead->cont), type, pHead->version, tsSdbObj.version); + } else if (pHead->version != tsSdbMgmt.version + 1) { + pthread_mutex_unlock(&tsSdbMgmt.mutex); + sdbError("vgId:1, sdb:%s, failed to restore %s key:%s from source(%d), hver:%" PRIu64 " too large, mver:%" PRIu64, + pTable->name, actStr[action], sdbGetKeyStr(pTable, pHead->cont), qtype, pHead->version, tsSdbMgmt.version); return TSDB_CODE_SYN_INVALID_VERSION; } else { - tsSdbObj.version = pHead->version; + tsSdbMgmt.version = pHead->version; } } - int32_t code = walWrite(tsSdbObj.wal, pHead); + int32_t code = walWrite(tsSdbMgmt.wal, pHead); if (code < 0) { - pthread_mutex_unlock(&tsSdbObj.mutex); + pthread_mutex_unlock(&tsSdbMgmt.mutex); return code; } - pthread_mutex_unlock(&tsSdbObj.mutex); + pthread_mutex_unlock(&tsSdbMgmt.mutex); - // from app, oper is created - if (pOper != NULL) { + // from app, row is created + if (pRow != NULL) { // forward to peers - pOper->processedCount = 0; - int32_t syncCode = syncForwardToPeer(tsSdbObj.sync, pHead, pOper, TAOS_QTYPE_RPC); - if (syncCode <= 0) pOper->processedCount = 1; + pRow->processedCount = 0; + int32_t syncCode = syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC); + if (syncCode <= 0) pRow->processedCount = 1; if (syncCode < 0) { - sdbError("table:%s, failed to forward request, result:%s action:%s record:%s ver:%" PRId64 ", msg:%p", pTable->tableName, - tstrerror(syncCode), sdbGetActionStr(action), sdbGetKeyStr(pTable, pHead->cont), pHead->version, pOper->pMsg); + sdbError("vgId:1, sdb:%s, failed to forward req since %s action:%s key:%s hver:%" PRIu64 ", msg:%p", pTable->name, + tstrerror(syncCode), actStr[action], sdbGetKeyStr(pTable, pHead->cont), pHead->version, pRow->pMsg); } else if (syncCode > 0) { - sdbDebug("table:%s, forward request is sent, action:%s record:%s ver:%" PRId64 ", msg:%p", pTable->tableName, - sdbGetActionStr(action), sdbGetKeyStr(pTable, pHead->cont), pHead->version, pOper->pMsg); + sdbDebug("vgId:1, sdb:%s, forward req is sent, action:%s key:%s hver:%" PRIu64 ", msg:%p", pTable->name, + actStr[action], sdbGetKeyStr(pTable, pHead->cont), pHead->version, pRow->pMsg); } else { - sdbTrace("table:%s, no need to send fwd request, action:%s record:%s ver:%" PRId64 ", msg:%p", pTable->tableName, - sdbGetActionStr(action), sdbGetKeyStr(pTable, pHead->cont), pHead->version, pOper->pMsg); + sdbTrace("vgId:1, sdb:%s, no need to send fwd req, action:%s key:%s hver:%" PRIu64 ", msg:%p", pTable->name, + actStr[action], sdbGetKeyStr(pTable, pHead->cont), pHead->version, pRow->pMsg); } return syncCode; } - sdbDebug("table:%s, record from wal/fwd is disposed, action:%s record:%s ver:%" PRId64, pTable->tableName, - sdbGetActionStr(action), sdbGetKeyStr(pTable, pHead->cont), pHead->version); + sdbDebug("vgId:1, sdb:%s, record from wal/fwd is disposed, action:%s key:%s hver:%" PRIu64, pTable->name, + actStr[action], sdbGetKeyStr(pTable, pHead->cont), pHead->version); // even it is WAL/FWD, it shall be called to update version in sync - syncForwardToPeer(tsSdbObj.sync, pHead, pOper, TAOS_QTYPE_RPC); + syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC); - // from wal or forward msg, oper not created, should add into hash + // from wal or forward msg, row not created, should add into hash if (action == SDB_ACTION_INSERT) { - SSdbOper oper = {.rowSize = pHead->len, .rowData = pHead->cont, .table = pTable}; - code = (*pTable->decodeFp)(&oper); - return sdbInsertHash(pTable, &oper); + SSdbRow row = {.rowSize = pHead->len, .rowData = pHead->cont, .pTable = pTable}; + code = (*pTable->fpDecode)(&row); + return sdbInsertHash(pTable, &row); } else if (action == SDB_ACTION_DELETE) { - void *pRow = sdbGetRowMeta(pTable, pHead->cont); - if (pRow == NULL) { - sdbDebug("table:%s, object:%s not exist in hash, ignore delete action", pTable->tableName, + void *pObj = sdbGetRowMeta(pTable, pHead->cont); + if (pObj == NULL) { + sdbDebug("vgId:1, sdb:%s, object:%s not exist in hash, ignore delete action", pTable->name, sdbGetKeyStr(pTable, pHead->cont)); return TSDB_CODE_SUCCESS; } - SSdbOper oper = {.table = pTable, .pObj = pRow}; - return sdbDeleteHash(pTable, &oper); + SSdbRow row = {.pTable = pTable, .pObj = pObj}; + return sdbDeleteHash(pTable, &row); } else if (action == SDB_ACTION_UPDATE) { - void *pRow = sdbGetRowMeta(pTable, pHead->cont); - if (pRow == NULL) { - sdbDebug("table:%s, object:%s not exist in hash, ignore update action", pTable->tableName, + void *pObj = sdbGetRowMeta(pTable, pHead->cont); + if (pObj == NULL) { + sdbDebug("vgId:1, sdb:%s, object:%s not exist in hash, ignore update action", pTable->name, sdbGetKeyStr(pTable, pHead->cont)); return TSDB_CODE_SUCCESS; } - SSdbOper oper = {.rowSize = pHead->len, .rowData = pHead->cont, .table = pTable}; - code = (*pTable->decodeFp)(&oper); - return sdbUpdateHash(pTable, &oper); + SSdbRow row = {.rowSize = pHead->len, .rowData = pHead->cont, .pTable = pTable}; + code = (*pTable->fpDecode)(&row); + return sdbUpdateHash(pTable, &row); } else { return TSDB_CODE_MND_INVALID_MSG_TYPE; } } -int32_t sdbInsertRow(SSdbOper *pOper) { - SSdbTable *pTable = (SSdbTable *)pOper->table; +int32_t sdbInsertRow(SSdbRow *pRow) { + SSdbTable *pTable = pRow->pTable; if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE; - if (sdbGetRowFromObj(pTable, pOper->pObj)) { - sdbError("table:%s, failed to insert record:%s, already exist", pTable->tableName, - sdbGetKeyStrFromObj(pTable, pOper->pObj)); - sdbDecRef(pTable, pOper->pObj); + if (sdbGetRowFromObj(pTable, pRow->pObj)) { + sdbError("vgId:1, sdb:%s, failed to insert:%s since it exist", pTable->name, sdbGetRowStr(pTable, pRow->pObj)); + sdbDecRef(pTable, pRow->pObj); return TSDB_CODE_MND_SDB_OBJ_ALREADY_THERE; } if (pTable->keyType == SDB_KEY_AUTO) { - *((uint32_t *)pOper->pObj) = atomic_add_fetch_32(&pTable->autoIndex, 1); + *((uint32_t *)pRow->pObj) = atomic_add_fetch_32(&pTable->autoIndex, 1); // let vgId increase from 2 - if (pTable->autoIndex == 1 && strcmp(pTable->tableName, "vgroups") == 0) { - *((uint32_t *)pOper->pObj) = atomic_add_fetch_32(&pTable->autoIndex, 1); + if (pTable->autoIndex == 1 && pTable->id == SDB_TABLE_VGROUP) { + *((uint32_t *)pRow->pObj) = atomic_add_fetch_32(&pTable->autoIndex, 1); } } - int32_t code = sdbInsertHash(pTable, pOper); + int32_t code = sdbInsertHash(pTable, pRow); if (code != TSDB_CODE_SUCCESS) { - sdbError("table:%s, failed to insert into hash", pTable->tableName); + sdbError("vgId:1, sdb:%s, failed to insert:%s into hash", pTable->name, sdbGetRowStr(pTable, pRow->pObj)); return code; } // just insert data into memory - if (pOper->type != SDB_OPER_GLOBAL) { + if (pRow->type != SDB_OPER_GLOBAL) { return TSDB_CODE_SUCCESS; } - if (pOper->reqFp) { - return (*pOper->reqFp)(pOper->pMsg); + if (pRow->fpReq) { + return (*pRow->fpReq)(pRow->pMsg); } else { - return sdbInsertRowImp(pOper); + return sdbWriteRowToQueue(pRow, SDB_ACTION_INSERT); } } -int32_t sdbInsertRowImp(SSdbOper *pOper) { - SSdbTable *pTable = (SSdbTable *)pOper->table; - if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE; - - int32_t size = sizeof(SSdbOper) + sizeof(SWalHead) + pTable->maxRowSize + SDB_SYNC_HACK; - SSdbOper *pNewOper = taosAllocateQitem(size); - - SWalHead *pHead = (void *)pNewOper + sizeof(SSdbOper) + SDB_SYNC_HACK; - pHead->version = 0; - pHead->len = pOper->rowSize; - pHead->msgType = pTable->tableId * 10 + SDB_ACTION_INSERT; - - pOper->rowData = pHead->cont; - (*pTable->encodeFp)(pOper); - pHead->len = pOper->rowSize; - - memcpy(pNewOper, pOper, sizeof(SSdbOper)); - - if (pNewOper->pMsg != NULL) { - sdbDebug("app:%p:%p, table:%s record:%p:%s, insert action is add to sdb queue", pNewOper->pMsg->rpcMsg.ahandle, - pNewOper->pMsg, pTable->tableName, pOper->pObj, sdbGetKeyStrFromObj(pTable, pOper->pObj)); - } - - sdbIncRef(pNewOper->table, pNewOper->pObj); - taosWriteQitem(tsSdbWriteQueue, TAOS_QTYPE_RPC, pNewOper); - - return TSDB_CODE_MND_ACTION_IN_PROGRESS; -} - -bool sdbCheckRowDeleted(void *pTableInput, void *pRow) { - SSdbTable *pTable = pTableInput; +bool sdbCheckRowDeleted(void *tparam, void *pRow) { + SSdbTable *pTable = tparam; if (pTable == NULL) return false; int32_t *updateEnd = pRow + pTable->refCountPos - 4; return atomic_val_compare_exchange_32(updateEnd, 1, 1) == 1; } -int32_t sdbDeleteRow(SSdbOper *pOper) { - SSdbTable *pTable = (SSdbTable *)pOper->table; +int32_t sdbDeleteRow(SSdbRow *pRow) { + SSdbTable *pTable = pRow->pTable; if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE; - void *pRow = sdbGetRowMetaFromObj(pTable, pOper->pObj); - if (pRow == NULL) { - sdbDebug("table:%s, record is not there, delete failed", pTable->tableName); + void *pObj = sdbGetRowMetaFromObj(pTable, pRow->pObj); + if (pObj == NULL) { + sdbDebug("vgId:1, sdb:%s, record is not there, delete failed", pTable->name); return TSDB_CODE_MND_SDB_OBJ_NOT_THERE; } - sdbIncRef(pTable, pOper->pObj); - - int32_t code = sdbDeleteHash(pTable, pOper); + int32_t code = sdbDeleteHash(pTable, pRow); if (code != TSDB_CODE_SUCCESS) { - sdbError("table:%s, failed to delete from hash", pTable->tableName); - sdbDecRef(pTable, pOper->pObj); + sdbError("vgId:1, sdb:%s, failed to delete from hash", pTable->name); return code; } // just delete data from memory - if (pOper->type != SDB_OPER_GLOBAL) { - sdbDecRef(pTable, pOper->pObj); + if (pRow->type != SDB_OPER_GLOBAL) { return TSDB_CODE_SUCCESS; } - if (pOper->reqFp) { - return (*pOper->reqFp)(pOper->pMsg); + if (pRow->fpReq) { + return (*pRow->fpReq)(pRow->pMsg); } else { - return sdbDeleteRowImp(pOper); + return sdbWriteRowToQueue(pRow, SDB_ACTION_DELETE); } } -int32_t sdbDeleteRowImp(SSdbOper *pOper) { - SSdbTable *pTable = (SSdbTable *)pOper->table; +int32_t sdbUpdateRow(SSdbRow *pRow) { + SSdbTable *pTable = pRow->pTable; if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE; - int32_t size = sizeof(SSdbOper) + sizeof(SWalHead) + pTable->maxRowSize + SDB_SYNC_HACK; - SSdbOper *pNewOper = taosAllocateQitem(size); - - SWalHead *pHead = (void *)pNewOper + sizeof(SSdbOper) + SDB_SYNC_HACK; - pHead->version = 0; - pHead->msgType = pTable->tableId * 10 + SDB_ACTION_DELETE; - - pOper->rowData = pHead->cont; - (*pTable->encodeFp)(pOper); - pHead->len = pOper->rowSize; - - memcpy(pNewOper, pOper, sizeof(SSdbOper)); - - if (pNewOper->pMsg != NULL) { - sdbDebug("app:%p:%p, table:%s record:%p:%s, delete action is add to sdb queue", pNewOper->pMsg->rpcMsg.ahandle, - pNewOper->pMsg, pTable->tableName, pOper->pObj, sdbGetKeyStrFromObj(pTable, pOper->pObj)); - } - - taosWriteQitem(tsSdbWriteQueue, TAOS_QTYPE_RPC, pNewOper); - - return TSDB_CODE_MND_ACTION_IN_PROGRESS; -} - -int32_t sdbUpdateRow(SSdbOper *pOper) { - SSdbTable *pTable = (SSdbTable *)pOper->table; - if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE; - - void *pRow = sdbGetRowMetaFromObj(pTable, pOper->pObj); - if (pRow == NULL) { - sdbDebug("table:%s, record is not there, update failed", pTable->tableName); + void *pObj = sdbGetRowMetaFromObj(pTable, pRow->pObj); + if (pObj == NULL) { + sdbDebug("vgId:1, sdb:%s, record is not there, update failed", pTable->name); return TSDB_CODE_MND_SDB_OBJ_NOT_THERE; } - int32_t code = sdbUpdateHash(pTable, pOper); + int32_t code = sdbUpdateHash(pTable, pRow); if (code != TSDB_CODE_SUCCESS) { - sdbError("table:%s, failed to update hash", pTable->tableName); + sdbError("vgId:1, sdb:%s, failed to update hash", pTable->name); return code; } // just update data in memory - if (pOper->type != SDB_OPER_GLOBAL) { + if (pRow->type != SDB_OPER_GLOBAL) { return TSDB_CODE_SUCCESS; } - if (pOper->reqFp) { - return (*pOper->reqFp)(pOper->pMsg); + if (pRow->fpReq) { + return (*pRow->fpReq)(pRow->pMsg); } else { - return sdbUpdateRowImp(pOper); + return sdbWriteRowToQueue(pRow, SDB_ACTION_UPDATE); } } -int32_t sdbUpdateRowImp(SSdbOper *pOper) { - SSdbTable *pTable = (SSdbTable *)pOper->table; - if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE; - - int32_t size = sizeof(SSdbOper) + sizeof(SWalHead) + pTable->maxRowSize + SDB_SYNC_HACK; - SSdbOper *pNewOper = taosAllocateQitem(size); - - SWalHead *pHead = (void *)pNewOper + sizeof(SSdbOper) + SDB_SYNC_HACK; - pHead->version = 0; - pHead->msgType = pTable->tableId * 10 + SDB_ACTION_UPDATE; - - pOper->rowData = pHead->cont; - (*pTable->encodeFp)(pOper); - pHead->len = pOper->rowSize; - - memcpy(pNewOper, pOper, sizeof(SSdbOper)); - - if (pNewOper->pMsg != NULL) { - sdbDebug("app:%p:%p, table:%s record:%p:%s, update action is add to sdb queue", pNewOper->pMsg->rpcMsg.ahandle, - pNewOper->pMsg, pTable->tableName, pOper->pObj, sdbGetKeyStrFromObj(pTable, pOper->pObj)); - } - - sdbIncRef(pNewOper->table, pNewOper->pObj); - taosWriteQitem(tsSdbWriteQueue, TAOS_QTYPE_RPC, pNewOper); - - return TSDB_CODE_MND_ACTION_IN_PROGRESS; -} - -void *sdbFetchRow(void *handle, void *pNode, void **ppRow) { - SSdbTable *pTable = (SSdbTable *)handle; +void *sdbFetchRow(void *tparam, void *pNode, void **ppRow) { + SSdbTable *pTable = tparam; *ppRow = NULL; if (pTable == NULL) return NULL; @@ -882,7 +778,7 @@ void *sdbFetchRow(void *handle, void *pNode, void **ppRow) { } *ppRow = *ppMetaRow; - sdbIncRef(handle, *ppMetaRow); + sdbIncRef(pTable, *ppMetaRow); return pIter; } @@ -899,19 +795,19 @@ void *sdbOpenTable(SSdbTableDesc *pDesc) { if (pTable == NULL) return NULL; pthread_mutex_init(&pTable->mutex, NULL); - tstrncpy(pTable->tableName, pDesc->tableName, SDB_TABLE_LEN); + tstrncpy(pTable->name, pDesc->name, SDB_TABLE_LEN); pTable->keyType = pDesc->keyType; - pTable->tableId = pDesc->tableId; + pTable->id = pDesc->id; pTable->hashSessions = pDesc->hashSessions; pTable->maxRowSize = pDesc->maxRowSize; pTable->refCountPos = pDesc->refCountPos; - pTable->insertFp = pDesc->insertFp; - pTable->deleteFp = pDesc->deleteFp; - pTable->updateFp = pDesc->updateFp; - pTable->encodeFp = pDesc->encodeFp; - pTable->decodeFp = pDesc->decodeFp; - pTable->destroyFp = pDesc->destroyFp; - pTable->restoredFp = pDesc->restoredFp; + pTable->fpInsert = pDesc->fpInsert; + pTable->fpDelete = pDesc->fpDelete; + pTable->fpUpdate = pDesc->fpUpdate; + pTable->fpEncode = pDesc->fpEncode; + pTable->fpDecode = pDesc->fpDecode; + pTable->fpDestroy = pDesc->fpDestroy; + pTable->fpRestored = pDesc->fpRestored; _hash_fn_t hashFp = taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT); if (pTable->keyType == SDB_KEY_STRING || pTable->keyType == SDB_KEY_VAR_STRING) { @@ -919,8 +815,8 @@ void *sdbOpenTable(SSdbTableDesc *pDesc) { } pTable->iHandle = taosHashInit(pTable->hashSessions, hashFp, true, true); - tsSdbObj.numOfTables++; - tsSdbObj.tableList[pTable->tableId] = pTable; + tsSdbMgmt.numOfTables++; + tsSdbMgmt.tableList[pTable->id] = pTable; return pTable; } @@ -928,87 +824,87 @@ void sdbCloseTable(void *handle) { SSdbTable *pTable = (SSdbTable *)handle; if (pTable == NULL) return; - tsSdbObj.numOfTables--; - tsSdbObj.tableList[pTable->tableId] = NULL; + tsSdbMgmt.numOfTables--; + tsSdbMgmt.tableList[pTable->id] = NULL; SHashMutableIterator *pIter = taosHashCreateIter(pTable->iHandle); while (taosHashIterNext(pIter)) { void **ppRow = taosHashIterGet(pIter); if (ppRow == NULL) continue; - SSdbOper oper = { + SSdbRow row = { .pObj = *ppRow, - .table = pTable, + .pTable = pTable, }; - (*pTable->destroyFp)(&oper); + (*pTable->fpDestroy)(&row); } taosHashDestroyIter(pIter); taosHashCleanup(pTable->iHandle); pthread_mutex_destroy(&pTable->mutex); - sdbDebug("table:%s, is closed, numOfTables:%d", pTable->tableName, tsSdbObj.numOfTables); + sdbDebug("vgId:1, sdb:%s, is closed, numOfTables:%d", pTable->name, tsSdbMgmt.numOfTables); free(pTable); } -int32_t sdbInitWriteWorker() { +static int32_t sdbInitWorker() { tsSdbPool.num = 1; - tsSdbPool.writeWorker = (SSdbWriteWorker *)calloc(sizeof(SSdbWriteWorker), tsSdbPool.num); + tsSdbPool.worker = calloc(sizeof(SSdbWorker), tsSdbPool.num); - if (tsSdbPool.writeWorker == NULL) return -1; + if (tsSdbPool.worker == NULL) return -1; for (int32_t i = 0; i < tsSdbPool.num; ++i) { - SSdbWriteWorker *pWorker = tsSdbPool.writeWorker + i; + SSdbWorker *pWorker = tsSdbPool.worker + i; pWorker->workerId = i; } - sdbAllocWriteQueue(); + sdbAllocQueue(); - mInfo("sdb write is opened"); + mInfo("vgId:1, sdb write is opened"); return 0; } -void sdbCleanupWriteWorker() { +static void sdbCleanupWorker() { for (int32_t i = 0; i < tsSdbPool.num; ++i) { - SSdbWriteWorker *pWorker = tsSdbPool.writeWorker + i; + SSdbWorker *pWorker = tsSdbPool.worker + i; if (pWorker->thread) { - taosQsetThreadResume(tsSdbWriteQset); + taosQsetThreadResume(tsSdbWQset); } } for (int32_t i = 0; i < tsSdbPool.num; ++i) { - SSdbWriteWorker *pWorker = tsSdbPool.writeWorker + i; + SSdbWorker *pWorker = tsSdbPool.worker + i; if (pWorker->thread) { pthread_join(pWorker->thread, NULL); } } - sdbFreeWritequeue(); - tfree(tsSdbPool.writeWorker); + sdbFreeQueue(); + tfree(tsSdbPool.worker); - mInfo("sdb write is closed"); + mInfo("vgId:1, sdb write is closed"); } -int32_t sdbAllocWriteQueue() { - tsSdbWriteQueue = taosOpenQueue(); - if (tsSdbWriteQueue == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; +static int32_t sdbAllocQueue() { + tsSdbWQueue = taosOpenQueue(); + if (tsSdbWQueue == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - tsSdbWriteQset = taosOpenQset(); - if (tsSdbWriteQset == NULL) { - taosCloseQueue(tsSdbWriteQueue); + tsSdbWQset = taosOpenQset(); + if (tsSdbWQset == NULL) { + taosCloseQueue(tsSdbWQueue); return TSDB_CODE_MND_OUT_OF_MEMORY; } - taosAddIntoQset(tsSdbWriteQset, tsSdbWriteQueue, NULL); + taosAddIntoQset(tsSdbWQset, tsSdbWQueue, NULL); - tsSdbWriteQall = taosAllocateQall(); - if (tsSdbWriteQall == NULL) { - taosCloseQset(tsSdbWriteQset); - taosCloseQueue(tsSdbWriteQueue); + tsSdbWQall = taosAllocateQall(); + if (tsSdbWQall == NULL) { + taosCloseQset(tsSdbWQset); + taosCloseQueue(tsSdbWQueue); return TSDB_CODE_MND_OUT_OF_MEMORY; } for (int32_t i = 0; i < tsSdbPool.num; ++i) { - SSdbWriteWorker *pWorker = tsSdbPool.writeWorker + i; + SSdbWorker *pWorker = tsSdbPool.worker + i; pWorker->workerId = i; pthread_attr_t thAttr; @@ -1017,9 +913,9 @@ int32_t sdbAllocWriteQueue() { if (pthread_create(&pWorker->thread, &thAttr, sdbWorkerFp, pWorker) != 0) { mError("failed to create thread to process sdb write queue, reason:%s", strerror(errno)); - taosFreeQall(tsSdbWriteQall); - taosCloseQset(tsSdbWriteQset); - taosCloseQueue(tsSdbWriteQueue); + taosFreeQall(tsSdbWQall); + taosCloseQset(tsSdbWQset); + taosCloseQueue(tsSdbWQueue); return TSDB_CODE_MND_OUT_OF_MEMORY; } @@ -1027,85 +923,128 @@ int32_t sdbAllocWriteQueue() { mDebug("sdb write worker:%d is launched, total:%d", pWorker->workerId, tsSdbPool.num); } - mDebug("sdb write queue:%p is allocated", tsSdbWriteQueue); + mDebug("sdb write queue:%p is allocated", tsSdbWQueue); return TSDB_CODE_SUCCESS; } -void sdbFreeWritequeue() { - taosCloseQueue(tsSdbWriteQueue); - taosFreeQall(tsSdbWriteQall); - taosCloseQset(tsSdbWriteQset); - tsSdbWriteQall = NULL; - tsSdbWriteQset = NULL; - tsSdbWriteQueue = NULL; +static void sdbFreeQueue() { + taosCloseQueue(tsSdbWQueue); + taosFreeQall(tsSdbWQall); + taosCloseQset(tsSdbWQset); + tsSdbWQall = NULL; + tsSdbWQset = NULL; + tsSdbWQueue = NULL; } -int32_t sdbWriteToQueue(void *param, void *data, int32_t qtype, void *pMsg) { - SWalHead *pHead = data; - int32_t size = sizeof(SWalHead) + pHead->len; - SWalHead *pWal = taosAllocateQitem(size); - memcpy(pWal, pHead, size); +static int32_t sdbWriteToQueue(SSdbRow *pRow, int32_t qtype) { + SWalHead *pHead = pRow->pHead; - taosWriteQitem(tsSdbWriteQueue, qtype, pWal); - return 0; + if (pHead->len > TSDB_MAX_WAL_SIZE) { + sdbError("vgId:1, wal len:%d exceeds limit, hver:%" PRIu64, pHead->len, pHead->version); + taosFreeQitem(pRow); + return TSDB_CODE_WAL_SIZE_LIMIT; + } + + int32_t queued = atomic_add_fetch_32(&tsSdbMgmt.queuedMsg, 1); + if (queued > MAX_QUEUED_MSG_NUM) { + sdbDebug("vgId:1, too many msg:%d in sdb queue, flow control", queued); + taosMsleep(1); + } + + sdbIncRef(pRow->pTable, pRow->pObj); + + sdbTrace("vgId:1, msg:%p qtype:%s write into to sdb queue, queued:%d", pRow->pMsg, qtypeStr[qtype], queued); + taosWriteQitem(tsSdbWQueue, qtype, pRow); + + return TSDB_CODE_MND_ACTION_IN_PROGRESS; } -static void *sdbWorkerFp(void *param) { - SWalHead *pHead; - SSdbOper *pOper; - int32_t type; - int32_t numOfMsgs; - void * item; - void * unUsed; +static void sdbFreeFromQueue(SSdbRow *pRow) { + int32_t queued = atomic_sub_fetch_32(&tsSdbMgmt.queuedMsg, 1); + sdbTrace("vgId:1, msg:%p free from sdb queue, queued:%d", pRow->pMsg, queued); + + sdbDecRef(pRow->pTable, pRow->pObj); + taosFreeQitem(pRow); +} + +static int32_t sdbWriteWalToQueue(void *vparam, void *wparam, int32_t qtype, void *rparam) { + SWalHead *pHead = wparam; + + int32_t size = sizeof(SSdbRow) + sizeof(SWalHead) + pHead->len; + SSdbRow *pRow = taosAllocateQitem(size); + if (pRow == NULL) { + return TSDB_CODE_VND_OUT_OF_MEMORY; + } + + memcpy(pRow->pHead, pHead, sizeof(SWalHead) + pHead->len); + pRow->rowData = pRow->pHead->cont; + + return sdbWriteToQueue(pRow, qtype); +} + +static int32_t sdbWriteRowToQueue(SSdbRow *pInputRow, int32_t action) { + SSdbTable *pTable = pInputRow->pTable; + if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE; + + int32_t size = sizeof(SSdbRow) + sizeof(SWalHead) + pTable->maxRowSize; + SSdbRow *pRow = taosAllocateQitem(size); + if (pRow == NULL) { + return TSDB_CODE_VND_OUT_OF_MEMORY; + } + + memcpy(pRow, pInputRow, sizeof(SSdbRow)); + pRow->processedCount = 1; + + SWalHead *pHead = pRow->pHead; + pRow->rowData = pHead->cont; + (*pTable->fpEncode)(pRow); + + pHead->len = pRow->rowSize; + pHead->version = 0; + pHead->msgType = pTable->id * 10 + action; + + return sdbWriteToQueue(pRow, TAOS_QTYPE_RPC); +} + +int32_t sdbInsertRowToQueue(SSdbRow *pRow) { return sdbWriteRowToQueue(pRow, SDB_ACTION_INSERT); } + +static void *sdbWorkerFp(void *pWorker) { + SSdbRow *pRow; + int32_t qtype; + void * unUsed; while (1) { - numOfMsgs = taosReadAllQitemsFromQset(tsSdbWriteQset, tsSdbWriteQall, &unUsed); + int32_t numOfMsgs = taosReadAllQitemsFromQset(tsSdbWQset, tsSdbWQall, &unUsed); if (numOfMsgs == 0) { - sdbDebug("qset:%p, sdb got no message from qset, exiting", tsSdbWriteQset); + sdbDebug("qset:%p, sdb got no message from qset, exiting", tsSdbWQset); break; } for (int32_t i = 0; i < numOfMsgs; ++i) { - taosGetQitem(tsSdbWriteQall, &type, &item); - if (type == TAOS_QTYPE_RPC) { - pOper = (SSdbOper *)item; - pOper->processedCount = 1; - pHead = (void *)pOper + sizeof(SSdbOper) + SDB_SYNC_HACK; - if (pOper->pMsg != NULL) { - sdbDebug("app:%p:%p, table:%s record:%p:%s ver:%" PRIu64 ", will be processed in sdb queue", - pOper->pMsg->rpcMsg.ahandle, pOper->pMsg, ((SSdbTable *)pOper->table)->tableName, pOper->pObj, - sdbGetKeyStr(pOper->table, pHead->cont), pHead->version); - } - } else { - pHead = (SWalHead *)item; - pOper = NULL; - } + taosGetQitem(tsSdbWQall, &qtype, (void **)&pRow); + sdbTrace("vgId:1, msg:%p, row:%p hver:%" PRIu64 ", will be processed in sdb queue", pRow->pMsg, pRow->pObj, + pRow->pHead->version); - int32_t code = sdbWrite(pOper, pHead, type, NULL); - if (code > 0) code = 0; - if (pOper) { - pOper->retCode = code; - } else { - pHead->len = code; // hackway - } + pRow->code = sdbProcessWrite((qtype == TAOS_QTYPE_RPC) ? pRow : NULL, pRow->pHead, qtype, NULL); + if (pRow->code > 0) pRow->code = 0; + + sdbTrace("vgId:1, msg:%p is processed in sdb queue, code:%x", pRow->pMsg, pRow->code); } - walFsync(tsSdbObj.wal, true); + walFsync(tsSdbMgmt.wal, true); // browse all items, and process them one by one - taosResetQitems(tsSdbWriteQall); + taosResetQitems(tsSdbWQall); for (int32_t i = 0; i < numOfMsgs; ++i) { - taosGetQitem(tsSdbWriteQall, &type, &item); + taosGetQitem(tsSdbWQall, &qtype, (void **)&pRow); - if (type == TAOS_QTYPE_RPC) { - pOper = (SSdbOper *)item; - sdbConfirmForward(NULL, pOper, pOper->retCode); - } else if (type == TAOS_QTYPE_FWD) { - pHead = (SWalHead *)item; - syncConfirmForward(tsSdbObj.sync, pHead->version, pHead->len); - taosFreeQitem(item); + if (qtype == TAOS_QTYPE_RPC) { + sdbConfirmForward(NULL, pRow, pRow->code); } else { - taosFreeQitem(item); + if (qtype == TAOS_QTYPE_FWD) { + syncConfirmForward(tsSdbMgmt.sync, pRow->pHead->version, pRow->code); + } + sdbFreeFromQueue(pRow); } } } diff --git a/src/mnode/src/mnodeTable.c b/src/mnode/src/mnodeTable.c index 2b5e6455c0..4d5f0808f5 100644 --- a/src/mnode/src/mnodeTable.c +++ b/src/mnode/src/mnodeTable.c @@ -99,13 +99,13 @@ static void mnodeDestroyChildTable(SCTableObj *pTable) { tfree(pTable); } -static int32_t mnodeChildTableActionDestroy(SSdbOper *pOper) { - mnodeDestroyChildTable(pOper->pObj); +static int32_t mnodeChildTableActionDestroy(SSdbRow *pRow) { + mnodeDestroyChildTable(pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t mnodeChildTableActionInsert(SSdbOper *pOper) { - SCTableObj *pTable = pOper->pObj; +static int32_t mnodeChildTableActionInsert(SSdbRow *pRow) { + SCTableObj *pTable = pRow->pObj; SVgObj *pVgroup = mnodeGetVgroup(pTable->vgId); if (pVgroup == NULL) { @@ -153,8 +153,8 @@ static int32_t mnodeChildTableActionInsert(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeChildTableActionDelete(SSdbOper *pOper) { - SCTableObj *pTable = pOper->pObj; +static int32_t mnodeChildTableActionDelete(SSdbRow *pRow) { + SCTableObj *pTable = pRow->pObj; if (pTable->vgId == 0) { return TSDB_CODE_MND_VGROUP_NOT_EXIST; } @@ -189,8 +189,8 @@ static int32_t mnodeChildTableActionDelete(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeChildTableActionUpdate(SSdbOper *pOper) { - SCTableObj *pNew = pOper->pObj; +static int32_t mnodeChildTableActionUpdate(SSdbRow *pRow) { + SCTableObj *pNew = pRow->pObj; SCTableObj *pTable = mnodeGetChildTable(pNew->info.tableId); if (pTable != pNew) { void *oldTableId = pTable->info.tableId; @@ -216,50 +216,50 @@ static int32_t mnodeChildTableActionUpdate(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeChildTableActionEncode(SSdbOper *pOper) { - SCTableObj *pTable = pOper->pObj; - assert(pTable != NULL && pOper->rowData != NULL); +static int32_t mnodeChildTableActionEncode(SSdbRow *pRow) { + SCTableObj *pTable = pRow->pObj; + assert(pTable != NULL && pRow->rowData != NULL); int32_t len = strlen(pTable->info.tableId); if (len >= TSDB_TABLE_FNAME_LEN) return TSDB_CODE_MND_INVALID_TABLE_ID; - memcpy(pOper->rowData, pTable->info.tableId, len); - memset(pOper->rowData + len, 0, 1); + memcpy(pRow->rowData, pTable->info.tableId, len); + memset(pRow->rowData + len, 0, 1); len++; - memcpy(pOper->rowData + len, (char*)pTable + sizeof(char *), tsChildTableUpdateSize); + memcpy(pRow->rowData + len, (char*)pTable + sizeof(char *), tsChildTableUpdateSize); len += tsChildTableUpdateSize; if (pTable->info.type != TSDB_CHILD_TABLE) { int32_t schemaSize = pTable->numOfColumns * sizeof(SSchema); - memcpy(pOper->rowData + len, pTable->schema, schemaSize); + memcpy(pRow->rowData + len, pTable->schema, schemaSize); len += schemaSize; if (pTable->sqlLen != 0) { - memcpy(pOper->rowData + len, pTable->sql, pTable->sqlLen); + memcpy(pRow->rowData + len, pTable->sql, pTable->sqlLen); len += pTable->sqlLen; } } - pOper->rowSize = len; + pRow->rowSize = len; return TSDB_CODE_SUCCESS; } -static int32_t mnodeChildTableActionDecode(SSdbOper *pOper) { - assert(pOper->rowData != NULL); +static int32_t mnodeChildTableActionDecode(SSdbRow *pRow) { + assert(pRow->rowData != NULL); SCTableObj *pTable = calloc(1, sizeof(SCTableObj)); if (pTable == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - int32_t len = strlen(pOper->rowData); + int32_t len = strlen(pRow->rowData); if (len >= TSDB_TABLE_FNAME_LEN) { free(pTable); return TSDB_CODE_MND_INVALID_TABLE_ID; } - pTable->info.tableId = strdup(pOper->rowData); + pTable->info.tableId = strdup(pRow->rowData); len++; - memcpy((char*)pTable + sizeof(char *), pOper->rowData + len, tsChildTableUpdateSize); + memcpy((char*)pTable + sizeof(char *), pRow->rowData + len, tsChildTableUpdateSize); len += tsChildTableUpdateSize; if (pTable->info.type != TSDB_CHILD_TABLE) { @@ -269,7 +269,7 @@ static int32_t mnodeChildTableActionDecode(SSdbOper *pOper) { mnodeDestroyChildTable(pTable); return TSDB_CODE_MND_INVALID_TABLE_TYPE; } - memcpy(pTable->schema, pOper->rowData + len, schemaSize); + memcpy(pTable->schema, pRow->rowData + len, schemaSize); len += schemaSize; if (pTable->sqlLen != 0) { @@ -278,11 +278,11 @@ static int32_t mnodeChildTableActionDecode(SSdbOper *pOper) { mnodeDestroyChildTable(pTable); return TSDB_CODE_MND_OUT_OF_MEMORY; } - memcpy(pTable->sql, pOper->rowData + len, pTable->sqlLen); + memcpy(pTable->sql, pRow->rowData + len, pTable->sqlLen); } } - pOper->pObj = pTable; + pRow->pObj = pTable; return TSDB_CODE_SUCCESS; } @@ -297,7 +297,7 @@ static int32_t mnodeChildTableActionRestored() { SDbObj *pDb = mnodeGetDbByTableId(pTable->info.tableId); if (pDb == NULL || pDb->status != TSDB_DB_STATUS_READY) { mError("ctable:%s, failed to get db or db in dropping, discard it", pTable->info.tableId); - SSdbOper desc = {.type = SDB_OPER_LOCAL, .pObj = pTable, .table = tsChildTableSdb}; + SSdbRow desc = {.type = SDB_OPER_LOCAL, .pObj = pTable, .pTable = tsChildTableSdb}; sdbDeleteRow(&desc); mnodeDecTableRef(pTable); mnodeDecDbRef(pDb); @@ -309,7 +309,7 @@ static int32_t mnodeChildTableActionRestored() { if (pVgroup == NULL) { mError("ctable:%s, failed to get vgId:%d tid:%d, discard it", pTable->info.tableId, pTable->vgId, pTable->tid); pTable->vgId = 0; - SSdbOper desc = {.type = SDB_OPER_LOCAL, .pObj = pTable, .table = tsChildTableSdb}; + SSdbRow desc = {.type = SDB_OPER_LOCAL, .pObj = pTable, .pTable = tsChildTableSdb}; sdbDeleteRow(&desc); mnodeDecTableRef(pTable); continue; @@ -320,7 +320,7 @@ static int32_t mnodeChildTableActionRestored() { mError("ctable:%s, db:%s not match with vgId:%d db:%s sid:%d, discard it", pTable->info.tableId, pDb->name, pTable->vgId, pVgroup->dbName, pTable->tid); pTable->vgId = 0; - SSdbOper desc = {.type = SDB_OPER_LOCAL, .pObj = pTable, .table = tsChildTableSdb}; + SSdbRow desc = {.type = SDB_OPER_LOCAL, .pObj = pTable, .pTable = tsChildTableSdb}; sdbDeleteRow(&desc); mnodeDecTableRef(pTable); continue; @@ -331,7 +331,7 @@ static int32_t mnodeChildTableActionRestored() { if (pSuperTable == NULL) { mError("ctable:%s, stable:%" PRIu64 " not exist", pTable->info.tableId, pTable->suid); pTable->vgId = 0; - SSdbOper desc = {.type = SDB_OPER_LOCAL, .pObj = pTable, .table = tsChildTableSdb}; + SSdbRow desc = {.type = SDB_OPER_LOCAL, .pObj = pTable, .pTable = tsChildTableSdb}; sdbDeleteRow(&desc); mnodeDecTableRef(pTable); continue; @@ -352,19 +352,19 @@ static int32_t mnodeInitChildTables() { tsChildTableUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj.info.type; SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_CTABLE, - .tableName = "ctables", + .id = SDB_TABLE_CTABLE, + .name = "ctables", .hashSessions = TSDB_DEFAULT_CTABLES_HASH_SIZE, .maxRowSize = sizeof(SCTableObj) + sizeof(SSchema) * (TSDB_MAX_TAGS + TSDB_MAX_COLUMNS + 16) + TSDB_TABLE_FNAME_LEN + TSDB_CQ_SQL_SIZE, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_VAR_STRING, - .insertFp = mnodeChildTableActionInsert, - .deleteFp = mnodeChildTableActionDelete, - .updateFp = mnodeChildTableActionUpdate, - .encodeFp = mnodeChildTableActionEncode, - .decodeFp = mnodeChildTableActionDecode, - .destroyFp = mnodeChildTableActionDestroy, - .restoredFp = mnodeChildTableActionRestored + .fpInsert = mnodeChildTableActionInsert, + .fpDelete = mnodeChildTableActionDelete, + .fpUpdate = mnodeChildTableActionUpdate, + .fpEncode = mnodeChildTableActionEncode, + .fpDecode = mnodeChildTableActionDecode, + .fpDestroy = mnodeChildTableActionDestroy, + .fpRestored = mnodeChildTableActionRestored }; tsChildTableSdb = sdbOpenTable(&tableDesc); @@ -430,13 +430,13 @@ static void mnodeDestroySuperTable(SSTableObj *pStable) { tfree(pStable); } -static int32_t mnodeSuperTableActionDestroy(SSdbOper *pOper) { - mnodeDestroySuperTable(pOper->pObj); +static int32_t mnodeSuperTableActionDestroy(SSdbRow *pRow) { + mnodeDestroySuperTable(pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t mnodeSuperTableActionInsert(SSdbOper *pOper) { - SSTableObj *pStable = pOper->pObj; +static int32_t mnodeSuperTableActionInsert(SSdbRow *pRow) { + SSTableObj *pStable = pRow->pObj; SDbObj *pDb = mnodeGetDbByTableId(pStable->info.tableId); if (pDb != NULL && pDb->status == TSDB_DB_STATUS_READY) { mnodeAddSuperTableIntoDb(pDb); @@ -446,8 +446,8 @@ static int32_t mnodeSuperTableActionInsert(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeSuperTableActionDelete(SSdbOper *pOper) { - SSTableObj *pStable = pOper->pObj; +static int32_t mnodeSuperTableActionDelete(SSdbRow *pRow) { + SSTableObj *pStable = pRow->pObj; SDbObj *pDb = mnodeGetDbByTableId(pStable->info.tableId); if (pDb != NULL) { mnodeRemoveSuperTableFromDb(pDb); @@ -458,8 +458,8 @@ static int32_t mnodeSuperTableActionDelete(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeSuperTableActionUpdate(SSdbOper *pOper) { - SSTableObj *pNew = pOper->pObj; +static int32_t mnodeSuperTableActionUpdate(SSdbRow *pRow) { + SSTableObj *pNew = pRow->pObj; SSTableObj *pTable = mnodeGetSuperTable(pNew->info.tableId); if (pTable != NULL && pTable != pNew) { void *oldTableId = pTable->info.tableId; @@ -483,43 +483,43 @@ static int32_t mnodeSuperTableActionUpdate(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeSuperTableActionEncode(SSdbOper *pOper) { - SSTableObj *pStable = pOper->pObj; - assert(pOper->pObj != NULL && pOper->rowData != NULL); +static int32_t mnodeSuperTableActionEncode(SSdbRow *pRow) { + SSTableObj *pStable = pRow->pObj; + assert(pRow->pObj != NULL && pRow->rowData != NULL); int32_t len = strlen(pStable->info.tableId); if (len >= TSDB_TABLE_FNAME_LEN) len = TSDB_CODE_MND_INVALID_TABLE_ID; - memcpy(pOper->rowData, pStable->info.tableId, len); - memset(pOper->rowData + len, 0, 1); + memcpy(pRow->rowData, pStable->info.tableId, len); + memset(pRow->rowData + len, 0, 1); len++; - memcpy(pOper->rowData + len, (char*)pStable + sizeof(char *), tsSuperTableUpdateSize); + memcpy(pRow->rowData + len, (char*)pStable + sizeof(char *), tsSuperTableUpdateSize); len += tsSuperTableUpdateSize; int32_t schemaSize = sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags); - memcpy(pOper->rowData + len, pStable->schema, schemaSize); + memcpy(pRow->rowData + len, pStable->schema, schemaSize); len += schemaSize; - pOper->rowSize = len; + pRow->rowSize = len; return TSDB_CODE_SUCCESS; } -static int32_t mnodeSuperTableActionDecode(SSdbOper *pOper) { - assert(pOper->rowData != NULL); +static int32_t mnodeSuperTableActionDecode(SSdbRow *pRow) { + assert(pRow->rowData != NULL); SSTableObj *pStable = (SSTableObj *) calloc(1, sizeof(SSTableObj)); if (pStable == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - int32_t len = strlen(pOper->rowData); + int32_t len = strlen(pRow->rowData); if (len >= TSDB_TABLE_FNAME_LEN){ free(pStable); return TSDB_CODE_MND_INVALID_TABLE_ID; } - pStable->info.tableId = strdup(pOper->rowData); + pStable->info.tableId = strdup(pRow->rowData); len++; - memcpy((char*)pStable + sizeof(char *), pOper->rowData + len, tsSuperTableUpdateSize); + memcpy((char*)pStable + sizeof(char *), pRow->rowData + len, tsSuperTableUpdateSize); len += tsSuperTableUpdateSize; int32_t schemaSize = sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags); @@ -529,9 +529,9 @@ static int32_t mnodeSuperTableActionDecode(SSdbOper *pOper) { return TSDB_CODE_MND_NOT_SUPER_TABLE; } - memcpy(pStable->schema, pOper->rowData + len, schemaSize); + memcpy(pStable->schema, pRow->rowData + len, schemaSize); - pOper->pObj = pStable; + pRow->pObj = pStable; return TSDB_CODE_SUCCESS; } @@ -545,19 +545,19 @@ static int32_t mnodeInitSuperTables() { tsSuperTableUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj.info.type; SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_STABLE, - .tableName = "stables", + .id = SDB_TABLE_STABLE, + .name = "stables", .hashSessions = TSDB_DEFAULT_STABLES_HASH_SIZE, .maxRowSize = sizeof(SSTableObj) + sizeof(SSchema) * (TSDB_MAX_TAGS + TSDB_MAX_COLUMNS + 16) + TSDB_TABLE_FNAME_LEN, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_VAR_STRING, - .insertFp = mnodeSuperTableActionInsert, - .deleteFp = mnodeSuperTableActionDelete, - .updateFp = mnodeSuperTableActionUpdate, - .encodeFp = mnodeSuperTableActionEncode, - .decodeFp = mnodeSuperTableActionDecode, - .destroyFp = mnodeSuperTableActionDestroy, - .restoredFp = mnodeSuperTableActionRestored + .fpInsert = mnodeSuperTableActionInsert, + .fpDelete = mnodeSuperTableActionDelete, + .fpUpdate = mnodeSuperTableActionUpdate, + .fpEncode = mnodeSuperTableActionEncode, + .fpDecode = mnodeSuperTableActionDecode, + .fpDestroy = mnodeSuperTableActionDestroy, + .fpRestored = mnodeSuperTableActionRestored }; tsSuperTableSdb = sdbOpenTable(&tableDesc); @@ -703,7 +703,7 @@ static int32_t mnodeProcessCreateTableMsg(SMnodeMsg *pMsg) { if (pMsg->pDb == NULL) pMsg->pDb = mnodeGetDb(pCreate->db); if (pMsg->pDb == NULL) { - mError("app:%p:%p, table:%s, failed to create, db not selected", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId); + mError("msg:%p, app:%p table:%s, failed to create, db not selected", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return TSDB_CODE_MND_DB_NOT_SELECTED; } @@ -715,24 +715,24 @@ static int32_t mnodeProcessCreateTableMsg(SMnodeMsg *pMsg) { if (pMsg->pTable == NULL) pMsg->pTable = mnodeGetTable(pCreate->tableId); if (pMsg->pTable != NULL && pMsg->retry == 0) { if (pCreate->getMeta) { - mDebug("app:%p:%p, table:%s, continue to get meta", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId); + mDebug("msg:%p, app:%p table:%s, continue to get meta", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return mnodeGetChildTableMeta(pMsg); } else if (pCreate->igExists) { - mDebug("app:%p:%p, table:%s, is already exist", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId); + mDebug("msg:%p, app:%p table:%s, is already exist", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return TSDB_CODE_SUCCESS; } else { - mError("app:%p:%p, table:%s, failed to create, table already exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, failed to create, table already exist", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return TSDB_CODE_MND_TABLE_ALREADY_EXIST; } } if (pCreate->numOfTags != 0) { - mDebug("app:%p:%p, table:%s, create stable msg is received from thandle:%p", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, create stable msg is received from thandle:%p", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId, pMsg->rpcMsg.handle); return mnodeProcessCreateSuperTableMsg(pMsg); } else { - mDebug("app:%p:%p, table:%s, create ctable msg is received from thandle:%p", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, create ctable msg is received from thandle:%p", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId, pMsg->rpcMsg.handle); return mnodeProcessCreateChildTableMsg(pMsg); } @@ -742,17 +742,18 @@ static int32_t mnodeProcessDropTableMsg(SMnodeMsg *pMsg) { SCMDropTableMsg *pDrop = pMsg->rpcMsg.pCont; if (pMsg->pDb == NULL) pMsg->pDb = mnodeGetDbByTableId(pDrop->tableId); if (pMsg->pDb == NULL) { - mError("app:%p:%p, table:%s, failed to drop table, db not selected or db in dropping", pMsg->rpcMsg.ahandle, pMsg, pDrop->tableId); + mError("msg:%p, app:%p table:%s, failed to drop table, db not selected or db in dropping", pMsg, + pMsg->rpcMsg.ahandle, pDrop->tableId); return TSDB_CODE_MND_DB_NOT_SELECTED; } - + if (pMsg->pDb->status != TSDB_DB_STATUS_READY) { mError("db:%s, status:%d, in dropping", pMsg->pDb->name, pMsg->pDb->status); return TSDB_CODE_MND_DB_IN_DROPPING; } if (mnodeCheckIsMonitorDB(pMsg->pDb->name, tsMonitorDbName)) { - mError("app:%p:%p, table:%s, failed to drop table, in monitor database", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, failed to drop table, in monitor database", pMsg, pMsg->rpcMsg.ahandle, pDrop->tableId); return TSDB_CODE_MND_MONITOR_DB_FORBIDDEN; } @@ -760,22 +761,22 @@ static int32_t mnodeProcessDropTableMsg(SMnodeMsg *pMsg) { if (pMsg->pTable == NULL) pMsg->pTable = mnodeGetTable(pDrop->tableId); if (pMsg->pTable == NULL) { if (pDrop->igNotExists) { - mDebug("app:%p:%p, table:%s, table is not exist, treat as success", pMsg->rpcMsg.ahandle, pMsg, pDrop->tableId); + mDebug("msg:%p, app:%p table:%s is not exist, treat as success", pMsg, pMsg->rpcMsg.ahandle, pDrop->tableId); return TSDB_CODE_SUCCESS; } else { - mError("app:%p:%p, table:%s, failed to drop table, table not exist", pMsg->rpcMsg.ahandle, pMsg, pDrop->tableId); + mError("msg:%p, app:%p table:%s, failed to drop, table not exist", pMsg, pMsg->rpcMsg.ahandle, pDrop->tableId); return TSDB_CODE_MND_INVALID_TABLE_NAME; } } if (pMsg->pTable->type == TSDB_SUPER_TABLE) { SSTableObj *pSTable = (SSTableObj *)pMsg->pTable; - mInfo("app:%p:%p, table:%s, start to drop stable, uid:%" PRIu64 ", numOfChildTables:%d, sizeOfVgList:%d", - pMsg->rpcMsg.ahandle, pMsg, pDrop->tableId, pSTable->uid, pSTable->numOfTables, (int32_t)taosHashGetSize(pSTable->vgHash)); + mInfo("msg:%p, app:%p table:%s, start to drop stable, uid:%" PRIu64 ", numOfChildTables:%d, sizeOfVgList:%d", + pMsg, pMsg->rpcMsg.ahandle, pDrop->tableId, pSTable->uid, pSTable->numOfTables, (int32_t)taosHashGetSize(pSTable->vgHash)); return mnodeProcessDropSuperTableMsg(pMsg); } else { SCTableObj *pCTable = (SCTableObj *)pMsg->pTable; - mInfo("app:%p:%p, table:%s, start to drop ctable, vgId:%d tid:%d uid:%" PRIu64, pMsg->rpcMsg.ahandle, pMsg, + mInfo("msg:%p, app:%p table:%s, start to drop ctable, vgId:%d tid:%d uid:%" PRIu64, pMsg, pMsg->rpcMsg.ahandle, pDrop->tableId, pCTable->vgId, pCTable->tid, pCTable->uid); return mnodeProcessDropChildTableMsg(pMsg); } @@ -784,12 +785,12 @@ static int32_t mnodeProcessDropTableMsg(SMnodeMsg *pMsg) { static int32_t mnodeProcessTableMetaMsg(SMnodeMsg *pMsg) { STableInfoMsg *pInfo = pMsg->rpcMsg.pCont; pInfo->createFlag = htons(pInfo->createFlag); - mDebug("app:%p:%p, table:%s, table meta msg is received from thandle:%p, createFlag:%d", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, table meta msg is received from thandle:%p, createFlag:%d", pMsg, pMsg->rpcMsg.ahandle, pInfo->tableId, pMsg->rpcMsg.handle, pInfo->createFlag); if (pMsg->pDb == NULL) pMsg->pDb = mnodeGetDbByTableId(pInfo->tableId); if (pMsg->pDb == NULL) { - mError("app:%p:%p, table:%s, failed to get table meta, db not selected", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, failed to get table meta, db not selected", pMsg, pMsg->rpcMsg.ahandle, pInfo->tableId); return TSDB_CODE_MND_DB_NOT_SELECTED; } @@ -802,11 +803,11 @@ static int32_t mnodeProcessTableMetaMsg(SMnodeMsg *pMsg) { if (pMsg->pTable == NULL) pMsg->pTable = mnodeGetTable(pInfo->tableId); if (pMsg->pTable == NULL) { if (!pInfo->createFlag) { - mError("app:%p:%p, table:%s, failed to get table meta, table not exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, failed to get table meta, table not exist", pMsg, pMsg->rpcMsg.ahandle, pInfo->tableId); return TSDB_CODE_MND_INVALID_TABLE_NAME; } else { - mDebug("app:%p:%p, table:%s, failed to get table meta, start auto create table ", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, failed to get table meta, start auto create table ", pMsg, pMsg->rpcMsg.ahandle, pInfo->tableId); return mnodeAutoCreateChildTable(pMsg); } @@ -826,9 +827,9 @@ static int32_t mnodeCreateSuperTableCb(SMnodeMsg *pMsg, int32_t code) { if (code == TSDB_CODE_SUCCESS) { mLInfo("stable:%s, is created in sdb, uid:%" PRIu64, pTable->info.tableId, pTable->uid); } else { - mError("app:%p:%p, stable:%s, failed to create in sdb, reason:%s", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, + mError("msg:%p, app:%p stable:%s, failed to create in sdb, reason:%s", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, tstrerror(code)); - SSdbOper desc = {.type = SDB_OPER_GLOBAL, .pObj = pTable, .table = tsSuperTableSdb}; + SSdbRow desc = {.type = SDB_OPER_GLOBAL, .pObj = pTable, .pTable = tsSuperTableSdb}; sdbDeleteRow(&desc); } @@ -841,7 +842,7 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) { SCMCreateTableMsg *pCreate = pMsg->rpcMsg.pCont; SSTableObj * pStable = calloc(1, sizeof(SSTableObj)); if (pStable == NULL) { - mError("app:%p:%p, table:%s, failed to create, no enough memory", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId); + mError("msg:%p, app:%p table:%s, failed to create, no enough memory", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return TSDB_CODE_MND_OUT_OF_MEMORY; } @@ -860,7 +861,7 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) { pStable->schema = (SSchema *)calloc(1, schemaSize); if (pStable->schema == NULL) { free(pStable); - mError("app:%p:%p, table:%s, failed to create, no schema input", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId); + mError("msg:%p, app:%p table:%s, failed to create, no schema input", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return TSDB_CODE_MND_INVALID_TABLE_NAME; } memcpy(pStable->schema, pCreate->schema, numOfCols * sizeof(SSchema)); @@ -878,20 +879,20 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) { pMsg->pTable = (STableObj *)pStable; mnodeIncTableRef(pMsg->pTable); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsSuperTableSdb, + .pObj = pStable, .rowSize = sizeof(SSTableObj) + schemaSize, - .pMsg = pMsg, - .writeCb = mnodeCreateSuperTableCb + .pMsg = pMsg, + .fpRsp = mnodeCreateSuperTableCb }; - int32_t code = sdbInsertRow(&oper); + int32_t code = sdbInsertRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mnodeDestroySuperTable(pStable); pMsg->pTable = NULL; - mError("app:%p:%p, table:%s, failed to create, sdb error", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId); + mError("msg:%p, app:%p table:%s, failed to create, sdb error", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); } return code; @@ -900,9 +901,9 @@ static int32_t mnodeProcessCreateSuperTableMsg(SMnodeMsg *pMsg) { static int32_t mnodeDropSuperTableCb(SMnodeMsg *pMsg, int32_t code) { SSTableObj *pTable = (SSTableObj *)pMsg->pTable; if (code != TSDB_CODE_SUCCESS) { - mError("app:%p:%p, stable:%s, failed to drop, sdb error", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId); + mError("msg:%p, app:%p stable:%s, failed to drop, sdb error", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); } else { - mLInfo("app:%p:%p, stable:%s, is dropped from sdb", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId); + mLInfo("msg:%p, app:%p stable:%s, is dropped from sdb", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); } return code; @@ -925,8 +926,8 @@ static int32_t mnodeProcessDropSuperTableMsg(SMnodeMsg *pMsg) { pDrop->uid = htobe64(pStable->uid); mnodeExtractTableName(pStable->info.tableId, pDrop->tableId); - mInfo("app:%p:%p, stable:%s, send drop stable msg to vgId:%d", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, - pVgroup->vgId); + mInfo("msg:%p, app:%p stable:%s, send drop stable msg to vgId:%d", pMsg, pMsg->rpcMsg.ahandle, + pStable->info.tableId, pVgroup->vgId); SRpcEpSet epSet = mnodeGetEpSetFromVgroup(pVgroup); SRpcMsg rpcMsg = {.pCont = pDrop, .contLen = sizeof(SDropSTableMsg), .msgType = TSDB_MSG_TYPE_MD_DROP_STABLE}; dnodeSendMsgToDnode(&epSet, &rpcMsg); @@ -937,17 +938,17 @@ static int32_t mnodeProcessDropSuperTableMsg(SMnodeMsg *pMsg) { mnodeDropAllChildTablesInStable(pStable); } - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, - .pMsg = pMsg, - .writeCb = mnodeDropSuperTableCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsSuperTableSdb, + .pObj = pStable, + .pMsg = pMsg, + .fpRsp = mnodeDropSuperTableCb }; - int32_t code = sdbDeleteRow(&oper); + int32_t code = sdbDeleteRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { - mError("app:%p:%p, table:%s, failed to drop, reason:%s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mError("msg:%p, app:%p table:%s, failed to drop, reason:%s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tstrerror(code)); } @@ -967,7 +968,7 @@ static int32_t mnodeFindSuperTableTagIndex(SSTableObj *pStable, const char *tagN static int32_t mnodeAddSuperTableTagCb(SMnodeMsg *pMsg, int32_t code) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; - mLInfo("app:%p:%p, stable %s, add tag result:%s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mLInfo("msg:%p, app:%p stable %s, add tag result:%s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tstrerror(code)); return code; @@ -976,20 +977,20 @@ static int32_t mnodeAddSuperTableTagCb(SMnodeMsg *pMsg, int32_t code) { static int32_t mnodeAddSuperTableTag(SMnodeMsg *pMsg, SSchema schema[], int32_t ntags) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; if (pStable->numOfTags + ntags > TSDB_MAX_TAGS) { - mError("app:%p:%p, stable:%s, add tag, too many tags", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId); + mError("msg:%p, app:%p stable:%s, add tag, too many tags", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId); return TSDB_CODE_MND_TOO_MANY_TAGS; } for (int32_t i = 0; i < ntags; i++) { if (mnodeFindSuperTableColumnIndex(pStable, schema[i].name) > 0) { - mError("app:%p:%p, stable:%s, add tag, column:%s already exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p stable:%s, add tag, column:%s already exist", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, schema[i].name); return TSDB_CODE_MND_TAG_ALREAY_EXIST; } if (mnodeFindSuperTableTagIndex(pStable, schema[i].name) > 0) { - mError("app:%p:%p, stable:%s, add tag, tag:%s already exist", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, - schema[i].name); + mError("msg:%p, app:%p stable:%s, add tag, tag:%s already exist", pMsg, pMsg->rpcMsg.ahandle, + pStable->info.tableId, schema[i].name); return TSDB_CODE_MND_FIELD_ALREAY_EXIST; } } @@ -1007,23 +1008,23 @@ static int32_t mnodeAddSuperTableTag(SMnodeMsg *pMsg, SSchema schema[], int32_t pStable->numOfTags += ntags; pStable->tversion++; - mInfo("app:%p:%p, stable %s, start to add tag %s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mInfo("msg:%p, app:%p stable %s, start to add tag %s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, schema[0].name); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, - .pMsg = pMsg, - .writeCb = mnodeAddSuperTableTagCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsSuperTableSdb, + .pObj = pStable, + .pMsg = pMsg, + .fpRsp = mnodeAddSuperTableTagCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } static int32_t mnodeDropSuperTableTagCb(SMnodeMsg *pMsg, int32_t code) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; - mLInfo("app:%p:%p, stable %s, drop tag result:%s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mLInfo("msg:%p, app:%p stable %s, drop tag result:%s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tstrerror(code)); return code; } @@ -1032,7 +1033,7 @@ static int32_t mnodeDropSuperTableTag(SMnodeMsg *pMsg, char *tagName) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; int32_t col = mnodeFindSuperTableTagIndex(pStable, tagName); if (col < 0) { - mError("app:%p:%p, stable:%s, drop tag, tag:%s not exist", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mError("msg:%p, app:%p stable:%s, drop tag, tag:%s not exist", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tagName); return TSDB_CODE_MND_TAG_NOT_EXIST; } @@ -1042,22 +1043,22 @@ static int32_t mnodeDropSuperTableTag(SMnodeMsg *pMsg, char *tagName) { pStable->numOfTags--; pStable->tversion++; - mInfo("app:%p:%p, stable %s, start to drop tag %s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, tagName); + mInfo("msg:%p, app:%p stable %s, start to drop tag %s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tagName); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, - .pMsg = pMsg, - .writeCb = mnodeDropSuperTableTagCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsSuperTableSdb, + .pObj = pStable, + .pMsg = pMsg, + .fpRsp = mnodeDropSuperTableTagCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } static int32_t mnodeModifySuperTableTagNameCb(SMnodeMsg *pMsg, int32_t code) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; - mLInfo("app:%p:%p, stable %s, modify tag result:%s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mLInfo("msg:%p, app:%p stable %s, modify tag result:%s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tstrerror(code)); return code; } @@ -1066,7 +1067,7 @@ static int32_t mnodeModifySuperTableTagName(SMnodeMsg *pMsg, char *oldTagName, c SSTableObj *pStable = (SSTableObj *)pMsg->pTable; int32_t col = mnodeFindSuperTableTagIndex(pStable, oldTagName); if (col < 0) { - mError("app:%p:%p, stable:%s, failed to modify table tag, oldName: %s, newName: %s", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p stable:%s, failed to modify table tag, oldName: %s, newName: %s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, oldTagName, newTagName); return TSDB_CODE_MND_TAG_NOT_EXIST; } @@ -1085,18 +1086,18 @@ static int32_t mnodeModifySuperTableTagName(SMnodeMsg *pMsg, char *oldTagName, c SSchema *schema = (SSchema *) (pStable->schema + pStable->numOfColumns + col); tstrncpy(schema->name, newTagName, sizeof(schema->name)); - mInfo("app:%p:%p, stable %s, start to modify tag %s to %s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mInfo("msg:%p, app:%p stable %s, start to modify tag %s to %s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, oldTagName, newTagName); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, - .pMsg = pMsg, - .writeCb = mnodeModifySuperTableTagNameCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsSuperTableSdb, + .pObj = pStable, + .pMsg = pMsg, + .fpRsp = mnodeModifySuperTableTagNameCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } static int32_t mnodeFindSuperTableColumnIndex(SSTableObj *pStable, char *colName) { @@ -1112,7 +1113,7 @@ static int32_t mnodeFindSuperTableColumnIndex(SSTableObj *pStable, char *colName static int32_t mnodeAddSuperTableColumnCb(SMnodeMsg *pMsg, int32_t code) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; - mLInfo("app:%p:%p, stable %s, add column result:%s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mLInfo("msg:%p, app:%p stable %s, add column result:%s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tstrerror(code)); return code; } @@ -1121,19 +1122,19 @@ static int32_t mnodeAddSuperTableColumn(SMnodeMsg *pMsg, SSchema schema[], int32 SDbObj *pDb = pMsg->pDb; SSTableObj *pStable = (SSTableObj *)pMsg->pTable; if (ncols <= 0) { - mError("app:%p:%p, stable:%s, add column, ncols:%d <= 0", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, ncols); + mError("msg:%p, app:%p stable:%s, add column, ncols:%d <= 0", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, ncols); return TSDB_CODE_MND_APP_ERROR; } for (int32_t i = 0; i < ncols; i++) { if (mnodeFindSuperTableColumnIndex(pStable, schema[i].name) > 0) { - mError("app:%p:%p, stable:%s, add column, column:%s already exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p stable:%s, add column, column:%s already exist", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, schema[i].name); return TSDB_CODE_MND_FIELD_ALREAY_EXIST; } if (mnodeFindSuperTableTagIndex(pStable, schema[i].name) > 0) { - mError("app:%p:%p, stable:%s, add column, tag:%s already exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p stable:%s, add column, tag:%s already exist", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, schema[i].name); return TSDB_CODE_MND_TAG_ALREAY_EXIST; } @@ -1160,22 +1161,22 @@ static int32_t mnodeAddSuperTableColumn(SMnodeMsg *pMsg, SSchema schema[], int32 mnodeDecAcctRef(pAcct); } - mInfo("app:%p:%p, stable %s, start to add column", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId); + mInfo("msg:%p, app:%p stable %s, start to add column", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, - .pMsg = pMsg, - .writeCb = mnodeAddSuperTableColumnCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsSuperTableSdb, + .pObj = pStable, + .pMsg = pMsg, + .fpRsp = mnodeAddSuperTableColumnCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } static int32_t mnodeDropSuperTableColumnCb(SMnodeMsg *pMsg, int32_t code) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; - mLInfo("app:%p:%p, stable %s, delete column result:%s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mLInfo("msg:%p, app:%p stable %s, delete column result:%s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tstrerror(code)); return code; } @@ -1185,7 +1186,7 @@ static int32_t mnodeDropSuperTableColumn(SMnodeMsg *pMsg, char *colName) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; int32_t col = mnodeFindSuperTableColumnIndex(pStable, colName); if (col <= 0) { - mError("app:%p:%p, stable:%s, drop column, column:%s not exist", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mError("msg:%p, app:%p stable:%s, drop column, column:%s not exist", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, colName); return TSDB_CODE_MND_FIELD_NOT_EXIST; } @@ -1205,22 +1206,22 @@ static int32_t mnodeDropSuperTableColumn(SMnodeMsg *pMsg, char *colName) { mnodeDecAcctRef(pAcct); } - mInfo("app:%p:%p, stable %s, start to delete column", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId); + mInfo("msg:%p, app:%p stable %s, start to delete column", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, - .pMsg = pMsg, - .writeCb = mnodeDropSuperTableColumnCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsSuperTableSdb, + .pObj = pStable, + .pMsg = pMsg, + .fpRsp = mnodeDropSuperTableColumnCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } static int32_t mnodeChangeSuperTableColumnCb(SMnodeMsg *pMsg, int32_t code) { SSTableObj *pStable = (SSTableObj *)pMsg->pTable; - mLInfo("app:%p:%p, stable %s, change column result:%s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mLInfo("msg:%p, app:%p stable %s, change column result:%s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, tstrerror(code)); return code; } @@ -1229,7 +1230,7 @@ static int32_t mnodeChangeSuperTableColumn(SMnodeMsg *pMsg, char *oldName, char SSTableObj *pStable = (SSTableObj *)pMsg->pTable; int32_t col = mnodeFindSuperTableColumnIndex(pStable, oldName); if (col < 0) { - mError("app:%p:%p, stable:%s, change column, oldName: %s, newName: %s", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p stable:%s, change column, oldName:%s, newName:%s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, oldName, newName); return TSDB_CODE_MND_FIELD_NOT_EXIST; } @@ -1248,18 +1249,18 @@ static int32_t mnodeChangeSuperTableColumn(SMnodeMsg *pMsg, char *oldName, char SSchema *schema = (SSchema *) (pStable->schema + col); tstrncpy(schema->name, newName, sizeof(schema->name)); - mInfo("app:%p:%p, stable %s, start to modify column %s to %s", pMsg->rpcMsg.ahandle, pMsg, pStable->info.tableId, + mInfo("msg:%p, app:%p stable %s, start to modify column %s to %s", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, oldName, newName); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, - .pMsg = pMsg, - .writeCb = mnodeChangeSuperTableColumnCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsSuperTableSdb, + .pObj = pStable, + .pMsg = pMsg, + .fpRsp = mnodeChangeSuperTableColumnCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } // show super tables @@ -1417,12 +1418,12 @@ void mnodeDropAllSuperTables(SDbObj *pDropDb) { if (pTable == NULL) break; if (strncmp(prefix, pTable->info.tableId, prefixLen) == 0) { - SSdbOper oper = { - .type = SDB_OPER_LOCAL, - .table = tsSuperTableSdb, - .pObj = pTable, + SSdbRow row = { + .type = SDB_OPER_LOCAL, + .pTable = tsSuperTableSdb, + .pObj = pTable, }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); numOfTables ++; } @@ -1470,7 +1471,7 @@ static int32_t mnodeGetSuperTableMeta(SMnodeMsg *pMsg) { pMsg->rpcRsp.rsp = pMeta; - mDebug("app:%p:%p, stable:%s, uid:%" PRIu64 " table meta is retrieved", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p stable:%s, uid:%" PRIu64 " table meta is retrieved", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->uid); return TSDB_CODE_SUCCESS; } @@ -1503,12 +1504,12 @@ static int32_t mnodeProcessSuperTableVgroupMsg(SMnodeMsg *pMsg) { char * stableName = (char *)pInfo + sizeof(SSTableVgroupMsg) + (TSDB_TABLE_FNAME_LEN)*i; SSTableObj *pTable = mnodeGetSuperTable(stableName); if (pTable == NULL) { - mError("app:%p:%p, stable:%s, not exist while get stable vgroup info", pMsg->rpcMsg.ahandle, pMsg, stableName); + mError("msg:%p, app:%p stable:%s, not exist while get stable vgroup info", pMsg, pMsg->rpcMsg.ahandle, stableName); mnodeDecTableRef(pTable); continue; } if (pTable->vgHash == NULL) { - mDebug("app:%p:%p, stable:%s, no vgroup exist while get stable vgroup info", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p stable:%s, no vgroup exist while get stable vgroup info", pMsg, pMsg->rpcMsg.ahandle, stableName); mnodeDecTableRef(pTable); @@ -1650,7 +1651,7 @@ static int32_t mnodeDoCreateChildTableFp(SMnodeMsg *pMsg) { SCTableObj *pTable = (SCTableObj *)pMsg->pTable; assert(pTable); - mDebug("app:%p:%p, table:%s, created in mnode, vgId:%d sid:%d, uid:%" PRIu64, pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, created in mnode, vgId:%d sid:%d, uid:%" PRIu64, pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid); SCMCreateTableMsg *pCreate = pMsg->rpcMsg.pCont; @@ -1679,22 +1680,22 @@ static int32_t mnodeDoCreateChildTableCb(SMnodeMsg *pMsg, int32_t code) { if (code == TSDB_CODE_SUCCESS) { if (pCreate->getMeta) { - mDebug("app:%p:%p, table:%s, created in dnode and continue to get meta, thandle:%p", pMsg->rpcMsg.ahandle, pMsg, - pTable->info.tableId, pMsg->rpcMsg.handle); + mDebug("msg:%p, app:%p table:%s, created in dnode and continue to get meta, thandle:%p", pMsg, + pMsg->rpcMsg.ahandle, pTable->info.tableId, pMsg->rpcMsg.handle); pMsg->retry = 0; dnodeReprocessMWriteMsg(pMsg); } else { - mDebug("app:%p:%p, table:%s, created in dnode, thandle:%p", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, + mDebug("msg:%p, app:%p table:%s, created in dnode, thandle:%p", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pMsg->rpcMsg.handle); dnodeSendRpcMWriteRsp(pMsg, TSDB_CODE_SUCCESS); } return TSDB_CODE_MND_ACTION_IN_PROGRESS; } else { - mError("app:%p:%p, table:%s, failed to create table sid:%d, uid:%" PRIu64 ", reason:%s", pMsg->rpcMsg.ahandle, pMsg, - pTable->info.tableId, pTable->tid, pTable->uid, tstrerror(code)); - SSdbOper desc = {.type = SDB_OPER_GLOBAL, .pObj = pTable, .table = tsChildTableSdb}; + mError("msg:%p, app:%p table:%s, failed to create table sid:%d, uid:%" PRIu64 ", reason:%s", pMsg, + pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->tid, pTable->uid, tstrerror(code)); + SSdbRow desc = {.type = SDB_OPER_GLOBAL, .pObj = pTable, .pTable = tsChildTableSdb}; sdbDeleteRow(&desc); return code; } @@ -1705,7 +1706,7 @@ static int32_t mnodeDoCreateChildTable(SMnodeMsg *pMsg, int32_t tid) { SCMCreateTableMsg *pCreate = pMsg->rpcMsg.pCont; SCTableObj *pTable = calloc(1, sizeof(SCTableObj)); if (pTable == NULL) { - mError("app:%p:%p, table:%s, failed to alloc memory", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId); + mError("msg:%p, app:%p table:%s, failed to alloc memory", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return TSDB_CODE_MND_OUT_OF_MEMORY; } @@ -1724,7 +1725,7 @@ static int32_t mnodeDoCreateChildTable(SMnodeMsg *pMsg, int32_t tid) { STagData *pTagData = (STagData *)pCreate->schema; // it is a tag key if (pMsg->pSTable == NULL) pMsg->pSTable = mnodeGetSuperTable(pTagData->name); if (pMsg->pSTable == NULL) { - mError("app:%p:%p, table:%s, corresponding super table:%s does not exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, corresponding super table:%s does not exist", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId, pTagData->name); mnodeDestroyChildTable(pTable); return TSDB_CODE_MND_INVALID_TABLE_NAME; @@ -1772,7 +1773,7 @@ static int32_t mnodeDoCreateChildTable(SMnodeMsg *pMsg, int32_t tid) { } memcpy(pTable->sql, (char *) (pCreate->schema) + numOfCols * sizeof(SSchema), pTable->sqlLen); pTable->sql[pTable->sqlLen - 1] = 0; - mDebug("app:%p:%p, table:%s, stream sql len:%d sql:%s", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, + mDebug("msg:%p, app:%p table:%s, stream sql len:%d sql:%s", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->sqlLen, pTable->sql); } } @@ -1780,22 +1781,22 @@ static int32_t mnodeDoCreateChildTable(SMnodeMsg *pMsg, int32_t tid) { pMsg->pTable = (STableObj *)pTable; mnodeIncTableRef(pMsg->pTable); - SSdbOper desc = { - .type = SDB_OPER_GLOBAL, - .pObj = pTable, - .table = tsChildTableSdb, - .pMsg = pMsg, - .reqFp = mnodeDoCreateChildTableFp + SSdbRow desc = { + .type = SDB_OPER_GLOBAL, + .pObj = pTable, + .pTable = tsChildTableSdb, + .pMsg = pMsg, + .fpReq = mnodeDoCreateChildTableFp }; int32_t code = sdbInsertRow(&desc); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mnodeDestroyChildTable(pTable); pMsg->pTable = NULL; - mError("app:%p:%p, table:%s, failed to create, reason:%s", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId, + mError("msg:%p, app:%p table:%s, failed to create, reason:%s", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId, tstrerror(code)); } else { - mDebug("app:%p:%p, table:%s, allocated in vgroup, vgId:%d sid:%d uid:%" PRIu64, pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, allocated in vgroup, vgId:%d sid:%d uid:%" PRIu64, pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pVgroup->vgId, pTable->tid, pTable->uid); } @@ -1806,7 +1807,7 @@ static int32_t mnodeProcessCreateChildTableMsg(SMnodeMsg *pMsg) { SCMCreateTableMsg *pCreate = pMsg->rpcMsg.pCont; int32_t code = grantCheck(TSDB_GRANT_TIMESERIES); if (code != TSDB_CODE_SUCCESS) { - mError("app:%p:%p, table:%s, failed to create, grant timeseries failed", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, failed to create, grant timeseries failed", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return code; } @@ -1817,7 +1818,7 @@ static int32_t mnodeProcessCreateChildTableMsg(SMnodeMsg *pMsg) { int32_t tid = 0; code = mnodeGetAvailableVgroup(pMsg, &pVgroup, &tid); if (code != TSDB_CODE_SUCCESS) { - mDebug("app:%p:%p, table:%s, failed to get available vgroup, reason:%s", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, failed to get available vgroup, reason:%s", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId, tstrerror(code)); return code; } @@ -1836,22 +1837,22 @@ static int32_t mnodeProcessCreateChildTableMsg(SMnodeMsg *pMsg) { } if (pMsg->pTable == NULL) { - mError("app:%p:%p, table:%s, object not found, retry:%d reason:%s", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId, pMsg->retry, + mError("msg:%p, app:%p table:%s, object not found, retry:%d reason:%s", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId, pMsg->retry, tstrerror(terrno)); return terrno; } else { - mDebug("app:%p:%p, table:%s, send create msg to vnode again", pMsg->rpcMsg.ahandle, pMsg, pCreate->tableId); + mDebug("msg:%p, app:%p table:%s, send create msg to vnode again", pMsg, pMsg->rpcMsg.ahandle, pCreate->tableId); return mnodeDoCreateChildTableFp(pMsg); } } static int32_t mnodeSendDropChildTableMsg(SMnodeMsg *pMsg, bool needReturn) { SCTableObj *pTable = (SCTableObj *)pMsg->pTable; - mLInfo("app:%p:%p, ctable:%s, is dropped from sdb", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId); + mLInfo("msg:%p, app:%p ctable:%s, is dropped from sdb", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); SMDDropTableMsg *pDrop = rpcMallocCont(sizeof(SMDDropTableMsg)); if (pDrop == NULL) { - mError("app:%p:%p, ctable:%s, failed to drop ctable, no enough memory", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p ctable:%s, failed to drop ctable, no enough memory", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); return TSDB_CODE_MND_OUT_OF_MEMORY; } @@ -1864,7 +1865,7 @@ static int32_t mnodeSendDropChildTableMsg(SMnodeMsg *pMsg, bool needReturn) { SRpcEpSet epSet = mnodeGetEpSetFromVgroup(pMsg->pVgroup); - mInfo("app:%p:%p, ctable:%s, send drop ctable msg, vgId:%d sid:%d uid:%" PRIu64, pMsg->rpcMsg.ahandle, pMsg, + mInfo("msg:%p, app:%p ctable:%s, send drop ctable msg, vgId:%d sid:%d uid:%" PRIu64, pMsg, pMsg->rpcMsg.ahandle, pDrop->tableId, pTable->vgId, pTable->tid, pTable->uid); SRpcMsg rpcMsg = { @@ -1885,7 +1886,7 @@ static int32_t mnodeSendDropChildTableMsg(SMnodeMsg *pMsg, bool needReturn) { static int32_t mnodeDropChildTableCb(SMnodeMsg *pMsg, int32_t code) { if (code != TSDB_CODE_SUCCESS) { SCTableObj *pTable = (SCTableObj *)pMsg->pTable; - mError("app:%p:%p, ctable:%s, failed to drop, sdb error", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId); + mError("msg:%p, app:%p ctable:%s, failed to drop, sdb error", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); return code; } @@ -1896,22 +1897,22 @@ static int32_t mnodeProcessDropChildTableMsg(SMnodeMsg *pMsg) { SCTableObj *pTable = (SCTableObj *)pMsg->pTable; if (pMsg->pVgroup == NULL) pMsg->pVgroup = mnodeGetVgroup(pTable->vgId); if (pMsg->pVgroup == NULL) { - mError("app:%p:%p, table:%s, failed to drop ctable, vgroup not exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, failed to drop ctable, vgroup not exist", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); return TSDB_CODE_MND_APP_ERROR; } - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsChildTableSdb, - .pObj = pTable, - .pMsg = pMsg, - .writeCb = mnodeDropChildTableCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsChildTableSdb, + .pObj = pTable, + .pMsg = pMsg, + .fpRsp = mnodeDropChildTableCb }; - int32_t code = sdbDeleteRow(&oper); + int32_t code = sdbDeleteRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { - mError("app:%p:%p, ctable:%s, failed to drop, reason:%s", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, + mError("msg:%p, app:%p ctable:%s, failed to drop, reason:%s", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, tstrerror(code)); } @@ -1932,7 +1933,7 @@ static int32_t mnodeFindNormalTableColumnIndex(SCTableObj *pTable, char *colName static int32_t mnodeAlterNormalTableColumnCb(SMnodeMsg *pMsg, int32_t code) { SCTableObj *pTable = (SCTableObj *)pMsg->pTable; if (code != TSDB_CODE_SUCCESS) { - mError("app:%p:%p, ctable %s, failed to alter column, reason:%s", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, + mError("msg:%p, app:%p ctable %s, failed to alter column, reason:%s", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, tstrerror(code)); return code; } @@ -1946,7 +1947,7 @@ static int32_t mnodeAlterNormalTableColumnCb(SMnodeMsg *pMsg, int32_t code) { pMsg->pVgroup = mnodeGetVgroup(pTable->vgId); if (pMsg->pVgroup == NULL) { rpcFreeCont(pMDCreate); - mError("app:%p:%p, ctable %s, vgId:%d not exist in mnode", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, + mError("msg:%p, app:%p ctable %s, vgId:%d not exist in mnode", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->vgId); return TSDB_CODE_MND_VGROUP_NOT_EXIST; } @@ -1961,7 +1962,7 @@ static int32_t mnodeAlterNormalTableColumnCb(SMnodeMsg *pMsg, int32_t code) { .msgType = TSDB_MSG_TYPE_MD_ALTER_TABLE }; - mDebug("app:%p:%p, ctable %s, send alter column msg to vgId:%d", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, + mDebug("msg:%p, app:%p ctable %s, send alter column msg to vgId:%d", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pMsg->pVgroup->vgId); dnodeSendMsgToDnode(&epSet, &rpcMsg); @@ -1972,13 +1973,13 @@ static int32_t mnodeAddNormalTableColumn(SMnodeMsg *pMsg, SSchema schema[], int3 SCTableObj *pTable = (SCTableObj *)pMsg->pTable; SDbObj *pDb = pMsg->pDb; if (ncols <= 0) { - mError("app:%p:%p, ctable:%s, add column, ncols:%d <= 0", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, ncols); + mError("msg:%p, app:%p ctable:%s, add column, ncols:%d <= 0", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, ncols); return TSDB_CODE_MND_APP_ERROR; } for (int32_t i = 0; i < ncols; i++) { if (mnodeFindNormalTableColumnIndex(pTable, schema[i].name) > 0) { - mError("app:%p:%p, ctable:%s, add column, column:%s already exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p ctable:%s, add column, column:%s already exist", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, schema[i].name); return TSDB_CODE_MND_FIELD_ALREAY_EXIST; } @@ -2003,17 +2004,17 @@ static int32_t mnodeAddNormalTableColumn(SMnodeMsg *pMsg, SSchema schema[], int3 mnodeDecAcctRef(pAcct); } - mInfo("app:%p:%p, ctable %s, start to add column", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId); + mInfo("msg:%p, app:%p ctable %s, start to add column", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsChildTableSdb, - .pObj = pTable, - .pMsg = pMsg, - .writeCb = mnodeAlterNormalTableColumnCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsChildTableSdb, + .pObj = pTable, + .pMsg = pMsg, + .fpRsp = mnodeAlterNormalTableColumnCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } static int32_t mnodeDropNormalTableColumn(SMnodeMsg *pMsg, char *colName) { @@ -2021,8 +2022,8 @@ static int32_t mnodeDropNormalTableColumn(SMnodeMsg *pMsg, char *colName) { SCTableObj *pTable = (SCTableObj *)pMsg->pTable; int32_t col = mnodeFindNormalTableColumnIndex(pTable, colName); if (col <= 0) { - mError("app:%p:%p, ctable:%s, drop column, column:%s not exist", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, - colName); + mError("msg:%p, app:%p ctable:%s, drop column, column:%s not exist", pMsg, pMsg->rpcMsg.ahandle, + pTable->info.tableId, colName); return TSDB_CODE_MND_FIELD_NOT_EXIST; } @@ -2036,24 +2037,24 @@ static int32_t mnodeDropNormalTableColumn(SMnodeMsg *pMsg, char *colName) { mnodeDecAcctRef(pAcct); } - mInfo("app:%p:%p, ctable %s, start to drop column %s", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, colName); + mInfo("msg:%p, app:%p ctable %s, start to drop column %s", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, colName); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsChildTableSdb, - .pObj = pTable, - .pMsg = pMsg, - .writeCb = mnodeAlterNormalTableColumnCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsChildTableSdb, + .pObj = pTable, + .pMsg = pMsg, + .fpRsp = mnodeAlterNormalTableColumnCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } static int32_t mnodeChangeNormalTableColumn(SMnodeMsg *pMsg, char *oldName, char *newName) { SCTableObj *pTable = (SCTableObj *)pMsg->pTable; int32_t col = mnodeFindNormalTableColumnIndex(pTable, oldName); if (col < 0) { - mError("app:%p:%p, ctable:%s, change column, oldName: %s, newName: %s", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p ctable:%s, change column, oldName: %s, newName: %s", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, oldName, newName); return TSDB_CODE_MND_FIELD_NOT_EXIST; } @@ -2072,18 +2073,18 @@ static int32_t mnodeChangeNormalTableColumn(SMnodeMsg *pMsg, char *oldName, char SSchema *schema = (SSchema *) (pTable->schema + col); tstrncpy(schema->name, newName, sizeof(schema->name)); - mInfo("app:%p:%p, ctable %s, start to modify column %s to %s", pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, + mInfo("msg:%p, app:%p ctable %s, start to modify column %s to %s", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, oldName, newName); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsChildTableSdb, - .pObj = pTable, - .pMsg = pMsg, - .writeCb = mnodeAlterNormalTableColumnCb + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsChildTableSdb, + .pObj = pTable, + .pMsg = pMsg, + .fpRsp = mnodeAlterNormalTableColumnCb }; - return sdbUpdateRow(&oper); + return sdbUpdateRow(&row); } static int32_t mnodeSetSchemaFromNormalTable(SSchema *pSchema, SCTableObj *pTable) { @@ -2128,7 +2129,7 @@ static int32_t mnodeDoGetChildTableMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta) { if (pMsg->pVgroup == NULL) pMsg->pVgroup = mnodeGetVgroup(pTable->vgId); if (pMsg->pVgroup == NULL) { - mError("app:%p:%p, table:%s, failed to get table meta, vgroup not exist", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, failed to get table meta, vgroup not exist", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); return TSDB_CODE_MND_VGROUP_NOT_EXIST; } @@ -2143,7 +2144,7 @@ static int32_t mnodeDoGetChildTableMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta) { } pMeta->vgroup.vgId = htonl(pMsg->pVgroup->vgId); - mDebug("app:%p:%p, table:%s, uid:%" PRIu64 " table meta is retrieved, vgId:%d sid:%d", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, uid:%" PRIu64 " table meta is retrieved, vgId:%d sid:%d", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->uid, pTable->vgId, pTable->tid); return TSDB_CODE_SUCCESS; @@ -2154,16 +2155,16 @@ static int32_t mnodeAutoCreateChildTable(SMnodeMsg *pMsg) { STagData *pTags = (STagData *)pInfo->tags; int32_t tagLen = htonl(pTags->dataLen); if (pTags->name[0] == 0) { - mError("app:%p:%p, table:%s, failed to create table on demand for stable is empty, tagLen:%d", pMsg->rpcMsg.ahandle, - pMsg, pInfo->tableId, tagLen); - return TSDB_CODE_MND_INVALID_STABLE_NAME; + mError("msg:%p, app:%p table:%s, failed to create table on demand for stable is empty, tagLen:%d", pMsg, + pMsg->rpcMsg.ahandle, pInfo->tableId, tagLen); + return TSDB_CODE_MND_INVALID_STABLE_NAME; } int32_t contLen = sizeof(SCMCreateTableMsg) + offsetof(STagData, data) + tagLen; SCMCreateTableMsg *pCreateMsg = calloc(1, contLen); if (pCreateMsg == NULL) { - mError("app:%p:%p, table:%s, failed to create table while get meta info, no enough memory", pMsg->rpcMsg.ahandle, - pMsg, pInfo->tableId); + mError("msg:%p, app:%p table:%s, failed to create table while get meta info, no enough memory", pMsg, + pMsg->rpcMsg.ahandle, pInfo->tableId); return TSDB_CODE_MND_OUT_OF_MEMORY; } @@ -2175,8 +2176,8 @@ static int32_t mnodeAutoCreateChildTable(SMnodeMsg *pMsg) { pCreateMsg->contLen = htonl(contLen); memcpy(pCreateMsg->schema, pTags, contLen - sizeof(SCMCreateTableMsg)); - mDebug("app:%p:%p, table:%s, start to create on demand, tagLen:%d stable:%s", - pMsg->rpcMsg.ahandle, pMsg, pInfo->tableId, tagLen, pTags->name); + mDebug("msg:%p, app:%p table:%s, start to create on demand, tagLen:%d stable:%s", pMsg, pMsg->rpcMsg.ahandle, + pInfo->tableId, tagLen, pTags->name); if (pMsg->rpcMsg.pCont != pMsg->pCont) { tfree(pMsg->rpcMsg.pCont); @@ -2192,7 +2193,7 @@ static int32_t mnodeGetChildTableMeta(SMnodeMsg *pMsg) { STableMetaMsg *pMeta = rpcMallocCont(sizeof(STableMetaMsg) + sizeof(SSchema) * (TSDB_MAX_TAGS + TSDB_MAX_COLUMNS + 16)); if (pMeta == NULL) { - mError("app:%p:%p, table:%s, failed to get table meta, no enough memory", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p table:%s, failed to get table meta, no enough memory", pMsg, pMsg->rpcMsg.ahandle, pMsg->pTable->tableId); return TSDB_CODE_MND_OUT_OF_MEMORY; } @@ -2218,12 +2219,12 @@ void mnodeDropAllChildTablesInVgroups(SVgObj *pVgroup) { if (pTable == NULL) break; if (pTable->vgId == pVgroup->vgId) { - SSdbOper oper = { - .type = SDB_OPER_LOCAL, - .table = tsChildTableSdb, - .pObj = pTable, + SSdbRow row = { + .type = SDB_OPER_LOCAL, + .pTable = tsChildTableSdb, + .pObj = pTable, }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); numOfTables++; } mnodeDecTableRef(pTable); @@ -2251,12 +2252,12 @@ void mnodeDropAllChildTables(SDbObj *pDropDb) { if (pTable == NULL) break; if (strncmp(prefix, pTable->info.tableId, prefixLen) == 0) { - SSdbOper oper = { - .type = SDB_OPER_LOCAL, - .table = tsChildTableSdb, - .pObj = pTable, + SSdbRow row = { + .type = SDB_OPER_LOCAL, + .pTable = tsChildTableSdb, + .pObj = pTable, }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); numOfTables++; } mnodeDecTableRef(pTable); @@ -2280,12 +2281,12 @@ static void mnodeDropAllChildTablesInStable(SSTableObj *pStable) { if (pTable == NULL) break; if (pTable->superTable == pStable) { - SSdbOper oper = { - .type = SDB_OPER_LOCAL, - .table = tsChildTableSdb, - .pObj = pTable, + SSdbRow row = { + .type = SDB_OPER_LOCAL, + .pTable = tsChildTableSdb, + .pObj = pTable, }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); numOfTables++; } @@ -2317,12 +2318,12 @@ static int32_t mnodeProcessTableCfgMsg(SMnodeMsg *pMsg) { pCfg->dnodeId = htonl(pCfg->dnodeId); pCfg->vgId = htonl(pCfg->vgId); pCfg->sid = htonl(pCfg->sid); - mDebug("app:%p:%p, dnode:%d, vgId:%d sid:%d, receive table config msg", pMsg->rpcMsg.ahandle, pMsg, pCfg->dnodeId, + mDebug("msg:%p, app:%p dnode:%d, vgId:%d sid:%d, receive table config msg", pMsg, pMsg->rpcMsg.ahandle, pCfg->dnodeId, pCfg->vgId, pCfg->sid); SCTableObj *pTable = mnodeGetTableByPos(pCfg->vgId, pCfg->sid); if (pTable == NULL) { - mError("app:%p:%p, dnode:%d, vgId:%d sid:%d, table not found", pMsg->rpcMsg.ahandle, pMsg, pCfg->dnodeId, + mError("msg:%p, app:%p dnode:%d, vgId:%d sid:%d, table not found", pMsg, pMsg->rpcMsg.ahandle, pCfg->dnodeId, pCfg->vgId, pCfg->sid); return TSDB_CODE_MND_INVALID_TABLE_ID; } @@ -2343,38 +2344,37 @@ static int32_t mnodeProcessTableCfgMsg(SMnodeMsg *pMsg) { static void mnodeProcessDropChildTableRsp(SRpcMsg *rpcMsg) { if (rpcMsg->ahandle == NULL) return; - SMnodeMsg *mnodeMsg = rpcMsg->ahandle; - mnodeMsg->received++; + SMnodeMsg *pMsg = rpcMsg->ahandle; + pMsg->received++; - SCTableObj *pTable = (SCTableObj *)mnodeMsg->pTable; + SCTableObj *pTable = (SCTableObj *)pMsg->pTable; assert(pTable); - mInfo("app:%p:%p, table:%s, drop table rsp received, vgId:%d sid:%d uid:%" PRIu64 ", thandle:%p result:%s", - mnodeMsg->rpcMsg.ahandle, mnodeMsg, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid, - mnodeMsg->rpcMsg.handle, tstrerror(rpcMsg->code)); + mInfo("msg:%p, app:%p table:%s, drop table rsp received, vgId:%d sid:%d uid:%" PRIu64 ", thandle:%p result:%s", pMsg, + pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid, pMsg->rpcMsg.handle, + tstrerror(rpcMsg->code)); if (rpcMsg->code != TSDB_CODE_SUCCESS) { - mError("app:%p:%p, table:%s, failed to drop in dnode, vgId:%d sid:%d uid:%" PRIu64 ", reason:%s", - mnodeMsg->rpcMsg.ahandle, mnodeMsg, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid, - tstrerror(rpcMsg->code)); - dnodeSendRpcMWriteRsp(mnodeMsg, rpcMsg->code); + mError("msg:%p, app:%p table:%s, failed to drop in dnode, vgId:%d sid:%d uid:%" PRIu64 ", reason:%s", pMsg, + pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid, tstrerror(rpcMsg->code)); + dnodeSendRpcMWriteRsp(pMsg, rpcMsg->code); return; } - if (mnodeMsg->pVgroup == NULL) mnodeMsg->pVgroup = mnodeGetVgroup(pTable->vgId); - if (mnodeMsg->pVgroup == NULL) { - mError("app:%p:%p, table:%s, failed to get vgroup", mnodeMsg->rpcMsg.ahandle, mnodeMsg, pTable->info.tableId); - dnodeSendRpcMWriteRsp(mnodeMsg, TSDB_CODE_MND_VGROUP_NOT_EXIST); + if (pMsg->pVgroup == NULL) pMsg->pVgroup = mnodeGetVgroup(pTable->vgId); + if (pMsg->pVgroup == NULL) { + mError("msg:%p, app:%p table:%s, failed to get vgroup", pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId); + dnodeSendRpcMWriteRsp(pMsg, TSDB_CODE_MND_VGROUP_NOT_EXIST); return; } - if (mnodeMsg->pVgroup->numOfTables <= 0) { - mInfo("app:%p:%p, vgId:%d, all tables is dropped, drop vgroup", mnodeMsg->rpcMsg.ahandle, mnodeMsg, - mnodeMsg->pVgroup->vgId); - mnodeDropVgroup(mnodeMsg->pVgroup, NULL); + if (pMsg->pVgroup->numOfTables <= 0) { + mInfo("msg:%p, app:%p vgId:%d, all tables is dropped, drop vgroup", pMsg, pMsg->rpcMsg.ahandle, + pMsg->pVgroup->vgId); + mnodeDropVgroup(pMsg->pVgroup, NULL); } - dnodeSendRpcMWriteRsp(mnodeMsg, TSDB_CODE_SUCCESS); + dnodeSendRpcMWriteRsp(pMsg, TSDB_CODE_SUCCESS); } /* @@ -2384,70 +2384,70 @@ static void mnodeProcessDropChildTableRsp(SRpcMsg *rpcMsg) { static void mnodeProcessCreateChildTableRsp(SRpcMsg *rpcMsg) { if (rpcMsg->ahandle == NULL) return; - SMnodeMsg *mnodeMsg = rpcMsg->ahandle; - mnodeMsg->received++; + SMnodeMsg *pMsg = rpcMsg->ahandle; + pMsg->received++; - SCTableObj *pTable = (SCTableObj *)mnodeMsg->pTable; + SCTableObj *pTable = (SCTableObj *)pMsg->pTable; assert(pTable); // If the table is deleted by another thread during creation, stop creating and send drop msg to vnode if (sdbCheckRowDeleted(tsChildTableSdb, pTable)) { - mDebug("app:%p:%p, table:%s, create table rsp received, but a deleting opertion incoming, vgId:%d sid:%d uid:%" PRIu64, - mnodeMsg->rpcMsg.ahandle, mnodeMsg, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid); + mDebug("msg:%p, app:%p table:%s, create table rsp received, but a deleting opertion incoming, vgId:%d sid:%d uid:%" PRIu64, + pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid); // if the vgroup is already dropped from hash, it can't be accquired by pTable->vgId // so the refCount of vgroup can not be decreased // SVgObj *pVgroup = mnodeGetVgroup(pTable->vgId); // if (pVgroup == NULL) { - // mnodeRemoveTableFromVgroup(mnodeMsg->pVgroup, pTable); + // mnodeRemoveTableFromVgroup(pMsg->pVgroup, pTable); // } // mnodeDecVgroupRef(pVgroup); - mnodeSendDropChildTableMsg(mnodeMsg, false); + mnodeSendDropChildTableMsg(pMsg, false); rpcMsg->code = TSDB_CODE_SUCCESS; - dnodeSendRpcMWriteRsp(mnodeMsg, rpcMsg->code); + dnodeSendRpcMWriteRsp(pMsg, rpcMsg->code); return; } if (rpcMsg->code == TSDB_CODE_SUCCESS || rpcMsg->code == TSDB_CODE_TDB_TABLE_ALREADY_EXIST) { - SSdbOper desc = { - .type = SDB_OPER_GLOBAL, - .pObj = pTable, - .table = tsChildTableSdb, - .pMsg = mnodeMsg, - .writeCb = mnodeDoCreateChildTableCb + SSdbRow desc = { + .type = SDB_OPER_GLOBAL, + .pObj = pTable, + .pTable = tsChildTableSdb, + .pMsg = pMsg, + .fpRsp = mnodeDoCreateChildTableCb }; - int32_t code = sdbInsertRowImp(&desc); + int32_t code = sdbInsertRowToQueue(&desc); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { - mnodeMsg->pTable = NULL; + pMsg->pTable = NULL; mnodeDestroyChildTable(pTable); - dnodeSendRpcMWriteRsp(mnodeMsg, code); + dnodeSendRpcMWriteRsp(pMsg, code); } } else { - mnodeMsg->retry++; + pMsg->retry++; int32_t sec = taosGetTimestampSec(); - if (mnodeMsg->retry < CREATE_CTABLE_RETRY_TIMES && ABS(sec - mnodeMsg->incomingTs) < CREATE_CTABLE_RETRY_SEC) { - mDebug("app:%p:%p, table:%s, create table rsp received, need retry, times:%d vgId:%d sid:%d uid:%" PRIu64 + if (pMsg->retry < CREATE_CTABLE_RETRY_TIMES && ABS(sec - pMsg->incomingTs) < CREATE_CTABLE_RETRY_SEC) { + mDebug("msg:%p, app:%p table:%s, create table rsp received, need retry, times:%d vgId:%d sid:%d uid:%" PRIu64 " result:%s thandle:%p", - mnodeMsg->rpcMsg.ahandle, mnodeMsg, pTable->info.tableId, mnodeMsg->retry, pTable->vgId, pTable->tid, - pTable->uid, tstrerror(rpcMsg->code), mnodeMsg->rpcMsg.handle); + pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pMsg->retry, pTable->vgId, pTable->tid, pTable->uid, + tstrerror(rpcMsg->code), pMsg->rpcMsg.handle); - dnodeDelayReprocessMWriteMsg(mnodeMsg); + dnodeDelayReprocessMWriteMsg(pMsg); } else { - mError("app:%p:%p, table:%s, failed to create in dnode, vgId:%d sid:%d uid:%" PRIu64 + mError("msg:%p, app:%p table:%s, failed to create in dnode, vgId:%d sid:%d uid:%" PRIu64 ", result:%s thandle:%p incomingTs:%d curTs:%d retryTimes:%d", - mnodeMsg->rpcMsg.ahandle, mnodeMsg, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid, - tstrerror(rpcMsg->code), mnodeMsg->rpcMsg.handle, mnodeMsg->incomingTs, sec, mnodeMsg->retry); + pMsg, pMsg->rpcMsg.ahandle, pTable->info.tableId, pTable->vgId, pTable->tid, pTable->uid, + tstrerror(rpcMsg->code), pMsg->rpcMsg.handle, pMsg->incomingTs, sec, pMsg->retry); - SSdbOper oper = {.type = SDB_OPER_GLOBAL, .table = tsChildTableSdb, .pObj = pTable}; - sdbDeleteRow(&oper); + SSdbRow row = {.type = SDB_OPER_GLOBAL, .pTable = tsChildTableSdb, .pObj = pTable}; + sdbDeleteRow(&row); if (rpcMsg->code == TSDB_CODE_APP_NOT_READY) { //Avoid retry again in client rpcMsg->code = TSDB_CODE_MND_VGROUP_NOT_READY; } - dnodeSendRpcMWriteRsp(mnodeMsg, rpcMsg->code); + dnodeSendRpcMWriteRsp(pMsg, rpcMsg->code); } } } @@ -2455,28 +2455,28 @@ static void mnodeProcessCreateChildTableRsp(SRpcMsg *rpcMsg) { static void mnodeProcessAlterTableRsp(SRpcMsg *rpcMsg) { if (rpcMsg->ahandle == NULL) return; - SMnodeMsg *mnodeMsg = rpcMsg->ahandle; - mnodeMsg->received++; + SMnodeMsg *pMsg = rpcMsg->ahandle; + pMsg->received++; - SCTableObj *pTable = (SCTableObj *)mnodeMsg->pTable; + SCTableObj *pTable = (SCTableObj *)pMsg->pTable; assert(pTable); if (rpcMsg->code == TSDB_CODE_SUCCESS || rpcMsg->code == TSDB_CODE_TDB_TABLE_ALREADY_EXIST) { - mDebug("app:%p:%p, ctable:%s, altered in dnode, thandle:%p result:%s", mnodeMsg->rpcMsg.ahandle, mnodeMsg, - pTable->info.tableId, mnodeMsg->rpcMsg.handle, tstrerror(rpcMsg->code)); + mDebug("msg:%p, app:%p ctable:%s, altered in dnode, thandle:%p result:%s", pMsg, pMsg->rpcMsg.ahandle, + pTable->info.tableId, pMsg->rpcMsg.handle, tstrerror(rpcMsg->code)); - dnodeSendRpcMWriteRsp(mnodeMsg, TSDB_CODE_SUCCESS); + dnodeSendRpcMWriteRsp(pMsg, TSDB_CODE_SUCCESS); } else { - if (mnodeMsg->retry++ < ALTER_CTABLE_RETRY_TIMES) { - mDebug("app:%p:%p, table:%s, alter table rsp received, need retry, times:%d result:%s thandle:%p", - mnodeMsg->rpcMsg.ahandle, mnodeMsg, pTable->info.tableId, mnodeMsg->retry, tstrerror(rpcMsg->code), - mnodeMsg->rpcMsg.handle); + if (pMsg->retry++ < ALTER_CTABLE_RETRY_TIMES) { + mDebug("msg:%p, app:%p table:%s, alter table rsp received, need retry, times:%d result:%s thandle:%p", + pMsg->rpcMsg.ahandle, pMsg, pTable->info.tableId, pMsg->retry, tstrerror(rpcMsg->code), + pMsg->rpcMsg.handle); - dnodeDelayReprocessMWriteMsg(mnodeMsg); + dnodeDelayReprocessMWriteMsg(pMsg); } else { - mError("app:%p:%p, table:%s, failed to alter in dnode, result:%s thandle:%p", mnodeMsg->rpcMsg.ahandle, mnodeMsg, - pTable->info.tableId, tstrerror(rpcMsg->code), mnodeMsg->rpcMsg.handle); - dnodeSendRpcMWriteRsp(mnodeMsg, rpcMsg->code); + mError("msg:%p, app:%p table:%s, failed to alter in dnode, result:%s thandle:%p", pMsg, pMsg->rpcMsg.ahandle, + pTable->info.tableId, tstrerror(rpcMsg->code), pMsg->rpcMsg.handle); + dnodeSendRpcMWriteRsp(pMsg, rpcMsg->code); } } } @@ -2719,12 +2719,12 @@ static int32_t mnodeRetrieveShowTables(SShowObj *pShow, char *data, int32_t rows static int32_t mnodeProcessAlterTableMsg(SMnodeMsg *pMsg) { SAlterTableMsg *pAlter = pMsg->rpcMsg.pCont; - mDebug("app:%p:%p, table:%s, alter table msg is received from thandle:%p", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p table:%s, alter table msg is received from thandle:%p", pMsg, pMsg->rpcMsg.ahandle, pAlter->tableId, pMsg->rpcMsg.handle); if (pMsg->pDb == NULL) pMsg->pDb = mnodeGetDbByTableId(pAlter->tableId); if (pMsg->pDb == NULL) { - mError("app:%p:%p, table:%s, failed to alter table, db not selected", pMsg->rpcMsg.ahandle, pMsg, pAlter->tableId); + mError("msg:%p, app:%p table:%s, failed to alter table, db not selected", pMsg, pMsg->rpcMsg.ahandle, pAlter->tableId); return TSDB_CODE_MND_DB_NOT_SELECTED; } @@ -2734,13 +2734,13 @@ static int32_t mnodeProcessAlterTableMsg(SMnodeMsg *pMsg) { } if (mnodeCheckIsMonitorDB(pMsg->pDb->name, tsMonitorDbName)) { - mError("app:%p:%p, table:%s, failed to alter table, its log db", pMsg->rpcMsg.ahandle, pMsg, pAlter->tableId); + mError("msg:%p, app:%p table:%s, failed to alter table, its log db", pMsg, pMsg->rpcMsg.ahandle, pAlter->tableId); return TSDB_CODE_MND_MONITOR_DB_FORBIDDEN; } if (pMsg->pTable == NULL) pMsg->pTable = mnodeGetTable(pAlter->tableId); if (pMsg->pTable == NULL) { - mError("app:%p:%p, table:%s, failed to alter table, table not exist", pMsg->rpcMsg.ahandle, pMsg, pAlter->tableId); + mError("msg:%p, app:%p table:%s, failed to alter table, table not exist", pMsg, pMsg->rpcMsg.ahandle, pAlter->tableId); return TSDB_CODE_MND_INVALID_TABLE_NAME; } @@ -2749,7 +2749,7 @@ static int32_t mnodeProcessAlterTableMsg(SMnodeMsg *pMsg) { pAlter->tagValLen = htonl(pAlter->tagValLen); if (pAlter->numOfCols > 2) { - mError("app:%p:%p, table:%s, error numOfCols:%d in alter table", pMsg->rpcMsg.ahandle, pMsg, pAlter->tableId, + mError("msg:%p, app:%p table:%s, error numOfCols:%d in alter table", pMsg, pMsg->rpcMsg.ahandle, pAlter->tableId, pAlter->numOfCols); return TSDB_CODE_MND_APP_ERROR; } @@ -2760,7 +2760,7 @@ static int32_t mnodeProcessAlterTableMsg(SMnodeMsg *pMsg) { int32_t code = TSDB_CODE_COM_OPS_NOT_SUPPORT; if (pMsg->pTable->type == TSDB_SUPER_TABLE) { - mDebug("app:%p:%p, table:%s, start to alter stable", pMsg->rpcMsg.ahandle, pMsg, pAlter->tableId); + mDebug("msg:%p, app:%p table:%s, start to alter stable", pMsg, pMsg->rpcMsg.ahandle, pAlter->tableId); if (pAlter->type == TSDB_ALTER_TABLE_ADD_TAG_COLUMN) { code = mnodeAddSuperTableTag(pMsg, pAlter->schema, 1); } else if (pAlter->type == TSDB_ALTER_TABLE_DROP_TAG_COLUMN) { @@ -2776,7 +2776,7 @@ static int32_t mnodeProcessAlterTableMsg(SMnodeMsg *pMsg) { } else { } } else { - mDebug("app:%p:%p, table:%s, start to alter ctable", pMsg->rpcMsg.ahandle, pMsg, pAlter->tableId); + mDebug("msg:%p, app:%p table:%s, start to alter ctable", pMsg, pMsg->rpcMsg.ahandle, pAlter->tableId); if (pAlter->type == TSDB_ALTER_TABLE_UPDATE_TAG_VAL) { return TSDB_CODE_COM_OPS_NOT_SUPPORT; } else if (pAlter->type == TSDB_ALTER_TABLE_ADD_COLUMN) { diff --git a/src/mnode/src/mnodeUser.c b/src/mnode/src/mnodeUser.c index cd02d5a935..dc76d92eb8 100644 --- a/src/mnode/src/mnodeUser.c +++ b/src/mnode/src/mnodeUser.c @@ -42,13 +42,13 @@ static int32_t mnodeProcessAlterUserMsg(SMnodeMsg *pMsg); static int32_t mnodeProcessDropUserMsg(SMnodeMsg *pMsg); static int32_t mnodeProcessAuthMsg(SMnodeMsg *pMsg); -static int32_t mnodeUserActionDestroy(SSdbOper *pOper) { - tfree(pOper->pObj); +static int32_t mnodeUserActionDestroy(SSdbRow *pRow) { + tfree(pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t mnodeUserActionInsert(SSdbOper *pOper) { - SUserObj *pUser = pOper->pObj; +static int32_t mnodeUserActionInsert(SSdbRow *pRow) { + SUserObj *pUser = pRow->pObj; SAcctObj *pAcct = mnodeGetAcct(pUser->acct); if (pAcct != NULL) { @@ -62,8 +62,8 @@ static int32_t mnodeUserActionInsert(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeUserActionDelete(SSdbOper *pOper) { - SUserObj *pUser = pOper->pObj; +static int32_t mnodeUserActionDelete(SSdbRow *pRow) { + SUserObj *pUser = pRow->pObj; SAcctObj *pAcct = mnodeGetAcct(pUser->acct); if (pAcct != NULL) { @@ -74,8 +74,8 @@ static int32_t mnodeUserActionDelete(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeUserActionUpdate(SSdbOper *pOper) { - SUserObj *pUser = pOper->pObj; +static int32_t mnodeUserActionUpdate(SSdbRow *pRow) { + SUserObj *pUser = pRow->pObj; SUserObj *pSaved = mnodeGetUser(pUser->user); if (pUser != pSaved) { memcpy(pSaved, pUser, tsUserUpdateSize); @@ -85,19 +85,19 @@ static int32_t mnodeUserActionUpdate(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeUserActionEncode(SSdbOper *pOper) { - SUserObj *pUser = pOper->pObj; - memcpy(pOper->rowData, pUser, tsUserUpdateSize); - pOper->rowSize = tsUserUpdateSize; +static int32_t mnodeUserActionEncode(SSdbRow *pRow) { + SUserObj *pUser = pRow->pObj; + memcpy(pRow->rowData, pUser, tsUserUpdateSize); + pRow->rowSize = tsUserUpdateSize; return TSDB_CODE_SUCCESS; } -static int32_t mnodeUserActionDecode(SSdbOper *pOper) { +static int32_t mnodeUserActionDecode(SSdbRow *pRow) { SUserObj *pUser = (SUserObj *)calloc(1, sizeof(SUserObj)); if (pUser == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - memcpy(pUser, pOper->rowData, tsUserUpdateSize); - pOper->pObj = pUser; + memcpy(pUser, pRow->rowData, tsUserUpdateSize); + pRow->pObj = pUser; return TSDB_CODE_SUCCESS; } @@ -150,25 +150,25 @@ int32_t mnodeInitUsers() { SUserObj tObj; tsUserUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; - SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_USER, - .tableName = "users", + SSdbTableDesc desc = { + .id = SDB_TABLE_USER, + .name = "users", .hashSessions = TSDB_DEFAULT_USERS_HASH_SIZE, .maxRowSize = tsUserUpdateSize, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_STRING, - .insertFp = mnodeUserActionInsert, - .deleteFp = mnodeUserActionDelete, - .updateFp = mnodeUserActionUpdate, - .encodeFp = mnodeUserActionEncode, - .decodeFp = mnodeUserActionDecode, - .destroyFp = mnodeUserActionDestroy, - .restoredFp = mnodeUserActionRestored + .fpInsert = mnodeUserActionInsert, + .fpDelete = mnodeUserActionDelete, + .fpUpdate = mnodeUserActionUpdate, + .fpEncode = mnodeUserActionEncode, + .fpDecode = mnodeUserActionDecode, + .fpDestroy = mnodeUserActionDestroy, + .fpRestored = mnodeUserActionRestored }; - tsUserSdb = sdbOpenTable(&tableDesc); + tsUserSdb = sdbOpenTable(&desc); if (tsUserSdb == NULL) { - mError("table:%s, failed to create hash", tableDesc.tableName); + mError("table:%s, failed to create hash", desc.name); return -1; } @@ -179,7 +179,7 @@ int32_t mnodeInitUsers() { mnodeAddShowRetrieveHandle(TSDB_MGMT_TABLE_USER, mnodeRetrieveUsers); mnodeAddPeerMsgHandle(TSDB_MSG_TYPE_DM_AUTH, mnodeProcessAuthMsg); - mDebug("table:%s, hash is created", tableDesc.tableName); + mDebug("table:%s, hash is created", desc.name); return 0; } @@ -205,14 +205,14 @@ void mnodeDecUserRef(SUserObj *pUser) { } static int32_t mnodeUpdateUser(SUserObj *pUser, void *pMsg) { - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsUserSdb, - .pObj = pUser, - .pMsg = pMsg + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsUserSdb, + .pObj = pUser, + .pMsg = pMsg }; - int32_t code = sdbUpdateRow(&oper); + int32_t code = sdbUpdateRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("user:%s, failed to alter by %s, reason:%s", pUser->user, mnodeGetUserFromMsg(pMsg), tstrerror(code)); } else { @@ -259,15 +259,15 @@ int32_t mnodeCreateUser(SAcctObj *pAcct, char *name, char *pass, void *pMsg) { pUser->superAuth = 1; } - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsUserSdb, - .pObj = pUser, - .rowSize = sizeof(SUserObj), - .pMsg = pMsg + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsUserSdb, + .pObj = pUser, + .rowSize = sizeof(SUserObj), + .pMsg = pMsg }; - code = sdbInsertRow(&oper); + code = sdbInsertRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("user:%s, failed to create by %s, reason:%s", pUser->user, mnodeGetUserFromMsg(pMsg), tstrerror(code)); tfree(pUser); @@ -279,14 +279,14 @@ int32_t mnodeCreateUser(SAcctObj *pAcct, char *name, char *pass, void *pMsg) { } static int32_t mnodeDropUser(SUserObj *pUser, void *pMsg) { - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsUserSdb, - .pObj = pUser, - .pMsg = pMsg + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsUserSdb, + .pObj = pUser, + .pMsg = pMsg }; - int32_t code = sdbDeleteRow(&oper); + int32_t code = sdbDeleteRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("user:%s, failed to drop by %s, reason:%s", pUser->user, mnodeGetUserFromMsg(pMsg), tstrerror(code)); } else { @@ -562,12 +562,12 @@ void mnodeDropAllUsers(SAcctObj *pAcct) { if (pUser == NULL) break; if (strncmp(pUser->acct, pAcct->user, acctNameLen) == 0) { - SSdbOper oper = { - .type = SDB_OPER_LOCAL, - .table = tsUserSdb, - .pObj = pUser, + SSdbRow row = { + .type = SDB_OPER_LOCAL, + .pTable = tsUserSdb, + .pObj = pUser, }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); numOfUsers++; } diff --git a/src/mnode/src/mnodeVgroup.c b/src/mnode/src/mnodeVgroup.c index 9e398e94f1..f9a49e5ec2 100644 --- a/src/mnode/src/mnodeVgroup.c +++ b/src/mnode/src/mnodeVgroup.c @@ -72,13 +72,13 @@ static void mnodeDestroyVgroup(SVgObj *pVgroup) { tfree(pVgroup); } -static int32_t mnodeVgroupActionDestroy(SSdbOper *pOper) { - mnodeDestroyVgroup(pOper->pObj); +static int32_t mnodeVgroupActionDestroy(SSdbRow *pRow) { + mnodeDestroyVgroup(pRow->pObj); return TSDB_CODE_SUCCESS; } -static int32_t mnodeVgroupActionInsert(SSdbOper *pOper) { - SVgObj *pVgroup = pOper->pObj; +static int32_t mnodeVgroupActionInsert(SSdbRow *pRow) { + SVgObj *pVgroup = pRow->pObj; // refer to db SDbObj *pDb = mnodeGetDb(pVgroup->dbName); @@ -115,8 +115,8 @@ static int32_t mnodeVgroupActionInsert(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeVgroupActionDelete(SSdbOper *pOper) { - SVgObj *pVgroup = pOper->pObj; +static int32_t mnodeVgroupActionDelete(SSdbRow *pRow) { + SVgObj *pVgroup = pRow->pObj; if (pVgroup->pDb == NULL) { mError("vgId:%d, db:%s is not exist while insert into hash", pVgroup->vgId, pVgroup->dbName); @@ -137,8 +137,8 @@ static int32_t mnodeVgroupActionDelete(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeVgroupActionUpdate(SSdbOper *pOper) { - SVgObj *pNew = pOper->pObj; +static int32_t mnodeVgroupActionUpdate(SSdbRow *pRow) { + SVgObj *pNew = pRow->pObj; SVgObj *pVgroup = mnodeGetVgroup(pNew->vgId); if (pVgroup != pNew) { @@ -176,25 +176,25 @@ static int32_t mnodeVgroupActionUpdate(SSdbOper *pOper) { return TSDB_CODE_SUCCESS; } -static int32_t mnodeVgroupActionEncode(SSdbOper *pOper) { - SVgObj *pVgroup = pOper->pObj; - memcpy(pOper->rowData, pVgroup, tsVgUpdateSize); - SVgObj *pTmpVgroup = pOper->rowData; +static int32_t mnodeVgroupActionEncode(SSdbRow *pRow) { + SVgObj *pVgroup = pRow->pObj; + memcpy(pRow->rowData, pVgroup, tsVgUpdateSize); + SVgObj *pTmpVgroup = pRow->rowData; for (int32_t i = 0; i < TSDB_MAX_REPLICA; ++i) { pTmpVgroup->vnodeGid[i].pDnode = NULL; pTmpVgroup->vnodeGid[i].role = 0; } - pOper->rowSize = tsVgUpdateSize; + pRow->rowSize = tsVgUpdateSize; return TSDB_CODE_SUCCESS; } -static int32_t mnodeVgroupActionDecode(SSdbOper *pOper) { +static int32_t mnodeVgroupActionDecode(SSdbRow *pRow) { SVgObj *pVgroup = (SVgObj *) calloc(1, sizeof(SVgObj)); if (pVgroup == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY; - memcpy(pVgroup, pOper->rowData, tsVgUpdateSize); - pOper->pObj = pVgroup; + memcpy(pVgroup, pRow->rowData, tsVgUpdateSize); + pRow->pObj = pVgroup; return TSDB_CODE_SUCCESS; } @@ -206,23 +206,23 @@ int32_t mnodeInitVgroups() { SVgObj tObj; tsVgUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; - SSdbTableDesc tableDesc = { - .tableId = SDB_TABLE_VGROUP, - .tableName = "vgroups", + SSdbTableDesc desc = { + .id = SDB_TABLE_VGROUP, + .name = "vgroups", .hashSessions = TSDB_DEFAULT_VGROUPS_HASH_SIZE, .maxRowSize = tsVgUpdateSize, .refCountPos = (int8_t *)(&tObj.refCount) - (int8_t *)&tObj, .keyType = SDB_KEY_AUTO, - .insertFp = mnodeVgroupActionInsert, - .deleteFp = mnodeVgroupActionDelete, - .updateFp = mnodeVgroupActionUpdate, - .encodeFp = mnodeVgroupActionEncode, - .decodeFp = mnodeVgroupActionDecode, - .destroyFp = mnodeVgroupActionDestroy, - .restoredFp = mnodeVgroupActionRestored, + .fpInsert = mnodeVgroupActionInsert, + .fpDelete = mnodeVgroupActionDelete, + .fpUpdate = mnodeVgroupActionUpdate, + .fpEncode = mnodeVgroupActionEncode, + .fpDecode = mnodeVgroupActionDecode, + .fpDestroy = mnodeVgroupActionDestroy, + .fpRestored = mnodeVgroupActionRestored, }; - tsVgroupSdb = sdbOpenTable(&tableDesc); + tsVgroupSdb = sdbOpenTable(&desc); if (tsVgroupSdb == NULL) { mError("failed to init vgroups data"); return -1; @@ -253,13 +253,13 @@ SVgObj *mnodeGetVgroup(int32_t vgId) { } void mnodeUpdateVgroup(SVgObj *pVgroup) { - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsVgroupSdb, - .pObj = pVgroup + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsVgroupSdb, + .pObj = pVgroup }; - int32_t code = sdbUpdateRow(&oper); + int32_t code = sdbUpdateRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mError("vgId:%d, failed to update vgroup", pVgroup->vgId); } @@ -421,7 +421,7 @@ int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSi int32_t sid = taosAllocateId(pVgroup->idPool); if (sid <= 0) { - mDebug("app:%p:%p, db:%s, no enough sid in vgId:%d", pMsg->rpcMsg.ahandle, pMsg, pDb->name, pVgroup->vgId); + mDebug("msg:%p, app:%p db:%s, no enough sid in vgId:%d", pMsg, pMsg->rpcMsg.ahandle, pDb->name, pVgroup->vgId); continue; } @@ -442,8 +442,8 @@ int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSi int32_t code = TSDB_CODE_MND_NO_ENOUGH_DNODES; if (pDb->numOfVgroups < maxVgroupsPerDb) { - mDebug("app:%p:%p, db:%s, try to create a new vgroup, numOfVgroups:%d maxVgroupsPerDb:%d", pMsg->rpcMsg.ahandle, - pMsg, pDb->name, pDb->numOfVgroups, maxVgroupsPerDb); + mDebug("msg:%p, app:%p db:%s, try to create a new vgroup, numOfVgroups:%d maxVgroupsPerDb:%d", pMsg, + pMsg->rpcMsg.ahandle, pDb->name, pDb->numOfVgroups, maxVgroupsPerDb); pthread_mutex_unlock(&pDb->mutex); code = mnodeCreateVgroup(pMsg); if (code == TSDB_CODE_MND_ACTION_IN_PROGRESS) { @@ -455,8 +455,8 @@ int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSi if (pDb->numOfVgroups < 1) { pthread_mutex_unlock(&pDb->mutex); - mDebug("app:%p:%p, db:%s, failed create new vgroup since:%s, numOfVgroups:%d maxVgroupsPerDb:%d ", - pMsg->rpcMsg.ahandle, pMsg, pDb->name, tstrerror(code), pDb->numOfVgroups, maxVgroupsPerDb); + mDebug("msg:%p, app:%p db:%s, failed create new vgroup since:%s, numOfVgroups:%d maxVgroupsPerDb:%d ", pMsg, + pMsg->rpcMsg.ahandle, pDb->name, tstrerror(code), pDb->numOfVgroups, maxVgroupsPerDb); return code; } @@ -474,7 +474,7 @@ int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSi int32_t sid = taosAllocateId(pVgroup->idPool); if (sid <= 0) { - mError("app:%p:%p, db:%s, no enough sid in vgId:%d", pMsg->rpcMsg.ahandle, pMsg, pDb->name, pVgroup->vgId); + mError("msg:%p, app:%p db:%s, no enough sid in vgId:%d", pMsg, pMsg->rpcMsg.ahandle, pDb->name, pVgroup->vgId); pthread_mutex_unlock(&pDb->mutex); return TSDB_CODE_MND_NO_ENOUGH_DNODES; } @@ -496,10 +496,10 @@ static int32_t mnodeCreateVgroupFp(SMnodeMsg *pMsg) { SDbObj *pDb = pMsg->pDb; assert(pVgroup); - mInfo("app:%p:%p, vgId:%d, is created in mnode, db:%s replica:%d", pMsg->rpcMsg.ahandle, pMsg, pVgroup->vgId, + mInfo("msg:%p, app:%p vgId:%d, is created in mnode, db:%s replica:%d", pMsg, pMsg->rpcMsg.ahandle, pVgroup->vgId, pDb->name, pVgroup->numOfVnodes); for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { - mInfo("app:%p:%p, vgId:%d, index:%d, dnode:%d", pMsg->rpcMsg.ahandle, pMsg, pVgroup->vgId, i, + mInfo("msg:%p, app:%p vgId:%d, index:%d, dnode:%d", pMsg, pMsg->rpcMsg.ahandle, pVgroup->vgId, i, pVgroup->vnodeGid[i].dnodeId); } @@ -517,30 +517,30 @@ static int32_t mnodeCreateVgroupCb(SMnodeMsg *pMsg, int32_t code) { assert(pVgroup); if (code != TSDB_CODE_SUCCESS) { - mError("app:%p:%p, vgId:%d, failed to create in sdb, reason:%s", pMsg->rpcMsg.ahandle, pMsg, pVgroup->vgId, + mError("msg:%p, app:%p vgId:%d, failed to create in sdb, reason:%s", pMsg, pMsg->rpcMsg.ahandle, pVgroup->vgId, tstrerror(code)); - SSdbOper desc = {.type = SDB_OPER_GLOBAL, .pObj = pVgroup, .table = tsVgroupSdb}; + SSdbRow desc = {.type = SDB_OPER_GLOBAL, .pObj = pVgroup, .pTable = tsVgroupSdb}; sdbDeleteRow(&desc); return code; } else { - mInfo("app:%p:%p, vgId:%d, is created in sdb, db:%s replica:%d", pMsg->rpcMsg.ahandle, pMsg, pVgroup->vgId, - pDb->name, pVgroup->numOfVnodes); + mInfo("msg:%p, app:%p vgId:%d, is created in sdb, db:%s replica:%d", pMsg, pMsg->rpcMsg.ahandle, pVgroup->vgId, + pDb->name, pVgroup->numOfVnodes); pVgroup->status = TAOS_VG_STATUS_READY; - SSdbOper desc = {.type = SDB_OPER_GLOBAL, .pObj = pVgroup, .table = tsVgroupSdb}; + SSdbRow desc = {.type = SDB_OPER_GLOBAL, .pObj = pVgroup, .pTable = tsVgroupSdb}; (void)sdbUpdateRow(&desc); dnodeReprocessMWriteMsg(pMsg); return TSDB_CODE_MND_ACTION_IN_PROGRESS; // if (pVgroup->status == TAOS_VG_STATUS_CREATING || pVgroup->status == TAOS_VG_STATUS_READY) { - // mInfo("app:%p:%p, vgId:%d, is created in sdb, db:%s replica:%d", pMsg->rpcMsg.ahandle, pMsg, pVgroup->vgId, + // mInfo("msg:%p, app:%p vgId:%d, is created in sdb, db:%s replica:%d", pMsg, pMsg->rpcMsg.ahandle, pVgroup->vgId, // pDb->name, pVgroup->numOfVnodes); // pVgroup->status = TAOS_VG_STATUS_READY; - // SSdbOper desc = {.type = SDB_OPER_GLOBAL, .pObj = pVgroup, .table = tsVgroupSdb}; + // SSdbRow desc = {.type = SDB_OPER_GLOBAL, .pObj = pVgroup, .pTable = tsVgroupSdb}; // (void)sdbUpdateRow(&desc); // dnodeReprocessMWriteMsg(pMsg); // return TSDB_CODE_MND_ACTION_IN_PROGRESS; // } else { - // mError("app:%p:%p, vgId:%d, is created in sdb, db:%s replica:%d, but vgroup is dropping", pMsg->rpcMsg.ahandle, + // mError("msg:%p, app:%p vgId:%d, is created in sdb, db:%s replica:%d, but vgroup is dropping", pMsg->rpcMsg.ahandle, // pMsg, pVgroup->vgId, pDb->name, pVgroup->numOfVnodes); // return TSDB_CODE_MND_VGROUP_NOT_EXIST; // } @@ -571,16 +571,16 @@ int32_t mnodeCreateVgroup(SMnodeMsg *pMsg) { pMsg->pVgroup = pVgroup; mnodeIncVgroupRef(pVgroup); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsVgroupSdb, - .pObj = pVgroup, - .rowSize = sizeof(SVgObj), - .pMsg = pMsg, - .reqFp = mnodeCreateVgroupFp + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsVgroupSdb, + .pObj = pVgroup, + .rowSize = sizeof(SVgObj), + .pMsg = pMsg, + .fpReq = mnodeCreateVgroupFp }; - code = sdbInsertRow(&oper); + code = sdbInsertRow(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { pMsg->pVgroup = NULL; mnodeDestroyVgroup(pVgroup); @@ -595,12 +595,12 @@ void mnodeDropVgroup(SVgObj *pVgroup, void *ahandle) { } else { mDebug("vgId:%d, replica:%d is deleting from sdb", pVgroup->vgId, pVgroup->numOfVnodes); mnodeSendDropVgroupMsg(pVgroup, NULL); - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsVgroupSdb, - .pObj = pVgroup + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsVgroupSdb, + .pObj = pVgroup }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); } } @@ -770,7 +770,7 @@ static int32_t mnodeRetrieveVgroups(SShowObj *pShow, char *data, int32_t rows, v SDnodeObj * pDnode = pVgroup->vnodeGid[i].pDnode; const char *role = "NULL"; if (pDnode != NULL) { - role = mnodeGetMnodeRoleStr(pVgroup->vnodeGid[i].role); + role = syncRole[pVgroup->vnodeGid[i].role]; } pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; @@ -957,28 +957,28 @@ static void mnodeProcessCreateVnodeRsp(SRpcMsg *rpcMsg) { if (mnodeMsg->received != mnodeMsg->expected) return; if (mnodeMsg->received == mnodeMsg->successed) { - SSdbOper oper = { + SSdbRow row = { .type = SDB_OPER_GLOBAL, - .table = tsVgroupSdb, + .pTable = tsVgroupSdb, .pObj = pVgroup, .rowSize = sizeof(SVgObj), .pMsg = mnodeMsg, - .writeCb = mnodeCreateVgroupCb + .fpRsp = mnodeCreateVgroupCb }; - int32_t code = sdbInsertRowImp(&oper); + int32_t code = sdbInsertRowToQueue(&row); if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_MND_ACTION_IN_PROGRESS) { mnodeMsg->pVgroup = NULL; mnodeDestroyVgroup(pVgroup); dnodeSendRpcMWriteRsp(mnodeMsg, code); } } else { - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsVgroupSdb, - .pObj = pVgroup + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsVgroupSdb, + .pObj = pVgroup }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); dnodeSendRpcMWriteRsp(mnodeMsg, mnodeMsg->code); } } @@ -1031,12 +1031,12 @@ static void mnodeProcessDropVnodeRsp(SRpcMsg *rpcMsg) { if (mnodeMsg->received != mnodeMsg->expected) return; - SSdbOper oper = { - .type = SDB_OPER_GLOBAL, - .table = tsVgroupSdb, - .pObj = pVgroup + SSdbRow row = { + .type = SDB_OPER_GLOBAL, + .pTable = tsVgroupSdb, + .pObj = pVgroup }; - int32_t code = sdbDeleteRow(&oper); + int32_t code = sdbDeleteRow(&row); if (code != 0) { code = TSDB_CODE_MND_SDB_ERROR; } @@ -1084,12 +1084,12 @@ void mnodeDropAllDnodeVgroups(SDnodeObj *pDropDnode) { if (pVgroup->vnodeGid[0].dnodeId == pDropDnode->dnodeId) { mnodeDropAllChildTablesInVgroups(pVgroup); - SSdbOper oper = { - .type = SDB_OPER_LOCAL, - .table = tsVgroupSdb, - .pObj = pVgroup, + SSdbRow row = { + .type = SDB_OPER_LOCAL, + .pTable = tsVgroupSdb, + .pObj = pVgroup, }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); numOfVgroups++; } mnodeDecVgroupRef(pVgroup); @@ -1135,12 +1135,12 @@ void mnodeDropAllDbVgroups(SDbObj *pDropDb) { if (pVgroup == NULL) break; if (pVgroup->pDb == pDropDb) { - SSdbOper oper = { - .type = SDB_OPER_LOCAL, - .table = tsVgroupSdb, - .pObj = pVgroup, + SSdbRow row = { + .type = SDB_OPER_LOCAL, + .pTable = tsVgroupSdb, + .pObj = pVgroup, }; - sdbDeleteRow(&oper); + sdbDeleteRow(&row); numOfVgroups++; } diff --git a/src/mnode/src/mnodeWrite.c b/src/mnode/src/mnodeWrite.c index d021745d2b..8893316ffc 100644 --- a/src/mnode/src/mnodeWrite.c +++ b/src/mnode/src/mnodeWrite.c @@ -43,7 +43,7 @@ void mnodeAddWriteMsgHandle(uint8_t msgType, int32_t (*fp)(SMnodeMsg *mnodeMsg)) int32_t mnodeProcessWrite(SMnodeMsg *pMsg) { if (pMsg->rpcMsg.pCont == NULL) { - mError("app:%p:%p, msg:%s content is null", pMsg->rpcMsg.ahandle, pMsg, taosMsg[pMsg->rpcMsg.msgType]); + mError("msg:%p, app:%p type:%s content is null", pMsg, pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); return TSDB_CODE_MND_INVALID_MSG_LEN; } @@ -54,15 +54,15 @@ int32_t mnodeProcessWrite(SMnodeMsg *pMsg) { rpcRsp->rsp = epSet; rpcRsp->len = sizeof(SRpcEpSet); - mDebug("app:%p:%p, msg:%s in write queue, will be redirected, numOfEps:%d inUse:%d", pMsg->rpcMsg.ahandle, pMsg, + mDebug("msg:%p, app:%p type:%s in write queue, will be redirected, numOfEps:%d inUse:%d", pMsg, pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType], epSet->numOfEps, epSet->inUse); for (int32_t i = 0; i < epSet->numOfEps; ++i) { if (strcmp(epSet->fqdn[i], tsLocalFqdn) == 0 && htons(epSet->port[i]) == tsServerPort) { epSet->inUse = (i + 1) % epSet->numOfEps; - mDebug("app:%p:%p, mnode index:%d ep:%s:%d, set inUse to %d", pMsg->rpcMsg.ahandle, pMsg, i, epSet->fqdn[i], + mDebug("msg:%p, app:%p mnode index:%d ep:%s:%d, set inUse to %d", pMsg, pMsg->rpcMsg.ahandle, i, epSet->fqdn[i], htons(epSet->port[i]), epSet->inUse); } else { - mDebug("app:%p:%p, mnode index:%d ep:%s:%d", pMsg->rpcMsg.ahandle, pMsg, i, epSet->fqdn[i], + mDebug("msg:%p, app:%p mnode index:%d ep:%s:%d", pMsg, pMsg->rpcMsg.ahandle, i, epSet->fqdn[i], htons(epSet->port[i])); } } @@ -71,19 +71,19 @@ int32_t mnodeProcessWrite(SMnodeMsg *pMsg) { } if (tsMnodeProcessWriteMsgFp[pMsg->rpcMsg.msgType] == NULL) { - mError("app:%p:%p, msg:%s not processed", pMsg->rpcMsg.ahandle, pMsg, taosMsg[pMsg->rpcMsg.msgType]); + mError("msg:%p, app:%p type:%s not processed", pMsg, pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); return TSDB_CODE_MND_MSG_NOT_PROCESSED; } int32_t code = mnodeInitMsg(pMsg); if (code != TSDB_CODE_SUCCESS) { - mError("app:%p:%p, msg:%s not processed, reason:%s", pMsg->rpcMsg.ahandle, pMsg, taosMsg[pMsg->rpcMsg.msgType], + mError("msg:%p, app:%p type:%s not processed, reason:%s", pMsg, pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType], tstrerror(code)); return code; } if (!pMsg->pUser->writeAuth) { - mError("app:%p:%p, msg:%s not processed, no write auth", pMsg->rpcMsg.ahandle, pMsg, + mError("msg:%p, app:%p type:%s not processed, no write auth", pMsg, pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]); return TSDB_CODE_MND_NO_RIGHTS; } diff --git a/src/os/inc/osTime.h b/src/os/inc/osTime.h index 6b209219c6..b20ccadadb 100644 --- a/src/os/inc/osTime.h +++ b/src/os/inc/osTime.h @@ -38,14 +38,14 @@ int32_t taosGetTimestampSec(); static FORCE_INLINE int64_t taosGetTimestampMs() { struct timeval systemTime; gettimeofday(&systemTime, NULL); - return (int64_t)systemTime.tv_sec * 1000L + (uint64_t)systemTime.tv_usec / 1000; + return (int64_t)systemTime.tv_sec * 1000L + (int64_t)systemTime.tv_usec / 1000; } //@return timestamp in microsecond static FORCE_INLINE int64_t taosGetTimestampUs() { struct timeval systemTime; gettimeofday(&systemTime, NULL); - return (int64_t)systemTime.tv_sec * 1000000L + (uint64_t)systemTime.tv_usec; + return (int64_t)systemTime.tv_sec * 1000000L + (int64_t)systemTime.tv_usec; } /* diff --git a/src/os/inc/osWindows.h b/src/os/inc/osWindows.h index 36e30528bf..5003e48c44 100644 --- a/src/os/inc/osWindows.h +++ b/src/os/inc/osWindows.h @@ -43,6 +43,7 @@ #include "msvcProcess.h" #include "msvcDirect.h" #include "msvcFcntl.h" +#include "msvcLibgen.h" #include "msvcStdio.h" #include "sys/msvcStat.h" #include "sys/msvcTypes.h" diff --git a/src/os/src/windows/wSysinfo.c b/src/os/src/windows/wSysinfo.c index 61adc3ee14..1bfee25c4a 100644 --- a/src/os/src/windows/wSysinfo.c +++ b/src/os/src/windows/wSysinfo.c @@ -31,7 +31,10 @@ #pragma comment(lib, "Mswsock.lib ") #endif +#pragma warning(push) +#pragma warning(disable:4091) #include +#pragma warning(pop) static void taosGetSystemTimezone() { // get and set default timezone diff --git a/src/plugins/http/inc/httpInt.h b/src/plugins/http/inc/httpInt.h index affc0e838e..ebdfabf310 100644 --- a/src/plugins/http/inc/httpInt.h +++ b/src/plugins/http/inc/httpInt.h @@ -118,7 +118,7 @@ typedef struct { typedef struct { char *module; - bool (*decodeFp)(struct HttpContext *pContext); + bool (*fpDecode)(struct HttpContext *pContext); } HttpDecodeMethod; typedef struct { diff --git a/src/plugins/http/src/httpHandle.c b/src/plugins/http/src/httpHandle.c index b50217cfc4..7c56507514 100644 --- a/src/plugins/http/src/httpHandle.c +++ b/src/plugins/http/src/httpHandle.c @@ -21,11 +21,11 @@ #include "httpHandle.h" bool httpDecodeRequest(HttpContext* pContext) { - if (pContext->decodeMethod->decodeFp == NULL) { + if (pContext->decodeMethod->fpDecode == NULL) { return false; } - return (*pContext->decodeMethod->decodeFp)(pContext); + return (*pContext->decodeMethod->fpDecode)(pContext); } /** diff --git a/src/plugins/monitor/src/monitorMain.c b/src/plugins/monitor/src/monitorMain.c index de1e0e233c..24998b54cd 100644 --- a/src/plugins/monitor/src/monitorMain.c +++ b/src/plugins/monitor/src/monitorMain.c @@ -148,10 +148,12 @@ static void *monitorThreadFunc(void *param) { } if (tsMonitor.state == MON_STATE_NOT_INIT) { + int code = 0; + for (; tsMonitor.cmdIndex < MON_CMD_MAX; ++tsMonitor.cmdIndex) { monitorBuildMonitorSql(tsMonitor.sql, tsMonitor.cmdIndex); void *res = taos_query(tsMonitor.conn, tsMonitor.sql); - int code = taos_errno(res); + code = taos_errno(res); taos_free_result(res); if (code != 0) { @@ -162,7 +164,7 @@ static void *monitorThreadFunc(void *param) { } } - if (tsMonitor.start) { + if (tsMonitor.start && code == 0) { tsMonitor.state = MON_STATE_INITED; } } diff --git a/src/query/inc/qExecutor.h b/src/query/inc/qExecutor.h index 6b4b188c5e..895b414a56 100644 --- a/src/query/inc/qExecutor.h +++ b/src/query/inc/qExecutor.h @@ -171,11 +171,10 @@ typedef struct SQuery { typedef struct SQueryRuntimeEnv { jmp_buf env; - SResultRow* pResultRow; // todo refactor to merge with SWindowResInfo SQuery* pQuery; SQLFunctionCtx* pCtx; int32_t numOfRowsPerPage; - uint16_t offset[TSDB_MAX_COLUMNS]; + uint16_t* offset; uint16_t scanFlag; // denotes reversed scan of data or not SFillInfo* pFillInfo; SWindowResInfo windowResInfo; diff --git a/src/query/inc/qUtil.h b/src/query/inc/qUtil.h index 93dca42fdc..4cd0e60ebe 100644 --- a/src/query/inc/qUtil.h +++ b/src/query/inc/qUtil.h @@ -34,7 +34,7 @@ int32_t initWindowResInfo(SWindowResInfo* pWindowResInfo, int32_t size, int32_t void cleanupTimeWindowInfo(SWindowResInfo* pWindowResInfo); void resetTimeWindowInfo(SQueryRuntimeEnv* pRuntimeEnv, SWindowResInfo* pWindowResInfo); -void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num); +void clearFirstNWindowRes(SQueryRuntimeEnv *pRuntimeEnv, int32_t num); void clearClosedTimeWindow(SQueryRuntimeEnv* pRuntimeEnv); int32_t numOfClosedTimeWindow(SWindowResInfo* pWindowResInfo); diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 869f57f117..d0874c36bc 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -177,7 +177,7 @@ static void getNextTimeWindow(SQuery* pQuery, STimeWindow* tw) { static int32_t mergeIntoGroupResultImpl(SQInfo *pQInfo, SArray *group); static void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult); -static void setWindowResOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult); +static void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult); static void resetMergeResultBuf(SQueryRuntimeEnv* pRuntimeEnv, SQLFunctionCtx *pCtx, SResultRow *pRow); static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId); @@ -618,7 +618,7 @@ static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SWindowRes // set time window for current result pResultRow->win = (*win); - setWindowResOutputBufInitCtx(pRuntimeEnv, pResultRow); + setResultRowOutputBufInitCtx(pRuntimeEnv, pResultRow); return TSDB_CODE_SUCCESS; } @@ -660,7 +660,13 @@ static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_se */ static int32_t doCheckQueryCompleted(SQueryRuntimeEnv *pRuntimeEnv, TSKEY lastKey, SWindowResInfo *pWindowResInfo) { SQuery *pQuery = pRuntimeEnv->pQuery; - if (pRuntimeEnv->scanFlag != MASTER_SCAN || (!QUERY_IS_INTERVAL_QUERY(pQuery))) { + if (pRuntimeEnv->scanFlag != MASTER_SCAN) { + return pWindowResInfo->size; + } + + // for group by normal column query, close time window and return. + if (!QUERY_IS_INTERVAL_QUERY(pQuery)) { + closeAllTimeWindow(pWindowResInfo); return pWindowResInfo->size; } @@ -847,35 +853,50 @@ static int32_t getNextQualifiedWindow(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow } int32_t startPos = 0; + // tumbling time window query, a special case of sliding time window query if (pQuery->interval.sliding == pQuery->interval.interval && prevPosition != -1) { int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order); startPos = prevPosition + factor; } else { - startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order); + if (startKey <= pDataBlockInfo->window.skey && QUERY_IS_ASC_QUERY(pQuery)) { + startPos = 0; + } else if (startKey >= pDataBlockInfo->window.ekey && !QUERY_IS_ASC_QUERY(pQuery)) { + startPos = pDataBlockInfo->rows - 1; + } else { + startPos = searchFn((char *)primaryKeys, pDataBlockInfo->rows, startKey, pQuery->order.order); + } } /* * This time window does not cover any data, try next time window, * this case may happen when the time window is too small */ - if (QUERY_IS_ASC_QUERY(pQuery) && primaryKeys[startPos] > pNext->ekey) { - TSKEY next = primaryKeys[startPos]; - if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { - pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision); - pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; + if (primaryKeys == NULL) { + if (QUERY_IS_ASC_QUERY(pQuery)) { + assert(pDataBlockInfo->window.skey <= pNext->ekey); } else { - pNext->ekey += ((next - pNext->ekey + pQuery->interval.sliding - 1)/pQuery->interval.sliding) * pQuery->interval.sliding; - pNext->skey = pNext->ekey - pQuery->interval.interval + 1; + assert(pDataBlockInfo->window.ekey >= pNext->skey); } - } else if ((!QUERY_IS_ASC_QUERY(pQuery)) && primaryKeys[startPos] < pNext->skey) { - TSKEY next = primaryKeys[startPos]; - if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { - pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision); - pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; - } else { - pNext->skey -= ((pNext->skey - next + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding; - pNext->ekey = pNext->skey + pQuery->interval.interval - 1; + } else { + if (QUERY_IS_ASC_QUERY(pQuery) && primaryKeys[startPos] > pNext->ekey) { + TSKEY next = primaryKeys[startPos]; + if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { + pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision); + pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; + } else { + pNext->ekey += ((next - pNext->ekey + pQuery->interval.sliding - 1)/pQuery->interval.sliding) * pQuery->interval.sliding; + pNext->skey = pNext->ekey - pQuery->interval.interval + 1; + } + } else if ((!QUERY_IS_ASC_QUERY(pQuery)) && primaryKeys[startPos] < pNext->skey) { + TSKEY next = primaryKeys[startPos]; + if (pQuery->interval.intervalUnit == 'n' || pQuery->interval.intervalUnit == 'y') { + pNext->skey = taosTimeTruncate(next, &pQuery->interval, pQuery->precision); + pNext->ekey = taosTimeAdd(pNext->skey, pQuery->interval.interval, pQuery->interval.intervalUnit, pQuery->precision) - 1; + } else { + pNext->skey -= ((pNext->skey - next + pQuery->interval.sliding - 1) / pQuery->interval.sliding) * pQuery->interval.sliding; + pNext->ekey = pNext->skey + pQuery->interval.interval - 1; + } } } @@ -1236,7 +1257,7 @@ static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx return QUERY_IS_ASC_QUERY(pQuery); } - // todo add comments + // denote the order type if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) { return pCtx->param[0].i64Key == pQuery->order.order; } @@ -1433,7 +1454,7 @@ static int32_t tableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBl // interval query with limit applied int32_t numOfRes = 0; - if (QUERY_IS_INTERVAL_QUERY(pQuery)) { + if (QUERY_IS_INTERVAL_QUERY(pQuery) || pRuntimeEnv->groupbyNormalCol) { numOfRes = doCheckQueryCompleted(pRuntimeEnv, lastKey, pWindowResInfo); } else { numOfRes = (int32_t)getNumOfResult(pRuntimeEnv); @@ -1606,10 +1627,10 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int16_t order SQuery *pQuery = pRuntimeEnv->pQuery; pRuntimeEnv->pCtx = (SQLFunctionCtx *)calloc(pQuery->numOfOutput, sizeof(SQLFunctionCtx)); + pRuntimeEnv->offset = calloc(pQuery->numOfOutput, sizeof(int16_t)); pRuntimeEnv->rowCellInfoOffset = calloc(pQuery->numOfOutput, sizeof(int32_t)); - pRuntimeEnv->pResultRow = getNewResultRow(pRuntimeEnv->pool); - if (pRuntimeEnv->pResultRow == NULL || pRuntimeEnv->pCtx == NULL || pRuntimeEnv->rowCellInfoOffset == NULL) { + if (pRuntimeEnv->offset == NULL || pRuntimeEnv->pCtx == NULL || pRuntimeEnv->rowCellInfoOffset == NULL) { goto _clean; } @@ -1649,15 +1670,15 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int16_t order assert(isValidDataType(pCtx->inputType)); pCtx->ptsOutputBuf = NULL; - pCtx->outputBytes = pQuery->pExpr1[i].bytes; - pCtx->outputType = pQuery->pExpr1[i].type; + pCtx->outputBytes = pQuery->pExpr1[i].bytes; + pCtx->outputType = pQuery->pExpr1[i].type; - pCtx->order = pQuery->order.order; - pCtx->functionId = pSqlFuncMsg->functionId; - pCtx->stableQuery = pRuntimeEnv->stableQuery; + pCtx->order = pQuery->order.order; + pCtx->functionId = pSqlFuncMsg->functionId; + pCtx->stableQuery = pRuntimeEnv->stableQuery; pCtx->interBufBytes = pQuery->pExpr1[i].interBytes; - pCtx->numOfParams = pSqlFuncMsg->numOfParams; + pCtx->numOfParams = pSqlFuncMsg->numOfParams; for (int32_t j = 0; j < pCtx->numOfParams; ++j) { int16_t type = pSqlFuncMsg->arg[j].argType; int16_t bytes = pSqlFuncMsg->arg[j].argBytes; @@ -1705,6 +1726,8 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int16_t order _clean: tfree(pRuntimeEnv->pCtx); + tfree(pRuntimeEnv->offset); + tfree(pRuntimeEnv->rowCellInfoOffset); return TSDB_CODE_QRY_OUT_OF_MEMORY; } @@ -1754,6 +1777,8 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { doFreeQueryHandle(pQInfo); pRuntimeEnv->pTSBuf = tsBufDestroy(pRuntimeEnv->pTSBuf); + + tfree(pRuntimeEnv->offset); tfree(pRuntimeEnv->keyBuf); tfree(pRuntimeEnv->rowCellInfoOffset); @@ -2394,7 +2419,7 @@ static void ensureOutputBufferSimple(SQueryRuntimeEnv* pRuntimeEnv, int32_t capa assert(bytes > 0 && capacity > 0); char *tmp = realloc(pQuery->sdata[i], bytes * capacity + sizeof(tFilePage)); - if (tmp == NULL) { // todo handle the oom + if (tmp == NULL) { longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); } else { pQuery->sdata[i] = (tFilePage *)tmp; @@ -2425,7 +2450,7 @@ static void ensureOutputBuffer(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pB assert(bytes > 0 && newSize > 0); char *tmp = realloc(pQuery->sdata[i], bytes * newSize + sizeof(tFilePage)); - if (tmp == NULL) { // todo handle the oom + if (tmp == NULL) { longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); } else { memset(tmp + sizeof(tFilePage) + bytes * pRec->rows, 0, (size_t)((newSize - pRec->rows) * bytes)); @@ -3316,7 +3341,10 @@ int32_t initResultRow(SResultRow *pResultRow) { void resetCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv) { SQuery *pQuery = pRuntimeEnv->pQuery; - SResultRow* pRow = pRuntimeEnv->pResultRow; + + int32_t groupIndex = 0; + int32_t uid = 0; + SResultRow* pRow = doPrepareResultRowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, (char *)&groupIndex, sizeof(groupIndex), true, uid); for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; @@ -3811,7 +3839,7 @@ void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult) { } } -void setWindowResOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult) { +void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult) { SQuery *pQuery = pRuntimeEnv->pQuery; // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group @@ -4598,12 +4626,6 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo tsBufSetTraverseOrder(pRuntimeEnv->pTSBuf, order); } - // create runtime environment - code = setupQueryRuntimeEnv(pRuntimeEnv, pQuery->order.order); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - int32_t ps = DEFAULT_PAGE_SIZE; int32_t rowsize = 0; getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize); @@ -4635,7 +4657,7 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo return code; } } - } else if (pRuntimeEnv->groupbyNormalCol || QUERY_IS_INTERVAL_QUERY(pQuery)) { + } else if (pRuntimeEnv->groupbyNormalCol || QUERY_IS_INTERVAL_QUERY(pQuery) || (!isSTableQuery)) { int32_t numOfResultRows = getInitialPageNum(pQInfo); getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize); code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rowsize, ps, TWOMB, pQInfo); @@ -4656,6 +4678,12 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo } } + // create runtime environment + code = setupQueryRuntimeEnv(pRuntimeEnv, pQuery->order.order); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + if (pQuery->fillType != TSDB_FILL_NONE && !isPointInterpoQuery(pQuery)) { SFillColInfo* pColInfo = createFillColInfo(pQuery); STimeWindow w = TSWINDOW_INITIALIZER; @@ -5336,8 +5364,11 @@ static char *getArithemicInputSrc(void *param, const char *name, int32_t colId) } static void doSecondaryArithmeticProcess(SQuery* pQuery) { - SArithmeticSupport arithSup = {0}; + if (pQuery->numOfExpr2 == 0) { + return; + } + SArithmeticSupport arithSup = {0}; tFilePage **data = calloc(pQuery->numOfExpr2, POINTER_BYTES); for (int32_t i = 0; i < pQuery->numOfExpr2; ++i) { int32_t bytes = pQuery->pExpr2[i].bytes; @@ -5494,7 +5525,7 @@ static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) int32_t numOfClosed = numOfClosedTimeWindow(&pRuntimeEnv->windowResInfo); int32_t c = (int32_t)(MIN(numOfClosed, pQuery->limit.offset)); - clearFirstNTimeWindow(pRuntimeEnv, c); + clearFirstNWindowRes(pRuntimeEnv, c); pQuery->limit.offset -= c; } @@ -5515,10 +5546,12 @@ static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { TSKEY newStartKey = TSKEY_INITIAL_VAL; // skip blocks without load the actual data block from file if no filter condition present - skipTimeInterval(pRuntimeEnv, &newStartKey); - if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0 && pRuntimeEnv->pFillInfo == NULL) { - setQueryStatus(pQuery, QUERY_COMPLETED); - return; + if (!pRuntimeEnv->groupbyNormalCol) { + skipTimeInterval(pRuntimeEnv, &newStartKey); + if (pQuery->limit.offset > 0 && pQuery->numOfFilterCols == 0 && pRuntimeEnv->pFillInfo == NULL) { + setQueryStatus(pQuery, QUERY_COMPLETED); + return; + } } while (1) { @@ -5529,11 +5562,11 @@ static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { pQuery->rec.rows = 0; copyFromWindowResToSData(pQInfo, &pRuntimeEnv->windowResInfo); - clearFirstNTimeWindow(pRuntimeEnv, pQInfo->groupIndex); + clearFirstNWindowRes(pRuntimeEnv, pQInfo->groupIndex); } // no result generated, abort - if (pQuery->rec.rows == 0) { + if (pQuery->rec.rows == 0 || pRuntimeEnv->groupbyNormalCol) { break; } @@ -5561,10 +5594,21 @@ static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { // all data scanned, the group by normal column can return if (pRuntimeEnv->groupbyNormalCol) { // todo refactor with merge interval time result - pQInfo->groupIndex = 0; - pQuery->rec.rows = 0; - copyFromWindowResToSData(pQInfo, &pRuntimeEnv->windowResInfo); - clearFirstNTimeWindow(pRuntimeEnv, pQInfo->groupIndex); + // maxOutput <= 0, means current query does not generate any results + int32_t numOfClosed = numOfClosedTimeWindow(&pRuntimeEnv->windowResInfo); + + if ((pQuery->limit.offset > 0 && pQuery->limit.offset < numOfClosed) || pQuery->limit.offset == 0) { + // skip offset result rows + clearFirstNWindowRes(pRuntimeEnv, (int32_t) pQuery->limit.offset); + + pQuery->rec.rows = 0; + pQInfo->groupIndex = 0; + copyFromWindowResToSData(pQInfo, &pRuntimeEnv->windowResInfo); + clearFirstNWindowRes(pRuntimeEnv, pQInfo->groupIndex); + + doSecondaryArithmeticProcess(pQuery); + limitResults(pRuntimeEnv); + } } } @@ -5594,7 +5638,7 @@ static void tableQueryImpl(SQInfo *pQInfo) { if (pRuntimeEnv->windowResInfo.size > 0) { copyFromWindowResToSData(pQInfo, &pRuntimeEnv->windowResInfo); - clearFirstNTimeWindow(pRuntimeEnv, pQInfo->groupIndex); + clearFirstNWindowRes(pRuntimeEnv, pQInfo->groupIndex); if (pQuery->rec.rows > 0) { qDebug("QInfo:%p %"PRId64" rows returned from group results, total:%"PRId64"", pQInfo, pQuery->rec.rows, pQuery->rec.total); diff --git a/src/query/src/qFill.c b/src/query/src/qFill.c index 1764289219..ca1203cb17 100644 --- a/src/query/src/qFill.c +++ b/src/query/src/qFill.c @@ -332,7 +332,7 @@ static void doFillOneRowResult(SFillInfo* pFillInfo, tFilePage** data, char** sr point1 = (SPoint){.key = *(TSKEY*)(prev), .val = prev + pCol->col.offset}; point2 = (SPoint){.key = ts, .val = srcData[i] + pFillInfo->index * bytes}; - point = (SPoint){.key = pFillInfo->start, .val = val1}; + point = (SPoint){.key = pFillInfo->currentKey, .val = val1}; taosGetLinearInterpolationVal(type, &point1, &point2, &point); } } else { diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index 4481ff5e8f..0853565fc6 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -225,7 +225,8 @@ tSQLExpr *tSQLExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) { tSQLExprDestroy(pLeft); tSQLExprDestroy(pRight); - } else if ((pLeft->nSQLOptr == TK_FLOAT && pRight->nSQLOptr == TK_INTEGER) || (pLeft->nSQLOptr == TK_INTEGER && pRight->nSQLOptr == TK_FLOAT)) { + } else if ((pLeft->nSQLOptr == TK_FLOAT && pRight->nSQLOptr == TK_INTEGER) || (pLeft->nSQLOptr == TK_INTEGER && pRight->nSQLOptr == TK_FLOAT) || + (pLeft->nSQLOptr == TK_FLOAT && pRight->nSQLOptr == TK_FLOAT)) { pExpr->val.nType = TSDB_DATA_TYPE_DOUBLE; pExpr->nSQLOptr = TK_FLOAT; diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index e9ed8dc1c3..9848fcc4d5 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -165,7 +165,7 @@ static char* doFlushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { static char* flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { int32_t ret = TSDB_CODE_SUCCESS; - assert(pResultBuf->numOfPages * pResultBuf->pageSize == pResultBuf->totalBufSize && pResultBuf->numOfPages >= pResultBuf->inMemPages); + assert(((int64_t) pResultBuf->numOfPages * pResultBuf->pageSize) == pResultBuf->totalBufSize && pResultBuf->numOfPages >= pResultBuf->inMemPages); if (pResultBuf->file == NULL) { if ((ret = createDiskFile(pResultBuf)) != TSDB_CODE_SUCCESS) { diff --git a/src/query/src/qUtil.c b/src/query/src/qUtil.c index f4f89a8709..c5317226c7 100644 --- a/src/query/src/qUtil.c +++ b/src/query/src/qUtil.c @@ -53,7 +53,7 @@ void cleanupTimeWindowInfo(SWindowResInfo *pWindowResInfo) { return; } if (pWindowResInfo->capacity == 0) { - assert(/*pWindowResInfo->hashList == NULL && */pWindowResInfo->pResult == NULL); + assert(pWindowResInfo->pResult == NULL); return; } @@ -64,10 +64,18 @@ void resetTimeWindowInfo(SQueryRuntimeEnv *pRuntimeEnv, SWindowResInfo *pWindowR if (pWindowResInfo == NULL || pWindowResInfo->capacity == 0) { return; } - + +// assert(pWindowResInfo->size == 1); + for (int32_t i = 0; i < pWindowResInfo->size; ++i) { SResultRow *pWindowRes = pWindowResInfo->pResult[i]; clearResultRow(pRuntimeEnv, pWindowRes); + + int32_t groupIndex = 0; + int64_t uid = 0; + + SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, &groupIndex, sizeof(groupIndex), uid); + taosHashRemove(pRuntimeEnv->pResultRowHashTable, (const char *)pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(sizeof(groupIndex))); } pWindowResInfo->curIndex = -1; @@ -77,7 +85,7 @@ void resetTimeWindowInfo(SQueryRuntimeEnv *pRuntimeEnv, SWindowResInfo *pWindowR pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL; } -void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) { +void clearFirstNWindowRes(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) { SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo; if (pWindowResInfo == NULL || pWindowResInfo->capacity == 0 || pWindowResInfo->size == 0 || num == 0) { return; @@ -88,6 +96,11 @@ void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) { int16_t type = pWindowResInfo->type; STableId* id = TSDB_TABLEID(pRuntimeEnv->pQuery->current->pTable); // uid is always set to be 0. + int64_t uid = id->uid; + if (pRuntimeEnv->groupbyNormalCol) { + uid = 0; + } + char *key = NULL; int16_t bytes = -1; @@ -97,14 +110,14 @@ void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) { // todo refactor if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - key = varDataVal(pResult->key); + key = varDataVal(pResult->key); bytes = varDataLen(pResult->key); } else { key = (char*) &pResult->win.skey; bytes = tDataTypeDesc[pWindowResInfo->type].nSize; } - SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, key, bytes, id->uid); + SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, key, bytes, uid); taosHashRemove(pRuntimeEnv->pResultRowHashTable, (const char *)pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes)); } else { break; @@ -137,14 +150,14 @@ void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) { bytes = tDataTypeDesc[pWindowResInfo->type].nSize; } - SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, key, bytes, id->uid); + SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, key, bytes, uid); int32_t *p = (int32_t *)taosHashGet(pRuntimeEnv->pResultRowHashTable, (const char *)pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes)); assert(p != NULL); int32_t v = (*p - num); assert(v >= 0 && v <= pWindowResInfo->size); - SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, key, bytes, id->uid); + SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, key, bytes, uid); taosHashPut(pRuntimeEnv->pResultRowHashTable, pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), (char *)&v, sizeof(int32_t)); } @@ -158,7 +171,7 @@ void clearClosedTimeWindow(SQueryRuntimeEnv *pRuntimeEnv) { } int32_t numOfClosed = numOfClosedTimeWindow(pWindowResInfo); - clearFirstNTimeWindow(pRuntimeEnv, numOfClosed); + clearFirstNWindowRes(pRuntimeEnv, numOfClosed); } int32_t numOfClosedTimeWindow(SWindowResInfo *pWindowResInfo) { diff --git a/src/sync/inc/syncInt.h b/src/sync/inc/syncInt.h index 7156a2d08a..7d846ebc80 100644 --- a/src/sync/inc/syncInt.h +++ b/src/sync/inc/syncInt.h @@ -27,16 +27,20 @@ extern "C" { #define sDebug(...) { if (sDebugFlag & DEBUG_DEBUG) { taosPrintLog("SYN ", sDebugFlag, __VA_ARGS__); }} #define sTrace(...) { if (sDebugFlag & DEBUG_TRACE) { taosPrintLog("SYN ", sDebugFlag, __VA_ARGS__); }} -#define TAOS_SMSG_SYNC_DATA 1 -#define TAOS_SMSG_FORWARD 2 -#define TAOS_SMSG_FORWARD_RSP 3 -#define TAOS_SMSG_SYNC_REQ 4 -#define TAOS_SMSG_SYNC_RSP 5 -#define TAOS_SMSG_SYNC_MUST 6 -#define TAOS_SMSG_STATUS 7 +typedef enum { + TAOS_SMSG_SYNC_DATA = 1, + TAOS_SMSG_FORWARD = 2, + TAOS_SMSG_FORWARD_RSP = 3, + TAOS_SMSG_SYNC_REQ = 4, + TAOS_SMSG_SYNC_RSP = 5, + TAOS_SMSG_SYNC_MUST = 6, + TAOS_SMSG_STATUS = 7 +} ESyncMsgType; #define SYNC_MAX_SIZE (TSDB_MAX_WAL_SIZE + sizeof(SWalHead) + sizeof(SSyncHead) + 16) #define SYNC_RECV_BUFFER_SIZE (5*1024*1024) +#define SYNC_FWD_TIMER 300 +#define SYNC_ROLE_TIMER 10000 #define nodeRole pNode->peerInfo[pNode->selfIndex]->role #define nodeVersion pNode->peerInfo[pNode->selfIndex]->version @@ -68,6 +72,9 @@ typedef struct { typedef struct { int8_t role; int8_t ack; + int8_t type; + int8_t reserved[3]; + uint16_t tranId; uint64_t version; SPeerStatus peersStatus[]; } SPeersStatus; @@ -106,7 +113,7 @@ typedef struct { int8_t nacks; int8_t confirmed; int32_t code; - uint64_t time; + int64_t time; } SFwdInfo; typedef struct { @@ -120,12 +127,12 @@ typedef struct SsyncPeer { int32_t nodeId; uint32_t ip; uint16_t port; + int8_t role; + int8_t sstatus; // sync status char fqdn[TSDB_FQDN_LEN]; // peer ip string char id[TSDB_EP_LEN + 32]; // peer vgId + end point - int8_t role; - int8_t sstatus; // sync status uint64_t version; - uint64_t sversion; // track the peer version in retrieve process + uint64_t sversion; // track the peer version in retrieve process int32_t syncFd; int32_t peerFd; // forward FD int32_t numOfRetrieves; // number of retrieves tried @@ -135,7 +142,7 @@ typedef struct SsyncPeer { int32_t notifyFd; int32_t watchNum; int32_t *watchFd; - int8_t refCount; // reference count + int32_t refCount; // reference count struct SSyncNode *pSyncNode; } SSyncPeer; @@ -143,16 +150,16 @@ typedef struct SSyncNode { char path[TSDB_FILENAME_LEN]; int8_t replica; int8_t quorum; + int8_t selfIndex; uint32_t vgId; int64_t rid; void *ahandle; - int8_t selfIndex; SSyncPeer *peerInfo[TAOS_SYNC_MAX_REPLICA+1]; // extra one for arbitrator SSyncPeer *pMaster; - int8_t refCount; SRecvBuffer *pRecv; SSyncFwds *pSyncFwds; // saved forward info if quorum >1 void *pFwdTimer; + void *pRoleTimer; FGetFileInfo getFileInfo; FGetWalInfo getWalInfo; FWriteToCache writeToCache; diff --git a/src/sync/src/syncMain.c b/src/sync/src/syncMain.c index 6ff04aad64..843de9461f 100644 --- a/src/sync/src/syncMain.c +++ b/src/sync/src/syncMain.c @@ -13,8 +13,7 @@ * along with this program. If not, see . */ -//#include -//#include +#define _DEFAULT_SOURCE #include "os.h" #include "hash.h" #include "tlog.h" @@ -50,7 +49,7 @@ static int32_t tsSyncRefId = -1; static void syncProcessSyncRequest(char *pMsg, SSyncPeer *pPeer); static void syncRecoverFromMaster(SSyncPeer *pPeer); static void syncCheckPeerConnection(void *param, void *tmrId); -static void syncSendPeersStatusMsgToPeer(SSyncPeer *pPeer, char ack); +static void syncSendPeersStatusMsgToPeer(SSyncPeer *pPeer, char ack, int8_t type, uint16_t tranId); static void syncProcessBrokenLink(void *param); static int32_t syncProcessPeerMsg(void *param, void *buffer); static void syncProcessIncommingConnection(int32_t connFd, uint32_t sourceIp); @@ -59,6 +58,7 @@ static void syncAddArbitrator(SSyncNode *pNode); static void syncFreeNode(void *); static void syncRemoveConfirmedFwdInfo(SSyncNode *pNode); static void syncMonitorFwdInfos(void *param, void *tmrId); +static void syncMonitorNodeRole(void *param, void *tmrId); static void syncProcessFwdAck(SSyncNode *pNode, SFwdInfo *pFwdInfo, int32_t code); static void syncSaveFwdInfo(SSyncNode *pNode, uint64_t version, void *mhandle); static void syncRestartPeer(SSyncPeer *pPeer); @@ -73,6 +73,32 @@ char* syncRole[] = { "master" }; +typedef enum { + SYNC_STATUS_BROADCAST, + SYNC_STATUS_BROADCAST_RSP, + SYNC_STATUS_SETUP_CONN, + SYNC_STATUS_SETUP_CONN_RSP, + SYNC_STATUS_EXCHANGE_DATA, + SYNC_STATUS_EXCHANGE_DATA_RSP, + SYNC_STATUS_CHECK_ROLE, + SYNC_STATUS_CHECK_ROLE_RSP +} ESyncStatusType; + +char *statusType[] = { + "broadcast", + "broadcast-rsp", + "setup-conn", + "setup-conn-rsp", + "exchange-data", + "exchange-data-rsp", + "check-role", + "check-role-rsp" +}; + +uint16_t syncGenTranId() { + return taosRand() & 0XFFFF; +} + int32_t syncInit() { SPoolInfo info; @@ -145,7 +171,7 @@ void syncCleanUp() { int64_t syncStart(const SSyncInfo *pInfo) { const SSyncCfg *pCfg = &pInfo->syncCfg; - SSyncNode *pNode = (SSyncNode *)calloc(sizeof(SSyncNode), 1); + SSyncNode *pNode = calloc(sizeof(SSyncNode), 1); if (pNode == NULL) { sError("no memory to allocate syncNode"); terrno = TAOS_SYSTEM_ERROR(errno); @@ -180,8 +206,8 @@ int64_t syncStart(const SSyncInfo *pInfo) { const SNodeInfo *pNodeInfo = pCfg->nodeInfo + i; pNode->peerInfo[i] = syncAddPeer(pNode, pNodeInfo); if (pNode->peerInfo[i] == NULL) { - sError("vgId:%d, node:%d fqdn:%s port:%u is not configured, stop taosd", pNode->vgId, pNodeInfo->nodeId, pNodeInfo->nodeFqdn, - pNodeInfo->nodePort); + sError("vgId:%d, node:%d fqdn:%s port:%u is not configured, stop taosd", pNode->vgId, pNodeInfo->nodeId, + pNodeInfo->nodeFqdn, pNodeInfo->nodePort); syncStop(pNode->rid); exit(1); } @@ -211,9 +237,16 @@ int64_t syncStart(const SSyncInfo *pInfo) { return -1; } - pNode->pFwdTimer = taosTmrStart(syncMonitorFwdInfos, 300, (void *)pNode->rid, tsSyncTmrCtrl); + pNode->pFwdTimer = taosTmrStart(syncMonitorFwdInfos, SYNC_FWD_TIMER, (void *)pNode->rid, tsSyncTmrCtrl); if (pNode->pFwdTimer == NULL) { - sError("vgId:%d, failed to allocate timer", pNode->vgId); + sError("vgId:%d, failed to allocate fwd timer", pNode->vgId); + syncStop(pNode->rid); + return -1; + } + + pNode->pRoleTimer = taosTmrStart(syncMonitorNodeRole, SYNC_ROLE_TIMER, (void *)pNode->rid, tsSyncTmrCtrl); + if (pNode->pRoleTimer == NULL) { + sError("vgId:%d, failed to allocate role timer", pNode->vgId); syncStop(pNode->rid); return -1; } @@ -240,6 +273,7 @@ void syncStop(int64_t rid) { if (tsVgIdHash) taosHashRemove(tsVgIdHash, (const char *)&pNode->vgId, sizeof(int32_t)); if (pNode->pFwdTimer) taosTmrStop(pNode->pFwdTimer); + if (pNode->pRoleTimer) taosTmrStop(pNode->pRoleTimer); for (int32_t i = 0; i < pNode->replica; ++i) { pPeer = pNode->peerInfo[i]; @@ -319,12 +353,10 @@ int32_t syncReconfig(int64_t rid, const SSyncCfg *pNewCfg) { pthread_mutex_unlock(&(pNode->mutex)); - sInfo("vgId:%d, %d replicas are configured, quorum:%d role:%s", pNode->vgId, pNode->replica, pNode->quorum, - syncRole[nodeRole]); + sInfo("vgId:%d, %d replicas are configured, quorum:%d", pNode->vgId, pNode->replica, pNode->quorum); syncBroadcastStatus(pNode); taosReleaseRef(tsSyncRefId, rid); - return 0; } @@ -356,10 +388,10 @@ void syncConfirmForward(int64_t rid, uint64_t version, int32_t code) { pFwdRsp->code = code; int32_t msgLen = sizeof(SSyncHead) + sizeof(SFwdRsp); - int32_t retLen = write(pPeer->peerFd, msg, msgLen); + int32_t retLen = taosWriteMsg(pPeer->peerFd, msg, msgLen); if (retLen == msgLen) { - sDebug("%s, forward-rsp is sent, code:%x hver:%" PRIu64, pPeer->id, code, version); + sTrace("%s, forward-rsp is sent, code:%x hver:%" PRIu64, pPeer->id, code, version); } else { sDebug("%s, failed to send forward ack, restart", pPeer->id); syncRestartConnection(pPeer); @@ -369,6 +401,7 @@ void syncConfirmForward(int64_t rid, uint64_t version, int32_t code) { taosReleaseRef(tsSyncRefId, rid); } +#if 0 void syncRecover(int64_t rid) { SSyncPeer *pPeer; @@ -385,7 +418,7 @@ void syncRecover(int64_t rid) { pthread_mutex_lock(&(pNode->mutex)); for (int32_t i = 0; i < pNode->replica; ++i) { - pPeer = (SSyncPeer *)pNode->peerInfo[i]; + pPeer = pNode->peerInfo[i]; if (pPeer->peerFd >= 0) { syncRestartConnection(pPeer); } @@ -395,6 +428,7 @@ void syncRecover(int64_t rid) { taosReleaseRef(tsSyncRefId, rid); } +#endif int32_t syncGetNodesRole(int64_t rid, SNodesRole *pNodesRole) { SSyncNode *pNode = taosAcquireRef(tsSyncRefId, rid); @@ -449,10 +483,10 @@ static void syncFreeNode(void *param) { tfree(pNode); } -void syncAddPeerRef(SSyncPeer *pPeer) { atomic_add_fetch_8(&pPeer->refCount, 1); } +void syncAddPeerRef(SSyncPeer *pPeer) { atomic_add_fetch_32(&pPeer->refCount, 1); } int32_t syncDecPeerRef(SSyncPeer *pPeer) { - if (atomic_sub_fetch_8(&pPeer->refCount, 1) == 0) { + if (atomic_sub_fetch_32(&pPeer->refCount, 1) == 0) { taosReleaseRef(tsSyncRefId, pPeer->pSyncNode->rid); sDebug("%s, resource is freed", pPeer->id); @@ -510,7 +544,7 @@ static SSyncPeer *syncAddPeer(SSyncNode *pNode, const SNodeInfo *pInfo) { if (pPeer->nodeId == 0 || (ret > 0) || (ret == 0 && pPeer->port > tsSyncPort)) { int32_t checkMs = 100 + (pNode->vgId * 10) % 100; if (pNode->vgId > 1) checkMs = tsStatusInterval * 1000 + checkMs; - sDebug("%s, start to check peer connection after %d ms", pPeer->id, checkMs); + sDebug("%s, check peer connection after %d ms", pPeer->id, checkMs); taosTmrReset(syncCheckPeerConnection, checkMs, pPeer, tsSyncTmrCtrl, &pPeer->timer); } @@ -524,7 +558,7 @@ void syncBroadcastStatus(SSyncNode *pNode) { for (int32_t i = 0; i < pNode->replica; ++i) { if (i == pNode->selfIndex) continue; pPeer = pNode->peerInfo[i]; - syncSendPeersStatusMsgToPeer(pPeer, 1); + syncSendPeersStatusMsgToPeer(pPeer, 1, SYNC_STATUS_BROADCAST, syncGenTranId()); } } @@ -544,8 +578,6 @@ static void syncChooseMaster(SSyncNode *pNode) { int32_t index = -1; int32_t replica = pNode->replica; - sDebug("vgId:%d, choose master", pNode->vgId); - for (int32_t i = 0; i < pNode->replica; ++i) { if (pNode->peerInfo[i]->role != TAOS_SYNC_ROLE_OFFLINE) { onlineNum++; @@ -611,11 +643,11 @@ static void syncChooseMaster(SSyncNode *pNode) { static SSyncPeer *syncCheckMaster(SSyncNode *pNode) { int32_t onlineNum = 0; - int32_t index = -1; + int32_t masterIndex = -1; int32_t replica = pNode->replica; - for (int32_t i = 0; i < pNode->replica; ++i) { - if (pNode->peerInfo[i]->role != TAOS_SYNC_ROLE_OFFLINE) { + for (int32_t index = 0; index < pNode->replica; ++index) { + if (pNode->peerInfo[index]->role != TAOS_SYNC_ROLE_OFFLINE) { onlineNum++; } } @@ -630,18 +662,17 @@ static SSyncPeer *syncCheckMaster(SSyncNode *pNode) { if (onlineNum <= replica * 0.5) { if (nodeRole != TAOS_SYNC_ROLE_UNSYNCED) { nodeRole = TAOS_SYNC_ROLE_UNSYNCED; - // pNode->peerInfo[pNode->selfIndex]->role = nodeRole; (*pNode->notifyRole)(pNode->ahandle, nodeRole); - sInfo("vgId:%d, change to unsynced state, online:%d replica:%d", pNode->vgId, onlineNum, replica); + sInfo("vgId:%d, self change to unsynced state, online:%d replica:%d", pNode->vgId, onlineNum, replica); } } else { - for (int32_t i = 0; i < pNode->replica; ++i) { - SSyncPeer *pTemp = pNode->peerInfo[i]; + for (int32_t index = 0; index < pNode->replica; ++index) { + SSyncPeer *pTemp = pNode->peerInfo[index]; if (pTemp->role != TAOS_SYNC_ROLE_MASTER) continue; - if (index < 0) { - index = i; + if (masterIndex < 0) { + masterIndex = index; } else { // multiple masters, it shall not happen - if (i == pNode->selfIndex) { + if (masterIndex == pNode->selfIndex) { sError("%s, peer is master, work as slave instead", pTemp->id); nodeRole = TAOS_SYNC_ROLE_SLAVE; (*pNode->notifyRole)(pNode->ahandle, nodeRole); @@ -650,77 +681,80 @@ static SSyncPeer *syncCheckMaster(SSyncNode *pNode) { } } - SSyncPeer *pMaster = (index >= 0) ? pNode->peerInfo[index] : NULL; + SSyncPeer *pMaster = (masterIndex >= 0) ? pNode->peerInfo[masterIndex] : NULL; return pMaster; } static int32_t syncValidateMaster(SSyncPeer *pPeer) { SSyncNode *pNode = pPeer->pSyncNode; - int32_t code = 0; + int32_t code = 0; if (nodeRole == TAOS_SYNC_ROLE_MASTER && nodeVersion < pPeer->version) { - sDebug("%s, slave has higher version, restart all connections!!!", pPeer->id); + sDebug("%s, peer has higher sver:%" PRIu64 ", restart all peer connections", pPeer->id, pPeer->version); nodeRole = TAOS_SYNC_ROLE_UNSYNCED; (*pNode->notifyRole)(pNode->ahandle, nodeRole); code = -1; - for (int32_t i = 0; i < pNode->replica; ++i) { - if (i == pNode->selfIndex) continue; - syncRestartPeer(pNode->peerInfo[i]); + for (int32_t index = 0; index < pNode->replica; ++index) { + if (index == pNode->selfIndex) continue; + syncRestartPeer(pNode->peerInfo[index]); } } return code; } -static void syncCheckRole(SSyncPeer *pPeer, SPeerStatus peersStatus[], int8_t newRole) { +static void syncCheckRole(SSyncPeer *pPeer, SPeerStatus* peersStatus, int8_t newPeerRole) { SSyncNode *pNode = pPeer->pSyncNode; - int8_t peerOldRole = pPeer->role; - int8_t selfOldRole = nodeRole; - int8_t i, syncRequired = 0; + int8_t oldPeerRole = pPeer->role; + int8_t oldSelfRole = nodeRole; + int8_t syncRequired = 0; - // pNode->peerInfo[pNode->selfIndex]->version = nodeVersion; - pPeer->role = newRole; - - sDebug("%s, own role:%s, new peer role:%s", pPeer->id, syncRole[nodeRole], syncRole[pPeer->role]); + pPeer->role = newPeerRole; + sDebug("%s, peer role:%s change to %s", pPeer->id, syncRole[oldPeerRole], syncRole[newPeerRole]); SSyncPeer *pMaster = syncCheckMaster(pNode); if (pMaster) { // master is there pNode->pMaster = pMaster; - sDebug("%s, it is the master, ver:%" PRIu64, pMaster->id, pMaster->version); + sDebug("%s, it is the master, sver:%" PRIu64, pMaster->id, pMaster->version); if (syncValidateMaster(pPeer) < 0) return; if (nodeRole == TAOS_SYNC_ROLE_UNSYNCED) { if (nodeVersion < pMaster->version) { + sDebug("%s, is master, sync required, self sver:%" PRIu64, pMaster->id, nodeVersion); syncRequired = 1; } else { - sInfo("%s is master, work as slave, ver:%" PRIu64, pMaster->id, pMaster->version); + sInfo("%s, is master, work as slave, self sver:%" PRIu64, pMaster->id, nodeVersion); nodeRole = TAOS_SYNC_ROLE_SLAVE; (*pNode->notifyRole)(pNode->ahandle, nodeRole); } } else if (nodeRole == TAOS_SYNC_ROLE_SLAVE && pMaster == pPeer) { - // nodeVersion = pMaster->version; + sDebug("%s, is master, continue work as slave, self sver:%" PRIu64, pMaster->id, nodeVersion); } } else { // master not there, if all peer's state and version are consistent, choose the master int32_t consistent = 0; - if (peersStatus) { - for (i = 0; i < pNode->replica; ++i) { - SSyncPeer *pTemp = pNode->peerInfo[i]; - if (pTemp->role != peersStatus[i].role) break; - if ((pTemp->role != TAOS_SYNC_ROLE_OFFLINE) && (pTemp->version != peersStatus[i].version)) break; + int32_t index = 0; + if (peersStatus != NULL) { + for (index = 0; index < pNode->replica; ++index) { + SSyncPeer *pTemp = pNode->peerInfo[index]; + if (pTemp->role != peersStatus[index].role) break; + if ((pTemp->role != TAOS_SYNC_ROLE_OFFLINE) && (pTemp->version != peersStatus[index].version)) break; } - if (i >= pNode->replica) consistent = 1; + if (index >= pNode->replica) consistent = 1; } else { if (pNode->replica == 2) consistent = 1; } if (consistent) { + sDebug("vgId:%d, choose master", pNode->vgId); syncChooseMaster(pNode); + } else { + sDebug("vgId:%d, version inconsistent, cannot choose master", pNode->vgId); } } @@ -728,7 +762,8 @@ static void syncCheckRole(SSyncPeer *pPeer, SPeerStatus peersStatus[], int8_t ne syncRecoverFromMaster(pMaster); } - if (peerOldRole != newRole || nodeRole != selfOldRole) { + if (oldPeerRole != newPeerRole || nodeRole != oldSelfRole) { + sDebug("vgId:%d, roles changed, broadcast status", pNode->vgId); syncBroadcastStatus(pNode); } @@ -738,7 +773,7 @@ static void syncCheckRole(SSyncPeer *pPeer, SPeerStatus peersStatus[], int8_t ne } static void syncRestartPeer(SSyncPeer *pPeer) { - sDebug("%s, restart connection", pPeer->id); + sDebug("%s, restart peer connection", pPeer->id); syncClosePeerConn(pPeer); @@ -746,6 +781,7 @@ static void syncRestartPeer(SSyncPeer *pPeer) { int32_t ret = strcmp(pPeer->fqdn, tsNodeFqdn); if (ret > 0 || (ret == 0 && pPeer->port > tsSyncPort)) { + sDebug("%s, check peer connection in 1000 ms", pPeer->id); taosTmrReset(syncCheckPeerConnection, tsSyncTimer * 1000, pPeer, tsSyncTmrCtrl, &pPeer->timer); } } @@ -784,7 +820,7 @@ static void syncProcessSyncRequest(char *msg, SSyncPeer *pPeer) { pthread_attr_destroy(&thattr); if (ret != 0) { - sError("%s, failed to create sync thread(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to create sync thread since %s", pPeer->id, strerror(errno)); syncDecPeerRef(pPeer); } else { pPeer->sstatus = TAOS_SYNC_STATUS_START; @@ -840,7 +876,7 @@ static void syncRecoverFromMaster(SSyncPeer *pPeer) { firstPkt.port = tsSyncPort; taosTmrReset(syncNotStarted, tsSyncTimer * 1000, pPeer, tsSyncTmrCtrl, &pPeer->timer); - if (write(pPeer->peerFd, &firstPkt, sizeof(firstPkt)) != sizeof(firstPkt)) { + if (taosWriteMsg(pPeer->peerFd, &firstPkt, sizeof(firstPkt)) != sizeof(firstPkt)) { sError("%s, failed to send sync-req to peer", pPeer->id); } else { nodeSStatus = TAOS_SYNC_STATUS_START; @@ -854,7 +890,7 @@ static void syncProcessFwdResponse(char *cont, SSyncPeer *pPeer) { SSyncFwds *pSyncFwds = pNode->pSyncFwds; SFwdInfo * pFwdInfo; - sDebug("%s, forward-rsp is received, code:%x ver:%" PRIu64, pPeer->id, pFwdRsp->code, pFwdRsp->version); + sTrace("%s, forward-rsp is received, code:%x hver:%" PRIu64, pPeer->id, pFwdRsp->code, pFwdRsp->version); SFwdInfo *pFirst = pSyncFwds->fwdInfo + pSyncFwds->first; if (pFirst->version <= pFwdRsp->version && pSyncFwds->fwds > 0) { @@ -873,7 +909,7 @@ static void syncProcessForwardFromPeer(char *cont, SSyncPeer *pPeer) { SSyncNode *pNode = pPeer->pSyncNode; SWalHead * pHead = (SWalHead *)cont; - sDebug("%s, forward is received, hver:%" PRIu64 ", len:%d", pPeer->id, pHead->version, pHead->len); + sTrace("%s, forward is received, hver:%" PRIu64 ", len:%d", pPeer->id, pHead->version, pHead->len); if (nodeRole == TAOS_SYNC_ROLE_SLAVE) { // nodeVersion = pHead->version; @@ -891,14 +927,14 @@ static void syncProcessPeersStatusMsg(char *cont, SSyncPeer *pPeer) { SSyncNode * pNode = pPeer->pSyncNode; SPeersStatus *pPeersStatus = (SPeersStatus *)cont; - sDebug("%s, status msg is received, self:%s ver:%" PRIu64 " peer:%s ver:%" PRIu64 ", ack:%d", pPeer->id, - syncRole[nodeRole], nodeVersion, syncRole[pPeersStatus->role], pPeersStatus->version, pPeersStatus->ack); + sDebug("%s, status msg is received, self:%s sver:%" PRIu64 " peer:%s sver:%" PRIu64 ", ack:%d tranId:%u type:%s", pPeer->id, + syncRole[nodeRole], nodeVersion, syncRole[pPeersStatus->role], pPeersStatus->version, pPeersStatus->ack, pPeersStatus->tranId, statusType[pPeersStatus->type]); pPeer->version = pPeersStatus->version; syncCheckRole(pPeer, pPeersStatus->peersStatus, pPeersStatus->role); if (pPeersStatus->ack) { - syncSendPeersStatusMsgToPeer(pPeer, 0); + syncSendPeersStatusMsgToPeer(pPeer, 0, pPeersStatus->type + 1, pPeersStatus->tranId); } } @@ -956,7 +992,7 @@ static int32_t syncProcessPeerMsg(void *param, void *buffer) { #define statusMsgLen sizeof(SSyncHead) + sizeof(SPeersStatus) + sizeof(SPeerStatus) * TAOS_SYNC_MAX_REPLICA -static void syncSendPeersStatusMsgToPeer(SSyncPeer *pPeer, char ack) { +static void syncSendPeersStatusMsgToPeer(SSyncPeer *pPeer, char ack, int8_t type, uint16_t tranId) { SSyncNode *pNode = pPeer->pSyncNode; char msg[statusMsgLen] = {0}; @@ -971,22 +1007,22 @@ static void syncSendPeersStatusMsgToPeer(SSyncPeer *pPeer, char ack) { pPeersStatus->version = nodeVersion; pPeersStatus->role = nodeRole; pPeersStatus->ack = ack; + pPeersStatus->type = type; + pPeersStatus->tranId = tranId; for (int32_t i = 0; i < pNode->replica; ++i) { pPeersStatus->peersStatus[i].role = pNode->peerInfo[i]->role; pPeersStatus->peersStatus[i].version = pNode->peerInfo[i]->version; } - int32_t retLen = write(pPeer->peerFd, msg, statusMsgLen); + int32_t retLen = taosWriteMsg(pPeer->peerFd, msg, statusMsgLen); if (retLen == statusMsgLen) { - sDebug("%s, status msg is sent, self:%s ver:%" PRIu64 ", ack:%d", pPeer->id, syncRole[pPeersStatus->role], - pPeersStatus->version, pPeersStatus->ack); + sDebug("%s, status msg is sent, self:%s sver:%" PRIu64 ", ack:%d tranId:%u type:%s", pPeer->id, syncRole[pPeersStatus->role], + pPeersStatus->version, pPeersStatus->ack, pPeersStatus->tranId, statusType[pPeersStatus->type]); } else { sDebug("%s, failed to send status msg, restart", pPeer->id); syncRestartConnection(pPeer); } - - return; } static void syncSetupPeerConnection(SSyncPeer *pPeer) { @@ -995,13 +1031,13 @@ static void syncSetupPeerConnection(SSyncPeer *pPeer) { taosTmrStopA(&pPeer->timer); if (pPeer->peerFd >= 0) { sDebug("%s, send role version to peer", pPeer->id); - syncSendPeersStatusMsgToPeer(pPeer, 1); + syncSendPeersStatusMsgToPeer(pPeer, 1, SYNC_STATUS_SETUP_CONN, syncGenTranId()); return; } int32_t connFd = taosOpenTcpClientSocket(pPeer->ip, pPeer->port, 0); if (connFd < 0) { - sDebug("%s, failed to open tcp socket(%s)", pPeer->id, strerror(errno)); + sDebug("%s, failed to open tcp socket since %s", pPeer->id, strerror(errno)); taosTmrReset(syncCheckPeerConnection, tsSyncTimer * 1000, pPeer, tsSyncTmrCtrl, &pPeer->timer); return; } @@ -1014,15 +1050,15 @@ static void syncSetupPeerConnection(SSyncPeer *pPeer) { firstPkt.port = tsSyncPort; firstPkt.sourceId = pNode->vgId; // tell arbitrator its vgId - if (write(connFd, &firstPkt, sizeof(firstPkt)) == sizeof(firstPkt)) { + if (taosWriteMsg(connFd, &firstPkt, sizeof(firstPkt)) == sizeof(firstPkt)) { sDebug("%s, connection to peer server is setup", pPeer->id); pPeer->peerFd = connFd; pPeer->role = TAOS_SYNC_ROLE_UNSYNCED; pPeer->pConn = taosAllocateTcpConn(tsTcpPool, pPeer, connFd); syncAddPeerRef(pPeer); } else { - sDebug("try later"); - close(connFd); + sDebug("%s, failed to setup peer connection to server since %s, try later", pPeer->id, strerror(errno)); + taosClose(connFd); taosTmrReset(syncCheckPeerConnection, tsSyncTimer * 1000, pPeer, tsSyncTmrCtrl, &pPeer->timer); } } @@ -1069,7 +1105,7 @@ static void syncProcessIncommingConnection(int32_t connFd, uint32_t sourceIp) { SFirstPkt firstPkt; if (taosReadMsg(connFd, &firstPkt, sizeof(firstPkt)) != sizeof(firstPkt)) { - sError("failed to read peer first pkt from ip:%s(%s)", ipstr, strerror(errno)); + sError("failed to read peer first pkt from ip:%s since %s", ipstr, strerror(errno)); taosCloseSocket(connFd); return; } @@ -1108,7 +1144,7 @@ static void syncProcessIncommingConnection(int32_t connFd, uint32_t sourceIp) { pPeer->pConn = taosAllocateTcpConn(tsTcpPool, pPeer, connFd); syncAddPeerRef(pPeer); sDebug("%s, ready to exchange data", pPeer->id); - syncSendPeersStatusMsgToPeer(pPeer, 1); + syncSendPeersStatusMsgToPeer(pPeer, 1, SYNC_STATUS_EXCHANGE_DATA, syncGenTranId()); } } @@ -1123,7 +1159,7 @@ static void syncProcessBrokenLink(void *param) { if (taosAcquireRef(tsSyncRefId, pNode->rid) == NULL) return; pthread_mutex_lock(&(pNode->mutex)); - sDebug("%s, TCP link is broken(%s)", pPeer->id, strerror(errno)); + sDebug("%s, TCP link is broken since %s", pPeer->id, strerror(errno)); pPeer->peerFd = -1; if (syncDecPeerRef(pPeer) != 0) { @@ -1154,7 +1190,7 @@ static void syncSaveFwdInfo(SSyncNode *pNode, uint64_t version, void *mhandle) { pFwdInfo->time = time; pSyncFwds->fwds++; - sDebug("vgId:%d, fwd info is saved, ver:%" PRIu64 " fwds:%d ", pNode->vgId, version, pSyncFwds->fwds); + sTrace("vgId:%d, fwd info is saved, hver:%" PRIu64 " fwds:%d ", pNode->vgId, version, pSyncFwds->fwds); } static void syncRemoveConfirmedFwdInfo(SSyncNode *pNode) { @@ -1168,7 +1204,7 @@ static void syncRemoveConfirmedFwdInfo(SSyncNode *pNode) { pSyncFwds->first = (pSyncFwds->first + 1) % tsMaxFwdInfo; pSyncFwds->fwds--; if (pSyncFwds->fwds == 0) pSyncFwds->first = pSyncFwds->last; - // sDebug("vgId:%d, fwd info is removed, ver:%d, fwds:%d", + // sDebug("vgId:%d, fwd info is removed, hver:%d, fwds:%d", // pNode->vgId, pFwdInfo->version, pSyncFwds->fwds); memset(pFwdInfo, 0, sizeof(SFwdInfo)); } @@ -1191,27 +1227,49 @@ static void syncProcessFwdAck(SSyncNode *pNode, SFwdInfo *pFwdInfo, int32_t code } if (confirm && pFwdInfo->confirmed == 0) { - sDebug("vgId:%d, forward is confirmed, ver:%" PRIu64 " code:%x", pNode->vgId, pFwdInfo->version, pFwdInfo->code); + sTrace("vgId:%d, forward is confirmed, hver:%" PRIu64 " code:%x", pNode->vgId, pFwdInfo->version, pFwdInfo->code); (*pNode->confirmForward)(pNode->ahandle, pFwdInfo->mhandle, pFwdInfo->code); pFwdInfo->confirmed = 1; } } +static void syncMonitorNodeRole(void *param, void *tmrId) { + int64_t rid = (int64_t)param; + SSyncNode *pNode = taosAcquireRef(tsSyncRefId, rid); + if (pNode == NULL) return; + + for (int32_t index = 0; index < pNode->replica; index++) { + if (index == pNode->selfIndex) continue; + + SSyncPeer *pPeer = pNode->peerInfo[index]; + if (pPeer->role > TAOS_SYNC_ROLE_UNSYNCED && nodeRole > TAOS_SYNC_ROLE_UNSYNCED) continue; + if (pPeer->sstatus > TAOS_SYNC_STATUS_INIT || nodeSStatus > TAOS_SYNC_STATUS_INIT) continue; + + syncSendPeersStatusMsgToPeer(pPeer, 1, SYNC_STATUS_CHECK_ROLE, syncGenTranId()); + } + + pNode->pRoleTimer = taosTmrStart(syncMonitorNodeRole, SYNC_ROLE_TIMER, (void *)pNode->rid, tsSyncTmrCtrl); + taosReleaseRef(tsSyncRefId, rid); +} + static void syncMonitorFwdInfos(void *param, void *tmrId) { - int64_t rid = (int64_t) param; + int64_t rid = (int64_t)param; SSyncNode *pNode = taosAcquireRef(tsSyncRefId, rid); if (pNode == NULL) return; SSyncFwds *pSyncFwds = pNode->pSyncFwds; - if (pSyncFwds) {; - uint64_t time = taosGetTimestampMs(); + if (pSyncFwds) { + int64_t time = taosGetTimestampMs(); if (pSyncFwds->fwds > 0) { pthread_mutex_lock(&(pNode->mutex)); for (int32_t i = 0; i < pSyncFwds->fwds; ++i) { SFwdInfo *pFwdInfo = pSyncFwds->fwdInfo + (pSyncFwds->first + i) % tsMaxFwdInfo; - if (time - pFwdInfo->time < 2000) break; + if (ABS(time - pFwdInfo->time) < 2000) break; + + sDebug("vgId:%d, forward info expired, hver:%" PRIu64 " curtime:%" PRIu64 " savetime:%" PRIu64, pNode->vgId, + pFwdInfo->version, time, pFwdInfo->time); syncProcessFwdAck(pNode, pFwdInfo, TSDB_CODE_RPC_NETWORK_UNAVAIL); } @@ -1219,7 +1277,7 @@ static void syncMonitorFwdInfos(void *param, void *tmrId) { pthread_mutex_unlock(&(pNode->mutex)); } - pNode->pFwdTimer = taosTmrStart(syncMonitorFwdInfos, 300, (void *)pNode->rid, tsSyncTmrCtrl); + pNode->pFwdTimer = taosTmrStart(syncMonitorFwdInfos, SYNC_FWD_TIMER, (void *)pNode->rid, tsSyncTmrCtrl); } taosReleaseRef(tsSyncRefId, rid); @@ -1234,7 +1292,7 @@ static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle if (pWalHead->version > nodeVersion + 1) { - sError("vgId:%d, hver:%" PRIu64 ", inconsistent with ver:%" PRIu64, pNode->vgId, pWalHead->version, nodeVersion); + sError("vgId:%d, hver:%" PRIu64 ", inconsistent with sver:%" PRIu64, pNode->vgId, pWalHead->version, nodeVersion); if (nodeRole == TAOS_SYNC_ROLE_SLAVE) { sInfo("vgId:%d, restart connection", pNode->vgId); for (int32_t i = 0; i < pNode->replica; ++i) { @@ -1277,9 +1335,9 @@ static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle int32_t retLen = write(pPeer->peerFd, pSyncHead, fwdLen); if (retLen == fwdLen) { - sDebug("%s, forward is sent, ver:%" PRIu64 " contLen:%d", pPeer->id, pWalHead->version, pWalHead->len); + sTrace("%s, forward is sent, hver:%" PRIu64 " contLen:%d", pPeer->id, pWalHead->version, pWalHead->len); } else { - sError("%s, failed to forward, ver:%" PRIu64 " retLen:%d", pPeer->id, pWalHead->version, retLen); + sError("%s, failed to forward, hver:%" PRIu64 " retLen:%d", pPeer->id, pWalHead->version, retLen); syncRestartConnection(pPeer); } } diff --git a/src/sync/src/syncRestore.c b/src/sync/src/syncRestore.c index 5d7b9eac9b..cc2315fb15 100644 --- a/src/sync/src/syncRestore.c +++ b/src/sync/src/syncRestore.c @@ -13,7 +13,9 @@ * along with this program. If not, see . */ +#define _DEFAULT_SOURCE #include "os.h" +#include "taoserror.h" #include "tlog.h" #include "tutil.h" #include "ttimer.h" @@ -126,7 +128,7 @@ static int32_t syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) { } if (code < 0) { - sError("%s, failed to restore %s(%s)", pPeer->id, name, strerror(errno)); + sError("%s, failed to restore %s since %s", pPeer->id, name, strerror(errno)); } return code; @@ -140,6 +142,7 @@ static int32_t syncRestoreWal(SSyncPeer *pPeer) { if (buffer == NULL) return -1; SWalHead *pHead = (SWalHead *)buffer; + uint64_t lastVer = 0; while (1) { ret = taosReadMsg(pPeer->syncFd, pHead, sizeof(SWalHead)); @@ -153,12 +156,19 @@ static int32_t syncRestoreWal(SSyncPeer *pPeer) { ret = taosReadMsg(pPeer->syncFd, pHead->cont, pHead->len); if (ret < 0) break; - sDebug("%s, restore a record, qtype:wal hver:%" PRIu64, pPeer->id, pHead->version); + sTrace("%s, restore a record, qtype:wal len:%d hver:%" PRIu64, pPeer->id, pHead->len, pHead->version); + + if (lastVer == pHead->version) { + sError("%s, failed to restore record, same hver:%" PRIu64 ", wal sync failed" PRIu64, pPeer->id, lastVer); + break; + } + lastVer = pHead->version; + (*pNode->writeToCache)(pNode->ahandle, pHead, TAOS_QTYPE_WAL, NULL); } if (code < 0) { - sError("%s, failed to restore wal(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to restore wal from syncFd:%d since %s", pPeer->id, pPeer->syncFd, strerror(errno)); } free(buffer); @@ -214,7 +224,7 @@ int32_t syncSaveIntoBuffer(SSyncPeer *pPeer, SWalHead *pHead) { memcpy(pRecv->offset, pHead, len); pRecv->offset += len; pRecv->forwards++; - sDebug("%s, fwd is saved into queue, ver:%" PRIu64 " fwds:%d", pPeer->id, pHead->version, pRecv->forwards); + sTrace("%s, fwd is saved into queue, hver:%" PRIu64 " fwds:%d", pPeer->id, pHead->version, pRecv->forwards); } else { sError("%s, buffer size:%d is too small", pPeer->id, pRecv->bufferSize); pRecv->code = -1; // set error code @@ -291,7 +301,7 @@ static int32_t syncRestoreDataStepByStep(SSyncPeer *pPeer) { } void *syncRestoreData(void *param) { - SSyncPeer *pPeer = (SSyncPeer *)param; + SSyncPeer *pPeer = param; SSyncNode *pNode = pPeer->pSyncNode; taosBlockSIGPIPE(); @@ -300,7 +310,8 @@ void *syncRestoreData(void *param) { (*pNode->notifyRole)(pNode->ahandle, TAOS_SYNC_ROLE_SYNCING); if (syncOpenRecvBuffer(pNode) < 0) { - sError("%s, failed to allocate recv buffer", pPeer->id); + sError("%s, failed to allocate recv buffer, restart connection", pPeer->id); + syncRestartConnection(pPeer); } else { if (syncRestoreDataStepByStep(pPeer) == 0) { sInfo("%s, it is synced successfully", pPeer->id); diff --git a/src/sync/src/syncRetrieve.c b/src/sync/src/syncRetrieve.c index 21151f1199..82f40854e8 100644 --- a/src/sync/src/syncRetrieve.c +++ b/src/sync/src/syncRetrieve.c @@ -13,10 +13,8 @@ * along with this program. If not, see . */ -#include -#include +#define _DEFAULT_SOURCE #include -#include #include "os.h" #include "tlog.h" #include "tutil.h" @@ -34,7 +32,7 @@ static int32_t syncAddIntoWatchList(SSyncPeer *pPeer, char *name) { pPeer->watchNum = 0; pPeer->notifyFd = inotify_init1(IN_NONBLOCK); if (pPeer->notifyFd < 0) { - sError("%s, failed to init inotify(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to init inotify since %s", pPeer->id, strerror(errno)); return -1; } @@ -51,14 +49,14 @@ static int32_t syncAddIntoWatchList(SSyncPeer *pPeer, char *name) { if (*wd >= 0) { if (inotify_rm_watch(pPeer->notifyFd, *wd) < 0) { - sError("%s, failed to remove wd:%d(%s)", pPeer->id, *wd, strerror(errno)); + sError("%s, failed to remove wd:%d since %s", pPeer->id, *wd, strerror(errno)); return -1; } } *wd = inotify_add_watch(pPeer->notifyFd, name, IN_MODIFY | IN_DELETE); if (*wd == -1) { - sError("%s, failed to add %s(%s)", pPeer->id, name, strerror(errno)); + sError("%s, failed to add %s since %s", pPeer->id, name, strerror(errno)); return -1; } else { sDebug("%s, monitor %s, wd:%d watchNum:%d", pPeer->id, name, *wd, pPeer->watchNum); @@ -75,7 +73,7 @@ static int32_t syncAreFilesModified(SSyncPeer *pPeer) { char buf[2048]; int32_t len = read(pPeer->notifyFd, buf, sizeof(buf)); if (len < 0 && errno != EAGAIN) { - sError("%s, failed to read notify FD(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to read notify FD since %s", pPeer->id, strerror(errno)); return -1; } @@ -161,7 +159,7 @@ static int32_t syncRetrieveFile(SSyncPeer *pPeer) { } if (code < 0) { - sError("%s, failed to retrieve file(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to retrieve file since %s", pPeer->id, strerror(errno)); } return code; @@ -201,7 +199,7 @@ static int32_t syncMonitorLastWal(SSyncPeer *pPeer, char *name) { taosClose(pPeer->notifyFd); pPeer->notifyFd = inotify_init1(IN_NONBLOCK); if (pPeer->notifyFd < 0) { - sError("%s, failed to init inotify(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to init inotify since %s", pPeer->id, strerror(errno)); return -1; } @@ -216,7 +214,7 @@ static int32_t syncMonitorLastWal(SSyncPeer *pPeer, char *name) { *wd = inotify_add_watch(pPeer->notifyFd, name, IN_MODIFY | IN_CLOSE_WRITE); if (*wd == -1) { - sError("%s, failed to watch last wal(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to watch last wal since %s", pPeer->id, strerror(errno)); return -1; } @@ -227,7 +225,7 @@ static int32_t syncCheckLastWalChanges(SSyncPeer *pPeer, uint32_t *pEvent) { char buf[2048]; int32_t len = read(pPeer->notifyFd, buf, sizeof(buf)); if (len < 0 && errno != EAGAIN) { - sError("%s, failed to read notify FD(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to read notify FD since %s", pPeer->id, strerror(errno)); return -1; } @@ -268,7 +266,7 @@ static int32_t syncRetrieveLastWal(SSyncPeer *pPeer, char *name, uint64_t fversi break; } - sDebug("%s, last wal is forwarded, ver:%" PRIu64, pPeer->id, pHead->version); + sTrace("%s, last wal is forwarded, hver:%" PRIu64, pPeer->id, pHead->version); int32_t ret = taosWriteMsg(pPeer->syncFd, pHead, wsize); if (ret != wsize) break; pPeer->sversion = pHead->version; @@ -418,13 +416,13 @@ static int32_t syncRetrieveWal(SSyncPeer *pPeer) { } if (code == 0) { - sDebug("%s, wal retrieve is finished", pPeer->id); + sInfo("%s, wal retrieve is finished", pPeer->id); pPeer->sstatus = TAOS_SYNC_STATUS_CACHE; SWalHead walHead; memset(&walHead, 0, sizeof(walHead)); code = taosWriteMsg(pPeer->syncFd, &walHead, sizeof(walHead)); } else { - sError("%s, failed to send wal(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to send wal since %s", pPeer->id, strerror(errno)); } return code; @@ -447,7 +445,7 @@ static int32_t syncRetrieveDataStepByStep(SSyncPeer *pPeer) { pPeer->sversion = 0; pPeer->sstatus = TAOS_SYNC_STATUS_FILE; - sDebug("%s, start to retrieve file", pPeer->id); + sInfo("%s, start to retrieve file", pPeer->id); if (syncRetrieveFile(pPeer) < 0) { sError("%s, failed to retrieve file", pPeer->id); return -1; @@ -456,7 +454,7 @@ static int32_t syncRetrieveDataStepByStep(SSyncPeer *pPeer) { // if no files are synced, there must be wal to sync, sversion must be larger than one if (pPeer->sversion == 0) pPeer->sversion = 1; - sDebug("%s, start to retrieve wal", pPeer->id); + sInfo("%s, start to retrieve wal", pPeer->id); if (syncRetrieveWal(pPeer) < 0) { sError("%s, failed to retrieve wal", pPeer->id); return -1; @@ -478,7 +476,7 @@ void *syncRetrieveData(void *param) { sInfo("%s, sync tcp is setup", pPeer->id); if (syncRetrieveDataStepByStep(pPeer) == 0) { - sDebug("%s, sync retrieve process is successful", pPeer->id); + sInfo("%s, sync retrieve process is successful", pPeer->id); } else { sError("%s, failed to retrieve data, restart connection", pPeer->id); syncRestartConnection(pPeer); diff --git a/src/sync/src/taosTcpPool.c b/src/sync/src/taosTcpPool.c index 875528e66b..d1d9815f4a 100644 --- a/src/sync/src/taosTcpPool.c +++ b/src/sync/src/taosTcpPool.c @@ -150,7 +150,7 @@ void *taosAllocateTcpConn(void *param, void *pPeer, int32_t connFd) { } void taosFreeTcpConn(void *param) { - SConnObj * pConn = (SConnObj *)param; + SConnObj * pConn = param; SThreadObj *pThread = pConn->pThread; sDebug("%p TCP connection will be closed, fd:%d", pThread, pConn->fd); diff --git a/src/sync/src/tarbitrator.c b/src/sync/src/tarbitrator.c index b7f819a3cd..4016042de2 100644 --- a/src/sync/src/tarbitrator.c +++ b/src/sync/src/tarbitrator.c @@ -115,14 +115,14 @@ static void arbProcessIncommingConnection(int32_t connFd, uint32_t sourceIp) { SFirstPkt firstPkt; if (taosReadMsg(connFd, &firstPkt, sizeof(firstPkt)) != sizeof(firstPkt)) { - sError("failed to read peer first pkt from ip:%s(%s)", ipstr, strerror(errno)); + sError("failed to read peer first pkt from ip:%s since %s", ipstr, strerror(errno)); taosCloseSocket(connFd); return; } - SNodeConn *pNode = (SNodeConn *)calloc(sizeof(SNodeConn), 1); + SNodeConn *pNode = calloc(sizeof(SNodeConn), 1); if (pNode == NULL) { - sError("failed to allocate memory(%s)", strerror(errno)); + sError("failed to allocate memory since %s", strerror(errno)); taosCloseSocket(connFd); return; } @@ -146,7 +146,7 @@ static void arbProcessIncommingConnection(int32_t connFd, uint32_t sourceIp) { static void arbProcessBrokenLink(void *param) { SNodeConn *pNode = param; - sDebug("%s, TCP link is broken(%s), close connection", pNode->id, strerror(errno)); + sDebug("%s, TCP link is broken since %s, close connection", pNode->id, strerror(errno)); tfree(pNode); } diff --git a/src/vnode/inc/vnodeInt.h b/src/vnode/inc/vnodeInt.h index c9689ce8b2..021831a644 100644 --- a/src/vnode/inc/vnodeInt.h +++ b/src/vnode/inc/vnodeInt.h @@ -37,8 +37,9 @@ extern int32_t vDebugFlag; typedef struct { int32_t vgId; // global vnode group ID int32_t refCount; // reference count - int32_t queuedMsg; - int32_t delay; + int32_t queuedWMsg; + int32_t queuedRMsg; + int32_t delayMs; int8_t status; int8_t role; int8_t accessState; diff --git a/src/vnode/src/vnodeMain.c b/src/vnode/src/vnodeMain.c index e3eb35ea32..339391369f 100644 --- a/src/vnode/src/vnodeMain.c +++ b/src/vnode/src/vnodeMain.c @@ -378,9 +378,9 @@ int32_t vnodeClose(int32_t vgId) { return 0; } -void vnodeRelease(void *pVnodeRaw) { - if (pVnodeRaw == NULL) return; - SVnodeObj *pVnode = pVnodeRaw; +void vnodeRelease(void *vparam) { + if (vparam == NULL) return; + SVnodeObj *pVnode = vparam; int32_t code = 0; int32_t vgId = pVnode->vgId; @@ -641,18 +641,19 @@ static void vnodeNotifyRole(void *ahandle, int8_t role) { pVnode->role = role; dnodeSendStatusMsgToMnode(); - if (pVnode->role == TAOS_SYNC_ROLE_MASTER) + if (pVnode->role == TAOS_SYNC_ROLE_MASTER) { cqStart(pVnode->cq); - else + } else { cqStop(pVnode->cq); + } } static void vnodeCtrlFlow(void *ahandle, int32_t mseconds) { SVnodeObj *pVnode = ahandle; - if (pVnode->delay != mseconds) { - vInfo("vgId:%d, sync flow control, mseconds:%d", pVnode->vgId, mseconds); + if (pVnode->delayMs != mseconds) { + pVnode->delayMs = mseconds; + vDebug("vgId:%d, sync flow control, mseconds:%d", pVnode->vgId, mseconds); } - pVnode->delay = mseconds; } static int vnodeResetTsdb(SVnodeObj *pVnode) { diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 4cc8819bcb..e10d62a0c9 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -41,8 +41,8 @@ void vnodeInitReadFp(void) { // still required, or there will be a deadlock, so we don’t do any check here, but put the check codes before the // request enters the queue // -int32_t vnodeProcessRead(void *param, SVReadMsg *pRead) { - SVnodeObj *pVnode = (SVnodeObj *)param; +int32_t vnodeProcessRead(void *vparam, SVReadMsg *pRead) { + SVnodeObj *pVnode = vparam; int32_t msgType = pRead->msgType; if (vnodeProcessReadMsgFp[msgType] == NULL) { @@ -53,8 +53,8 @@ int32_t vnodeProcessRead(void *param, SVReadMsg *pRead) { return (*vnodeProcessReadMsgFp[msgType])(pVnode, pRead); } -static int32_t vnodeCheckRead(void *param) { - SVnodeObj *pVnode = param; +static int32_t vnodeCheckRead(void *vparam) { + SVnodeObj *pVnode = vparam; if (pVnode->status != TAOS_VN_STATUS_READY) { vDebug("vgId:%d, vnode status is %s, refCount:%d pVnode:%p", pVnode->vgId, vnodeStatus[pVnode->status], pVnode->refCount, pVnode); @@ -76,6 +76,16 @@ static int32_t vnodeCheckRead(void *param) { return TSDB_CODE_SUCCESS; } +void vnodeFreeFromRQueue(void *vparam, SVReadMsg *pRead) { + SVnodeObj *pVnode = vparam; + + atomic_sub_fetch_32(&pVnode->queuedRMsg, 1); + vTrace("vgId:%d, free from vrqueue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedRMsg); + + taosFreeQitem(pRead); + vnodeRelease(pVnode); +} + int32_t vnodeWriteToRQueue(void *vparam, void *pCont, int32_t contLen, int8_t qtype, void *rparam) { SVnodeObj *pVnode = vparam; @@ -108,7 +118,8 @@ int32_t vnodeWriteToRQueue(void *vparam, void *pCont, int32_t contLen, int8_t qt pRead->qtype = qtype; atomic_add_fetch_32(&pVnode->refCount, 1); - vTrace("vgId:%d, get vnode rqueue, refCount:%d pVnode:%p", pVnode->vgId, pVnode->refCount, pVnode); + atomic_add_fetch_32(&pVnode->queuedRMsg, 1); + vTrace("vgId:%d, write into vrqueue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedRMsg); taosWriteQitem(pVnode->rqueue, qtype, pRead); return TSDB_CODE_SUCCESS; diff --git a/src/vnode/src/vnodeWrite.c b/src/vnode/src/vnodeWrite.c index 2234b4f8ed..2d2be602ed 100644 --- a/src/vnode/src/vnodeWrite.c +++ b/src/vnode/src/vnodeWrite.c @@ -77,7 +77,7 @@ int32_t vnodeProcessWrite(void *vparam, void *wparam, int32_t qtype, void *rpara // assign version pHead->version = pVnode->version + 1; - if (pVnode->delay) usleep(pVnode->delay * 1000); + if (pVnode->delayMs) taosMsleep(pVnode->delayMs); } else { // from wal or forward // for data from WAL or forward, version may be smaller @@ -245,13 +245,13 @@ int32_t vnodeWriteToWQueue(void *vparam, void *wparam, int32_t qtype, void *rpar atomic_add_fetch_32(&pVnode->refCount, 1); - int32_t queued = atomic_add_fetch_32(&pVnode->queuedMsg, 1); + int32_t queued = atomic_add_fetch_32(&pVnode->queuedWMsg, 1); if (queued > MAX_QUEUED_MSG_NUM) { vDebug("vgId:%d, too many msg:%d in vwqueue, flow control", pVnode->vgId, queued); taosMsleep(1); } - vTrace("vgId:%d, write into vwqueue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedMsg); + vTrace("vgId:%d, write into vwqueue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedWMsg); taosWriteQitem(pVnode->wqueue, qtype, pWrite); return TSDB_CODE_SUCCESS; @@ -260,8 +260,8 @@ int32_t vnodeWriteToWQueue(void *vparam, void *wparam, int32_t qtype, void *rpar void vnodeFreeFromWQueue(void *vparam, SVWriteMsg *pWrite) { SVnodeObj *pVnode = vparam; - atomic_sub_fetch_32(&pVnode->queuedMsg, 1); - vTrace("vgId:%d, free from vwqueue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedMsg); + atomic_sub_fetch_32(&pVnode->queuedWMsg, 1); + vTrace("vgId:%d, free from vwqueue, refCount:%d queued:%d", pVnode->vgId, pVnode->refCount, pVnode->queuedWMsg); taosFreeQitem(pWrite); vnodeRelease(pVnode); diff --git a/src/wal/src/walWrite.c b/src/wal/src/walWrite.c index 72464d4309..36b3dba165 100644 --- a/src/wal/src/walWrite.c +++ b/src/wal/src/walWrite.c @@ -144,9 +144,9 @@ void walFsync(void *handle, bool forceFsync) { if (pWal == NULL || pWal->fd < 0) return; if (forceFsync || (pWal->level == TAOS_WAL_FSYNC && pWal->fsyncPeriod == 0)) { - wTrace("vgId:%d, file:%s, do fsync", pWal->vgId, pWal->name); + wTrace("vgId:%d, fileId:%" PRId64 ", do fsync", pWal->vgId, pWal->fileId); if (fsync(pWal->fd) < 0) { - wError("vgId:%d, file:%s, fsync failed since %s", pWal->vgId, pWal->name, strerror(errno)); + wError("vgId:%d, fileId:%" PRId64 ", fsync failed since %s", pWal->vgId, pWal->fileId, strerror(errno)); } } } diff --git a/tests/examples/rust b/tests/examples/rust deleted file mode 160000 index f2ffd30521..0000000000 --- a/tests/examples/rust +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f2ffd30521b8e8afbc9d25c75f8eeeb6a48bd030 diff --git a/tests/perftest-scripts/perftest-query.sh b/tests/perftest-scripts/perftest-query.sh index bb5d9e0a9d..51bb9b36c3 100755 --- a/tests/perftest-scripts/perftest-query.sh +++ b/tests/perftest-scripts/perftest-query.sh @@ -1,8 +1,8 @@ #!/bin/bash today=`date +"%Y%m%d"` -WORK_DIR=/home/ubuntu/pxiao/ -PERFORMANCE_TEST_REPORT=$TDENGINE_DIR/tests/performance-test-report-$today.log +WORK_DIR=/home/ubuntu/pxiao +PERFORMANCE_TEST_REPORT=$WORK_DIR/TDengine/tests/performance-test-report-$today.log # Coloured Echoes # function red_echo { echo -e "\033[31m$@\033[0m"; } # @@ -60,11 +60,12 @@ function buildTDengine { } function runQueryPerfTest { - nohup $WORK_DIR/TDengine/debug/build/bin/taosd -c /etc/taodperf/ > /dev/null 2>&1 & + [ -f $PERFORMANCE_TEST_REPORT ] && rm $PERFORMANCE_TEST_REPORT + nohup $WORK_DIR/TDengine/debug/build/bin/taosd -c /etc/taosperf/ > /dev/null 2>&1 & echoInfo "Run Performance Test" cd $WORK_DIR/TDengine/tests/pytest - python3 query/queryPerformance.py | tee -a $PERFORMANCE_TEST_REPORT + python3 query/queryPerformance.py 0 | tee -a $PERFORMANCE_TEST_REPORT } @@ -77,9 +78,9 @@ function sendReport { sed -i 's/\x1b\[[0-9;]*m//g' $PERFORMANCE_TEST_REPORT BODY_CONTENT=`cat $PERFORMANCE_TEST_REPORT` - echo -e "to: ${receiver}\nsubject: Query Performace Report ${today}, commit ID: ${LOCAL_COMMIT}\n\n${today}:\n${BODY_CONTENT}" | \ + echo -e "From: \nto: ${receiver}\nsubject: Query Performace Report ${today}, commit ID: ${LOCAL_COMMIT}\n\n${today}:\n${BODY_CONTENT}" | \ (cat - && uuencode $PERFORMANCE_TEST_REPORT performance-test-report-$today.log) | \ - ssmtp "${receiver}" && echo "Report Sent!" + /usr/sbin/ssmtp "${receiver}" && echo "Report Sent!" } diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh index 3a9aa00617..525fbad6c1 100755 --- a/tests/pytest/fulltest.sh +++ b/tests/pytest/fulltest.sh @@ -202,6 +202,7 @@ python3 queryCount.py python3 ./test.py -f query/queryGroupbyWithInterval.py python3 client/twoClients.py python3 test.py -f query/queryInterval.py +python3 test.py -f query/queryFillTest.py # tools python3 test.py -f tools/taosdemo.py diff --git a/tests/pytest/handle_crash_gen_val_log.sh b/tests/pytest/handle_crash_gen_val_log.sh index 2d48de65c9..ce3d1c0c67 100755 --- a/tests/pytest/handle_crash_gen_val_log.sh +++ b/tests/pytest/handle_crash_gen_val_log.sh @@ -5,7 +5,7 @@ GREEN='\033[1;32m' GREEN_DARK='\033[0;32m' GREEN_UNDERLINE='\033[4;32m' NC='\033[0m' -nohup /root/TDinternal/debug/build/bin/taosd -c /root/TDinternal/community/sim/dnode1/cfg >/dev/null & +nohup /var/lib/jenkins/workspace/TDinternal/debug/build/bin/taosd -c /var/lib/jenkins/workspace/TDinternal/community/sim/dnode1/cfg >/dev/null & ./crash_gen.sh --valgrind -p -t 10 -s 100 -b 4 pidof taosd|xargs kill grep 'start to execute\|ERROR SUMMARY' valgrind.err|grep -v 'grep'|uniq|tee crash_gen_mem_err.log diff --git a/tests/pytest/query/queryFillTest.py b/tests/pytest/query/queryFillTest.py new file mode 100644 index 0000000000..9fd898041a --- /dev/null +++ b/tests/pytest/query/queryFillTest.py @@ -0,0 +1,68 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import taos +from util.log import tdLog +from util.cases import tdCases +from util.sql import tdSql + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + self.ts = 1537146000000 + + def run(self): + tdSql.prepare() + + print("==============step1") + tdSql.execute( + "create table if not exists stb (ts timestamp, col1 int, col2 int, col3 int) tags(loc nchar(20), id int)") + + currTs = self.ts + + for i in range(100): + sql = "create table tb%d using stb tags('city%d', 1)" % (i, i) + tdSql.execute(sql) + + sql = "insert into tb%d values" % i + for j in range(5): + val = 1 + j + sql += "(%d, %d, %d, %d)" % (currTs, val, val, val) + currTs += 1000000 + tdSql.execute(sql) + + tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h)") + tdSql.checkRows(139) + + tdSql.query("select first(col1) - avg(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' interval(1h) fill(null)") + tdSql.checkRows(141) + tdSql.checkData(0, 1, None) + tdSql.checkData(140, 1, None) + + tdSql.query("select max(col1) - min(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' and id = 1 group by loc, id") + rows = tdSql.queryRows + + tdSql.query("select spread(col1) from stb where ts > '2018-09-17 08:00:00.000' and ts < '2018-09-23 04:36:40.000' and id = 1 group by loc, id") + tdSql.checkRows(rows) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) \ No newline at end of file diff --git a/tests/pytest/query/queryInterval.py b/tests/pytest/query/queryInterval.py index ec3255ba7f..98b8c9fbef 100644 --- a/tests/pytest/query/queryInterval.py +++ b/tests/pytest/query/queryInterval.py @@ -32,30 +32,44 @@ class TDTestCase: tdSql.execute("insert into t0 using st tags('beijing') values(%d, 220) (%d, 221) (%d, 225) (%d, 228) (%d, 222)" % (self.ts, self.ts + 1000000000, self.ts + 2000000000, self.ts + 3000000000, self.ts + 6000000000)) tdSql.execute("insert into t1 using st tags('shanghai') values(%d, 220) (%d, 221) (%d, 225) (%d, 228) (%d, 222)" - % (self.ts, self.ts + 2000000000, self.ts + 4000000000, self.ts + 5000000000, self.ts + 7000000000)) + % (self.ts, self.ts + 2000000000, self.ts + 4000000000, self.ts + 5000000000, self.ts + 7000000000)) + tdSql.query("select avg(voltage) from st interval(1n)") - tdSql.checkRows(4) - tdSql.checkData(0, 1, 220.0) - tdSql.checkData(1, 1, 222.33333333333334) - tdSql.checkData(2, 1, 227.0) - tdSql.checkData(3, 1, 222.0) + tdSql.checkRows(3) + tdSql.checkData(0, 0, "2020-07-01 00:00:00") + tdSql.checkData(0, 1, 221.4) + tdSql.checkData(1, 0, "2020-08-01 00:00:00") + tdSql.checkData(1, 1, 227.0) + tdSql.checkData(2, 0, "2020-09-01 00:00:00") + tdSql.checkData(2, 1, 222.0) tdSql.query("select avg(voltage) from st interval(1n, 15d)") tdSql.checkRows(4) + tdSql.checkData(0, 0, "2020-06-16 00:00:00") tdSql.checkData(0, 1, 220.333333) + tdSql.checkData(1, 0, "2020-07-16 00:00:00") tdSql.checkData(1, 1, 224.666666) + tdSql.checkData(2, 0, "2020-08-16 00:00:00") tdSql.checkData(2, 1, 225.0) + tdSql.checkData(3, 0, "2020-09-16 00:00:00") tdSql.checkData(3, 1, 222.0) tdSql.query("select avg(voltage) from st interval(1n, 15d) group by loc") tdSql.checkRows(7) + tdSql.checkData(0, 0, "2020-06-16 00:00:00") tdSql.checkData(0, 1, 220.5) + tdSql.checkData(1, 0, "2020-07-16 00:00:00") tdSql.checkData(1, 1, 226.5) + tdSql.checkData(2, 0, "2020-08-16 00:00:00") tdSql.checkData(2, 1, 222.0) + tdSql.checkData(3, 0, "2020-06-16 00:00:00") tdSql.checkData(3, 1, 220.0) + tdSql.checkData(4, 0, "2020-07-16 00:00:00") tdSql.checkData(4, 1, 221.0) + tdSql.checkData(5, 0, "2020-08-16 00:00:00") tdSql.checkData(5, 1, 226.5) + tdSql.checkData(6, 0, "2020-09-16 00:00:00") tdSql.checkData(6, 1, 222.0) def stop(self): diff --git a/tests/pytest/query/queryPerformance.py b/tests/pytest/query/queryPerformance.py index e09900acc4..72af38450c 100644 --- a/tests/pytest/query/queryPerformance.py +++ b/tests/pytest/query/queryPerformance.py @@ -23,7 +23,7 @@ class taosdemoQueryPerformace: self.host = "127.0.0.1" self.user = "root" self.password = "taosdata" - self.config = "/etc/taos" + self.config = "/etc/taosperf" self.conn = taos.connect( self.host, self.user, diff --git a/tests/pytest/tools/taosdemo.py b/tests/pytest/tools/taosdemo.py index 5bf8ebaf03..1a976aef59 100644 --- a/tests/pytest/tools/taosdemo.py +++ b/tests/pytest/tools/taosdemo.py @@ -55,6 +55,12 @@ class TDTestCase: tdSql.query("select count(*) from meters") tdSql.checkData(0, 0, self.numberOfTables * self.numberOfRecords) + tdSql.query("select sum(f1) from test.meters interval(1h) sliding(30m)") + tdSql.checkRows(2) + + tdSql.query("select apercentile(f1, 1) from test.meters interval(10s)") + tdSql.checkRows(11) + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/script/general/parser/alter.sim b/tests/script/general/parser/alter.sim index 6b28b20fb8..5c15656f24 100644 --- a/tests/script/general/parser/alter.sim +++ b/tests/script/general/parser/alter.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = m_alt_db @@ -56,6 +56,7 @@ if $rows != 2 then endi print data03 = $data03 if $data03 != taos then + print expect taos, actual: $data03 return -1 endi sql drop table tb @@ -113,7 +114,7 @@ endi sql drop table tb sql drop table mt -sleep 3000 +sleep 500 ### ALTER TABLE WHILE STREAMING [TBASE271] #sql create table tb1 (ts timestamp, c1 int, c2 nchar(5), c3 int) #sql create table strm as select count(*), avg(c1), first(c2), sum(c3) from tb1 interval(2s) @@ -133,7 +134,7 @@ sleep 3000 # return -1 #endi #sql alter table tb1 drop column c3 -#sleep 6000 +#sleep 3000 #sql insert into tb1 values (now, 2, 'taos') #sleep 30000 #sql select * from strm @@ -144,9 +145,9 @@ sleep 3000 # return -1 #endi #sql alter table tb1 add column c3 int -#sleep 6000 -#sql insert into tb1 values (now, 3, 'taos', 3); #sleep 3000 +#sql insert into tb1 values (now, 3, 'taos', 3); +#sleep 500 #sql select * from strm #if $rows != 3 then # return -1 @@ -185,7 +186,7 @@ sql create database $db sql use $db sql create table mt (ts timestamp, c1 int, c2 nchar(7), c3 int) tags (t1 int) sql create table tb using mt tags(1) -sleep 3000 +sleep 500 sql insert into tb values ('2018-11-01 16:30:00.000', 1, 'insert', 1) sql alter table mt drop column c3 diff --git a/tests/script/general/parser/alter1.sim b/tests/script/general/parser/alter1.sim index 24cf79eae1..e013242b82 100644 --- a/tests/script/general/parser/alter1.sim +++ b/tests/script/general/parser/alter1.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect sql reset query cache @@ -87,7 +87,7 @@ if $data13 != NULL then return -1 endi -sleep 3000 +sleep 500 print ================== insert values into table sql insert into car1 values (now, 1, 1,1 ) (now +1s, 2,2,2,) car2 values (now, 1,3,3) diff --git a/tests/script/general/parser/alter_stable.sim b/tests/script/general/parser/alter_stable.sim index b64c919042..6b3f3a8f53 100644 --- a/tests/script/general/parser/alter_stable.sim +++ b/tests/script/general/parser/alter_stable.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ========== alter_stable.sim diff --git a/tests/script/general/parser/auto_create_tb.sim b/tests/script/general/parser/auto_create_tb.sim index 64fec4b56d..6deaf92a6c 100644 --- a/tests/script/general/parser/auto_create_tb.sim +++ b/tests/script/general/parser/auto_create_tb.sim @@ -4,7 +4,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ======================== dnode1 start @@ -208,11 +208,11 @@ endi print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 sql use $db #### auto create multiple tables @@ -298,7 +298,7 @@ endi sql create table tu(ts timestamp, k int); sql_error create table txu using tu tags(0) values(now, 1); -#[TBASE-675] +print =================> [TBASE-675] sql insert into tu values(1565971200000, 1) (1565971200000,2) (1565971200001, 3)(1565971200001, 4) sql select * from tu if $rows != 2 then diff --git a/tests/script/general/parser/auto_create_tb_drop_tb.sim b/tests/script/general/parser/auto_create_tb_drop_tb.sim index be334bca4a..8a429cf91a 100644 --- a/tests/script/general/parser/auto_create_tb_drop_tb.sim +++ b/tests/script/general/parser/auto_create_tb_drop_tb.sim @@ -4,7 +4,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c maxTablesPerVnode -v 4 system sh/cfg.sh -n dnode1 -c ctime -v 30 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = db @@ -49,7 +49,7 @@ while $t < $tbNum endw print ====== tables created -sleep 60000 +sleep 500 sql drop table tb2 $x = 0 @@ -59,9 +59,7 @@ while $x < $rowNum $t1 = $t1 . ' sql insert into tb1 using $stb tags( $t1 ) values ( $ts , $x ) $x = $x + 1 -endw - -sleep 6000 +endw $ts = $ts0 + $delta $ts = $ts + 1 diff --git a/tests/script/general/parser/binary_escapeCharacter.sim b/tests/script/general/parser/binary_escapeCharacter.sim index c3c867795a..e9e61f35bf 100644 --- a/tests/script/general/parser/binary_escapeCharacter.sim +++ b/tests/script/general/parser/binary_escapeCharacter.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect sql drop database if exists ecdb diff --git a/tests/script/general/parser/col_arithmetic_operation.sim b/tests/script/general/parser/col_arithmetic_operation.sim index 3208df95e4..d5ba57e6c7 100644 --- a/tests/script/general/parser/col_arithmetic_operation.sim +++ b/tests/script/general/parser/col_arithmetic_operation.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = ca_db @@ -34,7 +34,7 @@ while $i < $halfTbNum $tb1 = $tbPrefix . $tbId sql create table $tb using $stb tags( $i ) sql create table $tb1 using $stb tags( $tbId ) - + $x = 0 while $x < $rowNum $xs = $x * $delta @@ -46,8 +46,7 @@ while $i < $halfTbNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , NULL , $c , NULL , $c , NULL , $c , NULL, NULL , $nchar ) $x = $x + 1 endw $i = $i + 1 diff --git a/tests/script/general/parser/columnValue.sim b/tests/script/general/parser/columnValue.sim index e905f61215..2c03a3552a 100644 --- a/tests/script/general/parser/columnValue.sim +++ b/tests/script/general/parser/columnValue.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ========== columnValues.sim diff --git a/tests/script/general/parser/columnValue_bigint.sim b/tests/script/general/parser/columnValue_bigint.sim index e6839b2fb6..3546ca15ee 100644 --- a/tests/script/general/parser/columnValue_bigint.sim +++ b/tests/script/general/parser/columnValue_bigint.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_bool.sim b/tests/script/general/parser/columnValue_bool.sim index 7f3a6c3d6a..d68f375900 100644 --- a/tests/script/general/parser/columnValue_bool.sim +++ b/tests/script/general/parser/columnValue_bool.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_double.sim b/tests/script/general/parser/columnValue_double.sim index 733fc52285..fd2da37838 100644 --- a/tests/script/general/parser/columnValue_double.sim +++ b/tests/script/general/parser/columnValue_double.sim @@ -1,5 +1,5 @@ #### -sleep 3000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_float.sim b/tests/script/general/parser/columnValue_float.sim index c71b4b40ee..019cf176d0 100644 --- a/tests/script/general/parser/columnValue_float.sim +++ b/tests/script/general/parser/columnValue_float.sim @@ -1,5 +1,5 @@ #### -sleep 3000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_int.sim b/tests/script/general/parser/columnValue_int.sim index 2a909ebf3c..1f84df5ca0 100644 --- a/tests/script/general/parser/columnValue_int.sim +++ b/tests/script/general/parser/columnValue_int.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_smallint.sim b/tests/script/general/parser/columnValue_smallint.sim index cf34a85a2a..af5c581871 100644 --- a/tests/script/general/parser/columnValue_smallint.sim +++ b/tests/script/general/parser/columnValue_smallint.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/columnValue_tinyint.sim b/tests/script/general/parser/columnValue_tinyint.sim index 707242a23e..3efe52cc91 100644 --- a/tests/script/general/parser/columnValue_tinyint.sim +++ b/tests/script/general/parser/columnValue_tinyint.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect sql create database if not exists db sql use db diff --git a/tests/script/general/parser/commit.sim b/tests/script/general/parser/commit.sim index 4d85806b69..c798bf9d7c 100644 --- a/tests/script/general/parser/commit.sim +++ b/tests/script/general/parser/commit.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxTablesperVnode -v 100 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = sc_db @@ -50,8 +50,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -83,12 +82,12 @@ endw print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 -system sh/exec.sh -n dnode1 -s start sleep 3000 +system sh/exec.sh -n dnode1 -s start +sleep 500 print ================== server restart completed sql connect -sleep 3000 +sleep 500 print ====== select from table and check num of rows returned sql use $db diff --git a/tests/script/general/parser/constCol.sim b/tests/script/general/parser/constCol.sim index b5a4d4abea..4a8e443281 100644 --- a/tests/script/general/parser/constCol.sim +++ b/tests/script/general/parser/constCol.sim @@ -353,8 +353,8 @@ if $rows != 3 then endi print =============================> td-2036 -if $data00 != 0.3000000 then - print expect: 0.3000000, actual:$data00 +if $data00 != 0.300000000 then + print expect: 0.300000000, actual:$data00 return -1 endi diff --git a/tests/script/general/parser/create_db.sim b/tests/script/general/parser/create_db.sim index ed6e427fe7..3b7f24b6d9 100644 --- a/tests/script/general/parser/create_db.sim +++ b/tests/script/general/parser/create_db.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ======================== dnode1 start diff --git a/tests/script/general/parser/create_mt.sim b/tests/script/general/parser/create_mt.sim index f21a830671..e11f322761 100644 --- a/tests/script/general/parser/create_mt.sim +++ b/tests/script/general/parser/create_mt.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ======================== dnode1 start diff --git a/tests/script/general/parser/create_tb.sim b/tests/script/general/parser/create_tb.sim index 9d1672fdbe..609aad2adb 100644 --- a/tests/script/general/parser/create_tb.sim +++ b/tests/script/general/parser/create_tb.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ======================== dnode1 start diff --git a/tests/script/general/parser/dbtbnameValidate.sim b/tests/script/general/parser/dbtbnameValidate.sim index b46a222282..fd40ecc3f7 100644 --- a/tests/script/general/parser/dbtbnameValidate.sim +++ b/tests/script/general/parser/dbtbnameValidate.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect print ========== db name and table name check in create and drop, describe diff --git a/tests/script/general/parser/fill.sim b/tests/script/general/parser/fill.sim index 0547db7749..9851a4e7fc 100644 --- a/tests/script/general/parser/fill.sim +++ b/tests/script/general/parser/fill.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = m_fl_db diff --git a/tests/script/general/parser/fill_stb.sim b/tests/script/general/parser/fill_stb.sim index f0cd058352..83eb98c465 100644 --- a/tests/script/general/parser/fill_stb.sim +++ b/tests/script/general/parser/fill_stb.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = fl1_db diff --git a/tests/script/general/parser/fill_us.sim b/tests/script/general/parser/fill_us.sim index b597d378a2..dc8ee8659d 100644 --- a/tests/script/general/parser/fill_us.sim +++ b/tests/script/general/parser/fill_us.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = m_fl_db diff --git a/tests/script/general/parser/first_last.sim b/tests/script/general/parser/first_last.sim index 46431b0848..a934d3bcab 100644 --- a/tests/script/general/parser/first_last.sim +++ b/tests/script/general/parser/first_last.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxTablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = first_db @@ -76,11 +76,11 @@ run general/parser/first_last_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 run general/parser/first_last_query.sim diff --git a/tests/script/general/parser/first_last_query.sim b/tests/script/general/parser/first_last_query.sim index d43cd52878..a982f10362 100644 --- a/tests/script/general/parser/first_last_query.sim +++ b/tests/script/general/parser/first_last_query.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = first_db diff --git a/tests/script/general/parser/groupby.sim b/tests/script/general/parser/groupby.sim index 145c4a008f..19d9ae84cb 100644 --- a/tests/script/general/parser/groupby.sim +++ b/tests/script/general/parser/groupby.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = group_db @@ -33,12 +33,19 @@ sql create database if not exists $db keep 36500 sql use $db sql create table $mt (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9)) TAGS(t1 int, t2 binary(12)) +$half = $tbNum / 2 + $i = 0 -while $i < $tbNum +while $i < $half $tb = $tbPrefix . $i $tg2 = ' . abc $tg2 = $tg2 . ' + + $nextSuffix = $i + $half + $tb1 = $tbPrefix . $nextSuffix + sql create table $tb using $mt tags( $i , $tg2 ) + sql create table $tb1 using $mt tags( $nextSuffix , $tg2 ) $x = 0 while $x < $rowNum @@ -55,7 +62,7 @@ while $i < $tbNum $nchar = $nchar . $c $nchar = $nchar . ' - sql insert into $tb values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) + sql insert into $tb values ($tstart , $c , $c , $x , $x , $c , $c , $c , $binary , $nchar ) $tb1 values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) $tstart = $tstart + 1 $x = $x + 1 endw @@ -423,8 +430,172 @@ if $data97 != @group_tb0@ then return -1 endi -print ---------------------------------> group by binary|nchar data add cases +sql select count(*),first(ts),last(ts),min(c3) from group_tb1 group by c4; +if $rows != 10000 then + return -1 +endi +if $data00 != 1 then + return -1 +endi + +if $data01 != @70-01-01 08:01:40.000@ then + return -1 +endi + +if $data02 != @70-01-01 08:01:40.000@ then + return -1 +endi + +if $data03 != 0 then + return -1 +endi + +sql select count(*),first(ts),last(ts),min(c3) from group_tb1 group by c4 limit 1; +if $rows != 1 then + return -1 +endi + +sql select count(*),first(ts),last(ts),min(c3) from group_tb1 group by c4 limit 20 offset 9990; +if $rows != 10 then + return -1 +endi + +sql select count(*),first(ts),last(ts),min(c3),max(c3),sum(c3),avg(c3),sum(c4)/count(c4) from group_tb1 group by c4; +if $rows != 10000 then + return -1 +endi + +print ---------------------------------> group by binary|nchar data add cases +sql select count(*) from group_tb1 group by c8; +if $rows != 100 then + return -1 +endi + +sql select count(*),sum(c4), count(c4), sum(c4)/count(c4) from group_tb1 group by c8 +if $rows != 100 then + return -1 +endi + +if $data00 != 100 then + return -1 +endi + +if $data01 != 495000 then + return -1 +endi + +if $data02 != 100 then + return -1 +endi + +if $data03 != 4950.000000000 then + print expect 4950.000000000 , acutal $data03 + return -1 +endi + +if $data10 != 100 then + return -1 +endi + +if $data11 != 495100 then + return -1 +endi + +if $data13 != 4951.000000000 then + return -1 +endi + +print ====================> group by normal column + slimit + soffset +sql select count(*), c8 from group_mt0 group by c8 limit 1 offset 0; +if $rows != 100 then + return -1 +endi + +sql select sum(c2),c8,avg(c2), sum(c2)/count(*) from group_mt0 group by c8 slimit 2 soffset 99 +if $rows != 1 then + return -1 +endi + +if $data00 != 79200.000000000 then + return -1 +endi + +if $data01 != @binary99@ then + return -1 +endi + +if $data02 != 99.000000000 then + return -1 +endi + +if $data03 != 99.000000000 then + return -1 +endi + +print ============>td-1765 +sql select percentile(c4, 49),min(c4),max(c4),avg(c4),stddev(c4) from group_tb0 group by c8; +if $rows != 100 then + return -1 +endi + +if $data00 != 4851.000000000 then + return -1 +endi + +if $data01 != 0 then + return -1 +endi + +if $data02 != 9900 then + return -1 +endi + +if $data03 != 4950.000000000 then + return -1 +endi + +if $data04 != 2886.607004772 then + return -1 +endi + +if $data10 != 4852.000000000 then + return -1 +endi + +if $data11 != 1 then + return -1 +endi + +if $data12 != 9901 then + return -1 +endi + +if $data13 != 4951.000000000 then + return -1 +endi + +if $data14 != 2886.607004772 then + return -1 +endi + +print ================>td-2090 +sql select leastsquares(c2, 1, 1) from group_tb1 group by c8; +if $rows != 100 then + return -1 +endi + +if $data00 != @{slop:0.000000, intercept:0.000000}@ then + return -1 +endi + +if $data10 != @{slop:0.000000, intercept:1.000000}@ then + return -1 +endi + +if $data90 != @{slop:0.000000, intercept:9.000000}@ then + return -1 +endi #=========================== group by multi tags ====================== sql create table st (ts timestamp, c int) tags (t1 int, t2 int, t3 int, t4 int); diff --git a/tests/script/general/parser/import.sim b/tests/script/general/parser/import.sim index 7ab0437685..6da2483738 100644 --- a/tests/script/general/parser/import.sim +++ b/tests/script/general/parser/import.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = impt_db @@ -64,7 +64,7 @@ sleep 2000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 sql use $db sql select * from tb diff --git a/tests/script/general/parser/import_commit1.sim b/tests/script/general/parser/import_commit1.sim index 197ae58453..9c5144a630 100644 --- a/tests/script/general/parser/import_commit1.sim +++ b/tests/script/general/parser/import_commit1.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c ctime -v 30 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = ic_db @@ -40,7 +40,7 @@ while $x < $rowNum endw print ====== tables created -sleep 6000 +sleep 3000 $ts = $ts0 + $delta $ts = $ts + 1 diff --git a/tests/script/general/parser/import_commit2.sim b/tests/script/general/parser/import_commit2.sim index e400d0c3cb..000394386e 100644 --- a/tests/script/general/parser/import_commit2.sim +++ b/tests/script/general/parser/import_commit2.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c ctime -v 30 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = ic_db @@ -39,7 +39,7 @@ while $x < $rowNum endw print ====== tables created -sleep 6000 +sleep 3000 $ts = $ts0 + $delta $ts = $ts + 1 diff --git a/tests/script/general/parser/import_commit3.sim b/tests/script/general/parser/import_commit3.sim index 7e7451e689..997a4a22aa 100644 --- a/tests/script/general/parser/import_commit3.sim +++ b/tests/script/general/parser/import_commit3.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 1 system sh/cfg.sh -n dnode1 -c ctime -v 30 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = ic_db @@ -39,7 +39,7 @@ while $x < $rowNum endw print ====== tables created -sleep 6000 +sleep 3000 $ts = $ts + 1 sql insert into $tb values ( $ts , -1, -1, -1, -1, -1) @@ -47,7 +47,7 @@ $ts = $ts0 + $delta $ts = $ts + 1 sql import into $tb values ( $ts , -2, -2, -2, -2, -2) -sleep 6000 +sleep 3000 sql show databases diff --git a/tests/script/general/parser/insert_multiTbl.sim b/tests/script/general/parser/insert_multiTbl.sim index b24c1b629f..887f97a198 100644 --- a/tests/script/general/parser/insert_multiTbl.sim +++ b/tests/script/general/parser/insert_multiTbl.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start sleep 2000 sql connect -sleep 3000 +sleep 500 print ======================== dnode1 start sql create database mul_db diff --git a/tests/script/general/parser/insert_tb.sim b/tests/script/general/parser/insert_tb.sim index 4ba455c244..0a9eb9f678 100644 --- a/tests/script/general/parser/insert_tb.sim +++ b/tests/script/general/parser/insert_tb.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ======================== dnode1 start @@ -103,7 +103,7 @@ if $rows != 1 then endi sql drop database $db -sleep 1000 +sleep 500 sql create database $db sql use $db sql create table stb1 (ts timestamp, c1 int) tags(t1 int) @@ -136,7 +136,7 @@ if $data21 != 1.000000000 then endi sql drop database $db -sleep 1000 +sleep 500 sql create database $db sql use $db sql create table stb (ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 nchar(10), c6 binary(20)) tags(t1 int, t2 bigint, t3 double, t4 float, t5 nchar(10)) diff --git a/tests/script/general/parser/interp.sim b/tests/script/general/parser/interp.sim index 1cd857162d..0d5c1804dd 100644 --- a/tests/script/general/parser/interp.sim +++ b/tests/script/general/parser/interp.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = intp_db @@ -47,8 +47,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -60,7 +59,7 @@ run general/parser/interp_test.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/interp_test.sim b/tests/script/general/parser/interp_test.sim index 8bffae4af6..42738a8bd1 100644 --- a/tests/script/general/parser/interp_test.sim +++ b/tests/script/general/parser/interp_test.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = intp_db @@ -303,6 +303,8 @@ $tb = $tbPrefix . 0 return -1 endi + print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(linear) + sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(linear) if $rows != 1 then return -1 @@ -338,6 +340,8 @@ $tb = $tbPrefix . 0 return -1 endi # columns contain NULL values + + print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(linear) sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(linear) if $rows != 1 then return -1 @@ -380,6 +384,7 @@ $tb = $tbPrefix . 0 endi $t = $tsu + 1000 + print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) if $rows != 0 then return -1 @@ -387,6 +392,7 @@ $tb = $tbPrefix . 0 ## fill(value) $t = $ts0 + 1000 + print 91 sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, -1, -2) if $rows != 1 then return -1 @@ -456,6 +462,7 @@ $tb = $tbPrefix . 0 if $data09 != nchar0 then return -1 endi + # table has NULL columns sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(value, -1, -2, -3) if $rows != 1 then @@ -491,11 +498,14 @@ $tb = $tbPrefix . 0 ##### select interp from stable ## interp(*) from stb + print select interp(*) from $stb where ts = $ts0 sql select interp(*) from $stb where ts = $ts0 if $rows != 1 then return -1 endi $t = $ts0 + 1000 + print 92 + sql select interp(*) from $stb where ts = $t if $rows != 0 then return -1 diff --git a/tests/script/general/parser/join.sim b/tests/script/general/parser/join.sim index 624c2e72c4..3ee90cda35 100644 --- a/tests/script/general/parser/join.sim +++ b/tests/script/general/parser/join.sim @@ -7,7 +7,7 @@ system sh/cfg.sh -n dnode1 -c rpcDebugFlag -v 135 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = join_db @@ -360,9 +360,7 @@ endi sql select join_mt1.* from join_mt1 print $rows - -$val = 2000 -if $rows != $val then +if $rows != 2000 then return -1 endi diff --git a/tests/script/general/parser/join_multivnode.sim b/tests/script/general/parser/join_multivnode.sim index a5e71260b4..1c901dd2e3 100644 --- a/tests/script/general/parser/join_multivnode.sim +++ b/tests/script/general/parser/join_multivnode.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start sql connect -sleep 1000 +sleep 500 $dbPrefix = join_m_db $tbPrefix = join_tb @@ -136,9 +136,8 @@ sql select join_mt0.ts, join_mt1.t1, join_mt0.t1, join_mt1.tbname, join_mt0.tbna #1970-01-01 08:01:40.790 | 10 | 945.000000000 | 90 | true | true | 0 | sql_error select count(join_mt0.c1), sum(join_mt1.c2), first(join_mt0.c5), last(join_mt1.c7), first(join_mt1.c7) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts interval(10a) group by join_mt0.t1 order by join_mt0.ts desc limit 20 offset 19; - sql select count(join_mt0.c1), sum(join_mt0.c2)/count(*), avg(c2), first(join_mt0.c5), last(c7) from join_mt0 interval(10a) group by join_mt0.t1 order by join_mt0.ts desc; -if $rows != 100 then +if $rows != 300 then return -1 endi @@ -147,7 +146,7 @@ if $data00 != @70-01-01 08:01:40.990@ then return -1 endi -if $data01 != 30 then +if $data01 != 10 then return -1 endi @@ -168,7 +167,7 @@ if $data05 != 1 then return -1 endi -if $data06 != 2 then +if $data06 != 0 then return -1 endi @@ -177,7 +176,7 @@ if $data10 != @70-01-01 08:01:40.980@ then return -1 endi -if $data11 != 30 then +if $data11 != 10 then return -1 endi @@ -198,16 +197,19 @@ if $data15 != 1 then return -1 endi -if $data16 != 2 then +if $data16 != 0 then return -1 endi # this function will cause shell crash sql_error select count(join_mt0.c1), first(join_mt0.c1) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts interval(10a) group by join_mt0.t1 order by join_mt0.ts desc; - -sql_error select last(join_mt1.c7), first(join_mt1.c7) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts interval(10m) group by join_mt0.t1 order by join_mt0.ts asc; - +sql_error select last(join_mt1.c7), first(join_mt1.c7) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts interval(10m) group by join_mt0.t1 order by join_mt0.ts asc; sql_error select count(join_mt0.c1), first(join_mt0.c1)-last(join_mt1.c1), first(join_mt1.c9) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts;", NULL); + +print ================================> TD-2152 +sql_error select join_mt1.c1,join_mt0.c1 from join_mt1,join_mt0 where join_mt1.ts = join_mt0.ts and join_mt1.t1 = join_mt0.t1 order by t; + +print =================================> add result check sql select count(join_mt0.c1), first(join_mt0.c1)/count(*), first(join_mt1.c9) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts;", NULL); sql select count(join_mt0.c1), first(join_mt0.c1)-last(join_mt0.c1), first(join_mt1.c9) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts;", NULL); sql select last(join_mt0.c1) from join_mt0, join_mt1 where join_mt0.t1=join_mt1.t1 and join_mt0.ts=join_mt1.ts;", NULL); diff --git a/tests/script/general/parser/lastrow.sim b/tests/script/general/parser/lastrow.sim index 6321823fe2..cc71123a77 100644 --- a/tests/script/general/parser/lastrow.sim +++ b/tests/script/general/parser/lastrow.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = lr_db @@ -62,11 +62,11 @@ run general/parser/lastrow_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 run general/parser/lastrow_query.sim diff --git a/tests/script/general/parser/lastrow_query.sim b/tests/script/general/parser/lastrow_query.sim index f81a48d5b2..5b9c8b60c3 100644 --- a/tests/script/general/parser/lastrow_query.sim +++ b/tests/script/general/parser/lastrow_query.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = lr_db diff --git a/tests/script/general/parser/limit.sim b/tests/script/general/parser/limit.sim index d8c72349db..fb5e704bf1 100644 --- a/tests/script/general/parser/limit.sim +++ b/tests/script/general/parser/limit.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxVgroupsPerDb -v 1 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = lm_db @@ -62,11 +62,11 @@ run general/parser/limit_stb.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 run general/parser/limit_tb.sim run general/parser/limit_stb.sim diff --git a/tests/script/general/parser/limit1.sim b/tests/script/general/parser/limit1.sim index 8b927b2a7f..7236421ec2 100644 --- a/tests/script/general/parser/limit1.sim +++ b/tests/script/general/parser/limit1.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxVgroupsPerDb -v 1 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = lm1_db @@ -48,8 +48,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -62,7 +61,7 @@ run general/parser/limit1_stb.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/limit1_stb.sim b/tests/script/general/parser/limit1_stb.sim index fbcd8d0965..d5846adc45 100644 --- a/tests/script/general/parser/limit1_stb.sim +++ b/tests/script/general/parser/limit1_stb.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = lm1_db diff --git a/tests/script/general/parser/limit1_tb.sim b/tests/script/general/parser/limit1_tb.sim index a9484d10db..1e473eb858 100644 --- a/tests/script/general/parser/limit1_tb.sim +++ b/tests/script/general/parser/limit1_tb.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = lm1_db diff --git a/tests/script/general/parser/limit1_tblocks100.sim b/tests/script/general/parser/limit1_tblocks100.sim index f1702924aa..9a123e645c 100644 --- a/tests/script/general/parser/limit1_tblocks100.sim +++ b/tests/script/general/parser/limit1_tblocks100.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxVgroupsPerDb -v 1 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = lm1_db @@ -48,8 +48,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -62,7 +61,7 @@ run general/parser/limit1_stb.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/limit2.sim b/tests/script/general/parser/limit2.sim index d22c786aa3..47c3eb6d08 100644 --- a/tests/script/general/parser/limit2.sim +++ b/tests/script/general/parser/limit2.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c rowsInFileBlock -v 255 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = lm2_db @@ -69,7 +69,7 @@ print ====== tables created print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/limit2_query.sim b/tests/script/general/parser/limit2_query.sim index 8294247a86..f9a1dd8e4b 100644 --- a/tests/script/general/parser/limit2_query.sim +++ b/tests/script/general/parser/limit2_query.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = lm2_db diff --git a/tests/script/general/parser/limit2_tblocks100.sim b/tests/script/general/parser/limit2_tblocks100.sim index 64f86edd28..1aaa8e885a 100644 --- a/tests/script/general/parser/limit2_tblocks100.sim +++ b/tests/script/general/parser/limit2_tblocks100.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c rowsInFileBlock -v 255 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = lm2_db @@ -69,7 +69,7 @@ print ====== tables created print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 3000 +sleep 500 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/limit_stb.sim b/tests/script/general/parser/limit_stb.sim index c9df03ab2e..b41b7b726b 100644 --- a/tests/script/general/parser/limit_stb.sim +++ b/tests/script/general/parser/limit_stb.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = lm_db diff --git a/tests/script/general/parser/limit_tb.sim b/tests/script/general/parser/limit_tb.sim index 970c7b75c5..b917627fdf 100644 --- a/tests/script/general/parser/limit_tb.sim +++ b/tests/script/general/parser/limit_tb.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = lm_db diff --git a/tests/script/general/parser/mixed_blocks.sim b/tests/script/general/parser/mixed_blocks.sim index 41082bb144..d3558560df 100644 --- a/tests/script/general/parser/mixed_blocks.sim +++ b/tests/script/general/parser/mixed_blocks.sim @@ -5,7 +5,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = mb_db diff --git a/tests/script/general/parser/nchar.sim b/tests/script/general/parser/nchar.sim index bdac5ace55..ab4ed2607a 100644 --- a/tests/script/general/parser/nchar.sim +++ b/tests/script/general/parser/nchar.sim @@ -5,7 +5,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ======================== dnode1 start diff --git a/tests/script/general/parser/null_char.sim b/tests/script/general/parser/null_char.sim index 2e39fc7db2..7b1c81a295 100644 --- a/tests/script/general/parser/null_char.sim +++ b/tests/script/general/parser/null_char.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c tableMetaKeepTimer -v 3 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ========== NULL_char.sim @@ -251,7 +251,7 @@ endi ################### nchar sql alter table st41 set tag tag_nchar = "��˼����" sql select tag_binary, tag_nchar, tag_int, tag_bool, tag_float, tag_double from st41 -#sleep 1000 +#sleep 500 #if $data01 != ��˼���� then # print ==== expect ��˼����, actually $data01 # return -1 diff --git a/tests/script/general/parser/projection_limit_offset.sim b/tests/script/general/parser/projection_limit_offset.sim index 7c83ca0c2f..bc22bd6da9 100644 --- a/tests/script/general/parser/projection_limit_offset.sim +++ b/tests/script/general/parser/projection_limit_offset.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = group_db @@ -28,11 +28,19 @@ sql use $db sql create table $mt (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9)) TAGS(t1 int, t2 binary(12)) $i = 0 -while $i < $tbNum +$half = $tbNum / 2 + +while $i < $half $tb = $tbPrefix . $i $tg2 = ' . abc $tg2 = $tg2 . ' + + $tbId = $i + $half + + $tb1 = $tbPrefix . $tbId + sql create table $tb using $mt tags( $i , $tg2 ) + sql create table $tb1 using $mt tags( $i , $tg2 ) $x = 0 while $x < $rowNum @@ -49,7 +57,7 @@ while $i < $tbNum $nchar = $nchar . $c $nchar = $nchar . ' - sql insert into $tb values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) + sql insert into $tb values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) $tb1 values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) $tstart = $tstart + 1 $x = $x + 1 endw @@ -402,7 +410,7 @@ sql_error select k, sum(k)+1 from tm0; print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/selectResNum.sim b/tests/script/general/parser/selectResNum.sim index 42cedc034b..464f363222 100644 --- a/tests/script/general/parser/selectResNum.sim +++ b/tests/script/general/parser/selectResNum.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 200 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = sc_db @@ -50,8 +50,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -119,12 +118,12 @@ endw print ====== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 6000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ====== server restart completed -sleep 3000 +sleep 500 sql connect -sleep 3000 +sleep 500 sql use $db ##### repeat test after server restart diff --git a/tests/script/general/parser/select_across_vnodes.sim b/tests/script/general/parser/select_across_vnodes.sim index ac3a8f2b2b..44e5576dac 100644 --- a/tests/script/general/parser/select_across_vnodes.sim +++ b/tests/script/general/parser/select_across_vnodes.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 5 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = sav_db diff --git a/tests/script/general/parser/select_from_cache_disk.sim b/tests/script/general/parser/select_from_cache_disk.sim index 4fdfa7b55b..0fa0848144 100644 --- a/tests/script/general/parser/select_from_cache_disk.sim +++ b/tests/script/general/parser/select_from_cache_disk.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = scd_db @@ -35,11 +35,11 @@ sql insert into $tb values ('2018-09-17 09:00:00.030', 3) print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 sql use $db # generate some data in cache diff --git a/tests/script/general/parser/select_with_tags.sim b/tests/script/general/parser/select_with_tags.sim index 68d145a5f2..dab76f6004 100644 --- a/tests/script/general/parser/select_with_tags.sim +++ b/tests/script/general/parser/select_with_tags.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = select_tags_db diff --git a/tests/script/general/parser/set_tag_vals.sim b/tests/script/general/parser/set_tag_vals.sim index 38af57c73d..bf29fe3902 100644 --- a/tests/script/general/parser/set_tag_vals.sim +++ b/tests/script/general/parser/set_tag_vals.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxVgroupsPerDb -v 1 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = db diff --git a/tests/script/general/parser/single_row_in_tb.sim b/tests/script/general/parser/single_row_in_tb.sim index 4305ae1b5d..fe1edb1f73 100644 --- a/tests/script/general/parser/single_row_in_tb.sim +++ b/tests/script/general/parser/single_row_in_tb.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = sr_db @@ -32,7 +32,7 @@ run general/parser/single_row_in_tb_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/single_row_in_tb_query.sim b/tests/script/general/parser/single_row_in_tb_query.sim index a1ae70ec81..9e90b91220 100644 --- a/tests/script/general/parser/single_row_in_tb_query.sim +++ b/tests/script/general/parser/single_row_in_tb_query.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = sr_db diff --git a/tests/script/general/parser/sliding.sim b/tests/script/general/parser/sliding.sim index b9fd66334d..4283421169 100644 --- a/tests/script/general/parser/sliding.sim +++ b/tests/script/general/parser/sliding.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c debugFlag -v 135 system sh/cfg.sh -n dnode1 -c rpcDebugFlag -v 135 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = sliding_db diff --git a/tests/script/general/parser/slimit.sim b/tests/script/general/parser/slimit.sim index edbf0c8cc0..f7a23019cf 100644 --- a/tests/script/general/parser/slimit.sim +++ b/tests/script/general/parser/slimit.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = slm_db @@ -97,11 +97,11 @@ run general/parser/slimit_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 run general/parser/slimit_query.sim diff --git a/tests/script/general/parser/slimit1.sim b/tests/script/general/parser/slimit1.sim index 9e26a2882a..7a2511eb76 100644 --- a/tests/script/general/parser/slimit1.sim +++ b/tests/script/general/parser/slimit1.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = slm_alt_tg_db @@ -56,11 +56,11 @@ run general/parser/slimit1_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 run general/parser/slimit1_query.sim diff --git a/tests/script/general/parser/slimit1_query.sim b/tests/script/general/parser/slimit1_query.sim index 617ccb3fd9..c205d45689 100644 --- a/tests/script/general/parser/slimit1_query.sim +++ b/tests/script/general/parser/slimit1_query.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = slm_alt_tg_db diff --git a/tests/script/general/parser/slimit_alter_tags.sim b/tests/script/general/parser/slimit_alter_tags.sim index eccd4a6815..1072f9ccb4 100644 --- a/tests/script/general/parser/slimit_alter_tags.sim +++ b/tests/script/general/parser/slimit_alter_tags.sim @@ -4,7 +4,7 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 2 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = slm_alt_tg_db @@ -171,11 +171,11 @@ endi print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 sql use $db ### repeat above queries diff --git a/tests/script/general/parser/slimit_query.sim b/tests/script/general/parser/slimit_query.sim index 655bc5f8be..3020f80472 100644 --- a/tests/script/general/parser/slimit_query.sim +++ b/tests/script/general/parser/slimit_query.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = slm_db diff --git a/tests/script/general/parser/stream_on_sys.sim b/tests/script/general/parser/stream_on_sys.sim index 845a484488..1c8eb82c79 100644 --- a/tests/script/general/parser/stream_on_sys.sim +++ b/tests/script/general/parser/stream_on_sys.sim @@ -6,7 +6,7 @@ system sh/cfg.sh -n dnode1 -c monitor -v 1 system sh/cfg.sh -n dnode1 -c monitorInterval -v 1 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect print ======================== stream_on_sys.sim diff --git a/tests/script/general/parser/tags_dynamically_specifiy.sim b/tests/script/general/parser/tags_dynamically_specifiy.sim index 07bf4d8dd1..8303a9c86d 100644 --- a/tests/script/general/parser/tags_dynamically_specifiy.sim +++ b/tests/script/general/parser/tags_dynamically_specifiy.sim @@ -3,9 +3,9 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect -sleep 3000 +sleep 500 $db = dytag_db $tbNum = 10 diff --git a/tests/script/general/parser/tags_filter.sim b/tests/script/general/parser/tags_filter.sim index 9842b4fda6..c3d0fdfc61 100644 --- a/tests/script/general/parser/tags_filter.sim +++ b/tests/script/general/parser/tags_filter.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $db = tf_db diff --git a/tests/script/general/parser/tbnameIn.sim b/tests/script/general/parser/tbnameIn.sim index fd5f32972a..d0f74ae53d 100644 --- a/tests/script/general/parser/tbnameIn.sim +++ b/tests/script/general/parser/tbnameIn.sim @@ -3,7 +3,7 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = ti_db @@ -55,8 +55,7 @@ while $i < $halfNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) - sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) $x = $x + 1 endw @@ -68,7 +67,7 @@ run general/parser/tbnameIn_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed diff --git a/tests/script/general/parser/tbnameIn_query.sim b/tests/script/general/parser/tbnameIn_query.sim index 37cc1aa824..ad7456f557 100644 --- a/tests/script/general/parser/tbnameIn_query.sim +++ b/tests/script/general/parser/tbnameIn_query.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = ti_db diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index 3dd80b8e38..8593400ce8 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -1,113 +1,112 @@ -sleep 2000 run general/parser/alter.sim -sleep 2000 +sleep 500 run general/parser/alter1.sim -sleep 2000 +sleep 500 run general/parser/alter_stable.sim -sleep 2000 +sleep 500 run general/parser/auto_create_tb.sim -sleep 2000 +sleep 500 run general/parser/auto_create_tb_drop_tb.sim -sleep 2000 +sleep 500 run general/parser/col_arithmetic_operation.sim -sleep 2000 +sleep 500 run general/parser/columnValue.sim -sleep 2000 +sleep 500 run general/parser/commit.sim -sleep 2000 +sleep 500 run general/parser/create_db.sim -sleep 2000 +sleep 500 run general/parser/create_mt.sim -sleep 2000 +sleep 500 run general/parser/create_tb.sim -sleep 2000 +sleep 500 run general/parser/dbtbnameValidate.sim -sleep 2000 +sleep 500 run general/parser/fill.sim -sleep 2000 +sleep 500 run general/parser/fill_stb.sim -sleep 2000 +sleep 500 #run general/parser/fill_us.sim # -sleep 2000 +sleep 500 run general/parser/first_last.sim -sleep 2000 +sleep 500 run general/parser/import_commit1.sim -sleep 2000 +sleep 500 run general/parser/import_commit2.sim -sleep 2000 +sleep 500 run general/parser/import_commit3.sim -sleep 2000 +sleep 500 #run general/parser/import_file.sim -sleep 2000 +sleep 500 run general/parser/insert_tb.sim -sleep 2000 +sleep 500 run general/parser/tags_dynamically_specifiy.sim -sleep 2000 +sleep 500 run general/parser/interp.sim -sleep 2000 +sleep 500 run general/parser/lastrow.sim -sleep 2000 +sleep 500 run general/parser/limit.sim -sleep 2000 +sleep 500 run general/parser/limit1.sim -sleep 2000 +sleep 500 run general/parser/limit1_tblocks100.sim -sleep 2000 +sleep 500 run general/parser/limit2.sim -sleep 2000 +sleep 500 run general/parser/mixed_blocks.sim -sleep 2000 +sleep 500 run general/parser/nchar.sim -sleep 2000 +sleep 500 run general/parser/null_char.sim -sleep 2000 +sleep 500 run general/parser/selectResNum.sim -sleep 2000 +sleep 500 run general/parser/select_across_vnodes.sim -sleep 2000 +sleep 500 run general/parser/select_from_cache_disk.sim -sleep 2000 +sleep 500 run general/parser/set_tag_vals.sim -sleep 2000 +sleep 500 run general/parser/single_row_in_tb.sim -sleep 2000 +sleep 500 run general/parser/slimit.sim -sleep 2000 +sleep 500 run general/parser/slimit1.sim -sleep 2000 +sleep 500 run general/parser/slimit_alter_tags.sim -sleep 2000 +sleep 500 run general/parser/tbnameIn.sim -sleep 2000 +sleep 500 run general/parser/slimit_alter_tags.sim # persistent failed -sleep 2000 +sleep 500 run general/parser/join.sim -sleep 2000 +sleep 500 run general/parser/join_multivnode.sim -sleep 2000 +sleep 500 run general/parser/projection_limit_offset.sim -sleep 2000 +sleep 500 run general/parser/select_with_tags.sim -sleep 2000 +sleep 500 run general/parser/groupby.sim -sleep 2000 +sleep 500 run general/parser/tags_filter.sim -sleep 2000 +sleep 500 run general/parser/topbot.sim -sleep 2000 +sleep 500 run general/parser/union.sim -sleep 2000 +sleep 500 run general/parser/constCol.sim -sleep 2000 +sleep 500 run general/parser/where.sim -sleep 2000 +sleep 500 run general/parser/timestamp.sim -sleep 2000 +sleep 500 run general/parser/sliding.sim -#sleep 2000 +#sleep 500 #run general/parser/repeatStream.sim -#sleep 2000 +#sleep 500 #run general/parser/stream_on_sys.sim -#sleep 2000 +#sleep 500 #run general/parser/stream.sim \ No newline at end of file diff --git a/tests/script/general/parser/timestamp.sim b/tests/script/general/parser/timestamp.sim index 67da0f0869..72966459d0 100644 --- a/tests/script/general/parser/timestamp.sim +++ b/tests/script/general/parser/timestamp.sim @@ -5,7 +5,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = ts_db @@ -59,10 +59,10 @@ run general/parser/timestamp_query.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 3000 +sleep 500 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 3000 +sleep 500 run general/parser/timestamp_query.sim diff --git a/tests/script/general/parser/timestamp_query.sim b/tests/script/general/parser/timestamp_query.sim index 783c03602b..056e8bba6b 100644 --- a/tests/script/general/parser/timestamp_query.sim +++ b/tests/script/general/parser/timestamp_query.sim @@ -1,4 +1,4 @@ -sleep 3000 +sleep 500 sql connect $dbPrefix = ts_db diff --git a/tests/script/general/parser/topbot.sim b/tests/script/general/parser/topbot.sim index c2b41888d7..08e2f6ab00 100644 --- a/tests/script/general/parser/topbot.sim +++ b/tests/script/general/parser/topbot.sim @@ -5,7 +5,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 200 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = tb_db @@ -128,11 +128,11 @@ sql insert into test values(29999, 1)(70000, 2)(80000, 3) print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT -sleep 5000 +sleep 3000 system sh/exec.sh -n dnode1 -s start print ================== server restart completed sql connect -sleep 1000 +sleep 500 sql select count(*) from t1.test where ts>10000 and ts<90000 interval(5000a) if $rows != 3 then @@ -169,7 +169,7 @@ endw system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start sql connect -sleep 1000 +sleep 500 sql use db; $ts = 1000 @@ -221,7 +221,7 @@ sql insert into t2 values('2020-2-2 1:1:1', 1); system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start sql connect -sleep 1000 +sleep 500 sql use db sql select count(*), first(ts), last(ts) from t2 interval(1d); diff --git a/tests/script/general/parser/union.sim b/tests/script/general/parser/union.sim index 024b9c76ef..cb46ac6b0d 100644 --- a/tests/script/general/parser/union.sim +++ b/tests/script/general/parser/union.sim @@ -7,7 +7,7 @@ system sh/cfg.sh -n dnode1 -c rpcDebugFlag -v 135 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 1000 +sleep 500 sql connect $dbPrefix = union_db @@ -36,9 +36,16 @@ sql create table $mt (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 $i = 0 $t = 1578203484000 -while $i < $tbNum +$half = $tbNum / 2 + +while $i < $half $tb = $tbPrefix . $i + + $nextSuffix = $i + $half + $tb1 = $tbPrefix . $nextSuffix + sql create table $tb using $mt tags( $i ) + sql create table $tb1 using $mt tags( $nextSuffix ) $x = 0 while $x < $rowNum @@ -54,7 +61,7 @@ while $i < $tbNum $nchar = $nchar . ' $t1 = $t + $ms - sql insert into $tb values ($t1 , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) + sql insert into $tb values ($t1 , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) $tb1 values ($t1 , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) $x = $x + 1 endw @@ -96,7 +103,7 @@ while $i < $tbNum endw print sleep 1sec. -sleep 1000 +sleep 500 $i = 1 $tb = $tbPrefix . $i diff --git a/tests/script/general/parser/where.sim b/tests/script/general/parser/where.sim index 066fac43ad..8e17220b5b 100644 --- a/tests/script/general/parser/where.sim +++ b/tests/script/general/parser/where.sim @@ -5,7 +5,7 @@ system sh/cfg.sh -n dnode1 -c walLevel -v 0 system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 system sh/exec.sh -n dnode1 -s start -sleep 3000 +sleep 500 sql connect $dbPrefix = wh_db @@ -26,10 +26,17 @@ sql create database if not exists $db sql use $db sql create table $mt (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9)) TAGS(t1 int) +$half = $tbNum / 2 + $i = 0 -while $i < $tbNum +while $i < $half $tb = $tbPrefix . $i + + $nextSuffix = $i + $half + $tb1 = $tbPrefix . $nextSuffix + sql create table $tb using $mt tags( $i ) + sql create table $tb1 using $mt tags( $nextSuffix ) $x = 0 while $x < $rowNum @@ -42,7 +49,7 @@ while $i < $tbNum $binary = $binary . ' $nchar = 'nchar . $c $nchar = $nchar . ' - sql insert into $tb values ($ms , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) + sql insert into $tb values ($ms , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) $tb1 values ($ms , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) $x = $x + 1 endw diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index daf92679bd..64a6c871fc 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -277,6 +277,8 @@ cd ../../../debug; make ./test.sh -f unique/db/replica_part.sim ./test.sh -f unique/dnode/alternativeRole.sim +./test.sh -f unique/dnode/monitor.sim +./test.sh -f unique/dnode/monitor_bug.sim ./test.sh -f unique/dnode/simple.sim ./test.sh -f unique/dnode/balance1.sim ./test.sh -f unique/dnode/balance2.sim diff --git a/tests/script/unique/dnode/monitor.sim b/tests/script/unique/dnode/monitor.sim new file mode 100644 index 0000000000..1e5b0f6f56 --- /dev/null +++ b/tests/script/unique/dnode/monitor.sim @@ -0,0 +1,92 @@ +system sh/stop_dnodes.sh + +system sh/deploy.sh -n dnode1 -i 1 +system sh/deploy.sh -n dnode2 -i 2 + +system sh/cfg.sh -n dnode1 -c role -v 1 +system sh/cfg.sh -n dnode2 -c role -v 2 + +system sh/cfg.sh -n dnode1 -c wallevel -v 1 +system sh/cfg.sh -n dnode2 -c wallevel -v 1 + +system sh/cfg.sh -n dnode1 -c numOfMnodes -v 3 +system sh/cfg.sh -n dnode2 -c numOfMnodes -v 3 + +system sh/cfg.sh -n dnode1 -c minTablesPerVnode -v 10 +system sh/cfg.sh -n dnode2 -c minTablesPerVnode -v 10 +system sh/cfg.sh -n dnode1 -c maxTablesPerVnode -v 10 +system sh/cfg.sh -n dnode2 -c maxTablesPerVnode -v 10 + +system sh/cfg.sh -n dnode1 -c monitor -v 1 +system sh/cfg.sh -n dnode2 -c monitor -v 1 + +print ========== step1 +system sh/exec.sh -n dnode1 -s start +sql connect +sleep 5000 + +sql show dnodes +print dnode1 openVnodes $data3_1 +if $data2_1 != 0 then + return -1 +endi + +print ========== step2 +sql create dnode $hostname2 +system sh/exec.sh -n dnode2 -s start + +sleep 10000 +sql show dnodes +print dnode1 openVnodes $data2_1 +print dnode2 openVnodes $data2_2 +if $data2_1 != 0 then + return -1 +endi +if $data2_2 != 1 then + return -1 +endi + +print ========== step3 +sql show log.tables + +print $data00 +print $data10 +print $data20 +print $data30 +print $data40 +print $data50 + +if $rows != 5 then + return -1 +endi + +print ========== step4 +sql select * from log.dn1 +print $rows +$rows1 = $rows + +sleep 3000 +sql select * from log.dn1 +print $rows +$rows2 = $rows + +if $rows2 <= $rows1 then + return -1 +endi + +print ========== step5 +sql select * from log.dn2 +print $rows +$rows1 = $rows + +sleep 3000 +sql select * from log.dn2 +print $rows +$rows2 = $rows + +if $rows2 <= $rows1 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT +system sh/exec.sh -n dnode2 -s stop -x SIGINT diff --git a/tests/script/unique/dnode/monitor_bug.sim b/tests/script/unique/dnode/monitor_bug.sim index 519aae6ca9..3169c7cdba 100644 --- a/tests/script/unique/dnode/monitor_bug.sim +++ b/tests/script/unique/dnode/monitor_bug.sim @@ -18,8 +18,8 @@ sql connect sleep 5000 sql show dnodes -print dnode1 openVnodes $data3_1 -if $data3_1 != 3 then +print dnode1 openVnodes $data2_1 +if $data2_1 != 1 then return -1 endi @@ -31,22 +31,21 @@ $x = 0 show2: $x = $x + 1 sleep 2000 - if $x == 30 then + if $x == 10 then return -1 endi sql show dnodes -print dnode1 openVnodes $data3_1 -print dnode2 openVnodes $data3_2 -if $data3_1 != 4 then +print dnode1 openVnodes $data2_1 +print dnode2 openVnodes $data2_2 +if $data2_1 != 0 then goto show2 endi -if $data3_2 != 3 then +if $data2_2 != 1 then goto show2 endi print ========== step3 -sleep 3000 sql show log.tables print $data00 @@ -56,6 +55,23 @@ print $data30 print $data40 print $data50 -if $rows != 5 then +if $rows != 4 then return -1 endi + +print ========== step4 +sql select * from log.dn1 +print $rows +$rows1 = $rows + +sleep 3000 +sql select * from log.dn1 +print $rows +$rows2 = $rows + +if $rows2 <= $rows1 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT +system sh/exec.sh -n dnode2 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/test-all.sh b/tests/test-all.sh index 214360f3b8..ff47cbfd71 100755 --- a/tests/test-all.sh +++ b/tests/test-all.sh @@ -16,6 +16,10 @@ function runSimCaseOneByOne { ./test.sh -f $case > /dev/null 2>&1 && \ echo -e "${GREEN}$case success${NC}" | tee -a out.log || \ echo -e "${RED}$case failed${NC}" | tee -a out.log + out_log=`tail -1 out.log ` + if [[ $out_log =~ 'failed' ]];then + exit 8 + fi end_time=`date +%s` echo execution time of $case was `expr $end_time - $start_time`s. | tee -a out.log fi @@ -37,6 +41,10 @@ function runPyCaseOneByOne { echo -e "${GREEN}$case success${NC}" | tee -a pytest-out.log || \ echo -e "${RED}$case failed${NC}" | tee -a pytest-out.log end_time=`date +%s` + out_log=`tail -1 pytest-out.log ` + if [[ $out_log =~ 'failed' ]];then + exit 8 + fi echo execution time of $case was `expr $end_time - $start_time`s. | tee -a pytest-out.log else $line > /dev/null 2>&1