Changeset: aeb9d08b4d80 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/aeb9d08b4d80
Modified Files:
        sql/backends/monet5/vaults/odbc/odbc_loader.c
Branch: odbc_loader
Log Message:
Added checks on url, extract ODBC connection string part and SQL query string 
part.


diffs (121 lines):

diff --git a/sql/backends/monet5/vaults/odbc/odbc_loader.c 
b/sql/backends/monet5/vaults/odbc/odbc_loader.c
--- a/sql/backends/monet5/vaults/odbc/odbc_loader.c
+++ b/sql/backends/monet5/vaults/odbc/odbc_loader.c
@@ -27,8 +27,6 @@
 #include <sqlext.h>
 
 typedef struct odbc_loader_t {
-       char *url;
-       SQLCHAR *query;
        SQLHANDLE env;
        SQLHANDLE dbc;
        SQLHANDLE stmt;
@@ -67,22 +65,33 @@ odbc_relation(mvc *sql, sql_subfunc *f, 
 //     list *typelist = sa_list(sql->sa);
 //     list *nameslist = sa_list(sql->sa);
 
-       // TODO validate the url, should/could start with 'odbc:', if so
-       // remove 'odbc:' prefix from url so we get an ODBC connection string
+       if (!url || (url && strncasecmp("odbc:", url, 5) != 0))
+               return "Invalid URI. Expected to start with 'odbc:'.";
+
+       // skip 'odbc:' prefix from url so we get a connection string including 
the query
+       char * con_str = &url[5];
+       // the connection string must start with 'DSN=' or 'DRIVER=' else the 
ODBC driver manager can't load the ODBC driver
+       if (con_str && (strncasecmp("DSN=", con_str, 4) != 0) && 
(strncasecmp("DRIVER=", con_str, 7) != 0))
+               return "Invalid ODBC connection string. Should start with 
'DSN=' or 'DRIVER='.";
 
-       SQLCHAR * con_str = (SQLCHAR *) url;
-       // TODO validate the ODBC connection string, should start with 'DSN=' 
or 'DRIVER='
+       // locate the 'QUERY=' part to extract the SQL query string to execute
+       char * qry_str = strstr(con_str, "QUERY=");
+       if (qry_str == NULL)
+               return "Incomplete ODBC connection string. Missing 'QUERY=' 
part (to specify the SQL SELECT query to execute).";
 
-       // TODO get the SQL query string. Not from the url but from an 
additional provided parameter
-       // for test we use a static query:
-       SQLCHAR * query = (SQLCHAR *) "SELECT * FROM INFORMATION_SCHEMA.TABLES";
+       char * query = GDKstrdup(&qry_str[6]);  // we expect that QUERY= is at 
the end of the connection string
+
+       // create a new ODBC connection string without the QUERY= part
+       char * odbc_con_str = GDKstrndup(con_str, qry_str - con_str);
 
        SQLHANDLE env = SQL_NULL_HENV;
        SQLHANDLE dbc = SQL_NULL_HDBC;
        SQLHANDLE stmt = SQL_NULL_HSTMT;
        SQLRETURN ret;
        SQLSMALLINT nr_cols = 0;
-       char * errmsg;
+       char * errmsg = NULL;
+
+       // printf("Extracted ODBC connection string: %s\nand SQL query: %s\n", 
odbc_con_str, query);
 
        ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
        if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
@@ -91,51 +100,55 @@ odbc_relation(mvc *sql, sql_subfunc *f, 
                        ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
                        if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) 
{
                                SQLSMALLINT len = 0;
-                               ret = SQLDriverConnect(dbc, NULL, con_str, 
SQL_NTS, NULL, 0, &len, SQL_DRIVER_NOPROMPT);
+                               ret = SQLDriverConnect(dbc, NULL, (SQLCHAR *) 
odbc_con_str, SQL_NTS, NULL, 0, &len, SQL_DRIVER_NOPROMPT);
+                               // printf("After SQLDriverConnect(%s)\n", 
odbc_con_str);
                                if (ret == SQL_SUCCESS || ret == 
SQL_SUCCESS_WITH_INFO) {
                                        ret = SQLAllocHandle(SQL_HANDLE_STMT, 
dbc, &stmt);
                                        if (ret == SQL_SUCCESS || ret == 
SQL_SUCCESS_WITH_INFO) {
-                                               ret = SQLExecDirect(stmt, 
query, SQL_NTS);
+                                               ret = SQLExecDirect(stmt, 
(SQLCHAR *) query, SQL_NTS);
+                                               // printf("After 
SQLExecDirect(%s)\n", query);
                                                if (ret == SQL_SUCCESS || ret 
== SQL_SUCCESS_WITH_INFO) {
                                                        ret = 
SQLNumResultCols(stmt, &nr_cols);
+                                                       // printf("Query has %d 
result columns\n", nr_cols);
                                                        // TODO for each column 
get the name, type, size/digits and scale
                                                                // 
list_append(nameslist, name);
                                                                // 
list_append(typelist, type);
                                                } else {
-                                                       errmsg = "ODBC 
SQLExecDirect query failed.\n";
+                                                       errmsg = "ODBC 
SQLExecDirect query failed.";
                                                        goto failure;
                                                }
                                        } else {
-                                               errmsg = "Allocate ODBC STMT 
handle failed.\n";
+                                               errmsg = "Allocate ODBC STMT 
handle failed.";
                                                goto failure;
                                        }
                                } else {
-                                       errmsg = "ODBC SQLDriverConnect 
failed.\n";
+                                       errmsg = "Could not connect. ODBC 
SQLDriverConnect failed.";
                                        goto failure;
                                }
                        } else {
-                               errmsg = "Allocate ODBC DBC handle failed.\n";
+                               errmsg = "Allocate ODBC DBC handle failed.";
                                goto failure;
                        }
                } else {
-                       errmsg = "SQLSetEnvAttr (SQL_ATTR_ODBC_VERSION ODBC3) 
failed.\n";
+                       errmsg = "SQLSetEnvAttr (SQL_ATTR_ODBC_VERSION ODBC3) 
failed.";
                        goto failure;
                }
        } else {
-               errmsg = "Allocate ODBC environment handle failed.\n";
+               errmsg = "Allocate ODBC environment handle failed.";
                goto failure;
        }
 
        odbc_loader_t *r = (odbc_loader_t *)sa_alloc(sql->sa, 
sizeof(odbc_loader_t));
-       r->url = url;
-       r->query = query;
        r->env = env;
        r->dbc = dbc;
        r->stmt = stmt;
        r->nr_cols = nr_cols;
        f->sname = (char*)r; /* pass odbc_loader */
-       return NULL;
   failure:
+       if (query)
+               GDKfree(query);
+       if (odbc_con_str)
+               GDKfree(odbc_con_str);
        // TODO get DiagRecMsg to get driver err message and sqlstate
        odbc_cleanup(env, dbc, stmt);
        return errmsg;
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to