-- name: UpsertClipboard :one -- New rows start version 1; conflicts bump version by 1 (per-user monotonic). -- LWW: the DO UPDATE only runs when the new origin_ts is strictly greater than -- the stored one, so a delayed / out-of-order older copy changes nothing and -- RETURNING yields no row (the service reads sql.ErrNoRows as "stale, rejected"). INSERT INTO clipboard_state (user_id, content_type, content, source_device, updated_at, version, origin_ts) VALUES (?, ?, ?, ?, ?, 1, ?) ON CONFLICT (user_id) DO UPDATE SET content_type = excluded.content_type, content = excluded.content, source_device = excluded.source_device, updated_at = excluded.updated_at, version = clipboard_state.version + 1, origin_ts = excluded.origin_ts WHERE excluded.origin_ts > clipboard_state.origin_ts RETURNING version; -- name: GetClipboard :one SELECT user_id, content_type, content, source_device, updated_at, version, origin_ts FROM clipboard_state WHERE user_id = ?; -- name: ClearExpiredClipboards :execrows -- 清除 updated_at 早于 cutoff 的剪贴板内容(content / source_device 置空), -- 由 sweeper 周期调用实现短 TTL;保留行本身、仅抹掉内容。 UPDATE clipboard_state SET content = NULL, source_device = NULL WHERE content IS NOT NULL AND updated_at < ?;