aboutsummaryrefslogtreecommitdiff
path: root/lib/sql/header.ml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sql/header.ml')
-rw-r--r--lib/sql/header.ml74
1 files changed, 74 insertions, 0 deletions
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)