diff --git a/fe/fe-core/pom.xml b/fe/fe-core/pom.xml index 4b7452fccb5081..d6ba4a0b7f9421 100644 --- a/fe/fe-core/pom.xml +++ b/fe/fe-core/pom.xml @@ -156,6 +156,12 @@ under the License. guava-testlib test + + + com.googlecode.java-ipv6 + java-ipv6 + 0.17 + com.fasterxml.jackson.core diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java index 6cf83f5147655d..0ea9a5dc23e912 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java @@ -670,7 +670,7 @@ public int compareLiteral(LiteralExpr expr) { return diff < 0 ? -1 : (diff == 0 ? 0 : 1); } // date time will not overflow when doing addition and subtraction - return getStringValue().compareTo(expr.getStringValue()); + return Integer.signum(getStringValue().compareTo(expr.getStringValue())); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java index f084658936d6fe..6fbfc175ea039f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java @@ -249,6 +249,9 @@ public int compareLiteral(LiteralExpr expr) { if (expr instanceof NullLiteral) { return 1; } + if (expr == MaxLiteral.MAX_VALUE) { + return -1; + } if (expr instanceof DecimalLiteral) { return this.value.compareTo(((DecimalLiteral) expr).value); } else { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java index 8d4a9ef576523e..645afe52f99491 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java @@ -126,6 +126,9 @@ public int compareLiteral(LiteralExpr expr) { if (expr instanceof NullLiteral) { return 1; } + if (expr == MaxLiteral.MAX_VALUE) { + return -1; + } return Double.compare(value, expr.getDoubleValue()); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java index 34006c51710231..978c864434dce4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java @@ -261,17 +261,13 @@ public int compareLiteral(LiteralExpr expr) { if (expr instanceof NullLiteral) { return 1; } - if (expr instanceof StringLiteral) { - return ((StringLiteral) expr).compareLiteral(this); - } if (expr == MaxLiteral.MAX_VALUE) { return -1; } - if (value == expr.getLongValue()) { - return 0; - } else { - return value > expr.getLongValue() ? 1 : -1; + if (expr instanceof StringLiteral) { + return - ((StringLiteral) expr).compareLiteral(this); } + return Long.compare(value, expr.getLongValue()); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/AddMinMax.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/AddMinMax.java index 80d245c37800c1..891f04dcfd90b3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/AddMinMax.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/AddMinMax.java @@ -36,6 +36,7 @@ import org.apache.doris.nereids.trees.expressions.LessThanEqual; import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.util.ExpressionUtils; @@ -93,7 +94,7 @@ private enum MatchMinMax { private static class MinMaxValue { // min max range, if range = null means empty - Range range; + Range range; // expression in range is discrete value boolean isDiscrete; @@ -101,7 +102,7 @@ private static class MinMaxValue { // expr relative order, for keep order after add min-max to the expression int exprOrderIndex; - public MinMaxValue(Range range, boolean isDiscrete, int exprOrderIndex) { + public MinMaxValue(Range range, boolean isDiscrete, int exprOrderIndex) { this.range = range; this.isDiscrete = isDiscrete; this.exprOrderIndex = exprOrderIndex; @@ -171,25 +172,27 @@ private Expression addExprMinMaxValues(Expression expr, ExpressionRewriteContext List addExprs = Lists.newArrayListWithExpectedSize(minMaxExprs.size() * 2); for (Map.Entry entry : minMaxExprs) { Expression targetExpr = entry.getKey(); - Range range = entry.getValue().range; + Range range = entry.getValue().range; if (range.hasLowerBound() && range.hasUpperBound() && range.lowerEndpoint().equals(range.upperEndpoint()) && range.lowerBoundType() == BoundType.CLOSED && range.upperBoundType() == BoundType.CLOSED) { - Expression cmp = new EqualTo(targetExpr, range.lowerEndpoint()); + Expression cmp = new EqualTo(targetExpr, (Literal) range.lowerEndpoint()); addExprs.add(cmp); continue; } if (range.hasLowerBound()) { - Literal literal = range.lowerEndpoint(); + ComparableLiteral literal = range.lowerEndpoint(); Expression cmp = range.lowerBoundType() == BoundType.CLOSED - ? new GreaterThanEqual(targetExpr, literal) : new GreaterThan(targetExpr, literal); + ? new GreaterThanEqual(targetExpr, (Literal) literal) + : new GreaterThan(targetExpr, (Literal) literal); addExprs.add(cmp); } if (range.hasUpperBound()) { - Literal literal = range.upperEndpoint(); + ComparableLiteral literal = range.upperEndpoint(); Expression cmp = range.upperBoundType() == BoundType.CLOSED - ? new LessThanEqual(targetExpr, literal) : new LessThan(targetExpr, literal); + ? new LessThanEqual(targetExpr, (Literal) literal) + : new LessThan(targetExpr, (Literal) literal); addExprs.add(cmp); } } @@ -243,7 +246,7 @@ private MatchMinMax getExprMatchMinMax(Expression expr, ComparisonPredicate cp = (ComparisonPredicate) expr; Expression left = cp.left(); Expression right = cp.right(); - if (!(right instanceof Literal)) { + if (!(right instanceof ComparableLiteral)) { return MatchMinMax.MATCH_NONE; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnBound.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnBound.java index 1012708bc37c5d..808a706ae71370 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnBound.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnBound.java @@ -18,6 +18,7 @@ package org.apache.doris.nereids.rules.expression.rules; import org.apache.doris.catalog.PartitionKey; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import com.google.common.base.MoreObjects; @@ -36,7 +37,13 @@ private ColumnBound(Literal value) { @Override public int compareTo(ColumnBound o) { - return value.toLegacyLiteral().compareTo(o.value.toLegacyLiteral()); + if (!(value instanceof ComparableLiteral)) { + throw new RuntimeException("'" + value + "' (" + value.getDataType() + ") is not comparable"); + } + if (!(o.value instanceof ComparableLiteral)) { + throw new RuntimeException("'" + o.value + "' (" + o.value.getDataType() + ") is not comparable"); + } + return ((ComparableLiteral) value).compareTo((ComparableLiteral) o.value); } public static ColumnBound of(Literal expr) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java index c4dd18acaa2ef5..bfb5defbdf6ebd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java @@ -80,6 +80,7 @@ import org.apache.doris.nereids.trees.expressions.literal.ArrayLiteral; import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; @@ -266,7 +267,12 @@ public Expression visitEqualTo(EqualTo equalTo, ExpressionRewriteContext context if (checkedExpr.isPresent()) { return checkedExpr.get(); } - return BooleanLiteral.of(((Literal) equalTo.left()).compareTo((Literal) equalTo.right()) == 0); + if (equalTo.left() instanceof ComparableLiteral && equalTo.right() instanceof ComparableLiteral) { + return BooleanLiteral.of(((ComparableLiteral) equalTo.left()) + .compareTo((ComparableLiteral) equalTo.right()) == 0); + } else { + return BooleanLiteral.of(equalTo.left().equals(equalTo.right())); + } } @Override @@ -276,7 +282,8 @@ public Expression visitGreaterThan(GreaterThan greaterThan, ExpressionRewriteCon if (checkedExpr.isPresent()) { return checkedExpr.get(); } - return BooleanLiteral.of(((Literal) greaterThan.left()).compareTo((Literal) greaterThan.right()) > 0); + return BooleanLiteral.of(((ComparableLiteral) greaterThan.left()) + .compareTo((ComparableLiteral) greaterThan.right()) > 0); } @Override @@ -286,8 +293,8 @@ public Expression visitGreaterThanEqual(GreaterThanEqual greaterThanEqual, Expre if (checkedExpr.isPresent()) { return checkedExpr.get(); } - return BooleanLiteral.of(((Literal) greaterThanEqual.left()) - .compareTo((Literal) greaterThanEqual.right()) >= 0); + return BooleanLiteral.of(((ComparableLiteral) greaterThanEqual.left()) + .compareTo((ComparableLiteral) greaterThanEqual.right()) >= 0); } @Override @@ -297,7 +304,8 @@ public Expression visitLessThan(LessThan lessThan, ExpressionRewriteContext cont if (checkedExpr.isPresent()) { return checkedExpr.get(); } - return BooleanLiteral.of(((Literal) lessThan.left()).compareTo((Literal) lessThan.right()) < 0); + return BooleanLiteral.of(((ComparableLiteral) lessThan.left()) + .compareTo((ComparableLiteral) lessThan.right()) < 0); } @Override @@ -307,7 +315,8 @@ public Expression visitLessThanEqual(LessThanEqual lessThanEqual, ExpressionRewr if (checkedExpr.isPresent()) { return checkedExpr.get(); } - return BooleanLiteral.of(((Literal) lessThanEqual.left()).compareTo((Literal) lessThanEqual.right()) <= 0); + return BooleanLiteral.of(((ComparableLiteral) lessThanEqual.left()) + .compareTo((ComparableLiteral) lessThanEqual.right()) <= 0); } @Override @@ -322,7 +331,13 @@ public Expression visitNullSafeEqual(NullSafeEqual nullSafeEqual, ExpressionRewr if (l.isNullLiteral() && r.isNullLiteral()) { return BooleanLiteral.TRUE; } else if (!l.isNullLiteral() && !r.isNullLiteral()) { - return BooleanLiteral.of(l.compareTo(r) == 0); + if (nullSafeEqual.left() instanceof ComparableLiteral + && nullSafeEqual.right() instanceof ComparableLiteral) { + return BooleanLiteral.of(((ComparableLiteral) nullSafeEqual.left()) + .compareTo((ComparableLiteral) nullSafeEqual.right()) == 0); + } else { + return BooleanLiteral.of(l.equals(r)); + } } else { return BooleanLiteral.FALSE; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RangeInference.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RangeInference.java index 7c23ce36a3dbf4..d0ae0a18d4567b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RangeInference.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RangeInference.java @@ -29,7 +29,7 @@ import org.apache.doris.nereids.trees.expressions.LessThan; import org.apache.doris.nereids.trees.expressions.LessThanEqual; import org.apache.doris.nereids.trees.expressions.Or; -import org.apache.doris.nereids.trees.expressions.literal.Literal; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.util.ExpressionUtils; @@ -76,7 +76,8 @@ private ValueDesc buildRange(ExpressionRewriteContext context, ComparisonPredica return new UnknownValue(context, predicate); } // only handle `NumericType` and `DateLikeType` - if (right.isLiteral() && (right.getDataType().isNumericType() || right.getDataType().isDateLikeType())) { + if (right instanceof ComparableLiteral + && (right.getDataType().isNumericType() || right.getDataType().isDateLikeType())) { return ValueDesc.range(context, predicate); } return new UnknownValue(context, predicate); @@ -111,7 +112,7 @@ public ValueDesc visitEqualTo(EqualTo equalTo, ExpressionRewriteContext context) public ValueDesc visitInPredicate(InPredicate inPredicate, ExpressionRewriteContext context) { // only handle `NumericType` and `DateLikeType` if (inPredicate.getOptions().size() <= InPredicateDedup.REWRITE_OPTIONS_MAX_SIZE - && ExpressionUtils.isAllNonNullLiteral(inPredicate.getOptions()) + && ExpressionUtils.isAllNonNullComparableLiteral(inPredicate.getOptions()) && (ExpressionUtils.matchNumericType(inPredicate.getOptions()) || ExpressionUtils.matchDateLikeType(inPredicate.getOptions()))) { return ValueDesc.discrete(context, inPredicate); @@ -216,7 +217,7 @@ public static ValueDesc union(ExpressionRewriteContext context, /** merge discrete and ranges only, no merge other value desc */ public static List unionDiscreteAndRange(ExpressionRewriteContext context, Expression reference, List valueDescs) { - Set discreteValues = Sets.newHashSet(); + Set discreteValues = Sets.newHashSet(); for (ValueDesc valueDesc : valueDescs) { if (valueDesc instanceof DiscreteValue) { discreteValues.addAll(((DiscreteValue) valueDesc).getValues()); @@ -224,10 +225,10 @@ public static List unionDiscreteAndRange(ExpressionRewriteContext con } // for 'a > 8 or a = 8', then range (8, +00) can convert to [8, +00) - RangeSet rangeSet = TreeRangeSet.create(); + RangeSet rangeSet = TreeRangeSet.create(); for (ValueDesc valueDesc : valueDescs) { if (valueDesc instanceof RangeValue) { - Range range = ((RangeValue) valueDesc).range; + Range range = ((RangeValue) valueDesc).range; rangeSet.add(range); if (range.hasLowerBound() && range.lowerBoundType() == BoundType.OPEN @@ -250,7 +251,7 @@ public static List unionDiscreteAndRange(ExpressionRewriteContext con if (!discreteValues.isEmpty()) { result.add(new DiscreteValue(context, reference, discreteValues)); } - for (Range range : rangeSet.asRanges()) { + for (Range range : rangeSet.asRanges()) { result.add(new RangeValue(context, reference, range)); } for (ValueDesc valueDesc : valueDescs) { @@ -267,7 +268,7 @@ public static List unionDiscreteAndRange(ExpressionRewriteContext con /** intersect */ public static ValueDesc intersect(ExpressionRewriteContext context, RangeValue range, DiscreteValue discrete) { - Set newValues = discrete.values.stream().filter(x -> range.range.contains(x)) + Set newValues = discrete.values.stream().filter(x -> range.range.contains(x)) .collect(Collectors.toSet()); if (newValues.isEmpty()) { return new EmptyValue(context, range.reference); @@ -277,11 +278,11 @@ public static ValueDesc intersect(ExpressionRewriteContext context, RangeValue r } private static ValueDesc range(ExpressionRewriteContext context, ComparisonPredicate predicate) { - Literal value = (Literal) predicate.right(); + ComparableLiteral value = (ComparableLiteral) predicate.right(); if (predicate instanceof EqualTo) { return new DiscreteValue(context, predicate.left(), Sets.newHashSet(value)); } - Range range = null; + Range range = null; if (predicate instanceof GreaterThanEqual) { range = Range.atLeast(value); } else if (predicate instanceof GreaterThan) { @@ -296,8 +297,9 @@ private static ValueDesc range(ExpressionRewriteContext context, ComparisonPredi } public static ValueDesc discrete(ExpressionRewriteContext context, InPredicate in) { - // Set literals = (Set) Utils.fastToImmutableSet(in.getOptions()); - Set literals = in.getOptions().stream().map(Literal.class::cast).collect(Collectors.toSet()); + // Set literals = (Set) Utils.fastToImmutableSet(in.getOptions()); + Set literals = in.getOptions().stream() + .map(ComparableLiteral.class::cast).collect(Collectors.toSet()); return new DiscreteValue(context, in.getCompareExpr(), literals); } } @@ -328,14 +330,14 @@ public ValueDesc intersect(ValueDesc other) { * a > 1 => (1...+∞) */ public static class RangeValue extends ValueDesc { - Range range; + Range range; - public RangeValue(ExpressionRewriteContext context, Expression reference, Range range) { + public RangeValue(ExpressionRewriteContext context, Expression reference, Range range) { super(context, reference); this.range = range; } - public Range getRange() { + public Range getRange() { return range; } @@ -387,15 +389,15 @@ public String toString() { * a in (1,2,3) => [1,2,3] */ public static class DiscreteValue extends ValueDesc { - final Set values; + final Set values; public DiscreteValue(ExpressionRewriteContext context, - Expression reference, Set values) { + Expression reference, Set values) { super(context, reference); this.values = values; } - public Set getValues() { + public Set getValues() { return values; } @@ -405,7 +407,7 @@ public ValueDesc union(ValueDesc other) { return other.union(this); } if (other instanceof DiscreteValue) { - Set newValues = Sets.newHashSet(); + Set newValues = Sets.newHashSet(); newValues.addAll(((DiscreteValue) other).values); newValues.addAll(this.values); return new DiscreteValue(context, reference, newValues); @@ -422,7 +424,7 @@ public ValueDesc intersect(ValueDesc other) { return other.intersect(this); } if (other instanceof DiscreteValue) { - Set newValues = Sets.newHashSet(); + Set newValues = Sets.newHashSet(); newValues.addAll(((DiscreteValue) other).values); newValues.retainAll(this.values); if (newValues.isEmpty()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticComparisonRule.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticComparisonRule.java index 853b5a3dfc98c0..c08f3aafea6bc3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticComparisonRule.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyArithmeticComparisonRule.java @@ -37,6 +37,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksSub; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.util.TypeCoercionUtils; @@ -124,7 +125,7 @@ private static List tryRearrangeChildren(Expression left, Expression if (!left.child(1).isConstant()) { throw new RuntimeException(String.format("Expected literal when arranging children for Expr %s", left)); } - Literal leftLiteral = (Literal) FoldConstantRule.evaluate(left.child(1), context); + ComparableLiteral leftLiteral = (ComparableLiteral) FoldConstantRule.evaluate(left.child(1), context); Expression leftExpr = left.child(0); Class oppositeOperator = REARRANGEMENT_MAP.get(left.getClass()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java index 6ac69f1eb56375..097214e50b7c68 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/SimplifyRange.java @@ -32,6 +32,7 @@ import org.apache.doris.nereids.trees.expressions.GreaterThanEqual; import org.apache.doris.nereids.trees.expressions.LessThan; import org.apache.doris.nereids.trees.expressions.LessThanEqual; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.util.ExpressionUtils; @@ -43,6 +44,7 @@ import org.apache.commons.lang3.NotImplementedException; import java.util.List; +import java.util.stream.Collectors; /** * This class implements the function to simplify expression range. @@ -104,20 +106,20 @@ private Expression getExpression(EmptyValue value) { private Expression getExpression(RangeValue value) { Expression reference = value.getReference(); - Range range = value.getRange(); + Range range = value.getRange(); List result = Lists.newArrayList(); if (range.hasLowerBound()) { if (range.lowerBoundType() == BoundType.CLOSED) { - result.add(new GreaterThanEqual(reference, range.lowerEndpoint())); + result.add(new GreaterThanEqual(reference, (Literal) range.lowerEndpoint())); } else { - result.add(new GreaterThan(reference, range.lowerEndpoint())); + result.add(new GreaterThan(reference, (Literal) range.lowerEndpoint())); } } if (range.hasUpperBound()) { if (range.upperBoundType() == BoundType.CLOSED) { - result.add(new LessThanEqual(reference, range.upperEndpoint())); + result.add(new LessThanEqual(reference, (Literal) range.upperEndpoint())); } else { - result.add(new LessThan(reference, range.upperEndpoint())); + result.add(new LessThan(reference, (Literal) range.upperEndpoint())); } } if (!result.isEmpty()) { @@ -128,7 +130,8 @@ private Expression getExpression(RangeValue value) { } private Expression getExpression(DiscreteValue value) { - return ExpressionUtils.toInPredicateOrEqualTo(value.getReference(), value.getValues()); + return ExpressionUtils.toInPredicateOrEqualTo(value.getReference(), + value.getValues().stream().map(Literal.class::cast).collect(Collectors.toList())); } private Expression getExpression(UnknownValue value) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java index d343f6f93566cd..8c760ed55c7fed 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ComparisonPredicate.java @@ -64,6 +64,8 @@ public void checkLegalityBeforeTypeCoercion() { for (Expression c : children) { if (c.getDataType().isComplexType() && !c.getDataType().isArrayType()) { throw new AnalysisException("comparison predicate could not contains complex type: " + this.toSql()); + } else if (c.getDataType().isJsonType()) { + throw new AnalysisException("comparison predicate could not contains json type: " + this.toSql()); } } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/InPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/InPredicate.java index 57cc8c73c8b6c9..5a9c9aaecc172a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/InPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/InPredicate.java @@ -19,16 +19,16 @@ import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.exceptions.UnboundException; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BooleanType; import org.apache.doris.nereids.types.DataType; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import java.util.Collection; import java.util.List; @@ -168,11 +168,22 @@ public boolean isLiteralChildren() { return true; } - //use for ut + /** + * sort options, only use in ut + */ + @VisibleForTesting public Expression sortOptions() { - if (isLiteralChildren()) { - List values = options.stream().map(e -> (Literal) e).collect(Collectors.toList()); - return new InPredicate(compareExpr, Lists.newArrayList(Sets.newTreeSet(values))); + if (options.stream().allMatch(x -> x instanceof ComparableLiteral)) { + try { + List values = options.stream().map(e -> (ComparableLiteral) e) + .sorted() + .distinct() + .map(Literal.class::cast) + .collect(Collectors.toList()); + return new InPredicate(compareExpr, values); + } catch (Exception e) { + return this; + } } return this; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UnixTimestamp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UnixTimestamp.java index 178187ad9cbc65..9a968c189c4dc8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UnixTimestamp.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/UnixTimestamp.java @@ -21,6 +21,7 @@ import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; import org.apache.doris.nereids.trees.expressions.functions.Monotonic; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; @@ -176,7 +177,8 @@ public boolean isMonotonic(Literal lower, Literal upper) { if (null == upper) { upper = DateTimeLiteral.MAX_DATETIME; } - if (lower.compareTo(MAX) <= 0 && upper.compareTo(MAX) > 0) { + if (((ComparableLiteral) lower).compareTo(MAX) <= 0 + && ((ComparableLiteral) upper).compareTo(MAX) > 0) { return false; } else { return true; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ArrayLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ArrayLiteral.java index be84a5b32e35cf..e5d3b38b2f914b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ArrayLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ArrayLiteral.java @@ -36,7 +36,7 @@ /** * ArrayLiteral */ -public class ArrayLiteral extends Literal { +public class ArrayLiteral extends Literal implements ComparableLiteral { private final List items; @@ -70,6 +70,39 @@ public LiteralExpr toLegacyLiteral() { return new org.apache.doris.analysis.ArrayLiteral(getDataType().toCatalogDataType(), itemExprs); } + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof ArrayLiteral) { + ArrayLiteral otherArray = (ArrayLiteral) other; + int size = Math.min(otherArray.items.size(), this.items.size()); + for (int i = 0; i < size; i++) { + Literal thisItem = items.get(i); + Literal otherItem = otherArray.items.get(i); + if (!(thisItem instanceof ComparableLiteral)) { + throw new RuntimeException( + "array item '" + thisItem + "' (" + thisItem.dataType + ") is not comparable"); + } + if (!(otherItem instanceof ComparableLiteral)) { + throw new RuntimeException( + "array item '" + otherItem + "' (" + otherItem.dataType + ") is not comparable"); + } + int cmp = ((ComparableLiteral) thisItem).compareTo((ComparableLiteral) otherItem); + if (cmp != 0) { + return cmp; + } + } + return Integer.compare(this.items.size(), otherArray.items.size()); + } + if (other instanceof NullLiteral) { + return 1; + } + if (other instanceof MaxLiteral) { + return -1; + } + throw new RuntimeException("Cannot compare two values with different data types: " + + this + " (" + dataType + ") vs " + other + " (" + ((Literal) other).dataType + ")"); + } + @Override protected Expression uncheckedCastTo(DataType targetType) throws AnalysisException { if (this.dataType.equals(targetType)) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/BooleanLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/BooleanLiteral.java index f3b884dc15b3a7..210fe4c891216e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/BooleanLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/BooleanLiteral.java @@ -25,7 +25,7 @@ /** * Represents Boolean literal */ -public class BooleanLiteral extends Literal { +public class BooleanLiteral extends Literal implements ComparableLiteral { public static final BooleanLiteral TRUE = new BooleanLiteral(true); public static final BooleanLiteral FALSE = new BooleanLiteral(false); @@ -69,6 +69,21 @@ public LiteralExpr toLegacyLiteral() { return new BoolLiteral(value); } + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof BooleanLiteral) { + return Boolean.compare(value, ((BooleanLiteral) other).value); + } + if (other instanceof NullLiteral) { + return 1; + } + if (other instanceof MaxLiteral) { + return -1; + } + throw new RuntimeException("Cannot compare two values with different data types: " + + this + " (" + dataType + ") vs " + other + " (" + ((Literal) other).dataType + ")"); + } + @Override public double getDouble() { if (value) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/CharLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/CharLiteral.java index e1ca1fa3cebbc3..10e276b4abdca1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/CharLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/CharLiteral.java @@ -17,8 +17,6 @@ package org.apache.doris.nereids.trees.expressions.literal; -import org.apache.doris.analysis.LiteralExpr; -import org.apache.doris.analysis.StringLiteral; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.CharType; @@ -31,18 +29,8 @@ public CharLiteral(String value, int len) { super(len >= 0 ? value.substring(0, Math.min(value.length(), len)) : value, CharType.createCharType(len)); } - @Override - public String getValue() { - return value; - } - @Override public R accept(ExpressionVisitor visitor, C context) { return visitor.visitCharLiteral(this, context); } - - @Override - public LiteralExpr toLegacyLiteral() { - return new StringLiteral(value); - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ComparableLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ComparableLiteral.java new file mode 100644 index 00000000000000..00f734fd66bc8f --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ComparableLiteral.java @@ -0,0 +1,24 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 org.apache.doris.nereids.trees.expressions.literal; + +/** + * comparable literal + */ +public interface ComparableLiteral extends Comparable { +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java index 3bfc4a7dc81436..d6dc97343faa1e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java @@ -42,7 +42,7 @@ /** * Date literal in Nereids. */ -public class DateLiteral extends Literal { +public class DateLiteral extends Literal implements ComparableLiteral { public static final String JAVA_DATE_FORMAT = "yyyy-MM-dd"; public static final Set punctuations = ImmutableSet.of('!', '@', '#', '$', '%', '^', '&', '*', '(', ')', @@ -458,6 +458,30 @@ public LiteralExpr toLegacyLiteral() { return new org.apache.doris.analysis.DateLiteral(year, month, day, Type.DATE); } + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof DateLiteral) { + int cmp = Long.compare(getValue(), ((DateLiteral) other).getValue()); + if (cmp != 0) { + return cmp; + } + + long thisMicrosecond = this instanceof DateTimeV2Literal ? ((DateTimeV2Literal) this).getMicroSecond() : 0L; + long otherMicrosecond = other instanceof DateTimeV2Literal + ? ((DateTimeV2Literal) other).getMicroSecond() : 0L; + return Long.compare(thisMicrosecond, otherMicrosecond); + } + if (other instanceof NullLiteral) { + return 1; + } + if (other instanceof MaxLiteral) { + return -1; + } + + throw new RuntimeException("Cannot compare two values with different data types: " + + this + " (" + dataType + ") vs " + other + " (" + ((Literal) other).dataType + ")"); + } + public long getYear() { return year; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalLiteral.java index 1f0aa788cdc641..6b02ce002f8fcd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalLiteral.java @@ -51,6 +51,11 @@ public DecimalLiteral(DecimalV2Type dataType, BigDecimal value) { this.value = Objects.requireNonNull(adjustedValue); } + @Override + protected BigDecimal getBigDecimalValue() { + return value; + } + @Override public BigDecimal getValue() { return value; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalV3Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalV3Literal.java index 045da28bdb38a4..8067070a1812b1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalV3Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DecimalV3Literal.java @@ -77,6 +77,11 @@ public double getDouble() { return value.doubleValue(); } + @Override + protected BigDecimal getBigDecimalValue() { + return value; + } + /** * get ceiling of a decimal v3 literal * @param newScale scale we want to cast to diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteral.java index bc7b356c3762fe..7c2141818d7acb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DoubleLiteral.java @@ -23,6 +23,8 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DoubleType; +import java.math.BigDecimal; + /** * Double literal */ @@ -35,6 +37,11 @@ public DoubleLiteral(double value) { this.value = value; } + @Override + protected BigDecimal getBigDecimalValue() { + return new BigDecimal(String.valueOf(value)); + } + @Override public Double getValue() { return value; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/FloatLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/FloatLiteral.java index df75bbcfc5c440..7af1e196fa02db 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/FloatLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/FloatLiteral.java @@ -22,6 +22,8 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.FloatType; +import java.math.BigDecimal; + /** * float type literal */ @@ -34,6 +36,11 @@ public FloatLiteral(float value) { this.value = value; } + @Override + protected BigDecimal getBigDecimalValue() { + return new BigDecimal(String.valueOf(value)); + } + @Override public Float getValue() { return value; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv4Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv4Literal.java index e4e931738b02a2..a5bfdb1a671f8a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv4Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv4Literal.java @@ -27,7 +27,7 @@ /** * Represents IPv4 literal */ -public class IPv4Literal extends Literal { +public class IPv4Literal extends Literal implements ComparableLiteral { private static final Pattern IPV4_STD_REGEX = Pattern.compile("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); @@ -59,6 +59,21 @@ public LiteralExpr toLegacyLiteral() { return new org.apache.doris.analysis.IPv4Literal(value); } + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof IPv4Literal) { + return Long.compare(value, ((IPv4Literal) other).value); + } + if (other instanceof NullLiteral) { + return 1; + } + if (other instanceof MaxLiteral) { + return -1; + } + throw new RuntimeException("Cannot compare two values with different data types: " + + this + " (" + dataType + ") vs " + other + " (" + ((Literal) other).dataType + ")"); + } + void init(String ipv4) throws AnalysisException { checkValueValid(ipv4); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv6Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv6Literal.java index 0ac12ae85e477a..c26cc9b707297c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv6Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IPv6Literal.java @@ -22,28 +22,30 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.IPv6Type; +import com.googlecode.ipv6.IPv6Address; + import java.util.regex.Pattern; /** * Represents IPv6 literal */ -public class IPv6Literal extends Literal { +public class IPv6Literal extends Literal implements ComparableLiteral { private static final Pattern IPV6_STD_REGEX = Pattern.compile("^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"); private static final Pattern IPV6_COMPRESS_REGEX = Pattern.compile("^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4})*)?)::((([0-9A-Fa-f]{1,4}:)*[0-9A-Fa-f]{1,4})?)$"); - private final String value; + private final IPv6Address value; public IPv6Literal(String ipv6) throws AnalysisException { super(IPv6Type.INSTANCE); checkValueValid(ipv6); - this.value = ipv6; + this.value = IPv6Address.fromString(ipv6); } @Override - public String getValue() { + public IPv6Address getValue() { return value; } @@ -55,12 +57,27 @@ public R accept(ExpressionVisitor visitor, C context) { @Override public LiteralExpr toLegacyLiteral() { try { - return new org.apache.doris.analysis.IPv6Literal(value); + return new org.apache.doris.analysis.IPv6Literal(value.toString()); } catch (Exception e) { throw new AnalysisException("Invalid IPv6 format."); } } + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof IPv6Literal) { + return value.compareTo(((IPv6Literal) other).value); + } + if (other instanceof NullLiteral) { + return 1; + } + if (other instanceof MaxLiteral) { + return -1; + } + throw new RuntimeException("Cannot compare two values with different data types: " + + this + " (" + dataType + ") vs " + other + " (" + ((Literal) other).dataType + ")"); + } + public void checkValueValid(String ipv6) throws AnalysisException { if (ipv6.length() > 39) { throw new AnalysisException("The length of IPv6 must not exceed 39."); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLikeLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLikeLiteral.java index 54456bd9493564..8fe34c3ece055f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLikeLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLikeLiteral.java @@ -19,6 +19,8 @@ import org.apache.doris.nereids.types.DataType; +import java.math.BigDecimal; + /** IntegralLiteral */ public abstract class IntegerLikeLiteral extends NumericLiteral { /** @@ -38,5 +40,10 @@ public long getLongValue() { return getNumber().longValue(); } + @Override + protected BigDecimal getBigDecimalValue() { + return new BigDecimal(getLongValue()); + } + public abstract Number getNumber(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/LargeIntLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/LargeIntLiteral.java index 5f9d60a2ff72b5..bdefdafad1df4d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/LargeIntLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/LargeIntLiteral.java @@ -22,6 +22,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.LargeIntType; +import java.math.BigDecimal; import java.math.BigInteger; import java.util.Objects; @@ -62,6 +63,11 @@ public double getDouble() { return value.doubleValue(); } + @Override + protected BigDecimal getBigDecimalValue() { + return new BigDecimal(value); + } + @Override public Number getNumber() { return value; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java index bb6bbe62a6c292..60ffedcedbe755 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java @@ -54,7 +54,7 @@ * All data type literal expression in Nereids. * TODO: Increase the implementation of sub expression. such as Integer. */ -public abstract class Literal extends Expression implements LeafExpression, Comparable { +public abstract class Literal extends Expression implements LeafExpression { protected final DataType dataType; @@ -157,14 +157,6 @@ public R accept(ExpressionVisitor visitor, C context) { return visitor.visitLiteral(this, context); } - /** - * literal expr compare. - */ - @Override - public int compareTo(Literal other) { - return toLegacyLiteral().compareLiteral(other.toLegacyLiteral()); - } - /** * literal expr compare. */ diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MaxLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MaxLiteral.java index 763fdfb1f4f1f8..8d688feefde01a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MaxLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MaxLiteral.java @@ -22,7 +22,7 @@ import org.apache.doris.nereids.types.DataType; /** MaxLiteral */ -public class MaxLiteral extends Literal { +public class MaxLiteral extends Literal implements ComparableLiteral { public MaxLiteral(DataType dataType) { super(dataType); } @@ -37,6 +37,14 @@ public LiteralExpr toLegacyLiteral() { return org.apache.doris.analysis.MaxLiteral.MAX_VALUE; } + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof MaxLiteral) { + return 0; + } + return 1; + } + @Override public String computeToSql() { return "MAX_VALUE"; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NullLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NullLiteral.java index 5af08e6d130a43..80f7514e0f90b9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NullLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NullLiteral.java @@ -27,7 +27,7 @@ /** * Represents Null literal */ -public class NullLiteral extends Literal { +public class NullLiteral extends Literal implements ComparableLiteral { public static final NullLiteral INSTANCE = new NullLiteral(); @@ -59,6 +59,14 @@ public LiteralExpr toLegacyLiteral() { return org.apache.doris.analysis.NullLiteral.create(dataType.toCatalogDataType()); } + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof NullLiteral) { + return 0; + } + return -1; + } + @Override public double getDouble() { return 0; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NumericLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NumericLiteral.java index 93b03e4fafaf02..b22c9e3a6fc039 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NumericLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/NumericLiteral.java @@ -19,10 +19,13 @@ import org.apache.doris.nereids.types.DataType; +import java.math.BigDecimal; +import java.math.BigInteger; + /** * numeric literal */ -public abstract class NumericLiteral extends Literal { +public abstract class NumericLiteral extends Literal implements ComparableLiteral { /** * Constructor for NumericLiteral. * @@ -31,4 +34,39 @@ public abstract class NumericLiteral extends Literal { public NumericLiteral(DataType dataType) { super(dataType); } + + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof NumericLiteral) { + if (this instanceof IntegerLikeLiteral && other instanceof IntegerLikeLiteral) { + IntegerLikeLiteral thisInteger = (IntegerLikeLiteral) this; + IntegerLikeLiteral otherInteger = (IntegerLikeLiteral) other; + if (this instanceof LargeIntLiteral || other instanceof LargeIntLiteral) { + BigInteger leftValue = this instanceof LargeIntLiteral ? ((LargeIntLiteral) this).getValue() + : new BigInteger(String.valueOf(thisInteger.getLongValue())); + BigInteger rightValue = other instanceof LargeIntLiteral ? ((LargeIntLiteral) other).getValue() + : new BigInteger(String.valueOf(otherInteger.getLongValue())); + return leftValue.compareTo(rightValue); + } else { + return Long.compare(((IntegerLikeLiteral) this).getLongValue(), + ((IntegerLikeLiteral) other).getLongValue()); + } + } + if (this instanceof DecimalLiteral || this instanceof DecimalV3Literal + || other instanceof DecimalLiteral || other instanceof DecimalV3Literal) { + return this.getBigDecimalValue().compareTo(((NumericLiteral) other).getBigDecimalValue()); + } + return Double.compare(this.getDouble(), ((Literal) other).getDouble()); + } + if (other instanceof NullLiteral) { + return 1; + } + if (other instanceof MaxLiteral) { + return -1; + } + throw new RuntimeException("Cannot compare two values with different data types: " + + this + " (" + dataType + ") vs " + other + " (" + ((Literal) other).dataType + ")"); + } + + protected abstract BigDecimal getBigDecimalValue(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLikeLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLikeLiteral.java index dba9247fe70213..546e0ab64c9684 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLikeLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLikeLiteral.java @@ -17,14 +17,17 @@ package org.apache.doris.nereids.trees.expressions.literal; +import org.apache.doris.analysis.LiteralExpr; +import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.types.DataType; +import java.io.UnsupportedEncodingException; import java.util.Objects; /** * StringLikeLiteral. */ -public abstract class StringLikeLiteral extends Literal { +public abstract class StringLikeLiteral extends Literal implements ComparableLiteral { public static final int CHINESE_CHAR_BYTE_LENGTH = 4; public final String value; @@ -62,6 +65,59 @@ public String getValue() { return value; } + @Override + public LiteralExpr toLegacyLiteral() { + return new org.apache.doris.analysis.StringLiteral(value); + } + + @Override + public int compareTo(ComparableLiteral other) { + if (other instanceof StringLikeLiteral) { + // compare string with utf-8 byte array, same with DM,BE,StorageEngine + byte[] thisBytes = null; + byte[] otherBytes = null; + try { + thisBytes = getStringValue().getBytes("UTF-8"); + otherBytes = ((Literal) other).getStringValue().getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new AnalysisException(e.getMessage(), e); + } + + int minLength = Math.min(thisBytes.length, otherBytes.length); + int i = 0; + for (i = 0; i < minLength; i++) { + if (Byte.toUnsignedInt(thisBytes[i]) < Byte.toUnsignedInt(otherBytes[i])) { + return -1; + } else if (Byte.toUnsignedInt(thisBytes[i]) > Byte.toUnsignedInt(otherBytes[i])) { + return 1; + } + } + if (thisBytes.length > otherBytes.length) { + if (thisBytes[i] == 0x00) { + return 0; + } else { + return 1; + } + } else if (thisBytes.length < otherBytes.length) { + if (otherBytes[i] == 0x00) { + return 0; + } else { + return -1; + } + } else { + return 0; + } + } + if (other instanceof NullLiteral) { + return 1; + } + if (other instanceof MaxLiteral) { + return -1; + } + throw new RuntimeException("Cannot compare two values with different data types: " + + this + " (" + dataType + ") vs " + other + " (" + ((Literal) other).dataType + ")"); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLiteral.java index 603749c60b376d..4971248ad70140 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StringLiteral.java @@ -17,7 +17,6 @@ package org.apache.doris.nereids.trees.expressions.literal; -import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.StringType; @@ -26,8 +25,6 @@ */ public class StringLiteral extends StringLikeLiteral { - private final String value; - /** * Constructor for Literal. * @@ -35,21 +32,10 @@ public class StringLiteral extends StringLikeLiteral { */ public StringLiteral(String value) { super(value, StringType.INSTANCE); - this.value = value; - } - - @Override - public String getValue() { - return value; } @Override public R accept(ExpressionVisitor visitor, C context) { return visitor.visitStringLiteral(this, context); } - - @Override - public LiteralExpr toLegacyLiteral() { - return new org.apache.doris.analysis.StringLiteral(value); - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/VarcharLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/VarcharLiteral.java index 75161dd00042a8..e2860fcf027c74 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/VarcharLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/VarcharLiteral.java @@ -17,8 +17,6 @@ package org.apache.doris.nereids.trees.expressions.literal; -import org.apache.doris.analysis.LiteralExpr; -import org.apache.doris.analysis.StringLiteral; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.VarcharType; @@ -36,18 +34,8 @@ public VarcharLiteral(String value, int len) { super(len >= 0 ? value.substring(0, Math.min(value.length(), len)) : value, VarcharType.createVarcharType(len)); } - @Override - public String getValue() { - return getStringValue(); - } - @Override public R accept(ExpressionVisitor visitor, C context) { return visitor.visitVarcharLiteral(this, context); } - - @Override - public LiteralExpr toLegacyLiteral() { - return new StringLiteral(value); - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java index 3d8aef2c8428ab..d26f73195f79c4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java @@ -56,6 +56,7 @@ import org.apache.doris.nereids.trees.expressions.functions.agg.Min; import org.apache.doris.nereids.trees.expressions.functions.agg.Sum; import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; @@ -585,9 +586,9 @@ public static boolean isAllLiteral(List children) { /** * return true if all children are literal but not null literal. */ - public static boolean isAllNonNullLiteral(List children) { + public static boolean isAllNonNullComparableLiteral(List children) { for (Expression child : children) { - if ((!(child instanceof Literal)) || (child instanceof NullLiteral)) { + if ((!(child instanceof ComparableLiteral)) || (child instanceof NullLiteral)) { return false; } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java index 624a47f11bd132..fd522512ef5caf 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/FoldConstantTest.java @@ -64,6 +64,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.ToDays; import org.apache.doris.nereids.trees.expressions.functions.scalar.UnixTimestamp; import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; +import org.apache.doris.nereids.trees.expressions.literal.ComparableLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; @@ -280,11 +281,11 @@ void testFoldString() { ConvertTz c = new ConvertTz(DateTimeV2Literal.fromJavaDateType(LocalDateTime.of(1, 1, 1, 1, 1, 1)), StringLiteral.of("Asia/Shanghai"), StringLiteral.of("GMT")); Expression rewritten = executor.rewrite(c, context); - Assertions.assertTrue(new DateTimeV2Literal("0000-12-31 16:55:18.000000").compareTo((Literal) rewritten) == 0); + Assertions.assertTrue(new DateTimeV2Literal("0000-12-31 16:55:18.000000").compareTo((ComparableLiteral) rewritten) == 0); c = new ConvertTz(DateTimeV2Literal.fromJavaDateType(LocalDateTime.of(9999, 12, 31, 23, 59, 59, 999999000)), StringLiteral.of("Pacific/Galapagos"), StringLiteral.of("Pacific/Galapagos")); rewritten = executor.rewrite(c, context); - Assertions.assertTrue(new DateTimeV2Literal("9999-12-31 23:59:59.999999").compareTo((Literal) rewritten) == 0); + Assertions.assertTrue(new DateTimeV2Literal("9999-12-31 23:59:59.999999").compareTo((ComparableLiteral) rewritten) == 0); DateFormat d = new DateFormat(DateTimeLiteral.fromJavaDateType(LocalDateTime.of(1, 1, 1, 1, 1, 1)), StringLiteral.of("%y %m %d")); @@ -310,7 +311,7 @@ void testFoldString() { t = new DateTrunc(DateTimeV2Literal.fromJavaDateType(LocalDateTime.of(1, 1, 1, 1, 1, 1)), StringLiteral.of("week")); rewritten = executor.rewrite(t, context); - Assertions.assertTrue(((Literal) rewritten).compareTo(new DateTimeV2Literal("0001-01-01 00:00:00.000000")) == 0); + Assertions.assertTrue(((ComparableLiteral) rewritten).compareTo(new DateTimeV2Literal("0001-01-01 00:00:00.000000")) == 0); t = new DateTrunc(DateLiteral.fromJavaDateType(LocalDateTime.of(1, 1, 1, 1, 1, 1)), StringLiteral.of("week")); rewritten = executor.rewrite(t, context); @@ -862,9 +863,9 @@ void testDateTimeV2TypeDateTimeArithmeticFunctions() { new DateTimeLiteral("2023-05-07 02:41:42"), new VarcharLiteral("%x %v %X %V")).toSql()); - Assertions.assertTrue(new DateTimeV2Literal("2021-01-01 12:12:14.000000").compareTo((Literal) TimeRoundSeries + Assertions.assertTrue(new DateTimeV2Literal("2021-01-01 12:12:14.000000").compareTo((ComparableLiteral) TimeRoundSeries .secondCeil(new DateTimeV2Literal("2021-01-01 12:12:12.123"), new IntegerLiteral(2))) == 0); - Assertions.assertTrue(new DateTimeV2Literal("2021-01-01 12:12:12.000000").compareTo((Literal) TimeRoundSeries + Assertions.assertTrue(new DateTimeV2Literal("2021-01-01 12:12:12.000000").compareTo((ComparableLiteral) TimeRoundSeries .secondFloor(new DateTimeV2Literal("2021-01-01 12:12:12.123"), new IntegerLiteral(2))) == 0); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/CompareLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/CompareLiteralTest.java new file mode 100644 index 00000000000000..887b7673877b78 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/CompareLiteralTest.java @@ -0,0 +1,326 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 org.apache.doris.nereids.trees.expressions.literal; + +import org.apache.doris.common.ExceptionChecker; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.utframe.TestWithFeService; + +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.math.BigInteger; + +class CompareLiteralTest extends TestWithFeService { + + @Test + public void testScalar() { + // boolean type + checkCompareSameType(0, BooleanLiteral.of(true), BooleanLiteral.of(true)); + checkCompareSameType(1, BooleanLiteral.of(true), BooleanLiteral.of(false)); + checkCompareDiffType(BooleanLiteral.of(true), new IntegerLiteral(0)); + checkCompareDiffType(BooleanLiteral.of(true), new DoubleLiteral(0.5)); + checkCompareDiffType(BooleanLiteral.of(true), new DecimalLiteral(new BigDecimal("0.5"))); + checkCompareDiffType(BooleanLiteral.of(true), new IntegerLiteral(1)); + checkCompareDiffType(BooleanLiteral.of(true), new DoubleLiteral(1.0)); + checkCompareDiffType(BooleanLiteral.of(true), new DecimalLiteral(new BigDecimal("1.0"))); + checkCompareDiffType(BooleanLiteral.of(true), new StringLiteral("tru")); + checkCompareDiffType(BooleanLiteral.of(true), new StringLiteral("true")); + checkCompareDiffType(BooleanLiteral.of(true), new StringLiteral("truea")); + checkCompareSameType(0, BooleanLiteral.of(false), BooleanLiteral.of(false)); + checkCompareDiffType(BooleanLiteral.of(false), new IntegerLiteral(0)); + checkCompareDiffType(BooleanLiteral.of(false), new DoubleLiteral(0.5)); + checkCompareDiffType(BooleanLiteral.of(false), new DecimalLiteral(new BigDecimal("0.5"))); + checkCompareDiffType(BooleanLiteral.of(false), new IntegerLiteral(1)); + checkCompareDiffType(BooleanLiteral.of(false), new DoubleLiteral(1.0)); + checkCompareDiffType(BooleanLiteral.of(false), new DecimalLiteral(new BigDecimal("1.0"))); + checkCompareDiffType(BooleanLiteral.of(false), new StringLiteral("fals")); + checkCompareDiffType(BooleanLiteral.of(false), new StringLiteral("false")); + checkCompareDiffType(BooleanLiteral.of(false), new StringLiteral("falsea")); + + // numeric type + checkCompareSameType(0, new TinyIntLiteral((byte) 127), new TinyIntLiteral((byte) 127)); + checkCompareSameType(0, new TinyIntLiteral((byte) 127), new DoubleLiteral(127.0)); + checkCompareSameType(0, new TinyIntLiteral((byte) 127), new DecimalLiteral(new BigDecimal("127.0"))); + checkCompareSameType(0, new TinyIntLiteral((byte) 127), new DecimalV3Literal(new BigDecimal("127.0"))); + checkCompareDiffType(new TinyIntLiteral((byte) 127), new StringLiteral("12")); + checkCompareDiffType(new TinyIntLiteral((byte) 127), new StringLiteral("127")); + checkCompareDiffType(new TinyIntLiteral((byte) 127), new StringLiteral("127.0")); + checkCompareSameType(-1, new TinyIntLiteral((byte) 127), new SmallIntLiteral((short) 32767)); + checkCompareSameType(-1, new TinyIntLiteral((byte) 127), new DoubleLiteral(32767.0)); + checkCompareSameType(-1, new TinyIntLiteral((byte) 127), new DecimalLiteral(new BigDecimal("32767"))); + checkCompareSameType(-1, new TinyIntLiteral((byte) 127), new DecimalV3Literal(new BigDecimal("32767"))); + checkCompareSameType(-1, new TinyIntLiteral((byte) 127), new IntegerLiteral(2147483647)); + checkCompareSameType(-1, new TinyIntLiteral((byte) 127), new BigIntLiteral(9223372036854775807L)); + checkCompareSameType(-1, new TinyIntLiteral((byte) 127), new LargeIntLiteral(new BigInteger("9223372036854775808"))); + + checkCompareSameType(0, new SmallIntLiteral((short) 32767), new SmallIntLiteral((short) 32767)); + checkCompareSameType(0, new SmallIntLiteral((short) 32767), new DoubleLiteral(32767.0)); + checkCompareSameType(0, new SmallIntLiteral((short) 32767), new DecimalLiteral(new BigDecimal("32767.0"))); + checkCompareSameType(0, new SmallIntLiteral((short) 32767), new DecimalV3Literal(new BigDecimal("32767.0"))); + checkCompareDiffType(new SmallIntLiteral((short) 32767), new StringLiteral("3276")); + checkCompareDiffType(new SmallIntLiteral((short) 32767), new StringLiteral("32767")); + checkCompareDiffType(new SmallIntLiteral((short) 32767), new StringLiteral("32767.0")); + checkCompareSameType(-1, new SmallIntLiteral((short) 32767), new IntegerLiteral(2147483647)); + checkCompareSameType(-1, new SmallIntLiteral((short) 32767), new DoubleLiteral(2147483647.0)); + checkCompareSameType(-1, new SmallIntLiteral((short) 32767), new DecimalLiteral(new BigDecimal("2147483647"))); + checkCompareSameType(-1, new SmallIntLiteral((short) 32767), new DecimalV3Literal(new BigDecimal("2147483647"))); + checkCompareSameType(-1, new SmallIntLiteral((short) 32767), new BigIntLiteral(9223372036854775807L)); + checkCompareSameType(-1, new SmallIntLiteral((short) 32767), new LargeIntLiteral(new BigInteger("9223372036854775808"))); + + checkCompareSameType(0, new IntegerLiteral(2147483647), new IntegerLiteral(2147483647)); + checkCompareSameType(0, new IntegerLiteral(2147483647), new DoubleLiteral(2147483647.0)); + checkCompareSameType(0, new IntegerLiteral(2147483647), new DecimalLiteral(new BigDecimal("2147483647.0"))); + checkCompareSameType(0, new IntegerLiteral(2147483647), new DecimalV3Literal(new BigDecimal("2147483647.0"))); + checkCompareDiffType(new IntegerLiteral(2147483647), new StringLiteral("214748364")); + checkCompareDiffType(new IntegerLiteral(2147483647), new StringLiteral("2147483647")); + checkCompareDiffType(new IntegerLiteral(2147483647), new StringLiteral("2147483647.0")); + checkCompareSameType(-1, new IntegerLiteral(2147483647), new DecimalLiteral(new BigDecimal("922337203685477580"))); + checkCompareSameType(-1, new IntegerLiteral(2147483647), new DecimalV3Literal(new BigDecimal("9223372036854775807"))); + checkCompareSameType(-1, new IntegerLiteral(2147483647), new BigIntLiteral(9223372036854775807L)); + checkCompareSameType(-1, new IntegerLiteral(2147483647), new LargeIntLiteral(new BigInteger("9223372036854775808"))); + + checkCompareSameType(0, new BigIntLiteral(9223372036854775807L), new BigIntLiteral(9223372036854775807L)); + checkCompareSameType(0, new BigIntLiteral(922337203685477580L), new DecimalLiteral(new BigDecimal("922337203685477580.0"))); + checkCompareSameType(0, new BigIntLiteral(9223372036854775807L), new DecimalV3Literal(new BigDecimal("9223372036854775807.0"))); + checkCompareDiffType(new BigIntLiteral(9223372036854775807L), new StringLiteral("922337203685477580")); + checkCompareDiffType(new BigIntLiteral(9223372036854775807L), new StringLiteral("9223372036854775807")); + checkCompareDiffType(new BigIntLiteral(9223372036854775807L), new StringLiteral("9223372036854775807.0")); + checkCompareSameType(-1, new BigIntLiteral(922337203685477587L), new DecimalLiteral(new BigDecimal("922337203685477588"))); + checkCompareSameType(-1, new BigIntLiteral(9223372036854775807L), new DecimalV3Literal(new BigDecimal("9223372036854775808"))); + checkCompareSameType(-1, new BigIntLiteral(9223372036854775807L), new LargeIntLiteral(new BigInteger("9223372036854775808"))); + + checkCompareSameType(0, new LargeIntLiteral(new BigInteger("9223372036854775808")), new LargeIntLiteral(new BigInteger("9223372036854775808"))); + checkCompareSameType(0, new LargeIntLiteral(new BigInteger("922337203685477588")), new DecimalLiteral(new BigDecimal("922337203685477588.0"))); + checkCompareSameType(0, new LargeIntLiteral(new BigInteger("9223372036854775808")), new DecimalV3Literal(new BigDecimal("9223372036854775808.0"))); + checkCompareDiffType(new LargeIntLiteral(new BigInteger("9223372036854775808")), new StringLiteral("922337203685477580")); + checkCompareDiffType(new LargeIntLiteral(new BigInteger("9223372036854775808")), new StringLiteral("9223372036854775808")); + checkCompareDiffType(new LargeIntLiteral(new BigInteger("9223372036854775808")), new StringLiteral("9223372036854775808.0")); + checkCompareSameType(-1, new LargeIntLiteral(new BigInteger("922337203685477588")), new DecimalLiteral(new BigDecimal("922337203685477589"))); + checkCompareSameType(-1, new LargeIntLiteral(new BigInteger("9223372036854775808")), new DecimalV3Literal(new BigDecimal("9223372036854775809"))); + + checkCompareSameType(0, new FloatLiteral(100.5f), new FloatLiteral(100.5f)); + checkCompareSameType(0, new FloatLiteral(100.5f), new DoubleLiteral(100.5)); + checkCompareSameType(0, new FloatLiteral(100.5f), new DecimalLiteral(new BigDecimal("100.5"))); + checkCompareSameType(0, new FloatLiteral(100.5f), new DecimalV3Literal(new BigDecimal("100.5"))); + checkCompareDiffType(new FloatLiteral(100.0f), new StringLiteral("100")); + checkCompareDiffType(new FloatLiteral(100.0f), new StringLiteral("100.0")); + checkCompareDiffType(new FloatLiteral(100.0f), new StringLiteral("100.00")); + checkCompareSameType(-1, new FloatLiteral(100.5f), new FloatLiteral(100.6f)); + checkCompareSameType(-1, new FloatLiteral(100.5f), new DoubleLiteral(100.6)); + checkCompareSameType(-1, new FloatLiteral(100.5f), new DecimalLiteral(new BigDecimal("100.6"))); + checkCompareSameType(-1, new FloatLiteral(100.5f), new DecimalV3Literal(new BigDecimal("100.6"))); + + checkCompareSameType(0, new DoubleLiteral(100.5), new DoubleLiteral(100.5)); + checkCompareSameType(0, new DoubleLiteral(100.5), new DoubleLiteral(100.5)); + checkCompareSameType(0, new DoubleLiteral(100.5), new DecimalLiteral(new BigDecimal("100.5"))); + checkCompareSameType(0, new DoubleLiteral(100.5), new DecimalV3Literal(new BigDecimal("100.5"))); + checkCompareDiffType(new DoubleLiteral(100.0), new StringLiteral("100")); + checkCompareDiffType(new DoubleLiteral(100.0), new StringLiteral("100.0")); + checkCompareDiffType(new DoubleLiteral(100.0), new StringLiteral("100.00")); + checkCompareSameType(-1, new DoubleLiteral(100.5), new FloatLiteral(100.6f)); + checkCompareSameType(-1, new DoubleLiteral(100.5), new DoubleLiteral(100.6)); + checkCompareSameType(-1, new DoubleLiteral(100.5), new DecimalLiteral(new BigDecimal("100.6"))); + checkCompareSameType(-1, new DoubleLiteral(100.5), new DecimalV3Literal(new BigDecimal("100.6"))); + + checkCompareSameType(0, new DecimalLiteral(new BigDecimal("100.5")), new DoubleLiteral(100.5)); + checkCompareSameType(0, new DecimalLiteral(new BigDecimal("100.5")), new DecimalLiteral(new BigDecimal("100.5"))); + checkCompareSameType(0, new DecimalLiteral(new BigDecimal("100.5")), new DecimalV3Literal(new BigDecimal("100.5"))); + checkCompareDiffType(new DecimalLiteral(new BigDecimal("100.0")), new StringLiteral("100")); + checkCompareDiffType(new DecimalLiteral(new BigDecimal("100.0")), new StringLiteral("100.0")); + checkCompareDiffType(new DecimalLiteral(new BigDecimal("100.0")), new StringLiteral("100.00")); + checkCompareSameType(-1, new DecimalLiteral(new BigDecimal("100.5")), new FloatLiteral(100.6f)); + checkCompareSameType(-1, new DecimalLiteral(new BigDecimal("100.5")), new DoubleLiteral(100.6)); + checkCompareSameType(-1, new DecimalLiteral(new BigDecimal("100.5")), new DecimalLiteral(new BigDecimal("100.6"))); + checkCompareSameType(-1, new DecimalLiteral(new BigDecimal("100.5")), new DecimalV3Literal(new BigDecimal("100.6"))); + + checkCompareSameType(0, new DecimalV3Literal(new BigDecimal("100.5")), new DoubleLiteral(100.5)); + checkCompareSameType(0, new DecimalV3Literal(new BigDecimal("100.5")), new DecimalLiteral(new BigDecimal("100.5"))); + checkCompareSameType(0, new DecimalV3Literal(new BigDecimal("100.5")), new DecimalV3Literal(new BigDecimal("100.5"))); + checkCompareDiffType(new DecimalV3Literal(new BigDecimal("100.0")), new StringLiteral("100")); + checkCompareDiffType(new DecimalV3Literal(new BigDecimal("100.0")), new StringLiteral("100.0")); + checkCompareDiffType(new DecimalV3Literal(new BigDecimal("100.0")), new StringLiteral("100.00")); + checkCompareSameType(-1, new DecimalV3Literal(new BigDecimal("100.5")), new FloatLiteral(100.6f)); + checkCompareSameType(-1, new DecimalV3Literal(new BigDecimal("100.5")), new DoubleLiteral(100.6)); + checkCompareSameType(-1, new DecimalV3Literal(new BigDecimal("100.5")), new DecimalLiteral(new BigDecimal("100.6"))); + checkCompareSameType(-1, new DecimalV3Literal(new BigDecimal("100.5")), new DecimalV3Literal(new BigDecimal("100.6"))); + + // date type + checkCompareSameType(0, new DateLiteral("2020-01-10"), new DateLiteral("2020-01-10")); + checkCompareSameType(0, new DateLiteral("2020-01-10"), new DateV2Literal("2020-01-10")); + checkCompareSameType(0, new DateLiteral("2020-01-10"), new DateTimeLiteral("2020-01-10 00:00:00")); + checkCompareSameType(0, new DateLiteral("2020-01-10"), new DateTimeV2Literal("2020-01-10 00:00:00.00")); + checkCompareSameType(1, new DateLiteral("2020-01-10"), new DateLiteral("2020-01-09")); + checkCompareSameType(1, new DateLiteral("2020-01-10"), new DateV2Literal("2020-01-09")); + checkCompareSameType(1, new DateLiteral("2020-01-10"), new DateTimeLiteral("2020-01-09 00:00:00")); + checkCompareSameType(1, new DateLiteral("2020-01-10"), new DateTimeV2Literal("2020-01-09 00:00:00.00")); + checkCompareSameType(-1, new DateLiteral("2020-01-10"), new DateLiteral("2020-01-11")); + checkCompareSameType(-1, new DateLiteral("2020-01-10"), new DateV2Literal("2020-01-11")); + checkCompareSameType(-1, new DateLiteral("2020-01-10"), new DateTimeLiteral("2020-01-10 00:00:01")); + checkCompareSameType(-1, new DateLiteral("2020-01-10"), new DateTimeV2Literal("2020-01-10 00:00:00.01")); + checkCompareDiffType(new DateLiteral("2020-01-10"), new StringLiteral("2020-01-1")); + checkCompareDiffType(new DateLiteral("2020-01-10"), new StringLiteral("2020-01-10")); + checkCompareDiffType(new DateLiteral("2020-01-10"), new StringLiteral("2020-01-10 ")); + checkCompareSameType(0, new DateV2Literal("2020-01-10"), new DateLiteral("2020-01-10")); + checkCompareSameType(0, new DateV2Literal("2020-01-10"), new DateV2Literal("2020-01-10")); + checkCompareSameType(0, new DateV2Literal("2020-01-10"), new DateTimeLiteral("2020-01-10 00:00:00")); + checkCompareSameType(0, new DateV2Literal("2020-01-10"), new DateTimeV2Literal("2020-01-10 00:00:00.00")); + checkCompareSameType(1, new DateV2Literal("2020-01-10"), new DateLiteral("2020-01-09")); + checkCompareSameType(1, new DateV2Literal("2020-01-10"), new DateV2Literal("2020-01-09")); + checkCompareSameType(1, new DateV2Literal("2020-01-10"), new DateTimeLiteral("2020-01-09 00:00:00")); + checkCompareSameType(1, new DateV2Literal("2020-01-10"), new DateTimeV2Literal("2020-01-09 00:00:00.00")); + checkCompareSameType(-1, new DateV2Literal("2020-01-10"), new DateLiteral("2020-01-11")); + checkCompareSameType(-1, new DateV2Literal("2020-01-10"), new DateV2Literal("2020-01-11")); + checkCompareSameType(-1, new DateV2Literal("2020-01-10"), new DateTimeLiteral("2020-01-10 00:00:01")); + checkCompareSameType(-1, new DateV2Literal("2020-01-10"), new DateTimeV2Literal("2020-01-10 00:00:00.01")); + checkCompareDiffType(new DateV2Literal("2020-01-10"), new StringLiteral("2020-01-1")); + checkCompareDiffType(new DateV2Literal("2020-01-10"), new StringLiteral("2020-01-10")); + checkCompareDiffType(new DateV2Literal("2020-01-10"), new StringLiteral("2020-01-10 ")); + checkCompareSameType(0, new DateTimeLiteral("2020-01-10"), new DateLiteral("2020-01-10")); + checkCompareSameType(0, new DateTimeLiteral("2020-01-10"), new DateV2Literal("2020-01-10")); + checkCompareSameType(0, new DateTimeLiteral("2020-01-10"), new DateTimeLiteral("2020-01-10 00:00:00")); + checkCompareSameType(0, new DateTimeLiteral("2020-01-10"), new DateTimeV2Literal("2020-01-10 00:00:00.00")); + checkCompareSameType(1, new DateTimeLiteral("2020-01-10"), new DateLiteral("2020-01-09")); + checkCompareSameType(1, new DateTimeLiteral("2020-01-10"), new DateV2Literal("2020-01-09")); + checkCompareSameType(1, new DateTimeLiteral("2020-01-10"), new DateTimeLiteral("2020-01-09 00:00:00")); + checkCompareSameType(1, new DateTimeLiteral("2020-01-10"), new DateTimeV2Literal("2020-01-09 00:00:00.00")); + checkCompareSameType(-1, new DateTimeLiteral("2020-01-10"), new DateLiteral("2020-01-11")); + checkCompareSameType(-1, new DateTimeLiteral("2020-01-10"), new DateV2Literal("2020-01-11")); + checkCompareSameType(-1, new DateTimeLiteral("2020-01-10"), new DateTimeLiteral("2020-01-10 00:00:01")); + checkCompareSameType(-1, new DateTimeLiteral("2020-01-10"), new DateTimeV2Literal("2020-01-10 00:00:00.01")); + checkCompareDiffType(new DateTimeLiteral("2020-01-10"), new StringLiteral("2020-01-10 00:00")); + checkCompareDiffType(new DateTimeLiteral("2020-01-10"), new StringLiteral("2020-01-10 00:00:00")); + checkCompareDiffType(new DateTimeLiteral("2020-01-10"), new StringLiteral("2020-01-10 00:00:00.000")); + checkCompareSameType(0, new DateTimeV2Literal("2020-01-10"), new DateLiteral("2020-01-10")); + checkCompareSameType(0, new DateTimeV2Literal("2020-01-10"), new DateV2Literal("2020-01-10")); + checkCompareSameType(0, new DateTimeV2Literal("2020-01-10"), new DateTimeLiteral("2020-01-10 00:00:00")); + checkCompareSameType(0, new DateTimeV2Literal("2020-01-10"), new DateTimeV2Literal("2020-01-10 00:00:00.00")); + checkCompareSameType(1, new DateTimeV2Literal("2020-01-10"), new DateLiteral("2020-01-09")); + checkCompareSameType(1, new DateTimeV2Literal("2020-01-10"), new DateV2Literal("2020-01-09")); + checkCompareSameType(1, new DateTimeV2Literal("2020-01-10"), new DateTimeLiteral("2020-01-09 00:00:00")); + checkCompareSameType(1, new DateTimeV2Literal("2020-01-10"), new DateTimeV2Literal("2020-01-09 00:00:00.00")); + checkCompareSameType(-1, new DateTimeV2Literal("2020-01-10"), new DateLiteral("2020-01-11")); + checkCompareSameType(-1, new DateTimeV2Literal("2020-01-10"), new DateV2Literal("2020-01-11")); + checkCompareSameType(-1, new DateTimeV2Literal("2020-01-10"), new DateTimeLiteral("2020-01-10 00:00:01")); + checkCompareSameType(-1, new DateTimeV2Literal("2020-01-10"), new DateTimeV2Literal("2020-01-10 00:00:00.01")); + checkCompareDiffType(new DateTimeV2Literal("2020-01-10"), new StringLiteral("2020-01-10 00:00:0")); + checkCompareDiffType(new DateTimeV2Literal("2020-01-10"), new StringLiteral("2020-01-10 00:00:00")); + checkCompareDiffType(new DateTimeV2Literal("2020-01-10"), new StringLiteral("2020-01-10 00:00:00.00")); + + // string type + checkCompareSameType(0, new CharLiteral("abc", -1), new CharLiteral("abc", -1)); + checkCompareSameType(1, new CharLiteral("abc", -1), new CharLiteral("abc", 1)); + checkCompareSameType(0, new CharLiteral("abc", -1), new StringLiteral("abc")); + checkCompareSameType(0, new CharLiteral("abc", -1), new VarcharLiteral("abc")); + checkCompareSameType(0, new CharLiteral("abc", -1), new VarcharLiteral("abc", -1)); + checkCompareSameType(1, new CharLiteral("abc", -1), new VarcharLiteral("abc", 1)); + checkCompareSameType(1, new CharLiteral("abc", -1), new CharLiteral("ab", -1)); + checkCompareSameType(1, new CharLiteral("abc", -1), new StringLiteral("ab")); + checkCompareSameType(1, new CharLiteral("abc", -1), new VarcharLiteral("ab")); + checkCompareSameType(1, new CharLiteral("abc", -1), new VarcharLiteral("ab", -1)); + checkCompareSameType(-1, new CharLiteral("abc", -1), new CharLiteral("abcd", -1)); + checkCompareSameType(0, new CharLiteral("abc", -1), new CharLiteral("abcd", 3)); + checkCompareSameType(-1, new CharLiteral("abc", -1), new StringLiteral("abcd")); + checkCompareSameType(-1, new CharLiteral("abc", -1), new VarcharLiteral("abcd")); + checkCompareSameType(-1, new CharLiteral("abc", -1), new VarcharLiteral("abcd", -1)); + checkCompareSameType(0, new CharLiteral("abc", -1), new VarcharLiteral("abcd", 3)); + + // ip type + checkCompareSameType(0, new IPv4Literal("170.0.0.100"), new IPv4Literal("170.0.0.100")); + checkCompareSameType(1, new IPv4Literal("170.0.0.100"), new IPv4Literal("160.0.0.200")); + checkCompareDiffType(new IPv4Literal("172.0.0.100"), new IPv6Literal("1080:0:0:0:8:800:200C:417A")); + checkCompareSameType(0, new IPv6Literal("1080:0:0:0:8:800:200C:417A"), new IPv6Literal("1080:0:0:0:8:800:200C:417A")); + checkCompareSameType(1, new IPv6Literal("1080:0:0:0:8:800:200C:417A"), new IPv6Literal("1000:0:0:0:8:800:200C:41AA")); + IPv4Literal ipv4 = new IPv4Literal("170.0.0.100"); + Assertions.assertEquals(ipv4, new IPv4Literal(ipv4.toLegacyLiteral().getStringValue())); + IPv6Literal ipv6 = new IPv6Literal("1080:0:0:0:8:800:200C:417A"); + Assertions.assertEquals(ipv6, new IPv6Literal(ipv6.toLegacyLiteral().getStringValue())); + + // null type and max type + Assertions.assertEquals(0, (new NullLiteral(IntegerType.INSTANCE)).compareTo(new NullLiteral(IntegerType.INSTANCE))); + Assertions.assertEquals(-1, (new NullLiteral(IntegerType.INSTANCE)).compareTo(new MaxLiteral(IntegerType.INSTANCE))); + Assertions.assertEquals(0, (new MaxLiteral(IntegerType.INSTANCE)).compareTo(new MaxLiteral(IntegerType.INSTANCE))); + } + + @Test + public void testComplex() throws Exception { + // array type + checkCompareSameType(0, + new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new IntegerLiteral(200))), + new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new IntegerLiteral(200)))); + checkCompareSameType(1, + new ArrayLiteral(ImmutableList.of(new IntegerLiteral(200))), + new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new IntegerLiteral(200)))); + checkCompareSameType(1, + new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new IntegerLiteral(200), new IntegerLiteral(1))), + new ArrayLiteral(ImmutableList.of(new IntegerLiteral(100), new IntegerLiteral(200)))); + checkComparableNoException("select array(1,2) = array(1, 2)"); + checkComparableNoException("select array(1,2) > array(1, 2)"); + + // json type + checkNotComparable("select cast ('[1, 2]' as json) = cast('[1, 2]' as json)", + "comparison predicate could not contains json type"); + checkNotComparable("select cast('[1, 2]' as json) > cast('[1, 2]' as json)", + "comparison predicate could not contains json type"); + + // map type + checkNotComparable("select map(1, 2) = map(1, 2)", + "comparison predicate could not contains complex type"); + checkNotComparable("select map(1, 2) > map(1, 2)", + "comparison predicate could not contains complex type"); + checkNotComparable("select cast('(1, 2)' as map) = cast('(1, 2)' as map)", + "comparison predicate could not contains complex type"); + + // struct type + checkNotComparable("select struct(1, 2) = struct(1, 2)", + "comparison predicate could not contains complex type"); + checkNotComparable("select struct(1, 2) > struct(1, 2)", + "comparison predicate could not contains complex type"); + } + + private void checkCompareSameType(int expect, ComparableLiteral left, ComparableLiteral right) { + Assertions.assertEquals(expect, left.compareTo(right)); + Assertions.assertEquals(- expect, right.compareTo(left)); + if (((Literal) left).dataType.equals(((Literal) right).dataType) + && !(left instanceof IPv4Literal) && !(left instanceof IPv6Literal)) { + Assertions.assertEquals(expect, ((Literal) left).toLegacyLiteral() + .compareTo(((Literal) right).toLegacyLiteral())); + Assertions.assertEquals(- expect, ((Literal) right).toLegacyLiteral() + .compareTo(((Literal) left).toLegacyLiteral())); + } + + Assertions.assertEquals(1, left.compareTo(new NullLiteral(IntegerType.INSTANCE))); + Assertions.assertEquals(-1, left.compareTo(new MaxLiteral(IntegerType.INSTANCE))); + } + + private void checkCompareDiffType(ComparableLiteral left, ComparableLiteral right) { + Assertions.assertThrowsExactly(RuntimeException.class, () -> left.compareTo(right)); + Assertions.assertThrowsExactly(RuntimeException.class, () -> right.compareTo(left)); + } + + private void checkComparableNoException(String sql) throws Exception { + ExceptionChecker.expectThrowsNoException(() -> executeSql(sql)); + } + + private void checkNotComparable(String sql, String expectErrMsg) throws Exception { + ExceptionChecker.expectThrowsWithMsg(IllegalStateException.class, expectErrMsg, + () -> executeSql(sql)); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java index 35ac71314d414e..9b51382cb9fe7c 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java +++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java @@ -616,6 +616,16 @@ public StmtExecutor getSqlStmtExecutor(String queryStr) throws Exception { } } + public void executeSql(String queryStr) throws Exception { + connectContext.getState().reset(); + StmtExecutor stmtExecutor = new StmtExecutor(connectContext, queryStr); + stmtExecutor.execute(); + if (connectContext.getState().getStateType() == QueryState.MysqlStateType.ERR + || connectContext.getState().getErrorCode() != null) { + throw new IllegalStateException(connectContext.getState().getErrorMessage()); + } + } + public void createDatabase(String db) throws Exception { String createDbStmtStr = "CREATE DATABASE " + db; CreateDbStmt createDbStmt = (CreateDbStmt) parseAndAnalyzeStmt(createDbStmtStr); diff --git a/regression-test/suites/nereids_p0/literal/test_compare_literal.groovy b/regression-test/suites/nereids_p0/literal/test_compare_literal.groovy new file mode 100644 index 00000000000000..eb66cf8790287c --- /dev/null +++ b/regression-test/suites/nereids_p0/literal/test_compare_literal.groovy @@ -0,0 +1,153 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. + +suite('test_compare_literal') { + for (def val in [true, false]) { + sql "set debug_skip_fold_constant=${val}" + + // ipv4 + test { + sql "select cast('170.0.0.100' as ipv4) = cast('170.0.0.100' as ipv4)" + result([[true]]) + } + test { + sql "select cast('170.0.0.100' as ipv4) >= cast('170.0.0.100' as ipv4)" + result([[true]]) + } + test { + sql "select cast('170.0.0.100' as ipv4) > cast('170.0.0.100' as ipv4)" + result([[false]]) + } + test { + sql "select cast('170.0.0.100' as ipv4) = cast('160.0.0.200' as ipv4)" + result([[false]]) + } + test { + sql "select cast('170.0.0.100' as ipv4) >= cast('160.0.0.200' as ipv4)" + result([[true]]) + } + test { + sql "select cast('170.0.0.100' as ipv4) > cast('160.0.0.200' as ipv4)" + result([[true]]) + } + test { + sql "select cast('170.0.0.100' as ipv4) < cast('160.0.0.200' as ipv4)" + result([[false]]) + } + + // ipv6 + test { + sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) = cast('1080:0:0:0:8:800:200C:417A' as ipv6)" + result([[true]]) + } + test { + sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) >= cast('1080:0:0:0:8:800:200C:417A' as ipv6)" + result([[true]]) + } + test { + sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) > cast('1080:0:0:0:8:800:200C:417A' as ipv6)" + result([[false]]) + } + test { + sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) = cast('1000:0:0:0:8:800:200C:41AA' as ipv6)" + result([[false]]) + } + test { + sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) >= cast('1000:0:0:0:8:800:200C:41AA' as ipv6)" + result([[true]]) + } + test { + sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) > cast('1000:0:0:0:8:800:200C:41AA' as ipv6)" + result([[true]]) + } + test { + sql "select cast('1080:0:0:0:8:800:200C:417A' as ipv6) < cast('1000:0:0:0:8:800:200C:41AA' as ipv6)" + result([[false]]) + } + + // array + test { + sql 'select array(5, 6) = array(5, 6)' + result([[true]]) + } + test { + sql 'select array(5, 6) >= array(5, 6)' + result([[true]]) + } + test { + sql 'select array(5, 6) > array(5, 6)' + result([[false]]) + } + test { + sql 'select array(5, 6) = array(5, 7)' + result([[false]]) + } + test { + sql 'select array(5, 6) >= array(5, 7)' + result([[false]]) + } + test { + sql 'select array(5, 6) > array(5, 7)' + result([[false]]) + } + test { + sql 'select array(5, 6) < array(5, 7)' + result([[true]]) + } + test { + sql 'select array(5, 6) < array(5, 6, 1)' + result([[true]]) + } + test { + sql 'select array(5, 6) < array(6)' + result([[true]]) + } + } + + // test not comparable + sql 'set debug_skip_fold_constant=false' + + // json + test { + sql "select cast('[1, 2]' as json) = cast('[1, 2]' as json)" + exception 'comparison predicate could not contains json type' + } + test { + sql "select cast('[1, 2]' as json) > cast('[1, 2]' as json)" + exception 'comparison predicate could not contains json type' + } + + // map + test { + sql 'select map(1, 2) = map(1, 2)' + exception 'comparison predicate could not contains complex type' + } + test { + sql 'select map(1, 2) > map(1, 2)' + exception 'comparison predicate could not contains complex type' + } + + // struct + test { + sql 'select struct(1, 2) = struct(1, 2)' + exception 'comparison predicate could not contains complex type' + } + test { + sql 'select struct(1, 2) > struct(1, 2)' + exception 'comparison predicate could not contains complex type' + } +}