-- name: GetMostRecentPlaySessionForUser :one SELECT * FROM play_sessions WHERE user_id = $1 ORDER BY last_event_at DESC LIMIT 1; -- name: InsertPlaySession :one INSERT INTO play_sessions (user_id, started_at, last_event_at, client_id) VALUES ($1, $2, $2, $3) RETURNING *; -- name: TouchPlaySessionLastEvent :exec UPDATE play_sessions SET last_event_at = $2, track_count = track_count + 1 WHERE id = $1; -- name: GetOpenPlayEventForUser :one -- Returns the most recent play_event for a user where ended_at IS NULL. -- Used by the auto-close-prior step in playevents.RecordPlayStarted. SELECT * FROM play_events WHERE user_id = $1 AND ended_at IS NULL ORDER BY started_at DESC LIMIT 1; -- name: InsertPlayEvent :one -- pick_kind is non-NULL only for system-playlist plays whose track was -- found (with a stamped kind) in the user's live snapshot for that -- variant at ingestion time (#1249, generalized in #1270). INSERT INTO play_events ( user_id, track_id, session_id, started_at, client_id, source, pick_kind ) VALUES ($1, $2, $3, $4, $5, $6, sqlc.narg(pick_kind)::text) RETURNING *; -- name: GetSystemPickKindForTrack :one -- Looks a track up in the user's CURRENT snapshot of the given system -- variant and returns its pick_kind. Used at play-ingestion time to -- freeze provenance onto the play_event — snapshots rebuild daily, so -- attribution can't be reconstructed at read time (#1249/#1270). No -- row = track not in today's snapshot (caller stores NULL); a row with -- NULL pick_kind = the variant doesn't stamp (yet). songs_like_artist -- is non-singleton (up to 3 mixes/user); a track in two of them takes -- whichever LIMIT 1 hits — acceptable, tier stamps there describe the -- same eligibility ladder. SELECT pt.pick_kind FROM playlist_tracks pt JOIN playlists p ON p.id = pt.playlist_id WHERE p.user_id = $1 AND p.system_variant = $2 AND pt.track_id = $3 LIMIT 1; -- name: UpdatePlayEventEnded :one -- Closes a play_event by id with the given ended_at, duration, and skip flag. -- completion_ratio is computed from duration_played_ms and the track duration -- (looked up by the caller — sqlc doesn't do joins on UPDATE). UPDATE play_events SET ended_at = $2, duration_played_ms = $3, completion_ratio = $4, was_skipped = $5 WHERE id = $1 RETURNING *; -- name: GetPlayEventByID :one SELECT * FROM play_events WHERE id = $1; -- name: InsertSkipEvent :one INSERT INTO skip_events (user_id, track_id, session_id, skipped_at, position_ms) VALUES ($1, $2, $3, $4, $5) RETURNING *; -- name: ListRecentSessionTracks :many -- Returns up to $3 tracks in session $1 whose play_event started before -- $2, ordered newest-first. Used by playevents.RecordPlayStarted to -- build the session_vector for the just-inserted play_event. SELECT t.* FROM tracks t JOIN play_events pe ON pe.track_id = t.id WHERE pe.session_id = $1 AND pe.started_at < $2 ORDER BY pe.started_at DESC LIMIT $3; -- name: UpdatePlayEventVector :exec -- Used right after InsertPlayEvent to populate session_vector_at_play -- once the vector has been computed. UPDATE play_events SET session_vector_at_play = $2 WHERE id = $1; -- name: GetCurrentSessionVectorForUser :one -- Returns the session_vector_at_play of the user's most recent play_event -- in a still-active (un-timed-out) session. NoRows means no current vector. -- Joined with play_sessions so closed sessions don't leak stale vectors. SELECT pe.session_vector_at_play FROM play_events pe JOIN play_sessions s ON s.id = pe.session_id WHERE pe.user_id = $1 AND s.ended_at IS NULL ORDER BY pe.started_at DESC LIMIT 1;