--- /dev/null
+(* Copyright (C) 2000, HELM Team.
+ *
+ * This file is part of HELM, an Hypertextual, Electronic
+ * Library of Mathematics, developed at the Computer Science
+ * Department, University of Bologna, Italy.
+ *
+ * HELM is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * HELM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HELM; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * For details, see the HELM World-Wide-Web page,
+ * http://cs.unibo.it/helm/.
+ *)
+
+open Dbconn;;
+open Union;;
+open Intersect;;
+open Meet;;
+open Property;;
+open Sub;;
+open Context;;
+open Diff;;
+open Relation;;
+open Func;;
+open Pattern;;
+
+exception SVarUnbound of string;;
+exception RVarUnbound of string;;
+exception VVarUnbound of string;;
+exception PathUnbound of (string * string list);;
+
+exception InvalidConnection
+exception ConnectionFailed of string
+
+exception BooleExpTrue
+
+(* valuta una MathQL.set_exp e ritorna un MathQL.resource_set *)
+
+let galax_char = 'G'
+let stat_char = 'S'
+
+let execute_aux log m x =
+ let module M = MathQL in
+ let module X = MQueryMisc in
+let rec exec_set_exp c = function
+ M.SVar svar ->
+ (try
+ List.assoc svar c.svars
+ with Not_found ->
+ raise (SVarUnbound svar))
+ | M.RVar rvar ->
+ (try
+ [List.assoc rvar c.rvars]
+ with Not_found ->
+ raise (RVarUnbound rvar))
+ | M.Ref vexp -> List.map (fun s -> (s,[])) (exec_val_exp c vexp)
+ | M.Pattern vexp -> pattern_ex (exec_val_exp c vexp)
+ | M.Intersect (sexp1, sexp2) ->
+ let before = X.start_time() in
+ let rs1 = exec_set_exp c sexp1 in
+ let rs2 = exec_set_exp c sexp2 in
+ let res = intersect_ex rs1 rs2 in
+ let diff = X.stop_time before in
+ let ll1 = string_of_int (List.length rs1) in
+ let ll2 = string_of_int (List.length rs2) in
+ if String.contains m stat_char then
+ log ("INTERSECT(" ^ ll1 ^ "," ^ ll2 ^ ") = " ^ string_of_int (List.length res) ^
+ ": " ^ diff ^ "\n");
+ res
+ | M.Union (sexp1, sexp2) ->
+ let before = X.start_time () in
+ let res = union_ex (exec_set_exp c sexp1) (exec_set_exp c sexp2) in
+ let diff = X.stop_time before in
+ if String.contains m stat_char then log ("UNION: " ^ diff ^ "\n");
+ res
+ | M.LetSVar (svar, sexp1, sexp2) ->
+ let before = X.start_time() in
+ let c1 = upd_svars c ((svar, exec_set_exp c sexp1) :: c.svars) in
+ let res = exec_set_exp c1 sexp2 in
+ if String.contains m stat_char then begin
+ log ("LETIN " ^ svar ^ " = " ^ string_of_int (List.length res) ^ ": ");
+ log (X.stop_time before ^ "\n");
+ end;
+ res
+ | M.LetVVar (vvar, vexp, sexp) ->
+ let before = X.start_time() in
+ let c1 = upd_vvars c ((vvar, exec_val_exp c vexp) :: c.vvars) in
+ let res = exec_set_exp c1 sexp in
+ if String.contains m stat_char then begin
+ log ("LETIN " ^ vvar ^ " = " ^ string_of_int (List.length res) ^ ": ");
+ log (X.stop_time before ^ "\n");
+ end;
+ res
+ | M.Relation (inv, rop, path, sexp, assl) ->
+ let before = X.start_time() in
+ if String.contains m galax_char then begin
+ let res = relation_galax_ex inv rop path (exec_set_exp c sexp) assl in
+ if String.contains m stat_char then begin
+ log ("RELATION-GALAX " ^ (fst path) ^ " = " ^ string_of_int(List.length res) ^ ": ");
+ log (X.stop_time before ^ "\n")
+ end;
+ res
+ end else begin
+ let res = relation_ex inv rop path (exec_set_exp c sexp) assl in
+ if String.contains m stat_char then begin
+ log ("RELATION " ^ (fst path) ^ " = " ^ string_of_int(List.length res) ^ ": ");
+ log (X.stop_time before ^ "\n")
+ end;
+ res
+ end
+ | M.Select (rvar, sexp, bexp) ->
+ let before = X.start_time() in
+ let rset = (exec_set_exp c sexp) in
+ let rec select_ex =
+ function
+ [] -> []
+ | r::tl ->
+ let c1 = upd_rvars c ((rvar,r)::c.rvars) in
+ if (exec_boole_exp c1 bexp) then
+ r::(select_ex tl)
+ else
+ select_ex tl
+ in
+ let res = select_ex rset in
+ if String.contains m stat_char then begin
+ log ("SELECT " ^ rvar ^ " = " ^ string_of_int (List.length res) ^ ": ");
+ log (X.stop_time before ^ "\n");
+ end;
+ res
+ | M.Diff (sexp1, sexp2) -> diff_ex (exec_set_exp c sexp1) (exec_set_exp c sexp2)
+
+(* valuta una MathQL.boole_exp e ritorna un boole *)
+
+and exec_boole_exp c =
+ function
+ M.False -> false
+ | M.True -> true
+ | M.Not x -> not (exec_boole_exp c x)
+ | M.And (x, y) -> (exec_boole_exp c x) && (exec_boole_exp c y)
+ | M.Or (x, y) -> (exec_boole_exp c x) || (exec_boole_exp c y)
+ | M.Sub (vexp1, vexp2) ->
+ sub_ex (exec_val_exp c vexp1) (exec_val_exp c vexp2)
+ | M.Meet (vexp1, vexp2) ->
+ meet_ex (exec_val_exp c vexp1) (exec_val_exp c vexp2)
+ | M.Eq (vexp1, vexp2) -> (exec_val_exp c vexp1) = (exec_val_exp c vexp2)
+ | M.Ex l bexp ->
+ if l = [] then
+ (exec_boole_exp c bexp)
+ else
+ let latt =
+ List.map
+ (fun uri ->
+ let (r,attl) =
+ (try
+ List.assoc uri c.rvars
+ with Not_found -> assert false)
+ in
+ (uri,attl)
+ ) l (*latt = l + attributi*)
+ in
+ try
+ let rec prod c =
+ function
+ [] -> if (exec_boole_exp c bexp) then raise BooleExpTrue
+ | (uri,attl)::tail1 ->
+ (*per ogni el. di attl devo andare in ric. su tail1*)
+ let rec sub_prod attl =
+ match attl with
+ [] -> ()
+ | att::tail2 ->
+ let c1 = upd_groups c ((uri,att)::c.groups) in
+ prod c1 tail1; sub_prod tail2
+ in
+ sub_prod attl
+ in
+ prod c latt;
+ false
+ with BooleExpTrue -> true
+
+(* valuta una MathQL.val_exp e ritorna un MathQL.value *)
+
+and exec_val_exp c = function
+ M.Const x -> let
+ ol = List.sort compare x in
+ let rec edup = function
+
+ [] -> []
+ | s::tl -> if tl <> [] then
+ if s = (List.hd tl) then edup tl
+ else s::(edup tl)
+ else s::[]
+ in
+ edup ol
+ | M.Record (rvar, path) ->
+ (try
+ List.assoc path
+ (try
+ List.assoc rvar c.groups
+ with Not_found ->
+ raise (RVarUnbound rvar))
+ with Not_found ->
+ raise (PathUnbound path))
+ | M.VVar s ->
+ (try
+ List.assoc s c.vvars
+ with Not_found ->
+ raise (VVarUnbound s))
+ | M.RefOf sexp -> List.map (fun (s,_) -> s) (exec_set_exp c sexp)
+ | M.Fun (s, vexp) -> fun_ex s (exec_val_exp c vexp)
+ | M.Property (inv, rop, path, vexp) -> property_ex rop path inv (exec_val_exp c vexp)
+
+(* valuta una MathQL.set_exp nel contesto vuoto e ritorna un MathQL.resource_set *)
+in
+ exec_set_exp {svars = []; rvars = []; groups = []; vvars = []} x
+
+(* new interface ***********************************************************)
+
+module type Callbacks =
+ sig
+ val log : string -> unit (* logging function *)
+ end
+
+module Make (C: Callbacks) =
+ struct
+
+ let postgres = "P"
+ let galax = "G"
+ let stat = "S"
+ let quiet = "Q"
+ let warn = "W"
+
+ let execute m x = execute_aux C.log m x
+
+ let init m =
+ let default_connection_string =
+ "host=mowgli.cs.unibo.it dbname=helm_mowgli_new_schema user=helm"
+ in
+ let connection_string =
+ try Sys.getenv "POSTGRESQL_CONNECTION_STRING"
+ with Not_found -> default_connection_string
+ in
+ if String.contains m galax_char then true else
+ try Dbconn.init connection_string; true
+ with ConnectionFailed s -> false
+
+ let close m =
+ if String.contains m galax_char then () else Dbconn.close ()
+
+ let check m =
+ if String.contains m galax_char then false else
+ try ignore (Dbconn.pgc ()); true with InvalidConnection -> false
+
+ end