@@ -184,6 +184,9 @@ private static Optional<QueryPredicate> promoteOperandsAndCreatePredicate(@Nulla
184184 @ Nonnull Value leftChild ,
185185 @ Nonnull Value rightChild ,
186186 @ Nonnull final Comparisons .Type comparisonType ) {
187+ if (leftChild .getResultType ().getTypeCode () == Type .TypeCode .NULL && rightChild .getResultType ().getTypeCode () == Type .TypeCode .NULL && comparisonType == Comparisons .Type .NOT_DISTINCT_FROM ) {
188+ return Optional .of (ConstantPredicate .TRUE );
189+ }
187190 // maximumType may return null, but only for non-primitive types which is not possible here
188191 final var maxtype = Verify .verifyNotNull (Type .maximumType (leftChild .getResultType (), rightChild .getResultType ()));
189192
@@ -255,6 +258,7 @@ private static Comparisons.Type swapBinaryComparisonOperator(@Nonnull Comparison
255258 switch (type ) {
256259 case EQUALS :
257260 case NOT_EQUALS :
261+ case NOT_DISTINCT_FROM :
258262 return type ;
259263 case LESS_THAN :
260264 return Comparisons .Type .GREATER_THAN ;
@@ -290,6 +294,13 @@ private static Value encapsulate(@Nonnull final String functionName,
290294 } else {
291295 final Typed arg1 = arguments .get (1 );
292296 final Type res1 = arg1 .getResultType ();
297+ if (functionName .equals ("notDistinctFrom" )) {
298+ if (res0 .getTypeCode () == Type .TypeCode .NULL && res1 .getTypeCode () != Type .TypeCode .NULL ) {
299+ return encapsulate ("isNull" , Comparisons .Type .IS_NULL , List .of (arg1 ));
300+ } else if (res1 .getTypeCode () == Type .TypeCode .NULL && res0 .getTypeCode () != Type .TypeCode .NULL ) {
301+ return encapsulate ("isNull" , Comparisons .Type .IS_NULL , List .of (arg0 ));
302+ }
303+ }
293304 SemanticException .check (res1 .isPrimitive () || res1 .isEnum () || res1 .isUuid (), SemanticException .ErrorCode .COMPARAND_TO_COMPARISON_IS_OF_COMPLEX_TYPE );
294305
295306 final BinaryPhysicalOperator physicalOperator =
@@ -451,6 +462,21 @@ private static Value encapsulate(@Nonnull BuiltInFunction<Value> builtInFunction
451462 }
452463 }
453464
465+ /**
466+ * The {@code notDistinctFrom} function.
467+ */
468+ @ AutoService (BuiltInFunction .class )
469+ public static class NotDistinctFromFn extends BuiltInFunction <Value > {
470+ public NotDistinctFromFn () {
471+ super ("notDistinctFrom" ,
472+ List .of (new Type .Any (), new Type .Any ()), NotDistinctFromFn ::encapsulate );
473+ }
474+
475+ private static Value encapsulate (@ Nonnull BuiltInFunction <Value > builtInFunction , @ Nonnull final List <? extends Typed > arguments ) {
476+ return RelOpValue .encapsulate (builtInFunction .getFunctionName (), Comparisons .Type .NOT_DISTINCT_FROM , arguments );
477+ }
478+ }
479+
454480 private enum BinaryPhysicalOperator {
455481 // TODO think about equality epsilon for floating-point types.
456482 EQ_BU (Comparisons .Type .EQUALS , Type .TypeCode .BOOLEAN , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
@@ -763,6 +789,66 @@ private enum BinaryPhysicalOperator {
763789 GTE_SID (Comparisons .Type .GREATER_THAN_OR_EQUALS , Type .TypeCode .STRING , Type .TypeCode .UUID , (l , r ) -> Comparisons .evalComparison (Comparisons .Type .GREATER_THAN_OR_EQUALS , PromoteValue .PhysicalOperator .stringToUuidValue ((String ) l ), r )),
764790 GTE_UID (Comparisons .Type .GREATER_THAN_OR_EQUALS , Type .TypeCode .UNKNOWN , Type .TypeCode .UUID , (l , r ) -> null ),
765791 GTE_IDU (Comparisons .Type .GREATER_THAN_OR_EQUALS , Type .TypeCode .UUID , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
792+
793+ NOT_DISTINCT_FROM_BU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .BOOLEAN , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
794+ NOT_DISTINCT_FROM_BB (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .BOOLEAN , Type .TypeCode .BOOLEAN , (l , r ) -> (boolean )l == (boolean )r ),
795+ NOT_DISTINCT_FROM_IU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .INT , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
796+ NOT_DISTINCT_FROM_II (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .INT , Type .TypeCode .INT , (l , r ) -> (int )l == (int )r ),
797+ NOT_DISTINCT_FROM_IL (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .INT , Type .TypeCode .LONG , (l , r ) -> (int )l == (long )r ),
798+ NOT_DISTINCT_FROM_IF (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .INT , Type .TypeCode .FLOAT , (l , r ) -> (int )l == (float )r ),
799+ NOT_DISTINCT_FROM_ID (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .INT , Type .TypeCode .DOUBLE , (l , r ) -> (int )l == (double )r ),
800+ NOT_DISTINCT_FROM_LU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .LONG , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
801+ NOT_DISTINCT_FROM_LI (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .LONG , Type .TypeCode .INT , (l , r ) -> (long )l == (int )r ),
802+ NOT_DISTINCT_FROM_LL (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .LONG , Type .TypeCode .LONG , (l , r ) -> (long )l == (long )r ),
803+ NOT_DISTINCT_FROM_LF (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .LONG , Type .TypeCode .FLOAT , (l , r ) -> (long )l == (float )r ),
804+ NOT_DISTINCT_FROM_LD (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .LONG , Type .TypeCode .DOUBLE , (l , r ) -> (long )l == (double )r ),
805+ NOT_DISTINCT_FROM_FU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .FLOAT , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
806+ NOT_DISTINCT_FROM_FI (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .FLOAT , Type .TypeCode .INT , (l , r ) -> (float )l == (int )r ),
807+ NOT_DISTINCT_FROM_FL (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .FLOAT , Type .TypeCode .LONG , (l , r ) -> (float )l == (long )r ),
808+ NOT_DISTINCT_FROM_FF (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .FLOAT , Type .TypeCode .FLOAT , (l , r ) -> (float )l == (float )r ),
809+ NOT_DISTINCT_FROM_FD (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .FLOAT , Type .TypeCode .DOUBLE , (l , r ) -> (float )l == (double )r ),
810+ NOT_DISTINCT_FROM_DU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .DOUBLE , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
811+ NOT_DISTINCT_FROM_DI (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .DOUBLE , Type .TypeCode .INT , (l , r ) -> (double )l == (int )r ),
812+ NOT_DISTINCT_FROM_DL (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .DOUBLE , Type .TypeCode .LONG , (l , r ) -> (double )l == (long )r ),
813+ NOT_DISTINCT_FROM_DF (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .DOUBLE , Type .TypeCode .FLOAT , (l , r ) -> (double )l == (float )r ),
814+ NOT_DISTINCT_FROM_DD (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .DOUBLE , Type .TypeCode .DOUBLE , (l , r ) -> (double )l == (double )r ),
815+ NOT_DISTINCT_FROM_SU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .STRING , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
816+ NOT_DISTINCT_FROM_SS (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .STRING , Type .TypeCode .STRING , Object ::equals ), // TODO: locale-aware comparison
817+ NOT_DISTINCT_FROM_UU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
818+ NOT_DISTINCT_FROM_UB (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .BOOLEAN , (l , r ) -> null ),
819+ NOT_DISTINCT_FROM_UI (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .INT , (l , r ) -> null ),
820+ NOT_DISTINCT_FROM_UL (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .LONG , (l , r ) -> null ),
821+ NOT_DISTINCT_FROM_UF (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .FLOAT , (l , r ) -> null ),
822+ NOT_DISTINCT_FROM_UD (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .DOUBLE , (l , r ) -> null ),
823+ NOT_DISTINCT_FROM_US (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .STRING , (l , r ) -> null ),
824+ NOT_DISTINCT_FROM_UV (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .VERSION , (l , r ) -> null ),
825+ NOT_DISTINCT_FROM_VU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .VERSION , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
826+ NOT_DISTINCT_FROM_VV (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .VERSION , Type .TypeCode .VERSION , Object ::equals ),
827+
828+ NOT_DISTINCT_FROM_BYU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .BYTES , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
829+ NOT_DISTINCT_FROM_BYBY (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .BYTES , Type .TypeCode .BYTES , (l , r ) -> Comparisons .evalComparison (Comparisons .Type .NOT_DISTINCT_FROM , l , r )),
830+ NOT_DISTINCT_FROM_UBY (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .BYTES , (l , r ) -> null ),
831+
832+ NOT_DISTINCT_FROM_EE (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .ENUM , Type .TypeCode .ENUM , (l , r ) -> Comparisons .evalComparison (Comparisons .Type .NOT_DISTINCT_FROM , l , r )),
833+ NOT_DISTINCT_FROM_ES (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .ENUM , Type .TypeCode .STRING , (l , r ) -> {
834+ final var otherValue = PromoteValue .PhysicalOperator .stringToEnumValue (((Descriptors .EnumValueDescriptor ) l ).getType (), (String ) r );
835+ return Comparisons .evalComparison (Comparisons .Type .NOT_DISTINCT_FROM , l , otherValue );
836+ }),
837+ NOT_DISTINCT_FROM_SE (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .STRING , Type .TypeCode .ENUM , (l , r ) -> {
838+ final var otherValue = PromoteValue .PhysicalOperator .stringToEnumValue (((Descriptors .EnumValueDescriptor ) r ).getType (), (String ) l );
839+ return Comparisons .evalComparison (Comparisons .Type .NOT_DISTINCT_FROM , otherValue , r );
840+ }),
841+ NOT_DISTINCT_FROM_EU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .ENUM , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
842+ NOT_DISTINCT_FROM_UE (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .ENUM , (l , r ) -> null ),
843+
844+ NOT_DISTINCT_FROM_IDID (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UUID , Type .TypeCode .UUID , (l , r ) -> Comparisons .evalComparison (Comparisons .Type .NOT_DISTINCT_FROM , l , r )),
845+ NOT_DISTINCT_FROM_IDS (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UUID , Type .TypeCode .STRING , (l , r ) -> Comparisons .evalComparison (Comparisons .Type .NOT_DISTINCT_FROM , l , PromoteValue .PhysicalOperator .stringToUuidValue ((String ) r ))),
846+ NOT_DISTINCT_FROM_SID (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .STRING , Type .TypeCode .UUID , (l , r ) -> Comparisons .evalComparison (Comparisons .Type .NOT_DISTINCT_FROM , PromoteValue .PhysicalOperator .stringToUuidValue ((String ) l ), r )),
847+ NOT_DISTINCT_FROM_UID (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UNKNOWN , Type .TypeCode .UUID , (l , r ) -> null ),
848+ NOT_DISTINCT_FROM_IDU (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .UUID , Type .TypeCode .UNKNOWN , (l , r ) -> null ),
849+
850+ NOT_DISTINCT_FROM_NN (Comparisons .Type .NOT_DISTINCT_FROM , Type .TypeCode .NULL , Type .TypeCode .NULL , (l , r ) -> true ),
851+
766852 ;
767853 // We can pass down UUID or String till here.
768854
0 commit comments