Mercurial > hg > monetdb-java
comparison src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java @ 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 | 6aa38e8c0f2d |
children | 06d69b82d409 |
comparison
equal
deleted
inserted
replaced
618:21d0f4a43697 | 619:ffc2fc8e82ec |
---|---|
2423 // ignore | 2423 // ignore |
2424 } finally { | 2424 } finally { |
2425 MonetConnection.closeResultsetStatement(pkey, null); | 2425 MonetConnection.closeResultsetStatement(pkey, null); |
2426 } | 2426 } |
2427 | 2427 |
2428 // 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) | |
2429 // 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) | |
2430 | |
2428 final StringBuilder query = new StringBuilder(1500); | 2431 final StringBuilder query = new StringBuilder(1500); |
2429 // Note: DISTINCT is needed to filter out possible duplicate column names from multiple unique constraints | 2432 query.append("SELECT "); |
2430 query.append("SELECT DISTINCT cast(").append(DatabaseMetaData.bestRowSession).append(" AS smallint) AS \"SCOPE\", " + | 2433 if (!hasPK) { |
2434 // Note: currently DISTINCT is needed to filter out possible duplicate column names when there are multiple unique constraints !! | |
2435 // TODO: when no PK and there are multiple unique constraints determine which one to select such that DISTINCT keyword is not needed anymore | |
2436 query.append("DISTINCT "); | |
2437 } | |
2438 query.append("cast(").append(DatabaseMetaData.bestRowSession).append(" AS smallint) AS \"SCOPE\", " + | |
2431 "c.\"name\" AS \"COLUMN_NAME\", " + | 2439 "c.\"name\" AS \"COLUMN_NAME\", " + |
2432 "cast(").append(MonetDriver.getSQLTypeMap("c.\"type\"")).append(" AS int) AS \"DATA_TYPE\", " + | 2440 "cast(").append(MonetDriver.getSQLTypeMap("c.\"type\"")).append(" AS int) AS \"DATA_TYPE\", " + |
2433 "c.\"type\" AS \"TYPE_NAME\", " + | 2441 "c.\"type\" AS \"TYPE_NAME\", " + |
2434 "c.\"type_digits\" AS \"COLUMN_SIZE\", " + | 2442 "c.\"type_digits\" AS \"COLUMN_SIZE\", " + |
2435 "cast(0 as int) AS \"BUFFER_LENGTH\", " + | 2443 "cast(0 as int) AS \"BUFFER_LENGTH\", " + |
2439 "JOIN \"sys\".\"objects\" o ON k.\"id\" = o.\"id\" " + | 2447 "JOIN \"sys\".\"objects\" o ON k.\"id\" = o.\"id\" " + |
2440 "JOIN \"sys\".\"columns\" c ON (k.\"table_id\" = c.\"table_id\" AND o.\"name\" = c.\"name\") " + | 2448 "JOIN \"sys\".\"columns\" c ON (k.\"table_id\" = c.\"table_id\" AND o.\"name\" = c.\"name\") " + |
2441 "JOIN \"sys\".\"tables\" t ON k.\"table_id\" = t.\"id\" " + | 2449 "JOIN \"sys\".\"tables\" t ON k.\"table_id\" = t.\"id\" " + |
2442 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + | 2450 "JOIN \"sys\".\"schemas\" s ON t.\"schema_id\" = s.\"id\" " + |
2443 "WHERE k.\"type\" = ").append(hasPK ? "0" : "1"); // the primary key (type = 0) or else any unique key (type = 1) | 2451 "WHERE k.\"type\" = ").append(hasPK ? "0" : "1"); // the primary key (type = 0) or else any unique key (type = 1) |
2444 // 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) | |
2445 | 2452 |
2446 if (catalog != null && !catalog.isEmpty()) { | 2453 if (catalog != null && !catalog.isEmpty()) { |
2447 // non-empty catalog selection. | 2454 // non-empty catalog selection. |
2448 // as we do not support catalogs this always results in no rows returned | 2455 // as we do not support catalogs this always results in no rows returned |
2449 query.append(" AND 1=0"); | 2456 query.append(" AND 1=0"); |
2463 } else { | 2470 } else { |
2464 query.append(" AND 1=0"); | 2471 query.append(" AND 1=0"); |
2465 } | 2472 } |
2466 } | 2473 } |
2467 | 2474 |
2468 query.append(" ORDER BY \"SCOPE\", o.\"nr\", \"COLUMN_NAME\""); | 2475 // was: query.append(" ORDER BY \"SCOPE\", o.\"nr\", \"COLUMN_NAME\""); |
2476 // But as of Jan2022 this ordering returns error: SELECT: with DISTINCT ORDER BY expressions must appear in select list | |
2477 // 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 | |
2478 query.append(" ORDER BY \"SCOPE\", "); | |
2479 if (hasPK) | |
2480 query.append("o.\"nr\", "); | |
2481 query.append("\"COLUMN_NAME\""); | |
2469 | 2482 |
2470 return executeMetaDataQuery(query.toString()); | 2483 return executeMetaDataQuery(query.toString()); |
2471 } | 2484 } |
2472 | 2485 |
2473 /** | 2486 /** |