[common] Fix equals/hashCode contract violation in Schema.PrimaryKey#3629
Open
NestDream wants to merge 1 commit into
Open
[common] Fix equals/hashCode contract violation in Schema.PrimaryKey#3629NestDream wants to merge 1 commit into
NestDream wants to merge 1 commit into
Conversation
Schema.PrimaryKey.equals() compares only the primary-key column names,
but hashCode() folded in super.hashCode() (the Object identity hash).
Two value-equal PrimaryKey instances therefore returned different hash
codes, violating the general contract of Object.hashCode() ("equal
objects must have equal hash codes"). The defect propagates to
Schema.hashCode() and to the public TableDescriptor, which include the
primary key.
Schema and PrimaryKey are public API (@PublicEvolving / @PublicStable),
so any code that puts a schema or table descriptor into a HashSet/HashMap
is affected. This is easy to hit after a schema round-trips through its
JSON form (as Fluss does when it persists a schema to ZooKeeper via
SchemaZNode and reads it back): the reloaded schema is equal() to the
in-memory one but hashes differently, so a hash-based lookup misses it.
Compute hashCode() over columnNames only, matching the field equals()
compares and aligning with the value-based hashing already used by
Schema and Column.
Tests:
- TableSchemaTest#testPrimaryKeySchemaSurvivesJsonRoundTripAsHashKey:
unit test over the toJsonBytes/fromJsonBytes round-trip; also asserts
that two primary keys with equal columns but different constraint
names are equal and hash-equal.
- FlussAdminITCase#testPrimaryKeySchemaReadBackIsUsableAsHashKey:
end-to-end test that creates a primary-key table via the Admin API and
asserts the schema read back from the cluster is usable as a hash key.
Both fail before the fix and pass after.
Generated-by: Claude Code (Fable 5) following https://github.com/apache/fluss/blob/main/AGENTS.md
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Linked issue: close #3628
Schema.PrimaryKey.hashCode()folds insuper.hashCode()(theObjectper-instance hash) whileequals()compares onlycolumnNames, so two value-equal primary keys return different hash codes. This violates theObject.equals/hashCodecontract and propagates throughSchema.hashCode()and the publicTableDescriptor, so an equal schema/table descriptor can be missing from aHashSet/HashMap(e.g. after atoJsonBytes/fromJsonBytesround-trip). Standalone reproduction against the released 0.9.1-incubating artifact: https://github.com/NestDream/fluss-pk-hashcode-demoBrief change log
Schema.PrimaryKey.hashCode():Objects.hash(super.hashCode(), columnNames)→Objects.hash(columnNames), matching the fieldequals()compares and the value-based hashing already used bySchemaandColumn.Tests
TableSchemaTest#testPrimaryKeySchemaSurvivesJsonRoundTripAsHashKey(unit): round-trips a primary-key schema viatoJsonBytes/fromJsonBytesand asserts the reloaded schema hashes equally and is found in aHashSet<Schema>; also asserts two primary keys with equal columns but different constraint names are equal and hash-equal. Fails before the fix, passes after.FlussAdminITCase#testPrimaryKeySchemaReadBackIsUsableAsHashKey(end-to-end): creates a primary-key table viaAdmin.createTable, reads the schema back viaAdmin.getTableSchema, and asserts it is usable as a hash key. Fails before the fix, passes after.TableSchemaTest,TableDescriptorTest,SchemaJsonSerdeTestcontinue to pass (mvn verify -pl fluss-common: 1684 tests, 0 failures).API and Format
No public API or storage format change.
hashCode()is never persisted or transmitted (SchemaJsonSerdewrites explicit fields; on-the-wire schema identity is the separateschemaId).Documentation
No documentation change; behavior-only fix.
Assisted by: Claude Code (Fable 5) following the guidelines