Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
慢慢CG
TDengine
提交
8d325f16
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看板
提交
8d325f16
编写于
10月 13, 2020
作者:
F
freemine
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
1. support SQLWCHAR
2. more precise error message, according ODBC doc
上级
e88979de
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
1122 addition
and
513 deletion
+1122
-513
src/client/src/tscPrepare.c
src/client/src/tscPrepare.c
+56
-0
src/connector/odbc/src/todbc.c
src/connector/odbc/src/todbc.c
+716
-512
src/connector/odbc/src/todbc_util.c
src/connector/odbc/src/todbc_util.c
+226
-0
src/connector/odbc/src/todbc_util.h
src/connector/odbc/src/todbc_util.h
+52
-0
src/connector/odbc/tests/main.c
src/connector/odbc/tests/main.c
+1
-1
src/connector/odbc/tests/odbc.py
src/connector/odbc/tests/odbc.py
+44
-0
src/inc/taos.h
src/inc/taos.h
+17
-0
src/inc/taoserror.h
src/inc/taoserror.h
+10
-0
未找到文件。
src/client/src/tscPrepare.c
浏览文件 @
8d325f16
...
@@ -637,3 +637,59 @@ TAOS_RES *taos_stmt_use_result(TAOS_STMT* stmt) {
...
@@ -637,3 +637,59 @@ TAOS_RES *taos_stmt_use_result(TAOS_STMT* stmt) {
pStmt
->
pSql
=
NULL
;
pStmt
->
pSql
=
NULL
;
return
result
;
return
result
;
}
}
int
taos_stmt_num_params
(
TAOS_STMT
*
stmt
,
int
*
nums
)
{
STscStmt
*
pStmt
=
(
STscStmt
*
)
stmt
;
if
(
stmt
==
NULL
||
pStmt
->
taos
==
NULL
||
pStmt
->
pSql
==
NULL
)
{
terrno
=
TSDB_CODE_TSC_DISCONNECTED
;
return
TSDB_CODE_TSC_DISCONNECTED
;
}
SSqlObj
*
pSql
=
pStmt
->
pSql
;
SSqlCmd
*
pCmd
=
&
pSql
->
cmd
;
*
nums
=
pCmd
->
numOfParams
;
return
TSDB_CODE_SUCCESS
;
}
int
taos_stmt_get_param
(
TAOS_STMT
*
stmt
,
int
idx
,
int
*
type
,
int
*
bytes
)
{
STscStmt
*
pStmt
=
(
STscStmt
*
)
stmt
;
if
(
stmt
==
NULL
||
pStmt
->
taos
==
NULL
||
pStmt
->
pSql
==
NULL
)
{
terrno
=
TSDB_CODE_TSC_DISCONNECTED
;
return
TSDB_CODE_TSC_DISCONNECTED
;
}
SSqlObj
*
pSql
=
pStmt
->
pSql
;
SSqlCmd
*
pCmd
=
&
pSql
->
cmd
;
STableDataBlocks
*
pBlock
=
taosArrayGetP
(
pCmd
->
pDataBlocks
,
0
);
assert
(
pCmd
->
numOfParams
==
pBlock
->
numOfParams
);
if
(
idx
<
0
||
idx
>=
pBlock
->
numOfParams
)
return
-
1
;
SParamInfo
*
param
=
pBlock
->
params
+
idx
;
if
(
type
)
*
type
=
param
->
type
;
if
(
bytes
)
*
bytes
=
param
->
bytes
;
return
TSDB_CODE_SUCCESS
;
}
const
char
*
taos_data_type
(
int
type
)
{
switch
(
type
)
{
case
TSDB_DATA_TYPE_NULL
:
return
"TSDB_DATA_TYPE_NULL"
;
case
TSDB_DATA_TYPE_BOOL
:
return
"TSDB_DATA_TYPE_BOOL"
;
case
TSDB_DATA_TYPE_TINYINT
:
return
"TSDB_DATA_TYPE_TINYINT"
;
case
TSDB_DATA_TYPE_SMALLINT
:
return
"TSDB_DATA_TYPE_SMALLINT"
;
case
TSDB_DATA_TYPE_INT
:
return
"TSDB_DATA_TYPE_INT"
;
case
TSDB_DATA_TYPE_BIGINT
:
return
"TSDB_DATA_TYPE_BIGINT"
;
case
TSDB_DATA_TYPE_FLOAT
:
return
"TSDB_DATA_TYPE_FLOAT"
;
case
TSDB_DATA_TYPE_DOUBLE
:
return
"TSDB_DATA_TYPE_DOUBLE"
;
case
TSDB_DATA_TYPE_BINARY
:
return
"TSDB_DATA_TYPE_BINARY"
;
case
TSDB_DATA_TYPE_TIMESTAMP
:
return
"TSDB_DATA_TYPE_TIMESTAMP"
;
case
TSDB_DATA_TYPE_NCHAR
:
return
"TSDB_DATA_TYPE_NCHAR"
;
default:
return
"UNKNOWN"
;
}
}
src/connector/odbc/src/todbc.c
浏览文件 @
8d325f16
...
@@ -13,34 +13,22 @@
...
@@ -13,34 +13,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
// #define _BSD_SOURCE
#define _XOPEN_SOURCE
#define _DEFAULT_SOURCE
#include "taos.h"
#include "taos.h"
#include "os.h"
#include "os.h"
#include "taoserror.h"
#include "taoserror.h"
#include "todbc_util.h"
#include <sql.h>
#include <sql.h>
#include <sqlext.h>
#include <sqlext.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <time.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 GET_REF(obj) atomic_load_64(&obj->refcount)
#define GET_REF(obj) atomic_load_64(&obj->refcount)
#define INC_REF(obj) atomic_add_fetch_64(&obj->refcount, 1)
#define INC_REF(obj) atomic_add_fetch_64(&obj->refcount, 1)
#define DEC_REF(obj) atomic_sub_fetch_64(&obj->refcount, 1)
#define DEC_REF(obj) atomic_sub_fetch_64(&obj->refcount, 1)
...
@@ -76,6 +64,7 @@ do {
...
@@ -76,6 +64,7 @@ do {
if (NativeError) *NativeError = obj->err.err_no; \
if (NativeError) *NativeError = obj->err.err_no; \
snprintf((char*)MessageText, BufferLength, "%s", obj->err.err_str); \
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 = strlen(obj->err.err_str); \
if (TextLength && obj->err.err_str) *TextLength = utf8_chars(obj->err.err_str); \
} while (0)
} while (0)
#define FREE_ERROR(obj) \
#define FREE_ERROR(obj) \
...
@@ -90,7 +79,7 @@ do { \
...
@@ -90,7 +79,7 @@ do { \
#define SET_UNSUPPORT_ERROR(obj, sqlstate, err_fmt, ...) \
#define SET_UNSUPPORT_ERROR(obj, sqlstate, err_fmt, ...) \
do { \
do { \
SET_ERROR(obj, sqlstate, TSDB_CODE_
COM_OPS_NOT_SUPPORT, err_fmt, ##__VA_ARGS__);
\
SET_ERROR(obj, sqlstate, TSDB_CODE_
ODBC_NOT_SUPPORT, err_fmt, ##__VA_ARGS__);
\
} while (0) \
} while (0) \
#define SET_HANDLE_INVALID(obj, sqlstate, err_fmt, ...) \
#define SET_HANDLE_INVALID(obj, sqlstate, err_fmt, ...) \
...
@@ -108,6 +97,22 @@ do { \
...
@@ -108,6 +97,22 @@ do { \
} \
} \
} while (0)
} while (0)
#define CHK_CONN(obj) \
do { \
if (!obj->conn) { \
SET_ERROR(obj, "HY000", TSDB_CODE_ODBC_INVALID_HANDLE, "connection closed or not ready"); \
return SQL_ERROR; \
} \
} while (0);
#define CHK_CONN_TAOS(obj) \
do { \
if (!obj->conn->taos) { \
SET_ERROR(obj, "HY000", TSDB_CODE_ODBC_INVALID_HANDLE, "connection to data source closed or not ready"); \
return SQL_ERROR; \
} \
} while (0);
#define CHK_RS(r_091c, sql_091c, fmt_091c, ...) \
#define CHK_RS(r_091c, sql_091c, fmt_091c, ...) \
do { \
do { \
r_091c = SQL_ERROR; \
r_091c = SQL_ERROR; \
...
@@ -184,7 +189,6 @@ struct sql_s {
...
@@ -184,7 +189,6 @@ struct sql_s {
conn_t
*
conn
;
conn_t
*
conn
;
TAOS_STMT
*
stmt
;
TAOS_STMT
*
stmt
;
TAOS_BIND
*
binds
;
param_bind_t
*
params
;
param_bind_t
*
params
;
int
n_params
;
int
n_params
;
TAOS_RES
*
rs
;
TAOS_RES
*
rs
;
...
@@ -205,8 +209,9 @@ struct c_target_s {
...
@@ -205,8 +209,9 @@ struct c_target_s {
static
pthread_once_t
init_once
=
PTHREAD_ONCE_INIT
;
static
pthread_once_t
init_once
=
PTHREAD_ONCE_INIT
;
static
void
init_routine
(
void
);
static
void
init_routine
(
void
);
static
int
do_field_display_size
(
TAOS_FIELD
*
field
);
static
int
do_field_display_size
(
TAOS_FIELD
*
field
);
static
void
do_convert
(
SQLPOINTER
TargetValue
,
SQLLEN
BufferLength
,
SQLLEN
*
StrLen_or_Ind
,
TAOS_FIELD
*
field
,
void
*
row
);
static
SQLRETURN
doSQLAllocEnv
(
SQLHENV
*
EnvironmentHandle
)
static
SQLRETURN
doSQLAllocEnv
(
SQLHENV
*
EnvironmentHandle
)
{
{
...
@@ -269,7 +274,7 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle,
...
@@ -269,7 +274,7 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle,
do
{
do
{
conn
=
(
conn_t
*
)
calloc
(
1
,
sizeof
(
*
conn
));
conn
=
(
conn_t
*
)
calloc
(
1
,
sizeof
(
*
conn
));
if
(
!
conn
)
{
if
(
!
conn
)
{
SET_ERROR
(
env
,
"HY00
0"
,
TSDB_CODE_ODBC_OOM
,
"failed to alloc connection handle
"
);
SET_ERROR
(
env
,
"HY00
1"
,
TSDB_CODE_ODBC_OOM
,
"
"
);
break
;
break
;
}
}
...
@@ -336,7 +341,7 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
...
@@ -336,7 +341,7 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
if
(
!
conn
)
return
SQL_ERROR
;
if
(
!
conn
)
return
SQL_ERROR
;
if
(
conn
->
taos
)
{
if
(
conn
->
taos
)
{
SET_ERROR
(
conn
,
"
HY000"
,
TSDB_CODE_TSC_APP_ERROR
,
"connection still in use"
);
SET_ERROR
(
conn
,
"
08002"
,
TSDB_CODE_ODBC_CONNECTION_BUSY
,
"connection still in use"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -346,7 +351,7 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
...
@@ -346,7 +351,7 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
do
{
do
{
if
((
ServerName
&&
!
serverName
)
||
(
UserName
&&
!
userName
)
||
(
Authentication
&&
!
auth
))
{
if
((
ServerName
&&
!
serverName
)
||
(
UserName
&&
!
userName
)
||
(
Authentication
&&
!
auth
))
{
SET_ERROR
(
conn
,
"HY00
0"
,
TSDB_CODE_ODBC_OOM
,
"failed to allocate resources
"
);
SET_ERROR
(
conn
,
"HY00
1"
,
TSDB_CODE_ODBC_OOM
,
"
"
);
break
;
break
;
}
}
...
@@ -354,7 +359,7 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
...
@@ -354,7 +359,7 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
// TODO: shall receive ip/port from odbc.ini
// TODO: shall receive ip/port from odbc.ini
conn
->
taos
=
taos_connect
(
"localhost"
,
userName
,
auth
,
NULL
,
0
);
conn
->
taos
=
taos_connect
(
"localhost"
,
userName
,
auth
,
NULL
,
0
);
if
(
!
conn
->
taos
)
{
if
(
!
conn
->
taos
)
{
SET_ERROR
(
conn
,
"
HY000
"
,
terrno
,
"failed to connect to data source"
);
SET_ERROR
(
conn
,
"
08001
"
,
terrno
,
"failed to connect to data source"
);
break
;
break
;
}
}
}
while
(
0
);
}
while
(
0
);
...
@@ -409,7 +414,7 @@ static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle,
...
@@ -409,7 +414,7 @@ static SQLRETURN doSQLAllocStmt(SQLHDBC ConnectionHandle,
do
{
do
{
sql_t
*
sql
=
(
sql_t
*
)
calloc
(
1
,
sizeof
(
*
sql
));
sql_t
*
sql
=
(
sql_t
*
)
calloc
(
1
,
sizeof
(
*
sql
));
if
(
!
sql
)
{
if
(
!
sql
)
{
SET_ERROR
(
conn
,
"HY00
0"
,
TSDB_CODE_ODBC_OOM
,
"failed to alloc statement handle
"
);
SET_ERROR
(
conn
,
"HY00
1"
,
TSDB_CODE_ODBC_OOM
,
"
"
);
break
;
break
;
}
}
...
@@ -442,7 +447,7 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle,
...
@@ -442,7 +447,7 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle,
if
(
Option
==
SQL_CLOSE
)
return
SQL_SUCCESS
;
if
(
Option
==
SQL_CLOSE
)
return
SQL_SUCCESS
;
if
(
Option
!=
SQL_DROP
)
{
if
(
Option
!=
SQL_DROP
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
COM_OPS
_NOT_SUPPORT
,
"free statement with Option[%x] not supported yet"
,
Option
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
ODBC
_NOT_SUPPORT
,
"free statement with Option[%x] not supported yet"
,
Option
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -458,10 +463,6 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle,
...
@@ -458,10 +463,6 @@ static SQLRETURN doSQLFreeStmt(SQLHSTMT StatementHandle,
sql
->
stmt
=
NULL
;
sql
->
stmt
=
NULL
;
}
}
if
(
sql
->
binds
)
{
free
(
sql
->
binds
);
sql
->
binds
=
NULL
;
}
if
(
sql
->
params
)
{
if
(
sql
->
params
)
{
free
(
sql
->
params
);
free
(
sql
->
params
);
sql
->
params
=
NULL
;
sql
->
params
=
NULL
;
...
@@ -494,15 +495,8 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
...
@@ -494,15 +495,8 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
sql
->
rs
)
{
if
(
sql
->
rs
)
{
taos_free_result
(
sql
->
rs
);
taos_free_result
(
sql
->
rs
);
...
@@ -515,11 +509,6 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
...
@@ -515,11 +509,6 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
sql
->
stmt
=
NULL
;
sql
->
stmt
=
NULL
;
}
}
if
(
sql
->
binds
)
{
free
(
sql
->
binds
);
sql
->
binds
=
NULL
;
}
if
(
sql
->
params
)
{
if
(
sql
->
params
)
{
free
(
sql
->
params
);
free
(
sql
->
params
);
sql
->
params
=
NULL
;
sql
->
params
=
NULL
;
...
@@ -531,11 +520,11 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
...
@@ -531,11 +520,11 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
SQLRETURN
r
=
SQL_ERROR
;
SQLRETURN
r
=
SQL_ERROR
;
do
{
do
{
if
(
!
stxt
)
{
if
(
!
stxt
)
{
SET_ERROR
(
sql
,
"HY00
0"
,
TSDB_CODE_ODBC_OOM
,
"failed to allocate resources
"
);
SET_ERROR
(
sql
,
"HY00
1"
,
TSDB_CODE_ODBC_OOM
,
"
"
);
break
;
break
;
}
}
sql
->
rs
=
taos_query
(
sql
->
conn
->
taos
,
stxt
);
sql
->
rs
=
taos_query
(
sql
->
conn
->
taos
,
stxt
);
CHK_RS
(
r
,
sql
,
"failed to
query
"
);
CHK_RS
(
r
,
sql
,
"failed to
execute
"
);
}
while
(
0
);
}
while
(
0
);
SFRE
(
stxt
,
StatementText
,
TextLength
);
SFRE
(
stxt
,
StatementText
,
TextLength
);
...
@@ -551,24 +540,24 @@ SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle,
...
@@ -551,24 +540,24 @@ SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle,
return
r
;
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
);
}
static
SQLRETURN
doSQLNumResultCols
(
SQLHSTMT
StatementHandle
,
static
SQLRETURN
doSQLNumResultCols
(
SQLHSTMT
StatementHandle
,
SQLSMALLINT
*
ColumnCount
)
SQLSMALLINT
*
ColumnCount
)
{
{
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
!
sql
->
rs
)
{
if
(
!
sql
->
rs
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
TSC_QUERY_CACHE_ERASED
,
"no result set cached or not ready
"
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
ODBC_NO_RESULT
,
"
"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -594,18 +583,11 @@ static SQLRETURN doSQLRowCount(SQLHSTMT StatementHandle,
...
@@ -594,18 +583,11 @@ static SQLRETURN doSQLRowCount(SQLHSTMT StatementHandle,
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
!
sql
->
rs
)
{
if
(
!
sql
->
rs
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
TSC_QUERY_CACHE_ERASED
,
"no result set cached or not ready
"
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
ODBC_NO_RESULT
,
"
"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -629,22 +611,14 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle,
...
@@ -629,22 +611,14 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle,
SQLPOINTER
CharacterAttribute
,
SQLSMALLINT
BufferLength
,
SQLPOINTER
CharacterAttribute
,
SQLSMALLINT
BufferLength
,
SQLSMALLINT
*
StringLength
,
SQLLEN
*
NumericAttribute
)
SQLSMALLINT
*
StringLength
,
SQLLEN
*
NumericAttribute
)
{
{
D
(
"......"
);
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
!
sql
->
rs
)
{
if
(
!
sql
->
rs
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
TSC_QUERY_CACHE_ERASED
,
"no result set cached or not ready
"
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
ODBC_NO_RESULT
,
"
"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -652,22 +626,12 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle,
...
@@ -652,22 +626,12 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle,
TAOS_FIELD
*
fields
=
taos_fetch_fields
(
sql
->
rs
);
TAOS_FIELD
*
fields
=
taos_fetch_fields
(
sql
->
rs
);
if
(
nfields
==
0
||
fields
==
NULL
)
{
if
(
nfields
==
0
||
fields
==
NULL
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_MND_FIELD_NOT_EXIST
,
"no fields in result set"
);
SET_ERROR
(
sql
,
"07005"
,
TSDB_CODE_ODBC_NO_FIELDS
,
""
);
return
SQL_ERROR
;
}
if
(
ColumnNumber
<
0
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_APP_ERROR
,
"ColumnNumber[%d] underflow"
,
ColumnNumber
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
if
(
ColumnNumber
==
0
)
{
if
(
ColumnNumber
<=
0
||
ColumnNumber
>
nfields
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"ColumnNumber[0] not supported"
);
SET_ERROR
(
sql
,
"07009"
,
TSDB_CODE_ODBC_OUT_OF_RANGE
,
"invalid column number [%d]"
,
ColumnNumber
);
return
SQL_ERROR
;
}
if
(
ColumnNumber
>
nfields
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_APP_ERROR
,
"ColumnNumber[%d] overflow"
,
ColumnNumber
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -685,9 +649,9 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle,
...
@@ -685,9 +649,9 @@ static SQLRETURN doSQLColAttribute(SQLHSTMT StatementHandle,
*
NumericAttribute
=
SQL_FALSE
;
*
NumericAttribute
=
SQL_FALSE
;
}
break
;
}
break
;
default:
{
default:
{
SET_ERROR
(
sql
,
"HY0
00"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
SET_ERROR
(
sql
,
"HY0
91"
,
TSDB_CODE_ODBC_OUT_OF_RANGE
,
"
ColumnNumber[%d] FieldIdentifier
[%d] not supported yet"
,
"
FieldIdentifier[%d/0x%x] for Column
[%d] not supported yet"
,
ColumnNumber
,
FieldIdentifi
er
);
FieldIdentifier
,
FieldIdentifier
,
ColumnNumb
er
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
break
;
}
break
;
}
}
...
@@ -772,23 +736,16 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -772,23 +736,16 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
!
sql
->
rs
)
{
if
(
!
sql
->
rs
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
TSC_QUERY_CACHE_ERASED
,
"no result set cached or not ready
"
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
ODBC_NO_RESULT
,
"
"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
if
(
!
sql
->
row
)
{
if
(
!
sql
->
row
)
{
SET_ERROR
(
sql
,
"
HY000"
,
TSDB_CODE_TSC_QUERY_CACHE_ERASED
,
"no rows cached or not ready
"
);
SET_ERROR
(
sql
,
"
24000"
,
TSDB_CODE_ODBC_INVALID_CURSOR
,
"
"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -797,23 +754,8 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -797,23 +754,8 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
int
nfields
=
taos_field_count
(
sql
->
rs
);
int
nfields
=
taos_field_count
(
sql
->
rs
);
TAOS_FIELD
*
fields
=
taos_fetch_fields
(
sql
->
rs
);
TAOS_FIELD
*
fields
=
taos_fetch_fields
(
sql
->
rs
);
if
(
nfields
==
0
||
fields
==
NULL
)
{
if
(
ColumnNumber
<=
0
||
ColumnNumber
>
nfields
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_MND_FIELD_NOT_EXIST
,
"no fields in result set"
);
SET_ERROR
(
sql
,
"07009"
,
TSDB_CODE_ODBC_OUT_OF_RANGE
,
"invalid column number [%d]"
,
ColumnNumber
);
return
SQL_ERROR
;
}
if
(
ColumnNumber
<
0
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_APP_ERROR
,
"ColumnNumber[%d] underflow"
,
ColumnNumber
);
return
SQL_ERROR
;
}
if
(
ColumnNumber
==
0
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"ColumnNumber[0] not supported"
);
return
SQL_ERROR
;
}
if
(
ColumnNumber
>
nfields
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_APP_ERROR
,
"ColumnNumber[%d] overflow"
,
ColumnNumber
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -834,8 +776,6 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -834,8 +776,6 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
target
.
len
=
BufferLength
;
target
.
len
=
BufferLength
;
target
.
soi
=
StrLen_or_Ind
;
target
.
soi
=
StrLen_or_Ind
;
SQLRETURN
r
=
SQL_ERROR
;
switch
(
field
->
type
)
{
switch
(
field
->
type
)
{
case
TSDB_DATA_TYPE_BOOL
:
{
case
TSDB_DATA_TYPE_BOOL
:
{
int8_t
v
=
*
(
int8_t
*
)
row
;
int8_t
v
=
*
(
int8_t
*
)
row
;
...
@@ -851,7 +791,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -851,7 +791,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_bool_to_c_char
(
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
);
case
SQL_C_BINARY
:
return
conv_tsdb_bool_to_c_binary
(
sql
,
&
target
,
field
,
v
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -868,7 +810,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -868,7 +810,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_v1_to_c_char
(
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
);
case
SQL_C_BINARY
:
return
conv_tsdb_v1_to_c_binary
(
sql
,
&
target
,
field
,
v
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -884,7 +828,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -884,7 +828,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_v2_to_c_char
(
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
);
case
SQL_C_BINARY
:
return
conv_tsdb_v2_to_c_binary
(
sql
,
&
target
,
field
,
v
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -899,7 +845,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -899,7 +845,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_v4_to_c_char
(
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
);
case
SQL_C_BINARY
:
return
conv_tsdb_v4_to_c_binary
(
sql
,
&
target
,
field
,
v
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -913,7 +861,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -913,7 +861,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_v8_to_c_char
(
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_BINARY
:
return
conv_tsdb_v8_to_c_binary
(
sql
,
&
target
,
field
,
v
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -926,7 +876,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -926,7 +876,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_f4_to_c_char
(
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_BINARY
:
return
conv_tsdb_f4_to_c_binary
(
sql
,
&
target
,
field
,
v
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -938,7 +890,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -938,7 +890,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_f8_to_c_char
(
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_BINARY
:
return
conv_tsdb_f8_to_c_binary
(
sql
,
&
target
,
field
,
v
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -962,7 +916,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -962,7 +916,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_BINARY
:
return
conv_tsdb_ts_to_c_bin
(
sql
,
&
target
,
field
,
&
ts
);
case
SQL_C_BINARY
:
return
conv_tsdb_ts_to_c_bin
(
sql
,
&
target
,
field
,
&
ts
);
case
SQL_C_TIMESTAMP
:
return
conv_tsdb_ts_to_c_ts
(
sql
,
&
target
,
field
,
&
ts
);
case
SQL_C_TIMESTAMP
:
return
conv_tsdb_ts_to_c_ts
(
sql
,
&
target
,
field
,
&
ts
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -973,7 +929,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -973,7 +929,9 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_bin_to_c_str
(
sql
,
&
target
,
field
,
bin
);
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_BINARY
:
return
conv_tsdb_bin_to_c_bin
(
sql
,
&
target
,
field
,
bin
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
...
@@ -991,81 +949,21 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
...
@@ -991,81 +949,21 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
case
SQL_C_CHAR
:
return
conv_tsdb_str_to_c_str
(
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_BINARY
:
return
conv_tsdb_str_to_c_bin
(
sql
,
&
target
,
field
,
str
);
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"from TSDB_DATA_TYPE [%d] to SQL_C_TYPE [%d] not supported"
,
field
->
type
,
target
.
ct
);
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
;
return
SQL_ERROR
;
}
}
}
}
}
break
;
}
break
;
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_CONV_NOT_SUPPORT
,
"field [@%d] type [%d] not supported yet"
,
ColumnNumber
,
field
->
type
);
SET_ERROR
(
sql
,
"HYC00"
,
TSDB_CODE_ODBC_OUT_OF_RANGE
,
"no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for col [%d]"
,
taos_data_type
(
field
->
type
),
field
->
type
,
field
->
type
,
sql_c_type
(
target
.
ct
),
target
.
ct
,
target
.
ct
,
ColumnNumber
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
break
;
}
break
;
}
}
if
(
1
)
return
r
;
switch
(
TargetType
)
{
case
SQL_C_CHAR
:
{
do_convert
(
TargetValue
,
BufferLength
,
StrLen_or_Ind
,
field
,
row
);
}
break
;
case
SQL_C_TIMESTAMP
:
{
TIMESTAMP_STRUCT
ts
=
{
0
};
DASSERT
(
BufferLength
==
sizeof
(
ts
));
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
=
0
;
memcpy
(
TargetValue
,
&
ts
,
sizeof
(
ts
));
}
break
;
case
SQL_C_LONG
:
{
int32_t
v
=
*
(
int32_t
*
)
row
;
DASSERT
(
BufferLength
==
sizeof
(
v
));
memcpy
(
TargetValue
,
&
v
,
sizeof
(
v
));
}
break
;
case
SQL_C_SBIGINT
:
{
int64_t
v
=
*
(
int64_t
*
)
row
;
DASSERT
(
BufferLength
==
sizeof
(
v
));
memcpy
(
TargetValue
,
&
v
,
sizeof
(
v
));
}
break
;
case
SQL_C_FLOAT
:
{
float
v
=
*
(
float
*
)
row
;
DASSERT
(
BufferLength
==
sizeof
(
v
));
memcpy
(
TargetValue
,
&
v
,
sizeof
(
v
));
}
break
;
case
SQL_C_DOUBLE
:
{
double
v
=
*
(
double
*
)
row
;
DASSERT
(
BufferLength
==
sizeof
(
v
));
memcpy
(
TargetValue
,
&
v
,
sizeof
(
v
));
}
break
;
case
SQL_C_BINARY
:
{
if
(
StrLen_or_Ind
)
{
if
(
field
->
type
==
TSDB_DATA_TYPE_NCHAR
)
{
*
StrLen_or_Ind
=
strnlen
((
const
char
*
)
row
,
field
->
bytes
);
}
else
{
*
StrLen_or_Ind
=
field
->
bytes
;
}
}
size_t
n
=
field
->
bytes
;
if
(
n
>
BufferLength
)
n
=
BufferLength
;
memcpy
(
TargetValue
,
(
const
char
*
)
row
,
n
);
}
break
;
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"ColumnNumber[%d] TargetType[%d] BufferLength[%ld] not supported yet"
,
ColumnNumber
,
TargetType
,
BufferLength
);
return
SQL_ERROR
;
}
break
;
}
return
SQL_SUCCESS
;
}
}
SQLRETURN
SQL_API
SQLGetData
(
SQLHSTMT
StatementHandle
,
SQLRETURN
SQL_API
SQLGetData
(
SQLHSTMT
StatementHandle
,
...
@@ -1085,18 +983,11 @@ static SQLRETURN doSQLFetch(SQLHSTMT StatementHandle)
...
@@ -1085,18 +983,11 @@ static SQLRETURN doSQLFetch(SQLHSTMT StatementHandle)
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
!
sql
->
rs
)
{
if
(
!
sql
->
rs
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
TSC_QUERY_CACHE_ERASED
,
"no result set cached or not ready
"
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
ODBC_NO_RESULT
,
"
"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -1117,15 +1008,8 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
...
@@ -1117,15 +1008,8 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
sql
->
rs
)
{
if
(
sql
->
rs
)
{
taos_free_result
(
sql
->
rs
);
taos_free_result
(
sql
->
rs
);
...
@@ -1138,10 +1022,6 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
...
@@ -1138,10 +1022,6 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
sql
->
stmt
=
NULL
;
sql
->
stmt
=
NULL
;
}
}
if
(
sql
->
binds
)
{
free
(
sql
->
binds
);
sql
->
binds
=
NULL
;
}
if
(
sql
->
params
)
{
if
(
sql
->
params
)
{
free
(
sql
->
params
);
free
(
sql
->
params
);
sql
->
params
=
NULL
;
sql
->
params
=
NULL
;
...
@@ -1151,13 +1031,13 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
...
@@ -1151,13 +1031,13 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
do
{
do
{
sql
->
stmt
=
taos_stmt_init
(
sql
->
conn
->
taos
);
sql
->
stmt
=
taos_stmt_init
(
sql
->
conn
->
taos
);
if
(
!
sql
->
stmt
)
{
if
(
!
sql
->
stmt
)
{
SET_ERROR
(
sql
,
"HY00
0"
,
terrno
,
"failed to initialize
statement internally"
);
SET_ERROR
(
sql
,
"HY00
1"
,
terrno
,
"failed to initialize TAOS
statement internally"
);
break
;
break
;
}
}
int
r
=
taos_stmt_prepare
(
sql
->
stmt
,
(
const
char
*
)
StatementText
,
TextLength
);
int
r
=
taos_stmt_prepare
(
sql
->
stmt
,
(
const
char
*
)
StatementText
,
TextLength
);
if
(
r
)
{
if
(
r
)
{
SET_ERROR
(
sql
,
"HY000"
,
r
,
"failed to prepare a statement"
);
SET_ERROR
(
sql
,
"HY000"
,
r
,
"failed to prepare a
TAOS
statement"
);
taos_stmt_close
(
sql
->
stmt
);
taos_stmt_close
(
sql
->
stmt
);
sql
->
stmt
=
NULL
;
sql
->
stmt
=
NULL
;
break
;
break
;
...
@@ -1175,89 +1055,525 @@ SQLRETURN SQL_API SQLPrepare(SQLHSTMT StatementHandle,
...
@@ -1175,89 +1055,525 @@ SQLRETURN SQL_API SQLPrepare(SQLHSTMT StatementHandle,
return
r
;
return
r
;
}
}
static
SQLRETURN
doSQLExecute
(
SQLHSTMT
StatementHandle
)
static
const
int
yes
=
1
;
{
static
const
int
no
=
0
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
static
SQLRETURN
do_bind_param_value
(
sql_t
*
sql
,
int
idx
,
param_bind_t
*
param
,
TAOS_BIND
*
bind
)
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
{
if
(
!
param
->
valid
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_NOT_SUPPORT
,
"parameter [@%d] not bound yet"
,
idx
+
1
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
if
(
param
->
StrLen_or_Ind
&&
*
param
->
StrLen_or_Ind
==
SQL_NULL_DATA
)
{
if
(
!
sql
->
conn
->
taos
)
{
bind
->
is_null
=
(
int
*
)
&
yes
;
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_SUCCESS
;
return
SQL_ERROR
;
}
}
bind
->
is_null
=
(
int
*
)
&
no
;
if
(
!
sql
->
stmt
)
{
int
type
=
0
;
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_SQL
,
"no statement cached or not ready"
);
int
bytes
=
0
;
int
r
=
taos_stmt_get_param
(
sql
->
stmt
,
idx
,
&
type
,
&
bytes
);
if
(
r
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_OUT_OF_RANGE
,
"parameter [@%d] not valid"
,
idx
+
1
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
if
(
sql
->
rs
)
{
// ref: https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/converting-data-from-c-to-sql-data-types?view=sql-server-ver15
taos_free_result
(
sql
->
rs
);
switch
(
type
)
{
sql
->
rs
=
NULL
;
case
TSDB_DATA_TYPE_BOOL
:
{
sql
->
row
=
NULL
;
bind
->
buffer_type
=
type
;
}
bind
->
buffer_length
=
sizeof
(
bind
->
u
.
b
);
bind
->
buffer
=
&
bind
->
u
.
b
;
int
r
=
0
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
for
(
int
i
=
0
;
i
<
sql
->
n_params
;
++
i
)
{
case
SQL_C_LONG
:
{
param_bind_t
*
pb
=
sql
->
params
+
i
;
bind
->
u
.
b
=
*
(
int32_t
*
)
param
->
ParameterValue
;
if
(
!
pb
->
valid
)
{
}
break
;
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"default parameter [@%d] not supported yet"
,
i
+
1
);
case
SQL_C_BIT
:
{
return
SQL_ERROR
;
bind
->
u
.
b
=
*
(
int8_t
*
)
param
->
ParameterValue
;
}
}
break
;
TAOS_BIND
*
b
=
sql
->
binds
+
i
;
case
SQL_C_CHAR
:
int
yes
=
1
;
case
SQL_C_WCHAR
:
int
no
=
0
;
case
SQL_C_SHORT
:
if
(
pb
->
StrLen_or_Ind
&&
*
pb
->
StrLen_or_Ind
==
SQL_NULL_DATA
)
{
case
SQL_C_SSHORT
:
b
->
is_null
=
&
yes
;
case
SQL_C_USHORT
:
}
else
{
case
SQL_C_SLONG
:
b
->
is_null
=
&
no
;
case
SQL_C_ULONG
:
switch
(
b
->
buffer_type
)
{
case
SQL_C_FLOAT
:
case
TSDB_DATA_TYPE_BOOL
:
case
SQL_C_DOUBLE
:
case
TSDB_DATA_TYPE_TINYINT
:
case
SQL_C_TINYINT
:
case
TSDB_DATA_TYPE_SMALLINT
:
case
SQL_C_STINYINT
:
case
TSDB_DATA_TYPE_INT
:
case
SQL_C_UTINYINT
:
case
TSDB_DATA_TYPE_BIGINT
:
case
SQL_C_SBIGINT
:
case
TSDB_DATA_TYPE_FLOAT
:
case
SQL_C_UBIGINT
:
case
TSDB_DATA_TYPE_DOUBLE
:
case
SQL_C_BINARY
:
case
TSDB_DATA_TYPE_TIMESTAMP
:
{
case
SQL_C_DATE
:
b
->
length
=
&
b
->
buffer_length
;
case
SQL_C_TIME
:
b
->
buffer
=
pb
->
ParameterValue
;
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
TSDB_DATA_TYPE_TINYINT
:
{
bind
->
buffer_type
=
type
;
bind
->
buffer_length
=
sizeof
(
bind
->
u
.
v1
);
bind
->
buffer
=
&
bind
->
u
.
v1
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
case
SQL_C_TINYINT
:
{
bind
->
u
.
v1
=
*
(
int8_t
*
)
param
->
ParameterValue
;
}
break
;
case
SQL_C_SHORT
:
{
bind
->
u
.
v1
=
*
(
int16_t
*
)
param
->
ParameterValue
;
}
break
;
case
SQL_C_LONG
:
{
bind
->
u
.
v1
=
*
(
int32_t
*
)
param
->
ParameterValue
;
}
break
;
case
SQL_C_SBIGINT
:
{
bind
->
u
.
v1
=
*
(
int64_t
*
)
param
->
ParameterValue
;
}
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
:
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
TSDB_DATA_TYPE_SMALLINT
:
{
bind
->
buffer_type
=
type
;
bind
->
buffer_length
=
sizeof
(
bind
->
u
.
v2
);
bind
->
buffer
=
&
bind
->
u
.
v2
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
case
SQL_C_LONG
:
{
bind
->
u
.
v2
=
*
(
int32_t
*
)
param
->
ParameterValue
;
}
break
;
case
SQL_C_SHORT
:
{
bind
->
u
.
v2
=
*
(
int16_t
*
)
param
->
ParameterValue
;
}
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_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
:
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
TSDB_DATA_TYPE_INT
:
{
bind
->
buffer_type
=
type
;
bind
->
buffer_length
=
sizeof
(
bind
->
u
.
v4
);
bind
->
buffer
=
&
bind
->
u
.
v4
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
case
SQL_C_LONG
:
{
bind
->
u
.
v4
=
*
(
int32_t
*
)
param
->
ParameterValue
;
}
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_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
:
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
TSDB_DATA_TYPE_BIGINT
:
{
bind
->
buffer_type
=
type
;
bind
->
buffer_length
=
sizeof
(
bind
->
u
.
v8
);
bind
->
buffer
=
&
bind
->
u
.
v8
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
case
SQL_C_SBIGINT
:
{
bind
->
u
.
v8
=
*
(
int64_t
*
)
param
->
ParameterValue
;
}
break
;
case
SQL_C_LONG
:
{
bind
->
u
.
v8
=
*
(
int32_t
*
)
param
->
ParameterValue
;
}
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_BIT
:
case
SQL_C_TINYINT
:
case
SQL_C_STINYINT
:
case
SQL_C_UTINYINT
:
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
:
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
TSDB_DATA_TYPE_FLOAT
:
{
bind
->
buffer_type
=
type
;
bind
->
buffer_length
=
sizeof
(
bind
->
u
.
f4
);
bind
->
buffer
=
&
bind
->
u
.
f4
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
case
SQL_C_DOUBLE
:
{
bind
->
u
.
f4
=
*
(
double
*
)
param
->
ParameterValue
;
}
break
;
case
SQL_C_FLOAT
:
{
bind
->
u
.
f4
=
*
(
float
*
)
param
->
ParameterValue
;
}
break
;
case
SQL_C_CHAR
:
case
SQL_C_WCHAR
:
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_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
:
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
TSDB_DATA_TYPE_DOUBLE
:
{
bind
->
buffer_type
=
type
;
bind
->
buffer_length
=
sizeof
(
bind
->
u
.
f8
);
bind
->
buffer
=
&
bind
->
u
.
f8
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
case
SQL_C_DOUBLE
:
{
bind
->
u
.
f8
=
*
(
double
*
)
param
->
ParameterValue
;
}
break
;
case
SQL_C_CHAR
:
case
SQL_C_WCHAR
:
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_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
:
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
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
(
param
->
ValueType
)
{
case
SQL_C_WCHAR
:
{
DASSERT
(
param
->
StrLen_or_Ind
);
DASSERT
(
*
param
->
StrLen_or_Ind
!=
SQL_NTS
);
size_t
bytes
=
0
;
SQLCHAR
*
utf8
=
wchars_to_chars
(
param
->
ParameterValue
,
*
param
->
StrLen_or_Ind
/
2
,
&
bytes
);
bind
->
allocated
=
1
;
bind
->
u
.
bin
=
utf8
;
bind
->
buffer_length
=
bytes
;
bind
->
buffer
=
bind
->
u
.
bin
;
}
break
;
}
break
;
case
TSDB_DATA_TYPE_BINARY
:
case
SQL_C_BINARY
:
{
case
TSDB_DATA_TYPE_NCHAR
:
{
bind
->
u
.
bin
=
(
unsigned
char
*
)
param
->
ParameterValue
;
if
(
!
pb
->
StrLen_or_Ind
)
{
if
(
*
param
->
StrLen_or_Ind
==
SQL_NTS
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"value [@%d] bad StrLen_or_Ind"
,
i
+
1
);
bind
->
buffer_length
=
strlen
((
const
char
*
)
param
->
ParameterValue
);
return
SQL_ERROR
;
}
else
{
bind
->
buffer_length
=
*
param
->
StrLen_or_Ind
;
}
}
size_t
n
=
*
pb
->
StrLen_or_Ind
;
bind
->
buffer
=
bind
->
u
.
bin
;
if
(
n
==
SQL_NTS
)
{
}
break
;
n
=
strlen
(
pb
->
ParameterValue
);
case
SQL_C_CHAR
:
}
else
if
(
n
<
0
||
n
>
b
->
buffer_length
)
{
case
SQL_C_SHORT
:
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"value [@%d] bad StrLen_or_Ind"
,
i
+
1
);
case
SQL_C_SSHORT
:
return
SQL_ERROR
;
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
TSDB_DATA_TYPE_TIMESTAMP
:
{
bind
->
buffer_type
=
type
;
bind
->
buffer_length
=
sizeof
(
bind
->
u
.
v8
);
bind
->
buffer
=
&
bind
->
u
.
v8
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
case
SQL_C_WCHAR
:
{
DASSERT
(
param
->
StrLen_or_Ind
);
DASSERT
(
*
param
->
StrLen_or_Ind
!=
SQL_NTS
);
size_t
bytes
=
0
;
SQLCHAR
*
utf8
=
wchars_to_chars
(
param
->
ParameterValue
,
*
param
->
StrLen_or_Ind
/
2
,
&
bytes
);
struct
tm
tm
=
{
0
};
strptime
((
const
char
*
)
utf8
,
"%Y-%m-%d %H:%M:%S"
,
&
tm
);
int64_t
t
=
(
int64_t
)
mktime
(
&
tm
);
t
*=
1000
;
bind
->
u
.
v8
=
t
;
free
(
utf8
);
}
break
;
case
SQL_C_SBIGINT
:
{
int64_t
t
=
*
(
int64_t
*
)
param
->
ParameterValue
;
bind
->
u
.
v8
=
t
;
}
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_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
:
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
TSDB_DATA_TYPE_NCHAR
:
{
bind
->
buffer_type
=
type
;
bind
->
length
=
&
bind
->
buffer_length
;
switch
(
param
->
ValueType
)
{
case
SQL_C_WCHAR
:
{
DASSERT
(
param
->
StrLen_or_Ind
);
DASSERT
(
*
param
->
StrLen_or_Ind
!=
SQL_NTS
);
size_t
bytes
=
0
;
SQLCHAR
*
utf8
=
wchars_to_chars
(
param
->
ParameterValue
,
*
param
->
StrLen_or_Ind
/
2
,
&
bytes
);
bind
->
allocated
=
1
;
bind
->
u
.
nchar
=
(
char
*
)
utf8
;
bind
->
buffer_length
=
bytes
;
bind
->
buffer
=
bind
->
u
.
nchar
;
}
break
;
case
SQL_C_CHAR
:
{
bind
->
u
.
nchar
=
(
char
*
)
param
->
ParameterValue
;
if
(
*
param
->
StrLen_or_Ind
==
SQL_NTS
)
{
bind
->
buffer_length
=
strlen
((
const
char
*
)
param
->
ParameterValue
);
}
else
{
bind
->
buffer_length
=
*
param
->
StrLen_or_Ind
;
}
}
bind
->
buffer
=
bind
->
u
.
nchar
;
b
->
buffer_length
=
n
;
b
->
length
=
&
b
->
buffer_length
;
b
->
buffer
=
pb
->
ParameterValue
;
}
break
;
}
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
:
case
SQL_C_NUMERIC
:
case
SQL_C_GUID
:
default:
{
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"value [@%d] not supported yet"
,
i
+
1
);
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
break
;
}
break
;
}
}
}
}
break
;
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
(
param
->
ValueType
),
param
->
ValueType
,
param
->
ValueType
,
taos_data_type
(
type
),
type
,
type
,
idx
+
1
);
return
SQL_ERROR
;
}
break
;
}
return
SQL_SUCCESS
;
}
static
SQLRETURN
do_execute
(
sql_t
*
sql
,
TAOS_BIND
*
binds
)
{
SQLRETURN
r
=
SQL_SUCCESS
;
for
(
int
i
=
0
;
i
<
sql
->
n_params
;
++
i
)
{
r
=
do_bind_param_value
(
sql
,
i
,
sql
->
params
+
i
,
binds
+
i
);
if
(
r
==
SQL_SUCCESS
)
continue
;
return
r
;
}
}
if
(
sql
->
n_params
>
0
)
{
if
(
sql
->
n_params
>
0
)
{
PROFILE
(
r
=
taos_stmt_bind_param
(
sql
->
stmt
,
sql
->
binds
));
PROFILE
(
r
=
taos_stmt_bind_param
(
sql
->
stmt
,
binds
));
if
(
r
)
{
if
(
r
)
{
SET_ERROR
(
sql
,
"HY000"
,
r
,
"failed to bind parameters
"
);
SET_ERROR
(
sql
,
"HY000"
,
r
,
"failed to bind parameters
[%d in total]"
,
sql
->
n_params
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -1274,12 +1590,54 @@ static SQLRETURN doSQLExecute(SQLHSTMT StatementHandle)
...
@@ -1274,12 +1590,54 @@ static SQLRETURN doSQLExecute(SQLHSTMT StatementHandle)
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
SQLRETURN
ret
=
SQL_ERROR
;
PROFILE
(
sql
->
rs
=
taos_stmt_use_result
(
sql
->
stmt
));
PROFILE
(
sql
->
rs
=
taos_stmt_use_result
(
sql
->
stmt
));
CHK_RS
(
r
et
,
sql
,
"failed to use result"
);
CHK_RS
(
r
,
sql
,
"failed to use result"
);
return
ret
;
return
r
;
}
static
SQLRETURN
doSQLExecute
(
SQLHSTMT
StatementHandle
)
{
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
CHK_CONN
(
sql
);
CHK_CONN_TAOS
(
sql
);
if
(
!
sql
->
stmt
)
{
SET_ERROR
(
sql
,
"HY010"
,
TSDB_CODE_ODBC_STATEMENT_NOT_READY
,
""
);
return
SQL_ERROR
;
}
if
(
sql
->
rs
)
{
taos_free_result
(
sql
->
rs
);
sql
->
rs
=
NULL
;
sql
->
row
=
NULL
;
}
TAOS_BIND
*
binds
=
NULL
;
if
(
sql
->
n_params
>
0
)
{
binds
=
(
TAOS_BIND
*
)
calloc
(
sql
->
n_params
,
sizeof
(
*
binds
));
if
(
!
binds
)
{
SET_ERROR
(
sql
,
"HY001"
,
TSDB_CODE_ODBC_OOM
,
""
);
return
SQL_ERROR
;
}
}
SQLRETURN
r
=
do_execute
(
sql
,
binds
);
if
(
binds
)
{
for
(
int
i
=
0
;
i
<
sql
->
n_params
;
++
i
)
{
TAOS_BIND
*
bind
=
binds
+
i
;
if
(
bind
->
allocated
)
{
free
(
bind
->
u
.
nchar
);
bind
->
u
.
nchar
=
NULL
;
}
}
free
(
binds
);
}
return
r
;
}
}
SQLRETURN
SQL_API
SQLExecute
(
SQLHSTMT
StatementHandle
)
SQLRETURN
SQL_API
SQLExecute
(
SQLHSTMT
StatementHandle
)
...
@@ -1373,159 +1731,30 @@ static SQLRETURN doSQLBindParameter(
...
@@ -1373,159 +1731,30 @@ static SQLRETURN doSQLBindParameter(
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
!
sql
->
stmt
)
{
if
(
!
sql
->
stmt
)
{
SET_ERROR
(
sql
,
"HY0
00"
,
TSDB_CODE_TSC_INVALID_SQL
,
"no statement cached or not ready
"
);
SET_ERROR
(
sql
,
"HY0
10"
,
TSDB_CODE_ODBC_STATEMENT_NOT_READY
,
"
"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
if
(
fParamType
!=
SQL_PARAM_INPUT
)
{
if
(
fParamType
!=
SQL_PARAM_INPUT
)
{
SET_ERROR
(
sql
,
"HY
000"
,
TSDB_CODE_COM_OPS
_NOT_SUPPORT
,
"non-input parameter [@%d] not supported yet"
,
ParameterNumber
);
SET_ERROR
(
sql
,
"HY
105"
,
TSDB_CODE_ODBC
_NOT_SUPPORT
,
"non-input parameter [@%d] not supported yet"
,
ParameterNumber
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
int
buffer_type
=
0
;
// ref: https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/converting-data-from-c-to-sql-data-types?view=sql-server-ver15
switch
(
ValueType
)
{
case
SQL_C_BIT
:
{
switch
(
ParameterType
)
{
case
SQL_BIT
:
buffer_type
=
TSDB_DATA_TYPE_BOOL
;
break
;
case
SQL_TINYINT
:
buffer_type
=
TSDB_DATA_TYPE_TINYINT
;
break
;
case
SQL_SMALLINT
:
buffer_type
=
TSDB_DATA_TYPE_SMALLINT
;
break
;
case
SQL_INTEGER
:
buffer_type
=
TSDB_DATA_TYPE_INT
;
break
;
case
SQL_BIGINT
:
buffer_type
=
TSDB_DATA_TYPE_BIGINT
;
break
;
case
SQL_FLOAT
:
buffer_type
=
TSDB_DATA_TYPE_FLOAT
;
break
;
case
SQL_DOUBLE
:
buffer_type
=
TSDB_DATA_TYPE_DOUBLE
;
break
;
case
SQL_VARCHAR
:
buffer_type
=
TSDB_DATA_TYPE_NCHAR
;
break
;
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"parameter[@%d] no conversion from [%d] to [%d]"
,
ParameterNumber
,
ValueType
,
ParameterType
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
SQL_C_TINYINT
:
case
SQL_C_SHORT
:
case
SQL_C_LONG
:
case
SQL_C_SBIGINT
:
case
SQL_C_FLOAT
:
case
SQL_C_DOUBLE
:
case
SQL_C_NUMERIC
:
{
switch
(
ParameterType
)
{
case
SQL_BIT
:
buffer_type
=
TSDB_DATA_TYPE_BOOL
;
break
;
case
SQL_TINYINT
:
buffer_type
=
TSDB_DATA_TYPE_TINYINT
;
break
;
case
SQL_SMALLINT
:
buffer_type
=
TSDB_DATA_TYPE_SMALLINT
;
break
;
case
SQL_INTEGER
:
buffer_type
=
TSDB_DATA_TYPE_INT
;
break
;
case
SQL_BIGINT
:
buffer_type
=
TSDB_DATA_TYPE_BIGINT
;
break
;
case
SQL_FLOAT
:
buffer_type
=
TSDB_DATA_TYPE_FLOAT
;
break
;
case
SQL_DOUBLE
:
buffer_type
=
TSDB_DATA_TYPE_DOUBLE
;
break
;
case
SQL_VARCHAR
:
buffer_type
=
TSDB_DATA_TYPE_NCHAR
;
break
;
case
SQL_TIMESTAMP
:
buffer_type
=
TSDB_DATA_TYPE_TIMESTAMP
;
break
;
// extention to taos
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"parameter[@%d] no conversion from [%d] to [%d]"
,
ParameterNumber
,
ValueType
,
ParameterType
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
SQL_C_DATE
:
case
SQL_C_TIME
:
case
SQL_C_TIMESTAMP
:
{
switch
(
ParameterType
)
{
case
SQL_VARCHAR
:
buffer_type
=
TSDB_DATA_TYPE_NCHAR
;
break
;
case
SQL_TIMESTAMP
:
buffer_type
=
TSDB_DATA_TYPE_TIMESTAMP
;
break
;
// extention to taos
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"parameter[@%d] no conversion from [%d] to [%d]"
,
ParameterNumber
,
ValueType
,
ParameterType
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
SQL_C_CHAR
:
{
switch
(
ParameterType
)
{
case
SQL_BIT
:
buffer_type
=
TSDB_DATA_TYPE_BOOL
;
break
;
case
SQL_TINYINT
:
buffer_type
=
TSDB_DATA_TYPE_TINYINT
;
break
;
case
SQL_SMALLINT
:
buffer_type
=
TSDB_DATA_TYPE_SMALLINT
;
break
;
case
SQL_INTEGER
:
buffer_type
=
TSDB_DATA_TYPE_INT
;
break
;
case
SQL_BIGINT
:
buffer_type
=
TSDB_DATA_TYPE_BIGINT
;
break
;
case
SQL_FLOAT
:
buffer_type
=
TSDB_DATA_TYPE_FLOAT
;
break
;
case
SQL_DOUBLE
:
buffer_type
=
TSDB_DATA_TYPE_DOUBLE
;
break
;
case
SQL_VARCHAR
:
buffer_type
=
TSDB_DATA_TYPE_NCHAR
;
break
;
case
SQL_VARBINARY
:
buffer_type
=
TSDB_DATA_TYPE_BINARY
;
break
;
case
SQL_TIMESTAMP
:
buffer_type
=
TSDB_DATA_TYPE_TIMESTAMP
;
break
;
// extention to taos
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"parameter[@%d] no conversion from [%d] to [%d]"
,
ParameterNumber
,
ValueType
,
ParameterType
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
case
SQL_C_BINARY
:
{
switch
(
ParameterType
)
{
case
SQL_BIT
:
buffer_type
=
TSDB_DATA_TYPE_BOOL
;
break
;
case
SQL_TINYINT
:
buffer_type
=
TSDB_DATA_TYPE_TINYINT
;
break
;
case
SQL_SMALLINT
:
buffer_type
=
TSDB_DATA_TYPE_SMALLINT
;
break
;
case
SQL_INTEGER
:
buffer_type
=
TSDB_DATA_TYPE_INT
;
break
;
case
SQL_BIGINT
:
buffer_type
=
TSDB_DATA_TYPE_BIGINT
;
break
;
case
SQL_FLOAT
:
buffer_type
=
TSDB_DATA_TYPE_FLOAT
;
break
;
case
SQL_DOUBLE
:
buffer_type
=
TSDB_DATA_TYPE_DOUBLE
;
break
;
case
SQL_VARCHAR
:
buffer_type
=
TSDB_DATA_TYPE_NCHAR
;
break
;
case
SQL_VARBINARY
:
buffer_type
=
TSDB_DATA_TYPE_BINARY
;
break
;
case
SQL_TIMESTAMP
:
buffer_type
=
TSDB_DATA_TYPE_TIMESTAMP
;
break
;
// extention to taos
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"parameter[@%d] no conversion from [%d] to [%d]"
,
ParameterNumber
,
ValueType
,
ParameterType
);
return
SQL_ERROR
;
}
break
;
}
}
break
;
default:
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"parameter[@%d] no conversion from [%d] to [%d]"
,
ParameterNumber
,
ValueType
,
ParameterType
);
return
SQL_ERROR
;
}
break
;
}
param_bind_t
*
ar
=
(
param_bind_t
*
)(
sql
->
n_params
>=
ParameterNumber
?
sql
->
params
:
realloc
(
sql
->
params
,
ParameterNumber
*
sizeof
(
*
ar
)));
param_bind_t
*
ar
=
(
param_bind_t
*
)(
sql
->
n_params
>=
ParameterNumber
?
sql
->
params
:
realloc
(
sql
->
params
,
ParameterNumber
*
sizeof
(
*
ar
)));
TAOS_BIND
*
binds
=
(
TAOS_BIND
*
)(
sql
->
n_params
>=
ParameterNumber
?
sql
->
binds
:
realloc
(
sql
->
binds
,
ParameterNumber
*
sizeof
(
*
binds
)));
if
(
!
ar
)
{
if
(
!
ar
||
!
binds
)
{
SET_ERROR
(
sql
,
"HY001"
,
TSDB_CODE_ODBC_OOM
,
""
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_OOM
,
"failed to allocate resources for Parameter[%d]"
,
ParameterNumber
);
if
(
ar
)
sql
->
params
=
ar
;
if
(
binds
)
sql
->
binds
=
binds
;
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
sql
->
params
=
ar
;
sql
->
params
=
ar
;
sql
->
binds
=
binds
;
if
(
sql
->
n_params
<
ParameterNumber
)
{
if
(
sql
->
n_params
<
ParameterNumber
)
{
sql
->
n_params
=
ParameterNumber
;
sql
->
n_params
=
ParameterNumber
;
}
}
param_bind_t
*
pb
=
ar
+
ParameterNumber
-
1
;
param_bind_t
*
pb
=
ar
+
ParameterNumber
-
1
;
TAOS_BIND
*
b
=
binds
+
ParameterNumber
-
1
;
b
->
buffer_type
=
buffer_type
;
b
->
buffer_length
=
LengthPrecision
;
b
->
buffer
=
NULL
;
b
->
length
=
NULL
;
b
->
is_null
=
NULL
;
b
->
is_unsigned
=
0
;
b
->
error
=
NULL
;
pb
->
ParameterNumber
=
ParameterNumber
;
pb
->
ParameterNumber
=
ParameterNumber
;
pb
->
ValueType
=
ValueType
;
pb
->
ValueType
=
ValueType
;
...
@@ -1571,12 +1800,12 @@ static SQLRETURN doSQLDriverConnect(
...
@@ -1571,12 +1800,12 @@ static SQLRETURN doSQLDriverConnect(
if
(
!
conn
)
return
SQL_ERROR
;
if
(
!
conn
)
return
SQL_ERROR
;
if
(
fDriverCompletion
!=
SQL_DRIVER_NOPROMPT
)
{
if
(
fDriverCompletion
!=
SQL_DRIVER_NOPROMPT
)
{
SET_ERROR
(
conn
,
"HY
000"
,
TSDB_CODE_TSC_APP_ERROR
,
"option[%d] other than SQL_DRIVER_NOPROMPT not supported yet"
,
fDriverCompletion
);
SET_ERROR
(
conn
,
"HY
C00"
,
TSDB_CODE_ODBC_NOT_SUPPORT
,
"option[%d] other than SQL_DRIVER_NOPROMPT not supported yet"
,
fDriverCompletion
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
if
(
conn
->
taos
)
{
if
(
conn
->
taos
)
{
SET_ERROR
(
conn
,
"
HY000"
,
TSDB_CODE_TSC_APP_ERROR
,
"connection still in use"
);
SET_ERROR
(
conn
,
"
08002"
,
TSDB_CODE_ODBC_CONNECTION_BUSY
,
"connection still in use"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -1591,18 +1820,16 @@ static SQLRETURN doSQLDriverConnect(
...
@@ -1591,18 +1820,16 @@ static SQLRETURN doSQLDriverConnect(
do
{
do
{
if
(
szConnStrIn
&&
!
connStr
)
{
if
(
szConnStrIn
&&
!
connStr
)
{
SET_ERROR
(
conn
,
"HY00
0"
,
TSDB_CODE_ODBC_OOM
,
"failed to allocate resources
"
);
SET_ERROR
(
conn
,
"HY00
1"
,
TSDB_CODE_ODBC_OOM
,
"
"
);
break
;
break
;
}
}
int
n
=
sscanf
((
const
char
*
)
connStr
,
"DSN=%m[^;]; UID=%m[^;]; PWD=%m[^;] %n"
,
&
serverName
,
&
userName
,
&
auth
,
&
bytes
);
int
n
=
sscanf
((
const
char
*
)
connStr
,
"DSN=%m[^;]; UID=%m[^;]; PWD=%m[^;] %n"
,
&
serverName
,
&
userName
,
&
auth
,
&
bytes
);
if
(
n
<
1
)
{
if
(
n
<
1
)
{
SET_ERROR
(
conn
,
"HY000"
,
TSDB_CODE_
RPC_NETWORK_UNAVAIL
,
"unrecognized connection string: [%s]"
,
(
const
char
*
)
szConnStrIn
);
SET_ERROR
(
conn
,
"HY000"
,
TSDB_CODE_
ODBC_BAD_CONNSTR
,
"unrecognized connection string: [%s]"
,
(
const
char
*
)
szConnStrIn
);
break
;
break
;
}
}
D
(
"DSN:[%s];UID:[%s];PWD:[%s]"
,
serverName
,
userName
,
auth
);
// TODO: data-race
// TODO: data-race
// TODO: shall receive ip/port from odbc.ini
// TODO: shall receive ip/port from odbc.ini
conn
->
taos
=
taos_connect
(
"localhost"
,
userName
,
auth
,
NULL
,
0
);
conn
->
taos
=
taos_connect
(
"localhost"
,
userName
,
auth
,
NULL
,
0
);
...
@@ -1652,11 +1879,11 @@ static SQLRETURN doSQLSetConnectAttr(SQLHDBC ConnectionHandle,
...
@@ -1652,11 +1879,11 @@ static SQLRETURN doSQLSetConnectAttr(SQLHDBC ConnectionHandle,
if
(
!
conn
)
return
SQL_ERROR
;
if
(
!
conn
)
return
SQL_ERROR
;
if
(
Attribute
!=
SQL_ATTR_AUTOCOMMIT
)
{
if
(
Attribute
!=
SQL_ATTR_AUTOCOMMIT
)
{
SET_ERROR
(
conn
,
"HY
000"
,
TSDB_CODE_COM_OPS
_NOT_SUPPORT
,
"Attribute other than SQL_ATTR_AUTOCOMMIT not supported yet"
);
SET_ERROR
(
conn
,
"HY
C00"
,
TSDB_CODE_ODBC
_NOT_SUPPORT
,
"Attribute other than SQL_ATTR_AUTOCOMMIT not supported yet"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
if
(
Value
!=
(
SQLPOINTER
)
SQL_AUTOCOMMIT_ON
)
{
if
(
Value
!=
(
SQLPOINTER
)
SQL_AUTOCOMMIT_ON
)
{
SET_ERROR
(
conn
,
"HY
000"
,
TSDB_CODE_COM_OPS
_NOT_SUPPORT
,
"Attribute Value other than SQL_AUTOCOMMIT_ON not supported yet[%p]"
,
Value
);
SET_ERROR
(
conn
,
"HY
C00"
,
TSDB_CODE_ODBC
_NOT_SUPPORT
,
"Attribute Value other than SQL_AUTOCOMMIT_ON not supported yet[%p]"
,
Value
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -1681,29 +1908,19 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle,
...
@@ -1681,29 +1908,19 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle,
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
sql_t
*
sql
=
(
sql_t
*
)
StatementHandle
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
)
return
SQL_ERROR
;
if
(
!
sql
->
conn
)
{
CHK_CONN
(
sql
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection yet"
);
CHK_CONN_TAOS
(
sql
);
return
SQL_ERROR
;
}
if
(
!
sql
->
conn
->
taos
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_TSC_INVALID_CONNECTION
,
"no connection to data source yet"
);
return
SQL_ERROR
;
}
if
(
!
sql
->
rs
)
{
if
(
!
sql
->
rs
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
TSC_QUERY_CACHE_ERASED
,
"no result set cached or not ready
"
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_
ODBC_NO_RESULT
,
"
"
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
TAOS_FIELD
*
fields
=
taos_fetch_fields
(
sql
->
rs
);
if
(
!
fields
)
{
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_MND_FIELD_NOT_EXIST
,
"fields not ready or unavailable"
);
return
SQL_ERROR
;
}
int
nfields
=
taos_field_count
(
sql
->
rs
);
int
nfields
=
taos_field_count
(
sql
->
rs
);
if
(
ColumnNumber
<
1
||
ColumnNumber
>
nfields
)
{
TAOS_FIELD
*
fields
=
taos_fetch_fields
(
sql
->
rs
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_MND_FIELD_NOT_EXIST
,
"ColumnNumber not in valid range"
);
if
(
ColumnNumber
<=
0
||
ColumnNumber
>
nfields
)
{
SET_ERROR
(
sql
,
"07009"
,
TSDB_CODE_ODBC_OUT_OF_RANGE
,
"invalid column number [%d]"
,
ColumnNumber
);
return
SQL_ERROR
;
return
SQL_ERROR
;
}
}
...
@@ -1759,7 +1976,8 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle,
...
@@ -1759,7 +1976,8 @@ static SQLRETURN doSQLDescribeCol(SQLHSTMT StatementHandle,
}
break
;
}
break
;
default:
default:
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_COM_OPS_NOT_SUPPORT
,
"unknown TSDB_DATA_TYPE [%x]"
,
field
->
type
);
SET_ERROR
(
sql
,
"HY000"
,
TSDB_CODE_ODBC_NOT_SUPPORT
,
"unknown [%s[%d/0x%x]]"
,
taos_data_type
(
field
->
type
),
field
->
type
,
field
->
type
);
return
SQL_ERROR
;
return
SQL_ERROR
;
break
;
break
;
}
}
...
@@ -1795,9 +2013,52 @@ SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle,
...
@@ -1795,9 +2013,52 @@ SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle,
return
r
;
return
r
;
}
}
static
SQLRETURN
doSQLNumParams
(
SQLHSTMT
hstmt
,
SQLSMALLINT
*
pcpar
)
{
sql_t
*
sql
=
(
sql_t
*
)
hstmt
;
if
(
!
sql
)
return
SQL_ERROR
;
CHK_CONN
(
sql
);
CHK_CONN_TAOS
(
sql
);
if
(
!
sql
->
stmt
)
{
SET_ERROR
(
sql
,
"HY010"
,
TSDB_CODE_ODBC_STATEMENT_NOT_READY
,
""
);
return
SQL_ERROR
;
}
int
params
=
0
;
int
r
=
taos_stmt_num_params
(
sql
->
stmt
,
&
params
);
if
(
r
)
{
SET_ERROR
(
sql
,
"HY000"
,
terrno
,
"fetch num of statement params failed"
);
return
SQL_ERROR
;
}
if
(
pcpar
)
*
pcpar
=
params
;
return
SQL_SUCCESS
;
}
SQLRETURN
SQL_API
SQLNumParams
(
SQLHSTMT
hstmt
,
SQLSMALLINT
*
pcpar
)
{
SQLRETURN
r
;
r
=
doSQLNumParams
(
hstmt
,
pcpar
);
return
r
;
}
static
void
init_routine
(
void
)
{
static
void
init_routine
(
void
)
{
if
(
0
)
{
string_conv
(
NULL
,
NULL
,
NULL
,
0
,
NULL
,
0
,
NULL
,
NULL
);
utf8_to_ucs4le
(
NULL
,
NULL
);
ucs4le_to_utf8
(
NULL
,
0
,
NULL
);
}
taos_init
();
taos_init
();
}
}
...
@@ -1845,65 +2106,6 @@ static int do_field_display_size(TAOS_FIELD *field) {
...
@@ -1845,65 +2106,6 @@ static int do_field_display_size(TAOS_FIELD *field) {
return
10
;
return
10
;
}
}
static
void
do_convert
(
SQLPOINTER
TargetValue
,
SQLLEN
BufferLength
,
SQLLEN
*
StrLen_or_Ind
,
TAOS_FIELD
*
field
,
void
*
row
)
{
switch
(
field
->
type
)
{
case
TSDB_DATA_TYPE_TINYINT
:
snprintf
((
char
*
)
TargetValue
,
BufferLength
,
"%d"
,
*
((
int8_t
*
)
row
));
break
;
case
TSDB_DATA_TYPE_SMALLINT
:
snprintf
((
char
*
)
TargetValue
,
BufferLength
,
"%d"
,
*
((
int16_t
*
)
row
));
break
;
case
TSDB_DATA_TYPE_INT
:
snprintf
((
char
*
)
TargetValue
,
BufferLength
,
"%d"
,
*
((
int32_t
*
)
row
));
break
;
case
TSDB_DATA_TYPE_BIGINT
:
snprintf
((
char
*
)
TargetValue
,
BufferLength
,
"%"
PRId64
,
*
((
int64_t
*
)
row
));
break
;
case
TSDB_DATA_TYPE_FLOAT
:
{
float
fv
=
0
;
fv
=
GET_FLOAT_VAL
(
row
);
snprintf
((
char
*
)
TargetValue
,
BufferLength
,
"%f"
,
fv
);
}
break
;
case
TSDB_DATA_TYPE_DOUBLE
:
{
double
dv
=
0
;
dv
=
GET_DOUBLE_VAL
(
row
);
snprintf
((
char
*
)
TargetValue
,
BufferLength
,
"%lf"
,
dv
);
}
break
;
case
TSDB_DATA_TYPE_BINARY
:
case
TSDB_DATA_TYPE_NCHAR
:
{
size_t
xlen
=
0
;
char
*
p
=
(
char
*
)
TargetValue
;
size_t
n
=
BufferLength
;
for
(
xlen
=
0
;
xlen
<
field
->
bytes
-
VARSTR_HEADER_SIZE
;
xlen
++
)
{
char
c
=
((
char
*
)
row
)[
xlen
];
if
(
c
==
0
)
break
;
int
v
=
snprintf
(
p
,
n
,
"%c"
,
c
);
p
+=
v
;
n
-=
v
;
if
(
n
<=
0
)
break
;
}
if
(
n
>
0
)
*
p
=
'\0'
;
((
char
*
)
TargetValue
)[
BufferLength
-
1
]
=
'\0'
;
*
StrLen_or_Ind
=
BufferLength
-
n
;
}
break
;
case
TSDB_DATA_TYPE_TIMESTAMP
:
snprintf
((
char
*
)
TargetValue
,
BufferLength
,
"%"
PRId64
,
*
((
int64_t
*
)
row
));
break
;
case
TSDB_DATA_TYPE_BOOL
:
snprintf
((
char
*
)
TargetValue
,
BufferLength
,
"%d"
,
*
((
int8_t
*
)
row
));
default:
break
;
}
}
// convertion from TSDB_DATA_TYPE_XXX to SQL_C_XXX
// 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
)
static
SQLRETURN
conv_tsdb_bool_to_c_bit
(
sql_t
*
sql
,
c_target_t
*
target
,
TAOS_FIELD
*
field
,
int8_t
b
)
{
{
...
@@ -2353,6 +2555,7 @@ static SQLRETURN conv_tsdb_ts_to_c_ts(sql_t *sql, c_target_t *target, TAOS_FIELD
...
@@ -2353,6 +2555,7 @@ static SQLRETURN conv_tsdb_ts_to_c_ts(sql_t *sql, c_target_t *target, TAOS_FIELD
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_str
(
sql_t
*
sql
,
c_target_t
*
target
,
TAOS_FIELD
*
field
,
const
unsigned
char
*
bin
)
{
{
size_t
n
=
field
->
bytes
;
size_t
n
=
field
->
bytes
;
n
=
strlen
((
const
char
*
)
bin
);
*
target
->
soi
=
n
;
*
target
->
soi
=
n
;
if
(
target
->
ptr
)
memcpy
(
target
->
ptr
,
bin
,
(
n
>
target
->
len
?
target
->
len
:
n
));
if
(
target
->
ptr
)
memcpy
(
target
->
ptr
,
bin
,
(
n
>
target
->
len
?
target
->
len
:
n
));
if
(
n
<=
target
->
len
)
return
SQL_SUCCESS
;
if
(
n
<=
target
->
len
)
return
SQL_SUCCESS
;
...
@@ -2364,6 +2567,7 @@ static SQLRETURN conv_tsdb_bin_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIE
...
@@ -2364,6 +2567,7 @@ static SQLRETURN conv_tsdb_bin_to_c_str(sql_t *sql, c_target_t *target, TAOS_FIE
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_bin_to_c_bin
(
sql_t
*
sql
,
c_target_t
*
target
,
TAOS_FIELD
*
field
,
const
unsigned
char
*
bin
)
{
{
size_t
n
=
field
->
bytes
;
size_t
n
=
field
->
bytes
;
n
=
strlen
((
const
char
*
)
bin
);
*
target
->
soi
=
n
;
*
target
->
soi
=
n
;
if
(
target
->
ptr
)
memcpy
(
target
->
ptr
,
bin
,
(
n
>
target
->
len
?
target
->
len
:
n
));
if
(
target
->
ptr
)
memcpy
(
target
->
ptr
,
bin
,
(
n
>
target
->
len
?
target
->
len
:
n
));
if
(
n
<=
target
->
len
)
return
SQL_SUCCESS
;
if
(
n
<=
target
->
len
)
return
SQL_SUCCESS
;
...
...
src/connector/odbc/src/todbc_util.c
0 → 100644
浏览文件 @
8d325f16
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "todbc_util.h"
#include "iconv.h"
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
#include <stdlib.h>
#include <string.h>
const
char
*
sql_sql_type
(
int
type
)
{
switch
(
type
)
{
case
SQL_BIT
:
return
"SQL_BIT"
;
case
SQL_TINYINT
:
return
"SQL_TINYINT"
;
case
SQL_SMALLINT
:
return
"SQL_SMALLINT"
;
case
SQL_INTEGER
:
return
"SQL_INTEGER"
;
case
SQL_BIGINT
:
return
"SQL_BIGINT"
;
case
SQL_FLOAT
:
return
"SQL_FLOAT"
;
case
SQL_DOUBLE
:
return
"SQL_DOUBLE"
;
case
SQL_DECIMAL
:
return
"SQL_DECIMAL"
;
case
SQL_NUMERIC
:
return
"SQL_NUMERIC"
;
case
SQL_REAL
:
return
"SQL_REAL"
;
case
SQL_CHAR
:
return
"SQL_CHAR"
;
case
SQL_VARCHAR
:
return
"SQL_VARCHAR"
;
case
SQL_LONGVARCHAR
:
return
"SQL_LONGVARCHAR"
;
case
SQL_WCHAR
:
return
"SQL_WCHAR"
;
case
SQL_WVARCHAR
:
return
"SQL_WVARCHAR"
;
case
SQL_WLONGVARCHAR
:
return
"SQL_WLONGVARCHAR"
;
case
SQL_BINARY
:
return
"SQL_BINARY"
;
case
SQL_VARBINARY
:
return
"SQL_VARBINARY"
;
case
SQL_LONGVARBINARY
:
return
"SQL_LONGVARBINARY"
;
case
SQL_DATE
:
return
"SQL_DATE"
;
case
SQL_TIME
:
return
"SQL_TIME"
;
case
SQL_TIMESTAMP
:
return
"SQL_TIMESTAMP"
;
case
SQL_TYPE_DATE
:
return
"SQL_TYPE_DATE"
;
case
SQL_TYPE_TIME
:
return
"SQL_TYPE_TIME"
;
case
SQL_TYPE_TIMESTAMP
:
return
"SQL_TYPE_TIMESTAMP"
;
case
SQL_INTERVAL_MONTH
:
return
"SQL_INTERVAL_MONTH"
;
case
SQL_INTERVAL_YEAR
:
return
"SQL_INTERVAL_YEAR"
;
case
SQL_INTERVAL_YEAR_TO_MONTH
:
return
"SQL_INTERVAL_YEAR_TO_MONTH"
;
case
SQL_INTERVAL_DAY
:
return
"SQL_INTERVAL_DAY"
;
case
SQL_INTERVAL_HOUR
:
return
"SQL_INTERVAL_HOUR"
;
case
SQL_INTERVAL_MINUTE
:
return
"SQL_INTERVAL_MINUTE"
;
case
SQL_INTERVAL_SECOND
:
return
"SQL_INTERVAL_SECOND"
;
case
SQL_INTERVAL_DAY_TO_HOUR
:
return
"SQL_INTERVAL_DAY_TO_HOUR"
;
case
SQL_INTERVAL_DAY_TO_MINUTE
:
return
"SQL_INTERVAL_DAY_TO_MINUTE"
;
case
SQL_INTERVAL_DAY_TO_SECOND
:
return
"SQL_INTERVAL_DAY_TO_SECOND"
;
case
SQL_INTERVAL_HOUR_TO_MINUTE
:
return
"SQL_INTERVAL_HOUR_TO_MINUTE"
;
case
SQL_INTERVAL_HOUR_TO_SECOND
:
return
"SQL_INTERVAL_HOUR_TO_SECOND"
;
case
SQL_INTERVAL_MINUTE_TO_SECOND
:
return
"SQL_INTERVAL_MINUTE_TO_SECOND"
;
case
SQL_GUID
:
return
"SQL_GUID"
;
default:
return
"UNKNOWN"
;
}
}
const
char
*
sql_c_type
(
int
type
)
{
switch
(
type
)
{
case
SQL_C_CHAR
:
return
"SQL_C_CHAR"
;
case
SQL_C_WCHAR
:
return
"SQL_C_WCHAR"
;
case
SQL_C_SHORT
:
return
"SQL_C_SHORT"
;
case
SQL_C_SSHORT
:
return
"SQL_C_SSHORT"
;
case
SQL_C_USHORT
:
return
"SQL_C_USHORT"
;
case
SQL_C_LONG
:
return
"SQL_C_LONG"
;
case
SQL_C_SLONG
:
return
"SQL_C_SLONG"
;
case
SQL_C_ULONG
:
return
"SQL_C_ULONG"
;
case
SQL_C_FLOAT
:
return
"SQL_C_FLOAT"
;
case
SQL_C_DOUBLE
:
return
"SQL_C_DOUBLE"
;
case
SQL_C_BIT
:
return
"SQL_C_BIT"
;
case
SQL_C_TINYINT
:
return
"SQL_C_TINYINT"
;
case
SQL_C_STINYINT
:
return
"SQL_C_STINYINT"
;
case
SQL_C_UTINYINT
:
return
"SQL_C_UTINYINT"
;
case
SQL_C_SBIGINT
:
return
"SQL_C_SBIGINT"
;
case
SQL_C_UBIGINT
:
return
"SQL_C_UBIGINT"
;
case
SQL_C_BINARY
:
return
"SQL_C_BINARY"
;
case
SQL_C_DATE
:
return
"SQL_C_DATE"
;
case
SQL_C_TIME
:
return
"SQL_C_TIME"
;
case
SQL_C_TIMESTAMP
:
return
"SQL_C_TIMESTAMP"
;
case
SQL_C_TYPE_DATE
:
return
"SQL_C_TYPE_DATE"
;
case
SQL_C_TYPE_TIME
:
return
"SQL_C_TYPE_TIME"
;
case
SQL_C_TYPE_TIMESTAMP
:
return
"SQL_C_TYPE_TIMESTAMP"
;
case
SQL_C_NUMERIC
:
return
"SQL_C_NUMERIC"
;
case
SQL_C_GUID
:
return
"SQL_C_GUID"
;
default:
return
"UNKNOWN"
;
}
}
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"
;
const
char
*
tocode
=
"UCS-2LE"
;
iconv_t
conv
=
iconv_open
(
tocode
,
fromcode
);
if
(
!
conv
)
return
-
1
;
size_t
slen
=
strlen
(
src
);
char
buf
[
4096
];
size_t
dlen
=
sizeof
(
buf
);
char
*
ps
=
(
char
*
)
src
;
char
*
pd
=
buf
;
iconv
(
conv
,
&
ps
,
&
slen
,
&
pd
,
&
dlen
);
DASSERT
(
slen
==
0
);
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
;
}
src/connector/odbc/src/todbc_util.h
0 → 100644
浏览文件 @
8d325f16
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _TODBC_UTIL_H_
#define _TODBC_UTIL_H_
#include <libgen.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sql.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)
const
char
*
sql_sql_type
(
int
type
);
const
char
*
sql_c_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_
src/connector/odbc/tests/main.c
浏览文件 @
8d325f16
...
@@ -193,7 +193,7 @@ int main(int argc, char *argv[]) {
...
@@ -193,7 +193,7 @@ int main(int argc, char *argv[]) {
data
.
f8
=
9999999
.
999999
;
data
.
f8
=
9999999
.
999999
;
memset
(
data
.
bin
,
0
,
sizeof
(
data
.
bin
));
memset
(
data
.
bin
,
0
,
sizeof
(
data
.
bin
));
memset
(
data
.
blob
,
0
,
sizeof
(
data
.
blob
));
memset
(
data
.
blob
,
0
,
sizeof
(
data
.
blob
));
snprintf
(
data
.
bin
,
sizeof
(
data
.
bin
),
"hello"
);
snprintf
(
data
.
bin
,
sizeof
(
data
.
bin
),
"hel
我
lo"
);
snprintf
(
data
.
blob
,
sizeof
(
data
.
blob
),
"world"
);
snprintf
(
data
.
blob
,
sizeof
(
data
.
blob
),
"world"
);
snprintf
(
data
.
blob
,
sizeof
(
data
.
blob
),
"wo人rld"
);
snprintf
(
data
.
blob
,
sizeof
(
data
.
blob
),
"wo人rld"
);
SQLHSTMT
stmt
=
{
0
};
SQLHSTMT
stmt
=
{
0
};
...
...
src/connector/odbc/tests/odbc.py
浏览文件 @
8d325f16
...
@@ -9,4 +9,48 @@ row = cursor.fetchone()
...
@@ -9,4 +9,48 @@ row = cursor.fetchone()
while
row
:
while
row
:
print
(
row
)
print
(
row
)
row
=
cursor
.
fetchone
()
row
=
cursor
.
fetchone
()
cursor
.
close
()
#cursor = cnxn.cursor()
#cursor.execute("""
#INSERT INTO db.t values (?,?,?,?,?,?,?,?,?,?)
#""",
#"2020-12-12 00:00:00",
#1,
#27,
#32767,
#147483647,
#223372036854775807,
#23.456,
#899.999999,
#"foo",
#"bar")
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(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
.
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
.
close
()
cursor
=
cnxn
.
cursor
()
cursor
.
execute
(
"SELECT * from db.t"
)
row
=
cursor
.
fetchone
()
while
row
:
print
(
row
)
row
=
cursor
.
fetchone
()
cursor
.
close
()
src/inc/taos.h
浏览文件 @
8d325f16
...
@@ -69,6 +69,8 @@ DLL_EXPORT int taos_options(TSDB_OPTION option, const void *arg, ...);
...
@@ -69,6 +69,8 @@ DLL_EXPORT int taos_options(TSDB_OPTION option, const void *arg, ...);
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
(
const
char
*
ip
,
const
char
*
user
,
const
char
*
pass
,
const
char
*
db
,
uint16_t
port
);
DLL_EXPORT
void
taos_close
(
TAOS
*
taos
);
DLL_EXPORT
void
taos_close
(
TAOS
*
taos
);
const
char
*
taos_data_type
(
int
type
);
typedef
struct
TAOS_BIND
{
typedef
struct
TAOS_BIND
{
int
buffer_type
;
int
buffer_type
;
void
*
buffer
;
void
*
buffer
;
...
@@ -77,10 +79,25 @@ typedef struct TAOS_BIND {
...
@@ -77,10 +79,25 @@ typedef struct TAOS_BIND {
int
*
is_null
;
int
*
is_null
;
int
is_unsigned
;
// unused
int
is_unsigned
;
// unused
int
*
error
;
// unused
int
*
error
;
// unused
union
{
int64_t
ts
;
int8_t
b
;
int8_t
v1
;
int16_t
v2
;
int32_t
v4
;
int64_t
v8
;
float
f4
;
double
f8
;
unsigned
char
*
bin
;
char
*
nchar
;
}
u
;
unsigned
int
allocated
;
}
TAOS_BIND
;
}
TAOS_BIND
;
TAOS_STMT
*
taos_stmt_init
(
TAOS
*
taos
);
TAOS_STMT
*
taos_stmt_init
(
TAOS
*
taos
);
int
taos_stmt_prepare
(
TAOS_STMT
*
stmt
,
const
char
*
sql
,
unsigned
long
length
);
int
taos_stmt_prepare
(
TAOS_STMT
*
stmt
,
const
char
*
sql
,
unsigned
long
length
);
int
taos_stmt_num_params
(
TAOS_STMT
*
stmt
,
int
*
nums
);
int
taos_stmt_get_param
(
TAOS_STMT
*
stmt
,
int
idx
,
int
*
type
,
int
*
bytes
);
int
taos_stmt_bind_param
(
TAOS_STMT
*
stmt
,
TAOS_BIND
*
bind
);
int
taos_stmt_bind_param
(
TAOS_STMT
*
stmt
,
TAOS_BIND
*
bind
);
int
taos_stmt_add_batch
(
TAOS_STMT
*
stmt
);
int
taos_stmt_add_batch
(
TAOS_STMT
*
stmt
);
int
taos_stmt_execute
(
TAOS_STMT
*
stmt
);
int
taos_stmt_execute
(
TAOS_STMT
*
stmt
);
...
...
src/inc/taoserror.h
浏览文件 @
8d325f16
...
@@ -355,6 +355,16 @@ TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, 0, 0x2101, "out of mem
...
@@ -355,6 +355,16 @@ TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, 0, 0x2101, "out of mem
TAOS_DEFINE_ERROR
(
TSDB_CODE_ODBC_CONV_UNDEF
,
0
,
0x2102
,
"convertion undefined"
)
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_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_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"
)
#ifdef TAOS_ERROR_C
#ifdef TAOS_ERROR_C
};
};
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录