From: Peter Rabbitson Date: Mon, 8 Jun 2009 11:00:54 +0000 (+0000) Subject: First stab at adding resultsources to each join in select - works won-der-ful-ly X-Git-Tag: v0.08106~19^2~3 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=ba61fa2a8d50d0068905aa968b7514f1136ce110;p=dbsrgits%2FDBIx-Class.git First stab at adding resultsources to each join in select - works won-der-ful-ly --- diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 4ab4afa..7ef13b5 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -2435,7 +2435,11 @@ sub _resolve_from { my $attrs = $self->{attrs}; my $from = $attrs->{from} - || [ { $attrs->{alias} => $source->from } ]; + || [ { + -result_source => $source, + -alias => $attrs->{alias}, + $attrs->{alias} => $source->from, + } ]; my $seen = { %{$attrs->{seen_join}||{}} }; @@ -2540,7 +2544,11 @@ sub _resolved_attrs { push( @{ $attrs->{as} }, @$adds ); } - $attrs->{from} ||= [ { $self->{attrs}{alias} => $source->from } ]; + $attrs->{from} ||= [ { + -result_source => $source, + -alias => $self->{attrs}{alias}, + $self->{attrs}{alias} => $source->from, + } ]; if ( exists $attrs->{join} || exists $attrs->{prefetch} ) { my $join = delete $attrs->{join} || {}; @@ -2613,7 +2621,7 @@ sub _joinpath_aliases { my $p = $paths; $p = $p->{$_} ||= {} for @{$j->[0]{-join_path}}; - push @{$p->{-join_aliases} }, $j->[0]{-join_alias}; + push @{$p->{-join_aliases} }, $j->[0]{-alias}; } return $paths; diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index cd819a8..c8f7e8d 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -1120,10 +1120,13 @@ sub _resolve_join { $type = $rel_info->{attrs}{join_type} || ''; $force_left->{force} = 1 if lc($type) eq 'left'; } - return [ { $as => $self->related_source($join)->from, + + my $rel_src = $self->related_source($join); + return [ { $as => $rel_src->from, + -result_source => $rel_src, -join_type => $type, -join_path => [@$jpath, $join], - -join_alias => $as, + -alias => $as, -relation_chain_depth => $seen->{-relation_chain_depth} || 0, }, $self->_resolve_condition($rel_info->{cond}, $as, $alias) ]; diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index c20a931..666d318 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -10,7 +10,7 @@ use DBI; use DBIx::Class::SQLAHacks; use DBIx::Class::Storage::DBI::Cursor; use DBIx::Class::Storage::Statistics; -use Scalar::Util qw/blessed weaken/; +use Scalar::Util(); use List::Util(); __PACKAGE__->mk_group_accessors('simple' => @@ -717,7 +717,7 @@ sub _connect { if($dbh && !$self->unsafe) { my $weak_self = $self; - weaken($weak_self); + Scalar::Util::weaken($weak_self); $dbh->{HandleError} = sub { if ($weak_self) { $weak_self->throw_exception("DBI Exception: $_[0]"); @@ -898,7 +898,7 @@ sub txn_rollback { sub _prep_for_execute { my ($self, $op, $extra_bind, $ident, $args) = @_; - if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) { + if( Scalar::Util::blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) { $ident = $ident->from(); } @@ -990,7 +990,7 @@ sub _execute { sub insert { my ($self, $source, $to_insert) = @_; - + my $ident = $source->from; my $bind_attributes = $self->source_bind_attributes($source); @@ -1092,7 +1092,7 @@ sub delete { my $self = shift @_; my $source = shift @_; - my $bind_attrs = {}; ## If ever it's needed... + my $bind_attrs = $self->source_bind_attributes($source); return $self->_execute('delete' => [], $source, $bind_attrs, @_); } @@ -1213,7 +1213,42 @@ sub _select_args { ( map { $_ => $attrs->{$_} } (@in_order_attrs) ) }; } - my $bind_attrs = {}; ## Future support + + # the reason this is so contrived is because we have several tables in + # from, each with its own set of bindattrs + my $alias2source; + if ( Scalar::Util::blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) { + $alias2source->{$ident->alias} = $ident; + } + elsif (ref $ident eq 'ARRAY') { + + for (@$ident) { + my $tabinfo; + if (ref $_ eq 'HASH') { + $tabinfo = $_; + } + if (ref $_ eq 'ARRAY' and ref $_->[0] eq 'HASH') { + $tabinfo = $_->[0]; + } + + $alias2source->{$tabinfo->{-alias}} = $tabinfo->{-result_source} + if ($tabinfo->{-result_source}); + } + } + + my $bind_attrs = {}; + for my $alias (keys %$alias2source) { + my $bindtypes = $self->source_bind_attributes ($alias2source->{$alias}) || {}; + for my $col (keys %$bindtypes) { + + my $fqcn = join ('.', $alias, $col); + $bind_attrs->{$fqcn} = $bindtypes->{$col} if $bindtypes->{$col}; + + # so that unqualified searches can be bound too + $bind_attrs->{$col} = $bind_attrs->{$fqcn} if $alias eq 'me'; + } + } + my @args = ('select', $attrs->{bind}, $ident, $bind_attrs, $select, $condition, $order); if ($attrs->{software_limit} || $sql_maker->_default_limit_syntax eq "GenericSubQ") { diff --git a/t/bind/bindtype_columns.t b/t/bind/bindtype_columns.t index 1462d9b..629185d 100644 --- a/t/bind/bindtype_columns.t +++ b/t/bind/bindtype_columns.t @@ -49,10 +49,7 @@ my $new; is($row->get_column('bytea'), $big_long_string, "Created the blob correctly."); } -TODO: { - local $TODO = - 'Passing bind attributes to $sth->bind_param() should be implemented (it only works in $storage->insert ATM)'; - +{ my $rs = $schema->resultset('BindType')->search({ bytea => $big_long_string }); # search on the bytea column (select)