This commit is contained in:
Mateusz Gruszczyński
2025-09-26 22:42:10 +02:00
parent b679700c6d
commit dfa3028dad
6 changed files with 44 additions and 21 deletions

View File

@@ -6,7 +6,7 @@ PYTHONPATH=. python3 _tools/db/migrate_sqlite_to_pgsql.py
rm -rf venv_migrate rm -rf venv_migrate
# reset wszystkich sekwencji w pgsql # reset wszystkich sekwencji w pgsql
docker exec -it pgsql-db psql -U zbiorki -d zbiorki docker exec -it zbiorka-pgsql-db psql -U zbiorki -d zbiorki
DO $$ DO $$

View File

@@ -1,23 +1,28 @@
import sys import sys
import os import os
from dotenv import load_dotenv
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../"))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")))
load_dotenv()
from sqlalchemy import create_engine, MetaData from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from config import Config from config import Config
from dotenv import load_dotenv
load_dotenv()
# Źródło: SQLite # Źródło: SQLite
sqlite_engine = create_engine("sqlite:///instance/baza.db") sqlite_engine = create_engine("sqlite:///instance/baza.db")
sqlite_meta = MetaData() sqlite_meta = MetaData()
sqlite_meta.reflect(bind=sqlite_engine) sqlite_meta.reflect(bind=sqlite_engine)
# Cel: PostgreSQL # Cel: PostgreSQL
pg_engine = create_engine(Config.SQLALCHEMY_DATABASE_URI) pg_engine = create_engine(Config.SQLALCHEMY_DATABASE_URI)
pg_meta = MetaData() pg_meta = MetaData()
pg_meta.reflect(bind=pg_engine) pg_meta.reflect(bind=pg_engine)
# Sesje # Sesje
SQLiteSession = sessionmaker(bind=sqlite_engine) SQLiteSession = sessionmaker(bind=sqlite_engine)
PGSession = sessionmaker(bind=pg_engine) PGSession = sessionmaker(bind=pg_engine)
@@ -25,19 +30,20 @@ PGSession = sessionmaker(bind=pg_engine)
sqlite_session = SQLiteSession() sqlite_session = SQLiteSession()
pg_session = PGSession() pg_session = PGSession()
def migrate_table(table_name): def migrate_table(table_name):
print("➡️ Używana baza docelowa:", Config.SQLALCHEMY_DATABASE_URI) print("Używana baza docelowa:", Config.SQLALCHEMY_DATABASE_URI)
print(f"\n➡️ Migruję tabelę: {table_name}") print(f"Migruję tabelę: {table_name}")
source_table = sqlite_meta.tables.get(table_name) source_table = sqlite_meta.tables.get(table_name)
target_table = pg_meta.tables.get(table_name) target_table = pg_meta.tables.get(table_name)
if source_table is None or target_table is None: if source_table is None or target_table is None:
print(f"⚠️ Pominięto: {table_name} (brak w jednej z baz)") print(f"Pominięto: {table_name} (brak w jednej z baz)")
return return
rows = sqlite_session.execute(source_table.select()).fetchall() rows = sqlite_session.execute(source_table.select()).fetchall()
if not rows: if not rows:
print(" Brak danych do migracji.") print("Brak danych do migracji.")
return return
insert_data = [dict(row._mapping) for row in rows] insert_data = [dict(row._mapping) for row in rows]
@@ -46,16 +52,17 @@ def migrate_table(table_name):
with pg_engine.begin() as conn: with pg_engine.begin() as conn:
conn.execute(target_table.delete()) conn.execute(target_table.delete())
conn.execute(target_table.insert(), insert_data) conn.execute(target_table.insert(), insert_data)
print(f"Przeniesiono: {len(rows)} rekordów") print(f"Przeniesiono: {len(rows)} rekordów")
except Exception as e: except Exception as e:
print(f"Błąd przy migracji {table_name}: {e}") print(f"Błąd przy migracji {table_name}: {e}")
def main(): def main():
tables = ["user", "shopping_list", "item", "expense", "receipt", "suggested_product"] tables = ["zbiorka", "przedmiot", "uzytkownik", "wydatek", "ustawienia_globalne", "wplata"]
for table in tables: for table in tables:
migrate_table(table) migrate_table(table)
print("\n🎉 Migracja zakończona pomyślnie.") print("\nMigracja zakończona pomyślnie.")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

14
app.py
View File

@@ -178,13 +178,13 @@ def load_user(user_id):
@event.listens_for(Engine, "connect") @event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record): def set_sqlite_pragma(dbapi_connection, connection_record):
try: if dbapi_connection.__class__.__module__.startswith('sqlite3'):
cursor = dbapi_connection.cursor() try:
cursor.execute("PRAGMA foreign_keys=ON") cursor = dbapi_connection.cursor()
cursor.close() cursor.execute("PRAGMA foreign_keys=ON")
except Exception: cursor.close()
pass except Exception:
pass
def get_real_ip(): def get_real_ip():
headers = request.headers headers = request.headers

View File

@@ -19,6 +19,19 @@ GIT_BRANCH="${GIT_BRANCH:-$(git -C "$REPO_DIR" rev-parse --abbrev-ref HEAD 2>/de
DB_PROFILE="sqlite" # domyślnie sqlite, czyli brak profilu pgsql/mysql DB_PROFILE="sqlite" # domyślnie sqlite, czyli brak profilu pgsql/mysql
SERVICES=() SERVICES=()
# Tworzenie katalogów danych dla baz jeśli brak
if [[ "$DB_PROFILE" == "pgsql" ]]; then
if [[ ! -d "./db/pgsql" ]]; then
log "Tworzę katalog ./db/pgsql dla danych PostgreSQL"
mkdir -p ./db/pgsql
fi
elif [[ "$DB_PROFILE" == "mysql" ]]; then
if [[ ! -d "./db/mysql" ]]; then
log "Tworzę katalog ./db/mysql dla danych MySQL"
mkdir -p ./db/mysql
fi
fi
# Przetwarzanie argumentów # Przetwarzanie argumentów
if [[ $# -gt 0 ]]; then if [[ $# -gt 0 ]]; then
case "$1" in case "$1" in

View File

@@ -42,7 +42,7 @@ services:
pgsql: pgsql:
image: postgres:17 image: postgres:17
container_name: pgsql-db container_name: zbiorka-pgsql-db
environment: environment:
POSTGRES_DB: ${DB_NAME} POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER} POSTGRES_USER: ${DB_USER}
@@ -54,7 +54,7 @@ services:
mysql: mysql:
image: mysql:8 image: mysql:8
container_name: mysql-db container_name: zbiorka-mysql-db
environment: environment:
MYSQL_DATABASE: ${DB_NAME} MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER} MYSQL_USER: ${DB_USER}

View File

@@ -3,4 +3,7 @@ Flask-SQLAlchemy
Flask-Login Flask-Login
Werkzeug Werkzeug
waitress waitress
markdown markdown
psycopg2-binary # pgsql
pymysql # mysql
cryptography # mysql8