From: Matt S Trout Date: Fri, 17 Aug 2012 14:32:23 +0000 (+0100) Subject: first cut at GenericSubquery X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=01d7143b9a6bfa8e70c6cb2b1caea5cba0465286;p=dbsrgits%2FData-Query.git first cut at GenericSubquery --- diff --git a/lib/Data/Query/Renderer/SQL/Slice/GenericSubquery.pm b/lib/Data/Query/Renderer/SQL/Slice/GenericSubquery.pm new file mode 100644 index 0000000..c01c48c --- /dev/null +++ b/lib/Data/Query/Renderer/SQL/Slice/GenericSubquery.pm @@ -0,0 +1,67 @@ +package Data::Query::Renderer::SQL::Slice::GenericSubquery; + +use Data::Query::ExprHelpers; +use Moo::Role; + +with 'Data::Query::Renderer::SQL::Slice::SubqueryRemap'; + +sub _render_slice { + my ($self, $dq) = @_; + die "Slice's inner is not a Select" + unless is_Select my $orig_select = $dq->{from}; + my %remapped = $self->_subquery_remap($orig_select); + my $first_from = $remapped{inner_body}; + $first_from = $first_from->{from} if is_Where($first_from); + while (is_Join $first_from) { + $first_from = $first_from->{left}; + } + $first_from = $first_from->{from} if is_Alias($first_from); + my $first_order = $remapped{inside_order}[0]{by}; + my $count_col = $first_order->{elements}[-1]; + my $count_alias = 'rownum__emulation'; + my $count_sel = Select( + [ Operator({ 'SQL.Naive' => 'apply' }, [ Identifier('COUNT'), Identifier('*') ]) ], + Where( + Operator( + { 'SQL.Naive' => ($first_order->{reverse} ? '>' : '<') }, + [ Identifier($count_alias, $count_col), $first_order ] + ), + Alias($count_alias, $first_from) + ) + ); + my $count_where = Operator( + { 'SQL.Naive' => ($dq->{offset} ? 'BETWEEN' : '<') }, + [ $count_sel, ( + $dq->{offset} + ? ( + $dq->{offset}, + { + %{$dq->{limit}}, + value => $dq->{limit}{value}+$dq->{offset}{value}-1 + } + ) + : ($dq->{limit}) + ) + ] + ); + return $self->render( + Select( + $remapped{outside_select_list}, + (compose { no warnings 'once'; Order($b->{by}, $b->{reverse}, $a) } + @{$remapped{outside_order}}, + Where( + $count_where, + Alias( + $remapped{default_inside_alias}, + Select( + $remapped{inside_select_list}, + $remapped{inner_body}, + ) + ) + ) + ) + ) + ); +} + +1;