Oracle example, fails
[sqlgg.git] / rA.ml
blobd98fcecf6bccbef71bbfd8d0b720bebc379e5736
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 Schema =
17 struct
18 type t = attr list
19 deriving (Show)
21 exception Error of t * string
23 (** FIXME attribute case sensitivity? *)
24 let by_name name = function attr -> attr.name = name
25 let find_by_name t name = List.find_all (by_name name) t
27 let find t name =
28 match find_by_name t name with
29 | [x] -> x
30 | [] -> raise (Error (t,"missing attribute : " ^ name))
31 | _ -> raise (Error (t,"duplicate attribute : " ^ name))
33 let make_unique = List.unique ~cmp:(fun a1 a2 -> a1.name = a2.name && a1.name <> "")
34 let is_unique t = List.length (make_unique t) = List.length t
35 let check_unique t = is_unique t || raise (Error (t,"duplicate attributes"))
37 let project names t = List.map (find t) names
39 let rename t before after =
40 List.map (fun attr ->
41 match attr.name with
42 | x when x = before -> { attr with name=after }
43 | _ -> attr ) t
45 let cross t1 t2 = t1 @ t2
47 (** [contains t attr] tests whether schema [t] contains attribute [attr] *)
48 let contains t attr = find t attr.name = attr
50 let check_contains t attr =
51 if not (contains t attr) then
52 raise (Error (t,"type mismatch for attribute " ^ attr.name))
54 let sub l a = List.filter (fun x -> not (List.mem x a)) l
56 let to_string v = Show.show<t>(v)
57 let names t = t >> List.map (fun attr -> attr.name) >> String.concat "," >> sprintf "[%s]"
59 let natural_ t1 t2 =
60 let (common,t1only) = List.partition (fun x -> List.mem x t2) t1 in
61 if 0 = List.length common then failwith "natural'";
62 let t2only = sub t2 common in
63 common @ t1only @ t2only
65 let natural t1 t2 =
66 try natural_ t1 t2 with
67 | _ -> raise (Error (t1,"no common attributes for natural join of " ^
68 (names t1) ^ " and " ^ (names t2)))
70 let join_using l t1 t2 =
71 let common = List.map (find t1) l in
72 List.iter (check_contains t2) common;
73 common @ sub t1 common @ sub t2 common
75 let compound t1 t2 =
76 let types = List.map (fun attr -> attr.domain) in
77 if types t1 <> types t2 then
78 raise (Error (t1, (to_string t1) ^ " not equal to " ^ (to_string t2)))
79 else
82 let add t col pos =
83 match find_by_name t col.name with
84 | [] ->
85 begin
86 match pos with
87 | `First -> col::t
88 | `Last -> t @ [col]
89 | `After name ->
90 try
91 let (i,_) = List.findi (fun _ attr -> by_name name attr) t in
92 let (l1,l2) = List.split_nth (i+1) t in
93 l1 @ (col :: l2)
94 with
95 Not_found -> raise (Error (t,"Can't insert column " ^ col.name ^ " after non-existing column " ^ name))
96 end
97 | _ -> raise (Error (t,"Already has column " ^ col.name))
99 let drop t col =
100 ignore (find t col);
101 List.remove_if (by_name col) t
103 let to_string x = Show.show<t>(x)
104 let print x = prerr_endline (to_string x)
108 type table = string * Schema.t deriving (Show)
110 let print_table t = print_endline (Show.show<table>(t))
113 open Schema
115 let test = [{name="a";domain=Type.Int}; {name="b";domain=Type.Int}; {name="c";domain=Type.Text};];;
117 let () = print test
118 let () = print (project ["b";"c";"b"] test)
119 let () = print (project ["b";"d"] test)
120 let () = print (rename test "a" "new_a")