changeset 2191:849404a3af27

Change behavior of SQL equality to do the intuitive thing for nullable types
author Adam Chlipala <adam@chlipala.net>
date Sun, 01 Nov 2015 17:02:16 -0500
parents 22117edf8fd3
children fb113569519e 985c8016b592
files lib/ur/basis.urs src/monoize.sml
diffstat 2 files changed, 34 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/lib/ur/basis.urs	Sun Nov 01 16:33:14 2015 -0500
+++ b/lib/ur/basis.urs	Sun Nov 01 17:02:16 2015 -0500
@@ -554,6 +554,9 @@
 val sql_mod : sql_binary int int int
 
 val sql_eq : t ::: Type -> sql_binary t t bool
+(* Note that the semantics of this operator on nullable types are different than for standard SQL!
+ * Instead, we do it the sane way, where [NULL = NULL]. *)
+
 val sql_ne : t ::: Type -> sql_binary t t bool
 val sql_lt : t ::: Type -> sql_binary t t bool
 val sql_le : t ::: Type -> sql_binary t t bool
--- a/src/monoize.sml	Sun Nov 01 16:33:14 2015 -0500
+++ b/src/monoize.sml	Sun Nov 01 17:02:16 2015 -0500
@@ -2592,22 +2592,45 @@
                  _), _),
                 _), _),
                _), _),
-              _), _),
+              arg1), _),
              _), _),
             _) =>
             let
                 val s = (L'.TFfi ("Basis", "string"), loc)
+
+                val default = strcat [str "(",
+                                      (L'.ERel 1, loc),
+                                      str " ",
+                                      (L'.ERel 2, loc),
+                                      str " ",
+                                      (L'.ERel 0, loc),
+                                      str ")"]
+
+                val body = case #1 arg1 of
+                               L.CApp ((L.CFfi ("Basis", "option"), _), _) =>
+                                (L'.ECase ((L'.ERel 2, loc),
+                                           [((L'.PPrim (Prim.String (Prim.Normal, "=")), loc),
+                                             strcat [str "((",
+                                                     (L'.ERel 1, loc),
+                                                     str " ",
+                                                     (L'.ERel 2, loc),
+                                                     str " ",
+                                                     (L'.ERel 0, loc),
+                                                     str ") OR ((",
+                                                     (L'.ERel 1, loc),
+                                                     str ") IS NULL AND (",
+                                                     (L'.ERel 0, loc),
+                                                     str ") IS NULL))"]),
+                                            ((L'.PWild, loc),
+                                             default)],
+                                           {disc = s,
+                                            result = s}), loc)
+                             | _ => default
             in
                 ((L'.EAbs ("c", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc),
                            (L'.EAbs ("e1", s, (L'.TFun (s, s), loc),
                                      (L'.EAbs ("e2", s, s,
-                                               strcat [str "(",
-                                                       (L'.ERel 1, loc),
-                                                       str " ",
-                                                       (L'.ERel 2, loc),
-                                                       str " ",
-                                                       (L'.ERel 0, loc),
-                                                       str ")"]), loc)), loc)), loc),
+                                               body), loc)), loc)), loc),
                  fm)
             end
           | L.EFfi ("Basis", "sql_and") => (str "AND", fm)