my $updated_cols = $source->storage->insert(
$source,
{ $self->get_columns },
- keys %auto_pri
+ (keys %auto_pri) && $source->storage->can_insert_returning
? { returning => [ sort { $auto_pri{$a} cmp $auto_pri{$b} } keys %auto_pri ] }
: ()
,
# default cursor class, overridable in connect_info attributes
__PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor');
-__PACKAGE__->mk_group_accessors('inherited' => qw/sql_maker_class/);
+__PACKAGE__->mk_group_accessors('inherited' => qw/
+ sql_maker_class
+ can_insert_returning
+/);
__PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks');
sub insert {
my $self = shift;
- my ($source, $to_insert) = @_;
+ my ($source, $to_insert, $opts) = @_;
my $updated_cols = $self->_prefetch_insert_auto_nextvals (@_);
my $bind_attributes = $self->source_bind_attributes($source);
- $self->_execute('insert' => [], $source, $bind_attributes, $to_insert);
+ my ($rv, $sth) = $self->_execute('insert' => [], $source, $bind_attributes, $to_insert, $opts);
+
+ if ($opts->{returning}) {
+ my @ret_cols = @{$opts->{returning}};
+
+ my @ret_vals = eval {
+ local $SIG{__WARN__} = sub {};
+ my @r = $sth->fetchrow_array;
+ $sth->finish;
+ @r;
+ };
+
+ my %ret;
+ @ret{@ret_cols} = @ret_vals if (@ret_vals);
+
+ $updated_cols = {
+ %$updated_cols,
+ %ret,
+ };
+ }
return $updated_cols;
}
+++ /dev/null
-package DBIx::Class::Storage::DBI::InsertReturning;
-
-use strict;
-use warnings;
-
-use base qw/DBIx::Class::Storage::DBI/;
-use mro 'c3';
-
-=head1 NAME
-
-DBIx::Class::Storage::DBI::InsertReturning - Storage component for RDBMSes
-supporting INSERT ... RETURNING
-
-=head1 DESCRIPTION
-
-Provides Auto-PK and
-L<is_auto_increment|DBIx::Class::ResultSource/is_auto_increment> support for
-databases supporting the C<INSERT ... RETURNING> syntax.
-
-=cut
-
-sub insert {
- my $self = shift;
- my ($source, $to_insert, $opts) = @_;
-
- return $self->next::method (@_) unless ($opts && $opts->{returning});
-
- my $updated_cols = $self->_prefetch_insert_auto_nextvals ($source, $to_insert);
-
- my $bind_attributes = $self->source_bind_attributes($source);
- my ($rv, $sth) = $self->_execute (insert => [], $source, $bind_attributes, $to_insert, $opts);
-
- if (my @ret_cols = @{$opts->{returning}}) {
-
- my @ret_vals = eval {
- local $SIG{__WARN__} = sub {};
- my @r = $sth->fetchrow_array;
- $sth->finish;
- @r;
- };
-
- my %ret;
- @ret{@ret_cols} = @ret_vals if (@ret_vals);
-
- $updated_cols = {
- %$updated_cols,
- %ret,
- };
- }
-
- return $updated_cols;
-}
-
-=head1 AUTHOR
-
-See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
-
-1;
use base qw/
DBIx::Class::Storage::DBI::MultiColumnIn
- DBIx::Class::Storage::DBI::InsertReturning
/;
use mro 'c3';
warn __PACKAGE__.": DBD::Pg 2.9.2 or greater is strongly recommended\n"
if ($DBD::Pg::VERSION < 2.009002); # pg uses (used?) version::qv()
+sub can_insert_returning {
+ # FIXME !!!
+ # pg before 8.2 doesn't support this, need to check version
+ return 1;
+}
+
sub with_deferred_fk_checks {
my ($self, $sub) = @_;
my $txn_scope_guard = $self->txn_scope_guard;
$self->_do_query('SET CONSTRAINTS ALL DEFERRED');
-
+
my $sg = Scope::Guard->new(sub {
$self->_do_query('SET CONSTRAINTS ALL IMMEDIATE');
});
after => sub { $txn_scope_guard->commit });
}
+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( sprintf(
+ 'could not determine sequence for column %s.%s, please consider adding a schema-qualified sequence to its column info',
+ $source->name,
+ $col,
+ ));
+
+ push @values, $self->_dbh->last_insert_id(undef, undef, undef, undef, {sequence => $seq});
+ }
+
+ return @values;
+}
+
sub _sequence_fetch {
my ($self, $function, $sequence) = @_;
$self->throw_exception('No sequence to fetch') unless $sequence;
-
+
my ($val) = $self->_get_dbh->selectrow_array(
sprintf "select $function('%s')",
$sequence
);
return $val;
-}
+}
sub _dbh_get_autoinc_seq {
my ($self, $dbh, $source, $col) = @_;
is($st->pkid1, 55, "Auto-PK for sequence without default: First primary key set manually");
-######## test non-integer non-serial auto-pk
+######## test non-serial auto-pk
-$schema->source('TimestampPrimaryKey')->name('dbic_t_schema.timestamp_primary_key_test');
-my $row = $schema->resultset('TimestampPrimaryKey')->create({});
-ok $row->id;
+if ($schema->storage->can_insert_returning) {
+ $schema->source('TimestampPrimaryKey')->name('dbic_t_schema.timestamp_primary_key_test');
+ my $row = $schema->resultset('TimestampPrimaryKey')->create({});
+ ok $row->id;
+}
######## test with_deferred_fk_checks