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/cmake/version.inc b/cmake/version.inc index 741f76da43..2f0ec81aea 100644 --- a/cmake/version.inc +++ b/cmake/version.inc @@ -4,7 +4,7 @@ PROJECT(TDengine) IF (DEFINED VERNUMBER) SET(TD_VER_NUMBER ${VERNUMBER}) ELSE () - SET(TD_VER_NUMBER "2.0.7.0") + SET(TD_VER_NUMBER "2.0.8.0") ENDIF () IF (DEFINED VERCOMPATIBLE) 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/snap/snapcraft.yaml b/snap/snapcraft.yaml index 1738ff7ec8..059c0650c2 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,6 +1,6 @@ name: tdengine base: core18 -version: '2.0.7.0' +version: '2.0.8.0' icon: snap/gui/t-dengine.svg summary: an open-source big data platform designed and optimized for IoT. description: | @@ -72,7 +72,7 @@ parts: - usr/bin/taosd - usr/bin/taos - usr/bin/taosdemo - - usr/lib/libtaos.so.2.0.6.0 + - usr/lib/libtaos.so.2.0.8.0 - usr/lib/libtaos.so.1 - usr/lib/libtaos.so 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/dnodeEps.c b/src/dnode/src/dnodeEps.c index 9c90c39181..83f294e05e 100644 --- a/src/dnode/src/dnodeEps.c +++ b/src/dnode/src/dnodeEps.c @@ -33,7 +33,7 @@ static void dnodePrintEps(SDnodeEps *eps); int32_t dnodeInitEps() { pthread_mutex_init(&tsEpsMutex, NULL); - tsEpsHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, true); + tsEpsHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); dnodeResetEps(NULL); int32_t ret = dnodeReadEps(); if (ret == 0) { 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..77a3b36e73 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 { @@ -64,33 +64,32 @@ typedef struct { if name is provided(name[0] is not zero), get the named file at the specified index. If not there, return zero. If it is there, set the size to file size, and return file magic number. Index shall not be updated. */ -typedef uint32_t (*FGetFileInfo)(void *ahandle, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion); +typedef uint32_t (*FGetFileInfo)(int32_t vgId, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion); // get the wal file from index or after // return value, -1: error, 1:more wal files, 0:last WAL. if name[0]==0, no WAL file -typedef int32_t (*FGetWalInfo)(void *ahandle, char *fileName, int64_t *fileId); +typedef int32_t (*FGetWalInfo)(int32_t vgId, char *fileName, int64_t *fileId); // when a forward pkt is received, call this to handle data -typedef int32_t (*FWriteToCache)(void *ahandle, void *pHead, int32_t qtype, void *pMsg); +typedef int32_t (*FWriteToCache)(int32_t vgId, void *pHead, int32_t qtype, void *pMsg); // when forward is confirmed by peer, master call this API to notify app -typedef void (*FConfirmForward)(void *ahandle, void *mhandle, int32_t code); +typedef void (*FConfirmForward)(int32_t vgId, void *mhandle, int32_t code); // when role is changed, call this to notify app -typedef void (*FNotifyRole)(void *ahandle, int8_t role); +typedef void (*FNotifyRole)(int32_t vgId, int8_t role); // if a number of retrieving data failed, call this to start flow control -typedef void (*FNotifyFlowCtrl)(void *ahandle, int32_t mseconds); +typedef void (*FNotifyFlowCtrl)(int32_t vgId, int32_t mseconds); // when data file is synced successfully, notity app -typedef int32_t (*FNotifyFileSynced)(void *ahandle, uint64_t fversion); +typedef int32_t (*FNotifyFileSynced)(int32_t vgId, uint64_t fversion); typedef struct { int32_t vgId; // vgroup ID uint64_t version; // initial version SSyncCfg syncCfg; // configuration from mgmt - char path[128]; // path to the file - void * ahandle; // handle provided by APP + char path[TSDB_FILENAME_LEN]; // path to the file FGetFileInfo getFileInfo; FGetWalInfo getWalInfo; FWriteToCache writeToCache; 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..36e1a1eb2b 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(int32_t vgId, 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); + if (syncGetNodesRole(tsSdbMgmt.sync, &roles) != 0) return; - 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); } } @@ -232,93 +228,80 @@ void sdbUpdateMnodeRoles() { mnodeUpdateMnodeEpSet(); } -static uint32_t sdbGetFileInfo(void *ahandle, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion) { +static uint32_t sdbGetFileInfo(int32_t vgId, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion) { sdbUpdateMnodeRoles(); return 0; } -static int32_t sdbGetWalInfo(void *ahandle, char *fileName, int64_t *fileId) { - return walGetWalFile(tsSdbObj.wal, fileName, fileId); +static int32_t sdbGetWalInfo(int32_t vgId, char *fileName, int64_t *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)); +static void sdbNotifyRole(int32_t vgId, int8_t 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(int32_t vgId, 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}; @@ -386,26 +370,26 @@ void sdbUpdateSync(void *pMnodes) { syncInfo.version = sdbGetVersion(); syncInfo.syncCfg = syncCfg; sprintf(syncInfo.path, "%s", tsMnodeDir); - 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 +400,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 +471,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 +486,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 +495,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 +542,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 +777,7 @@ void *sdbFetchRow(void *handle, void *pNode, void **ppRow) { } *ppRow = *ppMetaRow; - sdbIncRef(handle, *ppMetaRow); + sdbIncRef(pTable, *ppMetaRow); return pIter; } @@ -899,28 +794,28 @@ 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) { hashFp = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); } - pTable->iHandle = taosHashInit(pTable->hashSessions, hashFp, true, true); + pTable->iHandle = taosHashInit(pTable->hashSessions, hashFp, true, HASH_ENTRY_LOCK); - tsSdbObj.numOfTables++; - tsSdbObj.tableList[pTable->tableId] = pTable; + tsSdbMgmt.numOfTables++; + tsSdbMgmt.tableList[pTable->id] = pTable; return pTable; } @@ -928,87 +823,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 +912,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 +922,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(int32_t vgId, 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(1, 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..d0a5402986 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); @@ -394,7 +394,7 @@ static void mnodeAddTableIntoStable(SSTableObj *pStable, SCTableObj *pCtable) { atomic_add_fetch_32(&pStable->numOfTables, 1); if (pStable->vgHash == NULL) { - pStable->vgHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, false); + pStable->vgHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); } if (pStable->vgHash != NULL) { @@ -413,7 +413,7 @@ static void mnodeRemoveTableFromStable(SSTableObj *pStable, SCTableObj *pCtable) SVgObj *pVgroup = mnodeGetVgroup(pCtable->vgId); if (pVgroup == NULL) { - taosHashRemove(pStable->vgHash, (char *)&pCtable->vgId, sizeof(pCtable->vgId)); + taosHashRemove(pStable->vgHash, &pCtable->vgId, sizeof(pCtable->vgId)); mDebug("table:%s, vgId:%d is remove from stable vgList, sizeOfVgList:%d", pStable->info.tableId, pCtable->vgId, (int32_t)taosHashGetSize(pStable->vgHash)); } @@ -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 2645cff678..c5ba551f20 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..7dbb1985d4 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,29 +150,29 @@ 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; + SSyncPeer * peerInfo[TAOS_SYNC_MAX_REPLICA + 1]; // extra one for arbitrator + SSyncPeer * pMaster; SRecvBuffer *pRecv; - SSyncFwds *pSyncFwds; // saved forward info if quorum >1 - void *pFwdTimer; - FGetFileInfo getFileInfo; - FGetWalInfo getWalInfo; - FWriteToCache writeToCache; - FConfirmForward confirmForward; - FNotifyRole notifyRole; - FNotifyFlowCtrl notifyFlowCtrl; + SSyncFwds * pSyncFwds; // saved forward info if quorum >1 + void * pFwdTimer; + void * pRoleTimer; + FGetFileInfo getFileInfo; + FGetWalInfo getWalInfo; + FWriteToCache writeToCache; + FConfirmForward confirmForward; + FNotifyRole notifyRole; + FNotifyFlowCtrl notifyFlowCtrl; FNotifyFileSynced notifyFileSynced; - pthread_mutex_t mutex; + pthread_mutex_t mutex; } SSyncNode; // sync module global extern int32_t tsSyncNum; extern char tsNodeFqdn[TSDB_FQDN_LEN]; +extern char * syncStatus[]; void *syncRetrieveData(void *param); void *syncRestoreData(void *param); diff --git a/src/sync/src/syncMain.c b/src/sync/src/syncMain.c index 6ff04aad64..8d3997a5d6 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,8 +73,42 @@ char* syncRole[] = { "master" }; +char *syncStatus[] = { + "init", + "start", + "file", + "cache", + "invalid" +}; + +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; + SPoolInfo info = {0}; info.numOfThreads = tsSyncTcpThreads; info.serverIp = 0; @@ -98,7 +132,7 @@ int32_t syncInit() { return -1; } - tsVgIdHash = taosHashInit(TSDB_MIN_VNODES, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, true); + tsVgIdHash = taosHashInit(TSDB_MIN_VNODES, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); if (tsVgIdHash == NULL) { sError("failed to init tsVgIdHash"); taosTmrCleanUp(tsSyncTmrCtrl); @@ -145,7 +179,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); @@ -155,7 +189,6 @@ int64_t syncStart(const SSyncInfo *pInfo) { tstrncpy(pNode->path, pInfo->path, sizeof(pNode->path)); pthread_mutex_init(&pNode->mutex, NULL); - pNode->ahandle = pInfo->ahandle; pNode->getFileInfo = pInfo->getFileInfo; pNode->getWalInfo = pInfo->getWalInfo; pNode->writeToCache = pInfo->writeToCache; @@ -176,18 +209,18 @@ int64_t syncStart(const SSyncInfo *pInfo) { return -1; } - for (int32_t i = 0; i < pCfg->replica; ++i) { - 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); + for (int32_t index = 0; index < pCfg->replica; ++index) { + const SNodeInfo *pNodeInfo = pCfg->nodeInfo + index; + pNode->peerInfo[index] = syncAddPeer(pNode, pNodeInfo); + if (pNode->peerInfo[index] == NULL) { + 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); } if ((strcmp(pNodeInfo->nodeFqdn, tsNodeFqdn) == 0) && (pNodeInfo->nodePort == tsSyncPort)) { - pNode->selfIndex = i; + pNode->selfIndex = index; } } @@ -211,18 +244,25 @@ 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; } syncAddArbitrator(pNode); - taosHashPut(tsVgIdHash, (const char *)&pNode->vgId, sizeof(int32_t), (char *)(&pNode), sizeof(SSyncNode *)); + taosHashPut(tsVgIdHash, &pNode->vgId, sizeof(int32_t), &pNode, sizeof(SSyncNode *)); if (pNode->notifyRole) { - (*pNode->notifyRole)(pNode->ahandle, nodeRole); + (*pNode->notifyRole)(pNode->vgId, nodeRole); } return pNode->rid; @@ -236,20 +276,21 @@ void syncStop(int64_t rid) { sInfo("vgId:%d, cleanup sync", pNode->vgId); - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); - if (tsVgIdHash) taosHashRemove(tsVgIdHash, (const char *)&pNode->vgId, sizeof(int32_t)); + if (tsVgIdHash) taosHashRemove(tsVgIdHash, &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]; + for (int32_t index = 0; index < pNode->replica; ++index) { + pPeer = pNode->peerInfo[index]; if (pPeer) syncRemovePeer(pPeer); } pPeer = pNode->peerInfo[TAOS_SYNC_MAX_REPLICA]; if (pPeer) syncRemovePeer(pPeer); - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); taosReleaseRef(tsSyncRefId, rid); taosRemoveRef(tsSyncRefId, rid); @@ -264,7 +305,7 @@ int32_t syncReconfig(int64_t rid, const SSyncCfg *pNewCfg) { sInfo("vgId:%d, reconfig, role:%s replica:%d old:%d", pNode->vgId, syncRole[nodeRole], pNewCfg->replica, pNode->replica); - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); for (i = 0; i < pNode->replica; ++i) { for (j = 0; j < pNewCfg->replica; ++j) { @@ -314,17 +355,15 @@ int32_t syncReconfig(int64_t rid, const SSyncCfg *pNewCfg) { if (pNewCfg->replica <= 1) { sInfo("vgId:%d, no peers are configured, work as master!", pNode->vgId); nodeRole = TAOS_SYNC_ROLE_MASTER; - (*pNode->notifyRole)(pNode->ahandle, nodeRole); + (*pNode->notifyRole)(pNode->vgId, nodeRole); } - pthread_mutex_unlock(&(pNode->mutex)); + 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 +395,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 +408,7 @@ void syncConfirmForward(int64_t rid, uint64_t version, int32_t code) { taosReleaseRef(tsSyncRefId, rid); } +#if 0 void syncRecover(int64_t rid) { SSyncPeer *pPeer; @@ -379,22 +419,23 @@ void syncRecover(int64_t rid) { // if take this node to unsync state, the whole system may not work nodeRole = TAOS_SYNC_ROLE_UNSYNCED; - (*pNode->notifyRole)(pNode->ahandle, nodeRole); + (*pNode->notifyRole)(pNode->vgId, nodeRole); nodeVersion = 0; - pthread_mutex_lock(&(pNode->mutex)); + 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); } } - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); taosReleaseRef(tsSyncRefId, rid); } +#endif int32_t syncGetNodesRole(int64_t rid, SNodesRole *pNodesRole) { SSyncNode *pNode = taosAcquireRef(tsSyncRefId, rid); @@ -449,10 +490,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); @@ -465,6 +506,8 @@ int32_t syncDecPeerRef(SSyncPeer *pPeer) { } static void syncClosePeerConn(SSyncPeer *pPeer) { + sDebug("%s, pfd:%d sfd:%d will be closed", pPeer->id, pPeer->peerFd, pPeer->syncFd); + taosTmrStopA(&pPeer->timer); taosClose(pPeer->syncFd); if (pPeer->peerFd >= 0) { @@ -510,7 +553,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); } @@ -519,22 +562,20 @@ static SSyncPeer *syncAddPeer(SSyncNode *pNode, const SNodeInfo *pInfo) { } void syncBroadcastStatus(SSyncNode *pNode) { - SSyncPeer *pPeer; - - for (int32_t i = 0; i < pNode->replica; ++i) { - if (i == pNode->selfIndex) continue; - pPeer = pNode->peerInfo[i]; - syncSendPeersStatusMsgToPeer(pPeer, 1); + for (int32_t index = 0; index < pNode->replica; ++index) { + if (index == pNode->selfIndex) continue; + SSyncPeer *pPeer = pNode->peerInfo[index]; + syncSendPeersStatusMsgToPeer(pPeer, 1, SYNC_STATUS_BROADCAST, syncGenTranId()); } } static void syncResetFlowCtrl(SSyncNode *pNode) { - for (int32_t i = 0; i < pNode->replica; ++i) { - pNode->peerInfo[i]->numOfRetrieves = 0; + for (int32_t index = 0; index < pNode->replica; ++index) { + pNode->peerInfo[index]->numOfRetrieves = 0; } if (pNode->notifyFlowCtrl) { - (*pNode->notifyFlowCtrl)(pNode->ahandle, 0); + (*pNode->notifyFlowCtrl)(pNode->vgId, 0); } } @@ -544,8 +585,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++; @@ -599,7 +638,7 @@ static void syncChooseMaster(SSyncNode *pNode) { } #endif syncResetFlowCtrl(pNode); - (*pNode->notifyRole)(pNode->ahandle, nodeRole); + (*pNode->notifyRole)(pNode->vgId, nodeRole); } else { pPeer = pNode->peerInfo[index]; sInfo("%s, it shall work as master", pPeer->id); @@ -611,11 +650,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,97 +669,99 @@ 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); + (*pNode->notifyRole)(pNode->vgId, nodeRole); + 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); + (*pNode->notifyRole)(pNode->vgId, nodeRole); } } } } - 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); + (*pNode->notifyRole)(pNode->vgId, 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); + (*pNode->notifyRole)(pNode->vgId, 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, cannot choose master since roles inconsistent", pNode->vgId); } } @@ -728,7 +769,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,14 +780,16 @@ 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, last sstatus:%s", pPeer->id, syncStatus[pPeer->sstatus]); syncClosePeerConn(pPeer); pPeer->sstatus = TAOS_SYNC_STATUS_INIT; + sDebug("%s, peer conn is restart and set sstatus:%s", pPeer->id, syncStatus[pPeer->sstatus]); 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); } } @@ -770,7 +814,7 @@ static void syncProcessSyncRequest(char *msg, SSyncPeer *pPeer) { } if (pPeer->sstatus != TAOS_SYNC_STATUS_INIT) { - sDebug("%s, sync is already started", pPeer->id); + sDebug("%s, sync is already started for sstatus:%s", pPeer->id, syncStatus[pPeer->sstatus]); return; // already started } @@ -784,11 +828,11 @@ 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; - sDebug("%s, thread is created to retrieve data", pPeer->id); + sDebug("%s, thread is created to retrieve data, set sstatus:%s", pPeer->id, syncStatus[pPeer->sstatus]); } } @@ -796,27 +840,28 @@ static void syncNotStarted(void *param, void *tmrId) { SSyncPeer *pPeer = param; SSyncNode *pNode = pPeer->pSyncNode; - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); pPeer->timer = NULL; - sInfo("%s, sync connection is still not up, restart", pPeer->id); + pPeer->sstatus = TAOS_SYNC_STATUS_INIT; + sInfo("%s, sync conn is still not up, restart and set sstatus:%s", pPeer->id, syncStatus[pPeer->sstatus]); syncRestartConnection(pPeer); - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); } static void syncTryRecoverFromMaster(void *param, void *tmrId) { SSyncPeer *pPeer = param; SSyncNode *pNode = pPeer->pSyncNode; - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); syncRecoverFromMaster(pPeer); - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); } static void syncRecoverFromMaster(SSyncPeer *pPeer) { SSyncNode *pNode = pPeer->pSyncNode; if (nodeSStatus != TAOS_SYNC_STATUS_INIT) { - sDebug("%s, sync is already started, status:%d", pPeer->id, nodeSStatus); + sDebug("%s, sync is already started since sstatus:%s", pPeer->id, syncStatus[nodeSStatus]); return; } @@ -840,11 +885,11 @@ 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; - sInfo("%s, sync-req is sent", pPeer->id); + sInfo("%s, sync-req is sent to peer, set sstatus:%s", pPeer->id, syncStatus[nodeSStatus]); } } @@ -854,7 +899,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,16 +918,17 @@ 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; - (*pNode->writeToCache)(pNode->ahandle, pHead, TAOS_QTYPE_FWD, NULL); + (*pNode->writeToCache)(pNode->vgId, pHead, TAOS_QTYPE_FWD, NULL); } else { if (nodeSStatus != TAOS_SYNC_STATUS_INIT) { syncSaveIntoBuffer(pPeer, pHead); } else { - sError("%s, forward discarded, hver:%" PRIu64, pPeer->id, pHead->version); + sError("%s, forward discarded since sstatus:%s, hver:%" PRIu64, pPeer->id, syncStatus[nodeSStatus], + pHead->version); } } } @@ -891,14 +937,15 @@ 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 is received, self:%s:%s:%" PRIu64 ", peer:%s:%" PRIu64 ", ack:%d tranId:%u type:%s pfd:%d", + pPeer->id, syncRole[nodeRole], syncStatus[nodeSStatus], nodeVersion, syncRole[pPeersStatus->role], + pPeersStatus->version, pPeersStatus->ack, pPeersStatus->tranId, statusType[pPeersStatus->type], pPeer->peerFd); pPeer->version = pPeersStatus->version; syncCheckRole(pPeer, pPeersStatus->peersStatus, pPeersStatus->role); if (pPeersStatus->ack) { - syncSendPeersStatusMsgToPeer(pPeer, 0); + syncSendPeersStatusMsgToPeer(pPeer, 0, pPeersStatus->type + 1, pPeersStatus->tranId); } } @@ -933,7 +980,7 @@ static int32_t syncProcessPeerMsg(void *param, void *buffer) { char * cont = buffer; SSyncNode *pNode = pPeer->pSyncNode; - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); int32_t code = syncReadPeerMsg(pPeer, &head, cont); @@ -949,14 +996,14 @@ static int32_t syncProcessPeerMsg(void *param, void *buffer) { } } - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); return code; } #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 +1018,24 @@ 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 is sent, self:%s:%s:%" PRIu64 ", peer:%s:%s:%" PRIu64 ", ack:%d tranId:%u type:%s pfd:%d", + pPeer->id, syncRole[nodeRole], syncStatus[nodeSStatus], nodeVersion, syncRole[pPeer->role], + syncStatus[pPeer->sstatus], pPeer->version, pPeersStatus->ack, pPeersStatus->tranId, + statusType[pPeersStatus->type], pPeer->peerFd); } else { sDebug("%s, failed to send status msg, restart", pPeer->id); syncRestartConnection(pPeer); } - - return; } static void syncSetupPeerConnection(SSyncPeer *pPeer) { @@ -995,13 +1044,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 +1063,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)) { - sDebug("%s, connection to peer server is setup", pPeer->id); + if (taosWriteMsg(connFd, &firstPkt, sizeof(firstPkt)) == sizeof(firstPkt)) { + sDebug("%s, connection to peer server is setup, pfd:%d sfd:%d", pPeer->id, connFd, pPeer->syncFd); 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); } } @@ -1031,12 +1080,12 @@ static void syncCheckPeerConnection(void *param, void *tmrId) { SSyncPeer *pPeer = param; SSyncNode *pNode = pPeer->pSyncNode; - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); sDebug("%s, check peer connection", pPeer->id); syncSetupPeerConnection(pPeer); - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); } static void syncCreateRestoreDataThread(SSyncPeer *pPeer) { @@ -1069,7 +1118,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; } @@ -1083,7 +1132,7 @@ static void syncProcessIncommingConnection(int32_t connFd, uint32_t sourceIp) { } SSyncNode *pNode = *ppNode; - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); SSyncPeer *pPeer; for (i = 0; i < pNode->replica; ++i) { @@ -1102,17 +1151,18 @@ static void syncProcessIncommingConnection(int32_t connFd, uint32_t sourceIp) { pPeer->syncFd = connFd; syncCreateRestoreDataThread(pPeer); } else { - sDebug("%s, TCP connection is already up, close one", pPeer->id); + sDebug("%s, TCP connection is already up(pfd:%d), close one, new pfd:%d sfd:%d", pPeer->id, pPeer->peerFd, connFd, + pPeer->syncFd); syncClosePeerConn(pPeer); pPeer->peerFd = connFd; 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()); } } - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); } static void syncProcessBrokenLink(void *param) { @@ -1121,22 +1171,22 @@ static void syncProcessBrokenLink(void *param) { SSyncNode *pNode = pPeer->pSyncNode; if (taosAcquireRef(tsSyncRefId, pNode->rid) == NULL) return; - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); - sDebug("%s, TCP link is broken(%s)", pPeer->id, strerror(errno)); + sDebug("%s, TCP link is broken since %s, pfd:%d sfd:%d", pPeer->id, strerror(errno), pPeer->peerFd, pPeer->syncFd); pPeer->peerFd = -1; if (syncDecPeerRef(pPeer) != 0) { syncRestartConnection(pPeer); } - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); taosReleaseRef(tsSyncRefId, pNode->rid); } static void syncSaveFwdInfo(SSyncNode *pNode, uint64_t version, void *mhandle) { SSyncFwds *pSyncFwds = pNode->pSyncFwds; - uint64_t time = taosGetTimestampMs(); + int64_t time = taosGetTimestampMs(); if (pSyncFwds->fwds >= tsMaxFwdInfo) { pSyncFwds->first = (pSyncFwds->first + 1) % tsMaxFwdInfo; @@ -1154,7 +1204,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 +1218,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,35 +1241,60 @@ 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); - (*pNode->confirmForward)(pNode->ahandle, pFwdInfo->mhandle, pFwdInfo->code); + sTrace("vgId:%d, forward is confirmed, hver:%" PRIu64 " code:%x", pNode->vgId, pFwdInfo->version, pFwdInfo->code); + (*pNode->confirmForward)(pNode->vgId, 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; + + sDebug("%s, check roles since self:%s sstatus:%s, peer:%s sstatus:%s", pPeer->id, syncRole[pPeer->role], + syncStatus[pPeer->sstatus], syncRole[nodeRole], syncStatus[nodeSStatus]); + syncSendPeersStatusMsgToPeer(pPeer, 1, SYNC_STATUS_CHECK_ROLE, syncGenTranId()); + break; + } + + 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)); + 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); } syncRemoveConfirmedFwdInfo(pNode); - pthread_mutex_unlock(&(pNode->mutex)); + 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); @@ -1232,9 +1307,8 @@ static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle int32_t fwdLen; int32_t code = 0; - 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) { @@ -1248,14 +1322,15 @@ static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle // always update version nodeVersion = pWalHead->version; - sTrace("vgId:%d, forward to peer, replica:%d role:%s qtype:%s hver:%" PRIu64, pNode->vgId, pNode->replica, - syncRole[nodeRole], qtypeStr[qtype], pWalHead->version); if (pNode->replica == 1 || nodeRole != TAOS_SYNC_ROLE_MASTER) return 0; // only pkt from RPC or CQ can be forwarded if (qtype != TAOS_QTYPE_RPC && qtype != TAOS_QTYPE_CQ) return 0; + sTrace("vgId:%d, forward to peer, replica:%d role:%s qtype:%s hver:%" PRIu64, pNode->vgId, pNode->replica, + syncRole[nodeRole], qtypeStr[qtype], pWalHead->version); + // a hacker way to improve the performance pSyncHead = (SSyncHead *)(((char *)pWalHead) - sizeof(SSyncHead)); pSyncHead->type = TAOS_SMSG_FORWARD; @@ -1263,7 +1338,7 @@ static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle pSyncHead->len = sizeof(SWalHead) + pWalHead->len; fwdLen = pSyncHead->len + sizeof(SSyncHead); // include the WAL and SYNC head - pthread_mutex_lock(&(pNode->mutex)); + pthread_mutex_lock(&pNode->mutex); for (int32_t i = 0; i < pNode->replica; ++i) { pPeer = pNode->peerInfo[i]; @@ -1275,16 +1350,16 @@ static int32_t syncForwardToPeerImpl(SSyncNode *pNode, void *data, void *mhandle code = 1; } - int32_t retLen = write(pPeer->peerFd, pSyncHead, fwdLen); + int32_t retLen = taosWriteMsg(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); } } - pthread_mutex_unlock(&(pNode->mutex)); + pthread_mutex_unlock(&pNode->mutex); return code; } diff --git a/src/sync/src/syncRestore.c b/src/sync/src/syncRestore.c index 5d7b9eac9b..2ca4b5424e 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" @@ -36,7 +38,7 @@ static void syncRemoveExtraFile(SSyncPeer *pPeer, int32_t sindex, int32_t eindex while (1) { name[0] = 0; - magic = (*pNode->getFileInfo)(pNode->ahandle, name, &index, eindex, &size, &fversion); + magic = (*pNode->getFileInfo)(pNode->vgId, name, &index, eindex, &size, &fversion); if (magic == 0) break; snprintf(fname, sizeof(fname), "%s/%s", pNode->path, name); @@ -63,7 +65,10 @@ static int32_t syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) { while (1) { // read file info int32_t ret = taosReadMsg(pPeer->syncFd, &(minfo), sizeof(minfo)); - if (ret < 0) break; + if (ret < 0) { + sError("%s, failed to read file info while restore file since %s", pPeer->id, strerror(errno)); + break; + } // if no more file from master, break; if (minfo.name[0] == 0 || minfo.magic == 0) { @@ -81,8 +86,8 @@ static int32_t syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) { // check the file info sinfo = minfo; - sDebug("%s, get file info:%s", pPeer->id, minfo.name); - sinfo.magic = (*pNode->getFileInfo)(pNode->ahandle, sinfo.name, &sinfo.index, TAOS_SYNC_MAX_INDEX, &sinfo.size, + sDebug("%s, get file:%s info size:%" PRId64, pPeer->id, minfo.name, minfo.size); + sinfo.magic = (*pNode->getFileInfo)(pNode->vgId, sinfo.name, &sinfo.index, TAOS_SYNC_MAX_INDEX, &sinfo.size, &sinfo.fversion); // if file not there or magic is not the same, file shall be synced @@ -90,8 +95,11 @@ static int32_t syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) { fileAck.sync = (sinfo.magic != minfo.magic || sinfo.name[0] == 0) ? 1 : 0; // send file ack - ret = taosWriteMsg(pPeer->syncFd, &(fileAck), sizeof(fileAck)); - if (ret < 0) break; + ret = taosWriteMsg(pPeer->syncFd, &fileAck, sizeof(fileAck)); + if (ret < 0) { + sError("%s, failed to write file:%s ack while restore file since %s", pPeer->id, minfo.name, strerror(errno)); + break; + } // if sync is not required, continue if (fileAck.sync == 0) { @@ -106,14 +114,17 @@ static int32_t syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) { int32_t dfd = open(name, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); if (dfd < 0) { - sError("%s, failed to open file:%s", pPeer->id, name); + sError("%s, failed to open file:%s while restore file since %s", pPeer->id, minfo.name, strerror(errno)); break; } ret = taosCopyFds(pPeer->syncFd, dfd, minfo.size); fsync(dfd); close(dfd); - if (ret < 0) break; + if (ret < 0) { + sError("%s, failed to copy file:%s while restore file since %s", pPeer->id, minfo.name, strerror(errno)); + break; + } fileChanged = true; sDebug("%s, %s is received, size:%" PRId64, pPeer->id, minfo.name, minfo.size); @@ -123,10 +134,11 @@ static int32_t syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) { // data file is changed, code shall be set to 1 *fversion = minfo.fversion; code = 1; + sDebug("%s, file changed while restore file", pPeer->id); } 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,25 +152,40 @@ 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)); - if (ret < 0) break; + if (ret < 0) { + sError("%s, failed to read walhead while restore wal since %s", pPeer->id, strerror(errno)); + break; + } if (pHead->len == 0) { + sDebug("%s, wal is synced over", pPeer->id); code = 0; break; } // wal sync over ret = taosReadMsg(pPeer->syncFd, pHead->cont, pHead->len); - if (ret < 0) break; + if (ret < 0) { + sError("%s, failed to read walcont, len:%d while restore wal since %s", pPeer->id, pHead->len, strerror(errno)); + break; + } - sDebug("%s, restore a record, qtype:wal hver:%" PRIu64, pPeer->id, pHead->version); - (*pNode->writeToCache)(pNode->ahandle, pHead, TAOS_QTYPE_WAL, NULL); + 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->vgId, 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); @@ -169,7 +196,7 @@ static char *syncProcessOneBufferedFwd(SSyncPeer *pPeer, char *offset) { SSyncNode *pNode = pPeer->pSyncNode; SWalHead * pHead = (SWalHead *)offset; - (*pNode->writeToCache)(pNode->ahandle, pHead, TAOS_QTYPE_FWD, NULL); + (*pNode->writeToCache)(pNode->vgId, pHead, TAOS_QTYPE_FWD, NULL); offset += pHead->len + sizeof(SWalHead); return offset; @@ -214,7 +241,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 @@ -257,7 +284,7 @@ static int32_t syncRestoreDataStepByStep(SSyncPeer *pPeer) { nodeSStatus = TAOS_SYNC_STATUS_FILE; uint64_t fversion = 0; - sDebug("%s, start to restore file", pPeer->id); + sDebug("%s, start to restore file, set sstatus:%s", pPeer->id, syncStatus[nodeSStatus]); int32_t code = syncRestoreFile(pPeer, &fversion); if (code < 0) { sError("%s, failed to restore file", pPeer->id); @@ -266,7 +293,7 @@ static int32_t syncRestoreDataStepByStep(SSyncPeer *pPeer) { // if code > 0, data file is changed, notify app, and pass the version if (code > 0 && pNode->notifyFileSynced) { - if ((*pNode->notifyFileSynced)(pNode->ahandle, fversion) < 0) { + if ((*pNode->notifyFileSynced)(pNode->vgId, fversion) < 0) { sError("%s, app not in ready state", pPeer->id); return -1; } @@ -281,7 +308,7 @@ static int32_t syncRestoreDataStepByStep(SSyncPeer *pPeer) { } nodeSStatus = TAOS_SYNC_STATUS_CACHE; - sDebug("%s, start to insert buffered points", pPeer->id); + sDebug("%s, start to insert buffered points, set sstatus:%s", pPeer->id, syncStatus[nodeSStatus]); if (syncProcessBufferedFwd(pPeer) < 0) { sError("%s, failed to insert buffered points", pPeer->id); return -1; @@ -291,16 +318,17 @@ static int32_t syncRestoreDataStepByStep(SSyncPeer *pPeer) { } void *syncRestoreData(void *param) { - SSyncPeer *pPeer = (SSyncPeer *)param; + SSyncPeer *pPeer = param; SSyncNode *pNode = pPeer->pSyncNode; taosBlockSIGPIPE(); __sync_fetch_and_add(&tsSyncNum, 1); - (*pNode->notifyRole)(pNode->ahandle, TAOS_SYNC_ROLE_SYNCING); + (*pNode->notifyRole)(pNode->vgId, 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); @@ -313,9 +341,11 @@ void *syncRestoreData(void *param) { } } - (*pNode->notifyRole)(pNode->ahandle, nodeRole); + (*pNode->notifyRole)(pNode->vgId, nodeRole); nodeSStatus = TAOS_SYNC_STATUS_INIT; + sInfo("%s, sync over, set sstatus:%s", pPeer->id, syncStatus[nodeSStatus]); + taosClose(pPeer->syncFd); syncCloseRecvBuffer(pNode); __sync_fetch_and_sub(&tsSyncNum, 1); diff --git a/src/sync/src/syncRetrieve.c b/src/sync/src/syncRetrieve.c index 21151f1199..58d09d080e 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; } @@ -110,13 +108,16 @@ static int32_t syncRetrieveFile(SSyncPeer *pPeer) { while (1) { // retrieve file info fileInfo.name[0] = 0; - fileInfo.magic = (*pNode->getFileInfo)(pNode->ahandle, fileInfo.name, &fileInfo.index, TAOS_SYNC_MAX_INDEX, + fileInfo.magic = (*pNode->getFileInfo)(pNode->vgId, fileInfo.name, &fileInfo.index, TAOS_SYNC_MAX_INDEX, &fileInfo.size, &fileInfo.fversion); // fileInfo.size = htonl(size); // send the file info int32_t ret = taosWriteMsg(pPeer->syncFd, &(fileInfo), sizeof(fileInfo)); - if (ret < 0) break; + if (ret < 0) { + sError("%s, failed to write file:%s info while retrieve file since %s", pPeer->id, fileInfo.name, strerror(errno)); + break; + } // if no file anymore, break if (fileInfo.magic == 0 || fileInfo.name[0] == 0) { @@ -126,8 +127,11 @@ static int32_t syncRetrieveFile(SSyncPeer *pPeer) { } // wait for the ack from peer - ret = taosReadMsg(pPeer->syncFd, &(fileAck), sizeof(fileAck)); - if (ret < 0) break; + ret = taosReadMsg(pPeer->syncFd, &fileAck, sizeof(fileAck)); + if (ret < 0) { + sError("%s, failed to read file:%s ack while retrieve file since %s", pPeer->id, fileInfo.name, strerror(errno)); + break; + } // set the peer sync version pPeer->sversion = fileInfo.fversion; @@ -136,7 +140,10 @@ static int32_t syncRetrieveFile(SSyncPeer *pPeer) { snprintf(name, sizeof(name), "%s/%s", pNode->path, fileInfo.name); // add the file into watch list - if (syncAddIntoWatchList(pPeer, name) < 0) break; + if (syncAddIntoWatchList(pPeer, name) < 0) { + sError("%s, failed to watch file:%s while retrieve file since %s", pPeer->id, fileInfo.name, strerror(errno)); + break; + } // if sync is not required, continue if (fileAck.sync == 0) { @@ -147,21 +154,30 @@ static int32_t syncRetrieveFile(SSyncPeer *pPeer) { // send the file to peer int32_t sfd = open(name, O_RDONLY); - if (sfd < 0) break; + if (sfd < 0) { + sError("%s, failed to open file:%s while retrieve file since %s", pPeer->id, fileInfo.name, strerror(errno)); + break; + } ret = taosSendFile(pPeer->syncFd, sfd, NULL, fileInfo.size); close(sfd); - if (ret < 0) break; + if (ret < 0) { + sError("%s, failed to send file:%s while retrieve file since %s", pPeer->id, fileInfo.name, strerror(errno)); + break; + } sDebug("%s, %s is sent, size:%" PRId64, pPeer->id, name, fileInfo.size); fileInfo.index++; // check if processed files are modified - if (syncAreFilesModified(pPeer) != 0) break; + if (syncAreFilesModified(pPeer) != 0) { + sInfo("%s, file:%s are modified while retrieve file since %s", pPeer->id, fileInfo.name, strerror(errno)); + break; + } } if (code < 0) { - sError("%s, failed to retrieve file(%s)", pPeer->id, strerror(errno)); + sError("%s, failed to retrieve file", pPeer->id); } return code; @@ -201,7 +217,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 +232,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 +243,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 +284,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; @@ -320,6 +336,7 @@ static int32_t syncProcessLastWal(SSyncPeer *pPeer, char *wname, int64_t index) if (((event & IN_MODIFY) == 0) || once) { if (fversion == 0) { pPeer->sstatus = TAOS_SYNC_STATUS_CACHE; // start to forward pkt + sDebug("%s, fversion is 0 then set sstatus:%s", pPeer->id, syncStatus[pPeer->sstatus]); fversion = nodeVersion; // must read data to fversion } } @@ -356,7 +373,7 @@ static int32_t syncProcessLastWal(SSyncPeer *pPeer, char *wname, int64_t index) index++; wname[0] = 0; - code = (*pNode->getWalInfo)(pNode->ahandle, wname, &index); + code = (*pNode->getWalInfo)(pNode->vgId, wname, &index); if (code < 0) break; if (wname[0] == 0) { code = 0; @@ -384,7 +401,7 @@ static int32_t syncRetrieveWal(SSyncPeer *pPeer) { while (1) { // retrieve wal info wname[0] = 0; - code = (*pNode->getWalInfo)(pNode->ahandle, wname, &index); + code = (*pNode->getWalInfo)(pNode->vgId, wname, &index); if (code < 0) break; // error if (wname[0] == 0) { // no wal file sDebug("%s, no wal file", pPeer->id); @@ -418,13 +435,14 @@ static int32_t syncRetrieveWal(SSyncPeer *pPeer) { } if (code == 0) { - sDebug("%s, wal retrieve is finished", pPeer->id); pPeer->sstatus = TAOS_SYNC_STATUS_CACHE; + sInfo("%s, wal retrieve is finished, set sstatus:%s", pPeer->id, syncStatus[pPeer->sstatus]); + 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; @@ -440,14 +458,14 @@ static int32_t syncRetrieveDataStepByStep(SSyncPeer *pPeer) { tstrncpy(firstPkt.fqdn, tsNodeFqdn, sizeof(firstPkt.fqdn)); firstPkt.port = tsSyncPort; - if (write(pPeer->syncFd, (char *)&firstPkt, sizeof(firstPkt)) < 0) { + if (taosWriteMsg(pPeer->syncFd, (char *)&firstPkt, sizeof(firstPkt)) < 0) { sError("%s, failed to send syncCmd", pPeer->id); return -1; } pPeer->sversion = 0; pPeer->sstatus = TAOS_SYNC_STATUS_FILE; - sDebug("%s, start to retrieve file", pPeer->id); + sInfo("%s, start to retrieve file, set sstatus:%s", pPeer->id, syncStatus[pPeer->sstatus]); if (syncRetrieveFile(pPeer) < 0) { sError("%s, failed to retrieve file", pPeer->id); return -1; @@ -456,7 +474,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 +496,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); @@ -489,10 +507,10 @@ void *syncRetrieveData(void *param) { // if file is changed 3 times continuously, start flow control pPeer->numOfRetrieves++; if (pPeer->numOfRetrieves >= 2 && pNode->notifyFlowCtrl) - (*pNode->notifyFlowCtrl)(pNode->ahandle, 4 << (pPeer->numOfRetrieves - 2)); + (*pNode->notifyFlowCtrl)(pNode->vgId, 4 << (pPeer->numOfRetrieves - 2)); } else { pPeer->numOfRetrieves = 0; - if (pNode->notifyFlowCtrl) (*pNode->notifyFlowCtrl)(pNode->ahandle, 0); + if (pNode->notifyFlowCtrl) (*pNode->notifyFlowCtrl)(pNode->vgId, 0); } pPeer->fileChanged = 0; 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/sync/test/syncServer.c b/src/sync/test/syncServer.c index 9dd3feb461..5a64a0a36a 100644 --- a/src/sync/test/syncServer.c +++ b/src/sync/test/syncServer.c @@ -70,7 +70,7 @@ int writeIntoWal(SWalHead *pHead) { return 0; } -void confirmForward(void *ahandle, void *mhandle, int32_t code) { +void confirmForward(int32_t vgId, void *mhandle, int32_t code) { SRpcMsg * pMsg = (SRpcMsg *)mhandle; SWalHead *pHead = (SWalHead *)(((char *)pMsg->pCont) - sizeof(SWalHead)); @@ -227,7 +227,7 @@ void processRequestMsg(SRpcMsg *pMsg, SRpcEpSet *pEpSet) { taosWriteQitem(qhandle, TAOS_QTYPE_RPC, pTemp); } -uint32_t getFileInfo(void *ahandle, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion) { +uint32_t getFileInfo(int32_t vgId, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion) { uint32_t magic; struct stat fstat; char aname[280]; @@ -254,7 +254,7 @@ uint32_t getFileInfo(void *ahandle, char *name, uint32_t *index, uint32_t eindex return magic; } -int getWalInfo(void *ahandle, char *name, int64_t *index) { +int getWalInfo(int32_t vgId, char *name, int64_t *index) { struct stat fstat; char aname[280]; @@ -272,7 +272,7 @@ int getWalInfo(void *ahandle, char *name, int64_t *index) { return 1; } -int writeToCache(void *ahandle, void *data, int type) { +int writeToCache(int32_t vgId, void *data, int type) { SWalHead *pHead = data; uDebug("pkt from peer is received, ver:%" PRIu64 " len:%d type:%d", pHead->version, pHead->len, type); @@ -285,9 +285,9 @@ int writeToCache(void *ahandle, void *data, int type) { return 0; } -void confirmFwd(void *ahandle, int64_t version) { return; } +void confirmFwd(int32_t vgId, int64_t version) { return; } -void notifyRole(void *ahandle, int8_t r) { +void notifyRole(int32_t vgId, int8_t r) { role = r; printf("current role:%s\n", syncRole[role]); } @@ -296,7 +296,6 @@ void initSync() { pCfg->replica = 1; pCfg->quorum = 1; syncInfo.vgId = 1; - syncInfo.ahandle = &syncInfo; syncInfo.getFileInfo = getFileInfo; syncInfo.getWalInfo = getWalInfo; syncInfo.writeToCache = writeToCache; diff --git a/src/util/src/tsocket.c b/src/util/src/tsocket.c index 1be79b7bbd..2543c81708 100644 --- a/src/util/src/tsocket.c +++ b/src/util/src/tsocket.c @@ -107,7 +107,7 @@ int32_t taosWriteMsg(SOCKET fd, void *buf, int32_t nbytes) { while (nleft > 0) { nwritten = (int32_t)taosWriteSocket(fd, (char *)ptr, (size_t)nleft); if (nwritten <= 0) { - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) + if (errno == EINTR /* || errno == EAGAIN || errno == EWOULDBLOCK */) continue; else return -1; @@ -133,7 +133,7 @@ int32_t taosReadMsg(SOCKET fd, void *buf, int32_t nbytes) { if (nread == 0) { break; } else if (nread < 0) { - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + if (errno == EINTR/* || errno == EAGAIN || errno == EWOULDBLOCK*/) { continue; } else { return -1; 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 7447acc488..b94fea52bd 100644 --- a/src/vnode/src/vnodeMain.c +++ b/src/vnode/src/vnodeMain.c @@ -30,19 +30,21 @@ static SHashObj*tsVnodesHash; static void vnodeCleanUp(SVnodeObj *pVnode); -static int vnodeProcessTsdbStatus(void *arg, int status, int eno); -static uint32_t vnodeGetFileInfo(void *ahandle, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion); -static int vnodeGetWalInfo(void *ahandle, char *fileName, int64_t *fileId); -static void vnodeNotifyRole(void *ahandle, int8_t role); -static void vnodeCtrlFlow(void *handle, int32_t mseconds); -static int vnodeNotifyFileSynced(void *ahandle, uint64_t fversion); +static int32_t vnodeProcessTsdbStatus(void *arg, int32_t status, int32_t eno); +static uint32_t vnodeGetFileInfo(int32_t vgId, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion); +static int32_t vnodeGetWalInfo(int32_t vgId, char *fileName, int64_t *fileId); +static void vnodeNotifyRole(int32_t vgId, int8_t role); +static void vnodeCtrlFlow(int32_t vgId, int32_t mseconds); +static int32_t vnodeNotifyFileSynced(int32_t vgId, uint64_t fversion); +static void vnodeConfirmForard(int32_t vgId, void *wparam, int32_t code); +static int32_t vnodeWriteToCache(int32_t vgId, void *wparam, int32_t qtype, void *rparam); #ifndef _SYNC int64_t syncStart(const SSyncInfo *info) { return NULL; } -int32_t syncForwardToPeer(int64_t rid, void *pHead, void *mhandle, int qtype) { return 0; } +int32_t syncForwardToPeer(int64_t rid, void *pHead, void *mhandle, int32_t qtype) { return 0; } void syncStop(int64_t rid) {} -int32_t syncReconfig(int64_t rid, const SSyncCfg * cfg) { return 0; } -int syncGetNodesRole(int64_t rid, SNodesRole * cfg) { return 0; } +int32_t syncReconfig(int64_t rid, const SSyncCfg *cfg) { return 0; } +int32_t syncGetNodesRole(int64_t rid, SNodesRole *cfg) { return 0; } void syncConfirmForward(int64_t rid, uint64_t version, int32_t code) {} #endif @@ -55,13 +57,13 @@ char* vnodeStatus[] = { }; int32_t vnodeInitResources() { - int code = syncInit(); + int32_t code = syncInit(); if (code != 0) return code; vnodeInitWriteFp(); vnodeInitReadFp(); - tsVnodesHash = taosHashInit(TSDB_MIN_VNODES, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, true); + tsVnodesHash = taosHashInit(TSDB_MIN_VNODES, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); if (tsVnodesHash == NULL) { vError("failed to init vnode list"); return TSDB_CODE_VND_OUT_OF_MEMORY; @@ -173,8 +175,8 @@ int32_t vnodeDrop(int32_t vgId) { return TSDB_CODE_SUCCESS; } -int32_t vnodeAlter(void *param, SCreateVnodeMsg *pVnodeCfg) { - SVnodeObj *pVnode = param; +int32_t vnodeAlter(void *vparam, SCreateVnodeMsg *pVnodeCfg) { + SVnodeObj *pVnode = vparam; // vnode in non-ready state and still needs to return success instead of TSDB_CODE_VND_INVALID_STATUS // cfgVersion can be corrected by status msg @@ -325,16 +327,28 @@ int32_t vnodeOpen(int32_t vnode, char *rootDir) { walRemoveAllOldFiles(pVnode->wal); walRenew(pVnode->wal); + pVnode->qMgmt = qOpenQueryMgmt(pVnode->vgId); + if (pVnode->qMgmt == NULL) { + vnodeCleanUp(pVnode); + return terrno; + } + + pVnode->events = NULL; + + vDebug("vgId:%d, vnode is opened in %s, pVnode:%p", pVnode->vgId, rootDir, pVnode); + tsdbIncCommitRef(pVnode->vgId); + + taosHashPut(tsVnodesHash, &pVnode->vgId, sizeof(int32_t), &pVnode, sizeof(SVnodeObj *)); + SSyncInfo syncInfo; syncInfo.vgId = pVnode->vgId; syncInfo.version = pVnode->version; syncInfo.syncCfg = pVnode->syncCfg; sprintf(syncInfo.path, "%s", rootDir); - syncInfo.ahandle = pVnode; syncInfo.getWalInfo = vnodeGetWalInfo; syncInfo.getFileInfo = vnodeGetFileInfo; - syncInfo.writeToCache = vnodeWriteToWQueue; - syncInfo.confirmForward = dnodeSendRpcVWriteRsp; + syncInfo.writeToCache = vnodeWriteToCache; + syncInfo.confirmForward = vnodeConfirmForard; syncInfo.notifyRole = vnodeNotifyRole; syncInfo.notifyFlowCtrl = vnodeCtrlFlow; syncInfo.notifyFileSynced = vnodeNotifyFileSynced; @@ -346,24 +360,13 @@ int32_t vnodeOpen(int32_t vnode, char *rootDir) { if (pVnode->sync <= 0) { vError("vgId:%d, failed to open sync module, replica:%d reason:%s", pVnode->vgId, pVnode->syncCfg.replica, tstrerror(terrno)); + vnodeRelease(pVnode); vnodeCleanUp(pVnode); return terrno; } -#endif +#endif - pVnode->qMgmt = qOpenQueryMgmt(pVnode->vgId); - if (pVnode->qMgmt == NULL) { - vnodeCleanUp(pVnode); - return terrno; - } - - pVnode->events = NULL; pVnode->status = TAOS_VN_STATUS_READY; - vDebug("vgId:%d, vnode is opened in %s, pVnode:%p", pVnode->vgId, rootDir, pVnode); - - tsdbIncCommitRef(pVnode->vgId); - taosHashPut(tsVnodesHash, (const char *)&pVnode->vgId, sizeof(int32_t), (char *)(&pVnode), sizeof(SVnodeObj *)); - return TSDB_CODE_SUCCESS; } @@ -378,9 +381,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; @@ -389,7 +392,7 @@ void vnodeRelease(void *pVnodeRaw) { assert(refCount >= 0); if (refCount > 0) { - if (pVnode->status == TAOS_VN_STATUS_RESET && refCount == 2) { + if (pVnode->status == TAOS_VN_STATUS_RESET && refCount <= 3) { tsem_post(&pVnode->sem); } return; @@ -567,11 +570,11 @@ void vnodeSetAccess(SVgroupAccess *pAccess, int32_t numOfVnodes) { static void vnodeCleanUp(SVnodeObj *pVnode) { // remove from hash, so new messages wont be consumed - taosHashRemove(tsVnodesHash, (const char *)&pVnode->vgId, sizeof(int32_t)); + taosHashRemove(tsVnodesHash, &pVnode->vgId, sizeof(int32_t)); if (pVnode->status != TAOS_VN_STATUS_INIT) { // it may be in updateing or reset state, then it shall wait - int i = 0; + int32_t i = 0; while (atomic_val_compare_exchange_8(&pVnode->status, TAOS_VN_STATUS_READY, TAOS_VN_STATUS_CLOSING) != TAOS_VN_STATUS_READY) { if (++i % 1000 == 0) { @@ -595,7 +598,7 @@ static void vnodeCleanUp(SVnodeObj *pVnode) { } // TODO: this is a simple implement -static int vnodeProcessTsdbStatus(void *arg, int status, int eno) { +static int32_t vnodeProcessTsdbStatus(void *arg, int32_t status, int32_t eno) { SVnodeObj *pVnode = arg; if (eno != TSDB_CODE_SUCCESS) { @@ -608,56 +611,88 @@ static int vnodeProcessTsdbStatus(void *arg, int status, int eno) { if (status == TSDB_STATUS_COMMIT_START) { pVnode->fversion = pVnode->version; vDebug("vgId:%d, start commit, fver:%" PRIu64 " vver:%" PRIu64, pVnode->vgId, pVnode->fversion, pVnode->version); - if (pVnode->status == TAOS_VN_STATUS_INIT) { - return 0; - } else { + if (pVnode->status != TAOS_VN_STATUS_INIT) { return walRenew(pVnode->wal); } + return 0; } if (status == TSDB_STATUS_COMMIT_OVER) { vDebug("vgId:%d, commit over, fver:%" PRIu64 " vver:%" PRIu64, pVnode->vgId, pVnode->fversion, pVnode->version); pVnode->isFull = 0; - walRemoveOneOldFile(pVnode->wal); + if (pVnode->status != TAOS_VN_STATUS_INIT) { + walRemoveOneOldFile(pVnode->wal); + } return vnodeSaveVersion(pVnode); } return 0; } -static uint32_t vnodeGetFileInfo(void *ahandle, char *name, uint32_t *index, uint32_t eindex, int64_t *size, +static uint32_t vnodeGetFileInfo(int32_t vgId, char *name, uint32_t *index, uint32_t eindex, int64_t *size, uint64_t *fversion) { - SVnodeObj *pVnode = ahandle; + SVnodeObj *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vError("vgId:%d, vnode not found while get file info", vgId); + return 0; + } + *fversion = pVnode->fversion; - return tsdbGetFileInfo(pVnode->tsdb, name, index, eindex, size); + uint32_t ret = tsdbGetFileInfo(pVnode->tsdb, name, index, eindex, size); + + vnodeRelease(pVnode); + return ret; } -static int vnodeGetWalInfo(void *ahandle, char *fileName, int64_t *fileId) { - SVnodeObj *pVnode = ahandle; - return walGetWalFile(pVnode->wal, fileName, fileId); +static int32_t vnodeGetWalInfo(int32_t vgId, char *fileName, int64_t *fileId) { + SVnodeObj *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vError("vgId:%d, vnode not found while get wal info", vgId); + return -1; + } + + int32_t code = walGetWalFile(pVnode->wal, fileName, fileId); + + vnodeRelease(pVnode); + return code; } -static void vnodeNotifyRole(void *ahandle, int8_t role) { - SVnodeObj *pVnode = ahandle; +static void vnodeNotifyRole(int32_t vgId, int8_t role) { + SVnodeObj *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vError("vgId:%d, vnode not found while notify role", vgId); + return; + } + vInfo("vgId:%d, sync role changed from %s to %s", pVnode->vgId, syncRole[pVnode->role], syncRole[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); } - pVnode->delay = mseconds; + + vnodeRelease(pVnode); } -static int vnodeResetTsdb(SVnodeObj *pVnode) { +static void vnodeCtrlFlow(int32_t vgId, int32_t mseconds) { + SVnodeObj *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vError("vgId:%d, vnode not found while ctrl flow", vgId); + return; + } + + if (pVnode->delayMs != mseconds) { + pVnode->delayMs = mseconds; + vDebug("vgId:%d, sync flow control, mseconds:%d", pVnode->vgId, mseconds); + } + + vnodeRelease(pVnode); +} + +static int32_t vnodeResetTsdb(SVnodeObj *pVnode) { char rootDir[128] = "\0"; sprintf(rootDir, "%s/tsdb", pVnode->rootDir); @@ -667,11 +702,11 @@ static int vnodeResetTsdb(SVnodeObj *pVnode) { void *tsdb = pVnode->tsdb; pVnode->tsdb = NULL; - + // acquire vnode int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1); - if (refCount > 2) { + if (refCount > 3) { tsem_wait(&pVnode->sem); } @@ -691,14 +726,44 @@ static int vnodeResetTsdb(SVnodeObj *pVnode) { return 0; } -static int vnodeNotifyFileSynced(void *ahandle, uint64_t fversion) { - SVnodeObj *pVnode = ahandle; +static int32_t vnodeNotifyFileSynced(int32_t vgId, uint64_t fversion) { + SVnodeObj *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vError("vgId:%d, vnode not found while notify file synced", vgId); + return 0; + } pVnode->fversion = fversion; pVnode->version = fversion; vnodeSaveVersion(pVnode); - vDebug("vgId:%d, data file is synced, fver:%" PRIu64 " vver:%" PRIu64, pVnode->vgId, pVnode->fversion, - pVnode->version); - return vnodeResetTsdb(pVnode); + vDebug("vgId:%d, data file is synced, fver:%" PRIu64 " vver:%" PRIu64, vgId, fversion, fversion); + int32_t code = vnodeResetTsdb(pVnode); + + vnodeRelease(pVnode); + return code; +} + +void vnodeConfirmForard(int32_t vgId, void *wparam, int32_t code) { + void *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vError("vgId:%d, vnode not found while confirm forward", vgId); + return; + } + + dnodeSendRpcVWriteRsp(pVnode, wparam, code); + vnodeRelease(pVnode); +} + +static int32_t vnodeWriteToCache(int32_t vgId, void *wparam, int32_t qtype, void *rparam) { + SVnodeObj *pVnode = vnodeAcquire(vgId); + if (pVnode == NULL) { + vError("vgId:%d, vnode not found while write to cache", vgId); + return TSDB_CODE_VND_INVALID_VGROUP_ID; + } + + int32_t code = vnodeWriteToWQueue(pVnode, wparam, qtype, rparam); + + vnodeRelease(pVnode); + return code; } diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 4cc8819bcb..5ef79cfbf0 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,7 @@ 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(SVnodeObj *pVnode) { 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 +75,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 +117,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..a0227d84ba 100644 --- a/src/vnode/src/vnodeWrite.c +++ b/src/vnode/src/vnodeWrite.c @@ -48,10 +48,10 @@ void vnodeInitWriteFp(void) { } int32_t vnodeProcessWrite(void *vparam, void *wparam, int32_t qtype, void *rparam) { - int32_t code = 0; - SVnodeObj * pVnode = vparam; - SWalHead * pHead = wparam; - SRspRet * pRspRet = rparam; + int32_t code = 0; + SVnodeObj *pVnode = vparam; + SWalHead * pHead = wparam; + SRspRet * pRspRet = rparam; if (vnodeProcessWriteMsgFp[pHead->msgType] == NULL) { vError("vgId:%d, msg:%s not processed since no handle, qtype:%s hver:%" PRIu64, pVnode->vgId, @@ -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/cluster/clusterSetup.py b/tests/pytest/cluster/clusterSetup.py index 36af8ac42e..dbda5657b6 100644 --- a/tests/pytest/cluster/clusterSetup.py +++ b/tests/pytest/cluster/clusterSetup.py @@ -31,6 +31,23 @@ class Node: self.homeDir = homeDir self.conn = Connection("{}@{}".format(username, hostName), connect_kwargs={"password": "{}".format(password)}) + def buildTaosd(self): + try: + self.conn.cd("/root/TDinternal/community") + self.conn.run("git checkout develop") + self.conn.run("git pull") + self.conn.cd("/root/TDinternal") + self.conn.run("git checkout develop") + self.conn.run("git pull") + self.conn.cd("/root/TDinternal/debug") + self.conn.run("cmake ..") + self.conn.run("make") + self.conn.run("make install") + except Exception as e: + print("Build Taosd error for node %d " % self.index) + logging.exception(e) + pass + def startTaosd(self): try: self.conn.run("sudo systemctl start taosd") @@ -50,7 +67,7 @@ class Node: self.conn.run("sudo systemctl restart taosd") except Exception as e: print("Stop Taosd error for node %d " % self.index) - logging.exception(e) + logging.exception(e) def removeTaosd(self): try: @@ -105,9 +122,11 @@ class Node: class Nodes: def __init__(self): - self.node1 = Node(1, 'ubuntu', '192.168.1.52', 'node1', 'tbase125!', '/home/ubuntu') - self.node2 = Node(2, 'ubuntu', '192.168.1.53', 'node2', 'tbase125!', '/home/ubuntu') - self.node3 = Node(3, 'ubuntu', '192.168.1.54', 'node3', 'tbase125!', '/home/ubuntu') + self.node1 = Node(1, 'root', '52.151.60.239', 'node1', 'r', '/root/') + self.node2 = Node(2, 'root', '52.183.32.246', 'node1', 'r', '/root/') + self.node3 = Node(3, 'root', '51.143.46.79', 'node1', 'r', '/root/') + self.node4 = Node(4, 'root', '52.183.2.76', 'node1', 'r', '/root/') + self.node5 = Node(5, 'root', '13.66.225.87', 'node1', 'r', '/root/') def stopAllTaosd(self): self.node1.stopTaosd() 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/queryJoin.py b/tests/pytest/query/queryJoin.py index 5ad49a265e..57b7e8868d 100644 --- a/tests/pytest/query/queryJoin.py +++ b/tests/pytest/query/queryJoin.py @@ -141,6 +141,40 @@ class TDTestCase: tdSql.query("select * from meters1, meters3 where meters1.ts = meters3.ts and meters1.tag1 = meters3.tag1") tdSql.checkRows(0) + tdSql.execute("create table join_mt0(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))") + tdSql.execute("create table join_mt1(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), t3 int)") + + ts = 1538548685000 + for i in range(3): + tdSql.execute("create table join_tb%d using join_mt0 tags(%d, 'abc')" % (i, i)) + sql = "insert into join_tb%d values" % i + for j in range(500): + val = j % 100 + sql += "(%d, %d, %f, %d, %d, %d, %f, %d, 'binary%d', 'nchar%d')" % (ts + j, val, val * 1.0, val, val, val, val * 1.0, val % 2, val, val) + tdSql.execute(sql) + sql = "insert into join_tb%d values" % i + for j in range(500, 1000): + val = j % 100 + sql += "(%d, %d, %f, %d, %d, %d, %f, %d, 'binary%d', 'nchar%d')" % (ts + 500 + j, val, val * 1.0, val, val, val, val * 1.0, val % 2, val, val) + tdSql.execute(sql) + + for i in range(3): + tdSql.execute("create table join_1_tb%d using join_mt1 tags(%d, 'abc%d', %d)" % (i, i, i, i)) + sql = "insert into join_1_tb%d values" % i + for j in range(500): + val = j % 100 + sql += "(%d, %d, %f, %d, %d, %d, %f, %d, 'binary%d', 'nchar%d')" % (ts + j, val, val * 1.0, val, val, val, val * 1.0, val % 2, val, val) + tdSql.execute(sql) + sql = "insert into join_1_tb%d values" % i + for j in range(500, 1000): + val = j % 100 + sql += "(%d, %d, %f, %d, %d, %d, %f, %d, 'binary%d', 'nchar%d')" % (ts + 500 + j, val, val * 1.0, val, val, val, val * 1.0, val % 2, val, val) + tdSql.execute(sql) + + tdSql.error("select count(join_mt0.c1), sum(join_mt1.c2), first(join_mt0.c5), last(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") + tdSql.error("select count(join_mt0.c1), first(join_mt0.c1)-first(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") + tdSql.error("select count(join_mt0.c1), first(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 interval(10a) group by join_mt0.t1, join_mt0.t2 order by join_mt0.t1 desc slimit 3") + tdSql.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, join_mt0.t2, join_mt1.t1 order by join_mt0.ts desc, join_mt1.ts asc limit 10;") def stop(self): tdSql.close() 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