$self->dbh_do('_dbh_last_insert_id', $seq);
}
+sub _get_pg_search_path {
+ my ($self,$dbh) = @_;
+ # cache the search path as ['schema','schema',...] in the storage
+ # obj
+ $self->{_pg_search_path} ||= do {
+ my @search_path;
+ my ($sp_string) = $dbh->selectrow_array('SHOW search_path');
+ while( $sp_string =~ s/("[^"]+"|[^,]+),?// ) {
+ unless( defined $1 and length $1 ) {
+ $self->throw_exception("search path sanity check failed: '$1'")
+ }
+ push @search_path, $1;
+ }
+ \@search_path
+ };
+}
+
sub _dbh_get_autoinc_seq {
my ($self, $dbh, $schema, $table, @pri) = @_;
- while (my $col = shift @pri) {
- my $info = $dbh->column_info(undef,$schema,$table,$col)->fetchrow_hashref;
- if(defined $info->{COLUMN_DEF} and
- $info->{COLUMN_DEF} =~ /^nextval\(+'([^']+)'::(?:text|regclass)\)/) {
- my $seq = $1;
- # may need to strip quotes -- see if this works
- return $seq =~ /\./ ? $seq : $info->{TABLE_SCHEM} . "." . $seq;
- }
+ # get the list of postgres schemas to search. if we have a schema
+ # specified, use that. otherwise, use the search path
+ my @search_path;
+ if( defined $schema and length $schema ) {
+ @search_path = ( $schema );
+ } else {
+ @search_path = @{ $self->_get_pg_search_path($dbh) };
+ }
+
+ foreach my $search_schema (@search_path) {
+ foreach my $col (@pri) {
+ my $info = $dbh->column_info(undef,$search_schema,$table,$col)->fetchrow_hashref;
+ if($info) {
+ # if we get here, we have definitely found the right
+ # column.
+ if( defined $info->{COLUMN_DEF} and
+ $info->{COLUMN_DEF}
+ =~ /^nextval\(+'([^']+)'::(?:text|regclass)\)/i
+ ) {
+ my $seq = $1;
+ return $seq =~ /\./ ? $seq : $info->{TABLE_SCHEM} . "." . $seq;
+ } else {
+ # we have found the column, but cannot figure out
+ # the nextval seq
+ return;
+ }
+ }
+ }
}
return;
}
plan skip_all => 'Set $ENV{DBICTEST_PG_DSN}, _USER and _PASS to run this test '.
'(note: This test drops and creates tables called \'artist\', \'casecheck\', \'array_test\' and \'sequence_test\''.
' as well as following sequences: \'pkid1_seq\', \'pkid2_seq\' and \'nonpkid_seq\''.
- ' as well as following schemas: \'testschema\'!)'
+ ' as well as following schemas: \'testschema\',\'anothertestschema\'!)'
unless ($dsn && $user);
-plan tests => 39;
+plan tests => 42;
DBICTest::Schema->load_classes( 'Casecheck', 'ArrayTest' );
-my $schema = DBICTest::Schema->connect($dsn, $user, $pass);
+my $schema = DBICTest::Schema->connect($dsn, $user, $pass,);
# Check that datetime_parser returns correctly before we explicitly connect.
SKIP: {
local $SIG{__WARN__} = sub {};
_cleanup ($dbh);
+ my $artist_table_def = <<EOS;
+(
+ artistid serial PRIMARY KEY
+ , name VARCHAR(100)
+ , rank INTEGER NOT NULL DEFAULT '13'
+ , charfield CHAR(10)
+ , arrayfield INTEGER[]
+)
+EOS
$dbh->do("CREATE SCHEMA testschema;");
- $dbh->do("CREATE TABLE testschema.artist (artistid serial PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10), arrayfield INTEGER[]);");
+ $dbh->do("CREATE TABLE testschema.artist $artist_table_def;");
$dbh->do("CREATE TABLE testschema.sequence_test (pkid1 integer, pkid2 integer, nonpkid integer, name VARCHAR(100), CONSTRAINT pk PRIMARY KEY(pkid1, pkid2));");
$dbh->do("CREATE SEQUENCE pkid1_seq START 1 MAXVALUE 999999 MINVALUE 0");
$dbh->do("CREATE SEQUENCE pkid2_seq START 10 MAXVALUE 999999 MINVALUE 0");
$dbh->do("CREATE SEQUENCE nonpkid_seq START 20 MAXVALUE 999999 MINVALUE 0");
ok ( $dbh->do('CREATE TABLE testschema.casecheck (id serial PRIMARY KEY, "name" VARCHAR(1), "NAME" VARCHAR(2), "UC_NAME" VARCHAR(3), "storecolumn" VARCHAR(10));'), 'Creation of casecheck table');
ok ( $dbh->do('CREATE TABLE testschema.array_test (id serial PRIMARY KEY, arrayfield INTEGER[]);'), 'Creation of array_test table');
+ $dbh->do("CREATE SCHEMA anothertestschema;");
+ $dbh->do("CREATE TABLE anothertestschema.artist $artist_table_def;");
+ $dbh->do("CREATE SCHEMA yetanothertestschema;");
+ $dbh->do("CREATE TABLE yetanothertestschema.artist $artist_table_def;");
+ $dbh->do('set search_path=testschema,public');
}
# store_column is called once for create() for non sequence columns
# This is in Core now, but it's here just to test that it doesn't break
$schema->class('Artist')->load_components('PK::Auto');
+cmp_ok( $schema->resultset('Artist')->count, '==', 0, 'this should start with an empty artist table');
+
+{ # test that auto-pk also works with the defined search path by
+ # un-schema-qualifying the table name
+ my $artist_name_save = $schema->source("Artist")->name;
+ $schema->source("Artist")->name("artist");
+
+ my $unq_new;
+ lives_ok {
+ $unq_new = $schema->resultset('Artist')->create({ name => 'baz' });
+ } 'insert into unqualified, shadowed table succeeds';
+
+ is($unq_new && $unq_new->artistid, 1, "and got correct artistid");
+
+ $schema->source("Artist")->name($artist_name_save);
+}
+
my $new = $schema->resultset('Artist')->create({ name => 'foo' });
-is($new->artistid, 1, "Auto-PK worked");
+is($new->artistid, 2, "Auto-PK worked");
$new = $schema->resultset('Artist')->create({ name => 'bar' });
-is($new->artistid, 2, "Auto-PK worked");
+is($new->artistid, 3, "Auto-PK worked");
+
my $test_type_info = {
'artistid' => {
'DROP SEQUENCE pkid2_seq',
'DROP SEQUENCE nonpkid_seq',
'DROP SCHEMA testschema',
+ 'DROP TABLE anothertestschema.artist',
+ 'DROP SCHEMA anothertestschema',
+ 'DROP TABLE yetanothertestschema.artist',
+ 'DROP SCHEMA yetanothertestschema',
) {
eval { $dbh->do ($stat) };
}