Fixed up SQLT test/runtime deps
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI.pm
index 7e86c00..e1d50ef 100644 (file)
@@ -464,9 +464,10 @@ sub connect_info {
   #  the new set of options
   $self->_sql_maker(undef);
   $self->_sql_maker_opts({});
-  $self->_connect_info($info_arg);
+  $self->_connect_info([@$info_arg]); # copy for _connect_info
+
+  my $dbi_info = [@$info_arg]; # copy for _dbi_connect_info
 
-  my $dbi_info = [@$info_arg]; # copy for DBI
   my $last_info = $dbi_info->[-1];
   if(ref $last_info eq 'HASH') {
     for my $storage_opt (qw/on_connect_do disable_sth_caching/) {
@@ -483,28 +484,8 @@ sub connect_info {
     # Get rid of any trailing empty hashref
     pop(@$dbi_info) if !keys %$last_info;
   }
-
   $self->_dbi_connect_info($dbi_info);
 
-  if(ref $dbi_info->[0] ne 'CODE') {
-      # Extend to 3 arguments with undefs, if necessary
-      while(scalar(@$dbi_info) < 3) { push(@$dbi_info, undef) }
-
-      # Complain if 4th argument is defined and is not a HASH
-      if(defined $dbi_info->[3] && ref $dbi_info->[3] ne 'HASH') {
-          warn "4th argument of DBI connect info is defined "
-               . " but is not a hashref!";
-      }
-
-      # Set AutoCommit to 1 if not specified manually
-      else {
-          $dbi_info->[3] ||= {};
-          if(!defined $dbi_info->[3]->{AutoCommit}) {
-              $dbi_info->[3]->{AutoCommit} = 1;
-          }
-      }
-  }
-
   $self->_connect_info;
 }
 
@@ -781,9 +762,8 @@ sub _connect {
 
   $DBI::connect_via = $old_connect_via if $old_connect_via;
 
-  if (!$dbh || $@) {
-    $self->throw_exception("DBI Connection failed: " . ($@ || $DBI::errstr));
-  }
+  $self->throw_exception("DBI Connection failed: " . ($@||$DBI::errstr))
+    if !$dbh || $@;
 
   $dbh;
 }
@@ -850,15 +830,14 @@ sub txn_rollback {
 #  easier to override in NoBindVars without duping the rest.  It takes up
 #  all of _execute's args, and emits $sql, @bind.
 sub _prep_for_execute {
-  my ($self, $op, $extra_bind, $ident, @args) = @_;
+  my ($self, $op, $extra_bind, $ident, $args) = @_;
 
-  my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
+  my ($sql, @bind) = $self->sql_maker->$op($ident, @$args);
   unshift(@bind,
     map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
       if $extra_bind;
-  @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
 
-  return ($sql, @bind);
+  return ($sql, \@bind);
 }
 
 sub _execute {
@@ -867,71 +846,49 @@ sub _execute {
   if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) {
     $ident = $ident->from();
   }
-  
-  my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
-  unshift(@bind,
-    map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind)
-      if $extra_bind;
+
+  my ($sql, $bind) = $self->_prep_for_execute($op, $extra_bind, $ident, \@args);
+
   if ($self->debug) {
       my @debug_bind =
-        map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @bind;
+        map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @$bind;
       $self->debugobj->query_start($sql, @debug_bind);
   }
 
-  my ($rv, $sth);
-  RETRY: while (1) {
-    $sth = eval { $self->sth($sql,$op) };
-
-    if (!$sth || $@) {
-      $self->throw_exception(
-        'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
-      );
-    }
-
-    if ($sth) {
-      my $time = time();
-      $rv = eval {
-        my $placeholder_index = 1; 
+  my $sth = eval { $self->sth($sql,$op) };
+  $self->throw_exception("no sth generated via sql ($@): $sql") if $@;
 
-        foreach my $bound (@bind) {
+  my $rv = eval {
+    my $placeholder_index = 1; 
 
-          my $attributes = {};
-          my($column_name, @data) = @$bound;
+    foreach my $bound (@$bind) {
+      my $attributes = {};
+      my($column_name, @data) = @$bound;
 
-          if( $bind_attributes ) {
-            $attributes = $bind_attributes->{$column_name}
-            if defined $bind_attributes->{$column_name};
-          }
+      if ($bind_attributes) {
+        $attributes = $bind_attributes->{$column_name}
+        if defined $bind_attributes->{$column_name};
+      }
 
-          foreach my $data (@data)
-          {
-            $data = ref $data ? ''.$data : $data; # stringify args
+      foreach my $data (@data) {
+        $data = ref $data ? ''.$data : $data; # stringify args
 
-            $sth->bind_param($placeholder_index, $data, $attributes);
-            $placeholder_index++;
-          }
-        }
-        $sth->execute();
-      };
-    
-      if ($@ || !$rv) {
-        $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr))
-          if $self->connected;
-        $self->_populate_dbh;
-      } else {
-        last RETRY;
+        $sth->bind_param($placeholder_index, $data, $attributes);
+        $placeholder_index++;
       }
-    } else {
-      $self->throw_exception("'$sql' did not generate a statement.");
     }
-  } # While(1) to retry if disconencted
+    $sth->execute();
+  };
+
+  $self->throw_exception("Error executing '$sql': " . ($@ || $sth->errstr))
+    if $@ || !$rv;
 
   if ($self->debug) {
      my @debug_bind =
-       map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @bind; 
+       map { defined ($_ && $_->[1]) ? qq{'$_->[1]'} : q{'NULL'} } @$bind; 
      $self->debugobj->query_end($sql, @debug_bind);
   }
-  return (wantarray ? ($rv, $sth, @bind) : $rv);
+  return (wantarray ? ($rv, $sth, @$bind) : $rv);
 }
 
 sub insert {
@@ -940,11 +897,13 @@ sub insert {
   my $ident = $source->from; 
   my $bind_attributes = $self->source_bind_attributes($source);
 
+  eval { $self->_execute('insert' => [], $source, $bind_attributes, $to_insert) };
   $self->throw_exception(
     "Couldn't insert ".join(', ',
       map "$_ => $to_insert->{$_}", keys %$to_insert
-    )." into ${ident}"
-  ) unless ($self->_execute('insert' => [], $source, $bind_attributes, $to_insert));
+    )." into ${ident}: $@"
+  ) if $@;
+
   return $to_insert;
 }
 
@@ -1129,9 +1088,9 @@ sub _dbh_sth {
     ? $dbh->prepare($sql)
     : $dbh->prepare_cached($sql, {}, 3);
 
-  $self->throw_exception(
-    'no sth generated via sql (' . ($@ || $dbh->errstr) . "): $sql"
-  ) if !$sth;
+  # XXX You would think RaiseError would make this impossible,
+  #  but apparently that's not true :(
+  die $dbh->errstr if !$sth;
 
   $sth;
 }
@@ -1272,8 +1231,9 @@ sub create_ddl_dir
   $version ||= $schema->VERSION || '1.x';
   $sqltargs = { ( add_drop_table => 1 ), %{$sqltargs || {}} };
 
-  eval "use SQL::Translator";
-  $self->throw_exception("Can't create a ddl file without SQL::Translator: $@") if $@;
+  $self->throw_exception(q{Can't create a ddl file without SQL::Translator 0.08: '}
+      . $self->_check_sqlt_message . q{'})
+          if !$self->_check_sqlt_version;
 
   my $sqlt = SQL::Translator->new({
 #      debug => 1,
@@ -1312,12 +1272,7 @@ sub create_ddl_dir
 
     if($preversion)
     {
-      eval "use SQL::Translator::Diff";
-      if($@)
-      {
-        warn("Can't diff versions without SQL::Translator::Diff: $@");
-        next;
-      }
+      require SQL::Translator::Diff;
 
       my $prefilename = $schema->ddl_filename($db, $dir, $preversion);
 #      print "Previous version $prefilename\n";
@@ -1426,25 +1381,23 @@ sub deployment_statements {
       return join('', @rows);
   }
 
-  eval "use SQL::Translator";
-  if(!$@)
-  {
-    eval "use SQL::Translator::Parser::DBIx::Class;";
-    $self->throw_exception($@) if $@;
-    eval "use SQL::Translator::Producer::${type};";
-    $self->throw_exception($@) if $@;
-
-    # sources needs to be a parser arg, but for simplicty allow at top level 
-    # coming in
-    $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
-        if exists $sqltargs->{sources};
-
-    my $tr = SQL::Translator->new(%$sqltargs);
-    SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
-    return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
-  }
+  $self->throw_exception(q{Can't deploy without SQL::Translator 0.08: '}
+      . $self->_check_sqlt_message . q{'})
+          if !$self->_check_sqlt_version;
+
+  require SQL::Translator::Parser::DBIx::Class;
+  eval qq{use SQL::Translator::Producer::${type}};
+  $self->throw_exception($@) if $@;
+
+  # sources needs to be a parser arg, but for simplicty allow at top level 
+  # coming in
+  $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources}
+      if exists $sqltargs->{sources};
+
+  my $tr = SQL::Translator->new(%$sqltargs);
+  SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
+  return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
 
-  $self->throw_exception("No SQL::Translator, and no Schema file found, aborting deploy");
   return;
 
 }
@@ -1460,7 +1413,7 @@ sub deploy {
       next if($_ =~ /^COMMIT/m);
       next if $_ =~ /^\s+$/; # skip whitespace only
       $self->debugobj->query_start($_) if $self->debug;
-      $self->dbh->do($_) or warn "SQL was:\n $_"; # XXX exceptions?
+      $self->dbh->do($_); # shouldn't be using ->dbh ?
       $self->debugobj->query_end($_) if $self->debug;
     }
   }
@@ -1500,6 +1453,22 @@ sub build_datetime_parser {
   return $type;
 }
 
+{
+    my $_check_sqlt_version; # private
+    my $_check_sqlt_message; # private
+    sub _check_sqlt_version {
+        return $_check_sqlt_version if defined $_check_sqlt_version;
+        eval 'use SQL::Translator 0.08';
+        $_check_sqlt_message = $@ ? $@ : '';
+        $_check_sqlt_version = $@ ? 0 : 1;
+    }
+
+    sub _check_sqlt_message {
+        _check_sqlt_version if !defined $_check_sqlt_message;
+        $_check_sqlt_message;
+    }
+}
+
 sub DESTROY {
   my $self = shift;
   return if !$self->_dbh;