Changeset: d48c16143352 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d48c16143352
Removed Files:
        sql/test/proto_loader/odbc/Tests/monetodbc_uuid_crash.test
Modified Files:
        sql/backends/monet5/vaults/odbc/odbc_loader.c
        sql/test/proto_loader/odbc/Tests/All
        sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test
Branch: Mar2025
Log Message:

Fix server crash when reading uuid column data. It is now mapped to a char(36).


diffs (228 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
@@ -104,6 +104,15 @@ map_rescol_type(SQLSMALLINT dataType, SQ
 //                     prec = scale;   /* make precision large enough to 
contain all decimal digits */
 //             return sql_bind_subtype(sql->sa, "decimal", prec, scale);
        }
+       case SQL_GUID:
+       {
+               /* represents a uuid of length 36, such as: 
dbe7343c-1f11-4fa9-a9c8-a31cd26f92fe */
+               sql_subtype * tp = sql_bind_subtype(sql->sa, "uuid", 0, 0);     
// this fails to return a valid pointer
+               if (tp != NULL)
+                       return tp;
+               /* fall back to map it to a char(36) result column type */
+               return sql_bind_subtype(sql->sa, "char", (unsigned int) 
UUID_STRLEN, 0);
+       }
 
        case SQL_BIT:
                typenm = "boolean";
@@ -205,11 +214,6 @@ map_rescol_type(SQLSMALLINT dataType, SQ
                typenm = "sec_interval";
                interval_type = 12;
                break;
-
-       case SQL_GUID:
-               /* represents a uuid of length 36, such as: 
dbe7343c-1f11-4fa9-a9c8-a31cd26f92fe */
-               typenm = "uuid";
-               break;
        }
        return sql_bind_subtype(sql->sa, typenm, interval_type, 0);
 }
@@ -579,6 +583,7 @@ odbc_query(int caller, mvc *sql, sql_sub
                sql_subtype * sql_mtype;
                list * typelist = sa_list(sql->sa);
                list * nameslist = sa_list(sql->sa);
+               strcpy(tname, "");
                for (SQLUSMALLINT col = 1; col <= (SQLUSMALLINT) nr_cols; 
col++) {
                        /* for each result column get name, datatype, size and 
decdigits */
                        // TODO use ODBC W function
@@ -591,9 +596,12 @@ odbc_query(int caller, mvc *sql, sql_sub
                        if (trace_enabled)
                                printf("ResCol %u, name: %s, type %d (%s), size 
%u, decdigits %d\n",
                                        col, cname, dataType, 
nameofSQLtype(dataType), (unsigned int)columnSize, decimalDigits);
+                       sql_mtype = map_rescol_type(dataType, columnSize, 
decimalDigits, sql);
+                       if (sql_mtype == NULL)
+                               continue;       /* skip this column */
+
                        colname = sa_strdup(sql->sa, cname);
                        list_append(nameslist, colname);
-                       sql_mtype = map_rescol_type(dataType, columnSize, 
decimalDigits, sql);
                        list_append(typelist, sql_mtype);
 
                        if (res_exps) {
@@ -663,6 +671,10 @@ odbc_query(int caller, mvc *sql, sql_sub
                                dataType = SQL_VARCHAR; /* read it as string */
                                columnSize = 50;
                        } else
+                       if (dataType == SQL_GUID) {
+                               dataType = SQL_VARCHAR; /* read it as string */
+                               columnSize = UUID_STRLEN;
+                       } else
                        if (dataType == SQL_DECIMAL || dataType == SQL_NUMERIC) 
{
                                /* MonetDB has limits for the precision and 
scale */
                                if (columnSize > MAX_PREC || abs(decimalDigits) 
> MAX_PREC) {
@@ -909,13 +921,9 @@ odbc_query(int caller, mvc *sql, sql_sub
                                                targetValuePtr = (SQLPOINTER *) 
&itv_val;
                                                break;
                                        case SQL_GUID:
-                                               /* read guid data as string 
data */
-//                                             targetType = SQL_C_CHAR;
-//                                             targetValuePtr = (SQLPOINTER *) 
str_val;
-//                                             bufferLength = 
largestStringSize;
                                                targetType = SQL_C_GUID;
                                                targetValuePtr = (SQLPOINTER *) 
&guid_val;
-                                               bufferLength = 16;
+                                               bufferLength = (SQLLEN) 
sizeof(SQLGUID);
                                                break;
                                        case SQL_BINARY:
                                        case SQL_VARBINARY:
@@ -1180,23 +1188,28 @@ odbc_query(int caller, mvc *sql, sql_sub
                                                                        
printf("Data row %lu col %u: 
%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", row, col+1,
                                                                                
guid_val.Data1, guid_val.Data2, guid_val.Data3, guid_val.Data4[0], 
guid_val.Data4[1], guid_val.Data4[2],
                                                                                
guid_val.Data4[3], guid_val.Data4[4], guid_val.Data4[5], guid_val.Data4[6], 
guid_val.Data4[7]);
-                                                               // uuid is 16 
bytes, same as SQLGUID guid_val
-                                                               memcpy((void *) 
&uuid_val, (void *) &guid_val, sizeof(uuid));
-                                                               gdkret = 
BUNappend(b, (void *) &uuid_val, false);
+                                                               if 
(colmetadata[col].battype == TYPE_uuid) {
+                                                                       // uuid 
is 16 bytes, same as SQLGUID guid_val
+                                                                       
memcpy((void *) &uuid_val, (void *) &guid_val, sizeof(uuid));
+                                                                       gdkret 
= BUNappend(b, (void *) &uuid_val, false);
+                                                               } else {
+                                                                       gdkret 
= BUNappend(b, ATOMnilptr(b->ttype), false);
+                                                               }
                                                                break;
                                                        case SQL_BINARY:
                                                        case SQL_VARBINARY:
                                                        case SQL_LONGVARBINARY:
-                                                       case TYPE_blob:
-                                                       {
-                                                               //TODO convert 
blob_val to blob struct which starts with length (4 bytes) and next data bytes.
                                                                if 
(trace_enabled)
                                                                        
printf("Data row %lu col %u: blob_val\n", row, col+1);
-                                                               // TODO gdkret 
= BUNappend(b, (void *) blob_val, false);
-                                                               /* for now 
append NULL value, as all bats need to be the correct length */
-                                                               gdkret = 
BUNappend(b, ATOMnilptr(b->ttype), false);
+                                                               if 
(colmetadata[col].battype == TYPE_blob) {
+                                                                       //TODO 
convert blob_val to blob struct which starts with length (4 bytes) and next 
data bytes.
+                                                                       // TODO 
gdkret = BUNappend(b, (void *) blob_val, false);
+                                                                       /* for 
now append NULL value, as all bats need to be the correct length */
+                                                                       gdkret 
= BUNappend(b, ATOMnilptr(b->ttype), false);
+                                                               } else {
+                                                                       gdkret 
= BUNappend(b, ATOMnilptr(b->ttype), false);
+                                                               }
                                                                break;
-                                                       }
                                                }
                                                if (gdkret != GDK_SUCCEED)
                                                        if (trace_enabled)
@@ -1225,6 +1238,8 @@ odbc_query(int caller, mvc *sql, sql_sub
                                        *rescol = b->batCacheid;
                                        BBPkeepref(b);
                                }
+                               if (trace_enabled)
+                                       printf("col %d pass bat %d\n", col, 
b->ttype);
                        }
                        /* free locally allocated memory */
                        GDKfree(colmetadata);
@@ -1237,6 +1252,9 @@ odbc_query(int caller, mvc *sql, sql_sub
        if (odbc_con_str)
                GDKfree(odbc_con_str);
 
+       if (trace_enabled)
+               printf("caller %d at finish, ret %d (%s) errmsg %s\n", caller, 
ret, nameOfRetCode(ret), (errmsg) ? errmsg : "");
+
        if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
                /* an ODBC function call returned an error or warning, get the 
error msg from the ODBC driver */
                SQLSMALLINT handleType;
@@ -1267,7 +1285,10 @@ odbc_query(int caller, mvc *sql, sql_sub
                odbc_cleanup(env, dbc, stmt);
                return retmsg;
        }
+
        odbc_cleanup(env, dbc, stmt);
+       if (trace_enabled)
+               printf("after odbc_cleanup(%p, %p, %p) errmsg %s\n", env, dbc, 
stmt, (errmsg) ? errmsg : "");
        return (errmsg != NULL) ? (str)errmsg : MAL_SUCCEED;
 }
 
@@ -1302,14 +1323,16 @@ odbc_load(void *BE, sql_subfunc *f, char
        for (node *n = f->coltypes->h, *nn = f->colnames->h; n && nn; col++, n 
= n->next, nn = nn->next) {
                const char *name = nn->data;
                sql_subtype *tp = n->data;
-               int type = newBatType(tp->type->localtype);
-               if (col)
-                       q = pushReturn(be->mb, q, newTmpVariable(be->mb, type));
-               else
-                       getArg(q, 0) = newTmpVariable(be->mb, type);
-               stmt *s = stmt_blackbox_result(be, q, col, tp);
-               s = stmt_alias(be, s, col+1, f->tname, name);
-               list_append(l, s);
+               if (tp) {
+                       int type = newBatType(tp->type->localtype);
+                       if (col)
+                               q = pushReturn(be->mb, q, 
newTmpVariable(be->mb, type));
+                       else
+                               getArg(q, 0) = newTmpVariable(be->mb, type);
+                       stmt *s = stmt_blackbox_result(be, q, col, tp);
+                       s = stmt_alias(be, s, col+1, f->tname, name);
+                       list_append(l, s);
+               }
        }
        q = pushStr(be->mb, q, url);
        q = pushPtr(be->mb, q, f);
diff --git a/sql/test/proto_loader/odbc/Tests/All 
b/sql/test/proto_loader/odbc/Tests/All
--- a/sql/test/proto_loader/odbc/Tests/All
+++ b/sql/test/proto_loader/odbc/Tests/All
@@ -5,4 +5,3 @@ HAVE_SQLITE3ODBC&HAVE_DATA_PATH?sqlite3o
 HAVE_ODBC?monetodbc_datatypes
 KNOWNFAIL&HAVE_ODBC?monetodbc_bigdec_failure
 KNOWNFAIL&HAVE_ODBC?monetodbc_interval_day_overflow
-KNOWNFAIL&HAVE_ODBC?monetodbc_uuid_crash
diff --git a/sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test 
b/sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test
--- a/sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test
+++ b/sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test
@@ -430,3 +430,18 @@ 1:39:59.999000
 0:00:00
 NULL
 
+---- UUID ----
+
+query TTT
+select cast('eda7b074-3e0f-4bef-bdec-19c61bedb18f' as uuid) as val1, 
cast('beefc4f7-0264-4735-9b7a-75fd371ef803' as uuid) as val2, cast(NULL as 
uuid) as valnil
+----
+eda7b074-3e0f-4bef-bdec-19c61bedb18f
+beefc4f7-0264-4735-9b7a-75fd371ef803
+NULL
+
+query TTT
+select * from 'odbc:DSN=MonetDB-Test;QUERY=select 
cast(''eda7b074-3e0f-4bef-bdec-19c61bedb18f'' as uuid) as val1, 
cast(''beefc4f7-0264-4735-9b7a-75fd371ef803'' as uuid) as val2, cast(NULL as 
uuid) as valnil'
+----
+eda7b074-3e0f-4bef-bdec-19c61bedb18f
+beefc4f7-0264-4735-9b7a-75fd371ef803
+NULL
diff --git a/sql/test/proto_loader/odbc/Tests/monetodbc_uuid_crash.test 
b/sql/test/proto_loader/odbc/Tests/monetodbc_uuid_crash.test
deleted file mode 100644
--- a/sql/test/proto_loader/odbc/Tests/monetodbc_uuid_crash.test
+++ /dev/null
@@ -1,20 +0,0 @@
-query TTT
-select cast('eda7b074-3e0f-4bef-bdec-19c61bedb18f' as uuid) as val1, 
cast('beefc4f7-0264-4735-9b7a-75fd371ef803' as uuid) as val2, cast(NULL as 
uuid) as valnil
-----
-eda7b074-3e0f-4bef-bdec-19c61bedb18f
-beefc4f7-0264-4735-9b7a-75fd371ef803
-NULL
-
--- next query crashes the mserver, before calling SQLGetData(SQL_C_GUID) in 
odbc_loader.c
-query T
---select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(NULL as uuid) as 
valnil'
-----
-NULL
-
--- next query crashes the mserver, before calling SQLGetData(SQL_C_GUID) in 
odbc_loader.c
-query TT
-select * from 'odbc:DSN=MonetDB-Test;QUERY=select 
cast(''eda7b074-3e0f-4bef-bdec-19c61bedb18f'' as uuid) as val1, 
cast(''beefc4f7-0264-4735-9b7a-75fd371ef803'' as uuid) as val2'
-----
-eda7b074-3e0f-4bef-bdec-19c61bedb18f
-beefc4f7-0264-4735-9b7a-75fd371ef803
-
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to