X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FAbstract%2FTree.pm;h=f6076ba3881988c6f4ae957097bd23966c76f4dd;hb=1c33db5d0ccacdfc4d6028ec596b0f34a045471c;hp=fd9f665652df6717cc7ba70fadf40426034b51e5;hpb=4e914a7c1dd88467a0d287073c9a9db477725394;p=dbsrgits%2FSQL-Abstract.git diff --git a/lib/SQL/Abstract/Tree.pm b/lib/SQL/Abstract/Tree.pm index fd9f665..f6076ba 100644 --- a/lib/SQL/Abstract/Tree.pm +++ b/lib/SQL/Abstract/Tree.pm @@ -63,17 +63,25 @@ my @expression_start_keywords = ( )', 'ON', 'WHERE', - 'VALUES', + '(?: DEFAULT \s+ )? VALUES', 'EXISTS', 'GROUP \s+ BY', 'HAVING', 'ORDER \s+ BY', + 'SKIP', + 'FIRST', 'LIMIT', 'OFFSET', 'FOR', 'UNION', 'INTERSECT', 'EXCEPT', + 'BEGIN \s+ WORK', + 'COMMIT', + 'ROLLBACK \s+ TO \s+ SAVEPOINT', + 'ROLLBACK', + 'SAVEPOINT', + 'RELEASE \s+ SAVEPOINT', 'RETURNING', 'ROW_NUMBER \s* \( \s* \) \s+ OVER', ); @@ -146,11 +154,16 @@ my %indents = ( join => 1, 'left join' => 1, on => 2, + having => 0, 'group by' => 0, 'order by' => 0, set => 1, into => 1, values => 1, + limit => 1, + offset => 1, + skip => 1, + first => 1, ); my %profiles = ( @@ -161,31 +174,52 @@ my %profiles = ( indent_amount => 2, newline => "\n", colormap => {}, - indentmap => { %indents }, + indentmap => \%indents, eval { require Term::ANSIColor } ? do { my $c = \&Term::ANSIColor::color; + + my $red = [$c->('red') , $c->('reset')]; + my $cyan = [$c->('cyan') , $c->('reset')]; + my $green = [$c->('green') , $c->('reset')]; + my $yellow = [$c->('yellow') , $c->('reset')]; + my $blue = [$c->('blue') , $c->('reset')]; + my $magenta = [$c->('magenta'), $c->('reset')]; + my $b_o_w = [$c->('black on_white'), $c->('reset')]; ( - placeholder_surround => [$c->('black on_cyan'), $c->('reset')], + placeholder_surround => [q(') . $c->('black on_magenta'), $c->('reset') . q(')], colormap => { - select => [$c->('red'), $c->('reset')], - 'insert into' => [$c->('red'), $c->('reset')], - update => [$c->('red'), $c->('reset')], - 'delete from' => [$c->('red'), $c->('reset')], - - set => [$c->('cyan'), $c->('reset')], - from => [$c->('cyan'), $c->('reset')], - - where => [$c->('green'), $c->('reset')], - values => [$c->('yellow'), $c->('reset')], - - join => [$c->('magenta'), $c->('reset')], - 'left join' => [$c->('magenta'), $c->('reset')], - on => [$c->('blue'), $c->('reset')], - - 'group by' => [$c->('yellow'), $c->('reset')], - 'order by' => [$c->('yellow'), $c->('reset')], + 'begin work' => $b_o_w, + commit => $b_o_w, + rollback => $b_o_w, + savepoint => $b_o_w, + 'rollback to savepoint' => $b_o_w, + 'release savepoint' => $b_o_w, + + select => $red, + 'insert into' => $red, + update => $red, + 'delete from' => $red, + + set => $cyan, + from => $cyan, + + where => $green, + values => $yellow, + + join => $magenta, + 'left join' => $magenta, + on => $blue, + + 'group by' => $yellow, + having => $yellow, + 'order by' => $yellow, + + skip => $green, + first => $green, + limit => $green, + offset => $green, } ); } : (), @@ -197,7 +231,7 @@ my %profiles = ( indent_amount => 2, newline => "\n", colormap => {}, - indentmap => { %indents }, + indentmap => \%indents, }, html => { fill_in_placeholders => 1, @@ -210,17 +244,34 @@ my %profiles = ( 'insert into' => ['' , ''], update => ['' , ''], 'delete from' => ['' , ''], - where => ['' , ''], + + set => ['', ''], from => ['' , ''], + + where => ['' , ''], + values => ['', ''], + join => ['' , ''], + 'left join' => ['',''], on => ['' , ''], + 'group by' => ['', ''], + having => ['', ''], 'order by' => ['', ''], - set => ['', ''], - into => ['', ''], - values => ['', ''], + + skip => ['', ''], + first => ['', ''], + limit => ['', ''], + offset => ['', ''], + + 'begin work' => ['', ''], + commit => ['', ''], + rollback => ['', ''], + savepoint => ['', ''], + 'rollback to savepoint' => ['', ''], + 'release savepoint' => ['', ''], }, - indentmap => { %indents }, + indentmap => \%indents, }, none => { colormap => {}, @@ -233,6 +284,9 @@ sub new { my $args = shift || {}; my $profile = delete $args->{profile} || 'none'; + + die "No such profile '$profile'!" unless exists $profiles{$profile}; + my $data = $merger->merge( $profiles{$profile}, $args ); bless $data, $class @@ -248,7 +302,7 @@ sub parse { defined $token and length $token - and + and $token =~ /\S/ ); } @@ -318,8 +372,8 @@ sub _recurse_parse { elsif ( $token =~ / ^ $expr_start_re $ /x ) { my $op = uc $token; my $right = $self->_recurse_parse($tokens, PARSE_IN_EXPR); - $left = $left ? [ $left, [$op => [$right] ]] - : [ $op => [$right] ]; + $left = $left ? [ $left, [$op => [$right||()] ]] + : [ $op => [$right||()] ]; } # NOT elsif ( $token =~ /^ NOT $/ix ) { @@ -377,7 +431,7 @@ sub pad_keyword { $before = $self->newline . $self->indent($depth + $self->indentmap->{lc $keyword}); } $before = '' if $depth == 0 and defined $starters{lc $keyword}; - return [$before, ' ']; + return [$before, '']; } sub indent { ($_[0]->indent_string||'') x ( ( $_[0]->indent_amount || 0 ) * $_[1] ) } @@ -434,10 +488,14 @@ sub _unparse { return $self->fill_in_placeholder($bindargs); } elsif ($car eq 'PAREN') { - return '(' . - join(' ', - map $self->_unparse($_, $bindargs, $depth + 2), @{$cdr}) . - ($self->_is_key($cdr)?( $self->newline||'' ).$self->indent($depth + 1):'') . ') '; + return sprintf ('(%s)', + join (' ', map { $self->_unparse($_, $bindargs, $depth + 2) } @{$cdr} ) + . + ($self->_is_key($cdr) + ? ( $self->newline||'' ) . $self->indent($depth + 1) + : '' + ) + ); } elsif ($car eq 'AND' or $car eq 'OR' or $car =~ / ^ $binary_op_re $ /x ) { return join (" $car ", map $self->_unparse($_, $bindargs, $depth), @{$cdr});