Change db to Mysql

This commit is contained in:
2025-08-10 10:51:19 -04:00
parent be9f913fbb
commit 0e517b110f
7 changed files with 4219 additions and 21 deletions
+214
View File
@@ -0,0 +1,214 @@
#!/usr/bin/env python3
"""
Database Schema Fix Script
This script fixes the password_hash column length issue and other potential
schema mismatches between PostgreSQL and MySQL.
Usage:
python fix_schema.py
"""
import sys
import os
# Add app directory to path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
try:
from app import app, db
from sqlalchemy import text, inspect
except ImportError as e:
print(f"❌ Error importing modules: {e}")
sys.exit(1)
def fix_mysql_schema():
"""Fix MySQL schema to accommodate PostgreSQL data types"""
print("🔧 FIXING MYSQL SCHEMA")
print("=" * 50)
try:
with app.app_context():
# Check current schema
inspector = inspect(db.engine)
# Fix users table
print("📋 Checking users table schema...")
users_columns = inspector.get_columns('users')
schema_fixes = []
# Check password_hash column length
password_hash_col = next((col for col in users_columns if col['name'] == 'password_hash'), None)
if password_hash_col:
# Check if it's too small (PostgreSQL scrypt hashes can be 200+ characters)
if password_hash_col['type'].length and password_hash_col['type'].length < 255:
schema_fixes.append("ALTER TABLE users MODIFY COLUMN password_hash VARCHAR(255)")
print(f" ⚠️ password_hash column too small ({password_hash_col['type'].length} chars)")
else:
print(f" ✅ password_hash column size OK")
# Check for other potential issues
qr_codes_columns = inspector.get_columns('qr_codes')
# Check qr_code_image column (base64 images can be very long)
qr_image_col = next((col for col in qr_codes_columns if col['name'] == 'qr_code_image'), None)
if qr_image_col:
# QR code images should be TEXT or LONGTEXT, not VARCHAR
if hasattr(qr_image_col['type'], 'length') and qr_image_col['type'].length:
schema_fixes.append("ALTER TABLE qr_codes MODIFY COLUMN qr_code_image LONGTEXT")
print(f" ⚠️ qr_code_image should be LONGTEXT")
else:
print(f" ✅ qr_code_image column type OK")
# Check location_address column
location_addr_col = next((col for col in qr_codes_columns if col['name'] == 'location_address'), None)
if location_addr_col:
if hasattr(location_addr_col['type'], 'length') and location_addr_col['type'].length and location_addr_col['type'].length < 500:
schema_fixes.append("ALTER TABLE qr_codes MODIFY COLUMN location_address TEXT")
print(f" ⚠️ location_address column too small")
else:
print(f" ✅ location_address column size OK")
# Check attendance_data table
print("📋 Checking attendance_data table schema...")
attendance_columns = inspector.get_columns('attendance_data')
# Check address column
address_col = next((col for col in attendance_columns if col['name'] == 'address'), None)
if address_col:
if hasattr(address_col['type'], 'length') and address_col['type'].length and address_col['type'].length < 500:
schema_fixes.append("ALTER TABLE attendance_data MODIFY COLUMN address VARCHAR(500)")
print(f" ⚠️ address column too small")
else:
print(f" ✅ address column size OK")
# Check user_agent column (can be very long)
user_agent_col = next((col for col in attendance_columns if col['name'] == 'user_agent'), None)
if user_agent_col:
if hasattr(user_agent_col['type'], 'length') and user_agent_col['type'].length:
schema_fixes.append("ALTER TABLE attendance_data MODIFY COLUMN user_agent TEXT")
print(f" ⚠️ user_agent should be TEXT")
else:
print(f" ✅ user_agent column type OK")
# Apply fixes
if schema_fixes:
print(f"\n🔨 Applying {len(schema_fixes)} schema fixes...")
for i, fix in enumerate(schema_fixes, 1):
try:
print(f" {i}. {fix}")
db.session.execute(text(fix))
print(f" ✅ Applied successfully")
except Exception as e:
print(f" ❌ Failed: {e}")
db.session.rollback()
return False
db.session.commit()
print(f"\n✅ All schema fixes applied successfully!")
return True
else:
print(f"\n✅ No schema fixes needed - schema looks good!")
return True
except Exception as e:
print(f"❌ Error fixing schema: {e}")
import traceback
traceback.print_exc()
return False
def show_current_schema():
"""Show current MySQL schema for debugging"""
print("\n📋 CURRENT MYSQL SCHEMA")
print("=" * 30)
try:
with app.app_context():
inspector = inspect(db.engine)
tables = ['users', 'qr_codes', 'attendance_data']
for table in tables:
if table in inspector.get_table_names():
print(f"\n📊 {table} table:")
columns = inspector.get_columns(table)
for col in columns:
col_type = str(col['type'])
nullable = "NULL" if col['nullable'] else "NOT NULL"
default = f" DEFAULT {col['default']}" if col['default'] else ""
print(f" {col['name']:<20} {col_type:<20} {nullable}{default}")
else:
print(f"\n{table} table not found")
except Exception as e:
print(f"❌ Error showing schema: {e}")
def test_data_compatibility():
"""Test if sample data would fit in current schema"""
print("\n🧪 TESTING DATA COMPATIBILITY")
print("=" * 35)
# Test password hash length
sample_password_hash = "scrypt:32768:8:1$GMnEGe3K4utb6mNW$3472a6003b60b095d4a9cbb201fe85e662a4d03b7162cf0c5ca896112f04b8f04c202311002ec17d56ef3ad15b232175762ad80be289cb83d546095ddfe14c77"
print(f"📏 Sample password hash length: {len(sample_password_hash)} characters")
# Test QR code image (typical base64 image)
sample_qr_image = "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51" + "A" * 2000 # Simulate base64 image
print(f"📏 Sample QR image length: {len(sample_qr_image)} characters")
# Test user agent string
sample_user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
print(f"📏 Sample user agent length: {len(sample_user_agent)} characters")
try:
with app.app_context():
inspector = inspect(db.engine)
# Check users table
users_columns = inspector.get_columns('users')
password_col = next((col for col in users_columns if col['name'] == 'password_hash'), None)
if password_col and hasattr(password_col['type'], 'length') and password_col['type'].length:
if len(sample_password_hash) > password_col['type'].length:
print(f"❌ Password hash won't fit (needs {len(sample_password_hash)}, has {password_col['type'].length})")
else:
print(f"✅ Password hash will fit")
else:
print(f"✅ Password hash column is TEXT/unlimited")
except Exception as e:
print(f"❌ Error testing compatibility: {e}")
def main():
"""Main function"""
print("MYSQL SCHEMA FIX UTILITY")
print("=" * 60)
# Show current schema
show_current_schema()
# Test compatibility
test_data_compatibility()
# Ask user if they want to apply fixes
print(f"\n" + "="*60)
response = input("Apply schema fixes? (y/n): ").lower().strip()
if response == 'y':
success = fix_mysql_schema()
if success:
print(f"\n🎉 Schema fixes completed!")
print(f"💡 You can now run the migration script again:")
print(f" python migrate_fixed.py --import-mysql")
else:
print(f"\n❌ Schema fixes failed. Check the errors above.")
else:
print(f"\n📋 Schema fixes skipped.")
print(f"💡 To manually fix the password_hash issue, run:")
print(f" ALTER TABLE users MODIFY COLUMN password_hash VARCHAR(255);")
if __name__ == '__main__':
main()