feat(server): initial implementation of migrations
parent
96d0c2f1eb
commit
d1979ab05f
52
src/db/db.v
52
src/db/db.v
|
@ -1,19 +1,65 @@
|
||||||
module db
|
module db
|
||||||
|
|
||||||
import sqlite
|
import sqlite
|
||||||
import models { BuildLog, GitRepo }
|
|
||||||
|
|
||||||
struct VieterDb {
|
struct VieterDb {
|
||||||
conn sqlite.DB
|
conn sqlite.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MigrationVersion {
|
||||||
|
id int [primary]
|
||||||
|
version int
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
migrations_up = [$embed_file('migrations/001-initial/up.sql')]
|
||||||
|
migrations_down = [$embed_file('migrations/001-initial/down.sql')]
|
||||||
|
)
|
||||||
|
|
||||||
// init initializes a database & adds the correct tables.
|
// init initializes a database & adds the correct tables.
|
||||||
pub fn init(db_path string) ?VieterDb {
|
pub fn init(db_path string) ?VieterDb {
|
||||||
conn := sqlite.connect(db_path)?
|
conn := sqlite.connect(db_path)?
|
||||||
|
|
||||||
sql conn {
|
sql conn {
|
||||||
create table GitRepo
|
create table MigrationVersion
|
||||||
create table BuildLog
|
}
|
||||||
|
|
||||||
|
cur_version := sql conn {
|
||||||
|
select from MigrationVersion limit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no row yet, we add it here
|
||||||
|
if cur_version == MigrationVersion{} {
|
||||||
|
sql conn {
|
||||||
|
insert cur_version into MigrationVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply each migration in order
|
||||||
|
for i in cur_version.version .. db.migrations_up.len {
|
||||||
|
migration := db.migrations_up[i].to_string()
|
||||||
|
|
||||||
|
version_num := i + 1
|
||||||
|
|
||||||
|
// vfmt does not like these dots
|
||||||
|
println('Applying migration $version_num' + '...')
|
||||||
|
|
||||||
|
// The sqlite library seems to not like it when multiple statements are
|
||||||
|
// passed in a single exec. Therefore, we split them & run them all
|
||||||
|
// separately.
|
||||||
|
for part in migration.split(';').map(it.trim_space()).filter(it != '') {
|
||||||
|
res := conn.exec_none(part)
|
||||||
|
|
||||||
|
if res != sqlite.sqlite_done {
|
||||||
|
return error('An error occurred while applying migration $version_num')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The where clause doesn't really matter, as there will always only be
|
||||||
|
// one entry anyways.
|
||||||
|
sql conn {
|
||||||
|
update MigrationVersion set version = version_num where id > 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return VieterDb{
|
return VieterDb{
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
DROP TABLE BuildLog;
|
||||||
|
DROP TABLE GitRepoArch;
|
||||||
|
DROP TABLE GitRepo;
|
|
@ -0,0 +1,22 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS GitRepo (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
url TEXT NOT NULL,
|
||||||
|
branch TEXT NOT NULL,
|
||||||
|
repo TEXT NOT NULL,
|
||||||
|
schedule TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS GitRepoArch (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
repo_id INTEGER NOT NULL,
|
||||||
|
value TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS BuildLog (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
repo_id INTEGER NOT NULL,
|
||||||
|
start_time INTEGER NOT NULL,
|
||||||
|
end_time iNTEGER NOT NULL,
|
||||||
|
arch TEXT NOT NULL,
|
||||||
|
exit_code INTEGER NOT NULL
|
||||||
|
);
|
|
@ -68,7 +68,9 @@ pub fn server(conf Config) ? {
|
||||||
}
|
}
|
||||||
|
|
||||||
db_file := os.join_path_single(conf.data_dir, server.db_file_name)
|
db_file := os.join_path_single(conf.data_dir, server.db_file_name)
|
||||||
db := db.init(db_file) or { util.exit_with_message(1, 'Failed to initialize database.') }
|
db := db.init(db_file) or {
|
||||||
|
util.exit_with_message(1, 'Failed to initialize database: $err.msg()')
|
||||||
|
}
|
||||||
|
|
||||||
web.run(&App{
|
web.run(&App{
|
||||||
logger: logger
|
logger: logger
|
||||||
|
|
Loading…
Reference in New Issue