diff options
Diffstat (limited to 'lib/syntax/cte.ml')
-rw-r--r-- | lib/syntax/cte.ml | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/syntax/cte.ml b/lib/syntax/cte.ml new file mode 100644 index 0000000..ff43d6d --- /dev/null +++ b/lib/syntax/cte.ml @@ -0,0 +1,53 @@ +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) |