Merge 'trunk' into 'on_connect_call'
Rafael Kitover [Thu, 18 Jun 2009 22:26:51 +0000 (22:26 +0000)]
r5536@hlagh (orig r6698):  wintrmute | 2009-06-17 01:32:30 -0700
Replace vague language around whether load_classes/namespaces is preferred,
with an explanation that load_namespaces() is generally preferred, and explain
when load_classes is appropriate.
r5539@hlagh (orig r6701):  caelum | 2009-06-17 10:50:47 -0700
fix page with offset bug
r5546@hlagh (orig r6703):  ribasushi | 2009-06-17 23:40:18 -0700
Cleanup attribute handling - I deal with resolved attributes throughout, no point in complicating things further
r5547@hlagh (orig r6704):  abraxxa | 2009-06-18 03:30:01 -0700
added test for nested has_many prefetch without entries

r5549@hlagh (orig r6706):  ribasushi | 2009-06-18 03:43:36 -0700
HRI fix
r5550@hlagh (orig r6707):  ribasushi | 2009-06-18 05:05:42 -0700
wtf

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

@@@ -14,15 -14,13 +14,15 @@@ use List::Util()
  
  __PACKAGE__->mk_group_accessors('simple' =>
      qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts
 -       _conn_pid _conn_tid transaction_depth _dbh_autocommit savepoints/
 +       _conn_pid _conn_tid transaction_depth _dbh_autocommit _on_connect_do
 +       _on_disconnect_do _on_connect_do_store _on_disconnect_do_store
 +       savepoints/
  );
  
  # the values for these accessors are picked out (and deleted) from
  # the attribute hashref passed to connect_info
  my @storage_options = qw/
 -  on_connect_do on_disconnect_do disable_sth_caching unsafe auto_savepoint
 +  on_connect_call on_disconnect_call disable_sth_caching unsafe auto_savepoint
  /;
  __PACKAGE__->mk_group_accessors('simple' => @storage_options);
  
@@@ -179,91 -177,6 +179,91 @@@ immediately before disconnecting from t
  Note, this only runs if you explicitly call L</disconnect> on the
  storage object.
  
 +=item on_connect_call
 +
 +A more generalized form of L</on_connect_do> that calls the specified
 +C<connect_call_METHOD> methods in your storage driver.
 +
 +  on_connect_do => 'select 1'
 +
 +is equivalent to:
 +
 +  on_connect_call => [ [ do_sql => 'select 1' ] ]
 +
 +Its values may contain:
 +
 +=over
 +
 +=item a scalar
 +
 +Will call the C<connect_call_METHOD> method.
 +
 +=item a code reference
 +
 +Will execute C<< $code->($storage) >>
 +
 +=item an array reference
 +
 +Each value can be a method name or code reference.
 +
 +=item an array of arrays
 +
 +For each array, the first item is taken to be the C<connect_call_> method name
 +or code reference, and the rest are parameters to it.
 +
 +=back
 +
 +Some predefined storage methods you may use:
 +
 +=over
 +
 +=item do_sql
 +
 +Executes a SQL string or a code reference that returns a SQL string. This is
 +what L</on_connect_do> and L</on_disconnect_do> use.
 +
 +It can take:
 +
 +=over
 +
 +=item a scalar
 +
 +Will execute the scalar as SQL.
 +
 +=item an arrayref
 +
 +Taken to be arguments to L<DBI/do>, the SQL string optionally followed by the
 +attributes hashref and bind values.
 +
 +=item a code reference
 +
 +Will execute C<< $code->($storage) >> and execute the return array refs as
 +above.
 +
 +=back
 +
 +=item datetime_setup
 +
 +Execute any statements necessary to initialize the database session to return
 +and accept datetime/timestamp values used with
 +L<DBIx::Class::InflateColumn::DateTime>.
 +
 +Only necessary for some databases, see your specific storage driver for
 +implementation details.
 +
 +=back
 +
 +=item on_disconnect_call
 +
 +Takes arguments in the same form as L</on_connect_call> and executes them
 +immediately before disconnecting from the database.
 +
 +Calls the C<disconnect_call_METHOD> methods as opposed to the
 +C<connect_call_METHOD> methods called by L</on_connect_call>.
 +
 +Note, this only runs if you explicitly call L</disconnect> on the
 +storage object.
 +
  =item disable_sth_caching
  
  If set to a true value, this option will disable the caching of
@@@ -434,11 -347,6 +434,11 @@@ sub connect_info 
          $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
        }
      }
 +    for my $connect_do_opt (qw/on_connect_do on_disconnect_do/) {
 +      if(my $opt_val = delete $attrs{$connect_do_opt}) {
 +        $self->$connect_do_opt($opt_val);
 +      }
 +    }
    }
  
    %attrs = () if (ref $args[0] eq 'CODE');  # _connect() never looks past $args[0] in this case
  
  This method is deprecated in favour of setting via L</connect_info>.
  
 +=cut
 +
 +sub on_connect_do {
 +  my $self = shift;
 +  $self->_setup_connect_do(on_connect_do => @_);
 +}
 +
 +=head2 on_disconnect_do
 +
 +This method is deprecated in favour of setting via L</connect_info>.
 +
 +=cut
 +
 +sub on_disconnect_do {
 +  my $self = shift;
 +  $self->_setup_connect_do(on_disconnect_do => @_);
 +}
 +
 +sub _setup_connect_do {
 +  my ($self, $opt) = (shift, shift);
 +
 +  my $accessor = "_$opt";
 +  my $store    = "_${opt}_store";
 +
 +  return $self->$accessor if not @_;
 +
 +  my $val = shift;
 +
 +  if (not defined $val) {
 +    $self->$accessor(undef);
 +    $self->$store(undef);
 +    return;
 +  }
 +
 +  my @store;
 +
 +  if (not ref($val)) {
 +    push @store, [ 'do_sql', $val ];
 +  } elsif (ref($val) eq 'CODE') {
 +    push @store, $val;
 +  } elsif (ref($val) eq 'ARRAY') {
 +    push @store, map [ 'do_sql', $_ ], @$val;
 +  } else {
 +    $self->throw_exception("Invalid type for $opt ".ref($val));
 +  }
 +
 +  $self->$store(\@store);
 +  $self->$accessor($val);
 +}
  
  =head2 dbh_do
  
@@@ -647,12 -506,8 +647,12 @@@ sub disconnect 
    my ($self) = @_;
  
    if( $self->connected ) {
 -    my $connection_do = $self->on_disconnect_do;
 -    $self->_do_connection_actions($connection_do) if ref($connection_do);
 +    if (my $connection_call = $self->on_disconnect_call) {
 +      $self->_do_connection_actions(disconnect_call_ => $connection_call)
 +    }
 +    if (my $connection_do   = $self->_on_disconnect_do_store) {
 +      $self->_do_connection_actions(disconnect_call_ => $connection_do)
 +    }
  
      $self->_dbh->rollback unless $self->_dbh_autocommit;
      $self->_dbh->disconnect;
@@@ -769,12 -624,8 +769,12 @@@ sub _populate_dbh 
    #  there is no transaction in progress by definition
    $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1;
  
 -  my $connection_do = $self->on_connect_do;
 -  $self->_do_connection_actions($connection_do) if $connection_do;
 +  if (my $connection_call = $self->on_connect_call) {
 +    $self->_do_connection_actions(connect_call_ => $connection_call)
 +  }
 +  if (my $connection_do = $self->_on_connect_do_store) {
 +    $self->_do_connection_actions(connect_call_ => $connection_do)
 +  }
  }
  
  sub _determine_driver {
  }
  
  sub _do_connection_actions {
 -  my $self = shift;
 -  my $connection_do = shift;
 -
 -  if (!ref $connection_do) {
 -    $self->_do_query($connection_do);
 -  }
 -  elsif (ref $connection_do eq 'ARRAY') {
 -    $self->_do_query($_) foreach @$connection_do;
 -  }
 -  elsif (ref $connection_do eq 'CODE') {
 -    $connection_do->($self);
 -  }
 -  else {
 -    $self->throw_exception (sprintf ("Don't know how to process conection actions of type '%s'", ref $connection_do) );
 +  my $self          = shift;
 +  my $method_prefix = shift;
 +  my $call          = shift;
 +
 +  if (not ref($call)) {
 +    my $method = $method_prefix . $call;
 +    $self->$method(@_);
 +  } elsif (ref($call) eq 'CODE') {
 +    $self->$call(@_);
 +  } elsif (ref($call) eq 'ARRAY') {
 +    if (ref($call->[0]) ne 'ARRAY') {
 +      $self->_do_connection_actions($method_prefix, $_) for @$call;
 +    } else {
 +      $self->_do_connection_actions($method_prefix, @$_) for @$call;
 +    }
 +  } else {
 +    $self->throw_exception (sprintf ("Don't know how to process conection actions of type '%s'", ref($call)) );
    }
  
    return $self;
  }
  
 +sub connect_call_do_sql {
 +  my $self = shift;
 +  $self->_do_query(@_);
 +}
 +
 +sub disconnect_call_do_sql {
 +  my $self = shift;
 +  $self->_do_query(@_);
 +}
 +
 +# override in db-specific backend when necessary
 +sub connect_call_datetime_setup { 1 }
 +
  sub _do_query {
    my ($self, $action) = @_;
  
@@@ -1476,8 -1311,8 +1476,8 @@@ sub count 
  
    my $tmp_attrs = { %$attrs };
  
-   # take off any pagers, record_filter is cdbi, and no point of ordering a count
-   delete $tmp_attrs->{$_} for (qw/select as rows offset page order_by record_filter/);
+   # take off any limits, record_filter is cdbi, and no point of ordering a count
+   delete $tmp_attrs->{$_} for (qw/select as rows offset order_by record_filter/);
  
    # overwrite the selector
    $tmp_attrs->{select} = { count => '*' };
@@@ -1501,7 -1336,7 +1501,7 @@@ sub count_grouped 
    my $sub_attrs = { %$attrs };
  
    # these can not go in the subquery, and there is no point of ordering it
-   delete $sub_attrs->{$_} for qw/prefetch collapse select as order_by/;
+   delete $sub_attrs->{$_} for qw/collapse select as order_by/;
  
    # if we prefetch, we group_by primary keys only as this is what we would get out of the rs via ->next/->all
    # simply deleting group_by suffices, as the code below will re-fill it
    }];
  
    # the subquery replaces this
-   delete $attrs->{$_} for qw/where bind prefetch collapse group_by having having_bind rows offset page pager/;
+   delete $attrs->{$_} for qw/where bind collapse group_by having having_bind rows offset/;
  
    return $self->count ($source, $attrs);
  }