mfotl2sql.ml 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. (********************************************************************
  2. MFOTL to SQL translation
  3. Author: Eugen Zalinescu (eugen.zalinescu@inf.ethz.ch)
  4. Copyright (C) 2013 ETHZ
  5. Version 0.1
  6. *********************************************************************)
  7. open Predicate
  8. open MFOTL
  9. (* We follow more or less the book "Foundations of Databases"
  10. by Abiteboul, Hull, and Vianu. *)
  11. type col = int
  12. type 'c col_eq = 'c * 'c
  13. type 'c col_minus = 'c * 'c
  14. type 'c col_expr = 'c col_minus (* only this is needed (for now?) *)
  15. (* selection constraints *)
  16. type 'c sel_constraint =
  17. | Eq_Col of 'c * 'c
  18. | Eq_Val of 'c * cst
  19. | Eq_Null of 'c
  20. | NEq_Col of 'c * 'c
  21. | NEq_Val of 'c * cst
  22. | Less_Col of 'c * 'c
  23. | Less_Col_Val of 'c * cst
  24. | Less_Val_Col of cst * 'c
  25. | LEq_Col of 'c * 'c
  26. | LEq_Col_Val of 'c * cst
  27. | Leq_Val_Col of cst * 'c
  28. | Less_ColExpr_Val of ('c col_expr) * cst
  29. | Less_Val_ColExpr of cst * ('c col_expr)
  30. | LEq_ColExpr_Val of ('c col_expr) * cst
  31. | LEq_Val_ColExpr of cst * ('c col_expr)
  32. (* expressions in (unnamed) relational algebra *)
  33. type ra_expr =
  34. | TCst of cst (* a unary table with one element *)
  35. | Table of string (* name *)
  36. | Sel of col sel_constraint * ra_expr (* atomic selection, subsumed by generalized selection *)
  37. | Proj of col list * ra_expr (* the columns on which the projection is made *)
  38. | CrossProd of ra_expr * ra_expr
  39. | Union of ra_expr * ra_expr
  40. | Diff of ra_expr * ra_expr
  41. | Inter of ra_expr * ra_expr
  42. | GSel of col sel_constraint list * ra_expr
  43. | EquiJoin of col col_eq list * ra_expr * ra_expr
  44. (* btw, the last 3 operators can be expressed in terms of the previous ones *)
  45. | AntiJoin of col col_eq list * ra_expr * ra_expr (* only introduced because some RDBMSs do not support Diff *)
  46. (* TODO: add function to check well-definedness *)
  47. (* TODO: add function to transform expressions into normal form *)
  48. (*** some auxiliary functions ***)
  49. let tbl_time = "time"
  50. let id = fun x -> x
  51. let shift x = x + 2
  52. let apply_shift = List.map shift
  53. let string_of_list del f l =
  54. let rec enum = function
  55. | [] -> ""
  56. | [h] -> f h
  57. | h :: t -> (f h) ^ del ^ (enum t)
  58. in
  59. enum l
  60. (* all integers between [m] and [n] *)
  61. let all_ints m n =
  62. let rec f i acc =
  63. if i < m then
  64. acc
  65. else
  66. f (i-1) (i :: acc)
  67. in
  68. f n []
  69. let all_pos l =
  70. let rec allpos i = function
  71. | [] -> []
  72. | _ :: t -> i :: allpos (i+1) t
  73. in
  74. allpos 0 l
  75. let all_pos' l =
  76. [0; 1] @ apply_shift (all_pos l)
  77. let get_matches fv1 fv2 =
  78. let rec matches crtpos = function
  79. | x :: t ->
  80. (try
  81. let pos2 = Misc.get_pos x fv2 in
  82. (crtpos, pos2) :: (matches (crtpos + 1) t)
  83. with Not_found ->
  84. matches (crtpos + 1) t
  85. )
  86. | [] -> []
  87. in
  88. matches 0 fv1
  89. (* we return a cuple of selection constraints and of columns on which
  90. the table will be projected *)
  91. (* we add 2 to each column: the first two columns are the timepoint and the timestamp *)
  92. let get_constraints terms =
  93. let rec get assign (constr, proj) pos = function
  94. | [] -> constr, proj
  95. | (Var x) :: rest ->
  96. if List.mem_assoc x assign then
  97. (* we have seen this variable before; add a constraint *)
  98. let posx = List.assoc x assign in
  99. get
  100. assign
  101. (constr @ [Eq_Col (shift posx, shift pos)], proj)
  102. (pos + 1)
  103. rest
  104. else
  105. (* it is a new variable; we will project on it; remember it *)
  106. get
  107. ((x, pos) :: assign)
  108. (constr, proj @ [shift pos])
  109. (pos + 1)
  110. rest
  111. | (Cst c) :: rest ->
  112. get assign (Eq_Val (shift pos, c) :: constr, proj) (pos + 1) rest
  113. in
  114. get [] ([], []) 0 terms
  115. (* we follow the structure of Rewriting.is_monitorable *)
  116. (* TODO: add assertions *)
  117. let mfotl2ra set_support f =
  118. let rec tf = function
  119. | Pred p ->
  120. let name, _, args = Predicate.get_info p in
  121. let constr, projs = get_constraints args in
  122. if projs = apply_shift (all_pos args) then
  123. if constr = [] then
  124. Table name
  125. else
  126. GSel (constr, Table name)
  127. else
  128. if constr = [] then
  129. Proj ([0; 1] @ projs, Table name)
  130. else
  131. Proj ([0; 1] @ projs, (GSel (constr, Table name)))
  132. | Neg f ->
  133. assert (MFOTL.free_vars f = []);
  134. let e = tf f in
  135. Diff (Table tbl_time, e)
  136. | And (f1, f2) ->
  137. let fv1 = MFOTL.free_vars f1 in
  138. let e1 = tf f1 in
  139. (match f2 with
  140. | Equal (Var x, Var y) ->
  141. if x = y then
  142. e1
  143. else
  144. let bx = List.mem x fv1 in
  145. let by = List.mem y fv1 in
  146. if bx && by then (* hence both x and y are free in f1 *)
  147. let posx = Misc.get_pos x fv1 in
  148. let posy = Misc.get_pos y fv1 in
  149. Sel (Eq_Col (shift posx, shift posy), e1)
  150. else if bx then
  151. let posx = Misc.get_pos x fv1 in
  152. Proj ((all_pos' fv1) @ [shift posx], e1)
  153. else if by then
  154. let posy = Misc.get_pos y fv1 in
  155. Proj ((all_pos' fv1) @ [shift posy], e1)
  156. else
  157. failwith "[tf] f1 AND (x=y)"
  158. | Equal (Var x, Cst c)
  159. | Equal (Cst c, Var x) ->
  160. if List.mem x fv1 then
  161. (* we select those tuples who's value of [x] is [c] *)
  162. let posx = Misc.get_pos x fv1 in
  163. Sel (Eq_Val (shift posx, c), e1)
  164. else (* we add a new column in which all values are [c] *)
  165. CrossProd (e1, TCst c)
  166. | Less (Cst c, Var y) ->
  167. let posy = Misc.get_pos y fv1 in
  168. Sel (Less_Val_Col (c, shift posy), e1)
  169. | Less (Var x, Cst c) ->
  170. let posx = Misc.get_pos x fv1 in
  171. Sel (Less_Col_Val (shift posx, c), e1)
  172. | Less (Var x, Var y) ->
  173. let posx = Misc.get_pos x fv1 in
  174. let posy = Misc.get_pos y fv1 in
  175. Sel (Less_Col (shift posx, shift posy), e1)
  176. | Neg (Equal (Var x, Var y)) ->
  177. let posx = Misc.get_pos x fv1 in
  178. let posy = Misc.get_pos y fv1 in
  179. Sel (NEq_Col (shift posx, shift posy), e1)
  180. | Neg (Equal (Var x, Cst c))
  181. | Neg (Equal (Cst c, Var x)) ->
  182. let posx = Misc.get_pos x fv1 in
  183. Sel (NEq_Val (shift posx, c), e1)
  184. | Neg (Less (Var x, Var y)) ->
  185. if x = y then (* then the formula f1 AND f2 is equiv. with f1 *)
  186. e1
  187. else
  188. if List.mem x fv1 && List.mem y fv1 then
  189. (* hence both x and y are free in f1 *)
  190. let posx = Misc.get_pos x fv1 in
  191. let posy = Misc.get_pos y fv1 in
  192. Sel (LEq_Col (shift posy, shift posx), e1)
  193. else
  194. failwith "[mfotl2ra] f1 AND (NOT (x<y))"
  195. | Neg (Less (Cst c, Var y)) when (List.mem y fv1) ->
  196. let posy = Misc.get_pos y fv1 in
  197. Sel (LEq_Col_Val (shift posy, c), e1)
  198. | Neg f2' ->
  199. let e2 = tf f2' in
  200. let fv2 = MFOTL.free_vars f2 in
  201. assert (Misc.subset fv2 fv1);
  202. let matches = get_matches fv1 fv2 in
  203. let matches' = [(0, 0); (1, 1)] @ List.map (fun (x, y) -> (shift x, shift y)) matches in
  204. if set_support then
  205. if fv1 = fv2 then
  206. Diff (e1, e2)
  207. else
  208. Diff (e1, (EquiJoin (matches', e1, e2)))
  209. else
  210. AntiJoin (matches', e1, e2)
  211. | _ ->
  212. let e2 = tf f2 in
  213. let fv2 = MFOTL.free_vars f2 in
  214. if set_support && fv1 = fv2 then
  215. Inter (e1, e2)
  216. else
  217. let matches = get_matches fv1 fv2 in
  218. let matches' = [(0, 0); (1, 1)] @ List.map (fun (x, y) -> (shift x, shift y)) matches in
  219. EquiJoin (matches', e1, e2)
  220. )
  221. | Or (f1, f2) -> Union (tf f1, tf f2)
  222. | Exists (x, f) ->
  223. let e = tf f in
  224. let fv = MFOTL.free_vars f in
  225. let rec pos i = function
  226. | [] -> []
  227. | h :: t ->
  228. let rest = pos (i+1) t in
  229. if h = x then rest else i :: rest
  230. in
  231. let pos_proj = apply_shift (pos 0 fv) in
  232. Proj ([0; 1] @ pos_proj, e)
  233. | Once (intv, f) ->
  234. let e = tf f in
  235. let n = List.length (MFOTL.free_vars f) in
  236. (* the first two columns are the timepoint and the timestamp columns in Time,
  237. the 3rd and 4th columns are the timepoint and the timestamp columns in [e] *)
  238. let proj = [0; 1] @ (all_ints 4 (n+3)) in
  239. let (l,r) = intv in
  240. let cst_of_ts ts = Int (int_of_float ts) in
  241. let bigger_than_l = function
  242. | CBnd a -> LEq_Val_ColExpr (cst_of_ts a, (1, 3))
  243. | OBnd a -> Less_Val_ColExpr (cst_of_ts a, (1, 3))
  244. | Inf -> failwith "[bigger_than_l] l <> Inf"
  245. in
  246. let smaller_than_r = function
  247. | CBnd b -> [LEq_ColExpr_Val ((1, 3), cst_of_ts b)]
  248. | OBnd b -> [Less_ColExpr_Val ((1, 3), cst_of_ts b)]
  249. | Inf -> []
  250. in
  251. let constraints = [LEq_Col (2, 0); bigger_than_l l] @ (smaller_than_r r) in
  252. Proj (proj, GSel (constraints, CrossProd ((Table tbl_time), e)))
  253. | Eventually (intv, f) ->
  254. let e = tf f in
  255. let n = List.length (MFOTL.free_vars f) in
  256. (* the first two columns are the timepoint and the timestamp columns in Time,
  257. the 3rd and 4th columns are the timepoint and the timestamp columns in [e] *)
  258. let proj = [0; 1] @ (all_ints 4 (n+3)) in
  259. let (l,r) = intv in
  260. let cst_of_ts ts = Int (int_of_float ts) in
  261. let bigger_than_l = function
  262. | CBnd a -> LEq_Val_ColExpr (cst_of_ts a, (3, 1))
  263. | OBnd a -> Less_Val_ColExpr (cst_of_ts a, (3, 1))
  264. | Inf -> failwith "[bigger_than_l] l <> Inf"
  265. in
  266. let smaller_than_r = function
  267. | CBnd b -> [LEq_ColExpr_Val ((3, 1), cst_of_ts b)]
  268. | OBnd b -> [Less_ColExpr_Val ((3, 1), cst_of_ts b)]
  269. | Inf -> []
  270. in
  271. let constraints = [LEq_Col (0, 2); bigger_than_l l] @ (smaller_than_r r) in
  272. Proj (proj, GSel (constraints, CrossProd ((Table tbl_time), e)))
  273. | Since (intv, Neg f1, f2) ->
  274. let fv1 = MFOTL.free_vars f1 in
  275. let fv2 = MFOTL.free_vars f2 in
  276. assert(Misc.subset fv1 fv2 && Misc.subset fv2 fv1);
  277. let e1 = tf f1 in
  278. let e2 = tf f2 in
  279. let n = List.length fv1 in
  280. (* the first two columns are the timepoint and the timestamp columns in Time,
  281. the 3rd and 4th columns are the timepoint and the timestamp columns in [e] *)
  282. let (l,r) = intv in
  283. let cst_of_ts ts = Int (int_of_float ts) in
  284. let bigger_than_l = function
  285. | CBnd a -> LEq_Val_ColExpr (cst_of_ts a, (1, 3))
  286. | OBnd a -> Less_Val_ColExpr (cst_of_ts a, (1, 3))
  287. | Inf -> failwith "[bigger_than_l] l <> Inf"
  288. in
  289. let smaller_than_r = function
  290. | CBnd b -> [LEq_ColExpr_Val ((1, 3), cst_of_ts b)]
  291. | OBnd b -> [Less_ColExpr_Val ((1, 3), cst_of_ts b)]
  292. | Inf -> []
  293. in
  294. let constraints = [LEq_Col (2, 0); bigger_than_l l] @ (smaller_than_r r) in
  295. let e2' = GSel (constraints, CrossProd ((Table tbl_time), e2)) in
  296. let e1_time = GSel (constraints, CrossProd ((Table tbl_time), (Table tbl_time))) in
  297. let constraints' = [LEq_Col (4, 0); Less_Col (2, 4)] in
  298. let proj' = [0; 1; 2; 3] @ (all_ints 6 (n+5)) in
  299. let e1' = Proj (proj', GSel (constraints', CrossProd (e1_time, e1))) in
  300. let proj = [0; 1] @ (all_ints 4 (n+3)) in
  301. Proj (proj, Diff (e2', e1'))
  302. (* | Since (intv, f1, f2) -> TODO *)
  303. (* need to rewrite \forall k. f1 as \neg\exists k.\neg f1 and push
  304. f2 inside the negation... *)
  305. | _ -> failwith "[mfotl2ra] either not possible or not yet implemented"
  306. in tf f
  307. (** Pretty-printing RA expressions **)
  308. let string_of_cst = function
  309. | Int n -> string_of_int n
  310. | Str s -> "'" ^ s ^ "'"
  311. let string_of_sel f = function
  312. | Eq_Col (col, col') -> (f col) ^ " = " ^ (f col')
  313. | Eq_Val (col, c) -> (f col) ^ " = " ^ (string_of_cst c)
  314. | Eq_Null col -> (f col) ^ " IS NULL"
  315. | NEq_Col (col, col') -> (f col) ^ " <> " ^ (f col')
  316. | NEq_Val (col, c) -> (f col) ^ " <> " ^ (string_of_cst c)
  317. | Less_Col (col, col') -> (f col) ^ " < " ^ (f col')
  318. | Less_Col_Val (col, c) -> (f col) ^ " < " ^ (string_of_cst c)
  319. | Less_Val_Col (c, col) -> (string_of_cst c) ^ " < " ^ (f col)
  320. | LEq_Col (col, col') -> (f col) ^ " <= " ^ (f col')
  321. | LEq_Col_Val (col, c) -> (f col) ^ " <= " ^ (string_of_cst c)
  322. | Leq_Val_Col (c, col) -> (string_of_cst c) ^ " <= " ^ (f col)
  323. | Less_ColExpr_Val ((col, col'), c) -> (f col) ^ " - " ^ (f col') ^ " < " ^ (string_of_cst c)
  324. | Less_Val_ColExpr (c, (col, col')) -> (string_of_cst c) ^ " < " ^ (f col) ^ " - " ^ (f col')
  325. | LEq_ColExpr_Val ((col, col'), c) -> (f col) ^ " - " ^ (f col') ^ " <= " ^ (string_of_cst c)
  326. | LEq_Val_ColExpr (c, (col, col')) -> (string_of_cst c) ^ " <= " ^ (f col) ^ " - " ^ (f col')
  327. let rec pr_string_of_ra ppf = function
  328. | TCst c ->
  329. Format.fprintf ppf "@[<2>TCst %s@]" (string_of_cst c)
  330. | Table t ->
  331. Format.fprintf ppf "@[<2>Table %s@]" t
  332. | Sel (sel, e) ->
  333. Format.fprintf ppf "@[<2>Sel %s@\n%a@]"
  334. (string_of_sel string_of_int sel)
  335. pr_string_of_ra e
  336. | Proj (projs, e) ->
  337. Format.fprintf ppf "@[<2>Proj %s@\n%a@]"
  338. (string_of_list ", " string_of_int projs)
  339. pr_string_of_ra e
  340. | CrossProd (e1, e2) ->
  341. Format.fprintf ppf "@[<2>CrossProd@\n%a@\n%a@]"
  342. pr_string_of_ra e1
  343. pr_string_of_ra e2
  344. | Union (e1, e2) ->
  345. Format.fprintf ppf "@[<2>Union@\n%a@\n%a@]"
  346. pr_string_of_ra e1
  347. pr_string_of_ra e2
  348. | Diff (e1, e2) ->
  349. Format.fprintf ppf "@[<2>Diff@\n%a@\n%a@]"
  350. pr_string_of_ra e1
  351. pr_string_of_ra e2
  352. | Inter (e1, e2) ->
  353. Format.fprintf ppf "@[<2>Inter@\n%a@\n%a@]"
  354. pr_string_of_ra e1
  355. pr_string_of_ra e2
  356. | GSel (sels, e) ->
  357. Format.fprintf ppf "@[<2>GSel %s@\n%a@]"
  358. (string_of_list ", " (string_of_sel string_of_int) sels)
  359. pr_string_of_ra e
  360. | EquiJoin (cols, e1, e2) ->
  361. Format.fprintf ppf "@[<2>EquiJoin %s@\n%a@\n%a@]"
  362. (string_of_list ", " (fun (x, y) -> (string_of_int x) ^ " = " ^ (string_of_int y)) cols)
  363. pr_string_of_ra e1
  364. pr_string_of_ra e2
  365. | AntiJoin (cols, e1, e2) ->
  366. Format.fprintf ppf "@[<2>AntiJoin %s@\n%a@\n%a@]"
  367. (string_of_list ", " (fun (x, y) -> (string_of_int x) ^ " = " ^ (string_of_int y)) cols)
  368. pr_string_of_ra e1
  369. pr_string_of_ra e2
  370. (* let string_of_ra e = *)
  371. (* pr_string_of_ra Format.str_formatter e; *)
  372. (* Format.print_flush(); *)
  373. (* (\* Format.print_newline (); *\) *)
  374. (* let s = Buffer.contents Format.stdbuf in *)
  375. (* Buffer.clear Format.stdbuf; *)
  376. (* s *)
  377. let print_ra e =
  378. pr_string_of_ra Format.std_formatter e
  379. (*** unnamed RA to named RA ***)
  380. type orig = S | L | R (* from left or right child, or from (it)self *)
  381. type att_name = orig * string
  382. (* expressions in (unnamed) relational algebra *)
  383. type nra_expr =
  384. | NTCst of att_name list * cst
  385. | NTable of att_name list * string
  386. | NSel of att_name list * att_name sel_constraint * nra_expr
  387. | NProj of att_name list * nra_expr
  388. | NCrossProd of att_name list * nra_expr * nra_expr
  389. | NUnion of att_name list * nra_expr * nra_expr
  390. | NDiff of att_name list * nra_expr * nra_expr
  391. | NInter of att_name list * nra_expr * nra_expr
  392. | NGSel of att_name list * att_name sel_constraint list * nra_expr
  393. | NEquiJoin of att_name list * att_name col_eq list * nra_expr * nra_expr
  394. | NAntiJoin of att_name list * att_name col_eq list * nra_expr * nra_expr
  395. | NRename of att_name list * nra_expr
  396. let get_atts e =
  397. match e with
  398. | NRename (a, _)
  399. | NTCst (a, _)
  400. | NTable (a, _)
  401. | NSel (a, _, _)
  402. | NProj (a, _)
  403. | NCrossProd (a, _, _)
  404. | NUnion (a, _, _)
  405. | NDiff (a, _, _)
  406. | NInter (a, _, _)
  407. | NGSel (a, _, _)
  408. | NEquiJoin (a, _, _, _)
  409. | NAntiJoin (a, _, _, _) -> a
  410. let atts_mem x atts =
  411. List.mem (snd x) (List.map snd atts)
  412. let tf_sel atts sel =
  413. let nb = List.length atts in
  414. let nth_in n =
  415. assert (n < nb);
  416. List.nth atts n
  417. in
  418. match sel with
  419. | Eq_Col (pos, pos') -> Eq_Col (nth_in pos, nth_in pos')
  420. | Eq_Val (pos, c) -> Eq_Val (nth_in pos, c)
  421. | Eq_Null pos -> Eq_Null (nth_in pos)
  422. | NEq_Col (pos, pos') -> NEq_Col (nth_in pos, nth_in pos')
  423. | NEq_Val (pos, c) -> NEq_Val (nth_in pos, c)
  424. | Less_Col (pos, pos') -> Less_Col (nth_in pos, nth_in pos')
  425. | Less_Col_Val (pos, c) -> Less_Col_Val (nth_in pos, c)
  426. | Less_Val_Col (c, pos) -> Less_Val_Col (c, nth_in pos)
  427. | LEq_Col (pos, pos') -> LEq_Col (nth_in pos, nth_in pos')
  428. | LEq_Col_Val (pos, c) -> LEq_Col_Val (nth_in pos, c)
  429. | Leq_Val_Col (c, pos) -> Leq_Val_Col (c, nth_in pos)
  430. | Less_ColExpr_Val ((pos, pos'), c) -> Less_ColExpr_Val ((nth_in pos, nth_in pos'), c)
  431. | Less_Val_ColExpr (c, (pos, pos')) -> Less_Val_ColExpr (c, (nth_in pos, nth_in pos'))
  432. | LEq_ColExpr_Val ((pos, pos'), c) -> LEq_ColExpr_Val ((nth_in pos, nth_in pos'), c)
  433. | LEq_Val_ColExpr (c, (pos, pos')) -> LEq_Val_ColExpr (c, (nth_in pos, nth_in pos'))
  434. let tf_projs atts projs =
  435. let n = List.length atts in
  436. (* print_endline ("[tf_projs] atts: " ^ string_of_list ", " id atts); *)
  437. List.map (fun i ->
  438. assert (i < n);
  439. List.nth atts i
  440. ) projs
  441. let tf_eq_cols atts1 atts2 eq_cols =
  442. let n1 = List.length atts1 in
  443. let n2 = List.length atts1 in
  444. List.map (fun (i1, i2) ->
  445. assert (i1 < n1);
  446. assert (i2 < n2);
  447. List.nth atts1 i1, List.nth atts2 i2
  448. ) eq_cols
  449. let ra2nra e atts =
  450. let c = ref 0 in
  451. let rec trans e =
  452. match e with
  453. | TCst a ->
  454. NTCst ([S, "x" ^ (incr c; string_of_int !c)], a)
  455. | Table t ->
  456. let att_names = List.map (fun (name, _) -> (S, name)) (List.assoc t atts) in
  457. (* print_endline ("[trans, Table] " ^ t ^ " a: " ^ string_of_list ", " id att_names); *)
  458. NTable (att_names, t)
  459. | Sel (sel, e) ->
  460. let e' = trans e in
  461. let a = get_atts e' in
  462. (* print_endline ("[trans, Sel] a: " ^ string_of_list ", " id a); *)
  463. NSel (a, tf_sel a sel, e')
  464. | Proj (projs, e) ->
  465. let e' = trans e in
  466. let a = get_atts e' in
  467. let a' = tf_projs a projs in
  468. (* print_endline ("[trans, Proj] a: " ^ string_of_list ", " id a); *)
  469. (* print_endline ("[trans, Proj] a': " ^ string_of_list ", " id a'); *)
  470. NProj (a', e')
  471. | CrossProd (e1, e2) ->
  472. let e1' = trans e1 in
  473. let atts1 = get_atts e1' in
  474. let e2' = trans e2 in
  475. let atts2 = get_atts e2' in
  476. let atts2' =
  477. let rec rename_duplicates = function
  478. | [] -> []
  479. | (o, a) as h :: rest ->
  480. if atts_mem h atts1 then
  481. (o, (a ^ "_bis")) :: (rename_duplicates rest)
  482. else
  483. h :: rename_duplicates rest
  484. in
  485. rename_duplicates atts2
  486. in
  487. (* print_endline ("[trans, CrossProd] a1: " ^ string_of_list ", " id a1); *)
  488. (* print_endline ("[trans, CrossProd] a2': " ^ string_of_list ", " id a2'); *)
  489. let upd_atts1 = List.map (fun (_, a) -> (L, a)) atts1 in
  490. let upd_atts2 = List.map (fun (_, a) -> (R, a)) atts2' in
  491. NCrossProd (upd_atts1 @ upd_atts2, e1', NRename (atts2', e2'))
  492. | Union (e1, e2) ->
  493. let e1' = trans e1 in
  494. let a1 = get_atts e1' in
  495. let e2' = trans e2 in
  496. let a2 = get_atts e2' in
  497. assert (List.length a1 = List.length a2);
  498. NUnion (a1, e1', e2')
  499. | Diff (e1, e2) ->
  500. let e1' = trans e1 in
  501. let a1 = get_atts e1' in
  502. let e2' = trans e2 in
  503. let a2 = get_atts e2' in
  504. (* print_endline ("[trans, Diff] a1: " ^ string_of_list ", " id a1); *)
  505. (* print_endline ("[trans, Diff] a2: " ^ string_of_list ", " id a2); *)
  506. assert (List.length a1 = List.length a2);
  507. NDiff (a1, e1', e2')
  508. | Inter (e1, e2) ->
  509. let e1' = trans e1 in
  510. let a1 = get_atts e1' in
  511. let e2' = trans e2 in
  512. let a2 = get_atts e2' in
  513. assert (List.length a1 = List.length a2);
  514. NInter (a1, e1', e2')
  515. | GSel (sel, e) ->
  516. let e' = trans e in
  517. let a = get_atts e' in
  518. (* print_endline ("[trans, GSel] a: " ^ string_of_list ", " id a); *)
  519. NGSel (a, List.map (tf_sel a) sel, e')
  520. | EquiJoin (eq_cols, e1, e2) ->
  521. let e1' = trans e1 in
  522. let atts1 = get_atts e1' in
  523. let e2' = trans e2 in
  524. let atts2 = get_atts e2' in
  525. let n_eq_cols = tf_eq_cols atts1 atts2 eq_cols in
  526. let ncols2 = List.map snd n_eq_cols in
  527. let a1 = List.map snd atts1 in
  528. let atts2', new_atts2 =
  529. let rec elim_and_rename = function
  530. | [] -> [], []
  531. | (o, a) as h :: rest ->
  532. let all_atts2, not_in_atts1 = elim_and_rename rest in
  533. if List.mem h ncols2 then (* this column is matched, hence also in a1 *)
  534. h :: all_atts2, not_in_atts1
  535. else
  536. if List.mem a a1 then
  537. let renamed_h = (o, a ^ "_bis") in
  538. renamed_h :: all_atts2, renamed_h :: not_in_atts1
  539. else
  540. h :: all_atts2, h :: not_in_atts1
  541. in
  542. elim_and_rename atts2
  543. in
  544. let upd_atts1 = List.map (fun (_, a) -> (L, a)) atts1 in
  545. let upd_atts2 = List.map (fun (_, a) -> (R, a)) new_atts2 in
  546. (* print_endline ("[trans, EquiJoin] atts1: " ^ string_of_list ", " f atts1); *)
  547. (* print_endline ("[trans, EquiJoin] atts2: " ^ string_of_list ", " f atts2); *)
  548. (* print_endline ("[trans, EquiJoin] atts2': " ^ string_of_list ", " f atts2'); *)
  549. NEquiJoin (upd_atts1 @ upd_atts2, n_eq_cols, e1', NRename (atts2', e2'))
  550. | AntiJoin (eq_cols, e1, e2) ->
  551. (* failwith "[ra2nra] AntiJoin translation not implemented yet" *)
  552. let e1' = trans e1 in
  553. let atts1 = get_atts e1' in
  554. let e2' = trans e2 in
  555. let atts2 = get_atts e2' in
  556. let n_eq_cols = tf_eq_cols atts1 atts2 eq_cols in
  557. let ncols2 = List.map snd n_eq_cols in
  558. let atts2', new_atts2 =
  559. let rec elim_and_rename = function
  560. | [] -> [], []
  561. | (o,a) as h :: rest ->
  562. let all_atts2, not_in_atts1 = elim_and_rename rest in
  563. if List.mem h ncols2 then (* this column is matched, hence also in atts1 *)
  564. h :: all_atts2, not_in_atts1
  565. else
  566. if List.mem h atts1 then
  567. let renamed_h = (o, a ^ "_bis") in
  568. renamed_h :: all_atts2, renamed_h :: not_in_atts1
  569. else
  570. h :: all_atts2, h :: not_in_atts1
  571. in
  572. elim_and_rename atts2
  573. in
  574. let upd_atts1 = List.map (fun (_, a) -> (L, a)) atts1 in
  575. let upd_atts2 = List.map (fun (_, a) -> (R, a)) new_atts2 in
  576. (* print_endline ("[trans, AntiJoin] atts1: " ^ string_of_list ", " id atts1); *)
  577. (* print_endline ("[trans, AntiJoin] atts2: " ^ string_of_list ", " id atts2); *)
  578. (* print_endline ("[trans, AntiJoin] atts2': " ^ string_of_list ", " id atts2'); *)
  579. NAntiJoin (upd_atts1 @ upd_atts2, n_eq_cols, e1', NRename (atts2', e2'))
  580. in
  581. trans e
  582. (** Pretty-printing named RA expressions **)
  583. let string_of_orig = function
  584. | L -> "L"
  585. | R -> "R"
  586. | S -> "S"
  587. let string_of_oatt (o, a) =
  588. (string_of_orig o) ^ "." ^ a
  589. let string_of_atts atts =
  590. "[" ^ (string_of_list ", " string_of_oatt atts) ^ "]"
  591. let rec pr_string_of_nra ppf = function
  592. | NRename (a, e) ->
  593. Format.fprintf ppf "@[<2>NRename %s@\n%a@]"
  594. (string_of_atts a)
  595. pr_string_of_nra e
  596. | NTCst (a, c) ->
  597. Format.fprintf ppf "@[<2>NTCst %s %s@]"
  598. (string_of_atts a) (string_of_cst c)
  599. | NTable (a, t) ->
  600. Format.fprintf ppf "@[<2>NTable %s %s@]"
  601. (string_of_atts a) t
  602. | NSel (a, sel, e) ->
  603. Format.fprintf ppf "@[<2>NSel %s %s@\n%a@]"
  604. (string_of_atts a)
  605. (string_of_sel string_of_oatt sel)
  606. pr_string_of_nra e
  607. | NProj (projs, e) ->
  608. Format.fprintf ppf "@[<2>NProj %s@\n%a@]"
  609. (string_of_atts projs)
  610. pr_string_of_nra e
  611. | NCrossProd (a, e1, e2) ->
  612. Format.fprintf ppf "@[<2>NCrossProd %s@\n%a@\n%a@]"
  613. (string_of_atts a)
  614. pr_string_of_nra e1
  615. pr_string_of_nra e2
  616. | NUnion (a, e1, e2) ->
  617. Format.fprintf ppf "@[<2>NUnion %s@\n%a@\n%a@]"
  618. (string_of_atts a)
  619. pr_string_of_nra e1
  620. pr_string_of_nra e2
  621. | NDiff (a, e1, e2) ->
  622. Format.fprintf ppf "@[<2>NDiff %s@\n%a@\n%a@]"
  623. (string_of_atts a)
  624. pr_string_of_nra e1
  625. pr_string_of_nra e2
  626. | NInter (a, e1, e2) ->
  627. Format.fprintf ppf "@[<2>NInter %s@\n%a@\n%a@]"
  628. (string_of_atts a)
  629. pr_string_of_nra e1
  630. pr_string_of_nra e2
  631. | NGSel (a, sels, e) ->
  632. Format.fprintf ppf "@[<2>NGSel %s %s@\n%a@]"
  633. (string_of_atts a)
  634. (string_of_list ", " (string_of_sel string_of_oatt) sels)
  635. pr_string_of_nra e
  636. | NEquiJoin (a, cols, e1, e2) ->
  637. Format.fprintf ppf "@[<2>NEquiJoin %s %s@\n%a@\n%a@]"
  638. (string_of_atts a)
  639. (string_of_list ", "
  640. (fun (x, y) ->
  641. (string_of_oatt x) ^ " = " ^ (string_of_oatt y))
  642. cols)
  643. pr_string_of_nra e1
  644. pr_string_of_nra e2
  645. | NAntiJoin (a, cols, e1, e2) ->
  646. Format.fprintf ppf "@[<2>NAntiJoin %s %s@\n%a@\n%a@]"
  647. (string_of_atts a)
  648. (string_of_list ", "
  649. (fun (x, y) ->
  650. (string_of_oatt x) ^ " = " ^ (string_of_oatt y))
  651. cols)
  652. pr_string_of_nra e1
  653. pr_string_of_nra e2
  654. let print_nra e =
  655. pr_string_of_nra Format.std_formatter e
  656. (*** RA to SQL ***)
  657. type col_name = string
  658. type tbl_name = string
  659. type col_spec = tbl_name * col_name * col_name option (* last argument is used for renaming *)
  660. type sql_table_ref = (* a table reference always has a name *)
  661. | SQL_table_name of tbl_name
  662. | SQL_subquery of tbl_name * sql_query
  663. | SQL_join of tbl_name * (col_spec * col_spec) list * sql_table_ref * sql_table_ref
  664. | SQL_left_join of tbl_name * (col_spec * col_spec) list * sql_table_ref * sql_table_ref
  665. and
  666. sql_query =
  667. | SQL_value of cst
  668. | SQL_select of col_spec list * bool * col_spec sel_constraint list * sql_table_ref list
  669. | SQL_union of sql_query * sql_query
  670. | SQL_diff of sql_query * sql_query
  671. | SQL_inter of sql_query * sql_query
  672. type transf_aux =
  673. | Aux_tables of col_spec list * bool * col_spec sel_constraint list * sql_table_ref list
  674. | Aux_query of sql_query
  675. let aux2query = function
  676. | Aux_query q -> q
  677. | Aux_tables (cols, b, sels, tblsl) -> SQL_select (cols, b, sels, tblsl)
  678. let new_name c =
  679. incr c;
  680. ("T" ^ string_of_int !c)
  681. let aux2subquery c aux =
  682. let q = aux2query aux in
  683. SQL_subquery (new_name c, q)
  684. let get_name = function
  685. | SQL_table_name t
  686. | SQL_subquery (t, _)
  687. | SQL_join (t, _, _, _)
  688. | SQL_left_join (t, _, _, _)
  689. -> t
  690. let get_tbl_name o tbl_names =
  691. match tbl_names with
  692. | [name1; name2] ->
  693. (match o with
  694. | L -> name1
  695. | R -> name2
  696. | S -> ""
  697. )
  698. | _ -> ""
  699. let sel_map f = function
  700. | Eq_Col (col, col') -> Eq_Col (f col, f col')
  701. | Eq_Val (col, c) -> Eq_Val (f col, c)
  702. | Eq_Null col -> Eq_Null (f col)
  703. | NEq_Col (col, col') -> NEq_Col (f col, f col')
  704. | NEq_Val (col, c) -> NEq_Val (f col, c)
  705. | Less_Col (col, col') -> Less_Col (f col, f col')
  706. | Less_Col_Val (col, c) -> Less_Col_Val (f col, c)
  707. | Less_Val_Col (c, col) -> Less_Val_Col (c, f col)
  708. | LEq_Col (col, col') -> LEq_Col (f col, f col')
  709. | LEq_Col_Val (col, c) -> LEq_Col_Val (f col, c)
  710. | Leq_Val_Col (c, col) -> Leq_Val_Col (c, f col)
  711. | Less_ColExpr_Val ((col, col'), c) ->
  712. Less_ColExpr_Val ((f col, f col'), c)
  713. | Less_Val_ColExpr (c, (col, col')) ->
  714. Less_Val_ColExpr (c, (f col, f col'))
  715. | LEq_ColExpr_Val ((col, col'), c) ->
  716. LEq_ColExpr_Val ((f col, f col'), c)
  717. | LEq_Val_ColExpr (c, (col, col')) ->
  718. LEq_Val_ColExpr (c, (f col, f col'))
  719. (* idea: selections and projections accumulate *)
  720. let nra2sql e =
  721. let c = ref 0 in
  722. let rec transf = function
  723. | NTCst (_, c) -> Aux_query (SQL_value c)
  724. | NTable (atts, name) ->
  725. let tbl_name = "tbl_" ^ name in
  726. let cols = List.map (fun (orig, a) -> (tbl_name, a, None)) atts in
  727. Aux_tables (cols, true, [], [SQL_table_name tbl_name])
  728. | NSel (a, sel, e) ->
  729. transf (NGSel (a, [sel], e))
  730. | NGSel (_, sels, e) ->
  731. (match transf e with
  732. | Aux_tables (proj, b, lower_sels, tbls) ->
  733. let tbl_names = List.map get_name tbls in
  734. let sels' = List.map
  735. (sel_map (fun (o, a) -> (get_tbl_name o tbl_names, a, None)))
  736. sels
  737. in
  738. Aux_tables (proj, b, sels' @ lower_sels, tbls)
  739. | Aux_query q ->
  740. (* let tbl_name = new_name c in *)
  741. let sels' = List.map (sel_map (fun (o, a) -> ("", a, None))) sels in
  742. Aux_tables ([], true, sels', [SQL_subquery (new_name c, q)])
  743. )
  744. | NProj (projs, e) ->
  745. (match transf e with
  746. | Aux_tables (cols, _, sels, tbls) ->
  747. let tbl_names =
  748. match tbls with
  749. | [SQL_join (_, _, sq1, sq2)] -> [get_name sq1; get_name sq2]
  750. | [SQL_left_join (_, _, sq1, sq2)] -> [get_name sq1; get_name sq2]
  751. | _ -> List.map get_name tbls
  752. in
  753. let projs' = List.map
  754. (fun (o, a) -> (get_tbl_name o tbl_names, a, None))
  755. projs
  756. in
  757. Aux_tables (projs', false, sels, tbls)
  758. | Aux_query q ->
  759. let projs' = List.map (fun (o, a) -> ("", a, None)) projs in
  760. Aux_tables (projs', false, [], [SQL_subquery (new_name c, q)])
  761. )
  762. | NUnion (_, e1, e2) ->
  763. (* build now the queries and then take the union *)
  764. let q1 = aux2query (transf e1) in
  765. let q2 = aux2query (transf e2) in
  766. Aux_query (SQL_union (q1, q2))
  767. | NDiff (_, e1, e2) ->
  768. (* build now the queries and then take the union *)
  769. let q1 = aux2query (transf e1) in
  770. let q2 = aux2query (transf e2) in
  771. Aux_query (SQL_diff (q1, q2))
  772. | NInter (_, e1, e2) ->
  773. (* build now the queries and then take the union *)
  774. let q1 = aux2query (transf e1) in
  775. let q2 = aux2query (transf e2) in
  776. Aux_query (SQL_inter (q1, q2))
  777. | NCrossProd (atts, e1, e2) ->
  778. let sq1 = aux2subquery c (transf e1) in
  779. let sq2 = aux2subquery c (transf e2) in
  780. (* let a1 = get_atts e1 in *)
  781. let atts' = List.map
  782. (fun (o, a) ->
  783. match o with
  784. | L -> (get_name sq1), a, None
  785. | R -> (get_name sq2), a, None
  786. | S -> failwith "[nra2sql, NCrossProd] impossible"
  787. )
  788. atts
  789. in
  790. Aux_tables (atts', true, [], [sq1; sq2])
  791. | NEquiJoin (atts, cols, e1, e2) ->
  792. let atts', sq1, sq2 = transf_join c atts e1 e2 in
  793. let tbl1, tbl2 = get_name sq1, get_name sq2 in
  794. let cols' = List.map
  795. (fun ((o1, a1), (o2, a2)) -> (tbl1, a1, None), (tbl2, a2, None))
  796. cols
  797. in
  798. Aux_tables (atts', false, [], [SQL_join (new_name c, cols', sq1, sq2)])
  799. | NAntiJoin (atts, cols, e1, e2) ->
  800. let atts', sq1, sq2 = transf_join c atts e1 e2 in
  801. let tbl1, tbl2 = get_name sq1, get_name sq2 in
  802. let (_, aname) = List.hd (get_atts e2) in
  803. let a = (tbl2, aname, None) in
  804. (* assert (List.mem a atts'); *)
  805. let cols' = List.map
  806. (fun ((o1, a1), (o2, a2)) -> (tbl1, a1, None), (tbl2, a2, None))
  807. cols
  808. in
  809. Aux_tables (atts', false, [Eq_Null a], [SQL_left_join (new_name c, cols', sq1, sq2)])
  810. | NRename (atts, e) ->
  811. (match transf e with
  812. | Aux_query q -> transf e (* failwith "[nra2sql] renaming unclear" *)
  813. | Aux_tables (cols, _, sels, tbls) ->
  814. let old_atts = get_atts e in
  815. let att_names = List.map snd old_atts in
  816. let cols' = List.map
  817. (fun (tn, x, x') ->
  818. match x' with
  819. | None ->
  820. if List.mem x att_names then
  821. let pos = Misc.get_pos x att_names in
  822. let new_x = List.nth atts pos in
  823. if x = snd new_x then
  824. (tn, x, None)
  825. else
  826. (tn, x, Some (snd new_x))
  827. else
  828. (tn, x, None)
  829. | Some new_x ->
  830. if List.mem x att_names then
  831. failwith "[nra2sql] double renaming"
  832. else
  833. if x = new_x then
  834. (tn, x, None)
  835. else
  836. (tn, x, Some new_x)
  837. ) cols
  838. in
  839. Aux_tables (cols', false, sels, tbls)
  840. )
  841. and
  842. transf_join c atts e1 e2 =
  843. let sq1 = aux2subquery c (transf e1) in
  844. let sq2 = aux2subquery c (transf e2) in
  845. let atts1 = get_atts e1 in
  846. let atts2 = get_atts e2 in
  847. let atts' = List.map
  848. (fun a ->
  849. let orig, aname = a in
  850. match orig with
  851. | L ->
  852. assert (atts_mem a atts1);
  853. (get_name sq1), aname, None
  854. | R ->
  855. assert (atts_mem a atts2);
  856. (get_name sq2), aname, None
  857. | S ->
  858. if atts_mem a atts1 then
  859. (get_name sq1), aname, None
  860. else
  861. (get_name sq2), aname, None
  862. )
  863. atts
  864. in
  865. atts', sq1, sq2
  866. in
  867. aux2query (transf e)
  868. (** Pretty-printing SQL queries **)
  869. let string_of_col_spec no_tbl (tn, x, x') =
  870. let str =
  871. match x' with
  872. | None -> x
  873. | Some new_x -> x ^ " AS " ^ new_x
  874. in
  875. if tn = "" || no_tbl then
  876. str
  877. else
  878. tn ^ "." ^ str
  879. let is_table tbl_refs =
  880. match tbl_refs with
  881. | [SQL_table_name _] -> true
  882. | _ -> false
  883. let rec pr_string_of_query ppf = function
  884. | SQL_value c -> (* TODO: we need to give a name to the column *)
  885. Format.fprintf ppf "@[ SELECT %s @]" (string_of_cst c)
  886. | SQL_select (cols, all, sels, tbls) ->
  887. (* assert (cols <> []); *)
  888. assert (tbls <> []);
  889. let string_of_cols = string_of_col_spec (is_table tbls) in
  890. let cols_str = string_of_list ", " string_of_cols cols in
  891. let sels_str = string_of_list " AND "
  892. (string_of_sel string_of_cols)
  893. sels
  894. in
  895. let select_str =
  896. if cols_str = "" || all then "SELECT *" else "SELECT " ^ cols_str
  897. in
  898. Format.fprintf ppf "@[@[%s@]@ @[FROM %a@]" select_str pr_string_of_table_refs tbls;
  899. if sels_str = "" then
  900. Format.fprintf ppf "@]"
  901. else
  902. Format.fprintf ppf "@ WHERE %s@]" sels_str
  903. | SQL_union (q1, q2) ->
  904. Format.fprintf ppf "@[ (%a)@\nUNION@\n (%a)@]"
  905. pr_string_of_query q1
  906. pr_string_of_query q2
  907. | SQL_diff (q1, q2) ->
  908. Format.fprintf ppf "@[ (%a)@\nEXCEPT@\n (%a)@]"
  909. pr_string_of_query q1
  910. pr_string_of_query q2
  911. | SQL_inter (q1, q2) ->
  912. Format.fprintf ppf "@[ (%a)@\nINTERSECT@\n (%a)@]"
  913. pr_string_of_query q1
  914. pr_string_of_query q2
  915. and pr_string_of_table_ref ppf = function
  916. | SQL_table_name name -> Format.fprintf ppf "%s" name
  917. | SQL_subquery (name, q) ->
  918. Format.fprintf ppf "@[(%a) AS %s@]"
  919. pr_string_of_query q name
  920. | SQL_join (name, eq_cols, tbl1, tbl2) ->
  921. (* let t1 = get_name tbl1 in *)
  922. (* let t2 = get_name tbl2 in *)
  923. let cols_str = string_of_list
  924. " AND "
  925. (fun ((t1,x,_), (t2,y,_)) -> t1 ^ "." ^ x ^ " = " ^ t2 ^ "." ^ y)
  926. eq_cols
  927. in
  928. let fmt =
  929. match tbl1, tbl2 with
  930. | SQL_table_name _, SQL_table_name _ ->
  931. format_of_string "@[%a@ JOIN@ %a@ @[ON %s@]@]"
  932. | SQL_table_name _, _ ->
  933. format_of_string "@[%a@ JOIN@\n %a@ @[ON %s@]@]"
  934. | _, SQL_table_name _ ->
  935. format_of_string "@[ %a@\nJOIN@ %a@ @[ON %s@]@]"
  936. | _ -> format_of_string
  937. "@[ %a@\nJOIN@\n %a@ @[ON %s@]@]"
  938. in
  939. Format.fprintf ppf fmt
  940. pr_string_of_table_ref tbl1
  941. pr_string_of_table_ref tbl2
  942. cols_str
  943. | SQL_left_join (name, eq_cols, tbl1, tbl2) ->
  944. let cols_str = string_of_list
  945. " AND "
  946. (fun ((t1,x,_), (t2,y,_)) -> t1 ^ "." ^ x ^ " = " ^ t2 ^ "." ^ y)
  947. eq_cols
  948. in
  949. let fmt =
  950. match tbl1, tbl2 with
  951. | SQL_table_name _, SQL_table_name _ ->
  952. format_of_string "@[%a@ LEFT JOIN@ %a@ @[ON %s@]@]"
  953. | SQL_table_name _, _ ->
  954. format_of_string "@[%a@ LEFT JOIN@\n %a@ @[ON %s@]@]"
  955. | _, SQL_table_name _ ->
  956. format_of_string "@[ %a@\nLEFT JOIN@ %a@ @[ON %s@]@]"
  957. | _ -> format_of_string
  958. "@[ %a@\nLEFT JOIN@\n %a@ @[ON %s@]@]"
  959. in
  960. Format.fprintf ppf fmt
  961. pr_string_of_table_ref tbl1
  962. pr_string_of_table_ref tbl2
  963. cols_str
  964. and pr_string_of_table_refs ppf = function
  965. | [t] -> Format.fprintf ppf "%a" pr_string_of_table_ref t
  966. | [t1; t2] ->
  967. Format.fprintf ppf "%a,@;<1 5>%a"
  968. pr_string_of_table_ref t1
  969. pr_string_of_table_ref t2
  970. | _ -> failwith "[pr_string_of_table_refs] internal error"
  971. (* let string_of_query q = *)
  972. (* pr_string_of_query Format.str_formatter q; *)
  973. (* Format.print_flush(); *)
  974. (* let s = Buffer.contents Format.stdbuf in *)
  975. (* Buffer.clear Format.stdbuf; *)
  976. (* s *)
  977. let print_query q =
  978. pr_string_of_query Format.std_formatter q
  979. (*** Usage ***)
  980. let usage_string = "mfotl2sql -sig <sig_file> -formula <formula_file> [-negate] [-no_set_support] [-debug <unit>]"
  981. let formulafile = ref ""
  982. let sigfile = ref ""
  983. let negate = ref false
  984. let no_set_support = ref false
  985. let debug = ref ""
  986. let debug_tf = ref false
  987. let analyse_formulafile ic =
  988. let ic = open_in !formulafile in
  989. Formula_parser.formula Formula_lexer.token (Lexing.from_channel ic)
  990. let main () =
  991. Misc.split_debug !debug;
  992. let attr = Log.get_signature !sigfile in
  993. let f = analyse_formulafile !formulafile in
  994. let f = if !negate then Neg f else f in
  995. let is_mon, pf, vt_list = Rewriting.check_formula attr f in
  996. if is_mon then
  997. let all_attr =
  998. (tbl_time, ("tp", TInt) :: ("ts", TInt) :: []) ::
  999. List.map
  1000. (fun (p, atts) ->
  1001. (p, ("tp", TInt) :: ("ts", TInt) :: atts)
  1002. )
  1003. attr
  1004. in
  1005. let ra_e = mfotl2ra (not !no_set_support) pf in
  1006. if !debug_tf then
  1007. begin
  1008. print_ra ra_e;Format.print_newline();Format.print_newline();
  1009. end;
  1010. let nra_e = ra2nra ra_e all_attr in
  1011. if !debug_tf then
  1012. begin
  1013. print_nra nra_e;Format.print_newline();Format.print_newline();
  1014. end;
  1015. let q = nra2sql nra_e in
  1016. print_string "-- ";
  1017. Predicate.print_vartypes_list vt_list;
  1018. print_query q;
  1019. Format.print_newline();Format.print_newline()
  1020. let _ =
  1021. Arg.parse [
  1022. "-sig", Arg.Set_string sigfile, "\t\tChoose the signature file";
  1023. "-formula", Arg.Set_string formulafile, "\tChoose the formula file";
  1024. "-negate", Arg.Set negate, "\tAnalyze the negation of the input formula";
  1025. "-no_set_support", Arg.Set no_set_support, "\tDo not use EXCEPT nor INTER";
  1026. "-debug", Arg.Set_string debug, "\tChoose unit to debug";
  1027. "-debug_tf", Arg.Set debug_tf, "\tDebug this module";
  1028. ]
  1029. (fun _ -> ())
  1030. usage_string;
  1031. main ();