[Enhancement](function) support unix_timestamp with float (#26827)
--------- Co-authored-by: YangWithU <plzw8@outlook.com>
This commit is contained in:
@ -30,6 +30,7 @@ import org.apache.doris.catalog.Function;
|
||||
import org.apache.doris.catalog.FunctionSet;
|
||||
import org.apache.doris.catalog.FunctionUtil;
|
||||
import org.apache.doris.catalog.MapType;
|
||||
import org.apache.doris.catalog.PrimitiveType;
|
||||
import org.apache.doris.catalog.ScalarFunction;
|
||||
import org.apache.doris.catalog.ScalarType;
|
||||
import org.apache.doris.catalog.StructField;
|
||||
@ -1681,6 +1682,27 @@ public class FunctionCallExpr extends Expr {
|
||||
children.set(1, new StringLiteral("%Y-%m-%d %H:%i:%s"));
|
||||
}
|
||||
}
|
||||
|
||||
if (fnName.getFunction().equalsIgnoreCase("unix_timestamp") && children.size() == 1) {
|
||||
if (getChild(0).type.isDatetimeV2()) {
|
||||
ScalarType type = (ScalarType) getChild(0).type;
|
||||
Preconditions.checkArgument(type.getScalarScale() <= 6,
|
||||
"DatetimeV2's scale shouldn't exceed 6 but meet " + type.getScalarScale());
|
||||
fn.setReturnType(
|
||||
ScalarType.createDecimalType(PrimitiveType.DECIMAL64, 10 + type.getScalarScale(),
|
||||
type.getScalarScale()));
|
||||
} else if (getChild(0).type.isStringType()) {
|
||||
// use DATETIME to make scale adaptive
|
||||
ScalarType type = ((ScalarType) (((StringLiteral) getChild(0))
|
||||
.uncheckedCastTo(ScalarType.DATETIME).type));
|
||||
if (type.isDatetimeV2()) {
|
||||
int scale = ((ScalarType) (((StringLiteral) getChild(0))
|
||||
.uncheckedCastTo(ScalarType.DATETIME).type)).getScalarScale();
|
||||
fn.setReturnType(
|
||||
ScalarType.createDecimalType(PrimitiveType.DECIMAL64, 10 + scale, scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fnName.getFunction().equalsIgnoreCase("convert_to")) {
|
||||
if (children.size() < 2 || !getChild(1).isConstant()) {
|
||||
|
||||
@ -25,14 +25,17 @@ 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.DecimalV3Literal;
|
||||
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.SmallIntLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
|
||||
import org.apache.doris.nereids.types.DecimalV3Type;
|
||||
import org.apache.doris.nereids.types.VarcharType;
|
||||
import org.apache.doris.nereids.util.DateUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
@ -494,9 +497,19 @@ public class DateTimeExtractAndTransform {
|
||||
return new IntegerLiteral(getTimestamp(date.toJavaDateType()));
|
||||
}
|
||||
|
||||
@ExecFunction(name = "unix_timestamp", argTypes = {"DATETIMEV2"}, returnType = "INT")
|
||||
/**
|
||||
* date transformation function: unix_timestamp
|
||||
*/
|
||||
@ExecFunction(name = "unix_timestamp", argTypes = { "DATETIMEV2" }, returnType = "DECIMALV3")
|
||||
public static Expression unixTimestamp(DateTimeV2Literal date) {
|
||||
return new IntegerLiteral(getTimestamp(date.toJavaDateType()));
|
||||
if (date.getMicroSecond() == 0) {
|
||||
return new DecimalV3Literal(DecimalV3Type.createDecimalV3TypeLooseCheck(10, 0),
|
||||
new BigDecimal(getTimestamp(date.toJavaDateType()).toString()));
|
||||
}
|
||||
int scale = date.getDataType().getScale();
|
||||
String val = getTimestamp(date.toJavaDateType()).toString() + "." + date.getMicrosecondString();
|
||||
return new DecimalV3Literal(DecimalV3Type.createDecimalV3TypeLooseCheck(10 + scale, scale),
|
||||
new BigDecimal(val));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -21,12 +21,13 @@ import org.apache.doris.catalog.FunctionSignature;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
|
||||
import org.apache.doris.nereids.trees.expressions.functions.Nondeterministic;
|
||||
import org.apache.doris.nereids.trees.expressions.functions.PropagateNullableOnDateLikeV2Args;
|
||||
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
|
||||
import org.apache.doris.nereids.types.DataType;
|
||||
import org.apache.doris.nereids.types.DateTimeType;
|
||||
import org.apache.doris.nereids.types.DateTimeV2Type;
|
||||
import org.apache.doris.nereids.types.DateType;
|
||||
import org.apache.doris.nereids.types.DateV2Type;
|
||||
import org.apache.doris.nereids.types.DecimalV3Type;
|
||||
import org.apache.doris.nereids.types.IntegerType;
|
||||
import org.apache.doris.nereids.types.StringType;
|
||||
import org.apache.doris.nereids.types.VarcharType;
|
||||
@ -40,16 +41,19 @@ import java.util.List;
|
||||
* ScalarFunction 'unix_timestamp'. This class is generated by GenerateFunction.
|
||||
*/
|
||||
public class UnixTimestamp extends ScalarFunction
|
||||
implements ExplicitlyCastableSignature, PropagateNullableOnDateLikeV2Args, Nondeterministic {
|
||||
implements ExplicitlyCastableSignature, Nondeterministic {
|
||||
|
||||
// we got changes when computeSignature
|
||||
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
|
||||
FunctionSignature.ret(IntegerType.INSTANCE).args(),
|
||||
FunctionSignature.ret(IntegerType.INSTANCE).args(DateTimeV2Type.SYSTEM_DEFAULT),
|
||||
FunctionSignature.ret(DecimalV3Type.createDecimalV3Type(16, 6)).args(DateTimeV2Type.SYSTEM_DEFAULT),
|
||||
FunctionSignature.ret(IntegerType.INSTANCE).args(DateV2Type.INSTANCE),
|
||||
FunctionSignature.ret(IntegerType.INSTANCE).args(DateTimeType.INSTANCE),
|
||||
FunctionSignature.ret(IntegerType.INSTANCE).args(DateType.INSTANCE),
|
||||
FunctionSignature.ret(IntegerType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT),
|
||||
FunctionSignature.ret(IntegerType.INSTANCE).args(StringType.INSTANCE, StringType.INSTANCE)
|
||||
FunctionSignature.ret(DecimalV3Type.createDecimalV3Type(16, 6)).args(VarcharType.SYSTEM_DEFAULT,
|
||||
VarcharType.SYSTEM_DEFAULT),
|
||||
FunctionSignature.ret(DecimalV3Type.createDecimalV3Type(16, 6)).args(StringType.INSTANCE,
|
||||
StringType.INSTANCE)
|
||||
);
|
||||
|
||||
/**
|
||||
@ -74,14 +78,41 @@ public class UnixTimestamp extends ScalarFunction
|
||||
}
|
||||
|
||||
/**
|
||||
* custom compute nullable.
|
||||
* [['unix_timestamp'], 'INT', [], 'ALWAYS_NOT_NULLABLE'],
|
||||
* [['unix_timestamp'], 'INT', ['DATETIME'], 'DEPEND_ON_ARGUMENT'],
|
||||
* [['unix_timestamp'], 'INT', ['DATE'], 'DEPEND_ON_ARGUMENT'],
|
||||
* [['unix_timestamp'], 'DECIMAL64', ['DATETIMEV2'], 'DEPEND_ON_ARGUMENT'],
|
||||
* [['unix_timestamp'], 'INT', ['DATEV2'], 'DEPEND_ON_ARGUMENT'],
|
||||
* [['unix_timestamp'], 'INT', ['VARCHAR', 'VARCHAR'], 'ALWAYS_NULLABLE'],
|
||||
* [['unix_timestamp'], 'INT', ['STRING', 'STRING'], 'ALWAYS_NULLABLE'],
|
||||
*/
|
||||
@Override
|
||||
public boolean nullable() {
|
||||
if (arity() == 0) {
|
||||
return false;
|
||||
}
|
||||
return PropagateNullableOnDateLikeV2Args.super.nullable();
|
||||
if (arity() == 1) {
|
||||
return child(0).nullable();
|
||||
}
|
||||
if (arity() == 2 && child(0).getDataType().isStringLikeType() && child(1).getDataType().isStringLikeType()) {
|
||||
return true;
|
||||
}
|
||||
return child(0).nullable() || child(1).nullable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionSignature computeSignature(FunctionSignature signature) {
|
||||
if (arity() != 1) {
|
||||
return signature;
|
||||
}
|
||||
DataType argType0 = getArgumentType(0);
|
||||
if (argType0.isDateTimeV2Type()) {
|
||||
int scale = ((DateTimeV2Type) argType0).getScale();
|
||||
return signature.withReturnType(DecimalV3Type.createDecimalV3Type(10 + scale, scale));
|
||||
} else if (argType0.isStringLikeType()) {
|
||||
return signature.withReturnType(DecimalV3Type.createDecimalV3Type(16, 6));
|
||||
}
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -106,6 +106,14 @@ public class DateTimeV2Literal extends DateTimeLiteral {
|
||||
(int) (microSecond / Math.pow(10, DateTimeV2Type.MAX_SCALE - getDataType().getScale())));
|
||||
}
|
||||
|
||||
public String getMicrosecondString() {
|
||||
if (microSecond == 0) {
|
||||
return "0";
|
||||
}
|
||||
return String.format("%0" + getDataType().getScale() + "d",
|
||||
(int) (microSecond / Math.pow(10, DateTimeV2Type.MAX_SCALE - getDataType().getScale())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression plusYears(long years) {
|
||||
return fromJavaDateType(
|
||||
|
||||
@ -468,6 +468,11 @@ public class TypeCoercionUtils {
|
||||
return promoted;
|
||||
}
|
||||
}
|
||||
// adapt scale when from string to datetimev2 with float
|
||||
if (type.isStringLikeType() && dataType.isDateTimeV2Type()) {
|
||||
return recordTypeCoercionForSubQuery(input,
|
||||
DateTimeV2Type.forTypeFromString(((Literal) input).getStringValue()));
|
||||
}
|
||||
}
|
||||
return recordTypeCoercionForSubQuery(input, dataType);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user