From: Ash Berlin Date: Wed, 7 Feb 2007 17:10:24 +0000 (+0000) Subject: Added { -desc => 'foo' } order by support X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=86298391f5ac09aaf36b30e2bb436cc8dc1a1735;p=scpubgit%2FQ-Branch.git Added { -desc => 'foo' } order by support --- diff --git a/Changes b/Changes index 9655aab..9c45927 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,7 @@ Revision history for SQL::Abstract + - Added { -desc => 'column' } order by support (Ash) + ---------------------------- revision 1.20 date: 2005/08/18 18:41:58; author: nwiger; state: Exp; lines: +104 -50 diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP new file mode 100644 index 0000000..fa93767 --- /dev/null +++ b/MANIFEST.SKIP @@ -0,0 +1,44 @@ +# Avoid version control files. +\bRCS\b +\bCVS\b +,v$ +\B\.svn\b + +# Avoid Makemaker generated and utility files. +\bMakefile$ +\bblib +\bMakeMaker-\d +\bpm_to_blib$ +\bblibdirs$ +^MANIFEST\.SKIP$ + +# for developers only :) +^TODO$ +^VERSIONING\.SKETCH$ + +# Avoid Module::Build generated and utility files. +\bBuild$ +\b_build + +# Avoid temp and backup files. +~$ +\.tmp$ +\.old$ +\.bak$ +\#$ +\b\.# + +# avoid OS X finder files +\.DS_Store$ + +# Don't ship the test db +^t/var + +# Don't ship the last dist we built :) +\.tar\.gz$ + +# Skip maint stuff +^maint/ + +# Avoid copies to .orig +\.orig$ diff --git a/lib/SQL/Abstract.pm b/lib/SQL/Abstract.pm index 13d5c3f..af8716a 100644 --- a/lib/SQL/Abstract.pm +++ b/lib/SQL/Abstract.pm @@ -1,4 +1,3 @@ - package SQL::Abstract; =head1 NAME @@ -555,7 +554,7 @@ sub insert { =head2 update($table, \%fieldvals, \%where) This takes a table, hashref of field/value pairs, and an optional -hashref WHERE clause. It returns an SQL UPDATE function and a list +hashref L. It returns an SQL UPDATE function and a list of bind values. =cut @@ -605,7 +604,7 @@ sub update { =head2 select($table, \@fields, \%where, \@order) This takes a table, arrayref of fields (or '*'), optional hashref -WHERE clause, and optional arrayref order by, and returns the +L, and optional array or hash ref L, and returns the corresponding SQL SELECT statement and list of bind values. =cut @@ -630,7 +629,7 @@ sub select { =head2 delete($table, \%where) -This takes a table name and optional hashref WHERE clause. +This takes a table name and optional hashref L. It returns an SQL DELETE statement and list of bind values. =cut @@ -848,14 +847,43 @@ sub _recurse_where { sub _order_by { my $self = shift; - my $ref = ref $_[0]; - - my @vals = $ref eq 'ARRAY' ? @{$_[0]} : - $ref eq 'SCALAR' ? $_[0] : - $ref eq '' ? $_[0] : - puke "Unsupported data struct $ref for ORDER BY"; + my $ref = ref $_[0] || ''; + + my $_order_hash = sub { + local *__ANON__ = '_order_by_hash'; + my ($col, $order); + if ( $col = $_->{-desc} ) { + $order = 'DESC' + } elsif ( $col = $_->{-asc} ) { + $order = 'ASC'; + } else { + puke "Hash must have a key of '-desc' or '-asc' for ORDER BY"; + } + return $self->_quote($col) . " $order"; + + }; + + my @vals; + if ($ref eq 'ARRAY') { + foreach (@{ $_[0] }) { + my $ref = ref $_; + if (!$ref || $ref eq 'SCALAR') { + push @vals, $self->_quote($_); + } elsif ($ref eq 'HASH') { + push @vals, $_order_hash->($_); + } else { + puke "Unsupported nested data struct $ref for ORDER BY"; + } + } + } elsif ($ref eq 'HASH') { + push @vals, $_order_hash->($_[0]); + } elsif (!$ref || $ref eq 'SCALAR') { + push @vals, $self->_quote($_[0]); + } else { + puke "Unsupported data struct $ref for ORDER BY"; + } - my $val = join ', ', map { $self->_quote($_) } @vals; + my $val = join ', ', @vals; return $val ? $self->_sqlcase(' order by')." $val" : ''; } @@ -1120,7 +1148,7 @@ In addition to C<-and> and C<-or>, there is also a special C<-nest> operator which adds an additional set of parens, to create a subquery. For example, to get something like this: - $stmt = WHERE user = ? AND ( workhrs > ? OR geo = ? ) + $stmt = "WHERE user = ? AND ( workhrs > ? OR geo = ? )"; @bind = ('nwiger', '20', 'ASIA'); You would do: @@ -1237,6 +1265,12 @@ knew everything ahead of time, you wouldn't have to worry about dynamically-generating SQL and could just hardwire it into your script. +=head1 ORDER BY CLAUSES + +Some functions take an order by clause. This can either be a scalar (just a +column name,) a hash of C<< { -desc => 'col' } >> or C<< { -asc => 'col' } >>, +or an array of either of the two previous forms. + =head1 PERFORMANCE Thanks to some benchmarking by Mark Stosberg, it turns out that @@ -1318,6 +1352,7 @@ There are a number of individuals that have really helped out with this module. Unfortunately, most of them submitted bugs via CPAN so I have no idea who they are! But the people I do know are: + Ash Berlin (order_by hash term support) Matt Trout (DBIx::Class support) Mark Stosberg (benchmarking) Chas Owens (initial "IN" operator support) @@ -1331,7 +1366,7 @@ Thanks! =head1 SEE ALSO -L, L, L, L +L, L, L, L. =head1 AUTHOR diff --git a/t/04from.t b/t/04from.t index 5e702b5..2803389 100644 --- a/t/04from.t +++ b/t/04from.t @@ -9,12 +9,6 @@ plan tests => 4; use SQL::Abstract; -sub is { - my ($got, $expect, $msg) = @_; - ok($got eq $expect) or - warn "got [${got}]\ninstead of [${expect}]\nfor test ${msg}\n\n"; -} - my $sa = new SQL::Abstract; my @j = ( diff --git a/t/05quotes.t b/t/05quotes.t index af40887..361038f 100644 --- a/t/05quotes.t +++ b/t/05quotes.t @@ -49,35 +49,33 @@ is($sql, q/SELECT COUNT( * ) FROM `cd` `me` JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )/, 'got correct SQL for count query with quoting'); + ($sql,) = $sql_maker->select( - [ - { - 'me' => 'cd' - } - ], - [ - 'me.cdid', - 'me.artist', - 'me.title', - 'me.year' - ], - undef, - [ - 'year DESC' - ], - undef, - undef + [ + { + 'me' => 'cd' + } + ], + [ + 'me.cdid', + 'me.artist', + 'me.title', + 'me.year' + ], + undef, + [ + { -desc => 'year' } + ], + undef, + undef ); -TODO: { - local $TODO = "order_by with quoting needs fixing (ash/castaway)"; - is($sql, - q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY `year` DESC/, - 'quoted ORDER BY with DESC okay'); -} +is($sql, + q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY `year` DESC/, + 'quoted ORDER BY with DESC okay'); ($sql,) = $sql_maker->select(