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)
|
||||
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")
|
||||
|
|
|
@ -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 *userName = NULL;
|
||||
char *auth = NULL;
|
||||
int bytes = 0;
|
||||
char *host = NULL;
|
||||
char *ip = NULL;
|
||||
int port = 0;
|
||||
|
||||
do {
|
||||
if (szConnStrIn && !connStr) {
|
||||
|
@ -2086,15 +2088,23 @@ static SQLRETURN doSQLDriverConnect(
|
|||
break;
|
||||
}
|
||||
|
||||
int n = sscanf((const char*)connStr, "DSN=%m[^;]; UID=%m[^;]; PWD=%m[^;] %n", &serverName, &userName, &auth, &bytes);
|
||||
if (n<1) {
|
||||
int n = todbc_parse_conn_string((const char *)connStr, &serverName, &userName, &auth, &host);
|
||||
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, ':');
|
||||
if (p) {
|
||||
ip = strndup(host, p-host);
|
||||
port = atoi(p+1);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: data-race
|
||||
// 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) {
|
||||
SET_ERROR(conn, "HY000", terrno, "failed to connect to data source");
|
||||
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_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,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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_WCHAR, encoding='utf-8')
|
||||
#cnxn.setencoding(encoding='utf-8')
|
||||
|
|
Loading…
Reference in New Issue