Skip to content

Commit 65717f6

Browse files
committed
SQL: Fix Nullability of DATEADD (#47921)
Previously, Nullability was set to UNKNOWN instead of TRUE which resulted on QueryFolder not correctly folding to NULL if any of the args was null. Remove the overriding nullable() also for DatePart/DateTrunc to allow delegation the parent class. (cherry picked from commit 05a7108)
1 parent ac209c1 commit 65717f6

File tree

6 files changed

+45
-47
lines changed

6 files changed

+45
-47
lines changed

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BinaryDateTimeFunction.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
99
import org.elasticsearch.xpack.sql.expression.Expressions;
10-
import org.elasticsearch.xpack.sql.expression.Nullability;
1110
import org.elasticsearch.xpack.sql.expression.function.scalar.BinaryScalarFunction;
1211
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
1312
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
@@ -79,11 +78,6 @@ protected Pipe makePipe() {
7978

8079
protected abstract Pipe createPipe(Pipe left, Pipe right, ZoneId zoneId);
8180

82-
@Override
83-
public Nullability nullable() {
84-
return Nullability.TRUE;
85-
}
86-
8781
@Override
8882
protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) {
8983
return new ScriptTemplate(

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateAdd.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
99
import org.elasticsearch.xpack.sql.expression.Expressions;
10-
import org.elasticsearch.xpack.sql.expression.Nullability;
1110
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
1211
import org.elasticsearch.xpack.sql.tree.NodeInfo;
1312
import org.elasticsearch.xpack.sql.tree.Source;
@@ -136,11 +135,6 @@ protected NodeInfo<? extends Expression> info() {
136135
return NodeInfo.create(this, DateAdd::new, first(), second(), third(), zoneId());
137136
}
138137

139-
@Override
140-
public Nullability nullable() {
141-
return Nullability.UNKNOWN;
142-
}
143-
144138
@Override
145139
protected Pipe createPipe(Pipe first, Pipe second, Pipe third, ZoneId zoneId) {
146140
return new DateAddPipe(source(), this, first, second, third, zoneId);

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DatePart.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9-
import org.elasticsearch.xpack.sql.expression.Nullability;
109
import org.elasticsearch.xpack.sql.expression.function.scalar.BinaryScalarFunction;
1110
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeProcessor.DateTimeExtractor;
1211
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
@@ -97,11 +96,6 @@ protected NodeInfo<? extends Expression> info() {
9796
return NodeInfo.create(this, DatePart::new, left(), right(), zoneId());
9897
}
9998

100-
@Override
101-
public Nullability nullable() {
102-
return Nullability.TRUE;
103-
}
104-
10599
@Override
106100
protected String scriptMethodName() {
107101
return "datePart";

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTrunc.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9-
import org.elasticsearch.xpack.sql.expression.Nullability;
109
import org.elasticsearch.xpack.sql.expression.function.scalar.BinaryScalarFunction;
1110
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
1211
import org.elasticsearch.xpack.sql.tree.NodeInfo;
@@ -153,11 +152,6 @@ protected NodeInfo<? extends Expression> info() {
153152
return NodeInfo.create(this, DateTrunc::new, left(), right(), zoneId());
154153
}
155154

156-
@Override
157-
public Nullability nullable() {
158-
return Nullability.TRUE;
159-
}
160-
161155
@Override
162156
protected String scriptMethodName() {
163157
return "dateTrunc";

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/ThreeArgsDateTimeFunction.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
99
import org.elasticsearch.xpack.sql.expression.Expressions;
10-
import org.elasticsearch.xpack.sql.expression.Nullability;
1110
import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunction;
1211
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
1312
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
@@ -69,11 +68,6 @@ protected Pipe makePipe() {
6968

7069
protected abstract Pipe createPipe(Pipe first, Pipe second, Pipe third, ZoneId zoneId);
7170

72-
@Override
73-
public Nullability nullable() {
74-
return Nullability.TRUE;
75-
}
76-
7771
@Override
7872
public boolean foldable() {
7973
return first().foldable() && second().foldable() && third().foldable();

x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
import org.elasticsearch.xpack.sql.expression.function.aggregate.SumOfSquares;
3636
import org.elasticsearch.xpack.sql.expression.function.aggregate.VarPop;
3737
import org.elasticsearch.xpack.sql.expression.function.scalar.Cast;
38+
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateAdd;
39+
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DatePart;
40+
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTrunc;
3841
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DayName;
3942
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DayOfMonth;
4043
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DayOfYear;
@@ -614,14 +617,39 @@ public void testSimplifyLeastRandomNullsWithValue() {
614617
assertEquals(TWO, e.children().get(1));
615618
assertEquals(DataType.INTEGER, e.dataType());
616619
}
617-
620+
618621
public void testConcatFoldingIsNotNull() {
619622
FoldNull foldNull = new FoldNull();
620623
assertEquals(1, foldNull.rule(new Concat(EMPTY, NULL, ONE)).fold());
621624
assertEquals(1, foldNull.rule(new Concat(EMPTY, ONE, NULL)).fold());
622625
assertEquals(StringUtils.EMPTY, foldNull.rule(new Concat(EMPTY, NULL, NULL)).fold());
623626
}
624627

628+
public void testFoldNullDateAdd() {
629+
FoldNull foldNull = new FoldNull();
630+
assertNullLiteral(foldNull.rule(new DateAdd(EMPTY, NULL, TWO, THREE, UTC)));
631+
assertNullLiteral(foldNull.rule(new DateAdd(EMPTY, ONE, NULL, THREE, UTC)));
632+
assertNullLiteral(foldNull.rule(new DateAdd(EMPTY, ONE, TWO, NULL, UTC)));
633+
assertNullLiteral(foldNull.rule(new DateAdd(EMPTY, NULL, NULL, NULL, UTC)));
634+
assertTrue(foldNull.rule(new DateAdd(EMPTY, ONE, TWO, THREE, UTC)) instanceof DateAdd);
635+
}
636+
637+
public void testFoldNullDatePart() {
638+
FoldNull foldNull = new FoldNull();
639+
assertNullLiteral(foldNull.rule(new DatePart(EMPTY, NULL, TWO, UTC)));
640+
assertNullLiteral(foldNull.rule(new DatePart(EMPTY, ONE, NULL, UTC)));
641+
assertNullLiteral(foldNull.rule(new DatePart(EMPTY, NULL, NULL, UTC)));
642+
assertTrue(foldNull.rule(new DatePart(EMPTY, ONE, TWO, UTC)) instanceof DatePart);
643+
}
644+
645+
public void testFoldNullDateTrunc() {
646+
FoldNull foldNull = new FoldNull();
647+
assertNullLiteral(foldNull.rule(new DateTrunc(EMPTY, NULL, TWO, UTC)));
648+
assertNullLiteral(foldNull.rule(new DateTrunc(EMPTY, ONE, NULL, UTC)));
649+
assertNullLiteral(foldNull.rule(new DateTrunc(EMPTY, NULL, NULL, UTC)));
650+
assertTrue(foldNull.rule(new DateTrunc(EMPTY, ONE, TWO, UTC)) instanceof DateTrunc);
651+
}
652+
625653
public void testSimplifyCaseConditionsFoldWhenFalse() {
626654
// CASE WHEN a = 1 THEN 'foo1'
627655
// WHEN 1 = 2 THEN 'bar1'
@@ -1453,7 +1481,7 @@ public void testTranslateMaxToLast() {
14531481
assertSame(last, aggregates.get(0));
14541482
assertEquals(max2, aggregates.get(1));
14551483
}
1456-
1484+
14571485
public void testSortAggregateOnOrderByWithTwoFields() {
14581486
FieldAttribute firstField = new FieldAttribute(EMPTY, "first_field", new EsField("first_field", DataType.BYTE, emptyMap(), true));
14591487
FieldAttribute secondField = new FieldAttribute(EMPTY, "second_field",
@@ -1462,20 +1490,20 @@ public void testSortAggregateOnOrderByWithTwoFields() {
14621490
Alias secondAlias = new Alias(EMPTY, "second_alias", secondField);
14631491
Order firstOrderBy = new Order(EMPTY, firstField, OrderDirection.ASC, Order.NullsPosition.LAST);
14641492
Order secondOrderBy = new Order(EMPTY, secondField, OrderDirection.ASC, Order.NullsPosition.LAST);
1465-
1493+
14661494
OrderBy orderByPlan = new OrderBy(EMPTY,
14671495
new Aggregate(EMPTY, FROM(), Arrays.asList(secondField, firstField), Arrays.asList(secondAlias, firstAlias)),
14681496
Arrays.asList(firstOrderBy, secondOrderBy));
14691497
LogicalPlan result = new SortAggregateOnOrderBy().apply(orderByPlan);
1470-
1498+
14711499
assertTrue(result instanceof OrderBy);
14721500
List<Order> order = ((OrderBy) result).order();
14731501
assertEquals(2, order.size());
14741502
assertTrue(order.get(0).child() instanceof FieldAttribute);
14751503
assertTrue(order.get(1).child() instanceof FieldAttribute);
14761504
assertEquals("first_field", ((FieldAttribute) order.get(0).child()).name());
14771505
assertEquals("second_field", ((FieldAttribute) order.get(1).child()).name());
1478-
1506+
14791507
assertTrue(((OrderBy) result).child() instanceof Aggregate);
14801508
Aggregate agg = (Aggregate) ((OrderBy) result).child();
14811509
List<?> groupings = agg.groupings();
@@ -1485,7 +1513,7 @@ public void testSortAggregateOnOrderByWithTwoFields() {
14851513
assertEquals(firstField, groupings.get(0));
14861514
assertEquals(secondField, groupings.get(1));
14871515
}
1488-
1516+
14891517
public void testSortAggregateOnOrderByOnlyAliases() {
14901518
FieldAttribute firstField = new FieldAttribute(EMPTY, "first_field", new EsField("first_field", DataType.BYTE, emptyMap(), true));
14911519
FieldAttribute secondField = new FieldAttribute(EMPTY, "second_field",
@@ -1494,20 +1522,20 @@ public void testSortAggregateOnOrderByOnlyAliases() {
14941522
Alias secondAlias = new Alias(EMPTY, "second_alias", secondField);
14951523
Order firstOrderBy = new Order(EMPTY, firstAlias, OrderDirection.ASC, Order.NullsPosition.LAST);
14961524
Order secondOrderBy = new Order(EMPTY, secondAlias, OrderDirection.ASC, Order.NullsPosition.LAST);
1497-
1525+
14981526
OrderBy orderByPlan = new OrderBy(EMPTY,
14991527
new Aggregate(EMPTY, FROM(), Arrays.asList(secondAlias, firstAlias), Arrays.asList(secondAlias, firstAlias)),
15001528
Arrays.asList(firstOrderBy, secondOrderBy));
15011529
LogicalPlan result = new SortAggregateOnOrderBy().apply(orderByPlan);
1502-
1530+
15031531
assertTrue(result instanceof OrderBy);
15041532
List<Order> order = ((OrderBy) result).order();
15051533
assertEquals(2, order.size());
15061534
assertTrue(order.get(0).child() instanceof Alias);
15071535
assertTrue(order.get(1).child() instanceof Alias);
15081536
assertEquals("first_alias", ((Alias) order.get(0).child()).name());
15091537
assertEquals("second_alias", ((Alias) order.get(1).child()).name());
1510-
1538+
15111539
assertTrue(((OrderBy) result).child() instanceof Aggregate);
15121540
Aggregate agg = (Aggregate) ((OrderBy) result).child();
15131541
List<?> groupings = agg.groupings();
@@ -1536,28 +1564,28 @@ public void testPivotRewrite() {
15361564
assertEquals(column, in.value());
15371565
assertEquals(Arrays.asList(L(1), L(2)), in.list());
15381566
}
1539-
1567+
15401568
/**
15411569
* Test queries like SELECT MIN(agg_field), MAX(agg_field) FROM table WHERE MATCH(match_field,'A') AND/OR QUERY('match_field:A')
15421570
* or SELECT STDDEV_POP(agg_field), VAR_POP(agg_field) FROM table WHERE MATCH(match_field,'A') AND/OR QUERY('match_field:A')
15431571
*/
15441572
public void testAggregatesPromoteToStats_WithFullTextPredicatesConditions() {
15451573
FieldAttribute matchField = new FieldAttribute(EMPTY, "match_field", new EsField("match_field", DataType.TEXT, emptyMap(), true));
15461574
FieldAttribute aggField = new FieldAttribute(EMPTY, "agg_field", new EsField("agg_field", DataType.INTEGER, emptyMap(), true));
1547-
1575+
15481576
FullTextPredicate matchPredicate = new MatchQueryPredicate(EMPTY, matchField, "A", StringUtils.EMPTY);
15491577
FullTextPredicate multiMatchPredicate = new MultiMatchQueryPredicate(EMPTY, "match_field", "A", StringUtils.EMPTY);
15501578
FullTextPredicate stringQueryPredicate = new StringQueryPredicate(EMPTY, "match_field:A", StringUtils.EMPTY);
15511579
List<FullTextPredicate> predicates = Arrays.asList(matchPredicate, multiMatchPredicate, stringQueryPredicate);
15521580

15531581
FullTextPredicate left = randomFrom(predicates);
15541582
FullTextPredicate right = randomFrom(predicates);
1555-
1583+
15561584
BinaryLogic or = new Or(EMPTY, left, right);
15571585
BinaryLogic and = new And(EMPTY, left, right);
15581586
BinaryLogic condition = randomFrom(or, and);
15591587
Filter filter = new Filter(EMPTY, FROM(), condition);
1560-
1588+
15611589
List<AggregateFunction> aggregates;
15621590
boolean isSimpleStats = randomBoolean();
15631591
if (isSimpleStats) {
@@ -1576,13 +1604,13 @@ public void testAggregatesPromoteToStats_WithFullTextPredicatesConditions() {
15761604
} else {
15771605
result = new ReplaceAggsWithExtendedStats().apply(aggregatePlan);
15781606
}
1579-
1607+
15801608
assertTrue(result instanceof Aggregate);
15811609
Aggregate resultAgg = (Aggregate) result;
15821610
assertEquals(2, resultAgg.aggregates().size());
15831611
assertTrue(resultAgg.aggregates().get(0) instanceof InnerAggregate);
15841612
assertTrue(resultAgg.aggregates().get(1) instanceof InnerAggregate);
1585-
1613+
15861614
InnerAggregate resultFirstAgg = (InnerAggregate) resultAgg.aggregates().get(0);
15871615
InnerAggregate resultSecondAgg = (InnerAggregate) resultAgg.aggregates().get(1);
15881616
assertEquals(resultFirstAgg.inner(), firstAggregate);
@@ -1598,8 +1626,8 @@ public void testAggregatesPromoteToStats_WithFullTextPredicatesConditions() {
15981626
assertEquals(((ExtendedStats) resultFirstAgg.outer()).field(), aggField);
15991627
assertEquals(((ExtendedStats) resultSecondAgg.outer()).field(), aggField);
16001628
}
1601-
1629+
16021630
assertTrue(resultAgg.child() instanceof Filter);
16031631
assertEquals(resultAgg.child(), filter);
16041632
}
1605-
}
1633+
}

0 commit comments

Comments
 (0)