From fc1dc0cd332aa277856827027aeddc27c34d7cb0 Mon Sep 17 00:00:00 2001 From: Dave Cramer Date: Thu, 11 Dec 2003 15:50:20 +0000 Subject: [PATCH] patch to deal with unique foreign keys in 7.4 from Kris Jurka --- .../jdbc1/AbstractJdbc1DatabaseMetaData.java | 54 +++++++++++++++- .../test/jdbc2/DatabaseMetaDataTest.java | 71 +++++++++++++++++++++- 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java index 0ded6e608b..f7f8241571 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java @@ -2966,7 +2966,59 @@ public abstract class AbstractJdbc1DatabaseMetaData * the PK_NAME field. */ - if (connection.haveMinimumServerVersion("7.3")) { + if (connection.haveMinimumServerVersion("7.4")) { + String sql = "SELECT NULL::text AS PKTABLE_CAT, pkn.nspname AS PKTABLE_SCHEMA, pkc.relname AS PKTABLE_NAME, pka.attname AS PKCOLUMN_NAME, "+ + "NULL::text AS FK_TABLE_CAT, fkn.nspname AS FKTABLE_SCHEMA, fkc.relname AS FKTABLE_NAME, fka.attname AS FKCOLUMN_NAME, "+ + "pos.n AS KEY_SEQ, "+ + "CASE con.confupdtype "+ + " WHEN 'c' THEN " + DatabaseMetaData.importedKeyCascade + + " WHEN 'n' THEN " + DatabaseMetaData.importedKeySetNull + + " WHEN 'd' THEN " + DatabaseMetaData.importedKeySetDefault + + " WHEN 'r' THEN " + DatabaseMetaData.importedKeyRestrict + + " WHEN 'a' THEN " + DatabaseMetaData.importedKeyNoAction + + " ELSE NULL END AS UPDATE_RULE, "+ + "CASE con.confdeltype "+ + " WHEN 'c' THEN " + DatabaseMetaData.importedKeyCascade + + " WHEN 'n' THEN " + DatabaseMetaData.importedKeySetNull + + " WHEN 'd' THEN " + DatabaseMetaData.importedKeySetDefault + + " WHEN 'r' THEN " + DatabaseMetaData.importedKeyRestrict + + " WHEN 'a' THEN " + DatabaseMetaData.importedKeyNoAction + + " ELSE NULL END AS DELETE_RULE, "+ + "con.conname AS FK_NAME, pkic.relname AS PK_NAME, "+ + "CASE "+ + " WHEN con.condeferrable AND con.condeferred THEN " + DatabaseMetaData.importedKeyInitiallyDeferred + + " WHEN con.condeferrable THEN " + DatabaseMetaData.importedKeyInitiallyImmediate + + " ELSE " + DatabaseMetaData.importedKeyNotDeferrable+ + " END AS DEFERRABILITY "+ + " FROM "+ + " pg_catalog.pg_namespace pkn, pg_catalog.pg_class pkc, pg_catalog.pg_attribute pka, "+ + " pg_catalog.pg_namespace fkn, pg_catalog.pg_class fkc, pg_catalog.pg_attribute fka, "+ + " pg_catalog.pg_constraint con, information_schema._pg_keypositions() pos(n), "+ + " pg_catalog.pg_depend dep, pg_catalog.pg_class pkic "+ + " WHERE pkn.oid = pkc.relnamespace AND pkc.oid = pka.attrelid AND pka.attnum = con.confkey[pos.n] AND con.confrelid = pkc.oid "+ + " AND fkn.oid = fkc.relnamespace AND fkc.oid = fka.attrelid AND fka.attnum = con.conkey[pos.n] AND con.conrelid = fkc.oid "+ + " AND con.contype = 'f' AND con.oid = dep.objid AND pkic.oid = dep.refobjid AND pkic.relkind = 'i' AND dep.classid = 'pg_constraint'::regclass::oid AND dep.refclassid = 'pg_class'::regclass::oid "; + if (primarySchema != null && !"".equals(primarySchema)) { + sql += " AND pkn.nspname = '"+escapeQuotes(primarySchema)+"' "; + } + if (foreignSchema != null && !"".equals(foreignSchema)) { + sql += " AND fkn.nspname = '"+escapeQuotes(foreignSchema)+"' "; + } + if (primaryTable != null && !"".equals(primaryTable)) { + sql += " AND pkc.relname = '"+escapeQuotes(primaryTable)+"' "; + } + if (foreignTable != null && !"".equals(foreignTable)) { + sql += " AND fkc.relname = '"+escapeQuotes(foreignTable)+"' "; + } + + if (primaryTable != null) { + sql += " ORDER BY fkn.nspname,fkc.relname,pos.n"; + } else { + sql += " ORDER BY pkn.nspname,pkc.relname,pos.n"; + } + + return connection.createStatement().executeQuery(sql); + } else if (connection.haveMinimumServerVersion("7.3")) { select = "SELECT DISTINCT n1.nspname as pnspname,n2.nspname as fnspname, "; from = " FROM pg_catalog.pg_namespace n1 "+ " JOIN pg_catalog.pg_class c1 ON (c1.relnamespace = n1.oid) "+ diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java index cfdab7fe9f..dc5e44e252 100644 --- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java +++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java @@ -9,7 +9,7 @@ import java.sql.*; * * PS: Do you know how difficult it is to type on a train? ;-) * - * $PostgreSQL: pgsql/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java,v 1.20 2003/11/29 22:41:23 pgsql Exp $ + * $PostgreSQL: pgsql/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java,v 1.21 2003/12/11 15:50:20 davec Exp $ */ public class DatabaseMetaDataTest extends TestCase @@ -169,6 +169,75 @@ public class DatabaseMetaDataTest extends TestCase } } + public void testForeignKeysToUniqueIndexes() + { + try + { + if (!TestUtil.haveMinimumServerVersion(con,"7.4")) + return; + + 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++) + { + assertTrue("pkt".equals(rs.getString("PKTABLE_NAME"))); + assertTrue("fkt".equals(rs.getString("FKTABLE_NAME"))); + assertTrue("pkt_un_b".equals(rs.getString("PK_NAME"))); + assertTrue("b".equals(rs.getString("PKCOLUMN_NAME"))); + } + assertTrue(j == 1); + + TestUtil.dropTable(con1, "fkt"); + TestUtil.dropTable(con1, "pkt"); + con1.close(); + } + catch (SQLException ex) + { + fail(ex.getMessage()); + } + } + + public void testMultiColumnForeignKeys() + { + 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++) + { + assertTrue("pkt".equals(rs.getString("PKTABLE_NAME"))); + assertTrue("fkt".equals(rs.getString("FKTABLE_NAME"))); + assertTrue(j+1 == rs.getInt("KEY_SEQ")); + if (j == 0) { + assertTrue("b".equals(rs.getString("PKCOLUMN_NAME"))); + assertTrue("c".equals(rs.getString("FKCOLUMN_NAME"))); + } else { + assertTrue("a".equals(rs.getString("PKCOLUMN_NAME"))); + assertTrue("d".equals(rs.getString("FKCOLUMN_NAME"))); + } + } + assertTrue(j == 2); + + TestUtil.dropTable(con1, "fkt"); + TestUtil.dropTable(con1, "pkt"); + con1.close(); + } + catch (SQLException ex) + { + fail(ex.getMessage()); + } + } + public void testForeignKeys() { try -- 2.11.0