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]
