Merge 'trunk' into 'cdbicompat_integration'
Matt S Trout [Tue, 21 Aug 2007 19:56:43 +0000 (19:56 +0000)]
r11194@jules (orig r3695):  matthewt | 2007-08-21 19:24:53 +0100
 r10460@jules (orig r3640):  tomboh | 2007-08-01 12:27:38 +0100
 Add an 'on_disconnect_do' argument to
 DBIx::Class::Storage::DBI::connect_info that, on disconnection, do what
 'on_connect_do' does on connection.  Currently, this only works if the
 code explicitly calls disconnect() on the Storage object.

 While I'm here, make both 'on_connect_do' and 'on_disconnect_do' accept
 code references as well as strings containing SQL statements.

 Finally, remove code to call compose_connection() from DBICTest.pm that
 never gets called any more.

r11195@jules (orig r3696):  matthewt | 2007-08-21 19:24:57 +0100
 r11152@jules (orig r3678):  tomboh | 2007-08-15 09:24:32 +0100
 Restore code that I removed in revision 3640 that tests still need

r11196@jules (orig r3697):  matthewt | 2007-08-21 19:25:00 +0100
 r11153@jules (orig r3679):  tomboh | 2007-08-15 09:25:47 +0100
 Let on_connect_do() and on_disconnect_do() take code references.
 Provide tests and documentation for this.

r11197@jules (orig r3698):  matthewt | 2007-08-21 19:25:33 +0100

r11199@jules (orig r3700):  matthewt | 2007-08-21 19:50:00 +0100
arrayrefs for on_connect_do
r11200@jules (orig r3701):  matthewt | 2007-08-21 19:53:44 +0100
note on_connect_do changes
r11201@jules (orig r3702):  matthewt | 2007-08-21 20:17:22 +0100
oracle datetime inflator patch
r11202@jules (orig r3703):  matthewt | 2007-08-21 20:52:09 +0100
force CDBICompat deps for developers, fix tests to work with latest Class::Trigger

1  2 
lib/DBIx/Class/Storage/DBI.pm

@@@ -14,7 -14,7 +14,7 @@@ use Scalar::Util qw/blessed weaken/
  __PACKAGE__->mk_group_accessors('simple' =>
      qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts
         _conn_pid _conn_tid disable_sth_caching on_connect_do
-        transaction_depth unsafe _dbh_autocommit/
+        on_disconnect_do transaction_depth unsafe _dbh_autocommit/
  );
  
  __PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor');
@@@ -347,9 -347,30 +347,30 @@@ connection-specific options
  
  =item on_connect_do
  
- This can be set to an arrayref of literal sql statements, which will
- be executed immediately after making the connection to the database
- every time we [re-]connect.
+ Specifies things to do immediately after connecting or re-connecting to
+ the database.  Its value may contain:
+ =over
+ =item an array reference
+ This contains SQL statements to execute in order.  Each element contains
+ a string or a code reference that returns a string.
+ =item a code reference
+ This contains some code to execute.  Unlike code references within an
+ array reference, its return value is ignored.
+ =back
+ =item on_disconnect_do
+ Takes arguments in the same for as L<on_connect_do> and executes them
+ immediately before disconnecting from the database.
+ Note, this only runs if you explicitly call L<disconnect> on the
+ storage object.
  
  =item disable_sth_caching
  
@@@ -481,9 -502,10 +502,10 @@@ sub connect_info 
    my $last_info = $dbi_info->[-1];
    if(ref $last_info eq 'HASH') {
      $last_info = { %$last_info }; # so delete is non-destructive
-     for my $storage_opt (
-         qw/on_connect_do disable_sth_caching unsafe cursor_class/
-       ) {
+     my @storage_option = qw(
+       on_connect_do on_disconnect_do disable_sth_caching unsafe cursor_class
+     );
+     for my $storage_opt (@storage_option) {
        if(my $value = delete $last_info->{$storage_opt}) {
          $self->$storage_opt($value);
        }
@@@ -650,6 -672,9 +672,9 @@@ sub disconnect 
    my ($self) = @_;
  
    if( $self->connected ) {
+     my $connection_do = $self->on_disconnect_do;
+     $self->_do_connection_actions($connection_do) if ref($connection_do);
      $self->_dbh->rollback unless $self->_dbh_autocommit;
      $self->_dbh->disconnect;
      $self->_dbh(undef);
@@@ -742,17 -767,43 +767,43 @@@ sub _populate_dbh 
      }
    }
  
-   # if on-connect sql statements are given execute them
-   foreach my $sql_statement (@{$self->on_connect_do || []}) {
-     $self->_query_start($sql_statement);
-     $self->_dbh->do($sql_statement);
-     $self->_query_end($sql_statement);
-   }
+   my $connection_do = $self->on_connect_do;
+   $self->_do_connection_actions($connection_do) if ref($connection_do);
  
    $self->_conn_pid($$);
    $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
  }
  
+ sub _do_connection_actions {
+   my $self = shift;
+   my $connection_do = shift;
+   if (ref $connection_do eq 'ARRAY') {
+     $self->_do_query($_) foreach @$connection_do;
+   }
+   elsif (ref $connection_do eq 'CODE') {
+     $connection_do->();
+   }
+   return $self;
+ }
+ sub _do_query {
+   my ($self, $action) = @_;
+   if (ref $action eq 'CODE') {
+     $action->($self);
+   }
+   else {
+     my @to_run = (ref $action eq 'ARRAY') ? (@$action) : ($action);
+     $self->_query_start(@to_run);
+     $self->_dbh->do(@to_run);
+     $self->_query_end(@to_run);
+   }
+   return $self;
+ }
  sub _connect {
    my ($self, @info) = @_;
  
@@@ -1051,9 -1102,6 +1102,9 @@@ sub _select 
    } else {
      $self->throw_exception("rows attribute must be positive if present")
        if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
 +
 +    # MySQL actually recommends this approach.  I cringe.
 +    $attrs->{rows} = 2**48 if not defined $attrs->{rows} and defined $attrs->{offset};
      push @args, $attrs->{rows}, $attrs->{offset};
    }
    return $self->_execute(@args);