Mercurial > hg > monetdb-java
changeset 619:ffc2fc8e82ec
Fixed an SQL query problem in DatabaseMetaData.getBestRowIdentifier() method when used with MonetDB Jan2022 (or newer) releases.
It returned java.sql.SQLException: SELECT: with DISTINCT ORDER BY expressions must appear in select list
Added test.
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Wed, 19 Jan 2022 19:04:03 +0100 (2022-01-19) |
parents | 21d0f4a43697 |
children | 5ab170ddc66a |
files | ChangeLog src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java tests/JDBC_API_Tester.java |
diffstat | 3 files changed, 31 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,14 @@ - Compiled and released new jar files: monetdb-jdbc-3.2.jre8.jar, monetdb-mcl-1.21.jre8.jar and jdbcclient.jre8.jar +* Wed Jan 19 2022 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> +- Fixed an SQL query problem in DatabaseMetaData.getBestRowIdentifier() + method when used with MonetDB Jan2022 (or newer) releases. It + returned java.sql.SQLException: + SELECT: with DISTINCT ORDER BY expressions must appear in select list + As of MonetDB Jan2022 (11.43.1) such queries are no longer allowed. + The internally used SQL query has been improved. + * Thu Jan 13 2022 Martin van Dinther <martin.van.dinther@monetdbsolutions.com> - Extended JdbcClient application with support for following \d commands: \dt \dv \dSt \dSv \df \dp \dSf \dSp \dn \dSn and \ds
--- a/src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java +++ b/src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java @@ -2425,9 +2425,17 @@ public class MonetDatabaseMetaData MonetConnection.closeResultsetStatement(pkey, null); } + // TODO: when there is No PK and there are multiple unique constraints, pick only the unique constraint which has a) the least number of columns and b) the smallest total(size in bytes) + // TODO: when there is No PK and No unique constraints, we potentially should return all columns of the table (else in SQuirreL no header is shown in the "Row IDs" tab) + final StringBuilder query = new StringBuilder(1500); - // Note: DISTINCT is needed to filter out possible duplicate column names from multiple unique constraints - query.append("SELECT DISTINCT cast(").append(DatabaseMetaData.bestRowSession).append(" AS smallint) AS \"SCOPE\", " + + query.append("SELECT "); + if (!hasPK) { + // Note: currently DISTINCT is needed to filter out possible duplicate column names when there are multiple unique constraints !! + // TODO: when no PK and there are multiple unique constraints determine which one to select such that DISTINCT keyword is not needed anymore + query.append("DISTINCT "); + } + query.append("cast(").append(DatabaseMetaData.bestRowSession).append(" AS smallint) AS \"SCOPE\", " + "c.\"name\" AS \"COLUMN_NAME\", " + "cast(").append(MonetDriver.getSQLTypeMap("c.\"type\"")).append(" AS int) AS \"DATA_TYPE\", " + "c.\"type\" AS \"TYPE_NAME\", " + @@ -2441,7 +2449,6 @@ public class MonetDatabaseMetaData "JOIN \"sys\".\"tables\" t ON k.\"table_id\" = t.\"id\" " + "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + "WHERE k.\"type\" = ").append(hasPK ? "0" : "1"); // the primary key (type = 0) or else any unique key (type = 1) - // TODO: when there is no PK and there are multiple unique constraints, pick only the unique constraint which has a) the least number of columns and b) the smallest total(size in bytes) if (catalog != null && !catalog.isEmpty()) { // non-empty catalog selection. @@ -2465,7 +2472,13 @@ public class MonetDatabaseMetaData } } - query.append(" ORDER BY \"SCOPE\", o.\"nr\", \"COLUMN_NAME\""); + // was: query.append(" ORDER BY \"SCOPE\", o.\"nr\", \"COLUMN_NAME\""); + // But as of Jan2022 this ordering returns error: SELECT: with DISTINCT ORDER BY expressions must appear in select list + // so had to remove the o.\"nr\", part when there is No PKey. This means the columns are than ordered on names instead of creation order in their unique constraint definition + query.append(" ORDER BY \"SCOPE\", "); + if (hasPK) + query.append("o.\"nr\", "); + query.append("\"COLUMN_NAME\""); return executeMetaDataQuery(query.toString()); }
--- a/tests/JDBC_API_Tester.java +++ b/tests/JDBC_API_Tester.java @@ -735,6 +735,12 @@ final public class JDBC_API_Tester { "null sys key_types false null key_types_key_type_id_pkey 2 1 key_type_id null 3 0 null\n" + "null sys key_types false null key_types_key_type_name_unique 2 1 key_type_name null 3 0 null\n"); + compareResultSet(dbmd.getBestRowIdentifier(null, "sys", "function_languages", DatabaseMetaData.bestRowTransaction, true), + "getBestRowIdentifier(null, sys, function_languages, DatabaseMetaData.bestRowTransaction, true)", + "Resultset with 8 columns\n" + + "SCOPE COLUMN_NAME DATA_TYPE TYPE_NAME COLUMN_SIZE BUFFER_LENGTH DECIMAL_DIGITS PSEUDO_COLUMN\n" + + "2 language_id 5 smallint 16 0 0 1\n"); + compareResultSet(dbmd.getTablePrivileges(null, "sys", "table\\_types"), "getTablePrivileges(null, sys, table\\_types)", "Resultset with 7 columns\n" + "TABLE_CAT TABLE_SCHEM TABLE_NAME GRANTOR GRANTEE PRIVILEGE IS_GRANTABLE\n" +