[Regression](datev2) Add test cases for datev2/datetimev2 (#11831)
This commit is contained in:
@ -431,9 +431,6 @@ public class DateLiteral extends LiteralExpr {
|
||||
minute = getOrDefault(dateTime, ChronoField.MINUTE_OF_HOUR, 0);
|
||||
second = getOrDefault(dateTime, ChronoField.SECOND_OF_MINUTE, 0);
|
||||
microsecond = getOrDefault(dateTime, ChronoField.MICRO_OF_SECOND, 0);
|
||||
if (type.isDatetimeV2()) {
|
||||
this.roundFloor(((ScalarType) type).getScalarScale());
|
||||
}
|
||||
this.type = type;
|
||||
} catch (Exception ex) {
|
||||
throw new AnalysisException("date literal [" + s + "] is invalid: " + ex.getMessage());
|
||||
@ -526,12 +523,14 @@ public class DateLiteral extends LiteralExpr {
|
||||
if (type.isDate() || type.isDateV2()) {
|
||||
return String.format("%04d-%02d-%02d", year, month, day);
|
||||
} else if (type.isDatetimeV2()) {
|
||||
long ms = Double.valueOf(microsecond / (int) (Math.pow(10, 6 - ((ScalarType) type).getScalarScale()))
|
||||
* (Math.pow(10, 6 - ((ScalarType) type).getScalarScale()))).longValue();
|
||||
String tmp = String.format("%04d-%02d-%02d %02d:%02d:%02d",
|
||||
year, month, day, hour, minute, second);
|
||||
if (microsecond == 0) {
|
||||
if (ms == 0) {
|
||||
return tmp;
|
||||
}
|
||||
return tmp + String.format(".%06d", microsecond);
|
||||
return tmp + String.format(".%06d", ms);
|
||||
} else {
|
||||
return String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
|
||||
}
|
||||
@ -542,13 +541,23 @@ public class DateLiteral extends LiteralExpr {
|
||||
long remain = Double.valueOf(microsecond % (Math.pow(10, 6 - newScale))).longValue();
|
||||
if (remain != 0) {
|
||||
microsecond = Double.valueOf((microsecond + (Math.pow(10, 6 - newScale)))
|
||||
/ (Math.pow(10, 6 - newScale)) * (Math.pow(10, 6 - newScale))).longValue();
|
||||
/ (int) (Math.pow(10, 6 - newScale)) * (Math.pow(10, 6 - newScale))).longValue();
|
||||
}
|
||||
if (microsecond > MAX_MICROSECOND) {
|
||||
microsecond %= microsecond;
|
||||
DateLiteral result = this.plusSeconds(1);
|
||||
this.second = result.second;
|
||||
this.minute = result.minute;
|
||||
this.hour = result.hour;
|
||||
this.day = result.day;
|
||||
this.month = result.month;
|
||||
this.year = result.year;
|
||||
}
|
||||
type = ScalarType.createDatetimeV2Type(newScale);
|
||||
}
|
||||
|
||||
public void roundFloor(int newScale) {
|
||||
microsecond = Double.valueOf(microsecond / (Math.pow(10, 6 - newScale))
|
||||
microsecond = Double.valueOf(microsecond / (int) (Math.pow(10, 6 - newScale))
|
||||
* (Math.pow(10, 6 - newScale))).longValue();
|
||||
type = ScalarType.createDatetimeV2Type(newScale);
|
||||
}
|
||||
@ -580,6 +589,9 @@ public class DateLiteral extends LiteralExpr {
|
||||
|
||||
@Override
|
||||
protected void toThrift(TExprNode msg) {
|
||||
if (type.isDatetimeV2()) {
|
||||
this.roundFloor(((ScalarType) type).getScalarScale());
|
||||
}
|
||||
msg.node_type = TExprNodeType.DATE_LITERAL;
|
||||
msg.date_literal = new TDateLiteral(getStringValue());
|
||||
}
|
||||
@ -870,11 +882,11 @@ public class DateLiteral extends LiteralExpr {
|
||||
return new DateLiteral(getTimeFormatter().plusHours(hour), type);
|
||||
}
|
||||
|
||||
public DateLiteral plusMinutes(int minute) throws AnalysisException {
|
||||
public DateLiteral plusMinutes(int minute) {
|
||||
return new DateLiteral(getTimeFormatter().plusMinutes(minute), type);
|
||||
}
|
||||
|
||||
public DateLiteral plusSeconds(int second) throws AnalysisException {
|
||||
public DateLiteral plusSeconds(int second) {
|
||||
return new DateLiteral(getTimeFormatter().plusSeconds(second), type);
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
package org.apache.doris.analysis;
|
||||
|
||||
import org.apache.doris.catalog.Type;
|
||||
import org.apache.doris.common.AnalysisException;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
@ -42,10 +43,10 @@ public class DefaultValueExprDef {
|
||||
* generate a FunctionCallExpr
|
||||
* @return FunctionCallExpr of exprName
|
||||
*/
|
||||
public FunctionCallExpr getExpr() {
|
||||
public FunctionCallExpr getExpr(Type type) {
|
||||
FunctionCallExpr expr = new FunctionCallExpr(exprName, new FunctionParams(null));
|
||||
try {
|
||||
expr.analyzeImplForDefaultValue();
|
||||
expr.analyzeImplForDefaultValue(type);
|
||||
} catch (AnalysisException e) {
|
||||
LOG.warn("analyzeImplForDefaultValue fail: {}", e);
|
||||
}
|
||||
|
||||
@ -827,9 +827,10 @@ public class FunctionCallExpr extends Expr {
|
||||
* to generate a builtinFunction.
|
||||
* @throws AnalysisException
|
||||
*/
|
||||
public void analyzeImplForDefaultValue() throws AnalysisException {
|
||||
public void analyzeImplForDefaultValue(Type type) throws AnalysisException {
|
||||
fn = getBuiltinFunction(fnName.getFunction(), new Type[0], Function.CompareMode.IS_NONSTRICT_SUPERTYPE_OF);
|
||||
type = ScalarType.getDefaultDateType(fn.getReturnType());
|
||||
fn.setReturnType(type);
|
||||
this.type = type;
|
||||
for (int i = 0; i < children.size(); ++i) {
|
||||
if (getChild(i).getType().isNull()) {
|
||||
uncheckedCastChild(Type.BOOLEAN, i);
|
||||
@ -936,6 +937,9 @@ public class FunctionCallExpr extends Expr {
|
||||
childTypes[2] = assignmentCompatibleType;
|
||||
fn = getBuiltinFunction(fnName.getFunction(), childTypes,
|
||||
Function.CompareMode.IS_NONSTRICT_SUPERTYPE_OF);
|
||||
if (assignmentCompatibleType.isDatetimeV2()) {
|
||||
fn.setReturnType(assignmentCompatibleType);
|
||||
}
|
||||
} else if (AggregateFunction.SUPPORT_ORDER_BY_AGGREGATE_FUNCTION_NAME_SET.contains(
|
||||
fnName.getFunction().toLowerCase())) {
|
||||
// order by elements add as child like windows function. so if we get the
|
||||
@ -995,6 +999,15 @@ public class FunctionCallExpr extends Expr {
|
||||
throw new AnalysisException(getFunctionNotFoundError(collectChildReturnTypes()));
|
||||
}
|
||||
|
||||
if (fn.getArgs().length == children.size() && fn.getArgs().length == 1) {
|
||||
if (fn.getArgs()[0].isDatetimeV2() && children.get(0).getType().isDatetimeV2()) {
|
||||
fn.setArgType(children.get(0).getType(), 0);
|
||||
if (fn.getReturnType().isDatetimeV2()) {
|
||||
fn.setReturnType(children.get(0).getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fnName.getFunction().equalsIgnoreCase("from_unixtime")
|
||||
|| fnName.getFunction().equalsIgnoreCase("date_format")) {
|
||||
// if has only one child, it has default time format: yyyy-MM-dd HH:mm:ss.SSSSSS
|
||||
|
||||
@ -319,7 +319,7 @@ public class Column implements Writable {
|
||||
return defaultValueLiteral;
|
||||
}
|
||||
if (defaultValueExprDef != null) {
|
||||
return defaultValueExprDef.getExpr();
|
||||
return defaultValueExprDef.getExpr(type);
|
||||
}
|
||||
Expr result = defaultValueLiteral.castTo(getType());
|
||||
result.checkValueValid();
|
||||
|
||||
@ -180,6 +180,10 @@ public class Function implements Writable {
|
||||
this.retType = type;
|
||||
}
|
||||
|
||||
public void setArgType(Type type, int i) {
|
||||
argTypes[i] = type;
|
||||
}
|
||||
|
||||
public Type[] getArgs() {
|
||||
return argTypes;
|
||||
}
|
||||
|
||||
@ -986,6 +986,12 @@ public class ScalarType extends Type {
|
||||
PrimitiveType largerType =
|
||||
(t1.type.ordinal() > t2.type.ordinal() ? t1.type : t2.type);
|
||||
PrimitiveType result = null;
|
||||
if (t1.isDatetimeV2() && t2.isDatetimeV2()) {
|
||||
return t1.scale > t2.scale ? t1 : t2;
|
||||
}
|
||||
if ((t1.isDatetimeV2() || t1.isDateV2()) && (t1.isDatetimeV2() || t1.isDateV2())) {
|
||||
return t1.isDatetimeV2() ? t1 : t2;
|
||||
}
|
||||
if (strict) {
|
||||
result = strictCompatibilityMatrix[smallerType.ordinal()][largerType.ordinal()];
|
||||
}
|
||||
|
||||
@ -1547,6 +1547,8 @@ public abstract class Type {
|
||||
return t1;
|
||||
} else if (t2.isDatetimeV2()) {
|
||||
return t2;
|
||||
} else if (t2.isDateV2() || t1.isDateV2()) {
|
||||
return Type.DATETIMEV2;
|
||||
} else {
|
||||
return ScalarType.getDefaultDateType(Type.DATETIME);
|
||||
}
|
||||
|
||||
@ -591,10 +591,10 @@ public class DeleteHandler implements Writable {
|
||||
Type.fromPrimitiveType(column.getDataType())));
|
||||
} else if (column.getDataType() == PrimitiveType.DATETIMEV2) {
|
||||
DateLiteral dateLiteral = new DateLiteral(value,
|
||||
ScalarType.createDecimalType(ScalarType.MAX_DATETIMEV2_SCALE));
|
||||
ScalarType.createDatetimeV2Type(ScalarType.MAX_DATETIMEV2_SCALE));
|
||||
value = dateLiteral.getStringValue();
|
||||
binaryPredicate.setChild(1, LiteralExpr.create(value,
|
||||
ScalarType.createDecimalType(ScalarType.MAX_DATETIMEV2_SCALE)));
|
||||
ScalarType.createDatetimeV2Type(ScalarType.MAX_DATETIMEV2_SCALE)));
|
||||
}
|
||||
LiteralExpr.create(value, Type.fromPrimitiveType(column.getDataType()));
|
||||
} catch (AnalysisException e) {
|
||||
|
||||
@ -99,44 +99,41 @@ public class RoundLiteralInBinaryPredicatesRule implements ExprRewriteRule {
|
||||
Expr expr1 = expr.getChild(1);
|
||||
if (expr0.getType().isDatetimeV2() && expr1 instanceof DateLiteral && expr1.getType().isDatetimeV2()) {
|
||||
DateLiteral literal = (DateLiteral) expr1;
|
||||
if (((ScalarType) expr0.getType()).getScalarScale()
|
||||
< ((ScalarType) expr1.getType()).getScalarScale()) {
|
||||
switch (op) {
|
||||
case EQ: {
|
||||
long originValue = literal.getMicrosecond();
|
||||
literal.roundCeiling(((ScalarType) expr0.getType()).getScalarScale());
|
||||
if (literal.getMicrosecond() == originValue) {
|
||||
expr.setChild(1, literal);
|
||||
return expr;
|
||||
} else {
|
||||
return new BoolLiteral(false);
|
||||
}
|
||||
}
|
||||
case NE: {
|
||||
long originValue = literal.getMicrosecond();
|
||||
literal.roundCeiling(((ScalarType) expr0.getType()).getScalarScale());
|
||||
if (literal.getMicrosecond() == originValue) {
|
||||
expr.setChild(1, literal);
|
||||
return expr;
|
||||
} else {
|
||||
return new BoolLiteral(true);
|
||||
}
|
||||
}
|
||||
case GT:
|
||||
case LE: {
|
||||
literal.roundFloor(((ScalarType) expr0.getType()).getScalarScale());
|
||||
switch (op) {
|
||||
case EQ: {
|
||||
long originValue = literal.getMicrosecond();
|
||||
literal.roundCeiling(((ScalarType) expr0.getType()).getScalarScale());
|
||||
if (literal.getMicrosecond() == originValue) {
|
||||
expr.setChild(1, literal);
|
||||
return expr;
|
||||
} else {
|
||||
return new BoolLiteral(false);
|
||||
}
|
||||
case LT:
|
||||
case GE: {
|
||||
literal.roundCeiling(((ScalarType) expr0.getType()).getScalarScale());
|
||||
expr.setChild(1, literal);
|
||||
return expr;
|
||||
}
|
||||
default:
|
||||
return expr;
|
||||
}
|
||||
case NE: {
|
||||
long originValue = literal.getMicrosecond();
|
||||
literal.roundCeiling(((ScalarType) expr0.getType()).getScalarScale());
|
||||
if (literal.getMicrosecond() == originValue) {
|
||||
expr.setChild(1, literal);
|
||||
return expr;
|
||||
} else {
|
||||
return new BoolLiteral(true);
|
||||
}
|
||||
}
|
||||
case GT:
|
||||
case LE: {
|
||||
literal.roundFloor(((ScalarType) expr0.getType()).getScalarScale());
|
||||
expr.setChild(1, literal);
|
||||
return expr;
|
||||
}
|
||||
case LT:
|
||||
case GE: {
|
||||
literal.roundCeiling(((ScalarType) expr0.getType()).getScalarScale());
|
||||
expr.setChild(1, literal);
|
||||
return expr;
|
||||
}
|
||||
default:
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
|
||||
Reference in New Issue
Block a user