add flex-scanner to parse driver connection string
This commit is contained in:
parent
aadbd94fb1
commit
e6fba26472
|
@ -3,7 +3,6 @@ PROJECT(TDengine)
|
||||||
|
|
||||||
IF (TD_LINUX_64)
|
IF (TD_LINUX_64)
|
||||||
find_program(HAVE_ODBCINST NAMES odbcinst)
|
find_program(HAVE_ODBCINST NAMES odbcinst)
|
||||||
|
|
||||||
IF (HAVE_ODBCINST)
|
IF (HAVE_ODBCINST)
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
# shall we revert CMAKE_REQUIRED_LIBRARIES and how?
|
# 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")
|
message(WARNING "unixodbc-dev is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc-dev")
|
||||||
else ()
|
else ()
|
||||||
message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built")
|
message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built")
|
||||||
AUX_SOURCE_DIRECTORY(src SRC)
|
find_package(FLEX)
|
||||||
|
if(NOT FLEX_FOUND)
|
||||||
# generate dynamic library (*.so)
|
message(FATAL_ERROR "you need to install flex first")
|
||||||
ADD_LIBRARY(todbc SHARED ${SRC})
|
else ()
|
||||||
SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
ADD_SUBDIRECTORY(src)
|
||||||
SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1)
|
ADD_SUBDIRECTORY(tests)
|
||||||
TARGET_LINK_LIBRARIES(todbc taos)
|
endif()
|
||||||
|
|
||||||
install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/install.sh ${CMAKE_BINARY_DIR})")
|
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(tests)
|
|
||||||
endif()
|
endif()
|
||||||
ELSE ()
|
ELSE ()
|
||||||
message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc")
|
message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc")
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
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 ()
|
||||||
|
|
|
@ -2078,7 +2078,9 @@ static SQLRETURN doSQLDriverConnect(
|
||||||
char *serverName = NULL;
|
char *serverName = NULL;
|
||||||
char *userName = NULL;
|
char *userName = NULL;
|
||||||
char *auth = NULL;
|
char *auth = NULL;
|
||||||
int bytes = 0;
|
char *host = NULL;
|
||||||
|
char *ip = NULL;
|
||||||
|
int port = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (szConnStrIn && !connStr) {
|
if (szConnStrIn && !connStr) {
|
||||||
|
@ -2086,15 +2088,23 @@ static SQLRETURN doSQLDriverConnect(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = sscanf((const char*)connStr, "DSN=%m[^;]; UID=%m[^;]; PWD=%m[^;] %n", &serverName, &userName, &auth, &bytes);
|
int n = todbc_parse_conn_string((const char *)connStr, &serverName, &userName, &auth, &host);
|
||||||
if (n<1) {
|
if (n) {
|
||||||
SET_ERROR(conn, "HY000", TSDB_CODE_ODBC_BAD_CONNSTR, "unrecognized connection string: [%s]", (const char*)szConnStrIn);
|
SET_ERROR(conn, "HY000", TSDB_CODE_ODBC_BAD_CONNSTR, "unrecognized connection string: [%s]", (const char*)szConnStrIn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (host) {
|
||||||
|
char *p = strchr(host, ':');
|
||||||
|
if (p) {
|
||||||
|
ip = strndup(host, p-host);
|
||||||
|
port = atoi(p+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: data-race
|
// TODO: data-race
|
||||||
// TODO: shall receive ip/port from odbc.ini
|
// TODO: shall receive ip/port from odbc.ini
|
||||||
conn->taos = taos_connect("localhost", userName, auth, NULL, 0);
|
conn->taos = taos_connect(ip ? ip : "localhost", userName, auth, NULL, port);
|
||||||
|
free(ip); ip = NULL;
|
||||||
if (!conn->taos) {
|
if (!conn->taos) {
|
||||||
SET_ERROR(conn, "HY000", terrno, "failed to connect to data source");
|
SET_ERROR(conn, "HY000", terrno, "failed to connect to data source");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
%{
|
||||||
|
#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]+ { set_val(); CHG_STATE(VAL); }
|
||||||
|
<EQ>[{] { CHG_STATE(BRACE1); }
|
||||||
|
<EQ>.|\n { return -1; }
|
||||||
|
|
||||||
|
<BRACE1>[^{}\n]+ { set_val(); CHG_STATE(BRACE2); }
|
||||||
|
<BRACE1>.|\n { return -1; }
|
||||||
|
|
||||||
|
<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(1, arg);
|
||||||
|
yyset_extra(¶ms, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ const char* sql_c_type(int type);
|
||||||
int is_valid_sql_c_type(int type);
|
int is_valid_sql_c_type(int type);
|
||||||
int is_valid_sql_sql_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,
|
int string_conv(const char *fromcode, const char *tocode,
|
||||||
const unsigned char *src, size_t sbytes,
|
const unsigned char *src, size_t sbytes,
|
||||||
unsigned char *dst, size_t dbytes,
|
unsigned char *dst, size_t dbytes,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import pyodbc
|
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.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
|
cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
|
||||||
#cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
|
#cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
|
||||||
#cnxn.setencoding(encoding='utf-8')
|
#cnxn.setencoding(encoding='utf-8')
|
||||||
|
|
Loading…
Reference in New Issue