1 (** SQL syntax and RA *)
7 type expr
= [ `Value
of Type.t
(** literal value *)
9 | `Func
of (Type.t
* bool) * expr list
(** return type, grouping, parameters *)
10 | `Column
of string * string option (** name, table *)
14 type expr_q
= [ `Value
of Type.t
(** literal value *)
16 | `Func
of (Type.t
* bool) * expr_q list
(** return type, grouping, parameters *)
20 let expr_to_string = Show.show
<expr
>
25 | Expr
of expr
* string option (** name *)
28 type columns
= column list deriving
(Show
)
30 let collect f l
= List.flatten
(List.map f l
)
33 let schema_as_params = List.map
(fun attr
-> (Some attr
.RA.name
,(0,0)), Some attr
.RA.domain
)
35 (** replace every Column with Value of corresponding type *)
36 let resolve_columns tables joined_schema expr
=
37 let schema_of_table name
= name
>> Tables.get_from tables
>> snd
in
40 | `Value x
-> `Value x
41 | `Column
(name
,table
) ->
42 let attr = RA.Schema.find
(Option.map_default
schema_of_table joined_schema table
) 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 *)
54 | `Func
((ret
,g
),l
) ->
55 (** Assumption: sql functions/operators have type schema '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
((<>) Type.Any
) t with
60 | h
::t -> if List.for_all
((=) h
) t then h
else Type.Any
63 | `Param
(n
,Type.Any
) -> `Param
(n
,t)
66 let ret = if Type.Any
<> ret then ret else t in
67 `Func
((ret,g
),(List.map
assign l
)),ret
68 | `Param
(_
,t) -> e
, t
72 let show_e e
= Show.show
<expr_q
> (e
) >> print_endline
74 let resolve_types tables joined_schema expr
=
76 >> resolve_columns tables joined_schema
77 >> tee
(if Sqlgg_config.debug1
() then show_e else ignore
)
79 >> tee
(if Sqlgg_config.debug1
() then print_newline $
show_e $ fst
else ignore
)
81 let infer_schema columns tables joined_schema
=
82 (* let all = tables >> List.map snd >> List.flatten in *)
83 let schema name
= name
>> Tables.get_from tables
>> snd
in
84 let resolve1 = function
85 | All
-> joined_schema
90 | `Column
(name
,Some
t) -> RA.Schema.find
(schema t) name
91 | `Column
(name
,None
) -> RA.Schema.find joined_schema name
92 | _
-> RA.attr "" (resolve_types tables joined_schema e
>> snd
)
94 let col = Option.map_default
(fun n
-> {col with RA.name
= n
}) col name
in
97 collect resolve1 columns
99 let test_all_grouping columns
=
101 (* grouping function of zero or single parameter *)
102 | Expr
(`Func
((_
,true),args
),_
) when List.length args
<= 1 -> true
105 List.for_all
test columns
107 let test_all_const columns
=
108 let rec is_const = function
109 | `Func
(_
,args
) -> List.for_all
is_const args
114 | Expr
(e
,_
) -> is_const e
117 List.for_all
test columns
123 | `Func
(_
,l
) -> List.fold_left
loop acc l
126 loop [] e
>> List.rev
128 let get_params tables joined_schema e
=
129 e
>> resolve_types tables joined_schema
>> fst
>> get_params_q
133 let e = Sub [Value Type.Text; Param (Next,None); Sub []; Param (Named "ds", Some Type.Int);] in
134 e >> get_params >> to_string >> print_endline
137 let params_of_column tables j_s
= function
138 | All
| AllOf
_ -> []
139 | Expr
(e,_) -> get_params tables j_s
e
141 let params_of_columns tables j_s
= collect (params_of_column tables j_s
)
143 let get_params_opt tables j_s
= function
144 | Some x
-> get_params tables j_s x
147 let get_params_l tables j_s l
= collect (get_params tables j_s
) l
149 let do_join (tables
,params
,schema) ((table1
,params1
),kind
) =
150 let (_,schema1
) = table1
in
151 let tables = tables @ [table1
] in
152 let schema = match kind
with
155 | `Default
-> RA.Schema.cross
schema schema1
156 | `Natural
-> RA.Schema.natural
schema schema1
157 | `Using l
-> RA.Schema.join_using l
schema schema1
159 let p = match kind
with
160 | `Cross
| `Default
| `Natural
| `Using
_ -> []
161 | `Search
e -> get_params tables schema e
163 tables,params
@ params1
@ p , schema
165 let join ((t0
,p0
),joins
) =
166 let (tables,params
,joined_schema
) = List.fold_left
do_join ([t0
],p0
,snd t0
) joins
in
167 (* let joined_schema = tables >> List.map snd >> List.flatten in *)
168 (tables,params
,joined_schema)
170 let cross = List.fold_left
RA.Schema.cross []
172 (* all columns from tables, without duplicates *)
173 (* FIXME check type of duplicates *)
174 let all_columns = RA.Schema.make_unique $
cross
175 let all_tbl_columns = all_columns $
List.map snd
177 let split_column_assignments tables l
=
179 let exprs = ref [] in
180 let all = all_tbl_columns tables in
181 List.iter
(fun ((cname
,tname
as col),expr
) ->
182 cols := col :: !cols;
185 | Some name
-> Tables.get_from
tables name
>> snd
188 (* hint expression to unify with the column type *)
189 let typ = (RA.Schema.find
schema cname
).RA.domain
in
190 exprs := (`Func
((Type.Any
,false), [`Value
typ;expr
])) :: !exprs) l
;
191 (List.rev
!cols, List.rev
!exprs)
193 let params_of_assigns tables ss
=
194 let (_,exprs) = split_column_assignments tables ss
in
195 get_params_l tables (cross (List.map snd
tables)) exprs
197 let params_of_order o final_schema
tables =
198 get_params_l tables (final_schema
:: (List.map snd
tables) >> all_columns) o
200 let rec ensure_simple_expr = function
201 | `Value
_ | `Param
_ as x
-> x
202 | `Column
_ -> failwith
"Not a simple expression"
203 | `Func
((_,grouping
),_) when grouping
-> failwith
"Grouping function not allowed in simple expression"
204 | `Func
(x
,l
) -> `Func
(x
,List.map
ensure_simple_expr l
)