(*TODO implement plants as special posts? *) open Db type t = { id : string ; date : int ; nick : string (*TODO ? ; comment : string *) ; images : (string * string) list ; tags : string list ; longitude : float ; latitude : float ; replies : string list ; citations : string list } (* ('a option, string) result *) let ( let** ) o f = match o with | Error e -> Error (Format.sprintf "db error: %s" (Caqti_error.show e)) | Ok None -> Error (Format.sprintf "db error: value not found") | Ok (Some x) -> f x (* ('a, string) result *) let ( let* ) o f = match o with | Error e -> Error (Format.sprintf "db error: %s" (Caqti_error.show e)) | Ok x -> f x module Q = struct let create_plant_user_table = Caqti_request.exec Caqti_type.unit "CREATE TABLE IF NOT EXISTS plant_user (plant_id TEXT, nick TEXT, \ PRIMARY KEY(plant_id), FOREIGN KEY(nick) REFERENCES user(nick));" let create_plant_image_table = Caqti_request.exec Caqti_type.unit "CREATE TABLE IF NOT EXISTS plant_image ( plant_id TEXT, image TEXT,id \ INTEGER, FOREIGN KEY(plant_id) REFERENCES plant_user(plant_id));" let create_plant_tag_table = Caqti_request.exec Caqti_type.unit "CREATE TABLE IF NOT EXISTS plant_tag (plant_id TEXT, tag TEXT, FOREIGN \ KEY(plant_id) REFERENCES plant_user(plant_id));" let create_plant_gps_table = Caqti_request.exec Caqti_type.unit "CREATE TABLE IF NOT EXISTS plant_gps (plant_id TEXT, lat FLOAT,lng \ FLOAT, FOREIGN KEY(plant_id) REFERENCES plant_user(plant_id));" let upload_plant_id = Caqti_request.exec Caqti_type.(tup2 string string) "INSERT INTO plant_user VALUES (?,?);" let upload_plant_tag = Caqti_request.exec Caqti_type.(tup2 string string) "INSERT INTO plant_tag VALUES (?,?);" let upload_plant_gps = Caqti_request.exec Caqti_type.(tup3 string float float) "INSERT INTO plant_gps VALUES (?,?,?);" let upload_plant_image = Caqti_request.exec Caqti_type.(tup3 string string int) "INSERT INTO plant_image VALUES (?,?,?);" let get_user_plants = Caqti_request.collect Caqti_type.string Caqti_type.string "SELECT plant_id FROM plant_user WHERE nick=?;" let list_plant_ids = Caqti_request.collect Caqti_type.unit Caqti_type.string "SELECT plant_id FROM plant_user;" let count_plant_image = Caqti_request.find_opt Caqti_type.string Caqti_type.int "SELECT COUNT(*) FROM plant_image WHERE plant_id=?;" let get_plant_image = Caqti_request.find_opt Caqti_type.(tup2 string int) Caqti_type.string "SELECT image FROM plant_image WHERE plant_id=? AND id=?;" let get_plant_tags = Caqti_request.collect Caqti_type.string Caqti_type.string "SELECT tag FROM plant_tag WHERE plant_id=?;" let get_plant_gps = Caqti_request.find_opt Caqti_type.string Caqti_type.(tup2 float float) "SELECT lat, lng FROM plant_gps WHERE plant_id=?;" end let () = let tables = [ Q.create_plant_user_table ; Q.create_plant_image_table ; Q.create_plant_tag_table ; Q.create_plant_gps_table ] in if List.exists Result.is_error (List.map (fun query -> Db.exec query ()) tables) then Dream.warning (fun log -> log "can't create table") let view_plant plant_id = let** count = Db.find_opt Q.count_plant_image plant_id in let gps = match Db.find_opt Q.get_plant_gps plant_id with | Ok (Some (lat, lng)) -> Float.to_string lat ^ " " ^ Float.to_string lng | Ok None -> "" | Error e -> Format.sprintf "db error: %s" (Caqti_error.show e) in let images = String.concat "\n" (List.map (Format.sprintf {|