[improvement](column) Support for the default value of current_timestamp in microsecond (#21487)

This commit is contained in:
zy-kkk
2023-07-11 14:04:13 +08:00
committed by GitHub
parent ca71048f7f
commit d3be10ee58
6 changed files with 222 additions and 7 deletions

View File

@ -3518,6 +3518,10 @@ opt_default_value ::=
{:
RESULT = ColumnDef.DefaultValue.CURRENT_TIMESTAMP_DEFAULT_VALUE;
:}
| KW_DEFAULT KW_CURRENT_TIMESTAMP LPAREN INTEGER_LITERAL:precision RPAREN
{:
RESULT = ColumnDef.DefaultValue.currentTimeStampDefaultValueWithPrecision(precision);
:}
;
opt_is_key ::=

View File

@ -36,6 +36,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
@ -88,6 +89,12 @@ public class ColumnDef {
this.defaultValueExprDef = new DefaultValueExprDef(exprName);
}
public DefaultValue(boolean isSet, String value, String exprName, Long precision) {
this.isSet = isSet;
this.value = value;
this.defaultValueExprDef = new DefaultValueExprDef(exprName, precision);
}
// default "CURRENT_TIMESTAMP", only for DATETIME type
public static String CURRENT_TIMESTAMP = "CURRENT_TIMESTAMP";
public static String NOW = "now";
@ -104,14 +111,60 @@ public class ColumnDef {
// default "value", "[]" means empty array
public static DefaultValue ARRAY_EMPTY_DEFAULT_VALUE = new DefaultValue(true, "[]");
public static DefaultValue currentTimeStampDefaultValueWithPrecision(Long precision) {
if (precision > ScalarType.MAX_DATETIMEV2_SCALE || precision < 0) {
throw new IllegalArgumentException("column's default value current_timestamp"
+ " precision must be between 0 and 6");
}
if (precision == 0) {
return new DefaultValue(true, CURRENT_TIMESTAMP, NOW);
}
String value = CURRENT_TIMESTAMP + "(" + precision + ")";
String exprName = NOW;
return new DefaultValue(true, value, exprName, precision);
}
public boolean isCurrentTimeStamp() {
return "CURRENT_TIMESTAMP".equals(value) && NOW.equals(defaultValueExprDef.getExprName());
}
public boolean isCurrentTimeStampWithPrecision() {
return defaultValueExprDef != null && value.startsWith(CURRENT_TIMESTAMP + "(")
&& NOW.equals(defaultValueExprDef.getExprName());
}
public long getCurrentTimeStampPrecision() {
if (isCurrentTimeStampWithPrecision()) {
return Long.parseLong(value.substring(CURRENT_TIMESTAMP.length() + 1, value.length() - 1));
}
return 0;
}
public String getValue() {
return isCurrentTimeStamp()
? LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()).toString().replace('T', ' ')
: value;
if (isCurrentTimeStamp()) {
return LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()).toString().replace('T', ' ');
} else if (isCurrentTimeStampWithPrecision()) {
long precision = getCurrentTimeStampPrecision();
String format = "yyyy-MM-dd HH:mm:ss";
if (precision == 0) {
return LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()).toString().replace('T', ' ');
} else if (precision == 1) {
format = "yyyy-MM-dd HH:mm:ss.S";
} else if (precision == 2) {
format = "yyyy-MM-dd HH:mm:ss.SS";
} else if (precision == 3) {
format = "yyyy-MM-dd HH:mm:ss.SSS";
} else if (precision == 4) {
format = "yyyy-MM-dd HH:mm:ss.SSSS";
} else if (precision == 5) {
format = "yyyy-MM-dd HH:mm:ss.SSSSS";
} else if (precision == 6) {
format = "yyyy-MM-dd HH:mm:ss.SSSSSS";
}
return LocalDateTime.now(TimeUtils.getTimeZone().toZoneId())
.format(DateTimeFormatter.ofPattern(format));
}
return value;
}
}
@ -459,6 +512,17 @@ public class ColumnDef {
new DateLiteral(defaultValue, scalarType);
} else {
if (defaultValueExprDef.getExprName().equals(DefaultValue.NOW)) {
if (defaultValueExprDef.getPrecision() != null) {
Long defaultValuePrecision = defaultValueExprDef.getPrecision();
String typeStr = scalarType.toString();
int typePrecision =
Integer.parseInt(typeStr.substring(typeStr.indexOf("(") + 1, typeStr.indexOf(")")));
if (defaultValuePrecision > typePrecision) {
typeStr = typeStr.replace("V2", "");
throw new AnalysisException("default value precision: " + defaultValue
+ " can not be greater than type precision: " + typeStr);
}
}
break;
} else {
throw new AnalysisException("date literal [" + defaultValue + "] is invalid");

View File

@ -22,29 +22,52 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.io.Text;
import org.apache.doris.common.io.Writable;
import org.apache.doris.persist.gson.GsonPostProcessable;
import org.apache.doris.persist.gson.GsonUtils;
import com.google.common.collect.Lists;
import com.google.gson.annotations.SerializedName;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.List;
/**
* This def used for column which defaultValue is an expression.
*/
public class DefaultValueExprDef {
public class DefaultValueExprDef implements Writable, GsonPostProcessable {
private static final Logger LOG = LogManager.getLogger(DefaultValueExprDef.class);
@SerializedName("exprName")
private String exprName;
@SerializedName("precision")
private Long precision;
public DefaultValueExprDef(String exprName) {
this.exprName = exprName;
}
public DefaultValueExprDef(String exprName, Long precision) {
this.exprName = exprName;
this.precision = precision;
}
/**
* generate a FunctionCallExpr
* @return FunctionCallExpr of exprName
*/
public FunctionCallExpr getExpr(Type type) {
FunctionCallExpr expr = new FunctionCallExpr(exprName, new FunctionParams(null));
List<Expr> exprs = null;
if (precision != null) {
exprs = Lists.newArrayList();
exprs.add(new IntLiteral(precision));
}
FunctionCallExpr expr = new FunctionCallExpr(exprName, new FunctionParams(exprs));
try {
expr.analyzeImplForDefaultValue(type);
} catch (AnalysisException e) {
@ -56,4 +79,26 @@ public class DefaultValueExprDef {
public String getExprName() {
return exprName;
}
public Long getPrecision() {
return precision;
}
@Override
public void write(DataOutput out) throws IOException {
String json = GsonUtils.GSON.toJson(this);
Text.writeString(out, json);
}
public static DefaultValueExprDef read(DataInput in) throws IOException {
String json = Text.readString(in);
return GsonUtils.GSON.fromJson(json, DefaultValueExprDef.class);
}
@Override
public void gsonPostProcess() throws IOException {
if (precision == null) {
precision = 0L;
}
}
}

View File

@ -1230,8 +1230,14 @@ public class InternalCatalog implements CatalogIf<Database> {
boolean setDefault = StringUtils.isNotBlank(column.getDefaultValue());
DefaultValue defaultValue;
if (column.getDefaultValueExprDef() != null) {
defaultValue = new DefaultValue(setDefault, column.getDefaultValue(),
if (column.getDefaultValueExprDef().getPrecision() != null) {
defaultValue = new DefaultValue(setDefault, column.getDefaultValue(),
column.getDefaultValueExprDef().getExprName(),
column.getDefaultValueExprDef().getPrecision());
} else {
defaultValue = new DefaultValue(setDefault, column.getDefaultValue(),
column.getDefaultValueExprDef().getExprName());
}
} else {
defaultValue = new DefaultValue(setDefault, column.getDefaultValue());
}