Commits

Kota UENISHI committed 8b655c3

query engine...?

Comments (0)

Files changed (8)

 # OCAML_LIB_FLAGS +=
 
 .DEFAULT: $(OCamlProgram $(PROGRAM), $(FILES))
+
+test: $(PROGRAM)
 	./$(PROGRAM)

sql/json_lexer.mll

     in_quote := false;
     QUOTE (String.sub quote_buf 0 (!quote_ptr))
   }
-  | "\n"         { print "f"; token lexbuf }
-  | digit as i { INT(int_of_string i) }
+  | "\n"       { print "f"; token lexbuf }
+  | digit as s { print ">>"; print s; INT(int_of_string s) }
 (*  | eof	         { print "eof."; EOF } *)
   | _            { token lexbuf }
 and quote = parse

sql/json_parser.mly

 
 %{
 
-  open Printf
-  let _ = Parsing.set_trace false;;
+  let _ = Parsing.set_trace true;;
   let debugprint = ref true;;
   
   let print str = if !debugprint then print_endline str;;
 
 exp:
   | value { $1 }
-
+;
 value:
   | QUOTE { Json.String($1) }
   | INT   { Json.Number(Json.Int($1)) }
   | FALSE { Json.Bool(false)}
   | NULL  { Json.Null }
 ;
-
 pairs:
   | QUOTE COLON value { [($1, $3)] }
   | QUOTE COLON value COMMA pairs
       { ($1, $3)::$5 }
-
+;
 values:
   | value { [$1] }
   | value COMMA values { $1::$3 }
+;
       print_endline (Printexc.to_string exn);
       raise exn;;
 
-let sample_query = "select * from mytable where colA == 'foo'";;
+let parse_json_file filename =
+  let lexbuf = Lexing.from_channel (open_in filename) in
+  try
+    Json_parser.input Json_lexer.token lexbuf
+  with
+    | exn ->
+      print_endline (Printexc.to_string exn);
+      raise exn;;
+
+let sample_query = "select * from mytable where colA == 'foo';";;
 let sample_json  = "{ \"hello\":\"world!\", \"v\": 345, \"a\": [23,3,4, 0] }";;
 
-let _ =
+
+let test() =
   print_endline sample_query;
 (*  Sql.pp_query (Sql.Select(Sql.Columns(["hoge"; "hage"]), "tttttttttttttt")); *)
   let q = parse_sql sample_query in
   Sql.pp_query q;
+
+  print_endline "select * from testooo;";
+  let q = parse_sql "select * from testooo;" in
+  Sql.pp_query q;
+
   print_endline sample_json;
   let j = parse_json sample_json in
   print_endline (Json.pp_json j);
+
   print_endline " => hello";;
 
+let rec eval_pairs cond = function
+  | [] -> false;
+  | (k,Json.Number(Json.Int(v)))::tl ->
+    begin match cond with
+      | Sql.Gt_i(k, i) -> v > i;
+      | Sql.Lt_i(k, i) -> v < i;
+      | Sql.Equal_i(k, i) -> v = i;
+      | _ -> eval_pairs cond tl
+    end
+  | (k,Json.Number(Json.Float(v)))::tl ->
+    begin match cond with
+      | Sql.Gt_f(k, f) -> v > f;
+      | Sql.Lt_f(k, f) -> v < f;
+      | _ -> eval_pairs cond tl
+    end
+  | (k,Json.String(s))::tl ->
+    begin match cond with
+      | Sql.Equal_s(k, v) -> s = v;
+      | Sql.Regexp(_,_) -> raise Sql.Not_implemented_regexp;
+      | _ -> eval_pairs cond tl
+    end
+  | _::tl -> eval_pairs cond tl;;
+
+
+let rec eval_cond pairs = function
+  | Sql.And(c0, c1) -> (eval_cond pairs c0) && (eval_cond pairs c1);
+  | Sql.Or(c0, c1)  -> (eval_cond pairs c0) || (eval_cond pairs c1);
+  | Sql.Not(c)      -> not (eval_cond pairs c);
+  | c -> eval_pairs c pairs;;
+
+let eval_conds conds = function
+  | Json.Object(pairs) ->
+    List.for_all (eval_cond pairs) conds;
+  | _ -> false;;
+
+let rec get_col col = function
+  | [] -> Json.Null;
+  | (k,v)::_ when k=col -> v;
+  | _::tl  -> get_col col tl;;
+
+let run_query q data =
+  match q with
+    | Sql.Select(Sql.All_col,_,conds)->
+      let ans_rows = List.filter (eval_conds conds) data in
+      ans_rows;
+    | Sql.Select(Sql.Columns(cols),_,conds) ->
+      let ans_rows = List.filter (eval_conds conds) data in
+      ans_rows;; (* TODO *)
+
+let rec do_loop () =
+  print_string "> ";
+  let line = read_line() in
+  let q = parse_sql line in
+  Sql.pp_query q;
+  let table_name = Sql.get_table_name q in
+  let json = parse_json_file (table_name ^ ".json") in
+  let ans = run_query q [json] in
+  List.iter print_endline (List.map Json.pp_json ans);
+  do_loop();;
+
+let _ =
+  (* test();; *)
+  do_loop();;
 type query = Select of columns * string * condition list
              (* columns, table, wheres *)
 
+exception Not_implemented_regexp
+
 let pp_cols = function
   | All_col -> "*";
   | Columns(cols) -> (String.concat "," cols);;
 let pp_query = function
   | Select(columns, table, where) ->
     Printf.printf "select: %s from %s where %s\n" (pp_cols columns) table (pp_where where);;
+
+let get_table_name = function
+  | Select(_, table, _) -> table;;

sql/sql_lexer.mll

 {
 
 open Sql_parser
-let debugprint = ref false;;
+let debugprint = ref true;;
 let print str =  if !debugprint then print_endline str;;
 
 let quote_buf = String.create 8192;;
   | ","      { COMMA }
   | "*"      { ASTERISK }
   | "=="     { EQUAL }
+  | ';'      { SEMICOLON }
   | "'"      {
     in_quote := true;
     quote_ptr := 0;
     quote lexbuf;
     in_quote := false;
-     QUOTE (String.sub quote_buf 0 (!quote_ptr))
+    QUOTE (String.sub quote_buf 0 (!quote_ptr))
   }
-  | literal as s { LITERAL(s) }
-  | "\n"         { print "f"; token lexbuf }
-(*  | eof	         { print "eof."; EOF } *)
-  | _            { token lexbuf }
+  | digit as s { print "<<<"; print s; INT(int_of_string s) }
+  | literal as s { print s; LITERAL(s) }
+(*  | "\n"         { print "f"; token lexbuf } *)
+  | _ as c       { print_char c; print "boo";  token lexbuf }
 and quote = parse
   | "'"  { () }
   | _ as c {
-    (* print_char c; *)
     String.set quote_buf (!quote_ptr) c;
     quote_ptr := (!quote_ptr) + 1;
     quote lexbuf
   }
 
-
 {}

sql/sql_parser.mly

 
 %{
 
-  open Printf
   let _ = Parsing.set_trace true;;
   let debugprint = ref true;;
   
   let print str = if !debugprint then print_endline str;;
-  
   let parse_error s = print ("parse_error->"^s);;
 
 %}
 %token DOT
 %token LBRACE RBRACE
 %token COMMA
+%token SEMICOLON
 %token ASTERISK
 %token GT LT EQ NEQ NOT
 %token EQUAL
 input: | exp { $1 };
 
 exp:
-  | SELECT ASTERISK FROM LITERAL { Sql.Select(Sql.All_col, $4, []) }
-  | SELECT columns  FROM LITERAL { Sql.Select(Sql.Columns($2), $4, []) }
-  | SELECT ASTERISK FROM LITERAL where_clause { Sql.Select(Sql.All_col, $4, $5) }
-  | SELECT columns  FROM LITERAL where_clause { Sql.Select(Sql.Columns($2), $4, $5) }
+  | SELECT ASTERISK FROM LITERAL SEMICOLON
+      { print "here<";  print $4; Sql.Select(Sql.All_col, $4, []) }
+  | SELECT columns  FROM LITERAL SEMICOLON
+      { print "here<<"; print $4; Sql.Select(Sql.Columns($2), $4, []) }
+
+  | SELECT ASTERISK FROM LITERAL where_clause SEMICOLON
+      { print "hehe"; print $4; Sql.Select(Sql.All_col, $4, $5) }
+  | SELECT columns  FROM LITERAL where_clause SEMICOLON
+      { print "hoho"; print $4; Sql.Select(Sql.Columns($2), $4, $5) }
+;
 
 columns:
   | LITERAL  { [$1] }
-{ "hello":"world" }
+{ "hello":"world", "foo":"bar" }