postgresql-jdbc.git / summary / log / commit / refs
commit 17cac52fe9cb80001cfd1fd72ec2b03fa4c5d64e
Author: Sophiah Ho <182134868+SophiahHo@users.noreply.github.com>
Commit: GitHub <noreply@github.com>
Date: Thu Dec 12 17:20:54 2024 +0000
Fix PgDatabaseMetaData implementation of catalog as param and return value (#3390)
* fix: fix getSchemas(String catalog, String schemaPattern) to process catalog parameter and return catalog metadata per JDBC spec
* fix: populate TABLE_CATALOG with current_database()::information_schema.sql_identifier in getSchemas
* fix: include catalog filter in getSchemas
* fix: an empty string for schemaPattern should return no rows instead of being ignored per JDBC spec
* test: update getSchemas() test with null catalog argument and assert TABLE_CATALOG in ResultSet is not null
* test: add new tests for getSchemas
* fix: update getTables to follow JDBC spec
* fix: use top-level Javadoc spec on interface and align with JDBC implementation convention of other databases
* fix: filter by catalog in getColumns
* fix: update getFunctions, getFunctionColumns to follow JDBC spec
* fix: update getProcedures, getProcedureColumns to follow JDBC spec
* fix: update getIndexInfo per JDBC spec
* fix: update getPrimaryKeys per JDBC spec
* fix: update other methods in PgDatabaseMetaData to match specifications in DatabaseMetaData interface
* test: use null for catalog arg
* test: update tests
* test: add tests for empty catalog and schema arguments
* test: add test for percent sign catalog argument
* test: add tests for empty and percent sign catalog, empty schema
* test: add tests for percent sign catalog argument
* test: use empty functionNamePattern in getFunctionsWithBlankPatterns
* test: update tests to use try-with-resources for Connection and Statement
* fix: fix error messages
---------
Co-authored-by: Sophiah Ho <sophiah.ho@precisely.com>
.../org/postgresql/jdbc/PgDatabaseMetaData.java | 180 ++++--
.../test/jdbc2/DatabaseMetaDataTest.java | 659 ++++++++++++++-------
.../test/jdbc3/DatabaseMetaDataTest.java | 10 +-
.../test/jdbc4/DatabaseMetaDataTest.java | 311 ++++++++--
.../test/jdbc42/DatabaseMetaDataTest.java | 31 +-
5 files changed, 875 insertions(+), 316 deletions(-)
diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java
index fc342454..0c749689 100644
--- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java
+++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java
@@ -1188,7 +1188,8 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
@Nullable String procedureNamePattern)
throws SQLException {
String sql;
- sql = "SELECT NULL AS \"PROCEDURE_CAT\", n.nspname AS \"PROCEDURE_SCHEM\", p.proname AS \"PROCEDURE_NAME\", "
+ sql = "SELECT current_database() AS \"PROCEDURE_CAT\", "
+ + " n.nspname AS \"PROCEDURE_SCHEM\", p.proname AS \"PROCEDURE_NAME\", "
+ "NULL, NULL, NULL, d.description AS \"REMARKS\", "
+ DatabaseMetaData.procedureReturnsResult + " AS \"PROCEDURE_TYPE\", "
+ " p.proname || '_' || p.oid AS \"SPECIFIC_NAME\" "
@@ -1201,10 +1202,13 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
if (connection.haveMinimumServerVersion(ServerVersion.v11)) {
sql += " AND p.prokind='p'";
}
- if (schemaPattern != null && !schemaPattern.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+ if (schemaPattern != null) {
sql += " AND n.nspname LIKE " + escapeQuotes(schemaPattern);
}
- if (procedureNamePattern != null && !procedureNamePattern.isEmpty()) {
+ if (procedureNamePattern != null) {
sql += " AND p.proname LIKE " + escapeQuotes(procedureNamePattern);
}
if (connection.getHideUnprivilegedObjects()) {
@@ -1246,14 +1250,17 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
f[19] = new Field("SPECIFIC_NAME", Oid.VARCHAR);
String sql;
- sql = "SELECT n.nspname,p.proname,p.prorettype,p.proargtypes, t.typtype,t.typrelid, "
+ sql = "SELECT current_database(), n.nspname,p.proname,p.prorettype,p.proargtypes, t.typtype,t.typrelid, "
+ " p.proargnames, p.proargmodes, p.proallargtypes, p.oid "
+ " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n, pg_catalog.pg_type t "
+ " WHERE p.pronamespace=n.oid AND p.prorettype=t.oid ";
- if (schemaPattern != null && !schemaPattern.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+ if (schemaPattern != null) {
sql += " AND n.nspname LIKE " + escapeQuotes(schemaPattern);
}
- if (procedureNamePattern != null && !procedureNamePattern.isEmpty()) {
+ if (procedureNamePattern != null) {
sql += " AND p.proname LIKE " + escapeQuotes(procedureNamePattern);
}
sql += " ORDER BY n.nspname, p.proname, p.oid::text ";
@@ -1263,6 +1270,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
+ byte[] catalogName = rs.getBytes("current_database");
byte[] schema = rs.getBytes("nspname");
byte[] procedureName = rs.getBytes("proname");
byte[] specificName =
@@ -1303,7 +1311,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
if ("b".equals(returnTypeType) || "d".equals(returnTypeType) || "e".equals(returnTypeType)
|| ("p".equals(returnTypeType) && argModesArray == null)) {
byte[] @Nullable [] tuple = new byte[columns][];
- tuple[0] = null;
+ tuple[0] = catalogName;
tuple[1] = schema;
tuple[2] = procedureName;
tuple[3] = connection.encodeString("returnValue");
@@ -1329,7 +1337,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
// Add a row for each argument.
for (int i = 0; i < numArgs; i++) {
byte[] @Nullable [] tuple = new byte[columns][];
- tuple[0] = null;
+ tuple[0] = catalogName;
tuple[1] = schema;
tuple[2] = procedureName;
@@ -1385,7 +1393,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
while (columnrs.next()) {
int columnTypeOid = (int) columnrs.getLong("atttypid");
byte[] @Nullable [] tuple = new byte[columns][];
- tuple[0] = null;
+ tuple[0] = catalogName;
tuple[1] = schema;
tuple[2] = procedureName;
tuple[3] = columnrs.getBytes("attname");
@@ -1423,7 +1431,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
String select;
String orderby;
String useSchemas = "SCHEMAS";
- select = "SELECT NULL AS \"TABLE_CAT\", n.nspname AS \"TABLE_SCHEM\", c.relname AS \"TABLE_NAME\", "
+ select = "SELECT current_database() AS \"TABLE_CAT\", n.nspname AS \"TABLE_SCHEM\", c.relname AS \"TABLE_NAME\", "
+ " CASE n.nspname ~ '^pg_' OR n.nspname = 'information_schema' "
+ " WHEN true THEN CASE "
+ " WHEN n.nspname = 'pg_catalog' OR n.nspname = 'information_schema' THEN CASE c.relkind "
@@ -1467,7 +1475,11 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
+ " LEFT JOIN pg_catalog.pg_description d ON (c.oid = d.objoid AND d.objsubid = 0 and d.classoid = 'pg_class'::regclass) "
+ " WHERE c.relnamespace = n.oid ";
- if (schemaPattern != null && !schemaPattern.isEmpty()) {
+ if (catalog != null) {
+ select += " AND current_database() = " + escapeQuotes(catalog);
+ }
+
+ if (schemaPattern != null) {
select += " AND n.nspname LIKE " + escapeQuotes(schemaPattern);
}
@@ -1488,9 +1500,10 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
orderby = " ORDER BY \"TABLE_TYPE\",\"TABLE_SCHEM\",\"TABLE_NAME\" ";
- if (tableNamePattern != null && !tableNamePattern.isEmpty()) {
+ if (tableNamePattern != null) {
select += " AND c.relname LIKE " + escapeQuotes(tableNamePattern);
}
+
if (types != null) {
select += " AND (false ";
StringBuilder orclause = new StringBuilder();
@@ -1603,11 +1616,14 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
public ResultSet getSchemas(@Nullable String catalog, @Nullable String schemaPattern)
throws SQLException {
String sql;
- sql = "SELECT nspname AS \"TABLE_SCHEM\", NULL AS \"TABLE_CATALOG\" FROM pg_catalog.pg_namespace "
+ sql = "SELECT nspname AS \"TABLE_SCHEM\", current_database() AS \"TABLE_CATALOG\" FROM pg_catalog.pg_namespace "
+ " WHERE nspname <> 'pg_toast' AND (nspname !~ '^pg_temp_' "
+ " OR nspname = (pg_catalog.current_schemas(true))[1]) AND (nspname !~ '^pg_toast_temp_' "
+ " OR nspname = replace((pg_catalog.current_schemas(true))[1], 'pg_temp_', 'pg_toast_temp_')) ";
- if (schemaPattern != null && !schemaPattern.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+ if (schemaPattern != null) {
sql += " AND nspname LIKE " + escapeQuotes(schemaPattern);
}
if (connection.getHideUnprivilegedObjects()) {
@@ -1692,8 +1708,8 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
sql = "";
}
- sql += "SELECT n.nspname,c.relname,a.attname,a.atttypid,a.attnotnull "
- + "OR (t.typtype = 'd' AND t.typnotnull) AS attnotnull,a.atttypmod,a.attlen,t.typtypmod,";
+ sql += "SELECT current_database(), n.nspname,c.relname,a.attname,a.atttypid,a.attnotnull "
+ + " OR (t.typtype = 'd' AND t.typnotnull) AS attnotnull,a.atttypmod,a.attlen,t.typtypmod,";
if (connection.haveMinimumServerVersion(ServerVersion.v8_4)) {
sql += "row_number() OVER (PARTITION BY a.attrelid ORDER BY a.attnum) AS attnum, ";
@@ -1724,16 +1740,19 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
+ " LEFT JOIN pg_catalog.pg_namespace dn ON (dc.relnamespace=dn.oid AND dn.nspname='pg_catalog') "
+ " WHERE c.relkind in ('r','p','v','f','m') and a.attnum > 0 AND NOT a.attisdropped ";
- if (schemaPattern != null && !schemaPattern.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+ if (schemaPattern != null) {
sql += " AND n.nspname LIKE " + escapeQuotes(schemaPattern);
}
- if (tableNamePattern != null && !tableNamePattern.isEmpty()) {
+ if (tableNamePattern != null) {
sql += " AND c.relname LIKE " + escapeQuotes(tableNamePattern);
}
if (connection.haveMinimumServerVersion(ServerVersion.v8_4)) {
sql += ") c WHERE true ";
}
- if (columnNamePattern != null && !columnNamePattern.isEmpty()) {
+ if (columnNamePattern != null) {
sql += " AND attname LIKE " + escapeQuotes(columnNamePattern);
}
sql += " ORDER BY nspname,c.relname,attnum ";
@@ -1745,8 +1764,8 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
int typeOid = (int) rs.getLong("atttypid");
int typeMod = rs.getInt("atttypmod");
- tuple[0] = null; // Catalog name, not supported
- tuple[1] = rs.getBytes("nspname"); // Schema
+ tuple[0] = rs.getBytes("current_database"); // Catalog (database) name
+ tuple[1] = rs.getBytes("nspname"); // Schema name
tuple[2] = rs.getBytes("relname"); // Table name
tuple[3] = rs.getBytes("attname"); // Column name
@@ -1885,7 +1904,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
f[7] = new Field("IS_GRANTABLE", Oid.VARCHAR);
String sql;
- sql = "SELECT n.nspname,c.relname,r.rolname,c.relacl, "
+ sql = "SELECT current_database(), n.nspname,c.relname,r.rolname,c.relacl, "
+ (connection.haveMinimumServerVersion(ServerVersion.v8_4) ? "a.attacl, " : "")
+ " a.attname "
+ " FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c, "
@@ -1896,13 +1915,16 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
+ " AND c.relkind = 'r' "
+ " AND a.attnum > 0 AND NOT a.attisdropped ";
- if (schema != null && !schema.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+ if (schema != null) {
sql += " AND n.nspname = " + escapeQuotes(schema);
}
- if (table != null && !table.isEmpty()) {
+ if (table != null) {
sql += " AND c.relname = " + escapeQuotes(table);
}
- if (columnNamePattern != null && !columnNamePattern.isEmpty()) {
+ if (columnNamePattern != null) {
sql += " AND a.attname LIKE " + escapeQuotes(columnNamePattern);
}
sql += " ORDER BY attname ";
@@ -1910,6 +1932,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
+ byte[] catalogName = rs.getBytes("current_database");
byte[] schemaName = rs.getBytes("nspname");
byte[] tableName = rs.getBytes("relname");
byte[] column = rs.getBytes("attname");
@@ -1935,7 +1958,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
for (@Nullable String[] grants : grantor) {
String grantable = owner.equals(grantee) ? "YES" : grants[1];
byte[] @Nullable [] tuple = new byte[8][];
- tuple[0] = null;
+ tuple[0] = catalogName;
tuple[1] = schemaName;
tuple[2] = tableName;
tuple[3] = column;
@@ -1970,17 +1993,21 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
String sql;
// r = ordinary table, p = partitioned table, v = view, m = materialized view, f = foreign table
- sql = "SELECT n.nspname,c.relname,r.rolname,c.relacl "
+ sql = "SELECT current_database(), n.nspname,c.relname,r.rolname,c.relacl "
+ " FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c, pg_catalog.pg_roles r "
+ " WHERE c.relnamespace = n.oid "
+ " AND c.relowner = r.oid "
+ " AND c.relkind IN ('r','p','v','m','f') ";
- if (schemaPattern != null && !schemaPattern.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+
+ if (schemaPattern != null) {
sql += " AND n.nspname LIKE " + escapeQuotes(schemaPattern);
}
- if (tableNamePattern != null && !tableNamePattern.isEmpty()) {
+ if (tableNamePattern != null) {
sql += " AND c.relname LIKE " + escapeQuotes(tableNamePattern);
}
sql += " ORDER BY nspname, relname ";
@@ -1988,6 +2015,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
+ byte[] catalogName = rs.getBytes("current_database");
byte[] schema = rs.getBytes("nspname");
byte[] table = rs.getBytes("relname");
String owner = castNonNull(rs.getString("rolname"));
@@ -2007,7 +2035,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
// owner always has grant privileges
String grantable = owner.equals(granteeUser) ? "YES" : grantTuple[1];
byte[] @Nullable [] tuple = new byte[7][];
- tuple[0] = null;
+ tuple[0] = catalogName;
tuple[1] = schema;
tuple[2] = table;
tuple[3] = connection.encodeString(grantor);
@@ -2221,7 +2249,11 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
+ " ON (a.attnum = (i.keys).x AND a.attrelid = i.indrelid) "
+ "WHERE true ";
- if (schema != null && !schema.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+
+ if (schema != null) {
sql += " AND n.nspname = " + escapeQuotes(schema);
}
@@ -2312,7 +2344,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
// when returning primary keys.
String keyCountColumn = connection.haveMinimumServerVersion(ServerVersion.v11) ? "i.indnkeyatts" : "i.indnatts";
- sql = "SELECT NULL AS TABLE_CAT, n.nspname AS TABLE_SCHEM, "
+ sql = "SELECT current_database() AS TABLE_CAT, n.nspname AS TABLE_SCHEM, "
+ " ct.relname AS TABLE_NAME, a.attname AS COLUMN_NAME, "
+ " (information_schema._pg_expandarray(i.indkey)).n AS KEY_SEQ, ci.relname AS PK_NAME, "
+ " information_schema._pg_expandarray(i.indkey) AS KEYS, a.attnum AS A_ATTNUM, "
@@ -2324,11 +2356,15 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
+ " JOIN pg_catalog.pg_class ci ON (ci.oid = i.indexrelid) "
+ "WHERE true ";
- if (schema != null && !schema.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+
+ if (schema != null) {
sql += " AND n.nspname = " + escapeQuotes(schema);
}
- if (table != null && !table.isEmpty()) {
+ if (table != null) {
sql += " AND ct.relname = " + escapeQuotes(table);
}
@@ -2425,8 +2461,8 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
*/
String sql =
- "SELECT NULL::text AS \"PKTABLE_CAT\", pkn.nspname AS \"PKTABLE_SCHEM\", pkc.relname AS \"PKTABLE_NAME\", pka.attname AS \"PKCOLUMN_NAME\", "
- + "NULL::text AS \"FKTABLE_CAT\", fkn.nspname AS \"FKTABLE_SCHEM\", fkc.relname AS \"FKTABLE_NAME\", fka.attname AS \"FKCOLUMN_NAME\", "
+ "SELECT current_database() AS \"PKTABLE_CAT\", pkn.nspname AS \"PKTABLE_SCHEM\", pkc.relname AS \"PKTABLE_NAME\", pka.attname AS \"PKCOLUMN_NAME\", "
+ + "current_database() AS \"FKTABLE_CAT\", fkn.nspname AS \"FKTABLE_SCHEM\", fkc.relname AS \"FKTABLE_NAME\", fka.attname AS \"FKCOLUMN_NAME\", "
+ "pos.n AS \"KEY_SEQ\", "
+ "CASE con.confupdtype "
+ " WHEN 'c' THEN " + DatabaseMetaData.importedKeyCascade
@@ -2485,16 +2521,22 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
sql += " AND pkic.oid = con.conindid ";
}
- if (primarySchema != null && !primarySchema.isEmpty()) {
+ if (primaryCatalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(primaryCatalog);
+ }
+ if (primarySchema != null) {
sql += " AND pkn.nspname = " + escapeQuotes(primarySchema);
}
- if (foreignSchema != null && !foreignSchema.isEmpty()) {
+ if (foreignCatalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(foreignCatalog);
+ }
+ if (foreignSchema != null) {
sql += " AND fkn.nspname = " + escapeQuotes(foreignSchema);
}
- if (primaryTable != null && !primaryTable.isEmpty()) {
+ if (primaryTable != null) {
sql += " AND pkc.relname = " + escapeQuotes(primaryTable);
}
- if (foreignTable != null && !foreignTable.isEmpty()) {
+ if (foreignTable != null) {
sql += " AND fkc.relname = " + escapeQuotes(foreignTable);
}
@@ -2673,7 +2715,8 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
*/
String sql;
if (connection.haveMinimumServerVersion(ServerVersion.v8_3)) {
- sql = "SELECT NULL AS TABLE_CAT, n.nspname AS TABLE_SCHEM, "
+ sql = "SELECT current_database() AS TABLE_CAT, "
+ + " n.nspname AS TABLE_SCHEM, "
+ " ct.relname AS TABLE_NAME, NOT i.indisunique AS NON_UNIQUE, "
+ " NULL AS INDEX_QUALIFIER, ci.relname AS INDEX_NAME, "
+ " CASE i.indisclustered "
@@ -2697,7 +2740,11 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
+ " JOIN pg_catalog.pg_am am ON (ci.relam = am.oid) "
+ "WHERE true ";
- if (schema != null && !schema.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+
+ if (schema != null) {
sql += " AND n.nspname = " + escapeQuotes(schema);
}
@@ -2743,13 +2790,18 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
String from;
String where;
- select = "SELECT NULL AS \"TABLE_CAT\", n.nspname AS \"TABLE_SCHEM\", ";
+ select = "SELECT current_database() AS \"TABLE_CAT\", "
+ + " n.nspname AS \"TABLE_SCHEM\", ";
from = " FROM pg_catalog.pg_namespace n, pg_catalog.pg_class ct, pg_catalog.pg_class ci, "
+ " pg_catalog.pg_attribute a, pg_catalog.pg_am am ";
where = " AND n.oid = ct.relnamespace ";
from += ", pg_catalog.pg_index i ";
- if (schema != null && !schema.isEmpty()) {
+ if (catalog != null) {
+ where += " AND current_database() = " + escapeQuotes(catalog);
+ }
+
+ if (schema != null) {
where += " AND n.nspname = " + escapeQuotes(schema);
}
@@ -2865,11 +2917,11 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
public ResultSet getUDTs(@Nullable String catalog, @Nullable String schemaPattern,
@Nullable String typeNamePattern, int @Nullable [] types) throws SQLException {
String sql = "select "
- + "null as type_cat, n.nspname as type_schem, t.typname as type_name, null as class_name, "
+ + "current_database() as \"TYPE_CAT\", n.nspname as \"TYPE_SCHEM\", t.typname as \"TYPE_NAME\", null as \"CLASS_NAME\", "
+ "CASE WHEN t.typtype='c' then " + Types.STRUCT + " else "
+ Types.DISTINCT
- + " end as data_type, pg_catalog.obj_description(t.oid, 'pg_type') "
- + "as remarks, CASE WHEN t.typtype = 'd' then (select CASE";
+ + " end as \"DATA_TYPE\", pg_catalog.obj_description(t.oid, 'pg_type') "
+ + "as \"REMARKS\", CASE WHEN t.typtype = 'd' then (select CASE";
TypeInfo typeInfo = connection.getTypeInfo();
StringBuilder sqlwhen = new StringBuilder();
@@ -2886,7 +2938,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
sql += sqlwhen.toString();
sql += " else " + Types.OTHER + " end from pg_type base_type where base_type.oid=t.typbasetype) "
- + "else null end as base_type "
+ + "else null end as \"BASE_TYPE\" "
+ "from pg_catalog.pg_type t, pg_catalog.pg_namespace n where t.typnamespace = n.oid and n.nspname != 'pg_catalog' and n.nspname != 'pg_toast'";
StringBuilder toAdd = new StringBuilder();
@@ -2926,6 +2978,10 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
toAdd.append(" and t.typname like ").append(escapeQuotes(typeNamePattern));
}
+ if (catalog != null) {
+ toAdd.append(" and current_database() = ").append(escapeQuotes(catalog));
+ }
+
// schemaPattern may have been modified above
if (schemaPattern != null) {
toAdd.append(" and n.nspname like ").append(escapeQuotes(schemaPattern));
@@ -2937,7 +2993,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
sql += " AND has_type_privilege(t.oid, 'USAGE')";
}
- sql += " order by data_type, type_schem, type_name";
+ sql += " order by \"DATA_TYPE\", \"TYPE_SCHEM\", \"TYPE_NAME\" ";
return createMetaDataStatement().executeQuery(sql);
}
@@ -3034,7 +3090,8 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
// Build query and result
String sql;
- sql = "SELECT current_database() AS \"FUNCTION_CAT\", n.nspname AS \"FUNCTION_SCHEM\", p.proname AS \"FUNCTION_NAME\", "
+ sql = "SELECT current_database() AS \"FUNCTION_CAT\", "
+ + " n.nspname AS \"FUNCTION_SCHEM\", p.proname AS \"FUNCTION_NAME\", "
+ " d.description AS \"REMARKS\", "
+ funcTypeSql + " AS \"FUNCTION_TYPE\", "
+ " p.proname || '_' || p.oid AS \"SPECIFIC_NAME\" "
@@ -3046,13 +3103,16 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
if (connection.haveMinimumServerVersion(ServerVersion.v11)) {
sql += " AND p.prokind='f'";
}
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
/*
if the user provides a schema then search inside the schema for it
*/
- if (schemaPattern != null && !schemaPattern.isEmpty()) {
+ if (schemaPattern != null) {
sql += " AND n.nspname LIKE " + escapeQuotes(schemaPattern);
}
- if (functionNamePattern != null && !functionNamePattern.isEmpty()) {
+ if (functionNamePattern != null) {
sql += " AND p.proname LIKE " + escapeQuotes(functionNamePattern);
}
if (connection.getHideUnprivilegedObjects()) {
@@ -3091,14 +3151,17 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
f[16] = new Field("SPECIFIC_NAME", Oid.VARCHAR);
String sql;
- sql = "SELECT n.nspname,p.proname,p.prorettype,p.proargtypes, t.typtype,t.typrelid, "
+ sql = "SELECT current_database(), n.nspname,p.proname,p.prorettype,p.proargtypes, t.typtype,t.typrelid, "
+ " p.proargnames, p.proargmodes, p.proallargtypes, p.oid "
+ " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n, pg_catalog.pg_type t "
+ " WHERE p.pronamespace=n.oid AND p.prorettype=t.oid ";
- if (schemaPattern != null && !schemaPattern.isEmpty()) {
+ if (catalog != null) {
+ sql += " AND current_database() = " + escapeQuotes(catalog);
+ }
+ if (schemaPattern != null) {
sql += " AND n.nspname LIKE " + escapeQuotes(schemaPattern);
}
- if (functionNamePattern != null && !functionNamePattern.isEmpty()) {
+ if (functionNamePattern != null) {
sql += " AND p.proname LIKE " + escapeQuotes(functionNamePattern);
}
sql += " ORDER BY n.nspname, p.proname, p.oid::text ";
@@ -3108,6 +3171,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
+ byte[] catalogName = rs.getBytes("current_database");
byte[] schema = rs.getBytes("nspname");
byte[] functionName = rs.getBytes("proname");
byte[] specificName =
@@ -3148,7 +3212,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
if ("b".equals(returnTypeType) || "d".equals(returnTypeType) || "e".equals(returnTypeType)
|| ("p".equals(returnTypeType) && argModesArray == null)) {
byte[] @Nullable [] tuple = new byte[columns][];
- tuple[0] = null;
+ tuple[0] = catalogName;
tuple[1] = schema;
tuple[2] = functionName;
tuple[3] = connection.encodeString("returnValue");
@@ -3174,7 +3238,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
// Add a row for each argument.
for (int i = 0; i < numArgs; i++) {
byte[] @Nullable [] tuple = new byte[columns][];
- tuple[0] = null;
+ tuple[0] = catalogName;
tuple[1] = schema;
tuple[2] = functionName;
@@ -3231,7 +3295,7 @@ public class PgDatabaseMetaData implements DatabaseMetaData {
while (columnrs.next()) {
int columnTypeOid = (int) columnrs.getLong("atttypid");
byte[] @Nullable [] tuple = new byte[columns][];
- tuple[0] = null;
+ tuple[0] = catalogName;
tuple[1] = schema;
tuple[2] = functionName;
tuple[3] = columnrs.getBytes("attname");
diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
index d90dd461..58d6c0aa 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
@@ -256,6 +256,21 @@ public class DatabaseMetaDataTest {
}
}
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void tables_whenCatalogAndSchemaArgsEmpty_expectNoResults(BinaryMode binaryMode) throws Exception {
+ DatabaseMetaData dbmd = con.getMetaData();
+ assertNotNull(dbmd);
+
+ ResultSet rs = dbmd.getTables("", "", "metadatates%", new String[]{"TABLE"});
+ assertFalse(rs.next());
+ rs.close();
+
+ rs = dbmd.getColumns("", "", "meta%", "%");
+ assertFalse(rs.next());
+ rs.close();
+ }
+
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
void tables(BinaryMode binaryMode) throws Exception {
@@ -280,7 +295,7 @@ public class DatabaseMetaDataTest {
rs.close();
- rs = dbmd.getColumns("", "", "meta%", "%");
+ rs = dbmd.getColumns(null, null, "meta%", "%");
assertTrue(rs.next());
assertEquals("metadatatest", rs.getString("TABLE_NAME"));
assertEquals("id", rs.getString("COLUMN_NAME"));
@@ -297,262 +312,398 @@ public class DatabaseMetaDataTest {
assertEquals(Types.TIMESTAMP, rs.getInt("DATA_TYPE"));
}
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void crossReference_whenCatalogAndSchemaArgsEmpty_expectNoResults(BinaryMode binaryMode) throws Exception {
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "vv", "a int not null, b int not null, constraint vv_pkey primary key ( a, b )");
+
+ TestUtil.createTable(con1, "ww",
+ "m int not null, n int not null, constraint m_pkey primary key ( m, n ), constraint ww_m_fkey foreign key ( m, n ) references vv ( a, b )");
+
+ DatabaseMetaData dbmd = con.getMetaData();
+ assertNotNull(dbmd);
+
+ ResultSet rs = dbmd.getCrossReference("", "", "vv", null, null, "ww");
+ assertFalse(rs.next());
+
+ TestUtil.dropTable(con1, "vv");
+ TestUtil.dropTable(con1, "ww");
+ }
+ }
+
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
void crossReference(BinaryMode binaryMode) throws Exception {
- Connection con1 = TestUtil.openDB();
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "vv", "a int not null, b int not null, constraint vv_pkey primary key ( a, b )");
- TestUtil.createTable(con1, "vv", "a int not null, b int not null, constraint vv_pkey primary key ( a, b )");
+ TestUtil.createTable(con1, "ww",
+ "m int not null, n int not null, constraint m_pkey primary key ( m, n ), constraint ww_m_fkey foreign key ( m, n ) references vv ( a, b )");
- TestUtil.createTable(con1, "ww",
- "m int not null, n int not null, constraint m_pkey primary key ( m, n ), constraint ww_m_fkey foreign key ( m, n ) references vv ( a, b )");
+ DatabaseMetaData dbmd = con.getMetaData();
+ assertNotNull(dbmd);
- DatabaseMetaData dbmd = con.getMetaData();
- assertNotNull(dbmd);
+ ResultSet rs = dbmd.getCrossReference(null, null, "vv", null, null, "ww");
+ String[] expectedPkColumnNames = new String[]{"a", "b"};
+ String[] expectedFkColumnNames = new String[]{"m", "n"};
+ int numRows = 0;
- ResultSet rs = dbmd.getCrossReference(null, "", "vv", null, "", "ww");
- String[] expectedPkColumnNames = new String[]{"a", "b"};
- String[] expectedFkColumnNames = new String[]{"m", "n"};
- int numRows = 0;
+ for (int j = 1; rs.next(); j++) {
- for (int j = 1; rs.next(); j++) {
+ String pkTableName = rs.getString("PKTABLE_NAME");
+ assertEquals("vv", pkTableName);
- String pkTableName = rs.getString("PKTABLE_NAME");
- assertEquals("vv", pkTableName);
+ String pkColumnName = rs.getString("PKCOLUMN_NAME");
+ assertEquals(expectedPkColumnNames[j - 1], pkColumnName);
- String pkColumnName = rs.getString("PKCOLUMN_NAME");
- assertEquals(expectedPkColumnNames[j - 1], pkColumnName);
+ String fkTableName = rs.getString("FKTABLE_NAME");
+ assertEquals("ww", fkTableName);
- String fkTableName = rs.getString("FKTABLE_NAME");
- assertEquals("ww", fkTableName);
+ String fkColumnName = rs.getString("FKCOLUMN_NAME");
+ assertEquals(expectedFkColumnNames[j - 1], fkColumnName);
- String fkColumnName = rs.getString("FKCOLUMN_NAME");
- assertEquals(expectedFkColumnNames[j - 1], fkColumnName);
+ String fkName = rs.getString("FK_NAME");
+ assertEquals("ww_m_fkey", fkName);
- String fkName = rs.getString("FK_NAME");
- assertEquals("ww_m_fkey", fkName);
+ String pkName = rs.getString("PK_NAME");
+ assertEquals("vv_pkey", pkName);
- String pkName = rs.getString("PK_NAME");
- assertEquals("vv_pkey", pkName);
+ int keySeq = rs.getInt("KEY_SEQ");
+ assertEquals(j, keySeq);
+ numRows += 1;
+ }
+ assertEquals(2, numRows);
- int keySeq = rs.getInt("KEY_SEQ");
- assertEquals(j, keySeq);
- numRows += 1;
+ TestUtil.dropTable(con1, "vv");
+ TestUtil.dropTable(con1, "ww");
}
- assertEquals(2, numRows);
+ }
- TestUtil.dropTable(con1, "vv");
- TestUtil.dropTable(con1, "ww");
- TestUtil.closeDB(con1);
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void foreignKeyActions_whenSchemaArgEmpty_expectNoResults(BinaryMode binaryMode) throws Exception {
+ try (Connection conn = TestUtil.openDB()) {
+ TestUtil.createTable(conn, "pkt", "id int primary key");
+ TestUtil.createTable(conn, "fkt1",
+ "id int references pkt on update restrict on delete cascade");
+ TestUtil.createTable(conn, "fkt2",
+ "id int references pkt on update set null on delete set default");
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getImportedKeys(null, "", "fkt1");
+ assertFalse(rs.next());
+ rs.close();
+
+ rs = dbmd.getImportedKeys(null, "", "fkt2");
+ assertFalse(rs.next());
+ rs.close();
+
+ TestUtil.dropTable(conn, "fkt2");
+ TestUtil.dropTable(conn, "fkt1");
+ TestUtil.dropTable(conn, "pkt");
+ }
}
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
void foreignKeyActions(BinaryMode binaryMode) throws Exception {
- Connection conn = TestUtil.openDB();
- TestUtil.createTable(conn, "pkt", "id int primary key");
- TestUtil.createTable(conn, "fkt1",
- "id int references pkt on update restrict on delete cascade");
- TestUtil.createTable(conn, "fkt2",
- "id int references pkt on update set null on delete set default");
- DatabaseMetaData dbmd = conn.getMetaData();
-
- ResultSet rs = dbmd.getImportedKeys(null, "", "fkt1");
- assertTrue(rs.next());
- assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE"));
- assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("DELETE_RULE"));
- rs.close();
+ try (Connection conn = TestUtil.openDB()) {
+ TestUtil.createTable(conn, "pkt", "id int primary key");
+ TestUtil.createTable(conn, "fkt1",
+ "id int references pkt on update restrict on delete cascade");
+ TestUtil.createTable(conn, "fkt2",
+ "id int references pkt on update set null on delete set default");
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getImportedKeys(null, null, "fkt1");
+ assertTrue(rs.next());
+ assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE"));
+ assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("DELETE_RULE"));
+ rs.close();
- rs = dbmd.getImportedKeys(null, "", "fkt2");
- assertTrue(rs.next());
- assertEquals(DatabaseMetaData.importedKeySetNull, rs.getInt("UPDATE_RULE"));
- assertEquals(DatabaseMetaData.importedKeySetDefault, rs.getInt("DELETE_RULE"));
- rs.close();
+ rs = dbmd.getImportedKeys(null, null, "fkt2");
+ assertTrue(rs.next());
+ assertEquals(DatabaseMetaData.importedKeySetNull, rs.getInt("UPDATE_RULE"));
+ assertEquals(DatabaseMetaData.importedKeySetDefault, rs.getInt("DELETE_RULE"));
+ rs.close();
+
+ TestUtil.dropTable(conn, "fkt2");
+ TestUtil.dropTable(conn, "fkt1");
+ TestUtil.dropTable(conn, "pkt");
+ }
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void foreignKeysToUniqueIndexes_whenCatalogAndSchemaArgsEmpty_expect(BinaryMode binaryMode) throws Exception {
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "pkt",
+ "a int not null, b int not null, CONSTRAINT pkt_pk_a PRIMARY KEY (a), CONSTRAINT pkt_un_b UNIQUE (b)");
+ TestUtil.createTable(con1, "fkt",
+ "c int, d int, CONSTRAINT fkt_fk_c FOREIGN KEY (c) REFERENCES pkt(b)");
+
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getImportedKeys("", "", "fkt");
+ assertFalse(rs.next());
- TestUtil.dropTable(conn, "fkt2");
- TestUtil.dropTable(conn, "fkt1");
- TestUtil.dropTable(conn, "pkt");
- TestUtil.closeDB(conn);
+ TestUtil.dropTable(con1, "fkt");
+ TestUtil.dropTable(con1, "pkt");
+ }
}
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
void foreignKeysToUniqueIndexes(BinaryMode binaryMode) throws Exception {
- Connection con1 = TestUtil.openDB();
- TestUtil.createTable(con1, "pkt",
- "a int not null, b int not null, CONSTRAINT pkt_pk_a PRIMARY KEY (a), CONSTRAINT pkt_un_b UNIQUE (b)");
- TestUtil.createTable(con1, "fkt",
- "c int, d int, CONSTRAINT fkt_fk_c FOREIGN KEY (c) REFERENCES pkt(b)");
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "pkt",
+ "a int not null, b int not null, CONSTRAINT pkt_pk_a PRIMARY KEY (a), CONSTRAINT pkt_un_b UNIQUE (b)");
+ TestUtil.createTable(con1, "fkt",
+ "c int, d int, CONSTRAINT fkt_fk_c FOREIGN KEY (c) REFERENCES pkt(b)");
- DatabaseMetaData dbmd = con.getMetaData();
- ResultSet rs = dbmd.getImportedKeys("", "", "fkt");
- int j = 0;
- for (; rs.next(); j++) {
- assertEquals("pkt", rs.getString("PKTABLE_NAME"));
- assertEquals("fkt", rs.getString("FKTABLE_NAME"));
- assertEquals("pkt_un_b", rs.getString("PK_NAME"));
- assertEquals("b", rs.getString("PKCOLUMN_NAME"));
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getImportedKeys(null, null, "fkt");
+ int j = 0;
+ for (; rs.next(); j++) {
+ assertEquals("pkt", rs.getString("PKTABLE_NAME"));
+ assertEquals("fkt", rs.getString("FKTABLE_NAME"));
+ assertEquals("pkt_un_b", rs.getString("PK_NAME"));
+ assertEquals("b", rs.getString("PKCOLUMN_NAME"));
+ }
+ assertEquals(1, j);
+
+ TestUtil.dropTable(con1, "fkt");
+ TestUtil.dropTable(con1, "pkt");
}
- assertEquals(1, j);
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void multiColumnForeignKeys_whenCatalogAndSchemaArgsEmpty_expectNoResults(BinaryMode binaryMode) throws Exception {
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "pkt",
+ "a int not null, b int not null, CONSTRAINT pkt_pk PRIMARY KEY (a,b)");
+ TestUtil.createTable(con1, "fkt",
+ "c int, d int, CONSTRAINT fkt_fk_pkt FOREIGN KEY (c,d) REFERENCES pkt(b,a)");
- TestUtil.dropTable(con1, "fkt");
- TestUtil.dropTable(con1, "pkt");
- con1.close();
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getImportedKeys("", "", "fkt");
+ assertFalse(rs.next());
+
+ TestUtil.dropTable(con1, "fkt");
+ TestUtil.dropTable(con1, "pkt");
+ }
}
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
void multiColumnForeignKeys(BinaryMode binaryMode) throws Exception {
- Connection con1 = TestUtil.openDB();
- TestUtil.createTable(con1, "pkt",
- "a int not null, b int not null, CONSTRAINT pkt_pk PRIMARY KEY (a,b)");
- TestUtil.createTable(con1, "fkt",
- "c int, d int, CONSTRAINT fkt_fk_pkt FOREIGN KEY (c,d) REFERENCES pkt(b,a)");
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "pkt",
+ "a int not null, b int not null, CONSTRAINT pkt_pk PRIMARY KEY (a,b)");
+ TestUtil.createTable(con1, "fkt",
+ "c int, d int, CONSTRAINT fkt_fk_pkt FOREIGN KEY (c,d) REFERENCES pkt(b,a)");
- DatabaseMetaData dbmd = con.getMetaData();
- ResultSet rs = dbmd.getImportedKeys("", "", "fkt");
- int j = 0;
- for (; rs.next(); j++) {
- assertEquals("pkt", rs.getString("PKTABLE_NAME"));
- assertEquals("fkt", rs.getString("FKTABLE_NAME"));
- assertEquals(j + 1, rs.getInt("KEY_SEQ"));
- if (j == 0) {
- assertEquals("b", rs.getString("PKCOLUMN_NAME"));
- assertEquals("c", rs.getString("FKCOLUMN_NAME"));
- } else {
- assertEquals("a", rs.getString("PKCOLUMN_NAME"));
- assertEquals("d", rs.getString("FKCOLUMN_NAME"));
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getImportedKeys(null, null, "fkt");
+ int j = 0;
+ for (; rs.next(); j++) {
+ assertEquals("pkt", rs.getString("PKTABLE_NAME"));
+ assertEquals("fkt", rs.getString("FKTABLE_NAME"));
+ assertEquals(j + 1, rs.getInt("KEY_SEQ"));
+ if (j == 0) {
+ assertEquals("b", rs.getString("PKCOLUMN_NAME"));
+ assertEquals("c", rs.getString("FKCOLUMN_NAME"));
+ } else {
+ assertEquals("a", rs.getString("PKCOLUMN_NAME"));
+ assertEquals("d", rs.getString("FKCOLUMN_NAME"));
+ }
}
+ assertEquals(2, j);
+
+ TestUtil.dropTable(con1, "fkt");
+ TestUtil.dropTable(con1, "pkt");
}
- assertEquals(2, j);
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void sameTableForeignKeys_whenSchemaArgEmpty_expectNoResults(BinaryMode binaryMode) throws Exception {
+ try (Connection con1 = TestUtil.openDB()) {
+
+ TestUtil.createTable(con1, "person",
+ "FIRST_NAME character varying(100) NOT NULL," + "LAST_NAME character varying(100) NOT NULL,"
+ + "FIRST_NAME_PARENT_1 character varying(100),"
+ + "LAST_NAME_PARENT_1 character varying(100),"
+ + "FIRST_NAME_PARENT_2 character varying(100),"
+ + "LAST_NAME_PARENT_2 character varying(100),"
+ + "CONSTRAINT PERSON_pkey PRIMARY KEY (FIRST_NAME , LAST_NAME ),"
+ + "CONSTRAINT PARENT_1_fkey FOREIGN KEY (FIRST_NAME_PARENT_1, LAST_NAME_PARENT_1)"
+ + "REFERENCES PERSON (FIRST_NAME, LAST_NAME) MATCH SIMPLE "
+ + "ON UPDATE CASCADE ON DELETE CASCADE,"
+ + "CONSTRAINT PARENT_2_fkey FOREIGN KEY (FIRST_NAME_PARENT_2, LAST_NAME_PARENT_2)"
+ + "REFERENCES PERSON (FIRST_NAME, LAST_NAME) MATCH SIMPLE "
+ + "ON UPDATE CASCADE ON DELETE CASCADE");
+
+ DatabaseMetaData dbmd = con.getMetaData();
+ assertNotNull(dbmd);
+ ResultSet rs = dbmd.getImportedKeys(null, "", "person");
+ assertFalse(rs.next());
- TestUtil.dropTable(con1, "fkt");
- TestUtil.dropTable(con1, "pkt");
- con1.close();
+ TestUtil.dropTable(con1, "person");
+ }
}
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
void sameTableForeignKeys(BinaryMode binaryMode) throws Exception {
- Connection con1 = TestUtil.openDB();
-
- TestUtil.createTable(con1, "person",
- "FIRST_NAME character varying(100) NOT NULL," + "LAST_NAME character varying(100) NOT NULL,"
- + "FIRST_NAME_PARENT_1 character varying(100),"
- + "LAST_NAME_PARENT_1 character varying(100),"
- + "FIRST_NAME_PARENT_2 character varying(100),"
- + "LAST_NAME_PARENT_2 character varying(100),"
- + "CONSTRAINT PERSON_pkey PRIMARY KEY (FIRST_NAME , LAST_NAME ),"
- + "CONSTRAINT PARENT_1_fkey FOREIGN KEY (FIRST_NAME_PARENT_1, LAST_NAME_PARENT_1)"
- + "REFERENCES PERSON (FIRST_NAME, LAST_NAME) MATCH SIMPLE "
- + "ON UPDATE CASCADE ON DELETE CASCADE,"
- + "CONSTRAINT PARENT_2_fkey FOREIGN KEY (FIRST_NAME_PARENT_2, LAST_NAME_PARENT_2)"
- + "REFERENCES PERSON (FIRST_NAME, LAST_NAME) MATCH SIMPLE "
- + "ON UPDATE CASCADE ON DELETE CASCADE");
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "person",
+ "FIRST_NAME character varying(100) NOT NULL," + "LAST_NAME character varying(100) NOT NULL,"
+ + "FIRST_NAME_PARENT_1 character varying(100),"
+ + "LAST_NAME_PARENT_1 character varying(100),"
+ + "FIRST_NAME_PARENT_2 character varying(100),"
+ + "LAST_NAME_PARENT_2 character varying(100),"
+ + "CONSTRAINT PERSON_pkey PRIMARY KEY (FIRST_NAME , LAST_NAME ),"
+ + "CONSTRAINT PARENT_1_fkey FOREIGN KEY (FIRST_NAME_PARENT_1, LAST_NAME_PARENT_1)"
+ + "REFERENCES PERSON (FIRST_NAME, LAST_NAME) MATCH SIMPLE "
+ + "ON UPDATE CASCADE ON DELETE CASCADE,"
+ + "CONSTRAINT PARENT_2_fkey FOREIGN KEY (FIRST_NAME_PARENT_2, LAST_NAME_PARENT_2)"
+ + "REFERENCES PERSON (FIRST_NAME, LAST_NAME) MATCH SIMPLE "
+ + "ON UPDATE CASCADE ON DELETE CASCADE");
- DatabaseMetaData dbmd = con.getMetaData();
- assertNotNull(dbmd);
- ResultSet rs = dbmd.getImportedKeys(null, "", "person");
+ DatabaseMetaData dbmd = con.getMetaData();
+ assertNotNull(dbmd);
+ ResultSet rs = dbmd.getImportedKeys(null, null, "person");
- final List<String> fkNames = new ArrayList<>();
+ final List<String> fkNames = new ArrayList<>();
- int lastFieldCount = -1;
- while (rs.next()) {
- // destination table (all foreign keys point to the same)
- String pkTableName = rs.getString("PKTABLE_NAME");
- assertEquals("person", pkTableName);
-
- // destination fields
- String pkColumnName = rs.getString("PKCOLUMN_NAME");
- assertTrue("first_name".equals(pkColumnName) || "last_name".equals(pkColumnName));
-
- // source table (all foreign keys are in the same)
- String fkTableName = rs.getString("FKTABLE_NAME");
- assertEquals("person", fkTableName);
-
- // foreign key name
- String fkName = rs.getString("FK_NAME");
- // sequence number within the foreign key
- int seq = rs.getInt("KEY_SEQ");
- if (seq == 1) {
- // begin new foreign key
- assertFalse(fkNames.contains(fkName));
- fkNames.add(fkName);
- // all foreign keys have 2 fields
- assertTrue(lastFieldCount < 0 || lastFieldCount == 2);
- } else {
- // continue foreign key, i.e. fkName matches the last foreign key
- assertEquals(fkNames.get(fkNames.size() - 1), fkName);
- // see always increases by 1
- assertEquals(seq, lastFieldCount + 1);
+ int lastFieldCount = -1;
+ while (rs.next()) {
+ // destination table (all foreign keys point to the same)
+ String pkTableName = rs.getString("PKTABLE_NAME");
+ assertEquals("person", pkTableName);
+
+ // destination fields
+ String pkColumnName = rs.getString("PKCOLUMN_NAME");
+ assertTrue("first_name".equals(pkColumnName) || "last_name".equals(pkColumnName));
+
+ // source table (all foreign keys are in the same)
+ String fkTableName = rs.getString("FKTABLE_NAME");
+ assertEquals("person", fkTableName);
+
+ // foreign key name
+ String fkName = rs.getString("FK_NAME");
+ // sequence number within the foreign key
+ int seq = rs.getInt("KEY_SEQ");
+ if (seq == 1) {
+ // begin new foreign key
+ assertFalse(fkNames.contains(fkName));
+ fkNames.add(fkName);
+ // all foreign keys have 2 fields
+ assertTrue(lastFieldCount < 0 || lastFieldCount == 2);
+ } else {
+ // continue foreign key, i.e. fkName matches the last foreign key
+ assertEquals(fkNames.get(fkNames.size() - 1), fkName);
+ // see always increases by 1
+ assertEquals(seq, lastFieldCount + 1);
+ }
+ lastFieldCount = seq;
}
- lastFieldCount = seq;
+ // there's more than one foreign key from a table to another
+ assertEquals(2, fkNames.size());
+
+ TestUtil.dropTable(con1, "person");
}
- // there's more than one foreign key from a table to another
- assertEquals(2, fkNames.size());
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void foreignKeys_whenSchemaArgNull_expectNoResults(BinaryMode binaryMode) throws Exception {
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "people", "id int4 primary key, name text");
+ TestUtil.createTable(con1, "policy", "id int4 primary key, name text");
+
+ TestUtil.createTable(con1, "users",
+ "id int4 primary key, people_id int4, policy_id int4,"
+ + "CONSTRAINT people FOREIGN KEY (people_id) references people(id),"
+ + "constraint policy FOREIGN KEY (policy_id) references policy(id)");
+
+ DatabaseMetaData dbmd = con.getMetaData();
+ assertNotNull(dbmd);
+
+ ResultSet rs = dbmd.getImportedKeys(null, "", "users");
+ assertFalse(rs.next());
+ rs.close();
- TestUtil.dropTable(con1, "person");
- TestUtil.closeDB(con1);
+ rs = dbmd.getExportedKeys(null, "", "people");
+ assertFalse(rs.next());
+ rs.close();
+
+ TestUtil.dropTable(con1, "users");
+ TestUtil.dropTable(con1, "people");
+ TestUtil.dropTable(con1, "policy");
+ }
}
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
void foreignKeys(BinaryMode binaryMode) throws Exception {
- Connection con1 = TestUtil.openDB();
- TestUtil.createTable(con1, "people", "id int4 primary key, name text");
- TestUtil.createTable(con1, "policy", "id int4 primary key, name text");
+ try (Connection con1 = TestUtil.openDB()) {
+ TestUtil.createTable(con1, "people", "id int4 primary key, name text");
+ TestUtil.createTable(con1, "policy", "id int4 primary key, name text");
- TestUtil.createTable(con1, "users",
- "id int4 primary key, people_id int4, policy_id int4,"
- + "CONSTRAINT people FOREIGN KEY (people_id) references people(id),"
- + "constraint policy FOREIGN KEY (policy_id) references policy(id)");
+ TestUtil.createTable(con1, "users",
+ "id int4 primary key, people_id int4, policy_id int4,"
+ + "CONSTRAINT people FOREIGN KEY (people_id) references people(id),"
+ + "constraint policy FOREIGN KEY (policy_id) references policy(id)");
- DatabaseMetaData dbmd = con.getMetaData();
- assertNotNull(dbmd);
+ DatabaseMetaData dbmd = con.getMetaData();
+ assertNotNull(dbmd);
- ResultSet rs = dbmd.getImportedKeys(null, "", "users");
- int j = 0;
- for (; rs.next(); j++) {
+ ResultSet rs = dbmd.getImportedKeys(null, null, "users");
+ int j = 0;
+ for (; rs.next(); j++) {
- String pkTableName = rs.getString("PKTABLE_NAME");
- assertTrue("people".equals(pkTableName) || "policy".equals(pkTableName));
+ String pkTableName = rs.getString("PKTABLE_NAME");
+ assertTrue("people".equals(pkTableName) || "policy".equals(pkTableName));
- String pkColumnName = rs.getString("PKCOLUMN_NAME");
- assertEquals("id", pkColumnName);
+ String pkColumnName = rs.getString("PKCOLUMN_NAME");
+ assertEquals("id", pkColumnName);
- String fkTableName = rs.getString("FKTABLE_NAME");
- assertEquals("users", fkTableName);
+ String fkTableName = rs.getString("FKTABLE_NAME");
+ assertEquals("users", fkTableName);
- String fkColumnName = rs.getString("FKCOLUMN_NAME");
- assertTrue("people_id".equals(fkColumnName) || "policy_id".equals(fkColumnName));
+ String fkColumnName = rs.getString("FKCOLUMN_NAME");
+ assertTrue("people_id".equals(fkColumnName) || "policy_id".equals(fkColumnName));
- String fkName = rs.getString("FK_NAME");
- assertTrue(fkName.startsWith("people") || fkName.startsWith("policy"));
+ String fkName = rs.getString("FK_NAME");
+ assertTrue(fkName.startsWith("people") || fkName.startsWith("policy"));
- String pkName = rs.getString("PK_NAME");
- assertTrue("people_pkey".equals(pkName) || "policy_pkey".equals(pkName));
+ String pkName = rs.getString("PK_NAME");
+ assertTrue("people_pkey".equals(pkName) || "policy_pkey".equals(pkName));
- }
+ }
- assertEquals(2, j);
+ assertEquals(2, j);
- rs = dbmd.getExportedKeys(null, "", "people");
+ rs = dbmd.getExportedKeys(null, null, "people");
- // this is hacky, but it will serve the purpose
- assertTrue(rs.next());
+ // this is hacky, but it will serve the purpose
+ assertTrue(rs.next());
- assertEquals("people", rs.getString("PKTABLE_NAME"));
- assertEquals("id", rs.getString("PKCOLUMN_NAME"));
+ assertEquals("people", rs.getString("PKTABLE_NAME"));
+ assertEquals("id", rs.getString("PKCOLUMN_NAME"));
- assertEquals("users", rs.getString("FKTABLE_NAME"));
- assertEquals("people_id", rs.getString("FKCOLUMN_NAME"));
+ assertEquals("users", rs.getString("FKTABLE_NAME"));
+ assertEquals("people_id", rs.getString("FKCOLUMN_NAME"));
- assertTrue(rs.getString("FK_NAME").startsWith("people"));
+ assertTrue(rs.getString("FK_NAME").startsWith("people"));
- TestUtil.dropTable(con1, "users");
- TestUtil.dropTable(con1, "people");
- TestUtil.dropTable(con1, "policy");
- TestUtil.closeDB(con1);
+ TestUtil.dropTable(con1, "users");
+ TestUtil.dropTable(con1, "people");
+ TestUtil.dropTable(con1, "policy");
+ }
}
@MethodSource("data")
@@ -849,9 +1000,17 @@ public class DatabaseMetaDataTest {
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
- void notNullDomainColumn(BinaryMode binaryMode) throws SQLException {
+ void notNullDomainColumn_whenCatalogAndSchemaAndColumnNameArgsEmpty_expectNoResults(BinaryMode binaryMode) throws SQLException {
DatabaseMetaData dbmd = con.getMetaData();
ResultSet rs = dbmd.getColumns("", "", "domaintable", "");
+ assertFalse(rs.next());
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void notNullDomainColumn(BinaryMode binaryMode) throws SQLException {
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getColumns(null, null, "domaintable", null);
assertTrue(rs.next());
assertEquals("id", rs.getString("COLUMN_NAME"));
assertEquals("NO", rs.getString("IS_NULLABLE"));
@@ -862,9 +1021,17 @@ public class DatabaseMetaDataTest {
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
- void domainColumnSize(BinaryMode binaryMode) throws SQLException {
+ void domainColumnSize_whenCatalogAndSchemaAndColumnNameArgsEmpty_expectNoResults(BinaryMode binaryMode) throws SQLException {
DatabaseMetaData dbmd = con.getMetaData();
ResultSet rs = dbmd.getColumns("", "", "domaintable", "");
+ assertFalse(rs.next());
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void domainColumnSize(BinaryMode binaryMode) throws SQLException {
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getColumns(null, null, "domaintable", null);
assertTrue(rs.next());
assertEquals("id", rs.getString("COLUMN_NAME"));
assertEquals(10, rs.getInt("COLUMN_SIZE"));
@@ -1218,7 +1385,7 @@ public class DatabaseMetaDataTest {
assertEquals("jdbc", schema, "schema name ");
// now test to see if the fully qualified stuff works as planned
- rs = dbmd.getUDTs("catalog", "public", "catalog.jdbc.testint8", null);
+ rs = dbmd.getUDTs(System.getProperty("database"), "public", "catalog.jdbc.testint8", null);
assertTrue(rs.next());
cat = rs.getString("type_cat");
schema = rs.getString("type_schem");
@@ -1465,9 +1632,17 @@ public class DatabaseMetaDataTest {
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
- void informationAboutArrayTypes(BinaryMode binaryMode) throws SQLException {
+ void informationAboutArrayTypes_whenCatalogSchemaColumnNamePatternArgsEmpty_expectNoResults(BinaryMode binaryMode) throws SQLException {
DatabaseMetaData dbmd = con.getMetaData();
ResultSet rs = dbmd.getColumns("", "", "arraytable", "");
+ assertFalse(rs.next());
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void informationAboutArrayTypes(BinaryMode binaryMode) throws SQLException {
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getColumns(null, null, "arraytable", null);
assertTrue(rs.next());
assertEquals("a", rs.getString("COLUMN_NAME"));
assertEquals(5, rs.getInt("COLUMN_SIZE"));
@@ -1480,11 +1655,22 @@ public class DatabaseMetaDataTest {
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
- void primaryKeysWithIncludeColumns(BinaryMode binaryMode) throws SQLException {
+ void primaryKeysWithIncludeColumns_whenCatalogAndSchemaArgsEmpty_expectNoResults(BinaryMode binaryMode) throws SQLException {
String tableName = "pk_include_column";
if (TestUtil.haveMinimumServerVersion(con, ServerVersion.v11)) {
DatabaseMetaData dbmd = con.getMetaData();
ResultSet rs = dbmd.getPrimaryKeys("", "", tableName);
+ assertFalse(rs.next());
+ }
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void primaryKeysWithIncludeColumns(BinaryMode binaryMode) throws SQLException {
+ String tableName = "pk_include_column";
+ if (TestUtil.haveMinimumServerVersion(con, ServerVersion.v11)) {
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getPrimaryKeys(null, null, tableName);
// getPrimaryKeys should return only the key columns and not the included column
assertTrue(rs.next());
@@ -1500,76 +1686,109 @@ public class DatabaseMetaDataTest {
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
- void partitionedTablesIndex(BinaryMode binaryMode) throws SQLException {
+ void partitionedTablesIndex_whenCatalogAndSchemaArgsEmpty_expectNoResults(BinaryMode binaryMode) throws SQLException {
if (TestUtil.haveMinimumServerVersion(con, ServerVersion.v11)) {
- Statement stmt = null;
- try {
- stmt = con.createStatement();
+ try (Statement stmt = con.createStatement()) {
stmt.execute(
"CREATE TABLE measurement (logdate date not null primary key,peaktemp int,unitsales int ) PARTITION BY RANGE (logdate);");
DatabaseMetaData dbmd = con.getMetaData();
ResultSet rs = dbmd.getPrimaryKeys("", "", "measurement");
+ assertFalse(rs.next());
+
+ stmt.execute("drop table if exists measurement");
+ }
+ }
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void partitionedTablesIndex(BinaryMode binaryMode) throws SQLException {
+ if (TestUtil.haveMinimumServerVersion(con, ServerVersion.v11)) {
+ try (Statement stmt = con.createStatement()) {
+ stmt.execute(
+ "CREATE TABLE measurement (logdate date not null primary key,peaktemp int,unitsales int ) PARTITION BY RANGE (logdate);");
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getPrimaryKeys(null, null, "measurement");
assertTrue(rs.next());
assertEquals("measurement_pkey", rs.getString(6));
- } finally {
- if (stmt != null) {
- stmt.execute("drop table if exists measurement");
- stmt.close();
- }
+ stmt.execute("drop table if exists measurement");
}
}
+ }
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void partitionedTables_whenCatalogAndSchemaArgsEmpty_expectNoResults(BinaryMode binaryMode) throws SQLException {
+ if (TestUtil.haveMinimumServerVersion(con, ServerVersion.v11)) {
+ try (Statement stmt = con.createStatement()) {
+ stmt.execute(
+ "CREATE TABLE measurement (logdate date not null primary key,peaktemp int,unitsales int ) PARTITION BY RANGE (logdate);");
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getTables("", "", "measurement", new String[]{"PARTITIONED TABLE"});
+ assertFalse(rs.next());
+ rs.close();
+ rs = dbmd.getPrimaryKeys("", "", "measurement");
+ assertFalse(rs.next());
+
+ stmt.execute("drop table if exists measurement");
+ }
+ }
}
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
void partitionedTables(BinaryMode binaryMode) throws SQLException {
if (TestUtil.haveMinimumServerVersion(con, ServerVersion.v11)) {
- Statement stmt = null;
- try {
- stmt = con.createStatement();
+ try (Statement stmt = con.createStatement()) {
stmt.execute(
"CREATE TABLE measurement (logdate date not null primary key,peaktemp int,unitsales int ) PARTITION BY RANGE (logdate);");
DatabaseMetaData dbmd = con.getMetaData();
- ResultSet rs = dbmd.getTables("", "", "measurement", new String[]{"PARTITIONED TABLE"});
+ ResultSet rs = dbmd.getTables(null, null, "measurement", new String[]{"PARTITIONED TABLE"});
assertTrue(rs.next());
assertEquals("measurement", rs.getString("table_name"));
rs.close();
- rs = dbmd.getPrimaryKeys("", "", "measurement");
+ rs = dbmd.getPrimaryKeys(null, null, "measurement");
assertTrue(rs.next());
assertEquals("measurement_pkey", rs.getString(6));
- } finally {
- if (stmt != null) {
- stmt.execute("drop table if exists measurement");
- stmt.close();
- }
+ stmt.execute("drop table if exists measurement");
}
}
}
@MethodSource("data")
@ParameterizedTest(name = "binary = {0}")
- void identityColumns(BinaryMode binaryMode) throws SQLException {
+ void identityColumns_whenCatalogAndSchemaArgsEmpty_expectNoResults(BinaryMode binaryMode) throws SQLException {
if ( TestUtil.haveMinimumServerVersion(con, ServerVersion.v10) ) {
- Statement stmt = null;
- try {
- stmt = con.createStatement();
+ try (Statement stmt = con.createStatement()) {
stmt.execute("CREATE TABLE test_new ("
+ "id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,"
+ "payload text)");
DatabaseMetaData dbmd = con.getMetaData();
ResultSet rs = dbmd.getColumns("", "", "test_new", "id");
+ assertFalse(rs.next());
+
+ stmt.execute("drop table test_new");
+ }
+ }
+ }
+
+ @MethodSource("data")
+ @ParameterizedTest(name = "binary = {0}")
+ void identityColumns(BinaryMode binaryMode) throws SQLException {
+ if ( TestUtil.haveMinimumServerVersion(con, ServerVersion.v10) ) {
+ try (Statement stmt = con.createStatement()) {
+ stmt.execute("CREATE TABLE test_new ("
+ + "id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,"
+ + "payload text)");
+ DatabaseMetaData dbmd = con.getMetaData();
+ ResultSet rs = dbmd.getColumns(null, null, "test_new", "id");
assertTrue(rs.next());
assertEquals("id", rs.getString("COLUMN_NAME"));
assertTrue(rs.getBoolean("IS_AUTOINCREMENT"));
- } finally {
- if ( stmt != null ) {
- stmt.execute("drop table test_new");
- stmt.close();
- }
+ stmt.execute("drop table test_new");
}
}
}
@@ -1579,7 +1798,7 @@ public class DatabaseMetaDataTest {
void generatedColumns(BinaryMode binaryMode) throws SQLException {
if ( TestUtil.haveMinimumServerVersion(con, ServerVersion.v12) ) {
DatabaseMetaData dbmd = con.getMetaData();
- ResultSet rs = dbmd.getColumns("", "", "employee", "gross_pay");
+ ResultSet rs = dbmd.getColumns(null, null, "employee", "gross_pay");
assertTrue(rs.next());
assertEquals("gross_pay", rs.getString("COLUMN_NAME"));
assertTrue(rs.getBoolean("IS_GENERATEDCOLUMN"));
@@ -1688,7 +1907,7 @@ public class DatabaseMetaDataTest {
assertEquals("SPECIFIC_NAME", rsmd.getColumnName(17));
assertTrue(rs.next());
- assertNull(rs.getString(1));
+ assertNotNull(rs.getString(1));
assertEquals("public", rs.getString(2));
assertEquals("f1", rs.getString(3));
assertEquals("returnValue", rs.getString(4));
@@ -1698,7 +1917,7 @@ public class DatabaseMetaDataTest {
assertEquals(0, rs.getInt(15));
assertTrue(rs.next());
- assertNull(rs.getString(1));
+ assertNotNull(rs.getString(1));
assertEquals("public", rs.getString(2));
assertEquals("f1", rs.getString(3));
assertEquals("$1", rs.getString(4));
@@ -1708,7 +1927,7 @@ public class DatabaseMetaDataTest {
assertEquals(1, rs.getInt(15));
assertTrue(rs.next());
- assertNull(rs.getString(1));
+ assertNotNull(rs.getString(1));
assertEquals("public", rs.getString(2));
assertEquals("f1", rs.getString(3));
assertEquals("$2", rs.getString(4));
diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc3/DatabaseMetaDataTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc3/DatabaseMetaDataTest.java
index 05c5b3d0..03411916 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/jdbc3/DatabaseMetaDataTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc3/DatabaseMetaDataTest.java
@@ -42,10 +42,18 @@ class DatabaseMetaDataTest {
}
@Test
- void getColumnsForDomain() throws Exception {
+ void getColumnsForDomain_whenCatalogArgPercentSign_expectNoResults() throws Exception {
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rs = dbmd.getColumns("%", "%", "domtab", "%");
+ assertFalse(rs.next());
+ }
+
+ @Test
+ void getColumnsForDomain() throws Exception {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getColumns(null, "%", "domtab", "%");
assertTrue(rs.next());
assertEquals("a", rs.getString("COLUMN_NAME"));
assertEquals(Types.DISTINCT, rs.getInt("DATA_TYPE"));
diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc4/DatabaseMetaDataTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc4/DatabaseMetaDataTest.java
index 80e16e4a..70424fe7 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/jdbc4/DatabaseMetaDataTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc4/DatabaseMetaDataTest.java
@@ -7,11 +7,10 @@ package org.postgresql.test.jdbc4;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.postgresql.core.ServerVersion;
@@ -30,6 +29,7 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.UUID;
class DatabaseMetaDataTest {
@@ -78,10 +78,18 @@ class DatabaseMetaDataTest {
}
@Test
- void getColumnsForAutoIncrement() throws Exception {
+ void getColumnsForAutoIncrement_whenCatalogArgPercentSign_expectNoResults() throws Exception {
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rs = dbmd.getColumns("%", "%", "sercoltest", "%");
+ assertFalse(rs.next());
+ }
+
+ @Test
+ void getColumnsForAutoIncrement() throws Exception {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getColumns(null, "%", "sercoltest", "%");
assertTrue(rs.next());
assertEquals("a", rs.getString("COLUMN_NAME"));
assertEquals("YES", rs.getString("IS_AUTOINCREMENT"));
@@ -93,42 +101,105 @@ class DatabaseMetaDataTest {
assertFalse(rs.next());
}
+ @Test
+ void getSchemas_whenCatalogArgPercentSign_expectNoResults() throws SQLException {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getSchemas("%", "publ%");
+
+ assertFalse(rs.next());
+ }
+
@Test
void getSchemas() throws SQLException {
DatabaseMetaData dbmd = conn.getMetaData();
- ResultSet rs = dbmd.getSchemas("", "publ%");
+ ResultSet rs = dbmd.getSchemas(null, "publ%");
assertTrue(rs.next());
assertEquals("public", rs.getString("TABLE_SCHEM"));
- assertNull(rs.getString("TABLE_CATALOG"));
+ assertNotNull(rs.getString("TABLE_CATALOG"));
assertFalse(rs.next());
}
+ @Test
+ void getSchemas_whenNullCatalogAndSchemaPattern_expectRows() throws SQLException {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getSchemas(null, null);
+
+ assertTrue(rs.next());
+ }
+
+ @Test
+ void getSchemas_whenEmptySchemaPattern_expectNoRows() throws SQLException {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getSchemas(null, "");
+
+ assertFalse(rs.next());
+ }
+
+ @Test
+ void getSchemas_whenEmptyCatalog_expectNoRows() throws SQLException {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getSchemas("", null);
+
+ assertFalse(rs.next());
+ }
+
+ @Test
+ void getSchemas_whenRandomCatalog_expectNoRows() throws SQLException {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getSchemas(UUID.randomUUID().toString(), null);
+
+ assertFalse(rs.next());
+ }
+
+ @Test
+ void getFunctionsInSchemaForFunctions_whenCatalogArgEmpty_expectNoResults() throws SQLException {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ try (ResultSet rs = dbmd.getFunctions("", "hasfunctions", null)) {
+ assertFalse(rs.next());
+ }
+
+ try (ResultSet rs = dbmd.getFunctions("", "hasfunctions", "addfunction")) {
+ assertFalse(rs.next());
+ }
+
+ try (ResultSet rs = dbmd.getFunctions("", "nofunctions", null)) {
+ boolean hasFunctions = rs.next();
+ assertFalse(hasFunctions, "There should be no functions in the nofunctions schema");
+ }
+ }
+
@Test
void getFunctionsInSchemaForFunctions() throws SQLException {
DatabaseMetaData dbmd = conn.getMetaData();
- try (ResultSet rs = dbmd.getFunctions("", "hasfunctions", "")) {
+ try (ResultSet rs = dbmd.getFunctions(null, "hasfunctions", null)) {
List<CatalogObject> list = assertFunctionRSAndReturnList(rs);
assertEquals(1, list.size(), "There should be one function in the hasfunctions schema");
assertListContains("getFunctions('', 'hasfunctions', '') must contain addfunction", list, "hasfunctions", "addfunction");
}
- try (ResultSet rs = dbmd.getFunctions("", "hasfunctions", "addfunction")) {
+ try (ResultSet rs = dbmd.getFunctions(null, "hasfunctions", "addfunction")) {
List<CatalogObject> list = assertFunctionRSAndReturnList(rs);
assertEquals(1, list.size(), "There should be one function in the hasfunctions schema with name addfunction");
assertListContains("getFunctions('', 'hasfunctions', 'addfunction') must contain addfunction", list, "hasfunctions", "addfunction");
}
- try (ResultSet rs = dbmd.getFunctions("", "nofunctions", "")) {
+ try (ResultSet rs = dbmd.getFunctions(null, "nofunctions", null)) {
boolean hasFunctions = rs.next();
assertFalse(hasFunctions, "There should be no functions in the nofunctions schema");
}
}
@Test
- void getFunctionsInSchemaForProcedures() throws SQLException {
+ void getFunctionsInSchemaForProcedures_whenCatalogArgEmpty_expectNoResults() throws SQLException {
// Due to the introduction of actual stored procedures in PostgreSQL 11, getFunctions should not return procedures for PostgreSQL versions 11+
// On older installation we do not create the procedures so the below schemas should all be empty
DatabaseMetaData dbmd = conn.getMetaData();
@@ -148,12 +219,58 @@ class DatabaseMetaDataTest {
}
@Test
- void getProceduresInSchemaForFunctions() throws SQLException {
+ void getFunctionsInSchemaForProcedures() throws SQLException {
+ // Due to the introduction of actual stored procedures in PostgreSQL 11, getFunctions should not return procedures for PostgreSQL versions 11+
+ // On older installation we do not create the procedures so the below schemas should all be empty
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ // Search for functions in schema "hasprocedures"
+ try (ResultSet rs = dbmd.getFunctions(null, "hasprocedures", null)) {
+ assertFalse(rs.next(), "The hasprocedures schema not return procedures from getFunctions");
+ }
+ // Search for functions in schema "noprocedures" (which should never expect records)
+ try (ResultSet rs = dbmd.getFunctions(null, "noprocedures", null)) {
+ assertFalse(rs.next(), "The noprocedures schema should not have functions");
+ }
+ // Search for functions by procedure name "addprocedure"
+ try (ResultSet rs = dbmd.getFunctions(null, "hasprocedures", "addprocedure")) {
+ assertFalse(rs.next(), "Should not return procedures from getFunctions by schema + name");
+ }
+ }
+
+ @Test
+ void getProceduresInSchemaForFunctions_whenCatalogArgEmpty_expectNoResults() throws SQLException {
// Due to the introduction of actual stored procedures in PostgreSQL 11, getProcedures should not return functions for PostgreSQL versions 11+
DatabaseMetaData dbmd = conn.getMetaData();
// Search for procedures in schema "hasfunctions" (which should expect a record only for PostgreSQL < 11)
try (ResultSet rs = dbmd.getProcedures("", "hasfunctions", null)) {
+ assertFalse(rs.next());
+ }
+
+ // Search for procedures in schema "nofunctions" (which should never expect records)
+ try (ResultSet rs = dbmd.getProcedures("", "nofunctions", null)) {
+ assertFalse(rs.next(), "getProcedures(...) should not return procedures for schema nofunctions");
+ }
+
+ // Search for procedures by function name "addfunction" within schema "hasfunctions" (which should expect a record for PostgreSQL < 11)
+ try (ResultSet rs = dbmd.getProcedures("", "hasfunctions", "addfunction")) {
+ assertFalse(rs.next());
+ }
+
+ // Search for procedures by function name "addfunction" within schema "nofunctions" (which should never expect records)
+ try (ResultSet rs = dbmd.getProcedures("", "nofunctions", "addfunction")) {
+ assertFalse(rs.next(), "getProcedures(...) should not return procedures for schema nofunctions + addfunction");
+ }
+ }
+
+ @Test
+ void getProceduresInSchemaForFunctions() throws SQLException {
+ // Due to the introduction of actual stored procedures in PostgreSQL 11, getProcedures should not return functions for PostgreSQL versions 11+
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ // Search for procedures in schema "hasfunctions" (which should expect a record only for PostgreSQL < 11)
+ try (ResultSet rs = dbmd.getProcedures(null, "hasfunctions", null)) {
if (TestUtil.haveMinimumServerVersion(conn, ServerVersion.v11)) {
assertFalse(rs.next(), "PostgreSQL11+ should not return functions from getProcedures");
} else {
@@ -163,12 +280,12 @@ class DatabaseMetaDataTest {
}
// Search for procedures in schema "nofunctions" (which should never expect records)
- try (ResultSet rs = dbmd.getProcedures("", "nofunctions", null)) {
+ try (ResultSet rs = dbmd.getProcedures(null, "nofunctions", null)) {
assertFalse(rs.next(), "getProcedures(...) should not return procedures for schema nofunctions");
}
// Search for procedures by function name "addfunction" within schema "hasfunctions" (which should expect a record for PostgreSQL < 11)
- try (ResultSet rs = dbmd.getProcedures("", "hasfunctions", "addfunction")) {
+ try (ResultSet rs = dbmd.getProcedures(null, "hasfunctions", "addfunction")) {
if (TestUtil.haveMinimumServerVersion(conn, ServerVersion.v11)) {
assertFalse(rs.next(), "PostgreSQL11+ should not return functions from getProcedures");
} else {
@@ -178,29 +295,28 @@ class DatabaseMetaDataTest {
}
// Search for procedures by function name "addfunction" within schema "nofunctions" (which should never expect records)
- try (ResultSet rs = dbmd.getProcedures("", "nofunctions", "addfunction")) {
+ try (ResultSet rs = dbmd.getProcedures(null, "nofunctions", "addfunction")) {
assertFalse(rs.next(), "getProcedures(...) should not return procedures for schema nofunctions + addfunction");
}
}
@Test
- void getProceduresInSchemaForProcedures() throws SQLException {
+ void getProceduresInSchemaForProcedures_whenCatalogArgEmpty_expectNoResults() throws SQLException {
// Only run this test for PostgreSQL version 11+; assertions for versions prior would be vacuously true as we don't create a procedure in the setup for older versions
Assumptions.assumeTrue(TestUtil.haveMinimumServerVersion(conn, ServerVersion.v11));
DatabaseMetaData dbmd = conn.getMetaData();
try (ResultSet rs = dbmd.getProcedures("", "hasprocedures", null)) {
- int count = assertProcedureRS(rs);
- assertEquals(1, count, "getProcedures() should be non-empty for the hasprocedures schema");
+ assertFalse(rs.next());
}
try (ResultSet rs = dbmd.getProcedures("", "noprocedures", null)) {
- assertFalse(rs.next(), "getProcedures() should be empty for the hasprocedures schema");
+ assertFalse(rs.next(), "getProcedures() should be empty for the noprocedures schema");
}
try (ResultSet rs = dbmd.getProcedures("", "hasfunctions", null)) {
- assertFalse(rs.next(), "getProcedures() should be empty for the nofunctions schema");
+ assertFalse(rs.next(), "getProcedures() should be empty for the hasfunctions schema");
}
try (ResultSet rs = dbmd.getProcedures("", "nofunctions", null)) {
@@ -208,6 +324,51 @@ class DatabaseMetaDataTest {
}
}
+ @Test
+ void getProceduresInSchemaForProcedures() throws SQLException {
+ // Only run this test for PostgreSQL version 11+; assertions for versions prior would be vacuously true as we don't create a procedure in the setup for older versions
+ Assumptions.assumeTrue(TestUtil.haveMinimumServerVersion(conn, ServerVersion.v11));
+
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ try (ResultSet rs = dbmd.getProcedures(null, "hasprocedures", null)) {
+ int count = assertProcedureRS(rs);
+ assertEquals(1, count, "getProcedures() should be non-empty for the hasprocedures schema");
+ }
+
+ try (ResultSet rs = dbmd.getProcedures(null, "noprocedures", null)) {
+ assertFalse(rs.next(), "getProcedures() should be empty for the noprocedures schema");
+ }
+
+ try (ResultSet rs = dbmd.getProcedures(null, "hasfunctions", null)) {
+ assertFalse(rs.next(), "getProcedures() should be empty for the hasfunctions schema");
+ }
+
+ try (ResultSet rs = dbmd.getProcedures(null, "nofunctions", null)) {
+ assertFalse(rs.next(), "getProcedures() should be empty for the nofunctions schema");
+ }
+ }
+
+ @Test
+ void getFunctionsWithEmptyPatterns() throws SQLException {
+ DatabaseMetaData dbmd = conn.getMetaData();
+ try (ResultSet rs = dbmd.getFunctions("", "", "")) {
+ assertFalse(rs.next());
+ }
+
+ try (ResultSet rs = dbmd.getFunctions("", null, null)) {
+ assertFalse(rs.next());
+ }
+
+ try (ResultSet rs = dbmd.getFunctions(null, "", null)) {
+ assertFalse(rs.next());
+ }
+
+ try (ResultSet rs = dbmd.getFunctions(null, null, "")) {
+ assertFalse(rs.next());
+ }
+ }
+
@Test
void getFunctionsWithBlankPatterns() throws SQLException {
int minFuncCount = 1000;
@@ -215,38 +376,71 @@ class DatabaseMetaDataTest {
final int totalCount;
try (ResultSet rs = dbmd.getFunctions("", "", "")) {
+ assertFalse(rs.next());
+ }
+
+ // Should not be same as blank pattern
+ try (ResultSet rs = dbmd.getFunctions(null, null, null)) {
List<CatalogObject> list = assertFunctionRSAndReturnList(rs);
totalCount = list.size(); // Rest of this test will validate against this value
assertThat(totalCount > minFuncCount, is(true));
assertListContains("getFunctions('', '', '') must contain addfunction", list, "hasfunctions", "addfunction");
}
- // Should be same as blank pattern
+ // Catalog parameter has effect on our getFunctions filtering
+ try (ResultSet rs = dbmd.getFunctions("ANYTHING_WILL_WORK", null, null)) {
+ assertFalse(rs.next());
+ }
+
+ // Filter by schema
+ try (ResultSet rs = dbmd.getFunctions("", "pg_catalog", null)) {
+ assertFalse(rs.next());
+ }
+
+ // Filter by schema and function name
+ try (ResultSet rs = dbmd.getFunctions("", "pg_catalog", "abs")) {
+ assertFalse(rs.next());
+ }
+
+ // Filter by function name only
+ try (ResultSet rs = dbmd.getFunctions("", "", "abs")) {
+ assertFalse(rs.next());
+ }
+ }
+
+ @Test
+ void getFunctionsWithNullPatterns() throws SQLException {
+ int minFuncCount = 1000;
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ final int totalCount;
+
try (ResultSet rs = dbmd.getFunctions(null, null, null)) {
- int count = assertGetFunctionRS(rs);
- assertThat(count, is(totalCount));
+ List<CatalogObject> list = assertFunctionRSAndReturnList(rs);
+ totalCount = list.size(); // Rest of this test will validate against this value
+ assertThat(totalCount > minFuncCount, is(true));
+ assertListContains("getFunctions('', '', '') must contain addfunction", list, "hasfunctions", "addfunction");
}
- // Catalog parameter has no affect on our getFunctions filtering
- try (ResultSet rs = dbmd.getFunctions("ANYTHING_WILL_WORK", null, null)) {
- int count = assertGetFunctionRS(rs);
- assertThat(count, is(totalCount));
+ // Catalog parameter has effect on our getFunctions filtering
+ try (ResultSet rs = dbmd.getFunctions(UUID.randomUUID().toString(), null, null)) {
+ assertFalse(rs.next());
}
// Filter by schema
- try (ResultSet rs = dbmd.getFunctions("", "pg_catalog", null)) {
+ try (ResultSet rs = dbmd.getFunctions(null, "pg_catalog", null)) {
int count = assertGetFunctionRS(rs);
assertThat(count > minFuncCount, is(true));
}
// Filter by schema and function name
- try (ResultSet rs = dbmd.getFunctions("", "pg_catalog", "abs")) {
+ try (ResultSet rs = dbmd.getFunctions(null, "pg_catalog", "abs")) {
int count = assertGetFunctionRS(rs);
assertThat(count >= 1, is(true));
}
// Filter by function name only
- try (ResultSet rs = dbmd.getFunctions("", "", "abs")) {
+ try (ResultSet rs = dbmd.getFunctions(null, null, "abs")) {
int count = assertGetFunctionRS(rs);
assertThat(count >= 1, is(true));
}
@@ -357,7 +551,7 @@ class DatabaseMetaDataTest {
private List<CatalogObject> assertProcedureRSAndReturnList(ResultSet rs) throws SQLException {
// There should be at least one row
assertThat(rs.next(), is(true));
- assertThat(rs.getString("PROCEDURE_CAT"), nullValue());
+ assertThat(rs.getString("PROCEDURE_CAT"), is(System.getProperty("database")));
assertThat(rs.getString("PROCEDURE_SCHEM"), notNullValue());
assertThat(rs.getString("PROCEDURE_NAME"), notNullValue());
assertThat(rs.getShort("PROCEDURE_TYPE") >= 0, is(true));
@@ -397,6 +591,55 @@ class DatabaseMetaDataTest {
assertTrue(found, message + "; schema=" + schema + " name=" + name);
}
+ @Test
+ void getFunctionsWithSpecificTypes_whenCatalogAndSchemaArgsEmpty_expectNoResults() throws SQLException {
+ // These function creation are borrow from jdbc2/DatabaseMetaDataTest
+ // We modify to ensure new function created are returned by getFunctions()
+
+ DatabaseMetaData dbmd = conn.getMetaData();
+ if (TestUtil.haveMinimumServerVersion(conn, ServerVersion.v8_4)) {
+ Statement stmt = conn.createStatement();
+ stmt.execute(
+ "CREATE OR REPLACE FUNCTION getfunc_f1(int, varchar) RETURNS int AS 'SELECT 1;' LANGUAGE SQL");
+ ResultSet rs = dbmd.getFunctions("", "", "getfunc_f1");
+ assertThat(rs.next(), is(false));
+ rs.close();
+ stmt.execute("DROP FUNCTION getfunc_f1(int, varchar)");
+
+ stmt.execute(
+ "CREATE OR REPLACE FUNCTION getfunc_f3(IN a int, INOUT b varchar, OUT c timestamptz) AS $f$ BEGIN b := 'a'; c := now(); return; END; $f$ LANGUAGE plpgsql");
+ rs = dbmd.getFunctions("", "", "getfunc_f3");
+ assertThat(rs.next(), is(false));
+ rs.close();
+ stmt.execute("DROP FUNCTION getfunc_f3(int, varchar)");
+
+ // RETURNS TABLE requires PostgreSQL 8.4+
+ stmt.execute(
+ "CREATE OR REPLACE FUNCTION getfunc_f5() RETURNS TABLE (i int) LANGUAGE sql AS 'SELECT 1'");
+
+ rs = dbmd.getFunctions("", "", "getfunc_f5");
+ assertThat(rs.next(), is(false));
+ rs.close();
+ stmt.execute("DROP FUNCTION getfunc_f5()");
+ } else {
+ // For PG 8.3 or 8.2 it will resulted in unknown function type
+ Statement stmt = conn.createStatement();
+ stmt.execute(
+ "CREATE OR REPLACE FUNCTION getfunc_f1(int, varchar) RETURNS int AS 'SELECT 1;' LANGUAGE SQL");
+ ResultSet rs = dbmd.getFunctions("", "", "getfunc_f1");
+ assertThat(rs.next(), is(false));
+ rs.close();
+ stmt.execute("DROP FUNCTION getfunc_f1(int, varchar)");
+
+ stmt.execute(
+ "CREATE OR REPLACE FUNCTION getfunc_f3(IN a int, INOUT b varchar, OUT c timestamptz) AS $f$ BEGIN b := 'a'; c := now(); return; END; $f$ LANGUAGE plpgsql");
+ rs = dbmd.getFunctions("", "", "getfunc_f3");
+ assertThat(rs.next(), is(false));
+ rs.close();
+ stmt.execute("DROP FUNCTION getfunc_f3(int, varchar)");
+ }
+ }
+
@Test
void getFunctionsWithSpecificTypes() throws SQLException {
// These function creation are borrow from jdbc2/DatabaseMetaDataTest
@@ -407,7 +650,7 @@ class DatabaseMetaDataTest {
Statement stmt = conn.createStatement();
stmt.execute(
"CREATE OR REPLACE FUNCTION getfunc_f1(int, varchar) RETURNS int AS 'SELECT 1;' LANGUAGE SQL");
- ResultSet rs = dbmd.getFunctions("", "", "getfunc_f1");
+ ResultSet rs = dbmd.getFunctions(null, null, "getfunc_f1");
assertThat(rs.next(), is(true));
assertThat(rs.getString("FUNCTION_NAME"), is("getfunc_f1"));
assertThat(rs.getShort("FUNCTION_TYPE"), is((short) DatabaseMetaData.functionNoTable));
@@ -417,7 +660,7 @@ class DatabaseMetaDataTest {
stmt.execute(
"CREATE OR REPLACE FUNCTION getfunc_f3(IN a int, INOUT b varchar, OUT c timestamptz) AS $f$ BEGIN b := 'a'; c := now(); return; END; $f$ LANGUAGE plpgsql");
- rs = dbmd.getFunctions("", "", "getfunc_f3");
+ rs = dbmd.getFunctions(null, null, "getfunc_f3");
assertThat(rs.next(), is(true));
assertThat(rs.getString("FUNCTION_NAME"), is("getfunc_f3"));
assertThat(rs.getShort("FUNCTION_TYPE"), is((short) DatabaseMetaData.functionNoTable));
@@ -429,7 +672,7 @@ class DatabaseMetaDataTest {
stmt.execute(
"CREATE OR REPLACE FUNCTION getfunc_f5() RETURNS TABLE (i int) LANGUAGE sql AS 'SELECT 1'");
- rs = dbmd.getFunctions("", "", "getfunc_f5");
+ rs = dbmd.getFunctions(null, null, "getfunc_f5");
assertThat(rs.next(), is(true));
assertThat(rs.getString("FUNCTION_NAME"), is("getfunc_f5"));
assertThat(rs.getShort("FUNCTION_TYPE"), is((short) DatabaseMetaData.functionReturnsTable));
@@ -441,7 +684,7 @@ class DatabaseMetaDataTest {
Statement stmt = conn.createStatement();
stmt.execute(
"CREATE OR REPLACE FUNCTION getfunc_f1(int, varchar) RETURNS int AS 'SELECT 1;' LANGUAGE SQL");
- ResultSet rs = dbmd.getFunctions("", "", "getfunc_f1");
+ ResultSet rs = dbmd.getFunctions(null, null, "getfunc_f1");
assertThat(rs.next(), is(true));
assertThat(rs.getString("FUNCTION_NAME"), is("getfunc_f1"));
assertThat(rs.getShort("FUNCTION_TYPE"), is((short) DatabaseMetaData.functionResultUnknown));
@@ -451,7 +694,7 @@ class DatabaseMetaDataTest {
stmt.execute(
"CREATE OR REPLACE FUNCTION getfunc_f3(IN a int, INOUT b varchar, OUT c timestamptz) AS $f$ BEGIN b := 'a'; c := now(); return; END; $f$ LANGUAGE plpgsql");
- rs = dbmd.getFunctions("", "", "getfunc_f3");
+ rs = dbmd.getFunctions(null, null, "getfunc_f3");
assertThat(rs.next(), is(true));
assertThat(rs.getString("FUNCTION_NAME"), is("getfunc_f3"));
assertThat(rs.getShort("FUNCTION_TYPE"), is((short) DatabaseMetaData.functionResultUnknown));
diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc42/DatabaseMetaDataTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc42/DatabaseMetaDataTest.java
index 9878b910..3a98eb14 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/jdbc42/DatabaseMetaDataTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc42/DatabaseMetaDataTest.java
@@ -54,10 +54,18 @@ class DatabaseMetaDataTest {
}
@Test
- void getColumnsForNullScale() throws Exception {
+ void getColumnsForNullScale_whenCatalogArgPercentSign_expectNoResults() throws Exception {
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rs = dbmd.getColumns("%", "%", "decimaltest", "%");
+ assertFalse(rs.next());
+ }
+
+ @Test
+ void getColumnsForNullScale() throws Exception {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getColumns(null, "%", "decimaltest", "%");
assertTrue(rs.next());
assertEquals("a", rs.getString("COLUMN_NAME"));
assertEquals(0, rs.getInt("DECIMAL_DIGITS"));
@@ -72,10 +80,18 @@ class DatabaseMetaDataTest {
}
@Test
- void getCorrectSQLTypeForOffPathTypes() throws Exception {
+ void getCorrectSQLTypeForOffPathTypes_whenCatalogArgPercentSign_expectNoResults() throws Exception {
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rs = dbmd.getColumns("%", "%", "off_path_table", "%");
+ assertFalse(rs.next());
+ }
+
+ @Test
+ void getCorrectSQLTypeForOffPathTypes() throws Exception {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getColumns(null, "%", "off_path_table", "%");
assertTrue(rs.next());
assertEquals("var", rs.getString("COLUMN_NAME"));
assertEquals("\"test_schema\".\"_test_enum\"", rs.getString("TYPE_NAME"), "Detects correct off-path type name");
@@ -85,11 +101,20 @@ class DatabaseMetaDataTest {
}
@Test
- void getCorrectSQLTypeForShadowedTypes() throws Exception {
+ void getCorrectSQLTypeForShadowedTypes_whenCatalogArgPercentSign_expectNoResults() throws Exception {
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rs = dbmd.getColumns("%", "%", "on_path_table", "%");
+ assertFalse(rs.next());
+ }
+
+ @Test
+ void getCorrectSQLTypeForShadowedTypes() throws Exception {
+ DatabaseMetaData dbmd = conn.getMetaData();
+
+ ResultSet rs = dbmd.getColumns(null, "%", "on_path_table", "%");
+
assertTrue(rs.next());
assertEquals("a", rs.getString("COLUMN_NAME"));
assertEquals("\"test_schema\".\"_test_enum\"", rs.getString("TYPE_NAME"), "Correctly maps types from other schemas");
[parent: 7f4c9f8facb4]