Changeset: 6e09d66b9963 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/6e09d66b9963
Modified Files:
        sql/backends/monet5/vaults/odbc/odbc_loader.c
        sql/test/proto_loader/odbc/Tests/monetodbc-Windows.test
        sql/test/proto_loader/odbc/Tests/monetodbc.test
        sql/test/proto_loader/odbc/Tests/sqlite3odbc.test.in
Branch: Mar2025
Log Message:

Make function getErrMsg() more generic such it can be used in more places.
Added fractions part for the INTERVAL ... SECOND types.


diffs (244 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
@@ -293,21 +293,21 @@ str_to_hge(const char *s) {
 
 /* an ODBC function call returned an error, get the error msg from the ODBC 
driver */
 static char *
-getErrMsg(SQLHANDLE stmt) {
+getErrMsg(SQLSMALLINT handleType, SQLHANDLE handle) {
        SQLRETURN ret = SQL_ERROR;
        SQLCHAR state[SQL_SQLSTATE_SIZE +1];
        SQLINTEGER errnr;
        SQLCHAR msg[4096];
        SQLSMALLINT msglen;
 
-       if (stmt == SQL_NULL_HSTMT)
+       if (handle == SQL_NULL_HSTMT)
                return NULL;
 
        // TODO use ODBC W function
-       ret = SQLGetDiagRec(SQL_HANDLE_STMT, stmt, 1, state, &errnr, msg, 
(sizeof(msg) -1), &msglen);
+       ret = SQLGetDiagRec(handleType, handle, 1, state, &errnr, msg, 
(sizeof(msg) -1), &msglen);
        if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
-               char * format = "odbc_loader SQLstate %s, Errnr %d, Message %s";
-               char * retmsg = (char *) GDKmalloc(strlen(format) + msglen);
+               const char format[] = "SQLSTATE %s, Error code %d, Message %s";
+               char * retmsg = (char *) malloc(sizeof(format) + MIN(msglen, 
4096));
                if (retmsg != NULL) {
                        if (state[SQL_SQLSTATE_SIZE] != '\0')
                                state[SQL_SQLSTATE_SIZE] = '\0';
@@ -473,7 +473,7 @@ odbc_query(int caller, mvc *sql, sql_sub
                        printf("After SQLGetInfo(dbc, SQL_DBMS_NAME) returned 
%d\n", ret);
                if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
                        if (strcmp("MonetDB", name) == 0) {
-                               /* let the MonetDB driver enable returning 
HUGEINT as column datatype */
+                               /* make the MonetDB ODBC driver enable 
returning SQL_HUGEINT as column datatype */
                                ret = SQLGetTypeInfo(stmt, SQL_HUGEINT);
                                if (trace_enabled)
                                        printf("After SQLGetTypeInfo(stmt, 
SQL_HUGEINT) returned %d\n", ret);
@@ -883,11 +883,11 @@ odbc_query(int caller, mvc *sql, sql_sub
                                ret = SQLGetData(stmt, col+1, targetType, 
targetValuePtr, bufferLength, &strLen);
                                if (ret != SQL_SUCCESS && ret != 
SQL_SUCCESS_WITH_INFO) {
                                        if (trace_enabled) {
-                                               char * ODBCmsg = 
getErrMsg(stmt);
+                                               char * ODBCmsg = 
getErrMsg(SQL_HANDLE_STMT, stmt);
                                                printf("Failed to get C_type %d 
data for col %u of row %lu. ODBCmsg: %s\n",
-                                                       targetType, col+1, row, 
(ODBCmsg != NULL) ? ODBCmsg : "");
+                                                       targetType, col+1, row, 
(ODBCmsg) ? ODBCmsg : "");
                                                if (ODBCmsg)
-                                                       GDKfree(ODBCmsg);
+                                                       free(ODBCmsg);
                                        }
                                        /* as all bats need to be the correct 
length, append NULL value */
                                        if (BUNappend(b, ATOMnilptr(b->ttype), 
false) != GDK_SUCCEED)
@@ -927,6 +927,7 @@ odbc_query(int caller, mvc *sql, sql_sub
                                                                                
break;
 #ifdef HAVE_HGE
                                                                        case 
TYPE_hge:
+                                                                               
/* HUGEINT values are read as string */
                                                                                
hge_val = str_to_hge(str_val);
                                                                                
gdkret = BUNappend(b, (void *) &hge_val, false);
                                                                                
break;
@@ -964,13 +965,6 @@ odbc_query(int caller, mvc *sql, sql_sub
                                                                        
printf("Data row %lu col %u: %" PRId64 "\n", row, col+1, lng_val);
                                                                gdkret = 
BUNappend(b, (void *) &lng_val, false);
                                                                break;
-#ifdef HAVE_HGE
-//                                                     case SQL_HUGEINT:
-//                                                             if 
(trace_enabled)
-//                                                                     
printf("Data row %lu col %u: %" PRId128 "\n", row, col+1, hge_val);
-//                                                             gdkret = 
BUNappend(b, (void *) &hge_val, false);
-//                                                             break;
-#endif
                                                        case SQL_DECIMAL:
                                                        case SQL_NUMERIC:
                                                        {
@@ -1103,7 +1097,8 @@ odbc_query(int caller, mvc *sql, sql_sub
                                                        }
                                                        case 
SQL_INTERVAL_SECOND:
                                                        {
-                                                               lng_val = (lng) 
itv_val.intval.day_second.second * 1000;
+                                                               lng_val = (lng) 
(itv_val.intval.day_second.second * 1000)
+                                                                       + 
itv_val.intval.day_second.fraction;
                                                                if 
(itv_val.interval_sign == SQL_TRUE)
                                                                        lng_val 
= -lng_val;
                                                                if 
(trace_enabled)
@@ -1136,10 +1131,11 @@ odbc_query(int caller, mvc *sql, sql_sub
                                                        }
                                                        case 
SQL_INTERVAL_DAY_TO_SECOND:
                                                        {
-                                                               lng_val = (lng) 
((((((itv_val.intval.day_second.day *24)
+                                                               lng_val = (lng) 
(((((((itv_val.intval.day_second.day *24)
                                                                        + 
itv_val.intval.day_second.hour) *60)
                                                                        + 
itv_val.intval.day_second.minute) *60)
-                                                                       + 
itv_val.intval.day_second.second) *1000;
+                                                                       + 
itv_val.intval.day_second.second) *1000)
+                                                                       + 
itv_val.intval.day_second.fraction;
                                                                if 
(itv_val.interval_sign == SQL_TRUE)
                                                                        lng_val 
= -lng_val;
                                                                if 
(trace_enabled)
@@ -1160,9 +1156,10 @@ odbc_query(int caller, mvc *sql, sql_sub
                                                        }
                                                        case 
SQL_INTERVAL_HOUR_TO_SECOND:
                                                        {
-                                                               lng_val = (lng) 
((((itv_val.intval.day_second.hour *60)
+                                                               lng_val = (lng) 
(((((itv_val.intval.day_second.hour *60)
                                                                        + 
itv_val.intval.day_second.minute) *60)
-                                                                       + 
itv_val.intval.day_second.second) *1000;
+                                                                       + 
itv_val.intval.day_second.second) *1000)
+                                                                       + 
itv_val.intval.day_second.fraction;
                                                                if 
(itv_val.interval_sign == SQL_TRUE)
                                                                        lng_val 
= -lng_val;
                                                                if 
(trace_enabled)
@@ -1172,8 +1169,9 @@ odbc_query(int caller, mvc *sql, sql_sub
                                                        }
                                                        case 
SQL_INTERVAL_MINUTE_TO_SECOND:
                                                        {
-                                                               lng_val = (lng) 
((itv_val.intval.day_second.minute *60)
-                                                                       + 
itv_val.intval.day_second.second) * 1000;
+                                                               lng_val = (lng) 
(((itv_val.intval.day_second.minute *60)
+                                                                       + 
itv_val.intval.day_second.second) *1000)
+                                                                       + 
itv_val.intval.day_second.fraction;
                                                                if 
(itv_val.interval_sign == SQL_TRUE)
                                                                        lng_val 
= -lng_val;
                                                                if 
(trace_enabled)
@@ -1247,10 +1245,8 @@ odbc_query(int caller, mvc *sql, sql_sub
                /* an ODBC function call returned an error, get the error msg 
from the ODBC driver */
                SQLSMALLINT handleType;
                SQLHANDLE handle;
-               SQLCHAR state[SQL_SQLSTATE_SIZE +1];
-               SQLINTEGER errnr;
-               SQLCHAR msg[2048];
-               SQLSMALLINT msglen;
+               str retmsg;
+               char * ODBCmsg;
 
                /* get err message(s) from the right handle */
                if (stmt != SQL_NULL_HSTMT) {
@@ -1264,20 +1260,16 @@ odbc_query(int caller, mvc *sql, sql_sub
                        handleType = SQL_HANDLE_ENV;
                        handle = env;
                }
-               // TODO use ODBC W function
-               ret = SQLGetDiagRec(handleType, handle, 1, state, &errnr, msg, 
(sizeof(msg) -1), &msglen);
-               if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
-                       str retmsg;
-                       if (state[SQL_SQLSTATE_SIZE] != '\0')
-                               state[SQL_SQLSTATE_SIZE] = '\0';
-                       if (errmsg != NULL) {
-                               retmsg = sa_message(sql->sa, "odbc_loader" " %s 
SQLstate %s, Errnr %d, Message %s", errmsg, (char*)state, errnr, (char*)msg);
-                       } else {
-                               retmsg = sa_message(sql->sa, "odbc_loader" " 
SQLstate %s, Errnr %d, Message %s", (char*)state, errnr, (char*)msg);
-                       }
-                       odbc_cleanup(env, dbc, stmt);
-                       return retmsg;
+               ODBCmsg = getErrMsg(handleType, handle);
+               if (errmsg != NULL) {
+                       retmsg = sa_message(sql->sa, "odbc_loader" " %s %s", 
errmsg, (ODBCmsg) ? ODBCmsg : "");
+               } else {
+                       retmsg = sa_message(sql->sa, "odbc_loader" " %s", 
(ODBCmsg) ? ODBCmsg : "");
                }
+               if (ODBCmsg)
+                       free(ODBCmsg);
+               odbc_cleanup(env, dbc, stmt);
+               return retmsg;
        }
        odbc_cleanup(env, dbc, stmt);
        return (errmsg != NULL) ? (str)errmsg : MAL_SUCCEED;
diff --git a/sql/test/proto_loader/odbc/Tests/monetodbc-Windows.test 
b/sql/test/proto_loader/odbc/Tests/monetodbc-Windows.test
--- a/sql/test/proto_loader/odbc/Tests/monetodbc-Windows.test
+++ b/sql/test/proto_loader/odbc/Tests/monetodbc-Windows.test
@@ -6,28 +6,28 @@ select * from proto_loader('odbc:Driver=
 statement error 42000!CATALOG: no such table returning function 'proto_loader'
 select * from proto_loader('odbc:DRIVER=/usr/lib64/libMonetODBC.so', 
'monetdb', 'monetdb', 'SELECT * FROM INFORMATION_SCHEMA.TABLES')
 
---statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate 08001, Errnr 0, Message [MonetDB][ODBC Driver 
11.51.5]could not connect: Connection refused'
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate 08001, Errnr 0, Message [MonetDB][ODBC Driver 
...
+--statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE 08001, Error code 0, Message [MonetDB][ODBC 
Driver 11.51.5]could not connect: Connection refused'
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE 08001, Error code 0, Message [MonetDB][ODBC 
Driver ...
 select * from proto_loader('odbc:DSN=MonetDB;QUERY=SELECT * FROM 
INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate HY000, Errnr 556, Message General error: 
Invalid file dsn '''
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE HY000, Error code 556, Message General error: 
Invalid file dsn '''
 select * from proto_loader('odbc:FILEDSN=MonetDB;QUERY=SELECT * FROM 
INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate IM002, Errnr 0, Message [Microsoft][ODBC 
Driver Manager] Data source name not found and no default driver specified'
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE IM002, Error code 0, Message [Microsoft][ODBC 
Driver Manager] Data source name not found and no default driver specified'
 select * from proto_loader('odbc:DRIVER=MonetODBC.dll;QUERY=SELECT * FROM 
INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate IM002, Errnr 0, Message [Microsoft][ODBC 
Driver Manager] Data source name not found and no default driver specified'
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE IM002, Error code 0, Message [Microsoft][ODBC 
Driver Manager] Data source name not found and no default driver specified'
 select * from 
proto_loader('odbc:DRIVER=/usr/lib64/libMonetODBC.so;UID=monetdb;PWD=monetdb;QUERY=SELECT
 * FROM INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate 08001, Errnr 0, Message [MonetDB][ODBC Driver 
...
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE 08001, Error code 0, Message [MonetDB][ODBC 
Driver ...
 select * from 
proto_loader('odbc:DSN=MonetDB;UID=monetdb;PWD=monetdb;QUERY=SELECT * FROM 
INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate 08001, Errnr 0, Message [MonetDB][ODBC Driver 
...
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE 08001, Error code 0, Message [MonetDB][ODBC 
Driver ...
 select * from 
proto_loader('odbc:DSN=MonetDB;Database=demo;UID=monetdb;PWD=monetdb;QUERY=SELECT
 * FROM INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate 08001, Errnr 0, Message [MonetDB][ODBC Driver 
...
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE 08001, Error code 0, Message [MonetDB][ODBC 
Driver ...
 select * from 
proto_loader('odbc:DSN=MonetDB;Database=mTests_sql_test_proto_loader_odbc;UID=monetdb;PWD=monetdb;QUERY=SELECT
 * FROM INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate 08001, Errnr 0, Message [MonetDB][ODBC Driver 
...
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE 08001, Error code 0, Message [MonetDB][ODBC 
Driver ...
 select * from 
proto_loader('odbc:DSN=MonetDB;Database=mTests_sql_test_proto_loader_odbc;Port=40655;UID=monetdb;PWD=monetdb;QUERY=SELECT
 * FROM INFORMATION_SCHEMA.TABLES')
 
diff --git a/sql/test/proto_loader/odbc/Tests/monetodbc.test 
b/sql/test/proto_loader/odbc/Tests/monetodbc.test
--- a/sql/test/proto_loader/odbc/Tests/monetodbc.test
+++ b/sql/test/proto_loader/odbc/Tests/monetodbc.test
@@ -6,10 +6,10 @@ select * from proto_loader('odbc:Dsn=Mon
 statement error 42000!CATALOG: no such table returning function 'proto_loader'
 select * from proto_loader('odbc:DSN=MonetDB-Test', 'monetdb', 'monetdb', 
'SELECT * FROM INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate IM002, Errnr 0, Message [unixODBC][Driver 
Manager]Data source name not found and no default driver specified'
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE IM002, Error code 0, Message 
[unixODBC][Driver Manager]Data source name not found and no default driver 
specified'
 select * from proto_loader('odbc:FILEDSN=MonetDB-Test;QUERY=SELECT * FROM 
INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate 01000, Errnr 0, Message [unixODBC][Driver 
Manager]Can't open lib 'libMonetODBC' : file not found'
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE 01000, Error code 0, Message 
[unixODBC][Driver Manager]Can't open lib 'libMonetODBC' : file not found'
 select * from proto_loader('odbc:DRIVER=libMonetODBC;QUERY=SELECT * FROM 
INFORMATION_SCHEMA.TABLES')
 
 query TT
diff --git a/sql/test/proto_loader/odbc/Tests/sqlite3odbc.test.in 
b/sql/test/proto_loader/odbc/Tests/sqlite3odbc.test.in
--- a/sql/test/proto_loader/odbc/Tests/sqlite3odbc.test.in
+++ b/sql/test/proto_loader/odbc/Tests/sqlite3odbc.test.in
@@ -1,12 +1,12 @@
 -- test with 'odbc:DRIVER=/usr/lib64/libsqlite3odbc.so;' protocol specification
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate HY000, Errnr 14, Message [SQLite]connect 
failed'
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE HY000, Error code 14, Message [SQLite]connect 
failed'
 select * from 
proto_loader('odbc:DRIVER=/usr/lib64/libsqlite3odbc.so;QUERY=SELECT * FROM 
INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLstate HY000, Errnr 14, Message [SQLite]connect 
failed'
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLDriverConnect failed. SQLSTATE HY000, Error code 14, Message [SQLite]connect 
failed'
 select * from 
proto_loader('odbc:DRIVER=/usr/lib64/libsqlite3odbc.so;Database=~/Downloads/sqlite_dbs/chinook.db;QUERY=SELECT
 * FROM INFORMATION_SCHEMA.TABLES')
 
-statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLExecDirect query failed. SQLstate HY000, Errnr 1, Message [SQLite]no such 
table: INFORMATION_SCHEMA.TABLES (1)'
+statement error 42000!SELECT: proto_loader function failed 'odbc_loader 
SQLExecDirect query failed. SQLSTATE HY000, Error code 1, Message [SQLite]no 
such table: INFORMATION_SCHEMA.TABLES (1)'
 select * from 
proto_loader('odbc:DRIVER=/usr/lib64/libsqlite3odbc.so;Database=odbc_loader_test.db;QUERY=SELECT
 * FROM INFORMATION_SCHEMA.TABLES')
 
 query TTT
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to