Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null by default #126

Open
wants to merge 2 commits into
base: null
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/sql.ml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ type attr = {name : string; domain : Type.t; extra : Constraints.t; }

let make_attribute name kind extra =
if Constraints.mem Null extra && Constraints.mem NotNull extra then fail "Column %s can be either NULL or NOT NULL, but not both" name;
let domain = Type.{ t = Option.default Int kind; nullability = if Constraints.mem Null extra then Nullable else Strict } in
let domain = Type.{ t = Option.default Int kind; nullability = if Constraints.mem NotNull extra then Strict else Nullable } in
{name;domain;extra}

let unnamed_attribute domain = {name="";domain;extra=Constraints.empty}
Expand Down
4 changes: 2 additions & 2 deletions lib/sql_parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ reference_action_clause:

reference_action:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT { }

on_conflict: ON CONFLICT algo=conflict_algo { algo }
column_def_extra: PRIMARY? KEY { Some PrimaryKey }
| NOT NULL { Some NotNull }
Expand All @@ -348,7 +348,7 @@ column_def_extra: PRIMARY? KEY { Some PrimaryKey }
| AUTOINCREMENT { Some Autoincrement }
| on_conflict { None }
| CHECK LPAREN expr RPAREN { None }
| DEFAULT e=default_value { match e with Value { t = Any; nullability = _ } -> Some Null | _ -> None } (* FIXME check type with column *)
| DEFAULT default_value { None }
| COLLATE IDENT { None }
| pair(GENERATED,ALWAYS)? AS LPAREN expr RPAREN either(VIRTUAL,STORED)? { None } (* FIXME params and typing ignored *)

Expand Down
77 changes: 42 additions & 35 deletions src/test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,46 +37,53 @@ let wrong sql =
sql >:: (fun () -> ("Expected error in : " ^ sql) @? (try ignore (Main.parse_one' (sql,[])); false with _ -> true))

let attr ?(extra=[]) n d = make_attribute n (Some d) (Constraints.of_list extra)
let attr' ?(extra=[]) ?(nullability=Type.Strict) name kind =
let domain: Type.t = { t = kind; nullability; } in
{name;domain;extra=Constraints.of_list extra }

let named s t = new_param { label = Some s; pos = (0,0) } (Type.strict t)
let named_nullable s t = new_param { label = Some s; pos = (0,0) } (Type.nullable t)
let param_nullable t = new_param { label = None; pos = (0,0) } (Type.nullable t)
let param t = new_param { label = None; pos = (0,0) } (Type.strict t)

let test = Type.[
tt "CREATE TABLE test (id INT, str TEXT, name TEXT)" [] [];
tt "SELECT str FROM test WHERE id=?"
[attr "str" Text]
[param Int];
tt "SELECT x,y+? AS z FROM (SELECT id AS y,CONCAT(str,name) AS x FROM test WHERE id=@id*2) ORDER BY x,x+z LIMIT @lim"
[attr "x" Text; attr "z" Int]
[param Int; named "id" Int; named "lim" Int; ];
[attr' ~nullability:(Nullable) "str" Text]
[param_nullable Int];
tt "SELECT x,y+? AS z FROM (SELECT id AS y,CONCAT(str,name) AS x FROM test WHERE id=@id*2) ORDER BY x,x+z LIMIT @lim"
[attr' "x" Text; attr' ~nullability:(Nullable) "z" Int]
[param_nullable Int; named "id" Int; named "lim" Int; ];
tt "select test.name,other.name as other_name from test, test as other where test.id=other.id + @delta"
[attr "name" Text; attr "other_name" Text]
[named "delta" Int];
[ attr' ~nullability:(Nullable) "name" Text;
attr' ~nullability:(Nullable) "other_name" Text
]
[named_nullable "delta" Int];
tt "select test.name from test where test.id + @x = ? or test.id - @x = ?"
[attr "name" Text;]
[named "x" Int; param Int; named "x" Int; param Int;];
[attr' ~nullability:(Nullable) "name" Text;]
[named_nullable "x" Int; param_nullable Int; named_nullable "x" Int; param_nullable Int;];
tt "insert into test values"
[]
[named "id" Int; named "str" Text; named "name" Text];
[named_nullable "id" Int; named_nullable "str" Text; named_nullable "name" Text];
tt "insert into test (str,name) values"
[]
[named "str" Text; named "name" Text];
[named_nullable "str" Text; named_nullable "name" Text];
tt "insert into test values (2,'hello' || ' world',@name)"
[]
[named "name" Text];
tt "insert or replace into test values (2,?,?)" [] [param Text; param Text;];
tt "replace into test values (2,?,?)" [] [param Text; param Text;];
tt "select str, case when id > @id then name when id < @id then 'qqq' else @def end as q from test"
[attr "str" Text; attr "q" Text]
[named "id" Int; named "id" Int; named "def" Text];
wrong "insert into test values (1,2)";
[named_nullable "name" Text];
tt "insert or replace into test values (2,?,?)" [] [param_nullable Text; param_nullable Text;];
tt "replace into test values (2,?,?)" [] [param_nullable Text; param_nullable Text;];
tt "select str, case when id > @id then name when id < @id then 'qqq' else @def end as q from test"
[attr' ~nullability:(Nullable) "str" Text; attr' ~nullability:(Nullable) "q" Text]
[named_nullable "id" Int; named_nullable "id" Int; named_nullable "def" Text];
wrong "insert into test values (1,2)";
wrong "insert into test (str,name) values (1,'str','name')";
(* check precedence of boolean and arithmetic operators *)
tt "select str from test where id>=@id and id-@x<@id"
[attr "str" Text;]
[named "id" Int; named "x" Int; named "id" Int];
[attr' ~nullability:(Nullable) "str" Text;]
[named_nullable "id" Int; named_nullable "x" Int; named_nullable "id" Int];
tt "select 3/5"
[attr "" Float;]
[attr' ~nullability:(Strict) "" Float;]
[];
]

Expand Down Expand Up @@ -109,22 +116,22 @@ let test4 =
tt "select max(x,y) from test4" a [] ~kind:(Select `Nat);
tt "select max(x,y) from test4 limit 1" a [] ~kind:(Select `Zero_one);
tt "select max(x,y) from test4 limit 2" a [] ~kind:(Select `Nat);
tt "select 1" a [] ~kind:(Select `One);
tt "select greatest(1+2,10)" a [] ~kind:(Select `One);
tt "select greatest(1+2,10) where 1 = 2" a [] ~kind:(Select `Zero_one);
tt "select 1 from test4" a [] ~kind:(Select `Nat);
tt "select 1+2 from test4" a [] ~kind:(Select `Nat);
tt "select 1" [attr' ~nullability:(Strict) "" Int] [] ~kind:(Select `One);
tt "select greatest(1+2,10)" [attr' ~nullability:(Strict) "" Int] [] ~kind:(Select `One);
tt "select greatest(1+2,10) where 1 = 2" [attr' ~nullability:(Strict) "" Int] [] ~kind:(Select `Zero_one);
tt "select 1 from test4" [attr' ~nullability:(Strict) "" Int] [] ~kind:(Select `Nat);
tt "select 1+2 from test4" [attr' ~nullability:(Strict) "" Int] [] ~kind:(Select `Nat);
tt "select least(10+unix_timestamp(),random()), concat('test',upper('qqqq')) from test"
[attr "" Int; attr "" Text] [] ~kind:(Select `Nat);
tt "select greatest(10,x) from test4" a [] ~kind:(Select `Nat);
tt "select 1+2 from test4 where x=y" a [] ~kind:(Select `Nat);
tt "select max(x) as q from test4 where y = x + @n" [attr "q" Int] [named "n" Int] ~kind:(Select `One);
tt "select coalesce(max(x),0) as q from test4 where y = x + @n" [attr "q" Int] [named "n" Int] ~kind:(Select `One);
[attr' ~nullability:(Strict) "" Int; attr' ~nullability:(Strict) "" Text] [] ~kind:(Select `Nat);
tt "select greatest(10,x) from test4" [attr' ~nullability:(Nullable) "" Int] [] ~kind:(Select `Nat);
tt "select 1+2 from test4 where x=y" [attr' ~nullability:(Strict) "" Int] [] ~kind:(Select `Nat);
tt "select max(x) as q from test4 where y = x + @n" [attr' ~nullability:(Nullable) "q" Int] [named_nullable "n" Int] ~kind:(Select `One);
tt "select coalesce(max(x),0) as q from test4 where y = x + @n" [attr "q" Int] [named_nullable "n" Int] ~kind:(Select `One);
]

let test_parsing = [
tt "CREATE TABLE test5_1 (x INT NOT NULL, y INT DEFAULT -1) ENGINE=MEMORY" [] [];
tt "SELECT 2+3, 2+-3, -10 FROM test5_1" [attr "" Int; attr "" Int; attr "" Int] [];
tt "CREATE TABLE test5_1 (x INT NOT NULL, y INT NOT NULL DEFAULT -1) ENGINE=MEMORY" [] [];
tt "SELECT 2+3, 2+-3, -10 FROM test5_1" [attr' "" Int; attr' "" Int; attr' "" Int] [];
]

(*
Expand All @@ -151,12 +158,12 @@ let test_join_result_cols () =
do_test
"SELECT * FROM t1 NATURAL JOIN t2 WHERE j > @x"
(ints ["j";"i";"k"])
[named "x" Int];
[named_nullable "x" Int];
(* NATURAL JOIN with common column qualified in WHERE *)
do_test
"SELECT * FROM t1 NATURAL JOIN t2 WHERE t2.j > @x"
(ints ["j";"i";"k"])
[named "x" Int];
[named_nullable "x" Int];
()

let test_enum = [
Expand Down
12 changes: 6 additions & 6 deletions test/out/bug39_select_if.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
<value name="x" type="Datetime"/>
</in>
<out>
<value name="id" type="Int"/>
<value name="host" type="Text"/>
<value name="_2" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="host" type="Text" nullable="true"/>
<value name="_2" type="Int" nullable="true"/>
</out>
</stmt>
<table name="profiles">
<schema>
<value name="id" type="Int"/>
<value name="host" type="Text"/>
<value name="today_count" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="host" type="Text" nullable="true"/>
<value name="today_count" type="Int" nullable="true"/>
</schema>
</table>
</sqlgg>
6 changes: 3 additions & 3 deletions test/out/bug7.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@
<stmt name="ins1" sql="insert into test1 values (@x1,@x2)" category="DML" kind="insert" target="test1" cardinality="0">
<in>
<value name="x1" type="Int"/>
<value name="x2" type="Int"/>
<value name="x2" type="Int" nullable="true"/>
</in>
<out/>
</stmt>
<stmt name="ins2" sql="insert into test1 (x1,x2) values (@x1,@x2)" category="DML" kind="insert" target="test1" cardinality="0">
<in>
<value name="x1" type="Int"/>
<value name="x2" type="Int"/>
<value name="x2" type="Int" nullable="true"/>
</in>
<out/>
</stmt>
<table name="test1">
<schema>
<value name="x1" type="Int"/>
<value name="x2" type="Int"/>
<value name="x2" type="Int" nullable="true"/>
</schema>
</table>
</sqlgg>
8 changes: 4 additions & 4 deletions test/out/database.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
</stmt>
<table name="database2.test">
<schema>
<value name="id" type="Int"/>
<value name="amount" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="amount" type="Int" nullable="true"/>
</schema>
</table>
<table name="database1.test">
<schema>
<value name="id" type="Int"/>
<value name="txt" type="Text"/>
<value name="id" type="Int" nullable="true"/>
<value name="txt" type="Text" nullable="true"/>
</schema>
</table>
</sqlgg>
6 changes: 3 additions & 3 deletions test/out/float.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
<stmt name="insert" sql="insert into transactions values (@amount,@date)" category="DML" kind="insert" target="transactions" cardinality="0">
<in>
<value name="amount" type="Float"/>
<value name="date" type="Datetime"/>
<value name="date" type="Datetime" nullable="true"/>
</in>
<out/>
</stmt>
<stmt name="select" sql="select amount + 2.5 from transactions where `date` &gt; @date and amount &gt; @limit" category="DQL" kind="select" cardinality="n">
<in>
<value name="date" type="Datetime"/>
<value name="date" type="Datetime" nullable="true"/>
<value name="limit" type="Float"/>
</in>
<out>
Expand All @@ -24,7 +24,7 @@
<table name="transactions">
<schema>
<value name="amount" type="Float"/>
<value name="date" type="Datetime"/>
<value name="date" type="Datetime" nullable="true"/>
</schema>
</table>
</sqlgg>
22 changes: 11 additions & 11 deletions test/out/inargument.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,29 @@
</stmt>
<stmt name="find" sql="SELECT * FROM foo&#x0A;WHERE id IN @@ids" category="DQL" kind="select" cardinality="n">
<in>
<value name="ids" type="set(Int)"/>
<value name="ids" type="set(Int)" nullable="true"/>
</in>
<out>
<value name="id" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="foo" type="Text" nullable="true"/>
</out>
</stmt>
<stmt name="get" sql="SELECT * FROM foo&#x0A;WHERE (id IN @@ids)&#x0A;LIMIT 1" category="DQL" kind="select" cardinality="0,1">
<in>
<value name="ids" type="set(Int)"/>
<value name="ids" type="set(Int)" nullable="true"/>
</in>
<out>
<value name="id" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="foo" type="Text" nullable="true"/>
</out>
</stmt>
<stmt name="find2" sql="SELECT * FROM foo&#x0A;WHERE (id IN @@ids) AND foo NOT IN @@foos" category="DQL" kind="select" cardinality="n">
<in>
<value name="ids" type="set(Int)"/>
<value name="ids" type="set(Int)" nullable="true"/>
<value name="foos" type="set(Text)" nullable="true"/>
</in>
<out>
<value name="id" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="foo" type="Text" nullable="true"/>
</out>
</stmt>
Expand All @@ -43,17 +43,17 @@
<value name="foos_with_suffix" type="set(Text)"/>
</in>
<out>
<value name="id" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="foo" type="Text" nullable="true"/>
</out>
</stmt>
<stmt name="get2" sql="SELECT * FROM foo&#x0A;WHERE id IN @@ids AND (foo NOT IN @@foos)&#x0A;LIMIT 1" category="DQL" kind="select" cardinality="0,1">
<in>
<value name="ids" type="set(Int)"/>
<value name="ids" type="set(Int)" nullable="true"/>
<value name="foos" type="set(Text)" nullable="true"/>
</in>
<out>
<value name="id" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="foo" type="Text" nullable="true"/>
</out>
</stmt>
Expand All @@ -64,7 +64,7 @@
<value name="lengths" type="set(Int)"/>
</in>
<out>
<value name="id" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="foo" type="Text" nullable="true"/>
<value name="foo_id" type="Int"/>
<value name="baz" type="Text"/>
Expand All @@ -78,7 +78,7 @@
</table>
<table name="foo">
<schema>
<value name="id" type="Int"/>
<value name="id" type="Int" nullable="true"/>
<value name="foo" type="Text" nullable="true"/>
</schema>
</table>
Expand Down