X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSQLMaker%2FLimitDialects.pm;h=76399887da4d66d04eb799420f9d4f9a52aba35c;hb=8f6986ac3a13c85fbbf0f783f47daf9304a409e1;hp=e9a1c87daa0028e484b3b8984822bac0f2245449;hpb=ebc5c60a4ff45bb9ab7630e2512015b3b7cb2c96;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/SQLMaker/LimitDialects.pm b/lib/DBIx/Class/SQLMaker/LimitDialects.pm index e9a1c87..7639988 100644 --- a/lib/DBIx/Class/SQLMaker/LimitDialects.pm +++ b/lib/DBIx/Class/SQLMaker/LimitDialects.pm @@ -121,10 +121,10 @@ sub _RowNumberOver { } # and this is order re-alias magic - for ($sq_attrs->{order_supplement}, $sq_attrs->{outer_renames}) { - for my $col (keys %$_) { + for my $map ($sq_attrs->{order_supplement}, $sq_attrs->{outer_renames}) { + for my $col (sort { (length $b) <=> (length $a) } keys %{$map||{}} ) { my $re_col = quotemeta ($col); - $rno_ord =~ s/$re_col/$_->{$col}/; + $rno_ord =~ s/$re_col/$map->{$col}/; } } @@ -279,7 +279,7 @@ EOS $rs_attrs->{order_by} and $rs_attrs->{_rsroot_rsrc}->storage->_order_by_is_stable( - $rs_attrs->{from}, $rs_attrs->{order_by} + @{$rs_attrs}{qw/from order_by where/} ) ) { push @{$self->{limit_bind}}, [ $self->__total_bindtype => $offset + $rows ], [ $self->__offset_bindtype => $offset + 1 ]; @@ -331,10 +331,11 @@ sub _prep_for_skimming_limit { if ($sq_attrs->{order_by_requested}) { $self->throw_exception ( 'Unable to safely perform "skimming type" limit with supplied unstable order criteria' - ) unless $rs_attrs->{_rsroot_rsrc}->schema->storage->_order_by_is_stable( + ) unless ($rs_attrs->{_rsroot_rsrc}->schema->storage->_order_by_is_stable( $rs_attrs->{from}, - $requested_order - ); + $requested_order, + $rs_attrs->{where}, + )); $inner_order = $requested_order; } @@ -382,23 +383,11 @@ sub _prep_for_skimming_limit { # Whatever order bindvals there are, they will be realiased and # reselected, and need to show up at end of the initial inner select push @{$self->{select_bind}}, @{$self->{order_bind}}; - - # if this is a part of something bigger, we need to add back all - # the extra order_by's, as they may be relied upon by the outside - # of a prefetch or something - if ($rs_attrs->{_is_internal_subuery}) { - $sq_attrs->{selection_outer} .= sprintf ", $extra_order_sel->{$_} AS $_" - for sort - { $extra_order_sel->{$a} cmp $extra_order_sel->{$b} } - grep { $_ !~ /[^\w\-]/ } # ignore functions - keys %$extra_order_sel - ; - } } # and this is order re-alias magic for my $map ($sq_attrs->{order_supplement}, $sq_attrs->{outer_renames}) { - for my $col (sort { $map->{$a} cmp $map->{$b} } keys %{$map||{}}) { + for my $col (sort { (length $b) <=> (length $a) } keys %{$map||{}}) { my $re_col = quotemeta ($col); $_ =~ s/$re_col/$map->{$col}/ for ($sq_attrs->{order_by_middle}, $sq_attrs->{order_by_requested}); @@ -536,9 +525,9 @@ sub _RowCountOrGenericSubQ { return $self->_GenericSubQ(@_) if $offset; - return sprintf <<"EOF", $rows, $sql; + return sprintf <<"EOF", $rows, $sql, $self->_parse_rs_attrs( $rs_attrs ); SET ROWCOUNT %d -%s +%s %s SET ROWCOUNT 0 EOF } @@ -556,8 +545,11 @@ This is the most evil limit "dialect" (more of a hack) for I stupid databases. It works by ordering the set by some unique column, and calculating the amount of rows that have a less-er value (thus emulating a L-like index). Of course this implies the set can only be ordered by a single unique -column. Also note that this technique can be and often is B. +column. + +Also note that this technique can be and often is B. You +may have much better luck using L +instead. Currently used by B, due to lack of any other option. @@ -702,6 +694,7 @@ sub _subqueried_limit_attrs { my $sql_alias = (ref $s) eq 'HASH' ? $s->{-as} : undef; push @sel, { + arg => $s, sql => $sql_sel, unquoted_sql => do { local $self->{quote_char}; @@ -716,7 +709,9 @@ sub _subqueried_limit_attrs { , }; - $in_sel_index->{$sql_sel}++; + # anything with a placeholder in it needs re-selection + $in_sel_index->{$sql_sel}++ unless $sql_sel =~ / (?: ^ | \W ) \? (?: \W | $ ) /x; + $in_sel_index->{$self->_quote ($sql_alias)}++ if $sql_alias; # record unqualified versions too, so we do not have @@ -732,11 +727,14 @@ sub _subqueried_limit_attrs { # unless we are dealing with the current source alias # (which will transcend the subqueries as it is necessary # for possible further chaining) + # same for anything we do not recognize my ($sel, $renamed); for my $node (@sel) { push @{$sel->{original}}, $node->{sql}; if ( + ! $in_sel_index->{$node->{sql}} + or $node->{as} =~ / (?{unquoted_sql} =~ / (?{inner}}, $node->{sql}; - push @{$sel->{outer}}, $self->_quote ($node->{as}); + push @{$sel->{outer}}, $self->_quote (ref $node->{arg} ? $node->{as} : $node->{arg}); } } @@ -763,7 +761,7 @@ sub _subqueried_limit_attrs { next if $in_sel_index->{$chunk}; $extra_order_sel->{$chunk} ||= $self->_quote ( - 'ORDER__BY__' . scalar keys %{$extra_order_sel||{}} + 'ORDER__BY__' . sprintf '%03d', scalar keys %{$extra_order_sel||{}} ); }