# HG changeset patch # User Adam Chlipala # Date 1269549711 14400 # Node ID 601a77af047780bac5a08afe8eb3f30da63ee5ea # Parent 1da49fd79e20ffb46d9998b5fe3a35a8635ef27d 'AS' clauses for expression columns may be omitted diff -r 1da49fd79e20 -r 601a77af0477 doc/manual.tex --- a/doc/manual.tex Thu Mar 25 16:27:10 2010 -0400 +++ b/doc/manual.tex Thu Mar 25 16:41:51 2010 -0400 @@ -1959,6 +1959,7 @@ &&& p,^+ & \textrm{particular columns} \\ \textrm{Pre-projections} & p &::=& t.f & \textrm{one column from a table} \\ &&& t.\{\{c\}\} & \textrm{a record of columns from a table (of kind $\{\mt{Type}\}$)} \\ + &&& E \; [\mt{AS} \; f] & \textrm{expression column} \\ \textrm{Table names} & t &::=& x & \textrm{constant table name (automatically capitalized)} \\ &&& X & \textrm{constant table name} \\ &&& \{\{c\}\} & \textrm{computed table name (of kind $\mt{Name}$)} \\ @@ -1997,6 +1998,8 @@ Additionally, an SQL expression may be inserted into normal Ur code with the syntax $(\mt{SQL} \; E)$ or $(\mt{WHERE} \; E)$. Similar shorthands exist for other nonterminals, with the prefix $\mt{FROM}$ for $\mt{FROM}$ items and $\mt{SELECT1}$ for pre-queries. +Unnamed expression columns in $\mt{SELECT}$ clauses are assigned consecutive natural numbers, starting with 1. + \subsubsection{DML} DML commands $D$ are added to the rules for expressions $e$. diff -r 1da49fd79e20 -r 601a77af0477 src/urweb.grm --- a/src/urweb.grm Thu Mar 25 16:27:10 2010 -0400 +++ b/src/urweb.grm Thu Mar 25 16:41:51 2010 -0400 @@ -42,7 +42,7 @@ datatype select_item = Field of con * con - | Exp of con * exp + | Exp of con option * exp | Fields of con * con datatype select = @@ -58,7 +58,7 @@ | (CName x1, CName x2) => x1 = x2 | _ => false -fun amend_select loc (si, (tabs, exps)) = +fun amend_select loc (si, (count, tabs, exps)) = case si of Field (tx, fx) => let @@ -76,7 +76,7 @@ else ErrorMsg.errorAt loc "Select of field from unbound table"; - (tabs, exps) + (count, tabs, exps) end | Fields (tx, fs) => let @@ -92,9 +92,10 @@ else ErrorMsg.errorAt loc "Select of field from unbound table"; - (tabs, exps) + (count, tabs, exps) end - | Exp (c, e) => (tabs, (c, e) :: exps) + | Exp (SOME c, e) => (count, tabs, (c, e) :: exps) + | Exp (NONE, e) => (count+1, tabs, ((CName (Int.toString count), loc), e) :: exps) fun amend_group loc (gi, tabs) = let @@ -1460,7 +1461,8 @@ | Items sis => let val tabs = map (fn nm => (nm, (CRecord [], loc))) (#1 tables) - val (tabs, exps) = foldl (amend_select loc) (tabs, []) sis + val (_, tabs, exps) = foldl (amend_select loc) + (1, tabs, []) sis val empties = List.mapPartial (fn (nm, (CRecord [], _)) => SOME nm | _ => NONE) tabs @@ -1662,7 +1664,8 @@ | LBRACE cexp RBRACE (cexp) seli : tident DOT fident (Field (tident, fident)) - | sqlexp AS fident (Exp (fident, sqlexp)) + | sqlexp (Exp (NONE, sqlexp)) + | sqlexp AS fident (Exp (SOME fident, sqlexp)) | tident DOT LBRACE LBRACE cexp RBRACE RBRACE (Fields (tident, cexp)) selis : seli ([seli]) diff -r 1da49fd79e20 -r 601a77af0477 tests/agg.ur --- a/tests/agg.ur Thu Mar 25 16:27:10 2010 -0400 +++ b/tests/agg.ur Thu Mar 25 16:41:51 2010 -0400 @@ -1,13 +1,14 @@ table t1 : {A : int, B : string, C : float} table t2 : {A : float, D : int, E : option string} -val q1 = (SELECT COUNT( * ) AS X FROM t1) -val q2 = (SELECT AVG(t1.A) AS X FROM t1) -val q3 = (SELECT SUM(t1.C) AS X FROM t1) -val q4 = (SELECT MIN(t1.B) AS X, MAX(t1.A) AS Y FROM t1) -val q5 = (SELECT SUM(t1.A) AS X FROM t1 GROUP BY t1.B) -val q6 = (SELECT COUNT(t2.E) AS N FROM t2 GROUP BY t2.D) +val q1 : sql_query [] _ _ = (SELECT COUNT( * ) FROM t1) +val q2 : sql_query [] _ _ = (SELECT AVG(t1.A) FROM t1) +val q3 : sql_query [] _ _ = (SELECT SUM(t1.C) FROM t1) +val q4 : sql_query [] _ _ = (SELECT MIN(t1.B), MAX(t1.A) FROM t1) +val q5 : sql_query [] _ _ = (SELECT SUM(t1.A) FROM t1 GROUP BY t1.B) +val q6 = (SELECT COUNT(t2.E) FROM t2 GROUP BY t2.D) fun main () : transaction page = - xml <- queryX q6 (fn r => {[r.N]};); - return {xml} + xml <- queryX q6 (fn r => {[r.1]};); + xml2 <- queryX q4 (fn r => {[r.1]}, {[r.2]};); + return {xml}
{xml2}