// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.31.1 // source: github_snapshot.sql package db import ( "context" "github.com/jackc/pgx/v5/pgtype" ) const deleteGitHubPRCheckRuns = `-- name: DeleteGitHubPRCheckRuns :exec DELETE FROM github_pull_request_check_run WHERE pr_id = $1 ` // First half of the atomic per-check replace. Runs inside the same transaction // as UpdateGitHubPRSnapshot and the inserts below. func (q *Queries) DeleteGitHubPRCheckRuns(ctx context.Context, prID pgtype.UUID) error { _, err := q.db.Exec(ctx, deleteGitHubPRCheckRuns, prID) return err } const getGitHubPullRequestByID = `-- name: GetGitHubPullRequestByID :one SELECT id, workspace_id, installation_id, repo_owner, repo_name, pr_number, title, state, html_url, branch, author_login, author_avatar_url, merged_at, closed_at, pr_created_at, pr_updated_at, created_at, updated_at, head_sha, mergeable_state, additions, deletions, changed_files, api_mergeable, api_merge_state_status, checks_rollup_state, snapshot_head_sha, snapshot_fetched_at FROM github_pull_request WHERE id = $1 ` func (q *Queries) GetGitHubPullRequestByID(ctx context.Context, id pgtype.UUID) (GithubPullRequest, error) { row := q.db.QueryRow(ctx, getGitHubPullRequestByID, id) var i GithubPullRequest err := row.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.RepoOwner, &i.RepoName, &i.PrNumber, &i.Title, &i.State, &i.HtmlUrl, &i.Branch, &i.AuthorLogin, &i.AuthorAvatarUrl, &i.MergedAt, &i.ClosedAt, &i.PrCreatedAt, &i.PrUpdatedAt, &i.CreatedAt, &i.UpdatedAt, &i.HeadSha, &i.MergeableState, &i.Additions, &i.Deletions, &i.ChangedFiles, &i.ApiMergeable, &i.ApiMergeStateStatus, &i.ChecksRollupState, &i.SnapshotHeadSha, &i.SnapshotFetchedAt, ) return i, err } const insertGitHubPRCheckRun = `-- name: InsertGitHubPRCheckRun :exec INSERT INTO github_pull_request_check_run ( pr_id, head_sha, ordinal, name, status, conclusion, details_url, is_status_context ) VALUES ( $1, $2, $3, $4, $5, $7, $8, $6 ) ` type InsertGitHubPRCheckRunParams struct { PrID pgtype.UUID `json:"pr_id"` HeadSha string `json:"head_sha"` Ordinal int32 `json:"ordinal"` Name string `json:"name"` Status string `json:"status"` IsStatusContext bool `json:"is_status_context"` Conclusion pgtype.Text `json:"conclusion"` DetailsUrl pgtype.Text `json:"details_url"` } func (q *Queries) InsertGitHubPRCheckRun(ctx context.Context, arg InsertGitHubPRCheckRunParams) error { _, err := q.db.Exec(ctx, insertGitHubPRCheckRun, arg.PrID, arg.HeadSha, arg.Ordinal, arg.Name, arg.Status, arg.IsStatusContext, arg.Conclusion, arg.DetailsUrl, ) return err } const listGitHubPRNumbersByHeadSHA = `-- name: ListGitHubPRNumbersByHeadSHA :many SELECT DISTINCT pr_number FROM github_pull_request WHERE installation_id = $1 AND repo_owner = $2 AND repo_name = $3 AND head_sha = $4 ` type ListGitHubPRNumbersByHeadSHAParams struct { InstallationID int64 `json:"installation_id"` RepoOwner string `json:"repo_owner"` RepoName string `json:"repo_name"` HeadSha string `json:"head_sha"` } // Resolves a commit SHA to the PR numbers whose head it is. `status` webhook // events (legacy commit statuses) carry a SHA + repo but no PR number, so we // map back through the mirrored head_sha to find which PR(s) to refresh. func (q *Queries) ListGitHubPRNumbersByHeadSHA(ctx context.Context, arg ListGitHubPRNumbersByHeadSHAParams) ([]int32, error) { rows, err := q.db.Query(ctx, listGitHubPRNumbersByHeadSHA, arg.InstallationID, arg.RepoOwner, arg.RepoName, arg.HeadSha, ) if err != nil { return nil, err } defer rows.Close() items := []int32{} for rows.Next() { var pr_number int32 if err := rows.Scan(&pr_number); err != nil { return nil, err } items = append(items, pr_number) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGitHubPRRowsByAddress = `-- name: ListGitHubPRRowsByAddress :many SELECT id, workspace_id, head_sha, state FROM github_pull_request WHERE installation_id = $1 AND repo_owner = $2 AND repo_name = $3 AND pr_number = $4 ` type ListGitHubPRRowsByAddressParams struct { InstallationID int64 `json:"installation_id"` RepoOwner string `json:"repo_owner"` RepoName string `json:"repo_name"` PrNumber int32 `json:"pr_number"` } type ListGitHubPRRowsByAddressRow struct { ID pgtype.UUID `json:"id"` WorkspaceID pgtype.UUID `json:"workspace_id"` HeadSha string `json:"head_sha"` State string `json:"state"` } // ===================== // GitHub API snapshot (MUL-5265, Plan C) // // These queries back the API-snapshot refresh pipeline. The GitHub GraphQL // response is the single source of truth; each successful fetch is written as // one atomic batch replace (guarded update of the PR row + full replace of the // per-check rows) inside a single transaction. // ===================== // One (installation, owner, repo, number) address can map to several // github_pull_request rows — the same installation can be bound to multiple // workspaces (#4823/#4855), each mirroring its own row. A single API fetch is // applied to every matching row (each guarded by its own head_sha). func (q *Queries) ListGitHubPRRowsByAddress(ctx context.Context, arg ListGitHubPRRowsByAddressParams) ([]ListGitHubPRRowsByAddressRow, error) { rows, err := q.db.Query(ctx, listGitHubPRRowsByAddress, arg.InstallationID, arg.RepoOwner, arg.RepoName, arg.PrNumber, ) if err != nil { return nil, err } defer rows.Close() items := []ListGitHubPRRowsByAddressRow{} for rows.Next() { var i ListGitHubPRRowsByAddressRow if err := rows.Scan( &i.ID, &i.WorkspaceID, &i.HeadSha, &i.State, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listStaleUndecidedGitHubPRs = `-- name: ListStaleUndecidedGitHubPRs :many WITH candidates AS ( SELECT installation_id, repo_owner, repo_name, pr_number FROM github_pull_request AS pr WHERE state IN ('open', 'draft') AND (snapshot_fetched_at IS NULL OR snapshot_fetched_at < $6) AND ( snapshot_fetched_at IS NULL OR api_mergeable IS NULL OR api_mergeable = 'UNKNOWN' OR checks_rollup_state IN ('PENDING', 'EXPECTED') OR EXISTS ( SELECT 1 FROM github_pull_request_check_run AS cr WHERE cr.pr_id = pr.id AND cr.status <> 'completed' ) ) GROUP BY installation_id, repo_owner, repo_name, pr_number ) SELECT installation_id, repo_owner, repo_name, pr_number FROM candidates ORDER BY ( ROW(installation_id, repo_owner, repo_name, pr_number) > ROW( $1::BIGINT, $2::TEXT, $3::TEXT, $4::INTEGER ) ) DESC, installation_id, repo_owner, repo_name, pr_number LIMIT $5 ` type ListStaleUndecidedGitHubPRsParams struct { AfterInstallationID int64 `json:"after_installation_id"` AfterRepoOwner string `json:"after_repo_owner"` AfterRepoName string `json:"after_repo_name"` AfterPrNumber int32 `json:"after_pr_number"` MaxRows int32 `json:"max_rows"` OlderThan pgtype.Timestamptz `json:"older_than"` } type ListStaleUndecidedGitHubPRsRow struct { InstallationID int64 `json:"installation_id"` RepoOwner string `json:"repo_owner"` RepoName string `json:"repo_name"` PrNumber int32 `json:"pr_number"` } // TTL / safety-net sweep source. Returns distinct addresses of open/draft PRs // whose snapshot is both stale and undecided. A decided snapshot leaves the // periodic refresh set; later webhook or view activity can still refresh it. // The caller advances an address cursor after each bounded batch. Rows after // the cursor sort first, followed by a wrap to the start, so even perpetually // failing addresses cannot pin the same first LIMIT rows forever. func (q *Queries) ListStaleUndecidedGitHubPRs(ctx context.Context, arg ListStaleUndecidedGitHubPRsParams) ([]ListStaleUndecidedGitHubPRsRow, error) { rows, err := q.db.Query(ctx, listStaleUndecidedGitHubPRs, arg.AfterInstallationID, arg.AfterRepoOwner, arg.AfterRepoName, arg.AfterPrNumber, arg.MaxRows, arg.OlderThan, ) if err != nil { return nil, err } defer rows.Close() items := []ListStaleUndecidedGitHubPRsRow{} for rows.Next() { var i ListStaleUndecidedGitHubPRsRow if err := rows.Scan( &i.InstallationID, &i.RepoOwner, &i.RepoName, &i.PrNumber, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const updateGitHubPRSnapshot = `-- name: UpdateGitHubPRSnapshot :execrows UPDATE github_pull_request SET api_mergeable = $1, api_merge_state_status = $2, checks_rollup_state = $3, snapshot_head_sha = $4, snapshot_fetched_at = $5, updated_at = now() WHERE id = $6 AND head_sha = $4 ` type UpdateGitHubPRSnapshotParams struct { ApiMergeable pgtype.Text `json:"api_mergeable"` ApiMergeStateStatus pgtype.Text `json:"api_merge_state_status"` ChecksRollupState pgtype.Text `json:"checks_rollup_state"` HeadSha string `json:"head_sha"` FetchedAt pgtype.Timestamptz `json:"fetched_at"` PrID pgtype.UUID `json:"pr_id"` } // Head-SHA anti-stale write (acceptance criterion 1): the snapshot is written // only when the row's current head_sha still equals the head the snapshot was // fetched for. If the head advanced (a newer push landed while this request was // in flight, mirrored by the pull_request webhook), 0 rows are updated and the // caller discards the whole response — the per-check replace is skipped too. func (q *Queries) UpdateGitHubPRSnapshot(ctx context.Context, arg UpdateGitHubPRSnapshotParams) (int64, error) { result, err := q.db.Exec(ctx, updateGitHubPRSnapshot, arg.ApiMergeable, arg.ApiMergeStateStatus, arg.ChecksRollupState, arg.HeadSha, arg.FetchedAt, arg.PrID, ) if err != nil { return 0, err } return result.RowsAffected(), nil }