warn named duplicates only, tweak grammar
[sqlgg.git] / rA.ml
blobbcd3dd83a430446eb4f8d6ba0fb88827f4ca773d
1 (*
2 Relational Algebra
3 *)
5 open ListMore
6 open Printf
7 open Operators
9 module Type = Sql.Type
11 type attr = {name : string; domain : Type.t;}
12 deriving (Show)
14 let attr n d = {name=n;domain=d}
16 module Scheme =
17 struct
18 type t = attr list
19 deriving (Show)
21 exception Error of t * string
23 let find t name =
24 match List.find_all (fun attr -> attr.name = name) t with
25 | [x] -> x
26 | [] -> raise (Error (t,"missing attribute : " ^ name))
27 | _ -> raise (Error (t,"duplicate attribute : " ^ name))
29 let is_unique t =
30 let t1 = List.unique ~cmp:(fun a1 a2 -> a1.name = a2.name && a1.name <> "") t in
31 List.length t1 = List.length t
33 let check_unique t = is_unique t || raise (Error (t,"duplicate attributes"))
35 let project names t = List.map (find t) names
37 let rename t before after =
38 List.map (fun attr ->
39 match attr.name with
40 | x when x = before -> { attr with name=after }
41 | _ -> attr ) t
43 let cross t1 t2 = t1 @ t2
45 (** [contains t attr] tests whether schema [t] contains attribute [attr] *)
46 let contains t attr = find t attr.name = attr
48 let check_contains t attr =
49 if not (contains t attr) then
50 raise (Error (t,"type mismatch for attribute " ^ attr.name))
52 let sub l a = List.filter (fun x -> not (List.mem x a)) l
54 let to_string v = Show.show<t>(v)
55 let names t = t >> List.map (fun attr -> attr.name) >> String.concat "," >> sprintf "[%s]"
57 let natural_ t1 t2 =
58 let (common,t1only) = List.partition (fun x -> List.mem x t2) t1 in
59 if 0 = List.length common then failwith "natural'";
60 let t2only = sub t2 common in
61 common @ t1only @ t2only
63 let natural t1 t2 =
64 try natural_ t1 t2 with
65 | _ -> raise (Error (t1,"no common attributes for natural join of " ^
66 (names t1) ^ " and " ^ (names t2)))
68 let join_using l t1 t2 =
69 let common = List.map (find t1) l in
70 List.iter (check_contains t2) common;
71 common @ sub t1 common @ sub t2 common
73 (* FIXME? should be less strict -- check only types *)
74 let compound t1 t2 =
75 if t1 <> t2 then
76 raise (Error (t1, (to_string t1) ^ " not equal to " ^ (to_string t2)))
77 else
80 let to_string x = Show.show<t>(x)
81 let print x = prerr_endline (to_string x)
83 end
85 type table = string * Scheme.t deriving (Show)
87 let print_table t = print_endline (Show.show<table>(t))
90 open Scheme
92 let test = [{name="a";domain=Type.Int}; {name="b";domain=Type.Int}; {name="c";domain=Type.Text};];;
94 let () = print test
95 let () = print (project ["b";"c";"b"] test)
96 let () = print (project ["b";"d"] test)
97 let () = print (rename test "a" "new_a")