Skip to content

fix(expression): treat COUNT(*) as referencing no fields in GetReferencedFieldIds - #981

Open
LuciferYang wants to merge 1 commit into
apache:mainfrom
LuciferYang:fix/sweep-4-binder-countstar-null-deref
Open

LuciferYang wants to merge 1 commit into
apache:mainfrom
LuciferYang:fix/sweep-4-binder-countstar-null-deref

Conversation

@LuciferYang

Copy link
Copy Markdown
Contributor

What

ReferenceVisitor::GetReferencedFieldIds crashed on a bound COUNT(*). ReferenceVisitor::Aggregate dereferenced aggregate->reference(), which is nullptr for COUNT(*) (its term is null by construction). The visitor is reached through the exported GetReferencedFieldIds, so a consumer doing aggregate pushdown would segfault on the most common SQL aggregate.

Closes #978.

How

Aggregate now inserts the field id only when reference() is non-null, so COUNT(*) contributes nothing (it references no columns). COUNT(col) / MAX / MIN keep their existing behavior.

Testing

Two tests in expression_visitor_test.cc:

  • CountStar — binding COUNT(*) and calling GetReferencedFieldIds returns an empty set. Without the fix this segfaults the test binary at the null dereference.
  • AggregateWithTerm — MAX(age) still reports its field id {3}, pinning the non-null branch so a mutation that drops or inverts the guard is caught.

…ncedFieldIds

ReferenceVisitor::Aggregate unconditionally called
aggregate->reference()->field_id(), but BoundAggregate::reference()
returns nullptr for aggregates without a term such as COUNT(*), so
GetReferencedFieldIds on a bound count(*) dereferenced null and
crashed. Skip the insert when there is no reference; the aggregate
then correctly contributes no field ids, matching the Java reference.
Copilot AI balanced review requested due to automatic review settings October 1, 2026 11:30

Copilot AI 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.

Copilot review overview

🟢 Approval recommended

The focused null-safety fix is correct and adequately covered by regression tests.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes #978 by preventing a null dereference when collecting field references from bound COUNT(*).

Changes:

  • Treats termless aggregates as referencing no fields.
  • Adds regression tests for COUNT(*) and MAX(age).
File Description
src/​iceberg/​expression/​binder.cc Guards nullable aggregate references.
src/​iceberg/​test/​expression_visitor_test.cc Tests termless and field-based aggregates.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

This branch has not been deployed

No deployments
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.

bug: ReferenceVisitor::GetReferencedFieldIds dereferences null on a bound COUNT(*)

2 participants