aboutsummaryrefslogtreecommitdiffstats
path: root/lib/drl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/drl')
-rw-r--r--lib/drl/ast.ml25
-rw-r--r--lib/drl/executor.ml70
-rw-r--r--lib/drl/parser.ml9
3 files changed, 104 insertions, 0 deletions
diff --git a/lib/drl/ast.ml b/lib/drl/ast.ml
new file mode 100644
index 0000000..f94965d
--- /dev/null
+++ b/lib/drl/ast.ml
@@ -0,0 +1,25 @@
+open Sexplib.Std
+
+(** Literal values for Const nodes *)
+type value =
+ | Int of int
+ | Float of float
+ | Str of string
+ | Bool of bool
+[@@deriving sexp]
+
+type direction = Asc | Desc
+[@@deriving sexp]
+
+type query =
+ | Base of string (** base relation by name *)
+ | Const of (string * value) list (** constant single-tuple relation *)
+ | Select of query * query (** σ semijoin: (filter, source) *)
+ | Join of string list * query * query (** ⋈ natural equijoin on named attrs *)
+ | Cartesian of query * query (** × Cartesian product *)
+ | Project of string list * query (** π restrict columns *)
+ | Rename of (string * string) list * query (** ρ rename (old,new) pairs *)
+ | Union of query * query (** ∪ — compatible schemas assumed *)
+ | Diff of query * query (** − *)
+ | Take of int * query (** τ *)
+[@@deriving sexp]
diff --git a/lib/drl/executor.ml b/lib/drl/executor.ml
new file mode 100644
index 0000000..7588b33
--- /dev/null
+++ b/lib/drl/executor.ml
@@ -0,0 +1,70 @@
+module Make(Storage : Management.Physical.S) = struct
+ module Alg = Algebra.Make(Storage)
+ module Ops = Manipulation.Make(Storage)
+
+ type error =
+ | RelationNotFound of string
+ | AlgebraError of Algebra.error
+
+ let wrap = Result.map_error (fun e -> AlgebraError e)
+
+ (* Convert Ast.value → AbstractValue.t (Obj.t) via Obj.repr *)
+ let ast_value_to_abstract : Ast.value -> Conventions.AbstractValue.t = function
+ | Ast.Int n -> Obj.repr n
+ | Ast.Float f -> Obj.repr f
+ | Ast.Str s -> Obj.repr s
+ | Ast.Bool b -> Obj.repr b
+
+ let rec execute
+ (storage : Storage.t)
+ (db : Management.Database.t)
+ (q : Ast.query)
+ : (Relation.t, error) Result.t =
+ let ( >>= ) = Result.bind in
+ match q with
+ | Ast.Base name ->
+ (match Ops.get_relation db ~name with
+ | None -> Error (RelationNotFound name)
+ | Some rel -> Ok rel)
+ | Ast.Const pairs ->
+ Ok (Alg.const_relation
+ (List.map (fun (k, v) -> (k, ast_value_to_abstract v)) pairs))
+ | Ast.Select (filter_q, source_q) ->
+ execute storage db filter_q >>= fun filter ->
+ execute storage db source_q >>= fun source ->
+ (* semijoin = project(source attrs, equijoin on common attrs) *)
+ let common = List.filter_map (fun (n, _) ->
+ if List.exists (fun (m, _) -> m = n) filter.Relation.schema
+ then Some n else None) source.Relation.schema in
+ let source_attrs = List.map fst source.Relation.schema in
+ wrap (Alg.equijoin storage common source filter) >>= fun joined ->
+ wrap (Alg.project storage source_attrs joined)
+ | Ast.Join (attrs, q1, q2) ->
+ execute storage db q1 >>= fun r1 ->
+ execute storage db q2 >>= fun r2 ->
+ wrap (Alg.equijoin storage attrs r1 r2)
+ | Ast.Project (attrs, q) ->
+ execute storage db q >>= fun rel ->
+ wrap (Alg.project storage attrs rel)
+ | Ast.Rename (renames, q) ->
+ execute storage db q >>= fun rel ->
+ wrap (Alg.rename storage renames rel)
+ | Ast.Cartesian (q1, q2) ->
+ execute storage db q1 >>= fun r1 ->
+ execute storage db q2 >>= fun r2 ->
+ (* Cartesian product = join on no attrs *)
+ wrap (Alg.equijoin storage [] r1 r2)
+ | Ast.Union (q1, q2) ->
+ execute storage db q1 >>= fun r1 ->
+ execute storage db q2 >>= fun r2 ->
+ wrap (Alg.union storage r1 r2)
+ | Ast.Diff (q1, q2) ->
+ execute storage db q1 >>= fun r1 ->
+ execute storage db q2 >>= fun r2 ->
+ wrap (Alg.diff storage r1 r2)
+ | Ast.Take (n, q) ->
+ execute storage db q >>= fun rel ->
+ wrap (Alg.take storage n rel)
+end
+
+module Memory = Make(Management.Physical.Memory)
diff --git a/lib/drl/parser.ml b/lib/drl/parser.ml
new file mode 100644
index 0000000..71d694b
--- /dev/null
+++ b/lib/drl/parser.ml
@@ -0,0 +1,9 @@
+type error = ParseError of string
+
+let of_string s =
+ match Sexplib.Sexp.of_string s |> Ast.query_of_sexp with
+ | q -> Ok q
+ | exception exn -> Error (ParseError (Printexc.to_string exn))
+
+let to_string q =
+ Ast.sexp_of_query q |> Sexplib.Sexp.to_string_hum