From 4611d8301a607087d5c1ca8799eeb4dc50164fc7 Mon Sep 17 00:00:00 2001 From: ygrek Date: Thu, 8 Nov 2018 17:02:56 +0200 Subject: [PATCH] sql: EXISTS --- lib/sql.ml | 2 +- lib/sql_parser.mly | 6 +++--- lib/syntax.ml | 10 +++++----- test/misc.sql | 8 +++++--- test/out/misc.xml | 11 +++++++++++ 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/sql.ml b/lib/sql.ml index e8ea789..1f200a7 100644 --- a/lib/sql.ml +++ b/lib/sql.ml @@ -234,7 +234,7 @@ and expr = | Value of Type.t (** literal value *) | Param of param | Fun of Type.func * expr list (** parameters *) - | Select of select_full * bool (* single *) + | Select of select_full * [ `AsValue | `Exists ] | Column of col_name | Inserted of string (** inserted value *) and column = diff --git a/lib/sql_parser.mly b/lib/sql_parser.mly index 4b8fe77..3dccc25 100644 --- a/lib/sql_parser.mly +++ b/lib/sql_parser.mly @@ -324,15 +324,15 @@ expr: | VALUES LPAREN n=IDENT RPAREN { Inserted n } | v=literal_value | v=datetime_value { v } | e1=expr mnot(IN) l=sequence(expr) { poly Bool (e1::l) } - | e1=expr mnot(IN) LPAREN select=select_stmt RPAREN { poly Bool [e1; Select (select, true)] } + | e1=expr mnot(IN) LPAREN select=select_stmt RPAREN { poly Bool [e1; Select (select, `AsValue)] } | e1=expr IN table=IDENT { Tables.check table; e1 } - | LPAREN select=select_stmt RPAREN { Select (select, true) } + | LPAREN select=select_stmt RPAREN { Select (select, `AsValue) } | PARAM { Param ($1,Any) } | f=IDENT LPAREN p=func_params RPAREN { Fun (Function.lookup f (List.length p), p) } | expr IS NOT? NULL { Fun (Ret Bool, [$1]) } | e1=expr IS NOT? distinct_from? e2=expr { poly Bool [e1;e2] } | expr mnot(BETWEEN) expr AND expr { poly Bool [$1;$3;$5] } - | mnot(EXISTS) LPAREN select=select_stmt RPAREN { Fun ((Ret Bool),[Select (select,false)]) } (* FIXME Poly Bool *) + | mnot(EXISTS) LPAREN select=select_stmt RPAREN { Fun (F (Typ Bool, [Typ Any]),[Select (select,`Exists)]) } | CASE e1=expr? branches=nonempty_list(case_branch) e2=preceded(ELSE,expr)? END (* FIXME typing *) { let maybe f = function None -> [] | Some x -> [f x] in diff --git a/lib/syntax.ml b/lib/syntax.ml index cedf167..9c78840 100644 --- a/lib/syntax.ml +++ b/lib/syntax.ml @@ -93,13 +93,13 @@ let rec resolve_columns env expr = | Param x -> `Param x | Fun (r,l) -> `Func (r,List.map each l) - | Select (select,single) -> + | Select (select, usage) -> let as_params = List.map (fun x -> `Param x) in let (schema,p,_) = eval_select_full env select in - match schema,single with - | [ {domain;_} ], true -> `Func (Type.Ret domain, as_params p) - | s, true -> raise (Schema.Error (s, "only one column allowed for SELECT operator in this expression")) - | _ -> fail "not implemented: multi-column select in expression" + match schema, usage with + | [ {domain;_} ], `AsValue -> `Func (Type.Ret domain, as_params p) + | s, `AsValue -> raise (Schema.Error (s, "only one column allowed for SELECT operator in this expression")) + | _, `Exists -> `Func (Type.Ret Any, as_params p) in each expr diff --git a/test/misc.sql b/test/misc.sql index 7cd626e..caf1870 100644 --- a/test/misc.sql +++ b/test/misc.sql @@ -14,9 +14,6 @@ INSERT INTO `appointments` ( NOW() + INTERVAL @delay SECOND ); SELECT SUM(CASE WHEN x > 10 THEN 1 ELSE 0 END) FROM test; --- delete from txn_ranges --- where id in (@tr1_id, @tr2_id) --- and not exists (select 1 from workareas where txn_range_id = txn_ranges.id) CREATE TABLE issue14 (x integer); INSERT INTO issue14 (x) VALUES (@x); @@ -74,3 +71,8 @@ SELECT 0 is 0, 0 is null, null is 0, null is null; -- @issue54_sql SELECT 42 is not distinct from null, 42 is distinct from null; + +CREATE TABLE workareas (work_id int, about text); +delete from test +where x in (@x1, @x2) + and not exists (select 1 from workareas where work_id = test.x); diff --git a/test/out/misc.xml b/test/out/misc.xml index 9a165ac..323a9b5 100644 --- a/test/out/misc.xml +++ b/test/out/misc.xml @@ -191,4 +191,15 @@ + + + + + + + + + + + -- 2.11.4.GIT