From ffbccc50f9da3cfb35a9d6772c0d052648e46693 Mon Sep 17 00:00:00 2001 From: Zac Blanco Date: Wed, 16 Oct 2024 11:26:37 -0700 Subject: [PATCH] use big-endian representation for uuids --- .../facebook/presto/common/type/UuidType.java | 13 ++- .../presto/type/TestUuidOperators.java | 101 ++++++++++++++++-- .../facebook/presto/type/TestUuidType.java | 3 +- .../plugin/postgresql/PostgreSqlClient.java | 5 +- 4 files changed, 105 insertions(+), 17 deletions(-) diff --git a/presto-common/src/main/java/com/facebook/presto/common/type/UuidType.java b/presto-common/src/main/java/com/facebook/presto/common/type/UuidType.java index 06aa22ee0683..f84922067943 100644 --- a/presto-common/src/main/java/com/facebook/presto/common/type/UuidType.java +++ b/presto-common/src/main/java/com/facebook/presto/common/type/UuidType.java @@ -28,6 +28,7 @@ import static com.facebook.presto.common.type.TypeSignature.parseTypeSignature; import static io.airlift.slice.SizeOf.SIZE_OF_LONG; import static io.airlift.slice.Slices.wrappedLongArray; +import static java.lang.Long.reverseBytes; import static java.lang.String.format; public class UuidType @@ -117,7 +118,9 @@ public Object getObjectValue(SqlFunctionProperties sqlFunctionProperties, Block if (block.isNull(position)) { return null; } - return new UUID(block.getLong(position, 0), block.getLong(position, SIZE_OF_LONG)).toString(); + return new UUID( + reverseBytes(block.getLong(position, 0)), + reverseBytes(block.getLong(position, SIZE_OF_LONG))).toString(); } @Override @@ -161,8 +164,8 @@ public final Slice getSlice(Block block, int position) public static Slice javaUuidToPrestoUuid(UUID uuid) { return wrappedLongArray( - uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits()); + reverseBytes(uuid.getMostSignificantBits()), + reverseBytes(uuid.getLeastSignificantBits())); } public static UUID prestoUuidToJavaUuid(Slice uuid) @@ -171,7 +174,7 @@ public static UUID prestoUuidToJavaUuid(Slice uuid) throw new IllegalStateException(format("Expected value to be exactly %d bytes but was %d", INT128_BYTES, uuid.length())); } return new UUID( - uuid.getLong(0), - uuid.getLong(SIZE_OF_LONG)); + reverseBytes(uuid.getLong(0)), + reverseBytes(uuid.getLong(SIZE_OF_LONG))); } } diff --git a/presto-main/src/test/java/com/facebook/presto/type/TestUuidOperators.java b/presto-main/src/test/java/com/facebook/presto/type/TestUuidOperators.java index 8a2e85ee2d0d..1309b474715c 100644 --- a/presto-main/src/test/java/com/facebook/presto/type/TestUuidOperators.java +++ b/presto-main/src/test/java/com/facebook/presto/type/TestUuidOperators.java @@ -63,11 +63,11 @@ public void testUUIDToVarcharCast() public void testVarbinaryToUUIDCast() { assertFunction("CAST(x'00000000000000000000000000000000' AS UUID)", UUID, "00000000-0000-0000-0000-000000000000"); - assertFunction("CAST(x'E9118675D21F1512595A08E4862A9E8F' AS UUID)", UUID, "12151fd2-7586-11e9-8f9e-2a86e4085a59"); - assertFunction("CAST(x'533BA1B0AD3304308E4582B5CA9177A9' AS UUID)", UUID, "300433ad-b0a1-3b53-a977-91cab582458e"); - assertFunction("CAST(x'8C4B12DE994E07D3A6AB9FF7FAB7A1A2' AS UUID)", UUID, "d3074e99-de12-4b8c-a2a1-b7faf79faba6"); - assertFunction("CAST(x'4957266AF8EAA7DFE874DF256033368D' AS UUID)", UUID, "dfa7eaf8-6a26-5749-8d36-336025df74e8"); - assertFunction("CAST(x'e9118675d21f1512595a08e4862a9e8f' AS UUID)", UUID, "12151fd2-7586-11e9-8f9e-2a86e4085a59"); + assertFunction("CAST(x'E9118675D21F1512595A08E4862A9E8F' AS UUID)", UUID, "e9118675-d21f-1512-595a-08e4862a9e8f"); + assertFunction("CAST(x'533BA1B0AD3304308E4582B5CA9177A9' AS UUID)", UUID, "533ba1b0-ad33-0430-8e45-82b5ca9177a9"); + assertFunction("CAST(x'8C4B12DE994E07D3A6AB9FF7FAB7A1A2' AS UUID)", UUID, "8c4b12de-994e-07d3-a6ab-9ff7fab7a1a2"); + assertFunction("CAST(x'4957266AF8EAA7DFE874DF256033368D' AS UUID)", UUID, "4957266a-f8ea-a7df-e874-df256033368d"); + assertFunction("CAST(x'e9118675d21f1512595a08e4862a9e8f' AS UUID)", UUID, "e9118675-d21f-1512-595a-08e4862a9e8f"); assertInvalidCast("CAST(x'f000001100' AS UUID)", "Invalid UUID binary length: 5"); } @@ -75,7 +75,7 @@ public void testVarbinaryToUUIDCast() public void testUUIDToVarbinaryCast() { assertFunction("CAST(UUID '00000000-0000-0000-0000-000000000000' AS VARBINARY)", VARBINARY, new SqlVarbinary(base16().decode("00000000000000000000000000000000"))); - assertFunction("CAST(UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' AS VARBINARY)", VARBINARY, new SqlVarbinary(base16().decode("B043E467655B5F6BA0589FD46C58E38E"))); + assertFunction("CAST(UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' AS VARBINARY)", VARBINARY, new SqlVarbinary(base16().decode("6B5F5B6567E443B08EE3586CD49F58A0"))); } @Test @@ -105,11 +105,92 @@ public void testNotEquals() @Test public void testOrderOperators() { - assertFunction("CAST('12151fd2-7586-11e9-8f9e-2a86e4085a58' AS UUID) < CAST('12151fd2-7586-11e9-8f9e-2a86e4085a59' AS UUID)", BOOLEAN, true); - assertFunction("CAST('12151fd2-7586-11e9-8f9e-2a86e4085a59' AS UUID) < CAST('12151fd2-7586-11e9-8f9e-2a86e4085a58' AS UUID)", BOOLEAN, false); + // LT + // equality + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) < CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + // check bytes in LSB + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) < CAST('00000000-0000-0000-0000-000000000001' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) < CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-ff00-000000000001' AS UUID) < CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) < CAST('00000000-0000-0000-ff00-000000000000' AS UUID)", BOOLEAN, true); - assertFunction("UUID '12151fd2-7586-11e9-8f9e-2a86e4085a52' BETWEEN UUID '12151fd2-7586-11e9-8f9e-2a86e4085a50' AND UUID '12151fd2-7586-11e9-8f9e-2a86e4085a59'", BOOLEAN, true); - assertFunction("UUID '12151fd2-7586-11e9-8f9e-2a86e4085a52' BETWEEN UUID '12151fd2-7586-11e9-8f9e-2a86e4085a54' AND UUID '12151fd2-7586-11e9-8f9e-2a86e4085a59'", BOOLEAN, false); + // check bytes in MSB + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) < CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) < CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('ff000000-0000-0001-0000-000000000000' AS UUID) < CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) < CAST('ff000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + + // check MSB side takes precedent over LSB side + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) < CAST('00000000-0000-0000-0000-000000000001' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) < CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('ff000000-0000-0000-0000-000000000001' AS UUID) < CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) < CAST('ff000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + + // ======================== + // LTE + // equality + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) <= CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + // check bytes in LSB + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) <= CAST('00000000-0000-0000-0000-000000000001' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) <= CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-ff00-000000000001' AS UUID) <= CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) <= CAST('00000000-0000-0000-ff00-000000000000' AS UUID)", BOOLEAN, true); + + // check bytes in MSB + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) <= CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) <= CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('ff000000-0000-0001-0000-000000000000' AS UUID) <= CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) <= CAST('ff000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + + // check MSB side takes precedent over LSB side + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) <= CAST('00000000-0000-0000-0000-000000000001' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) <= CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('ff000000-0000-0000-0000-000000000001' AS UUID) <= CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) <= CAST('ff000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + + // ======================== + // GT + // equality + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) > CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + // check bytes in LSB + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) > CAST('00000000-0000-0000-0000-000000000001' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) > CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-ff00-000000000001' AS UUID) > CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) > CAST('00000000-0000-0000-ff00-000000000000' AS UUID)", BOOLEAN, false); + + // check bytes in MSB + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) > CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) > CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('ff000000-0000-0001-0000-000000000000' AS UUID) > CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) > CAST('ff000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + + // check MSB side takes precedent over LSB side + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) > CAST('00000000-0000-0000-0000-000000000001' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) > CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('ff000000-0000-0000-0000-000000000001' AS UUID) > CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) > CAST('ff000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); + + // ======================== + // GTE + // equality + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) >= CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + // check bytes in LSB + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) >= CAST('00000000-0000-0000-0000-000000000001' AS UUID)", BOOLEAN, false); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) >= CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-ff00-000000000001' AS UUID) >= CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) >= CAST('00000000-0000-0000-ff00-000000000000' AS UUID)", BOOLEAN, false); + + // check bytes in MSB + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) >= CAST('00000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID) >= CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('ff000000-0000-0001-0000-000000000000' AS UUID) >= CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) >= CAST('ff000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + + // check MSB side takes precedent over LSB side + assertFunction("CAST('00000000-0000-0001-0000-000000000000' AS UUID) >= CAST('00000000-0000-0000-0000-000000000001' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) >= CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, false); + assertFunction("CAST('ff000000-0000-0000-0000-000000000001' AS UUID) >= CAST('00000000-0000-0001-0000-000000000000' AS UUID)", BOOLEAN, true); + assertFunction("CAST('00000000-0000-0000-0000-000000000001' AS UUID) >= CAST('ff000000-0000-0000-0000-000000000000' AS UUID)", BOOLEAN, false); } @Test diff --git a/presto-main/src/test/java/com/facebook/presto/type/TestUuidType.java b/presto-main/src/test/java/com/facebook/presto/type/TestUuidType.java index 40de2f70d981..5f693a3f0f99 100644 --- a/presto-main/src/test/java/com/facebook/presto/type/TestUuidType.java +++ b/presto-main/src/test/java/com/facebook/presto/type/TestUuidType.java @@ -21,6 +21,7 @@ import static com.facebook.presto.common.type.UuidType.UUID; import static com.facebook.presto.type.UuidOperators.castFromVarcharToUuid; +import static io.airlift.slice.SizeOf.SIZE_OF_LONG; import static io.airlift.slice.Slices.utf8Slice; import static org.testng.Assert.assertEquals; @@ -46,7 +47,7 @@ public static Block createTestBlock() protected Object getGreaterValue(Object value) { Slice slice = (Slice) value; - return Slices.wrappedLongArray(slice.getLong(0), slice.getLong(1) + 1); + return Slices.wrappedLongArray(slice.getLong(0), slice.getLong(SIZE_OF_LONG) + 1); } @Override diff --git a/presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java b/presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java index 48ea580d154e..01214d57d70e 100644 --- a/presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java +++ b/presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java @@ -59,6 +59,7 @@ import static com.fasterxml.jackson.databind.SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS; import static io.airlift.slice.Slices.utf8Slice; import static io.airlift.slice.Slices.wrappedLongArray; +import static java.lang.Long.reverseBytes; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; @@ -196,6 +197,8 @@ private ReadMapping uuidColumnMapping() private static Slice uuidSlice(UUID uuid) { - return wrappedLongArray(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); + return wrappedLongArray( + reverseBytes(uuid.getMostSignificantBits()), + reverseBytes(uuid.getLeastSignificantBits())); } }