-
Notifications
You must be signed in to change notification settings - Fork 29.3k
[SPARK-29918][SQL] RecordBinaryComparator should check endianness when compared by long #26548
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -56,8 +56,8 @@ public class RecordBinaryComparatorSuite { | |
|
|
||
| @Before | ||
| public void beforeEach() { | ||
| // Only compare between two input rows. | ||
| array = consumer.allocateArray(2); | ||
| // At most three input rows | ||
| array = consumer.allocateArray(3); | ||
| pos = 0; | ||
|
|
||
| dataPage = memoryManager.allocatePage(4096, consumer); | ||
|
|
@@ -88,7 +88,7 @@ private void insertRow(UnsafeRow row) { | |
| Platform.copyMemory(recordBase, recordOffset, baseObject, pageCursor, recordLength); | ||
| pageCursor += recordLength; | ||
|
|
||
| assert(pos < 2); | ||
| assert(pos < 3); | ||
| array.set(pos, recordAddress); | ||
| pos++; | ||
| } | ||
|
|
@@ -108,7 +108,7 @@ private int compare(int index1, int index2) { | |
| baseOffset2, recordLength2); | ||
| } | ||
|
|
||
| private final RecordComparator binaryComparator = new RecordBinaryComparator(); | ||
| private final RecordComparator binaryComparator = new RecordBinaryComparator(true); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... per the above comment, this wouldn't work on big-endian systems. |
||
|
|
||
| // Compute the most compact size for UnsafeRow's backing data. | ||
| private int computeSizeInBytes(int originalSize) { | ||
|
|
@@ -273,7 +273,7 @@ public void testBinaryComparatorWhenSubtractionIsDivisibleByMaxIntValue() throws | |
| insertRow(row1); | ||
| insertRow(row2); | ||
|
|
||
| assert(compare(0, 1) < 0); | ||
| assert(compare(0, 1) > 0); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, do you mean this is wrong before this PR?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The change definitely changes the ordering, as bytes are compared in a different order.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| @Test | ||
|
|
@@ -321,4 +321,69 @@ public void testBinaryComparatorWhenOnlyTheLastColumnDiffers() throws Exception | |
|
|
||
| assert(compare(0, 1) < 0); | ||
| } | ||
|
|
||
| @Test | ||
| public void testBinaryComparatorGiveSameResultWhenComparedByteByByteAndComparedByLong() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Heh, you might chop this down a bit. |
||
| throws Exception { | ||
| int numFields = 1; | ||
|
|
||
| UnsafeRow row1 = new UnsafeRow(numFields); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you need UnsafeRow in this test? the test case I posted seems fine by itself. It isn't specific to UnsafeRow, or at least, I'd make sure this test still triggers the problem after the change.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. test cast updated |
||
| byte[] data1 = new byte[100]; | ||
| row1.pointTo(data1, computeSizeInBytes(numFields * 8)); | ||
| row1.setLong(0, 0x0800000000000000L); | ||
|
|
||
| UnsafeRow row2 = new UnsafeRow(numFields); | ||
| byte[] data2 = new byte[100]; | ||
| row2.pointTo(data2, computeSizeInBytes(numFields * 8)); | ||
| row2.setLong(0, 0x0000008000000000L); | ||
|
|
||
| UnsafeRow row3 = new UnsafeRow(numFields); | ||
| byte[] data3 = new byte[100]; | ||
| row3.pointTo(data3, computeSizeInBytes(numFields * 8)); | ||
| row3.setLong(0, 0x0000008000000000L); | ||
|
|
||
| insertRow(row1); | ||
| insertRow(row2); | ||
| insertRow(row3); | ||
|
|
||
| // the bytes in row2 and row3 are the same. | ||
| // the base offset of row1 is 20, row2 is 40, row3 is 60 | ||
| // so the RecordBinaryComparator will compare row1 and row2 with two long comparison directly, | ||
| // while the comparison between row1 and row3 is started with 4 bytes byte-by-byte comparison, | ||
| // followed by a long comparison, and lastly 4 bytes byte-by-byte comparison. | ||
| assert(compare(0, 1) < 0); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just assert the comparison is the same, here and below. |
||
| assert(compare(0, 2) < 0); | ||
| } | ||
|
|
||
| @Test | ||
| public void testBinaryComparatorShouldComparedWithUnsignedLong() throws Exception { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| int numFields = 1; | ||
|
|
||
| UnsafeRow row1 = new UnsafeRow(numFields); | ||
| byte[] data1 = new byte[100]; | ||
| row1.pointTo(data1, computeSizeInBytes(numFields * 8)); | ||
| row1.setLong(0, 0xa000000000000000L); | ||
|
|
||
| UnsafeRow row2 = new UnsafeRow(numFields); | ||
| byte[] data2 = new byte[100]; | ||
| row2.pointTo(data2, computeSizeInBytes(numFields * 8)); | ||
| row2.setLong(0, 0x0000000000000000L); | ||
|
|
||
| UnsafeRow row3 = new UnsafeRow(numFields); | ||
| byte[] data3 = new byte[100]; | ||
| row3.pointTo(data3, computeSizeInBytes(numFields * 8)); | ||
| row3.setLong(0, 0x0000000000000000L); | ||
|
|
||
| insertRow(row1); | ||
| insertRow(row2); | ||
| insertRow(row3); | ||
|
|
||
| // the bytes in row2 and row3 are the same. | ||
| // the base offset of row1 is 20, row2 is 40, row3 is 60 | ||
| // so the RecordBinaryComparator will compare row1 and row2 with two long comparison directly, | ||
| // while the comparison between row1 and row3 is started with 4 bytes byte-by-byte comparison, | ||
| // followed by a long comparison, and lastly 4 bytes byte-by-byte comparison. | ||
| assert(compare(0, 1) > 0); | ||
| assert(compare(0, 2) > 0); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this. It's a fixed property of the entire VM / JVM. Just:
private static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder.equals(ByteOrder.LITTLE_ENDIAN);There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated