Spaces:
Sleeping
Sleeping
| # Database Safety Guide | |
| ## β οΈ CRITICAL: Database Management Rules | |
| ### Tables Are Managed in Supabase | |
| - **ALL tables are created and managed in Supabase** via `docs/schema/schema.sql` | |
| - **SQLAlchemy models ONLY map to existing tables** - they do NOT create tables | |
| - **Alembic migrations are DISABLED** for automatic execution | |
| ### Why This Approach? | |
| 1. **Safety** - Prevents accidental table creation/modification in production | |
| 2. **Control** - All schema changes reviewed and applied manually in Supabase | |
| 3. **Audit Trail** - Supabase tracks all schema changes | |
| 4. **Rollback** - Easy to rollback changes in Supabase dashboard | |
| ### How to Make Schema Changes | |
| #### β NEVER DO THIS: | |
| ```python | |
| # DON'T call this in production code! | |
| Base.metadata.create_all(bind=engine) | |
| ``` | |
| #### β CORRECT PROCESS: | |
| 1. **Update schema.sql** | |
| ```sql | |
| -- Add new column to users table | |
| ALTER TABLE users ADD COLUMN new_field TEXT; | |
| ``` | |
| 2. **Test in Supabase Dashboard** | |
| - Go to SQL Editor | |
| - Run the ALTER statement | |
| - Verify it works | |
| 3. **Update SQLAlchemy Model** | |
| ```python | |
| class User(BaseModel): | |
| __tablename__ = "users" | |
| new_field = Column(String(255), nullable=True) | |
| ``` | |
| 4. **Deploy Code** | |
| - Models now map to updated table | |
| - No automatic migrations run | |
| ### Alembic Configuration | |
| Alembic is configured but **NOT used for automatic migrations**. | |
| **Current setup:** | |
| - `alembic.ini` - Points to environment variable (not hardcoded) | |
| - `alembic/versions/` - Empty (no migration files) | |
| - Migrations must be run **manually** after review | |
| **If you need to use Alembic:** | |
| ```bash | |
| # 1. Create migration (review it first!) | |
| alembic revision --autogenerate -m "description" | |
| # 2. Review the generated migration file | |
| # Check: alembic/versions/xxx_description.py | |
| # 3. Test in development first | |
| alembic upgrade head | |
| # 4. If safe, run in production (manually) | |
| ``` | |
| ### Model Mapping Rules | |
| 1. **Use `__tablename__`** - Always specify snake_case table name | |
| ```python | |
| class User(BaseModel): | |
| __tablename__ = "users" # β Matches Supabase table | |
| ``` | |
| 2. **Match column names exactly** - Use snake_case | |
| ```python | |
| first_name = Column(String(100)) # β Matches DB column | |
| firstName = Column(String(100)) # β Won't work | |
| ``` | |
| 3. **Match data types** - Use correct SQLAlchemy types | |
| ```python | |
| # Supabase: UUID | |
| id = Column(UUID(as_uuid=True)) # β | |
| # Supabase: JSONB | |
| metadata = Column(JSONB, default={}) # β | |
| # Supabase: TIMESTAMP WITH TIME ZONE | |
| created_at = Column(DateTime(timezone=True)) # β | |
| ``` | |
| 4. **Don't define relationships yet** - Keep models simple | |
| ```python | |
| # β Avoid for now (adds complexity) | |
| # tickets = relationship("Ticket", back_populates="user") | |
| # β Use queries instead | |
| # tickets = db.query(Ticket).filter(Ticket.user_id == user.id).all() | |
| ``` | |
| ### Checking Table Structure | |
| **In Supabase Dashboard:** | |
| 1. Go to Table Editor | |
| 2. Select table | |
| 3. View columns, types, constraints | |
| **In Code:** | |
| ```python | |
| from sqlalchemy import inspect | |
| inspector = inspect(engine) | |
| columns = inspector.get_columns('users') | |
| print(columns) | |
| ``` | |
| ### Current Table Status | |
| All 41 tables exist in Supabase: | |
| - β users | |
| - β clients | |
| - β contractors | |
| - β projects | |
| - β tickets | |
| - β (36 more tables...) | |
| See `docs/schema/schema.sql` for complete schema. | |
| ### Safety Checklist | |
| Before deploying code: | |
| - [ ] No `Base.metadata.create_all()` calls in code | |
| - [ ] No automatic Alembic migrations in startup | |
| - [ ] Models use correct `__tablename__` | |
| - [ ] Column names match Supabase (snake_case) | |
| - [ ] Data types match Supabase schema | |
| - [ ] Tested queries work with existing tables | |
| ### Emergency: If Tables Get Created Accidentally | |
| If code accidentally creates duplicate tables: | |
| 1. **Stop the application immediately** | |
| 2. **Check Supabase logs** - See what was created | |
| 3. **Drop duplicate tables** (if any) | |
| ```sql | |
| DROP TABLE IF EXISTS duplicate_table_name; | |
| ``` | |
| 4. **Fix the code** - Remove table creation logic | |
| 5. **Redeploy** | |
| ### Questions? | |
| - Schema questions β Check `docs/schema/schema.sql` | |
| - Model questions β Check `src/app/models/` | |
| - Migration questions β Ask before running! | |