[refactor](Nereids): unify one DateLiteral init() (#27618)
`fromDateStr` will parse `date string` into `dateLiteral`, but `init()` already handle it, so we can use `init()` replace it.
This commit is contained in:
@ -64,6 +64,7 @@ import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class DateLiteral extends LiteralExpr {
|
||||
private static final Logger LOG = LogManager.getLogger(DateLiteral.class);
|
||||
@ -107,9 +108,6 @@ public class DateLiteral extends LiteralExpr {
|
||||
private static Map<String, Integer> WEEK_DAY_NAME_DICT = Maps.newHashMap();
|
||||
private static Set<Character> TIME_PART_SET = Sets.newHashSet();
|
||||
private static final int[] DAYS_IN_MONTH = new int[] {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
private static final int ALLOW_SPACE_MASK = 4 | 64;
|
||||
private static final int MAX_DATE_PARTS = 8;
|
||||
private static final int YY_PART_YEAR = 70;
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -245,6 +243,12 @@ public class DateLiteral extends LiteralExpr {
|
||||
analysisDone();
|
||||
}
|
||||
|
||||
public DateLiteral(String s) throws AnalysisException {
|
||||
super();
|
||||
init(s, null);
|
||||
analysisDone();
|
||||
}
|
||||
|
||||
public DateLiteral(long unixTimestamp, TimeZone timeZone, Type type) throws AnalysisException {
|
||||
Timestamp timestamp = new Timestamp(unixTimestamp);
|
||||
|
||||
@ -368,9 +372,11 @@ public class DateLiteral extends LiteralExpr {
|
||||
return new DateLiteral(type, false);
|
||||
}
|
||||
|
||||
private void init(String s, Type type) throws AnalysisException {
|
||||
private void init(String s, @Nullable Type type) throws AnalysisException {
|
||||
try {
|
||||
Preconditions.checkArgument(type.isDateType());
|
||||
if (type != null) {
|
||||
Preconditions.checkArgument(type.isDateType());
|
||||
}
|
||||
TemporalAccessor dateTime = null;
|
||||
boolean parsed = false;
|
||||
int offset = 0;
|
||||
@ -442,10 +448,11 @@ public class DateLiteral extends LiteralExpr {
|
||||
builder.appendLiteral(" ");
|
||||
}
|
||||
String[] timePart = s.contains(" ") ? s.split(" ")[1].split(":") : new String[] {};
|
||||
if (timePart.length > 0 && (type.equals(Type.DATE) || type.equals(Type.DATEV2))) {
|
||||
if (timePart.length > 0 && type != null && (type.equals(Type.DATE) || type.equals(Type.DATEV2))) {
|
||||
throw new AnalysisException("Invalid date value: " + s);
|
||||
}
|
||||
if (timePart.length == 0 && (type.equals(Type.DATETIME) || type.equals(Type.DATETIMEV2))) {
|
||||
if (timePart.length == 0 && type != null && (type.equals(Type.DATETIME) || type.equals(
|
||||
Type.DATETIMEV2))) {
|
||||
throw new AnalysisException("Invalid datetime value: " + s);
|
||||
}
|
||||
for (int i = 0; i < timePart.length; i++) {
|
||||
@ -485,10 +492,30 @@ 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 (microsecond != 0 && type.isDatetime()) {
|
||||
int dotIndex = s.lastIndexOf(".");
|
||||
int scale = s.length() - dotIndex - 1;
|
||||
type = ScalarType.createDatetimeV2Type(scale);
|
||||
|
||||
if (type != null) {
|
||||
if (microsecond != 0 && type.isDatetime()) {
|
||||
int dotIndex = s.lastIndexOf(".");
|
||||
int scale = s.length() - dotIndex - 1;
|
||||
type = ScalarType.createDatetimeV2Type(scale);
|
||||
}
|
||||
} else {
|
||||
if (hour == 0 && minute == 0 && second == 0 && microsecond == 0) {
|
||||
type = ScalarType.getDefaultDateType(Type.DATE);
|
||||
} else {
|
||||
type = ScalarType.getDefaultDateType(Type.DATETIME);
|
||||
if (type.isDatetimeV2() && microsecond != 0) {
|
||||
int scale = 6;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (microsecond % Math.pow(10.0, i + 1) > 0) {
|
||||
break;
|
||||
} else {
|
||||
scale -= 1;
|
||||
}
|
||||
}
|
||||
type = ScalarType.createDatetimeV2Type(scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.type = type;
|
||||
|
||||
@ -1677,136 +1704,6 @@ public class DateLiteral extends LiteralExpr {
|
||||
throw new InvalidFormatException("'" + value + "' is invalid");
|
||||
}
|
||||
|
||||
// The interval format is that with no delimiters
|
||||
// YYYY-MM-DD HH-MM-DD.FFFFFF AM in default format, and now doris will skip part 7
|
||||
// 0 1 2 3 4 5 6 7
|
||||
public void fromDateStr(String dateStr) throws AnalysisException {
|
||||
dateStr = dateStr.trim();
|
||||
if (dateStr.isEmpty()) {
|
||||
throw new AnalysisException("parse datetime value failed: " + dateStr);
|
||||
}
|
||||
int[] dateVal = new int[MAX_DATE_PARTS];
|
||||
int[] dateLen = new int[MAX_DATE_PARTS];
|
||||
|
||||
// Fix year length
|
||||
int pre = 0;
|
||||
int pos = 0;
|
||||
while (pos < dateStr.length() && (Character.isDigit(dateStr.charAt(pos)) || dateStr.charAt(pos) == 'T')) {
|
||||
pos++;
|
||||
}
|
||||
int yearLen = 4;
|
||||
int digits = pos - pre;
|
||||
boolean isIntervalFormat = false;
|
||||
// For YYYYMMDD/YYYYMMDDHHMMSS is 4 digits years
|
||||
if (pos == dateStr.length() || dateStr.charAt(pos) == '.') {
|
||||
if (digits == 4 || digits == 8 || digits >= 14) {
|
||||
yearLen = 4;
|
||||
} else {
|
||||
yearLen = 2;
|
||||
}
|
||||
isIntervalFormat = true;
|
||||
}
|
||||
|
||||
int fieldIdx = 0;
|
||||
int fieldLen = yearLen;
|
||||
while (pre < dateStr.length() && Character.isDigit(dateStr.charAt(pre)) && fieldIdx < MAX_DATE_PARTS - 1) {
|
||||
int start = pre;
|
||||
int tempVal = 0;
|
||||
boolean scanToDelim = (!isIntervalFormat) && (fieldIdx != 6);
|
||||
while (pre < dateStr.length() && Character.isDigit(dateStr.charAt(pre))
|
||||
&& (scanToDelim || fieldLen-- != 0)) {
|
||||
tempVal = tempVal * 10 + (dateStr.charAt(pre++) - '0');
|
||||
}
|
||||
dateVal[fieldIdx] = tempVal;
|
||||
dateLen[fieldIdx] = pre - start;
|
||||
fieldLen = 2;
|
||||
|
||||
if (pre == dateStr.length()) {
|
||||
fieldIdx++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (fieldIdx == 2 && dateStr.charAt(pre) == 'T') {
|
||||
// YYYYMMDDTHHMMDD, skip 'T' and continue
|
||||
pre++;
|
||||
fieldIdx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Second part
|
||||
if (fieldIdx == 5) {
|
||||
if (dateStr.charAt(pre) == '.') {
|
||||
pre++;
|
||||
fieldLen = 6;
|
||||
} else if (Character.isDigit(dateStr.charAt(pre))) {
|
||||
fieldIdx++;
|
||||
break;
|
||||
}
|
||||
fieldIdx++;
|
||||
continue;
|
||||
}
|
||||
// escape separator
|
||||
while (pre < dateStr.length() && ((Character.toString(dateStr.charAt(pre)).matches("\\p{Punct}"))
|
||||
|| Character.isSpaceChar(dateStr.charAt(pre)))) {
|
||||
if (Character.isSpaceChar(dateStr.charAt(pre))) {
|
||||
if (((1 << fieldIdx) & ALLOW_SPACE_MASK) == 0) {
|
||||
throw new AnalysisException("parse datetime value failed: " + dateStr);
|
||||
}
|
||||
}
|
||||
pre++;
|
||||
}
|
||||
fieldIdx++;
|
||||
}
|
||||
int numField = fieldIdx;
|
||||
if (!isIntervalFormat) {
|
||||
yearLen = dateLen[0];
|
||||
}
|
||||
for (; fieldIdx < MAX_DATE_PARTS; ++fieldIdx) {
|
||||
dateLen[fieldIdx] = 0;
|
||||
dateVal[fieldIdx] = 0;
|
||||
}
|
||||
if (yearLen == 2) {
|
||||
if (dateVal[0] < YY_PART_YEAR) {
|
||||
dateVal[0] += 2000;
|
||||
} else {
|
||||
dateVal[0] += 1900;
|
||||
}
|
||||
}
|
||||
|
||||
if (numField < 3) {
|
||||
throw new AnalysisException("parse datetime value failed: " + dateStr);
|
||||
}
|
||||
|
||||
year = dateVal[0];
|
||||
month = dateVal[1];
|
||||
day = dateVal[2];
|
||||
hour = dateVal[3];
|
||||
minute = dateVal[4];
|
||||
second = dateVal[5];
|
||||
microsecond = dateVal[6];
|
||||
|
||||
if (numField == 3) {
|
||||
type = ScalarType.getDefaultDateType(Type.DATE);
|
||||
} else {
|
||||
type = ScalarType.getDefaultDateType(Type.DATETIME);
|
||||
if (type.isDatetimeV2() && microsecond != 0) {
|
||||
int scale = 6;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (microsecond % Math.pow(10.0, i + 1) > 0) {
|
||||
break;
|
||||
} else {
|
||||
scale -= 1;
|
||||
}
|
||||
}
|
||||
type = ScalarType.createDatetimeV2Type(scale);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkRange() || checkDate()) {
|
||||
throw new AnalysisException("Datetime value is out of range: " + dateStr);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMinValue() {
|
||||
year = 0;
|
||||
month = 1;
|
||||
|
||||
@ -62,8 +62,7 @@ public class RewriteDateLiteralRule implements ExprRewriteRule {
|
||||
if (childExpr instanceof LiteralExpr) {
|
||||
try {
|
||||
String dateStr = childExpr.getStringValue();
|
||||
DateLiteral dateLiteral = new DateLiteral();
|
||||
dateLiteral.fromDateStr(dateStr);
|
||||
DateLiteral dateLiteral = new DateLiteral(dateStr);
|
||||
expr.setChild(1, dateLiteral);
|
||||
} catch (AnalysisException e) {
|
||||
if (ConnectContext.get() != null) {
|
||||
|
||||
Reference in New Issue
Block a user