aboutsummaryrefslogtreecommitdiff
path: root/lib/expression
diff options
context:
space:
mode:
authorSébastien Dailly <sebastien@dailly.me>2025-03-01 08:39:02 +0100
committerSébastien Dailly <sebastien@dailly.me>2025-03-06 20:57:10 +0100
commit81db1bfd580791910646525e30bc45af34533987 (patch)
treec610f53c284d3707a3d6fe49486b5c09e66dc41f /lib/expression
parent67320d8f04e1f302306b9aafdaaf4bafcf443839 (diff)
Rewrite the way to handle filters
Diffstat (limited to 'lib/expression')
-rw-r--r--lib/expression/_readme.rst39
-rw-r--r--lib/expression/filters.ml193
-rw-r--r--lib/expression/filters.mli9
3 files changed, 39 insertions, 202 deletions
diff --git a/lib/expression/_readme.rst b/lib/expression/_readme.rst
new file mode 100644
index 0000000..729a950
--- /dev/null
+++ b/lib/expression/_readme.rst
@@ -0,0 +1,39 @@
+All thoses modules transforms an expression.
+
+Simple transformations
+----------------------
+
+:Ast:
+
+ Regenerate the Ast from the expression
+
+:Repr:
+
+ Generate a representable string
+
+:Type_of:
+
+ Infer the type of an expression
+
+:Compose:
+
+ Allow to use a module into another one.
+
+:Headers:
+
+ Extract the headers to display in the result file
+
+Composed transformations
+------------------------
+
+:Filter:
+
+ Generate the filters in the query. This module identify if one the
+ expression is actually a group window and handle a special case for this.
+
+ This module relies on Ast
+
+:Query:
+
+ Build an sql query. This module relies on Type_of
+
diff --git a/lib/expression/filters.ml b/lib/expression/filters.ml
deleted file mode 100644
index 42c794b..0000000
--- a/lib/expression/filters.ml
+++ /dev/null
@@ -1,193 +0,0 @@
-(** This module evaluate the sql query to use in order to filter an expression
-
- The result is built over [Query] except for the group function, which are
- translated into a CTE in sql
- *)
-
-open StdLabels
-module Q = Query
-
-type 'a result = {
- repr : Format.formatter -> nested:Query.QueryParameter.t -> unit;
- group : 'a T.t option;
-}
-
-module Filter = struct
- type 'a repr = {
- repr : 'a Q.Query.repr;
- with_group : 'a T.t option;
- }
-
- type 'a obs = 'a result
- type 'a path_repr = 'a Q.Query.path_repr
-
- let observe : 'a Ast.obs * 'a repr -> 'a obs =
- fun (_, v) -> { repr = Q.Query.observe v.repr; group = v.with_group }
-
- let empty : 'a Ast.obs -> 'a repr =
- fun _ -> { repr = Q.Query.empty (); with_group = None }
-
- let expr : 'a Ast.obs * 'a repr -> 'a Ast.obs -> 'a repr =
- fun (_, expr) _ ->
- { repr = Q.Query.expr expr.repr; with_group = expr.with_group }
-
- let path : 'a path_repr -> 'a -> 'a Ast.obs -> 'a repr =
- fun repr p _ -> { repr = Q.Query.path repr p; with_group = None }
-
- let literal : string -> 'a Ast.obs -> 'a repr =
- fun l _ -> { repr = Q.Query.literal l; with_group = None }
-
- let integer : string -> 'a Ast.obs -> 'a repr =
- fun l _ -> { repr = Q.Query.integer l; with_group = None }
-
- let nvl : ('a Ast.obs * 'a repr) list -> 'a Ast.obs -> 'a repr =
- fun expression _ ->
- let expr_repr = List.map ~f:(fun v -> (snd v).repr) expression in
- let with_group =
- List.find_map ~f:(fun v -> (snd v).with_group) expression
- in
- match with_group with
- | None -> { repr = Q.Query.nvl expr_repr; with_group }
- | Some _ -> raise ImportErrors.MisplacedWindow
-
- let concat : ('a Ast.obs * 'a repr) list -> 'a Ast.obs -> 'a repr =
- fun expression _ ->
- let expr_repr = List.map ~f:(fun v -> (snd v).repr) expression in
- let with_group =
- List.find_map ~f:(fun v -> (snd v).with_group) expression
- in
- match with_group with
- | None -> { repr = Q.Query.concat expr_repr; with_group }
- | Some _ -> raise ImportErrors.MisplacedWindow
-
- let join : string -> ('a Ast.obs * 'a repr) list -> 'a Ast.obs -> 'a repr =
- fun sep expression _ ->
- let expr_repr = List.map ~f:(fun v -> (snd v).repr) expression
- and with_group =
- List.find_map ~f:(fun v -> (snd v).with_group) expression
- in
- match with_group with
- | None -> { repr = Q.Query.join sep expr_repr; with_group }
- | Some _ -> raise ImportErrors.MisplacedWindow
-
- let boperator :
- T.binary_operator ->
- 'a Ast.obs * 'a repr ->
- 'a Ast.obs * 'a repr ->
- 'a Ast.obs ->
- 'a repr =
- fun name (_, e1) (_, e2) _ ->
- let with_group =
- match (e1.with_group, e2.with_group) with
- | Some e, None -> Some e
- | None, Some e -> Some e
- | None, None -> None
- | _ -> raise ImportErrors.MisplacedWindow
- in
- { repr = Q.Query.boperator name e1.repr e2.repr; with_group }
-
- let gequality :
- T.binary_operator ->
- 'a Ast.obs * 'a repr ->
- ('a Ast.obs * 'a repr) list ->
- 'a Ast.obs ->
- 'a repr =
- fun name (_, e1) group _ ->
- let group_repr = List.map ~f:(fun v -> (snd v).repr) group
- and with_group = List.find_map ~f:(fun v -> (snd v).with_group) group in
-
- match with_group with
- | None ->
- {
- repr = Q.Query.gequality name e1.repr group_repr;
- with_group = e1.with_group;
- }
- | _ -> raise ImportErrors.MisplacedWindow
-
- let funct : string -> ('a Ast.obs * 'a repr) list -> 'a Ast.obs -> 'a repr =
- fun name expressions _ ->
- let expr_repr = List.map ~f:(fun v -> (snd v).repr) expressions in
- let with_group =
- List.find_map ~f:(fun v -> (snd v).with_group) expressions
- in
- match with_group with
- | None -> { repr = Q.Query.funct name expr_repr; with_group }
- | Some _ -> raise ImportErrors.MisplacedWindow
-
- let function' :
- T.funct -> ('a Ast.obs * 'a repr) list -> 'a Ast.obs -> 'a repr =
- fun name expressions _ ->
- let expr_repr = List.map ~f:(fun v -> (snd v).repr) expressions in
- let with_group =
- List.find_map ~f:(fun v -> (snd v).with_group) expressions
- in
- match with_group with
- | None ->
- { repr = Q.Query.funct (T.name_of_function name) expr_repr; with_group }
- | Some _ -> raise ImportErrors.MisplacedWindow
-
- (** Window functions are not handled in the filters, we save them as an AST
- in order to process them in a separated handler.
-
- It is not allowed to build nested window functions. *)
- let window :
- ('a Ast.obs * 'a repr) T.window ->
- ('a Ast.obs * 'a repr) list ->
- ('a Ast.obs * 'a repr) list ->
- 'a Ast.obs ->
- 'a repr =
- fun name expressions order ast ->
- ignore name;
- let with_group_expr =
- List.find_map ~f:(fun v -> (snd v).with_group) expressions
- and with_group_order =
- List.find_map ~f:(fun v -> (snd v).with_group) order
- in
- match (with_group_expr, with_group_order) with
- | Some _, _ | _, Some _ -> raise ImportErrors.MisplacedWindow
- | None, None ->
- (* The column name used with the cte. The name is fixed here, and used
- as is in [Analysers.Query.build_cte] and
- [Analysers.Query.eval_filters] *)
- let q = "cte.group0" in
- {
- with_group = Some ast;
- repr = Q.Query.funct "expr" [ Q.Query.literal q ];
- }
-end
-
-module ASTBuilder =
- Compose.Expression
- (Ast)
- (struct
- let v = ()
- end)
-
-module F :
- Sym.SYM_EXPR
- with type 'a obs = 'a result
- and type 'a path_repr = Format.formatter -> 'a -> unit =
- ASTBuilder.Make (Filter)
-
-module M = Sym.M (F)
-
-let query_of_expression :
- type b.
- b Q.binded_query ->
- Format.formatter ->
- (Format.formatter -> 'a -> unit) ->
- 'a T.t ->
- b * 'a T.t option =
- fun parameter formatter printer expr ->
- let repr = M.eval ~path_repr:printer expr in
- match parameter with
- | BindParam ->
- let p = Queue.create () in
- let parameter = Q.QueryParameter.Queue p in
- let value = F.observe repr in
- value.repr ~nested:parameter formatter;
- (p, value.group)
- | NoParam ->
- let value = F.observe repr in
- value.repr ~nested:Literal formatter;
- ((), value.group)
diff --git a/lib/expression/filters.mli b/lib/expression/filters.mli
deleted file mode 100644
index d462b5f..0000000
--- a/lib/expression/filters.mli
+++ /dev/null
@@ -1,9 +0,0 @@
-module F : Sym.SYM_EXPR with type 'a path_repr = Format.formatter -> 'a -> unit
-(** Query used inside the filter clauses *)
-
-val query_of_expression :
- 'b Query.binded_query ->
- Format.formatter ->
- (Format.formatter -> 'a -> unit) ->
- 'a T.t ->
- 'b * 'a T.t option