All checks were successful
Deploy production / deploy (push) Successful in 1m4s
- model the existing hardware schema in Drizzle (devices, components, new sensitivities) - idempotent reconciling migration: new columns, checks, setup_overview view, grants, meta.tables - seed: main PC labels/hostnames, planned AMD X3D + RTX 5090 build, stan-ovh (OVH RISE-S), other devices, sensitivity placeholders (no invented cm/360) - owner-only add/edit via modals; public view hides notes/order numbers - trackers dropdown entry + icon, seo/title/sitemap, owner write prefix
291 lines
18 KiB
SQL
291 lines
18 KiB
SQL
-- Hand-reconciled: the hardware schema already existed (hand-made 2026-10-22 from Stan's list +
|
|
-- order mails, see ~/dev/hardware/schema.sql; prices later moved to cents). This brings an existing
|
|
-- schema to the Drizzle model, and creates it from scratch on an empty database.
|
|
CREATE SCHEMA IF NOT EXISTS "hardware";
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "hardware"."devices" (
|
|
"id" bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "hardware"."devices_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
|
"name" text NOT NULL UNIQUE,
|
|
"label" text,
|
|
"hostnames" text[] DEFAULT '{}'::text[] NOT NULL,
|
|
"kind" text NOT NULL,
|
|
"status" text DEFAULT 'active' NOT NULL,
|
|
"brand" text,
|
|
"model" text,
|
|
"specs" jsonb DEFAULT '{}' NOT NULL,
|
|
"price_cents" integer,
|
|
"monthly_cents" integer,
|
|
"budget_cents" integer,
|
|
"shop" text,
|
|
"purchase_date" date,
|
|
"url" text,
|
|
"image_url" text,
|
|
"sort_order" integer DEFAULT 100 NOT NULL,
|
|
"notes" text,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT "devices_kind_check" CHECK (kind in ('desktop', 'laptop', 'server', 'vm', 'phone', 'tablet', 'monitor', 'other')),
|
|
CONSTRAINT "devices_status_check" CHECK (status in ('active', 'spare', 'planned', 'retired', 'sold')),
|
|
CONSTRAINT "devices_cents_check" CHECK ((price_cents is null or price_cents >= 0) and (monthly_cents is null or monthly_cents >= 0) and (budget_cents is null or budget_cents >= 0))
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "hardware"."components" (
|
|
"id" bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "hardware"."components_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
|
"device_id" bigint NOT NULL,
|
|
"category" text NOT NULL,
|
|
"brand" text,
|
|
"model" text NOT NULL,
|
|
"quantity" integer DEFAULT 1 NOT NULL,
|
|
"specs" jsonb DEFAULT '{}' NOT NULL,
|
|
"unit_price_cents" integer,
|
|
"total_price_cents" integer,
|
|
"shop" text,
|
|
"order_number" text,
|
|
"order_date" date,
|
|
"warranty_until" date,
|
|
"invoice_number" text,
|
|
"status" text DEFAULT 'in_use' NOT NULL,
|
|
"verified" boolean DEFAULT true NOT NULL,
|
|
"dpi" integer,
|
|
"measured_dpi" integer,
|
|
"url" text,
|
|
"image_url" text,
|
|
"notes" text,
|
|
"source" text,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT "components_dedupe_uq" UNIQUE NULLS NOT DISTINCT("device_id","model","order_number"),
|
|
CONSTRAINT "components_category_check" CHECK (category in ('case', 'cpu', 'motherboard', 'ram', 'cpu_cooler', 'gpu', 'psu', 'storage', 'fan', 'lighting', 'monitor', 'mouse', 'keyboard', 'headset', 'audio', 'controller', 'accessory', 'other')),
|
|
CONSTRAINT "components_status_check" CHECK (status in ('in_use', 'planned', 'spare', 'retired', 'sold')),
|
|
CONSTRAINT "components_quantity_check" CHECK (quantity > 0),
|
|
CONSTRAINT "components_unit_price_cents_check" CHECK (unit_price_cents >= 0),
|
|
CONSTRAINT "components_total_price_cents_check" CHECK (total_price_cents >= 0),
|
|
CONSTRAINT "components_dpi_check" CHECK ((dpi is null or dpi > 0) and (measured_dpi is null or measured_dpi > 0))
|
|
);
|
|
--> statement-breakpoint
|
|
CREATE TABLE IF NOT EXISTS "hardware"."sensitivities" (
|
|
"id" bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "hardware"."sensitivities_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 CACHE 1),
|
|
"game" text NOT NULL UNIQUE,
|
|
"cm_per_360" numeric(7,2),
|
|
"yaw" numeric(10,6),
|
|
"in_game_sens" numeric(10,4),
|
|
"mouse_id" bigint,
|
|
"fov" text,
|
|
"notes" text,
|
|
"sort_order" integer DEFAULT 100 NOT NULL,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT "sensitivities_cm_check" CHECK (cm_per_360 is null or cm_per_360 > 0),
|
|
CONSTRAINT "sensitivities_yaw_check" CHECK (yaw is null or yaw > 0)
|
|
);
|
|
--> statement-breakpoint
|
|
-- Existing tables: new columns.
|
|
ALTER TABLE "hardware"."devices"
|
|
ADD COLUMN IF NOT EXISTS "label" text,
|
|
ADD COLUMN IF NOT EXISTS "hostnames" text[] DEFAULT '{}'::text[] NOT NULL,
|
|
ADD COLUMN IF NOT EXISTS "status" text DEFAULT 'active' NOT NULL,
|
|
ADD COLUMN IF NOT EXISTS "brand" text,
|
|
ADD COLUMN IF NOT EXISTS "model" text,
|
|
ADD COLUMN IF NOT EXISTS "specs" jsonb DEFAULT '{}' NOT NULL,
|
|
ADD COLUMN IF NOT EXISTS "price_cents" integer,
|
|
ADD COLUMN IF NOT EXISTS "monthly_cents" integer,
|
|
ADD COLUMN IF NOT EXISTS "budget_cents" integer,
|
|
ADD COLUMN IF NOT EXISTS "shop" text,
|
|
ADD COLUMN IF NOT EXISTS "purchase_date" date,
|
|
ADD COLUMN IF NOT EXISTS "url" text,
|
|
ADD COLUMN IF NOT EXISTS "image_url" text,
|
|
ADD COLUMN IF NOT EXISTS "sort_order" integer DEFAULT 100 NOT NULL,
|
|
ADD COLUMN IF NOT EXISTS "updated_at" timestamp with time zone DEFAULT now() NOT NULL;
|
|
--> statement-breakpoint
|
|
ALTER TABLE "hardware"."components"
|
|
ADD COLUMN IF NOT EXISTS "dpi" integer,
|
|
ADD COLUMN IF NOT EXISTS "measured_dpi" integer,
|
|
ADD COLUMN IF NOT EXISTS "url" text,
|
|
ADD COLUMN IF NOT EXISTS "image_url" text;
|
|
--> statement-breakpoint
|
|
-- Checks: widen kinds/categories/statuses (drop + re-add by name).
|
|
ALTER TABLE "hardware"."devices" DROP CONSTRAINT IF EXISTS "devices_kind_check";
|
|
ALTER TABLE "hardware"."devices" ADD CONSTRAINT "devices_kind_check" CHECK (kind in ('desktop', 'laptop', 'server', 'vm', 'phone', 'tablet', 'monitor', 'other'));
|
|
ALTER TABLE "hardware"."devices" DROP CONSTRAINT IF EXISTS "devices_status_check";
|
|
ALTER TABLE "hardware"."devices" ADD CONSTRAINT "devices_status_check" CHECK (status in ('active', 'spare', 'planned', 'retired', 'sold'));
|
|
ALTER TABLE "hardware"."devices" DROP CONSTRAINT IF EXISTS "devices_cents_check";
|
|
ALTER TABLE "hardware"."devices" ADD CONSTRAINT "devices_cents_check" CHECK ((price_cents is null or price_cents >= 0) and (monthly_cents is null or monthly_cents >= 0) and (budget_cents is null or budget_cents >= 0));
|
|
ALTER TABLE "hardware"."components" DROP CONSTRAINT IF EXISTS "components_category_check";
|
|
ALTER TABLE "hardware"."components" ADD CONSTRAINT "components_category_check" CHECK (category in ('case', 'cpu', 'motherboard', 'ram', 'cpu_cooler', 'gpu', 'psu', 'storage', 'fan', 'lighting', 'monitor', 'mouse', 'keyboard', 'headset', 'audio', 'controller', 'accessory', 'other'));
|
|
ALTER TABLE "hardware"."components" DROP CONSTRAINT IF EXISTS "components_status_check";
|
|
ALTER TABLE "hardware"."components" ADD CONSTRAINT "components_status_check" CHECK (status in ('in_use', 'planned', 'spare', 'retired', 'sold'));
|
|
ALTER TABLE "hardware"."components" DROP CONSTRAINT IF EXISTS "components_dpi_check";
|
|
ALTER TABLE "hardware"."components" ADD CONSTRAINT "components_dpi_check" CHECK ((dpi is null or dpi > 0) and (measured_dpi is null or measured_dpi > 0));
|
|
--> statement-breakpoint
|
|
-- Dedupe key: unique index -> constraint (same name, same NULLS NOT DISTINCT semantics);
|
|
-- device FK -> Drizzle's name.
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'components_dedupe_uq' AND connamespace = 'hardware'::regnamespace) THEN
|
|
DROP INDEX IF EXISTS "hardware"."components_dedupe_uq";
|
|
ALTER TABLE "hardware"."components" ADD CONSTRAINT "components_dedupe_uq" UNIQUE NULLS NOT DISTINCT ("device_id","model","order_number");
|
|
END IF;
|
|
IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'components_device_id_fkey' AND connamespace = 'hardware'::regnamespace) THEN
|
|
ALTER TABLE "hardware"."components" RENAME CONSTRAINT "components_device_id_fkey" TO "components_device_id_devices_id_fkey";
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'components_device_id_devices_id_fkey' AND connamespace = 'hardware'::regnamespace) THEN
|
|
ALTER TABLE "hardware"."components" ADD CONSTRAINT "components_device_id_devices_id_fkey" FOREIGN KEY ("device_id") REFERENCES "hardware"."devices"("id") ON DELETE CASCADE;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'sensitivities_mouse_id_components_id_fkey' AND connamespace = 'hardware'::regnamespace) THEN
|
|
ALTER TABLE "hardware"."sensitivities" ADD CONSTRAINT "sensitivities_mouse_id_components_id_fkey" FOREIGN KEY ("mouse_id") REFERENCES "hardware"."components"("id") ON DELETE SET NULL;
|
|
END IF;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
CREATE INDEX IF NOT EXISTS "components_device_idx" ON "hardware"."components" ("device_id");
|
|
CREATE INDEX IF NOT EXISTS "components_category_idx" ON "hardware"."components" ("category");
|
|
CREATE INDEX IF NOT EXISTS "components_specs_gin" ON "hardware"."components" USING gin ("specs");
|
|
--> statement-breakpoint
|
|
-- Hand-written: updated_at triggers, overview view, grants, GUI registration, seed.
|
|
DO $$
|
|
DECLARE t text;
|
|
BEGIN
|
|
FOREACH t IN ARRAY ARRAY['devices','components','sensitivities'] LOOP
|
|
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'touch_updated_at' AND tgrelid = format('hardware.%I', t)::regclass) THEN
|
|
EXECUTE format('CREATE TRIGGER touch_updated_at BEFORE UPDATE ON hardware.%I FOR EACH ROW EXECUTE FUNCTION meta.touch_updated_at()', t);
|
|
END IF;
|
|
END LOOP;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DROP VIEW IF EXISTS "hardware"."setup_overview";
|
|
--> statement-breakpoint
|
|
CREATE VIEW "hardware"."setup_overview" AS
|
|
SELECT d.name AS device,
|
|
d.label AS device_label,
|
|
d.kind AS device_kind,
|
|
d.status AS device_status,
|
|
c.category,
|
|
c.brand,
|
|
c.model,
|
|
c.quantity,
|
|
c.total_price_cents,
|
|
round(c.total_price_cents::numeric / 100.0, 2) AS total_price_eur,
|
|
c.shop,
|
|
c.order_date,
|
|
c.warranty_until,
|
|
(c.warranty_until >= current_date) AS under_warranty,
|
|
c.status,
|
|
c.verified,
|
|
c.specs,
|
|
c.dpi,
|
|
c.measured_dpi,
|
|
c.notes,
|
|
c.order_number,
|
|
c.invoice_number,
|
|
c.source,
|
|
c.id AS component_id
|
|
FROM hardware.components c
|
|
JOIN hardware.devices d ON d.id = c.device_id
|
|
ORDER BY d.sort_order, d.name,
|
|
array_position(ARRAY['case','cpu','motherboard','ram','cpu_cooler','gpu','psu','storage','fan','lighting','monitor','mouse','keyboard','headset','audio','controller','accessory','other'], c.category),
|
|
c.order_date NULLS LAST, c.model;
|
|
--> statement-breakpoint
|
|
COMMENT ON VIEW "hardware"."setup_overview" IS 'Flat view of every component per device (build order), with a live under_warranty flag. status = ''in_use'' is the current setup, ''planned'' the upgrade plan.';
|
|
--> statement-breakpoint
|
|
DO $$
|
|
BEGIN
|
|
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'personal_app') THEN
|
|
GRANT USAGE ON SCHEMA hardware TO personal_app;
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA hardware TO personal_app;
|
|
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA hardware TO personal_app;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA hardware GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO personal_app;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA hardware GRANT USAGE, SELECT ON SEQUENCES TO personal_app;
|
|
END IF;
|
|
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'personal_ro') THEN
|
|
GRANT USAGE ON SCHEMA hardware TO personal_ro;
|
|
GRANT SELECT ON ALL TABLES IN SCHEMA hardware TO personal_ro;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA hardware GRANT SELECT ON TABLES TO personal_ro;
|
|
END IF;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
DO $$
|
|
BEGIN
|
|
IF to_regclass('meta.tables') IS NOT NULL THEN
|
|
INSERT INTO meta.tables (schema_name, table_name, slug, display_name, kind, editable, has_done, sort_order)
|
|
VALUES ('hardware','devices','hardware-devices','Hardware devices','core',true,false,1000),
|
|
('hardware','components','hardware-components','Hardware components','core',true,false,1000),
|
|
('hardware','sensitivities','hardware-sensitivities','Game sensitivities (cm/360)','core',true,false,1000)
|
|
ON CONFLICT DO NOTHING;
|
|
IF has_function_privilege('meta.sync(integer)', 'EXECUTE') THEN
|
|
PERFORM meta.sync();
|
|
END IF;
|
|
END IF;
|
|
END $$;
|
|
--> statement-breakpoint
|
|
-- ===== Seed (idempotent). Facts from Stan's own list, order mails and what he told Daisy;
|
|
-- unknowns stay null. No home address in public-facing notes.
|
|
INSERT INTO hardware.devices (name, kind) VALUES ('stan-pc','desktop'), ('old-pc-2021','desktop')
|
|
ON CONFLICT (name) DO NOTHING;
|
|
--> statement-breakpoint
|
|
UPDATE hardware.devices SET
|
|
label = 'Main PC', hostnames = '{stan-arch,stan-win11}', status = 'active', model = 'Custom build',
|
|
shop = 'Megekko', sort_order = 10,
|
|
notes = 'Stan''s main PC: Lian Li O11 Dynamic XL ROG White, i9-12900KF, RX 7900 XT, 10 Lian Li fans around the case + 3 NZXT Aer on the radiator. Dual-boots Arch (stan-arch) and Windows 11 + WSL2 (stan-win11). Desk peripherals and the Odyssey G9 are tracked here. Mostly bought at Megekko 2021-2022.'
|
|
WHERE name = 'stan-pc' AND label IS NULL;
|
|
--> statement-breakpoint
|
|
UPDATE hardware.devices SET
|
|
label = 'Previous PC (2021)', status = 'retired', model = 'Budget build', shop = 'Megekko',
|
|
purchase_date = '2021-01-31', sort_order = 90
|
|
WHERE name = 'old-pc-2021' AND label IS NULL;
|
|
--> statement-breakpoint
|
|
INSERT INTO hardware.devices (name, label, hostnames, kind, status, brand, model, specs, price_cents, monthly_cents, budget_cents, shop, purchase_date, url, sort_order, notes) VALUES
|
|
('stan-pc-next','Next PC (planned)','{}','desktop','planned',NULL,'High-end AMD + RTX 5090 build','{}',NULL,NULL,1000000,NULL,NULL,NULL,15,
|
|
'Planned upgrade, budget up to about EUR 10k: top AMD X3D CPU, RTX 5090, fast DDR5, PCIe Gen5 SSD, high-end motherboard and a cooler that fits. Parts not picked yet.'),
|
|
('stan-ovh','Server','{}','server','active','OVHcloud','RISE-S',
|
|
'{"cpu":"AMD Ryzen 7 9700X","ram":"64 GB DDR5 ECC","storage":"2x 512 GB NVMe (software RAID1)","os":"Ubuntu 26.04"}',
|
|
NULL,6174,NULL,'OVHcloud','2026-10-24','https://www.ovhcloud.com/en/bare-metal/rise/',20,
|
|
'Dedicated server, prod since 2026-10-24 (replaced stan-vm). EUR 61.74/month excl. VAT. Runs Postgres, Gitea, the website and the bots.'),
|
|
('stan-vm','Old VM','{}','vm','retired','Hetzner Cloud',NULL,'{"vcpu":4,"ram":"8 GB"}',NULL,2000,NULL,'Hetzner',NULL,NULL,80,
|
|
'Old always-on Hetzner VM (about EUR 20/month, bought before the price rises). Replaced by stan-ovh on 2026-10-24; stopped, kept as a fallback until Stan cancels it.'),
|
|
('stan-macbookpro','MacBook Pro','{}','laptop','active','Apple','MacBook Pro','{}',NULL,NULL,NULL,NULL,NULL,NULL,30,
|
|
'Exact model/chip not recorded yet. An M5 Max MacBook Pro is planned.'),
|
|
('stan-pixel','Phone','{}','phone','active','Google','Pixel 11 Pro XL','{"storage":"256 GB"}',NULL,NULL,NULL,'Belsimpel','2026-10-18',NULL,40,
|
|
'Main phone since 2026-10-19, stock Android. About EUR 1,299 SIM-free (exact amount not recorded).'),
|
|
('stan-iphone','Old phone','{}','phone','spare','Apple','iPhone 14 Pro Max','{}',NULL,NULL,NULL,NULL,NULL,NULL,45,
|
|
'Previous phone, kept (weak battery and speed).'),
|
|
('stan-ipad','iPad','{}','tablet','active','Apple','iPad Air 13-inch (M2)','{"screen_in":13,"chip":"Apple M2"}',NULL,NULL,NULL,NULL,NULL,NULL,50,
|
|
'With a keyboard case; used for typing on the go and Termius SSH.'),
|
|
('cargill-laptop','Work laptop','{}','laptop','active',NULL,NULL,'{"ram":"16 GB"}',NULL,NULL,NULL,NULL,NULL,NULL,60,
|
|
'Cargill work laptop (not personal; Windows + WSL2). Model not recorded.')
|
|
ON CONFLICT (name) DO NOTHING;
|
|
--> statement-breakpoint
|
|
-- Peripherals get real categories instead of "accessory".
|
|
UPDATE hardware.components SET category = 'mouse' WHERE category = 'accessory' AND model ILIKE 'MX Master%';
|
|
--> statement-breakpoint
|
|
UPDATE hardware.components SET category = 'keyboard' WHERE category = 'accessory' AND (model ILIKE 'Alloy Origins%' OR model ILIKE 'Pudding Keycaps%' OR model ILIKE 'UwU%');
|
|
--> statement-breakpoint
|
|
UPDATE hardware.components SET category = 'controller' WHERE category = 'accessory' AND brand = 'Thrustmaster';
|
|
--> statement-breakpoint
|
|
UPDATE hardware.components SET category = 'audio' WHERE category = 'accessory' AND model ILIKE '%mic boom arm%';
|
|
--> statement-breakpoint
|
|
UPDATE hardware.components SET notes = replace(notes, ', delivered 2026-03-03 to Houtenstraat 15 Gouda.', ', delivered 2026-03-03.') WHERE notes LIKE '%Houtenstraat%';
|
|
--> statement-breakpoint
|
|
INSERT INTO hardware.components (device_id, category, brand, model, quantity, specs, status, verified, notes, source)
|
|
SELECT d.id, v.category, v.brand, v.model, v.quantity, v.specs::jsonb, v.status, true, v.notes, v.source
|
|
FROM (VALUES
|
|
('stan-ovh','cpu','AMD','Ryzen 7 9700X',1,'{"cores":8,"threads":16,"socket":"AM5"}','in_use',NULL,'manual'),
|
|
('stan-ovh','ram',NULL,'64 GB DDR5 ECC',1,'{"type":"DDR5 ECC","capacity_gb":64}','in_use',NULL,'manual'),
|
|
('stan-ovh','storage',NULL,'512 GB NVMe SSD',2,'{"interface":"NVMe","capacity_gb":512,"raid":"software RAID1"}','in_use','Mirrored (RAID1), about 440 GB usable for data.','manual'),
|
|
('stan-pc-next','cpu','AMD','Top Ryzen X3D (model TBD)',1,'{"socket":"AM5"}','planned','Pick the fastest gaming X3D chip available when buying.','plan'),
|
|
('stan-pc-next','gpu','NVIDIA','GeForce RTX 5090',1,'{"vram_gb":32}','planned','Board partner TBD.','plan'),
|
|
('stan-pc-next','motherboard',NULL,'High-end AM5 motherboard (TBD)',1,'{"socket":"AM5"}','planned',NULL,'plan'),
|
|
('stan-pc-next','ram',NULL,'Fast DDR5 kit (TBD)',1,'{"type":"DDR5"}','planned',NULL,'plan'),
|
|
('stan-pc-next','storage',NULL,'PCIe 5.0 NVMe SSD (TBD)',1,'{"interface":"PCIe 5.0 x4 NVMe"}','planned',NULL,'plan'),
|
|
('stan-pc-next','cpu_cooler',NULL,'Cooler for the new CPU (TBD)',1,'{}','planned','Must fit the new socket and the O11 Dynamic XL (or the new case).','plan')
|
|
) AS v(device, category, brand, model, quantity, specs, status, notes, source)
|
|
JOIN hardware.devices d ON d.name = v.device
|
|
ON CONFLICT (device_id, model, order_number) DO NOTHING;
|
|
--> statement-breakpoint
|
|
-- Games Stan plays; cm/360 left empty for him to fill. CS2's yaw (0.022 deg/count) is the
|
|
-- Source engine constant, so its in-game value is computed from a mouse's measured DPI.
|
|
INSERT INTO hardware.sensitivities (game, yaw, sort_order) VALUES
|
|
('Counter-Strike 2', 0.022, 10),
|
|
('Call of Duty', NULL, 20),
|
|
('osu!', NULL, 30),
|
|
('Sea of Thieves', NULL, 40)
|
|
ON CONFLICT (game) DO NOTHING;
|