Merge 'trunk' into 'prefetch_redux'
Peter Rabbitson [Tue, 4 Aug 2009 10:36:20 +0000 (10:36 +0000)]
r7179@Thesaurus (orig r7176):  ribasushi | 2009-08-03 11:51:42 +0200
 r6983@Thesaurus (orig r6982):  ribasushi | 2009-07-04 11:46:57 +0200
 New branch to experiment with a sanifying mysql on_connect_call
 r6984@Thesaurus (orig r6983):  ribasushi | 2009-07-04 11:49:44 +0200
 Initial set_ansi_mode code - make sure to utilize _do_query instead of dbh->do, so the result is visible in the trace
 r6987@Thesaurus (orig r6986):  ribasushi | 2009-07-04 12:40:47 +0200
 Fix POD
 r7178@Thesaurus (orig r7175):  ribasushi | 2009-08-03 11:51:15 +0200
 Wrap up set_strict_mode for mysql

r7181@Thesaurus (orig r7178):  ribasushi | 2009-08-03 12:41:32 +0200
Sanify unqualified column bindtype handling
Silence a warning when using a custom {from}

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

@@@ -1264,7 -1264,7 +1264,7 @@@ sub _count_subq_rs 
    my $sub_attrs = { %$attrs };
  
    # extra selectors do not go in the subquery and there is no point of ordering it
 -  delete $sub_attrs->{$_} for qw/collapse prefetch_select select as order_by/;
 +  delete $sub_attrs->{$_} for qw/collapse select _prefetch_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
    # clobber old group_by regardless
@@@ -2875,12 -2875,6 +2875,12 @@@ sub _resolved_attrs 
      $attrs->{group_by} = [ $attrs->{group_by} ];
    }
  
 +  # generate the distinct induced group_by early, as prefetch will be carried via a
 +  # subquery (since a group_by is present)
 +  if (delete $attrs->{distinct}) {
 +    $attrs->{group_by} ||= [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ];
 +  }
 +
    $attrs->{collapse} ||= {};
    if ( my $prefetch = delete $attrs->{prefetch} ) {
      $prefetch = $self->_merge_attr( {}, $prefetch );
      my @prefetch =
        $source->_resolve_prefetch( $prefetch, $alias, $join_map, $prefetch_ordering, $attrs->{collapse} );
  
 -    $attrs->{prefetch_select} = [ map { $_->[0] } @prefetch ];
 -    push @{ $attrs->{select} }, @{$attrs->{prefetch_select}};
 +    # we need to somehow mark which columns came from prefetch
 +    $attrs->{_prefetch_select} = [ map { $_->[0] } @prefetch ];
 +
 +    push @{ $attrs->{select} }, @{$attrs->{_prefetch_select}};
      push @{ $attrs->{as} }, (map { $_->[1] } @prefetch);
  
      push( @{$attrs->{order_by}}, @$prefetch_ordering );
      $attrs->{_collapse_order_by} = \@$prefetch_ordering;
    }
  
 -
 -  if (delete $attrs->{distinct}) {
 -    $attrs->{group_by} ||= [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ];
 -  }
 -
    # if both page and offset are specified, produce a combined offset
    # even though it doesn't make much sense, this is what pre 081xx has
    # been doing
@@@ -2931,7 -2928,7 +2931,7 @@@ sub _joinpath_aliases 
    for my $j (@$fromspec) {
  
      next if ref $j ne 'ARRAY';
-     next if $j->[0]{-relation_chain_depth} < $cur_depth;
+     next if ($j->[0]{-relation_chain_depth} || 0) < $cur_depth;
  
      my $jpath = $j->[0]{-join_path};
  
@@@ -1401,8 -1401,21 +1401,21 @@@ sub _select_args 
        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 $rs_alias;
+       # Unqialified column names are nice, but at the same time can be
+       # rather ambiguous. What we do here is basically go along with
+       # the loop, adding an unqualified column slot to $bind_attrs,
+       # alongside the fully qualified name. As soon as we encounter
+       # another column by that name (which would imply another table)
+       # we unset the unqualified slot and never add any info to it
+       # to avoid erroneous type binding. If this happens the users
+       # only choice will be to fully qualify his column name
+       if (exists $bind_attrs->{$col}) {
+         $bind_attrs->{$col} = {};
+       }
+       else {
+         $bind_attrs->{$col} = $bind_attrs->{$fqcn};
+       }
      }
    }
  
      ( $attrs->{rows} && keys %{$attrs->{collapse}} )
         ||
      ( $attrs->{group_by} && @{$attrs->{group_by}} &&
 -      $attrs->{prefetch_select} && @{$attrs->{prefetch_select}} )
 +      $attrs->{_prefetch_select} && @{$attrs->{_prefetch_select}} )
    ) {
      ($ident, $select, $where, $attrs)
        = $self->_adjust_select_args_for_complex_prefetch ($ident, $select, $where, $attrs);
@@@ -1475,15 -1488,14 +1488,15 @@@ sub _adjust_select_args_for_complex_pre
    # separate attributes
    my $sub_attrs = { %$attrs };
    delete $attrs->{$_} for qw/where bind rows offset group_by having/;
 -  delete $sub_attrs->{$_} for qw/for collapse prefetch_select _collapse_order_by select as/;
 +  delete $sub_attrs->{$_} for qw/for collapse _prefetch_select _collapse_order_by select as/;
  
    my $alias = $attrs->{alias};
    my $sql_maker = $self->sql_maker;
  
    # create subquery select list - consider only stuff *not* brought in by the prefetch
    my $sub_select = [];
 -  for my $i (0 .. @{$attrs->{select}} - @{$attrs->{prefetch_select}} - 1) {
 +  my $sub_group_by;
 +  for my $i (0 .. @{$attrs->{select}} - @{$attrs->{_prefetch_select}} - 1) {
      my $sel = $attrs->{select}[$i];
  
      # alias any functions to the dbic-side 'as' label
  
    # if a multi-type join was needed in the subquery ("multi" is indicated by
    # presence in {collapse}) - add a group_by to simulate the collapse in the subq
 -  for my $alias (keys %inner_joins) {
 -
 -    # the dot comes from some weirdness in collapse
 -    # remove after the rewrite
 -    if ($attrs->{collapse}{".$alias"}) {
 -      $sub_attrs->{group_by} ||= $sub_select;
 -      last;
 +  unless ($sub_attrs->{group_by}) {
 +    for my $alias (keys %inner_joins) {
 +
 +      # the dot comes from some weirdness in collapse
 +      # remove after the rewrite
 +      if ($attrs->{collapse}{".$alias"}) {
 +        $sub_attrs->{group_by} ||= $sub_select;
 +        last;
 +      }
      }
    }