do not indent for the first select
[dbsrgits/SQL-Abstract.git] / lib / SQL / Abstract / Tree.pm
index 46c0b42..f967dc9 100644 (file)
@@ -183,26 +183,66 @@ sub format_keyword {
   return $keyword
 }
 
+
+my %ghetto_whitespacemap = (
+  select => 0,
+  where  => 1,
+  from   => 1,
+);
+
+sub whitespace {
+   my ($self, $keyword, $depth) = @_;
+
+   my $before = '';
+   my $after  = '';
+   if (defined $ghetto_whitespacemap{lc $keyword}) {
+      $before = $self->newline . $self->indent($depth + $ghetto_whitespacemap{lc $keyword});
+   }
+   $before = '' if $depth == 0 and lc $keyword eq 'select';
+   return [$before, $after];
+}
+
+sub newline { "\n" }
+
+sub indent { '   ' x $_[1] }
+
+sub _is_select {
+   my $tree = shift;
+   $tree = $tree->[0] while ref $tree;
+
+   lc $tree eq 'select';
+}
+
 sub unparse {
-  my ($self, $tree) = @_;
+  my ($self, $tree, $depth) = @_;
+
+  $depth ||= 0;
 
   if (not $tree ) {
     return '';
   }
-  elsif (ref $tree->[0]) {
-    return join (" ", map $self->unparse ($_), @$tree);
+
+  my $car = $tree->[0];
+  my $cdr = $tree->[1];
+
+  if (ref $car) {
+    return join ('', map $self->unparse($_, $depth), @$tree);
   }
-  elsif ($tree->[0] eq 'LITERAL') {
-    return $tree->[1][0];
+  elsif ($car eq 'LITERAL') {
+    return $cdr->[0];
   }
-  elsif ($tree->[0] eq 'PAREN') {
-    return sprintf '(%s)', join (" ", map $self->unparse($_), @{$tree->[1]});
+  elsif ($car eq 'PAREN') {
+    return '(' .
+      join(' ',
+        map $self->unparse($_, $depth + 2), @{$cdr}) .
+    (_is_select($cdr)?$self->newline.$self->indent($depth + 1):'') . ')';
   }
-  elsif ($tree->[0] eq 'OR' or $tree->[0] eq 'AND' or (grep { $tree->[0] =~ /^ $_ $/xi } @binary_op_keywords ) ) {
-    return join (" $tree->[0] ", map $self->unparse($_), @{$tree->[1]});
+  elsif ($car eq 'OR' or $car eq 'AND' or (grep { $car =~ /^ $_ $/xi } @binary_op_keywords ) ) {
+    return join (" $car ", map $self->unparse($_, $depth), @{$cdr});
   }
   else {
-    return sprintf '%s %s', $self->format_keyword($tree->[0]), $self->unparse ($tree->[1]);
+    my ($l, $r) = @{$self->whitespace($car, $depth)};
+    return sprintf "$l%s %s$r", $self->format_keyword($car), $self->unparse($cdr, $depth);
   }
 }