Files
2026-09-16 13:30:22 +08:00

85 lines
2.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Alembic 迁移环境:从 core.config 取连接串,metadata 由全部模型填充。"""
import os
import sys
from logging.config import fileConfig
from alembic import context
from sqlalchemy import create_mock_engine, engine_from_config, pool
# 将 src 加入 sys.path(与 scripts/init_db.py 一致),使 core / modules 可导入
_SRC_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "src")
def _setup_src_path():
if _SRC_DIR not in sys.path:
sys.path.insert(0, _SRC_DIR)
_setup_src_path()
from core.config import SQLALCHEMY_DATABASE_URL
from core.database import Base
# 加载全部模型以填充 metadata(create_app 会连带导入所有业务模块)
from core.app import create_app
create_app()
config = context.config
# set_section_option 不做 % 插值,避免 URL 中特殊字符被 configparser 转义
# 取当前活跃驱动连接串(DB_DRIVER 切换后 alembic 自动跟随)
config.set_section_option("alembic", "sqlalchemy.url", SQLALCHEMY_DATABASE_URL)
if config.config_file_name is not None:
fileConfig(config.config_file_name)
target_metadata = Base.metadata
def run_migrations_offline() -> None:
"""离线模式:不连库,将迁移编译为 SQL 输出。"""
url = config.get_main_option("sqlalchemy.url")
if url.startswith("mssql"):
# 上游 bug workaround:mssql 离线渲染列注释时 dialect.default_schema_name 为 None
# (离线无服务器探活),quote_schema(None) 触发 AttributeError;显式补 'dbo' 可完整渲染。
# create_mock_engine 把原始 DDL 构造体交给 executor,须用同一 dialect 编译成真正 SQL。
def _dump_mssql(sql, *multiparams, **params):
print(sql.compile(dialect=mock_connection.dialect, literal_binds=True))
mock_connection = create_mock_engine(url, _dump_mssql)
mock_connection.dialect.default_schema_name = "dbo"
context.configure(
connection=mock_connection,
target_metadata=target_metadata,
literal_binds=True,
)
else:
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online() -> None:
"""在线模式:连接数据库执行迁移。"""
connectable = engine_from_config(
config.get_section(config.config_ini_section, {}),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()