branch-2.1: [fix](Nereids) fix cast string to date #46065 (#46526)

pick: #46065

Related PR: #35637

Problem Summary:
When cast("201-01-01" as datetimev2(0)), The result is "2020-01-01" but
it is wrong. It should be result in "0201-01-01".
201 would be regarded as 20xy-0z as related pr show, it was a bug. But
actually it should not have this trasformation and result in
This commit is contained in:
LiBinfeng
2025-01-09 17:03:36 +08:00
committed by GitHub
parent eddea8b309
commit 4f41bad283
7 changed files with 38 additions and 87 deletions

View File

@ -456,7 +456,7 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule
return ((DateLikeType) dataType).fromString(((StringLikeLiteral) child).getStringValue());
} catch (AnalysisException t) {
if (cast.isExplicitType()) {
return new NullLiteral(dataType);
return cast;
} else {
// If cast is from type coercion, we don't use NULL literal and will throw exception.
throw t;

View File

@ -188,19 +188,23 @@ public class DateLiteral extends Literal {
if (len == 4 || len == 2) {
sb.append(s, i, j);
} else if (len == 3) {
if (partNumber == 0) {
String yy = s.substring(i, i + 2);
int year = Integer.parseInt(yy);
if (year >= 0 && year <= 69) {
sb.append("20");
} else if (year >= 70 && year <= 99) {
sb.append("19");
if (s.charAt(j) == '.') {
if (partNumber == 0) {
String yy = s.substring(i, i + 2);
int year = Integer.parseInt(yy);
if (year >= 0 && year <= 69) {
sb.append("20");
} else if (year >= 70 && year <= 99) {
sb.append("19");
}
sb.append(yy).append('-');
} else {
sb.append(s, i, i + 2).append(' ');
}
sb.append(yy).append('-');
j = j - 1;
} else {
sb.append(s, i, i + 2).append(' ');
sb.append("0").append(s, i, j);
}
j = j - 1;
} else if (len == 1) {
if (partNumber == 0) {
sb.append("000").append(c);

View File

@ -17,14 +17,10 @@
package org.apache.doris.nereids.rules.expression.rules;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.util.MemoPatternMatchSupported;
import org.apache.doris.nereids.util.PlanChecker;
import org.apache.doris.utframe.TestWithFeService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class SimplifyComparisonPredicateSqlTest extends TestWithFeService implements MemoPatternMatchSupported {
@ -96,74 +92,4 @@ class SimplifyComparisonPredicateSqlTest extends TestWithFeService implements Me
.when(f -> f.getConjuncts().stream().anyMatch(e -> e.toSql().equals("(b >= 111.12)")))
);
}
@Test
void dateLikeOverflow() {
PlanChecker.from(connectContext)
.analyze("select CAST('2021-01-32 00:00:00' AS DATETIME(6))")
.rewrite()
.matches(
logicalResultSink(
logicalOneRowRelation().when(p -> p.getProjects().get(0).child(0).equals(new NullLiteral(DateTimeV2Type.of(6))))
)
);
PlanChecker.from(connectContext)
.analyze("select CONVERT('2021-01-32 00:00:00', DATETIME(6))")
.rewrite()
.matches(
logicalResultSink(
logicalOneRowRelation().when(p -> p.getProjects().get(0).child(0).equals(new NullLiteral(DateTimeV2Type.of(6))))
)
);
PlanChecker.from(connectContext)
.analyze("select CONVERT_TZ('2021-01-32 00:00:00', '+08:00', 'America/London') = '2021-01-30'")
.rewrite()
.matches(
logicalResultSink(
logicalOneRowRelation().when(p -> p.getProjects().get(0).child(0) instanceof NullLiteral)
)
);
PlanChecker.from(connectContext)
.analyze("select CONVERT_TZ('2021-01-32 00:00:00', '+08:00', 'America/London')")
.rewrite()
.matches(
logicalResultSink(
logicalOneRowRelation().when(p -> p.getProjects().get(0).child(0) instanceof NullLiteral)
)
);
PlanChecker.from(connectContext)
.analyze("select CONVERT_TZ('2021-01-32 00:00:00.0000001', '+08:00', 'America/London')")
.rewrite()
.matches(
logicalResultSink(
logicalOneRowRelation().when(p -> p.getProjects().get(0).child(0) instanceof NullLiteral)
)
);
PlanChecker.from(connectContext)
.analyze("select CONVERT_TZ('2021-01-32 00:00:00.001', '+08:00', 'America/London') = '2021-01-30'")
.rewrite()
.matches(
logicalResultSink(
logicalOneRowRelation().when(p -> p.getProjects().get(0).child(0) instanceof NullLiteral)
)
);
Assertions.assertThrows(AnalysisException.class, () -> PlanChecker.from(connectContext)
.analyze("select CAST('2021-01-32 00:00:00' AS DATETIME(6)) = '2021-01-32 00:00:00'")
.rewrite()
);
Assertions.assertThrows(AnalysisException.class, () -> PlanChecker.from(connectContext)
.analyze("select CAST('2021-01-32 00:00:00' AS DATETIME(6)) = '2021-01-32 23:00:00'")
.rewrite()
);
Assertions.assertThrows(AnalysisException.class, () -> PlanChecker.from(connectContext)
.analyze("select CAST('2021-01-32 00:00:00' AS DATETIME(6)) = '1000'")
.rewrite()
);
}
}