2023-04-24 08:48:59 +00:00
|
|
|
from collections import OrderedDict
|
2023-04-25 11:25:53 +00:00
|
|
|
from typing import Optional
|
2023-05-01 08:12:50 +00:00
|
|
|
from importlib import import_module
|
2023-04-25 11:25:53 +00:00
|
|
|
|
|
|
|
from duckdb import DuckDBPyConnection
|
2023-04-24 08:48:59 +00:00
|
|
|
|
2023-05-09 11:30:51 +00:00
|
|
|
MAX_MIGRATION = 8
|
2023-04-24 08:48:59 +00:00
|
|
|
|
|
|
|
MIGRATIONS = OrderedDict()
|
|
|
|
|
2023-05-01 08:12:50 +00:00
|
|
|
for i in range(1, MAX_MIGRATION + 1):
|
|
|
|
MIGRATIONS[i] = import_module(f".migration_{i}", __package__).migration
|
2023-04-25 11:25:53 +00:00
|
|
|
|
|
|
|
def get_version(db: DuckDBPyConnection) -> int:
|
|
|
|
"""Get the current database version.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
db (DuckDBPyConnection): Database connection.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
int: Current database version.
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
return int(db.execute("SELECT MAX(id) FROM migrations").fetchone()[0])
|
|
|
|
except:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def migrate(db: DuckDBPyConnection, from_version: Optional[int] = None, to_version: Optional[int] = None) -> None:
|
|
|
|
"""Migrate the database to a specific version.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
db (DuckDBPyConnection): Database connection.
|
|
|
|
from_version (Optional[int]): Version to migrate from. If None, the current version is used.
|
|
|
|
to_version (Optional[int]): Version to migrate to. If None, the latest version is used.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if from_version is None:
|
|
|
|
from_version = get_version(db)
|
|
|
|
|
|
|
|
if to_version is None:
|
|
|
|
to_version = max(MIGRATIONS.keys())
|
|
|
|
|
|
|
|
if from_version > to_version:
|
|
|
|
raise ValueError("Cannot migrate from a higher version to a lower version.")
|
|
|
|
|
|
|
|
for version in range(from_version, to_version):
|
|
|
|
if version in MIGRATIONS:
|
|
|
|
MIGRATIONS[version + 1](db)
|
|
|
|
|
|
|
|
return from_version, to_version
|