Author: jzucker
Date: Thu Mar  4 18:53:06 2004
New Revision: 186

Modified:
   dbi/trunk/lib/DBI/SQL/Nano.pm
Log:
Nano now supports ORDER BY. Locking is next, then the book, I swear, the book is next 
:-)

Modified: dbi/trunk/lib/DBI/SQL/Nano.pm
==============================================================================
--- dbi/trunk/lib/DBI/SQL/Nano.pm       (original)
+++ dbi/trunk/lib/DBI/SQL/Nano.pm       Thu Mar  4 18:53:06 2004
@@ -72,7 +72,14 @@
                 $self->{column_names} = parse_comma_list($1) if $1;
                 die "Can't find columns!\n" unless $self->{column_names};
                 $self->{table_name}   = $2;
-                $self->{where_clause} = $self->parse_where_clause($4) if $4;
+                if ( my $clauses = $4) {
+                   if ($clauses =~ /^(.*)\s+ORDER\s+BY\s+(.*)$/is) {
+                        $clauses = $1;
+                        $self->{order_clause} = $self->parse_order_clause($2);
+                   }
+                    $self->{where_clause}=$self->parse_where_clause($clauses)
+                        if $clauses;
+               }
             };
         /^\s*INSERT\s+INTO\s+(\S+)\s*(\((.*?)\))?\s*VALUES\s*\((.+)\)/is
             &&do{
@@ -100,6 +107,16 @@
                                        and $self->{table_name};
     return $self;
 }
+sub parse_order_clause {
+    my($self,$str) = @_;
+    my @clause = split /\s+/,$str;
+    return { $clause[0] => 'ASC' } if @clause == 1;
+    die "Bad ORDER BY clause '$str'!\n" if @clause > 2;
+    $clause[1] ||= '';
+    return { $clause[0] => uc $clause[1] } if $clause[1] =~ /^ASC$/i
+                                           or $clause[1] =~ /^DESC$/i;
+    die "Bad ORDER BY clause '$clause[1]'!\n";
+}
 sub parse_coldef_list  {                # check column definitions
     my @col_defs;
     for ( split',',shift ) {
@@ -290,6 +307,41 @@
                if $self->{fetched_from_key};
         }
     }
+    if ( $self->{order_clause} ) {
+        my( $sort_col, $desc ) = each %{$self->{order_clause}};
+        undef $desc unless $desc eq 'DESC';
+        my @sortCols = ( $self->column_nums($table,$sort_col) );
+        my($c, $d, $colNum);
+        my $sortFunc = sub {
+            my $result;
+            $i = 0;
+            do {
+                $colNum = $sortCols[$i++];
+                # $desc = $sortCols[$i++];
+                $c = $a->[$colNum];
+                $d = $b->[$colNum];
+                if (!defined($c)) {
+                    $result = defined $d ? -1 : 0;
+                } elsif (!defined($d)) {
+                    $result = 1;
+               } elsif ( DBI::looks_like_number($c,$d) ) {
+                    $result = ($c <=> $d);
+                } else {
+                   if ($self->{"case_fold"}) {
+                        $result = lc $c cmp lc $d || $c cmp $d;
+                   }
+                    else {
+                        $result = $c cmp $d;
+                   }
+                }
+                if ($desc) {
+                    $result = -$result;
+                }
+            } while (!$result  &&  $i < @sortCols);
+            $result;
+        };
+        @rows = (sort $sortFunc @rows);
+    }
     (scalar(@rows), scalar @{$self->{column_names}}, [EMAIL PROTECTED]);
 }
 sub UPDATE ($$$) {
@@ -544,6 +596,7 @@
     | DELETE FROM <table_name> [<where_clause>]
     | UPDATE <table_name> SET <set_clause> <where_clause>
     | SELECT <select_col_list> FROM <table_name> [<where_clause>]
+                                                 [<order_clause>]
 
   the optional IF EXISTS clause ::=
     * similar to MySQL - prevents errors when trying to drop
@@ -604,6 +657,11 @@
          < > >= <= = <> LIKE CLIKE IS
     * CLIKE is a case insensitive LIKE
 
+  order_clause ::= column_name [ASC|DESC]
+    * a single column optional ORDER BY clause is supported
+    * as in standard SQL, if neither ASC (ascending) nor
+      DESC (descending) is specified, ASC becomes the default
+
 =head1 ACKNOWLEDGEMENTS
 
 Tim Bunce provided the original idea for this module, helped me out of the tangled 
trap of namespace, and provided help and advice all along the way.  Although I wrote 
it from the ground up, it is based on Jochen Weidmann's orignal design of 
SQL::Statement, so much of the credit for the API goes to him.

Reply via email to