From: Arthur Axel "fREW" Schmidt Date: Mon, 18 May 2009 16:16:44 +0000 (+0000) Subject: Fix order by clauses for MSSQL X-Git-Tag: v0.08103~74 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=fd4cb60a0c582000de4beef5ba7a519fd531e168;p=dbsrgits%2FDBIx-Class.git Fix order by clauses for MSSQL --- diff --git a/lib/DBIx/Class/SQLAHacks.pm b/lib/DBIx/Class/SQLAHacks.pm index 9fb3c24..4cbbcc6 100644 --- a/lib/DBIx/Class/SQLAHacks.pm +++ b/lib/DBIx/Class/SQLAHacks.pm @@ -256,9 +256,38 @@ sub _order_by { sub _order_directions { my ($self, $order) = @_; $order = $order->{order_by} if ref $order eq 'HASH'; + if (ref $order eq 'HASH') { + $order = [$self->_order_directions_hash($order)]; + } elsif (ref $order eq 'ARRAY') { + $order = [map { + if (ref $_ eq 'HASH') { + $self->_order_directions_hash($_); + } else { + $_; + } + } @{ $order }]; + } return $self->SUPER::_order_directions($order); } +sub _order_directions_hash { + my ($self, $order) = @_; + if (grep { $_ =~ /^-(desc|asc)/i } keys %{$order}) { + return map { + my $key = $_; + my @tmp; + s/^-(desc|asc)/\1/i; + my $dir = $_; + if (ref $order->{ $key } eq 'ARRAY') { + @tmp = map "$_ $dir", @{ $order->{ $key } }; + } else { # should be scalar + @tmp = ( "$order->{$key} $dir" ); + } + @tmp; + } keys %{$order}; + } +} + sub _table { my ($self, $from) = @_; if (ref $from eq 'ARRAY') { diff --git a/t/42toplimit.t b/t/42toplimit.t index 05c60cb..aefbc0c 100644 --- a/t/42toplimit.t +++ b/t/42toplimit.t @@ -5,24 +5,41 @@ use Test::More; use DBIx::Class::Storage::DBI; use lib qw(t/lib); use DBICTest; # do not remove even though it is not used +use DBIC::SqlMakerTest; -plan tests => 1; +plan tests => 8; my $sa = new DBIx::Class::SQLAHacks; - $sa->limit_dialect( 'Top' ); -is( - $sa->select( 'rubbish', [ 'foo.id', 'bar.id' ], undef, { order_by => 'artistid' }, 1, 3 ), - 'SELECT * FROM -( - SELECT TOP 1 * FROM - ( - SELECT TOP 4 foo.id, bar.id FROM rubbish ORDER BY artistid ASC - ) AS foo - ORDER BY artistid DESC -) AS bar -ORDER BY artistid ASC -', - "make sure limit_dialect( 'Top' ) is working okay" -); +sub test_order { + my $args = shift; + my $order_by = $args->{order_by}; + my $expected_sql_order = $args->{expected_sql_order}; + + my $query = $sa->select( 'foo', [qw{bar baz}], undef, { + order_by => $order_by, + }, 1, 3 + ); + is_same_sql( + $query, + "SELECT * FROM ( SELECT TOP 1 * FROM ( SELECT TOP 4 bar,baz FROM foo ORDER BY $expected_sql_order->[0] ) AS foo ORDER BY $expected_sql_order->[1] ) AS bar ORDER BY $expected_sql_order->[0]", + ); +} + + test_order({ order_by => \'foo DESC' , expected_sql_order => [ 'foo DESC', 'foo ASC' ] }); + test_order({ order_by => 'foo' , expected_sql_order => [ 'foo ASC', 'foo DESC'] }); + test_order({ order_by => [ qw{ foo bar} ], expected_sql_order => [ 'foo ASC,bar ASC', 'foo DESC, bar DESC']}); + test_order({ order_by => { -asc => 'foo' }, expected_sql_order => [ 'foo ASC', 'foo DESC' ] }); + test_order({ order_by => { -desc => 'foo' }, expected_sql_order => [ 'foo DESC', 'foo ASC' ] }); + + test_order({ order_by => ['foo', { -desc => 'bar' } ], expected_sql_order => [ 'foo ASC, bar DESC', 'foo DESC, bar ASC'] }); + test_order({ order_by => {-asc => [qw{ foo bar }] }, expected_sql_order => ['foo ASC, bar ASC', 'foo DESC, bar DESC' ] }); + test_order({ order_by => + [ + { -asc => 'foo' }, + { -desc => [qw{bar}] }, + { -asc => [qw{baz frew}]}, + ], + expected_sql_order => ['foo ASC, bar DESC, baz ASC, frew ASC', 'foo DESC, bar ASC, baz DESC, frew DESC'] + });