From: Dagfinn Ilmari Mannsåker Date: Sat, 26 Jan 2013 19:16:39 +0000 (+0000) Subject: Add support for NULLS FIRST/LAST in ORDER BY X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=e3335558366cad6a9cc6a6da3a7fe2c40e26639a;p=dbsrgits%2FData-Query.git Add support for NULLS FIRST/LAST in ORDER BY --- diff --git a/lib/Data/Query/ExprDeclare.pm b/lib/Data/Query/ExprDeclare.pm index 8cb1fbc..ad8e360 100644 --- a/lib/Data/Query/ExprDeclare.pm +++ b/lib/Data/Query/ExprDeclare.pm @@ -9,7 +9,7 @@ use Safe::Isa; use base qw(Exporter); our @EXPORT = qw( - expr SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP DESC LIMIT OFFSET + expr SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP DESC LIMIT OFFSET NULLS FIRST LAST ); sub expr (&) { @@ -84,7 +84,7 @@ sub FROM (&;@) { } while (is_Order($_[0])) { my $order = shift; - $from_dq = Order($order->{by}, $order->{reverse}, $from_dq); + $from_dq = Order($order->{by}, $order->{reverse}, $order->{nulls}, $from_dq); } return ($from_dq, @_); } @@ -119,6 +119,9 @@ sub WHERE (&;@) { } sub DESC { bless({}, 'LIES::DESC'), @_ } +sub NULLS { bless(\shift, 'LIES::NULLS'), @_ } +sub FIRST { 1, @_ } +sub LAST { -1, @_ } sub ORDER { my @order = map _value($_), _run_expr(shift); @@ -129,7 +132,9 @@ sub ORDER { 0; } }; - return ((compose { Order($b, $reverse, $a) } @order, undef), @_); + my $nulls = $_[0]->$_isa('LIES::NULLS') ? ${+shift} : undef; + + return ((compose { Order($b, $reverse, $nulls, $a) } @order, undef), @_); } sub LIMIT (&;@) { diff --git a/lib/Data/Query/ExprHelpers.pm b/lib/Data/Query/ExprHelpers.pm index 6020be6..be56f2f 100644 --- a/lib/Data/Query/ExprHelpers.pm +++ b/lib/Data/Query/ExprHelpers.pm @@ -31,7 +31,7 @@ my %map = ( Operator => [ qw(operator args) ], Select => [ qw(select from) ], Where => [ qw(where from) ], - Order => [ qw(by reverse from) ], + Order => [ qw(by reverse nulls from) ], Group => [ qw(by from) ], Delete => [ qw(where target) ], Update => [ qw(set where target) ], diff --git a/lib/Data/Query/Renderer/SQL/Naive.pm b/lib/Data/Query/Renderer/SQL/Naive.pm index 19c2288..aac3c73 100644 --- a/lib/Data/Query/Renderer/SQL/Naive.pm +++ b/lib/Data/Query/Renderer/SQL/Naive.pm @@ -371,14 +371,24 @@ sub _render_where { ] } -sub _render_order { +sub _order_chunk { my ($self, $dq) = @_; - my @ret = ( - $self->_format_keyword('ORDER BY'), + return +( $self->_render($dq->{by}), ($dq->{reverse} ? $self->_format_keyword('DESC') - : ()) + : ()), + ($dq->{nulls} + ? $self->_format_keyword('NULLS '.('', qw(FIRST LAST))[$dq->{nulls}]) + : ()), + ); +} + +sub _render_order { + my ($self, $dq) = @_; + my @ret = ( + $self->_format_keyword('ORDER BY'), + $self->_order_chunk($dq), ); my $from; while ($from = $dq->{from}) { @@ -386,10 +396,7 @@ sub _render_order { $dq = $from; push @ret, ( ',', - $self->_render($dq->{by}), - ($dq->{reverse} - ? $self->_format_keyword('DESC') - : ()) + $self->_order_chunk($dq), ); } unshift @ret, $self->_render($from) if $from; diff --git a/lib/Data/Query/Renderer/SQL/Slice/FetchFirst.pm b/lib/Data/Query/Renderer/SQL/Slice/FetchFirst.pm index 466258b..0bb96e0 100644 --- a/lib/Data/Query/Renderer/SQL/Slice/FetchFirst.pm +++ b/lib/Data/Query/Renderer/SQL/Slice/FetchFirst.pm @@ -53,7 +53,7 @@ sub _render_slice { ? Select( \@outside_select_list, compose { - Order($b->{by}, $b->{reverse}, $a) + Order($b->{by}, $b->{reverse}, $b->{nulls}, $a) } ( @outside_order, Alias($default_inside_alias, $_) @@ -72,7 +72,7 @@ sub _render_slice { : (), ], compose { - Order($b->{by}, !$b->{reverse}, $a) + Order($b->{by}, !$b->{reverse}, -$b->{nulls}, $a) } ( @outside_order, Alias( @@ -82,7 +82,7 @@ sub _render_slice { Select( \@inside_select_list, compose { - Order($b->{by}, $b->{reverse}, $a) + Order($b->{by}, $b->{reverse}, $b->{nulls}, $a) } @inside_order, $inner_body ) ) diff --git a/lib/Data/Query/Renderer/SQL/Slice/GenericSubquery.pm b/lib/Data/Query/Renderer/SQL/Slice/GenericSubquery.pm index 67b7b93..c10a890 100644 --- a/lib/Data/Query/Renderer/SQL/Slice/GenericSubquery.pm +++ b/lib/Data/Query/Renderer/SQL/Slice/GenericSubquery.pm @@ -56,7 +56,7 @@ sub _render_slice { return $self->render( Select( $remapped{outside_select_list}, - (compose { no warnings 'once'; Order($b->{by}, $b->{reverse}, $a) } + (compose { no warnings 'once'; Order($b->{by}, $b->{reverse}, $b->{nulls}, $a) } @{$remapped{outside_order}}, Where( $count_where, diff --git a/lib/Data/Query/Renderer/SQL/Slice/RowNumberOver.pm b/lib/Data/Query/Renderer/SQL/Slice/RowNumberOver.pm index 47b65bc..4f27fc6 100644 --- a/lib/Data/Query/Renderer/SQL/Slice/RowNumberOver.pm +++ b/lib/Data/Query/Renderer/SQL/Slice/RowNumberOver.pm @@ -24,7 +24,7 @@ sub _render_slice { my $rno_name = 'rno__row__index'; - my $order = compose { Order($b->{by}, $b->{reverse}, $a) } + my $order = compose { Order($b->{by}, $b->{reverse}, $b->{nulls}, $a) } @outside_order, undef; my $rno_node = Alias($rno_name, $self->_rno_literal($order)); diff --git a/t/example.t b/t/example.t index 4458a8b..9a8a6ff 100644 --- a/t/example.t +++ b/t/example.t @@ -51,7 +51,7 @@ DwarnL to_sql( ); DwarnL to_sql( - SELECT { $_->cd->name } FROM { $_->cds, AS 'cd' } ORDER BY { $_->year } + SELECT { $_->cd->name } FROM { $_->cds, AS 'cd' } ORDER BY { $_->year } DESC NULLS LAST ); my $lo =