discord-bot-kernel/src/db/migration.rs

90 lines
2.5 KiB
Rust

use sqlx::SqlitePool;
use tracing::info;
pub async fn run(pool: &SqlitePool) -> anyhow::Result<()> {
sqlx::query(
"CREATE TABLE IF NOT EXISTS _migrations (
version INTEGER PRIMARY KEY,
name TEXT NOT NULL,
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
)",
)
.execute(pool)
.await?;
let migrations = [
("V1__initial", V1_INITIAL),
("V2__tickets", V2_TICKETS),
("V3__reminders", V3_REMINDERS),
("V4__ticket_cooldown", V4_COOLDOWN),
];
for (name, sql) in migrations {
let exists: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM _migrations WHERE name = ?")
.bind(name)
.fetch_one(pool)
.await?;
if exists == 0 {
let mut tx = pool.begin().await?;
for stmt in sql.split(';').map(str::trim).filter(|s| !s.is_empty()) {
sqlx::query(stmt).execute(&mut *tx).await?;
}
sqlx::query("INSERT INTO _migrations(name) VALUES(?)")
.bind(name)
.execute(&mut *tx)
.await?;
tx.commit().await?;
info!(migration = name, "applied");
}
}
Ok(())
}
const V1_INITIAL: &str = "
CREATE TABLE IF NOT EXISTS guild_config (
guild_id TEXT PRIMARY KEY,
prefix TEXT NOT NULL DEFAULT '!',
lang TEXT NOT NULL DEFAULT 'ru'
);
CREATE TABLE IF NOT EXISTS user_stats (
user_id TEXT PRIMARY KEY,
xp INTEGER NOT NULL DEFAULT 0,
level INTEGER NOT NULL DEFAULT 0,
message_count INTEGER NOT NULL DEFAULT 0
);
";
const V2_TICKETS: &str = "
CREATE TABLE IF NOT EXISTS ticket_blacklist (
guild_id TEXT NOT NULL,
user_id TEXT NOT NULL,
reason TEXT NOT NULL,
PRIMARY KEY (guild_id, user_id)
);
CREATE TABLE IF NOT EXISTS ticket_claims (
channel_id TEXT PRIMARY KEY,
guild_id TEXT NOT NULL,
claimed_by TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS tickets (
channel_id TEXT PRIMARY KEY,
guild_id TEXT NOT NULL,
opener_id TEXT NOT NULL
);
";
const V3_REMINDERS: &str = "
CREATE TABLE IF NOT EXISTS reminders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
channel_id TEXT NOT NULL,
message TEXT NOT NULL,
due_at TEXT NOT NULL,
sent INTEGER NOT NULL DEFAULT 0
);
";
const V4_COOLDOWN: &str = "
CREATE TABLE IF NOT EXISTS ticket_cooldowns (
user_id TEXT NOT NULL,
guild_id TEXT NOT NULL,
expires_at INTEGER NOT NULL,
PRIMARY KEY (user_id, guild_id)
);
";