fix(api): add users pk column compatibility at startup
This commit is contained in:
@@ -939,3 +939,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` 的库,该逻辑不产生任何改动。
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -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` 的库无行为变化。
|
||||
Reference in New Issue
Block a user