(** 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) type attr_name = char list type relation = { rel_name : char list; rel_finite : bool } 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_finite : database -> query -> bool option **) let rec predicted_finite db = function | Base name -> ( match db_lookup name db with Some r -> Some r.rel_finite | None -> None) | Select (_, source) -> predicted_finite db source | Join (_, q1, q2) -> ( match predicted_finite db q1 with | Some f1 -> ( match predicted_finite db q2 with | Some f2 -> Some (f1 && f2) | None -> None) | None -> None) | Cartesian (q1, q2) -> ( match predicted_finite db q1 with | Some f1 -> ( match predicted_finite db q2 with | Some f2 -> Some (f1 && f2) | None -> None) | None -> None) | Project (_, q0) -> predicted_finite db q0 | Rename (_, q0) -> predicted_finite db q0 | Union (q1, q2) -> ( match predicted_finite db q1 with | Some f1 -> ( match predicted_finite db q2 with | Some f2 -> Some (f1 && f2) | None -> None) | None -> None) | Diff (q1, _) -> predicted_finite db q1 | _ -> Some true