#!/usr/bin/env python3 """ Migrate MariaDB export to SQLite for qaffee. Usage: python3 db/migrate_to_sqlite.py Creates data/qaffee.db ready for use with the Quarkus backend. Flyway will baseline at V4 on first startup (no re-migration needed). """ import re import sqlite3 import os import sys SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) REPO_ROOT = os.path.join(SCRIPT_DIR, '..') MIGRATION_DIR = os.path.join(REPO_ROOT, 'backend', 'src', 'main', 'resources', 'db', 'migration') EXPORT_FILE = os.path.join(SCRIPT_DIR, 'mariadb_export.sql') OUTPUT_FILE = os.path.join(REPO_ROOT, 'data', 'qaffee.db') # V2 (seed data) is intentionally skipped – it inserts dev/test rows that # conflict with production IDs in the export. MIGRATIONS = [ 'V1__initial_schema.sql', 'V3__company_logo.sql', 'V4__tally_price_at_booking.sql', ] # Tables to import in FK-safe order (parents before children) DATA_TABLES = ['company', 'employee', 'product', 'access_link', 'tally_entry'] def apply_migrations(conn: sqlite3.Connection) -> None: for filename in MIGRATIONS: path = os.path.join(MIGRATION_DIR, filename) with open(path, 'r', encoding='utf-8') as f: sql = f.read() conn.executescript(sql) print(f' schema {filename}') def mariadb_to_sqlite_sql(sql: str) -> str: # Remove MariaDB sandbox-mode comment at the top sql = re.sub(r'/\*M!.*?\*/', '', sql, flags=re.DOTALL) # Strip backtick identifier quotes sql = sql.replace('`', '') # Convert 0xABCD hex literals to SQLite X'ABCD' blob literals sql = re.sub(r'\b0x([0-9A-Fa-f]+)', r"X'\1'", sql) return sql def extract_insert(sql: str, table: str) -> str | None: """Return the full INSERT INTO VALUES ...; statement, or None.""" pattern = rf'(INSERT INTO {re.escape(table)} VALUES\s*.*?;)' match = re.search(pattern, sql, re.DOTALL) return match.group(1) if match else None def main() -> None: os.makedirs(os.path.dirname(OUTPUT_FILE), exist_ok=True) if os.path.exists(OUTPUT_FILE): os.remove(OUTPUT_FILE) print(f'Removed existing {OUTPUT_FILE}') print('Reading MariaDB export ...') with open(EXPORT_FILE, 'r', encoding='utf-8') as f: raw_sql = f.read() sqlite_sql = mariadb_to_sqlite_sql(raw_sql) print('Creating SQLite database ...') conn = sqlite3.connect(OUTPUT_FILE) print('Applying schema migrations:') apply_migrations(conn) print('Importing data:') for table in DATA_TABLES: stmt = extract_insert(sqlite_sql, table) if stmt is None: print(f' skip {table} (no data in export)') continue conn.executescript(stmt) # Count rows for feedback count = conn.execute(f'SELECT COUNT(*) FROM {table}').fetchone()[0] print(f' import {table} ({count} rows)') conn.commit() conn.close() size_kb = os.path.getsize(OUTPUT_FILE) // 1024 print(f'\nDone – {OUTPUT_FILE} ({size_kb} KB)') print() print('Next steps:') print(' 1. docker compose up --build') print(' Flyway will baseline at V4 and skip all migrations.') print(' 2. Verify at https://qaffee.cloud.aquantico.de') if __name__ == '__main__': main()