|
| 1 | +#!/usr/bin/env python3 |
| 2 | +"""Manually add missing columns to generated_roadmaps table.""" |
| 3 | + |
| 4 | +import sys |
| 5 | +from pathlib import Path |
| 6 | + |
| 7 | +# Add parent directory to path |
| 8 | +sys.path.insert(0, str(Path(__file__).parent.parent)) |
| 9 | + |
| 10 | +from sqlalchemy import create_engine, text |
| 11 | +from app.core.config import settings |
| 12 | + |
| 13 | +def main(): |
| 14 | + print("=" * 70) |
| 15 | + print("ADDING MISSING COLUMNS TO generated_roadmaps") |
| 16 | + print("=" * 70) |
| 17 | + |
| 18 | + engine = create_engine(str(settings.database_url)) |
| 19 | + |
| 20 | + # SQL statements to add missing columns |
| 21 | + column_additions = [ |
| 22 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS primary_language VARCHAR(64);", |
| 23 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS languages JSON;", |
| 24 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS topics JSON;", |
| 25 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS difficulty VARCHAR(32);", |
| 26 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS star_count INTEGER DEFAULT 0;", |
| 27 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS fork_count INTEGER DEFAULT 0;", |
| 28 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS last_pushed_at TIMESTAMP;", |
| 29 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS license VARCHAR(128);", |
| 30 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS contributor_count INTEGER DEFAULT 0;", |
| 31 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS view_count INTEGER DEFAULT 0;", |
| 32 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS sync_count INTEGER DEFAULT 0;", |
| 33 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS rating_count INTEGER DEFAULT 0;", |
| 34 | + "ALTER TABLE generated_roadmaps ADD COLUMN IF NOT EXISTS rating_sum INTEGER DEFAULT 0;", |
| 35 | + ] |
| 36 | + |
| 37 | + with engine.begin() as conn: |
| 38 | + print("\nAdding columns...") |
| 39 | + for i, sql in enumerate(column_additions, 1): |
| 40 | + try: |
| 41 | + print(f" {i}. {sql[:80]}...") |
| 42 | + conn.execute(text(sql)) |
| 43 | + print(f" ✅ Success") |
| 44 | + except Exception as e: |
| 45 | + print(f" ⚠️ Warning: {e}") |
| 46 | + # Continue anyway - column might already exist |
| 47 | + |
| 48 | + print("\n" + "=" * 70) |
| 49 | + print("✅ Column addition complete!") |
| 50 | + print("\nNow verifying columns exist...") |
| 51 | + |
| 52 | + # Verify columns were added |
| 53 | + with engine.connect() as conn: |
| 54 | + result = conn.execute(text(""" |
| 55 | + SELECT column_name |
| 56 | + FROM information_schema.columns |
| 57 | + WHERE table_name = 'generated_roadmaps' |
| 58 | + AND column_name IN ( |
| 59 | + 'primary_language', 'languages', 'topics', 'difficulty', |
| 60 | + 'star_count', 'fork_count', 'last_pushed_at', 'license', |
| 61 | + 'contributor_count', 'view_count', 'sync_count', |
| 62 | + 'rating_count', 'rating_sum' |
| 63 | + ) |
| 64 | + ORDER BY column_name |
| 65 | + """)) |
| 66 | + |
| 67 | + found_columns = [row[0] for row in result.fetchall()] |
| 68 | + |
| 69 | + expected = [ |
| 70 | + 'contributor_count', 'difficulty', 'fork_count', 'languages', |
| 71 | + 'last_pushed_at', 'license', 'primary_language', 'rating_count', |
| 72 | + 'rating_sum', 'star_count', 'sync_count', 'topics', 'view_count' |
| 73 | + ] |
| 74 | + |
| 75 | + print(f"\nFound {len(found_columns)}/{len(expected)} expected columns:") |
| 76 | + for col in sorted(found_columns): |
| 77 | + print(f" ✅ {col}") |
| 78 | + |
| 79 | + missing = set(expected) - set(found_columns) |
| 80 | + if missing: |
| 81 | + print(f"\n❌ Still missing: {', '.join(sorted(missing))}") |
| 82 | + sys.exit(1) |
| 83 | + else: |
| 84 | + print("\n🎉 All columns present!") |
| 85 | + |
| 86 | +if __name__ == "__main__": |
| 87 | + main() |
0 commit comments