Even cleaner way of handling returning (no column interrogation in storage)
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / InsertReturning.pm
index 1948a2f..f110cb5 100644 (file)
@@ -6,10 +6,6 @@ use warnings;
 use base qw/DBIx::Class::Storage::DBI/;
 use mro 'c3';
 
-__PACKAGE__->mk_group_accessors(simple => qw/
-  _returning_cols
-/);
-
 =head1 NAME
 
 DBIx::Class::Storage::DBI::InsertReturning - Storage component for RDBMSes
@@ -19,91 +15,42 @@ supporting INSERT ... RETURNING
 
 Provides Auto-PK and
 L<is_auto_increment|DBIx::Class::ResultSource/is_auto_increment> support for
-databases supporting the C<INSERT ... RETURNING> syntax. Currently
-L<PostgreSQL|DBIx::Class::Storage::DBI::Pg> and
-L<Firebird|DBIx::Class::Storage::DBI::InterBase>.
+databases supporting the C<INSERT ... RETURNING> syntax.
 
 =cut
 
-sub _prep_for_execute {
+sub insert {
   my $self = shift;
-  my ($op, $extra_bind, $ident, $args) = @_;
-
-  if ($op eq 'insert') {
-    $self->_returning_cols([]);
-
-    my %pk;
-    @pk{$ident->primary_columns} = ();
-
-    my @auto_inc_cols = grep {
-      my $inserting = $args->[0]{$_};
-
-      ($ident->column_info($_)->{is_auto_increment}
-        || exists $pk{$_})
-      && (
-        (not defined $inserting)
-        ||
-        (ref $inserting eq 'SCALAR' && $$inserting =~ /^null\z/i)
-      )
-    } $ident->columns;
+  my ($source, $to_insert, $opts) = @_;
 
-    if (@auto_inc_cols) {
-      $args->[1]{returning} = \@auto_inc_cols;
+  return $self->next::method (@_) unless ($opts && $opts->{returning});
 
-      $self->_returning_cols->[0] = \@auto_inc_cols;
-    }
-  }
-
-  return $self->next::method(@_);
-}
+  my $updated_cols = $self->_prefetch_insert_auto_nextvals ($source, $to_insert);
 
-sub _execute {
-  my $self = shift;
-  my ($op) = @_;
+  my $bind_attributes = $self->source_bind_attributes($source);
+  my ($rv, $sth) = $self->_execute (insert => [], $source, $bind_attributes, $to_insert, $opts);
 
-  my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
+  if (my @ret_cols = @{$opts->{returning}}) {
 
-  if ($op eq 'insert' && $self->_returning_cols) {
-    local $@;
-    my (@returning_cols) = eval {
+    my @ret_vals = eval {
       local $SIG{__WARN__} = sub {};
-      $sth->fetchrow_array
+      my @r = $sth->fetchrow_array;
+      $sth->finish;
+      @r;
     };
-    $self->_returning_cols->[1] = \@returning_cols;
-    $sth->finish;
-  }
 
-  return wantarray ? ($rv, $sth, @bind) : $rv;
-}
+    my %ret;
+    @ret{@ret_cols} = @ret_vals if (@ret_vals);
 
-sub insert {
-  my $self = shift;
-
-  my $updated_cols = $self->next::method(@_);
-
-  if ($self->_returning_cols->[0]) {
-    my %returning_cols;
-    @returning_cols{ @{ $self->_returning_cols->[0] } } = @{ $self->_returning_cols->[1] };
-
-    $updated_cols = { %$updated_cols, %returning_cols };
+    $updated_cols = {
+      %$updated_cols,
+      %ret,
+    };
   }
 
   return $updated_cols;
 }
 
-sub last_insert_id {
-  my ($self, $source, @cols) = @_;
-  my @result;
-
-  my %returning_cols;
-  @returning_cols{ @{ $self->_returning_cols->[0] } } =
-    @{ $self->_returning_cols->[1] };
-
-  push @result, $returning_cols{$_} for @cols;
-
-  return @result;
-}
-
 =head1 AUTHOR
 
 See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>