[Feature](Nereids) add executable function to support fold constant for functions (#18209)

1. Add date-time functions for fold constant for Nereids.
This is the list of executable date-time function nereids supports up to now:
- now()
- now(int)
- current_timestamp()
- current_timestamp(int)
- localtime()
- localtimestamp()
- curdate()
- current_date()
- curtime()
- current_time()
- date_{add/sub}(),{years/months/days/hours/minutes/seconds}_{add/sub}()
- datediff()
- {date/datev2}()
- {year/quarter/month/day/hour/minute/second}()
- dayof{year/month/week}()
- date_format()
- date_trunc()
- from_days()
- last_day()
- to_monday()
- from_unixtime()
- unix_timestamp()
- utc_timestamp()
- to_date()
- to_days()
- str_to_date()
- makedate()

2. solved problem:
- enable datev2/datetimev2 default.
- refactor Nereids foldConstantOnFE and support fold nested expression.
- separate the executable into multi-files for easily-reading and adding new functions
This commit is contained in:
mch_ucchi
2023-05-17 21:26:31 +08:00
committed by GitHub
parent 1eb929e1ca
commit 1d05feea1b
45 changed files with 6146 additions and 818 deletions

View File

@ -686,8 +686,6 @@ public class AnalyticExpr extends Expr {
Preconditions.checkState(getFnCall().getChildren().size() == 3);
}
Type type = getFnCall().getChildren().get(2).getType();
try {
if (!Type.matchExactType(getFnCall().getChildren().get(0).getType(),
getFnCall().getChildren().get(2).getType())) {
@ -700,10 +698,10 @@ public class AnalyticExpr extends Expr {
+ getFnCall().getChildren().get(0).getType());
}
if (getFnCall().getChildren().get(2) instanceof CastExpr) {
throw new AnalysisException("Type = " + type + " can't not convert to "
+ getFnCall().getChildren().get(0).getType());
}
// if (getFnCall().getChildren().get(2) instanceof CastExpr) {
// throw new AnalysisException("Type = " + type + " can't not convert to "
// + getFnCall().getChildren().get(0).getType());
// }
// check the value whether out of range
checkDefaultValue(analyzer);

View File

@ -1349,6 +1349,7 @@ public class FunctionCallExpr extends Expr {
uncheckedCastChild(assignmentCompatibleType, 2);
}
}
childTypes[0] = Type.BOOLEAN;
childTypes[1] = assignmentCompatibleType;
childTypes[2] = assignmentCompatibleType;
fn = getBuiltinFunction(fnName.getFunction(), childTypes,

View File

@ -24,7 +24,6 @@ import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.thrift.TExprNode;
@ -146,10 +145,6 @@ public class TimestampArithmeticExpr extends Expr {
if (t1 == PrimitiveType.DATEV2) {
return Type.DATEV2;
}
if (Config.enable_date_conversion
&& PrimitiveType.isImplicitCast(t1, PrimitiveType.DATETIMEV2)) {
return Type.DATETIMEV2;
}
if (PrimitiveType.isImplicitCast(t1, PrimitiveType.DATETIME)) {
return Type.DATETIME;
}

View File

@ -51,6 +51,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.CurrentCatalo
import org.apache.doris.nereids.trees.expressions.functions.scalar.CurrentUser;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Database;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Date;
import org.apache.doris.nereids.trees.expressions.functions.scalar.If;
import org.apache.doris.nereids.trees.expressions.functions.scalar.User;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Version;
import org.apache.doris.nereids.trees.expressions.literal.ArrayLiteral;
@ -69,11 +70,12 @@ import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.util.ExpressionUtils;
import org.apache.doris.qe.GlobalVariable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* evaluate an expression on fe.
@ -89,24 +91,12 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
} else if (expr instanceof AggregateExpression && ((AggregateExpression) expr).getFunction().isDistinct()) {
return expr;
}
expr = rewriteChildren(expr, ctx);
if (expr instanceof PropagateNullable
&& !(expr instanceof NullableAggregateFunction)
&& argsHasNullLiteral(expr)) {
return new NullLiteral(expr.getDataType());
}
return expr.accept(this, ctx);
}
/**
* process constant expression.
*/
@Override
public Expression visit(Expression expr, ExpressionRewriteContext ctx) {
return expr;
}
@Override
public Expression visitSlot(Slot slot, ExpressionRewriteContext context) {
return slot;
@ -119,24 +109,30 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitEqualTo(EqualTo equalTo, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(equalTo)) {
return equalTo;
equalTo = rewriteChildren(equalTo, context);
Optional<Expression> checkedExpr = preProcess(equalTo);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return BooleanLiteral.of(((Literal) equalTo.left()).compareTo((Literal) equalTo.right()) == 0);
}
@Override
public Expression visitGreaterThan(GreaterThan greaterThan, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(greaterThan)) {
return greaterThan;
greaterThan = rewriteChildren(greaterThan, context);
Optional<Expression> checkedExpr = preProcess(greaterThan);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return BooleanLiteral.of(((Literal) greaterThan.left()).compareTo((Literal) greaterThan.right()) > 0);
}
@Override
public Expression visitGreaterThanEqual(GreaterThanEqual greaterThanEqual, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(greaterThanEqual)) {
return greaterThanEqual;
greaterThanEqual = rewriteChildren(greaterThanEqual, context);
Optional<Expression> checkedExpr = preProcess(greaterThanEqual);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return BooleanLiteral.of(((Literal) greaterThanEqual.left())
.compareTo((Literal) greaterThanEqual.right()) >= 0);
@ -144,24 +140,30 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitLessThan(LessThan lessThan, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(lessThan)) {
return lessThan;
lessThan = rewriteChildren(lessThan, context);
Optional<Expression> checkedExpr = preProcess(lessThan);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return BooleanLiteral.of(((Literal) lessThan.left()).compareTo((Literal) lessThan.right()) < 0);
}
@Override
public Expression visitLessThanEqual(LessThanEqual lessThanEqual, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(lessThanEqual)) {
return lessThanEqual;
lessThanEqual = rewriteChildren(lessThanEqual, context);
Optional<Expression> checkedExpr = preProcess(lessThanEqual);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return BooleanLiteral.of(((Literal) lessThanEqual.left()).compareTo((Literal) lessThanEqual.right()) <= 0);
}
@Override
public Expression visitNullSafeEqual(NullSafeEqual nullSafeEqual, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(nullSafeEqual)) {
return nullSafeEqual;
nullSafeEqual = rewriteChildren(nullSafeEqual, context);
Optional<Expression> checkedExpr = preProcess(nullSafeEqual);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
Literal l = (Literal) nullSafeEqual.left();
Literal r = (Literal) nullSafeEqual.right();
@ -176,8 +178,10 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitNot(Not not, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(not)) {
return not;
not = rewriteChildren(not, context);
Optional<Expression> checkedExpr = preProcess(not);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return BooleanLiteral.of(!((BooleanLiteral) not.child()).getValue());
}
@ -213,22 +217,20 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitAnd(And and, ExpressionRewriteContext context) {
if (and.getArguments().stream().anyMatch(BooleanLiteral.FALSE::equals)) {
return BooleanLiteral.FALSE;
List<Expression> nonTrueLiteral = Lists.newArrayList();
for (Expression e : and.children()) {
e = e.accept(this, context);
if (BooleanLiteral.FALSE.equals(e)) {
return BooleanLiteral.FALSE;
} else if (e instanceof NullLiteral) {
return e;
} else if (!BooleanLiteral.TRUE.equals(e)) {
nonTrueLiteral.add(e);
}
}
if (argsHasNullLiteral(and)) {
return new NullLiteral(BooleanType.INSTANCE);
}
List<Expression> nonTrueLiteral = and.children()
.stream()
.filter(conjunct -> !BooleanLiteral.TRUE.equals(conjunct))
.collect(ImmutableList.toImmutableList());
if (nonTrueLiteral.isEmpty()) {
return BooleanLiteral.TRUE;
}
if (nonTrueLiteral.size() == and.arity()) {
return and;
}
if (nonTrueLiteral.size() == 1) {
return nonTrueLiteral.get(0);
}
@ -237,22 +239,20 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitOr(Or or, ExpressionRewriteContext context) {
if (or.getArguments().stream().anyMatch(BooleanLiteral.TRUE::equals)) {
return BooleanLiteral.TRUE;
List<Expression> nonFalseLiteral = Lists.newArrayList();
for (Expression e : or.children()) {
e = e.accept(this, context);
if (BooleanLiteral.TRUE.equals(e)) {
return BooleanLiteral.TRUE;
} else if (e instanceof NullLiteral) {
return e;
} else if (!BooleanLiteral.FALSE.equals(e)) {
nonFalseLiteral.add(e);
}
}
if (ExpressionUtils.isAllNullLiteral(or.getArguments())) {
return new NullLiteral(BooleanType.INSTANCE);
}
List<Expression> nonFalseLiteral = or.children()
.stream()
.filter(conjunct -> !BooleanLiteral.FALSE.equals(conjunct))
.collect(ImmutableList.toImmutableList());
if (nonFalseLiteral.isEmpty()) {
return BooleanLiteral.FALSE;
}
if (nonFalseLiteral.size() == or.arity()) {
return or;
}
if (nonFalseLiteral.size() == 1) {
return nonFalseLiteral.get(0);
}
@ -266,8 +266,10 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitCast(Cast cast, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(cast)) {
return cast;
cast = rewriteChildren(cast, context);
Optional<Expression> checkedExpr = preProcess(cast);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
Expression child = cast.child();
// todo: process other null case
@ -287,23 +289,31 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitBoundFunction(BoundFunction boundFunction, ExpressionRewriteContext context) {
boundFunction = rewriteChildren(boundFunction, context);
//functions, like current_date, do not have arg
if (boundFunction.getArguments().isEmpty()) {
return boundFunction;
}
if (!ExpressionUtils.isAllLiteral(boundFunction.getArguments())) {
return boundFunction;
Optional<Expression> checkedExpr = preProcess(boundFunction);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return ExpressionEvaluator.INSTANCE.eval(boundFunction);
}
@Override
public Expression visitBinaryArithmetic(BinaryArithmetic binaryArithmetic, ExpressionRewriteContext context) {
binaryArithmetic = rewriteChildren(binaryArithmetic, context);
Optional<Expression> checkedExpr = preProcess(binaryArithmetic);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return ExpressionEvaluator.INSTANCE.eval(binaryArithmetic);
}
@Override
public Expression visitCaseWhen(CaseWhen caseWhen, ExpressionRewriteContext context) {
caseWhen = rewriteChildren(caseWhen, context);
Expression newDefault = null;
boolean foundNewDefault = false;
@ -335,50 +345,68 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
return new CaseWhen(whenClauses, defaultResult);
}
@Override
public Expression visitIf(If ifExpr, ExpressionRewriteContext context) {
ifExpr = rewriteChildren(ifExpr, context);
if (ifExpr.child(0) instanceof NullLiteral || ifExpr.child(0).equals(BooleanLiteral.FALSE)) {
return ifExpr.child(2);
} else if (ifExpr.child(0).equals(BooleanLiteral.TRUE)) {
return ifExpr.child(1);
}
return ifExpr;
}
@Override
public Expression visitInPredicate(InPredicate inPredicate, ExpressionRewriteContext context) {
inPredicate = rewriteChildren(inPredicate, context);
Optional<Expression> checkedExpr = preProcess(inPredicate);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
// now the inPredicate contains literal only.
Expression value = inPredicate.child(0);
if (value.isNullLiteral()) {
return new NullLiteral(BooleanType.INSTANCE);
}
boolean valueIsLiteral = value.isLiteral();
if (!valueIsLiteral) {
return inPredicate;
}
boolean hasNull = false;
boolean isOptionContainsNull = false;
for (Expression item : inPredicate.getOptions()) {
if (item.isNullLiteral()) {
hasNull = true;
}
if (valueIsLiteral && value.equals(item)) {
if (value.equals(item)) {
return BooleanLiteral.TRUE;
} else if (item.isNullLiteral()) {
isOptionContainsNull = true;
}
}
if (hasNull) {
return NullLiteral.INSTANCE;
}
return BooleanLiteral.FALSE;
return isOptionContainsNull
? new NullLiteral(BooleanType.INSTANCE)
: BooleanLiteral.FALSE;
}
@Override
public Expression visitIsNull(IsNull isNull, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(isNull)) {
return isNull;
isNull = rewriteChildren(isNull, context);
Optional<Expression> checkedExpr = preProcess(isNull);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return Literal.of(isNull.child().nullable());
}
@Override
public Expression visitTimestampArithmetic(TimestampArithmetic arithmetic, ExpressionRewriteContext context) {
arithmetic = rewriteChildren(arithmetic, context);
Optional<Expression> checkedExpr = preProcess(arithmetic);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
return ExpressionEvaluator.INSTANCE.eval(arithmetic);
}
@Override
public Expression visitArray(Array array, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(array)) {
return array;
array = rewriteChildren(array, context);
Optional<Expression> checkedExpr = preProcess(array);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
List<Literal> arguments = (List) array.getArguments();
return new ArrayLiteral(arguments);
@ -386,8 +414,10 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
@Override
public Expression visitDate(Date date, ExpressionRewriteContext context) {
if (!allArgsIsAllLiteral(date)) {
return date;
date = rewriteChildren(date, context);
Optional<Expression> checkedExpr = preProcess(date);
if (checkedExpr.isPresent()) {
return checkedExpr.get();
}
Literal child = (Literal) date.child();
if (child instanceof NullLiteral) {
@ -409,17 +439,8 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
return new StringLiteral(GlobalVariable.version);
}
private Expression rewriteChildren(Expression expr, ExpressionRewriteContext ctx) {
List<Expression> newChildren = new ArrayList<>();
boolean hasNewChildren = false;
for (Expression child : expr.children()) {
Expression newChild = rewrite(child, ctx);
if (newChild != child) {
hasNewChildren = true;
}
newChildren.add(newChild);
}
return hasNewChildren ? expr.withChildren(newChildren) : expr;
private <E> E rewriteChildren(Expression expr, ExpressionRewriteContext ctx) {
return (E) super.visit(expr, ctx);
}
private boolean allArgsIsAllLiteral(Expression expression) {
@ -429,5 +450,16 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule {
private boolean argsHasNullLiteral(Expression expression) {
return ExpressionUtils.hasNullLiteral(expression.getArguments());
}
private Optional<Expression> preProcess(Expression expression) {
if (expression instanceof PropagateNullable && !(expression instanceof NullableAggregateFunction)
&& argsHasNullLiteral(expression)) {
return Optional.of(new NullLiteral(expression.getDataType()));
}
if (!allArgsIsAllLiteral(expression)) {
return Optional.of(expression);
}
return Optional.empty();
}
}

View File

@ -22,6 +22,7 @@ import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
import org.apache.doris.nereids.trees.expressions.EqualTo;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.InPredicate;
import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
import org.apache.doris.nereids.util.ExpressionUtils;
import com.google.common.base.Preconditions;
@ -52,13 +53,17 @@ public class InPredicateToEqualToRule extends AbstractExpressionRewriteRule {
Expression cmpExpr = inPredicate.getCompareExpr();
List<Expression> options = inPredicate.getOptions();
Preconditions.checkArgument(options.size() > 0, "InPredicate.options should not be empty");
if (options.size() > 2) {
if (options.size() > 2 || isOptionContainNullLiteral(options)) {
return new InPredicate(cmpExpr.accept(this, context), options);
}
Expression newCmpExpr = cmpExpr.accept(this, context);
List<Expression> disjunction = options.stream()
.map(option -> new EqualTo(newCmpExpr, option.accept(this, context)))
.collect(Collectors.toList());
return ExpressionUtils.or(disjunction);
return disjunction.isEmpty() ? BooleanLiteral.FALSE : ExpressionUtils.or(disjunction);
}
private boolean isOptionContainNullLiteral(List<Expression> options) {
return options.stream().anyMatch(Expression::isNullLiteral);
}
}

View File

@ -174,7 +174,7 @@ public class SimplifyComparisonPredicate extends AbstractExpressionRewriteRule {
private Expression migrateToDateV2(DateTimeLiteral l, AdjustType type) {
DateV2Literal d = new DateV2Literal(l.getYear(), l.getMonth(), l.getDay());
if (type == AdjustType.UPPER && (l.getHour() != 0 || l.getMinute() != 0 || l.getSecond() != 0)) {
d = d.plusDays(1);
d = ((DateV2Literal) d.plusDays(1));
}
return d;
}

View File

@ -19,13 +19,21 @@ package org.apache.doris.nereids.trees.expressions;
import org.apache.doris.catalog.Env;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.nereids.trees.expressions.functions.ExecutableFunctions;
import org.apache.doris.nereids.trees.expressions.functions.BoundFunction;
import org.apache.doris.nereids.trees.expressions.functions.ExpressionTrait;
import org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
import org.apache.doris.nereids.trees.expressions.functions.executable.DateTimeAcquire;
import org.apache.doris.nereids.trees.expressions.functions.executable.DateTimeArithmetic;
import org.apache.doris.nereids.trees.expressions.functions.executable.DateTimeExtractAndTransform;
import org.apache.doris.nereids.trees.expressions.functions.executable.ExecutableFunctions;
import org.apache.doris.nereids.trees.expressions.functions.executable.NumericArithmetic;
import org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.DecimalV3Type;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import java.lang.reflect.InvocationTargetException;
@ -65,6 +73,10 @@ public enum ExpressionEvaluator {
TimestampArithmetic arithmetic = (TimestampArithmetic) expression;
fnName = arithmetic.getFuncName();
args = new DataType[]{arithmetic.left().getDataType(), arithmetic.right().getDataType()};
} else if (expression instanceof BoundFunction) {
BoundFunction function = ((BoundFunction) expression);
fnName = function.getName();
args = function.children().stream().map(ExpressionTrait::getDataType).toArray(DataType[]::new);
}
if ((Env.getCurrentEnv().isNullResultWithOneNullParamFunction(fnName))) {
@ -123,15 +135,24 @@ public enum ExpressionEvaluator {
}
ImmutableMultimap.Builder<String, FunctionInvoker> mapBuilder =
new ImmutableMultimap.Builder<String, FunctionInvoker>();
Class clazz = ExecutableFunctions.class;
for (Method method : clazz.getDeclaredMethods()) {
ExecFunctionList annotationList = method.getAnnotation(ExecFunctionList.class);
if (annotationList != null) {
for (ExecFunction f : annotationList.value()) {
registerFEFunction(mapBuilder, method, f);
List<Class> classes = ImmutableList.of(
DateTimeExtractAndTransform.class,
ExecutableFunctions.class,
DateLiteral.class,
DateTimeArithmetic.class,
DateTimeAcquire.class,
NumericArithmetic.class
);
for (Class cls : classes) {
for (Method method : cls.getDeclaredMethods()) {
ExecFunctionList annotationList = method.getAnnotation(ExecFunctionList.class);
if (annotationList != null) {
for (ExecFunction f : annotationList.value()) {
registerFEFunction(mapBuilder, method, f);
}
}
registerFEFunction(mapBuilder, method, method.getAnnotation(ExecFunction.class));
}
registerFEFunction(mapBuilder, method, method.getAnnotation(ExecFunction.class));
}
this.functions = mapBuilder.build();
}

View File

@ -0,0 +1,100 @@
// 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.executable;
import org.apache.doris.nereids.trees.expressions.ExecFunction;
import org.apache.doris.nereids.trees.expressions.Expression;
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;
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
import java.time.LocalDateTime;
import java.util.TimeZone;
/**
* executable functions:
* unclassified date function
*/
public class DateTimeAcquire {
/**
* date acquire function: now
*/
@ExecFunction(name = "now", argTypes = {}, returnType = "DATETIME")
public static Expression now() {
return DateTimeLiteral.fromJavaDateType(LocalDateTime.now());
}
@ExecFunction(name = "now", argTypes = {"INT"}, returnType = "DATETIMEV2")
public static Expression now(IntegerLiteral precision) {
return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(),
precision.getValue());
}
/**
* date acquire function: current_timestamp
*/
@ExecFunction(name = "current_timestamp", argTypes = {}, returnType = "DATETIME")
public static Expression currentTimestamp() {
return DateTimeLiteral.fromJavaDateType(LocalDateTime.now());
}
@ExecFunction(name = "current_timestamp", argTypes = {"INT"}, returnType = "DATETIMEV2")
public static Expression currentTimestamp(IntegerLiteral precision) {
return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(), precision.getValue());
}
/**
* date acquire function: localtime/localtimestamp
*/
@ExecFunction(name = "localtime", argTypes = {}, returnType = "DATETIME")
public static Expression localTime() {
return DateTimeLiteral.fromJavaDateType(LocalDateTime.now(TimeZone.getDefault().toZoneId()));
}
@ExecFunction(name = "localtimestamp", argTypes = {}, returnType = "DATETIME")
public static Expression localTimestamp() {
return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(TimeZone.getDefault().toZoneId()));
}
/**
* date acquire function: current_date
*/
@ExecFunction(name = "curdate", argTypes = {}, returnType = "DATE")
public static Expression curDate() {
return DateLiteral.fromJavaDateType(LocalDateTime.now());
}
@ExecFunction(name = "current_date", argTypes = {}, returnType = "DATE")
public static Expression currentDate() {
return DateLiteral.fromJavaDateType(LocalDateTime.now());
}
/**
* date acquire function: current_time
*/
@ExecFunction(name = "curtime", argTypes = {}, returnType = "DATETIME")
public static Expression curTime() {
return DateTimeLiteral.fromJavaDateType(LocalDateTime.now());
}
@ExecFunction(name = "current_time", argTypes = {}, returnType = "DATETIME")
public static Expression currentTime() {
return DateTimeLiteral.fromJavaDateType(LocalDateTime.now());
}
}

View File

@ -0,0 +1,337 @@
// 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.executable;
import org.apache.doris.nereids.trees.expressions.ExecFunction;
import org.apache.doris.nereids.trees.expressions.Expression;
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;
import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
/**
* executable function:
* date_add/sub, years/months/days/hours/minutes/seconds_add/sub, datediff
*/
public class DateTimeArithmetic {
/**
* datetime arithmetic function date-add.
*/
@ExecFunction(name = "date_add", argTypes = {"DATE", "INT"}, returnType = "DATE")
public static Expression dateAdd(DateLiteral date, IntegerLiteral day) {
return daysAdd(date, day);
}
@ExecFunction(name = "date_add", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression dateAdd(DateTimeLiteral date, IntegerLiteral day) {
return daysAdd(date, day);
}
@ExecFunction(name = "date_add", argTypes = {"DATEV2", "INT"}, returnType = "DATEV2")
public static Expression dateAdd(DateV2Literal date, IntegerLiteral day) {
return daysAdd(date, day);
}
@ExecFunction(name = "date_add", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression dateAdd(DateTimeV2Literal date, IntegerLiteral day) {
return daysAdd(date, day);
}
/**
* datetime arithmetic function date-sub.
*/
@ExecFunction(name = "date_sub", argTypes = {"DATE", "INT"}, returnType = "DATE")
public static Expression dateSub(DateLiteral date, IntegerLiteral day) {
return dateAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "date_sub", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression dateSub(DateTimeLiteral date, IntegerLiteral day) {
return dateAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "date_sub", argTypes = {"DATEV2", "INT"}, returnType = "DATEV2")
public static Expression dateSub(DateV2Literal date, IntegerLiteral day) {
return dateAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "date_sub", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression dateSub(DateTimeV2Literal date, IntegerLiteral day) {
return dateAdd(date, new IntegerLiteral(-day.getValue()));
}
/**
* datetime arithmetic function years-add.
*/
@ExecFunction(name = "years_add", argTypes = {"DATE", "INT"}, returnType = "DATE")
public static Expression yearsAdd(DateLiteral date, IntegerLiteral year) {
return date.plusYears(year.getValue());
}
@ExecFunction(name = "years_add", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression yearsAdd(DateTimeLiteral date, IntegerLiteral year) {
return date.plusYears(year.getValue());
}
@ExecFunction(name = "years_add", argTypes = {"DATEV2", "INT"}, returnType = "DATEV2")
public static Expression yearsAdd(DateV2Literal date, IntegerLiteral year) {
return date.plusYears(year.getValue());
}
@ExecFunction(name = "years_add", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression yearsAdd(DateTimeV2Literal date, IntegerLiteral year) {
return date.plusYears(year.getValue());
}
/**
* datetime arithmetic function months-add.
*/
@ExecFunction(name = "months_add", argTypes = {"DATE", "INT"}, returnType = "DATE")
public static Expression monthsAdd(DateLiteral date, IntegerLiteral month) {
return date.plusMonths(month.getValue());
}
@ExecFunction(name = "months_add", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression monthsAdd(DateTimeLiteral date, IntegerLiteral month) {
return date.plusMonths(month.getValue());
}
@ExecFunction(name = "months_add", argTypes = {"DATEV2", "INT"}, returnType = "DATEV2")
public static Expression monthsAdd(DateV2Literal date, IntegerLiteral month) {
return date.plusMonths(month.getValue());
}
@ExecFunction(name = "months_add", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression monthsAdd(DateTimeV2Literal date, IntegerLiteral month) {
return date.plusMonths(month.getValue());
}
/**
* datetime arithmetic function days-add.
*/
@ExecFunction(name = "days_add", argTypes = {"DATE", "INT"}, returnType = "DATE")
public static Expression daysAdd(DateLiteral date, IntegerLiteral day) {
return date.plusDays(day.getValue());
}
@ExecFunction(name = "days_add", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression daysAdd(DateTimeLiteral date, IntegerLiteral day) {
return date.plusDays(day.getValue());
}
@ExecFunction(name = "days_add", argTypes = {"DATEV2", "INT"}, returnType = "DATEV2")
public static Expression daysAdd(DateV2Literal date, IntegerLiteral day) {
return date.plusDays(day.getValue());
}
@ExecFunction(name = "days_add", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression daysAdd(DateTimeV2Literal date, IntegerLiteral day) {
return date.plusDays(day.getValue());
}
/**
* datetime arithmetic function hours-add.
*/
@ExecFunction(name = "hours_add", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression hoursAdd(DateTimeLiteral date, IntegerLiteral hour) {
return date.plusHours(hour.getValue());
}
@ExecFunction(name = "hours_add", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression hoursAdd(DateTimeV2Literal date, IntegerLiteral hour) {
return date.plusHours(hour.getValue());
}
/**
* datetime arithmetic function minutes-add.
*/
@ExecFunction(name = "minutes_add", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression minutesAdd(DateTimeLiteral date, IntegerLiteral minute) {
return date.plusMinutes(minute.getValue());
}
@ExecFunction(name = "minutes_add", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression minutesAdd(DateTimeV2Literal date, IntegerLiteral minute) {
return date.plusMinutes(minute.getValue());
}
/**
* datetime arithmetic function seconds-add.
*/
@ExecFunction(name = "seconds_add", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression secondsAdd(DateTimeLiteral date, IntegerLiteral second) {
return date.plusSeconds(second.getValue());
}
@ExecFunction(name = "seconds_add", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression secondsAdd(DateTimeV2Literal date, IntegerLiteral second) {
return date.plusSeconds(second.getValue());
}
/**
* datetime arithmetic function microseconds-add.
*/
@ExecFunction(name = "microseconds_add", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression microSecondsAdd(DateTimeV2Literal date, IntegerLiteral microSecond) {
return date.plusMicroSeconds(microSecond.getValue());
}
/**
* datetime arithmetic function years-sub.
*/
@ExecFunction(name = "years_sub", argTypes = {"DATE", "INT"}, returnType = "DATE")
public static Expression yearsSub(DateLiteral date, IntegerLiteral year) {
return yearsAdd(date, new IntegerLiteral(-year.getValue()));
}
@ExecFunction(name = "years_sub", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression yearsSub(DateTimeLiteral date, IntegerLiteral year) {
return yearsAdd(date, new IntegerLiteral(-year.getValue()));
}
@ExecFunction(name = "years_sub", argTypes = {"DATEV2", "INT"}, returnType = "DATEV2")
public static Expression yearsSub(DateV2Literal date, IntegerLiteral year) {
return yearsAdd(date, new IntegerLiteral(-year.getValue()));
}
@ExecFunction(name = "years_sub", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression yearsSub(DateTimeV2Literal date, IntegerLiteral year) {
return yearsAdd(date, new IntegerLiteral(-year.getValue()));
}
/**
* datetime arithmetic function months-sub
*/
@ExecFunction(name = "months_sub", argTypes = {"DATE", "INT"}, returnType = "DATE")
public static Expression monthsSub(DateLiteral date, IntegerLiteral month) {
return monthsAdd(date, new IntegerLiteral(-month.getValue()));
}
@ExecFunction(name = "months_sub", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression monthsSub(DateTimeLiteral date, IntegerLiteral month) {
return monthsAdd(date, new IntegerLiteral(-month.getValue()));
}
@ExecFunction(name = "months_sub", argTypes = {"DATEV2", "INT"}, returnType = "DATEV2")
public static Expression monthsSub(DateV2Literal date, IntegerLiteral month) {
return monthsAdd(date, new IntegerLiteral(-month.getValue()));
}
@ExecFunction(name = "months_sub", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression monthsSub(DateTimeV2Literal date, IntegerLiteral month) {
return monthsAdd(date, new IntegerLiteral(-month.getValue()));
}
/**
* datetime arithmetic function days-sub
*/
@ExecFunction(name = "days_sub", argTypes = {"DATE", "INT"}, returnType = "DATE")
public static Expression daysSub(DateLiteral date, IntegerLiteral day) {
return daysAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "days_sub", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression daysSub(DateTimeLiteral date, IntegerLiteral day) {
return daysAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "days_sub", argTypes = {"DATEV2", "INT"}, returnType = "DATEV2")
public static Expression daysSub(DateV2Literal date, IntegerLiteral day) {
return daysAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "days_sub", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression daysSub(DateTimeV2Literal date, IntegerLiteral day) {
return daysAdd(date, new IntegerLiteral(-day.getValue()));
}
/**
* datetime arithmetic function hours-sub
*/
@ExecFunction(name = "hours_sub", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression hoursSub(DateTimeLiteral date, IntegerLiteral hour) {
return hoursAdd(date, new IntegerLiteral(-hour.getValue()));
}
@ExecFunction(name = "hours_sub", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression hoursSub(DateTimeV2Literal date, IntegerLiteral hour) {
return hoursAdd(date, new IntegerLiteral(-hour.getValue()));
}
/**
* datetime arithmetic function minutes-sub
*/
@ExecFunction(name = "minutes_sub", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression minutesSub(DateTimeLiteral date, IntegerLiteral minute) {
return minutesAdd(date, new IntegerLiteral(-minute.getValue()));
}
@ExecFunction(name = "minutes_sub", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression minutesSub(DateTimeV2Literal date, IntegerLiteral minute) {
return minutesAdd(date, new IntegerLiteral(-minute.getValue()));
}
/**
* datetime arithmetic function seconds-sub
*/
@ExecFunction(name = "seconds_sub", argTypes = {"DATETIME", "INT"}, returnType = "DATETIME")
public static Expression secondsSub(DateTimeLiteral date, IntegerLiteral second) {
return secondsAdd(date, new IntegerLiteral(-second.getValue()));
}
@ExecFunction(name = "seconds_sub", argTypes = {"DATETIMEV2", "INT"}, returnType = "DATETIMEV2")
public static Expression secondsSub(DateTimeV2Literal date, IntegerLiteral second) {
return secondsAdd(date, new IntegerLiteral(-second.getValue()));
}
/**
* datetime arithmetic function datediff
*/
@ExecFunction(name = "datediff", argTypes = {"DATETIME", "DATETIME"}, returnType = "INT")
public static Expression dateDiff(DateTimeLiteral date1, DateTimeLiteral date2) {
return new IntegerLiteral(dateDiff(date1.toJavaDateType(), date2.toJavaDateType()));
}
@ExecFunction(name = "datediff", argTypes = {"DATEV2", "DATEV2"}, returnType = "INT")
public static Expression dateDiff(DateV2Literal date1, DateV2Literal date2) {
return new IntegerLiteral(dateDiff(date1.toJavaDateType(), date2.toJavaDateType()));
}
@ExecFunction(name = "datediff", argTypes = {"DATEV2", "DATETIMEV2"}, returnType = "INT")
public static Expression dateDiff(DateV2Literal date1, DateTimeV2Literal date2) {
return new IntegerLiteral(dateDiff(date1.toJavaDateType(), date2.toJavaDateType()));
}
@ExecFunction(name = "datediff", argTypes = {"DATETIMEV2", "DATEV2"}, returnType = "INT")
public static Expression dateDiff(DateTimeV2Literal date1, DateV2Literal date2) {
return new IntegerLiteral(dateDiff(date1.toJavaDateType(), date2.toJavaDateType()));
}
@ExecFunction(name = "datediff", argTypes = {"DATETIMEV2", "DATETIMEV2"}, returnType = "INT")
public static Expression dateDiff(DateTimeV2Literal date1, DateTimeV2Literal date2) {
return new IntegerLiteral(dateDiff(date1.toJavaDateType(), date2.toJavaDateType()));
}
private static int dateDiff(LocalDateTime date1, LocalDateTime date2) {
return ((int) ChronoUnit.DAYS.between(date2.toLocalDate(), date1.toLocalDate()));
}
}

View File

@ -0,0 +1,583 @@
// 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.executable;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.ExecFunction;
import org.apache.doris.nereids.trees.expressions.Expression;
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;
import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
import org.apache.doris.nereids.util.DateUtils;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
/**
* executable function:
* year, quarter, month, week, dayOfYear, dayOfweek, dayOfMonth, hour, minute, second
*/
public class DateTimeExtractAndTransform {
/**
* datetime arithmetic function date-v2
*/
@ExecFunction(name = "datev2", argTypes = {"DATETIMEV2"}, returnType = "DATEV2")
public static Expression dateV2(DateTimeV2Literal dateTime) {
return new DateV2Literal(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay());
}
/**
* Executable datetime extract year
*/
@ExecFunction(name = "year", argTypes = {"DATE"}, returnType = "INT")
public static Expression year(DateLiteral date) {
return new IntegerLiteral(((int) date.getYear()));
}
@ExecFunction(name = "year", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression year(DateTimeLiteral date) {
return new IntegerLiteral(((int) date.getYear()));
}
@ExecFunction(name = "year", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression year(DateV2Literal date) {
return new IntegerLiteral(((int) date.getYear()));
}
@ExecFunction(name = "year", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression year(DateTimeV2Literal date) {
return new IntegerLiteral(((int) date.getYear()));
}
/**
* Executable datetime extract quarter
*/
@ExecFunction(name = "quarter", argTypes = {"DATE"}, returnType = "INT")
public static Expression quarter(DateLiteral date) {
return new IntegerLiteral(((int) date.getMonth() - 1) / 3 + 1);
}
@ExecFunction(name = "quarter", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression quarter(DateTimeLiteral date) {
return new IntegerLiteral(((int) date.getMonth() - 1) / 3 + 1);
}
@ExecFunction(name = "quarter", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression quarter(DateV2Literal date) {
return new IntegerLiteral(((int) date.getMonth() - 1) / 3 + 1);
}
@ExecFunction(name = "quarter", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression quarter(DateTimeV2Literal date) {
return new IntegerLiteral(((int) date.getMonth() - 1) / 3 + 1);
}
/**
* Executable datetime extract month
*/
@ExecFunction(name = "month", argTypes = {"DATE"}, returnType = "INT")
public static Expression month(DateLiteral date) {
return new IntegerLiteral(((int) date.getMonth()));
}
@ExecFunction(name = "month", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression month(DateTimeLiteral date) {
return new IntegerLiteral(((int) date.getMonth()));
}
@ExecFunction(name = "month", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression month(DateV2Literal date) {
return new IntegerLiteral(((int) date.getMonth()));
}
@ExecFunction(name = "month", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression month(DateTimeV2Literal date) {
return new IntegerLiteral(((int) date.getMonth()));
}
/**
* Executable datetime extract day
*/
@ExecFunction(name = "day", argTypes = {"DATE"}, returnType = "INT")
public static Expression day(DateLiteral date) {
return new IntegerLiteral(((int) date.getDay()));
}
@ExecFunction(name = "day", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression day(DateTimeLiteral date) {
return new IntegerLiteral(((int) date.getDay()));
}
@ExecFunction(name = "day", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression day(DateV2Literal date) {
return new IntegerLiteral(((int) date.getDay()));
}
@ExecFunction(name = "day", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression day(DateTimeV2Literal date) {
return new IntegerLiteral(((int) date.getDay()));
}
/**
* Executable datetime extract hour
*/
@ExecFunction(name = "hour", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression hour(DateTimeLiteral date) {
return new IntegerLiteral(((int) date.getHour()));
}
@ExecFunction(name = "hour", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression hour(DateTimeV2Literal date) {
return new IntegerLiteral(((int) date.getHour()));
}
/**
* Executable datetime extract hour
*/
@ExecFunction(name = "minute", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression minute(DateTimeLiteral date) {
return new IntegerLiteral(((int) date.getMinute()));
}
@ExecFunction(name = "minute", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression minute(DateTimeV2Literal date) {
return new IntegerLiteral(((int) date.getMinute()));
}
/**
* Executable datetime extract hour
*/
@ExecFunction(name = "second", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression second(DateTimeLiteral date) {
return new IntegerLiteral(((int) date.getSecond()));
}
@ExecFunction(name = "second", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression second(DateTimeV2Literal date) {
return new IntegerLiteral(((int) date.getSecond()));
}
/**
* Executable datetime extract dayofyear
*/
@ExecFunction(name = "dayofyear", argTypes = {"DATE"}, returnType = "INT")
public static Expression dayOfYear(DateLiteral date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfYear());
}
@ExecFunction(name = "dayofyear", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression dayOfYear(DateTimeLiteral date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfYear());
}
@ExecFunction(name = "dayofyear", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression dayOfYear(DateV2Literal date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfYear());
}
@ExecFunction(name = "dayofyear", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression dayOfYear(DateTimeV2Literal date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfYear());
}
/**
* Executable datetime extract dayofmonth
*/
@ExecFunction(name = "dayofmonth", argTypes = {"DATE"}, returnType = "INT")
public static Expression dayOfMonth(DateLiteral date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfMonth());
}
@ExecFunction(name = "dayofmonth", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression dayOfMonth(DateTimeLiteral date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfMonth());
}
@ExecFunction(name = "dayofmonth", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression dayOfMonth(DateV2Literal date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfMonth());
}
@ExecFunction(name = "dayofmonth", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression dayOfMonth(DateTimeV2Literal date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfMonth());
}
/**
* Executable datetime extract dayofweek
*/
@ExecFunction(name = "dayofweek", argTypes = {"DATE"}, returnType = "INT")
public static Expression dayOfWeek(DateLiteral date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfWeek().getValue() % 7 + 1);
}
@ExecFunction(name = "dayofweek", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression dayOfWeek(DateTimeLiteral date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfWeek().getValue() % 7 + 1);
}
@ExecFunction(name = "dayofweek", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression dayOfWeek(DateV2Literal date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfWeek().getValue() % 7 + 1);
}
@ExecFunction(name = "dayofweek", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression dayOfWeek(DateTimeV2Literal date) {
return new IntegerLiteral(date.toJavaDateType().getDayOfWeek().getValue() % 7 + 1);
}
private static int distanceToFirstDayOfWeek(LocalDateTime dateTime) {
return dateTime.getDayOfWeek().getValue() - 1;
}
private static LocalDateTime firstDayOfWeek(LocalDateTime dateTime) {
return dateTime.plusDays(-distanceToFirstDayOfWeek(dateTime));
}
/**
* datetime arithmetic function date-format
*/
@ExecFunction(name = "date_format", argTypes = {"DATE", "VARCHAR"}, returnType = "VARCHAR")
public static Expression dateFormat(DateLiteral date, VarcharLiteral format) {
return new VarcharLiteral(DateUtils.formatBuilder(format.getValue()).toFormatter().format(
java.time.LocalDate.of(((int) date.getYear()), ((int) date.getMonth()), ((int) date.getDay()))));
}
@ExecFunction(name = "date_format", argTypes = {"DATETIME", "VARCHAR"}, returnType = "VARCHAR")
public static Expression dateFormat(DateTimeLiteral date, VarcharLiteral format) {
return new VarcharLiteral(DateUtils.formatBuilder(format.getValue()).toFormatter().format(
java.time.LocalDateTime.of(((int) date.getYear()), ((int) date.getMonth()), ((int) date.getDay()),
((int) date.getHour()), ((int) date.getMinute()), ((int) date.getSecond()))));
}
@ExecFunction(name = "date_format", argTypes = {"DATEV2", "VARCHAR"}, returnType = "VARCHAR")
public static Expression dateFormat(DateV2Literal date, VarcharLiteral format) {
return new VarcharLiteral(DateUtils.formatBuilder(format.getValue()).toFormatter().format(
java.time.LocalDate.of(((int) date.getYear()), ((int) date.getMonth()), ((int) date.getDay()))));
}
@ExecFunction(name = "date_format", argTypes = {"DATETIMEV2", "VARCHAR"}, returnType = "VARCHAR")
public static Expression dateFormat(DateTimeV2Literal date, VarcharLiteral format) {
return new VarcharLiteral(DateUtils.formatBuilder(format.getValue()).toFormatter().format(
java.time.LocalDateTime.of(((int) date.getYear()), ((int) date.getMonth()), ((int) date.getDay()),
((int) date.getHour()), ((int) date.getMinute()), ((int) date.getSecond()))));
}
/**
* datetime arithmetic function date
*/
@ExecFunction(name = "date", argTypes = {"DATETIME"}, returnType = "DATE")
public static Expression date(DateTimeLiteral dateTime) throws AnalysisException {
return new DateLiteral(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay());
}
@ExecFunction(name = "date", argTypes = {"DATETIMEV2"}, returnType = "DATE")
public static Expression date(DateTimeV2Literal dateTime) throws AnalysisException {
return new DateLiteral(dateTime.getYear(), dateTime.getMonth(), dateTime.getDay());
}
/**
* datetime arithmetic function date-trunc
*/
@ExecFunction(name = "date_trunc", argTypes = {"DATETIME", "VARCHAR"}, returnType = "DATETIME")
public static Expression dateTrunc(DateTimeLiteral date, VarcharLiteral trunc) {
return DateTimeLiteral.fromJavaDateType(dateTruncHelper(date.toJavaDateType(), trunc.getValue()));
}
@ExecFunction(name = "date_trunc", argTypes = {"DATETIMEV2", "VARCHAR"}, returnType = "DATETIMEV2")
public static Expression dateTrunc(DateTimeV2Literal date, VarcharLiteral trunc) {
return DateTimeV2Literal.fromJavaDateType(dateTruncHelper(date.toJavaDateType(), trunc.getValue()));
}
private static LocalDateTime dateTruncHelper(LocalDateTime dateTime, String trunc) {
int year = dateTime.getYear();
int month = dateTime.getMonthValue();
int day = dateTime.getDayOfMonth();
int hour = dateTime.getHour();
int minute = dateTime.getMinute();
int second = dateTime.getSecond();
switch (trunc.toLowerCase()) {
case "year":
month = 0;
case "quarter": // CHECKSTYLE IGNORE THIS LINE
month = ((month - 1) / 3) * 3 + 1;
case "month": // CHECKSTYLE IGNORE THIS LINE
day = 1;
break;
case "week":
LocalDateTime firstDayOfWeek = firstDayOfWeek(dateTime);
year = firstDayOfWeek.getYear();
month = firstDayOfWeek.getMonthValue();
day = firstDayOfWeek.getDayOfMonth();
default: // CHECKSTYLE IGNORE THIS LINE
break;
}
switch (trunc.toLowerCase()) {
case "year":
case "quarter":
case "month":
case "week":
case "day": // CHECKSTYLE IGNORE THIS LINE
hour = 0;
case "hour": // CHECKSTYLE IGNORE THIS LINE
minute = 0;
case "minute": // CHECKSTYLE IGNORE THIS LINE
second = 0;
default: // CHECKSTYLE IGNORE THIS LINE
}
return LocalDateTime.of(year, month, day, hour, minute, second);
}
/**
* from_days.
*/
@ExecFunction(name = "from_days", argTypes = {"INT"}, returnType = "DATE")
public static Expression fromDays(IntegerLiteral n) {
// doris treat 0000AD as ordinary year but java LocalDateTime treat it as lunar year.
LocalDateTime res = LocalDateTime.of(0, 1, 1, 0, 0, 0)
.plusDays(n.getValue());
if (res.isBefore(LocalDateTime.of(0, 3, 1, 0, 0, 0))) {
res = res.plusDays(-1);
}
return DateLiteral.fromJavaDateType(res);
}
@ExecFunction(name = "last_day", argTypes = {"DATE"}, returnType = "DATE")
public static Expression lastDay(DateLiteral date) {
LocalDateTime nextMonthFirstDay = LocalDateTime.of((int) date.getYear(), (int) date.getMonth(), 1,
0, 0, 0).plusMonths(1);
return DateLiteral.fromJavaDateType(nextMonthFirstDay.minusDays(1));
}
@ExecFunction(name = "last_day", argTypes = {"DATETIME"}, returnType = "DATE")
public static Expression lastDay(DateTimeLiteral date) {
LocalDateTime nextMonthFirstDay = LocalDateTime.of((int) date.getYear(), (int) date.getMonth(), 1,
0, 0, 0).plusMonths(1);
return DateLiteral.fromJavaDateType(nextMonthFirstDay.minusDays(1));
}
@ExecFunction(name = "last_day", argTypes = {"DATEV2"}, returnType = "DATEV2")
public static Expression lastDay(DateV2Literal date) {
LocalDateTime nextMonthFirstDay = LocalDateTime.of((int) date.getYear(), (int) date.getMonth(), 1,
0, 0, 0).plusMonths(1);
return DateV2Literal.fromJavaDateType(nextMonthFirstDay.minusDays(1));
}
@ExecFunction(name = "last_day", argTypes = {"DATETIMEV2"}, returnType = "DATEV2")
public static Expression lastDay(DateTimeV2Literal date) {
LocalDateTime nextMonthFirstDay = LocalDateTime.of((int) date.getYear(), (int) date.getMonth(), 1,
0, 0, 0).plusMonths(1);
return DateV2Literal.fromJavaDateType(nextMonthFirstDay.minusDays(1));
}
/**
* datetime transformation function: to_monday
*/
@ExecFunction(name = "to_monday", argTypes = {"DATE"}, returnType = "DATE")
public static Expression toMonday(DateLiteral date) {
return DateLiteral.fromJavaDateType(toMonday(date.toJavaDateType()));
}
@ExecFunction(name = "to_monday", argTypes = {"DATETIME"}, returnType = "DATE")
public static Expression toMonday(DateTimeLiteral date) {
return DateLiteral.fromJavaDateType(toMonday(date.toJavaDateType()));
}
@ExecFunction(name = "to_monday", argTypes = {"DATEV2"}, returnType = "DATEV2")
public static Expression toMonday(DateV2Literal date) {
return DateV2Literal.fromJavaDateType(toMonday(date.toJavaDateType()));
}
@ExecFunction(name = "to_monday", argTypes = {"DATETIMEV2"}, returnType = "DATEV2")
public static Expression toMonday(DateTimeV2Literal date) {
return DateV2Literal.fromJavaDateType(toMonday(date.toJavaDateType()));
}
private static LocalDateTime toMonday(LocalDateTime dateTime) {
LocalDateTime specialUpperBound = LocalDateTime.of(1970, 1, 4, 0, 0, 0);
LocalDateTime specialLowerBound = LocalDateTime.of(1970, 1, 1, 0, 0, 0);
if (dateTime.isAfter(specialUpperBound) || dateTime.isBefore(specialLowerBound)) {
return dateTime.plusDays(-dateTime.getDayOfWeek().getValue() + 1);
}
return specialLowerBound;
}
/**
* date transformation function: from_unixtime
*/
@ExecFunction(name = "from_unixtime", argTypes = {"INT"}, returnType = "VARCHAR")
public static Expression fromUnixTime(IntegerLiteral second) {
if (second.getValue() < 0 || second.getValue() >= 253402271999L) {
return null;
}
return fromUnixTime(second, new VarcharLiteral("%Y-%m-%d %H:%i:%s"));
}
/**
* date transformation function: from_unixtime
*/
@ExecFunction(name = "from_unixtime", argTypes = {"INT", "VARCHAR"}, returnType = "VARCHAR")
public static Expression fromUnixTime(IntegerLiteral second, VarcharLiteral format) {
if (second.getValue() < 0) {
return null;
}
ZonedDateTime dateTime = LocalDateTime.of(1970, 1, 1, 0, 0, 0)
.plusSeconds(second.getValue())
.atZone(ZoneId.of("UTC+0"))
.toOffsetDateTime()
.atZoneSameInstant(ZoneId.systemDefault());
return dateFormat(new DateTimeLiteral(dateTime.getYear(), dateTime.getMonthValue(),
dateTime.getDayOfMonth(), dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond()),
format);
}
/**
* date transformation function: unix_timestamp
*/
@ExecFunction(name = "unix_timestamp", argTypes = {}, returnType = "INT")
public static Expression unixTimestamp() {
return new IntegerLiteral(getTimestamp(LocalDateTime.now()));
}
/**
* date transformation function: unix_timestamp
*/
@ExecFunction(name = "unix_timestamp", argTypes = {"DATE"}, returnType = "INT")
public static Expression unixTimestamp(DateLiteral date) {
return new IntegerLiteral(getTimestamp(date.toJavaDateType()));
}
@ExecFunction(name = "unix_timestamp", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression unixTimestamp(DateTimeLiteral date) {
return new IntegerLiteral(getTimestamp(date.toJavaDateType()));
}
@ExecFunction(name = "unix_timestamp", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression unixTimestamp(DateV2Literal date) {
return new IntegerLiteral(getTimestamp(date.toJavaDateType()));
}
@ExecFunction(name = "unix_timestamp", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression unixTimestamp(DateTimeV2Literal date) {
return new IntegerLiteral(getTimestamp(date.toJavaDateType()));
}
/**
* date transformation function: unix_timestamp
*/
@ExecFunction(name = "unix_timestamp", argTypes = {"VARCHAR", "VARCHAR"}, returnType = "INT")
public static Expression unixTimestamp(VarcharLiteral date, VarcharLiteral format) {
DateTimeFormatter formatter = DateUtils.formatBuilder(format.getValue()).toFormatter();
LocalDateTime dateObj;
try {
dateObj = LocalDateTime.parse(date.getValue(), formatter);
} catch (DateTimeParseException e) {
// means the date string doesn't contain time fields.
dateObj = LocalDate.parse(date.getValue(), formatter).atStartOfDay();
}
return new IntegerLiteral(getTimestamp(dateObj));
}
private static Integer getTimestamp(LocalDateTime dateTime) {
LocalDateTime specialUpperBound = LocalDateTime.of(2038, 1, 19, 3, 14, 7);
LocalDateTime specialLowerBound = LocalDateTime.of(1970, 1, 1, 0, 0, 0);
if (dateTime.isBefore(specialLowerBound) || dateTime.isAfter(specialUpperBound)) {
return 0;
}
return ((int) Duration.between(
specialLowerBound,
dateTime
.atZone(ZoneId.systemDefault())
.toOffsetDateTime().atZoneSameInstant(ZoneId.of("UTC+0"))
.toLocalDateTime()).getSeconds());
}
/**
* date transformation function: utc_timestamp
*/
@ExecFunction(name = "utc_timestamp", argTypes = {}, returnType = "INT")
public static Expression utcTimestamp() {
return DateTimeLiteral.fromJavaDateType(LocalDateTime.now());
}
/**
* date transformation function: to_date
*/
@ExecFunction(name = "to_date", argTypes = {"DATETIME"}, returnType = "DATE")
public static Expression toDate(DateTimeLiteral date) {
return new DateLiteral(date.getYear(), date.getMonth(), date.getDay());
}
@ExecFunction(name = "to_date", argTypes = {"DATETIMEV2"}, returnType = "DATE")
public static Expression toDate(DateTimeV2Literal date) {
return new DateLiteral(date.getYear(), date.getMonth(), date.getDay());
}
/**
* date transformation function: to_days
*/
@ExecFunction(name = "to_days", argTypes = {"DATE"}, returnType = "INT")
public static Expression toDays(DateLiteral date) {
return new IntegerLiteral(((int) Duration.between(
LocalDateTime.of(0, 1, 1, 0, 0, 0), date.toJavaDateType()).toDays()));
}
@ExecFunction(name = "to_days", argTypes = {"DATETIME"}, returnType = "INT")
public static Expression toDays(DateTimeLiteral date) {
return new IntegerLiteral(((int) Duration.between(
LocalDateTime.of(0, 1, 1, 0, 0, 0), date.toJavaDateType()).toDays()));
}
@ExecFunction(name = "to_days", argTypes = {"DATEV2"}, returnType = "INT")
public static Expression toDays(DateV2Literal date) {
return new IntegerLiteral(((int) Duration.between(
LocalDateTime.of(0, 1, 1, 0, 0, 0), date.toJavaDateType()).toDays()));
}
@ExecFunction(name = "to_days", argTypes = {"DATETIMEV2"}, returnType = "INT")
public static Expression toDays(DateTimeV2Literal date) {
return new IntegerLiteral(((int) Duration.between(
LocalDateTime.of(0, 1, 1, 0, 0, 0), date.toJavaDateType()).toDays()));
}
/**
* date transformation function: makedate
*/
@ExecFunction(name = "makedate", argTypes = {"INT", "INT"}, returnType = "DATE")
public static Expression makeDate(IntegerLiteral year, IntegerLiteral dayOfYear) {
return DateLiteral.fromJavaDateType(LocalDateTime.of(year.getValue(), 1, 1, 0, 0, 0)
.plusDays(dayOfYear.getValue() - 1));
}
/**
* date transformation function: str_to_date
*/
@ExecFunction(name = "str_to_date", argTypes = {"VARCHAR, VARCHAR"}, returnType = "DATETIME")
public static Expression strToDate(VarcharLiteral str, VarcharLiteral format) {
return DateTimeLiteral.fromJavaDateType(DateUtils.getTime(DateUtils.formatBuilder(format.getValue())
.toFormatter(), str.getValue()));
}
}

View File

@ -0,0 +1,129 @@
// 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.executable;
import org.apache.doris.nereids.trees.expressions.ExecFunction;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral;
import org.apache.doris.nereids.trees.expressions.literal.DecimalV3Literal;
import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
import org.apache.doris.nereids.trees.expressions.literal.FloatLiteral;
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
import java.util.Random;
import java.util.UUID;
/**
* functions that can be executed in FE.
*/
public class ExecutableFunctions {
public static final ExecutableFunctions INSTANCE = new ExecutableFunctions();
private static final Random RANDOM = new Random();
/**
* other scalar function
*/
@ExecFunction(name = "abs", argTypes = {"TINYINT"}, returnType = "TINYINT")
public static Expression abs(TinyIntLiteral literal) {
return new TinyIntLiteral((byte) Math.abs(literal.getValue()));
}
@ExecFunction(name = "abs", argTypes = {"SMALLINT"}, returnType = "SMALLINT")
public static Expression abs(SmallIntLiteral literal) {
return new SmallIntLiteral((short) Math.abs(literal.getValue()));
}
@ExecFunction(name = "abs", argTypes = {"INT"}, returnType = "INT")
public static Expression abs(IntegerLiteral literal) {
return new IntegerLiteral(Math.abs(literal.getValue()));
}
@ExecFunction(name = "abs", argTypes = {"BIGINT"}, returnType = "BIGINT")
public static Expression abs(BigIntLiteral literal) {
return new BigIntLiteral(Math.abs(literal.getValue()));
}
@ExecFunction(name = "abs", argTypes = {"LARGEINT"}, returnType = "LARGEINT")
public static Expression abs(LargeIntLiteral literal) {
return new LargeIntLiteral(literal.getValue().abs());
}
@ExecFunction(name = "abs", argTypes = {"FLOAT"}, returnType = "FLOAT")
public static Expression abs(FloatLiteral literal) {
return new FloatLiteral(Math.abs(literal.getValue()));
}
@ExecFunction(name = "abs", argTypes = {"DOUBLE"}, returnType = "DOUBLE")
public static Expression abs(DoubleLiteral literal) {
return new DoubleLiteral(Math.abs(literal.getValue()));
}
@ExecFunction(name = "abs", argTypes = {"DECIMAL"}, returnType = "DECIMAL")
public static Expression abs(DecimalLiteral literal) {
return new DecimalLiteral(literal.getValue().abs());
}
@ExecFunction(name = "abs", argTypes = {"DECIMALV3"}, returnType = "DECIMALV3")
public static Expression abs(DecimalV3Literal literal) {
return new DecimalV3Literal(literal.getValue().abs());
}
@ExecFunction(name = "acos", argTypes = {"DOUBLE"}, returnType = "DOUBLE")
public static Expression acos(DoubleLiteral literal) {
return new DoubleLiteral(Math.acos(literal.getValue()));
}
@ExecFunction(name = "append_trailing_if_char_absent", argTypes = {"VARCHAR", "VARCHAR"}, returnType = "VARCHAR")
public static Expression appendTrailingIfCharAbsent(VarcharLiteral literal, VarcharLiteral chr) {
if (literal.getValue().length() != 1) {
return null;
}
return literal.getValue().endsWith(chr.getValue()) ? literal
: new VarcharLiteral(literal.getValue() + chr.getValue());
}
@ExecFunction(name = "e", argTypes = {}, returnType = "DOUBLE")
public static Expression e() { // CHECKSTYLE IGNORE THIS LINE
return new DoubleLiteral(Math.E);
}
@ExecFunction(name = "p1", argTypes = {}, returnType = "DOUBLE")
public static Expression pi() {
return new DoubleLiteral(Math.PI);
}
@ExecFunction(name = "uuid", argTypes = {}, returnType = "VARCHAR")
public static Expression uuid() {
return new VarcharLiteral(UUID.randomUUID().toString());
}
@ExecFunction(name = "rand", argTypes = {}, returnType = "DOUBLE")
public static Expression rand() {
return new DoubleLiteral(RANDOM.nextDouble());
}
@ExecFunction(name = "random", argTypes = {}, returnType = "DOUBLE")
public static Expression random() {
return new DoubleLiteral(RANDOM.nextDouble());
}
}

View File

@ -15,21 +15,16 @@
// specific language governing permissions and limitations
// under the License.
package org.apache.doris.nereids.trees.expressions.functions;
package org.apache.doris.nereids.trees.expressions.functions.executable;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.ExecFunction;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral;
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;
import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral;
import org.apache.doris.nereids.trees.expressions.literal.DecimalV3Literal;
import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
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.SmallIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
@ -39,509 +34,513 @@ import java.math.BigDecimal;
import java.math.BigInteger;
/**
* functions that can be executed in FE.
* executable functions:
* add, subtract, multiply, divide
*/
public class ExecutableFunctions {
public static final ExecutableFunctions INSTANCE = new ExecutableFunctions();
public class NumericArithmetic {
/**
* Executable arithmetic functions
* Executable arithmetic functions add
*/
@ExecFunction(name = "add", argTypes = {"TINYINT", "TINYINT"}, returnType = "SMALLINT")
public static SmallIntLiteral addTinyIntTinyInt(TinyIntLiteral first, TinyIntLiteral second) {
public static Expression addTinyIntTinyInt(TinyIntLiteral first, TinyIntLiteral second) {
short result = (short) Math.addExact(first.getValue(), second.getValue());
return new SmallIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"TINYINT", "SMALLINT"}, returnType = "INT")
public static IntegerLiteral addTinyIntSmallInt(TinyIntLiteral first, SmallIntLiteral second) {
public static Expression addTinyIntSmallInt(TinyIntLiteral first, SmallIntLiteral second) {
int result = Math.addExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"TINYINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral addTinyIntInt(TinyIntLiteral first, IntegerLiteral second) {
public static Expression addTinyIntInt(TinyIntLiteral first, IntegerLiteral second) {
long result = Math.addExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"TINYINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral addTinyIntBigInt(TinyIntLiteral first, BigIntLiteral second) {
public static Expression addTinyIntBigInt(TinyIntLiteral first, BigIntLiteral second) {
long result = Math.addExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"TINYINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral addTinyIntLargeInt(TinyIntLiteral first, LargeIntLiteral second) {
public static Expression addTinyIntLargeInt(TinyIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().add(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"SMALLINT", "TINYINT"}, returnType = "INT")
public static IntegerLiteral addSmallIntTinyInt(SmallIntLiteral first, TinyIntLiteral second) {
public static Expression addSmallIntTinyInt(SmallIntLiteral first, TinyIntLiteral second) {
int result = Math.addExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"SMALLINT", "SMALLINT"}, returnType = "INT")
public static IntegerLiteral addSmallIntSmallInt(SmallIntLiteral first, SmallIntLiteral second) {
public static Expression addSmallIntSmallInt(SmallIntLiteral first, SmallIntLiteral second) {
int result = Math.addExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"SMALLINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral addSmallIntInt(SmallIntLiteral first, IntegerLiteral second) {
public static Expression addSmallIntInt(SmallIntLiteral first, IntegerLiteral second) {
long result = Math.addExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"SMALLINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral addSmallIntBigInt(SmallIntLiteral first, BigIntLiteral second) {
public static Expression addSmallIntBigInt(SmallIntLiteral first, BigIntLiteral second) {
long result = Math.addExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"SMALLINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral addSmallIntLargeInt(SmallIntLiteral first, LargeIntLiteral second) {
public static Expression addSmallIntLargeInt(SmallIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().add(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"INT", "TINYINT"}, returnType = "BIGINT")
public static BigIntLiteral addIntTinyInt(IntegerLiteral first, TinyIntLiteral second) {
public static Expression addIntTinyInt(IntegerLiteral first, TinyIntLiteral second) {
long result = Math.addExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"INT", "SMALLINT"}, returnType = "BIGINT")
public static BigIntLiteral addIntSmallInt(IntegerLiteral first, SmallIntLiteral second) {
public static Expression addIntSmallInt(IntegerLiteral first, SmallIntLiteral second) {
long result = Math.addExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"INT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral addIntInt(IntegerLiteral first, IntegerLiteral second) {
public static Expression addIntInt(IntegerLiteral first, IntegerLiteral second) {
long result = Math.addExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"INT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral addIntBigInt(IntegerLiteral first, BigIntLiteral second) {
public static Expression addIntBigInt(IntegerLiteral first, BigIntLiteral second) {
long result = Math.addExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"INT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral addIntLargeInt(IntegerLiteral first, LargeIntLiteral second) {
public static Expression addIntLargeInt(IntegerLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().add(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"BIGINT", "TINYINT"}, returnType = "BIGINT")
public static BigIntLiteral addBigIntTinyInt(BigIntLiteral first, TinyIntLiteral second) {
public static Expression addBigIntTinyInt(BigIntLiteral first, TinyIntLiteral second) {
long result = Math.addExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"BIGINT", "SMALLINT"}, returnType = "BIGINT")
public static BigIntLiteral addBigIntSmallInt(BigIntLiteral first, SmallIntLiteral second) {
public static Expression addBigIntSmallInt(BigIntLiteral first, SmallIntLiteral second) {
long result = Math.addExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"BIGINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral addBigIntInt(BigIntLiteral first, IntegerLiteral second) {
public static Expression addBigIntInt(BigIntLiteral first, IntegerLiteral second) {
long result = Math.addExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"BIGINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral addBigIntBigInt(BigIntLiteral first, BigIntLiteral second) {
public static Expression addBigIntBigInt(BigIntLiteral first, BigIntLiteral second) {
long result = Math.addExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"BIGINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral addBigIntLargeInt(BigIntLiteral first, LargeIntLiteral second) {
public static Expression addBigIntLargeInt(BigIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().add(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"LARGEINT", "TINYINT"}, returnType = "BIGINT")
public static LargeIntLiteral addLargeIntTinyInt(LargeIntLiteral first, TinyIntLiteral second) {
public static Expression addLargeIntTinyInt(LargeIntLiteral first, TinyIntLiteral second) {
BigInteger result = first.getValue().add(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"LARGEINT", "SMALLINT"}, returnType = "BIGINT")
public static LargeIntLiteral addLargeIntSmallInt(LargeIntLiteral first, SmallIntLiteral second) {
public static Expression addLargeIntSmallInt(LargeIntLiteral first, SmallIntLiteral second) {
BigInteger result = first.getValue().add(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"LARGEINT", "INT"}, returnType = "BIGINT")
public static LargeIntLiteral addLargeIntInt(LargeIntLiteral first, IntegerLiteral second) {
public static Expression addLargeIntInt(LargeIntLiteral first, IntegerLiteral second) {
BigInteger result = first.getValue().add(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"LARGEINT", "BIGINT"}, returnType = "BIGINT")
public static LargeIntLiteral addLargeIntBigInt(LargeIntLiteral first, BigIntLiteral second) {
public static Expression addLargeIntBigInt(LargeIntLiteral first, BigIntLiteral second) {
BigInteger result = first.getValue().add(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"LARGEINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral addLargeIntLargeInt(LargeIntLiteral first, LargeIntLiteral second) {
public static Expression addLargeIntLargeInt(LargeIntLiteral first, LargeIntLiteral second) {
BigInteger result = first.getValue().add(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"DOUBLE", "DOUBLE"}, returnType = "DOUBLE")
public static DoubleLiteral addDoubleDouble(DoubleLiteral first, DoubleLiteral second) {
public static Expression addDoubleDouble(DoubleLiteral first, DoubleLiteral second) {
double result = first.getValue() + second.getValue();
return new DoubleLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"DECIMAL", "DECIMAL"}, returnType = "DECIMAL")
public static DecimalLiteral addDecimalDecimal(DecimalLiteral first, DecimalLiteral second) {
public static Expression addDecimalDecimal(DecimalLiteral first, DecimalLiteral second) {
BigDecimal result = first.getValue().add(second.getValue());
return new DecimalLiteral(result);
}
@ExecFunction(name = "add", argTypes = {"DECIMALV3", "DECIMALV3"}, returnType = "DECIMALV3")
public static DecimalV3Literal addDecimalV3DecimalV3(DecimalV3Literal first, DecimalV3Literal second) {
public static Expression addDecimalV3DecimalV3(DecimalV3Literal first, DecimalV3Literal second) {
BigDecimal result = first.getValue().add(second.getValue());
return new DecimalV3Literal((DecimalV3Type) first.getDataType(), result);
}
/**
* Executable arithmetic functions subtract
*/
@ExecFunction(name = "subtract", argTypes = {"TINYINT", "TINYINT"}, returnType = "SMALLINT")
public static SmallIntLiteral subtractTinyIntTinyInt(TinyIntLiteral first, TinyIntLiteral second) {
public static Expression subtractTinyIntTinyInt(TinyIntLiteral first, TinyIntLiteral second) {
short result = (short) Math.subtractExact(first.getValue(), second.getValue());
return new SmallIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"TINYINT", "SMALLINT"}, returnType = "INT")
public static IntegerLiteral subtractTinyIntSmallInt(TinyIntLiteral first, SmallIntLiteral second) {
public static Expression subtractTinyIntSmallInt(TinyIntLiteral first, SmallIntLiteral second) {
int result = Math.subtractExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"TINYINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral subtractTinyIntInt(TinyIntLiteral first, IntegerLiteral second) {
public static Expression subtractTinyIntInt(TinyIntLiteral first, IntegerLiteral second) {
long result = Math.subtractExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"TINYINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral subtractTinyIntBigInt(TinyIntLiteral first, BigIntLiteral second) {
public static Expression subtractTinyIntBigInt(TinyIntLiteral first, BigIntLiteral second) {
long result = Math.subtractExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"TINYINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral subtractTinyIntLargeInt(TinyIntLiteral first, LargeIntLiteral second) {
public static Expression subtractTinyIntLargeInt(TinyIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().subtract(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"SMALLINT", "TINYINT"}, returnType = "INT")
public static IntegerLiteral subtractSmallIntTinyInt(SmallIntLiteral first, TinyIntLiteral second) {
public static Expression subtractSmallIntTinyInt(SmallIntLiteral first, TinyIntLiteral second) {
int result = Math.subtractExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"SMALLINT", "SMALLINT"}, returnType = "INT")
public static IntegerLiteral subtractSmallIntSmallInt(SmallIntLiteral first, SmallIntLiteral second) {
public static Expression subtractSmallIntSmallInt(SmallIntLiteral first, SmallIntLiteral second) {
int result = Math.subtractExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"SMALLINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral subtractSmallIntInt(SmallIntLiteral first, IntegerLiteral second) {
public static Expression subtractSmallIntInt(SmallIntLiteral first, IntegerLiteral second) {
long result = Math.subtractExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"SMALLINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral subtractSmallIntBigInt(SmallIntLiteral first, BigIntLiteral second) {
public static Expression subtractSmallIntBigInt(SmallIntLiteral first, BigIntLiteral second) {
long result = Math.subtractExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"SMALLINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral subtractSmallIntLargeInt(SmallIntLiteral first, LargeIntLiteral second) {
public static Expression subtractSmallIntLargeInt(SmallIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().subtract(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"INT", "TINYINT"}, returnType = "BIGINT")
public static BigIntLiteral subtractIntTinyInt(IntegerLiteral first, TinyIntLiteral second) {
public static Expression subtractIntTinyInt(IntegerLiteral first, TinyIntLiteral second) {
long result = Math.subtractExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"INT", "SMALLINT"}, returnType = "BIGINT")
public static BigIntLiteral subtractIntSmallInt(IntegerLiteral first, SmallIntLiteral second) {
public static Expression subtractIntSmallInt(IntegerLiteral first, SmallIntLiteral second) {
long result = Math.subtractExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"INT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral subtractIntInt(IntegerLiteral first, IntegerLiteral second) {
public static Expression subtractIntInt(IntegerLiteral first, IntegerLiteral second) {
long result = Math.subtractExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"INT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral subtractIntBigInt(IntegerLiteral first, BigIntLiteral second) {
public static Expression subtractIntBigInt(IntegerLiteral first, BigIntLiteral second) {
long result = Math.subtractExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"INT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral subtractIntLargeInt(IntegerLiteral first, LargeIntLiteral second) {
public static Expression subtractIntLargeInt(IntegerLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().subtract(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"BIGINT", "TINYINT"}, returnType = "BIGINT")
public static BigIntLiteral subtractBigIntTinyInt(BigIntLiteral first, TinyIntLiteral second) {
public static Expression subtractBigIntTinyInt(BigIntLiteral first, TinyIntLiteral second) {
long result = Math.subtractExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"BIGINT", "SMALLINT"}, returnType = "BIGINT")
public static BigIntLiteral subtractBigIntSmallInt(BigIntLiteral first, SmallIntLiteral second) {
public static Expression subtractBigIntSmallInt(BigIntLiteral first, SmallIntLiteral second) {
long result = Math.subtractExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"BIGINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral subtractBigIntInt(BigIntLiteral first, IntegerLiteral second) {
public static Expression subtractBigIntInt(BigIntLiteral first, IntegerLiteral second) {
long result = Math.subtractExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"BIGINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral subtractBigIntBigInt(BigIntLiteral first, BigIntLiteral second) {
public static Expression subtractBigIntBigInt(BigIntLiteral first, BigIntLiteral second) {
long result = Math.subtractExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"BIGINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral subtractBigIntLargeInt(BigIntLiteral first, LargeIntLiteral second) {
public static Expression subtractBigIntLargeInt(BigIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().subtract(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"LARGEINT", "TINYINT"}, returnType = "BIGINT")
public static LargeIntLiteral subtractLargeIntTinyInt(LargeIntLiteral first, TinyIntLiteral second) {
public static Expression subtractLargeIntTinyInt(LargeIntLiteral first, TinyIntLiteral second) {
BigInteger result = first.getValue().subtract(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"LARGEINT", "SMALLINT"}, returnType = "BIGINT")
public static LargeIntLiteral subtractLargeIntSmallInt(LargeIntLiteral first, SmallIntLiteral second) {
public static Expression subtractLargeIntSmallInt(LargeIntLiteral first, SmallIntLiteral second) {
BigInteger result = first.getValue().subtract(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"LARGEINT", "INT"}, returnType = "BIGINT")
public static LargeIntLiteral subtractLargeIntInt(LargeIntLiteral first, IntegerLiteral second) {
public static Expression subtractLargeIntInt(LargeIntLiteral first, IntegerLiteral second) {
BigInteger result = first.getValue().subtract(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"LARGEINT", "BIGINT"}, returnType = "BIGINT")
public static LargeIntLiteral subtractLargeIntBigInt(LargeIntLiteral first, BigIntLiteral second) {
public static Expression subtractLargeIntBigInt(LargeIntLiteral first, BigIntLiteral second) {
BigInteger result = first.getValue().subtract(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"LARGEINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral subtractLargeIntLargeInt(LargeIntLiteral first, LargeIntLiteral second) {
public static Expression subtractLargeIntLargeInt(LargeIntLiteral first, LargeIntLiteral second) {
BigInteger result = first.getValue().subtract(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"DOUBLE", "DOUBLE"}, returnType = "DOUBLE")
public static DoubleLiteral subtractDoubleDouble(DoubleLiteral first, DoubleLiteral second) {
public static Expression subtractDoubleDouble(DoubleLiteral first, DoubleLiteral second) {
double result = first.getValue() - second.getValue();
return new DoubleLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"DECIMAL", "DECIMAL"}, returnType = "DECIMAL")
public static DecimalLiteral subtractDecimalDecimal(DecimalLiteral first, DecimalLiteral second) {
public static Expression subtractDecimalDecimal(DecimalLiteral first, DecimalLiteral second) {
BigDecimal result = first.getValue().subtract(second.getValue());
return new DecimalLiteral(result);
}
@ExecFunction(name = "subtract", argTypes = {"DECIMALV3", "DECIMALV3"}, returnType = "DECIMALV3")
public static DecimalV3Literal subtractDecimalV3DecimalV3(DecimalV3Literal first, DecimalV3Literal second) {
public static Expression subtractDecimalV3DecimalV3(DecimalV3Literal first, DecimalV3Literal second) {
BigDecimal result = first.getValue().subtract(second.getValue());
return new DecimalV3Literal((DecimalV3Type) first.getDataType(), result);
}
/**
* Executable arithmetic functions multiply
*/
@ExecFunction(name = "multiply", argTypes = {"TINYINT", "TINYINT"}, returnType = "SMALLINT")
public static SmallIntLiteral multiplyTinyIntTinyInt(TinyIntLiteral first, TinyIntLiteral second) {
public static Expression multiplyTinyIntTinyInt(TinyIntLiteral first, TinyIntLiteral second) {
short result = (short) Math.multiplyExact(first.getValue(), second.getValue());
return new SmallIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"TINYINT", "SMALLINT"}, returnType = "INT")
public static IntegerLiteral multiplyTinyIntSmallInt(TinyIntLiteral first, SmallIntLiteral second) {
public static Expression multiplyTinyIntSmallInt(TinyIntLiteral first, SmallIntLiteral second) {
int result = Math.multiplyExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"TINYINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyTinyIntInt(TinyIntLiteral first, IntegerLiteral second) {
public static Expression multiplyTinyIntInt(TinyIntLiteral first, IntegerLiteral second) {
long result = Math.multiplyExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"TINYINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyTinyIntBigInt(TinyIntLiteral first, BigIntLiteral second) {
public static Expression multiplyTinyIntBigInt(TinyIntLiteral first, BigIntLiteral second) {
long result = Math.multiplyExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"TINYINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral multiplyTinyIntLargeInt(TinyIntLiteral first, LargeIntLiteral second) {
public static Expression multiplyTinyIntLargeInt(TinyIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().multiply(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"SMALLINT", "TINYINT"}, returnType = "INT")
public static IntegerLiteral multiplySmallIntTinyInt(SmallIntLiteral first, TinyIntLiteral second) {
public static Expression multiplySmallIntTinyInt(SmallIntLiteral first, TinyIntLiteral second) {
int result = Math.multiplyExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"SMALLINT", "SMALLINT"}, returnType = "INT")
public static IntegerLiteral multiplySmallIntSmallInt(SmallIntLiteral first, SmallIntLiteral second) {
public static Expression multiplySmallIntSmallInt(SmallIntLiteral first, SmallIntLiteral second) {
int result = Math.multiplyExact(first.getValue(), second.getValue());
return new IntegerLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"SMALLINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral multiplySmallIntInt(SmallIntLiteral first, IntegerLiteral second) {
public static Expression multiplySmallIntInt(SmallIntLiteral first, IntegerLiteral second) {
long result = Math.multiplyExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"SMALLINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral multiplySmallIntBigInt(SmallIntLiteral first, BigIntLiteral second) {
public static Expression multiplySmallIntBigInt(SmallIntLiteral first, BigIntLiteral second) {
long result = Math.multiplyExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"SMALLINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral multiplySmallIntLargeInt(SmallIntLiteral first, LargeIntLiteral second) {
public static Expression multiplySmallIntLargeInt(SmallIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().multiply(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"INT", "TINYINT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyIntTinyInt(IntegerLiteral first, TinyIntLiteral second) {
public static Expression multiplyIntTinyInt(IntegerLiteral first, TinyIntLiteral second) {
long result = Math.multiplyExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"INT", "SMALLINT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyIntSmallInt(IntegerLiteral first, SmallIntLiteral second) {
public static Expression multiplyIntSmallInt(IntegerLiteral first, SmallIntLiteral second) {
long result = Math.multiplyExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"INT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyIntInt(IntegerLiteral first, IntegerLiteral second) {
public static Expression multiplyIntInt(IntegerLiteral first, IntegerLiteral second) {
long result = Math.multiplyExact((long) first.getValue(), (long) second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"INT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyIntBigInt(IntegerLiteral first, BigIntLiteral second) {
public static Expression multiplyIntBigInt(IntegerLiteral first, BigIntLiteral second) {
long result = Math.multiplyExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"INT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral multiplyIntLargeInt(IntegerLiteral first, LargeIntLiteral second) {
public static Expression multiplyIntLargeInt(IntegerLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().multiply(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"BIGINT", "TINYINT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyBigIntTinyInt(BigIntLiteral first, TinyIntLiteral second) {
public static Expression multiplyBigIntTinyInt(BigIntLiteral first, TinyIntLiteral second) {
long result = Math.multiplyExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"BIGINT", "SMALLINT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyBigIntSmallInt(BigIntLiteral first, SmallIntLiteral second) {
public static Expression multiplyBigIntSmallInt(BigIntLiteral first, SmallIntLiteral second) {
long result = Math.multiplyExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"BIGINT", "INT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyBigIntInt(BigIntLiteral first, IntegerLiteral second) {
public static Expression multiplyBigIntInt(BigIntLiteral first, IntegerLiteral second) {
long result = Math.multiplyExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"BIGINT", "BIGINT"}, returnType = "BIGINT")
public static BigIntLiteral multiplyBigIntBigInt(BigIntLiteral first, BigIntLiteral second) {
public static Expression multiplyBigIntBigInt(BigIntLiteral first, BigIntLiteral second) {
long result = Math.multiplyExact(first.getValue(), second.getValue());
return new BigIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"BIGINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral multiplyBigIntLargeInt(BigIntLiteral first, LargeIntLiteral second) {
public static Expression multiplyBigIntLargeInt(BigIntLiteral first, LargeIntLiteral second) {
BigInteger result = second.getValue().multiply(new BigInteger(first.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"LARGEINT", "TINYINT"}, returnType = "BIGINT")
public static LargeIntLiteral multiplyLargeIntTinyInt(LargeIntLiteral first, TinyIntLiteral second) {
public static Expression multiplyLargeIntTinyInt(LargeIntLiteral first, TinyIntLiteral second) {
BigInteger result = first.getValue().multiply(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"LARGEINT", "SMALLINT"}, returnType = "BIGINT")
public static LargeIntLiteral multiplyLargeIntSmallInt(LargeIntLiteral first, SmallIntLiteral second) {
public static Expression multiplyLargeIntSmallInt(LargeIntLiteral first, SmallIntLiteral second) {
BigInteger result = first.getValue().multiply(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"LARGEINT", "INT"}, returnType = "BIGINT")
public static LargeIntLiteral multiplyLargeIntInt(LargeIntLiteral first, IntegerLiteral second) {
public static Expression multiplyLargeIntInt(LargeIntLiteral first, IntegerLiteral second) {
BigInteger result = first.getValue().multiply(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"LARGEINT", "BIGINT"}, returnType = "BIGINT")
public static LargeIntLiteral multiplyLargeIntBigInt(LargeIntLiteral first, BigIntLiteral second) {
public static Expression multiplyLargeIntBigInt(LargeIntLiteral first, BigIntLiteral second) {
BigInteger result = first.getValue().multiply(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"LARGEINT", "LARGEINT"}, returnType = "LARGEINT")
public static LargeIntLiteral multiplyLargeIntLargeInt(LargeIntLiteral first, LargeIntLiteral second) {
public static Expression multiplyLargeIntLargeInt(LargeIntLiteral first, LargeIntLiteral second) {
BigInteger result = first.getValue().multiply(new BigInteger(second.getValue().toString()));
return new LargeIntLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"DOUBLE", "DOUBLE"}, returnType = "DOUBLE")
public static DoubleLiteral multiplyDoubleDouble(DoubleLiteral first, DoubleLiteral second) {
public static Expression multiplyDoubleDouble(DoubleLiteral first, DoubleLiteral second) {
double result = first.getValue() * second.getValue();
return new DoubleLiteral(result);
}
@ExecFunction(name = "multiply", argTypes = {"DECIMAL", "DECIMAL"}, returnType = "DECIMAL")
public static DecimalLiteral multiplyDecimalDecimal(DecimalLiteral first, DecimalLiteral second) {
public static Expression multiplyDecimalDecimal(DecimalLiteral first, DecimalLiteral second) {
BigDecimal result = first.getValue().multiply(second.getValue());
return new DecimalLiteral(result);
}
@ -550,7 +549,7 @@ public class ExecutableFunctions {
* decimalV3 multiply in FE
*/
@ExecFunction(name = "multiply", argTypes = {"DECIMALV3", "DECIMALV3"}, returnType = "DECIMALV3")
public static DecimalV3Literal multiplyDecimalV3DecimalV3(DecimalV3Literal first, DecimalV3Literal second) {
public static Expression multiplyDecimalV3DecimalV3(DecimalV3Literal first, DecimalV3Literal second) {
BigDecimal result = first.getValue().multiply(second.getValue());
DecimalV3Type t1 = (DecimalV3Type) first.getDataType();
DecimalV3Type t2 = (DecimalV3Type) second.getDataType();
@ -559,8 +558,11 @@ public class ExecutableFunctions {
return new DecimalV3Literal(DecimalV3Type.createDecimalV3Type(precision, scale), result);
}
/**
* Executable arithmetic functions divide
*/
@ExecFunction(name = "divide", argTypes = {"DOUBLE", "DOUBLE"}, returnType = "DOUBLE")
public static Literal divideDouble(DoubleLiteral first, DoubleLiteral second) {
public static Expression divideDouble(DoubleLiteral first, DoubleLiteral second) {
if (second.getValue() == 0.0) {
return new NullLiteral(first.getDataType());
}
@ -569,7 +571,7 @@ public class ExecutableFunctions {
}
@ExecFunction(name = "divide", argTypes = {"DECIMAL", "DECIMAL"}, returnType = "DECIMAL")
public static Literal divideDecimal(DecimalLiteral first, DecimalLiteral second) {
public static Expression divideDecimal(DecimalLiteral first, DecimalLiteral second) {
if (first.getValue().compareTo(BigDecimal.ZERO) == 0) {
return new NullLiteral(first.getDataType());
}
@ -581,7 +583,7 @@ public class ExecutableFunctions {
* decimalv3 divide in FE
*/
@ExecFunction(name = "divide", argTypes = {"DECIMALV3", "DECIMALV3"}, returnType = "DECIMALV3")
public static Literal divideDecimalV3(DecimalV3Literal first, DecimalV3Literal second) {
public static Expression divideDecimalV3(DecimalV3Literal first, DecimalV3Literal second) {
if (first.getValue().compareTo(BigDecimal.ZERO) == 0) {
return new NullLiteral(first.getDataType());
}
@ -591,224 +593,4 @@ public class ExecutableFunctions {
return new DecimalV3Literal(DecimalV3Type.createDecimalV3Type(
t1.getPrecision(), t1.getScale() - t2.getScale()), result);
}
@ExecFunction(name = "date_sub", argTypes = { "DATE", "INT" }, returnType = "DATE")
public static DateLiteral dateSub(DateLiteral date, IntegerLiteral day) throws AnalysisException {
return dateAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "date_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral dateSub(DateTimeLiteral date, IntegerLiteral day) throws AnalysisException {
return dateAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "date_sub", argTypes = { "DATEV2", "INT" }, returnType = "DATEV2")
public static DateV2Literal dateSub(DateV2Literal date, IntegerLiteral day) throws AnalysisException {
return dateAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "date_sub", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal dateSub(DateTimeV2Literal date, IntegerLiteral day) throws AnalysisException {
return dateAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "date_add", argTypes = { "DATE", "INT" }, returnType = "DATE")
public static DateLiteral dateAdd(DateLiteral date, IntegerLiteral day) throws AnalysisException {
return daysAdd(date, day);
}
@ExecFunction(name = "date_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral dateAdd(DateTimeLiteral date, IntegerLiteral day) throws AnalysisException {
return daysAdd(date, day);
}
@ExecFunction(name = "date_add", argTypes = { "DATEV2", "INT" }, returnType = "DATEV2")
public static DateV2Literal dateAdd(DateV2Literal date, IntegerLiteral day) throws AnalysisException {
return daysAdd(date, day);
}
@ExecFunction(name = "date_add", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal dateAdd(DateTimeV2Literal date, IntegerLiteral day) throws AnalysisException {
return daysAdd(date, day);
}
@ExecFunction(name = "years_add", argTypes = { "DATE", "INT" }, returnType = "DATE")
public static DateLiteral yearsAdd(DateLiteral date, IntegerLiteral year) throws AnalysisException {
return date.plusYears(year.getValue());
}
@ExecFunction(name = "years_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral yearsAdd(DateTimeLiteral date, IntegerLiteral year) throws AnalysisException {
return date.plusYears(year.getValue());
}
@ExecFunction(name = "years_add", argTypes = { "DATEV2", "INT" }, returnType = "DATEV2")
public static DateV2Literal yearsAdd(DateV2Literal date, IntegerLiteral year) throws AnalysisException {
return date.plusYears(year.getValue());
}
@ExecFunction(name = "years_add", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal yearsAdd(DateTimeV2Literal date, IntegerLiteral year) throws AnalysisException {
return date.plusYears(year.getValue());
}
@ExecFunction(name = "months_add", argTypes = { "DATE", "INT" }, returnType = "DATE")
public static DateLiteral monthsAdd(DateLiteral date, IntegerLiteral month) throws AnalysisException {
return date.plusMonths(month.getValue());
}
@ExecFunction(name = "months_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral monthsAdd(DateTimeLiteral date, IntegerLiteral month) throws AnalysisException {
return date.plusMonths(month.getValue());
}
@ExecFunction(name = "months_add", argTypes = { "DATEV2", "INT" }, returnType = "DATEV2")
public static DateV2Literal monthsAdd(DateV2Literal date, IntegerLiteral month) throws AnalysisException {
return date.plusMonths(month.getValue());
}
@ExecFunction(name = "months_add", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal monthsAdd(DateTimeV2Literal date, IntegerLiteral month) throws AnalysisException {
return date.plusMonths(month.getValue());
}
@ExecFunction(name = "days_add", argTypes = { "DATE", "INT" }, returnType = "DATE")
public static DateLiteral daysAdd(DateLiteral date, IntegerLiteral day) throws AnalysisException {
return date.plusDays(day.getValue());
}
@ExecFunction(name = "days_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral daysAdd(DateTimeLiteral date, IntegerLiteral day) throws AnalysisException {
return date.plusDays(day.getValue());
}
@ExecFunction(name = "days_add", argTypes = { "DATEV2", "INT" }, returnType = "DATEV2")
public static DateV2Literal daysAdd(DateV2Literal date, IntegerLiteral day) throws AnalysisException {
return date.plusDays(day.getValue());
}
@ExecFunction(name = "days_add", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal daysAdd(DateTimeV2Literal date, IntegerLiteral day) throws AnalysisException {
return date.plusDays(day.getValue());
}
@ExecFunction(name = "hours_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral hoursAdd(DateTimeLiteral date, IntegerLiteral hour) throws AnalysisException {
return date.plusHours(hour.getValue());
}
@ExecFunction(name = "hours_add", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal hoursAdd(DateTimeV2Literal date, IntegerLiteral hour) throws AnalysisException {
return date.plusHours(hour.getValue());
}
@ExecFunction(name = "minutes_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral minutesAdd(DateTimeLiteral date, IntegerLiteral minute) throws AnalysisException {
return date.plusMinutes(minute.getValue());
}
@ExecFunction(name = "minutes_add", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal minutesAdd(DateTimeV2Literal date, IntegerLiteral minute) throws AnalysisException {
return date.plusMinutes(minute.getValue());
}
@ExecFunction(name = "seconds_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral secondsAdd(DateTimeLiteral date, IntegerLiteral second) throws AnalysisException {
return date.plusSeconds(second.getValue());
}
@ExecFunction(name = "seconds_add", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal secondsAdd(DateTimeV2Literal date, IntegerLiteral second) throws AnalysisException {
return date.plusSeconds(second.getValue());
}
@ExecFunction(name = "years_sub", argTypes = { "DATE", "INT" }, returnType = "DATE")
public static DateLiteral yearsSub(DateLiteral date, IntegerLiteral year) throws AnalysisException {
return yearsAdd(date, new IntegerLiteral(-year.getValue()));
}
@ExecFunction(name = "years_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral yearsSub(DateTimeLiteral date, IntegerLiteral year) throws AnalysisException {
return yearsAdd(date, new IntegerLiteral(-year.getValue()));
}
@ExecFunction(name = "years_sub", argTypes = { "DATEV2", "INT" }, returnType = "DATEV2")
public static DateV2Literal yearsSub(DateV2Literal date, IntegerLiteral year) throws AnalysisException {
return yearsAdd(date, new IntegerLiteral(-year.getValue()));
}
@ExecFunction(name = "years_sub", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal yearsSub(DateTimeV2Literal date, IntegerLiteral year) throws AnalysisException {
return yearsAdd(date, new IntegerLiteral(-year.getValue()));
}
@ExecFunction(name = "months_sub", argTypes = { "DATE", "INT" }, returnType = "DATE")
public static DateLiteral monthsSub(DateLiteral date, IntegerLiteral month) throws AnalysisException {
return monthsAdd(date, new IntegerLiteral(-month.getValue()));
}
@ExecFunction(name = "months_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral monthsSub(DateTimeLiteral date, IntegerLiteral month) throws AnalysisException {
return monthsAdd(date, new IntegerLiteral(-month.getValue()));
}
@ExecFunction(name = "months_sub", argTypes = { "DATEV2", "INT" }, returnType = "DATEV2")
public static DateV2Literal monthsSub(DateV2Literal date, IntegerLiteral month) throws AnalysisException {
return monthsAdd(date, new IntegerLiteral(-month.getValue()));
}
@ExecFunction(name = "months_sub", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal monthsSub(DateTimeV2Literal date, IntegerLiteral month) throws AnalysisException {
return monthsAdd(date, new IntegerLiteral(-month.getValue()));
}
@ExecFunction(name = "days_sub", argTypes = { "DATE", "INT" }, returnType = "DATE")
public static DateLiteral daysSub(DateLiteral date, IntegerLiteral day) throws AnalysisException {
return daysAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "days_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral daysSub(DateTimeLiteral date, IntegerLiteral day) throws AnalysisException {
return daysAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "days_sub", argTypes = { "DATEV2", "INT" }, returnType = "DATEV2")
public static DateV2Literal daysSub(DateV2Literal date, IntegerLiteral day) throws AnalysisException {
return daysAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "days_sub", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal daysSub(DateTimeV2Literal date, IntegerLiteral day) throws AnalysisException {
return daysAdd(date, new IntegerLiteral(-day.getValue()));
}
@ExecFunction(name = "hours_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral hoursSub(DateTimeLiteral date, IntegerLiteral hour) throws AnalysisException {
return hoursAdd(date, new IntegerLiteral(-hour.getValue()));
}
@ExecFunction(name = "hours_sub", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal hoursSub(DateTimeV2Literal date, IntegerLiteral hour) throws AnalysisException {
return hoursAdd(date, new IntegerLiteral(-hour.getValue()));
}
@ExecFunction(name = "minutes_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral minutesSub(DateTimeLiteral date, IntegerLiteral minute) throws AnalysisException {
return minutesAdd(date, new IntegerLiteral(-minute.getValue()));
}
@ExecFunction(name = "minutes_sub", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal minutesSub(DateTimeV2Literal date, IntegerLiteral minute) throws AnalysisException {
return minutesAdd(date, new IntegerLiteral(-minute.getValue()));
}
@ExecFunction(name = "seconds_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
public static DateTimeLiteral secondsSub(DateTimeLiteral date, IntegerLiteral second) throws AnalysisException {
return secondsAdd(date, new IntegerLiteral(-second.getValue()));
}
@ExecFunction(name = "seconds_sub", argTypes = { "DATETIMEV2", "INT" }, returnType = "DATETIMEV2")
public static DateTimeV2Literal secondsSub(DateTimeV2Literal date, IntegerLiteral second) throws AnalysisException {
return secondsAdd(date, new IntegerLiteral(-second.getValue()));
}
}

View File

@ -48,7 +48,7 @@ public class SecondsSub extends ScalarFunction
);
public SecondsSub(Expression arg0, Expression arg1) {
super("Seconds_sub", arg0, arg1);
super("seconds_sub", arg0, arg1);
}
@Override

View File

@ -20,6 +20,7 @@ package org.apache.doris.nereids.trees.expressions.literal;
import org.apache.doris.analysis.LiteralExpr;
import org.apache.doris.catalog.Type;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.DateType;
@ -44,7 +45,10 @@ public class DateLiteral extends Literal {
protected static DateTimeFormatter DATE_FORMATTER = null;
protected static DateTimeFormatter DATE_FORMATTER_TWO_DIGIT = null;
protected static DateTimeFormatter DATEKEY_FORMATTER = null;
// for cast datetime type to date type.
protected static DateTimeFormatter DATE_TIME_FORMATTER = null;
private static final LocalDateTime startOfAD = LocalDateTime.of(0, 1, 1, 0, 0, 0);
private static final LocalDateTime endOfAD = LocalDateTime.of(9999, 12, 31, 23, 59, 59);
private static final Logger LOG = LogManager.getLogger(DateLiteral.class);
private static final DateLiteral MIN_DATE = new DateLiteral(0000, 1, 1);
@ -61,6 +65,7 @@ public class DateLiteral extends Literal {
DATE_FORMATTER = DateUtils.formatBuilder("%Y-%m-%d").toFormatter();
DATEKEY_FORMATTER = DateUtils.formatBuilder("%Y%m%d").toFormatter();
DATE_FORMATTER_TWO_DIGIT = DateUtils.formatBuilder("%y-%m-%d").toFormatter();
DATE_TIME_FORMATTER = DateUtils.formatBuilder("%Y-%m-%d %H:%i:%s").toFormatter();
} catch (AnalysisException e) {
LOG.error("invalid date format", e);
System.exit(-1);
@ -114,6 +119,8 @@ public class DateLiteral extends Literal {
dateTime = DATE_FORMATTER_TWO_DIGIT.parse(s);
} else if (s.length() == DATEKEY_LENGTH && !s.contains("-")) {
dateTime = DATEKEY_FORMATTER.parse(s);
} else if (s.length() == 19) {
dateTime = DATE_TIME_FORMATTER.parse(s);
} else {
dateTime = DATE_FORMATTER.parse(s);
}
@ -143,6 +150,10 @@ public class DateLiteral extends Literal {
return false;
}
protected static boolean isDateOutOfRange(LocalDateTime dateTime) {
return dateTime.isBefore(startOfAD) || dateTime.isAfter(endOfAD);
}
@Override
public Long getValue() {
return (year * 10000 + month * 100 + day) * 1000000L;
@ -190,18 +201,25 @@ public class DateLiteral extends Literal {
return day;
}
public DateLiteral plusDays(int days) {
LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusDays(days);
return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth());
public Expression plusDays(int days) {
return fromJavaDateType(DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusDays(days));
}
public DateLiteral plusMonths(int months) {
LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusMonths(months);
return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth());
public Expression plusMonths(int months) {
return fromJavaDateType(DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusMonths(months));
}
public DateLiteral plusYears(int years) {
LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusYears(years);
return new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth());
public Expression plusYears(int years) {
return fromJavaDateType(DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusYears(years));
}
public LocalDateTime toJavaDateType() {
return LocalDateTime.of(((int) getYear()), ((int) getMonth()), ((int) getDay()), 0, 0, 0);
}
public static Expression fromJavaDateType(LocalDateTime dateTime) {
return isDateOutOfRange(dateTime)
? new NullLiteral(DateType.INSTANCE)
: new DateLiteral(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth());
}
}

View File

@ -20,6 +20,7 @@ package org.apache.doris.nereids.trees.expressions.literal;
import org.apache.doris.analysis.LiteralExpr;
import org.apache.doris.catalog.Type;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DateTimeType;
import org.apache.doris.nereids.types.coercion.DateLikeType;
@ -44,8 +45,6 @@ import java.util.Objects;
* date time literal.
*/
public class DateTimeLiteral extends DateLiteral {
protected static DateTimeFormatter DATE_TIME_FORMATTER = null;
protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_HOUR = null;
protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_MINUTE = null;
protected static DateTimeFormatter DATE_TIME_FORMATTER_TWO_DIGIT = null;
@ -272,40 +271,28 @@ public class DateTimeLiteral extends DateLiteral {
return new org.apache.doris.analysis.DateLiteral(year, month, day, hour, minute, second, Type.DATETIME);
}
public DateTimeLiteral plusDays(int days) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusDays(days);
return new DateTimeLiteral(d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond());
public Expression plusYears(int years) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusYears(years));
}
public DateTimeLiteral plusYears(int years) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusYears(years);
return new DateTimeLiteral(d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond());
public Expression plusMonths(int months) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusMonths(months));
}
public DateTimeLiteral plusMonths(int months) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusMonths(months);
return new DateTimeLiteral(d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond());
public Expression plusDays(int days) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusDays(days));
}
public DateTimeLiteral plusHours(int hours) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusHours(hours);
return new DateTimeLiteral(d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond());
public Expression plusHours(int hours) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusHours(hours));
}
public DateTimeLiteral plusMinutes(int minutes) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusMinutes(minutes);
return new DateTimeLiteral(d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond());
public Expression plusMinutes(int minutes) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusMinutes(minutes));
}
public DateTimeLiteral plusSeconds(int seconds) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusSeconds(seconds);
return new DateTimeLiteral(d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond());
public Expression plusSeconds(long seconds) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER, getStringValue()).plusSeconds(seconds));
}
public long getHour() {
@ -331,4 +318,16 @@ public class DateTimeLiteral extends DateLiteral {
DateTimeLiteral other = (DateTimeLiteral) o;
return Objects.equals(getValue(), other.getValue());
}
public LocalDateTime toJavaDateType() {
return LocalDateTime.of(((int) getYear()), ((int) getMonth()), ((int) getDay()),
((int) getHour()), ((int) getMinute()), ((int) getSecond()));
}
public static Expression fromJavaDateType(LocalDateTime dateTime) {
return isDateOutOfRange(dateTime)
? new NullLiteral(DateTimeType.INSTANCE)
: new DateTimeLiteral(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth(),
dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond());
}
}

View File

@ -19,6 +19,7 @@ package org.apache.doris.nereids.trees.expressions.literal;
import org.apache.doris.analysis.LiteralExpr;
import org.apache.doris.nereids.exceptions.UnboundException;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.util.DateUtils;
@ -38,6 +39,10 @@ public class DateTimeV2Literal extends DateTimeLiteral {
super(dateType, s);
}
public DateTimeV2Literal(long year, long month, long day, long hour, long minute, long second) {
super(DateTimeV2Type.SYSTEM_DEFAULT, year, month, day, hour, minute, second, 0);
}
public DateTimeV2Literal(long year, long month, long day, long hour, long minute, long second, long microSecond) {
super(DateTimeV2Type.SYSTEM_DEFAULT, year, month, day, hour, minute, second, microSecond);
}
@ -77,44 +82,59 @@ public class DateTimeV2Literal extends DateTimeLiteral {
}
@Override
public DateTimeV2Literal plusYears(int years) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue()).plusYears(years);
return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 1000L);
public Expression plusYears(int years) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue())
.plusYears(years), getDataType().getScale());
}
@Override
public DateTimeV2Literal plusMonths(int months) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue()).plusMonths(months);
return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 1000L);
public Expression plusMonths(int months) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue())
.plusMonths(months), getDataType().getScale());
}
@Override
public DateTimeV2Literal plusDays(int days) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue()).plusDays(days);
return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 1000L);
public Expression plusDays(int days) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue())
.plusDays(days), getDataType().getScale());
}
@Override
public DateTimeV2Literal plusHours(int hours) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue()).plusHours(hours);
return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 1000L);
public Expression plusHours(int hours) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue())
.plusHours(hours), getDataType().getScale());
}
@Override
public DateTimeV2Literal plusMinutes(int minutes) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue()).plusMinutes(minutes);
return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 1000L);
public Expression plusMinutes(int minutes) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue())
.plusMinutes(minutes), getDataType().getScale());
}
@Override
public DateTimeV2Literal plusSeconds(int seconds) {
LocalDateTime d = DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue()).plusSeconds(seconds);
return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthValue(), d.getDayOfMonth(),
d.getHour(), d.getMinute(), d.getSecond(), d.getNano() / 1000L);
public Expression plusSeconds(long seconds) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue())
.plusSeconds(seconds), getDataType().getScale());
}
public Expression plusMicroSeconds(int microSeconds) {
return fromJavaDateType(DateUtils.getTime(DATE_TIME_FORMATTER_TO_MICRO_SECOND, getStringValue())
.plusNanos(microSeconds * 1000L), getDataType().getScale());
}
public static Expression fromJavaDateType(LocalDateTime dateTime) {
return fromJavaDateType(dateTime, 0);
}
/**
* convert java LocalDateTime object to DateTimeV2Literal object.
*/
public static Expression fromJavaDateType(LocalDateTime dateTime, int precision) {
return isDateOutOfRange(dateTime)
? new NullLiteral(DateTimeV2Type.of(precision))
: new DateTimeV2Literal(DateTimeV2Type.of(precision),
dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth(),
dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond(),
dateTime.getNano() / (long) Math.pow(10, 9 - precision));
}
}

View File

@ -20,6 +20,7 @@ package org.apache.doris.nereids.trees.expressions.literal;
import org.apache.doris.analysis.LiteralExpr;
import org.apache.doris.catalog.Type;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DateV2Type;
import org.apache.doris.nereids.util.DateUtils;
@ -49,18 +50,21 @@ public class DateV2Literal extends DateLiteral {
return visitor.visitDateV2Literal(this, context);
}
public DateV2Literal plusDays(int days) {
LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusDays(days);
return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth());
public Expression plusDays(int days) {
return fromJavaDateType(DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusDays(days));
}
public DateV2Literal plusMonths(int months) {
LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusMonths(months);
return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth());
public Expression plusMonths(int months) {
return fromJavaDateType(DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusMonths(months));
}
public DateV2Literal plusYears(int years) {
LocalDateTime dateTime = DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusYears(years);
return new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth());
public Expression plusYears(int years) {
return fromJavaDateType(DateUtils.getTime(DATE_FORMATTER, getStringValue()).plusYears(years));
}
public static Expression fromJavaDateType(LocalDateTime dateTime) {
return isDateOutOfRange(dateTime)
? new NullLiteral(DateV2Type.INSTANCE)
: new DateV2Literal(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth());
}
}

View File

@ -180,7 +180,7 @@ public abstract class DataType implements AbstractDataType {
case "null_type": // ScalarType.NULL.toSql() return "null_type", so support it
return NullType.INSTANCE;
case "date":
return fromCatalogType(ScalarType.createDateType());
return DateType.INSTANCE;
case "datev2":
return DateV2Type.INSTANCE;
case "time":

View File

@ -59,6 +59,7 @@ import org.apache.doris.nereids.trees.expressions.literal.FloatLiteral;
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral;
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.SmallIntLiteral;
import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral;
import org.apache.doris.nereids.trees.expressions.literal.StringLiteral;
@ -227,7 +228,9 @@ public class TypeCoercionUtils {
* cast input type if input's datatype is not same with dateType.
*/
public static Expression castIfNotSameType(Expression input, DataType targetType) {
if (input.getDataType().equals(targetType) || isSubqueryAndDataTypeIsBitmap(input)
if (input.isNullLiteral()) {
return new NullLiteral(targetType);
} else if (input.getDataType().equals(targetType) || isSubqueryAndDataTypeIsBitmap(input)
|| (isVarCharOrStringType(input.getDataType())
&& isVarCharOrStringType(targetType))) {
return input;
@ -1011,7 +1014,7 @@ public class TypeCoercionUtils {
}
/**
* two types' common type, see {@link TypeCoercionUtilsTest#testFindPrimitiveCommonType()}
* two types' common type, see TypeCoercionUtilsTest#testFindCommonPrimitiveTypeForCaseWhen()
*/
@VisibleForTesting
protected static Optional<DataType> findCommonPrimitiveTypeForCaseWhen(DataType t1, DataType t2) {