1 (* SQL syntax and RA *)
8 type expr
= [ `Value
of Sql.Type.t
(** literal value *)
10 | `Func
of Sql.Type.t
option * expr list
(** return type, parameters *)
11 | `Column
of string * string option (** name, table *)
15 type expr_q
= [ `Value
of Sql.Type.t
(** literal value *)
17 | `Func
of Sql.Type.t
option * expr_q list
(** return type, parameters *)
21 let expr_to_string = Show.show
<expr
>
26 | Expr
of expr
* string option (** name *)
29 type columns
= column list deriving
(Show
)
31 let collect f l
= List.flatten
(List.map f l
)
33 let scheme_as_params = List.map
(fun attr
-> Named attr
.RA.name
, Some attr
.RA.domain
)
35 (** replace every Column with Value of corresponding type *)
36 let resolve_columns tables joined_scheme expr
=
37 let scheme name
= name
>> Tables.get_from tables
>> snd
in
40 | `Value x
-> `Value x
42 let attr = RA.Scheme.find
(Option.map_default
scheme joined_scheme x
) name
in
44 | `Param x
-> `Param x
45 | `Func
(r
,l
) -> `Func
(r
,(List.map
each l
))
49 (** assign types to parameters where possible *)
50 let assign_types expr
=
51 let rec typeof e
= (* FIXME simplify *)
53 | `Value t
-> e
, Some t
55 (** Assumption: sql functions/operators have type scheme 'a -> ... -> 'a -> 'a -> 'b
56 i.e. all parameters of some equal type *)
57 let (l
,t
) = l
>> List.map
typeof >> List.split
in
58 let t = match List.filter_valid
t with
60 | h
::t -> if List.for_all
((=) h
) t then Some h
else None
63 print_endline (Show.show<expr_q list>(l));
64 print_endline (Show.show<Sql.Type.t option>(t));
67 | `Param
(n
,None
) -> `Param
(n
,t)
70 let ret = if Option.is_some
ret then ret else t in
71 `Func
(ret,(List.map
assign l
)),ret
72 | `Param
(_
,t) -> e
, t
76 let show_e e
= Show.show
<expr_q
> (e
) >> print_endline
78 let resolve_types tables joined_scheme expr
=
80 >> resolve_columns tables joined_scheme
84 let infer_scheme columns tables joined_scheme
=
85 (* let all = tables >> List.map snd >> List.flatten in *)
86 let scheme name
= name
>> Tables.get_from tables
>> snd
in
87 let resolve1 = function
88 | All
-> joined_scheme
93 | `Column
(name
,Some
t) -> RA.Scheme.find
(scheme t) name
94 | `Column
(name
,None
) -> RA.Scheme.find joined_scheme name
95 | _
-> RA.attr "" (Option.default
Sql.Type.Text
(resolve_types tables joined_scheme e
>> snd
))
97 let col = Option.map_default
(fun n
-> {col with RA.name
= n
}) col name
in
100 collect resolve1 columns
106 | `Func
(_
,l
) -> List.fold_left
loop acc l
109 loop [] e
>> List.rev
111 let get_params tables joined_scheme e
=
112 e
>> resolve_types tables joined_scheme
>> fst
>> get_params
116 let e = Sub [Value Sql.Type.Text; Param (Next,None); Sub []; Param (Named "ds", Some Sql.Type.Int);] in
117 e >> get_params >> to_string >> print_endline
120 let params_of_column tables j_s
= function
121 | All
| AllOf
_ -> []
122 | Expr
(e,_) -> get_params tables j_s
e
124 let params_of_columns tables j_s
= collect (params_of_column tables j_s
)
126 let get_params_opt tables j_s
= function
127 | Some x
-> get_params tables j_s x
130 let get_params_l tables j_s l
= collect (get_params tables j_s
) l
132 let do_join (tables
,params
,scheme) ((table1
,params1
),kind
) =
133 let (_,scheme1
) = table1
in
134 let tables = tables @ [table1
] in
136 let scheme = match kind
with
138 | `Default
-> RA.Scheme.cross
scheme scheme1
139 | `Natural
-> RA.Scheme.natural
scheme scheme1
140 | `Using l
-> RA.Scheme.join_using l
scheme scheme1
141 | `Search
e -> begin p := get_params tables scheme e; RA.Scheme.cross
scheme scheme1
end
143 tables,params
@ params1
@ !p,scheme
145 let join ((t0
,p0
),joins
) =
146 let (tables,params
,joined_scheme
) = List.fold_left
do_join ([t0
],p0
,snd t0
) joins
in
147 (* let joined_scheme = tables >> List.map snd >> List.flatten in *)
148 (tables,params
,joined_scheme)