run_migrations.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import os
  2. import db
  3. import sys
  4. # Ensure backend dir is in path
  5. sys.path.append(os.path.dirname(os.path.abspath(__file__)))
  6. MIGRATIONS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "migrations")
  7. def init_migrations_table():
  8. query = """
  9. CREATE TABLE IF NOT EXISTS `schema_migrations` (
  10. `id` int(11) NOT NULL AUTO_INCREMENT,
  11. `migration_name` varchar(255) NOT NULL,
  12. `applied_at` timestamp DEFAULT CURRENT_TIMESTAMP,
  13. PRIMARY KEY (`id`),
  14. UNIQUE KEY `migration_name` (`migration_name`)
  15. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  16. """
  17. db.execute_commit(query)
  18. def get_applied_migrations():
  19. rows = db.execute_query("SELECT migration_name FROM schema_migrations")
  20. return [r['migration_name'] for r in rows]
  21. def run_migrations():
  22. print(f"Checking for migrations in {MIGRATIONS_DIR}...")
  23. init_migrations_table()
  24. applied = get_applied_migrations()
  25. # Get all .sql files from migrations dir
  26. files = [f for f in os.listdir(MIGRATIONS_DIR) if f.endswith(".sql")]
  27. files.sort() # Ensure they run in order (001, 002...)
  28. count = 0
  29. for filename in files:
  30. if filename not in applied:
  31. print(f"Applying migration: {filename}...")
  32. filepath = os.path.join(MIGRATIONS_DIR, filename)
  33. with open(filepath, "r", encoding="utf-8") as f:
  34. sql = f.read()
  35. # Execute the migration (handling potential multiple statements)
  36. # Simple splitter by semicolon (works for basic schemas)
  37. statements = [s.strip() for s in sql.split(";") if s.strip()]
  38. for stmt in statements:
  39. try:
  40. db.execute_commit(stmt)
  41. except Exception as e:
  42. # Ignore "Duplicate column name" or "Table already exists" errors
  43. err_msg = str(e).lower()
  44. if "duplicate column" in err_msg or "already exists" in err_msg or "duplicate key" in err_msg:
  45. print(f" Note: Statement skipped (already applied or exists): {stmt[:50]}...")
  46. else:
  47. raise e
  48. # Mark as applied
  49. db.execute_commit("INSERT INTO schema_migrations (migration_name) VALUES (%s)", (filename,))
  50. print(f"Successfully applied {filename}")
  51. count += 1
  52. if count == 0:
  53. print("No new migrations to apply.")
  54. else:
  55. print(f"Applied {count} migrations.")
  56. if __name__ == "__main__":
  57. try:
  58. run_migrations()
  59. except Exception as e:
  60. print(f"MIGRATION ERROR: {e}")
  61. sys.exit(1)