squash
Matt Phillips [Fri, 10 May 2013 21:40:03 +0000 (17:40 -0400)]
lib/DBIx/Class/SQLMaker.pm
lib/DBIx/Class/Storage/DBI.pm

index 0db6ef2..556c54f 100644 (file)
@@ -224,6 +224,36 @@ sub insert {
   next::method(@_);
 }
 
+sub _insert_ARRAYREFREF {
+  my ($self, $data) = @_;
+
+  my ($cols, $subquery) = @$data;
+  if (not $subuery) {
+    # if somehow someone is calling this with the original SQLA api,
+    # pass it along
+    return next::method($self, $cols);
+  }
+
+  my $subsql, @subbind = @$subquery;
+
+  my @fields = sort @$cols;
+
+  my ($sql, @bind) = $self->_insert_values($data);
+
+  $_ = $self->_quote($_) foreach @$fields;
+  $sql = "( ".join(", ", sort @$fields).") ".$sql;
+
+  return ($sql, @bind);
+
+  # when passing ARRAYREFREF with [cols], SQLA drops INTO $table (cols)
+  # we inject the returned sql here
+  #$_ = $self->_quote($_) foreach @fields;
+  #  $sql = "( ".join(", ", @fields).") ".$sql;
+    my $sql = sprintf(
+      'INSERT INTO %s( %s ) VALUES', $_[0]->_quote($_[1])
+    );
+}
+
 sub _recurse_fields {
   my ($self, $fields) = @_;
   my $ref = ref $fields;
index a5085cd..bc08b97 100644 (file)
@@ -1976,12 +1976,6 @@ sub insert_bulk {
     elsif (ref $data eq 'ARRAY') {
       shift @$data;
     }
-    elsif (ref $data eq 'REF' && ref $$data eq 'ARRAY') {
-      $data;
-    }
-    else {
-      $self->throw_exception('invalid data (not CODE, ARRAY or ARRAYREF) passed to insert_bulk');
-    }
   };
 
   my @col_range = (0..$#$cols);
@@ -2016,56 +2010,56 @@ sub insert_bulk {
   # can be later matched up by address), because we want to supply a real
   # value on which perhaps e.g. datatype checks will be performed
   my ($proto_data, $value_type_by_col_idx);
-  for my $i (@col_range) {
-    my $colname = $cols->[$i];
-    if (ref $reference_row eq 'REF' && ref $$reference_row eq 'ARRAY') {
-      $proto_data = $reference_row;
-      last;
-    }
-    elsif (ref $reference_row eq 'ARRAY' && ref $reference_row->[$i] eq 'SCALAR') {
-      # no bind value at all - no type
-      $proto_data->{$colname} = $reference_row->[$i];
-    }
-    elsif (ref $reference_row->[$i] eq 'REF' and ref ${$reference_row->[$i]} eq 'ARRAY' ) {
-      # repack, so we don't end up mangling the original \[]
-      my ($sql, @bind) = @${$reference_row->[$i]};
+    for my $i (@col_range) {
+      last if not $reference_row;
 
-      # normalization of user supplied stuff
-      my $resolved_bind = $self->_resolve_bindattrs(
-        $source, \@bind, $colinfos,
-      );
+      my $colname = $cols->[$i];
+      if (ref $reference_row eq 'REF' && ref $$reference_row eq 'ARRAY') {
+        $proto_data = $reference_row;
+        last;
+      }
+      elsif (ref $reference_row eq 'ARRAY' && ref $reference_row->[$i] eq 'SCALAR') {
+        # no bind value at all - no type
+        $proto_data->{$colname} = $reference_row->[$i];
+      }
+      elsif (ref $reference_row->[$i] eq 'REF' and ref ${$reference_row->[$i]} eq 'ARRAY' ) {
+        # repack, so we don't end up mangling the original \[]
+        my ($sql, @bind) = @${$reference_row->[$i]};
+
+        # normalization of user supplied stuff
+        my $resolved_bind = $self->_resolve_bindattrs(
+          $source, \@bind, $colinfos,
+        );
 
-      # store value-less (attrs only) bind info - we will be comparing all
-      # supplied binds against this for sanity
-      $value_type_by_col_idx->{$i} = [ map { $_->[0] } @$resolved_bind ];
+        # store value-less (attrs only) bind info - we will be comparing all
+        # supplied binds against this for sanity
+        $value_type_by_col_idx->{$i} = [ map { $_->[0] } @$resolved_bind ];
+
+        $proto_data->{$colname} = \[ $sql, map { [
+          # inject slice order to use for $proto_bind construction
+            { %{$resolved_bind->[$_][0]}, _bind_data_slice_idx => $i, _literal_bind_subindex => $_+1 }
+              =>
+            $resolved_bind->[$_][1]
+          ] } (0 .. $#bind)
+        ];
+      }
+      else {
+        $value_type_by_col_idx->{$i} = undef;
 
-      $proto_data->{$colname} = \[ $sql, map { [
-        # inject slice order to use for $proto_bind construction
-          { %{$resolved_bind->[$_][0]}, _bind_data_slice_idx => $i, _literal_bind_subindex => $_+1 }
+        $proto_data->{$colname} = \[ '?', [
+          { dbic_colname => $colname, _bind_data_slice_idx => $i }
             =>
-          $resolved_bind->[$_][1]
-        ] } (0 .. $#bind)
-      ];
-    }
-    else {
-      $value_type_by_col_idx->{$i} = undef;
-
-      $proto_data->{$colname} = \[ '?', [
-        { dbic_colname => $colname, _bind_data_slice_idx => $i }
-          =>
-        $reference_row->[$i]
-      ] ];
+          $reference_row->[$i]
+        ] ];
+      }
     }
-  }
 
   my ($sql, $proto_bind) = $self->_prep_for_execute (
     'insert',
     $source,
-    [ $proto_data ],
+    [ $proto_data || ($cols => $data) ],
   );
 
-    use DDP; p $proto_data;
-
   if (! @$proto_bind and keys %$value_type_by_col_idx) {
     # if the bindlist is empty and we had some dynamic binds, this means the
     # storage ate them away (e.g. the NoBindVars component) and interpolated