Skip to content

Commit 35b081c

Browse files
committed
toClassWithRealEquals take nonnull input
1 parent b93b544 commit 35b081c

File tree

2 files changed

+35
-86
lines changed

2 files changed

+35
-86
lines changed

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/expressions/Comparisons.java

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import com.apple.foundationdb.record.query.plan.cascades.BooleanWithConstraint;
5858
import com.apple.foundationdb.record.query.plan.cascades.Correlated;
5959
import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier;
60+
import com.apple.foundationdb.record.query.plan.cascades.typing.Type;
6061
import com.apple.foundationdb.record.query.plan.explain.DefaultExplainFormatter;
6162
import com.apple.foundationdb.record.query.plan.explain.ExplainTokens;
6263
import com.apple.foundationdb.record.query.plan.explain.ExplainTokensWithPrecedence;
@@ -75,6 +76,7 @@
7576
import com.apple.foundationdb.record.util.ProtoUtils;
7677
import com.apple.foundationdb.tuple.ByteArrayUtil;
7778
import com.apple.foundationdb.tuple.ByteArrayUtil2;
79+
import com.apple.foundationdb.tuple.Tuple;
7880
import com.google.auto.service.AutoService;
7981
import com.google.common.base.Suppliers;
8082
import com.google.common.base.Verify;
@@ -213,11 +215,9 @@ private static Comparable toComparable(@Nullable Object obj) {
213215
}
214216
}
215217

216-
@Nullable
217-
public static Object toClassWithRealEquals(@Nullable Object obj) {
218-
if (obj == null) {
219-
return null;
220-
} else if (obj instanceof ByteString) {
218+
@Nonnull
219+
public static Object toClassWithRealEquals(@Nonnull Object obj) {
220+
if (obj instanceof ByteString) {
221221
return obj;
222222
} else if (obj instanceof byte[]) {
223223
return ByteString.copyFrom((byte[])obj);
@@ -247,7 +247,7 @@ private static boolean compareEquals(@Nonnull Object value, @Nonnull Object comp
247247
}
248248

249249
@SpotBugsSuppressWarnings("NP_BOOLEAN_RETURN_NULL")
250-
private static boolean compareNotDistinctFrom(Object value, Object comparand) {
250+
private static boolean compareNotDistinctFrom(@Nullable Object value, @Nullable Object comparand) {
251251
if (value == null && comparand == null) {
252252
return true;
253253
} else if (value == null || comparand == null) {
@@ -256,7 +256,7 @@ private static boolean compareNotDistinctFrom(Object value, Object comparand) {
256256
if (value instanceof Message) {
257257
return MessageHelpers.compareMessageEquals(value, comparand);
258258
} else {
259-
return toClassWithRealEquals(value).equals(toClassWithRealEquals(comparand));
259+
return toClassWithRealEquals(Objects.requireNonNull(value)).equals(toClassWithRealEquals(Objects.requireNonNull(comparand)));
260260
}
261261
}
262262
}
@@ -316,7 +316,12 @@ private static Boolean compareListStartsWith(@Nullable Object value, @Nonnull Li
316316
if (i > list.size()) {
317317
return false;
318318
}
319-
if (!toClassWithRealEquals(comparand.get(i)).equals(toClassWithRealEquals(list.get(i)))) {
319+
if (comparand.get(i) == null && list.get(i) == null) {
320+
continue;
321+
}
322+
if (comparand.get(i) == null || list.get(i) == null) {
323+
return false;
324+
} else if (!toClassWithRealEquals(comparand.get(i)).equals(toClassWithRealEquals(list.get(i)))) {
320325
return false;
321326
}
322327
}
@@ -341,11 +346,12 @@ private static Boolean compareIn(@Nullable Object value, @Nullable Object compar
341346
return true;
342347
}
343348
} else {
344-
if (toClassWithRealEquals(value).equals(toClassWithRealEquals(comparandItem))) {
349+
if (comparandItem == null) {
350+
hasNull = true;
351+
} else if (toClassWithRealEquals(value).equals(toClassWithRealEquals(comparandItem))) {
345352
return true;
346353
}
347354
}
348-
hasNull |= comparandItem == null;
349355
}
350356
return hasNull ? null : false;
351357
} else {
@@ -689,7 +695,7 @@ private static BiMap<Type, PComparisonType> getProtoEnumBiMap() {
689695
}
690696

691697
@Nullable
692-
public static Type invertComparisonType(@Nonnull final Comparisons.Type type) {
698+
public static Type invertComparisonType(@Nonnull final Type type) {
693699
if (type.isUnary()) {
694700
return null;
695701
}
@@ -846,7 +852,7 @@ default Object getComparand() {
846852

847853
/**
848854
* Get whether the comparison is with the result of a multi-column key.
849-
* If so, {@link #getComparand} will return a {@link com.apple.foundationdb.tuple.Tuple}.
855+
* If so, {@link #getComparand} will return a {@link Tuple}.
850856
* @return {@code true} if the comparand is for multiple key columns
851857
*/
852858
default boolean hasMultiColumnComparand() {
@@ -1780,7 +1786,7 @@ public static class ListComparison implements Comparison {
17801786
@SuppressWarnings("rawtypes")
17811787
private final List comparand;
17821788
@Nullable
1783-
private final Descriptors.FieldDescriptor.JavaType javaType;
1789+
private final JavaType javaType;
17841790

17851791
@Nonnull
17861792
@SuppressWarnings("rawtypes")
@@ -1798,8 +1804,8 @@ public ListComparison(@Nonnull Type type, @Nonnull List comparand) {
17981804
default:
17991805
throw new RecordCoreException("ListComparison only supports EQUALS, NOT_EQUALS, STARTS_WITH and IN");
18001806
}
1801-
if (comparand == null || (this.type == Type.IN && comparand.stream().anyMatch(o -> o == null))) {
1802-
throw new NullPointerException("List comparand is null, or contains null");
1807+
if (this.type == Type.IN && comparand.stream().anyMatch(o -> o == null)) {
1808+
throw new NullPointerException("List comparand contains null");
18031809
}
18041810
if (comparand.isEmpty()) {
18051811
javaType = null;
@@ -1813,10 +1819,10 @@ public ListComparison(@Nonnull Type type, @Nonnull List comparand) {
18131819
}
18141820
}
18151821
this.comparand = comparand;
1816-
this.comparandListWithEqualsSupplier = Suppliers.memoize(() -> Lists.transform(comparand, Comparisons::toClassWithRealEquals));
1822+
this.comparandListWithEqualsSupplier = Suppliers.memoize(() -> Lists.transform(comparand, obj -> obj != null ? toClassWithRealEquals(obj) : null));
18171823
}
18181824

1819-
private static Descriptors.FieldDescriptor.JavaType getJavaType(@Nonnull Object o) {
1825+
private static JavaType getJavaType(@Nonnull Object o) {
18201826
if (o instanceof Boolean) {
18211827
return JavaType.BOOLEAN;
18221828
} else if (o instanceof ByteString || o instanceof byte[]) {

yaml-tests/src/test/resources/aggregate-index-tests.yamsql

Lines changed: 12 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -156,20 +156,8 @@ test_block:
156156
# At some point, should be able to roll up values from the aggregate index. However, even
157157
# controlling for that, it can still use the index
158158
- query: select max(col2) from T1 use index (mv8);
159-
- supported_version: 4.1.9.0
160159
- explain: "ISCAN(MV8 <,>) | MAP (_ AS _0) | AGG (max_l(_._0.COL2) AS _0) | ON EMPTY NULL | MAP (_._0._0 AS _0)"
161160
- result: [{!l 13}]
162-
-
163-
- query: select max(col2) from T1 use index (mv8);
164-
- maxRows: 1
165-
# Cannot use FORCE_CONTINUATIONS with older versions due to: https://github.com/FoundationDB/fdb-record-layer/issues/3096
166-
# (Extra values being produced after exhausting source of an aggregate cursor)
167-
# Can remove once we do not care about backwards compatibility before 4.1.9.0
168-
- initialVersionLessThan: 4.1.9.0
169-
# Different (incorrect) behavior for different past versions
170-
- initialVersionAtLeast: 4.1.9.0
171-
- result: [{!l 13}]
172-
- result: []
173161
-
174162
# Min/max indexes need keep what amounts to a standard value index on their keys (in order to properly look up
175163
# the min/max). That index should be usable for normal queries just like a value index. Note that the scan is
@@ -183,43 +171,14 @@ test_block:
183171
- result: [{!l 5}, {!l 4}, {!l 3}, {!l 2}, {!l 1}]
184172
-
185173
- query: select min(col3) from T2 group by col1, col2;
186-
- supported_version: 4.1.9.0
187174
- explain: "ISCAN(MV2 <,>) | MAP (_ AS _0) | AGG (min_l(_._0.COL3) AS _0) GROUP BY (_._0.COL1 AS _0, _._0.COL2 AS _1) | MAP (_._1._0 AS _0)"
188175
- result: [{!l 1}, {!l 2}, {!l 3}]
189-
-
190-
- query: select min(col3) from T2 group by col1, col2;
191-
# Cannot use FORCE_CONTINUATIONS with older versions due to: https://github.com/FoundationDB/fdb-record-layer/issues/3096
192-
# (Extra values being produced after exhausting source of an aggregate cursor)
193-
# Can remove once we do not care about backwards compatibility before 4.1.9.0
194-
- maxRows: 1
195-
- initialVersionLessThan: 4.1.9.0
196-
# Different (incorrect) behavior for different past versions
197-
- initialVersionAtLeast: 4.1.9.0
198-
- result: [{!l 1}]
199-
- result: [{!l 2}]
200-
- result: [{!l 3}]
201-
- result: []
202176
-
203177
# this should use the aggregate index in the future, for now, it is using streaming aggregate
204178
# over base table scan.
205179
- query: select max(col2) from t2;
206-
- supported_version: 4.1.9.0
207180
- explain: "ISCAN(MV3 <,>) | MAP (_ AS _0) | AGG (max_l(_._0.COL2) AS _0) | ON EMPTY NULL | MAP (_._0._0 AS _0)"
208181
- result: [{!l 2}]
209-
-
210-
- query: select max(col2) from t2;
211-
# Cannot use FORCE_CONTINUATIONS with older versions due to: https://github.com/FoundationDB/fdb-record-layer/issues/3096
212-
# (Extra values being produced after exhausting source of an aggregate cursor)
213-
# Can remove once we do not care about backwards compatibility before 4.1.9.0
214-
- supported_version: 4.1.9.0
215-
- maxRows: 1
216-
- initialVersionLessThan: 4.1.9.0
217-
- result: [{!l 2}]
218-
- result: [{!null _}]
219-
- result: [{!l 2}] # ad infinitum
220-
- initialVersionAtLeast: 4.1.9.0
221-
- result: [{!l 2}]
222-
- result: []
223182
-
224183
- query: select col1, sum(col2) from T1 USE INDEX (vi1) group by col1;
225184
- explain: "ISCAN(VI1 <,>) | MAP (_ AS _0) | AGG (sum_l(_._0.COL2) AS _0) GROUP BY (_._0.COL1 AS _0) | MAP (_._0._0 AS COL1, _._1._0 AS _1)"
@@ -273,28 +232,12 @@ test_block:
273232
-
274233
# Permuted max index can also be used to evaluate other aggregate functions via aggregation and roll-up
275234
- query: select col3, sum(col2) as s from t2 use index (mv9) where col1 = 1 group by col1, col3 order by col3 asc;
276-
- supported_version: 4.1.9.0
277235
- explain: "ISCAN(MV9 [EQUALS promote(@c20 AS LONG)]) | MAP (_ AS _0) | AGG (sum_l(_._0.COL2) AS _0) GROUP BY (_._0.COL1 AS _0, _._0.COL3 AS _1) | MAP (_._0._1 AS COL3, _._1._0 AS S)"
278236
- result: [{COL3: 1, S: 1}, {COL3: 2, S: 2}, {COL3: 100, S: 1}, {COL3: 200, S: 2}]
279-
-
280-
- query: select col3, sum(col2) as s from t2 use index (mv9) where col1 = 1 group by col1, col3 order by col3 asc;
281-
# Cannot use FORCE_CONTINUATIONS with older versions due to: https://github.com/FoundationDB/fdb-record-layer/issues/3096
282-
# (Extra values being produced after exhausting source of an aggregate cursor)
283-
# Can remove once we do not care about backwards compatibility before 4.1.9.0
284-
- maxRows: 0
285-
- result: [{COL3: 1, S: 1}, {COL3: 2, S: 2}, {COL3: 100, S: 1}, {COL3: 200, S: 2}]
286237
-
287238
- query: select col3, sum(col2) as s from t2 use index (mv9) where col1 = 1 group by col1, col3 order by col3 desc;
288-
- supported_version: 4.1.9.0
289239
- explain: "ISCAN(MV9 [EQUALS promote(@c20 AS LONG)] REVERSE) | MAP (_ AS _0) | AGG (sum_l(_._0.COL2) AS _0) GROUP BY (_._0.COL1 AS _0, _._0.COL3 AS _1) | MAP (_._0._1 AS COL3, _._1._0 AS S)"
290240
- result: [{COL3: 200, S: 2}, {COL3: 100, S: 1}, {COL3: 2, S: 2}, {COL3: 1, S: 1}]
291-
-
292-
- query: select col3, sum(col2) as s from t2 use index (mv9) where col1 = 1 group by col1, col3 order by col3 desc;
293-
# Cannot use FORCE_CONTINUATIONS with older versions due to: https://github.com/FoundationDB/fdb-record-layer/issues/3096
294-
# (Extra values being produced after exhausting source of an aggregate cursor)
295-
# Can remove once we do not care about backwards compatibility before 4.1.9.0
296-
- maxRows: 0
297-
- result: [{COL3: 200, S: 2}, {COL3: 100, S: 1}, {COL3: 2, S: 2}, {COL3: 1, S: 1}]
298241
# -
299242
# # grouping by constant is not yet supported.
300243
# - query: select sum(col2) from t1 group by 3,2,1;
@@ -379,9 +322,9 @@ test_block:
379322
-
380323
- query: select b, c, d, e, max(x) from t5 where a = 0 group by a, b, c, d, e order by b, max(x), c, d, e
381324
- explain: "AISCAN(MV16 [EQUALS promote(@c19 AS LONG)] BY_GROUP -> [_0: KEY:[0], _1: KEY:[1], _2: KEY:[3], _3: KEY:[4], _4: KEY:[5], _5: KEY:[2]]) | MAP (_._1 AS B, _._2 AS C, _._3 AS D, _._4 AS E, _._5 AS _4)"
382-
- initialVersionLessThan: !current_version
325+
- initialVersionLessThan: 4.3.5.0
383326
- error: "0AF00"
384-
- initialVersionAtLeast: !current_version
327+
- initialVersionAtLeast: 4.3.5.0
385328
- result: [
386329
{b: "bar", c: 0, d: 1, e: "e1", _4: 11},
387330
{b: "bar", c: 0, d: 1, e: "e2", _4: 11},
@@ -408,9 +351,9 @@ test_block:
408351
-
409352
- query: select b, c, d, e, min(x) from t5 where a = 0 group by a, b, c, d, e order by b, min(x), c, d, e
410353
- explain: "AISCAN(MV17 [EQUALS promote(@c19 AS LONG)] BY_GROUP -> [_0: KEY:[0], _1: KEY:[1], _2: KEY:[3], _3: KEY:[4], _4: KEY:[5], _5: KEY:[2]]) | MAP (_._1 AS B, _._2 AS C, _._3 AS D, _._4 AS E, _._5 AS _4)"
411-
- initialVersionLessThan: !current_version
354+
- initialVersionLessThan: 4.3.5.0
412355
- error: "0AF00"
413-
- initialVersionAtLeast: !current_version
356+
- initialVersionAtLeast: 4.3.5.0
414357
- result: [
415358
{b: "bar", c: 0, d: 1, e: "e1", _4: 0},
416359
{b: "bar", c: 0, d: 1, e: "e2", _4: 0},
@@ -437,9 +380,9 @@ test_block:
437380
-
438381
- query: select b, c, d, e, max(x) from t5 where a = 0 group by a, b, c, d, e order by b, c, max(x), d, e
439382
- explain: "AISCAN(MV18 [EQUALS promote(@c19 AS LONG)] BY_GROUP -> [_0: KEY:[0], _1: KEY:[1], _2: KEY:[2], _3: KEY:[4], _4: KEY:[5], _5: KEY:[3]]) | MAP (_._1 AS B, _._2 AS C, _._3 AS D, _._4 AS E, _._5 AS _4)"
440-
- initialVersionLessThan: !current_version
383+
- initialVersionLessThan: 4.3.5.0
441384
- error: "0AF00"
442-
- initialVersionAtLeast: !current_version
385+
- initialVersionAtLeast: 4.3.5.0
443386
- result: [
444387
{b: "bar", c: 0, d: 1, e: "e1", _4: 11},
445388
{b: "bar", c: 0, d: 1, e: "e2", _4: 11},
@@ -466,9 +409,9 @@ test_block:
466409
-
467410
- query: select b, c, d, e, min(x) from t5 where a = 0 group by a, b, c, d, e order by b, c, min(x), d, e
468411
- explain: "AISCAN(MV19 [EQUALS promote(@c19 AS LONG)] BY_GROUP -> [_0: KEY:[0], _1: KEY:[1], _2: KEY:[2], _3: KEY:[4], _4: KEY:[5], _5: KEY:[3]]) | MAP (_._1 AS B, _._2 AS C, _._3 AS D, _._4 AS E, _._5 AS _4)"
469-
- initialVersionLessThan: !current_version
412+
- initialVersionLessThan: 4.3.5.0
470413
- error: "0AF00"
471-
- initialVersionAtLeast: !current_version
414+
- initialVersionAtLeast: 4.3.5.0
472415
- result: [
473416
{b: "bar", c: 0, d: 1, e: "e1", _4: 0},
474417
{b: "bar", c: 0, d: 1, e: "e2", _4: 0},
@@ -567,9 +510,9 @@ test_block:
567510
-
568511
- query: select b, c, d, e, max(x) from t5 where a = 0 group by a, b, c, d, e having b IN ('foo', 'bar') and d IN (1, 2) order by max(x), c, e
569512
- explain: "[IN @c34] INUNION q0 -> { [IN promote(@c42 AS ARRAY(LONG))] INUNION q1 -> { AISCAN(MV16 [EQUALS promote(@c19 AS LONG), EQUALS q0] BY_GROUP -> [_0: KEY:[0], _1: KEY:[1], _2: KEY:[3], _3: KEY:[4], _4: KEY:[5], _5: KEY:[2]]) | FILTER _._3 EQUALS q1 | MAP (_._1 AS B, _._2 AS C, _._3 AS D, _._4 AS E, _._5 AS _4) } COMPARE BY (_._4, _.C, _.E, _.D) } COMPARE BY (_._4, _.C, _.E, _.B)"
570-
- initialVersionLessThan: !current_version
513+
- initialVersionLessThan: 4.3.5.0
571514
- error: "0AF00"
572-
- initialVersionAtLeast: !current_version
515+
- initialVersionAtLeast: 4.3.5.0
573516
- result: [
574517
{b: "foo", c: 0, d: 2, e: "e2", _4: 8},
575518
{b: "foo", c: 3, d: 1, e: "e1", _4: 8},
@@ -583,9 +526,9 @@ test_block:
583526
-
584527
- query: select b, c, d, e, min(x) from t5 where a = 0 group by a, b, c, d, e having b IN ('foo', 'bar') and d IN (1, 2) order by min(x), c, e
585528
- explain: "[IN @c34] INUNION q0 -> { [IN promote(@c42 AS ARRAY(LONG))] INUNION q1 -> { AISCAN(MV17 [EQUALS promote(@c19 AS LONG), EQUALS q0] BY_GROUP -> [_0: KEY:[0], _1: KEY:[1], _2: KEY:[3], _3: KEY:[4], _4: KEY:[5], _5: KEY:[2]]) | FILTER _._3 EQUALS q1 | MAP (_._1 AS B, _._2 AS C, _._3 AS D, _._4 AS E, _._5 AS _4) } COMPARE BY (_._4, _.C, _.E, _.D) } COMPARE BY (_._4, _.C, _.E, _.B)"
586-
- initialVersionLessThan: !current_version
529+
- initialVersionLessThan: 4.3.5.0
587530
- error: "0AF00"
588-
- initialVersionAtLeast: !current_version
531+
- initialVersionAtLeast: 4.3.5.0
589532
- result: [
590533
{b: "bar", c: 0, d: 1, e: "e1", _4: 0},
591534
{b: "bar", c: 0, d: 1, e: "e2", _4: 0},

0 commit comments

Comments
 (0)