X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSQLMaker%2FLimitDialects.pm;h=0e6eb7e999a729dba731fb19f8b0914060a78562;hb=02562a2092543488bba4ccd98c39abca72560555;hp=18b53298afbecca0944b01236bce4cf07441bb55;hpb=df4312bcd2871c005751ce8c49c98c6be3692699;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/SQLMaker/LimitDialects.pm b/lib/DBIx/Class/SQLMaker/LimitDialects.pm index 18b5329..0e6eb7e 100644 --- a/lib/DBIx/Class/SQLMaker/LimitDialects.pm +++ b/lib/DBIx/Class/SQLMaker/LimitDialects.pm @@ -3,9 +3,6 @@ package DBIx::Class::SQLMaker::LimitDialects; use warnings; use strict; -use List::Util 'first'; -use namespace::clean; - # constants are used not only here, but also in comparison tests sub __rows_bindtype () { +{ sqlt_datatype => 'integer' } @@ -61,7 +58,7 @@ sub _LimitOffset { =head2 LimitXY - SELECT ... LIMIT $offset $limit + SELECT ... LIMIT $offset, $limit Supported by B and any L based DBD @@ -157,7 +154,7 @@ sub _rno_default_order { SELECT SKIP $offset FIRST $limit * FROM ... -Suported by B, almost like LimitOffset. According to +Supported by B, almost like LimitOffset. According to L C<... SKIP $offset LIMIT $limit ...> is also supported. =cut @@ -273,12 +270,12 @@ EOS # method, and the slower BETWEEN query is used instead # # FIXME - this is quite expensive, and does not perform caching of any sort - # as soon as some of the DQ work becomes viable consider switching this - # over + # as soon as some of the SQLA-inlining work becomes viable consider adding + # some rudimentary caching support if ( $rs_attrs->{order_by} and - $rs_attrs->{_rsroot_rsrc}->storage->_order_by_is_stable( + $rs_attrs->{result_source}->schema->storage->_order_by_is_stable( @{$rs_attrs}{qw/from order_by where/} ) ) { @@ -331,7 +328,7 @@ 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->{result_source}->schema->storage->_order_by_is_stable( $rs_attrs->{from}, $requested_order, $rs_attrs->{where}, @@ -343,11 +340,11 @@ sub _prep_for_skimming_limit { $inner_order = [ map { "$rs_attrs->{alias}.$_" } ( @{ - $rs_attrs->{_rsroot_rsrc}->_identifying_column_set + $rs_attrs->{result_source}->_identifying_column_set || $self->throw_exception(sprintf( 'Unable to auto-construct stable order criteria for "skimming type" limit ' - . "dialect based on source '%s'", $rs_attrs->{_rsroot_rsrc}->name) ); + . "dialect based on source '%s'", $rs_attrs->{result_source}->name) ); } ) ]; } @@ -532,29 +529,37 @@ Currently used by B, due to lack of any other option. sub _GenericSubQ { my ($self, $sql, $rs_attrs, $rows, $offset) = @_; - my $root_rsrc = $rs_attrs->{_rsroot_rsrc}; + my $main_rsrc = $rs_attrs->{result_source}; # Explicitly require an order_by # GenSubQ is slow enough as it is, just emulating things # like in other cases is not wise - make the user work # to shoot their DBA in the foot - my $supplied_order = delete $rs_attrs->{order_by} or $self->throw_exception ( + $self->throw_exception ( 'Generic Subquery Limit does not work on resultsets without an order. Provide a stable, ' - . 'root-table-based order criteria.' + . 'main-table-based order criteria.' + ) unless $rs_attrs->{order_by}; + + my $usable_order_colinfo = $main_rsrc->schema->storage->_extract_colinfo_of_stable_main_source_order_by_portion( + $rs_attrs ); - my $usable_order_colinfo = $root_rsrc->storage->_extract_colinfo_of_stable_main_source_order_by_portion( - $root_rsrc, - $supplied_order, - $rs_attrs->{where}, - ) or $self->throw_exception( - 'Generic Subquery Limit can not work with order criteria based on sources other than the current one' + $self->throw_exception( + 'Generic Subquery Limit can not work with order criteria based on sources other than the main one' + ) if ( + ! keys %{$usable_order_colinfo||{}} + or + grep + { $_->{-source_alias} ne $rs_attrs->{alias} } + (values %$usable_order_colinfo) ); ### ### ### we need to know the directions after we figured out the above - reextract *again* ### this is eyebleed - trying to get it to work at first + my $supplied_order = delete $rs_attrs->{order_by}; + my @order_bits = do { local $self->{quote_char}; local $self->{order_bind}; @@ -574,8 +579,8 @@ sub _GenericSubQ { # calculate the condition my $count_tbl_alias = 'rownum__emulation'; - my $root_alias = $rs_attrs->{alias}; - my $root_tbl_name = $root_rsrc->name; + my $main_alias = $rs_attrs->{alias}; + my $main_tbl_name = $main_rsrc->name; my (@unqualified_names, @qualified_names, @is_desc, @new_order_by); @@ -594,7 +599,7 @@ sub _GenericSubQ { for my $i (0 .. $#order_bits) { my $ci = $usable_order_colinfo->{$order_bits[$i]}; - my ($subq_col, $main_col) = map { "$_.$ci->{-colname}" } ($count_tbl_alias, $root_alias); + my ($subq_col, $main_col) = map { "$_.$ci->{-colname}" } ($count_tbl_alias, $main_alias); my $cur_cond = { $subq_col => { ($is_desc[$i] ? '>' : '<') => { -ident => $main_col } } }; push @skip_colpair_stack, [ @@ -683,7 +688,7 @@ WHERE ( SELECT COUNT(*) FROM %s %s $counted_where ) $rownum_cond $inner_order_sql ", map { $self->_quote ($_) } ( $rs_attrs->{alias}, - $root_tbl_name, + $main_tbl_name, $count_tbl_alias, )); } @@ -693,7 +698,7 @@ $inner_order_sql # # Generates inner/outer select lists for various limit dialects # which result in one or more subqueries (e.g. RNO, Top, RowNum) -# Any non-root-table columns need to have their table qualifier +# Any non-main-table columns need to have their table qualifier # turned into a column alias (otherwise names in subqueries clash # and/or lose their source table) # @@ -732,16 +737,22 @@ sub _subqueried_limit_attrs { my $s = $rs_attrs->{select}[$i]; my $sql_alias = (ref $s) eq 'HASH' ? $s->{-as} : undef; - # we throw away the @bind here deliberately - my ($sql_sel) = $self->_recurse_fields ($s); + my ($sql_sel) = length ref $s + # we throw away the @bind here deliberately + ? $self->_recurse_fields( $s ) + : $self->_quote( $s ) + ; push @sel, { arg => $s, sql => $sql_sel, - unquoted_sql => do { - local $self->{quote_char}; - ($self->_recurse_fields ($s))[0]; # ignore binds again - }, + unquoted_sql => ( length ref $s + ? do { + local $self->{quote_char}; + ($self->_recurse_fields ($s))[0]; # ignore binds again + } + : $s + ), as => $sql_alias || @@ -821,14 +832,17 @@ sub _unqualify_colname { return $fqcn; } -1; - -=head1 AUTHORS +=head1 FURTHER QUESTIONS? -See L. +Check the list of L. -=head1 LICENSE +=head1 COPYRIGHT AND LICENSE -You may distribute this code under the same terms as Perl itself. +This module is free software L +by the L. You can +redistribute it and/or modify it under the same terms as the +L. =cut + +1;