← back to Vintage Wallpaper Archive

sql/001_schema.sql

95 lines

-- vintage_wallpaper_archive schema
-- Source: https://vintagewallpaperarchive.com (Hannah's Treasures, Shopify-hosted)
-- Internal-use only. Images and copy are © Hannah's Treasures.
-- Do NOT push to public site or Shopify without ownership clearance.

CREATE TABLE IF NOT EXISTS products (
  shopify_product_id      BIGINT PRIMARY KEY,
  handle                  TEXT NOT NULL UNIQUE,
  title                   TEXT NOT NULL,
  vendor                  TEXT,
  product_type            TEXT,
  body_html               TEXT,
  body_text               TEXT,         -- stripped of HTML for fulltext search
  tags                    TEXT[],
  options                 JSONB,        -- [{name, position, values:[]}]
  published_at            TIMESTAMPTZ,
  created_at_remote       TIMESTAMPTZ,
  updated_at_remote       TIMESTAMPTZ,
  -- normalized fields parsed from body_html (best-effort)
  pattern_width_inches    NUMERIC,
  pattern_repeat_inches   NUMERIC,
  era_year                INT,          -- e.g. 1940 from "1940s scenic"
  era_decade              INT,          -- e.g. 1940 (decade rounded)
  match_type              TEXT,         -- "straight across", "half drop", "random"
  -- provenance + compliance
  source                  TEXT NOT NULL DEFAULT 'vintage-wallpaper-archive-shopify-public',
  source_url              TEXT,
  owned_by_steve          BOOLEAN NOT NULL DEFAULT FALSE,
  image_license           TEXT NOT NULL DEFAULT 'unknown_third_party',
  ok_for_commercial_use   BOOLEAN NOT NULL DEFAULT FALSE,
  -- forensic completeness
  raw_payload             JSONB NOT NULL,
  ingested_at             TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  ingest_run_id           TEXT
);

CREATE INDEX IF NOT EXISTS idx_products_handle    ON products (handle);
CREATE INDEX IF NOT EXISTS idx_products_era_year  ON products (era_year);
CREATE INDEX IF NOT EXISTS idx_products_tags_gin  ON products USING GIN (tags);
-- idx_products_body_trgm is created after pg_trgm extension at bottom of file

CREATE TABLE IF NOT EXISTS variants (
  shopify_variant_id      BIGINT PRIMARY KEY,
  shopify_product_id      BIGINT NOT NULL REFERENCES products(shopify_product_id) ON DELETE CASCADE,
  sku                     TEXT,
  title                   TEXT,
  position                INT,
  price                   NUMERIC,
  compare_at_price        NUMERIC,
  available               BOOLEAN,
  taxable                 BOOLEAN,
  requires_shipping       BOOLEAN,
  option1                 TEXT,
  option2                 TEXT,
  option3                 TEXT,
  grams                   INT,
  created_at_remote       TIMESTAMPTZ,
  updated_at_remote       TIMESTAMPTZ,
  ingested_at             TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_variants_product ON variants (shopify_product_id);
CREATE INDEX IF NOT EXISTS idx_variants_sku     ON variants (sku);

CREATE TABLE IF NOT EXISTS images (
  shopify_image_id        BIGINT PRIMARY KEY,
  shopify_product_id      BIGINT NOT NULL REFERENCES products(shopify_product_id) ON DELETE CASCADE,
  position                INT,
  src                     TEXT NOT NULL,
  alt                     TEXT,
  width                   INT,
  height                  INT,
  variant_ids             BIGINT[],
  created_at_remote       TIMESTAMPTZ,
  updated_at_remote       TIMESTAMPTZ,
  ingested_at             TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_images_product ON images (shopify_product_id);

CREATE TABLE IF NOT EXISTS ingest_runs (
  run_id                  TEXT PRIMARY KEY,
  started_at              TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  finished_at             TIMESTAMPTZ,
  pages_fetched           INT NOT NULL DEFAULT 0,
  products_seen           INT NOT NULL DEFAULT 0,
  products_upserted       INT NOT NULL DEFAULT 0,
  variants_upserted       INT NOT NULL DEFAULT 0,
  images_upserted         INT NOT NULL DEFAULT 0,
  errors                  INT NOT NULL DEFAULT 0,
  notes                   TEXT
);

-- pg_trgm for fuzzy body_text search (must come before any gin_trgm_ops index)
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX IF NOT EXISTS idx_products_body_trgm ON products USING GIN (body_text gin_trgm_ops);