Skip to content

Commit

Permalink
[enhance](nereids) date_add, date_sub, date_diff, date_floor, date_ce…
Browse files Browse the repository at this point in the history
…il function implement Monotonic (#44943)

date_add, date_sub, date_diff, date_floor, date_ceil function implement Monotonic, so we can do prune range partition for this functions, for example `date_add(dt, 1) = '2024-01-01'`
  • Loading branch information
feiniaofeiafei authored Dec 21, 2024
1 parent 0ab4eae commit f6071a3
Show file tree
Hide file tree
Showing 46 changed files with 1,019 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.expressions.literal.MaxLiteral;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BooleanType;
import org.apache.doris.nereids.util.ExpressionUtils;
Expand Down Expand Up @@ -807,22 +808,29 @@ private EvaluateRangeResult computeMonotonicFunctionRange(EvaluateRangeResult re
: new NonNullable(funcChild));
partitionSlotContainsNull.put((Expression) func, withNullable.nullable());

if (!result.childrenResult.get(0).columnRanges.containsKey(funcChild)) {
if (!result.childrenResult.get(childIndex).columnRanges.containsKey(funcChild)) {
return result;
}
ColumnRange childRange = result.childrenResult.get(0).columnRanges.get(funcChild);
ColumnRange childRange = result.childrenResult.get(childIndex).columnRanges.get(funcChild);
if (childRange.isEmptyRange() || childRange.asRanges().size() != 1
|| (!childRange.span().hasLowerBound() && !childRange.span().hasUpperBound())) {
return result;
}
Range<ColumnBound> span = childRange.span();
// null means positive infinity or negative infinity
Literal lower = span.hasLowerBound() ? span.lowerEndpoint().getValue() : null;
Literal upper = span.hasUpperBound() && !(span.upperEndpoint().getValue() instanceof MaxLiteral)
? span.upperEndpoint().getValue() : null;
if (!func.isMonotonic(lower, upper)) {
return result;
}
Expression lowerValue = lower != null ? FoldConstantRuleOnFE.evaluate(func.withConstantArgs(lower),
expressionRewriteContext) : null;
Expression upperValue = upper != null ? FoldConstantRuleOnFE.evaluate(func.withConstantArgs(upper),
expressionRewriteContext) : null;
if (lowerValue instanceof NullLiteral || upperValue instanceof NullLiteral) {
return result;
}
if (!func.isPositive()) {
Expression temp = lowerValue;
lowerValue = upperValue;
Expand All @@ -842,6 +850,9 @@ private EvaluateRangeResult computeMonotonicFunctionRange(EvaluateRangeResult re
if (upperValue instanceof Literal) {
newRange = newRange.withUpperBound((Literal) upperValue);
}
if (newRange.isEmptyRange() || !newRange.span().hasLowerBound() && !newRange.span().hasUpperBound()) {
return result;
}
context.rangeMap.put((Expression) func, newRange);
newRanges.put((Expression) func, newRange);
return new EvaluateRangeResult((Expression) func, newRanges, result.childrenResult);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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.functions;

import org.apache.doris.nereids.trees.expressions.literal.Literal;

/** monotonicity for XX_ADD XX_SUB */
public interface DateAddSubMonotonic extends Monotonic {
@Override
default boolean isMonotonic(Literal lower, Literal upper) {
return child(1) instanceof Literal;
}

@Override
default boolean isPositive() {
return true;
}

@Override
default int getMonotonicFunctionChildIndex() {
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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.functions;

import org.apache.doris.nereids.trees.expressions.literal.Literal;

/** monotonicity of XX_CEIL and XX_FLOOR */
public interface DateCeilFloorMonotonic extends Monotonic {
@Override
default boolean isMonotonic(Literal lower, Literal upper) {
switch (arity()) {
case 1:
return true;
case 2:
return !(child(0) instanceof Literal) && child(1) instanceof Literal;
case 3:
return !(child(0) instanceof Literal) && child(1) instanceof Literal && child(2) instanceof Literal;
default:
return false;
}
}

@Override
default boolean isPositive() {
return true;
}

@Override
default int getMonotonicFunctionChildIndex() {
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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.functions;

import org.apache.doris.nereids.trees.expressions.literal.Literal;

/** monotonicity for XX_DIFF */
public interface DateDiffMonotonic extends Monotonic {
@Override
default boolean isMonotonic(Literal lower, Literal upper) {
return !(child(0) instanceof Literal) && child(1) instanceof Literal
|| child(0) instanceof Literal && !(child(1) instanceof Literal);
}

@Override
default boolean isPositive() {
return child(1) instanceof Literal;
}

@Override
default int getMonotonicFunctionChildIndex() {
return child(1) instanceof Literal ? 0 : 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@
package org.apache.doris.nereids.trees.expressions.functions;

import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.literal.Literal;

/** monotonicity of expressions */
public interface Monotonic extends ExpressionTrait {
default boolean isMonotonic(Literal lower, Literal upper) {
return true;
}

// true means that the function is an increasing function
boolean isPositive();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
import org.apache.doris.nereids.trees.expressions.functions.DateCeilFloorMonotonic;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
Expand All @@ -37,7 +38,7 @@
* ScalarFunction 'day_ceil'. This class is generated by GenerateFunction.
*/
public class DayCeil extends ScalarFunction
implements ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral {
implements ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral, DateCeilFloorMonotonic {

public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(DateTimeV2Type.SYSTEM_DEFAULT).args(DateTimeV2Type.SYSTEM_DEFAULT),
Expand Down Expand Up @@ -106,4 +107,18 @@ public List<FunctionSignature> getSignatures() {
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitDayCeil(this, context);
}

@Override
public Expression withConstantArgs(Expression literal) {
switch (arity()) {
case 1:
return new DayCeil(literal);
case 2:
return new DayCeil(literal, child(1));
case 3:
return new DayCeil(literal, child(1), child(2));
default:
throw new IllegalStateException("The function " + getName() + " has invalid child number.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
import org.apache.doris.nereids.trees.expressions.functions.DateCeilFloorMonotonic;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
Expand All @@ -37,7 +38,7 @@
* ScalarFunction 'day_floor'. This class is generated by GenerateFunction.
*/
public class DayFloor extends ScalarFunction
implements ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral {
implements ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral, DateCeilFloorMonotonic {

public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(DateTimeV2Type.SYSTEM_DEFAULT).args(DateTimeV2Type.SYSTEM_DEFAULT),
Expand Down Expand Up @@ -106,4 +107,18 @@ public List<FunctionSignature> getSignatures() {
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitDayFloor(this, context);
}

@Override
public Expression withConstantArgs(Expression literal) {
switch (arity()) {
case 1:
return new DayFloor(literal);
case 2:
return new DayFloor(literal, child(1));
case 3:
return new DayFloor(literal, child(1), child(2));
default:
throw new IllegalStateException("The function " + getName() + " has invalid child number.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.doris.common.Config;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic;
import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.functions.PropagateNullableOnDateLikeV2Args;
import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
Expand All @@ -41,7 +42,7 @@
*/
public class DaysAdd extends ScalarFunction
implements BinaryExpression, ExplicitlyCastableSignature,
ComputeSignatureForDateArithmetic, PropagateNullableOnDateLikeV2Args {
ComputeSignatureForDateArithmetic, PropagateNullableOnDateLikeV2Args, DateAddSubMonotonic {
// When enable_date_conversion is true, we prefer to V2 signature.
// This preference follows original planner. refer to ScalarType.getDefaultDateType()
private static final List<FunctionSignature> SIGNATURES = Config.enable_date_conversion ? ImmutableList.of(
Expand Down Expand Up @@ -77,4 +78,9 @@ public List<FunctionSignature> getSignatures() {
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitDaysAdd(this, context);
}

@Override
public Expression withConstantArgs(Expression literal) {
return new DaysAdd(literal, child(1));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@

import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.DateDiffMonotonic;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.functions.PropagateNullableOnDateLikeV2Args;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
Expand All @@ -37,7 +39,7 @@
* ScalarFunction 'days_diff'. This class is generated by GenerateFunction.
*/
public class DaysDiff extends ScalarFunction
implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullableOnDateLikeV2Args {
implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullableOnDateLikeV2Args, DateDiffMonotonic {

private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(BigIntType.INSTANCE)
Expand Down Expand Up @@ -73,4 +75,13 @@ public List<FunctionSignature> getSignatures() {
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitDaysDiff(this, context);
}

@Override
public Expression withConstantArgs(Expression literal) {
if (child(1) instanceof Literal) {
return new DaysDiff(literal, child(1));
} else {
return new DaysDiff(child(0), literal);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.doris.common.Config;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic;
import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.functions.PropagateNullableOnDateLikeV2Args;
import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
Expand All @@ -41,7 +42,7 @@
*/
public class DaysSub extends ScalarFunction
implements BinaryExpression, ExplicitlyCastableSignature,
ComputeSignatureForDateArithmetic, PropagateNullableOnDateLikeV2Args {
ComputeSignatureForDateArithmetic, PropagateNullableOnDateLikeV2Args, DateAddSubMonotonic {
// When enable_date_conversion is true, we prefer to V2 signature.
// This preference follows original planner. refer to ScalarType.getDefaultDateType()
private static final List<FunctionSignature> SIGNATURES = Config.enable_date_conversion ? ImmutableList.of(
Expand Down Expand Up @@ -77,4 +78,9 @@ public List<FunctionSignature> getSignatures() {
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitDaysSub(this, context);
}

@Override
public Expression withConstantArgs(Expression literal) {
return new DaysSub(literal, child(1));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
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.functions.PropagateNullLiteral;
import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
Expand All @@ -36,7 +37,7 @@
* ScalarFunction 'from_days'. This class is generated by GenerateFunction.
*/
public class FromDays extends ScalarFunction
implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral {
implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral, Monotonic {

public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(DateV2Type.INSTANCE).args(IntegerType.INSTANCE)
Expand Down Expand Up @@ -67,4 +68,19 @@ public List<FunctionSignature> getSignatures() {
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitFromDays(this, context);
}

@Override
public boolean isPositive() {
return true;
}

@Override
public int getMonotonicFunctionChildIndex() {
return 0;
}

@Override
public Expression withConstantArgs(Expression literal) {
return new FromDays(literal);
}
}
Loading

0 comments on commit f6071a3

Please sign in to comment.