From 83cefdd94aafcd64d4b4599bee64d8a49686a06c Mon Sep 17 00:00:00 2001 From: ygrek Date: Sat, 9 May 2009 00:09:41 +0300 Subject: [PATCH] + IN --- sql_lexer.mll | 2 +- sql_parser.mly | 34 +++++++++++++++++++++++++++++----- tables.ml | 1 + 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/sql_lexer.mll b/sql_lexer.mll index 09153e1..f3d5986 100644 --- a/sql_lexer.mll +++ b/sql_lexer.mll @@ -76,7 +76,7 @@ let keywords = "having",HAVING; ] in let all token l = k := !k @ List.map (fun x -> x,token) l in - all (FUNCTION (Some T.Int)) ["max"; "min"; "length"; "random";]; + all (FUNCTION (Some T.Int)) ["max"; "min"; "length"; "random";"count"]; all (FUNCTION (Some T.Text)) ["concat";]; all CONFLICT_ALGO ["ignore"; "replace"; "abort"; "fail"; "rollback";]; all JOIN_TYPE1 ["left";"right";"full"]; diff --git a/sql_parser.mly b/sql_parser.mly index 22209c6..cf7eb6c 100644 --- a/sql_parser.mly +++ b/sql_parser.mly @@ -31,14 +31,16 @@ %token SELECT INSERT OR INTO CREATE UPDATE TABLE VALUES WHERE ASTERISK DISTINCT ALL LIMIT ORDER BY DESC ASC EQUAL DELETE FROM DEFAULT OFFSET SET JOIN LIKE_OP EXCL TILDE NOT TEST_NULL BETWEEN AND ESCAPE USING COMPOUND_OP AS - CONCAT_OP JOIN_TYPE1 JOIN_TYPE2 NATURAL REPLACE + CONCAT_OP JOIN_TYPE1 JOIN_TYPE2 NATURAL REPLACE IN GROUP HAVING %token UNIQUE PRIMARY KEY AUTOINCREMENT ON CONFLICT %token NUM_BINARY_OP PLUS MINUS %token T_INTEGER T_BLOB T_TEXT +%left TEST_NULL %left AND OR %nonassoc EQUAL %nonassoc NUM_BINARY_OP +%left MATCH %left PLUS MINUS %left ASTERISK @@ -96,11 +98,15 @@ select_stmt: select_core list(preceded(COMPOUND_OP,select_core)) o=loption(order select_core: SELECT select_type? r=separated_nonempty_list(COMMA,column1) FROM t=table_list w=where? + g=loption(group) + h=having? { let (tbls,p2) = t in let p1 = Syntax.params_of_columns tbls r in let p3 = Syntax.get_params_opt tbls w in - (Syntax.get_scheme r tbls, p1 @ p2 @ p3, tbls) + let p4 = Syntax.get_params_l tbls g in + let p5 = Syntax.get_params_opt tbls h in + (Syntax.get_scheme r tbls, p1 @ p2 @ p3 @ p4 @ p5, tbls) } table_list: source join_source* @@ -143,6 +149,8 @@ order: ORDER BY l=separated_nonempty_list(COMMA,terminated(expr,order_type?)) { order_type: DESC | ASC { } where: WHERE e=expr { e } +group: GROUP BY l=separated_nonempty_list(COMMA,expr) { l } +having: HAVING e=expr { e } column1: | IDENT DOT ASTERISK { Syntax.AllOf $1 } @@ -165,17 +173,33 @@ set_column: name=IDENT EQUAL e=expr { name,e } (* expr: expr1 { $1 >> Syntax.expr_to_string >> prerr_endline; $1 } *) +mnot(X): NOT x = X | x = X { x } + expr: expr numeric_bin_op expr %prec PLUS { `Func ((Some Int),[$1;$3]) } | expr boolean_bin_op expr %prec AND { `Func ((Some Int),[$1;$3]) } | expr CONCAT_OP expr { `Func ((Some Text),[$1;$3]) } -(* | expr NOT? LIKE_OP expr (*escape?*) { Sub [$1;$4] } *) -(* | unary_op expr { $2 } *) + | e1=expr mnot(LIKE_OP) e2=expr (*escape?*) %prec MATCH { `Func (None,[e1;e2]) } + | unary_op expr { $2 } | LPAREN expr RPAREN { $2 } | IDENT { `Column ($1,None) } | t=IDENT DOT c=IDENT | IDENT DOT t=IDENT DOT c=IDENT { `Column (c,Some t) } | INTEGER { `Value Int } + | e1=expr mnot(IN) LPAREN l=separated_nonempty_list(COMMA,expr) RPAREN { `Func (None,e1::l) } + | e1=expr mnot(IN) LPAREN select=select_stmt RPAREN + { + let (s,p) = select in + if (List.length s <> 1) then + raise (RA.Scheme.Error (s,"only one column allowed for IN operator")); + let l = List.map (fun x -> `Param x) p in + `Func (None,e1::l) + } + | e1=expr IN table=IDENT + { + Tables.check(table); + e1 + } (* | FLOAT { `Value Float } *) | TEXT { `Value Text } | BLOB { `Value Blob } @@ -195,7 +219,7 @@ unary_op: EXCL { } | PLUS { } | MINUS { } | TILDE { } - | NOT { } ; + | NOT { } sql_type: T_INTEGER { Type.Int } | T_BLOB { Type.Blob } diff --git a/tables.ml b/tables.ml index 5a8942f..b1e5d16 100644 --- a/tables.ml +++ b/tables.ml @@ -14,6 +14,7 @@ let get_from tables name = let get name = get_from !all name let get_scheme name = snd (get name) +let check name = ignore (get name) let add v = let (name,scheme) = v in -- 2.11.4.GIT