Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
慢慢CG
TDengine
提交
74250358
T
TDengine
项目概览
慢慢CG
/
TDengine
与 Fork 源项目一致
Fork自
taosdata / TDengine
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
74250358
编写于
11月 02, 2020
作者:
F
freemine
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
special concern about `binary` field
上级
9491a4ac
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
109 addition
and
74 deletion
+109
-74
src/CMakeLists.txt
src/CMakeLists.txt
+1
-1
src/connector/odbc/src/todbc.c
src/connector/odbc/src/todbc.c
+108
-73
未找到文件。
src/CMakeLists.txt
浏览文件 @
74250358
...
...
@@ -21,5 +21,5 @@ ADD_SUBDIRECTORY(wal)
ADD_SUBDIRECTORY
(
cq
)
ADD_SUBDIRECTORY
(
dnode
)
ADD_SUBDIRECTORY
(
connector/odbc
)
ADD_SUBDIRECTORY
(
connector/jdbc
)
#
ADD_SUBDIRECTORY(connector/jdbc)
src/connector/odbc/src/todbc.c
浏览文件 @
74250358
...
...
@@ -22,6 +22,7 @@
#include "taos.h"
#include "tglobal.h"
#include "taoserror.h"
#include "todbc_util.h"
#include "todbc_conv.h"
...
...
@@ -250,6 +251,7 @@ struct env_s {
unsigned
int
destroying
:
1
;
char
env_locale
[
64
];
char
env_charset
[
64
];
taos_error_t
err
;
};
...
...
@@ -258,8 +260,8 @@ struct conn_s {
uint64_t
refcount
;
env_t
*
env
;
char
client_enc
[
64
];
char
server_enc
[
64
];
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
;
...
...
@@ -267,8 +269,6 @@ struct conn_s {
tsdb_conv_t
*
utf16_to_utf8
;
tsdb_conv_t
*
utf16_to_server
;
tsdb_conv_t
*
client_to_utf8
;
tsdb_conv_t
*
env_to_client
;
tsdb_conv_t
*
client_to_env
;
TAOS
*
taos
;
...
...
@@ -330,14 +330,14 @@ static tsdb_conv_t* tsdb_conn_utf8_to_client(conn_t *conn) {
return
conn
->
utf8_to_client
;
}
tsdb_conv_t
*
tsdb_conn_utf16_to_utf8
(
conn_t
*
conn
)
{
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
;
}
tsdb_conv_t
*
tsdb_conn_utf16_to_server
(
conn_t
*
conn
)
{
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
);
}
...
...
@@ -351,24 +351,7 @@ static tsdb_conv_t* tsdb_conn_client_to_utf8(conn_t *conn) {
return
conn
->
client_to_utf8
;
}
static
tsdb_conv_t
*
tsdb_conn_env_to_client
(
conn_t
*
conn
)
{
if
(
!
conn
->
env_to_client
)
{
conn
->
env_to_client
=
tsdb_conv_open
(
conn
->
env
->
env_locale
,
conn
->
client_enc
);
}
return
conn
->
env_to_client
;
}
static
tsdb_conv_t
*
tsdb_conn_client_to_env
(
conn_t
*
conn
)
{
if
(
!
conn
->
client_to_env
)
{
conn
->
client_to_env
=
tsdb_conv_open
(
conn
->
client_enc
,
conn
->
env
->
env_locale
);
}
return
conn
->
client_to_env
;
}
static
void
tsdb_conn_close_convs
(
conn_t
*
conn
)
{
if
(
0
)
{
tsdb_conn_server_to_client
(
NULL
);
}
if
(
conn
->
client_to_server
)
{
tsdb_conv_close
(
conn
->
client_to_server
);
conn
->
client_to_server
=
NULL
;
...
...
@@ -393,14 +376,6 @@ static void tsdb_conn_close_convs(conn_t *conn) {
tsdb_conv_close
(
conn
->
client_to_utf8
);
conn
->
client_to_utf8
=
NULL
;
}
if
(
conn
->
env_to_client
)
{
tsdb_conv_close
(
conn
->
env_to_client
);
conn
->
env_to_client
=
NULL
;
}
if
(
conn
->
client_to_env
)
{
tsdb_conv_close
(
conn
->
client_to_env
);
conn
->
client_to_env
=
NULL
;
}
}
#define SFREE(buffer, v, src) \
...
...
@@ -421,11 +396,8 @@ static SQLRETURN doSQLAllocEnv(SQLHENV *EnvironmentHandle)
DASSERT
(
INC_REF
(
env
)
>
0
);
#ifdef _MSC_VER
snprintf
(
env
->
env_locale
,
sizeof
(
env
->
env_locale
),
GB18030_ENC
);
#else
snprintf
(
env
->
env_locale
,
sizeof
(
env
->
env_locale
),
UTF8_ENC
);
#endif
snprintf
(
env
->
env_locale
,
sizeof
(
env
->
env_locale
),
"%s"
,
tsLocale
);
snprintf
(
env
->
env_charset
,
sizeof
(
env
->
env_charset
),
"%s"
,
tsCharset
);
*
EnvironmentHandle
=
env
;
...
...
@@ -490,8 +462,8 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle,
conn
->
env
=
env
;
snprintf
(
conn
->
client_enc
,
sizeof
(
conn
->
client_enc
),
"%s"
,
conn
->
env
->
env_
locale
);
snprintf
(
conn
->
server_enc
,
sizeof
(
conn
->
server_enc
),
"%s"
,
conn
->
env
->
env_
locale
);
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
;
...
...
@@ -808,13 +780,13 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
SQLRETURN
r
=
SQL_SUCCESS
;
stack_buffer_t
buffer
;
buffer
.
next
=
0
;
tsdb_conv_t
*
client_to_
env
=
tsdb_conn_client_to_env
(
conn
);
tsdb_conv_t
*
client_to_
server
=
tsdb_conn_client_to_server
(
conn
);
const
char
*
stxt
=
NULL
;
do
{
TSDB_CONV_CODE
code
=
tsdb_conv
(
client_to_
env
,
&
buffer
,
(
const
char
*
)
StatementText
,
(
size_t
)
TextLength
,
&
stxt
,
NULL
);
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
);
tsdb_conv_free
(
client_to_
env
,
stxt
,
&
buffer
,
(
const
char
*
)
StatementText
);
tsdb_conv_free
(
client_to_
server
,
stxt
,
&
buffer
,
(
const
char
*
)
StatementText
);
return
r
;
}
...
...
@@ -1218,14 +1190,29 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
field_bytes
-=
VARSTR_HEADER_SIZE
;
switch
(
target
.
ct
)
{
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
(
StrLen_or_Ind
)
*
StrLen_or_Ind
=
(
SQLLEN
)((
size_t
)
BufferLength
-
len
);
CHK_CONV
(
0
,
code
);
(
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
=
"<bad-charset>"
;
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
,
...
...
@@ -1240,10 +1227,10 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
field_bytes
-=
VARSTR_HEADER_SIZE
;
switch
(
target
.
ct
)
{
case
SQL_C_CHAR
:
{
tsdb_conv_t
*
env_to_client
=
tsdb_conn_env
_to_client
(
conn
);
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
(
env
_to_client
,
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
);
...
...
@@ -2044,38 +2031,84 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
valueType
)
{
case
SQL_C_WCHAR
:
{
tsdb_conv_t
*
utf16_to_server
=
tsdb_conn_utf16_to_server
(
conn
);
// 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
);
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
;
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
}
CHK_CONV
(
1
,
code
);
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
:
{
tsdb_conv_t
*
client_to_server
=
tsdb_conn_client_to_server
(
conn
);
// 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
);
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
;
// 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
}
CHK_CONV
(
1
,
code
);
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
:
...
...
@@ -2131,12 +2164,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
CHK_CONV
(
1
,
code
);
}
break
;
case
SQL_C_CHAR
:
{
tsdb_conv_t
*
client_to_
env
=
tsdb_conn_client_to_env
(
conn
);
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_
env
,
NULL
,
(
const
char
*
)
paramValue
,
slen
,
&
buf
,
&
blen
);
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
;
...
...
@@ -2819,6 +2852,8 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle,
static
void
init_routine
(
void
)
{
taos_init
();
D
(
"tsLocale: [%s]"
,
tsLocale
);
D
(
"tsCharset: [%s]"
,
tsCharset
);
}
static
size_t
do_field_display_size
(
TAOS_FIELD
*
field
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录