Files
HealthLog/prisma/migrations/0097_v170_mood_intake_sync/migration.sql
T
Marc-André BombeckandClaude Opus 4.8 50e0a65228 chore(release): v1.7.0
v1.7.0 — health-record export (PDF + FHIR), flexible medication schedules, first-paint dashboard snapshot, full HealthKit coverage, offline sync delta feed, Coach data clustering. See CHANGELOG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 14:36:17 +02:00

51 lines
2.5 KiB
SQL

-- v1.7.0 sync — extend the offline-sync feed to mood + medication intakes.
--
-- Adds the same reconciliation columns the measurement feed already
-- carries (`sync_version` LWW counter + `deleted_at` soft-delete
-- tombstone) to `mood_entries` and `medication_intake_events`, plus an
-- `updated_at` column to `medication_intake_events` (which had none) so
-- the `/api/sync/changes` keyset feed can order on it. `mood_entries`
-- already has `updated_at`, so it only gains the two sync columns.
--
-- Conflict semantics mirror the per-domain rules in the iOS-coord
-- contract: mood is last-writer-wins by `sync_version`; an intake is an
-- immutable fact whose correction is a tombstone + re-insert, so its
-- `sync_version` only bumps on the soft-delete write.
--
-- Every add is additive + order-safe:
-- - `sync_version` defaults to 0 (constant) → metadata-only ADD COLUMN.
-- - `deleted_at` is nullable, no default → metadata-only.
-- - `updated_at` on intakes is NOT NULL with `DEFAULT now()` so the
-- ADD COLUMN backfills existing rows to their migration instant
-- without a table rewrite (constant-folded default on PG 11+). The
-- Prisma `@updatedAt` directive maintains it from the app layer on
-- every subsequent write; the DB default only seeds legacy rows.
--
-- Supporting keyset indexes match the measurement feed's
-- `(user_id, updated_at, id)` index from migration 0096 so the delta
-- drain reads straight off the index in order rather than sorting the
-- user's whole set per page.
--
-- Reversibility (down):
-- DROP INDEX IF EXISTS "medication_intake_events_user_id_updated_at_id_idx";
-- DROP INDEX IF EXISTS "mood_entries_user_id_updated_at_id_idx";
-- ALTER TABLE "medication_intake_events"
-- DROP COLUMN "deleted_at", DROP COLUMN "sync_version", DROP COLUMN "updated_at";
-- ALTER TABLE "mood_entries"
-- DROP COLUMN "deleted_at", DROP COLUMN "sync_version";
ALTER TABLE "mood_entries"
ADD COLUMN "sync_version" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "deleted_at" TIMESTAMP(3);
ALTER TABLE "medication_intake_events"
ADD COLUMN "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN "sync_version" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "deleted_at" TIMESTAMP(3);
CREATE INDEX IF NOT EXISTS "mood_entries_user_id_updated_at_id_idx"
ON "mood_entries" ("user_id", "updated_at", "id");
CREATE INDEX IF NOT EXISTS "medication_intake_events_user_id_updated_at_id_idx"
ON "medication_intake_events" ("user_id", "updated_at", "id");