/* * 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 com.facebook.presto.operator.aggregation; import com.facebook.presto.metadata.MetadataManager; import com.facebook.presto.metadata.Signature; import com.facebook.presto.spi.block.Block; import com.facebook.presto.spi.type.BigintType; import com.facebook.presto.spi.type.BooleanType; import com.facebook.presto.spi.type.DecimalType; import com.facebook.presto.spi.type.DoubleType; import com.facebook.presto.spi.type.SqlVarbinary; import com.facebook.presto.spi.type.Type; import com.facebook.presto.spi.type.VarbinaryType; import com.facebook.presto.spi.type.VarcharType; import com.facebook.presto.type.ArrayType; import org.testng.annotations.Test; import static com.facebook.presto.block.BlockAssertions.createArrayBigintBlock; import static com.facebook.presto.block.BlockAssertions.createBooleansBlock; import static com.facebook.presto.block.BlockAssertions.createDoublesBlock; import static com.facebook.presto.block.BlockAssertions.createLongDecimalsBlock; import static com.facebook.presto.block.BlockAssertions.createLongsBlock; import static com.facebook.presto.block.BlockAssertions.createShortDecimalsBlock; import static com.facebook.presto.block.BlockAssertions.createStringsBlock; import static com.facebook.presto.metadata.FunctionKind.AGGREGATE; import static com.facebook.presto.operator.aggregation.AggregationTestUtils.assertAggregation; import static com.facebook.presto.operator.aggregation.ChecksumAggregationFunction.PRIME64; import static com.facebook.presto.spi.type.StandardTypes.BIGINT; import static com.facebook.presto.spi.type.StandardTypes.BOOLEAN; import static com.facebook.presto.spi.type.StandardTypes.DOUBLE; import static com.facebook.presto.spi.type.StandardTypes.VARBINARY; import static com.facebook.presto.spi.type.StandardTypes.VARCHAR; import static com.facebook.presto.spi.type.TypeSignature.parseTypeSignature; import static io.airlift.slice.Slices.wrappedLongArray; import static java.util.Arrays.asList; public class TestChecksumAggregation { private static final MetadataManager metadata = MetadataManager.createTestMetadataManager(); @Test public void testEmpty() throws Exception { InternalAggregationFunction booleanAgg = metadata.getFunctionRegistry().getAggregateFunctionImplementation( new Signature("checksum", AGGREGATE, parseTypeSignature(VARBINARY), parseTypeSignature(BOOLEAN))); assertAggregation(booleanAgg, null, createBooleansBlock()); } @Test public void testBoolean() throws Exception { InternalAggregationFunction booleanAgg = metadata.getFunctionRegistry().getAggregateFunctionImplementation( new Signature("checksum", AGGREGATE, parseTypeSignature(VARBINARY), parseTypeSignature(BOOLEAN))); Block block = createBooleansBlock(null, null, true, false, false); assertAggregation(booleanAgg, expectedChecksum(BooleanType.BOOLEAN, block), block); } @Test public void testLong() throws Exception { InternalAggregationFunction longAgg = metadata.getFunctionRegistry().getAggregateFunctionImplementation( new Signature("checksum", AGGREGATE, parseTypeSignature(VARBINARY), parseTypeSignature(BIGINT))); Block block = createLongsBlock(null, 1L, 2L, 100L, null, Long.MAX_VALUE, Long.MIN_VALUE); assertAggregation(longAgg, expectedChecksum(BigintType.BIGINT, block), block); } @Test public void testDouble() throws Exception { InternalAggregationFunction doubleAgg = metadata.getFunctionRegistry().getAggregateFunctionImplementation( new Signature("checksum", AGGREGATE, parseTypeSignature(VARBINARY), parseTypeSignature(DOUBLE))); Block block = createDoublesBlock(null, 2.0, null, 3.0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NaN); assertAggregation(doubleAgg, expectedChecksum(DoubleType.DOUBLE, block), block); } @Test public void testString() throws Exception { InternalAggregationFunction stringAgg = metadata.getFunctionRegistry().getAggregateFunctionImplementation( new Signature("checksum", AGGREGATE, parseTypeSignature(VARBINARY), parseTypeSignature(VARCHAR))); Block block = createStringsBlock("a", "a", null, "b", "c"); assertAggregation(stringAgg, expectedChecksum(VarcharType.VARCHAR, block), block); } @Test public void testShortDecimal() throws Exception { InternalAggregationFunction decimalAgg = metadata.getFunctionRegistry().getAggregateFunctionImplementation(new Signature("checksum", AGGREGATE, parseTypeSignature(VARBINARY), parseTypeSignature("decimal(10,2)"))); Block block = createShortDecimalsBlock("11.11", "22.22", null, "33.33", "44.44"); DecimalType shortDecimalType = DecimalType.createDecimalType(1); assertAggregation(decimalAgg, expectedChecksum(shortDecimalType, block), block); } @Test public void testLongDecimal() throws Exception { InternalAggregationFunction decimalAgg = metadata.getFunctionRegistry().getAggregateFunctionImplementation(new Signature("checksum", AGGREGATE, parseTypeSignature(VARBINARY), parseTypeSignature("decimal(19,2)"))); Block block = createLongDecimalsBlock("11.11", "22.22", null, "33.33", "44.44"); DecimalType longDecimalType = DecimalType.createDecimalType(19); assertAggregation(decimalAgg, expectedChecksum(longDecimalType, block), block); } @Test public void testArray() throws Exception { ArrayType arrayType = new ArrayType(BigintType.BIGINT); InternalAggregationFunction stringAgg = metadata.getFunctionRegistry().getAggregateFunctionImplementation(new Signature("checksum", AGGREGATE, VarbinaryType.VARBINARY.getTypeSignature(), arrayType.getTypeSignature())); Block block = createArrayBigintBlock(asList(null, asList(1L, 2L), asList(3L, 4L), asList(5L, 6L))); assertAggregation(stringAgg, expectedChecksum(arrayType, block), block); } private static SqlVarbinary expectedChecksum(Type type, Block block) { long result = 0; for (int i = 0; i < block.getPositionCount(); i++) { if (block.isNull(i)) { result += PRIME64; } else { result += type.hash(block, i) * PRIME64; } } return new SqlVarbinary(wrappedLongArray(result).getBytes()); } }