From 33d4a2a9498e641e9adad90334ec0d33e990c8cc Mon Sep 17 00:00:00 2001 From: praveenkrishna Date: Tue, 7 May 2019 19:20:01 +0530 Subject: [PATCH] Add UUID type and operators --- .../src/main/sphinx/language/types.rst | 13 ++ .../prestosql/metadata/FunctionRegistry.java | 3 + .../java/io/prestosql/type/TypeRegistry.java | 2 + .../java/io/prestosql/type/UuidOperators.java | 200 ++++++++++++++++++ .../main/java/io/prestosql/type/UuidType.java | 162 ++++++++++++++ .../io/prestosql/type/TestUuidOperators.java | 130 ++++++++++++ .../java/io/prestosql/type/TestUuidType.java | 63 ++++++ .../io/prestosql/spi/type/StandardTypes.java | 1 + 8 files changed, 574 insertions(+) create mode 100644 presto-main/src/main/java/io/prestosql/type/UuidOperators.java create mode 100644 presto-main/src/main/java/io/prestosql/type/UuidType.java create mode 100644 presto-main/src/test/java/io/prestosql/type/TestUuidOperators.java create mode 100644 presto-main/src/test/java/io/prestosql/type/TestUuidType.java diff --git a/presto-docs/src/main/sphinx/language/types.rst b/presto-docs/src/main/sphinx/language/types.rst index 9dbc38e1deb4..3ab88a8dfd3a 100644 --- a/presto-docs/src/main/sphinx/language/types.rst +++ b/presto-docs/src/main/sphinx/language/types.rst @@ -237,6 +237,19 @@ Network Address Examples: ``IPADDRESS '10.0.0.1'``, ``IPADDRESS '2001:db8::1'`` +UUID +---- + +.. _uuid_type: + +``UUID`` +^^^^^^^^ + + This type represents a UUID (Universally Unique IDentifier), also known as a + GUID (Globally Unique IDentifier), using the format defined in :rfc:`4122`. + + Example: ``UUID '12151fd2-7586-11e9-8f9e-2a86e4085a59'`` + HyperLogLog ----------- diff --git a/presto-main/src/main/java/io/prestosql/metadata/FunctionRegistry.java b/presto-main/src/main/java/io/prestosql/metadata/FunctionRegistry.java index cbc18931fd31..5ebeb53514b8 100644 --- a/presto-main/src/main/java/io/prestosql/metadata/FunctionRegistry.java +++ b/presto-main/src/main/java/io/prestosql/metadata/FunctionRegistry.java @@ -192,6 +192,7 @@ import io.prestosql.type.TinyintOperators; import io.prestosql.type.TypeRegistry; import io.prestosql.type.UnknownOperators; +import io.prestosql.type.UuidOperators; import io.prestosql.type.VarbinaryOperators; import io.prestosql.type.VarcharOperators; import io.prestosql.type.setdigest.BuildSetDigestAggregation; @@ -532,6 +533,8 @@ public FunctionRegistry(TypeManager typeManager, BlockEncodingSerde blockEncodin .scalars(QuantileDigestOperators.class) .scalars(IpAddressOperators.class) .scalar(IpAddressOperators.IpAddressDistinctFromOperator.class) + .scalars(UuidOperators.class) + .scalar(UuidOperators.UuidDistinctFromOperator.class) .scalars(LikeFunctions.class) .scalars(ArrayFunctions.class) .scalars(HmacFunctions.class) diff --git a/presto-main/src/main/java/io/prestosql/type/TypeRegistry.java b/presto-main/src/main/java/io/prestosql/type/TypeRegistry.java index 4f831d0142d4..ec814e7a4f03 100644 --- a/presto-main/src/main/java/io/prestosql/type/TypeRegistry.java +++ b/presto-main/src/main/java/io/prestosql/type/TypeRegistry.java @@ -90,6 +90,7 @@ import static io.prestosql.type.Re2JRegexpType.RE2J_REGEXP; import static io.prestosql.type.RowParametricType.ROW; import static io.prestosql.type.UnknownType.UNKNOWN; +import static io.prestosql.type.UuidType.UUID; import static io.prestosql.type.setdigest.SetDigestType.SET_DIGEST; import static java.util.Objects.requireNonNull; @@ -147,6 +148,7 @@ public TypeRegistry(Set types, FeaturesConfig featuresConfig) addType(JSON); addType(CODE_POINTS); addType(IPADDRESS); + addType(UUID); addParametricType(VarcharParametricType.VARCHAR); addParametricType(CharParametricType.CHAR); addParametricType(DecimalParametricType.DECIMAL); diff --git a/presto-main/src/main/java/io/prestosql/type/UuidOperators.java b/presto-main/src/main/java/io/prestosql/type/UuidOperators.java new file mode 100644 index 000000000000..355421ff1e41 --- /dev/null +++ b/presto-main/src/main/java/io/prestosql/type/UuidOperators.java @@ -0,0 +1,200 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.type; + +import io.airlift.slice.Slice; +import io.airlift.slice.XxHash64; +import io.prestosql.spi.PrestoException; +import io.prestosql.spi.block.Block; +import io.prestosql.spi.function.BlockIndex; +import io.prestosql.spi.function.BlockPosition; +import io.prestosql.spi.function.IsNull; +import io.prestosql.spi.function.LiteralParameters; +import io.prestosql.spi.function.ScalarOperator; +import io.prestosql.spi.function.SqlNullable; +import io.prestosql.spi.function.SqlType; +import io.prestosql.spi.type.StandardTypes; + +import static io.airlift.slice.SizeOf.SIZE_OF_LONG; +import static io.airlift.slice.Slices.utf8Slice; +import static io.airlift.slice.Slices.wrappedBuffer; +import static io.airlift.slice.Slices.wrappedLongArray; +import static io.prestosql.spi.StandardErrorCode.INVALID_CAST_ARGUMENT; +import static io.prestosql.spi.function.OperatorType.BETWEEN; +import static io.prestosql.spi.function.OperatorType.CAST; +import static io.prestosql.spi.function.OperatorType.EQUAL; +import static io.prestosql.spi.function.OperatorType.GREATER_THAN; +import static io.prestosql.spi.function.OperatorType.GREATER_THAN_OR_EQUAL; +import static io.prestosql.spi.function.OperatorType.HASH_CODE; +import static io.prestosql.spi.function.OperatorType.INDETERMINATE; +import static io.prestosql.spi.function.OperatorType.IS_DISTINCT_FROM; +import static io.prestosql.spi.function.OperatorType.LESS_THAN; +import static io.prestosql.spi.function.OperatorType.LESS_THAN_OR_EQUAL; +import static io.prestosql.spi.function.OperatorType.NOT_EQUAL; +import static io.prestosql.spi.function.OperatorType.XX_HASH_64; +import static io.prestosql.type.UuidType.UUID; + +public final class UuidOperators +{ + private UuidOperators() {} + + @ScalarOperator(EQUAL) + @SqlType(StandardTypes.BOOLEAN) + @SqlNullable + public static Boolean equal(@SqlType(StandardTypes.UUID) Slice left, @SqlType(StandardTypes.UUID) Slice right) + { + return left.equals(right); + } + + @ScalarOperator(NOT_EQUAL) + @SqlType(StandardTypes.BOOLEAN) + @SqlNullable + public static Boolean notEqual(@SqlType(StandardTypes.UUID) Slice left, @SqlType(StandardTypes.UUID) Slice right) + { + return !left.equals(right); + } + + @ScalarOperator(LESS_THAN) + @SqlType(StandardTypes.BOOLEAN) + public static boolean lessThan(@SqlType(StandardTypes.UUID) Slice left, @SqlType(StandardTypes.UUID) Slice right) + { + return left.compareTo(right) < 0; + } + + @ScalarOperator(LESS_THAN_OR_EQUAL) + @SqlType(StandardTypes.BOOLEAN) + public static boolean lessThanOrEqual(@SqlType(StandardTypes.UUID) Slice left, @SqlType(StandardTypes.UUID) Slice right) + { + return left.compareTo(right) <= 0; + } + + @ScalarOperator(GREATER_THAN) + @SqlType(StandardTypes.BOOLEAN) + public static boolean greaterThan(@SqlType(StandardTypes.UUID) Slice left, @SqlType(StandardTypes.UUID) Slice right) + { + return left.compareTo(right) > 0; + } + + @ScalarOperator(GREATER_THAN_OR_EQUAL) + @SqlType(StandardTypes.BOOLEAN) + public static boolean greaterThanOrEqual(@SqlType(StandardTypes.UUID) Slice left, @SqlType(StandardTypes.UUID) Slice right) + { + return left.compareTo(right) >= 0; + } + + @ScalarOperator(BETWEEN) + @SqlType(StandardTypes.BOOLEAN) + public static boolean between(@SqlType(StandardTypes.UUID) Slice value, @SqlType(StandardTypes.UUID) Slice min, @SqlType(StandardTypes.UUID) Slice max) + { + return min.compareTo(value) <= 0 && value.compareTo(max) <= 0; + } + + @ScalarOperator(HASH_CODE) + @SqlType(StandardTypes.BIGINT) + public static long hashCode(@SqlType(StandardTypes.UUID) Slice value) + { + return XxHash64.hash(value); + } + + @ScalarOperator(XX_HASH_64) + @SqlType(StandardTypes.BIGINT) + public static long xxHash64(@SqlType(StandardTypes.UUID) Slice value) + { + return XxHash64.hash(value); + } + + @LiteralParameters("x") + @ScalarOperator(CAST) + @SqlType(StandardTypes.UUID) + public static Slice castFromVarcharToUuid(@SqlType("varchar(x)") Slice slice) + { + try { + java.util.UUID uuid = java.util.UUID.fromString(slice.toStringUtf8()); + if (slice.length() == 36) { + return wrappedLongArray(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); + } + throw new PrestoException(INVALID_CAST_ARGUMENT, "Invalid UUID string length: " + slice.length()); + } + catch (IllegalArgumentException e) { + throw new PrestoException(INVALID_CAST_ARGUMENT, "Cannot cast value to UUID: " + slice.toStringUtf8()); + } + } + + @ScalarOperator(CAST) + @SqlType(StandardTypes.VARCHAR) + public static Slice castFromUuidToVarchar(@SqlType(StandardTypes.UUID) Slice slice) + { + return utf8Slice(new java.util.UUID(slice.getLong(0), slice.getLong(SIZE_OF_LONG)).toString()); + } + + @ScalarOperator(CAST) + @SqlType(StandardTypes.UUID) + public static Slice castFromVarbinaryToUuid(@SqlType("varbinary") Slice slice) + { + if (slice.length() == 16) { + return slice; + } + throw new PrestoException(INVALID_CAST_ARGUMENT, "Invalid UUID binary length: " + slice.length()); + } + + @ScalarOperator(CAST) + @SqlType(StandardTypes.VARBINARY) + public static Slice castFromUuidToVarbinary(@SqlType(StandardTypes.UUID) Slice slice) + { + return wrappedBuffer(slice.getBytes()); + } + + @ScalarOperator(IS_DISTINCT_FROM) + public static class UuidDistinctFromOperator + { + @SqlType(StandardTypes.BOOLEAN) + public static boolean isDistinctFrom( + @SqlType(StandardTypes.UUID) Slice left, + @IsNull boolean leftNull, + @SqlType(StandardTypes.UUID) Slice right, + @IsNull boolean rightNull) + { + if (leftNull != rightNull) { + return true; + } + if (leftNull) { + return false; + } + return notEqual(left, right); + } + + @SqlType(StandardTypes.BOOLEAN) + public static boolean isDistinctFrom( + @BlockPosition @SqlType(value = StandardTypes.UUID, nativeContainerType = Slice.class) Block left, + @BlockIndex int leftPosition, + @BlockPosition @SqlType(value = StandardTypes.UUID, nativeContainerType = Slice.class) Block right, + @BlockIndex int rightPosition) + { + if (left.isNull(leftPosition) != right.isNull(rightPosition)) { + return true; + } + if (left.isNull(leftPosition)) { + return false; + } + return left.compareTo(leftPosition, 0, UUID.getFixedSize(), right, rightPosition, 0, UUID.getFixedSize()) != 0; + } + } + + @ScalarOperator(INDETERMINATE) + @SqlType(StandardTypes.BOOLEAN) + public static boolean indeterminate(@SqlType(StandardTypes.UUID) Slice value, @IsNull boolean isNull) + { + return isNull; + } +} diff --git a/presto-main/src/main/java/io/prestosql/type/UuidType.java b/presto-main/src/main/java/io/prestosql/type/UuidType.java new file mode 100644 index 000000000000..08df1d405535 --- /dev/null +++ b/presto-main/src/main/java/io/prestosql/type/UuidType.java @@ -0,0 +1,162 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.type; + +import io.airlift.slice.Slice; +import io.airlift.slice.Slices; +import io.airlift.slice.XxHash64; +import io.prestosql.spi.block.Block; +import io.prestosql.spi.block.BlockBuilder; +import io.prestosql.spi.block.BlockBuilderStatus; +import io.prestosql.spi.block.Int128ArrayBlockBuilder; +import io.prestosql.spi.block.PageBuilderStatus; +import io.prestosql.spi.connector.ConnectorSession; +import io.prestosql.spi.type.AbstractType; +import io.prestosql.spi.type.FixedWidthType; +import io.prestosql.spi.type.StandardTypes; + +import java.util.UUID; + +import static io.airlift.slice.SizeOf.SIZE_OF_LONG; +import static io.prestosql.spi.block.Int128ArrayBlock.INT128_BYTES; +import static io.prestosql.spi.type.TypeSignature.parseTypeSignature; + +public class UuidType + extends AbstractType + implements FixedWidthType +{ + public static final UuidType UUID = new UuidType(); + + private UuidType() + { + super(parseTypeSignature(StandardTypes.UUID), Slice.class); + } + + @Override + public int getFixedSize() + { + return INT128_BYTES; + } + + @Override + public BlockBuilder createBlockBuilder(BlockBuilderStatus blockBuilderStatus, int expectedEntries, int expectedBytesPerEntry) + { + int maxBlockSizeInBytes; + if (blockBuilderStatus == null) { + maxBlockSizeInBytes = PageBuilderStatus.DEFAULT_MAX_PAGE_SIZE_IN_BYTES; + } + else { + maxBlockSizeInBytes = blockBuilderStatus.getMaxPageSizeInBytes(); + } + return new Int128ArrayBlockBuilder( + blockBuilderStatus, + Math.min(expectedEntries, maxBlockSizeInBytes / getFixedSize())); + } + + @Override + public BlockBuilder createBlockBuilder(BlockBuilderStatus blockBuilderStatus, int expectedEntries) + { + return createBlockBuilder(blockBuilderStatus, expectedEntries, getFixedSize()); + } + + @Override + public BlockBuilder createFixedSizeBlockBuilder(int positionCount) + { + return new Int128ArrayBlockBuilder(null, positionCount); + } + + @Override + public boolean isComparable() + { + return true; + } + + @Override + public boolean isOrderable() + { + return true; + } + + @Override + public boolean equalTo(Block leftBlock, int leftPosition, Block rightBlock, int rightPosition) + { + return leftBlock.getLong(leftPosition, SIZE_OF_LONG) == rightBlock.getLong(rightPosition, SIZE_OF_LONG) && + leftBlock.getLong(leftPosition, 0) == rightBlock.getLong(rightPosition, 0); + } + + @Override + public int compareTo(Block leftBlock, int leftPosition, Block rightBlock, int rightPosition) + { + // compare high order bits + int compare = Long.compare(leftBlock.getLong(leftPosition, SIZE_OF_LONG), rightBlock.getLong(rightPosition, SIZE_OF_LONG)); + if (compare != 0) { + return compare; + } + // compare low order bits + return Long.compare(leftBlock.getLong(leftPosition, 0), rightBlock.getLong(rightPosition, 0)); + } + + @Override + public long hash(Block block, int position) + { + return XxHash64.hash(getSlice(block, position)); + } + + @Override + public Object getObjectValue(ConnectorSession session, Block block, int position) + { + if (block.isNull(position)) { + return null; + } + return new UUID(block.getLong(position, 0), block.getLong(position, SIZE_OF_LONG)).toString(); + } + + @Override + public void appendTo(Block block, int position, BlockBuilder blockBuilder) + { + if (block.isNull(position)) { + blockBuilder.appendNull(); + } + else { + blockBuilder.writeLong(block.getLong(position, 0)); + blockBuilder.writeLong(block.getLong(position, SIZE_OF_LONG)); + blockBuilder.closeEntry(); + } + } + + @Override + public void writeSlice(BlockBuilder blockBuilder, Slice value) + { + writeSlice(blockBuilder, value, 0, value.length()); + } + + @Override + public void writeSlice(BlockBuilder blockBuilder, Slice value, int offset, int length) + { + if (length != INT128_BYTES) { + throw new IllegalStateException("Expected entry size to be exactly " + INT128_BYTES + " but was " + length); + } + blockBuilder.writeLong(value.getLong(offset)); + blockBuilder.writeLong(value.getLong(offset + SIZE_OF_LONG)); + blockBuilder.closeEntry(); + } + + @Override + public final Slice getSlice(Block block, int position) + { + return Slices.wrappedLongArray( + block.getLong(position, 0), + block.getLong(position, SIZE_OF_LONG)); + } +} diff --git a/presto-main/src/test/java/io/prestosql/type/TestUuidOperators.java b/presto-main/src/test/java/io/prestosql/type/TestUuidOperators.java new file mode 100644 index 000000000000..b93501a60ba8 --- /dev/null +++ b/presto-main/src/test/java/io/prestosql/type/TestUuidOperators.java @@ -0,0 +1,130 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.type; + +import io.prestosql.operator.scalar.AbstractTestFunctions; +import io.prestosql.spi.block.Block; +import io.prestosql.spi.block.BlockBuilder; +import io.prestosql.spi.type.SqlVarbinary; +import org.testng.annotations.Test; + +import static com.google.common.io.BaseEncoding.base16; +import static io.airlift.slice.Slices.utf8Slice; +import static io.prestosql.spi.function.OperatorType.HASH_CODE; +import static io.prestosql.spi.function.OperatorType.INDETERMINATE; +import static io.prestosql.spi.type.BigintType.BIGINT; +import static io.prestosql.spi.type.BooleanType.BOOLEAN; +import static io.prestosql.spi.type.VarbinaryType.VARBINARY; +import static io.prestosql.spi.type.VarcharType.VARCHAR; +import static io.prestosql.type.UuidOperators.castFromVarcharToUuid; +import static io.prestosql.type.UuidType.UUID; + +public class TestUuidOperators + extends AbstractTestFunctions +{ + @Test + public void testVarcharToUUIDCast() + { + assertFunction("CAST('00000000-0000-0000-0000-000000000000' AS UUID)", UUID, "00000000-0000-0000-0000-000000000000"); + assertFunction("CAST('12151fd2-7586-11e9-8f9e-2a86e4085a59' AS UUID)", UUID, "12151fd2-7586-11e9-8f9e-2a86e4085a59"); + assertFunction("CAST('300433ad-b0a1-3b53-a977-91cab582458e' AS UUID)", UUID, "300433ad-b0a1-3b53-a977-91cab582458e"); + assertFunction("CAST('d3074e99-de12-4b8c-a2a1-b7faf79faba6' AS UUID)", UUID, "d3074e99-de12-4b8c-a2a1-b7faf79faba6"); + assertFunction("CAST('dfa7eaf8-6a26-5749-8d36-336025df74e8' AS UUID)", UUID, "dfa7eaf8-6a26-5749-8d36-336025df74e8"); + assertFunction("CAST('12151FD2-7586-11E9-8F9E-2A86E4085A59' AS UUID)", UUID, "12151fd2-7586-11e9-8f9e-2a86e4085a59"); + assertInvalidCast("CAST('1-2-3-4-1' AS UUID)", "Invalid UUID string length: 9"); + assertInvalidCast("CAST('12151fd217586211e938f9e42a86e4085a59' AS UUID)", "Cannot cast value to UUID: 12151fd217586211e938f9e42a86e4085a59"); + } + + @Test + public void testUUIDToVarcharCast() + { + assertFunction("CAST(UUID 'd3074e99-de12-4b8c-a2a1-b7faf79faba6' AS VARCHAR)", VARCHAR, "d3074e99-de12-4b8c-a2a1-b7faf79faba6"); + assertFunction("CAST(CAST('d3074e99-de12-4b8c-a2a1-b7faf79faba6' AS UUID) AS VARCHAR)", VARCHAR, "d3074e99-de12-4b8c-a2a1-b7faf79faba6"); + } + + @Test + 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"); + assertInvalidCast("CAST(x'f000001100' AS UUID)", "Invalid UUID binary length: 5"); + } + + @Test + 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"))); + } + + @Test + public void testEquals() + { + assertFunction("UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' = UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0'", BOOLEAN, true); + assertFunction("CAST('6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' AS UUID) = CAST('6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' AS UUID)", BOOLEAN, true); + } + + @Test + public void testDistinctFrom() + { + assertFunction("UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' IS DISTINCT FROM UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0'", BOOLEAN, false); + assertFunction("CAST(NULL AS UUID) IS DISTINCT FROM CAST(NULL AS UUID)", BOOLEAN, false); + assertFunction("UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' IS DISTINCT FROM UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a1'", BOOLEAN, true); + assertFunction("UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' IS DISTINCT FROM CAST(NULL AS UUID)", BOOLEAN, true); + assertFunction("CAST(NULL AS UUID) IS DISTINCT FROM UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0'", BOOLEAN, true); + } + + @Test + public void testNotEquals() + { + assertFunction("UUID '6b5f5b65-67e4-43b0-8ee3-586cd49f58a0' != UUID '12151fd2-7586-11e9-8f9e-2a86e4085a59'", BOOLEAN, true); + assertFunction("CAST('12151fd2-7586-11e9-8f9e-2a86e4085a59' AS UUID) != UUID '12151fd2-7586-11e9-8f9e-2a86e4085a59'", BOOLEAN, false); + } + + @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); + + 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); + } + + @Test + public void testIndeterminate() + { + assertOperator(INDETERMINATE, "CAST(null AS UUID)", BOOLEAN, true); + assertOperator(INDETERMINATE, "UUID '12151fd2-7586-11e9-8f9e-2a86e4085a59'", BOOLEAN, false); + } + + @Test + public void testHash() + { + assertOperator(HASH_CODE, "CAST(null AS UUID)", BIGINT, null); + assertOperator(HASH_CODE, "UUID '12151fd2-7586-11e9-8f9e-2a86e4085a59'", BIGINT, hashFromType("12151fd2-7586-11e9-8f9e-2a86e4085a59")); + } + + private static long hashFromType(String uuidString) + { + BlockBuilder blockBuilder = UUID.createBlockBuilder(null, 1); + UUID.writeSlice(blockBuilder, castFromVarcharToUuid(utf8Slice(uuidString))); + Block block = blockBuilder.build(); + return UUID.hash(block, 0); + } +} diff --git a/presto-main/src/test/java/io/prestosql/type/TestUuidType.java b/presto-main/src/test/java/io/prestosql/type/TestUuidType.java new file mode 100644 index 000000000000..714ae9270bae --- /dev/null +++ b/presto-main/src/test/java/io/prestosql/type/TestUuidType.java @@ -0,0 +1,63 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.type; + +import io.airlift.slice.Slice; +import io.airlift.slice.Slices; +import io.prestosql.spi.block.Block; +import io.prestosql.spi.block.BlockBuilder; +import org.testng.annotations.Test; + +import static io.airlift.slice.Slices.utf8Slice; +import static io.prestosql.type.UuidOperators.castFromVarcharToUuid; +import static io.prestosql.type.UuidType.UUID; +import static org.testng.Assert.assertEquals; + +public class TestUuidType + extends AbstractTestType +{ + public TestUuidType() + { + super(UUID, String.class, createTestBlock()); + } + + public static Block createTestBlock() + { + BlockBuilder blockBuilder = UUID.createBlockBuilder(null, 1); + for (int i = 0; i < 10; i++) { + String uuid = "6b5f5b65-67e4-43b0-8ee3-586cd49f58a" + i; + UUID.writeSlice(blockBuilder, castFromVarcharToUuid(utf8Slice(uuid))); + } + return blockBuilder.build(); + } + + @Override + protected Object getGreaterValue(Object value) + { + Slice slice = (Slice) value; + return Slices.wrappedLongArray(slice.getLong(0), slice.getLong(1) + 1); + } + + @Override + protected Object getNonNullValue() + { + return Slices.wrappedLongArray(0, 0); + } + + @Test + public void testDisplayName() + { + assertEquals(UUID.getDisplayName(), "uuid"); + } +} diff --git a/presto-spi/src/main/java/io/prestosql/spi/type/StandardTypes.java b/presto-spi/src/main/java/io/prestosql/spi/type/StandardTypes.java index ecfbf2f8d75c..73640e66a395 100644 --- a/presto-spi/src/main/java/io/prestosql/spi/type/StandardTypes.java +++ b/presto-spi/src/main/java/io/prestosql/spi/type/StandardTypes.java @@ -43,6 +43,7 @@ public final class StandardTypes public static final String IPADDRESS = "ipaddress"; public static final String GEOMETRY = "Geometry"; public static final String BING_TILE = "BingTile"; + public static final String UUID = "uuid"; private StandardTypes() {} }