Skip to content

fix(row-cache): clamp negative start in View.rowidsInRange#942

Merged
paddymul merged 2 commits into
mainfrom
fix/row-cache-view-range-clamp
Jun 25, 2026
Merged

fix(row-cache): clamp negative start in View.rowidsInRange#942
paddymul merged 2 commits into
mainfrom
fix/row-cache-view-range-clamp

Conversation

@paddymul

Copy link
Copy Markdown
Collaborator

Summary

View.rowidsInRange(start, end) is a defensive range accessor — it already clamps end at length() and returns [] for an inverted range. It does not clamp a negative start, and the three view kinds diverge there:

  • IdentityView(20).rowidsInRange(-3, 2)[-3, -2, -1, 0, 1] (five nonexistent negative rowids)
  • SortView(...).rowidsInRange(-3, 2) / FilterView(...)[]

IdentityView silently emits rowids the RowStore can never satisfy; the array-backed views drop the window entirely. The renderer composes view at position k → rowid → RowStore.get(rowid), so a boundary window near row 0 (which the AG-Grid datasource will produce once RowCache is wired in at phase 7b) reads back garbage from one view kind and nothing from the others.

This is an oversight in the range accessor, not the positionAt "callers must clamp" contract (which is unchanged). The fix clamps start to 0 in all three rowidsInRange implementations so they agree and never index out of range.

TDD

Per repo convention, this PR opens with the failing test alone (46fb43b8) so CI is seen red before the fix lands; the fix commit follows on the same branch. Found while evaluating the phase 1–7a row-cache code (PR #719).

Test plan

  • CI red on the test-only commit (4 cases fail: each view kind diverges on rowidsInRange(-3, 2))
  • CI green after the fix commit
  • Existing Views/RowStore/RowStoreGc/ViewRegistry/RowCache suites stay green

🤖 Generated with Claude Code

IdentityView.rowidsInRange(-3, 2) returns nonexistent negative rowids
([-3,-2,-1,0,1]) while SortView/FilterView return an empty slice for the
same range. rowidsInRange already clamps end and handles inverted ranges
defensively, so the negative-start divergence is an oversight, not a
contract choice. This becomes a live bug once 7b wires rowidsInRange into
the AG-Grid datasource at a boundary window near row 0.

Test only — fix follows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clamp start to 0 in IdentityView/SortView/FilterView.rowidsInRange so all
three view kinds agree and never index out of range. rowidsInRange already
clamped end and handled inverted ranges; this completes that defensive
contract on the start side. The positionAt "callers must clamp" contract
is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 46fb43b854

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

];

test.each(cases)("%s — rowidsInRange(-3, 2) clamps start to 0", (_label, v) => {
expect(v.rowidsInRange(-3, 2)).toStrictEqual(v.rowidsInRange(0, 2));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Implement the negative-start clamp under test

This new contract is added without the corresponding View.rowidsInRange implementation change, so the Views.test.ts suite becomes red: IdentityView.rowidsInRange(-3, 2) currently returns [-3, -2, -1, 0, 1], while SortView/FilterView return an empty slice for this range, so this assertion fails for all three cases. Until Views.ts clamps start to 0, any CI job that runs the package Jest tests will fail on this commit.

Useful? React with 👍 / 👎.

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

📦 TestPyPI package published

pip install --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==0.15.2.dev28125040636

or with uv:

uv pip install --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==0.15.2.dev28125040636

MCP server for Claude Code

claude mcp add buckaroo-table -- uvx --from "buckaroo[mcp]==0.15.2.dev28125040636" --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo-table

📖 Docs preview

🎨 Storybook preview

@paddymul
paddymul added this pull request to the merge queue Jun 25, 2026
Merged via the queue into main with commit 8b814a9 Jun 25, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant