Source

hello / sql / main.ml

let parse_sql q =
  let lexbuf = Lexing.from_string q in
  try
    Sql_parser.input Sql_lexer.token lexbuf
  with
    | exn ->
      print_endline (Printexc.to_string exn);
      raise exn;;

let parse_json q =
  let lexbuf = Lexing.from_string q in
  try
    Json_parser.input Json_lexer.token lexbuf
  with
    | exn ->
      print_endline (Printexc.to_string exn);
      raise exn;;

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 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();;