diff options
Diffstat (limited to 'lib/analysers/query.ml')
-rw-r--r-- | lib/analysers/query.ml | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/lib/analysers/query.ml b/lib/analysers/query.ml index dff3b9d..bcf4a72 100644 --- a/lib/analysers/query.ml +++ b/lib/analysers/query.ml @@ -273,6 +273,49 @@ type query = { parameters : ImportCSV.DataType.t Seq.t; } +let rec take_elements : + prefix:'a list -> eq:('a -> 'a -> bool) -> 'a list -> 'a list = + fun ~prefix ~eq group -> + match (prefix, group) with + | [], any -> any + | _, [] -> [] + | hd1 :: tl1, hd2 :: tl2 when eq hd1 hd2 -> take_elements ~eq ~prefix:tl1 tl2 + | _, _ -> raise Not_found + +(** The window functions shall be grouped in the same way as the uniq property. + (We cannot make a partition over a group not kept in the final result). + + But the SQL query need to remove from the window function the elements + already defined in the group by statement, and we need to filter them from + the configuration before building the query. *) +let clean_window : + prefix:Path.t ImportExpression.T.t list -> + Path.t ImportExpression.T.t -> + Path.t ImportExpression.T.t = + fun ~prefix expression -> + let open ImportExpression.T in + let rec f = function + | Expr e -> Expr (f e) + | Empty -> Empty + | Literal s -> Literal s + | Integer i -> Integer i + | Path p -> Path p + | Concat pp -> Concat (List.map ~f pp) + | Function' (name, pp) -> Function' (name, List.map ~f pp) + | Function (name, pp) -> Function (name, List.map ~f pp) + | Nvl pp -> Nvl (List.map ~f pp) + | Join (sep, pp) -> Join (sep, List.map ~f pp) + | Window (window_f, group, order) -> + let w = map_window ~f window_f in + let group = + take_elements ~eq:(ImportExpression.T.equal Path.equal) ~prefix group + in + Window (w, List.map ~f group, List.map ~f order) + | BOperator (n, arg1, arg2) -> BOperator (n, f arg1, f arg2) + | GEquality (n, arg1, args) -> GEquality (n, f arg1, List.map ~f args) + in + f expression + (** Build the query and return also the mapping in order to identify each external links between files. @@ -301,7 +344,17 @@ let select : Syntax.t -> query * Path.t ImportExpression.T.t array = *) let headers = Array.make (List.length conf.columns) (Obj.magic None) in - let columns = List.to_seq conf.columns |> Seq.mapi (fun i c -> (i, c)) in + (* Transform the columns to extract from the query. + - Associate each of them with a number + - Clean the window functions and remove the part already defined in the + [uniq] parameter. + *) + let columns = + List.to_seq conf.columns + |> Seq.mapi (fun i c -> + let expression = c in + (i, clean_window ~prefix:conf.uniq expression)) + in let formatter = Format.formatter_of_buffer b in let () = Format.fprintf formatter "SELECT %a" |