nim-chat-sdk/chat_sdk/migration.nim

47 lines
1.4 KiB
Nim
Raw Permalink Normal View History

2025-08-04 10:43:59 +03:00
import os, sequtils, algorithm, strutils
2025-07-04 15:08:45 +08:00
import db_connector/db_sqlite
2025-07-09 18:16:51 +08:00
import chronicles
2025-07-04 15:08:45 +08:00
proc ensureMigrationTable(db: DbConn) =
2025-08-04 10:43:59 +03:00
db.exec(
sql"""
2025-07-04 15:08:45 +08:00
CREATE TABLE IF NOT EXISTS schema_migrations (
filename TEXT PRIMARY KEY,
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
2025-08-04 10:43:59 +03:00
"""
)
2025-07-04 15:08:45 +08:00
proc hasMigrationRun(db: DbConn, filename: string): bool =
2025-08-04 10:43:59 +03:00
for row in db.fastRows(
sql"SELECT 1 FROM schema_migrations WHERE filename = ?", filename
):
2025-07-04 15:08:45 +08:00
return true
return false
proc markMigrationRun(db: DbConn, filename: string) =
db.exec(sql"INSERT INTO schema_migrations (filename) VALUES (?)", filename)
proc runMigrations*(db: DbConn, dir = "migrations") =
2025-07-09 18:16:51 +08:00
info "Migration process starting up"
2025-07-04 15:08:45 +08:00
ensureMigrationTable(db)
let files = walkFiles(dir / "*.sql").toSeq().sorted()
for file in files:
if hasMigrationRun(db, file):
2025-07-09 18:16:51 +08:00
info "Migration already applied", file
2025-07-04 15:08:45 +08:00
else:
2025-07-09 18:16:51 +08:00
info "Applying migration", file
2025-08-04 10:43:59 +03:00
let sqlContent = readFile(file)
2025-08-18 16:40:58 +03:00
db.exec(sql"BEGIN TRANSACTION")
try:
# Split by semicolon and execute each statement separately
for stmt in sqlContent.split(';'):
let trimmedStmt = stmt.strip()
if trimmedStmt.len > 0:
db.exec(sql(trimmedStmt))
markMigrationRun(db, file)
db.exec(sql"COMMIT")
except:
db.exec(sql"ROLLBACK")
raise newException(ValueError, "Migration failed: " & file & " - " & getCurrentExceptionMsg())