Files
recflare/apps/econ/migrations/0027_wishlist.sql
T
2026-10-05 16:22:55 -04:00

35 lines
1.9 KiB
SQL

-- Item wishlists, owned by the `econ` worker. One row per item a player has wished for —
-- what the store's heart toggle writes (`POST /api/itemWishlists/v1/wishlist/add|remove`,
-- form-encoded `purchasableItemId=1534&customAvatarItemId=`) and the wishlist page reads
-- (`GET /api/itemWishlists/v1/wishlist/me|{accountId}`, a bare array of entries).
--
-- `wishlist_item_id` is a GUID: the client's `WishlistItemId` is a `Guid`, not an int, so the
-- row's key has to be one. `player_id` is the account the list belongs to.
--
-- A row names ONE item in one of two ways — a catalog item by `purchasable_item_id` (the
-- storefront's `PurchasableItemId`) or a player-made/first-party custom avatar item by
-- `custom_avatar_item_id` (its GUID, stored lowercase) — so exactly one of the two is set.
-- On the wire the client's `PurchasableItemId` is a plain int, so a custom-item row is served
-- as `PurchasableItemId: 0` with the GUID beside it; the column is still NULL here so the two
-- kinds of row can't be confused.
--
-- The two partial unique indexes make a wish boolean: a second `add` of the same item finds
-- the existing row rather than making a twin. `idx_wishlist_player` is the read's access
-- pattern (one player's whole list).
--
-- Kept in sync with WISHLIST_SCHEMA_DDL in src/wishlist-db.ts.
CREATE TABLE IF NOT EXISTS wishlist (
wishlist_item_id TEXT PRIMARY KEY,
player_id INTEGER NOT NULL,
purchasable_item_id INTEGER,
custom_avatar_item_id TEXT,
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_wishlist_player ON wishlist (player_id);
CREATE UNIQUE INDEX IF NOT EXISTS idx_wishlist_player_purchasable
ON wishlist (player_id, purchasable_item_id) WHERE purchasable_item_id IS NOT NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_wishlist_player_custom
ON wishlist (player_id, custom_avatar_item_id) WHERE custom_avatar_item_id IS NOT NULL;