IN sub-select generates SQL malformed SQL
jonathanstowe opened this issue · comments
While looking at #520 I noticed that an IN
with a sub-select like:
#!/usr/bin/env raku
use Red;
my $*RED-DB = database 'SQLite';
my $*RED-DEBUG = True;
model A {
has Str $.id is id;
has @.bs is relationship({ .a-id }, model => 'B' );
}
model B {
has Int $.id is serial;
has Str $.a-id is column({ name => 'a', model-name => 'A', column-name => 'id' });
has $.a is relationship({ .a-id }, model => 'A');
has Int $.c-id is referencing(model => 'C', column => 'id' );
has $.c is relationship({ .c-id }, model => 'C');
has Bool $.d is column is rw = True;
}
model C {
has Int $.id is serial;
has Str $.d is column;
has @.bs is relationship({ .c-id }, model => 'B' );
}
A.^create-table;
C.^create-table;
B.^create-table;
my $a = A.^create( id => 'FOO');
my $sub = $a.bs.grep( *.c.d (>) <a b c> ).map( *.id );
say $a.bs.grep(*.id (<) $sub).map( { .d = True }).save;
# vim: ft=raku
Gives rise to:
SQL : CREATE TABLE "a" (
id varchar(255) NOT NULL primary key
)
BIND: []
SQL : CREATE TABLE "c" (
id integer NOT NULL primary key AUTOINCREMENT,
d varchar(255) NOT NULL
)
BIND: []
SQL : CREATE TABLE "b" (
id integer NOT NULL primary key AUTOINCREMENT,
a varchar(255) NOT NULL references a(id),
c_id integer NULL references c(id),
d integer NOT NULL
)
BIND: []
SQL : BEGIN
BIND: []
SQL : INSERT INTO "a"(
id
)
VALUES(
?
)
BIND: ["FOO"]
SQL : SELECT
"a".id
FROM
"a"
WHERE
_rowid_ = last_insert_rowid()
LIMIT 1
BIND: []
SQL : SELECT
"a".id
FROM
"a"
WHERE
"a".id = 'FOO'
LIMIT 1
BIND: []
SQL : COMMIT
BIND: []
SQL : UPDATE b SET
d = 1
WHERE "b".a = ? AND "b".id IN SELECT
"b".id as "data_1"
FROM
"b"
LEFT JOIN "c" as b_c ON "b".c_id = "b_c".id
WHERE
"b".a = ? AND "b_c".d NOT IN ( ?, ?, ? )
Unknown Error!!!
Please, copy this backtrace and open an issue on https://github.com/FCO/Red/issues/new
Driver: Red::Driver::SQLite
Original error: X::DBDish::DBError.new(driver-name => "DBDish::SQLite", native-message => "near \"SELECT\": syntax error", code => 1, why => "Error")
Original error:
DBDish::SQLite: Error: near "SELECT": syntax error (1)
in method handle-error at /home/jonathan/.raku/sources/9649AE51DBA2ED07FF0A6B99F0A2C5DDBAD5E7E0 (DBDish::SQLite::Connection) line 17
in method prepare at /home/jonathan/.raku/sources/9649AE51DBA2ED07FF0A6B99F0A2C5DDBAD5E7E0 (DBDish::SQLite::Connection) line 26
in method prepare at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver/SQLite.pm6 (Red::Driver::SQLite) line 56
in code at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver.pm6 (Red::Driver) line 84
in code at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver.pm6 (Red::Driver) line 83
in method prepare at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver.pm6 (Red::Driver) line 80
in method execute at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver.pm6 (Red::Driver) line 114
in method save at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/ResultSeq.pm6 (Red::ResultSeq) line 376
in block <unit> at rec6 line 35
Actually thrown at:
in block at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver/SQLite.pm6 (Red::Driver::SQLite) line 52
in any at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver/SQLite.pm6 (Red::Driver::SQLite) line 50
in method prepare at /home/jonathan/.raku/sources/9649AE51DBA2ED07FF0A6B99F0A2C5DDBAD5E7E0 (DBDish::SQLite::Connection) line 37
in method prepare at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver/SQLite.pm6 (Red::Driver::SQLite) line 56
in code at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver.pm6 (Red::Driver) line 84
in code at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver.pm6 (Red::Driver) line 83
in method prepare at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver.pm6 (Red::Driver) line 80
in method execute at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/Driver.pm6 (Red::Driver) line 114
in method save at /home/jonathan/devel/raku/3rdparty-modules/Red/lib/Red/ResultSeq.pm6 (Red::ResultSeq) line 376
in block <unit> at rec6 line 35
i.e. it is omitting the required parentheses around the sub-select.
I thought this would be an easy fix, but it seems that it isn't so. Most sub-selects do get the parentheses but this one doesn't.
I'm planing to add an multi method translation(Red::AST::In $_ where *.right ~~ Red::AST::Select, $)
or something like that
Actually you could do that do that for any Red::AST::Infix
in order to support any sub-select on the RHS easily.
It breaks t/20-in-sql.t :(
It breaks t/20-in-sql.t :(
Yes that's what I found when I did my first (dumb) attempt at putting the parens round any sub-select.
@jonathanstowe could you confirm that's fixed?
Yep that's great 👍