mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
- migration 0311 creates mood_contexts, keyed by the entry, cascading from both the entry and the owner - work, contacts, leisure and one notable event; every field nullable, and an entry with nothing filled in gets no row at all - notes_encrypted registered in ENCRYPTED_COLUMNS and in the rotation script, so a key rotation cannot strand it
85 lines
3.7 KiB
SQL
85 lines
3.7 KiB
SQL
-- v1.38 — the day's context around a mood entry.
|
|
--
|
|
-- Work, contacts, leisure and a notable event, as an optional sub-row rather
|
|
-- than as twenty more columns on `mood_entries`. Level A went the other way in
|
|
-- migration 0310, and for the opposite reasons: those five values are on
|
|
-- nearly every row and every mood reader wants them, while this is sparse by
|
|
-- design (only the sections somebody opened produce anything at all) and only
|
|
-- the context surfaces read it.
|
|
--
|
|
-- An entry with nothing filled in gets NO row here. A table of all-NULL rows
|
|
-- would record "asked and answered nothing" where the truth is "never asked",
|
|
-- and the two are different facts.
|
|
--
|
|
-- Nothing in this table duplicates another module. Sleep, activity and vitals
|
|
-- are resolved at read time from the modules that own them, and body symptoms
|
|
-- stay in the illness tables. A stored copy would be a second home for the
|
|
-- same fact and would drift the first time somebody corrected the original.
|
|
--
|
|
-- The two multi-select lists are JSON arrays in TEXT columns, matching the
|
|
-- `mood_entries.tags` convention. Not queryable, read whole — acceptable
|
|
-- because every reader wants an entry's whole context anyway.
|
|
--
|
|
-- No CHECK constraints on the numeric ranges. Bounds are enforced server-side,
|
|
-- the same way `mood_entry_tag_links.rating` documents: a later change to a
|
|
-- scale must not strand rows written under the old one.
|
|
|
|
CREATE TABLE "mood_contexts" (
|
|
"mood_entry_id" TEXT NOT NULL,
|
|
"user_id" TEXT NOT NULL,
|
|
|
|
-- Work. `work_status` is one of off / partial / regular / overtime.
|
|
"work_status" TEXT,
|
|
"work_minutes" INTEGER,
|
|
"overtime_minutes" INTEGER,
|
|
"work_load" INTEGER,
|
|
"work_satisfaction" INTEGER,
|
|
|
|
-- Contacts. `contact_circles` is a JSON array of circle keys; the count is
|
|
-- never scored, which is why the experienced quality is its own column.
|
|
"contact_circles" TEXT,
|
|
"contact_form" TEXT,
|
|
"contact_extent" TEXT,
|
|
"contact_quality" INTEGER,
|
|
"contact_support" INTEGER,
|
|
|
|
-- Leisure. `leisure_categories` is a JSON array of category keys.
|
|
"leisure_categories" TEXT,
|
|
"leisure_minutes" INTEGER,
|
|
"leisure_joy" INTEGER,
|
|
"leisure_recovery" INTEGER,
|
|
|
|
-- One notable event, if there was one.
|
|
"event_type" TEXT,
|
|
"event_valence" INTEGER,
|
|
"event_at" TIMESTAMPTZ(3),
|
|
|
|
-- One AES-256-GCM note for the whole context, not one per section: four
|
|
-- ciphertext columns would be four rotation entries and four ways to
|
|
-- forget one. Registered in ENCRYPTED_COLUMNS and in the rotation script.
|
|
"notes_encrypted" BYTEA,
|
|
|
|
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updated_at" TIMESTAMPTZ(3) NOT NULL,
|
|
|
|
CONSTRAINT "mood_contexts_pkey" PRIMARY KEY ("mood_entry_id")
|
|
);
|
|
|
|
-- Deleting the entry deletes its context. The context has no meaning without
|
|
-- the entry it describes, and a row pointing at a deleted entry would be
|
|
-- readable by nobody and deletable by nobody. The user cascade matches every
|
|
-- other user-scoped table here.
|
|
ALTER TABLE "mood_contexts"
|
|
ADD CONSTRAINT "mood_contexts_mood_entry_id_fkey"
|
|
FOREIGN KEY ("mood_entry_id") REFERENCES "mood_entries"("id")
|
|
ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
ALTER TABLE "mood_contexts"
|
|
ADD CONSTRAINT "mood_contexts_user_id_fkey"
|
|
FOREIGN KEY ("user_id") REFERENCES "users"("id")
|
|
ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- The user-scoped sweep: the context analytics read a window of an account's
|
|
-- contexts, and the account-deletion path clears them by owner.
|
|
CREATE INDEX "mood_contexts_user_id_idx" ON "mood_contexts"("user_id");
|