Changeset: 0b9135e9878e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0b9135e9878e
Modified Files:
        clients/odbc/driver/SQLPrepare.c
        sql/common/sql_types.c
        sql/test/emptydb/Tests/check.stable.out.32bit
Branch: nested
Log Message:

merged with default


diffs (truncated from 636 to 300 lines):

diff --git a/clients/odbc/ChangeLog b/clients/odbc/ChangeLog
--- a/clients/odbc/ChangeLog
+++ b/clients/odbc/ChangeLog
@@ -1,3 +1,9 @@
 # ChangeLog file for odbc
 # This file is updated with Maddlog
 
+* Wed Jul  9 2025 Martin van Dinther <[email protected]>
+- Corrected SQLColAttribute() and SQLGetDescField() for when
+  FieldIdentifier is SQL_DESC_LITERAL_PREFIX or SQL_DESC_LITERAL_SUFFIX.
+  They will now return the correct literal prefix or suffix string
+  instead of an empty string depending on the datatype of the column.
+
diff --git a/clients/odbc/driver/ODBCDesc.c b/clients/odbc/driver/ODBCDesc.c
--- a/clients/odbc/driver/ODBCDesc.c
+++ b/clients/odbc/driver/ODBCDesc.c
@@ -460,3 +460,154 @@ ODBCLength(ODBCDescRec *rec, int lengtht
        }
        return SQL_NO_TOTAL;
 }
+
+/* the literal prefix and suffix strings depend on the sql_desc_concise_type
+   and for specific MonetDB types (inet, url, json, timetz, timestamptz)
+   on the sql_desc_type_name.
+ */
+void
+fillLiteralPrefixSuffix(ODBCDescRec *rec)
+{
+       switch (rec->sql_desc_concise_type) {
+       case SQL_CHAR:
+       case SQL_VARCHAR:
+       case SQL_LONGVARCHAR:
+       case SQL_WCHAR:
+       case SQL_WVARCHAR:
+       case SQL_WLONGVARCHAR:
+               if (rec->sql_desc_literal_prefix == NULL) {
+                       if (strcmp("inet", (char *)rec->sql_desc_type_name) == 
0) {
+                               rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("inet '");
+                       } else
+                       if (strcmp("url", (char *)rec->sql_desc_type_name) == 
0) {
+                               rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("url '");
+                       } else
+                       if (strcmp("json", (char *)rec->sql_desc_type_name) == 
0) {
+                               rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("json '");
+                       } else {
+                               rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("'");
+                       }
+               }
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("'");
+               break;
+       case SQL_TYPE_DATE:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) strdup("date 
'");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("'");
+               break;
+       case SQL_TYPE_TIME:
+               if (rec->sql_desc_literal_prefix == NULL) {
+                       if (strcmp("timetz", (char *)rec->sql_desc_type_name) 
== 0)
+                               rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("timetz '");
+                       else
+                               rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("time '");
+               }
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("'");
+               break;
+       case SQL_TYPE_TIMESTAMP:
+               if (rec->sql_desc_literal_prefix == NULL) {
+                       if (strcmp("timestamptz", (char 
*)rec->sql_desc_type_name) == 0)
+                               rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("timestamptz '");
+                       else
+                               rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("timestamp '");
+               }
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("'");
+               break;
+       case SQL_INTERVAL_YEAR:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
year");
+               break;
+       case SQL_INTERVAL_YEAR_TO_MONTH:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
year to month");
+               break;
+       case SQL_INTERVAL_MONTH:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
month");
+               break;
+       case SQL_INTERVAL_DAY:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
day");
+               break;
+       case SQL_INTERVAL_DAY_TO_HOUR:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
day to hour");
+               break;
+       case SQL_INTERVAL_DAY_TO_MINUTE:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
day to minute");
+               break;
+       case SQL_INTERVAL_DAY_TO_SECOND:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
day to second");
+               break;
+       case SQL_INTERVAL_HOUR:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
hour");
+               break;
+       case SQL_INTERVAL_HOUR_TO_MINUTE:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
hour to minute");
+               break;
+       case SQL_INTERVAL_HOUR_TO_SECOND:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
hour to second");
+               break;
+       case SQL_INTERVAL_MINUTE:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
minute");
+               break;
+       case SQL_INTERVAL_MINUTE_TO_SECOND:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
minute to second");
+               break;
+       case SQL_INTERVAL_SECOND:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) 
strdup("interval '");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("' 
second");
+               break;
+       case SQL_GUID:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) strdup("uuid 
'");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("'");
+               break;
+       case SQL_LONGVARBINARY:
+               if (rec->sql_desc_literal_prefix == NULL)
+                       rec->sql_desc_literal_prefix = (SQLCHAR *) strdup("blob 
'");
+               if (rec->sql_desc_literal_suffix == NULL)
+                       rec->sql_desc_literal_suffix = (SQLCHAR *) strdup("'");
+               break;
+       default:
+               break;
+       }
+}
diff --git a/clients/odbc/driver/ODBCDesc.h b/clients/odbc/driver/ODBCDesc.h
--- a/clients/odbc/driver/ODBCDesc.h
+++ b/clients/odbc/driver/ODBCDesc.h
@@ -95,6 +95,7 @@ void setODBCDescRecCount(ODBCDesc *desc,
 ODBCDescRec *addODBCDescRec(ODBCDesc *desc, SQLSMALLINT recno);
 
 SQLULEN ODBCLength(ODBCDescRec *rec, int lengthtype);
+void fillLiteralPrefixSuffix(ODBCDescRec *rec);
 
 SQLRETURN MNDBGetDescField(ODBCDesc *desc, SQLSMALLINT RecordNumber, 
SQLSMALLINT FieldIdentifier, SQLPOINTER Value, SQLINTEGER BufferLength, 
SQLINTEGER *StringLength);
 SQLRETURN MNDBSetDescField(ODBCDesc *desc, SQLSMALLINT RecordNumber, 
SQLSMALLINT FieldIdentifier, SQLPOINTER Value, SQLINTEGER BufferLength);
diff --git a/clients/odbc/driver/SQLColAttribute.c 
b/clients/odbc/driver/SQLColAttribute.c
--- a/clients/odbc/driver/SQLColAttribute.c
+++ b/clients/odbc/driver/SQLColAttribute.c
@@ -138,6 +138,7 @@ MNDBColAttribute(ODBCStmt *stmt,
                        *(SQLLEN *) NumericAttributePtr = rec->sql_desc_length;
                break;
        case SQL_DESC_LITERAL_PREFIX:
+               fillLiteralPrefixSuffix(rec);
                copyString(rec->sql_desc_literal_prefix,
                           strlen((char *) rec->sql_desc_literal_prefix),
                           CharacterAttributePtr, BufferLength,
@@ -145,7 +146,12 @@ MNDBColAttribute(ODBCStmt *stmt,
                           stmt, return SQL_ERROR);
                break;
        case SQL_DESC_LITERAL_SUFFIX:
-               copyString(rec->sql_desc_literal_suffix, strlen((char *) 
rec->sql_desc_literal_suffix), CharacterAttributePtr, BufferLength, 
StringLengthPtr, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR);
+               fillLiteralPrefixSuffix(rec);
+               copyString(rec->sql_desc_literal_suffix,
+                          strlen((char *) rec->sql_desc_literal_suffix),
+                          CharacterAttributePtr, BufferLength,
+                          StringLengthPtr, SQLSMALLINT, addStmtError,
+                          stmt, return SQL_ERROR);
                break;
        case SQL_DESC_LOCAL_TYPE_NAME:
                copyString(rec->sql_desc_local_type_name,
@@ -370,7 +376,12 @@ SQLColAttributeW(SQLHSTMT StatementHandl
        case SQL_DESC_SCHEMA_NAME:      /* SQL_COLUMN_OWNER_NAME */
        case SQL_DESC_TABLE_NAME:       /* SQL_COLUMN_TABLE_NAME */
        case SQL_DESC_TYPE_NAME:        /* SQL_COLUMN_TYPE_NAME */
-               ptr = malloc(BufferLength);
+               if (BufferLength < 0) {
+                       /* Invalid string or buffer length */
+                       addStmtError(stmt, "HY090", NULL, 0);
+                       return SQL_ERROR;
+               }
+               ptr = (SQLPOINTER) malloc(BufferLength);
                if (ptr == NULL) {
                        /* Memory allocation error */
                        addStmtError(stmt, "HY001", NULL, 0);
diff --git a/clients/odbc/driver/SQLExecute.c b/clients/odbc/driver/SQLExecute.c
--- a/clients/odbc/driver/SQLExecute.c
+++ b/clients/odbc/driver/SQLExecute.c
@@ -198,7 +198,7 @@ ODBCInitResult(ODBCStmt *stmt)
                int concise_type;
                char *s;
 
-               rec->sql_desc_auto_unique_value = SQL_FALSE;
+               rec->sql_desc_auto_unique_value = SQL_FALSE;    /* SQL_TRUE for 
serial and bigserial columns */
                rec->sql_desc_nullable = SQL_NULLABLE_UNKNOWN;
                rec->sql_desc_rowver = SQL_FALSE;
                rec->sql_desc_searchable = SQL_PRED_SEARCHABLE;
@@ -324,9 +324,12 @@ ODBCInitResult(ODBCStmt *stmt)
                    rec->sql_desc_concise_type == SQL_LONGVARCHAR ||
                    rec->sql_desc_concise_type == SQL_WCHAR ||
                    rec->sql_desc_concise_type == SQL_WVARCHAR ||
-                   rec->sql_desc_concise_type == SQL_WLONGVARCHAR)
-                       rec->sql_desc_case_sensitive = SQL_TRUE;
-               else
+                   rec->sql_desc_concise_type == SQL_WLONGVARCHAR) {
+                       if (strcmp("inet", (char *)rec->sql_desc_type_name) == 
0)
+                               rec->sql_desc_case_sensitive = SQL_FALSE;
+                       else
+                               rec->sql_desc_case_sensitive = SQL_TRUE;
+               } else
                        rec->sql_desc_case_sensitive = SQL_FALSE;
 
                s = mapi_get_table(hdl, i);
@@ -369,19 +372,20 @@ ODBCInitResult(ODBCStmt *stmt)
                    (rec->sql_desc_length = mapi_get_digits(hdl, i)) == 0)
                        rec->sql_desc_length = mapi_get_len(hdl, i);
 
+               /* initialise fields */
                rec->sql_desc_local_type_name = NULL;
                rec->sql_desc_catalog_name = NULL;
-               rec->sql_desc_literal_prefix = NULL;
-               rec->sql_desc_literal_suffix = NULL;
-
-               /* unused fields */
                rec->sql_desc_data_ptr = NULL;
                rec->sql_desc_indicator_ptr = NULL;
                rec->sql_desc_octet_length_ptr = NULL;
                rec->sql_desc_parameter_type = 0;
 
-               /* this must come after other fields have been
-                * initialized */
+               /* rec->sql_desc_literal_prefix and rec->sql_desc_literal_suffix
+                * are used. Do not set to NULL. They are filled once when
+                * SQLColAttribute(SQL_DESC_LITERAL_...FIX) or
+                * SQLGetDescField(SQL_DESC_LITERAL_...FIX) is called */
+
+               /* this must come after other fields have been initialized */
                if (rec->sql_desc_concise_type == SQL_CHAR ||
                    rec->sql_desc_concise_type == SQL_VARCHAR ||
                    rec->sql_desc_concise_type == SQL_LONGVARCHAR ||
diff --git a/clients/odbc/driver/SQLGetDescField.c 
b/clients/odbc/driver/SQLGetDescField.c
--- a/clients/odbc/driver/SQLGetDescField.c
+++ b/clients/odbc/driver/SQLGetDescField.c
@@ -167,20 +167,24 @@ MNDBGetDescField(ODBCDesc *desc,
                WriteData(ValuePtr, (SQLUINTEGER) rec->sql_desc_length, 
SQLULEN);
                return SQL_SUCCESS;
        case SQL_DESC_LITERAL_PREFIX:           /* SQLCHAR * */
-               if (isIRD(desc))
+               if (isIRD(desc)) {
+                       fillLiteralPrefixSuffix(rec);
                        copyString(rec->sql_desc_literal_prefix,
                                   strlen((char *) 
rec->sql_desc_literal_prefix),
                                   ValuePtr, BufferLength, StringLengthPtr,
                                   SQLINTEGER, addDescError, desc,
                                   return SQL_ERROR);
+               }
                return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
        case SQL_DESC_LITERAL_SUFFIX:           /* SQLCHAR * */
-               if (isIRD(desc))
+               if (isIRD(desc)) {
+                       fillLiteralPrefixSuffix(rec);
                        copyString(rec->sql_desc_literal_suffix,
                                   strlen((char *) 
rec->sql_desc_literal_suffix),
                                   ValuePtr, BufferLength, StringLengthPtr,
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to