创建基本的表结构
This commit is contained in:
81
konabot/common/permsys/migrates/__init__.py
Normal file
81
konabot/common/permsys/migrates/__init__.py
Normal file
@ -0,0 +1,81 @@
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
import aiosqlite
|
||||
from loguru import logger
|
||||
|
||||
from konabot.common.database import DatabaseManager
|
||||
from konabot.common.path import DATA_PATH
|
||||
|
||||
|
||||
PATH_THISFOLDER = Path(__file__).parent
|
||||
|
||||
SQL_CHECK_EXISTS = (PATH_THISFOLDER / "./check_migrate_version_exists.sql").read_text()
|
||||
SQL_CREATE_TABLE = (PATH_THISFOLDER / "./create_migrate_version_table.sql").read_text()
|
||||
SQL_GET_MIGRATE_VERSION = (PATH_THISFOLDER / "get_migrate_version.sql").read_text()
|
||||
SQL_UPDATE_VERSION = (PATH_THISFOLDER / "./update_migrate_version.sql").read_text()
|
||||
|
||||
db = DatabaseManager(DATA_PATH / "perm.sqlite3")
|
||||
|
||||
|
||||
@dataclass
|
||||
class Migration:
|
||||
upgrade: str | Path
|
||||
downgrade: str | Path
|
||||
|
||||
def get_upgrade_script(self) -> str:
|
||||
if isinstance(self.upgrade, Path):
|
||||
return self.upgrade.read_text()
|
||||
return self.upgrade
|
||||
|
||||
def get_downgrade_script(self) -> str:
|
||||
if isinstance(self.upgrade, Path):
|
||||
return self.upgrade.read_text()
|
||||
return self.upgrade
|
||||
|
||||
|
||||
migrations = [
|
||||
Migration(
|
||||
PATH_THISFOLDER / "./mu1_create_permsys_table.sql",
|
||||
PATH_THISFOLDER / "./md1_remove_permsys_table.sql",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
TARGET_VERSION = len(migrations)
|
||||
|
||||
|
||||
async def get_current_version(conn: aiosqlite.Connection) -> int:
|
||||
cursor = await conn.execute(SQL_CHECK_EXISTS)
|
||||
count = await cursor.fetchone()
|
||||
assert count is not None
|
||||
if count[0] < 1:
|
||||
logger.info("权限系统数据表不存在,现在创建表")
|
||||
await conn.executescript(SQL_CREATE_TABLE)
|
||||
await conn.commit()
|
||||
return -1
|
||||
cursor = await conn.execute(SQL_GET_MIGRATE_VERSION)
|
||||
row = await cursor.fetchone()
|
||||
if row is None:
|
||||
return -1
|
||||
return row[0]
|
||||
|
||||
|
||||
async def execute_migration(
|
||||
conn: aiosqlite.Connection,
|
||||
version: int = TARGET_VERSION,
|
||||
migrations: list[Migration] = migrations,
|
||||
):
|
||||
now_version = await get_current_version(conn)
|
||||
while now_version < version:
|
||||
migration = migrations[now_version]
|
||||
await conn.executescript(migration.get_upgrade_script())
|
||||
now_version += 1
|
||||
await conn.execute(SQL_UPDATE_VERSION, (now_version,))
|
||||
await conn.commit()
|
||||
while now_version > version:
|
||||
migration = migrations[now_version - 1]
|
||||
await conn.executescript(migration.get_downgrade_script())
|
||||
now_version -= 1
|
||||
await conn.execute(SQL_UPDATE_VERSION, (now_version,))
|
||||
await conn.commit()
|
||||
@ -0,0 +1,7 @@
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
sqlite_master
|
||||
WHERE
|
||||
type = 'table'
|
||||
AND name = 'migrate_version'
|
||||
@ -0,0 +1,3 @@
|
||||
CREATE TABLE migrate_version(version INT PRIMARY KEY);
|
||||
INSERT INTO migrate_version(version)
|
||||
VALUES(0);
|
||||
4
konabot/common/permsys/migrates/get_migrate_version.sql
Normal file
4
konabot/common/permsys/migrates/get_migrate_version.sql
Normal file
@ -0,0 +1,4 @@
|
||||
SELECT
|
||||
version
|
||||
FROM
|
||||
migrate_version;
|
||||
@ -0,0 +1,2 @@
|
||||
DROP TABLE IF EXISTS perm_entity;
|
||||
DROP TABLE IF EXISTS perm_info;
|
||||
25
konabot/common/permsys/migrates/mu1_create_permsys_table.sql
Normal file
25
konabot/common/permsys/migrates/mu1_create_permsys_table.sql
Normal file
@ -0,0 +1,25 @@
|
||||
CREATE TABLE perm_entity(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
platform TEXT NOT NULL,
|
||||
entity_type TEXT NOT NULL,
|
||||
external_id TEXT NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE perm_info(
|
||||
entity_id INTEGER NOT NULL,
|
||||
config_key TEXT NOT NULL,
|
||||
value BOOLEAN NOT NULL,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TRIGGER perm_entity_update AFTER UPDATE
|
||||
ON perm_entity BEGIN
|
||||
UPDATE perm_entity SET updated_at=CURRENT_TIMESTAMP WHERE id=old.id;
|
||||
END;
|
||||
CREATE TRIGGER perm_info_update AFTER UPDATE
|
||||
ON perm_info BEGIN
|
||||
UPDATE perm_info SET updated_at=CURRENT_TIMESTAMP WHERE id=old.id;
|
||||
END;
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
UPDATE migrate_version
|
||||
SET version = ?;
|
||||
32
tests/test_permsys.py
Normal file
32
tests/test_permsys.py
Normal file
@ -0,0 +1,32 @@
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
import pytest
|
||||
|
||||
from konabot.common.database import DatabaseManager
|
||||
from konabot.common.permsys.migrates import execute_migration, get_current_version
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def tempdb():
|
||||
with TemporaryDirectory() as _tempdir:
|
||||
tempdir = Path(_tempdir)
|
||||
db = DatabaseManager(tempdir / "perm.sqlite3")
|
||||
yield db
|
||||
await db.close_all_connections()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_db_version():
|
||||
async with tempdb() as db:
|
||||
async with db.get_conn() as conn:
|
||||
v = await get_current_version(conn)
|
||||
assert v == -1
|
||||
v = await get_current_version(conn)
|
||||
assert v == 0
|
||||
await execute_migration(conn, version=1)
|
||||
v = await get_current_version(conn)
|
||||
assert v == 1
|
||||
await execute_migration(conn, version=0)
|
||||
v = await get_current_version(conn)
|
||||
assert v == 0
|
||||
Reference in New Issue
Block a user