[DBD::Pg 2/2] Fix foreign_key_info with unspecified schema

dbdpg-commits-gENoVmVU/[email protected] Sat, 21 Sep 2013 22:48:56 -0400
Newsgroups gmane.comp.db.postgresql.dbdpg.cvs
Message-ID <[email protected]>
Committed by =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= <[email protected]>

Subject: [DBD::Pg 2/2] Fix foreign_key_info with unspecified schema

---
 Pg.pm          |    3 ++
 t/03dbmethod.t |   64 +++++++++++++++++++++++++++++++++----------------------
 2 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/Pg.pm b/Pg.pm
index 260eaf6..c620d21 100644
--- a/Pg.pm
+++ b/Pg.pm
@@ -877,6 +877,9 @@ use 5.006001;
 				if (length $_->[1]) {
 					$SQL .= ' AND n.nspname = ' . $dbh->quote($_->[1]);
 				}
+				else {
+					$SQL .= ' AND pg_catalog.pg_table_is_visible(c.oid)'
+				}
 				my $info = $dbh->selectall_arrayref($SQL);
 				return undef if ! @$info;
 				$oid{$_->[2]} = $info->[0][0];
diff --git a/t/03dbmethod.t b/t/03dbmethod.t
index 976182d..c831175 100644
--- a/t/03dbmethod.t
+++ b/t/03dbmethod.t
@@ -31,7 +31,7 @@ plan tests => 535;
 isnt ($dbh, undef, 'Connect to database for database handle method testing');
 
 my ($pglibversion,$pgversion) = ($dbh->{pg_lib_version},$dbh->{pg_server_version});
-my ($schema,$schema2) = ('dbd_pg_testschema', 'dbd_pg_testschema2');
+my ($schema,$schema2,$schema3) = ('dbd_pg_testschema', 'dbd_pg_testschema2', 'dbd_pg_testschema3');
 my ($table1,$table2,$table3) = ('dbd_pg_test1','dbd_pg_test2','dbd_pg_test3');
 my ($sequence2,$sequence3,$sequence4) = ('dbd_pg_testsequence2','dbd_pg_testsequence3','dbd_pg_testsequence4');
 
@@ -800,7 +800,7 @@ is ($sth, undef, $t);
 
 # Drop any tables that may exist
 my $fktables = join ',' => map { "'dbd_pg_test$_'" } (1..3);
-$SQL = "SELECT relname FROM pg_catalog.pg_class WHERE relkind='r' AND relname IN ($fktables)";
+$SQL = "SELECT n.nspname||'.'||r.relname FROM pg_catalog.pg_class r, pg_catalog.pg_namespace n WHERE relkind='r' AND r.relnamespace = n.oid AND r.relname IN ($fktables)";
 {
 	local $SIG{__WARN__} = sub {};
 	for (@{$dbh->selectall_arrayref($SQL)}) {
@@ -823,12 +823,21 @@ $sth = $dbh->foreign_key_info(undef,undef,'dbd_pg_test9',undef,undef,'dbd_pg_tes
 is ($sth, undef, $t);
 
 ## Create a pk table
-{
+
+# The order of the tables returned by the OID query in foreign_key_info
+# seems to be influenced by schema creation order, so create the schemas
+# in the opposite order of the search_path, so we have at least a vague
+# chance of testing that we respect the search_path order. Also create
+# the tables in the opposite order, for good measure
+$dbh->do("CREATE SCHEMA $schema3");
+$dbh->do("CREATE SCHEMA $schema2");
+$dbh->do("SET search_path = $schema2,$schema3");
+for my $s ($schema3, $schema2) {
 	local $SIG{__WARN__} = sub {};
-	$dbh->do('CREATE TABLE dbd_pg_test1 (a INT, b INT NOT NULL, c INT NOT NULL, '.
+	$dbh->do("CREATE TABLE $s.dbd_pg_test1 (a INT, b INT NOT NULL, c INT NOT NULL, ".
 			 'CONSTRAINT dbd_pg_test1_pk PRIMARY KEY (a))');
-	$dbh->do('ALTER TABLE dbd_pg_test1 ADD CONSTRAINT dbd_pg_test1_uc1 UNIQUE (b)');
-	$dbh->do('CREATE UNIQUE INDEX dbd_pg_test1_index_c ON dbd_pg_test1(c)');
+	$dbh->do("ALTER TABLE $s.dbd_pg_test1 ADD CONSTRAINT dbd_pg_test1_uc1 UNIQUE (b)");
+	$dbh->do("CREATE UNIQUE INDEX dbd_pg_test1_index_c ON $s.dbd_pg_test1(c)");
 	$dbh->commit();
 }
 
@@ -838,10 +847,10 @@ $sth = $dbh->foreign_key_info(undef,undef,$table1,undef,undef,undef);
 is ($sth, undef, $t);
 
 ## Create a simple foreign key table
-{
+for my $s ($schema3, $schema2) {
 	local $SIG{__WARN__} = sub {};
-	$dbh->do('CREATE TABLE dbd_pg_test2 (f1 INT PRIMARY KEY, f2 INT NOT NULL, f3 INT NOT NULL)');
-	$dbh->do('ALTER TABLE dbd_pg_test2 ADD CONSTRAINT dbd_pg_test2_fk1 FOREIGN KEY(f2) REFERENCES dbd_pg_test1(a)');
+	$dbh->do("CREATE TABLE $s.dbd_pg_test2 (f1 INT PRIMARY KEY, f2 INT NOT NULL, f3 INT NOT NULL)");
+	$dbh->do("ALTER TABLE $s.dbd_pg_test2 ADD CONSTRAINT dbd_pg_test2_fk1 FOREIGN KEY(f2) REFERENCES $s.dbd_pg_test1(a)");
 	$dbh->commit();
 }
 
@@ -886,11 +895,11 @@ $sth = $dbh->foreign_key_info(undef,undef,$table1,undef,undef,undef);
 $result = $sth->fetchall_arrayref();
 my $fk1 = [
 					 undef, ## Catalog
-					 $schema, ## Schema
+					 $schema2, ## Schema
 					 $table1, ## Table
 					 'a', ## Column
 					 undef, ## FK Catalog
-					 $schema, ## FK Schema
+					 $schema2, ## FK Schema
 					 $table2, ## FK Table
 					 'f2', ## FK Table
 					 1, ## Ordinal position
@@ -929,11 +938,11 @@ $sth = $dbh->foreign_key_info(undef,undef,$table1,undef,undef,undef);
 $result = $sth->fetchall_arrayref();
 my $fk2 = [
 					 undef,
-					 $schema,
+					 $schema2,
 					 $table1,
 					 'b',
 					 undef,
-					 $schema,
+					 $schema2,
 					 $table2,
 					 'f3',
 					 '1',
@@ -960,11 +969,11 @@ $sth = $dbh->foreign_key_info(undef,undef,$table1,undef,undef,undef);
 $result = $sth->fetchall_arrayref();
 my $fk3 = [
 					 undef,
-					 $schema,
+					 $schema2,
 					 $table1,
 					 'c',
 					 undef,
-					 $schema,
+					 $schema2,
 					 $table2,
 					 'f3',
 					 '1',
@@ -982,10 +991,10 @@ is_deeply ($result, $expected, $t);
 
 ## Create another foreign key table to point to the first (primary) table
 $t='DB handle method "foreign_key_info" works for multiple fks';
-{
+for my $s ($schema3, $schema2) {
 	local $SIG{__WARN__} = sub {};
-	$dbh->do('CREATE TABLE dbd_pg_test3 (ff1 INT NOT NULL)');
-	$dbh->do('ALTER TABLE dbd_pg_test3 ADD CONSTRAINT dbd_pg_test3_fk1 FOREIGN KEY(ff1) REFERENCES dbd_pg_test1(a)');
+	$dbh->do("CREATE TABLE $s.dbd_pg_test3 (ff1 INT NOT NULL)");
+	$dbh->do("ALTER TABLE $s.dbd_pg_test3 ADD CONSTRAINT dbd_pg_test3_fk1 FOREIGN KEY(ff1) REFERENCES $s.dbd_pg_test1(a)");
 	$dbh->commit();
 }
 
@@ -993,11 +1002,11 @@ $sth = $dbh->foreign_key_info(undef,undef,$table1,undef,undef,undef);
 $result = $sth->fetchall_arrayref();
 my $fk4 = [
 					 undef,
-					 $schema,
+					 $schema2,
 					 $table1,
 					 'a',
 					 undef,
-					 $schema,
+					 $schema2,
 					 $table3,
 					 'ff1',
 					 '1',
@@ -1034,11 +1043,11 @@ $result = $sth->fetchall_arrayref();
 ## "dbd_pg_test2_fk4" FOREIGN KEY (f1, f3, f2) REFERENCES dbd_pg_test1(c, a, b)
 my $fk5 = [
 					 undef,
-					 $schema,
+					 $schema2,
 					 $table1,
 					 'c',
 					 undef,
-					 $schema,
+					 $schema2,
 					 $table2,
 					 'f1',
 					 '1',
@@ -1083,12 +1092,15 @@ $result = $sth->fetchrow_hashref();
 ok (exists $result->{'FK_TABLE_NAME'}, $t);
 
 # Clean everything up
-{
-	$dbh->do('DROP TABLE dbd_pg_test3');
-	$dbh->do('DROP TABLE dbd_pg_test2');
-	$dbh->do('DROP TABLE dbd_pg_test1');
+for my $s ($schema3, $schema2) {
+	$dbh->do("DROP TABLE $s.dbd_pg_test3");
+	$dbh->do("DROP TABLE $s.dbd_pg_test2");
+	$dbh->do("DROP TABLE $s.dbd_pg_test1");
 }
+$dbh->do("DROP SCHEMA $schema2");
+$dbh->do("DROP SCHEMA $schema3");
 
+$dbh->do("SET search_path = $schema");
 #
 # Test of the "tables" database handle method
 #
-- 
1.7.1