2021-01-08 12:47:17 +00:00
|
|
|
module Rep = Representation
|
|
|
|
open Rep
|
2022-04-04 16:30:21 +00:00
|
|
|
open Caqti_request.Infix
|
2021-01-08 12:47:17 +00:00
|
|
|
|
2021-01-27 20:25:51 +00:00
|
|
|
let application_id = 1234839235l
|
|
|
|
|
2024-03-25 15:46:52 +00:00
|
|
|
(* Please update this when making changes! And also update
|
|
|
|
packaging/batch-viz.sh and packaging/visualizations.sh. *)
|
2024-01-09 16:28:03 +00:00
|
|
|
let current_version = 18L
|
2021-01-27 20:25:51 +00:00
|
|
|
|
2021-07-05 12:45:08 +00:00
|
|
|
type 'a id = 'a Rep.id
|
2021-01-08 12:47:17 +00:00
|
|
|
|
2021-01-28 11:17:06 +00:00
|
|
|
type file = Rep.file = {
|
2021-01-08 12:47:17 +00:00
|
|
|
filepath : Fpath.t;
|
|
|
|
sha256 : Cstruct.t;
|
2021-02-25 14:27:45 +00:00
|
|
|
size : int;
|
2021-01-08 12:47:17 +00:00
|
|
|
}
|
|
|
|
|
2021-07-05 12:45:08 +00:00
|
|
|
let last_insert_rowid = Rep.last_insert_rowid
|
2021-01-27 20:25:51 +00:00
|
|
|
|
|
|
|
let get_application_id =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->! Caqti_type.int32 @@
|
|
|
|
"PRAGMA application_id"
|
2021-01-27 20:25:51 +00:00
|
|
|
|
|
|
|
let get_version =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->! Caqti_type.int64 @@
|
|
|
|
"PRAGMA user_version"
|
2021-01-27 20:25:51 +00:00
|
|
|
|
|
|
|
let set_application_id =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
Printf.sprintf "PRAGMA application_id = %ld" application_id
|
2021-01-27 20:25:51 +00:00
|
|
|
|
|
|
|
let set_current_version =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
Printf.sprintf "PRAGMA user_version = %Ld" current_version
|
2021-01-27 20:25:51 +00:00
|
|
|
|
2021-01-08 12:47:17 +00:00
|
|
|
module Job = struct
|
|
|
|
let migrate =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
{| CREATE TABLE job (
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
|
|
name VARCHAR(255) NOT NULL UNIQUE
|
|
|
|
)
|
|
|
|
|}
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let rollback =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP TABLE IF EXISTS job"
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let get =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `job ->! Caqti_type.string @@
|
|
|
|
"SELECT name FROM job WHERE id = ?"
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let get_id_by_name =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.string ->? id `job @@
|
|
|
|
"SELECT id FROM job WHERE name = ?"
|
2021-01-08 12:47:17 +00:00
|
|
|
|
2021-06-29 14:59:08 +00:00
|
|
|
let get_all_with_section_synopsis =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->*
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t4 (id `job) string (option string) (option string)) @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT j.id, j.name, section.value, synopsis.value
|
|
|
|
FROM job j, tag section_tag, tag synopsis_tag
|
|
|
|
LEFT JOIN job_tag section ON section.job = j.id AND section.tag = section_tag.id
|
|
|
|
LEFT JOIN job_tag synopsis ON synopsis.job = j.id AND synopsis.tag = synopsis_tag.id
|
|
|
|
WHERE section_tag.tag = 'section' AND synopsis_tag.tag = 'synopsis'
|
|
|
|
ORDER BY section.value, j.name ASC
|
|
|
|
|}
|
2021-06-29 14:59:08 +00:00
|
|
|
|
2021-01-08 12:47:17 +00:00
|
|
|
let try_add =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.string ->. Caqti_type.unit @@
|
|
|
|
"INSERT OR IGNORE INTO job (name) VALUES (?)"
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let remove =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `job ->. Caqti_type.unit @@
|
|
|
|
"DELETE FROM job WHERE id = ?"
|
2021-01-08 12:47:17 +00:00
|
|
|
end
|
|
|
|
|
2021-06-29 14:59:08 +00:00
|
|
|
module Tag = struct
|
|
|
|
let migrate =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
{| CREATE TABLE tag (
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
|
|
tag VARCHAR(255) NOT NULL UNIQUE
|
|
|
|
)
|
|
|
|
|}
|
2021-06-29 14:59:08 +00:00
|
|
|
|
|
|
|
let rollback =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
2021-06-29 14:59:08 +00:00
|
|
|
"DROP TABLE IF EXISTS tag"
|
|
|
|
|
|
|
|
let get_id_by_name =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.string ->! id `tag @@
|
2021-06-29 14:59:08 +00:00
|
|
|
"SELECT id FROM tag WHERE tag = ?"
|
|
|
|
|
|
|
|
let try_add =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.string ->. Caqti_type.unit @@
|
|
|
|
"INSERT OR IGNORE INTO tag (tag) VALUES (?)"
|
2021-06-29 14:59:08 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
module Job_tag = struct
|
|
|
|
let migrate =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
{| CREATE TABLE job_tag (
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
|
|
tag INTEGER NOT NULL,
|
|
|
|
value TEXT NOT NULL,
|
|
|
|
job INTEGER NOT NULL,
|
|
|
|
|
|
|
|
FOREIGN KEY(job) REFERENCES job(id),
|
|
|
|
FOREIGN KEY(tag) REFERENCES tag(id),
|
|
|
|
UNIQUE(tag, job)
|
|
|
|
)
|
|
|
|
|}
|
2021-06-29 14:59:08 +00:00
|
|
|
|
|
|
|
let rollback =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
2021-06-29 14:59:08 +00:00
|
|
|
"DROP TABLE IF EXISTS job_tag"
|
|
|
|
|
|
|
|
let add =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t3 (id `tag) string (id `job)) ->. Caqti_type.unit @@
|
2022-04-04 16:30:21 +00:00
|
|
|
"INSERT INTO job_tag (tag, value, job) VALUES ($1, $2, $3)"
|
2021-06-30 10:55:00 +00:00
|
|
|
|
|
|
|
let update =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t3 (id `tag) string (id `job)) ->. Caqti_type.unit @@
|
2022-04-04 16:30:21 +00:00
|
|
|
"UPDATE job_tag SET value = $2 WHERE tag = $1 AND job = $3"
|
2021-06-29 14:59:08 +00:00
|
|
|
|
|
|
|
let get_value =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t2 (id `tag) (id `job)) ->? Caqti_type.string @@
|
2022-04-04 16:30:21 +00:00
|
|
|
"SELECT value FROM job_tag WHERE tag = ? AND job = ?"
|
2022-02-22 12:16:42 +00:00
|
|
|
|
|
|
|
let remove_by_job =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `job ->. Caqti_type.unit @@
|
|
|
|
"DELETE FROM job_tag WHERE job = ?"
|
2022-02-22 12:16:42 +00:00
|
|
|
|
2021-06-29 14:59:08 +00:00
|
|
|
end
|
|
|
|
|
2021-01-08 12:47:17 +00:00
|
|
|
module Build_artifact = struct
|
|
|
|
let migrate =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
{| CREATE TABLE build_artifact (
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
|
|
filepath TEXT NOT NULL, -- the path as in the build
|
|
|
|
sha256 BLOB NOT NULL,
|
|
|
|
size INTEGER NOT NULL,
|
|
|
|
build INTEGER NOT NULL,
|
|
|
|
|
|
|
|
FOREIGN KEY(build) REFERENCES build(id),
|
|
|
|
UNIQUE(build, filepath)
|
|
|
|
)
|
|
|
|
|}
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let rollback =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP TABLE IF EXISTS build_artifact"
|
2021-01-08 12:47:17 +00:00
|
|
|
|
2021-09-08 09:10:30 +00:00
|
|
|
let get =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build_artifact ->! file @@
|
2023-09-14 08:58:09 +00:00
|
|
|
{| SELECT filepath, sha256, size
|
2022-04-04 16:30:21 +00:00
|
|
|
FROM build_artifact WHERE id = ? |}
|
2021-09-08 09:10:30 +00:00
|
|
|
|
2021-01-08 12:47:17 +00:00
|
|
|
let get_by_build_uuid =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.t2 uuid fpath ->? Caqti_type.t2 (id `build_artifact) file @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT build_artifact.id, build_artifact.filepath,
|
2023-09-14 08:58:09 +00:00
|
|
|
build_artifact.sha256, build_artifact.size
|
2022-04-04 16:30:21 +00:00
|
|
|
FROM build_artifact
|
|
|
|
INNER JOIN build ON build.id = build_artifact.build
|
|
|
|
WHERE build.uuid = ? AND build_artifact.filepath = ?
|
|
|
|
|}
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let get_all_by_build =
|
2024-08-13 11:07:50 +00:00
|
|
|
id `build ->* Caqti_type.(t2 (id `build_artifact) file) @@
|
2023-09-14 08:58:09 +00:00
|
|
|
"SELECT id, filepath, sha256, size FROM build_artifact WHERE build = ?"
|
|
|
|
|
|
|
|
let exists =
|
|
|
|
cstruct ->! Caqti_type.bool @@
|
2023-09-14 10:29:47 +00:00
|
|
|
"SELECT EXISTS(SELECT 1 FROM build_artifact WHERE sha256 = ?)"
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let add =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t2 file (id `build)) ->. Caqti_type.unit @@
|
2023-09-14 08:58:09 +00:00
|
|
|
"INSERT INTO build_artifact (filepath, sha256, size, build) \
|
2023-09-14 10:49:50 +00:00
|
|
|
VALUES (?, ?, ?, ?)"
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let remove_by_build =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build ->. Caqti_type.unit @@
|
|
|
|
"DELETE FROM build_artifact WHERE build = ?"
|
2021-06-25 12:01:20 +00:00
|
|
|
|
|
|
|
let remove =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build_artifact ->. Caqti_type.unit @@
|
|
|
|
"DELETE FROM build_artifact WHERE id = ?"
|
2021-01-08 12:47:17 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
module Build = struct
|
|
|
|
type t = {
|
|
|
|
uuid : Uuidm.t;
|
|
|
|
start : Ptime.t;
|
|
|
|
finish : Ptime.t;
|
|
|
|
result : Builder.execution_result;
|
2021-08-31 11:59:45 +00:00
|
|
|
console : Fpath.t;
|
|
|
|
script : Fpath.t;
|
2021-11-05 10:45:26 +00:00
|
|
|
platform : string;
|
2021-07-05 12:45:08 +00:00
|
|
|
main_binary : [`build_artifact] id option;
|
2021-07-08 11:33:27 +00:00
|
|
|
input_id : Cstruct.t option;
|
2021-07-05 12:45:08 +00:00
|
|
|
user_id : [`user] id;
|
|
|
|
job_id : [`job] id;
|
2021-01-08 12:47:17 +00:00
|
|
|
}
|
|
|
|
|
2023-12-20 15:38:02 +00:00
|
|
|
let pp ppf t =
|
|
|
|
Fmt.pf ppf "@[<hov>{ uuid=@ %a;@ \
|
|
|
|
start=@ %a;@ \
|
|
|
|
finish=@ %a;@ \
|
|
|
|
result=@ @[<hov>%a@];@ \
|
|
|
|
console=@ %a;@ \
|
|
|
|
script=@ %a;@ \
|
|
|
|
platform=@ %S;@ \
|
|
|
|
main_binary=@ @[<hov>%a@];@ \
|
|
|
|
input_id=@ @[<hov>%a@];@ \
|
|
|
|
user_id=@ %Lx;@ \
|
|
|
|
job_id=@ %Lx;@ }@]"
|
|
|
|
Uuidm.pp t.uuid
|
|
|
|
Ptime.pp t.start
|
|
|
|
Ptime.pp t.finish
|
|
|
|
Builder.pp_execution_result t.result
|
|
|
|
Fpath.pp t.console
|
|
|
|
Fpath.pp t.script
|
|
|
|
t.platform
|
|
|
|
Fmt.(Dump.option int64) t.main_binary
|
|
|
|
Fmt.(Dump.option (using Cstruct.to_string string)) t.input_id
|
|
|
|
t.user_id
|
|
|
|
t.job_id
|
|
|
|
|
|
|
|
|
2021-01-08 12:47:17 +00:00
|
|
|
let t =
|
|
|
|
let rep =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t11
|
|
|
|
uuid
|
|
|
|
Rep.ptime
|
|
|
|
Rep.ptime
|
|
|
|
execution_result
|
|
|
|
fpath
|
|
|
|
fpath
|
|
|
|
string
|
|
|
|
(option (Rep.id `build_artifact))
|
|
|
|
(option Rep.cstruct)
|
2021-07-05 12:45:08 +00:00
|
|
|
(id `user)
|
|
|
|
(id `job))
|
2021-01-08 12:47:17 +00:00
|
|
|
in
|
2021-11-05 10:45:26 +00:00
|
|
|
let encode { uuid; start; finish; result; console; script; platform; main_binary; input_id; user_id; job_id } =
|
2024-08-13 11:07:50 +00:00
|
|
|
Ok (uuid, start, finish, result, console, script, platform, main_binary, input_id, user_id, job_id)
|
2021-01-08 12:47:17 +00:00
|
|
|
in
|
2024-08-13 11:07:50 +00:00
|
|
|
let decode (uuid, start, finish, result, console, script, platform, main_binary, input_id, user_id, job_id) =
|
2021-11-05 10:45:26 +00:00
|
|
|
Ok { uuid; start; finish; result; console; script; platform; main_binary; input_id; user_id; job_id }
|
2021-01-08 12:47:17 +00:00
|
|
|
in
|
|
|
|
Caqti_type.custom ~encode ~decode rep
|
|
|
|
|
|
|
|
let migrate =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
{| CREATE TABLE build (
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
|
|
uuid VARCHAR(36) NOT NULL UNIQUE,
|
|
|
|
start_d INTEGER NOT NULL,
|
|
|
|
start_ps INTEGER NOT NULL,
|
|
|
|
finish_d INTEGER NOT NULL,
|
|
|
|
finish_ps INTEGER NOT NULL,
|
|
|
|
result_code INTEGER NOT NULL,
|
|
|
|
result_msg TEXT,
|
|
|
|
console TEXT NOT NULL,
|
|
|
|
script TEXT NOT NULL,
|
|
|
|
platform TEXT NOT NULL,
|
|
|
|
main_binary INTEGER,
|
|
|
|
user INTEGER NOT NULL,
|
|
|
|
job INTEGER NOT NULL,
|
|
|
|
input_id BLOB, -- sha256 (sha256<opam-switch> || sha256<build-environment> || sha256<system-packages>)
|
|
|
|
|
|
|
|
FOREIGN KEY(main_binary) REFERENCES build_artifact(id) DEFERRABLE INITIALLY DEFERRED,
|
|
|
|
FOREIGN KEY(user) REFERENCES user(id),
|
|
|
|
FOREIGN KEY(job) REFERENCES job(id)
|
|
|
|
)
|
|
|
|
|}
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let rollback =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP TABLE IF EXISTS build"
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let get_by_uuid =
|
2024-08-13 11:07:50 +00:00
|
|
|
Rep.uuid ->? Caqti_type.t2 (id `build) t @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT id, uuid, start_d, start_ps, finish_d, finish_ps,
|
|
|
|
result_code, result_msg,
|
|
|
|
console, script, platform, main_binary, input_id, user, job
|
|
|
|
FROM build
|
|
|
|
WHERE uuid = ?
|
|
|
|
|}
|
2021-01-08 12:47:17 +00:00
|
|
|
|
|
|
|
let get_all =
|
2024-08-13 11:07:50 +00:00
|
|
|
id `job ->* Caqti_type.t2 (id `build) t @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT id, uuid, start_d, start_ps, finish_d, finish_ps,
|
|
|
|
result_code, result_msg, console,
|
|
|
|
script, platform, main_binary, input_id, user, job
|
|
|
|
FROM build
|
|
|
|
WHERE job = ?
|
|
|
|
ORDER BY start_d DESC, start_ps DESC
|
|
|
|
|}
|
2021-01-08 12:47:17 +00:00
|
|
|
|
2021-11-17 14:02:04 +00:00
|
|
|
let get_all_failed =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t3 int int (option string)) ->* Caqti_type.t2 Caqti_type.string t @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT job.name, b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg, b.console, b.script, b.platform,
|
|
|
|
b.main_binary, b.input_id, b.user, b.job
|
|
|
|
FROM build b
|
|
|
|
INNER JOIN job ON job.id = b.job
|
2023-09-09 08:22:51 +00:00
|
|
|
WHERE b.main_binary IS NULL AND ($3 IS NULL OR b.platform = $3)
|
2022-04-04 16:30:21 +00:00
|
|
|
ORDER BY start_d DESC, start_ps DESC
|
|
|
|
LIMIT $2
|
|
|
|
OFFSET $1
|
|
|
|
|}
|
2021-11-17 14:02:04 +00:00
|
|
|
|
2021-07-08 11:33:27 +00:00
|
|
|
let get_all_artifact_sha =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t2 (id `job) (option string)) ->* Rep.cstruct @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT DISTINCT a.sha256
|
|
|
|
FROM build_artifact a, build b
|
|
|
|
WHERE b.job = $1 AND b.main_binary = a.id
|
|
|
|
AND ($2 IS NULL OR b.platform = $2)
|
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
|}
|
2021-11-08 10:55:11 +00:00
|
|
|
|
2021-11-17 16:39:49 +00:00
|
|
|
let get_failed_builds =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t2 (id `job) (option string)) ->* t @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT uuid, start_d, start_ps, finish_d, finish_ps,
|
|
|
|
result_code, result_msg, console, script,
|
|
|
|
platform, main_binary, input_id, user, job
|
|
|
|
FROM build
|
2023-09-09 08:15:11 +00:00
|
|
|
WHERE job = $1
|
2023-09-09 08:22:51 +00:00
|
|
|
AND main_binary IS NULL
|
2022-04-04 16:30:21 +00:00
|
|
|
AND ($2 IS NULL OR platform = $2)
|
|
|
|
ORDER BY start_d DESC, start_ps DESC
|
|
|
|
|}
|
2021-11-08 10:55:11 +00:00
|
|
|
|
2021-11-17 16:00:58 +00:00
|
|
|
let get_latest_successful_with_binary =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t2 (id `job) string) ->? Caqti_type.t3 (id `build) t file @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT b.id,
|
|
|
|
b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg, b.console, b.script,
|
|
|
|
b.platform, b.main_binary, b.input_id, b.user, b.job,
|
2023-09-14 08:58:09 +00:00
|
|
|
a.filepath, a.sha256, a.size
|
2023-11-22 12:43:09 +00:00
|
|
|
FROM build b, build_artifact a
|
|
|
|
WHERE b.main_binary = a.id AND b.job = $1 AND b.platform = $2
|
|
|
|
AND b.main_binary IS NOT NULL
|
2022-04-04 16:30:21 +00:00
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
LIMIT 1
|
|
|
|
|}
|
2021-01-08 12:47:17 +00:00
|
|
|
|
2023-12-20 15:38:02 +00:00
|
|
|
let get_builds_older_than =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t3 (id `job) (option string) Rep.ptime) ->* Caqti_type.t2 (id `build) t @@
|
2024-02-12 13:59:57 +00:00
|
|
|
{| SELECT id, uuid, start_d, start_ps, finish_d, finish_ps,
|
2024-02-05 16:33:18 +00:00
|
|
|
result_code, result_msg, console, script,
|
|
|
|
platform, main_binary, input_id, user, job
|
|
|
|
FROM build
|
|
|
|
WHERE job = $1
|
2023-12-20 15:38:02 +00:00
|
|
|
AND ($2 IS NULL OR platform = $2)
|
2024-02-05 16:33:18 +00:00
|
|
|
AND (finish_d < $3 OR (finish_d = $3 AND finish_ps <= $4))
|
|
|
|
ORDER BY start_d DESC, start_ps DESC
|
2023-12-20 15:38:02 +00:00
|
|
|
|}
|
|
|
|
|
2024-01-09 12:05:24 +00:00
|
|
|
let get_builds_excluding_latest_n =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t3 (id `job) (option string) int) ->* Caqti_type.t2 (id `build) t @@
|
2024-02-12 13:59:57 +00:00
|
|
|
{| SELECT id, uuid, start_d, start_ps, finish_d, finish_ps,
|
2024-02-05 16:33:18 +00:00
|
|
|
result_code, result_msg, console, script,
|
|
|
|
platform, main_binary, input_id, user, job
|
|
|
|
FROM build
|
|
|
|
WHERE job = $1
|
2023-12-20 15:38:02 +00:00
|
|
|
AND ($2 IS NULL OR platform = $2)
|
2024-02-05 16:33:18 +00:00
|
|
|
ORDER BY start_d DESC, start_ps DESC
|
2023-12-20 15:38:02 +00:00
|
|
|
LIMIT -1 OFFSET $3
|
|
|
|
|}
|
2024-01-09 12:12:18 +00:00
|
|
|
(* "LIMIT -1 OFFSET n" is all rows except the first n *)
|
2023-12-20 15:38:02 +00:00
|
|
|
|
2024-02-13 13:07:16 +00:00
|
|
|
let get_nth_latest_successful =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t3 (id `job) (option string) int) ->? Caqti_type.t2 (id `build) t @@
|
2024-02-13 13:07:16 +00:00
|
|
|
{| SELECT id, uuid, start_d, start_ps, finish_d, finish_ps,
|
|
|
|
result_code, result_msg, console, script,
|
|
|
|
platform, main_binary, input_id, user, job
|
|
|
|
FROM build
|
|
|
|
WHERE job = $1
|
|
|
|
AND ($2 IS NULL OR platform = $2)
|
|
|
|
AND main_binary IS NOT NULL
|
|
|
|
ORDER BY start_d DESC, start_ps DESC
|
|
|
|
LIMIT 1 OFFSET $3
|
|
|
|
|}
|
|
|
|
|
2021-11-17 15:28:15 +00:00
|
|
|
let get_latest_successful =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.(t2 (id `job) (option string)) ->? t @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT
|
|
|
|
b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg, b.console, b.script,
|
|
|
|
b.platform, b.main_binary, b.input_id, b.user, b.job
|
|
|
|
FROM build b
|
2023-09-09 08:22:51 +00:00
|
|
|
WHERE b.job = $1
|
2022-04-04 16:30:21 +00:00
|
|
|
AND ($2 IS NULL OR b.platform = $2)
|
2023-08-25 10:32:42 +00:00
|
|
|
AND b.main_binary IS NOT NULL
|
2022-04-04 16:30:21 +00:00
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
LIMIT 1
|
|
|
|
|}
|
2021-11-08 10:55:11 +00:00
|
|
|
|
2021-11-17 15:28:15 +00:00
|
|
|
let get_previous_successful_different_output =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build ->? t @@
|
|
|
|
{| SELECT
|
|
|
|
b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg, b.console, b.script,
|
|
|
|
b.platform, b.main_binary, b.input_id, b.user, b.job
|
|
|
|
FROM build b, build b0, build_artifact a, build_artifact a0
|
|
|
|
WHERE b0.id = ? AND b0.job = b.job AND
|
|
|
|
b.platform = b0.platform AND
|
2023-11-22 11:23:00 +00:00
|
|
|
b.main_binary IS NOT NULL AND
|
2022-04-04 16:30:21 +00:00
|
|
|
a.id = b.main_binary AND a0.id = b0.main_binary AND
|
|
|
|
a.sha256 <> a0.sha256 AND
|
|
|
|
(b0.start_d > b.start_d OR b0.start_d = b.start_d AND b0.start_ps > b.start_ps)
|
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
LIMIT 1
|
|
|
|
|}
|
2021-04-23 10:06:39 +00:00
|
|
|
|
2021-11-17 15:28:15 +00:00
|
|
|
let get_next_successful_different_output =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build ->? t @@
|
|
|
|
{| SELECT
|
|
|
|
b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg, b.console, b.script,
|
|
|
|
b.platform, b.main_binary, b.input_id, b.user, b.job
|
|
|
|
FROM build b, build b0, build_artifact a, build_artifact a0
|
|
|
|
WHERE b0.id = ? AND b0.job = b.job AND
|
|
|
|
b.platform = b0.platform AND
|
2023-11-22 11:23:00 +00:00
|
|
|
b.main_binary IS NOT NULL AND
|
2022-04-04 16:30:21 +00:00
|
|
|
a.id = b.main_binary AND a0.id = b0.main_binary AND
|
|
|
|
a.sha256 <> a0.sha256 AND
|
|
|
|
(b0.start_d < b.start_d OR b0.start_d = b.start_d AND b0.start_ps < b.start_ps)
|
|
|
|
ORDER BY b.start_d ASC, b.start_ps ASC
|
|
|
|
LIMIT 1
|
|
|
|
|}
|
2021-11-08 10:55:11 +00:00
|
|
|
|
2021-07-08 11:33:27 +00:00
|
|
|
let get_same_input_same_output_builds =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build ->* t @@
|
|
|
|
{| SELECT b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg, b.console, b.script,
|
|
|
|
b.platform, b.main_binary, b.input_id, b.user, b.job
|
|
|
|
FROM build b0, build_artifact a0, build b, build_artifact a
|
|
|
|
WHERE b0.id = ? AND a0.id = b0.main_binary AND a0.sha256 = a.sha256
|
|
|
|
AND b.main_binary = a.id AND b.id <> b0.id AND b0.input_id = b.input_id
|
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
|}
|
2021-07-06 10:23:29 +00:00
|
|
|
|
2021-07-08 11:33:27 +00:00
|
|
|
let get_same_input_different_output_hashes =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build ->* Rep.cstruct @@
|
|
|
|
{| SELECT DISTINCT a.sha256
|
|
|
|
FROM build b0, build_artifact a0, build b, build_artifact a
|
|
|
|
WHERE b0.id = ? AND a0.id = b0.main_binary AND a0.sha256 <> a.sha256
|
|
|
|
AND b.main_binary = a.id AND b.id <> b0.id AND b0.input_id = b.input_id
|
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
|}
|
2021-07-08 11:33:27 +00:00
|
|
|
|
|
|
|
let get_different_input_same_output_input_ids =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build ->* Rep.cstruct @@
|
|
|
|
{| SELECT DISTINCT b.input_id
|
|
|
|
FROM build b0, build_artifact a0, build b, build_artifact a
|
|
|
|
WHERE b0.id = ? AND a0.id = b0.main_binary AND a0.sha256 = a.sha256
|
|
|
|
AND b.main_binary = a.id AND b0.input_id <> b.input_id
|
|
|
|
|}
|
2021-07-08 11:33:27 +00:00
|
|
|
|
|
|
|
let get_one_by_input_id =
|
2022-04-04 16:30:21 +00:00
|
|
|
Rep.cstruct ->! t @@
|
|
|
|
{| SELECT uuid, start_d, start_ps, finish_d, finish_ps,
|
|
|
|
result_code, result_msg, console, script,
|
|
|
|
platform, main_binary, input_id, user, job
|
|
|
|
FROM build
|
|
|
|
WHERE input_id = ?
|
|
|
|
ORDER BY start_d DESC, start_ps DESC
|
|
|
|
LIMIT 1
|
|
|
|
|}
|
2021-07-08 11:33:27 +00:00
|
|
|
|
2021-11-08 10:55:11 +00:00
|
|
|
let get_platforms_for_job =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `job ->* Caqti_type.string @@
|
2022-07-27 07:45:01 +00:00
|
|
|
"SELECT DISTINCT platform FROM build WHERE job = ? ORDER BY platform"
|
2021-11-08 10:55:11 +00:00
|
|
|
|
2021-01-08 12:47:17 +00:00
|
|
|
let add =
|
2022-04-04 16:30:21 +00:00
|
|
|
t ->. Caqti_type.unit @@
|
|
|
|
{| INSERT INTO build
|
|
|
|
(uuid, start_d, start_ps, finish_d, finish_ps,
|
|
|
|
result_code, result_msg, console, script, platform, main_binary, input_id, user, job)
|
|
|
|
VALUES
|
|
|
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
|
|
|}
|
2021-01-08 12:47:17 +00:00
|
|
|
|
2021-08-31 11:59:45 +00:00
|
|
|
let get_by_hash =
|
2022-04-04 16:30:21 +00:00
|
|
|
Rep.cstruct ->! t @@
|
|
|
|
{| SELECT
|
|
|
|
b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg, b.console, b.script,
|
|
|
|
b.platform, b.main_binary, b.input_id, b.user, b.job
|
|
|
|
FROM build_artifact a
|
|
|
|
INNER JOIN build b ON b.id = a.build
|
|
|
|
WHERE a.sha256 = ?
|
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
LIMIT 1
|
|
|
|
|}
|
2021-07-08 11:33:27 +00:00
|
|
|
|
2021-08-31 11:59:45 +00:00
|
|
|
let get_with_main_binary_by_hash =
|
2024-08-13 11:07:50 +00:00
|
|
|
Rep.cstruct ->! Caqti_type.t2 t file_opt @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg, b.console, b.script,
|
|
|
|
b.platform, b.main_binary, b.input_id, b.user, b.job,
|
2023-09-14 08:58:09 +00:00
|
|
|
a.filepath, a.sha256, a.size
|
2022-04-04 16:30:21 +00:00
|
|
|
FROM build_artifact a
|
|
|
|
INNER JOIN build b ON b.id = a.build
|
|
|
|
WHERE a.sha256 = ?
|
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
LIMIT 1
|
|
|
|
|}
|
2021-07-08 11:33:27 +00:00
|
|
|
|
2021-08-31 11:59:45 +00:00
|
|
|
let get_with_jobname_by_hash =
|
2024-08-13 11:07:50 +00:00
|
|
|
Rep.cstruct ->? Caqti_type.t2 Caqti_type.string t @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT job.name,
|
|
|
|
b.uuid, b.start_d, b.start_ps, b.finish_d, b.finish_ps,
|
|
|
|
b.result_code, b.result_msg,
|
|
|
|
b.console, b.script, b.platform, b.main_binary, b.input_id, b.user, b.job
|
|
|
|
FROM build_artifact a
|
|
|
|
INNER JOIN build b ON b.id = a.build
|
|
|
|
INNER JOIN job ON job.id = b.job
|
|
|
|
WHERE a.sha256 = ?
|
|
|
|
ORDER BY b.start_d DESC, b.start_ps DESC
|
|
|
|
LIMIT 1
|
|
|
|
|}
|
2021-03-08 16:01:00 +00:00
|
|
|
|
2021-06-02 10:29:08 +00:00
|
|
|
let set_main_binary =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.t2 (id `build) (id `build_artifact) ->. Caqti_type.unit @@
|
2022-04-04 16:30:21 +00:00
|
|
|
"UPDATE build SET main_binary = $2 WHERE id = $1"
|
2021-06-02 10:29:08 +00:00
|
|
|
|
2021-03-08 16:01:00 +00:00
|
|
|
let remove =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `build ->. Caqti_type.unit @@
|
|
|
|
"DELETE FROM build WHERE id = ?"
|
2021-01-08 12:47:17 +00:00
|
|
|
end
|
|
|
|
|
2021-01-20 21:50:35 +00:00
|
|
|
module User = struct
|
|
|
|
let migrate =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
{| CREATE TABLE user (
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
|
|
username VARCHAR(255) NOT NULL UNIQUE,
|
|
|
|
password_hash BLOB NOT NULL,
|
|
|
|
password_salt BLOB NOT NULL,
|
|
|
|
scrypt_n INTEGER NOT NULL,
|
|
|
|
scrypt_r INTEGER NOT NULL,
|
|
|
|
scrypt_p INTEGER NOT NULL,
|
|
|
|
restricted BOOLEAN NOT NULL
|
|
|
|
)
|
|
|
|
|}
|
2021-01-20 21:50:35 +00:00
|
|
|
|
|
|
|
let rollback =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP TABLE IF EXISTS user"
|
2021-01-20 21:50:35 +00:00
|
|
|
|
|
|
|
let get_user =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.string ->? Caqti_type.t2 (id `user) user_info @@
|
2022-04-04 16:30:21 +00:00
|
|
|
{| SELECT id, username, password_hash, password_salt,
|
|
|
|
scrypt_n, scrypt_r, scrypt_p, restricted
|
|
|
|
FROM user
|
|
|
|
WHERE username = ?
|
|
|
|
|}
|
2021-01-20 21:50:35 +00:00
|
|
|
|
|
|
|
let get_all =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->* Caqti_type.string @@
|
|
|
|
"SELECT username FROM user"
|
2021-01-20 21:50:35 +00:00
|
|
|
|
|
|
|
let add =
|
2022-04-04 16:30:21 +00:00
|
|
|
user_info ->. Caqti_type.unit @@
|
|
|
|
{| INSERT INTO user (username, password_hash, password_salt,
|
|
|
|
scrypt_n, scrypt_r, scrypt_p, restricted)
|
|
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
|
|
|}
|
2021-01-20 21:50:35 +00:00
|
|
|
|
|
|
|
let remove_user =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.string ->. Caqti_type.unit @@
|
|
|
|
"DELETE FROM user WHERE username = ?"
|
2021-01-20 21:50:35 +00:00
|
|
|
|
|
|
|
let update_user =
|
2022-04-04 16:30:21 +00:00
|
|
|
user_info ->. Caqti_type.unit @@
|
|
|
|
{| UPDATE user
|
|
|
|
SET password_hash = $2,
|
|
|
|
password_salt = $3,
|
|
|
|
scrypt_n = $4,
|
|
|
|
scrypt_r = $5,
|
|
|
|
scrypt_p = $6,
|
|
|
|
restricted = $7
|
|
|
|
WHERE username = $1
|
|
|
|
|}
|
2021-01-20 21:50:35 +00:00
|
|
|
end
|
|
|
|
|
2021-06-08 14:54:23 +00:00
|
|
|
module Access_list = struct
|
|
|
|
let migrate =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
{| CREATE TABLE access_list (
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
|
|
user INTEGER NOT NULL,
|
|
|
|
job INTEGER NOT NULL,
|
|
|
|
|
|
|
|
FOREIGN KEY(user) REFERENCES user(id),
|
|
|
|
FOREIGN KEY(job) REFERENCES job(id),
|
|
|
|
UNIQUE(user, job)
|
|
|
|
)
|
|
|
|
|}
|
2021-06-08 14:54:23 +00:00
|
|
|
|
|
|
|
let rollback =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP TABLE IF EXISTS access_list"
|
2021-06-08 14:54:23 +00:00
|
|
|
|
|
|
|
let get =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.t2 (id `user) (id `job) ->! id `access_list @@
|
2022-04-04 16:30:21 +00:00
|
|
|
"SELECT id FROM access_list WHERE user = ? AND job = ?"
|
2021-06-08 14:54:23 +00:00
|
|
|
|
|
|
|
let add =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.t2 (id `user) (id `job) ->. Caqti_type.unit @@
|
2022-04-04 16:30:21 +00:00
|
|
|
"INSERT INTO access_list (user, job) VALUES (?, ?)"
|
2021-06-08 14:54:23 +00:00
|
|
|
|
|
|
|
let remove =
|
2024-08-13 11:07:50 +00:00
|
|
|
Caqti_type.t2 (id `user) (id `job) ->. Caqti_type.unit @@
|
2022-04-04 16:30:21 +00:00
|
|
|
"DELETE FROM access_list WHERE user = ? AND job = ?"
|
2021-06-08 14:54:23 +00:00
|
|
|
|
2022-02-22 12:16:42 +00:00
|
|
|
let remove_by_job =
|
2022-04-04 16:30:21 +00:00
|
|
|
id `job ->. Caqti_type.unit @@
|
|
|
|
"DELETE FROM access_list WHERE job = ?"
|
2022-02-22 12:16:42 +00:00
|
|
|
|
2021-06-08 14:54:23 +00:00
|
|
|
let remove_all_by_username =
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.string ->. Caqti_type.unit @@
|
|
|
|
{| DELETE FROM access_list
|
|
|
|
WHERE access_list.id IN (
|
|
|
|
SELECT access_list.id
|
|
|
|
FROM access_list
|
|
|
|
INNER JOIN user ON access_list.user = user.id
|
|
|
|
WHERE user.username = ?
|
|
|
|
)
|
|
|
|
|}
|
2021-06-08 14:54:23 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
2021-01-08 12:47:17 +00:00
|
|
|
let migrate = [
|
|
|
|
Job.migrate;
|
|
|
|
Build.migrate;
|
|
|
|
Build_artifact.migrate;
|
2021-01-20 21:50:35 +00:00
|
|
|
User.migrate;
|
2021-06-08 14:54:23 +00:00
|
|
|
Access_list.migrate;
|
2021-06-29 14:59:08 +00:00
|
|
|
Tag.migrate;
|
|
|
|
Job_tag.migrate;
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"CREATE INDEX idx_build_job_start ON build(job, start_d DESC, start_ps DESC)";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
2023-09-09 08:22:51 +00:00
|
|
|
"CREATE INDEX idx_build_failed ON build(job, start_d DESC, start_ps DESC) WHERE main_binary IS NULL";
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"CREATE INDEX idx_build_input_id ON build(input_id)";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"CREATE INDEX idx_build_main_binary ON build(main_binary)";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"CREATE INDEX idx_build_artifact_sha256 ON build_artifact(sha256)";
|
2023-09-14 08:58:09 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"CREATE INDEX idx_build_artifact_build ON build_artifact(build)";
|
2021-01-27 20:25:51 +00:00
|
|
|
set_current_version;
|
|
|
|
set_application_id;
|
2021-01-08 12:47:17 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
let rollback = [
|
2021-06-29 14:59:08 +00:00
|
|
|
Job_tag.rollback;
|
|
|
|
Tag.rollback;
|
2021-06-08 14:54:23 +00:00
|
|
|
Access_list.rollback;
|
2021-01-20 21:50:35 +00:00
|
|
|
User.rollback;
|
2021-01-08 12:47:17 +00:00
|
|
|
Build_artifact.rollback;
|
|
|
|
Build.rollback;
|
|
|
|
Job.rollback;
|
2022-04-04 16:30:21 +00:00
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
2023-09-14 08:58:09 +00:00
|
|
|
"DROP INDEX IF EXISTS idx_build_artifact_build";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
2022-04-04 16:30:21 +00:00
|
|
|
"DROP INDEX IF EXISTS idx_build_artifact_sha256";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP INDEX IF EXISTS idx_build_failed";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP INDEX IF EXISTS idx_build_input_id";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP INDEX IF EXISTS idx_build_main_binary";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"DROP INDEX IF EXISTS idx_build_job_start";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"PRAGMA user_version = 0";
|
|
|
|
Caqti_type.unit ->. Caqti_type.unit @@
|
|
|
|
"PRAGMA application_id = 0";
|
2021-01-08 12:47:17 +00:00
|
|
|
]
|