aboutsummaryrefslogtreecommitdiff
path: root/lib/sql/hashs.ml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sql/hashs.ml')
-rw-r--r--lib/sql/hashs.ml79
1 files changed, 79 insertions, 0 deletions
diff --git a/lib/sql/hashs.ml b/lib/sql/hashs.ml
new file mode 100644
index 0000000..af1f092
--- /dev/null
+++ b/lib/sql/hashs.ml
@@ -0,0 +1,79 @@
+(**
+ This module store the hash of the indexes ([extern_key]) for each table in
+ order to update the file if the configuration changed.
+
+ The hashes are stored in a table named [hashes] and are evaluated just
+ before inserting the values.
+*)
+
+open StdLabels
+module Table = ImportDataTypes.Table
+
+let ( let* ) = Result.bind
+
+let create_table : 'a T.t -> unit T.result =
+ fun db ->
+ Sqlite3.exec db
+ "CREATE TABLE IF NOT EXISTS 'hashes' ('table' TEXT, 'hash' INTEGER, \
+ PRIMARY KEY ('table'))"
+ |> T.to_result
+
+let evaluate : ImportAnalyser.Dependency.t -> int =
+ fun table ->
+ (* Extract all the references to this table *)
+ let keys =
+ List.map (ImportAnalyser.Dependency.keys table)
+ ~f:(fun ImportAnalyser.Dependency.{ name; columns; expression } ->
+ ignore columns;
+ (name, expression))
+ in
+ Hashtbl.hash keys
+
+let insert : 'a T.t -> ImportAnalyser.Dependency.t -> unit T.result =
+ fun db table ->
+ let source = ImportAnalyser.Dependency.table table in
+ let table_name = Table.name source in
+
+ let hash = evaluate table in
+
+ let query =
+ String.concat ~sep:""
+ [
+ "INSERT INTO 'hashes' ('table', 'hash') VALUES ('";
+ table_name;
+ "', :hash) ON CONFLICT(hashes.'table') DO UPDATE SET 'hash' = :hash";
+ ]
+ in
+ let* statement =
+ try Ok (Sqlite3.prepare db query) with
+ | e -> Error e
+ in
+
+ let* _ = T.begin_transaction db in
+ let sql_data = Sqlite3.Data.INT (Int64.of_int hash) in
+
+ let* _ = Sqlite3.bind_name statement ":hash" sql_data |> T.to_result in
+ let* _ = T.to_result (Sqlite3.step statement) in
+ T.commit db
+
+let query : 'a T.t -> ImportDataTypes.Table.t -> int option T.result =
+ fun db table ->
+ let table_name = Table.name table in
+ let query =
+ String.concat ~sep:""
+ [ "SELECT hash FROM 'hashes' WHERE hashes.'table' = '"; table_name; "'" ]
+ in
+
+ let* stmt =
+ try Ok (Sqlite3.prepare db query) with
+ | e -> Error e
+ in
+ let state, res =
+ Sqlite3.fold stmt ~init:None ~f:(fun _ d ->
+ Some (T.to_datatype (Array.get d 0)))
+ in
+
+ let* _ = T.to_result state in
+ match res with
+ | Some (ImportCSV.DataType.Integer i) -> Ok (Some i)
+ | _ -> Ok None