open StdLabels module Path = ImportDataTypes.Path module Expression = ImportExpression.T type t = { filters : Path.t Expression.t list; group : Path.t Expression.t option; } (** Ensure the group criteria in window functions match the global group by criteria. Traverse the configuration tree until finding a group window. *) (** Check if the expression contains a group function *) let matchWindowGroup : 'a ImportExpression.T.t -> bool = fun expression -> let exception Found in let open ImportExpression.T in let rec f = function | Empty | Literal _ | Integer _ | Path _ -> () | Expr e -> f e | Concat pp | Function' (_, pp) | Function (_, pp) | Nvl pp | Join (_, pp) -> List.iter ~f pp | Window (_, _, _) -> raise Found | BOperator (_, arg1, arg2) -> f arg1; f arg2 | GEquality (_, arg1, args) -> f arg1; List.iter ~f args in try f expression; false with | Found -> true (** Transform a list of expression into a list of CTE to evaluate. *) let of_filters : Path.t Expression.t list -> t list = fun filters -> let last_group, prev = List.fold_left filters ~init:({ filters = []; group = None }, []) ~f:(fun (cte, acc) expr -> begin if matchWindowGroup expr then ( { filters = []; group = None }, { cte with group = Some expr } :: acc ) else ({ cte with filters = expr :: cte.filters }, acc) end) in List.rev (last_group :: prev)