Database Management Skill
1. SQLAlchemy Base Class & Models
All database models (except system/internal models where not applicable) must inherit from BaseModel defined in server/app/models/base.py.
Automatically Handled by BaseModel
- Table Names: Automatically converted from
PascalCaseclass names tosnake_case(e.g.,Todos->todos,Attachments->attachments). - Primary Keys: Defined as a native PostgreSQL UUID using
PG_UUID(as_uuid=True)with database-side generatorserver_default=text("gen_random_uuid()"). - Audit Fields: All models inherit these auditing and metadata fields:
id: Mapped[UUID] primary key.is_active: Boolean status defaulting totrueon the server.is_deleted: Soft-delete status defaulting tofalseon the server.created_at/updated_at: Timezone-aware UTC timestamps withserver_default=func.now()(andonupdate=func.now()for updates).created_by/updated_by: VARCHAR(100) auditing fields.
Best Practices for Custom Models
- Inheritance: Always subclass
BaseModel. - Use Database Defaults: Lean on PostgreSQL for default values as much as possible using
server_default(e.g.server_default=text("true")rather than Python-leveldefault=True). - Type Annotations: Use SQLAlchemy 2.0
Mapped[...]andmapped_column()syntax. - Foreign Keys:
- Explicitly define
ondeletebehavior (e.g.ondelete="CASCADE"). - Add
index=Truefor foreign key columns to ensure performant joins.
- Explicitly define
- Timezones: Use timezone-aware datetime objects (
TIMESTAMP(timezone=True)) or Pydantic UTC validation. - Relationships: Define back-populates and lazy loading modes explicitly (e.g.,
lazy="selectin"for eager loading without Cartesian products).
2. Database Queries & Transactions
- Async execution: All database interactions must be executed asynchronously using
AsyncSession. - Eager Loading: Always declare eager relationships where expected to avoid N+1 queries. Specify
eagerslist on models if supported by the service repository. - Optimistic Concurrency: Use auditing columns or version fields if concurrent updates are expected on highly mutated resources.
3. Migrations (Alembic)
- Autogeneration: Generate migrations via
alembic revision --autogenerate -m "description". - Review Migrations: Always review autogenerated migration scripts before applying them. Pay special attention to constraints, indexes, and type alterations.
- Reversible Migrations: Ensure all migrations implement both
upgrade()anddowngrade()functions.