Repository navigation
fix(store): hash BackendColumn by its name and value - #3404
Conversation
RocksDBSession.BackendColumn overrode equals() to compare name and value bytes but kept Object.hashCode(). A RocksDB scan allocates a new column for every row, so the hash-based iterators in hg-store-core never matched byte-equal rows that came from separate objects: - IntersectionFilterIterator (size 2) returned 0 rows for 100 keys read twice - UnionFilterIterator below its sort threshold returned 200 instead of 100 - MapLimitIterator's dedup set kept every copy hashCode() now combines Arrays.hashCode() of the same two arrays equals() compares, and new tests in hg-store-test build a fresh column per row. Fixes apache#3396
bitflicker64
left a comment
There was a problem hiding this comment.
Blocking: no. Summary: The content hash fixes the in-memory intersection, the union below its sort threshold and limit dedup for unchanged rows, and the new tests catch the bug on the base. The PR's note that MapLimitIterator now drops byte-equal copies does not hold for id-only queries, because the null-property projection stage overwrites the emitted column that the iterator keeps as its set key; that mutation predates this PR, so it is not blocking. Evidence: read the full diff plus the BusinessHandlerImpl dedup paths, IntersectionFilterIterator, UnionFilterIterator, MapLimitIterator, QueryUtil.buildPlan, ProjectionStage and AggregativeQueryObserver.executePlainPipeline. At this head, mvn test -pl hugegraph-store/hg-store-test -am -P store-core-test passes (139 tests, 1 skipped); with the base RocksDBSession.java, 4 of the 5 new tests fail. The only CI run on this head (HugeGraph-Server CI) is waiting for maintainer approval.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3404 +/- ##
============================================
+ Coverage 55.93% 56.13% +0.20%
- Complexity 2277 2386 +109
============================================
Files 774 775 +1
Lines 68534 69060 +526
Branches 9333 9507 +174
============================================
+ Hits 38334 38770 +436
- Misses 26634 26672 +38
- Partials 3566 3618 +52
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Purpose of the PR
RocksDBSession.BackendColumncompares name and value bytes inequals()but had nohashCode(), so it used identity hashing. A RocksDB scan allocates a new column per row, so the hash-based iterators inhg-store-corenever matched byte-equal rows held in separate objects. With 100 keys read twice, the intersection withsize = 2returned 0 rows instead of 100 and the union below its 10,000-entry sort threshold returned 200. Those are the issue's numbers, and the new tests reproduce them onmaster.Main Changes
RocksDBSession.BackendColumn.hashCode()returns31 * Arrays.hashCode(name) + Arrays.hashCode(value), the same arraysequals()compares (Bytes.equalsisArrays.equals, and both handle null arrays consistently).FilterIteratorColumnEqualityTestinhg-store-test, registered inCoreSuiteTest. Every row is built from fresh arrays, as the issue asks. It covers:HashSetentries for the same name with different values;IntersectionFilterIteratorwithsize = 2;UnionFilterIteratorbelow its sort threshold;MapLimitIterator.Behaviour changes reviewers should know about
MapLimitIterator(the LIMIT_DEDUP and PRECISE_DEDUP-with-limit paths inBusinessHandlerImpl) now drops byte-equal copies. Before, itsConcurrentHashSetkept all of them.ReduceIteratorpath does. So it also has the limitation the class comments already describe: a row repeated inside one source counts towardsize, so withsize = 2an element that appears twice in one source and not in the other is returned. This PR doesn't change that rule. Fixing it needs per-source counting, which I'd treat as a separate issue.StoreQueryParamfixesdedupOptiontoNONE, and the server'squery.dedup_optionsetting is never passed to the store, so only a gRPC client that setsdedup_optiongets here.Out of scope
lookupBack = true),scanIndexToElementIdsetsvalueto the owner id, which is the same in every source, so the two rules agree there. They can differ whenlookup = false, wherevalueis the raw index value. This PR keeps both rules and doesn't claim they're equivalent; the same-name/different-value test pins the equality rule.Verifying these changes
mvn test -pl hugegraph-store/hg-store-test -am -P store-core-test -Dtest=FilterIteratorColumnEqualityTest -Dsurefire.failIfNoSpecifiedTests=false: 4 of the 5 tests fail onmaster(hash codes differ, the intersection returns no keys, union and limit dedup return keys twice) and all 5 pass with this change. The iterator tests compare the exact set of returned keys.mvn test -pl hugegraph-store/hg-store-test -am -P store-core-test: 139 tests, 0 failures (1 skipped,IpUtilTest.testConfiguredLinkLocalStays, an environment assumption).mvn test -pl hugegraph-store/hg-store-test -am -P store-rocksdb-test: 19 tests, 0 failures.mvn editorconfig:check -pl hugegraph-store/hg-store-test -amandmvn apache-rat:checkpass.Does this PR potentially affect the following parts?
Documentation Status
Doc - TODO: required documentation is pending; complete it before merging.Doc - Done: documentation is included here or linked below.Doc - No Need: no user-visible documentation is affected.Documentation files in this PR or paired hugegraph-doc PR:
Equality and hashing
Conceptual illustration of the hash-based paths; sorted name-only grouping, repeated rows within one source, and SortShuffle remain outside this change. Default dedup remains NONE. This diagram does not certify tests or CI.