| 1 | // Code generated by sqlc. DO NOT EDIT. |
| 2 | // versions: |
| 3 | // sqlc v1.31.1 |
| 4 | // source: notifications.sql |
| 5 | |
| 6 | package notifdb |
| 7 | |
| 8 | import ( |
| 9 | "context" |
| 10 | |
| 11 | "github.com/jackc/pgx/v5/pgtype" |
| 12 | ) |
| 13 | |
| 14 | const countNotificationsForRecipient = `-- name: CountNotificationsForRecipient :one |
| 15 | SELECT count(*) FROM notifications |
| 16 | WHERE recipient_user_id = $1 |
| 17 | AND ($2::boolean = false OR unread = true) |
| 18 | ` |
| 19 | |
| 20 | type CountNotificationsForRecipientParams struct { |
| 21 | RecipientUserID int64 |
| 22 | Column2 bool |
| 23 | } |
| 24 | |
| 25 | func (q *Queries) CountNotificationsForRecipient(ctx context.Context, db DBTX, arg CountNotificationsForRecipientParams) (int64, error) { |
| 26 | row := db.QueryRow(ctx, countNotificationsForRecipient, arg.RecipientUserID, arg.Column2) |
| 27 | var count int64 |
| 28 | err := row.Scan(&count) |
| 29 | return count, err |
| 30 | } |
| 31 | |
| 32 | const countUnreadForRecipient = `-- name: CountUnreadForRecipient :one |
| 33 | SELECT count(*) FROM notifications |
| 34 | WHERE recipient_user_id = $1 AND unread = true |
| 35 | ` |
| 36 | |
| 37 | func (q *Queries) CountUnreadForRecipient(ctx context.Context, db DBTX, recipientUserID int64) (int64, error) { |
| 38 | row := db.QueryRow(ctx, countUnreadForRecipient, recipientUserID) |
| 39 | var count int64 |
| 40 | err := row.Scan(&count) |
| 41 | return count, err |
| 42 | } |
| 43 | |
| 44 | const getNotification = `-- name: GetNotification :one |
| 45 | SELECT id, recipient_user_id, kind, reason, repo_id, |
| 46 | thread_kind, thread_id, source_event_id, unread, |
| 47 | last_event_at, last_actor_user_id, summary, created_at, updated_at |
| 48 | FROM notifications WHERE id = $1 |
| 49 | ` |
| 50 | |
| 51 | func (q *Queries) GetNotification(ctx context.Context, db DBTX, id int64) (Notification, error) { |
| 52 | row := db.QueryRow(ctx, getNotification, id) |
| 53 | var i Notification |
| 54 | err := row.Scan( |
| 55 | &i.ID, |
| 56 | &i.RecipientUserID, |
| 57 | &i.Kind, |
| 58 | &i.Reason, |
| 59 | &i.RepoID, |
| 60 | &i.ThreadKind, |
| 61 | &i.ThreadID, |
| 62 | &i.SourceEventID, |
| 63 | &i.Unread, |
| 64 | &i.LastEventAt, |
| 65 | &i.LastActorUserID, |
| 66 | &i.Summary, |
| 67 | &i.CreatedAt, |
| 68 | &i.UpdatedAt, |
| 69 | ) |
| 70 | return i, err |
| 71 | } |
| 72 | |
| 73 | const insertThreadlessNotification = `-- name: InsertThreadlessNotification :one |
| 74 | INSERT INTO notifications ( |
| 75 | recipient_user_id, kind, reason, repo_id, |
| 76 | source_event_id, last_actor_user_id |
| 77 | ) VALUES ($1, $2, $3, $4, $5, $6) |
| 78 | RETURNING id, recipient_user_id, kind, reason, repo_id, |
| 79 | thread_kind, thread_id, source_event_id, unread, |
| 80 | last_event_at, last_actor_user_id, summary, created_at, updated_at |
| 81 | ` |
| 82 | |
| 83 | type InsertThreadlessNotificationParams struct { |
| 84 | RecipientUserID int64 |
| 85 | Kind string |
| 86 | Reason string |
| 87 | RepoID pgtype.Int8 |
| 88 | SourceEventID pgtype.Int8 |
| 89 | LastActorUserID pgtype.Int8 |
| 90 | } |
| 91 | |
| 92 | // For events with no thread (e.g. repo-admin lifecycle: archived). |
| 93 | // These don't coalesce; each fires its own row. Used sparingly. |
| 94 | func (q *Queries) InsertThreadlessNotification(ctx context.Context, db DBTX, arg InsertThreadlessNotificationParams) (Notification, error) { |
| 95 | row := db.QueryRow(ctx, insertThreadlessNotification, |
| 96 | arg.RecipientUserID, |
| 97 | arg.Kind, |
| 98 | arg.Reason, |
| 99 | arg.RepoID, |
| 100 | arg.SourceEventID, |
| 101 | arg.LastActorUserID, |
| 102 | ) |
| 103 | var i Notification |
| 104 | err := row.Scan( |
| 105 | &i.ID, |
| 106 | &i.RecipientUserID, |
| 107 | &i.Kind, |
| 108 | &i.Reason, |
| 109 | &i.RepoID, |
| 110 | &i.ThreadKind, |
| 111 | &i.ThreadID, |
| 112 | &i.SourceEventID, |
| 113 | &i.Unread, |
| 114 | &i.LastEventAt, |
| 115 | &i.LastActorUserID, |
| 116 | &i.Summary, |
| 117 | &i.CreatedAt, |
| 118 | &i.UpdatedAt, |
| 119 | ) |
| 120 | return i, err |
| 121 | } |
| 122 | |
| 123 | const listNotificationsForRecipient = `-- name: ListNotificationsForRecipient :many |
| 124 | SELECT n.id, n.recipient_user_id, n.kind, n.reason, n.repo_id, |
| 125 | n.thread_kind, n.thread_id, n.source_event_id, n.unread, |
| 126 | n.last_event_at, n.last_actor_user_id, n.summary, |
| 127 | n.created_at, n.updated_at, |
| 128 | coalesce(u.username, '') AS actor_username, |
| 129 | coalesce(r.name, '') AS repo_name, |
| 130 | coalesce(ru.username, '') AS repo_owner_username, |
| 131 | coalesce(i.number, 0) AS thread_number, |
| 132 | coalesce(i.title, '') AS thread_title |
| 133 | FROM notifications n |
| 134 | LEFT JOIN users u ON u.id = n.last_actor_user_id |
| 135 | LEFT JOIN repos r ON r.id = n.repo_id |
| 136 | LEFT JOIN users ru ON ru.id = r.owner_user_id |
| 137 | LEFT JOIN issues i ON i.id = n.thread_id |
| 138 | WHERE n.recipient_user_id = $1 |
| 139 | AND ($2::boolean = false OR n.unread = true) |
| 140 | ORDER BY n.last_event_at DESC |
| 141 | LIMIT $3 OFFSET $4 |
| 142 | ` |
| 143 | |
| 144 | type ListNotificationsForRecipientParams struct { |
| 145 | RecipientUserID int64 |
| 146 | Column2 bool |
| 147 | Limit int32 |
| 148 | Offset int32 |
| 149 | } |
| 150 | |
| 151 | type ListNotificationsForRecipientRow struct { |
| 152 | ID int64 |
| 153 | RecipientUserID int64 |
| 154 | Kind string |
| 155 | Reason string |
| 156 | RepoID pgtype.Int8 |
| 157 | ThreadKind NullNotificationThreadKind |
| 158 | ThreadID pgtype.Int8 |
| 159 | SourceEventID pgtype.Int8 |
| 160 | Unread bool |
| 161 | LastEventAt pgtype.Timestamptz |
| 162 | LastActorUserID pgtype.Int8 |
| 163 | Summary []byte |
| 164 | CreatedAt pgtype.Timestamptz |
| 165 | UpdatedAt pgtype.Timestamptz |
| 166 | ActorUsername string |
| 167 | RepoName string |
| 168 | RepoOwnerUsername string |
| 169 | ThreadNumber int64 |
| 170 | ThreadTitle string |
| 171 | } |
| 172 | |
| 173 | // Inbox view, recency-sorted. `onlyUnread` toggles the inbox |
| 174 | // filter ("Unread" tab vs "All"). |
| 175 | func (q *Queries) ListNotificationsForRecipient(ctx context.Context, db DBTX, arg ListNotificationsForRecipientParams) ([]ListNotificationsForRecipientRow, error) { |
| 176 | rows, err := db.Query(ctx, listNotificationsForRecipient, |
| 177 | arg.RecipientUserID, |
| 178 | arg.Column2, |
| 179 | arg.Limit, |
| 180 | arg.Offset, |
| 181 | ) |
| 182 | if err != nil { |
| 183 | return nil, err |
| 184 | } |
| 185 | defer rows.Close() |
| 186 | items := []ListNotificationsForRecipientRow{} |
| 187 | for rows.Next() { |
| 188 | var i ListNotificationsForRecipientRow |
| 189 | if err := rows.Scan( |
| 190 | &i.ID, |
| 191 | &i.RecipientUserID, |
| 192 | &i.Kind, |
| 193 | &i.Reason, |
| 194 | &i.RepoID, |
| 195 | &i.ThreadKind, |
| 196 | &i.ThreadID, |
| 197 | &i.SourceEventID, |
| 198 | &i.Unread, |
| 199 | &i.LastEventAt, |
| 200 | &i.LastActorUserID, |
| 201 | &i.Summary, |
| 202 | &i.CreatedAt, |
| 203 | &i.UpdatedAt, |
| 204 | &i.ActorUsername, |
| 205 | &i.RepoName, |
| 206 | &i.RepoOwnerUsername, |
| 207 | &i.ThreadNumber, |
| 208 | &i.ThreadTitle, |
| 209 | ); err != nil { |
| 210 | return nil, err |
| 211 | } |
| 212 | items = append(items, i) |
| 213 | } |
| 214 | if err := rows.Err(); err != nil { |
| 215 | return nil, err |
| 216 | } |
| 217 | return items, nil |
| 218 | } |
| 219 | |
| 220 | const markAllReadForRecipient = `-- name: MarkAllReadForRecipient :exec |
| 221 | UPDATE notifications SET unread = false, updated_at = now() |
| 222 | WHERE recipient_user_id = $1 AND unread = true |
| 223 | ` |
| 224 | |
| 225 | // Bounded sweep: a single call doesn't try to update millions of |
| 226 | // rows. Caller paginates via repeated calls when count > batch. |
| 227 | func (q *Queries) MarkAllReadForRecipient(ctx context.Context, db DBTX, recipientUserID int64) error { |
| 228 | _, err := db.Exec(ctx, markAllReadForRecipient, recipientUserID) |
| 229 | return err |
| 230 | } |
| 231 | |
| 232 | const setNotificationRead = `-- name: SetNotificationRead :exec |
| 233 | UPDATE notifications SET unread = false, updated_at = now() |
| 234 | WHERE id = $1 AND recipient_user_id = $2 |
| 235 | ` |
| 236 | |
| 237 | type SetNotificationReadParams struct { |
| 238 | ID int64 |
| 239 | RecipientUserID int64 |
| 240 | } |
| 241 | |
| 242 | func (q *Queries) SetNotificationRead(ctx context.Context, db DBTX, arg SetNotificationReadParams) error { |
| 243 | _, err := db.Exec(ctx, setNotificationRead, arg.ID, arg.RecipientUserID) |
| 244 | return err |
| 245 | } |
| 246 | |
| 247 | const setNotificationUnread = `-- name: SetNotificationUnread :exec |
| 248 | UPDATE notifications SET unread = true, updated_at = now() |
| 249 | WHERE id = $1 AND recipient_user_id = $2 |
| 250 | ` |
| 251 | |
| 252 | type SetNotificationUnreadParams struct { |
| 253 | ID int64 |
| 254 | RecipientUserID int64 |
| 255 | } |
| 256 | |
| 257 | func (q *Queries) SetNotificationUnread(ctx context.Context, db DBTX, arg SetNotificationUnreadParams) error { |
| 258 | _, err := db.Exec(ctx, setNotificationUnread, arg.ID, arg.RecipientUserID) |
| 259 | return err |
| 260 | } |
| 261 | |
| 262 | const upsertNotificationByThread = `-- name: UpsertNotificationByThread :one |
| 263 | |
| 264 | INSERT INTO notifications ( |
| 265 | recipient_user_id, kind, reason, repo_id, |
| 266 | thread_kind, thread_id, source_event_id, |
| 267 | last_event_at, last_actor_user_id |
| 268 | ) VALUES ( |
| 269 | $1, $2, $3, $4, $5, $6, $7, now(), $8 |
| 270 | ) |
| 271 | ON CONFLICT (recipient_user_id, thread_kind, thread_id) WHERE thread_id IS NOT NULL |
| 272 | DO UPDATE SET |
| 273 | kind = EXCLUDED.kind, |
| 274 | reason = EXCLUDED.reason, |
| 275 | source_event_id = EXCLUDED.source_event_id, |
| 276 | last_event_at = now(), |
| 277 | last_actor_user_id = EXCLUDED.last_actor_user_id, |
| 278 | unread = true, |
| 279 | updated_at = now() |
| 280 | RETURNING id, recipient_user_id, kind, reason, repo_id, |
| 281 | thread_kind, thread_id, source_event_id, unread, |
| 282 | last_event_at, last_actor_user_id, summary, created_at, updated_at |
| 283 | ` |
| 284 | |
| 285 | type UpsertNotificationByThreadParams struct { |
| 286 | RecipientUserID int64 |
| 287 | Kind string |
| 288 | Reason string |
| 289 | RepoID pgtype.Int8 |
| 290 | ThreadKind NullNotificationThreadKind |
| 291 | ThreadID pgtype.Int8 |
| 292 | SourceEventID pgtype.Int8 |
| 293 | LastActorUserID pgtype.Int8 |
| 294 | } |
| 295 | |
| 296 | // ─── notifications ───────────────────────────────────────────────── |
| 297 | // Coalesce-or-insert: if a row exists for (recipient, thread), bump |
| 298 | // last_event_at + last_actor + reason and re-flip unread=true so the |
| 299 | // inbox surfaces it again. Otherwise insert a fresh row. |
| 300 | // |
| 301 | // Returns the resulting row (whether it was created or updated) |
| 302 | // so the caller can chain an email-enqueue without a re-read. |
| 303 | func (q *Queries) UpsertNotificationByThread(ctx context.Context, db DBTX, arg UpsertNotificationByThreadParams) (Notification, error) { |
| 304 | row := db.QueryRow(ctx, upsertNotificationByThread, |
| 305 | arg.RecipientUserID, |
| 306 | arg.Kind, |
| 307 | arg.Reason, |
| 308 | arg.RepoID, |
| 309 | arg.ThreadKind, |
| 310 | arg.ThreadID, |
| 311 | arg.SourceEventID, |
| 312 | arg.LastActorUserID, |
| 313 | ) |
| 314 | var i Notification |
| 315 | err := row.Scan( |
| 316 | &i.ID, |
| 317 | &i.RecipientUserID, |
| 318 | &i.Kind, |
| 319 | &i.Reason, |
| 320 | &i.RepoID, |
| 321 | &i.ThreadKind, |
| 322 | &i.ThreadID, |
| 323 | &i.SourceEventID, |
| 324 | &i.Unread, |
| 325 | &i.LastEventAt, |
| 326 | &i.LastActorUserID, |
| 327 | &i.Summary, |
| 328 | &i.CreatedAt, |
| 329 | &i.UpdatedAt, |
| 330 | ) |
| 331 | return i, err |
| 332 | } |
| 333 |