my $quote_left = qr/[\`\'\"\[]/;
my $quote_right = qr/[\`\'\"\]]/;
+my $placeholder_re = qr/(?: \? | \$\d+ )/x;
+
# These SQL keywords always signal end of the current expression (except inside
# of a parenthesized subexpression).
# Format: A list of strings that will be compiled to extended syntax ie.
)',
'ON',
'WHERE',
- 'VALUES',
+ '(?: DEFAULT \s+ )? VALUES',
'EXISTS',
'GROUP \s+ BY',
'HAVING',
$binary_op_re,
"$op_look_behind (?i: AND|OR|NOT ) $op_look_ahead",
(map { quotemeta $_ } qw/, ( ) */),
+ $placeholder_re,
);
$all_known_re = qr/$all_known_re/x;
my $expr_term_re = qr/ ^ (?: $expr_start_re | \) ) $/x;
my $rhs_term_re = qr/ ^ (?: $expr_term_re | $binary_op_re | (?i: AND | OR | NOT | \, ) ) $/x;
-my $func_start_re = qr/^ (?: \? | \$\d+ | \( ) $/x;
+my $func_start_re = qr/^ (?: \* | $placeholder_re | \( ) $/x;
my %indents = (
select => 0,
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 ) {
: [ $op => [$right] ];
}
+ elsif ( $token =~ $placeholder_re) {
+ $left = $left ? [ $left, [ PLACEHOLDER => [ $token ] ] ]
+ : [ PLACEHOLDER => [ $token ] ];
+ }
# we're now in "unknown token" land - start eating tokens until
# we see something familiar
else {
$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] ) }
return join (' ', map $self->_unparse($_, $bindargs, $depth), @$tree);
}
elsif ($car eq 'LITERAL') {
- if ($cdr->[0] eq '?') {
- return $self->fill_in_placeholder($bindargs)
- }
return $cdr->[0];
}
+ elsif ($car eq 'PLACEHOLDER') {
+ 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});