117 lines
4.4 KiB
Python
117 lines
4.4 KiB
Python
#!/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()
|