Skip to content

Refuse a missing relation target before any row is read - #83

Merged
mo4islona merged 1 commit into
masterfrom
fix/missing-relation-table
Oct 21, 2026
Merged

mo4islona merged 1 commit into
masterfrom
fix/missing-relation-table

Conversation

@mo4islona

Copy link
Copy Markdown
Collaborator

Closes #81.

A relation's target was checked only when the relation had a row to follow. Take a dataset without traces and transactions: [{sighash: [...], traces: true}]. A chunk where no transaction matched answered as if the table were there. A chunk where one did failed with TableNotFound. So a stream over that dataset returned some pages and then failed.

Execution::prepare now checks every relation's target together with the block table and the item tables, before any row is read. Whether the query fails no longer depends on which rows match.

A selected column of a relation's target had the same gap. Only a scan checked that the column exists, and a relation with nothing to follow does no scan. The schema check in prepare now refuses a missing selected column of any planned table. For the header and the item tables this only moves the error earlier, because their scan already raised the same ColumnNotFound.

Behaviour change: if a dataset's chunks lack a table, a query that reaches that table through a relation now fails on every chunk. Before, it failed only on chunks where a row pointed at it. A query that names neither the table nor its columns is unaffected, and the engine still opens no table the query does not name.

Spec: INV-E4 now says that every table the query requests is needed, whatever the rows. INV-E3 says that a selected column is needed whether or not a row of its table is read. The CT-8 table, the coverage matrix and docs/architecture.md are updated to match.

Tests: a_missing_relation_table_is_an_error_without_inputs replaces a_missing_relation_table_is_not_observed_without_inputs. a_relation_target_missing_a_selected_column_is_an_error_without_inputs is new. Each runs four shapes in which a relation has nothing to follow, in both JSON and Arrow:

  • a range with no source rows, with includeAllBlocks
  • a range with no source rows, without it
  • a filter that matches no source row
  • the only item that asks for the relation matches nothing, next to an item that does match

Before the fix, all eight query/format combinations returned an answer. With either fix removed, its test fails.

CT-8 and make spec-check pass. The full suite (--features legacy-query -- --include-ignored, with the reference comparison) is still running; I will post the result here.

🤖 Generated with Claude Code

A relation's target was checked only when the relation had a row to follow,
so on a dataset without the table a stream answered the pages where nothing
matched and failed on the first page where something did. The target is now
checked with the other planned tables, whatever the rows.

A selected column of the target had the same hole: only a scan checked it,
and a relation with no row to follow scans nothing. The schema check now
refuses a missing selected column as well.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mo4islona
mo4islona merged commit 155460e into master Oct 21, 2026
2 checks passed
@mo4islona
mo4islona deleted the fix/missing-relation-table branch October 22, 2026 19:36
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.

A query that requests a table the chunk does not have must fail, also when no row points to it

1 participant