use List::Util 'first';
use Scalar::Util 'blessed';
use Sub::Name 'subname';
+use Data::Query::ExprHelpers;
use namespace::clean;
#
) {
# if none of the multipliers came from an order_by (guaranteed to have been combined
- # with a limit) - easy - just slap a group_by to simulate a collape and be on our way
+ # with a limit) - easy - just slap a group_by to simulate a collapse and be on our way
if (
! $inner_aliastypes->{ordering}
or
# exactly what we expect
# supplement the main selection with pks if not already there,
- # as they will have to be a part of the group_by to colapse
+ # as they will have to be a part of the group_by to collapse
# things properly
my $cur_sel = { map { $_ => 1 } @$inner_select };
# scan the *remaining* from spec against different attributes, and see which joins are needed
# in what role
- my $outer_aliastypes =
+ my $outer_aliastypes = $outer_attrs->{_aliastypes} =
$self->_resolve_aliastypes_from_select_args( $from, $outer_select, $where, $outer_attrs );
# unroll parents
# Unfortunately not much can be done until SQLA2 introspection arrives, and even
# then if where conditions apply to the *right* side of the prefetch, you may have
# to both filter the inner select (e.g. to apply a limit) and then have to re-filter
- # the outer select to exclude joins you didin't want in the first place
+ # the outer select to exclude joins you didn't want in the first place
#
# OTOH it can be seen as a plus: <ash> (notes that this query would make a DBA cry ;)
return (\@outer_from, $outer_select, $where, $outer_attrs);
#
# Due to a lack of SQLA2 we fall back to crude scans of all the
# select/where/order/group attributes, in order to determine what
-# aliases are neded to fulfill the query. This information is used
+# aliases are needed to fulfill the query. This information is used
# throughout the code to prune unnecessary JOINs from the queries
# in an attempt to reduce the execution time.
# Although the method is pretty horrific, the worst thing that can
# generate sql chunks
my $to_scan = {
restricting => [
- $sql_maker->_recurse_where ($where),
- $sql_maker->_parse_rs_attrs ({ having => $attrs->{having} }),
+ ($where
+ ? ($sql_maker->_recurse_where($where))[0]
+ : ()
+ ),
+ ($attrs->{having}
+ ? ($sql_maker->_recurse_where($attrs->{having}))[0]
+ : ()
+ ),
],
grouping => [
- $sql_maker->_parse_rs_attrs ({ group_by => $attrs->{group_by} }),
+ ($attrs->{group_by}
+ ? ($sql_maker->_render_sqla(group_by => $attrs->{group_by}))[0]
+ : (),
+ )
],
joining => [
$sql_maker->_recurse_from (
),
],
selecting => [
- $sql_maker->_recurse_fields ($select),
+ scalar $sql_maker->_render_sqla(select_select => $select),
],
ordering => [
map { $_->[0] } $self->_extract_order_criteria ($attrs->{order_by}, $sql_maker),
],
};
+ # local is not enough - need to ensure the inner objects get rebuilt
+ # with the original quoting setup (or lack thereof)
+ $sql_maker->clear_renderer;
+ $sql_maker->clear_converter;
+
# throw away empty chunks
$_ = [ map { $_ || () } @$_ ] for values %$to_scan;
sub _extract_order_criteria {
my ($self, $order_by, $sql_maker) = @_;
+ $sql_maker ||= $self->sql_maker;
+
+ my $order_dq = $sql_maker->converter->_order_by_to_dq($order_by);
+
+ my @by;
+ while (is_Literal($order_dq)) {
+ push @by, $order_dq->{by};
+ $order_dq = $order_dq->{from};
+ }
+
+ return map { [ $sql_maker->_render_dq($_) ] } @by;
+
my $parser = sub {
my ($sql_maker, $order_by, $orig_quote_chars) = @_;
die 'How did we get here...';
}
-# returns an arrayref of column names which *definitely* have som
+# returns an arrayref of column names which *definitely* have some
# sort of non-nullable equality requested in the given condition
# specification. This is used to figure out if a resultset is
# constrained to a column which is part of a unique constraint,