From 12d629024a5bf5ee6e887d8acf739c28da99b6fd Mon Sep 17 00:00:00 2001 From: freemine Date: Fri, 6 Nov 2020 20:13:50 +0800 Subject: [PATCH] implement windows odbc setup api --- src/connector/odbc/src/CMakeLists.txt | 2 +- src/connector/odbc/src/todbc.c | 218 ++++++++++++++++++++++++- src/connector/odbc/src/todbc_flex.h | 2 +- src/connector/odbc/src/todbc_scanner.l | 12 +- 4 files changed, 218 insertions(+), 16 deletions(-) diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt index c5ed1a4bd7..2699e1bc90 100644 --- a/src/connector/odbc/src/CMakeLists.txt +++ b/src/connector/odbc/src/CMakeLists.txt @@ -37,7 +37,7 @@ IF (TD_WINDOWS_64) ${todbc_flex_scanner_src} ${CMAKE_CURRENT_BINARY_DIR}/todbc.rc todbc.def) - TARGET_LINK_LIBRARIES(todbc taos_static) + TARGET_LINK_LIBRARIES(todbc taos_static odbccp32 legacy_stdio_definitions) target_include_directories(todbc PUBLIC .) target_compile_definitions(todbc PRIVATE "todbc_EXPORT") diff --git a/src/connector/odbc/src/todbc.c b/src/connector/odbc/src/todbc.c index cd3e0b290e..e6579d6dab 100644 --- a/src/connector/odbc/src/todbc.c +++ b/src/connector/odbc/src/todbc.c @@ -569,10 +569,18 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, D("server: %s", serverName); D("user: %s", userName); D("auth: %s", auth); - char haha[4096]; haha[0] = '\0'; - int n = SQLGetPrivateProfileString(serverName, "Server", "null", haha, sizeof(haha)-1, NULL); + char sbuf[4096]; sbuf[0] = '\0'; + int n = SQLGetPrivateProfileString(serverName, "Server", "null", sbuf, sizeof(sbuf)-1, "Odbc.ini"); D("n: %d", n); - D("haha: [%s]", haha); + D("sbuf: [%s]", sbuf); + if (n==0) snprintf(sbuf, sizeof(sbuf), "localhost:6030"); + char *ip = NULL; + int port = 0; + char *p = strchr(sbuf, ':'); + if (p) { + ip = strndup(sbuf, (size_t)(p-sbuf)); + port = atoi(p+1); + } if ((!serverName) || (!userName) || (!auth)) { SET_ERROR(conn, "HY001", TSDB_CODE_ODBC_OOM, ""); @@ -581,7 +589,7 @@ static SQLRETURN doSQLConnect(SQLHDBC ConnectionHandle, // 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, userName, auth, NULL, port); if (!conn->taos) { SET_ERROR(conn, "08001", terrno, "failed to connect to data source"); break; @@ -2561,10 +2569,10 @@ static SQLRETURN doSQLDriverConnect( } char *ip = NULL; int port = 0; - if (val.host) { - char *p = strchr(val.host, ':'); + if (val.server) { + char *p = strchr(val.server, ':'); if (p) { - ip = strndup(val.host, (size_t)(p-val.host)); + ip = strndup(val.server, (size_t)(p-val.server)); port = atoi(p+1); } } @@ -2869,19 +2877,213 @@ SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, return r; } +#define LOG(fmt, ...) \ +do { \ + FILE *fout = fopen("C:\\test\\test.log", "ab+"); \ + if (!fout) break; \ + fprintf(fout, "%s" fmt "\n", "", ##__VA_ARGS__); \ + fprintf(stderr, "%s" fmt "\n", "", ##__VA_ARGS__); \ + fclose(fout); \ +} while (0) + +typedef struct kv_s kv_t; +struct kv_s { + char *line; + int val; +}; + +static BOOL doDSNAdd(HWND hwndParent, LPCSTR lpszDriver, LPCSTR lpszAttributes) +{ + BOOL r = TRUE; + + kv_t *kvs = NULL; + + kv_t dsn = {0}; + kv_t driver = {0}; + + char driver_dll[MAX_PATH + 1]; + HMODULE hm = NULL; + + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCSTR) &ConfigDSN, &hm) == 0) + { + int ret = GetLastError(); + LOG("GetModuleHandle failed, error = %d\n", ret); + return FALSE; + } + if (GetModuleFileName(hm, driver_dll, sizeof(driver_dll)) == 0) + { + int ret = GetLastError(); + LOG("GetModuleFileName failed, error = %d\n", ret); + return FALSE; + } + LOG("path: [%s]", driver_dll); + + const char *p = lpszAttributes; + int ikvs = 0; + while (p && *p) { + LOG("attr: [%s]", p); + char *line = strdup(p); + if (!line) { r = FALSE; break; } + char *v = strchr(line, '='); + if (v) *v = '\0'; + + if (stricmp(line, "DSN")==0) { + if (!v) { r = FALSE; break; } + if (dsn.line) { + free(dsn.line); + dsn.line = NULL; + dsn.val = 0; + } + dsn.line = line; + if (v) dsn.val = v - line + 1; + } else if (stricmp(line, "Driver")==0) { + if (!v) { r = FALSE; break; } + if (driver.line) { + free(driver.line); + driver.line = NULL; + driver.val = 0; + } + driver.line = line; + if (v) driver.val = v - line + 1; + } else { + kv_t *t = (kv_t*)realloc(kvs, (ikvs+1)*sizeof(*t)); + if (!t) { r = FALSE; free(line); break; } + t[ikvs].line = line; + if (v) t[ikvs].val = v - line + 1; + + kvs = t; + ++ikvs; + } + + p += strlen(p) + 1; + } + + if (!dsn.line || !driver.line) { + LOG("lack of either DSN or Driver"); + } else { + LOG("Driver[%s]", driver.line+driver.val); + if (r) r = SQLWritePrivateProfileString("ODBC Data Sources", dsn.line+dsn.val, driver.line+driver.val, "Odbc.ini"); + LOG("r:%d", r); + if (r) r = SQLWritePrivateProfileString(dsn.line+dsn.val, "Driver", driver_dll, "Odbc.ini"); + LOG("r:%d", r); + } + + for (int i=0; r && ikey, "HOST")==0) { \ - free(yyextra->host); \ - yyextra->host = strdup(yytext); \ + free(yyextra->server); \ + yyextra->server = strdup(yytext); \ break; \ } \ if (strcasecmp(yyextra->key, "SERVER_ENC")==0) { \ free(yyextra->svr_enc); \ - yyextra->svr_enc = strdup(yytext); \ + yyextra->svr_enc = strdup(yytext); \ break; \ } \ if (strcasecmp(yyextra->key, "CLIENT_ENC")==0) { \ free(yyextra->cli_enc); \ - yyextra->cli_enc = strdup(yytext); \ + yyextra->cli_enc = strdup(yytext); \ break; \ } \ } while (0) @@ -152,8 +152,8 @@ void conn_val_reset(conn_val_t *val) { if (val->db) { free(val->db); val->db = NULL; } - if (val->host) { - free(val->host); val->host = NULL; + if (val->server) { + free(val->server); val->server = NULL; } if (val->svr_enc) { free(val->svr_enc); val->svr_enc = NULL;