Repository navigation
[python] Serialize high-precision decimals with Java's minimal bytes - #10872
Closed
plusplusjiajia wants to merge 1 commit into
Closed
plusplusjiajia wants to merge 1 commit into
plusplusjiajia wants to merge 1 commit into
Conversation
Decimals with precision above 18 store their unscaled value as two's complement bytes. PyPaimon computed the length as (bit_length() + 8) // 8, which adds a byte for negative values that are exactly -2^(8k-1), so -1.28 in DECIMAL(20,2) was written as ff80 while Java writes 80 (BigInteger.toByteArray). Such keys hashed to a different bucket than in Java (bucket 2 instead of 7 with 10 buckets), and such partition values had different bytes than Java's. BinaryRow serialization and the row format writer now use the minimal encoding through one shared helper, which the global index key serializer also uses instead of its own copy.
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
Decimals with precision above 18 store their unscaled value as two's complement bytes. PyPaimon computed the length as
(bit_length() + 8) // 8, which adds an extra byte for negative values that are exactly -2^(8k-1). For example, -1.28 inDECIMAL(20, 2)was written asff80, while Java writes80(BigInteger.toByteArray). Such primary keys hashed to a different bucket than in Java (bucket 2 instead of 7 with 10 buckets), and such partition values had different bytes than Java's.BinaryRowserialization and the row format writer now use the minimal encoding, like Java, through one shared helper. The global index key serializer also uses this helper instead of its own copy.Tests
DecimalTest#test_decimal_not_compact_java_bytesand#test_decimal_fixed_bucket_matches_javaindecimal_test.py:BinaryRowbytes and the fixed bucket match Java, and longer encodings are still read.TestFormatRowReaderWriter#test_decimal_minimal_bytes: the row format writer writes Java's bytes.DecimalKeySerializerTest#test_java_decimal_bytesandtest_decimal.py: the global index key serializer andDecimalkeep Java's bytes.Decimalcases guard existing behavior. The related tests pass locally: 104 tests. flake8 is clean.