/* * 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.sql.planner; import com.facebook.presto.metadata.Metadata; import com.facebook.presto.metadata.MetadataManager; import com.facebook.presto.spi.predicate.Domain; import com.facebook.presto.spi.predicate.Range; import com.facebook.presto.spi.predicate.TupleDomain; import com.facebook.presto.spi.predicate.ValueSet; import com.facebook.presto.spi.type.DecimalType; import com.facebook.presto.spi.type.Type; import com.facebook.presto.sql.planner.DomainTranslator.ExtractionResult; import com.facebook.presto.sql.tree.BetweenPredicate; import com.facebook.presto.sql.tree.Cast; import com.facebook.presto.sql.tree.ComparisonExpression; import com.facebook.presto.sql.tree.ComparisonExpressionType; import com.facebook.presto.sql.tree.DoubleLiteral; import com.facebook.presto.sql.tree.Expression; import com.facebook.presto.sql.tree.FunctionCall; import com.facebook.presto.sql.tree.GenericLiteral; import com.facebook.presto.sql.tree.InListExpression; import com.facebook.presto.sql.tree.InPredicate; import com.facebook.presto.sql.tree.IsNullPredicate; import com.facebook.presto.sql.tree.Literal; import com.facebook.presto.sql.tree.LongLiteral; import com.facebook.presto.sql.tree.NotExpression; import com.facebook.presto.sql.tree.NullLiteral; import com.facebook.presto.sql.tree.QualifiedName; import com.facebook.presto.sql.tree.StringLiteral; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.io.BaseEncoding; import io.airlift.slice.Slice; import io.airlift.slice.Slices; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.List; import java.util.Map; import static com.facebook.presto.SessionTestUtils.TEST_SESSION; import static com.facebook.presto.metadata.FunctionRegistry.getMagicLiteralFunctionSignature; import static com.facebook.presto.spi.predicate.TupleDomain.withColumnDomains; import static com.facebook.presto.spi.type.BigintType.BIGINT; import static com.facebook.presto.spi.type.BooleanType.BOOLEAN; import static com.facebook.presto.spi.type.CharType.createCharType; import static com.facebook.presto.spi.type.DateType.DATE; import static com.facebook.presto.spi.type.DecimalType.createDecimalType; import static com.facebook.presto.spi.type.Decimals.encodeScaledValue; import static com.facebook.presto.spi.type.DoubleType.DOUBLE; import static com.facebook.presto.spi.type.HyperLogLogType.HYPER_LOG_LOG; import static com.facebook.presto.spi.type.IntegerType.INTEGER; import static com.facebook.presto.spi.type.RealType.REAL; import static com.facebook.presto.spi.type.SmallintType.SMALLINT; import static com.facebook.presto.spi.type.TimestampType.TIMESTAMP; import static com.facebook.presto.spi.type.TinyintType.TINYINT; import static com.facebook.presto.spi.type.VarbinaryType.VARBINARY; import static com.facebook.presto.spi.type.VarcharType.VARCHAR; import static com.facebook.presto.sql.ExpressionUtils.and; import static com.facebook.presto.sql.ExpressionUtils.or; import static com.facebook.presto.sql.planner.LiteralInterpreter.toExpression; import static com.facebook.presto.sql.tree.BooleanLiteral.FALSE_LITERAL; import static com.facebook.presto.sql.tree.BooleanLiteral.TRUE_LITERAL; import static com.facebook.presto.sql.tree.ComparisonExpressionType.EQUAL; import static com.facebook.presto.sql.tree.ComparisonExpressionType.GREATER_THAN; import static com.facebook.presto.sql.tree.ComparisonExpressionType.GREATER_THAN_OR_EQUAL; import static com.facebook.presto.sql.tree.ComparisonExpressionType.IS_DISTINCT_FROM; import static com.facebook.presto.sql.tree.ComparisonExpressionType.LESS_THAN; import static com.facebook.presto.sql.tree.ComparisonExpressionType.LESS_THAN_OR_EQUAL; import static com.facebook.presto.sql.tree.ComparisonExpressionType.NOT_EQUAL; import static com.facebook.presto.testing.TestingConnectorSession.SESSION; import static com.facebook.presto.type.ColorType.COLOR; import static io.airlift.slice.Slices.utf8Slice; import static java.lang.String.format; import static java.util.Collections.nCopies; import static java.util.Objects.requireNonNull; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; public class TestDomainTranslator { private static final Metadata METADATA = MetadataManager.createTestMetadataManager(); private static final Symbol C_BIGINT = new Symbol("c_bigint"); private static final Symbol C_DOUBLE = new Symbol("c_double"); private static final Symbol C_VARCHAR = new Symbol("c_varchar"); private static final Symbol C_BOOLEAN = new Symbol("c_boolean"); private static final Symbol C_BIGINT_1 = new Symbol("c_bigint_1"); private static final Symbol C_DOUBLE_1 = new Symbol("c_double_1"); private static final Symbol C_VARCHAR_1 = new Symbol("c_varchar_1"); private static final Symbol C_TIMESTAMP = new Symbol("c_timestamp"); private static final Symbol C_DATE = new Symbol("c_date"); private static final Symbol C_COLOR = new Symbol("c_color"); private static final Symbol C_HYPER_LOG_LOG = new Symbol("c_hyper_log_log"); private static final Symbol C_VARBINARY = new Symbol("c_varbinary"); private static final Symbol C_DECIMAL_26_5 = new Symbol("c_decimal_26_5"); private static final Symbol C_DECIMAL_23_4 = new Symbol("c_decimal_23_4"); private static final Symbol C_INTEGER = new Symbol("c_integer"); private static final Symbol C_CHAR = new Symbol("c_char"); private static final Symbol C_DECIMAL_21_3 = new Symbol("c_decimal_21_3"); private static final Symbol C_DECIMAL_12_2 = new Symbol("c_decimal_12_2"); private static final Symbol C_DECIMAL_6_1 = new Symbol("c_decimal_6_1"); private static final Symbol C_DECIMAL_3_0 = new Symbol("c_decimal_3_0"); private static final Symbol C_DECIMAL_2_0 = new Symbol("c_decimal_2_0"); private static final Symbol C_SMALLINT = new Symbol("c_smallint"); private static final Symbol C_TINYINT = new Symbol("c_tinyint"); private static final Symbol C_REAL = new Symbol("c_real"); private static final Map<Symbol, Type> TYPES = ImmutableMap.<Symbol, Type>builder() .put(C_BIGINT, BIGINT) .put(C_DOUBLE, DOUBLE) .put(C_VARCHAR, VARCHAR) .put(C_BOOLEAN, BOOLEAN) .put(C_BIGINT_1, BIGINT) .put(C_DOUBLE_1, DOUBLE) .put(C_VARCHAR_1, VARCHAR) .put(C_TIMESTAMP, TIMESTAMP) .put(C_DATE, DATE) .put(C_COLOR, COLOR) // Equatable, but not orderable .put(C_HYPER_LOG_LOG, HYPER_LOG_LOG) // Not Equatable or orderable .put(C_VARBINARY, VARBINARY) .put(C_DECIMAL_26_5, createDecimalType(26, 5)) .put(C_DECIMAL_23_4, createDecimalType(23, 4)) .put(C_INTEGER, INTEGER) .put(C_CHAR, createCharType(10)) .put(C_DECIMAL_21_3, createDecimalType(21, 3)) .put(C_DECIMAL_12_2, createDecimalType(12, 2)) .put(C_DECIMAL_6_1, createDecimalType(6, 1)) .put(C_DECIMAL_3_0, createDecimalType(3, 0)) .put(C_DECIMAL_2_0, createDecimalType(2, 0)) .put(C_SMALLINT, SMALLINT) .put(C_TINYINT, TINYINT) .put(C_REAL, REAL) .build(); private static final long TIMESTAMP_VALUE = new DateTime(2013, 3, 30, 1, 5, 0, 0, DateTimeZone.UTC).getMillis(); private static final long DATE_VALUE = new DateTime(2001, 1, 22, 0, 0, 0, 0, DateTimeZone.UTC).getMillis(); private static final long COLOR_VALUE_1 = 1; private static final long COLOR_VALUE_2 = 2; @Test public void testNoneRoundTrip() throws Exception { TupleDomain<Symbol> tupleDomain = TupleDomain.none(); ExtractionResult result = fromPredicate(toPredicate(tupleDomain)); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), tupleDomain); } @Test public void testAllRoundTrip() throws Exception { TupleDomain<Symbol> tupleDomain = TupleDomain.all(); ExtractionResult result = fromPredicate(toPredicate(tupleDomain)); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), tupleDomain); } @Test public void testRoundTrip() throws Exception { TupleDomain<Symbol> tupleDomain = withColumnDomains(ImmutableMap.<Symbol, Domain>builder() .put(C_BIGINT, Domain.singleValue(BIGINT, 1L)) .put(C_DOUBLE, Domain.onlyNull(DOUBLE)) .put(C_VARCHAR, Domain.notNull(VARCHAR)) .put(C_BOOLEAN, Domain.singleValue(BOOLEAN, true)) .put(C_BIGINT_1, Domain.singleValue(BIGINT, 2L)) .put(C_DOUBLE_1, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(DOUBLE, 1.1), Range.equal(DOUBLE, 2.0), Range.range(DOUBLE, 3.0, false, 3.5, true)), true)) .put(C_VARCHAR_1, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(VARCHAR, utf8Slice("2013-01-01")), Range.greaterThan(VARCHAR, utf8Slice("2013-10-01"))), false)) .put(C_TIMESTAMP, Domain.singleValue(TIMESTAMP, TIMESTAMP_VALUE)) .put(C_DATE, Domain.singleValue(DATE, DATE_VALUE)) .put(C_COLOR, Domain.singleValue(COLOR, COLOR_VALUE_1)) .put(C_HYPER_LOG_LOG, Domain.notNull(HYPER_LOG_LOG)) .build()); ExtractionResult result = fromPredicate(toPredicate(tupleDomain)); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), tupleDomain); } @Test public void testInOptimization() throws Exception { Domain testDomain = Domain.create( ValueSet.all(BIGINT) .subtract(ValueSet.ofRanges( Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L), Range.equal(BIGINT, 3L))), false); TupleDomain<Symbol> tupleDomain = withColumnDomains(ImmutableMap.<Symbol, Domain>builder().put(C_BIGINT, testDomain).build()); assertEquals(toPredicate(tupleDomain), not(in(C_BIGINT, ImmutableList.of(1L, 2L, 3L)))); testDomain = Domain.create( ValueSet.ofRanges( Range.lessThan(BIGINT, 4L)).intersect( ValueSet.all(BIGINT) .subtract(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L), Range.equal(BIGINT, 3L)))), false); tupleDomain = withColumnDomains(ImmutableMap.<Symbol, Domain>builder().put(C_BIGINT, testDomain).build()); assertEquals(toPredicate(tupleDomain), and(lessThan(C_BIGINT, bigintLiteral(4L)), not(in(C_BIGINT, ImmutableList.of(1L, 2L, 3L))))); testDomain = Domain.create(ValueSet.ofRanges( Range.range(BIGINT, 1L, true, 3L, true), Range.range(BIGINT, 5L, true, 7L, true), Range.range(BIGINT, 9L, true, 11L, true)), false); tupleDomain = withColumnDomains(ImmutableMap.<Symbol, Domain>builder().put(C_BIGINT, testDomain).build()); assertEquals(toPredicate(tupleDomain), or(between(C_BIGINT, bigintLiteral(1L), bigintLiteral(3L)), (between(C_BIGINT, bigintLiteral(5L), bigintLiteral(7L))), (between(C_BIGINT, bigintLiteral(9L), bigintLiteral(11L))))); testDomain = Domain.create( ValueSet.ofRanges( Range.lessThan(BIGINT, 4L)) .intersect(ValueSet.all(BIGINT) .subtract(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L), Range.equal(BIGINT, 3L)))) .union(ValueSet.ofRanges(Range.range(BIGINT, 7L, true, 9L, true))), false); tupleDomain = withColumnDomains(ImmutableMap.<Symbol, Domain>builder().put(C_BIGINT, testDomain).build()); assertEquals(toPredicate(tupleDomain), or(and(lessThan(C_BIGINT, bigintLiteral(4L)), not(in(C_BIGINT, ImmutableList.of(1L, 2L, 3L)))), between(C_BIGINT, bigintLiteral(7L), bigintLiteral(9L)))); testDomain = Domain.create( ValueSet.ofRanges(Range.lessThan(BIGINT, 4L)) .intersect(ValueSet.all(BIGINT) .subtract(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L), Range.equal(BIGINT, 3L)))) .union(ValueSet.ofRanges(Range.range(BIGINT, 7L, false, 9L, false), Range.range(BIGINT, 11L, false, 13L, false))), false); tupleDomain = withColumnDomains(ImmutableMap.<Symbol, Domain>builder().put(C_BIGINT, testDomain).build()); assertEquals(toPredicate(tupleDomain), or( and(lessThan(C_BIGINT, bigintLiteral(4L)), not(in(C_BIGINT, ImmutableList.of(1L, 2L, 3L)))), and(greaterThan(C_BIGINT, bigintLiteral(7L)), lessThan(C_BIGINT, bigintLiteral(9L))), and(greaterThan(C_BIGINT, bigintLiteral(11L)), lessThan(C_BIGINT, bigintLiteral(13L))))); } @Test public void testToPredicateNone() throws Exception { TupleDomain<Symbol> tupleDomain = withColumnDomains(ImmutableMap.<Symbol, Domain>builder() .put(C_BIGINT, Domain.singleValue(BIGINT, 1L)) .put(C_DOUBLE, Domain.onlyNull(DOUBLE)) .put(C_VARCHAR, Domain.notNull(VARCHAR)) .put(C_BOOLEAN, Domain.none(BOOLEAN)) .build()); assertEquals(toPredicate(tupleDomain), FALSE_LITERAL); } @Test public void testToPredicateAllIgnored() throws Exception { TupleDomain<Symbol> tupleDomain = withColumnDomains(ImmutableMap.<Symbol, Domain>builder() .put(C_BIGINT, Domain.singleValue(BIGINT, 1L)) .put(C_DOUBLE, Domain.onlyNull(DOUBLE)) .put(C_VARCHAR, Domain.notNull(VARCHAR)) .put(C_BOOLEAN, Domain.all(BOOLEAN)) .build()); ExtractionResult result = fromPredicate(toPredicate(tupleDomain)); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.<Symbol, Domain>builder() .put(C_BIGINT, Domain.singleValue(BIGINT, 1L)) .put(C_DOUBLE, Domain.onlyNull(DOUBLE)) .put(C_VARCHAR, Domain.notNull(VARCHAR)) .build())); } @Test public void testToPredicate() throws Exception { TupleDomain<Symbol> tupleDomain; tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT))); assertEquals(toPredicate(tupleDomain), isNotNull(C_BIGINT)); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.onlyNull(BIGINT))); assertEquals(toPredicate(tupleDomain), isNull(C_BIGINT)); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.none(BIGINT))); assertEquals(toPredicate(tupleDomain), FALSE_LITERAL); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.all(BIGINT))); assertEquals(toPredicate(tupleDomain), TRUE_LITERAL); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 1L)), false))); assertEquals(toPredicate(tupleDomain), greaterThan(C_BIGINT, bigintLiteral(1L))); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThanOrEqual(BIGINT, 1L)), false))); assertEquals(toPredicate(tupleDomain), greaterThanOrEqual(C_BIGINT, bigintLiteral(1L))); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 1L)), false))); assertEquals(toPredicate(tupleDomain), lessThan(C_BIGINT, bigintLiteral(1L))); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.range(BIGINT, 0L, false, 1L, true)), false))); assertEquals(toPredicate(tupleDomain), and(greaterThan(C_BIGINT, bigintLiteral(0L)), lessThanOrEqual(C_BIGINT, bigintLiteral(1L)))); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 1L)), false))); assertEquals(toPredicate(tupleDomain), lessThanOrEqual(C_BIGINT, bigintLiteral(1L))); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.singleValue(BIGINT, 1L))); assertEquals(toPredicate(tupleDomain), equal(C_BIGINT, bigintLiteral(1L))); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false))); assertEquals(toPredicate(tupleDomain), in(C_BIGINT, ImmutableList.of(1L, 2L))); tupleDomain = withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 1L)), true))); assertEquals(toPredicate(tupleDomain), or(lessThan(C_BIGINT, bigintLiteral(1L)), isNull(C_BIGINT))); tupleDomain = withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1), true))); assertEquals(toPredicate(tupleDomain), or(equal(C_COLOR, colorLiteral(COLOR_VALUE_1)), isNull(C_COLOR))); tupleDomain = withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1).complement(), true))); assertEquals(toPredicate(tupleDomain), or(not(equal(C_COLOR, colorLiteral(COLOR_VALUE_1))), isNull(C_COLOR))); tupleDomain = withColumnDomains(ImmutableMap.of(C_HYPER_LOG_LOG, Domain.onlyNull(HYPER_LOG_LOG))); assertEquals(toPredicate(tupleDomain), isNull(C_HYPER_LOG_LOG)); tupleDomain = withColumnDomains(ImmutableMap.of(C_HYPER_LOG_LOG, Domain.notNull(HYPER_LOG_LOG))); assertEquals(toPredicate(tupleDomain), isNotNull(C_HYPER_LOG_LOG)); } @Test public void testFromUnknownPredicate() throws Exception { ExtractionResult result = fromPredicate(unprocessableExpression1(C_BIGINT)); assertTrue(result.getTupleDomain().isAll()); assertEquals(result.getRemainingExpression(), unprocessableExpression1(C_BIGINT)); // Test the complement result = fromPredicate(not(unprocessableExpression1(C_BIGINT))); assertTrue(result.getTupleDomain().isAll()); assertEquals(result.getRemainingExpression(), not(unprocessableExpression1(C_BIGINT))); } @Test public void testFromAndPredicate() throws Exception { Expression originalPredicate = and( and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT))); ExtractionResult result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), and(unprocessableExpression1(C_BIGINT), unprocessableExpression2(C_BIGINT))); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.range(BIGINT, 1L, false, 5L, false)), false)))); // Test complements originalPredicate = not(and( and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT)))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), originalPredicate); assertTrue(result.getTupleDomain().isAll()); originalPredicate = not(and( not(and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT))), not(and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT))))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), originalPredicate); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT)))); } @Test public void testFromOrPredicate() throws Exception { Expression originalPredicate = or( and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT))); ExtractionResult result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), originalPredicate); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT)))); originalPredicate = or( and(equal(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(equal(C_BIGINT, bigintLiteral(2L)), unprocessableExpression2(C_BIGINT))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), originalPredicate); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false)))); // Same unprocessableExpression means that we can do more extraction // If both sides are operating on the same single symbol originalPredicate = or( and(equal(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(equal(C_BIGINT, bigintLiteral(2L)), unprocessableExpression1(C_BIGINT))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), unprocessableExpression1(C_BIGINT)); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false)))); // And not if they have different symbols originalPredicate = or( and(equal(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(equal(C_DOUBLE, doubleLiteral(2.0)), unprocessableExpression1(C_BIGINT))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), originalPredicate); assertTrue(result.getTupleDomain().isAll()); // We can make another optimization if one side is the super set of the other side originalPredicate = or( and(greaterThan(C_BIGINT, bigintLiteral(1L)), greaterThan(C_DOUBLE, doubleLiteral(1.0)), unprocessableExpression1(C_BIGINT)), and(greaterThan(C_BIGINT, bigintLiteral(2L)), greaterThan(C_DOUBLE, doubleLiteral(2.0)), unprocessableExpression1(C_BIGINT))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), unprocessableExpression1(C_BIGINT)); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of( C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 1L)), false), C_DOUBLE, Domain.create(ValueSet.ofRanges(Range.greaterThan(DOUBLE, 1.0)), false)))); // We can't make those inferences if the unprocessableExpressions are non-deterministic originalPredicate = or( and(equal(C_BIGINT, bigintLiteral(1L)), randPredicate(C_BIGINT, BIGINT)), and(equal(C_BIGINT, bigintLiteral(2L)), randPredicate(C_BIGINT, BIGINT))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), originalPredicate); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false)))); // Test complements originalPredicate = not(or( and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT)), and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT)))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), and( not(and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT))), not(and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT))))); assertTrue(result.getTupleDomain().isAll()); originalPredicate = not(or( not(and(greaterThan(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT))), not(and(lessThan(C_BIGINT, bigintLiteral(5L)), unprocessableExpression2(C_BIGINT))))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), and(unprocessableExpression1(C_BIGINT), unprocessableExpression2(C_BIGINT))); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.range(BIGINT, 1L, false, 5L, false)), false)))); } @Test public void testFromNotPredicate() throws Exception { Expression originalPredicate = not(and(equal(C_BIGINT, bigintLiteral(1L)), unprocessableExpression1(C_BIGINT))); ExtractionResult result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), originalPredicate); assertTrue(result.getTupleDomain().isAll()); originalPredicate = not(unprocessableExpression1(C_BIGINT)); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), originalPredicate); assertTrue(result.getTupleDomain().isAll()); originalPredicate = not(TRUE_LITERAL); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalPredicate = not(equal(C_BIGINT, bigintLiteral(1L))); result = fromPredicate(originalPredicate); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 1L), Range.greaterThan(BIGINT, 1L)), false)))); } @Test public void testFromUnprocessableComparison() throws Exception { // If it is not a simple comparison, we should not try to process it Expression predicate = comparison(GREATER_THAN, unprocessableExpression1(C_BIGINT), unprocessableExpression2(C_BIGINT)); ExtractionResult result = fromPredicate(predicate); assertEquals(result.getRemainingExpression(), predicate); assertTrue(result.getTupleDomain().isAll()); // Complement predicate = not(comparison(GREATER_THAN, unprocessableExpression1(C_BIGINT), unprocessableExpression2(C_BIGINT))); result = fromPredicate(predicate); assertEquals(result.getRemainingExpression(), predicate); assertTrue(result.getTupleDomain().isAll()); } @Test public void testFromBasicComparisons() throws Exception { // Test out the extraction of all basic comparisons Expression originalExpression = greaterThan(C_BIGINT, bigintLiteral(2L)); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = greaterThanOrEqual(C_BIGINT, bigintLiteral(2L)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThanOrEqual(BIGINT, 2L)), false)))); originalExpression = lessThan(C_BIGINT, bigintLiteral(2L)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L)), false)))); originalExpression = lessThanOrEqual(C_BIGINT, bigintLiteral(2L)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = equal(C_BIGINT, bigintLiteral(2L)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 2L)), false)))); originalExpression = notEqual(C_BIGINT, bigintLiteral(2L)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L), Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = isDistinctFrom(C_BIGINT, bigintLiteral(2L)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L), Range.greaterThan(BIGINT, 2L)), true)))); originalExpression = equal(C_COLOR, colorLiteral(COLOR_VALUE_1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1), false)))); originalExpression = in(C_COLOR, ImmutableList.of(colorLiteral(COLOR_VALUE_1), colorLiteral(COLOR_VALUE_2))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1, COLOR_VALUE_2), false)))); originalExpression = isDistinctFrom(C_COLOR, colorLiteral(COLOR_VALUE_1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1).complement(), true)))); // Test complement originalExpression = not(greaterThan(C_BIGINT, bigintLiteral(2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = not(greaterThanOrEqual(C_BIGINT, bigintLiteral(2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L)), false)))); originalExpression = not(lessThan(C_BIGINT, bigintLiteral(2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThanOrEqual(BIGINT, 2L)), false)))); originalExpression = not(lessThanOrEqual(C_BIGINT, bigintLiteral(2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(equal(C_BIGINT, bigintLiteral(2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L), Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(notEqual(C_BIGINT, bigintLiteral(2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 2L)), false)))); originalExpression = not(isDistinctFrom(C_BIGINT, bigintLiteral(2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 2L)), false)))); originalExpression = not(equal(C_COLOR, colorLiteral(COLOR_VALUE_1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1).complement(), false)))); originalExpression = not(in(C_COLOR, ImmutableList.of(colorLiteral(COLOR_VALUE_1), colorLiteral(COLOR_VALUE_2)))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1, COLOR_VALUE_2).complement(), false)))); originalExpression = not(isDistinctFrom(C_COLOR, colorLiteral(COLOR_VALUE_1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1), false)))); } @Test public void testFromFlippedBasicComparisons() throws Exception { // Test out the extraction of all basic comparisons where the reference literal ordering is flipped ComparisonExpression originalExpression = comparison(GREATER_THAN, bigintLiteral(2L), C_BIGINT.toSymbolReference()); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L)), false)))); originalExpression = comparison(GREATER_THAN_OR_EQUAL, bigintLiteral(2L), C_BIGINT.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = comparison(LESS_THAN, bigintLiteral(2L), C_BIGINT.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = comparison(LESS_THAN_OR_EQUAL, bigintLiteral(2L), C_BIGINT.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThanOrEqual(BIGINT, 2L)), false)))); originalExpression = comparison(EQUAL, bigintLiteral(2L), C_BIGINT.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 2L)), false)))); originalExpression = comparison(EQUAL, colorLiteral(COLOR_VALUE_1), C_COLOR.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1), false)))); originalExpression = comparison(NOT_EQUAL, bigintLiteral(2L), C_BIGINT.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L), Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = comparison(NOT_EQUAL, colorLiteral(COLOR_VALUE_1), C_COLOR.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1).complement(), false)))); originalExpression = comparison(IS_DISTINCT_FROM, bigintLiteral(2L), C_BIGINT.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L), Range.greaterThan(BIGINT, 2L)), true)))); originalExpression = comparison(IS_DISTINCT_FROM, colorLiteral(COLOR_VALUE_1), C_COLOR.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1).complement(), true)))); originalExpression = comparison(IS_DISTINCT_FROM, nullLiteral(BIGINT), C_BIGINT.toSymbolReference()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT)))); } @Test public void testFromBasicComparisonsWithNulls() throws Exception { // Test out the extraction of all basic comparisons with null literals Expression originalExpression = greaterThan(C_BIGINT, nullLiteral(BIGINT)); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = greaterThan(C_VARCHAR, nullLiteral(VARCHAR)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_VARCHAR, Domain.create(ValueSet.none(VARCHAR), false)))); originalExpression = greaterThanOrEqual(C_BIGINT, nullLiteral(BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = lessThan(C_BIGINT, nullLiteral(BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = lessThanOrEqual(C_BIGINT, nullLiteral(BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = equal(C_BIGINT, nullLiteral(BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = equal(C_COLOR, nullLiteral(COLOR)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = notEqual(C_BIGINT, nullLiteral(BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = notEqual(C_COLOR, nullLiteral(COLOR)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = isDistinctFrom(C_BIGINT, nullLiteral(BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT)))); originalExpression = isDistinctFrom(C_COLOR, nullLiteral(COLOR)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.notNull(COLOR)))); // Test complements originalExpression = not(greaterThan(C_BIGINT, nullLiteral(BIGINT))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(greaterThanOrEqual(C_BIGINT, nullLiteral(BIGINT))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(lessThan(C_BIGINT, nullLiteral(BIGINT))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(lessThanOrEqual(C_BIGINT, nullLiteral(BIGINT))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(equal(C_BIGINT, nullLiteral(BIGINT))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(equal(C_COLOR, nullLiteral(COLOR))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(notEqual(C_BIGINT, nullLiteral(BIGINT))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(notEqual(C_COLOR, nullLiteral(COLOR))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(isDistinctFrom(C_BIGINT, nullLiteral(BIGINT))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.onlyNull(BIGINT)))); originalExpression = not(isDistinctFrom(C_COLOR, nullLiteral(COLOR))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.onlyNull(COLOR)))); } @Test void testNonImplictCastOnSymbolSide() { // we expect TupleDomain.all here(). // see comment in DomainTranslator.Visitor.visitComparisonExpression() // CAST(timestamp as DATE) = date_literal Expression originalExpression = equal( new Cast(C_TIMESTAMP.toSymbolReference(), DATE.toString()), LiteralInterpreter.toExpression(DATE_VALUE, DATE)); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), originalExpression); assertEquals(result.getTupleDomain(), TupleDomain.all()); // CAST(DECIMAL as BIGINT) = bigint_literal originalExpression = equal( new Cast(C_DECIMAL_12_2.toSymbolReference(), BIGINT.toString()), bigintLiteral(135L)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), originalExpression); assertEquals(result.getTupleDomain(), TupleDomain.all()); } @Test public void testFromComparisonsWithCoercions() throws Exception { // B is a double column. Check that it can be compared against longs Expression originalExpression = greaterThan(C_DOUBLE, cast(bigintLiteral(2L), DOUBLE)); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_DOUBLE, Domain.create(ValueSet.ofRanges(Range.greaterThan(DOUBLE, 2.0)), false)))); // C is a string column. Check that it can be compared. originalExpression = greaterThan(C_VARCHAR, stringLiteral("test", VARCHAR)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_VARCHAR, Domain.create(ValueSet.ofRanges(Range.greaterThan(VARCHAR, utf8Slice("test"))), false)))); // A is a long column. Check that it can be compared against doubles originalExpression = greaterThan(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = greaterThan(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = greaterThanOrEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThanOrEqual(BIGINT, 2L)), false)))); originalExpression = greaterThanOrEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = lessThan(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L)), false)))); originalExpression = lessThan(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = lessThanOrEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = lessThanOrEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = equal(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 2L)), false)))); originalExpression = equal(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.none(BIGINT)))); originalExpression = notEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L), Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = notEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT)))); originalExpression = isDistinctFrom(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L), Range.greaterThan(BIGINT, 2L)), true)))); originalExpression = isDistinctFrom(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isAll()); // Test complements // B is a double column. Check that it can be compared against longs originalExpression = not(greaterThan(C_DOUBLE, cast(bigintLiteral(2L), DOUBLE))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_DOUBLE, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(DOUBLE, 2.0)), false)))); // C is a string column. Check that it can be compared. originalExpression = not(greaterThan(C_VARCHAR, stringLiteral("test", VARCHAR))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_VARCHAR, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(VARCHAR, utf8Slice("test"))), false)))); // A is a long column. Check that it can be compared against doubles originalExpression = not(greaterThan(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = not(greaterThan(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = not(greaterThanOrEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L)), false)))); originalExpression = not(greaterThanOrEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThanOrEqual(BIGINT, 2L)), false)))); originalExpression = not(lessThan(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThanOrEqual(BIGINT, 2L)), false)))); originalExpression = not(lessThan(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(lessThanOrEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(lessThanOrEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(equal(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 2L), Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(equal(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT)))); originalExpression = not(notEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 2L)), false)))); originalExpression = not(notEqual(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.none(BIGINT)))); originalExpression = not(isDistinctFrom(cast(C_BIGINT, DOUBLE), doubleLiteral(2.0))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 2L)), false)))); originalExpression = not(isDistinctFrom(cast(C_BIGINT, DOUBLE), doubleLiteral(2.1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); } @Test public void testFromUnprocessableInPredicate() throws Exception { Expression originalExpression = new InPredicate(unprocessableExpression1(C_BIGINT), new InListExpression(ImmutableList.of(TRUE_LITERAL))); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), originalExpression); assertTrue(result.getTupleDomain().isAll()); originalExpression = new InPredicate(C_BOOLEAN.toSymbolReference(), new InListExpression(ImmutableList.of(unprocessableExpression1(C_BOOLEAN)))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), equal(C_BOOLEAN, unprocessableExpression1(C_BOOLEAN))); assertTrue(result.getTupleDomain().isAll()); originalExpression = new InPredicate(C_BOOLEAN.toSymbolReference(), new InListExpression(ImmutableList.of(TRUE_LITERAL, unprocessableExpression1(C_BOOLEAN)))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), or(equal(C_BOOLEAN, TRUE_LITERAL), equal(C_BOOLEAN, unprocessableExpression1(C_BOOLEAN)))); assertTrue(result.getTupleDomain().isAll()); // Test complement originalExpression = not(new InPredicate(C_BOOLEAN.toSymbolReference(), new InListExpression(ImmutableList.of(unprocessableExpression1(C_BOOLEAN))))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), not(equal(C_BOOLEAN, unprocessableExpression1(C_BOOLEAN)))); assertTrue(result.getTupleDomain().isAll()); } @Test public void testFromInPredicate() throws Exception { Expression originalExpression = in(C_BIGINT, ImmutableList.of(1L)); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.singleValue(BIGINT, 1L)))); originalExpression = in(C_COLOR, ImmutableList.of(colorLiteral(COLOR_VALUE_1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.singleValue(COLOR, COLOR_VALUE_1)))); originalExpression = in(C_BIGINT, ImmutableList.of(1L, 2L)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false)))); originalExpression = in(C_COLOR, ImmutableList.of(colorLiteral(COLOR_VALUE_1), colorLiteral(COLOR_VALUE_2))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1, COLOR_VALUE_2), false)))); originalExpression = not(in(C_BIGINT, ImmutableList.of(1L, 2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 1L), Range.range(BIGINT, 1L, false, 2L, false), Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(in(C_COLOR, ImmutableList.of(colorLiteral(COLOR_VALUE_1), colorLiteral(COLOR_VALUE_2)))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_COLOR, Domain.create(ValueSet.of(COLOR, COLOR_VALUE_1, COLOR_VALUE_2).complement(), false)))); // TODO update domain translator to properly handle cast // originalExpression = in(A, Arrays.asList(1L, 2L, (Expression) null)); // result = fromPredicate(originalExpression, TYPES, COLUMN_HANDLES); // assertEquals(result.getRemainingExpression(), TRUE_LITERAL); // assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(ACH, Domain.create(ValueSet.ofRanges(Range.equal(BIGINT, 1L), Range.equal(BIGINT, 2L)), false)))); // // originalExpression = not(in(A, Arrays.asList(1L, 2L, (Expression) null))); // result = fromPredicate(originalExpression, TYPES, COLUMN_HANDLES); // assertEquals(result.getRemainingExpression(), TRUE_LITERAL); // assertTrue(result.getTupleDomain().isNone()); // // originalExpression = in(A, Arrays.asList((Expression) null)); // result = fromPredicate(originalExpression, TYPES, COLUMN_HANDLES); // assertEquals(result.getRemainingExpression(), TRUE_LITERAL); // assertTrue(result.getTupleDomain().isNone()); // // originalExpression = not(in(A, Arrays.asList((Expression) null))); // result = fromPredicate(originalExpression, TYPES, COLUMN_HANDLES); // assertEquals(result.getRemainingExpression(), TRUE_LITERAL); // assertTrue(result.getTupleDomain().isNone()); } @Test public void testFromBetweenPredicate() throws Exception { Expression originalExpression = between(C_BIGINT, bigintLiteral(1L), bigintLiteral(2L)); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.range(BIGINT, 1L, true, 2L, true)), false)))); originalExpression = between(cast(C_BIGINT, DOUBLE), cast(bigintLiteral(1L), DOUBLE), doubleLiteral(2.1)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.range(BIGINT, 1L, true, 2L, true)), false)))); originalExpression = between(C_BIGINT, bigintLiteral(1L), nullLiteral(BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); // Test complements originalExpression = not(between(C_BIGINT, bigintLiteral(1L), bigintLiteral(2L))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 1L), Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(between(cast(C_BIGINT, DOUBLE), cast(bigintLiteral(1L), DOUBLE), doubleLiteral(2.1))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 1L), Range.greaterThan(BIGINT, 2L)), false)))); originalExpression = not(between(C_BIGINT, bigintLiteral(1L), nullLiteral(BIGINT))); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.lessThan(BIGINT, 1L)), false)))); } @Test public void testFromIsNullPredicate() throws Exception { Expression originalExpression = isNull(C_BIGINT); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.onlyNull(BIGINT)))); originalExpression = isNull(C_HYPER_LOG_LOG); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_HYPER_LOG_LOG, Domain.onlyNull(HYPER_LOG_LOG)))); originalExpression = not(isNull(C_BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT)))); originalExpression = not(isNull(C_HYPER_LOG_LOG)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_HYPER_LOG_LOG, Domain.notNull(HYPER_LOG_LOG)))); } @Test public void testFromIsNotNullPredicate() throws Exception { Expression originalExpression = isNotNull(C_BIGINT); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.notNull(BIGINT)))); originalExpression = isNotNull(C_HYPER_LOG_LOG); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_HYPER_LOG_LOG, Domain.notNull(HYPER_LOG_LOG)))); originalExpression = not(isNotNull(C_BIGINT)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.onlyNull(BIGINT)))); originalExpression = not(isNotNull(C_HYPER_LOG_LOG)); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_HYPER_LOG_LOG, Domain.onlyNull(HYPER_LOG_LOG)))); } @Test public void testFromBooleanLiteralPredicate() throws Exception { Expression originalExpression = TRUE_LITERAL; ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isAll()); originalExpression = not(TRUE_LITERAL); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = FALSE_LITERAL; result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(FALSE_LITERAL); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isAll()); } @Test public void testFromNullLiteralPredicate() throws Exception { Expression originalExpression = nullLiteral(); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); originalExpression = not(nullLiteral()); result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertTrue(result.getTupleDomain().isNone()); } @Test public void testExpressionConstantFolding() throws Exception { Expression originalExpression = comparison(GREATER_THAN, C_VARBINARY.toSymbolReference(), function("from_hex", stringLiteral("123456"))); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); Slice value = Slices.wrappedBuffer(BaseEncoding.base16().decode("123456")); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_VARBINARY, Domain.create(ValueSet.ofRanges(Range.greaterThan(VARBINARY, value)), false)))); Expression expression = toPredicate(result.getTupleDomain()); assertEquals(expression, comparison(GREATER_THAN, C_VARBINARY.toSymbolReference(), varbinaryLiteral(value))); } @Test void testMultipleCoercionsOnSymbolSide() throws Exception { ComparisonExpression originalExpression = comparison(GREATER_THAN, cast(cast(C_BIGINT, REAL), DOUBLE), doubleLiteral(3.7)); ExtractionResult result = fromPredicate(originalExpression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); assertEquals(result.getTupleDomain(), withColumnDomains(ImmutableMap.of(C_BIGINT, Domain.create(ValueSet.ofRanges(Range.greaterThan(BIGINT, 3L)), false)))); } @Test public void testNumericTypeTranslation() throws Exception { List<NumericValues> translationChain = ImmutableList.of( new NumericValues<>(C_DOUBLE, -1.0 * Double.MAX_VALUE, -22.0, -44.5556836, 23.0, 44.5556789, Double.MAX_VALUE), new NumericValues<>(C_REAL, realValue(-1.0f * Float.MAX_VALUE), realValue(-22.0f), realValue(-44.555687f), realValue(23.0f), realValue(44.555676f), realValue(Float.MAX_VALUE)), new NumericValues<>(C_DECIMAL_26_5, longDecimal("-999999999999999999999.99999"), longDecimal("-22.00000"), longDecimal("-44.55569"), longDecimal("23.00000"), longDecimal("44.55567"), longDecimal("999999999999999999999.99999")), new NumericValues<>(C_DECIMAL_23_4, longDecimal("-9999999999999999999.9999"), longDecimal("-22.0000"), longDecimal("-44.5557"), longDecimal("23.0000"), longDecimal("44.5556"), longDecimal("9999999999999999999.9999")), new NumericValues<>(C_BIGINT, Long.MIN_VALUE, -22L, -45L, 23L, 44L, Long.MAX_VALUE), new NumericValues<>(C_DECIMAL_21_3, longDecimal("-999999999999999999.999"), longDecimal("-22.000"), longDecimal("-44.556"), longDecimal("23.000"), longDecimal("44.555"), longDecimal("999999999999999999.999")), new NumericValues<>(C_DECIMAL_12_2, shortDecimal("-9999999999.99"), shortDecimal("-22.00"), shortDecimal("-44.56"), shortDecimal("23.00"), shortDecimal("44.55"), shortDecimal("9999999999.99")), new NumericValues<>(C_INTEGER, (long) Integer.MIN_VALUE, -22L, -45L, 23L, 44L, (long) Integer.MAX_VALUE), new NumericValues<>(C_DECIMAL_6_1, shortDecimal("-99999.9"), shortDecimal("-22.0"), shortDecimal("-44.6"), shortDecimal("23.0"), shortDecimal("44.5"), shortDecimal("99999.9")), new NumericValues<>(C_SMALLINT, (long) Short.MIN_VALUE, -22L, -45L, 23L, 44L, (long) Short.MAX_VALUE), new NumericValues<>(C_DECIMAL_3_0, shortDecimal("-999"), shortDecimal("-22"), shortDecimal("-45"), shortDecimal("23"), shortDecimal("44"), shortDecimal("999")), new NumericValues<>(C_TINYINT, (long) Byte.MIN_VALUE, -22L, -45L, 23L, 44L, (long) Byte.MAX_VALUE), new NumericValues<>(C_DECIMAL_2_0, shortDecimal("-99"), shortDecimal("-22"), shortDecimal("-45"), shortDecimal("23"), shortDecimal("44"), shortDecimal("99")) ); for (int literalIndex = 0; literalIndex < translationChain.size(); literalIndex++) { for (int columnIndex = literalIndex + 1; columnIndex < translationChain.size(); columnIndex++) { NumericValues literal = translationChain.get(literalIndex); NumericValues column = translationChain.get(columnIndex); testNumericTypeTranslation(column, literal); } } } private void testNumericTypeTranslation(NumericValues columnValues, NumericValues literalValues) { Type columnType = columnValues.getType(); Type literalType = literalValues.getType(); Type superType = METADATA.getTypeManager().getCommonSuperType(columnType, literalType).orElseThrow(() -> new IllegalArgumentException("uncompatible types in test (" + columnType + ", " + literalType + ")")); Expression max = toExpression(literalValues.getMax(), literalType); Expression min = toExpression(literalValues.getMin(), literalType); Expression integerPositive = toExpression(literalValues.getIntegerPositive(), literalType); Expression integerNegative = toExpression(literalValues.getIntegerNegative(), literalType); Expression fractionalPositive = toExpression(literalValues.getFractionalPositive(), literalType); Expression fractionalNegative = toExpression(literalValues.getFractionalNegative(), literalType); if (!literalType.equals(superType)) { max = cast(max, superType); min = cast(min, superType); integerPositive = cast(integerPositive, superType); integerNegative = cast(integerNegative, superType); fractionalPositive = cast(fractionalPositive, superType); fractionalNegative = cast(fractionalNegative, superType); } Symbol columnSymbol = columnValues.getColumn(); Expression columnExpression = columnSymbol.toSymbolReference(); if (!columnType.equals(superType)) { columnExpression = cast(columnExpression, superType); } // greater than or equal testSimpleComparison(greaterThanOrEqual(columnExpression, integerPositive), columnSymbol, Range.greaterThanOrEqual(columnType, columnValues.getIntegerPositive())); testSimpleComparison(greaterThanOrEqual(columnExpression, integerNegative), columnSymbol, Range.greaterThanOrEqual(columnType, columnValues.getIntegerNegative())); testSimpleComparison(greaterThanOrEqual(columnExpression, max), columnSymbol, Range.greaterThan(columnType, columnValues.getMax())); testSimpleComparison(greaterThanOrEqual(columnExpression, min), columnSymbol, Range.greaterThanOrEqual(columnType, columnValues.getMin())); if (literalValues.isFractional()) { testSimpleComparison(greaterThanOrEqual(columnExpression, fractionalPositive), columnSymbol, Range.greaterThan(columnType, columnValues.getFractionalPositive())); testSimpleComparison(greaterThanOrEqual(columnExpression, fractionalNegative), columnSymbol, Range.greaterThan(columnType, columnValues.getFractionalNegative())); } // greater than testSimpleComparison(greaterThan(columnExpression, integerPositive), columnSymbol, Range.greaterThan(columnType, columnValues.getIntegerPositive())); testSimpleComparison(greaterThan(columnExpression, integerNegative), columnSymbol, Range.greaterThan(columnType, columnValues.getIntegerNegative())); testSimpleComparison(greaterThan(columnExpression, max), columnSymbol, Range.greaterThan(columnType, columnValues.getMax())); testSimpleComparison(greaterThan(columnExpression, min), columnSymbol, Range.greaterThanOrEqual(columnType, columnValues.getMin())); if (literalValues.isFractional()) { testSimpleComparison(greaterThan(columnExpression, fractionalPositive), columnSymbol, Range.greaterThan(columnType, columnValues.getFractionalPositive())); testSimpleComparison(greaterThan(columnExpression, fractionalNegative), columnSymbol, Range.greaterThan(columnType, columnValues.getFractionalNegative())); } // less than or equal testSimpleComparison(lessThanOrEqual(columnExpression, integerPositive), columnSymbol, Range.lessThanOrEqual(columnType, columnValues.getIntegerPositive())); testSimpleComparison(lessThanOrEqual(columnExpression, integerNegative), columnSymbol, Range.lessThanOrEqual(columnType, columnValues.getIntegerNegative())); testSimpleComparison(lessThanOrEqual(columnExpression, max), columnSymbol, Range.lessThanOrEqual(columnType, columnValues.getMax())); testSimpleComparison(lessThanOrEqual(columnExpression, min), columnSymbol, Range.lessThan(columnType, columnValues.getMin())); if (literalValues.isFractional()) { testSimpleComparison(lessThanOrEqual(columnExpression, fractionalPositive), columnSymbol, Range.lessThanOrEqual(columnType, columnValues.getFractionalPositive())); testSimpleComparison(lessThanOrEqual(columnExpression, fractionalNegative), columnSymbol, Range.lessThanOrEqual(columnType, columnValues.getFractionalNegative())); } // less than testSimpleComparison(lessThan(columnExpression, integerPositive), columnSymbol, Range.lessThan(columnType, columnValues.getIntegerPositive())); testSimpleComparison(lessThan(columnExpression, integerNegative), columnSymbol, Range.lessThan(columnType, columnValues.getIntegerNegative())); testSimpleComparison(lessThan(columnExpression, max), columnSymbol, Range.lessThanOrEqual(columnType, columnValues.getMax())); testSimpleComparison(lessThan(columnExpression, min), columnSymbol, Range.lessThan(columnType, columnValues.getMin())); if (literalValues.isFractional()) { testSimpleComparison(lessThan(columnExpression, fractionalPositive), columnSymbol, Range.lessThanOrEqual(columnType, columnValues.getFractionalPositive())); testSimpleComparison(lessThan(columnExpression, fractionalNegative), columnSymbol, Range.lessThanOrEqual(columnType, columnValues.getFractionalNegative())); } // equal testSimpleComparison(equal(columnExpression, integerPositive), columnSymbol, Range.equal(columnType, columnValues.getIntegerPositive())); testSimpleComparison(equal(columnExpression, integerNegative), columnSymbol, Range.equal(columnType, columnValues.getIntegerNegative())); testSimpleComparison(equal(columnExpression, max), columnSymbol, Domain.none(columnType)); testSimpleComparison(equal(columnExpression, min), columnSymbol, Domain.none(columnType)); if (literalValues.isFractional()) { testSimpleComparison(equal(columnExpression, fractionalPositive), columnSymbol, Domain.none(columnType)); testSimpleComparison(equal(columnExpression, fractionalNegative), columnSymbol, Domain.none(columnType)); } // not equal testSimpleComparison(notEqual(columnExpression, integerPositive), columnSymbol, Domain.create(ValueSet.ofRanges(Range.lessThan(columnType, columnValues.getIntegerPositive()), Range.greaterThan(columnType, columnValues.getIntegerPositive())), false)); testSimpleComparison(notEqual(columnExpression, integerNegative), columnSymbol, Domain.create(ValueSet.ofRanges(Range.lessThan(columnType, columnValues.getIntegerNegative()), Range.greaterThan(columnType, columnValues.getIntegerNegative())), false)); testSimpleComparison(notEqual(columnExpression, max), columnSymbol, Domain.notNull(columnType)); testSimpleComparison(notEqual(columnExpression, min), columnSymbol, Domain.notNull(columnType)); if (literalValues.isFractional()) { testSimpleComparison(notEqual(columnExpression, fractionalPositive), columnSymbol, Domain.notNull(columnType)); testSimpleComparison(notEqual(columnExpression, fractionalNegative), columnSymbol, Domain.notNull(columnType)); } // is distinct from testSimpleComparison(isDistinctFrom(columnExpression, integerPositive), columnSymbol, Domain.create(ValueSet.ofRanges(Range.lessThan(columnType, columnValues.getIntegerPositive()), Range.greaterThan(columnType, columnValues.getIntegerPositive())), true)); testSimpleComparison(isDistinctFrom(columnExpression, integerNegative), columnSymbol, Domain.create(ValueSet.ofRanges(Range.lessThan(columnType, columnValues.getIntegerNegative()), Range.greaterThan(columnType, columnValues.getIntegerNegative())), true)); testSimpleComparison(isDistinctFrom(columnExpression, max), columnSymbol, Domain.all(columnType)); testSimpleComparison(isDistinctFrom(columnExpression, min), columnSymbol, Domain.all(columnType)); if (literalValues.isFractional()) { testSimpleComparison(isDistinctFrom(columnExpression, fractionalPositive), columnSymbol, Domain.all(columnType)); testSimpleComparison(isDistinctFrom(columnExpression, fractionalNegative), columnSymbol, Domain.all(columnType)); } } @Test public void testVarcharComparedToCharExpression() throws Exception { // greater than or equal testSimpleComparison(greaterThanOrEqual(cast(C_CHAR, VARCHAR), stringLiteral("123456789", VARCHAR)), C_CHAR, Range.greaterThan(createCharType(10), Slices.utf8Slice("12345678"))); testSimpleComparison(greaterThanOrEqual(cast(C_CHAR, VARCHAR), stringLiteral("1234567890", VARCHAR)), C_CHAR, Range.greaterThanOrEqual(createCharType(10), Slices.utf8Slice("1234567890"))); testSimpleComparison(greaterThanOrEqual(cast(C_CHAR, VARCHAR), stringLiteral("12345678901", VARCHAR)), C_CHAR, Range.greaterThan(createCharType(10), Slices.utf8Slice("1234567890"))); // greater than testSimpleComparison(greaterThan(cast(C_CHAR, VARCHAR), stringLiteral("123456789", VARCHAR)), C_CHAR, Range.greaterThan(createCharType(10), Slices.utf8Slice("12345678"))); testSimpleComparison(greaterThan(cast(C_CHAR, VARCHAR), stringLiteral("1234567890", VARCHAR)), C_CHAR, Range.greaterThan(createCharType(10), Slices.utf8Slice("1234567890"))); testSimpleComparison(greaterThan(cast(C_CHAR, VARCHAR), stringLiteral("12345678901", VARCHAR)), C_CHAR, Range.greaterThan(createCharType(10), Slices.utf8Slice("1234567890"))); // less than or equal testSimpleComparison(lessThanOrEqual(cast(C_CHAR, VARCHAR), stringLiteral("123456789", VARCHAR)), C_CHAR, Range.lessThanOrEqual(createCharType(10), Slices.utf8Slice("12345678"))); testSimpleComparison(lessThanOrEqual(cast(C_CHAR, VARCHAR), stringLiteral("1234567890", VARCHAR)), C_CHAR, Range.lessThanOrEqual(createCharType(10), Slices.utf8Slice("1234567890"))); testSimpleComparison(lessThanOrEqual(cast(C_CHAR, VARCHAR), stringLiteral("12345678901", VARCHAR)), C_CHAR, Range.lessThanOrEqual(createCharType(10), Slices.utf8Slice("1234567890"))); // less than testSimpleComparison(lessThan(cast(C_CHAR, VARCHAR), stringLiteral("123456789", VARCHAR)), C_CHAR, Range.lessThanOrEqual(createCharType(10), Slices.utf8Slice("12345678"))); testSimpleComparison(lessThan(cast(C_CHAR, VARCHAR), stringLiteral("1234567890", VARCHAR)), C_CHAR, Range.lessThan(createCharType(10), Slices.utf8Slice("1234567890"))); testSimpleComparison(lessThan(cast(C_CHAR, VARCHAR), stringLiteral("12345678901", VARCHAR)), C_CHAR, Range.lessThanOrEqual(createCharType(10), Slices.utf8Slice("1234567890"))); // equal testSimpleComparison(equal(cast(C_CHAR, VARCHAR), stringLiteral("123456789", VARCHAR)), C_CHAR, Domain.none(createCharType(10))); testSimpleComparison(equal(cast(C_CHAR, VARCHAR), stringLiteral("1234567890", VARCHAR)), C_CHAR, Range.equal(createCharType(10), Slices.utf8Slice("1234567890"))); testSimpleComparison(equal(cast(C_CHAR, VARCHAR), stringLiteral("12345678901", VARCHAR)), C_CHAR, Domain.none(createCharType(10))); // not equal testSimpleComparison(notEqual(cast(C_CHAR, VARCHAR), stringLiteral("123456789", VARCHAR)), C_CHAR, Domain.notNull(createCharType(10))); testSimpleComparison(notEqual(cast(C_CHAR, VARCHAR), stringLiteral("1234567890", VARCHAR)), C_CHAR, Domain.create(ValueSet.ofRanges( Range.lessThan(createCharType(10), Slices.utf8Slice("1234567890")), Range.greaterThan(createCharType(10), Slices.utf8Slice("1234567890"))), false)); testSimpleComparison(notEqual(cast(C_CHAR, VARCHAR), stringLiteral("12345678901", VARCHAR)), C_CHAR, Domain.notNull(createCharType(10))); // is distinct from testSimpleComparison(isDistinctFrom(cast(C_CHAR, VARCHAR), stringLiteral("123456789", VARCHAR)), C_CHAR, Domain.all(createCharType(10))); testSimpleComparison(isDistinctFrom(cast(C_CHAR, VARCHAR), stringLiteral("1234567890", VARCHAR)), C_CHAR, Domain.create(ValueSet.ofRanges( Range.lessThan(createCharType(10), Slices.utf8Slice("1234567890")), Range.greaterThan(createCharType(10), Slices.utf8Slice("1234567890"))), true)); testSimpleComparison(isDistinctFrom(cast(C_CHAR, VARCHAR), stringLiteral("12345678901", VARCHAR)), C_CHAR, Domain.all(createCharType(10))); } private static ExtractionResult fromPredicate(Expression originalPredicate) { return DomainTranslator.fromPredicate(METADATA, TEST_SESSION, originalPredicate, TYPES); } private static Expression toPredicate(TupleDomain<Symbol> tupleDomain) { return DomainTranslator.toPredicate(tupleDomain); } private static Expression unprocessableExpression1(Symbol symbol) { return comparison(GREATER_THAN, symbol.toSymbolReference(), symbol.toSymbolReference()); } private static Expression unprocessableExpression2(Symbol symbol) { return comparison(LESS_THAN, symbol.toSymbolReference(), symbol.toSymbolReference()); } private static Expression randPredicate(Symbol symbol, Type type) { return comparison(GREATER_THAN, symbol.toSymbolReference(), cast(new FunctionCall(QualifiedName.of("rand"), ImmutableList.of()), type)); } private static ComparisonExpression equal(Symbol symbol, Expression expression) { return equal(symbol.toSymbolReference(), expression); } private static ComparisonExpression notEqual(Symbol symbol, Expression expression) { return notEqual(symbol.toSymbolReference(), expression); } private static ComparisonExpression greaterThan(Symbol symbol, Expression expression) { return greaterThan(symbol.toSymbolReference(), expression); } private static ComparisonExpression greaterThanOrEqual(Symbol symbol, Expression expression) { return greaterThanOrEqual(symbol.toSymbolReference(), expression); } private static ComparisonExpression lessThan(Symbol symbol, Expression expression) { return lessThan(symbol.toSymbolReference(), expression); } private static ComparisonExpression lessThanOrEqual(Symbol symbol, Expression expression) { return lessThanOrEqual(symbol.toSymbolReference(), expression); } private static ComparisonExpression isDistinctFrom(Symbol symbol, Expression expression) { return isDistinctFrom(symbol.toSymbolReference(), expression); } private static Expression isNotNull(Symbol symbol) { return isNotNull(symbol.toSymbolReference()); } private static IsNullPredicate isNull(Symbol symbol) { return new IsNullPredicate(symbol.toSymbolReference()); } private static InPredicate in(Symbol symbol, List<?> values) { return in(symbol.toSymbolReference(), TYPES.get(symbol), values); } private static BetweenPredicate between(Symbol symbol, Expression min, Expression max) { return new BetweenPredicate(symbol.toSymbolReference(), min, max); } private static Expression isNotNull(Expression expression) { return new NotExpression(new IsNullPredicate(expression)); } private static IsNullPredicate isNull(Expression expression) { return new IsNullPredicate(expression); } private static InPredicate in(Expression expression, Type expressisonType, List<?> values) { List<Type> types = nCopies(values.size(), expressisonType); List<Expression> expressions = LiteralInterpreter.toExpressions(values, types); return new InPredicate(expression, new InListExpression(expressions)); } private static BetweenPredicate between(Expression expression, Expression min, Expression max) { return new BetweenPredicate(expression, min, max); } private static ComparisonExpression equal(Expression left, Expression right) { return comparison(EQUAL, left, right); } private static ComparisonExpression notEqual(Expression left, Expression right) { return comparison(NOT_EQUAL, left, right); } private static ComparisonExpression greaterThan(Expression left, Expression right) { return comparison(GREATER_THAN, left, right); } private static ComparisonExpression greaterThanOrEqual(Expression left, Expression right) { return comparison(GREATER_THAN_OR_EQUAL, left, right); } private static ComparisonExpression lessThan(Expression left, Expression expression) { return comparison(LESS_THAN, left, expression); } private static ComparisonExpression lessThanOrEqual(Expression left, Expression right) { return comparison(LESS_THAN_OR_EQUAL, left, right); } private static ComparisonExpression isDistinctFrom(Expression left, Expression right) { return comparison(IS_DISTINCT_FROM, left, right); } private static NotExpression not(Expression expression) { return new NotExpression(expression); } private static ComparisonExpression comparison(ComparisonExpressionType type, Expression expression1, Expression expression2) { return new ComparisonExpression(type, expression1, expression2); } private static Literal bigintLiteral(long value) { if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) { return new GenericLiteral("BIGINT", Long.toString(value)); } return new LongLiteral(Long.toString(value)); } private static DoubleLiteral doubleLiteral(double value) { return new DoubleLiteral(Double.toString(value)); } private static StringLiteral stringLiteral(String value) { return new StringLiteral(value); } private static Expression stringLiteral(String value, Type type) { return cast(stringLiteral(value), type); } private static NullLiteral nullLiteral() { return new NullLiteral(); } private static Expression nullLiteral(Type type) { return cast(new NullLiteral(), type); } private static Expression cast(Symbol symbol, Type type) { return cast(symbol.toSymbolReference(), type); } private static Expression cast(Expression expression, Type type) { return new Cast(expression, type.getTypeSignature().toString()); } private static FunctionCall colorLiteral(long value) { return new FunctionCall(QualifiedName.of(getMagicLiteralFunctionSignature(COLOR).getName()), ImmutableList.of(bigintLiteral(value))); } private static Expression varbinaryLiteral(Slice value) { return toExpression(value, VARBINARY); } private static FunctionCall function(String functionName, Expression... args) { return new FunctionCall(QualifiedName.of(functionName), ImmutableList.copyOf(args)); } private static Long shortDecimal(String value) { return new BigDecimal(value).unscaledValue().longValueExact(); } private static Slice longDecimal(String value) { return encodeScaledValue(new BigDecimal(value)); } private static Long realValue(float value) { return (long) Float.floatToIntBits(value); } private static void testSimpleComparison(Expression expression, Symbol symbol, Range expectedDomainRange) { testSimpleComparison(expression, symbol, Domain.create(ValueSet.ofRanges(expectedDomainRange), false)); } private static void testSimpleComparison(Expression expression, Symbol symbol, Domain domain) { ExtractionResult result = fromPredicate(expression); assertEquals(result.getRemainingExpression(), TRUE_LITERAL); TupleDomain<Symbol> actual = result.getTupleDomain(); TupleDomain<Symbol> expected = withColumnDomains(ImmutableMap.of(symbol, domain)); if (!actual.equals(expected)) { fail(format("for comparison [%s] expected %s but found %s", expression.toString(), expected.toString(SESSION), actual.toString(SESSION))); } } private static class NumericValues<T> { private final Symbol column; private final Type type; private final T min; private final T integerNegative; private final T fractionalNegative; private final T integerPositive; private final T fractionalPositive; private final T max; private NumericValues(Symbol column, T min, T integerNegative, T fractionalNegative, T integerPositive, T fractionalPositive, T max) { this.column = requireNonNull(column, "column is null"); this.type = requireNonNull(TYPES.get(column), "type for column not found: " + column); this.min = requireNonNull(min, "min is null"); this.integerNegative = requireNonNull(integerNegative, "integerNegative is null"); this.fractionalNegative = requireNonNull(fractionalNegative, "fractionalNegative is null"); this.integerPositive = requireNonNull(integerPositive, "integerPositive is null"); this.fractionalPositive = requireNonNull(fractionalPositive, "fractionalPositive is null"); this.max = requireNonNull(max, "max is null"); } public Symbol getColumn() { return column; } public Type getType() { return type; } public T getMin() { return min; } public T getIntegerNegative() { return integerNegative; } public T getFractionalNegative() { return fractionalNegative; } public T getIntegerPositive() { return integerPositive; } public T getFractionalPositive() { return fractionalPositive; } public T getMax() { return max; } public boolean isFractional() { return type == DOUBLE || type == REAL || (type instanceof DecimalType && ((DecimalType) type).getScale() > 0); } } }