Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions backend/db/migrations/001_create_tables.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
-- 001_create_tables.sql
-- Wine not? – tabeller og typer for PostgreSQL
-- Kjør med: psql -d winenot -v ON_ERROR_STOP=1 -f backend/db/migrations/001_create_tables.sql
-- En migrasjon som er merget, endres ikke. Nye endringer legges i en ny, nummerert fil.

BEGIN;

-- ---------- Typer ----------
-- Verdiene er de samme som i X-Wines, og rekkefølgen her bestemmer sorteringen.

CREATE TYPE body_level AS ENUM (
'Very light-bodied',
'Light-bodied',
'Medium-bodied',
'Full-bodied',
'Very full-bodied'
);

CREATE TYPE acidity_level AS ENUM (
'Low',
'Medium',
'High'
);

-- ---------- Oppslagstabeller ----------

CREATE TABLE countries (
code text PRIMARY KEY, -- Code fra X-Wines, f.eks. 'FR'
name text NOT NULL UNIQUE
);

CREATE TABLE regions (
id integer PRIMARY KEY, -- RegionID fra X-Wines
name text NOT NULL,
country_code text NOT NULL REFERENCES countries(code)
);

CREATE TABLE wineries (
id integer PRIMARY KEY, -- WineryID fra X-Wines
name text NOT NULL,
website text
);

CREATE TABLE grapes (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL UNIQUE
);

CREATE TABLE foods (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL UNIQUE -- verdier fra Harmonize, f.eks. 'Beef', 'Rich Fish'
);

-- ---------- Viner ----------

CREATE TABLE wines (
id integer PRIMARY KEY, -- WineID fra X-Wines
name text NOT NULL,
type text NOT NULL, -- Red, White, Rosé, Sparkling, Dessert, Dessert/Port
elaborate text, -- f.eks. 'Varietal/100%', 'Assemblage/Blend'
abv numeric(4,1), -- alkoholprosent
body body_level,
acidity acidity_level,
winery_id integer NOT NULL REFERENCES wineries(id),
region_id integer NOT NULL REFERENCES regions(id),
country_code text NOT NULL REFERENCES countries(code), -- bevisst duplisert fra regions: sparer en join ved landfilter
vintages integer[] NOT NULL DEFAULT '{}', -- 'N.V.' hoppes over i importskriptet
avg_rating numeric(3,2), -- forhåndsberegnet i importskriptet
rating_count integer NOT NULL DEFAULT 0
);

-- ---------- Mange-til-mange ----------

CREATE TABLE wine_grapes (
wine_id integer NOT NULL REFERENCES wines(id) ON DELETE CASCADE,
grape_id integer NOT NULL REFERENCES grapes(id) ON DELETE CASCADE,
PRIMARY KEY (wine_id, grape_id)
);

CREATE TABLE wine_foods (
wine_id integer NOT NULL REFERENCES wines(id) ON DELETE CASCADE,
food_id integer NOT NULL REFERENCES foods(id) ON DELETE CASCADE,
PRIMARY KEY (wine_id, food_id)
);

-- ---------- Brukere og favoritter (brukergenerert data) ----------

CREATE TABLE users (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
username text NOT NULL UNIQUE,
email text NOT NULL UNIQUE,
password_hash text NOT NULL, -- aldri klartekst; hashes med bcrypt/argon2 i backend
created_at timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE favorites (
user_id integer NOT NULL REFERENCES users(id) ON DELETE CASCADE,
wine_id integer NOT NULL REFERENCES wines(id) ON DELETE CASCADE,
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (user_id, wine_id) -- hindrer duplikater og dekker "mine favoritter"
);

COMMIT;
31 changes: 31 additions & 0 deletions backend/db/migrations/002_create_indexes.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-- 002_create_indexes.sql
-- Wine not? – indekser for søk, filtrering og sortering
-- Kjør med: psql -d winenot -v ON_ERROR_STOP=1 -f backend/db/migrations/002_create_indexes.sql

BEGIN;

CREATE EXTENSION IF NOT EXISTS pg_trgm; -- raskt delstreng-søk på vinnavn

-- Søk: WHERE name ILIKE '%tekst%'
CREATE INDEX wines_name_trgm_idx ON wines USING gin (name gin_trgm_ops);

-- Filtre
CREATE INDEX wines_type_idx ON wines (type);
CREATE INDEX wines_country_idx ON wines (country_code);
CREATE INDEX wines_region_idx ON wines (region_id);
CREATE INDEX wines_winery_idx ON wines (winery_id);
CREATE INDEX wines_taste_idx ON wines (body, acidity); -- Explore by taste
CREATE INDEX wines_vintages_idx ON wines USING gin (vintages); -- WHERE vintages @> ARRAY[2018]

-- Sortering (id som siste ledd gir stabil rekkefølge ved paginering)
CREATE INDEX wines_name_sort_idx ON wines (name, id);
CREATE INDEX wines_rating_idx ON wines (avg_rating DESC NULLS LAST, id);
CREATE INDEX wines_abv_idx ON wines (abv, id);

-- Primærnøklene dekker oppslag fra vin/bruker. Disse dekker motsatt vei.
CREATE INDEX wine_grapes_grape_idx ON wine_grapes (grape_id);
CREATE INDEX wine_foods_food_idx ON wine_foods (food_id);
CREATE INDEX favorites_wine_idx ON favorites (wine_id);
CREATE INDEX regions_country_idx ON regions (country_code);

COMMIT;