Skip Menu |

This queue is for tickets about the SQL-Interp CPAN distribution.

Report information
The Basics
Id: 30752
Status: resolved
Priority: 0/
Queue: SQL-Interp

People
Owner: MARKSTOS [...] cpan.org
Requestors: ARISTOTLE [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in:
  • 1.00
  • 1.01
  • 1.02
Fixed in: (no value)



Subject: `IN` rewriting does not account for `NOT IN` syntax
Try this: print sql_interp('SELECT COUNT(*) FROM foo WHERE bar NOT IN', []); It will print the following: SELECT COUNT(*) FROM foo WHERE bar 1=0 This is malformed SQL and won’t run. What it *should* have printed is either of the following: SELECT COUNT(*) FROM foo WHERE NOT 1=0 SELECT COUNT(*) FROM foo WHERE 1=1 Instead, the code as it stands deals only with unnegated IN operators and considers the NOT to be a column name. This is of course easy to work around by swapping the column name and the NOT: print sql_interp('SELECT COUNT(*) FROM foo WHERE NOT bar IN', []); That leads to syntactically and semantically correct output: SELECT COUNT(*) FROM foo WHERE NOT 1=0 However, this limitation is quite surprising, and it’s not hard to fix (patch attached as well, in case the web interface mangles it): --- Interp.pm.orig 2007-11-15 13:46:42.000000000 +0100 +++ Interp.pm 2007-11-15 13:54:16.000000000 +0100 @@ -165,3 +165,4 @@ elsif (ref $item) { - if ($sql =~ /\bIN\s*$/si) { + if ($sql =~ /\b(NOT\s+)?IN\s*$/si) { + my $not = quotemeta($1) || ''; $item = [ $$item ] if ref $item eq 'SCALAR'; @@ -169,3 +170,4 @@ if (@$item == 0) { - $sql =~ s/$id_match\s+IN\s*$/1=0/si or croak 'ASSERT'; + my $dummy_expr = $not ? '1=1' : '1=0'; + $sql =~ s/$id_match\s+IN\s*$/$dummy_expr/si or croak 'ASSERT'; }
Subject: Interp.pm.diff
--- Interp.pm.orig 2007-11-15 13:46:42.000000000 +0100 +++ Interp.pm 2007-11-15 13:54:16.000000000 +0100 @@ -165,3 +165,4 @@ elsif (ref $item) { - if ($sql =~ /\bIN\s*$/si) { + if ($sql =~ /\b(NOT\s+)?IN\s*$/si) { + my $not = quotemeta($1) || ''; $item = [ $$item ] if ref $item eq 'SCALAR'; @@ -169,3 +170,4 @@ if (@$item == 0) { - $sql =~ s/$id_match\s+IN\s*$/1=0/si or croak 'ASSERT'; + my $dummy_expr = $not ? '1=1' : '1=0'; + $sql =~ s/$id_match\s+IN\s*$/$dummy_expr/si or croak 'ASSERT'; }
Oops, that patch was missing a crucial bit… Correct patched attached (only, since the form does indeed mangle it…).
--- Interp.pm.orig 2007-11-15 13:46:42.000000000 +0100 +++ Interp.pm 2007-11-15 13:56:56.000000000 +0100 @@ -165,3 +165,4 @@ elsif (ref $item) { - if ($sql =~ /\bIN\s*$/si) { + if ($sql =~ /\b(NOT\s+)?IN\s*$/si) { + my $not = quotemeta($1) || ''; $item = [ $$item ] if ref $item eq 'SCALAR'; @@ -169,3 +170,4 @@ if (@$item == 0) { - $sql =~ s/$id_match\s+IN\s*$/1=0/si or croak 'ASSERT'; + my $dummy_expr = $not ? '1=1' : '1=0'; + $sql =~ s/$id_match\s+${not}IN\s*$/$dummy_expr/si or croak 'ASSERT'; }
Subject: Re: [rt.cpan.org #30752] (Thanks for SQL::Interp report)
Date: Thu, 15 Nov 2007 10:30:44 -0500
To: bug-SQL-Interp [...] rt.cpan.org
From: Mark Stosberg <mark [...] summersault.com>
Aristotle, Thanks for another useful bug report and patch. I expect to apply and release it as well after a final review. I'm glad you are a fan of SQL::Interp, too! I really like it and wish it was used a foundation of more other projects like SQL::Abstract has been. Mark
About to be released .
Hi Mark, sorry to reopen, but I made a mistake that causes harmless but annoying warnings: my $not = quotemeta($1) || ''; A `NOT`-less `IN` clause will cause an undefined `$1` to be passed to `quotemeta`, resulting in a warning. The empty-string default is there to prevent the same warning when `$not` later gets interpolated into the regex, but it escaped my notice that the `quotemeta` call needs the same safeguard. So that line needs to read as follows, instead: my $not = quotemeta($1 || ''); Sorry. :-(
Subject: Re: [rt.cpan.org #30752] `IN` rewriting does not account for `NOT IN` syntax
Date: Fri, 16 Nov 2007 09:50:08 -0500
To: bug-SQL-Interp [...] rt.cpan.org
From: Mark Stosberg <mark [...] summersault.com>
On Friday 16 November 2007 00:26, Aristotle Pagaltzis via RT wrote: Show quoted text
> Queue: SQL-Interp > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=30752 > > > Hi Mark, > > sorry to reopen, but I made a mistake that causes harmless but > annoying warnings: > > my $not = quotemeta($1) || ''; > > A `NOT`-less `IN` clause will cause an undefined `$1` to be passed to > `quotemeta`, resulting in a warning. The empty-string default is > there to prevent the same warning when `$not` later gets interpolated > into the regex, but it escaped my notice that the `quotemeta` call > needs the same safeguard. So that line needs to read as follows, > instead: > > my $not = quotemeta($1 || '');
Thanks for the report, Aristotle. I could have caught this myself, but didn't. I'll patch and release. Mark
1.06 has been uploaded to address this.