but subtle changes to query results in production
- Fix false negative comparison of ORDER BY <function> ASC
+ - More improvements of incorrect parsing (literal at end of list elt)
- Fix typos in POD and comments (RT#87776)
revision 1.74 2013-06-04
$_ = qr/ \A $_ \z /x;
}
-
+# what can be bunched together under one MISC in an AST
+my $compressable_node_re = qr/^ \- (?: MISC | LITERAL | PLACEHOLDER ) $/x;
my %indents = (
select => 0,
else {
my @lits = [ -LITERAL => [$token] ];
+ unshift @lits, pop @left if @left == 1;
+
unless ( $state == PARSE_RHS ) {
while (
@$tokens
! ( @$tokens > 1 and $tokens->[1] eq '(' )
) {
push @lits, [ -LITERAL => [ shift @$tokens ] ];
- }
+ }
}
- if (@left == 1) {
- unshift @lits, pop @left;
- }
-
@lits = [ -MISC => [ @lits ] ] if @lits > 1;
push @left, @lits;
}
- if (@$tokens) {
+ # compress -LITERAL -MISC and -PLACEHOLDER pieces into a single
+ # -MISC container
+ if (@left > 1) {
+ my $i = 0;
+ while ($#left > $i) {
+ if ($left[$i][0] =~ $compressable_node_re and $left[$i+1][0] =~ $compressable_node_re) {
+ splice @left, $i, 2, [ -MISC => [
+ map { $_->[0] eq '-MISC' ? @{$_->[1]} : $_ } (@left[$i, $i+1])
+ ]];
+ }
+ else {
+ $i++;
+ }
+ }
+ }
+
+ return @left if $state == PARSE_RHS;
- # deal with post-fix operators (asc/desc)
+ # deal with post-fix operators
+ if (@$tokens) {
+ # asc/desc
if ($tokens->[0] =~ $asc_desc_re) {
- return @left if $state == PARSE_RHS;
@left = [ ('-' . uc (shift @$tokens)) => [ @left ] ];
}
-
- return @left if $state == PARSE_RHS and $left[-1][0] eq '-LITERAL';
}
}
}
],
},
{
+ equal => 1,
+ statements => [
+ q/ORDER BY name + ?, [me].[id]/,
+ q/ORDER BY name + ? ASC, [me].[id]/,
+ ],
+ },
+ {
equal => 0,
opts => { order_by_asc_significant => 1 },
statements => [
eq_sql_bind eq_sql eq_bind is_same_sql_bind
)]);
-for my $test (@sql_tests) {
+for my $test ( @sql_tests ) {
# this does not work on 5.8.8 and earlier :(
#local @{*SQL::Abstract::Test::}{keys %{$test->{opts}}} = map { \$_ } values %{$test->{opts}}
[
"+"
]
+ ],
+ [
+ "-PLACEHOLDER",
+ [
+ "?"
+ ]
]
]
],
- [
- "-PLACEHOLDER",
- [
- "?"
- ]
- ]
]
],
[
[
"-"
]
- ]
+ ],
+ [
+ "-PLACEHOLDER",
+ [
+ "?"
+ ]
+ ],
]
],
- [
- "-PLACEHOLDER",
- [
- "?"
- ]
- ]
]
],
[
[
"/"
]
- ]
+ ],
+ [
+ "-PLACEHOLDER",
+ [
+ "?"
+ ]
+ ],
]
],
- [
- "-PLACEHOLDER",
- [
- "?"
- ]
- ]
]
],
[
]
],
[
- "=",
+ "-MISC",
[
[
- "-LITERAL",
- [
- "foo.a"
- ]
- ],
- [
- "-MISC",
+ "=",
[
[
- "-PLACEHOLDER",
+ "-LITERAL",
[
- "?"
+ "foo.a"
]
],
[
- "-LITERAL",
+ "-PLACEHOLDER",
[
- "STUFF"
+ "?"
]
- ]
+ ],
],
],
[
- 'moar',
+ "-LITERAL",
+ [
+ "STUFF"
+ ]
+ ],
+ ],
+ ],
+ [
+ 'moar',
+ [
+ [
+ '-PAREN',
[
[
- '-PAREN',
+ '-LITERAL',
[
- [
- '-LITERAL',
- [
- 'stuff'
- ]
- ]
+ 'stuff'
]
- ]
+ ]
]
]
]
use Test::More;
use Test::Exception;
+use Data::Dumper;
+$Data::Dumper::Terse = 1;
+$Data::Dumper::Sortkeys = 1;
+
use SQL::Abstract::Test import => ['is_same_sql'];
use SQL::Abstract::Tree;
"SELECT foo AS bar FROM baz ORDER BY x + ? DESC, oomph, y - ? DESC, unf, baz.g / ? ASC, buzz * 0 DESC, foo DESC, ickk ASC",
"SELECT inner_forum_roles.forum_id FROM forum_roles AS inner_forum_roles LEFT JOIN user_roles AS inner_user_roles USING(user_role_type_id) WHERE inner_user_roles.user_id = users__row.user_id",
"SELECT * FROM foo WHERE foo.a @@ to_tsquery('word')",
+ "SELECT * FROM foo ORDER BY name + ?, [me].[id]",
);
# FIXME FIXME FIXME
$_ =~ s/\s*([\(\)])\s*/$1 /g
for ($orig, $reassembled);
- is (lc($reassembled), lc($orig), sprintf 'roundtrip works (%s...)', substr $orig, 0, 20);
+ is (
+ lc($reassembled),
+ lc($orig),
+ sprintf( 'roundtrip works (%s...)', substr $orig, 0, 20 )
+ ) or do {
+ my ($ast1, $ast2) = map { Dumper $sqlat->parse($_) } ( $orig, $reassembled );
+
+ note "ast1: $ast1";
+ note "ast2: $ast2";
+ };
}
lives_ok { $sqlat->unparse( $sqlat->parse( <<'EOS' ) ) } 'Able to parse/unparse grossly malformed sql';