Skip to content

fix(api/purchases): add scheduled_execution_at to GetPlannedExecutions SELECT#1255

Open
cristim wants to merge 2 commits into
mainfrom
fix/qa579-planned-executions-scan
Open

fix(api/purchases): add scheduled_execution_at to GetPlannedExecutions SELECT#1255
cristim wants to merge 2 commits into
mainfrom
fix/qa579-planned-executions-scan

Conversation

@cristim

@cristim cristim commented Jun 19, 2026

Copy link
Copy Markdown
Member

Closes #1247

Symptom

On the Plans page, the "Planned Purchases" section fails to load with "Failed to load planned purchases: Internal server error" (HTTP 500). Reproducible by the Admin user, so this is not a permissions issue.

Root Cause

GetPlannedExecutions in internal/config/store_postgres.go projected only 26 columns in its SELECT, omitting scheduled_execution_at. The shared scanExecutionRows helper scans 27 columns, with &scheduledExecutionAt as the final (27th) scan target. Against a real PostgreSQL instance the row Scan fails with "expected 27 destination arguments in Scan, not 26", returning "failed to scan execution" which the handler surfaces as a 500.

This drifted in via PR #804 (revocation-delay feature, commit 8e5f139) which added scheduled_execution_at to scanExecutionRows and every other SELECT feeding it (ListStuckExecutions, GetPendingExecutions, GetStaleApprovedExecutions), but skipped GetPlannedExecutions.

Fix

  1. Add scheduled_execution_at to the GetPlannedExecutions SELECT in the correct position (after idempotency_key, matching the scanExecutionRows scan order and consistent with every sibling query).
  2. Tighten the regression test TestPGXMock_GetPlannedExecutions_ProjectsAllScanColumns: the mock ExpectQuery regexp now requires both idempotency_key AND scheduled_execution_at to appear in the issued SQL, so a future column-count drift is caught at test time instead of in production.

Why the old test was a false positive

The previous matcher (mock.ExpectQuery("idempotency_key")) matched any SQL containing idempotency_key and returned a 27-column mock result regardless of the actual projection, so it passed even with the bug present. The tightened alternation regexp (idempotency_key.*scheduled_execution_at|scheduled_execution_at.*idempotency_key) fails to match a projection missing either column, the mock then returns no rows, and the test fails.

Testing

  • go build ./...: pass
  • go test ./internal/config/...: 585 passed
  • Regression test, pre-fix (SELECT change reverted, tightened test active): FAILS with "could not match actual sql" because the issued SELECT does not contain scheduled_execution_at.
  • Regression test, post-fix (both files in place): PASSES.

Stacking

Stacked on #1254 (pre-commit repair); retarget to main when #1254 merges.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed database query handling for scheduled executions to ensure proper data retrieval and validation.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@cristim, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 8 minutes and 15 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: feaf3cfb-beb8-4d6f-807d-d8e6a75a494e

📥 Commits

Reviewing files that changed from the base of the PR and between 1de7bb0 and 9ccf5ed.

📒 Files selected for processing (2)
  • internal/config/store_postgres.go
  • internal/config/store_postgres_pgxmock_test.go
📝 Walkthrough

Walkthrough

GetPlannedExecutions in store_postgres.go was missing scheduled_execution_at from its SQL SELECT column list, causing a scan-column-count mismatch at runtime. One column is added to the projection, and the pgxmock regression test matcher is tightened to require both idempotency_key and scheduled_execution_at in the generated SQL.

Changes

Fix GetPlannedExecutions SQL projection and regression guard

Layer / File(s) Summary
Add scheduled_execution_at to SELECT and tighten test matcher
internal/config/store_postgres.go, internal/config/store_postgres_pgxmock_test.go
GetPlannedExecutions SELECT now includes scheduled_execution_at immediately after idempotency_key, matching the 27-column order expected by scanExecutionRows. The TestPGXMock_GetPlannedExecutions_ProjectsAllScanColumns regex is updated from matching only idempotency_key to requiring both idempotency_key and scheduled_execution_at in the projected SQL.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Suggested labels

priority/p1, urgency/now, effort/xs

Poem

A column was lost in the SELECT one day,
scheduled_execution_at had gone astray.
The scanner cried "27! Not 26!"
So the rabbit added one line to fix,
And tightened the test so it never can fray. 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding the scheduled_execution_at column to GetPlannedExecutions SELECT, which is the core fix for the regression bug.
Linked Issues check ✅ Passed The PR fully addresses all coding objectives from issue #1247: adding scheduled_execution_at to GetPlannedExecutions SELECT and tightening the regression test regexp to catch future column drift.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the column-mismatch bug in GetPlannedExecutions and strengthening its regression test; no unrelated modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/qa579-planned-executions-scan

Comment @coderabbitai help to get the list of available commands and usage tips.

@cristim cristim added triaged Item has been triaged type/bug Defect priority/p2 Backlog-worthy severity/high Significant harm urgency/this-sprint Within the current sprint impact/many Affects most users effort/s Hours labels Jun 19, 2026
@cristim

cristim commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim cristim changed the base branch from fix/1222-precommit-repair to main June 19, 2026 14:51
cristim added 2 commits June 19, 2026 17:24
…s SELECT

GetPlannedExecutions projected 26 columns, but scanExecutionRows scans 27
(the 27th being scheduled_execution_at). Against a real PostgreSQL instance
this caused rows.Scan to fail ("expected 27 destination arguments in Scan,
not 26"), returning "failed to scan execution" and surfacing as a 500 on
the Planned Purchases list endpoint.

The regression drifted in via PR #804 (commit 8e5f139) which added
scheduled_execution_at to scanExecutionRows and every other SELECT feeding
it, but skipped GetPlannedExecutions.

Also tighten TestPGXMock_GetPlannedExecutions_ProjectsAllScanColumns:
the mock ExpectQuery regexp now requires both idempotency_key AND
scheduled_execution_at in the SQL so future column-count drift is caught
at test time rather than in production.

Closes #1247
…GetPlannedExecutions test

The regression test already verified the scan column count (select+scan
both have 27 columns). This tightens it to also assert that a NULL
scheduled_execution_at comes back as a nil *time.Time pointer rather than
a zero-value time, confirming applyNullTimesToExecution's Valid-guard.
@cristim cristim force-pushed the fix/qa579-planned-executions-scan branch from 1de7bb0 to 9ccf5ed Compare June 19, 2026 15:33
@cristim

cristim commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/s Hours impact/many Affects most users priority/p2 Backlog-worthy severity/high Significant harm triaged Item has been triaged type/bug Defect urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(api/purchases): GET planned purchases returns 500 (GetPlannedExecutions SELECT omits scheduled_execution_at) (QA row 579)

1 participant