From: Robert Buels Date: Wed, 21 Oct 2009 01:10:38 +0000 (+0000) Subject: gutted Pg storage driver's sequence discovery to just rely on DBD::Pg's last_insert_i... X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=dc7bcc465e3c824e46290fc802739b1e29892512;p=dbsrgits%2FDBIx-Class-Historic.git gutted Pg storage driver's sequence discovery to just rely on DBD::Pg's last_insert_id. this needs testing with older versions of DBD::Pg --- diff --git a/lib/DBIx/Class/Storage/DBI/Pg.pm b/lib/DBIx/Class/Storage/DBI/Pg.pm index 3d25b83..a3788e6 100644 --- a/lib/DBIx/Class/Storage/DBI/Pg.pm +++ b/lib/DBIx/Class/Storage/DBI/Pg.pm @@ -22,117 +22,37 @@ sub with_deferred_fk_checks { sub last_insert_id { my ($self,$source,@cols) = @_; - my @values; - - for my $col (@cols) { - my $seq = ( $source->column_info($col)->{sequence} ||= $self->dbh_do('_dbh_get_autoinc_seq', $source, $col) ) - or $self->throw_exception( "could not determine sequence for " - . $source->name - . ".$col, please consider adding a " - . "schema-qualified sequence to its column info" - ); - - push @values, $self->_dbh_last_insert_id ($self->_dbh, $seq); - } - - return @values; + return map $self->dbh_do('_dbh_last_insert_id', $source, $_ ), @cols; } -# there seems to be absolutely no reason to have this as a separate method, -# but leaving intact in case someone is already overriding it sub _dbh_last_insert_id { - my ($self, $dbh, $seq) = @_; - $dbh->last_insert_id(undef, undef, undef, undef, {sequence => $seq}); -} + my ($self, $dbh, $source, $col ) = @_; + # if a sequence is defined, explicitly specify it to DBD::Pg's last_insert_id() + if( my $seq = $source->column_info($col)->{sequence} ) { + return $dbh->last_insert_id(undef, undef, undef, undef, {sequence => $seq}); -sub _dbh_get_autoinc_seq { - my ($self, $dbh, $source, $col) = @_; + } + # if not, parse out the schema and table names, pass them to + # DBD::Pg, and let it figure out (and cache) the sequence name + # itself. + else { - my $schema; - my $table = $source->name; + my $schema; + my $table = $source->name; - # deref table name if it needs it - $table = $$table - if ref $table eq 'SCALAR'; + # deref table name if necessary + $table = $$table if ref $table eq 'SCALAR'; - # parse out schema name if present - if( $table =~ /^(.+)\.(.+)$/ ) { - ( $schema, $table ) = ( $1, $2 ); - } + # parse out schema name if present + if ( $table =~ /^(.+)\.(.+)$/ ) { + ( $schema, $table ) = ( $1, $2 ); + } - # use DBD::Pg to fetch the column info if it is recent enough to - # work. otherwise, use custom SQL - my $seq_expr = $DBD::Pg::VERSION >= 2.015001 - ? eval{ $dbh->column_info(undef,$schema,$table,$col)->fetchrow_hashref->{COLUMN_DEF} } - : $self->_dbh_get_column_default( $dbh, $schema, $table, $col ); - - # if no default value is set on the column, or if we can't parse the - # default value as a sequence, throw. - unless ( defined $seq_expr and $seq_expr =~ /^nextval\(+'([^']+)'::(?:text|regclass)\)/i ){ - $seq_expr = '' unless defined $seq_expr; - $schema = "$schema." if defined $schema && length $schema; - $self->throw_exception( "no sequence found for $schema$table.$col, check table definition, " - . "or explicitly set the 'sequence' for this column in the " - . $source->source_name - . " class" - ); + return $dbh->last_insert_id( undef, $schema, $table, undef ); } - - return $1; } -# custom method for fetching column default, since column_info has a -# bug with older versions of DBD::Pg -sub _dbh_get_column_default { - my ( $self, $dbh, $schema, $table, $col ) = @_; - - # Build and execute a query into the pg_catalog to find the Pg - # expression for the default value for this column in this table. - # If the table name is schema-qualified, query using that specific - # schema name. - - # Otherwise, find the table in the standard Postgres way, using the - # search path. This is done with the pg_catalog.pg_table_is_visible - # function, which returns true if a given table is 'visible', - # meaning the first table of that name to be found in the search - # path. - - # I *think* we can be assured that this query will always find the - # correct column according to standard Postgres semantics. - # - # -- rbuels - - my $sqlmaker = $self->sql_maker; - local $sqlmaker->{bindtype} = 'normal'; - - my ($where, @bind) = $sqlmaker->where ({ - 'a.attnum' => {'>', 0}, - 'c.relname' => $table, - 'a.attname' => $col, - -not_bool => 'a.attisdropped', - (defined $schema && length $schema) - ? ( 'n.nspname' => $schema ) - : ( -bool => \'pg_catalog.pg_table_is_visible(c.oid)' ) - }); - - my ($seq_expr) = $dbh->selectrow_array(<