73
73
import com .apple .foundationdb .record .util .ProtoUtils ;
74
74
import com .apple .foundationdb .tuple .ByteArrayUtil ;
75
75
import com .apple .foundationdb .tuple .ByteArrayUtil2 ;
76
+ import com .apple .foundationdb .tuple .Tuple ;
76
77
import com .google .auto .service .AutoService ;
77
78
import com .google .common .base .Suppliers ;
78
79
import com .google .common .base .Verify ;
@@ -211,11 +212,9 @@ private static Comparable toComparable(@Nullable Object obj) {
211
212
}
212
213
}
213
214
214
- @ Nullable
215
- public static Object toClassWithRealEquals (@ Nullable Object obj ) {
216
- if (obj == null ) {
217
- return null ;
218
- } else if (obj instanceof ByteString ) {
215
+ @ Nonnull
216
+ public static Object toClassWithRealEquals (@ Nonnull Object obj ) {
217
+ if (obj instanceof ByteString ) {
219
218
return obj ;
220
219
} else if (obj instanceof byte []) {
221
220
return ByteString .copyFrom ((byte [])obj );
@@ -231,30 +230,30 @@ public static Object toClassWithRealEquals(@Nullable Object obj) {
231
230
}
232
231
233
232
@ SuppressWarnings ("unchecked" )
234
- public static int compare (@ Nullable Object fieldValue , @ Nullable Object comparand ) {
235
- if (fieldValue == null ) {
236
- if (comparand == null ) {
237
- return 0 ;
238
- } else {
239
- return -1 ;
240
- }
241
- } else if (comparand == null ) {
242
- return 1 ;
233
+ public static int compare (@ Nonnull Object fieldValue , @ Nonnull Object comparand ) {
234
+ return toComparable (fieldValue ).compareTo (toComparable (comparand ));
235
+ }
236
+
237
+ @ SpotBugsSuppressWarnings ("NP_BOOLEAN_RETURN_NULL" )
238
+ private static boolean compareEquals (@ Nonnull Object value , @ Nonnull Object comparand ) {
239
+ if (value instanceof Message ) {
240
+ return MessageHelpers .compareMessageEquals (value , comparand );
243
241
} else {
244
- return toComparable ( fieldValue ). compareTo ( toComparable (comparand ));
242
+ return toClassWithRealEquals ( value ). equals ( toClassWithRealEquals (comparand ));
245
243
}
246
244
}
247
245
248
- @ Nullable
249
246
@ SpotBugsSuppressWarnings ("NP_BOOLEAN_RETURN_NULL" )
250
- private static Boolean compareEquals (Object value , Object comparand ) {
251
- if (value == null || comparand == null ) {
252
- return null ;
247
+ private static boolean compareNotDistinctFrom (@ Nullable Object value , @ Nullable Object comparand ) {
248
+ if (value == null && comparand == null ) {
249
+ return true ;
250
+ } else if (value == null || comparand == null ) {
251
+ return false ;
253
252
} else {
254
253
if (value instanceof Message ) {
255
254
return MessageHelpers .compareMessageEquals (value , comparand );
256
255
} else {
257
- return toClassWithRealEquals (value ).equals (toClassWithRealEquals (comparand ));
256
+ return toClassWithRealEquals (Objects . requireNonNull ( value )) .equals (toClassWithRealEquals (Objects . requireNonNull ( comparand ) ));
258
257
}
259
258
}
260
259
}
@@ -283,6 +282,9 @@ private static Boolean compareStartsWith(@Nullable Object value, @Nullable Objec
283
282
@ Nullable
284
283
@ SpotBugsSuppressWarnings ("NP_BOOLEAN_RETURN_NULL" )
285
284
private static Boolean compareLike (@ Nullable Object value , @ Nullable Object pattern ) {
285
+ if (value == null ) {
286
+ return null ;
287
+ }
286
288
if (!(value instanceof String )) {
287
289
throw new RecordCoreException ("Illegal comparand value type: " + value );
288
290
}
@@ -311,7 +313,12 @@ private static Boolean compareListStartsWith(@Nullable Object value, @Nonnull Li
311
313
if (i > list .size ()) {
312
314
return false ;
313
315
}
314
- if (!toClassWithRealEquals (comparand .get (i )).equals (toClassWithRealEquals (list .get (i )))) {
316
+ if (comparand .get (i ) == null && list .get (i ) == null ) {
317
+ continue ;
318
+ }
319
+ if (comparand .get (i ) == null || list .get (i ) == null ) {
320
+ return false ;
321
+ } else if (!toClassWithRealEquals (comparand .get (i )).equals (toClassWithRealEquals (list .get (i )))) {
315
322
return false ;
316
323
}
317
324
}
@@ -336,11 +343,12 @@ private static Boolean compareIn(@Nullable Object value, @Nullable Object compar
336
343
return true ;
337
344
}
338
345
} else {
339
- if (toClassWithRealEquals (value ).equals (toClassWithRealEquals (comparandItem ))) {
346
+ if (comparandItem == null ) {
347
+ hasNull = true ;
348
+ } else if (toClassWithRealEquals (value ).equals (toClassWithRealEquals (comparandItem ))) {
340
349
return true ;
341
350
}
342
351
}
343
- hasNull |= comparandItem == null ;
344
352
}
345
353
return hasNull ? null : false ;
346
354
} else {
@@ -632,7 +640,9 @@ public enum Type {
632
640
@ API (API .Status .EXPERIMENTAL )
633
641
SORT (false ),
634
642
@ API (API .Status .EXPERIMENTAL )
635
- LIKE ;
643
+ LIKE ,
644
+ IS_DISTINCT_FROM (false ),
645
+ NOT_DISTINCT_FROM (true );
636
646
637
647
@ Nonnull
638
648
private static final Supplier <BiMap <Type , PComparisonType >> protoEnumBiMapSupplier =
@@ -682,7 +692,7 @@ private static BiMap<Type, PComparisonType> getProtoEnumBiMap() {
682
692
}
683
693
684
694
@ Nullable
685
- public static Type invertComparisonType (@ Nonnull final Comparisons . Type type ) {
695
+ public static Type invertComparisonType (@ Nonnull final Type type ) {
686
696
if (type .isUnary ()) {
687
697
return null ;
688
698
}
@@ -705,28 +715,44 @@ public static Type invertComparisonType(@Nonnull final Comparisons.Type type) {
705
715
@ Nullable
706
716
@ SpotBugsSuppressWarnings ("NP_BOOLEAN_RETURN_NULL" )
707
717
public static Boolean evalComparison (@ Nonnull Type type , @ Nullable Object value , @ Nullable Object comparand ) {
708
- if (value == null ) {
709
- return null ;
710
- }
711
718
switch (type ) {
712
719
case STARTS_WITH :
713
720
return compareStartsWith (value , comparand );
714
721
case IN :
715
722
return compareIn (value , comparand );
716
723
case EQUALS :
724
+ if (value == null || comparand == null ) {
725
+ return null ;
726
+ }
717
727
return compareEquals (value , comparand );
718
728
case NOT_EQUALS :
719
- if (comparand == null ) {
729
+ if (value == null || comparand == null ) {
720
730
return null ;
721
731
}
722
732
return !compareEquals (value , comparand );
733
+ case IS_DISTINCT_FROM :
734
+ return !compareNotDistinctFrom (value , comparand );
735
+ case NOT_DISTINCT_FROM :
736
+ return compareNotDistinctFrom (value , comparand );
723
737
case LESS_THAN :
738
+ if (value == null || comparand == null ) {
739
+ return null ;
740
+ }
724
741
return compare (value , comparand ) < 0 ;
725
742
case LESS_THAN_OR_EQUALS :
743
+ if (value == null || comparand == null ) {
744
+ return null ;
745
+ }
726
746
return compare (value , comparand ) <= 0 ;
727
747
case GREATER_THAN :
748
+ if (value == null || comparand == null ) {
749
+ return null ;
750
+ }
728
751
return compare (value , comparand ) > 0 ;
729
752
case GREATER_THAN_OR_EQUALS :
753
+ if (value == null || comparand == null ) {
754
+ return null ;
755
+ }
730
756
return compare (value , comparand ) >= 0 ;
731
757
case LIKE :
732
758
return compareLike (value , comparand );
@@ -823,7 +849,7 @@ default Object getComparand() {
823
849
824
850
/**
825
851
* Get whether the comparison is with the result of a multi-column key.
826
- * If so, {@link #getComparand} will return a {@link com.apple.foundationdb.tuple. Tuple}.
852
+ * If so, {@link #getComparand} will return a {@link Tuple}.
827
853
* @return {@code true} if the comparand is for multiple key columns
828
854
*/
829
855
default boolean hasMultiColumnComparand () {
@@ -1302,9 +1328,7 @@ public ConstrainedBoolean semanticEqualsTyped(@Nonnull final Comparison other, @
1302
1328
public Boolean eval (@ Nullable FDBRecordStoreBase <?> store , @ Nonnull EvaluationContext context , @ Nullable Object value ) {
1303
1329
// this is at evaluation time --> always use the context binding
1304
1330
final Object comparand = getComparand (store , context );
1305
- if (comparand == null ) {
1306
- return null ;
1307
- } else if (comparand == COMPARISON_SKIPPED_BINDING ) {
1331
+ if (comparand == COMPARISON_SKIPPED_BINDING ) {
1308
1332
return Boolean .TRUE ;
1309
1333
} else {
1310
1334
return evalComparison (type , value , comparand );
@@ -1620,9 +1644,7 @@ public ConstrainedBoolean semanticEqualsTyped(@Nonnull final Comparison other, @
1620
1644
public Boolean eval (@ Nullable FDBRecordStoreBase <?> store , @ Nonnull EvaluationContext context , @ Nullable Object v ) {
1621
1645
// this is at evaluation time --> always use the context binding
1622
1646
final Object comparand = getComparand (store , context );
1623
- if (comparand == null ) {
1624
- return null ;
1625
- } else if (comparand == COMPARISON_SKIPPED_BINDING ) {
1647
+ if (comparand == COMPARISON_SKIPPED_BINDING ) {
1626
1648
return Boolean .TRUE ;
1627
1649
} else {
1628
1650
return evalComparison (type , v , comparand );
@@ -1739,7 +1761,7 @@ public static class ListComparison implements Comparison {
1739
1761
@ SuppressWarnings ("rawtypes" )
1740
1762
private final List comparand ;
1741
1763
@ Nullable
1742
- private final Descriptors . FieldDescriptor . JavaType javaType ;
1764
+ private final JavaType javaType ;
1743
1765
1744
1766
@ Nonnull
1745
1767
@ SuppressWarnings ("rawtypes" )
@@ -1757,8 +1779,8 @@ public ListComparison(@Nonnull Type type, @Nonnull List comparand) {
1757
1779
default :
1758
1780
throw new RecordCoreException ("ListComparison only supports EQUALS, NOT_EQUALS, STARTS_WITH and IN" );
1759
1781
}
1760
- if (comparand == null || ( this .type == Type .IN && comparand .stream ().anyMatch (o -> o == null ) )) {
1761
- throw new NullPointerException ("List comparand is null, or contains null" );
1782
+ if (this .type == Type .IN && comparand .stream ().anyMatch (o -> o == null )) {
1783
+ throw new NullPointerException ("List comparand contains null" );
1762
1784
}
1763
1785
if (comparand .isEmpty ()) {
1764
1786
javaType = null ;
@@ -1772,10 +1794,10 @@ public ListComparison(@Nonnull Type type, @Nonnull List comparand) {
1772
1794
}
1773
1795
}
1774
1796
this .comparand = comparand ;
1775
- this .comparandListWithEqualsSupplier = Suppliers .memoize (() -> Lists .transform (comparand , Comparisons :: toClassWithRealEquals ));
1797
+ this .comparandListWithEqualsSupplier = Suppliers .memoize (() -> Lists .transform (comparand , obj -> obj != null ? toClassWithRealEquals ( obj ) : null ));
1776
1798
}
1777
1799
1778
- private static Descriptors . FieldDescriptor . JavaType getJavaType (@ Nonnull Object o ) {
1800
+ private static JavaType getJavaType (@ Nonnull Object o ) {
1779
1801
if (o instanceof Boolean ) {
1780
1802
return JavaType .BOOLEAN ;
1781
1803
} else if (o instanceof ByteString || o instanceof byte []) {
0 commit comments