use Test::More;
+use Data::Dumper;
+$Data::Dumper::Terse = 1;
+$Data::Dumper::Sortkeys = 1;
+
+# equivalent to $Module::Install::AUTHOR
+my $author = (
+ ( not -d './inc' )
+ or
+ ( -e ($^O eq 'VMS' ? './inc/_author' : './inc/.author') )
+);
+
+if (not $author and not $ENV{SQLATEST_TESTER} and not $ENV{AUTOMATED_TESTING}) {
+ plan skip_all => 'Skipping resource intensive self-tests, use SQLATEST_TESTER=1 to run';
+}
+
my @sql_tests = (
- # WHERE condition - equal
+ # WHERE condition - equal
{
equal => 1,
statements => [
/,
]
},
+ {
+ equal => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE a = 1 AND b = 1 AND c = 1/,
+ q/SELECT foo FROM bar WHERE (a = 1 AND b = 1 AND c = 1)/,
+ q/SELECT foo FROM bar WHERE (a = 1 AND b = 1) AND c = 1/,
+ q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 AND c = 1)/,
+ q/SELECT foo FROM bar WHERE ((((a = 1))) AND (b = 1 AND c = 1))/,
+ ]
+ },
+ {
+ equal => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE a = 1 OR b = 1 OR c = 1/,
+ q/SELECT foo FROM bar WHERE (a = 1 OR b = 1) OR c = 1/,
+ q/SELECT foo FROM bar WHERE a = 1 OR (b = 1 OR c = 1)/,
+ q/SELECT foo FROM bar WHERE a = 1 OR ((b = 1 OR (c = 1)))/,
+ ]
+ },
+ {
+ equal => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE (a = 1) AND (b = 1 OR c = 1 OR d = 1) AND (e = 1 AND f = 1)/,
+ q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 OR c = 1 OR d = 1) AND e = 1 AND (f = 1)/,
+ q/SELECT foo FROM bar WHERE ( ((a = 1) AND ( b = 1 OR (c = 1 OR d = 1) )) AND ((e = 1)) AND f = 1) /,
+ ]
+ },
+ {
+ equal => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE (a) AND (b = 2)/,
+ q/SELECT foo FROM bar WHERE (a AND b = 2)/,
+ q/SELECT foo FROM bar WHERE (a AND (b = 2))/,
+ q/SELECT foo FROM bar WHERE a AND (b = 2)/,
+ ]
+ },
+ {
+ equal => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE ((NOT a) AND b = 2)/,
+ q/SELECT foo FROM bar WHERE (NOT a) AND (b = 2)/,
+ q/SELECT foo FROM bar WHERE (NOT (a)) AND b = 2/,
+ ],
+ },
+ {
+ equal => 0,
+ statements => [
+ q/SELECT foo FROM bar WHERE NOT a AND (b = 2)/,
+ q/SELECT foo FROM bar WHERE (NOT a) AND (b = 2)/,
+ ]
+ },
+ {
+ equal => 0,
+ parenthesis_significant => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE a = 1 AND b = 1 AND c = 1/,
+ q/SELECT foo FROM bar WHERE (a = 1 AND b = 1 AND c = 1)/,
+ q/SELECT foo FROM bar WHERE (a = 1 AND b = 1) AND c = 1/,
+ q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 AND c = 1)/,
+ q/SELECT foo FROM bar WHERE ((((a = 1))) AND (b = 1 AND c = 1))/,
+ ]
+ },
+ {
+ equal => 0,
+ parenthesis_significant => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE a = 1 OR b = 1 OR c = 1/,
+ q/SELECT foo FROM bar WHERE (a = 1 OR b = 1) OR c = 1/,
+ q/SELECT foo FROM bar WHERE a = 1 OR (b = 1 OR c = 1)/,
+ q/SELECT foo FROM bar WHERE a = 1 OR ((b = 1 OR (c = 1)))/,
+ ]
+ },
+ {
+ equal => 0,
+ parenthesis_significant => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE (a = 1) AND (b = 1 OR c = 1 OR d = 1) AND (e = 1 AND f = 1)/,
+ q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 OR c = 1 OR d = 1) AND e = 1 AND (f = 1)/,
+ q/SELECT foo FROM bar WHERE ( ((a = 1) AND ( b = 1 OR (c = 1 OR d = 1) )) AND ((e = 1)) AND f = 1) /,
+ ]
+ },
# WHERE condition - different
{
q/SELECT foo FROM bar JOIN quux ON a = 1 WHERE a = 1 AND b = 1/,
]
},
+ {
+ equal => 0,
+ statements => [
+ q/SELECT foo FROM bar WHERE a = 1 AND b = 1 OR c = 1/,
+ q/SELECT foo FROM bar WHERE (a = 1 AND b = 1) OR c = 1/,
+ q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 OR c = 1)/,
+ ]
+ },
+ {
+ equal => 0,
+ statements => [
+ q/SELECT foo FROM bar WHERE a = 1 OR b = 1 AND c = 1/,
+ q/SELECT foo FROM bar WHERE (a = 1 OR b = 1) AND c = 1/,
+ q/SELECT foo FROM bar WHERE a = 1 OR (b = 1 AND c = 1)/,
+ ]
+ },
+ {
+ equal => 0,
+ parenthesis_significant => 1,
+ statements => [
+ q/SELECT foo FROM bar WHERE a IN (1,2,3)/,
+ q/SELECT foo FROM bar WHERE a IN (1,3,2)/,
+ q/SELECT foo FROM bar WHERE a IN ((1,2,3))/,
+ ]
+ },
+ {
+ equal => 0,
+ statements => [
+ # BETWEEN with/without parenthesis around itself/RHS is a sticky business
+ # if I made a mistake here, simply rewrite the special BETWEEN handling in
+ # _recurse_parse()
+ #
+ # by RIBASUSHI
+ q/SELECT foo FROM bar WHERE ( completion_date BETWEEN ? AND ? AND status = ? )/,
+ q/SELECT foo FROM bar WHERE completion_date BETWEEN (? AND ?) AND status = ?/,
+ q/SELECT foo FROM bar WHERE ( (completion_date BETWEEN (? AND ?) ) AND status = ? )/,
+ q/SELECT foo FROM bar WHERE ( (completion_date BETWEEN (? AND ? AND status = ?) ) )/,
+ ]
+ },
# JOIN condition - equal
{
{
equal => 0,
statements => [
+ q/DELETE FROM cd WHERE ( cdid IN ( SELECT me.cdid FROM (SELECT * FROM cd me WHERE ( year != ? ) GROUP BY me.cdid) me WHERE ( year != ? ) ) )/,
+ q/DELETE FROM cd WHERE ( cdid IN ( SELECT me.cdid FROM cd me WHERE ( year != ? ) GROUP BY me.cdid ) )/,
+ ],
+ },
+ {
+ equal => 0,
+ statements => [
q/SELECT * FROM (SELECT * FROM bar WHERE b = 1) AS foo WHERE a = 1/,
q/SELECT * FROM (SELECT * FROM bar WHERE b = 1) AS foo WHERE a = 2/,
q/SELECT * FROM (SELECT * FROM bar WHERE b = 1) AS foo WHERE (a = 3)/,
q/SELECT * FROM (SELECT * FROM bar WHERE ((b = 1) AND (c = 10))) AS foo WHERE (a = 2)/,
]
},
+ {
+ equal => 0,
+ statements => [
+ 'SELECT a,b,c FROM foo',
+ 'SELECT a,c,b FROM foo',
+ 'SELECT b,a,c FROM foo',
+ 'SELECT b,c,a FROM foo',
+ 'SELECT c,a,b FROM foo',
+ 'SELECT c,b,a FROM foo',
+ ],
+ },
+ {
+ equal => 0,
+ statements => [
+ 'SELECT * FROM foo WHERE a IN (1,2,3)',
+ 'SELECT * FROM foo WHERE a IN (1,3,2)',
+ 'SELECT * FROM foo WHERE a IN (2,1,3)',
+ 'SELECT * FROM foo WHERE a IN (2,3,1)',
+ 'SELECT * FROM foo WHERE a IN (3,1,2)',
+ 'SELECT * FROM foo WHERE a IN (3,2,1)',
+ ]
+ },
+ {
+ equal => 0,
+ statements => [
+ 'SELECT count(*) FROM foo',
+ 'SELECT count(*) AS bar FROM foo',
+ 'SELECT count(*) AS "bar" FROM foo',
+ 'SELECT count(a) FROM foo',
+ 'SELECT count(1) FROM foo',
+ ]
+ },
);
my @bind_tests = (
map { $_ * ($_ - 1) / 2 }
map { scalar @{$_->{bindvals}} }
@bind_tests
- );
+ ) +
+ 3;
-use_ok('SQL::Abstract::Test', import => [qw(eq_sql eq_bind is_same_sql_bind)]);
+use_ok('SQL::Abstract::Test', import => [qw(
+ eq_sql_bind eq_sql eq_bind is_same_sql_bind
+)]);
for my $test (@sql_tests) {
my $statements = $test->{statements};
while (@$statements) {
my $sql1 = shift @$statements;
foreach my $sql2 (@$statements) {
+
+ no warnings qw/once/; # perl 5.10 is dumb
+ local $SQL::Abstract::Test::parenthesis_significant = $test->{parenthesis_significant}
+ if $test->{parenthesis_significant};
my $equal = eq_sql($sql1, $sql2);
- if ($test->{equal}) {
- ok($equal, "equal SQL expressions considered equal");
- } else {
- ok(!$equal, "different SQL expressions considered not equal");
- }
- if ($equal ^ $test->{equal}) {
- diag("sql1: $sql1");
- diag("sql2: $sql2");
+ TODO: {
+ local $TODO = $test->{todo} if $test->{todo};
+
+ if ($test->{equal}) {
+ ok($equal, "equal SQL expressions should have been considered equal");
+ } else {
+ ok(!$equal, "different SQL expressions should have been considered not equal");
+ }
+
+ if ($equal ^ $test->{equal}) {
+ diag("sql1: $sql1");
+ diag("sql2: $sql2");
+ note('ast1: ' . Dumper SQL::Abstract::Test::parse ($sql1));
+ note('ast2: ' . Dumper SQL::Abstract::Test::parse ($sql2));
+ }
}
}
}
}
}
}
+
+ok(eq_sql_bind(
+ "SELECT * FROM foo WHERE id = ?", [42],
+ "SELECT * FROM foo WHERE (id = ?)", [42],
+ ),
+ "eq_sql_bind considers equal SQL expressions and bind values equal"
+);
+
+
+ok(!eq_sql_bind(
+ "SELECT * FROM foo WHERE id = ?", [42],
+ "SELECT * FROM foo WHERE (id = ?)", [0],
+ ),
+ "eq_sql_bind considers equal SQL expressions and different bind values different"
+);
+
+ok(!eq_sql_bind(
+ "SELECT * FROM foo WHERE id = ?", [42],
+ "SELECT * FROM bar WHERE (id = ?)", [42],
+ ),
+ "eq_sql_bind considers different SQL expressions and equal bind values different"
+);