adding charset-endec support
This commit is contained in:
parent
7d332df5cd
commit
f43bbfea22
|
@ -28,6 +28,11 @@
|
|||
|
||||
#include <sqlext.h>
|
||||
|
||||
#define UTF8_ENC "UTF-8"
|
||||
#define UTF16_ENC "UCS-2LE"
|
||||
#define UNICODE_ENC "UCS-4LE"
|
||||
#define GB18030_ENC "GB18030"
|
||||
|
||||
#define GET_REF(obj) atomic_load_64(&obj->refcount)
|
||||
#define INC_REF(obj) atomic_add_fetch_64(&obj->refcount, 1)
|
||||
#define DEC_REF(obj) atomic_sub_fetch_64(&obj->refcount, 1)
|
||||
|
@ -159,8 +164,8 @@ do { \
|
|||
|
||||
#define CHK_CONV(todb, statement) \
|
||||
do { \
|
||||
TSDB_CONV_CODE code = (statement); \
|
||||
switch (code) { \
|
||||
TSDB_CONV_CODE code_0c80 = (statement); \
|
||||
switch (code_0c80) { \
|
||||
case TSDB_CONV_OK: return SQL_SUCCESS; \
|
||||
case TSDB_CONV_OOM: { \
|
||||
SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, ""); \
|
||||
|
@ -225,6 +230,16 @@ struct conn_s {
|
|||
uint64_t refcount;
|
||||
env_t *env;
|
||||
|
||||
char client_enc[64];
|
||||
char server_enc[64];
|
||||
|
||||
tsdb_conv_t *client_to_server;
|
||||
tsdb_conv_t *server_to_client;
|
||||
tsdb_conv_t *utf8_to_client;
|
||||
tsdb_conv_t *utf16_to_utf8;
|
||||
tsdb_conv_t *utf16_to_server;
|
||||
tsdb_conv_t *client_to_utf8;
|
||||
|
||||
TAOS *taos;
|
||||
|
||||
taos_error_t err;
|
||||
|
@ -275,20 +290,88 @@ static iconv_t sql_get_w2c(sql_t *sql) {
|
|||
return sql->w2c;
|
||||
}
|
||||
|
||||
// typedef struct stack_buffer_s stack_buffer_t;
|
||||
// struct stack_buffer_s {
|
||||
// char buf[1024*16];
|
||||
// size_t next;
|
||||
// };
|
||||
//
|
||||
// static char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes);
|
||||
// static int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr);
|
||||
//
|
||||
// static const char* tsdb_conn_conv_client_to_server(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len);
|
||||
// static const char* tsdb_conn_conv_server_to_client(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len);
|
||||
// static const char* tsdb_conn_conv_wchars_to_server(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len);
|
||||
// static const char* tsdb_conn_conv_server_to_wchars(conn_t *conn, stack_buffer_t *buffer, const char *src, size_t len);
|
||||
//
|
||||
|
||||
static tsdb_conv_t* tsdb_conn_client_to_server(conn_t *conn) {
|
||||
if (!conn->client_to_server) {
|
||||
conn->client_to_server = tsdb_conv_open(conn->client_enc, conn->server_enc);
|
||||
}
|
||||
return conn->client_to_server;
|
||||
}
|
||||
|
||||
static tsdb_conv_t* tsdb_conn_server_to_client(conn_t *conn) {
|
||||
if (!conn->server_to_client) {
|
||||
conn->server_to_client = tsdb_conv_open(conn->server_enc, conn->client_enc);
|
||||
}
|
||||
return conn->server_to_client;
|
||||
}
|
||||
|
||||
static tsdb_conv_t* tsdb_conn_utf8_to_client(conn_t *conn) {
|
||||
if (!conn->utf8_to_client) {
|
||||
conn->utf8_to_client = tsdb_conv_open(UTF8_ENC, conn->client_enc);
|
||||
}
|
||||
return conn->utf8_to_client;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!conn->utf16_to_server) {
|
||||
conn->utf16_to_server = tsdb_conv_open(UTF16_ENC, conn->server_enc);
|
||||
}
|
||||
return conn->utf16_to_server;
|
||||
}
|
||||
|
||||
static tsdb_conv_t* tsdb_conn_client_to_utf8(conn_t *conn) {
|
||||
if (!conn->client_to_utf8) {
|
||||
conn->client_to_utf8 = tsdb_conv_open(conn->client_enc, UTF8_ENC);
|
||||
}
|
||||
return conn->client_to_utf8;
|
||||
}
|
||||
|
||||
static void tsdb_conn_close_convs(conn_t *conn) {
|
||||
if (0) {
|
||||
tsdb_conn_server_to_client(NULL);
|
||||
}
|
||||
if (conn->client_to_server) {
|
||||
tsdb_conv_close(conn->client_to_server);
|
||||
conn->client_to_server = NULL;
|
||||
}
|
||||
if (conn->server_to_client) {
|
||||
tsdb_conv_close(conn->server_to_client);
|
||||
conn->server_to_client = NULL;
|
||||
}
|
||||
if (conn->utf8_to_client) {
|
||||
tsdb_conv_close(conn->utf8_to_client);
|
||||
conn->utf8_to_client = NULL;
|
||||
}
|
||||
if (conn->utf16_to_utf8) {
|
||||
tsdb_conv_close(conn->utf16_to_utf8);
|
||||
conn->utf16_to_utf8 = NULL;
|
||||
}
|
||||
if (conn->utf16_to_server) {
|
||||
tsdb_conv_close(conn->utf16_to_server);
|
||||
conn->utf16_to_server = NULL;
|
||||
}
|
||||
if (conn->client_to_utf8) {
|
||||
tsdb_conv_close(conn->client_to_utf8);
|
||||
conn->client_to_utf8 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define SFREE(buffer, v, src) \
|
||||
do { \
|
||||
const char *v_096a = (const char*)(v); \
|
||||
const char *src_6a = (const char*)(src); \
|
||||
if (v_096a && v_096a!=src_6a && !is_owned_by_stack_buffer((buffer), v_096a)) { \
|
||||
free((char*)v_096a); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// static iconv_t sql_get_u2c(sql_t *sql) {
|
||||
// if (sql->u2c == (iconv_t)-1) {
|
||||
// sql->u2c = iconv_open("UTF-8", "UCS-4LE");
|
||||
|
@ -375,6 +458,9 @@ static SQLRETURN doSQLAllocConnect(SQLHENV EnvironmentHandle,
|
|||
break;
|
||||
}
|
||||
|
||||
snprintf(conn->client_enc, sizeof(conn->client_enc), UTF8_ENC);
|
||||
snprintf(conn->server_enc, sizeof(conn->server_enc), UTF8_ENC);
|
||||
|
||||
conn->env = env;
|
||||
*ConnectionHandle = conn;
|
||||
|
||||
|
@ -416,6 +502,7 @@ static SQLRETURN doSQLFreeConnect(SQLHDBC ConnectionHandle)
|
|||
|
||||
conn->env = NULL;
|
||||
FREE_ERROR(conn);
|
||||
tsdb_conn_close_convs(conn);
|
||||
free(conn);
|
||||
} while (0);
|
||||
|
||||
|
@ -434,6 +521,8 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
|
|||
SQLCHAR *UserName, SQLSMALLINT NameLength2,
|
||||
SQLCHAR *Authentication, SQLSMALLINT NameLength3)
|
||||
{
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
|
||||
conn_t *conn = (conn_t*)ConnectionHandle;
|
||||
if (!conn) return SQL_ERROR;
|
||||
|
||||
|
@ -451,12 +540,16 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
|
|||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
const char *serverName = SDUP(ServerName, NameLength1);
|
||||
const char *userName = SDUP(UserName, NameLength2);
|
||||
const char *auth = SDUP(Authentication, NameLength3);
|
||||
tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn);
|
||||
const char *serverName = NULL;
|
||||
const char *userName = NULL;
|
||||
const char *auth = NULL;
|
||||
|
||||
do {
|
||||
if ((ServerName && !serverName) || (UserName && !userName) || (Authentication && !auth)) {
|
||||
tsdb_conv(client_to_server, &buffer, (const char*)ServerName, (size_t)NameLength1, &serverName, NULL);
|
||||
tsdb_conv(client_to_server, &buffer, (const char*)UserName, (size_t)NameLength2, &userName, NULL);
|
||||
tsdb_conv(client_to_server, &buffer, (const char*)Authentication, (size_t)NameLength3, &auth, NULL);
|
||||
if ((!serverName) || (!userName) || (!auth)) {
|
||||
SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, "");
|
||||
break;
|
||||
}
|
||||
|
@ -470,9 +563,9 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle,
|
|||
}
|
||||
} while (0);
|
||||
|
||||
SFRE(serverName, ServerName, NameLength1);
|
||||
SFRE(userName, UserName, NameLength2);
|
||||
SFRE(auth, Authentication, NameLength3);
|
||||
tsdb_conv_free(client_to_server, serverName, &buffer, (const char*)ServerName);
|
||||
tsdb_conv_free(client_to_server, userName, &buffer, (const char*)UserName);
|
||||
tsdb_conv_free(client_to_server, auth, &buffer, (const char*)Authentication);
|
||||
|
||||
return conn->taos ? SQL_SUCCESS : SQL_ERROR;
|
||||
}
|
||||
|
@ -659,12 +752,16 @@ SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle,
|
|||
static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
|
||||
SQLCHAR *StatementText, SQLINTEGER TextLength)
|
||||
{
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
|
||||
sql_t *sql = (sql_t*)StatementHandle;
|
||||
if (!sql) return SQL_INVALID_HANDLE;
|
||||
|
||||
CHK_CONN(sql);
|
||||
CHK_CONN_TAOS(sql);
|
||||
|
||||
conn_t *conn = sql->conn;
|
||||
|
||||
NORM_STR_LENGTH(sql, StatementText, TextLength);
|
||||
|
||||
if (sql->rs) {
|
||||
|
@ -684,10 +781,12 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
|
|||
}
|
||||
sql->n_params = 0;
|
||||
|
||||
const char *stxt = SDUP(StatementText, TextLength);
|
||||
tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn);
|
||||
const char *stxt = NULL;
|
||||
|
||||
SQLRETURN r = SQL_ERROR;
|
||||
do {
|
||||
tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL);
|
||||
if (!stxt) {
|
||||
SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, "");
|
||||
break;
|
||||
|
@ -696,7 +795,7 @@ static SQLRETURN doSQLExecDirect(SQLHSTMT StatementHandle,
|
|||
CHK_RS(r, sql, "failed to execute");
|
||||
} while (0);
|
||||
|
||||
SFRE(stxt, StatementText, TextLength);
|
||||
tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -901,6 +1000,8 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
CHK_CONN(sql);
|
||||
CHK_CONN_TAOS(sql);
|
||||
|
||||
conn_t *conn = sql->conn;
|
||||
|
||||
if (!sql->rs) {
|
||||
SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NO_RESULT, "");
|
||||
return SQL_ERROR;
|
||||
|
@ -911,8 +1012,6 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
DASSERT(TargetValue);
|
||||
|
||||
int nfields = taos_field_count(sql->rs);
|
||||
TAOS_FIELD *fields = taos_fetch_fields(sql->rs);
|
||||
|
||||
|
@ -925,14 +1024,20 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "NULL TargetValue not allowed for col [%d]", ColumnNumber);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
if (BufferLength<0) {
|
||||
SET_ERROR(sql, "HY090", TSDB_CODE_ODBC_BAD_ARG, "");
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
TAOS_FIELD *field = fields + ColumnNumber-1;
|
||||
void *row = sql->row[ColumnNumber-1];
|
||||
|
||||
if (!row) {
|
||||
if (StrLen_or_Ind) {
|
||||
*StrLen_or_Ind = SQL_NULL_DATA;
|
||||
if (!StrLen_or_Ind) {
|
||||
SET_ERROR(sql, "22002", TSDB_CODE_ODBC_BAD_ARG, "NULL StrLen_or_Ind not allowed for col [%d]", ColumnNumber);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
*StrLen_or_Ind = SQL_NULL_DATA;
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -981,7 +1086,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
CHK_CONV(0, tsdb_int64_to_double(v, TargetValue));
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(0, tsdb_int64_to_char(v, TargetValue, (size_t)BufferLength));
|
||||
tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn);
|
||||
size_t len = (size_t)BufferLength;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write_int64(utf8_to_client, v, (char*)TargetValue, &len);
|
||||
if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len;
|
||||
CHK_CONV(0, code);
|
||||
} break;
|
||||
default: {
|
||||
SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT,
|
||||
|
@ -1003,7 +1112,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
return SQL_SUCCESS;
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(0, tsdb_double_to_char(v, TargetValue, (size_t)BufferLength));
|
||||
tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn);
|
||||
size_t len = (size_t)BufferLength;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write_double(utf8_to_client, v, (char*)TargetValue, &len);
|
||||
if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len;
|
||||
CHK_CONV(0, code);
|
||||
} break;
|
||||
default: {
|
||||
SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT,
|
||||
|
@ -1021,7 +1134,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
return SQL_SUCCESS;
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(0, tsdb_double_to_char(v, TargetValue, (size_t)BufferLength));
|
||||
tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn);
|
||||
size_t len = (size_t)BufferLength;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write_double(utf8_to_client, v, (char*)TargetValue, &len);
|
||||
if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len;
|
||||
CHK_CONV(0, code);
|
||||
} break;
|
||||
default: {
|
||||
SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT,
|
||||
|
@ -1050,7 +1167,11 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
return SQL_SUCCESS;
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(0, tsdb_timestamp_to_char(ts, TargetValue, (size_t)BufferLength));
|
||||
tsdb_conv_t *utf8_to_client = tsdb_conn_utf8_to_client(conn);
|
||||
size_t len = (size_t)BufferLength;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write_timestamp(utf8_to_client, ts, (char*)TargetValue, &len);
|
||||
if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)len;
|
||||
CHK_CONV(0, code);
|
||||
} break;
|
||||
case SQL_C_TYPE_TIMESTAMP:
|
||||
case SQL_C_TIMESTAMP: {
|
||||
|
@ -1070,7 +1191,14 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
field_bytes -= VARSTR_HEADER_SIZE;
|
||||
switch (target.ct) {
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, (size_t)BufferLength));
|
||||
tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn);
|
||||
size_t slen = strnlen((const char*)row, field_bytes);
|
||||
size_t len = (size_t)BufferLength;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write(server_to_client,
|
||||
(const char*)row, &slen,
|
||||
(char*)TargetValue, &len);
|
||||
if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len);
|
||||
CHK_CONV(0, code);
|
||||
} break;
|
||||
default: {
|
||||
SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT,
|
||||
|
@ -1085,7 +1213,14 @@ static SQLRETURN doSQLGetData(SQLHSTMT StatementHandle,
|
|||
field_bytes -= VARSTR_HEADER_SIZE;
|
||||
switch (target.ct) {
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(0, tsdb_chars_to_char((const char*)row, field_bytes, TargetValue, (size_t)BufferLength));
|
||||
tsdb_conv_t *server_to_client = tsdb_conn_server_to_client(conn);
|
||||
size_t slen = strnlen((const char*)row, field_bytes);
|
||||
size_t len = (size_t)BufferLength;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write(server_to_client,
|
||||
(const char*)row, &slen,
|
||||
(char*)TargetValue, &len);
|
||||
if (StrLen_or_Ind) *StrLen_or_Ind = (SQLLEN)((size_t)BufferLength - len);
|
||||
CHK_CONV(0, code);
|
||||
} break;
|
||||
default: {
|
||||
SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_NOT_SUPPORT,
|
||||
|
@ -1144,12 +1279,16 @@ SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle)
|
|||
static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
|
||||
SQLCHAR *StatementText, SQLINTEGER TextLength)
|
||||
{
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
|
||||
sql_t *sql = (sql_t*)StatementHandle;
|
||||
if (!sql) return SQL_INVALID_HANDLE;
|
||||
|
||||
CHK_CONN(sql);
|
||||
CHK_CONN_TAOS(sql);
|
||||
|
||||
conn_t *conn = sql->conn;
|
||||
|
||||
NORM_STR_LENGTH(sql, StatementText, TextLength);
|
||||
|
||||
if (sql->rs) {
|
||||
|
@ -1177,9 +1316,17 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
|
|||
break;
|
||||
}
|
||||
|
||||
tsdb_conv_t *client_to_server = tsdb_conn_client_to_server(conn);
|
||||
const char *stxt = NULL;
|
||||
int ok = 0;
|
||||
do {
|
||||
int r = taos_stmt_prepare(sql->stmt, (const char *)StatementText, (unsigned long)TextLength);
|
||||
tsdb_conv(client_to_server, &buffer, (const char*)StatementText, (size_t)TextLength, &stxt, NULL);
|
||||
if ((!stxt)) {
|
||||
SET_ERROR(sql, "HY001", TSDB_CODE_ODBC_OOM, "");
|
||||
break;
|
||||
}
|
||||
|
||||
int r = taos_stmt_prepare(sql->stmt, stxt, (unsigned long)strlen(stxt));
|
||||
if (r) {
|
||||
SET_ERROR(sql, "HY000", r, "failed to prepare a TAOS statement");
|
||||
break;
|
||||
|
@ -1216,6 +1363,8 @@ static SQLRETURN doSQLPrepare(SQLHSTMT StatementHandle,
|
|||
ok = 1;
|
||||
} while (0);
|
||||
|
||||
tsdb_conv_free(client_to_server, stxt, &buffer, (const char*)StatementText);
|
||||
|
||||
if (!ok) {
|
||||
taos_stmt_close(sql->stmt);
|
||||
sql->stmt = NULL;
|
||||
|
@ -1245,6 +1394,16 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
SET_ERROR(sql, "HY000", TSDB_CODE_ODBC_NOT_SUPPORT, "parameter [@%d] not bound yet", idx+1);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
if (param->ParameterValue==NULL) {
|
||||
SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ParameterValue [@%p] not allowed", param->ParameterValue);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
if (param->StrLen_or_Ind==NULL) {
|
||||
SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StrLen_or_Ind [@%p] not allowed", param->StrLen_or_Ind);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
conn_t *conn = sql->conn;
|
||||
|
||||
unsigned char *paramValue = param->ParameterValue;
|
||||
SQLSMALLINT valueType = param->ValueType;
|
||||
|
@ -1252,11 +1411,11 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
|
||||
size_t offset = ((size_t)idx_row) * sql->rowlen + sql->ptr_offset;
|
||||
|
||||
if (paramValue) paramValue += offset;
|
||||
if (soi) soi = (SQLLEN*)((char*)soi + offset);
|
||||
paramValue += offset;
|
||||
soi = (SQLLEN*)((char*)soi + offset);
|
||||
|
||||
|
||||
if (soi && *soi == SQL_NULL_DATA) {
|
||||
if (*soi == SQL_NULL_DATA) {
|
||||
bind->is_null = (int*)&yes;
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
@ -1271,6 +1430,7 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
}
|
||||
} else {
|
||||
switch (valueType) {
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_LONG: {
|
||||
type = TSDB_DATA_TYPE_INT;
|
||||
} break;
|
||||
|
@ -1282,7 +1442,6 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
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:
|
||||
|
@ -1344,7 +1503,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
CHK_CONV(1, tsdb_double_to_bit(*(double*)paramValue, &bind->u.b));
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(1, tsdb_chars_to_bit((const char *)paramValue, (size_t)*soi, &bind->u.b));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
if (slen==SQL_NTS) slen = strlen((const char*)paramValue);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_bit(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.b));
|
||||
// CHK_CONV(1, tsdb_chars_to_bit((const char *)paramValue, (size_t)*soi, &bind->u.b));
|
||||
} break;
|
||||
case SQL_C_WCHAR: {
|
||||
CHK_CONV(1, tsdb_wchars_to_bit(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.b));
|
||||
|
@ -1396,7 +1560,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
CHK_CONV(1, tsdb_int64_to_tinyint(*(int64_t*)paramValue, &bind->u.v1));
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(1, tsdb_chars_to_tinyint((const char*)paramValue, (size_t)*soi, &bind->u.v1));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
if (slen==SQL_NTS) slen = strlen((const char*)paramValue);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_tinyint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v1));
|
||||
// CHK_CONV(1, tsdb_chars_to_tinyint((const char *)paramValue, (size_t)*soi, &bind->u.v1));
|
||||
} break;
|
||||
case SQL_C_WCHAR: {
|
||||
CHK_CONV(1, tsdb_wchars_to_tinyint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v1));
|
||||
|
@ -1450,7 +1619,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
CHK_CONV(1, tsdb_int64_to_smallint(*(int64_t*)paramValue, &bind->u.v2));
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, (size_t)*soi, &bind->u.v2));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
if (slen==SQL_NTS) slen = strlen((const char*)paramValue);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_smallint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v2));
|
||||
// CHK_CONV(1, tsdb_chars_to_smallint((const char*)paramValue, (size_t)*soi, &bind->u.v2));
|
||||
} break;
|
||||
case SQL_C_WCHAR: {
|
||||
CHK_CONV(1, tsdb_wchars_to_smallint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v2));
|
||||
|
@ -1504,7 +1678,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
CHK_CONV(1, tsdb_int64_to_int(*(int64_t*)paramValue, &bind->u.v4));
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, (size_t)*soi, &bind->u.v4));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
if (slen==SQL_NTS) slen = strlen((const char*)paramValue);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_int(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v4));
|
||||
// CHK_CONV(1, tsdb_chars_to_int((const char*)paramValue, (size_t)*soi, &bind->u.v4));
|
||||
} break;
|
||||
case SQL_C_WCHAR: {
|
||||
CHK_CONV(1, tsdb_wchars_to_int(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v4));
|
||||
|
@ -1558,7 +1737,12 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
CHK_CONV(1, tsdb_int64_to_bigint(*(int64_t*)paramValue, &bind->u.v8));
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, (size_t)*soi, &bind->u.v8));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
if (slen==SQL_NTS) slen = strlen((const char*)paramValue);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_bigint(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8));
|
||||
// CHK_CONV(1, tsdb_chars_to_bigint((const char*)paramValue, (size_t)*soi, &bind->u.v8));
|
||||
} break;
|
||||
case SQL_C_WCHAR: {
|
||||
CHK_CONV(1, tsdb_wchars_to_bigint(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.v8));
|
||||
|
@ -1618,10 +1802,20 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
bind->u.f4 = (float)*(double*)paramValue;
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(1, tsdb_chars_to_float((const char*)paramValue, (size_t)*soi, &bind->u.f4));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
if (slen==SQL_NTS) slen = strlen((const char*)paramValue);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_float(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4));
|
||||
// CHK_CONV(1, tsdb_chars_to_float((const char*)paramValue, (size_t)*soi, &bind->u.f4));
|
||||
} break;
|
||||
case SQL_C_WCHAR: {
|
||||
CHK_CONV(1, tsdb_wchars_to_float(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f4));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
DASSERT(slen != SQL_NTS);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_float(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f4));
|
||||
// CHK_CONV(1, tsdb_wchars_to_float(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f4));
|
||||
} break;
|
||||
case SQL_C_USHORT:
|
||||
case SQL_C_ULONG:
|
||||
|
@ -1676,10 +1870,20 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
bind->u.f8 = *(double*)paramValue;
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, (size_t)*soi, &bind->u.f8));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
if (slen==SQL_NTS) slen = strlen((const char*)paramValue);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_double(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8));
|
||||
// CHK_CONV(1, tsdb_chars_to_double((const char*)paramValue, (size_t)*soi, &bind->u.f8));
|
||||
} break;
|
||||
case SQL_C_WCHAR: {
|
||||
CHK_CONV(1, tsdb_wchars_to_double(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f8));
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
DASSERT(slen != SQL_NTS);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_double(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.f8));
|
||||
// CHK_CONV(1, tsdb_wchars_to_double(sql_get_w2c(sql), (const unsigned char*)paramValue, (size_t)*soi, &bind->u.f8));
|
||||
} break;
|
||||
case SQL_C_USHORT:
|
||||
case SQL_C_ULONG:
|
||||
|
@ -1703,85 +1907,25 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
} break;
|
||||
}
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
bind->buffer_type = type;
|
||||
bind->length = &bind->buffer_length;
|
||||
switch (valueType) {
|
||||
case SQL_C_WCHAR: {
|
||||
DASSERT(soi);
|
||||
DASSERT(*soi != SQL_NTS);
|
||||
size_t bytes = 0;
|
||||
SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)*soi/2, &bytes);
|
||||
bind->allocated = 1;
|
||||
bind->u.bin = utf8;
|
||||
bind->buffer_length = bytes;
|
||||
bind->buffer = bind->u.bin;
|
||||
} break;
|
||||
case SQL_C_BINARY: {
|
||||
bind->u.bin = (unsigned char*)paramValue;
|
||||
if (*soi == SQL_NTS) {
|
||||
bind->buffer_length = strlen((const char*)paramValue);
|
||||
} else {
|
||||
bind->buffer_length = (uintptr_t)*soi;
|
||||
}
|
||||
bind->buffer = bind->u.bin;
|
||||
} break;
|
||||
case SQL_C_CHAR:
|
||||
case SQL_C_SHORT:
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
case SQL_C_LONG:
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_ULONG:
|
||||
case SQL_C_FLOAT:
|
||||
case SQL_C_DOUBLE:
|
||||
case SQL_C_TINYINT:
|
||||
case SQL_C_STINYINT:
|
||||
case SQL_C_UTINYINT:
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
case SQL_C_BIT:
|
||||
case SQL_C_DATE:
|
||||
case SQL_C_TIME:
|
||||
case SQL_C_TIMESTAMP:
|
||||
case SQL_C_TYPE_DATE:
|
||||
case SQL_C_TYPE_TIME:
|
||||
case SQL_C_TYPE_TIMESTAMP:
|
||||
case SQL_C_NUMERIC:
|
||||
case SQL_C_GUID:
|
||||
default: {
|
||||
SET_ERROR(sql, "HYC00", TSDB_CODE_ODBC_OUT_OF_RANGE,
|
||||
"no convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d]",
|
||||
sql_c_type(valueType), valueType, valueType,
|
||||
taos_data_type(type), type, type, idx+1);
|
||||
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 (valueType) {
|
||||
case SQL_C_CHAR: {
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *client_to_utf8 = tsdb_conn_client_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
DASSERT(slen != SQL_NTS);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_timestamp_ts(client_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8));
|
||||
} break;
|
||||
case SQL_C_WCHAR: {
|
||||
DASSERT(soi);
|
||||
DASSERT(*soi != SQL_NTS);
|
||||
size_t bytes = 0;
|
||||
int r = 0;
|
||||
int64_t t = 0;
|
||||
SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)*soi/2, &bytes);
|
||||
// why cast utf8 to 'char*' ?
|
||||
r = taosParseTime((char*)utf8, &t, (int)strlen((const char*)utf8), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
bind->u.v8 = t;
|
||||
free(utf8);
|
||||
if (r) {
|
||||
SET_ERROR(sql, "22007", TSDB_CODE_ODBC_OUT_OF_RANGE,
|
||||
"convertion from [%s[%d/0x%x]] to [%s[%d/0x%x]] for parameter [%d] failed",
|
||||
sql_c_type(valueType), valueType, valueType,
|
||||
taos_data_type(type), type, type, idx+1);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
stack_buffer_t buffer; buffer.next = 0;
|
||||
tsdb_conv_t *utf16_to_utf8 = tsdb_conn_utf16_to_utf8(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
DASSERT(slen != SQL_NTS);
|
||||
CHK_CONV(1, tsdb_conv_chars_to_timestamp_ts(utf16_to_utf8, &buffer, (const char *)paramValue, slen, &bind->u.v8));
|
||||
} break;
|
||||
case SQL_C_SBIGINT: {
|
||||
int64_t t = *(int64_t*)paramValue;
|
||||
|
@ -1818,28 +1962,127 @@ static SQLRETURN do_bind_param_value(sql_t *sql, int idx_row, int idx, param_bin
|
|||
} break;
|
||||
}
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
bind->buffer_type = type;
|
||||
bind->length = &bind->buffer_length;
|
||||
switch (valueType) {
|
||||
case SQL_C_WCHAR: {
|
||||
tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
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);
|
||||
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);
|
||||
// bind->u.bin = (unsigned char*)paramValue;
|
||||
// if (*soi == SQL_NTS) {
|
||||
// bind->buffer_length = strlen((const char*)paramValue);
|
||||
// } else {
|
||||
// bind->buffer_length = (uintptr_t)*soi;
|
||||
// }
|
||||
// bind->buffer = bind->u.bin;
|
||||
} 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_TINYINT:
|
||||
case SQL_C_STINYINT:
|
||||
case SQL_C_UTINYINT:
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
case SQL_C_BIT:
|
||||
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(valueType), valueType, 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 (valueType) {
|
||||
case SQL_C_WCHAR: {
|
||||
DASSERT(soi);
|
||||
DASSERT(*soi != SQL_NTS);
|
||||
size_t bytes = 0;
|
||||
SQLCHAR *utf8 = wchars_to_chars((const SQLWCHAR*)paramValue, (size_t)(*soi/2), &bytes);
|
||||
bind->allocated = 1;
|
||||
bind->u.nchar = (char*)utf8;
|
||||
bind->buffer_length = bytes;
|
||||
bind->buffer = bind->u.nchar;
|
||||
tsdb_conv_t *utf16_to_server = tsdb_conn_utf16_to_server(conn);
|
||||
size_t slen = (size_t)*soi;
|
||||
if (slen==SQL_NTS) slen = strlen((const char*)paramValue);
|
||||
const char *buf = NULL;
|
||||
size_t blen = 0;
|
||||
TSDB_CONV_CODE code = tsdb_conv(utf16_to_server, NULL, (const char *)paramValue, slen, &buf, &blen);
|
||||
if (code==TSDB_CONV_OK) {
|
||||
if (buf!=(const char*)paramValue) {
|
||||
bind->allocated = 1;
|
||||
}
|
||||
bind->u.nchar = (char*)buf;
|
||||
bind->buffer_length = blen;
|
||||
bind->buffer = bind->u.nchar;
|
||||
}
|
||||
CHK_CONV(1, code);
|
||||
} break;
|
||||
case SQL_C_CHAR: {
|
||||
bind->u.nchar = (char*)paramValue;
|
||||
if (*soi == SQL_NTS) {
|
||||
bind->buffer_length = strlen((const char*)paramValue);
|
||||
} else {
|
||||
bind->buffer_length = (uintptr_t)*soi;
|
||||
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;
|
||||
}
|
||||
bind->buffer = bind->u.nchar;
|
||||
CHK_CONV(1, code);
|
||||
// bind->u.nchar = (char*)paramValue;
|
||||
// if (*soi == SQL_NTS) {
|
||||
// bind->buffer_length = strlen((const char*)paramValue);
|
||||
// } else {
|
||||
// bind->buffer_length = (uintptr_t)*soi;
|
||||
// }
|
||||
// bind->buffer = bind->u.nchar;
|
||||
} break;
|
||||
case SQL_C_SHORT:
|
||||
case SQL_C_SSHORT:
|
||||
|
@ -2110,6 +2353,16 @@ static SQLRETURN doSQLBindParameter(
|
|||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
if (ParameterValue==NULL) {
|
||||
SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "ParameterValue [@%p] not allowed", ParameterValue);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
if (StrLen_or_Ind==NULL) {
|
||||
SET_ERROR(sql, "HY009", TSDB_CODE_ODBC_BAD_ARG, "StrLen_or_Ind [@%p] not allowed", StrLen_or_Ind);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
param_bind_t *pb = sql->params + ParameterNumber - 1;
|
||||
|
||||
pb->ParameterNumber = ParameterNumber;
|
||||
|
@ -2171,12 +2424,7 @@ static SQLRETURN doSQLDriverConnect(
|
|||
|
||||
const char *connStr = SDUP(szConnStrIn, cbConnStrIn);
|
||||
|
||||
char *serverName = NULL;
|
||||
char *userName = NULL;
|
||||
char *auth = NULL;
|
||||
char *host = NULL;
|
||||
char *ip = NULL;
|
||||
int port = 0;
|
||||
conn_val_t val = {0};
|
||||
|
||||
do {
|
||||
if (szConnStrIn && !connStr) {
|
||||
|
@ -2184,22 +2432,37 @@ static SQLRETURN doSQLDriverConnect(
|
|||
break;
|
||||
}
|
||||
|
||||
int n = todbc_parse_conn_string((const char *)connStr, &serverName, &userName, &auth, &host);
|
||||
int n = todbc_parse_conn_string((const char *)connStr, &val);
|
||||
if (n) {
|
||||
SET_ERROR(conn, "HY000", TSDB_CODE_ODBC_BAD_CONNSTR, "unrecognized connection string: [%s]", (const char*)szConnStrIn);
|
||||
break;
|
||||
}
|
||||
if (host) {
|
||||
char *p = strchr(host, ':');
|
||||
char *ip = NULL;
|
||||
int port = 0;
|
||||
if (val.host) {
|
||||
char *p = strchr(val.host, ':');
|
||||
if (p) {
|
||||
ip = strndup(host, (size_t)(p-host));
|
||||
ip = strndup(val.host, (size_t)(p-val.host));
|
||||
port = atoi(p+1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((val.cli_enc && strcmp(val.cli_enc, conn->client_enc)) ||
|
||||
(val.svr_enc && strcmp(val.svr_enc, conn->server_enc)) )
|
||||
{
|
||||
tsdb_conn_close_convs(conn);
|
||||
if (val.cli_enc) {
|
||||
snprintf(conn->client_enc, sizeof(conn->client_enc), "%s", val.cli_enc);
|
||||
}
|
||||
if (val.svr_enc) {
|
||||
snprintf(conn->server_enc, sizeof(conn->server_enc), "%s", val.svr_enc);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: data-race
|
||||
// TODO: shall receive ip/port from odbc.ini
|
||||
conn->taos = taos_connect(ip ? ip : "localhost", userName, auth, NULL, (uint16_t)port);
|
||||
// shall we support non-ansi uid/pwd/db etc?
|
||||
conn->taos = taos_connect(ip ? ip : "localhost", val.uid, val.pwd, val.db, (uint16_t)port);
|
||||
free(ip); ip = NULL;
|
||||
if (!conn->taos) {
|
||||
SET_ERROR(conn, "HY000", terrno, "failed to connect to data source");
|
||||
|
@ -2212,12 +2475,9 @@ static SQLRETURN doSQLDriverConnect(
|
|||
if (pcbConnStrOut) {
|
||||
*pcbConnStrOut = cbConnStrIn;
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
if (serverName) free(serverName);
|
||||
if (userName) free(userName);
|
||||
if (auth) free(auth);
|
||||
conn_val_reset(&val);
|
||||
|
||||
SFRE(connStr, szConnStrIn, cbConnStrIn);
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "todbc_conv.h"
|
||||
|
||||
#include "todbc_log.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
@ -53,11 +55,13 @@ static void buf_clean(buf_t *buf) {
|
|||
const char* tsdb_conv_code_str(TSDB_CONV_CODE code) {
|
||||
switch (code) {
|
||||
case TSDB_CONV_OK: return "TSDB_CONV_OK";
|
||||
case TSDB_CONV_NOT_AVAIL: return "TSDB_CONV_NOT_AVAIL";
|
||||
case TSDB_CONV_OOM: return "TSDB_CONV_OOM";
|
||||
case TSDB_CONV_OOR: return "TSDB_CONV_OOR";
|
||||
case TSDB_CONV_TRUNC_FRACTION: return "TSDB_CONV_TRUNC_FRACTION";
|
||||
case TSDB_CONV_TRUNC: return "TSDB_CONV_TRUNC";
|
||||
case TSDB_CONV_CHAR_NOT_NUM: return "TSDB_CONV_CHAR_NOT_NUM";
|
||||
case TSDB_CONV_CHAR_NOT_TS: return "TSDB_CONV_CHAR_NOT_TS";
|
||||
case TSDB_CONV_GENERAL: return "TSDB_CONV_GENERAL";
|
||||
case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR";
|
||||
default: return "UNKNOWN";
|
||||
|
@ -154,6 +158,7 @@ TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst) {
|
|||
|
||||
TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen) {
|
||||
int n = snprintf(dst, dlen, "%" PRId64 "", src);
|
||||
DASSERT(n>=0);
|
||||
|
||||
if (n<dlen) return TSDB_CONV_OK;
|
||||
|
||||
|
@ -238,6 +243,7 @@ TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst) {
|
|||
|
||||
TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen) {
|
||||
int n = snprintf(dst, dlen, "%lg", src);
|
||||
DASSERT(n>=0);
|
||||
|
||||
if (n<dlen) return TSDB_CONV_OK;
|
||||
|
||||
|
@ -250,6 +256,7 @@ TSDB_CONV_CODE tsdb_timestamp_to_char(SQL_TIMESTAMP_STRUCT src, char *dst, size_
|
|||
src.year, src.month, src.day,
|
||||
src.hour, src.minute, src.second,
|
||||
src.fraction / 1000000);
|
||||
DASSERT(n>=0);
|
||||
if (n<dlen) return TSDB_CONV_OK;
|
||||
|
||||
if (strlen(dst)>=19) return TSDB_CONV_TRUNC_FRACTION;
|
||||
|
@ -374,8 +381,43 @@ TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst) {
|
|||
return TSDB_CONV_CHAR_NOT_NUM;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst) {
|
||||
int64_t v = 0;
|
||||
// why cast to 'char*' ?
|
||||
int r = taosParseTime((char*)src, &v, (int32_t)smax, TSDB_TIME_PRECISION_MILLI, 0);
|
||||
|
||||
if (r) {
|
||||
return TSDB_CONV_CHAR_NOT_TS;
|
||||
}
|
||||
|
||||
time_t t = v/1000;
|
||||
struct tm vtm = {0};
|
||||
localtime_r(&t, &vtm);
|
||||
dst->year = (SQLSMALLINT)(vtm.tm_year + 1900);
|
||||
dst->month = (SQLUSMALLINT)(vtm.tm_mon + 1);
|
||||
dst->day = (SQLUSMALLINT)(vtm.tm_mday);
|
||||
dst->hour = (SQLUSMALLINT)(vtm.tm_hour);
|
||||
dst->minute = (SQLUSMALLINT)(vtm.tm_min);
|
||||
dst->second = (SQLUSMALLINT)(vtm.tm_sec);
|
||||
dst->fraction = (SQLUINTEGER)(v%1000 * 1000000);
|
||||
|
||||
return TSDB_CONV_OK;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_chars_to_timestamp_ts(const char *src, size_t smax, int64_t *dst) {
|
||||
// why cast to 'char*' ?
|
||||
int r = taosParseTime((char*)src, dst, (int32_t)smax, TSDB_TIME_PRECISION_MILLI, 0);
|
||||
|
||||
if (r) {
|
||||
return TSDB_CONV_CHAR_NOT_TS;
|
||||
}
|
||||
|
||||
return TSDB_CONV_OK;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax) {
|
||||
int n = snprintf(dst, dmax, "%s", src);
|
||||
DASSERT(n>=0);
|
||||
if (n<dmax) return TSDB_CONV_OK;
|
||||
|
||||
return TSDB_CONV_TRUNC;
|
||||
|
@ -524,5 +566,264 @@ TSDB_CONV_CODE tsdb_wchars_to_char(iconv_t cnv, const unsigned char *src, size_t
|
|||
return tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)dst, &dmax);
|
||||
}
|
||||
|
||||
char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes) {
|
||||
if (!buffer) return NULL;
|
||||
// align-by-size_of-size_t-bytes
|
||||
if (bytes==0) bytes = sizeof(size_t);
|
||||
bytes = (bytes + sizeof(size_t) - 1) / sizeof(size_t) * sizeof(size_t);
|
||||
|
||||
size_t next = buffer->next + bytes;
|
||||
if (next>sizeof(buffer->buf)) return NULL;
|
||||
|
||||
char *p = buffer->buf + buffer->next;
|
||||
buffer->next = next;
|
||||
return p;
|
||||
}
|
||||
|
||||
int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr) {
|
||||
if (!buffer) return 0;
|
||||
if (ptr>=buffer->buf && ptr<buffer->buf+buffer->next) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct tsdb_conv_s {
|
||||
iconv_t cnv;
|
||||
unsigned int direct:1;
|
||||
};
|
||||
|
||||
tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc) {
|
||||
tsdb_conv_t *cnv = (tsdb_conv_t*)calloc(1, sizeof(*cnv));
|
||||
if (!cnv) return NULL;
|
||||
if (strcmp(from_enc, to_enc)==0) {
|
||||
cnv->cnv = (iconv_t)-1;
|
||||
cnv->direct = 1;
|
||||
return cnv;
|
||||
}
|
||||
cnv->cnv = iconv_open(to_enc, from_enc);
|
||||
if (cnv->cnv == (iconv_t)-1) {
|
||||
free(cnv);
|
||||
return NULL;
|
||||
}
|
||||
cnv->direct = 0;
|
||||
return cnv;
|
||||
}
|
||||
|
||||
void tsdb_conv_close(tsdb_conv_t *cnv) {
|
||||
if (!cnv) return;
|
||||
if (!cnv->direct) {
|
||||
if (cnv->cnv != (iconv_t)-1) {
|
||||
iconv_close(cnv->cnv);
|
||||
}
|
||||
}
|
||||
cnv->cnv = (iconv_t)-1;
|
||||
cnv->direct = 0;
|
||||
free(cnv);
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen) {
|
||||
if (!cnv) return TSDB_CONV_NOT_AVAIL;
|
||||
if (cnv->direct) {
|
||||
size_t n = (*slen > *dlen) ? *dlen : *slen;
|
||||
memcpy(dst, src, n);
|
||||
*slen -= n;
|
||||
*dlen -= n;
|
||||
if (*dlen) dst[n] = '\0';
|
||||
return TSDB_CONV_OK;
|
||||
}
|
||||
if (!cnv->cnv) return TSDB_CONV_NOT_AVAIL;
|
||||
size_t r = iconv(cnv->cnv, (char**)&src, slen, &dst, dlen);
|
||||
if (r==(size_t)-1) return TSDB_CONV_BAD_CHAR;
|
||||
if (*slen) return TSDB_CONV_TRUNC;
|
||||
if (*dlen) *dst = '\0';
|
||||
return TSDB_CONV_OK;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen) {
|
||||
char utf8[64];
|
||||
int n = snprintf(utf8, sizeof(utf8), "%" PRId64 "", val);
|
||||
DASSERT(n>=0);
|
||||
DASSERT(n<sizeof(utf8));
|
||||
size_t len = (size_t)n;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write(cnv, utf8, &len, dst, dlen);
|
||||
*dlen = (size_t)n+1;
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_write_double(tsdb_conv_t *cnv, double val, char *dst, size_t *dlen) {
|
||||
char utf8[256];
|
||||
int n = snprintf(utf8, sizeof(utf8), "%g", val);
|
||||
DASSERT(n>=0);
|
||||
DASSERT(n<sizeof(utf8));
|
||||
size_t len = (size_t)n;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write(cnv, utf8, &len, dst, dlen);
|
||||
*dlen = (size_t)n+1;
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_write_timestamp(tsdb_conv_t *cnv, SQL_TIMESTAMP_STRUCT val, char *dst, size_t *dlen) {
|
||||
char utf8[256];
|
||||
int n = snprintf(utf8, sizeof(utf8), "%04d-%02d-%02d %02d:%02d:%02d.%03d",
|
||||
val.year, val.month, val.day,
|
||||
val.hour, val.minute, val.second,
|
||||
val.fraction / 1000000);
|
||||
DASSERT(n>=0);
|
||||
DASSERT(n<sizeof(utf8));
|
||||
size_t len = (size_t)n;
|
||||
TSDB_CONV_CODE code = tsdb_conv_write(cnv, utf8, &len, dst, dlen);
|
||||
*dlen = (size_t)n+1;
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_bit(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_bit(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_tinyint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_tinyint(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_smallint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int16_t *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_smallint(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_int(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int32_t *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_int(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_bigint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_bigint(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_ts(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_float(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, float *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_float(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_double(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, double *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_double(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_timestamp(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, SQL_TIMESTAMP_STRUCT *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_timestamp(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_timestamp_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst) {
|
||||
const char *utf8 = NULL;
|
||||
TSDB_CONV_CODE code = tsdb_conv(cnv, buffer, src, slen, &utf8, NULL);
|
||||
if (code) return code;
|
||||
code = tsdb_chars_to_timestamp_ts(utf8, sizeof(utf8), dst);
|
||||
tsdb_conv_free(cnv, utf8, buffer, src);
|
||||
return code;
|
||||
}
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, const char **dst, size_t *dlen) {
|
||||
if (!cnv) return TSDB_CONV_NOT_AVAIL;
|
||||
|
||||
char *buf;
|
||||
size_t blen;
|
||||
if (cnv->direct) {
|
||||
if (src[slen]=='\0') { // access violation?
|
||||
*dst = src;
|
||||
if (dlen) *dlen = slen;
|
||||
return TSDB_CONV_OK;
|
||||
}
|
||||
blen = slen + 1;
|
||||
} else {
|
||||
blen = (slen + 1) * 4;
|
||||
}
|
||||
|
||||
buf = stack_buffer_alloc(buffer, blen);
|
||||
if (!buf) {
|
||||
buf = (char*)malloc(blen);
|
||||
if (!buf) return TSDB_CONV_OOM;
|
||||
}
|
||||
|
||||
if (cnv->direct) {
|
||||
size_t n = slen;
|
||||
DASSERT(blen > n);
|
||||
memcpy(buf, src, n);
|
||||
buf[n] = '\0';
|
||||
*dst = buf;
|
||||
if (dlen) *dlen = n;
|
||||
return TSDB_CONV_OK;
|
||||
}
|
||||
|
||||
const char *orig_s = src;
|
||||
char *orig_d = buf;
|
||||
size_t orig_blen = blen;
|
||||
|
||||
TSDB_CONV_CODE code;
|
||||
size_t r = iconv(cnv->cnv, (char**)&src, &slen, &buf, &blen);
|
||||
do {
|
||||
if (r==(size_t)-1) {
|
||||
code = TSDB_CONV_BAD_CHAR;
|
||||
break;
|
||||
}
|
||||
if (slen) {
|
||||
code = TSDB_CONV_TRUNC;
|
||||
break;
|
||||
}
|
||||
DASSERT(blen);
|
||||
*buf = '\0';
|
||||
*dst = orig_d;
|
||||
if (dlen) *dlen = orig_blen - blen;
|
||||
return TSDB_CONV_OK;
|
||||
} while (0);
|
||||
|
||||
if (orig_d!=(char*)orig_s && !is_owned_by_stack_buffer(buffer, orig_d)) free(orig_d);
|
||||
return code;
|
||||
}
|
||||
|
||||
void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src) {
|
||||
if (ptr!=src && !is_owned_by_stack_buffer(buffer, ptr)) free((char*)ptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,17 +23,50 @@
|
|||
|
||||
typedef enum {
|
||||
TSDB_CONV_OK = 0,
|
||||
TSDB_CONV_NOT_AVAIL,
|
||||
TSDB_CONV_OOM,
|
||||
TSDB_CONV_OOR,
|
||||
TSDB_CONV_TRUNC_FRACTION,
|
||||
TSDB_CONV_TRUNC,
|
||||
TSDB_CONV_CHAR_NOT_NUM,
|
||||
TSDB_CONV_CHAR_NOT_TS,
|
||||
TSDB_CONV_GENERAL,
|
||||
TSDB_CONV_BAD_CHAR,
|
||||
} TSDB_CONV_CODE;
|
||||
|
||||
const char* tsdb_conv_code_str(TSDB_CONV_CODE code);
|
||||
|
||||
typedef struct stack_buffer_s stack_buffer_t;
|
||||
struct stack_buffer_s {
|
||||
char buf[1024*16];
|
||||
size_t next;
|
||||
};
|
||||
|
||||
char* stack_buffer_alloc(stack_buffer_t *buffer, size_t bytes);
|
||||
int is_owned_by_stack_buffer(stack_buffer_t *buffer, const char *ptr);
|
||||
|
||||
typedef struct tsdb_conv_s tsdb_conv_t;
|
||||
tsdb_conv_t* tsdb_conv_open(const char *from_enc, const char *to_enc);
|
||||
void tsdb_conv_close(tsdb_conv_t *cnv);
|
||||
TSDB_CONV_CODE tsdb_conv_write(tsdb_conv_t *cnv, const char *src, size_t *slen, char *dst, size_t *dlen);
|
||||
TSDB_CONV_CODE tsdb_conv_write_int64(tsdb_conv_t *cnv, int64_t val, char *dst, size_t *dlen);
|
||||
TSDB_CONV_CODE tsdb_conv_write_double(tsdb_conv_t *cnv, double val, char *dst, size_t *dlen);
|
||||
TSDB_CONV_CODE tsdb_conv_write_timestamp(tsdb_conv_t *cnv, SQL_TIMESTAMP_STRUCT val, char *dst, size_t *dlen);
|
||||
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_bit(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_tinyint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int8_t *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_smallint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int16_t *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_int(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int32_t *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_bigint(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_float(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, float *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_double(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, double *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_timestamp(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, SQL_TIMESTAMP_STRUCT *dst);
|
||||
TSDB_CONV_CODE tsdb_conv_chars_to_timestamp_ts(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, int64_t *dst);
|
||||
TSDB_CONV_CODE tsdb_conv(tsdb_conv_t *cnv, stack_buffer_t *buffer, const char *src, size_t slen, const char **dst, size_t *dlen);
|
||||
void tsdb_conv_free(tsdb_conv_t *cnv, const char *ptr, stack_buffer_t *buffer, const char *src);
|
||||
|
||||
|
||||
TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen);
|
||||
|
||||
|
||||
|
@ -66,6 +99,7 @@ TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst);
|
|||
TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst);
|
||||
TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst);
|
||||
TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst);
|
||||
TSDB_CONV_CODE tsdb_chars_to_timestamp(const char *src, size_t smax, SQL_TIMESTAMP_STRUCT *dst);
|
||||
TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax);
|
||||
|
||||
TSDB_CONV_CODE tsdb_wchars_to_bit(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst);
|
||||
|
|
|
@ -16,7 +16,21 @@
|
|||
#ifndef _TODBC_FLEX_H_
|
||||
#define _TODBC_FLEX_H_
|
||||
|
||||
int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host);
|
||||
typedef struct conn_val_s conn_val_t;
|
||||
struct conn_val_s {
|
||||
char *key;
|
||||
char *dsn;
|
||||
char *uid;
|
||||
char *pwd;
|
||||
char *db;
|
||||
char *host;
|
||||
char *svr_enc;
|
||||
char *cli_enc;
|
||||
};
|
||||
|
||||
|
||||
void conn_val_reset(conn_val_t *val);
|
||||
int todbc_parse_conn_string(const char *conn, conn_val_t *val);
|
||||
|
||||
#endif // _TODBC_FLEX_H_
|
||||
|
||||
|
|
|
@ -7,15 +7,6 @@
|
|||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
typedef struct params_s params_t;
|
||||
struct params_s {
|
||||
char *key;
|
||||
char *dsn;
|
||||
char *uid;
|
||||
char *pwd;
|
||||
char *host;
|
||||
};
|
||||
|
||||
#define PUSH_STATE(state) yy_push_state(state, yyscanner)
|
||||
#define POP_STATE() yy_pop_state(yyscanner)
|
||||
|
||||
|
@ -61,17 +52,32 @@ do { \
|
|||
yyextra->pwd = strdup(yytext); \
|
||||
break; \
|
||||
} \
|
||||
if (strcasecmp(yyextra->key, "DB")==0) { \
|
||||
free(yyextra->db); \
|
||||
yyextra->pwd = strdup(yytext); \
|
||||
break; \
|
||||
} \
|
||||
if (strcasecmp(yyextra->key, "HOST")==0) { \
|
||||
free(yyextra->host); \
|
||||
yyextra->host = strdup(yytext); \
|
||||
break; \
|
||||
} \
|
||||
if (strcasecmp(yyextra->key, "SERVER_ENC")==0) { \
|
||||
free(yyextra->svr_enc); \
|
||||
yyextra->host = strdup(yytext); \
|
||||
break; \
|
||||
} \
|
||||
if (strcasecmp(yyextra->key, "CLIENT_ENC")==0) { \
|
||||
free(yyextra->cli_enc); \
|
||||
yyextra->host = strdup(yytext); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
%}
|
||||
|
||||
%option prefix="todbc_yy"
|
||||
%option extra-type="struct params_s *"
|
||||
%option extra-type="conn_val_t *"
|
||||
%option nounistd
|
||||
%option never-interactive
|
||||
%option reentrant
|
||||
|
@ -115,20 +121,45 @@ do { \
|
|||
<VAL>.|\n { return -1; }
|
||||
%%
|
||||
|
||||
int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host) {
|
||||
int todbc_parse_conn_string(const char *conn, conn_val_t *val) {
|
||||
yyscan_t arg = {0};
|
||||
params_t params = {0};
|
||||
yylex_init(&arg);
|
||||
yyset_debug(0, arg);
|
||||
yyset_extra(¶ms, arg);
|
||||
yyset_extra(val, arg);
|
||||
yy_scan_string(conn, arg);
|
||||
int ret =yylex(arg);
|
||||
yylex_destroy(arg);
|
||||
*dsn = params.dsn;
|
||||
*uid = params.uid;
|
||||
*pwd = params.pwd;
|
||||
*host = params.host;
|
||||
if (val->key) free(val->key); val->key = NULL;
|
||||
if (ret) {
|
||||
conn_val_reset(val);
|
||||
}
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
void conn_val_reset(conn_val_t *val) {
|
||||
if (val->key) {
|
||||
free(val->key); val->key = NULL;
|
||||
}
|
||||
if (val->dsn) {
|
||||
free(val->dsn); val->dsn = NULL;
|
||||
}
|
||||
if (val->uid) {
|
||||
free(val->uid); val->uid = NULL;
|
||||
}
|
||||
if (val->pwd) {
|
||||
free(val->pwd); val->pwd = NULL;
|
||||
}
|
||||
if (val->db) {
|
||||
free(val->db); val->db = NULL;
|
||||
}
|
||||
if (val->host) {
|
||||
free(val->host); val->host = NULL;
|
||||
}
|
||||
if (val->svr_enc) {
|
||||
free(val->svr_enc); val->svr_enc = NULL;
|
||||
}
|
||||
if (val->cli_enc) {
|
||||
free(val->cli_enc); val->cli_enc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue