[Fix](from_unixtime) Keep consistent with MySQL & bug fix (#25966)

Bug fix: implicit convert from int32 -> int64 makes negative time stamp valid, so change signature to int64
Consistent: keep consistent with mysql.
This commit is contained in:
zhiqiang
2023-10-31 01:31:24 -05:00
committed by GitHub
parent 8d7abf60f9
commit 0449a240f4
17 changed files with 112 additions and 52 deletions

View File

@ -20,12 +20,15 @@ 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.IntegerLiteral;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
import org.apache.doris.nereids.types.VarcharType;
import org.apache.doris.nereids.util.DateUtils;
import java.time.Duration;
@ -446,22 +449,21 @@ public class DateTimeExtractAndTransform {
/**
* 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;
}
@ExecFunction(name = "from_unixtime", argTypes = {"BIGINT"}, returnType = "VARCHAR")
public static Expression fromUnixTime(BigIntLiteral second) {
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;
@ExecFunction(name = "from_unixtime", argTypes = {"BIGINT", "VARCHAR"}, returnType = "VARCHAR")
public static Expression fromUnixTime(BigIntLiteral second, VarcharLiteral format) {
// 32536771199L is max valid timestamp of mysql from_unix_time
if (second.getValue() < 0 || second.getValue() > 32536771199L) {
return new NullLiteral(VarcharType.SYSTEM_DEFAULT);
}
ZonedDateTime dateTime = LocalDateTime.of(1970, 1, 1, 0, 0, 0)
.plusSeconds(second.getValue())
.atZone(ZoneId.of("UTC+0"))

View File

@ -22,7 +22,7 @@ import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.IntegerType;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.StringType;
import org.apache.doris.nereids.types.VarcharType;
@ -38,9 +38,9 @@ public class FromUnixtime extends ScalarFunction
implements ExplicitlyCastableSignature, AlwaysNullable {
public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(IntegerType.INSTANCE),
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(IntegerType.INSTANCE, VarcharType.SYSTEM_DEFAULT),
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(IntegerType.INSTANCE, StringType.INSTANCE)
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(BigIntType.INSTANCE),
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(BigIntType.INSTANCE, VarcharType.SYSTEM_DEFAULT),
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(BigIntType.INSTANCE, StringType.INSTANCE)
);
/**

View File

@ -231,10 +231,11 @@ public class FEFunctions {
return new IntLiteral(unixTime, Type.INT);
}
@FEFunction(name = "from_unixtime", argTypes = { "INT" }, returnType = "VARCHAR")
@FEFunction(name = "from_unixtime", argTypes = { "BIGINT" }, returnType = "VARCHAR")
public static StringLiteral fromUnixTime(LiteralExpr unixTime) throws AnalysisException {
// if unixTime < 0, we should return null, throw a exception and let BE process
if (unixTime.getLongValue() < 0 || unixTime.getLongValue() >= Integer.MAX_VALUE) {
// 32536771199L is max valid timestamp of mysql from_unix_time
if (unixTime.getLongValue() < 0 || unixTime.getLongValue() > 32536771199L) {
throw new AnalysisException("unix timestamp out of range");
}
DateLiteral dl = new DateLiteral(unixTime.getLongValue() * 1000, TimeUtils.getTimeZone(),
@ -242,10 +243,11 @@ public class FEFunctions {
return new StringLiteral(dl.getStringValue());
}
@FEFunction(name = "from_unixtime", argTypes = { "INT", "VARCHAR" }, returnType = "VARCHAR")
@FEFunction(name = "from_unixtime", argTypes = { "BIGINT", "VARCHAR" }, returnType = "VARCHAR")
public static StringLiteral fromUnixTime(LiteralExpr unixTime, StringLiteral fmtLiteral) throws AnalysisException {
// if unixTime < 0, we should return null, throw a exception and let BE process
if (unixTime.getLongValue() < 0 || unixTime.getLongValue() >= Integer.MAX_VALUE) {
// 32536771199L is max valid timestamp of mysql from_unix_time
if (unixTime.getLongValue() < 0 || unixTime.getLongValue() >= 32536771199L) {
throw new AnalysisException("unix timestamp out of range");
}
DateLiteral dl = new DateLiteral(unixTime.getLongValue() * 1000, TimeUtils.getTimeZone(),

View File

@ -41,7 +41,7 @@ import java.util.function.Function;
/*
* rewrite sql: select * from table where from_unixtime(query_time) > '2021-03-02 12:12:23'
* into: select * from table where query_time > 1614658343
* query_time is integer type
* query_time is big integer type to keep consistent with mysql
* 1614658343 is the timestamp of 2021-03-02 12:12:23
* this rewrite can improve the query performance, because from_unixtime is cpu-exhausted
* */
@ -115,7 +115,7 @@ public class RewriteFromUnixTimeRule implements ExprRewriteRule {
return expr;
}
SlotRef sr = (SlotRef) paramSlot;
if (!sr.getColumn().getType().isIntegerType()) {
if (!sr.getColumn().getType().isBigIntType()) {
return new BoolLiteral(false);
}
Expr right = bp.getChild(1);