(** val negb : bool -> bool **)
let negb = function
| true -> false
| false -> true
(** val fst : ('a1 * 'a2) -> 'a1 **)
let fst = function
| (x, _) -> x
(** val snd : ('a1 * 'a2) -> 'a2 **)
let snd = function
| (_, y) -> y
(** val app : 'a1 list -> 'a1 list -> 'a1 list **)
let rec app l m =
match l with
| [] -> m
| a :: l1 -> a :: (app l1 m)
(** val map : ('a1 -> 'a2) -> 'a1 list -> 'a2 list **)
let rec map f = function
| [] -> []
| a :: l0 -> (f a) :: (map f l0)
(** val firstn : int -> 'a1 list -> 'a1 list **)
let rec firstn n l =
(fun fO fS n -> if n=0 then fO () else fS (n-1))
(fun _ -> [])
(fun n0 -> match l with
| [] -> []
| a :: l0 -> a :: (firstn n0 l0))
n
(** val flat_map : ('a1 -> 'a2 list) -> 'a1 list -> 'a2 list **)
let rec flat_map f = function
| [] -> []
| x :: l0 -> app (f x) (flat_map f l0)
(** val existsb : ('a1 -> bool) -> 'a1 list -> bool **)
let rec existsb f = function
| [] -> false
| a :: l0 -> (||) (f a) (existsb f l0)
(** val forallb : ('a1 -> bool) -> 'a1 list -> bool **)
let rec forallb f = function
| [] -> true
| a :: l0 -> (&&) (f a) (forallb f l0)
(** val filter : ('a1 -> bool) -> 'a1 list -> 'a1 list **)
let rec filter f = function
| [] -> []
| x :: l0 -> if f x then x :: (filter f l0) else filter f l0
(** val find : ('a1 -> bool) -> 'a1 list -> 'a1 option **)
let rec find f = function
| [] -> None
| x :: tl -> if f x then Some x else find f tl
(** val eqb : char list -> char list -> bool **)
let rec eqb s1 s2 =
match s1 with
| [] -> (match s2 with
| [] -> true
| _::_ -> false)
| c1::s1' ->
(match s2 with
| [] -> false
| c2::s2' -> if (=) c1 c2 then eqb s1' s2' else false)
(** val append : char list -> char list -> char list **)
let rec append s1 s2 =
match s1 with
| [] -> s2
| c::s1' -> c::(append s1' s2)
type attr_name = char list
type domain_name = char list
type schema = (attr_name * domain_name) list
(** val has_attr : attr_name -> schema -> bool **)
let has_attr a s =
existsb (fun p -> eqb a (fst p)) s
(** val attr_names : schema -> attr_name list **)
let attr_names s =
map fst s
(** val filter_schema : attr_name list -> schema -> schema **)
let filter_schema attrs s =
filter (fun p -> existsb (eqb (fst p)) attrs) s
(** val merge_schema : schema -> schema -> schema **)
let merge_schema s1 s2 =
app s1 (filter (fun p -> negb (has_attr (fst p) s1)) s2)
(** val remove_attrs : attr_name list -> schema -> schema **)
let remove_attrs attrs s =
filter (fun p -> negb (existsb (eqb (fst p)) attrs)) s
(** val rename_in_schema :
(attr_name * attr_name) list -> schema -> schema **)
let rename_in_schema renames s =
map (fun p ->
let a = fst p in
let d = snd p in
(match find (fun r -> eqb a (fst r)) renames with
| Some p0 -> let (_, a') = p0 in (a', d)
| None -> (a, d)))
s
type value (* AXIOM TO BE REALIZED *)
(** val value_eqb : value -> value -> bool **)
let value_eqb =
failwith "AXIOM TO BE REALIZED (Sakura.Relation.value_eqb)"
type tuple = (attr_name * value) list
(** val tuple_lookup : attr_name -> tuple -> value option **)
let rec tuple_lookup a = function
| [] -> None
| p :: rest ->
let (a', v) = p in if eqb a a' then Some v else tuple_lookup a rest
(** val project_tuple : attr_name list -> tuple -> tuple **)
let project_tuple attrs t =
filter (fun p -> existsb (eqb (fst p)) attrs) t
(** val rename_tuple : (attr_name * attr_name) list -> tuple -> tuple **)
let rename_tuple renames t =
map (fun p ->
let a = fst p in
let v = snd p in
(match find (fun r -> eqb a (fst r)) renames with
| Some p0 -> let (_, a') = p0 in (a', v)
| None -> (a, v)))
t
(** val merge_tuples : tuple -> tuple -> tuple **)
let merge_tuples t1 t2 =
app t1 (filter (fun p -> negb (existsb (eqb (fst p)) (map fst t1))) t2)
(** val tuples_agree_on : attr_name list -> tuple -> tuple -> bool **)
let tuples_agree_on attrs t1 t2 =
forallb (fun a ->
match tuple_lookup a t1 with
| Some v1 ->
(match tuple_lookup a t2 with
| Some v2 -> value_eqb v1 v2
| None -> false)
| None -> (match tuple_lookup a t2 with
| Some _ -> false
| None -> true))
attrs
type relation = { rel_name : char list; rel_schema : schema;
rel_tuples : tuple list }
type database = (char list * relation) list
(** val db_lookup : char list -> database -> relation option **)
let rec db_lookup name = function
| [] -> None
| p :: rest ->
let (n, r) = p in if eqb name n then Some r else db_lookup name rest
type literal =
| LitInt of int
| LitStr of char list
| LitBool of bool
type query =
| Base of char list
| Const of (attr_name * literal) list
| Select of query * query
| Join of attr_name list * query * query
| Cartesian of query * query
| Project of attr_name list * query
| Rename of (attr_name * attr_name) list * query
| Union of query * query
| Diff of query * query
| Take of int * query
(** val predicted_schema : database -> query -> schema option **)
let rec predicted_schema db = function
| Base name ->
(match db_lookup name db with
| Some r -> Some r.rel_schema
| None -> None)
| Const pairs ->
Some
(map (fun p -> ((fst p),
('a'::('b'::('s'::('t'::('r'::('a'::('c'::('t'::[])))))))))) pairs)
| Select (_, source) -> predicted_schema db source
| Join (attrs, q1, q2) ->
(match predicted_schema db q1 with
| Some s1 ->
(match predicted_schema db q2 with
| Some s2 ->
Some
(merge_schema s1
(remove_attrs (attr_names s1) (remove_attrs attrs s2)))
| None -> None)
| None -> None)
| Cartesian (q1, q2) ->
(match predicted_schema db q1 with
| Some s1 ->
(match predicted_schema db q2 with
| Some s2 -> Some (merge_schema s1 s2)
| None -> None)
| None -> None)
| Project (attrs, q') ->
(match predicted_schema db q' with
| Some s -> Some (filter_schema attrs s)
| None -> None)
| Rename (renames, q') ->
(match predicted_schema db q' with
| Some s -> Some (rename_in_schema renames s)
| None -> None)
| Union (q1, _) -> predicted_schema db q1
| Diff (q1, _) -> predicted_schema db q1
| Take (_, q') -> predicted_schema db q'
(** val literal_to_value : literal -> value **)
let literal_to_value =
failwith "AXIOM TO BE REALIZED (Sakura.Drl.literal_to_value)"
(** val eval_const : (attr_name * literal) list -> relation **)
let eval_const pairs =
let tuple0 = map (fun p -> ((fst p), (literal_to_value (snd p)))) pairs in
let sch =
map (fun p -> ((fst p),
('a'::('b'::('s'::('t'::('r'::('a'::('c'::('t'::[])))))))))) pairs
in
{ rel_name = ('c'::('o'::('n'::('s'::('t'::[]))))); rel_schema = sch;
rel_tuples = (tuple0 :: []) }
(** val semijoin : relation -> relation -> relation **)
let semijoin filter_rel source =
let common =
filter (fun a -> has_attr a filter_rel.rel_schema)
(attr_names source.rel_schema)
in
let matches = fun t ->
existsb (fun ft -> tuples_agree_on common t ft) filter_rel.rel_tuples
in
{ rel_name = source.rel_name; rel_schema = source.rel_schema; rel_tuples =
(filter matches source.rel_tuples) }
(** val equijoin : attr_name list -> relation -> relation -> relation **)
let equijoin attrs left right =
let joined =
flat_map (fun lt ->
flat_map (fun rt ->
if tuples_agree_on attrs lt rt then (merge_tuples lt rt) :: [] else [])
right.rel_tuples)
left.rel_tuples
in
let new_schema =
merge_schema left.rel_schema
(remove_attrs (attr_names left.rel_schema)
(remove_attrs attrs right.rel_schema))
in
{ rel_name =
(append ('j'::('o'::('i'::('n'::('_'::[])))))
(append left.rel_name (append ('_'::[]) right.rel_name)));
rel_schema = new_schema; rel_tuples = joined }
(** val cartesian : relation -> relation -> relation **)
let cartesian left right =
let joined =
flat_map (fun lt -> map (fun rt -> merge_tuples lt rt) right.rel_tuples)
left.rel_tuples
in
{ rel_name =
(append ('c'::('a'::('r'::('t'::('_'::[])))))
(append left.rel_name (append ('_'::[]) right.rel_name)));
rel_schema = (merge_schema left.rel_schema right.rel_schema); rel_tuples =
joined }
(** val project : attr_name list -> relation -> relation **)
let project attrs r =
{ rel_name = (append ('p'::('r'::('o'::('j'::('_'::[]))))) r.rel_name);
rel_schema = (filter_schema attrs r.rel_schema); rel_tuples =
(map (project_tuple attrs) r.rel_tuples) }
(** val rename : (attr_name * attr_name) list -> relation -> relation **)
let rename renames r =
{ rel_name =
(append ('r'::('e'::('n'::('a'::('m'::('e'::('_'::[]))))))) r.rel_name);
rel_schema = (rename_in_schema renames r.rel_schema); rel_tuples =
(map (rename_tuple renames) r.rel_tuples) }
(** val rel_union : relation -> relation -> relation **)
let rel_union r1 r2 =
{ rel_name =
(append ('u'::('n'::('i'::('o'::('n'::('_'::[]))))))
(append r1.rel_name (append ('_'::[]) r2.rel_name)));
rel_schema = r1.rel_schema; rel_tuples =
(app r1.rel_tuples r2.rel_tuples) }
(** val rel_diff : relation -> relation -> relation **)
let rel_diff r1 r2 =
let in_r2 = fun t ->
existsb (fun t2 -> tuples_agree_on (attr_names r1.rel_schema) t t2)
r2.rel_tuples
in
{ rel_name =
(append ('d'::('i'::('f'::('f'::('_'::[])))))
(append r1.rel_name (append ('_'::[]) r2.rel_name)));
rel_schema = r1.rel_schema; rel_tuples =
(filter (fun t -> negb (in_r2 t)) r1.rel_tuples) }
(** val take : int -> relation -> relation **)
let take n r =
{ rel_name = (append ('t'::('a'::('k'::('e'::('_'::[]))))) r.rel_name);
rel_schema = r.rel_schema; rel_tuples = (firstn n r.rel_tuples) }
(** val eval : database -> query -> relation option **)
let rec eval db = function
| Base name -> db_lookup name db
| Const pairs -> Some (eval_const pairs)
| Select (filter_q, source_q) ->
(match eval db filter_q with
| Some filter_rel ->
(match eval db source_q with
| Some source_rel -> Some (semijoin filter_rel source_rel)
| None -> None)
| None -> None)
| Join (attrs, q1, q2) ->
(match eval db q1 with
| Some r1 ->
(match eval db q2 with
| Some r2 -> Some (equijoin attrs r1 r2)
| None -> None)
| None -> None)
| Cartesian (q1, q2) ->
(match eval db q1 with
| Some r1 ->
(match eval db q2 with
| Some r2 -> Some (cartesian r1 r2)
| None -> None)
| None -> None)
| Project (attrs, q') ->
(match eval db q' with
| Some r -> Some (project attrs r)
| None -> None)
| Rename (renames, q') ->
(match eval db q' with
| Some r -> Some (rename renames r)
| None -> None)
| Union (q1, q2) ->
(match eval db q1 with
| Some r1 ->
(match eval db q2 with
| Some r2 -> Some (rel_union r1 r2)
| None -> None)
| None -> None)
| Diff (q1, q2) ->
(match eval db q1 with
| Some r1 ->
(match eval db q2 with
| Some r2 -> Some (rel_diff r1 r2)
| None -> None)
| None -> None)
| Take (n, q') ->
(match eval db q' with
| Some r -> Some (take n r)
| None -> None)