v1.8.3: fix migrations_runner — split SQL on ; for asyncpg compatibility
Tests / test (push) Has been cancelled
Tests / test-max-bot (push) Has been cancelled

This commit is contained in:
2026-06-02 19:04:34 +03:00
parent 8c1486da8b
commit 5bb9ffd459
+27 -2
View File
@@ -5,8 +5,12 @@
1. Создаёт таблицу _applied_migrations (если не существует) 1. Создаёт таблицу _applied_migrations (если не существует)
2. Проверяет какие SQL-файлы уже применены 2. Проверяет какие SQL-файлы уже применены
3. Применяет новые миграции по порядку 3. Применяет новые миграции по порядку
ВАЖНО: asyncpg не поддерживает несколько SQL-команд в одном text().
Поэтому каждый SQL-файл разбивается на отдельные команды по ';' .
""" """
import os import os
import re
import logging import logging
from sqlalchemy import text from sqlalchemy import text
from app.database import engine from app.database import engine
@@ -16,6 +20,24 @@ logger = logging.getLogger(__name__)
MIGRATIONS_DIR = os.path.join(os.path.dirname(__file__), "migrations") 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(): async def run_migrations():
"""Запуск всех неприменённых миграций из директории migrations/.""" """Запуск всех неприменённых миграций из директории migrations/."""
async with engine.begin() as conn: async with engine.begin() as conn:
@@ -47,9 +69,12 @@ async def run_migrations():
with open(filepath, "r", encoding="utf-8") as f: with open(filepath, "r", encoding="utf-8") as f:
sql = f.read() sql = f.read()
logger.info(f"Применение миграции: {filename}") statements = _split_sql(sql)
logger.info(f"Применение миграции: {filename} ({len(statements)} команд)")
try: try:
await conn.execute(text(sql)) for stmt in statements:
await conn.execute(text(stmt))
await conn.execute( await conn.execute(
text("INSERT INTO _applied_migrations (filename) VALUES (:fn)"), text("INSERT INTO _applied_migrations (filename) VALUES (:fn)"),
{"fn": filename} {"fn": filename}