v1.8.3: fix migrations_runner — split SQL on ; for asyncpg compatibility
This commit is contained in:
@@ -5,8 +5,12 @@
|
||||
1. Создаёт таблицу _applied_migrations (если не существует)
|
||||
2. Проверяет какие SQL-файлы уже применены
|
||||
3. Применяет новые миграции по порядку
|
||||
|
||||
ВАЖНО: asyncpg не поддерживает несколько SQL-команд в одном text().
|
||||
Поэтому каждый SQL-файл разбивается на отдельные команды по ';' .
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
from sqlalchemy import text
|
||||
from app.database import engine
|
||||
@@ -16,6 +20,24 @@ logger = logging.getLogger(__name__)
|
||||
MIGRATIONS_DIR = os.path.join(os.path.dirname(__file__), "migrations")
|
||||
|
||||
|
||||
def _split_sql(sql: str) -> list:
|
||||
"""Разбивает SQL-файл на отдельные команды, пропуская комментарии и пустые строки."""
|
||||
statements = []
|
||||
for stmt in sql.split(";"):
|
||||
# Убираем комментарии (-- ...) и пустые строки
|
||||
lines = []
|
||||
for line in stmt.split("\n"):
|
||||
stripped = line.strip()
|
||||
if stripped.startswith("--"):
|
||||
continue
|
||||
if stripped:
|
||||
lines.append(stripped)
|
||||
clean = " ".join(lines)
|
||||
if clean:
|
||||
statements.append(clean)
|
||||
return statements
|
||||
|
||||
|
||||
async def run_migrations():
|
||||
"""Запуск всех неприменённых миграций из директории migrations/."""
|
||||
async with engine.begin() as conn:
|
||||
@@ -47,9 +69,12 @@ async def run_migrations():
|
||||
with open(filepath, "r", encoding="utf-8") as f:
|
||||
sql = f.read()
|
||||
|
||||
logger.info(f"Применение миграции: {filename}")
|
||||
statements = _split_sql(sql)
|
||||
logger.info(f"Применение миграции: {filename} ({len(statements)} команд)")
|
||||
|
||||
try:
|
||||
await conn.execute(text(sql))
|
||||
for stmt in statements:
|
||||
await conn.execute(text(stmt))
|
||||
await conn.execute(
|
||||
text("INSERT INTO _applied_migrations (filename) VALUES (:fn)"),
|
||||
{"fn": filename}
|
||||
|
||||
Reference in New Issue
Block a user