提交 a11a2dac 编写于 作者: sangshuduo's avatar sangshuduo

Merge branch 'freemine-3981' into coverity

......@@ -268,7 +268,6 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) {
if (1) {
// allow user bind param data with different type
short size = 0;
union {
int8_t v1;
int16_t v2;
......@@ -600,7 +599,7 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) {
if ((*bind->length) > (uintptr_t)param->bytes) {
return TSDB_CODE_TSC_INVALID_VALUE;
}
size = (short)*bind->length;
short size = (short)*bind->length;
STR_WITH_SIZE_TO_VARSTR(data + param->offset, bind->buffer, size);
return TSDB_CODE_SUCCESS;
} break;
......
......@@ -3,7 +3,6 @@ PROJECT(TDengine)
IF (TD_LINUX_64)
find_program(HAVE_ODBCINST NAMES odbcinst)
IF (HAVE_ODBCINST)
include(CheckSymbolExists)
# shall we revert CMAKE_REQUIRED_LIBRARIES and how?
......@@ -14,17 +13,13 @@ IF (TD_LINUX_64)
message(WARNING "unixodbc-dev is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc-dev")
else ()
message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built")
AUX_SOURCE_DIRECTORY(src SRC)
# generate dynamic library (*.so)
ADD_LIBRARY(todbc SHARED ${SRC})
SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1)
TARGET_LINK_LIBRARIES(todbc taos)
install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/install.sh ${CMAKE_BINARY_DIR})")
ADD_SUBDIRECTORY(tests)
find_package(FLEX)
if(NOT FLEX_FOUND)
message(FATAL_ERROR "you need to install flex first")
else ()
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(tests)
endif()
endif()
ELSE ()
message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc")
......
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(TDengine)
IF (TD_LINUX_64)
FLEX_TARGET(todbcFlexScanner
todbc_scanner.l
${CMAKE_CURRENT_BINARY_DIR}/todbc_scanner.c
)
set(todbc_flex_scanner_src
${FLEX_todbcFlexScanner_OUTPUTS}
)
AUX_SOURCE_DIRECTORY(. SRC)
# generate dynamic library (*.so)
ADD_LIBRARY(todbc SHARED ${SRC} ${todbc_flex_scanner_src})
SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1)
TARGET_LINK_LIBRARIES(todbc taos)
target_include_directories(todbc PUBLIC
.)
install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})")
ENDIF ()
此差异已折叠。
/*
* 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_conv.h"
#include "todbc_util.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
typedef struct buf_s buf_t;
struct buf_s {
char buf[1024*16+1];
char *ptr;
};
static char* buf_init(buf_t *buf, size_t len);
static void buf_clean(buf_t *buf);
static char* buf_init(buf_t *buf, size_t len) {
if (len>sizeof(buf->buf)) {
buf->ptr = (char*)malloc(len);
} else if (len>0) {
buf->ptr = &buf->buf[0];
} else {
buf->ptr = NULL;
}
return buf->ptr;
}
static void buf_clean(buf_t *buf) {
if (buf->ptr && buf->ptr != buf->buf) {
free(buf->ptr);
buf->ptr = NULL;
}
}
const char* tsdb_conv_code_str(TSDB_CONV_CODE code) {
switch (code) {
case TSDB_CONV_OK: return "TSDB_CONV_OK";
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_GENERAL: return "TSDB_CONV_GENERAL";
case TSDB_CONV_BAD_CHAR: return "TSDB_CONV_BAD_CHAR";
default: return "UNKNOWN";
};
}
TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen) {
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
char *s = (char*)src;
char *d = (char*)dst;
size_t sl = *slen;
size_t dl = *dlen;
int n = iconv(cnv, &s, &sl, &d, &dl);
int e = errno;
if (dl) *d = '\0'; // what if all consumed?
*slen = sl;
*dlen = dl;
if (e==0) {
if (n) return TSDB_CONV_BAD_CHAR;
return TSDB_CONV_OK;
}
iconv(cnv, NULL, NULL, NULL, NULL);
switch (e) {
case E2BIG: return TSDB_CONV_TRUNC;
case EILSEQ: return TSDB_CONV_BAD_CHAR;
case EINVAL: return TSDB_CONV_BAD_CHAR;
default: return TSDB_CONV_GENERAL;
}
}
// src: int
TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst) {
*dst = (int8_t)src;
if (src==0 || src==1) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst) {
*dst = (int8_t)src;
if (src == *dst) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst) {
*dst = (int16_t)src;
if (src == *dst) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_int64_to_int(int64_t src, int32_t *dst) {
*dst = (int32_t)src;
if (src == *dst) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_int64_to_bigint(int64_t src, int64_t *dst) {
*dst = src;
return TSDB_CONV_OK;
}
TSDB_CONV_CODE tsdb_int64_to_ts(int64_t src, int64_t *dst) {
*dst = src;
time_t t = (time_t)(src / 1000);
struct tm tm = {0};
if (localtime_r(&t, &tm)) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_int64_to_float(int64_t src, float *dst) {
*dst = (float)src;
int64_t v = (int64_t)*dst;
if (v==src) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst) {
*dst = (double)src;
int64_t v = (int64_t)*dst;
if (v==src) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen) {
int n = snprintf(dst, dlen, "%" PRId64 "", src);
if (n<dlen) return TSDB_CONV_OK;
return TSDB_CONV_TRUNC;
}
// src: double
TSDB_CONV_CODE tsdb_double_to_bit(double src, int8_t *dst) {
*dst = (int8_t)src;
if (src<0 || src>=2) return TSDB_CONV_OOR;
if (src == *dst) return TSDB_CONV_OK;
int64_t v = (int64_t)src;
if (v == *dst) return TSDB_CONV_TRUNC_FRACTION;
return TSDB_CONV_TRUNC;
}
TSDB_CONV_CODE tsdb_double_to_tinyint(double src, int8_t *dst) {
*dst = (int8_t)src;
if (src<SCHAR_MIN || src>SCHAR_MAX) return TSDB_CONV_OOR;
if (src == *dst) return TSDB_CONV_OK;
int64_t v = (int64_t)src;
if (v == *dst) return TSDB_CONV_TRUNC_FRACTION;
return TSDB_CONV_TRUNC;
}
TSDB_CONV_CODE tsdb_double_to_smallint(double src, int16_t *dst) {
*dst = (int16_t)src;
if (src<SHRT_MIN || src>SHRT_MAX) return TSDB_CONV_OOR;
if (src == *dst) return TSDB_CONV_OK;
int64_t v = (int64_t)src;
if (v == *dst) return TSDB_CONV_TRUNC_FRACTION;
return TSDB_CONV_TRUNC;
}
TSDB_CONV_CODE tsdb_double_to_int(double src, int32_t *dst) {
*dst = (int32_t)src;
if (src<LONG_MIN || src>LONG_MAX) return TSDB_CONV_OOR;
if (src == *dst) return TSDB_CONV_OK;
int64_t v = (int64_t)src;
if (v == *dst) return TSDB_CONV_TRUNC_FRACTION;
return TSDB_CONV_TRUNC;
}
TSDB_CONV_CODE tsdb_double_to_bigint(double src, int64_t *dst) {
*dst = (int64_t)src;
if (src<LLONG_MIN || src>LLONG_MAX) return TSDB_CONV_OOR;
if (src == *dst) return TSDB_CONV_OK;
int64_t v = (int64_t)src;
if (v == *dst) return TSDB_CONV_TRUNC_FRACTION;
return TSDB_CONV_TRUNC;
}
TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst) {
TSDB_CONV_CODE code = tsdb_double_to_bigint(src, dst);
if (code==TSDB_CONV_OK || code==TSDB_CONV_TRUNC_FRACTION) {
int64_t v = (int64_t)src;
time_t t = (time_t)(v / 1000);
struct tm tm = {0};
if (localtime_r(&t, &tm)) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
return code;
}
TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen) {
int n = snprintf(dst, dlen, "%lg", src);
if (n<dlen) return TSDB_CONV_OK;
return TSDB_CONV_TRUNC;
}
// src: SQL_TIMESTAMP_STRUCT
TSDB_CONV_CODE tsdb_timestamp_to_char(SQL_TIMESTAMP_STRUCT src, char *dst, size_t dlen) {
int n = snprintf(dst, dlen, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
src.year, src.month, src.day,
src.hour, src.minute, src.second,
src.fraction / 1000000);
if (n<dlen) return TSDB_CONV_OK;
if (strlen(dst)>=19) return TSDB_CONV_TRUNC_FRACTION;
return TSDB_CONV_TRUNC;
}
// src: chars
TSDB_CONV_CODE tsdb_chars_to_bit(const char *src, size_t smax, int8_t *dst) {
if (strcmp(src, "0")==0) {
*dst = 0;
return TSDB_CONV_OK;
}
if (strcmp(src, "1")==0) {
*dst = 1;
return TSDB_CONV_OK;
}
double v;
int bytes;
int n = sscanf(src, "%lg%n", &v, &bytes);
if (n!=1) return TSDB_CONV_CHAR_NOT_NUM;
if (bytes!=strlen(src)) return TSDB_CONV_CHAR_NOT_NUM;
if (v<0 || v>=2) return TSDB_CONV_OOR;
return TSDB_CONV_TRUNC_FRACTION;
}
TSDB_CONV_CODE tsdb_chars_to_tinyint(const char *src, size_t smax, int8_t *dst) {
int64_t v;
TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v);
if (code!=TSDB_CONV_OK) return code;
*dst = (int8_t)v;
if (v==*dst) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_chars_to_smallint(const char *src, size_t smax, int16_t *dst) {
int64_t v;
TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v);
if (code!=TSDB_CONV_OK) return code;
*dst = (int16_t)v;
if (v==*dst) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_chars_to_int(const char *src, size_t smax, int32_t *dst) {
int64_t v;
TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v);
if (code!=TSDB_CONV_OK) return code;
*dst = (int32_t)v;
if (v==*dst) return TSDB_CONV_OK;
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst) {
int bytes;
int n = sscanf(src, "%" PRId64 "%n", dst, &bytes);
if (n!=1) return TSDB_CONV_CHAR_NOT_NUM;
if (bytes==strlen(src)) {
return TSDB_CONV_OK;
}
double v;
n = sscanf(src, "%lg%n", &v, &bytes);
if (n!=1) return TSDB_CONV_CHAR_NOT_NUM;
if (bytes==strlen(src)) {
return TSDB_CONV_TRUNC_FRACTION;
}
return TSDB_CONV_OK;
}
TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst) {
int64_t v;
TSDB_CONV_CODE code = tsdb_chars_to_bigint(src, smax, &v);
if (code!=TSDB_CONV_OK) return code;
*dst = v;
if (v==*dst) {
time_t t = (time_t)(v / 1000);
struct tm tm = {0};
if (localtime_r(&t, &tm)) return TSDB_CONV_OK;
}
return TSDB_CONV_OOR;
}
TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst) {
int bytes;
int n = sscanf(src, "%g%n", dst, &bytes);
if (n==1 && bytes==strlen(src)) {
return TSDB_CONV_OK;
}
return TSDB_CONV_CHAR_NOT_NUM;
}
TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst) {
int bytes;
int n = sscanf(src, "%lg%n", dst, &bytes);
if (n==1 && bytes==strlen(src)) {
return TSDB_CONV_OK;
}
return TSDB_CONV_CHAR_NOT_NUM;
}
TSDB_CONV_CODE tsdb_chars_to_char(const char *src, size_t smax, char *dst, size_t dmax) {
int n = snprintf(dst, dmax, "%s", src);
if (n<dmax) return TSDB_CONV_OK;
return TSDB_CONV_TRUNC;
}
// src: wchars
TSDB_CONV_CODE tsdb_wchars_to_bit(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst) {
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
size_t len = smax * 2;
buf_t buf;
buf_init(&buf, len+1);
if (!buf.ptr) return TSDB_CONV_OOM;
size_t dmax = len + 1;
TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax);
if (code==TSDB_CONV_OK) {
code = tsdb_chars_to_bit(buf.ptr, len+1-dmax, dst);
}
buf_clean(&buf);
return code;
}
TSDB_CONV_CODE tsdb_wchars_to_tinyint(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst) {
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
size_t len = smax * 2;
buf_t buf;
buf_init(&buf, len+1);
if (!buf.ptr) return TSDB_CONV_OOM;
size_t dmax = len + 1;
TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax);
if (code==TSDB_CONV_OK) {
code = tsdb_chars_to_tinyint(buf.ptr, len+1-dmax, dst);
}
buf_clean(&buf);
return code;
}
TSDB_CONV_CODE tsdb_wchars_to_smallint(iconv_t cnv, const unsigned char *src, size_t smax, int16_t *dst) {
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
size_t len = smax * 2;
buf_t buf;
buf_init(&buf, len+1);
if (!buf.ptr) return TSDB_CONV_OOM;
size_t dmax = len + 1;
TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax);
if (code==TSDB_CONV_OK) {
code = tsdb_chars_to_smallint(buf.ptr, len+1-dmax, dst);
}
buf_clean(&buf);
return code;
}
TSDB_CONV_CODE tsdb_wchars_to_int(iconv_t cnv, const unsigned char *src, size_t smax, int32_t *dst) {
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
size_t len = smax * 2;
buf_t buf;
buf_init(&buf, len+1);
if (!buf.ptr) return TSDB_CONV_OOM;
size_t dmax = len + 1;
TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax);
if (code==TSDB_CONV_OK) {
code = tsdb_chars_to_int(buf.ptr, len+1-dmax, dst);
}
buf_clean(&buf);
return code;
}
TSDB_CONV_CODE tsdb_wchars_to_bigint(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst) {
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
size_t len = smax * 2;
buf_t buf;
buf_init(&buf, len+1);
if (!buf.ptr) return TSDB_CONV_OOM;
size_t dmax = len + 1;
TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax);
if (code==TSDB_CONV_OK) {
code = tsdb_chars_to_bigint(buf.ptr, len+1-dmax, dst);
}
buf_clean(&buf);
return code;
}
TSDB_CONV_CODE tsdb_wchars_to_ts(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst) {
return tsdb_wchars_to_bigint(cnv, src, smax, dst);
}
TSDB_CONV_CODE tsdb_wchars_to_float(iconv_t cnv, const unsigned char *src, size_t smax, float *dst) {
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
size_t len = smax * 2;
buf_t buf;
buf_init(&buf, len+1);
if (!buf.ptr) return TSDB_CONV_OOM;
size_t dmax = len + 1;
TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax);
if (code==TSDB_CONV_OK) {
code = tsdb_chars_to_float(buf.ptr, len+1-dmax, dst);
}
buf_clean(&buf);
return code;
}
TSDB_CONV_CODE tsdb_wchars_to_double(iconv_t cnv, const unsigned char *src, size_t smax, double *dst) {
if(cnv == (iconv_t)-1) return TSDB_CONV_GENERAL;
size_t len = smax * 2;
buf_t buf;
buf_init(&buf, len+1);
if (!buf.ptr) return TSDB_CONV_OOM;
size_t dmax = len + 1;
TSDB_CONV_CODE code = tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)buf.ptr, &dmax);
if (code==TSDB_CONV_OK) {
code = tsdb_chars_to_double(buf.ptr, len+1-dmax, dst);
}
buf_clean(&buf);
return code;
}
TSDB_CONV_CODE tsdb_wchars_to_char(iconv_t cnv, const unsigned char *src, size_t smax, char *dst, size_t dmax) {
return tsdb_iconv_conv(cnv, src, &smax, (unsigned char*)dst, &dmax);
}
/*
* 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_conv_h_
#define _todbc_conv_h_
#include <inttypes.h>
#include <sqltypes.h>
#include <stddef.h>
#include "iconv.h"
typedef enum {
TSDB_CONV_OK = 0,
TSDB_CONV_OOM,
TSDB_CONV_OOR,
TSDB_CONV_TRUNC_FRACTION,
TSDB_CONV_TRUNC,
TSDB_CONV_CHAR_NOT_NUM,
TSDB_CONV_GENERAL,
TSDB_CONV_BAD_CHAR,
} TSDB_CONV_CODE;
const char* tsdb_conv_code_str(TSDB_CONV_CODE code);
TSDB_CONV_CODE tsdb_iconv_conv(iconv_t cnv, const unsigned char *src, size_t *slen, unsigned char *dst, size_t *dlen);
TSDB_CONV_CODE tsdb_int64_to_bit(int64_t src, int8_t *dst);
TSDB_CONV_CODE tsdb_int64_to_tinyint(int64_t src, int8_t *dst);
TSDB_CONV_CODE tsdb_int64_to_smallint(int64_t src, int16_t *dst);
TSDB_CONV_CODE tsdb_int64_to_int(int64_t src, int32_t *dst);
TSDB_CONV_CODE tsdb_int64_to_bigint(int64_t src, int64_t *dst);
TSDB_CONV_CODE tsdb_int64_to_ts(int64_t src, int64_t *dst);
TSDB_CONV_CODE tsdb_int64_to_float(int64_t src, float *dst);
TSDB_CONV_CODE tsdb_int64_to_double(int64_t src, double *dst);
TSDB_CONV_CODE tsdb_int64_to_char(int64_t src, char *dst, size_t dlen);
TSDB_CONV_CODE tsdb_double_to_bit(double src, int8_t *dst);
TSDB_CONV_CODE tsdb_double_to_tinyint(double src, int8_t *dst);
TSDB_CONV_CODE tsdb_double_to_smallint(double src, int16_t *dst);
TSDB_CONV_CODE tsdb_double_to_int(double src, int32_t *dst);
TSDB_CONV_CODE tsdb_double_to_bigint(double src, int64_t *dst);
TSDB_CONV_CODE tsdb_double_to_ts(double src, int64_t *dst);
TSDB_CONV_CODE tsdb_double_to_char(double src, char *dst, size_t dlen);
TSDB_CONV_CODE tsdb_timestamp_to_char(SQL_TIMESTAMP_STRUCT src, char *dst, size_t dlen);
TSDB_CONV_CODE tsdb_chars_to_bit(const char *src, size_t smax, int8_t *dst);
TSDB_CONV_CODE tsdb_chars_to_tinyint(const char *src, size_t smax, int8_t *dst);
TSDB_CONV_CODE tsdb_chars_to_smallint(const char *src, size_t smax, int16_t *dst);
TSDB_CONV_CODE tsdb_chars_to_int(const char *src, size_t smax, int32_t *dst);
TSDB_CONV_CODE tsdb_chars_to_bigint(const char *src, size_t smax, int64_t *dst);
TSDB_CONV_CODE tsdb_chars_to_ts(const char *src, size_t smax, int64_t *dst);
TSDB_CONV_CODE tsdb_chars_to_float(const char *src, size_t smax, float *dst);
TSDB_CONV_CODE tsdb_chars_to_double(const char *src, size_t smax, double *dst);
TSDB_CONV_CODE tsdb_chars_to_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);
TSDB_CONV_CODE tsdb_wchars_to_tinyint(iconv_t cnv, const unsigned char *src, size_t smax, int8_t *dst);
TSDB_CONV_CODE tsdb_wchars_to_smallint(iconv_t cnv, const unsigned char *src, size_t smax, int16_t *dst);
TSDB_CONV_CODE tsdb_wchars_to_int(iconv_t cnv, const unsigned char *src, size_t smax, int32_t *dst);
TSDB_CONV_CODE tsdb_wchars_to_bigint(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst);
TSDB_CONV_CODE tsdb_wchars_to_ts(iconv_t cnv, const unsigned char *src, size_t smax, int64_t *dst);
TSDB_CONV_CODE tsdb_wchars_to_float(iconv_t cnv, const unsigned char *src, size_t smax, float *dst);
TSDB_CONV_CODE tsdb_wchars_to_double(iconv_t cnv, const unsigned char *src, size_t smax, double *dst);
TSDB_CONV_CODE tsdb_wchars_to_char(iconv_t cnv, const unsigned char *src, size_t smax, char *dst, size_t dmax);
#endif // _todbc_conv_h_
/*
* 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_log_h_
#define _todbc_log_h_
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#define D(fmt, ...) \
fprintf(stderr, \
"%s[%d]:%s() " fmt "\n", \
basename((char*)__FILE__), __LINE__, __func__, \
##__VA_ARGS__)
#define DASSERT(statement) \
do { \
if (statement) break; \
D("Assertion failure: %s", #statement); \
abort(); \
} while (0)
#define DASSERTX(statement, fmt, ...) \
do { \
if (statement) break; \
D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \
abort(); \
} while (0)
#endif // _todbc_log_h_
%{
#include "todbc_util.h"
#include <stdio.h>
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)
#define CHG_STATE(state) \
do { \
yy_pop_state(yyscanner); \
yy_push_state(state, yyscanner); \
} while (0)
#define TOP_STATE(top) \
do { \
yy_push_state(INITIAL, yyscanner); \
top = yy_top_state(yyscanner); \
yy_pop_state(yyscanner); \
} while (0)
#define UNPUT() \
do { \
while (yyleng) unput(yytext[yyleng-1]); \
} while (0)
#define set_key() \
do { \
free(yyextra->key); \
yyextra->key = strdup(yytext); \
} while (0)
#define set_val() \
do { \
if (!yyextra->key) break; \
if (strcasecmp(yyextra->key, "DSN")==0) { \
free(yyextra->dsn); \
yyextra->dsn = strdup(yytext); \
break; \
} \
if (strcasecmp(yyextra->key, "UID")==0) { \
free(yyextra->uid); \
yyextra->uid = strdup(yytext); \
break; \
} \
if (strcasecmp(yyextra->key, "PWD")==0) { \
free(yyextra->pwd); \
yyextra->pwd = strdup(yytext); \
break; \
} \
if (strcasecmp(yyextra->key, "HOST")==0) { \
free(yyextra->host); \
yyextra->host = strdup(yytext); \
break; \
} \
} while (0)
%}
%option prefix="todbc_yy"
%option extra-type="struct params_s *"
%option reentrant
%option noyywrap
%option noinput nounput
%option debug verbose
%option stack
%option nodefault
%option warn
%option perf-report
%option 8bit
%x KEY EQ BRACE1 BRACE2 VAL
%%
<<EOF>> { int state; TOP_STATE(state);
if (state == INITIAL) yyterminate();
if (state == VAL) yyterminate();
return -1; }
[[:space:]]+ { }
[[:alnum:]]+ { set_key(); PUSH_STATE(KEY); }
.|\n { return -1; }
<KEY>[[:space:]]+ { }
<KEY>[=] { CHG_STATE(EQ); }
<KEY>.|\n { return -1; }
<EQ>[[:space:]]+ { }
<EQ>[^][{}(),;?*=!@/\\\n[:space:]]+ { set_val(); CHG_STATE(VAL); }
<EQ>[{] { CHG_STATE(BRACE1); }
<EQ>.|\n { return -1; }
<BRACE1>[[:space:]]+ { }
<BRACE1>[^{}\n[:space:]]+ { set_val(); CHG_STATE(BRACE2); }
<BRACE1>.|\n { return -1; }
<BRACE2>[[:space:]]+ { }
<BRACE2>[}] { CHG_STATE(VAL); }
<BRACE2>.|\n { return -1; }
<VAL>[;] { POP_STATE(); }
<VAL>.|\n { return -1; }
%%
int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host) {
yyscan_t arg = {0};
params_t params = {0};
yylex_init(&arg);
yyset_debug(0, arg);
yyset_extra(&params, 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;
return ret ? -1 : 0;
}
......@@ -236,3 +236,19 @@ SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes)
return dst;
}
size_t wchars_to_chars2(const SQLWCHAR *src, size_t slen, SQLCHAR *dst, size_t dlen)
{
size_t consumed=0, generated=0;
int n = string_conv("UCS-2LE", "UTF-8", (const unsigned char*)src, slen, dst, dlen, &consumed, &generated);
if (n) return -1;
return generated;
}
size_t chars_to_wchars2(const SQLCHAR *src, size_t slen, SQLWCHAR *dst, size_t dlen)
{
size_t consumed=0, generated=0;
int n = string_conv("UTF-8", "UCS-2LE", (const unsigned char*)src, slen, (unsigned char*)dst, dlen, &consumed, &generated);
if (n) return -1;
return generated;
}
......@@ -16,40 +16,19 @@
#ifndef _TODBC_UTIL_H_
#define _TODBC_UTIL_H_
#include <libgen.h>
#include "todbc_log.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)
#define DASSERTX(statement, fmt, ...) \
do { \
if (statement) break; \
D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \
abort(); \
} while (0)
const char* sql_sql_type(int type);
const char* sql_c_type(int type);
int is_valid_sql_c_type(int type);
int is_valid_sql_sql_type(int type);
int todbc_parse_conn_string(const char *conn, char **dsn, char **uid, char **pwd, char **host);
int string_conv(const char *fromcode, const char *tocode,
const unsigned char *src, size_t sbytes,
unsigned char *dst, size_t dbytes,
......@@ -60,4 +39,8 @@ 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);
size_t wchars_to_chars2(const SQLWCHAR *src, size_t slen, SQLCHAR *dst, size_t dlen);
size_t chars_to_wchars2(const SQLCHAR *src, size_t slen, SQLWCHAR *dst, size_t dlen);
#endif // _TODBC_UTIL_H_
#include <libgen.h>
#include <sql.h>
#include <sqlext.h>
......@@ -5,11 +6,20 @@
#include <string.h>
#include "os.h"
#include "../src/todbc_log.h"
// static const char *dsn = "TAOS_DSN";
// static const char *uid = "root";
// static const char *pwd = "taosdata";
#define CHK_TEST(statement) \
do { \
D("testing: %s", #statement); \
int r = (statement); \
if (r) return 1; \
} while (0);
typedef struct data_s data_t;
struct data_s {
int64_t ts;
......@@ -37,7 +47,7 @@ static const char *pro_stmts[] = {
// "drop database db"
};
#define CHK_RESULT(r, ht, h) \
#define CHK_RESULT(r, ht, h, fmt, ...) \
do { \
if (r==0) break; \
SQLCHAR ss[10]; \
......@@ -48,23 +58,124 @@ do {
es[0] = '\0'; \
SQLRETURN ret = SQLGetDiagRec(ht, h, 1, ss, &ne, es, sizeof(es), &n); \
if (ret) break; \
fprintf(stderr, "%s%s\n", ss, es); \
D("[%s]%s: " fmt "", ss, es, ##__VA_ARGS__); \
} while (0)
static int open_connect(const char *dsn, const char *uid, const char *pwd, SQLHENV *pEnv, SQLHDBC *pConn) {
SQLRETURN r;
SQLHENV env = {0};
SQLHDBC conn = {0};
r = SQLAllocEnv(&env);
if (r!=SQL_SUCCESS) return 1;
do {
r = SQLAllocConnect(env, &conn);
CHK_RESULT(r, SQL_HANDLE_ENV, env, "");
if (r!=SQL_SUCCESS) break;
do {
r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn),
(SQLCHAR*)uid, strlen(uid),
(SQLCHAR*)pwd, strlen(pwd));
CHK_RESULT(r, SQL_HANDLE_DBC, conn, "");
if (r==SQL_SUCCESS) {
*pEnv = env;
*pConn = conn;
return 0;
}
} while (0);
SQLFreeConnect(conn);
} while (0);
SQLFreeEnv(env);
return 1;
}
static int open_driver_connect(const char *connstr, SQLHENV *pEnv, SQLHDBC *pConn) {
SQLRETURN r;
SQLHENV env = {0};
SQLHDBC conn = {0};
r = SQLAllocEnv(&env);
if (r!=SQL_SUCCESS) return 1;
do {
r = SQLAllocConnect(env, &conn);
CHK_RESULT(r, SQL_HANDLE_ENV, env, "");
if (r!=SQL_SUCCESS) break;
do {
SQLCHAR buf[4096];
SQLSMALLINT blen = 0;
SQLHDBC ConnectionHandle = conn;
SQLHWND WindowHandle = NULL;
SQLCHAR * InConnectionString = (SQLCHAR*)connstr;
SQLSMALLINT StringLength1 = strlen(connstr);
SQLCHAR * OutConnectionString = buf;
SQLSMALLINT BufferLength = sizeof(buf);
SQLSMALLINT * StringLength2Ptr = &blen;
SQLUSMALLINT DriverCompletion = SQL_DRIVER_NOPROMPT;
r = SQLDriverConnect(ConnectionHandle, WindowHandle, InConnectionString,
StringLength1, OutConnectionString, BufferLength,
StringLength2Ptr, DriverCompletion);
CHK_RESULT(r, SQL_HANDLE_DBC, conn, "");
if (r==SQL_SUCCESS) {
*pEnv = env;
*pConn = conn;
return 0;
}
} while (0);
SQLFreeConnect(conn);
} while (0);
SQLFreeEnv(env);
return 1;
}
static int do_statement(SQLHSTMT stmt, const char *statement) {
SQLRETURN r = 0;
do {
fprintf(stderr, "prepare [%s]\n", statement);
r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement));
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
r = SQLExecDirect(stmt, (SQLCHAR*)statement, SQL_NTS);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: [%s]", statement);
if (r) break;
fprintf(stderr, "execute [%s]\n", statement);
r = SQLExecute(stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
SQLSMALLINT cols = 0;
r = SQLNumResultCols(stmt, &cols);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
if (r) break;
fprintf(stderr, "done\n");
if (cols <= 0) break;
char buf[4096];
while (1) {
SQLRETURN r = SQLFetch(stmt);
if (r==SQL_NO_DATA) break;
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
for (size_t i=0; i<cols; ++i) {
SQLLEN soi = 0;
r = SQLGetData(stmt, i+1, SQL_C_CHAR, buf, sizeof(buf), &soi);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
if (r) {
if (r!=SQL_SUCCESS_WITH_INFO) {
if (i>0) fprintf(stdout, "\n");
return r;
}
}
if (soi==SQL_NULL_DATA) {
fprintf(stdout, "%snull", i==0?"":",");
} else {
fprintf(stdout, "%s\"%s\"", i==0?"":",", buf);
}
}
fprintf(stdout, "\n");
}
// r = SQLFetch(stmt);
// if (r==SQL_NO_DATA) {
// D("..........");
// r = SQL_SUCCESS;
// break;
// }
// CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
// if (r) break;
// r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement));
// CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "");
// if (r) break;
// r = SQLExecute(stmt);
// CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
// if (r) break;
} while (0);
fprintf(stderr, "r: [%x][%d]\n", r, r);
return r;
}
......@@ -77,155 +188,344 @@ static int do_insert(SQLHSTMT stmt, data_t data) {
int ignored = 0;
do {
fprintf(stderr, "prepare [%s]\n", statement);
r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement));
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 1 [%s]\n", statement);
r = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_TIMESTAMP, ignored, ignored, &data.ts, ignored, NULL);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 2 [%s]\n", statement);
r = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, ignored, ignored, &data.b, ignored, NULL);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 3 [%s]\n", statement);
r = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_TINYINT, ignored, ignored, &data.v1, ignored, NULL);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 4 [%s]\n", statement);
r = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, ignored, ignored, &data.v2, ignored, NULL);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 5 [%s]\n", statement);
r = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, ignored, ignored, &data.v4, ignored, NULL);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 6 [%s]\n", statement);
r = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, ignored, ignored, &data.v8, ignored, NULL);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 7 [%s]\n", statement);
r = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, ignored, ignored, &data.f4, ignored, NULL);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 8 [%s]\n", statement);
r = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, ignored, ignored, &data.f8, ignored, NULL);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 9 [%s]\n", statement);
lbin = SQL_NTS;
r = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sizeof(data.bin)-1, ignored, &data.bin, ignored, &lbin);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "bind 10 [%s]\n", statement);
lblob = SQL_NTS;
r = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(data.blob)-1, ignored, &data.blob, ignored, &lblob);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
fprintf(stderr, "execute [%s]\n", statement);
r = SQLExecute(stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
CHK_RESULT(r, SQL_HANDLE_STMT, stmt, "statement: %s", statement);
if (r) break;
// ts += 1;
// v = 2;
// fprintf(stderr, "execute [%s]\n", statement);
// r = SQLExecute(stmt);
// if (r) break;
fprintf(stderr, "done\n");
} while (0);
fprintf(stderr, "r: [%x][%d]\n", r, r);
return r;
}
int main(int argc, char *argv[]) {
if (argc < 4) return 1;
const char *dsn = argv[1];
const char *uid = argv[2];
const char *pwd = argv[3];
SQLRETURN r;
static int test1(const char *dsn, const char *uid, const char *pwd) {
SQLRETURN r = SQL_SUCCESS;
SQLHENV env = {0};
SQLHDBC conn = {0};
r = SQLAllocEnv(&env);
if (r!=SQL_SUCCESS) return 1;
int n = open_connect(dsn, uid, pwd, &env, &conn);
if (n) return 1;
do {
r = SQLAllocConnect(env, &conn);
CHK_RESULT(r, SQL_HANDLE_ENV, env);
SQLHSTMT stmt = {0};
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
if (r!=SQL_SUCCESS) break;
do {
r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn),
(SQLCHAR*)uid, strlen(uid),
(SQLCHAR*)pwd, strlen(pwd));
CHK_RESULT(r, SQL_HANDLE_DBC, conn);
if (r!=SQL_SUCCESS) break;
if (do_statement(stmt, "drop database if exists db")) {
r = SQL_ERROR;
break;
}
for (size_t i=0; i<sizeof(pre_stmts)/sizeof(pre_stmts[0]); ++i) {
r = do_statement(stmt, pre_stmts[i]);
if (r!=SQL_SUCCESS) break;
}
do {
data_t data = {0};
data.ts = 1591060628001;
data.b = 1;
data.v1 = 127;
data.v2 = 32767;
data.v4 = 2147483647;
data.v8 = 9223372036854775807;
data.f4 = 123.456;
data.f8 = 9999999.999999;
memset(data.bin, 0, sizeof(data.bin));
memset(data.blob, 0, sizeof(data.blob));
snprintf(data.bin, sizeof(data.bin), "hel我lo");
snprintf(data.blob, sizeof(data.blob), "world");
snprintf(data.blob, sizeof(data.blob), "wo人rld");
SQLHSTMT stmt = {0};
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
if (r!=SQL_SUCCESS) break;
do {
do_statement(stmt, "drop database db");
for (size_t i=0; i<sizeof(pre_stmts)/sizeof(pre_stmts[0]); ++i) {
r = do_statement(stmt, pre_stmts[i]);
if (r!=SQL_SUCCESS) break;
}
do {
data_t data = {0};
data.ts = 1591060628001;
data.b = 1;
data.v1 = 127;
data.v2 = 32767;
data.v4 = 2147483647;
data.v8 = 9223372036854775807;
data.f4 = 123.456;
data.f8 = 9999999.999999;
memset(data.bin, 0, sizeof(data.bin));
memset(data.blob, 0, sizeof(data.blob));
snprintf(data.bin, sizeof(data.bin), "hel我lo");
snprintf(data.blob, sizeof(data.blob), "world");
snprintf(data.blob, sizeof(data.blob), "wo人rld");
SQLHSTMT stmt = {0};
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
if (r!=SQL_SUCCESS) break;
do {
r = do_insert(stmt, data);
if (r!=SQL_SUCCESS) break;
} while (0);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
// r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
// if (r!=SQL_SUCCESS) break;
// do {
// r = do_insert(stmt, ts++, v++);
// if (r!=SQL_SUCCESS) break;
// } while (0);
// SQLFreeHandle(SQL_HANDLE_STMT, stmt);
} while (0);
r = do_insert(stmt, data);
if (r!=SQL_SUCCESS) break;
for (size_t i=0; i<sizeof(pro_stmts)/sizeof(pro_stmts[0]); ++i) {
r = do_statement(stmt, pro_stmts[i]);
if (r!=SQL_SUCCESS) break;
}
} while (0);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
// r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
// if (r!=SQL_SUCCESS) break;
// do {
// r = do_insert(stmt, ts++, v++);
// if (r!=SQL_SUCCESS) break;
// } while (0);
// SQLFreeHandle(SQL_HANDLE_STMT, stmt);
} while (0);
SQLDisconnect(conn);
if (r!=SQL_SUCCESS) break;
for (size_t i=0; i<sizeof(pro_stmts)/sizeof(pro_stmts[0]); ++i) {
r = do_statement(stmt, pro_stmts[i]);
if (r!=SQL_SUCCESS) break;
}
} while (0);
SQLFreeConnect(conn);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
} while (0);
SQLDisconnect(conn);
SQLFreeConnect(conn);
SQLFreeEnv(env);
return r ? 1 : 0;
}
int test_statements(const char *dsn, const char *uid, const char *pwd, const char **statements) {
SQLRETURN r = SQL_SUCCESS;
SQLHENV env = {0};
SQLHDBC conn = {0};
int n = open_connect(dsn, uid, pwd, &env, &conn);
if (n) return 1;
do {
SQLHSTMT stmt = {0};
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
if (r!=SQL_SUCCESS) break;
const char **p = statements;
while (*p) {
if (do_statement(stmt, *p)) {
r = SQL_ERROR;
break;
}
++p;
}
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
} while (0);
SQLDisconnect(conn);
SQLFreeConnect(conn);
SQLFreeEnv(env);
return r ? 1 : 0;
}
int test_driver_connect(const char *connstr) {
SQLRETURN r = SQL_SUCCESS;
SQLHENV env = {0};
SQLHDBC conn = {0};
int n = open_driver_connect(connstr, &env, &conn);
if (n) return 1;
SQLDisconnect(conn);
SQLFreeConnect(conn);
SQLFreeEnv(env);
return r ? 1 : 0;
}
int create_statement(SQLHENV env, SQLHDBC conn, SQLHSTMT *pStmt) {
SQLHSTMT stmt = {0};
SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
CHK_RESULT(r, SQL_HANDLE_DBC, conn, "");
if (r==SQL_SUCCESS) {
*pStmt = stmt;
return 0;
}
if (r==SQL_SUCCESS_WITH_INFO) {
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
}
return 1;
}
int do_statements(SQLHSTMT stmt, const char **statements) {
const char **p = statements;
while (p && *p) {
CHK_TEST(do_statement(stmt, *p));
++p;
}
return 0;
}
int tests_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt) {
const char *statements[] = {
"drop database if exists m",
"create database m",
"use m",
// "create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, blob binary(1), name nchar(1))",
"create table t (ts timestamp, b bool)",
"insert into t values('2020-10-10 00:00:00', 0)",
"insert into t values('2020-10-10 00:00:00.001', 1)",
NULL
};
CHK_TEST(do_statements(stmt, statements));
return 0;
}
int tests(SQLHENV env, SQLHDBC conn) {
SQLHSTMT stmt = {0};
CHK_TEST(create_statement(env, conn, &stmt));
int r = tests_stmt(env, conn, stmt);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
return r ? 1 : 0;
}
int test_env(void) {
SQLRETURN r;
SQLHENV env = {0};
r = SQLAllocEnv(&env);
if (r!=SQL_SUCCESS) return 1;
SQLFreeEnv(env);
return 0;
}
int test_sqls_in_stmt(SQLHENV env, SQLHDBC conn, SQLHSTMT stmt, const char *sqls) {
FILE *f = fopen(sqls, "rb");
if (!f) {
D("failed to open file [%s]", sqls);
return -1;
}
int r = 0;
while (!feof(f)) {
char *line = NULL;
size_t len = 0;
ssize_t n = getline(&line, &len, f);
if (n==-1) break;
const char *p = NULL;
do {
if (line[0] == '#') break;
if (line[n-1] == '\n') line[n-1]='\0';
p = line;
while (isspace(*p)) ++p;
if (*p==0) break;
int positive = 1;
if (strncmp(p, "N:", 2)==0) {
positive = 0;
p += 2;
} else if (strncmp(p, "P:", 2)==0) {
p += 2;
}
D("statement: [%s]", p);
r = do_statement(stmt, p);
if (positive && r==0) break;
if (!positive && r) { r = 0; break; }
if (positive) return r;
D("expecting negative result, but got positive");
return -1;
} while (0);
free(line);
if (r) break;
}
fclose(f);
return r ? 1 : 0;
}
int test_sqls_in_conn(SQLHENV env, SQLHDBC conn, const char *sqls) {
SQLHSTMT stmt = {0};
CHK_TEST(create_statement(env, conn, &stmt));
int r = test_sqls_in_stmt(env, conn, stmt, sqls);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
return r ? 1 : 0;
}
int test_sqls(const char *dsn, const char *uid, const char *pwd, const char *connstr, const char *sqls) {
int r = 0;
SQLHENV env = {0};
SQLHDBC conn = {0};
if (dsn) {
CHK_TEST(open_connect(dsn, uid, pwd, &env, &conn));
} else {
CHK_TEST(open_driver_connect(connstr, &env, &conn));
}
r = test_sqls_in_conn(env, conn, sqls);
SQLDisconnect(conn);
SQLFreeConnect(conn);
SQLFreeEnv(env);
return r ? 1 : 0;
}
int main(int argc, char *argv[]) {
if (argc==1) {
CHK_TEST(test_env());
return 0;
}
const char *dsn = (argc>1) ? argv[1] : NULL;
const char *uid = (argc>2) ? argv[2] : NULL;
const char *pwd = (argc>3) ? argv[3] : NULL;
const char *connstr = (argc>4) ? argv[4] : NULL;
const char *sqls = (argc>5) ? argv[5] : NULL;
if (0) {
CHK_TEST(test_env());
CHK_TEST(test1(dsn, uid, pwd));
const char *statements[] = {
"drop database if exists m",
"create database m",
"use m",
"drop database m",
NULL
};
CHK_TEST(test_statements(dsn, uid, pwd, statements));
if (connstr)
CHK_TEST(test_driver_connect(connstr));
if (connstr) {
SQLHENV env = {0};
SQLHDBC conn = {0};
CHK_TEST(open_driver_connect(connstr, &env, &conn));
int r = tests(env, conn);
SQLDisconnect(conn);
SQLFreeConnect(conn);
SQLFreeEnv(env);
if (r) return 1;
}
}
if ((dsn || connstr) && 1) {
CHK_TEST(test_sqls(dsn, uid, pwd, connstr, sqls));
}
return 0;
}
import pyodbc
cnxn = pyodbc.connect('DSN=TAOS_DSN;UID=root;PWD=taosdata', autocommit=True)
# cnxn = pyodbc.connect('DSN={TAOS_DSN};UID={ root };PWD={ taosdata };HOST={ localhost:6030 }', autocommit=True)
cnxn = pyodbc.connect('DSN={TAOS_DSN}; UID=root;PWD=taosdata; HOST=localhost:6030', autocommit=True)
cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
#cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
#cnxn.setencoding(encoding='utf-8')
......@@ -118,3 +119,13 @@ while row:
row = cursor.fetchone()
cursor.close()
cursor = cnxn.cursor()
cursor.execute("create table db.f (ts timestamp, v1 float)")
cursor.close()
params = [ ('2020-10-20 00:00:10', '123.3') ]
cursor = cnxn.cursor()
cursor.fast_executemany = True
cursor.executemany("insert into db.f values (?, ?)", params)
cursor.close()
......@@ -355,20 +355,23 @@ TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_NULL, 0, 0x11A5, "value not
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_TYPE, 0, 0x11A6, "value type should be boolean, number or string")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, 0, 0x2101, "out of memory")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OOM, 0, 0x2100, "out of memory")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_CHAR_NOT_NUM, 0, 0x2101, "convertion not a valid literal input")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_UNDEF, 0, 0x2102, "convertion undefined")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC, 0, 0x2103, "convertion truncated")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_SUPPORT, 0, 0x2104, "convertion not supported")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OUT_OF_RANGE, 0, 0x2105, "out of range")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NOT_SUPPORT, 0, 0x2106, "not supported yet")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_HANDLE, 0, 0x2107, "invalid handle")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_RESULT, 0, 0x2108, "no result set")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_FIELDS, 0, 0x2109, "no fields returned")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_CURSOR, 0, 0x2110, "invalid cursor")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_STATEMENT_NOT_READY, 0, 0x2111, "statement not ready")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONNECTION_BUSY, 0, 0x2112, "connection still busy")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_CONNSTR, 0, 0x2113, "bad connection string")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_ARG, 0, 0x2114, "bad argument")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC_FRAC, 0, 0x2103, "convertion fractional truncated")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_TRUNC, 0, 0x2104, "convertion truncated")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_NOT_SUPPORT, 0, 0x2105, "convertion not supported")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONV_OOR, 0, 0x2106, "convertion numeric value out of range")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_OUT_OF_RANGE, 0, 0x2107, "out of range")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NOT_SUPPORT, 0, 0x2108, "not supported yet")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_HANDLE, 0, 0x2109, "invalid handle")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_RESULT, 0, 0x210a, "no result set")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_NO_FIELDS, 0, 0x210b, "no fields returned")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_INVALID_CURSOR, 0, 0x210c, "invalid cursor")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_STATEMENT_NOT_READY, 0, 0x210d, "statement not ready")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_CONNECTION_BUSY, 0, 0x210e, "connection still busy")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_CONNSTR, 0, 0x210f, "bad connection string")
TAOS_DEFINE_ERROR(TSDB_CODE_ODBC_BAD_ARG, 0, 0x2110, "bad argument")
#ifdef TAOS_ERROR_C
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册