Tutoriel backend — « Memo »

Schéma & migrations

Chaque module vit dans son propre schéma. Aucune clé étrangère ne traverse les schémas : on référence owner_id par UUID, sans REFERENCES core.users.

Première migration #

-- migrations/000001_memo_schema.up.sql
CREATE SCHEMA IF NOT EXISTS memo;

CREATE TABLE memo.notes (
    id         UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    owner_id   UUID NOT NULL,                 -- core.users.id, PAS de FK inter-schéma
    title      VARCHAR(500) NOT NULL,
    body       TEXT NOT NULL DEFAULT '',
    color      VARCHAR(7) NOT NULL DEFAULT '#1a73e8',
    pinned     BOOLEAN NOT NULL DEFAULT FALSE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_memo_notes_owner ON memo.notes(owner_id);

Le fichier .down.sql jumeau annule la migration (DROP TABLE memo.notes;).

Astuce

Comme les migrations tournent avec search_path = "memo,public", vous pouvez écrire notes sans préfixe — mais préfixer memo.notes reste plus explicite.

SQLx hors-ligne #

Pour builder sans base (CI, paquet) : embarquez le cache .sqlx et compilez avec SQLX_OFFLINE=true. Régénérez-le après tout changement de requête :

DATABASE_URL=postgres://… cargo sqlx prepare   # puis commitez .sqlx
Note

Le SQL ci-dessus est identique quel que soit le langage du module. Seul l'outil qui applique les migrations change (sqlx en Rust ; Alembic/Phinx, golang-migrate, etc. ailleurs) — pensez à fixer le search_path sur votre schéma.