@@ -644,12 +644,15 @@ The following is a high-level reference of _some_ of the available
644644_ extension methods_ :
645645
646646 * ` Expr<T?> ` , when ` T ` is one of ` bool ` , ` int ` , ` double ` , ` String ` , ` DateTime ` , has:
647- * ` .equals(Expr<T?> other) -> Expr<bool> `
648- * ` .notEquals(Expr<T?> other) -> Expr<bool> `
647+ * ` .equals(Expr<T> other) -> Expr<bool> `
648+ * ` .equalsUnlessNull(Expr<T?> other) -> Expr<bool?> `
649+ * ` .isNotDistinctFrom(Expr<T?> other) -> Expr<bool> `
649650 * ` .isNull() -> Expr<bool> `
650651 * ` .isNotNull() -> Expr<bool> `
651652 * ` .orElse(Expr<T> other) -> Expr<T> `
652653 * ` .asNotNull() -> Expr<T> `
654+ * ` Expr<T> ` , when ` T ` is one of ` bool ` , ` int ` , ` double ` , ` String ` , ` DateTime ` , has:
655+ * ` .equals(Expr<T?> other) -> Expr<bool> `
653656 * ` Expr<bool> ` , has:
654657 * ` .not() -> Expr<bool> ` (also available as operator ` ~ ` )
655658 * ` .and(Expr<bool> other) -> Expr<bool> ` (also available as operator ` & ` )
@@ -694,6 +697,58 @@ The reference above, deliberately omits variations such as
694697` .<method>Value(...) ` and ` .not<method>(...) ` because they are merely
695698convinience functions.
696699
700+ ### Equality operators
701+ In the previous reference there are 3 equality operators:
702+
703+ | ` package:typed_sql ` | Return type | SQL equivalent | ` NULL ` compared to ` NULL ` ? |
704+ | --------------------------| ---------------| :--------------------------:| :--------------------------:|
705+ | ` a.equals(b) ` | ` Expr<bool> ` | ` a = b ` | N/A |
706+ | ` a.equalsUnlessNull(b) ` | ` Expr<bool?> ` | ` a = b ` | ` NULL ` |
707+ | ` a.isNotDistinctFrom(b) ` | ` Expr<bool> ` | ` a IS NOT DISTINCT FROM b ` | ` TRUE ` |
708+
709+ The difference between these operators is what arguments they take, and how they
710+ behave when comparing to ` NULL ` . In SQL ` NULL = NULL ` yields ` UNKNOWN `
711+ represented by ` NULL ` . Meaning that when we compare two expressions in SQL using
712+ the ` = ` operator, the result cannot be ` TRUE ` if one of the expressions is ` NULL ` .
713+ This is very different from Dart. Thus, to avoid any confusion the SQL ` = `
714+ operator is exposed using the ` .equalsUnlessNull ` extension method.
715+
716+ The ` .equalsUnlessNull ` extension method will return ` NULL ` if any of the two
717+ operands are ` NULL ` , thus, the return type for ` .equalsUnlessNull ` is
718+ ` Expr<bool?> ` . This isn't very convenient, but if you're comparing two
719+ expressions where one of them is not nullable, you can use the ` .equals `
720+ extension method.
721+
722+ The ` .equals ` extension method requires that at least one of the two operands
723+ are not nullable. This is implemented by having two variants:
724+ * ` Expr<T>.equals(Expr<T?> other) -> Expr<bool> ` , and,
725+ * ` Expr<T?>.equals(Expr<T> other) -> Expr<bool> ` .
726+
727+ Thus, when using the ` .equals ` extension method the return type is ` Expr<bool> ` ,
728+ and the SQL operator used is ` = ` . The downside is that you cannot compare two
729+ nullable expressions. If you wish to compare two nullable expressions you can use
730+ ` .isNotDistinctFrom ` which has the same semantics as Dart, meaning that
731+ ` NULL IS NOT DISTINCT FROM NULL ` evaluates to ` TRUE ` . Or you can use
732+ ` .equalsUnlessNull ` if you want SQL semantics, where ` NULL = NULL ` evaluates to
733+ ` NULL ` .
734+
735+ If you wish to compare two nullable expressions in manner where ` NULL = NULL `
736+ evaluates to ` FALSE ` , you can use ` a.equalsUnlessNull(b).orElseValue(false) ` .
737+ Or you can do ` a.isNotDistinctFrom(b) & a.isNotNull() ` .
738+
739+ > [ !TIP]
740+ > While it is tempting to always use ` .isNotDistinctFrom ` , which has the same
741+ > comparison semantics as equality in Dart, there are many scenarios where
742+ > database engines are optimized for the ` = ` operator in SQL.
743+ > And if you are joining tables you'll
744+ > often find that you do not want to join two rows when the key in both tables
745+ > is ` NULL ` .
746+ >
747+ > Thus, whenever you find that the ` .equals ` extension method doesn't work,
748+ > because you are comparing two nullable expressions, do consider if you want
749+ > the ` NULL = NULL ` to be ` TRUE ` or ` FALSE ` , before resorting to use
750+ > ` .isNotDistinctFrom ` .
751+
697752
698753## Query reference
699754The following is a high-level overview of the most important extension methods
0 commit comments