domovoy_bot/database/migrate_to_pg.py

117 lines
4.4 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Скрипт для миграции данных из SQLite в PostgreSQL.
1. Считывает данные из sqlite:////home/matrixhasyou/swarm-services/domovoy-bot/database/domovoy.db
2. Записывает данные в postgresql://gemini_admin:secure_swarm_pass_2026@192.168.10.105:5433/domovoy_db
"""
import sys
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(BASE_DIR))
from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.orm import sessionmaker
SQLITE_URL = f"sqlite:///{BASE_DIR / 'database' / 'domovoy.db'}"
POSTGRES_URL = "postgresql://gemini_admin:secure_swarm_pass_2026@192.168.10.105:5433/domovoy_db"
def migrate():
print(f"🔄 Подключение к SQLite: {SQLITE_URL}")
sqlite_engine = create_engine(SQLITE_URL)
sqlite_meta = MetaData()
sqlite_meta.reflect(bind=sqlite_engine)
print(f"🔄 Подключение к PostgreSQL: {POSTGRES_URL}")
pg_engine = create_engine(POSTGRES_URL)
pg_meta = MetaData()
pg_meta.reflect(bind=pg_engine)
SqliteSession = sessionmaker(bind=sqlite_engine)
PgSession = sessionmaker(bind=pg_engine)
sqlite_session = SqliteSession()
pg_session = PgSession()
# Список таблиц в порядке зависимостей (сначала родители, потом потомки)
# Порядок важен из-за внешних ключей (Foreign Keys)
tables_order = [
'users',
'initiative_group',
'messages',
'services',
'verification_requests',
'spy_logs',
'announcements',
'polls',
'spam_warnings',
'message_rates',
'schedules',
'ads',
'payment_reminders',
'profile_history',
'achievements',
'thanks',
'events',
'event_participants',
'scheduled_posts',
'broadcasts',
'broadcast_reads',
'digests',
'email_audit',
'email_export_logs',
'artifacts'
]
# Сначала очистим таблицы в PostgreSQL в обратном порядке (чтобы не нарушать Foreign Keys)
print("🧹 Очистка целевых таблиц в PostgreSQL...")
for table_name in reversed(tables_order):
if table_name in pg_meta.tables:
pg_table = pg_meta.tables[table_name]
try:
pg_session.execute(pg_table.delete())
print(f" Удалены старые записи из {table_name}")
except Exception as e:
print(f" ⚠️ Ошибка очистки {table_name}: {e}")
pg_session.commit()
print("\n🚀 Начало переноса данных...")
for table_name in tables_order:
if table_name not in sqlite_meta.tables:
print(f" ⚠️ Таблица {table_name} отсутствует в SQLite, пропускаем.")
continue
sqlite_table = sqlite_meta.tables[table_name]
pg_table = pg_meta.tables[table_name]
# Получаем данные из SQLite
rows = sqlite_session.execute(sqlite_table.select()).all()
if not rows:
print(f" Таблица {table_name} пуста в SQLite")
continue
print(f" 📦 Перенос {len(rows)} строк для таблицы {table_name}...")
# Подготавливаем данные для вставки
data_to_insert = []
for r in rows:
# Превращаем строку Row в словарь с именами колонок
data_to_insert.append(dict(r._mapping))
# Вставляем данные в PostgreSQL
try:
pg_session.execute(pg_table.insert(), data_to_insert)
pg_session.commit()
print(f" ✅ Перенесено {table_name}")
except Exception as e:
pg_session.rollback()
print(f" ❌ Ошибка переноса таблицы {table_name}: {e}")
sys.exit(1)
sqlite_session.close()
pg_session.close()
print("\n🎉 Миграция успешно завершена!")
if __name__ == "__main__":
migrate()