|
@@ -11,9 +11,27 @@ logger = logging.getLogger(__name__)
|
|
|
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
DB_PATH = os.path.join(PROJECT_ROOT, "data", "trading_stats.sqlite")
|
|
|
|
|
|
-# MIGRATION_SET_VERSION identifies this specific group of schema changes.
|
|
|
-# We are bringing the schema to a state that includes the new P&L/risk columns.
|
|
|
-MIGRATION_SET_VERSION = 1
|
|
|
+# -----------------------------------------------------------------------------
|
|
|
+# MIGRATION DEFINITIONS
|
|
|
+# -----------------------------------------------------------------------------
|
|
|
+# Define the latest schema version the application expects.
|
|
|
+# Migrations will run until the DB schema_version matches this.
|
|
|
+LATEST_SCHEMA_VERSION = 2
|
|
|
+
|
|
|
+# Define columns for each migration version set
|
|
|
+# Version 1: Initial set of risk/P&L columns
|
|
|
+MIGRATION_SET_VERSION_1_COLUMNS = {
|
|
|
+ "liquidation_price": "REAL DEFAULT NULL",
|
|
|
+ "margin_used": "REAL DEFAULT NULL",
|
|
|
+ "leverage": "REAL DEFAULT NULL",
|
|
|
+ "position_value": "REAL DEFAULT NULL"
|
|
|
+}
|
|
|
+
|
|
|
+# Version 2: Added unrealized P&L percentage
|
|
|
+MIGRATION_SET_VERSION_2_COLUMNS = {
|
|
|
+ "unrealized_pnl_percentage": "REAL DEFAULT NULL"
|
|
|
+}
|
|
|
+# -----------------------------------------------------------------------------
|
|
|
|
|
|
def _get_db_connection(db_path):
|
|
|
"""Gets a database connection."""
|
|
@@ -67,11 +85,12 @@ def _add_column_if_not_exists(conn, table_name, column_name, column_definition):
|
|
|
logger.info(f"Column '{column_name}' effectively already exists in '{table_name}'. No action needed.")
|
|
|
else:
|
|
|
logger.error(f"Error adding column '{column_name}' to table '{table_name}': {e}")
|
|
|
+ raise # Re-raise to signal migration step failure
|
|
|
else:
|
|
|
logger.info(f"Column '{column_name}' already exists in table '{table_name}'. No action taken.")
|
|
|
|
|
|
def run_migrations():
|
|
|
- """Runs the database migrations."""
|
|
|
+ """Runs the database migrations sequentially."""
|
|
|
logger.info(f"Attempting to migrate database at: {DB_PATH}")
|
|
|
if not os.path.exists(DB_PATH):
|
|
|
logger.info(f"Database file not found at {DB_PATH}. Nothing to migrate. "
|
|
@@ -84,27 +103,36 @@ def run_migrations():
|
|
|
current_db_version = _get_current_schema_version(conn)
|
|
|
logger.info(f"Current reported database schema version: {current_db_version}")
|
|
|
|
|
|
- if current_db_version < MIGRATION_SET_VERSION:
|
|
|
- logger.info(f"Schema version {current_db_version} is older than target migration set {MIGRATION_SET_VERSION}. Starting migration...")
|
|
|
-
|
|
|
- # Define columns to add for MIGRATION_SET_VERSION 1
|
|
|
- # These definitions match what's in the TradingStats._create_tables() method
|
|
|
- columns_to_add = {
|
|
|
- "liquidation_price": "REAL DEFAULT NULL",
|
|
|
- "margin_used": "REAL DEFAULT NULL",
|
|
|
- "leverage": "REAL DEFAULT NULL",
|
|
|
- "position_value": "REAL DEFAULT NULL",
|
|
|
- "unrealized_pnl_percentage": "REAL DEFAULT NULL"
|
|
|
- }
|
|
|
-
|
|
|
- for col_name, col_def in columns_to_add.items():
|
|
|
- _add_column_if_not_exists(conn, "trades", col_name, col_def)
|
|
|
+ if current_db_version < LATEST_SCHEMA_VERSION:
|
|
|
+ logger.info(f"Schema version {current_db_version} is older than target latest schema version {LATEST_SCHEMA_VERSION}. Starting migration process...")
|
|
|
+
|
|
|
+ # --- Migration for Version 1 ---
|
|
|
+ if current_db_version < 1:
|
|
|
+ logger.info("Applying migration set for version 1...")
|
|
|
+ for col_name, col_def in MIGRATION_SET_VERSION_1_COLUMNS.items():
|
|
|
+ _add_column_if_not_exists(conn, "trades", col_name, col_def)
|
|
|
+ _set_schema_version(conn, 1)
|
|
|
+ current_db_version = 1 # Update current_db_version after successful migration
|
|
|
+ logger.info("Successfully migrated database to schema version 1.")
|
|
|
+
|
|
|
+ # --- Migration for Version 2 ---
|
|
|
+ if current_db_version < 2:
|
|
|
+ logger.info("Applying migration set for version 2...")
|
|
|
+ for col_name, col_def in MIGRATION_SET_VERSION_2_COLUMNS.items():
|
|
|
+ _add_column_if_not_exists(conn, "trades", col_name, col_def)
|
|
|
+ _set_schema_version(conn, 2)
|
|
|
+ current_db_version = 2 # Update current_db_version
|
|
|
+ logger.info("Successfully migrated database to schema version 2.")
|
|
|
|
|
|
- # After all operations for this version are successful, update the schema version in DB
|
|
|
- _set_schema_version(conn, MIGRATION_SET_VERSION)
|
|
|
- logger.info(f"Successfully migrated database to schema version {MIGRATION_SET_VERSION}.")
|
|
|
+ # Add more migration blocks here for future versions (e.g., if current_db_version < 3:)
|
|
|
+
|
|
|
+ if current_db_version == LATEST_SCHEMA_VERSION:
|
|
|
+ logger.info(f"All migrations applied. Database is now at schema version {current_db_version}.")
|
|
|
+ else:
|
|
|
+ logger.warning(f"Migration process completed, but DB schema version is {current_db_version}, expected {LATEST_SCHEMA_VERSION}. Check migration logic.")
|
|
|
+
|
|
|
else:
|
|
|
- logger.info(f"Database schema version {current_db_version} is already at or newer than migration set {MIGRATION_SET_VERSION}. No migration needed for this set.")
|
|
|
+ logger.info(f"Database schema version {current_db_version} is already at or newer than latest target schema {LATEST_SCHEMA_VERSION}. No migration needed.")
|
|
|
|
|
|
except sqlite3.Error as e:
|
|
|
logger.error(f"A database error occurred during migration: {e}")
|