changeset 233:c466678af854

SELECTing arbitrary expressions
author Adam Chlipala <adamc@hcoop.net>
date Thu, 28 Aug 2008 11:17:14 -0400
parents a338da9d82f3
children 82409ef72019
files lib/basis.lig src/elaborate.sml src/lacweb.grm tests/selexp.lac
diffstat 4 files changed, 63 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/lib/basis.lig	Thu Aug 21 16:03:45 2008 -0400
+++ b/lib/basis.lig	Thu Aug 28 11:17:14 2008 -0400
@@ -13,8 +13,8 @@
 
 (*** Queries *)
 
-con sql_query :: {{Type}} -> Type
-con sql_query1 :: {{Type}} -> {{Type}} -> Type
+con sql_query :: {{Type}} -> {Type} -> Type
+con sql_query1 :: {{Type}} -> {{Type}} -> {Type} -> Type
 con sql_exp :: {{Type}} -> {{Type}} -> Type -> Type
 
 con sql_subset :: {{Type}} -> {{Type}} -> Type
@@ -31,14 +31,17 @@
 
 val sql_query1 : tables ::: {{Type}}
         -> grouped ::: {{Type}}
-        -> selected ::: {{Type}}
+        -> selectedFields ::: {{Type}}
+        -> selectedExps ::: {Type}
         -> {From : $(fold (fn nm => fn fields :: {Type} => fn acc =>
                 [nm] ~ acc => [nm = sql_table fields] ++ acc) [] tables),
             Where : sql_exp tables [] bool,
             GroupBy : sql_subset tables grouped,
             Having : sql_exp grouped tables bool,
-            SelectFields : sql_subset grouped selected}
-        -> sql_query1 tables selected
+            SelectFields : sql_subset grouped selectedFields,
+            SelectExps : $(fold (fn nm => fn t :: Type => fn acc =>
+                [nm] ~ acc => [nm = sql_exp grouped tables t] ++ acc) [] selectedExps) }
+        -> sql_query1 tables selectedFields selectedExps
 
 type sql_relop 
 val sql_union : sql_relop
@@ -47,8 +50,11 @@
 val sql_relop : sql_relop
         -> tables1 ::: {{Type}}
         -> tables2 ::: {{Type}}
-        -> selected ::: {{Type}}
-        -> sql_query1 tables1 selected -> sql_query1 tables2 selected -> sql_query1 selected selected
+        -> selectedFields ::: {{Type}}
+        -> selectedExps ::: {Type}
+        -> sql_query1 tables1 selectedFields selectedExps
+        -> sql_query1 tables2 selectedFields selectedExps
+        -> sql_query1 selectedFields selectedFields selectedExps
 
 type sql_direction
 val sql_asc : sql_direction
@@ -69,12 +75,13 @@
 val sql_offset : int -> sql_offset
 
 val sql_query : tables ::: {{Type}}
-        -> selected ::: {{Type}}
-        -> {Rows : sql_query1 tables selected,
+        -> selectedFields ::: {{Type}}
+        -> selectedExps ::: {Type}
+        -> {Rows : sql_query1 tables selectedFields selectedExps,
             OrderBy : sql_order_by tables,
             Limit : sql_limit,
             Offset : sql_offset}
-        -> sql_query selected
+        -> sql_query selectedFields selectedExps
 
 val sql_field : otherTabs ::: {{Type}} -> otherFields ::: {Type} -> fieldType ::: Type -> agg ::: {{Type}}
         -> tab :: Name -> field :: Name
--- a/src/elaborate.sml	Thu Aug 21 16:03:45 2008 -0400
+++ b/src/elaborate.sml	Thu Aug 28 11:17:14 2008 -0400
@@ -1520,7 +1520,8 @@
                             let
                                 val r = ref NONE
                             in
-                                ((L'.EUnif r, loc), ran, [TypeClass (env, dom, r, loc)])
+                                ((L'.EApp (e1', (L'.EUnif r, loc)), loc),
+                                 ran, [TypeClass (env, dom, r, loc)])
                             end
                           | SOME pf => ((L'.EApp (e1', pf), loc), ran, gs1 @ gs2 @ enD gs3 @ enD gs4)
                     end
--- a/src/lacweb.grm	Thu Aug 21 16:03:45 2008 -0400
+++ b/src/lacweb.grm	Thu Aug 28 11:17:14 2008 -0400
@@ -42,6 +42,7 @@
 
 datatype select_item =
          Field of con * con
+       | Exp of con * exp
 
 datatype select =
          Star
@@ -56,25 +57,27 @@
       | (CName x1, CName x2) => x1 = x2
       | _ => false
 
-fun amend_select loc (si, tabs) =
-    let
-        val (tx, c) = case si of
-                          Field (tx, fx) => (tx, (CRecord ([(fx, (CWild (KType, loc), loc))]), loc))
+fun amend_select loc (si, (tabs, exps)) =
+    case si of
+        Field (tx, fx) =>
+        let
+            val c = (CRecord ([(fx, (CWild (KType, loc), loc))]), loc)
 
-        val (tabs, found) = ListUtil.foldlMap (fn ((tx', c'), found) =>
-                                                  if eqTnames (tx, tx') then
-                                                      ((tx', (CConcat (c, c'), loc)), true)
-                                                  else
-                                                      ((tx', c'), found))
-                            false tabs
-    in
-        if found then
-            ()
-        else
-            ErrorMsg.errorAt loc "Select of field from unbound table";
-
-        tabs
-    end
+            val (tabs, found) = ListUtil.foldlMap (fn ((tx', c'), found) =>
+                                                      if eqTnames (tx, tx') then
+                                                          ((tx', (CConcat (c, c'), loc)), true)
+                                                      else
+                                                          ((tx', c'), found))
+                                                  false tabs
+        in
+            if found then
+                ()
+            else
+                ErrorMsg.errorAt loc "Select of field from unbound table";
+            
+            (tabs, exps)
+        end
+      | Exp (c, e) => (tabs, (c, e) :: exps)
 
 fun amend_group loc (gi, tabs) =
     let
@@ -681,22 +684,24 @@
                                         (let
                                              val loc = s (SELECTleft, tablesright)
 
-                                             val sel =
+                                             val (sel, exps) =
                                                  case select of
-                                                     Star => map (fn (nm, _) =>
-                                                                     (nm, (CTuple [(CWild (KRecord (KType, loc), loc),
-                                                                                    loc),
-                                                                                   (CRecord [], loc)],
-                                                                           loc))) tables
+                                                     Star => (map (fn (nm, _) =>
+                                                                      (nm, (CTuple [(CWild (KRecord (KType, loc), loc),
+                                                                                     loc),
+                                                                                    (CRecord [], loc)],
+                                                                            loc))) tables,
+                                                              [])
                                                    | Items sis =>
                                                      let
                                                          val tabs = map (fn (nm, _) => (nm, (CRecord [], loc))) tables
-                                                         val tabs = foldl (amend_select loc) tabs sis
+                                                         val (tabs, exps) = foldl (amend_select loc) (tabs, []) sis
                                                      in
-                                                         map (fn (nm, c) => (nm,
-                                                                             (CTuple [c,
-                                                                                      (CWild (KRecord (KType, loc), loc),
-                                                                                       loc)], loc))) tabs
+                                                         (map (fn (nm, c) => (nm,
+                                                                              (CTuple [c,
+                                                                                       (CWild (KRecord (KType, loc), loc),
+                                                                                        loc)], loc))) tabs,
+                                                          exps)
                                                      end
 
                                              val sel = (CRecord sel, loc)
@@ -733,7 +738,9 @@
                                                                  hopt),
                                                                 ((CName "SelectFields", loc),
                                                                  (ECApp ((EVar (["Basis"], "sql_subset"), loc),
-                                                                         sel), loc))], loc)
+                                                                         sel), loc)),
+                                                                ((CName "SelectExps", loc),
+                                                                 (ERecord exps, loc))], loc)
 
                                              val e = (EApp (e, re), loc)
                                          in
@@ -762,6 +769,7 @@
        | LBRACE cexp RBRACE             (cexp)
 
 seli   : tident DOT fident              (Field (tident, fident))
+       | sqlexp AS fident               (Exp (fident, sqlexp))
 
 selis  : seli                           ([seli])
        | seli COMMA selis               (seli :: selis)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/selexp.lac	Thu Aug 28 11:17:14 2008 -0400
@@ -0,0 +1,6 @@
+table t1 : {A : int, B : string, C : float}
+table t2 : {A : float, D : int}
+
+val q1 = (SELECT 0 AS Zero FROM t1)
+val q2 = (SELECT t1.A < t2.D AS Lt FROM t1, t2)
+val q3 = (SELECT t1.A < t2.D AS Lt, t1.A, t2.D, t1.C = t2.A AS Eq FROM t1, t2)