return sprintf ('SELECT %s%s%s%s',
$offset
? do {
- push @{$self->{limit_bind}}, [ $self->__offset_bindtype => $offset];
+ push @{$self->{pre_select_bind}}, [ $self->__offset_bindtype => $offset];
'SKIP ? '
}
: ''
,
do {
- push @{$self->{limit_bind}}, [ $self->__rows_bindtype => $rows ];
+ push @{$self->{pre_select_bind}}, [ $self->__rows_bindtype => $rows ];
'FIRST ? '
},
$sql,
return sprintf ('SELECT %s%s%s%s',
do {
- push @{$self->{limit_bind}}, [ $self->__rows_bindtype => $rows ];
+ push @{$self->{pre_select_bind}}, [ $self->__rows_bindtype => $rows ];
'FIRST ? '
},
$offset
? do {
- push @{$self->{limit_bind}}, [ $self->__offset_bindtype => $offset];
+ push @{$self->{pre_select_bind}}, [ $self->__offset_bindtype => $offset];
'SKIP ? '
}
: ''
# ordered by a unique set of columns, it is not safe to use the faster
# method, and the slower BETWEEN query is used instead
#
- # FIXME - this is quite expensive, and doe snot perform caching of any sort
+ # 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
- if ( __order_by_is_unique($rs_attrs) ) {
-
+ if (
+ $rs_attrs->{order_by}
+ and
+ $rs_attrs->{_rsroot_rsrc}->storage->_order_by_is_stable(
+ $rs_attrs->{from}, $rs_attrs->{order_by}
+ )
+ ) {
# if offset is 0 (first page) the we can skip a subquery
if (! $offset) {
push @{$self->{limit_bind}}, [ $self->__rows_bindtype => $rows ];
}
}
-# determine if the supplied order_by contains a unique column (set)
-sub __order_by_is_unique {
- my $rs_attrs = shift;
- my $rsrc = $rs_attrs->{_rsroot_rsrc};
- my $order_by = $rs_attrs->{order_by}
- || return 0;
-
- my $storage = $rsrc->schema->storage;
-
- my @order_by_cols = map { $_->[0] } $storage->_extract_order_criteria($order_by)
- or return 0;
-
- my $colinfo =
- $storage->_resolve_column_info($rs_attrs->{from}, \@order_by_cols);
-
- my $sources = {
- map {( "$_" => $_ )} map { $_->{-result_source} } values %$colinfo
- };
-
- my $supplied_order = {
- map { $_ => 1 }
- grep { exists $colinfo->{$_} and ! $colinfo->{$_}{is_nullable} }
- @order_by_cols
- };
-
- return 0 unless keys %$supplied_order;
-
- for my $uks (
- map { values %$_ } map { +{ $_->unique_constraints } } values %$sources
- ) {
- return 1
- unless first { ! exists $supplied_order->{$_} } @$uks;
- }
-
- return 0;
-}
-
# used by _Top and _FetchFirst below
sub _prep_for_skimming_limit {
my ( $self, $sql, $rs_attrs ) = @_;
$r{mid_sel} .= ', ' . $extra_order_sel->{$extra_col};
}
- # since whatever order bindvals there are, they will be realiased
- # and need to show up in front of the entire initial inner subquery
- # *unshift* the selector bind stack to make this happen (horrible,
- # horrible, but we don't have another mechanism yet)
- unshift @{$self->{select_bind}}, @{$self->{order_bind}};
+ # Whatever order bindvals there are, they will be realiased and
+ # need to show up in front of the entire initial inner subquery
+ push @{$self->{pre_select_bind}}, @{$self->{order_bind}};
}
# and this is order re-alias magic
#
# Returns mangled proto-sql, inner/outer strings of SQL QUOTED selectors
# with aliases (to be used in whatever select statement), and an alias
-# index hashref of QUOTED SEL => QUOTED ALIAS pairs (to maybe be used
+# index hashref of QUOTED SEL => QUOTED ALIAS pairs (to maybe be used
# for string-subst higher up).
# If an order_by is supplied, the inner select needs to bring out columns
# used in implicit (non-selected) orders, and the order condition itself