feat:[TD-32642] add timezone support in windows

This commit is contained in:
wangmm0220 2024-12-06 17:00:50 +08:00
parent 86c2d5c1c0
commit 5cfadb657f
8 changed files with 171 additions and 38 deletions

View File

@ -661,9 +661,10 @@ ELSEIF(TD_DARWIN)
SET(TZ_OUTPUT_PATH /var/db/timezone/zoneinfo)
ENDIF()
MESSAGE(STATUS "timezone file path: " ${TZ_OUTPUT_PATH})
if(NOT ${TD_WINDOWS})
MESSAGE(STATUS "timezone file path: " ${TZ_OUTPUT_PATH})
execute_process(
COMMAND make TZDIR=${TZ_OUTPUT_PATH}/ tzdir.h
WORKING_DIRECTORY "${TD_CONTRIB_DIR}/tz"

View File

@ -687,12 +687,22 @@ TDengine 客户端驱动的版本号与 TDengine 服务端的版本号是一一
- **返回值**`0`:成功,`-1`:失败。
- `int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...)`
- **接口说明**:设置客户端每个连接选项(不影响服务端的行为,特别对于 charset 和 timezone,目前支持字符集设置(`TSDB_OPTION_CONNECTION_CHARSET`)、时区设置(`TSDB_OPTION_CONNECTION_TIMEZONE`)、用户 IP 设置(`TSDB_OPTION_CONNECTION_USER_IP`)、用户 APP 设置(`TSDB_OPTION_CONNECTION_USER_APP`)。字符集、时区默认为操作系统当前设置windows 不支持连接级别的时区设置,多次调用接口设置相同的配置,以后面的设置为准。
- **接口说明**:设置客户端每个连接选项,目前支持字符集设置(`TSDB_OPTION_CONNECTION_CHARSET`)、时区设置(`TSDB_OPTION_CONNECTION_TIMEZONE`)、用户 IP 设置(`TSDB_OPTION_CONNECTION_USER_IP`)、用户 APP 设置(`TSDB_OPTION_CONNECTION_USER_APP`)。
- **参数说明**
- `taos`: [入参] taos_connect 返回的连接句柄。
- `option`[入参] 设置项类型,具体类型的使用方法及约束详见 taos.h 文件。
- `arg`[入参] 设置项值。为 NULL 时表示重置该选项。
- **返回值**`0`:成功,`非0`:失败。
- `option`[入参] 设置项类型。
- `arg`[入参] 设置项值。
- **返回值**`0`:成功,`非0`:失败。
- **说明**
- 字符集、时区默认为操作系统当前设置windows 不支持连接级别的时区设置。
- arg 为 NULL 时表示重置该选项。
- 该接口只对当前连接有效,不会影响其他连接。
- 同样参数多次调用该接口,以后面的为准,可以作为修改的方法。
- TSDB_OPTION_CONNECTION_CLEAR 选项用于重置所有连接选项。
- 时区和字符集重置后使用操作系统的设置user ip 和 user app 重置后为空。
- 连接选项的值都是 string 类型user app 参数值最大为 23超过该值会被截断其他参数非法时报错。
- 时区参数设置为空或非法时,默认为 UTC。
- 时区和字符集只在 client 侧起作用,对于在服务端的相关行为不起作用。
- `char *taos_get_client_info()`
- **接口说明**:获取客户端版本信息。

View File

@ -181,31 +181,14 @@ typedef struct TAOS_STMT_OPTIONS {
bool singleTableBindOnce;
} TAOS_STMT_OPTIONS;
/*
description:
taos_options_connection use to set extra connect options and affect behavior for a connection.
This function may be called multiple times to set several options.
Call taos_options_connection() after taos_connect() or taos_connect_auth().
The option argument is the option that you want to set; the arg argument is the value for the option.
If you want to reset the option, set arg to NULL.
input:
taos: returned by taos_connect
option: option name
arg: option value
output:
0: success
others: fail, error msg can be got by taos_errstr(NULL)
*/
DLL_EXPORT int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...);
DLL_EXPORT void taos_cleanup(void);
DLL_EXPORT int taos_options(TSDB_OPTION option, const void *arg, ...);
DLL_EXPORT int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...);
DLL_EXPORT setConfRet taos_set_config(const char *config);
DLL_EXPORT int taos_init(void);
DLL_EXPORT TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port);
DLL_EXPORT TAOS *taos_connect_auth(const char *ip, const char *user, const char *auth, const char *db, uint16_t port);
DLL_EXPORT void taos_close(TAOS *taos);
DLL_EXPORT TAOS *taos_connect_auth(const char *ip, const char *user, const char *auth, const char *db, uint16_t port);
DLL_EXPORT void taos_close(TAOS *taos);
DLL_EXPORT const char *taos_data_type(int type);

View File

@ -413,18 +413,20 @@ static FORCE_INLINE int32_t tDecodeBinary(SDecoder* pCoder, uint8_t** val, uint3
static FORCE_INLINE int32_t tDecodeCStrAndLen(SDecoder* pCoder, char** val, uint32_t* len) {
TAOS_CHECK_RETURN(tDecodeBinary(pCoder, (uint8_t**)val, len));
(*len) -= 1; // *len = 0 - 1
if (*len > 0) { // notice!!! *len maybe 0
(*len) -= 1;
}
return 0;
}
static FORCE_INLINE int32_t tDecodeCStr(SDecoder* pCoder, char** val) {
uint32_t len;
uint32_t len = 0;
return tDecodeCStrAndLen(pCoder, val, &len);
}
static int32_t tDecodeCStrTo(SDecoder* pCoder, char* val) {
char* pStr;
uint32_t len;
char* pStr = NULL;
uint32_t len = 0;
TAOS_CHECK_RETURN(tDecodeCStrAndLen(pCoder, &pStr, &len));
if (len < pCoder->size) {
@ -482,12 +484,14 @@ static FORCE_INLINE int32_t tDecodeBinaryAlloc32(SDecoder* pCoder, void** val, u
static FORCE_INLINE int32_t tDecodeCStrAndLenAlloc(SDecoder* pCoder, char** val, uint64_t* len) {
TAOS_CHECK_RETURN(tDecodeBinaryAlloc(pCoder, (void**)val, len));
(*len) -= 1;
if (*len > 0){
(*len) -= 1;
}
return 0;
}
static FORCE_INLINE int32_t tDecodeCStrAlloc(SDecoder* pCoder, char** val) {
uint64_t len;
uint64_t len = 0;
return tDecodeCStrAndLenAlloc(pCoder, val, &len);
}

View File

@ -1489,4 +1489,124 @@ TEST(clientCase, sub_tb_mt_test) {
}
}
TEST(clientCase, timezone_Test) {
{
// taos_options( TSDB_OPTION_TIMEZONE, "UTC-8");
int code = taos_options(TSDB_OPTION_TIMEZONE, "UTC-8");
ASSERT_TRUE(code == 0);
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
TAOS_RES* pRes = taos_query(pConn, "drop database if exists db1");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
pRes = taos_query(pConn, "create database db1");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
pRes = taos_query(pConn, "create table db1.t1 (ts timestamp, v int)");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
char sql[256] = {0};
(void)sprintf(sql, "insert into db1.t1 values('2023-09-16 17:00:00', 1)");
pRes = taos_query(pConn, sql);
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
pRes = taos_query(pConn, "select * from db1.t1 where ts == '2023-09-16 17:00:00'");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
char str[512] = {0};
int rows = 0;
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
}
ASSERT_TRUE(rows == 1);
taos_free_result(pRes);
taos_close(pConn);
}
{
// taos_options( TSDB_OPTION_TIMEZONE, "UTC+8");
int code = taos_options(TSDB_OPTION_TIMEZONE, "UTC+8");
ASSERT_TRUE(code == 0);
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
TAOS_RES* pRes = taos_query(pConn, "select * from db1.t1 where ts == '2023-09-16 01:00:00'");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
int rows = 0;
char str[512] = {0};
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
}
ASSERT_TRUE(rows == 1);
taos_free_result(pRes);
char sql[256] = {0};
(void)sprintf(sql, "insert into db1.t1 values('2023-09-16 17:00:01', 1)");
pRes = taos_query(pConn, sql);
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
taos_free_result(pRes);
taos_close(pConn);
}
{
// taos_options( TSDB_OPTION_TIMEZONE, "UTC+0");
int code = taos_options(TSDB_OPTION_TIMEZONE, "UTC+0");
ASSERT_TRUE(code == 0);
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
TAOS_RES* pRes = taos_query(pConn, "select * from db1.t1 where ts == '2023-09-16 09:00:00'");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
int rows = 0;
char str[512] = {0};
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
}
ASSERT_TRUE(rows == 1);
taos_free_result(pRes);
{
TAOS_RES* pRes = taos_query(pConn, "select * from db1.t1 where ts == '2023-09-17 01:00:01'");
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
int rows = 0;
char str[512] = {0};
while ((pRow = taos_fetch_row(pRes)) != NULL) {
rows++;
}
ASSERT_TRUE(rows == 1);
taos_free_result(pRes);
}
taos_close(pConn);
}
}
#pragma GCC diagnostic pop

View File

@ -903,7 +903,7 @@ TEST(timezoneCase, localtime_performance_Test) {
timezone_t sp = tzalloc("Asia/Shanghai");
ASSERT(sp);
int cnt = 10000000;
int cnt = 1000000;
int times = 10;
int64_t time_localtime = 0;
int64_t time_localtime_rz = 0;

View File

@ -2077,8 +2077,7 @@ static int32_t taosCfgDynamicOptionsForClient(SConfig *pCfg, const char *name) {
int32_t code = TSDB_CODE_SUCCESS;
int32_t lino = 0;
if (strcasecmp("locale", name) == 0 || strcasecmp("charset", name) == 0
|| strcasecmp("timezone", name) == 0) {
if (strcasecmp("charset", name) == 0 || strcasecmp("timezone", name) == 0) {
goto _out;
}
cfgLock(pCfg);
@ -2169,6 +2168,22 @@ static int32_t taosCfgDynamicOptionsForClient(SConfig *pCfg, const char *name) {
}
break;
}
case 'l': {
if (strcasecmp("locale", name) == 0) {
SConfigItem *pLocaleItem = cfgGetItem(pCfg, "locale");
if (pLocaleItem == NULL) {
uError("failed to get locale from cfg");
code = TSDB_CODE_CFG_NOT_FOUND;
goto _out;
}
const char *locale = pLocaleItem->str;
TAOS_CHECK_GOTO(taosSetSystemLocale(locale), &lino, _out);
uInfo("locale set to '%s'", locale);
matched = true;
}
break;
}
case 'm': {
if (strcasecmp("metaCacheMaxSize", name) == 0) {
atomic_store_32(&tsMetaCacheMaxSize, pItem->i32);

View File

@ -230,8 +230,8 @@ static int32_t tSStructA_v1_decode(SCoder *pCoder, SStructA_v1 *pSAV1) {
if (tDecodeI32(pCoder, &pSAV1->A_a) < 0) return -1;
if (tDecodeI64(pCoder, &pSAV1->A_b) < 0) return -1;
const char *tstr;
uint64_t len;
const char *tstr = NULL;
uint64_t len = 0;
if (tDecodeCStrAndLen(pCoder, &tstr, &len) < 0) return -1;
pSAV1->A_c = (char *)tCoderMalloc(pCoder, len + 1);
memcpy(pSAV1->A_c, tstr, len + 1);
@ -269,8 +269,8 @@ static int32_t tSStructA_v2_decode(SCoder *pCoder, SStructA_v2 *pSAV2) {
if (tDecodeI32(pCoder, &pSAV2->A_a) < 0) return -1;
if (tDecodeI64(pCoder, &pSAV2->A_b) < 0) return -1;
const char *tstr;
uint64_t len;
const char *tstr = NULL;
uint64_t len = 0;
if (tDecodeCStrAndLen(pCoder, &tstr, &len) < 0) return -1;
pSAV2->A_c = (char *)tCoderMalloc(pCoder, len + 1);
memcpy(pSAV2->A_c, tstr, len + 1);