open StdLabels module Table = ImportDataTypes.Table module Path = ImportDataTypes.Path module Expression = ImportExpression.T open Ppx_yojson_conv_lib.Yojson_conv.Primitives let current_syntax = 1 let rec expression_of_yojson : (Yojson.Safe.t -> 'a) -> Yojson.Safe.t -> 'a Expression.t = fun f expr -> match expr with | `Null -> Empty | `List l -> Concat (List.map ~f:(expression_of_yojson f) l) | `String s as json -> ( try Path (f json) with | _ -> Literal s) | `Assoc [ (fn, `List [ `List l1; `List l2 ]) ] when String.equal "counter" (String.lowercase_ascii fn) -> Window ( Expression.Counter, List.map ~f:(expression_of_yojson f) l1, List.map ~f:(expression_of_yojson f) l2 ) | `Assoc [ (fn, `List [ expr1; `List l2; `List l3 ]) ] when String.equal "previous" (String.lowercase_ascii fn) -> Window ( Expression.Previous (expression_of_yojson f expr1), List.map ~f:(expression_of_yojson f) l2, List.map ~f:(expression_of_yojson f) l3 ) | `Assoc [ (fn, `List l) ] when String.equal "nvl" (String.lowercase_ascii fn) -> Nvl (List.map ~f:(expression_of_yojson f) l) | `Assoc [ (fn, `List l) ] -> Function (String.lowercase_ascii fn, List.map ~f:(expression_of_yojson f) l) | json -> ( try Path (f json) with | _ -> let str_json = Yojson.Safe.pretty_to_string json in raise (ImportErrors.JsonError { json = str_json; element = "Expression" }) ) type 'a expression = 'a Expression.t type column = Path.column let column_of_yojson : Yojson.Safe.t -> int = function | `Int i -> i | `String s -> ImportCSV.Csv.column_of_string s | _ -> raise (Invalid_argument "column") let yojson_of_column i = `String (ImportCSV.Csv.column_to_string i) type path = Syntax.Path.t = { alias : string option; [@default None] [@yojson_drop_default ( = )] (* External file to load, when the information is missing, load in the current file *) column : column; } [@@deriving of_yojson] let path_of_yojson : Yojson.Safe.t -> path = function | `String s -> Scanf.sscanf s ":%s@.%s" (fun table column -> if String.equal column "" then { alias = None; column = ImportCSV.Csv.column_of_string table } else { alias = Some table; column = ImportCSV.Csv.column_of_string column; }) | other -> path_of_yojson other let yojson_of_path : path -> Yojson.Safe.t = fun { alias; column } -> let table = match alias with | None -> "" | Some table -> String.cat table "." in `String (String.concat ~sep:"" [ ":"; table; ImportCSV.Csv.column_to_string column ]) type table = Table.t = { file : string; tab : int; [@default 1] [@yojson_drop_default ( = )] name : string; } [@@deriving of_yojson] type extern = { source : string option; [@default None] [@yojson_drop_default ( = )] intern_key : column expression; target : table; extern_key : column expression; allow_missing : bool; [@default false] [@yojson_drop_default ( = )] match_rule : string option; [@default None] [@yojson_drop_default ( = )] } [@@deriving of_yojson] type syntax_v1_extern = Syntax.extern let syntax_v1_extern_of_yojson yojson = let e = extern_of_yojson yojson in let intern_key : path Expression.t = Expression.map e.intern_key ~f:(fun column -> Syntax.Path.{ column; alias = e.source }) in Syntax. { extern_key = e.extern_key; intern_key; target = e.target; allow_missing = e.allow_missing; match_rule = e.match_rule; } type predicate = unit let predicate_of_yojson _ = () let yojson_of_predicate () = `Null type t = Syntax.t = { version : int; [@default current_syntax] source : table; externals : syntax_v1_extern list; [@default []] columns : path expression list; filters : path expression list; [@default []] [@yojson_drop_default ( = )] sort : path expression list; [@default []] [@yojson_drop_default ( = )] uniq : path expression list; [@default []] [@yojson_drop_default ( = )] } [@@deriving of_yojson]