fix(api): add users pk column compatibility at startup
fquiz 镜像构建与部署 / build-and-push (push) Has been cancelled
fquiz 镜像构建与部署 / deploy (push) Has been cancelled

This commit is contained in:
chengkai3
2026-05-01 08:49:53 +08:00
parent be675caaf7
commit 67fc0bc865
3 changed files with 58 additions and 1 deletions
+7
View File
@@ -961,3 +961,10 @@
- 缓冲区分析联动:
- `GET /api/v1/lightning-currents/stats/tower-buffer` 返回 `terrain_metrics`(若杆塔已有地形指标)。
- 风险分级引入地形暴露权重:`ng_for_risk = ng * (1 + 0.25 * exposure)`,但原始返回字段 `ng_per_km2_year` 保持未加权值。
## users 主键兼容口径(2026-05-01
- 用户主键列工程约定仍为 `users.user_id`
- 为兼容历史库(残留 `users.id`)并避免启动 seed 阶段出现 `UndefinedColumn: users.user_id``init_db()` 在 PostgreSQL 下新增启动期兼容逻辑:
- 若检测到 `users` 表存在且仅有 `id`、缺少 `user_id`,自动执行 `ALTER TABLE users RENAME COLUMN id TO user_id`,再继续 `create_all/seed`
- 对已对齐 `users.user_id` 的库,该逻辑不产生任何改动。
+31 -1
View File
@@ -2,7 +2,7 @@ from collections.abc import Generator
import logging
from typing import Any
from sqlalchemy import create_engine
from sqlalchemy import create_engine, inspect, text
from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker
from .config import get_settings
@@ -38,6 +38,35 @@ class Base(DeclarativeBase):
pass
def _ensure_user_pk_column_compatibility() -> None:
"""
Keep legacy databases compatible with the current ORM mapping.
Historical deployments may still use `users.id` as the primary key column.
Current models and foreign keys uniformly target `users.user_id`.
"""
if not database_url.startswith("postgresql"):
return
schema = settings.resolved_db_schema
with engine.begin() as connection:
db_inspector = inspect(connection)
if not db_inspector.has_table("users", schema=schema):
return
column_names = {
column["name"]
for column in db_inspector.get_columns("users", schema=schema)
}
if "user_id" in column_names or "id" not in column_names:
return
connection.execute(text("ALTER TABLE users RENAME COLUMN id TO user_id"))
logger.warning(
"Detected legacy users.id primary key; renamed to users.user_id for schema compatibility.",
)
def get_db() -> Generator[Session, None, None]:
db = SessionLocal()
try:
@@ -74,6 +103,7 @@ def init_db() -> None:
) # noqa: F401
from ..services.seed_service import seed_defaults
_ensure_user_pk_column_compatibility()
Base.metadata.create_all(bind=engine)
with SessionLocal() as db:
local_hosts = {"db", "localhost", "127.0.0.1", "::1"}
+20
View File
@@ -0,0 +1,20 @@
## Work Log - 修复 API 启动阶段 users 主键列兼容问题(2026-05-01
- 背景:
- 启动报错 `psycopg.errors.UndefinedColumn: column users.user_id does not exist`,触发点在 `seed_defaults -> _seed_permissions` 的关系加载 SQL。
- 当前 ORM 与外键约定统一使用 `users.user_id`,但历史库可能残留 `users.id` 主键列命名。
- 本次改动:
- `api/app/core/database.py`
- 新增 `_ensure_user_pk_column_compatibility()`
-`init_db()` 执行 `Base.metadata.create_all()` 前,针对 PostgreSQL 做一次兼容检查:
-`users` 表存在,且检测到仅有 `id` 而没有 `user_id`,自动执行:`ALTER TABLE users RENAME COLUMN id TO user_id`
- 其余情况不改动(已是 `user_id` 或两者都不存在时直接跳过)。
- 验证:
-`fquiz-api` 容器内执行 `init_db()``init_db_ok`
-`fquiz-api` 容器内执行查询,确认当前数据库 `users` 列包含 `user_id`
- 风险与影响:
- 影响范围:仅 PostgreSQL 且仅触发于“存在 `users.id` 且缺少 `users.user_id`”的历史库。
- 该变更属于启动期一次性 DDL 兼容动作;对已规范为 `users.user_id` 的库无行为变化。