diff --git a/server/migrations/008_machine_uid.sql b/server/migrations/008_machine_uid.sql index 8488031..3af40f3 100644 --- a/server/migrations/008_machine_uid.sql +++ b/server/migrations/008_machine_uid.sql @@ -34,8 +34,12 @@ ALTER TABLE connect_machines ADD COLUMN IF NOT EXISTS machine_uid TEXT; -- 2. Enforce one row per machine_uid, but ONLY for rows that actually have one. -- A partial UNIQUE index (WHERE machine_uid IS NOT NULL) lets unlimited legacy --- NULL rows coexist while making a non-null machine_uid a true dedup key — this --- is what upsert_machine's `ON CONFLICT (machine_uid)` arbiter binds to. +-- NULL rows coexist while making a non-null machine_uid a true dedup key. Because +-- this index is PARTIAL, Postgres only binds an ON CONFLICT inference clause to it +-- when the clause REPEATS the same predicate: upsert_machine's arbiter must be +-- `ON CONFLICT (machine_uid) WHERE machine_uid IS NOT NULL` (a bare +-- `ON CONFLICT (machine_uid)` raises "no unique or exclusion constraint matching +-- the ON CONFLICT specification" at runtime and persists no row). CREATE UNIQUE INDEX IF NOT EXISTS idx_connect_machines_machine_uid ON connect_machines (machine_uid) WHERE machine_uid IS NOT NULL; diff --git a/server/src/db/machines.rs b/server/src/db/machines.rs index b6b65d6..901260b 100644 --- a/server/src/db/machines.rs +++ b/server/src/db/machines.rs @@ -166,7 +166,7 @@ pub async fn upsert_machine( r#" INSERT INTO connect_machines (agent_id, hostname, is_persistent, status, last_seen, machine_uid) VALUES ($1, $2, $3, 'online', NOW(), $4) - ON CONFLICT (machine_uid) DO UPDATE SET + ON CONFLICT (machine_uid) WHERE machine_uid IS NOT NULL DO UPDATE SET agent_id = EXCLUDED.agent_id, hostname = EXCLUDED.hostname, status = 'online',