From 6b377719c10d5ab3343fd5221f99a4a21008e25a Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Thu, 14 Mar 2024 08:26:58 +0100 Subject: Initial commit --- lib/sql/header.ml | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 lib/sql/header.ml (limited to 'lib/sql/header.ml') diff --git a/lib/sql/header.ml b/lib/sql/header.ml new file mode 100644 index 0000000..3cac5fb --- /dev/null +++ b/lib/sql/header.ml @@ -0,0 +1,74 @@ +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 'header' ('table' TEXT, 'column' INTEGER, \ + 'label', PRIMARY KEY ('table', 'column'))" + |> T.to_result + +let insert_header : + 'a T.t -> + ImportDataTypes.Table.t -> + (int * ImportCSV.DataType.t) array -> + unit T.result = + fun db table values -> + let table_name = Table.name table in + + let query = + String.concat ~sep:"" + [ + "INSERT INTO 'header' ('table', 'column', 'label') VALUES ('"; + table_name; + "', :column, :label) ON CONFLICT(header.'table', header.'column') DO \ + UPDATE SET 'label' = :label"; + ] + in + + let statement = Sqlite3.prepare db query in + + let* _ = T.begin_transaction db in + let* _ = + Array.fold_left values ~init:(Ok ()) ~f:(fun acc (column, value) -> + let* _ = acc in + let sql_data = T.of_datatype value in + let* _ = Sqlite3.bind_name statement ":label" sql_data |> T.to_result in + + let* _ = + Sqlite3.bind_name statement ":column" + (Sqlite3.Data.INT (Int64.of_int column)) + |> T.to_result + in + let* _ = T.to_result (Sqlite3.step statement) in + T.reset statement) + in + T.commit db + +let query_headers : + 'a T.t -> ImportDataTypes.Table.t -> ImportCSV.DataType.t array T.result = + fun db table -> + let table_name = Table.name table in + let query = + String.concat ~sep:"" + [ + "SELECT label FROM 'header' WHERE header.'table' = '"; + table_name; + "' ORDER BY column DESC"; + ] + in + + let* stmt = + try Ok (Sqlite3.prepare db query) with + | e -> Error e + in + let state, res = + Sqlite3.fold stmt ~init:[] ~f:(fun acc d -> + let value = T.to_datatype (Array.get d 0) in + value :: acc) + in + + let* _ = T.to_result state in + Ok (Array.of_list res) -- cgit v1.2.3